ngwr 7.3.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/README.md +79 -31
  2. package/action-sheet/styles/_index.scss +93 -0
  3. package/alert/styles/_index.scss +45 -18
  4. package/anchor/styles/_index.scss +3 -3
  5. package/avatar/styles/_index.scss +2 -2
  6. package/back-top/styles/_index.scss +1 -1
  7. package/badge/styles/_index.scss +11 -7
  8. package/badge/styles/_tag.scss +4 -4
  9. package/bar-chart/styles/_index.scss +5 -6
  10. package/border-glow/styles/_index.scss +3 -3
  11. package/breadcrumbs/styles/_index.scss +7 -5
  12. package/burger/styles/_index.scss +3 -3
  13. package/button/styles/_index.scss +34 -24
  14. package/calendar/styles/_index.scss +15 -13
  15. package/calendar-heatmap/styles/_index.scss +5 -3
  16. package/card/styles/_index.scss +5 -5
  17. package/carousel/styles/_index.scss +6 -6
  18. package/cascader/styles/_index.scss +69 -29
  19. package/checkbox/styles/_index.scss +41 -9
  20. package/collapse/styles/_index.scss +7 -7
  21. package/color-picker/styles/_index.scss +26 -21
  22. package/command-palette/styles/_index.scss +22 -19
  23. package/compare/styles/_index.scss +6 -6
  24. package/context-menu/styles/_index.scss +17 -7
  25. package/counter/styles/_index.scss +12 -1
  26. package/date-picker/styles/_index.scss +13 -14
  27. package/density/styles/_index.scss +3 -3
  28. package/descriptions/styles/_index.scss +9 -9
  29. package/dialog/styles/_index.scss +10 -9
  30. package/divider/styles/_index.scss +3 -3
  31. package/donut-chart/styles/_index.scss +3 -3
  32. package/drag-drop/styles/_index.scss +11 -6
  33. package/drawer/styles/_index.scss +26 -17
  34. package/dropdown/styles/_index.scss +7 -7
  35. package/empty/styles/_index.scss +4 -4
  36. package/fesm2022/ngwr-action-sheet.mjs +81 -0
  37. package/fesm2022/ngwr-action-sheet.mjs.map +1 -0
  38. package/fesm2022/ngwr-affix.mjs +3 -3
  39. package/fesm2022/ngwr-alert.mjs +23 -11
  40. package/fesm2022/ngwr-alert.mjs.map +1 -1
  41. package/fesm2022/ngwr-anchor.mjs +4 -4
  42. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  43. package/fesm2022/ngwr-aurora.mjs +5 -4
  44. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  45. package/fesm2022/ngwr-avatar.mjs +4 -4
  46. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  47. package/fesm2022/ngwr-back-top.mjs +4 -4
  48. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  49. package/fesm2022/ngwr-badge.mjs +8 -8
  50. package/fesm2022/ngwr-badge.mjs.map +1 -1
  51. package/fesm2022/ngwr-bar-chart.mjs +4 -4
  52. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  53. package/fesm2022/ngwr-blur-text.mjs +3 -3
  54. package/fesm2022/ngwr-border-glow.mjs +4 -4
  55. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  56. package/fesm2022/ngwr-breadcrumbs.mjs +8 -8
  57. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  58. package/fesm2022/ngwr-burger.mjs +4 -4
  59. package/fesm2022/ngwr-burger.mjs.map +1 -1
  60. package/fesm2022/ngwr-button.mjs +8 -8
  61. package/fesm2022/ngwr-button.mjs.map +1 -1
  62. package/fesm2022/ngwr-calendar-heatmap.mjs +4 -4
  63. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  64. package/fesm2022/ngwr-calendar.mjs +5 -5
  65. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  66. package/fesm2022/ngwr-card.mjs +11 -11
  67. package/fesm2022/ngwr-card.mjs.map +1 -1
  68. package/fesm2022/ngwr-carousel.mjs +7 -7
  69. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  70. package/fesm2022/ngwr-cascader.mjs +58 -89
  71. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  72. package/fesm2022/ngwr-checkbox.mjs +80 -129
  73. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  74. package/fesm2022/ngwr-circular-text.mjs +5 -4
  75. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  76. package/fesm2022/ngwr-click-spark.mjs +27 -7
  77. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  78. package/fesm2022/ngwr-clipboard.mjs +28 -7
  79. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  80. package/fesm2022/ngwr-collapse.mjs +12 -12
  81. package/fesm2022/ngwr-collapse.mjs.map +1 -1
  82. package/fesm2022/ngwr-color-picker.mjs +58 -66
  83. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  84. package/fesm2022/ngwr-command-palette.mjs +4 -4
  85. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  86. package/fesm2022/ngwr-compare.mjs +4 -4
  87. package/fesm2022/ngwr-compare.mjs.map +1 -1
  88. package/fesm2022/ngwr-confetti.mjs +3 -3
  89. package/fesm2022/ngwr-context-menu.mjs +98 -75
  90. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  91. package/fesm2022/ngwr-cookie.mjs +19 -6
  92. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  93. package/fesm2022/ngwr-counter.mjs +32 -14
  94. package/fesm2022/ngwr-counter.mjs.map +1 -1
  95. package/fesm2022/ngwr-date-adapter-fns.mjs +3 -3
  96. package/fesm2022/ngwr-date-adapter-luxon.mjs +3 -3
  97. package/fesm2022/ngwr-date-adapter.mjs +10 -5
  98. package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
  99. package/fesm2022/ngwr-date-picker.mjs +142 -123
  100. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  101. package/fesm2022/ngwr-decrypt-text.mjs +3 -3
  102. package/fesm2022/ngwr-density.mjs +15 -15
  103. package/fesm2022/ngwr-density.mjs.map +1 -1
  104. package/fesm2022/ngwr-descriptions.mjs +7 -7
  105. package/fesm2022/ngwr-descriptions.mjs.map +1 -1
  106. package/fesm2022/ngwr-dialog.mjs +16 -16
  107. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  108. package/fesm2022/ngwr-directives.mjs +22 -88
  109. package/fesm2022/ngwr-directives.mjs.map +1 -1
  110. package/fesm2022/ngwr-divider.mjs +4 -4
  111. package/fesm2022/ngwr-divider.mjs.map +1 -1
  112. package/fesm2022/ngwr-donut-chart.mjs +11 -5
  113. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  114. package/fesm2022/ngwr-drag-drop.mjs +10 -9
  115. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  116. package/fesm2022/ngwr-drawer.mjs +19 -18
  117. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  118. package/fesm2022/ngwr-dropdown.mjs +13 -12
  119. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  120. package/fesm2022/ngwr-empty.mjs +4 -4
  121. package/fesm2022/ngwr-empty.mjs.map +1 -1
  122. package/fesm2022/ngwr-falling-text.mjs +5 -4
  123. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  124. package/fesm2022/ngwr-file-upload.mjs +58 -60
  125. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  126. package/fesm2022/ngwr-form.mjs +11 -11
  127. package/fesm2022/ngwr-form.mjs.map +1 -1
  128. package/fesm2022/ngwr-fuzzy-text.mjs +10 -8
  129. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  130. package/fesm2022/ngwr-gauge.mjs +4 -4
  131. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  132. package/fesm2022/ngwr-glitch-text.mjs +15 -7
  133. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  134. package/fesm2022/ngwr-gradient-text.mjs +4 -4
  135. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  136. package/fesm2022/ngwr-hotkey.mjs +7 -7
  137. package/fesm2022/ngwr-hotkey.mjs.map +1 -1
  138. package/fesm2022/ngwr-i18n.mjs +10 -10
  139. package/fesm2022/ngwr-i18n.mjs.map +1 -1
  140. package/fesm2022/ngwr-icon-adapters-lucide.mjs +6 -7
  141. package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -1
  142. package/fesm2022/ngwr-icon.mjs +4 -4
  143. package/fesm2022/ngwr-icon.mjs.map +1 -1
  144. package/fesm2022/ngwr-image-cropper.mjs +6 -5
  145. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  146. package/fesm2022/ngwr-input-number.mjs +56 -73
  147. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  148. package/fesm2022/ngwr-input-otp.mjs +52 -52
  149. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  150. package/fesm2022/ngwr-input.mjs +27 -18
  151. package/fesm2022/ngwr-input.mjs.map +1 -1
  152. package/fesm2022/ngwr-keyboard.mjs +4 -4
  153. package/fesm2022/ngwr-keyboard.mjs.map +1 -1
  154. package/fesm2022/ngwr-knob.mjs +47 -58
  155. package/fesm2022/ngwr-knob.mjs.map +1 -1
  156. package/fesm2022/ngwr-layout.mjs +16 -16
  157. package/fesm2022/ngwr-layout.mjs.map +1 -1
  158. package/fesm2022/ngwr-lightbox.mjs +20 -7
  159. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  160. package/fesm2022/ngwr-line-chart.mjs +4 -4
  161. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  162. package/fesm2022/ngwr-list.mjs +8 -8
  163. package/fesm2022/ngwr-list.mjs.map +1 -1
  164. package/fesm2022/ngwr-loading-bar.mjs +7 -7
  165. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  166. package/fesm2022/ngwr-marquee.mjs +6 -5
  167. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  168. package/fesm2022/ngwr-media.mjs +4 -4
  169. package/fesm2022/ngwr-media.mjs.map +1 -1
  170. package/fesm2022/ngwr-mention.mjs +15 -9
  171. package/fesm2022/ngwr-mention.mjs.map +1 -1
  172. package/fesm2022/ngwr-meta.mjs +7 -7
  173. package/fesm2022/ngwr-meta.mjs.map +1 -1
  174. package/fesm2022/ngwr-meter-group.mjs +4 -4
  175. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  176. package/fesm2022/ngwr-overlay.mjs +9 -4
  177. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  178. package/fesm2022/ngwr-page-header.mjs +4 -4
  179. package/fesm2022/ngwr-page-header.mjs.map +1 -1
  180. package/fesm2022/ngwr-pagination.mjs +6 -16
  181. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  182. package/fesm2022/ngwr-pipes.mjs +21 -21
  183. package/fesm2022/ngwr-platform.mjs +169 -5
  184. package/fesm2022/ngwr-platform.mjs.map +1 -1
  185. package/fesm2022/ngwr-popconfirm.mjs +7 -7
  186. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  187. package/fesm2022/ngwr-popover.mjs +7 -7
  188. package/fesm2022/ngwr-popover.mjs.map +1 -1
  189. package/fesm2022/ngwr-progress.mjs +4 -4
  190. package/fesm2022/ngwr-progress.mjs.map +1 -1
  191. package/fesm2022/ngwr-pull-to-refresh.mjs +172 -0
  192. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -0
  193. package/fesm2022/ngwr-qr.mjs +5 -5
  194. package/fesm2022/ngwr-qr.mjs.map +1 -1
  195. package/fesm2022/ngwr-radio.mjs +49 -72
  196. package/fesm2022/ngwr-radio.mjs.map +1 -1
  197. package/fesm2022/ngwr-rating.mjs +41 -65
  198. package/fesm2022/ngwr-rating.mjs.map +1 -1
  199. package/fesm2022/ngwr-result.mjs +13 -13
  200. package/fesm2022/ngwr-result.mjs.map +1 -1
  201. package/fesm2022/ngwr-rotating-text.mjs +15 -4
  202. package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
  203. package/fesm2022/ngwr-scroll.mjs +4 -4
  204. package/fesm2022/ngwr-scroll.mjs.map +1 -1
  205. package/fesm2022/ngwr-segmented.mjs +10 -22
  206. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  207. package/fesm2022/ngwr-select.mjs +303 -86
  208. package/fesm2022/ngwr-select.mjs.map +1 -1
  209. package/fesm2022/ngwr-shiny-text.mjs +7 -7
  210. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  211. package/fesm2022/ngwr-sidebar.mjs +4 -4
  212. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  213. package/fesm2022/ngwr-skeleton.mjs +4 -4
  214. package/fesm2022/ngwr-skeleton.mjs.map +1 -1
  215. package/fesm2022/ngwr-slider.mjs +79 -73
  216. package/fesm2022/ngwr-slider.mjs.map +1 -1
  217. package/fesm2022/ngwr-sparkline.mjs +4 -4
  218. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  219. package/fesm2022/ngwr-speed-dial.mjs +13 -5
  220. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  221. package/fesm2022/ngwr-spinner.mjs +4 -4
  222. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  223. package/fesm2022/ngwr-splash-cursor.mjs +4 -4
  224. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  225. package/fesm2022/ngwr-split-text.mjs +3 -3
  226. package/fesm2022/ngwr-splitter.mjs +4 -4
  227. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  228. package/fesm2022/ngwr-spotlight-card.mjs +8 -8
  229. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  230. package/fesm2022/ngwr-squircle.mjs +7 -7
  231. package/fesm2022/ngwr-squircle.mjs.map +1 -1
  232. package/fesm2022/ngwr-star-border.mjs +4 -4
  233. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  234. package/fesm2022/ngwr-statistic.mjs +138 -14
  235. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  236. package/fesm2022/ngwr-stepper.mjs +8 -8
  237. package/fesm2022/ngwr-stepper.mjs.map +1 -1
  238. package/fesm2022/ngwr-storage.mjs +4 -4
  239. package/fesm2022/ngwr-storage.mjs.map +1 -1
  240. package/fesm2022/ngwr-switch.mjs +22 -58
  241. package/fesm2022/ngwr-switch.mjs.map +1 -1
  242. package/fesm2022/ngwr-table.mjs +824 -20
  243. package/fesm2022/ngwr-table.mjs.map +1 -1
  244. package/fesm2022/ngwr-tabs.mjs +11 -8
  245. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  246. package/fesm2022/ngwr-textarea.mjs +94 -67
  247. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  248. package/fesm2022/ngwr-theme.mjs +20 -5
  249. package/fesm2022/ngwr-theme.mjs.map +1 -1
  250. package/fesm2022/ngwr-tilt-card.mjs +27 -11
  251. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  252. package/fesm2022/ngwr-timeline.mjs +7 -7
  253. package/fesm2022/ngwr-timeline.mjs.map +1 -1
  254. package/fesm2022/ngwr-toast.mjs +47 -25
  255. package/fesm2022/ngwr-toast.mjs.map +1 -1
  256. package/fesm2022/ngwr-toolbar.mjs +4 -4
  257. package/fesm2022/ngwr-toolbar.mjs.map +1 -1
  258. package/fesm2022/ngwr-tree.mjs +280 -84
  259. package/fesm2022/ngwr-tree.mjs.map +1 -1
  260. package/fesm2022/ngwr-typewriter.mjs +10 -5
  261. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  262. package/fesm2022/ngwr-typography.mjs +4 -4
  263. package/fesm2022/ngwr-typography.mjs.map +1 -1
  264. package/fesm2022/ngwr-validators.mjs +42 -4
  265. package/fesm2022/ngwr-validators.mjs.map +1 -1
  266. package/fesm2022/ngwr-version.mjs +1 -1
  267. package/fesm2022/ngwr-version.mjs.map +1 -1
  268. package/fesm2022/ngwr-virtual-scroll.mjs +9 -7
  269. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  270. package/fesm2022/ngwr-waves.mjs +6 -5
  271. package/fesm2022/ngwr-waves.mjs.map +1 -1
  272. package/fesm2022/ngwr-window.mjs +16 -15
  273. package/fesm2022/ngwr-window.mjs.map +1 -1
  274. package/file-upload/styles/_index.scss +14 -14
  275. package/form/styles/_index.scss +9 -9
  276. package/gauge/styles/_index.scss +2 -2
  277. package/glitch-text/styles/_index.scss +4 -7
  278. package/gradient-text/styles/_index.scss +1 -1
  279. package/image-cropper/styles/_index.scss +8 -7
  280. package/input/styles/_index.scss +35 -16
  281. package/input-number/styles/_index.scss +1 -1
  282. package/input-otp/styles/_index.scss +28 -10
  283. package/keyboard/styles/_index.scss +11 -9
  284. package/knob/styles/_index.scss +7 -3
  285. package/layout/styles/_index.scss +12 -12
  286. package/lightbox/styles/_index.scss +31 -10
  287. package/line-chart/styles/_index.scss +5 -5
  288. package/list/styles/_index.scss +6 -6
  289. package/llms-full.txt +45 -24
  290. package/llms.txt +48 -32
  291. package/marquee/styles/_index.scss +1 -1
  292. package/mention/styles/_index.scss +6 -6
  293. package/meter-group/styles/_index.scss +4 -4
  294. package/overlay/styles/_index.scss +9 -1
  295. package/package.json +21 -14
  296. package/page-header/styles/_index.scss +4 -4
  297. package/pagination/styles/_index.scss +6 -29
  298. package/popconfirm/styles/_index.scss +4 -4
  299. package/popover/styles/_index.scss +7 -7
  300. package/progress/styles/_index.scss +1 -1
  301. package/pull-to-refresh/styles/_index.scss +38 -0
  302. package/radio/styles/_index.scss +24 -9
  303. package/rating/styles/_index.scss +13 -2
  304. package/result/styles/_index.scss +3 -3
  305. package/schematics/migrations/v8/index.js +122 -0
  306. package/schematics/migrations/v9/index.js +71 -0
  307. package/schematics/migrations.json +10 -0
  308. package/schematics/ng-add/index.js +3 -3
  309. package/schematics/ng-add/schema.json +7 -7
  310. package/schematics/provider/schema.json +1 -1
  311. package/schematics/use/symbol-map.json +24 -2
  312. package/segmented/styles/_index.scss +35 -12
  313. package/select/styles/_index.scss +126 -43
  314. package/shiny-text/styles/_index.scss +4 -4
  315. package/sidebar/styles/_index.scss +15 -15
  316. package/slider/styles/_index.scss +7 -8
  317. package/speed-dial/styles/_index.scss +23 -6
  318. package/splash-cursor/styles/_index.scss +1 -0
  319. package/splitter/styles/_index.scss +11 -8
  320. package/spotlight-card/styles/_index.scss +11 -7
  321. package/star-border/styles/_index.scss +3 -3
  322. package/statistic/styles/_index.scss +51 -4
  323. package/stepper/styles/_index.scss +10 -10
  324. package/styles/_animations.scss +0 -23
  325. package/styles/_typography.scss +4 -1
  326. package/styles.scss +2 -1
  327. package/switch/styles/_index.scss +29 -10
  328. package/table/styles/_index.scss +456 -26
  329. package/tabs/styles/_index.scss +25 -6
  330. package/textarea/styles/_index.scss +65 -10
  331. package/theme/styles/_colors.scss +82 -1
  332. package/theme/styles/_dark.scss +22 -8
  333. package/theme/styles/_focus.scss +5 -0
  334. package/theme/styles/_variables.scss +24 -0
  335. package/tilt-card/styles/_index.scss +4 -4
  336. package/timeline/styles/_index.scss +18 -8
  337. package/toast/styles/_index.scss +24 -16
  338. package/toolbar/styles/_index.scss +5 -5
  339. package/tree/styles/_index.scss +63 -32
  340. package/types/ngwr-action-sheet.d.ts +75 -0
  341. package/types/ngwr-alert.d.ts +17 -7
  342. package/types/ngwr-anchor.d.ts +1 -1
  343. package/types/ngwr-avatar.d.ts +1 -1
  344. package/types/ngwr-back-top.d.ts +1 -1
  345. package/types/ngwr-badge.d.ts +4 -4
  346. package/types/ngwr-bar-chart.d.ts +1 -1
  347. package/types/ngwr-breadcrumbs.d.ts +1 -1
  348. package/types/ngwr-burger.d.ts +1 -1
  349. package/types/ngwr-button.d.ts +3 -3
  350. package/types/ngwr-calendar-heatmap.d.ts +1 -1
  351. package/types/ngwr-calendar.d.ts +1 -1
  352. package/types/ngwr-card.d.ts +1 -1
  353. package/types/ngwr-carousel.d.ts +1 -1
  354. package/types/ngwr-cascader.d.ts +31 -17
  355. package/types/ngwr-checkbox.d.ts +67 -44
  356. package/types/ngwr-click-spark.d.ts +13 -1
  357. package/types/ngwr-clipboard.d.ts +13 -2
  358. package/types/ngwr-collapse.d.ts +3 -3
  359. package/types/ngwr-color-picker.d.ts +24 -19
  360. package/types/ngwr-command-palette.d.ts +1 -1
  361. package/types/ngwr-compare.d.ts +1 -1
  362. package/types/ngwr-context-menu.d.ts +42 -23
  363. package/types/ngwr-cookie.d.ts +7 -1
  364. package/types/ngwr-counter.d.ts +9 -2
  365. package/types/ngwr-date-picker.d.ts +39 -23
  366. package/types/ngwr-density.d.ts +8 -8
  367. package/types/ngwr-descriptions.d.ts +1 -1
  368. package/types/ngwr-dialog.d.ts +1 -1
  369. package/types/ngwr-directives.d.ts +18 -49
  370. package/types/ngwr-divider.d.ts +2 -2
  371. package/types/ngwr-donut-chart.d.ts +1 -1
  372. package/types/ngwr-drag-drop.d.ts +1 -1
  373. package/types/ngwr-drawer.d.ts +1 -1
  374. package/types/ngwr-dropdown.d.ts +1 -1
  375. package/types/ngwr-empty.d.ts +1 -1
  376. package/types/ngwr-file-upload.d.ts +28 -17
  377. package/types/ngwr-form.d.ts +2 -2
  378. package/types/ngwr-fuzzy-text.d.ts +1 -1
  379. package/types/ngwr-gauge.d.ts +1 -1
  380. package/types/ngwr-glitch-text.d.ts +9 -3
  381. package/types/ngwr-hotkey.d.ts +1 -1
  382. package/types/ngwr-i18n.d.ts +1 -1
  383. package/types/ngwr-icon-adapters-lucide.d.ts +5 -3
  384. package/types/ngwr-icon.d.ts +1 -1
  385. package/types/ngwr-image-cropper.d.ts +1 -1
  386. package/types/ngwr-input-number.d.ts +25 -19
  387. package/types/ngwr-input-otp.d.ts +28 -18
  388. package/types/ngwr-input.d.ts +29 -15
  389. package/types/ngwr-keyboard.d.ts +1 -1
  390. package/types/ngwr-knob.d.ts +24 -19
  391. package/types/ngwr-layout.d.ts +1 -1
  392. package/types/ngwr-lightbox.d.ts +10 -2
  393. package/types/ngwr-line-chart.d.ts +1 -1
  394. package/types/ngwr-list.d.ts +1 -1
  395. package/types/ngwr-loading-bar.d.ts +1 -1
  396. package/types/ngwr-marquee.d.ts +1 -1
  397. package/types/ngwr-media.d.ts +1 -1
  398. package/types/ngwr-mention.d.ts +1 -1
  399. package/types/ngwr-meta.d.ts +1 -1
  400. package/types/ngwr-meter-group.d.ts +1 -1
  401. package/types/ngwr-page-header.d.ts +1 -1
  402. package/types/ngwr-pagination.d.ts +4 -10
  403. package/types/ngwr-platform.d.ts +93 -2
  404. package/types/ngwr-popconfirm.d.ts +3 -3
  405. package/types/ngwr-progress.d.ts +2 -2
  406. package/types/ngwr-pull-to-refresh.d.ts +69 -0
  407. package/types/ngwr-qr.d.ts +1 -1
  408. package/types/ngwr-radio.d.ts +39 -25
  409. package/types/ngwr-rating.d.ts +32 -20
  410. package/types/ngwr-result.d.ts +1 -1
  411. package/types/ngwr-rotating-text.d.ts +1 -0
  412. package/types/ngwr-scroll.d.ts +1 -1
  413. package/types/ngwr-segmented.d.ts +6 -3
  414. package/types/ngwr-select.d.ts +98 -27
  415. package/types/ngwr-sidebar.d.ts +1 -1
  416. package/types/ngwr-skeleton.d.ts +2 -2
  417. package/types/ngwr-slider.d.ts +35 -21
  418. package/types/ngwr-sparkline.d.ts +1 -1
  419. package/types/ngwr-speed-dial.d.ts +8 -2
  420. package/types/ngwr-spinner.d.ts +1 -1
  421. package/types/ngwr-splitter.d.ts +1 -1
  422. package/types/ngwr-spotlight-card.d.ts +1 -1
  423. package/types/ngwr-squircle.d.ts +1 -1
  424. package/types/ngwr-statistic.d.ts +75 -6
  425. package/types/ngwr-stepper.d.ts +2 -2
  426. package/types/ngwr-storage.d.ts +1 -1
  427. package/types/ngwr-switch.d.ts +24 -16
  428. package/types/ngwr-table.d.ts +417 -6
  429. package/types/ngwr-tabs.d.ts +1 -1
  430. package/types/ngwr-textarea.d.ts +45 -20
  431. package/types/ngwr-theme.d.ts +7 -2
  432. package/types/ngwr-tilt-card.d.ts +3 -0
  433. package/types/ngwr-timeline.d.ts +1 -1
  434. package/types/ngwr-toast.d.ts +8 -2
  435. package/types/ngwr-toolbar.d.ts +1 -1
  436. package/types/ngwr-tree.d.ts +100 -19
  437. package/types/ngwr-typography.d.ts +1 -1
  438. package/types/ngwr-validators.d.ts +4 -2
  439. package/types/ngwr-version.d.ts +1 -1
  440. package/types/ngwr-virtual-scroll.d.ts +1 -1
  441. package/types/ngwr-window.d.ts +1 -1
  442. package/typography/styles/_index.scss +11 -11
  443. package/virtual-scroll/styles/_index.scss +1 -1
  444. package/waves/styles/_index.scss +1 -1
  445. package/window/styles/_index.scss +26 -26
  446. package/fesm2022/ngwr-scramble-text.mjs +0 -165
  447. package/fesm2022/ngwr-scramble-text.mjs.map +0 -1
  448. package/scramble-text/scramble-text.scss +0 -1
  449. package/scramble-text/styles/_index.scss +0 -8
  450. package/types/ngwr-scramble-text.d.ts +0 -49
@@ -1,14 +1,12 @@
1
- import { coerceBooleanProperty } from '@angular/cdk/coercion';
1
+ import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
2
2
  import { ScrollStrategyOptions } from '@angular/cdk/overlay';
3
3
  import { TemplatePortal } from '@angular/cdk/portal';
4
- import { NgTemplateOutlet } from '@angular/common';
4
+ import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
5
5
  import * as i0 from '@angular/core';
6
- import { input, model, inject, ElementRef, ViewContainerRef, DestroyRef, signal, computed, viewChild, TemplateRef, effect, forwardRef, ViewEncapsulation, Component } from '@angular/core';
6
+ import { input, model, output, inject, ElementRef, ViewContainerRef, DestroyRef, PLATFORM_ID, signal, computed, viewChild, TemplateRef, effect, untracked, ViewEncapsulation, Component } from '@angular/core';
7
7
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
8
- import { NG_VALUE_ACCESSOR } from '@angular/forms';
9
8
  import { readI18nText, useI18nFormatter } from 'ngwr/i18n';
10
9
  import { WR_OVERLAY } from 'ngwr/overlay';
11
- import { noop } from 'ngwr/utils';
12
10
 
13
11
  /**
14
12
  * @license
@@ -27,9 +25,11 @@ let panelUid = 0;
27
25
  * - `'inline'` (default) — renders the tree list in-place. Use as a display
28
26
  * widget or form-less hierarchical picker.
29
27
  * - `'overlay'` — renders a `<wr-select>`-style trigger button (with chips
30
- * in multi mode) that opens a popover containing the tree. Acts as a
31
- * `ControlValueAccessor` — bind via `[(ngModel)]`, `[formControl]`, or
32
- * `formControlName`. Replaces the standalone `<wr-tree-select>`.
28
+ * in multi mode) that opens a popover containing the tree. A signal-forms
29
+ * native control: it implements `FormValueControl<unknown>`, so `[formField]`
30
+ * binds straight to its `value` model — no `ControlValueAccessor` in between.
31
+ * `[(value)]` and classic `[(ngModel)]` / reactive forms all keep working via
32
+ * Angular's bridge. Replaces the standalone `<wr-tree-select>`.
33
33
  *
34
34
  * Value type in `overlay` mode: `TId | null` in single mode,
35
35
  * `readonly TId[]` in multi mode.
@@ -39,17 +39,20 @@ let panelUid = 0;
39
39
  * <!-- Inline tree (display widget) -->
40
40
  * <wr-tree [nodes]="folders" [(selected)]="picked" [(expanded)]="open" />
41
41
  *
42
- * <!-- Form-bound combobox -->
42
+ * <!-- Form-bound combobox (signal forms) -->
43
43
  * <wr-tree
44
44
  * openOn="overlay"
45
45
  * [nodes]="folders"
46
46
  * selectionMode="single"
47
- * [(ngModel)]="picked"
47
+ * [formField]="form.folder"
48
48
  * placeholder="Pick a folder"
49
49
  * />
50
+ *
51
+ * <!-- standalone two-way binding -->
52
+ * <wr-tree openOn="overlay" [nodes]="folders" [(value)]="picked" placeholder="Pick a folder" />
50
53
  * ```
51
54
  *
52
- * @see https://ngwr.dev/components/tree
55
+ * @see https://ngwr.dev/reference/components/tree
53
56
  */
54
57
  class WrTree {
55
58
  /** Tree data. */
@@ -64,7 +67,12 @@ class WrTree {
64
67
  /** Selection behavior. @default 'single' */
65
68
  selectionMode = input('single', /* @ts-ignore */
66
69
  ...(ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []));
67
- /** Disable the whole tree. @default false */
70
+ /**
71
+ * Disable the whole tree. Bound automatically from the field's disabled
72
+ * state when used with `[formField]`.
73
+ *
74
+ * @default false
75
+ */
68
76
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
69
77
  // Overlay-mode inputs (ignored when openOn='inline')
70
78
  /** Render shape. @default 'inline' */
@@ -83,12 +91,48 @@ class WrTree {
83
91
  maxTagCount = input(0, { ...(ngDevMode ? { debugName: "maxTagCount" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, Number(v) || 0) });
84
92
  /** Auto-expand every node that has children on first open of the overlay. @default false */
85
93
  defaultExpandAll = input(false, { ...(ngDevMode ? { debugName: "defaultExpandAll" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
94
+ /**
95
+ * Window the visible-node list so a large tree keeps only ~one viewport of
96
+ * rows in the DOM. Opt-in and OFF by default — a tree without it renders
97
+ * byte-identically to today. Works in both `inline` and `overlay` shapes;
98
+ * while on, keyboard navigation switches to the `aria-activedescendant`
99
+ * pattern so Arrow / Home / End / Enter keep working across un-rendered rows.
100
+ * @default false
101
+ */
102
+ virtualScroll = input(false, { ...(ngDevMode ? { debugName: "virtualScroll" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
103
+ /**
104
+ * Uniform row height in px used to map scroll offset to node index. `0`
105
+ * (default) measures the first rendered row once and reuses it, so it adapts
106
+ * to the active density / touch target automatically. Read only when
107
+ * `virtualScroll` is on. @default 0
108
+ */
109
+ rowHeight = input(0, { ...(ngDevMode ? { debugName: "rowHeight" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, coerceNumberProperty(v, 0)) });
110
+ /**
111
+ * Height of the scroll viewport when `virtualScroll` is on — a number (px) or
112
+ * any CSS length (`'60vh'`). A numeric px value lets the server prerender the
113
+ * exact first window. @default 288
114
+ */
115
+ viewportHeight = input(288, /* @ts-ignore */
116
+ ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
117
+ /** Extra rows kept rendered above and below the viewport as scroll headroom. @default 6 */
118
+ overscan = input(6, { ...(ngDevMode ? { debugName: "overscan" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, coerceNumberProperty(v, 6)) });
119
+ /**
120
+ * Form value — the current selection as seen by a bound field. Bound by
121
+ * `[formField]`, or two-way via `[(value)]`. Shape follows `selectionMode`:
122
+ * `TId | null` in single mode, `readonly TId[]` in multi mode. Meaningful in
123
+ * `overlay` mode; inline mode drives selection via `[(selected)]` instead.
124
+ */
125
+ value = model(undefined, /* @ts-ignore */
126
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
127
+ /** Emitted on blur so a bound field can mark itself touched. */
128
+ touch = output();
86
129
  // Internals
87
130
  host = inject(ElementRef);
88
131
  overlay = inject(WR_OVERLAY);
89
132
  vcr = inject(ViewContainerRef);
90
133
  scrollStrategies = inject(ScrollStrategyOptions);
91
134
  destroyRef = inject(DestroyRef);
135
+ platformId = inject(PLATFORM_ID);
92
136
  /** Currently focused row's index in the flattened visible list. */
93
137
  focusedIndex = signal(0, /* @ts-ignore */
94
138
  ...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
@@ -102,12 +146,12 @@ class WrTree {
102
146
  const expanded = new Set(this.expanded());
103
147
  const out = [];
104
148
  const walk = (list, depth) => {
105
- for (const node of list) {
149
+ list.forEach((node, i) => {
106
150
  const hasChildren = (node.children?.length ?? 0) > 0;
107
- out.push({ node, depth, hasChildren });
151
+ out.push({ node, depth, hasChildren, index: out.length, posinset: i + 1, setsize: list.length });
108
152
  if (hasChildren && expanded.has(node.id))
109
153
  walk(node.children, depth + 1);
110
- }
154
+ });
111
155
  };
112
156
  walk(this.nodes(), 0);
113
157
  return out;
@@ -168,13 +212,9 @@ class WrTree {
168
212
  ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
169
213
  /** Trigger / panel id for `aria-controls`. */
170
214
  panelId = `wr-tree-panel-${++panelUid}`;
171
- disabledFromCva = signal(false, /* @ts-ignore */
172
- ...(ngDevMode ? [{ debugName: "disabledFromCva" }] : /* istanbul ignore next */ []));
173
- isDisabled = computed(() => this.disabled() || this.disabledFromCva(), /* @ts-ignore */
174
- ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
175
215
  classes = computed(() => {
176
216
  const parts = ['wr-tree'];
177
- if (this.isDisabled())
217
+ if (this.disabled())
178
218
  parts.push('wr-tree--disabled');
179
219
  if (this.isOverlay()) {
180
220
  parts.push('wr-tree--combobox');
@@ -188,10 +228,103 @@ class WrTree {
188
228
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
189
229
  panelTpl = viewChild('panelTpl', { ...(ngDevMode ? { debugName: "panelTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
190
230
  overlayRef = null;
191
- // ControlValueAccessor
192
- onChange = noop;
193
- /** @internal exposed so the trigger can fire on blur. */
194
- onTouched = noop;
231
+ // --- Virtual scroll -------------------------------------------------------
232
+ static FALLBACK_ROW_PX = 32;
233
+ static FALLBACK_VIEWPORT_PX = 288;
234
+ /** Live vertical scroll offset (px); 0 on the server / before first scroll. */
235
+ scrollTop = signal(0, /* @ts-ignore */
236
+ ...(ngDevMode ? [{ debugName: "scrollTop" }] : /* istanbul ignore next */ []));
237
+ /** Measured viewport clientHeight (px); 0 until the browser observer fires. */
238
+ viewportPx = signal(0, /* @ts-ignore */
239
+ ...(ngDevMode ? [{ debugName: "viewportPx" }] : /* istanbul ignore next */ []));
240
+ /** Measured first-row height (px) when `rowHeight` is auto; 0 until measured. */
241
+ measuredRowPx = signal(0, /* @ts-ignore */
242
+ ...(ngDevMode ? [{ debugName: "measuredRowPx" }] : /* istanbul ignore next */ []));
243
+ /** Virtualization active (opt-in and there is anything to window). */
244
+ virtualized = computed(() => this.virtualScroll() && this.flat().length > 0, /* @ts-ignore */
245
+ ...(ngDevMode ? [{ debugName: "virtualized" }] : /* istanbul ignore next */ []));
246
+ /** Effective uniform row height (px). */
247
+ effRowH = computed(() => this.rowHeight() > 0 ? this.rowHeight() : this.measuredRowPx() || WrTree.FALLBACK_ROW_PX, /* @ts-ignore */
248
+ ...(ngDevMode ? [{ debugName: "effRowH" }] : /* istanbul ignore next */ []));
249
+ /** Deterministic viewport px for SSR + first paint (numeric height, else fallback). */
250
+ fallbackViewportPx = computed(() => {
251
+ const h = this.viewportHeight();
252
+ if (typeof h === 'number')
253
+ return h;
254
+ return /^\d+$/.test(h) ? Number(h) : WrTree.FALLBACK_VIEWPORT_PX;
255
+ }, /* @ts-ignore */
256
+ ...(ngDevMode ? [{ debugName: "fallbackViewportPx" }] : /* istanbul ignore next */ []));
257
+ /** `viewportHeight` as a CSS length for the inline max-height (bare number → px). */
258
+ resolvedViewportHeight = computed(() => {
259
+ const h = this.viewportHeight();
260
+ return typeof h === 'number' || /^\d+$/.test(h) ? `${h}px` : h;
261
+ }, /* @ts-ignore */
262
+ ...(ngDevMode ? [{ debugName: "resolvedViewportHeight" }] : /* istanbul ignore next */ []));
263
+ /** Rendered window [start,end) + spacer pads (px). Pure math from `scrollTop`. */
264
+ virtualWindow = computed(() => {
265
+ const total = this.flat().length;
266
+ if (!this.virtualized() || total === 0)
267
+ return { start: 0, end: total, padTop: 0, padBottom: 0 };
268
+ const h = this.effRowH();
269
+ const vp = this.viewportPx() || this.fallbackViewportPx();
270
+ const over = this.overscan();
271
+ // Clamp `first` so a transient effRowH shrink (auto-measure landing below the
272
+ // fallback within one frame) can't push it past the list and slice to empty.
273
+ const first = Math.min(Math.floor(this.scrollTop() / h), total - 1);
274
+ // `+ 1` covers the partial row at the viewport's bottom edge even at overscan 0.
275
+ const count = Math.ceil(vp / h) + 1;
276
+ const start = Math.max(0, first - over);
277
+ const end = Math.min(total, first + count + over);
278
+ return { start, end, padTop: start * h, padBottom: (total - end) * h };
279
+ }, /* @ts-ignore */
280
+ ...(ngDevMode ? [{ debugName: "virtualWindow" }] : /* istanbul ignore next */ []));
281
+ /** Nodes placed in the list. SAME array instance as `flat()` when off → byte-identical DOM. */
282
+ windowRows = computed(() => {
283
+ if (!this.virtualized())
284
+ return this.flat();
285
+ const { start, end } = this.virtualWindow();
286
+ return this.flat().slice(start, end);
287
+ }, /* @ts-ignore */
288
+ ...(ngDevMode ? [{ debugName: "windowRows" }] : /* istanbul ignore next */ []));
289
+ /** Stable id for a row at flat index `i` — the `aria-activedescendant` target. */
290
+ rowId(i) {
291
+ return `${this.panelId}-row-${i}`;
292
+ }
293
+ /**
294
+ * Active-descendant id when virtualized (focus stays on the list container),
295
+ * else `null`. Returns `null` while the focused row is outside the rendered
296
+ * window (e.g. mouse-wheeled away) so `aria-activedescendant` never dangles at
297
+ * a removed element — the next arrow key scrolls it back and re-establishes it.
298
+ */
299
+ activeRowId = computed(() => {
300
+ if (!this.virtualized())
301
+ return null;
302
+ const i = this.focusedIndex();
303
+ const { start, end } = this.virtualWindow();
304
+ return i >= start && i < end ? this.rowId(i) : null;
305
+ }, /* @ts-ignore */
306
+ ...(ngDevMode ? [{ debugName: "activeRowId" }] : /* istanbul ignore next */ []));
307
+ /** The scrollable `<ul>` — inside the overlay panel in overlay mode, else in the host. */
308
+ get listElement() {
309
+ const root = this.overlayRef?.overlayElement ?? this.host.nativeElement;
310
+ return root.querySelector('.wr-tree__list');
311
+ }
312
+ /** Scroll flat index `i` just into view (sets the `scrollTop` signal synchronously). */
313
+ ensureVisible(i) {
314
+ const h = this.effRowH();
315
+ const vp = this.viewportPx() || this.fallbackViewportPx();
316
+ const top = i * h;
317
+ const cur = this.scrollTop();
318
+ let next = cur;
319
+ if (top < cur)
320
+ next = top;
321
+ else if (top + h > cur + vp)
322
+ next = top + h - vp;
323
+ if (next !== cur) {
324
+ this.scrollTop.set(next);
325
+ this.listElement?.scrollTo({ top: next });
326
+ }
327
+ }
195
328
  constructor() {
196
329
  // Drive the overlay open/close in response to the `open` signal.
197
330
  effect(() => {
@@ -207,49 +340,114 @@ class WrTree {
207
340
  this.closeOverlay();
208
341
  }
209
342
  });
343
+ // Disabling the control closes any open overlay (mirrors the side effect
344
+ // of the old CVA setDisabledState).
345
+ effect(() => {
346
+ if (this.disabled())
347
+ this.open.set(false);
348
+ });
349
+ // Bridge an external `value` write back into the internal `selected`
350
+ // state (this is the old writeValue body). `undefined` is the untouched
351
+ // sentinel — no field / ngModel has written yet, so leave any preset
352
+ // `[(selected)]` alone; a real `null` still clears, exactly as
353
+ // `writeValue(null)` did. Guarded against the echo of our own `emit()`
354
+ // (equality check under `untracked`) so a live pick is never clobbered.
355
+ effect(() => {
356
+ const value = this.value();
357
+ if (value === undefined)
358
+ return;
359
+ untracked(() => {
360
+ const next = this.isMulti()
361
+ ? Array.isArray(value)
362
+ ? value
363
+ : []
364
+ : value == null
365
+ ? []
366
+ : [value];
367
+ const current = this.selected();
368
+ if (next.length === current.length && next.every((id, i) => id === current[i]))
369
+ return;
370
+ this.selected.set(next);
371
+ });
372
+ });
373
+ // Wire the scroll listener + viewport/row measurement — only while virtual
374
+ // and in the browser. Re-runs when the list (re)appears (overlay open, data
375
+ // change), deferring the DOM read to a microtask so the portal / inline list
376
+ // is attached. No-op on the server (SSR renders the deterministic first
377
+ // window from inputs alone).
378
+ effect(onCleanup => {
379
+ if (!isPlatformBrowser(this.platformId) || !this.virtualScroll())
380
+ return;
381
+ const open = this.isOverlay() ? this.open() : true;
382
+ this.flat();
383
+ if (!open)
384
+ return;
385
+ let raf = 0;
386
+ let ro = null;
387
+ let el = null;
388
+ const onScroll = () => {
389
+ if (raf)
390
+ return;
391
+ raf = requestAnimationFrame(() => {
392
+ raf = 0;
393
+ if (el)
394
+ this.scrollTop.set(el.scrollTop);
395
+ });
396
+ };
397
+ queueMicrotask(() => {
398
+ el = this.listElement;
399
+ if (!el)
400
+ return;
401
+ // The overlay `<ul>` is destroyed + recreated on each open, but the
402
+ // `scrollTop` signal persists — restore the fresh element to it so a
403
+ // reopened panel isn't blank (window computed from a non-zero signal
404
+ // while the new DOM sits at scrollTop 0). No-op on first open / inline.
405
+ if (el.scrollTop !== this.scrollTop())
406
+ el.scrollTop = this.scrollTop();
407
+ this.viewportPx.set(el.clientHeight);
408
+ if (this.rowHeight() === 0) {
409
+ const h = el.querySelector('.wr-tree__row')?.offsetHeight ?? 0;
410
+ if (h > 0)
411
+ this.measuredRowPx.set(h);
412
+ }
413
+ el.addEventListener('scroll', onScroll, { passive: true });
414
+ if (typeof ResizeObserver !== 'undefined') {
415
+ ro = new ResizeObserver(() => {
416
+ if (el)
417
+ this.viewportPx.set(el.clientHeight);
418
+ });
419
+ ro.observe(el);
420
+ }
421
+ });
422
+ onCleanup(() => {
423
+ if (raf)
424
+ cancelAnimationFrame(raf);
425
+ if (el)
426
+ el.removeEventListener('scroll', onScroll);
427
+ ro?.disconnect();
428
+ });
429
+ });
210
430
  this.destroyRef.onDestroy(() => this.closeOverlay());
211
431
  }
212
- writeValue(value) {
213
- if (this.isMulti()) {
214
- this.selected.set(Array.isArray(value) ? value : []);
215
- }
216
- else if (value == null) {
217
- this.selected.set([]);
218
- }
219
- else {
220
- this.selected.set([value]);
221
- }
222
- }
223
- registerOnChange(fn) {
224
- this.onChange = fn;
225
- }
226
- registerOnTouched(fn) {
227
- this.onTouched = fn;
228
- }
229
- setDisabledState(isDisabled) {
230
- this.disabledFromCva.set(coerceBooleanProperty(isDisabled));
231
- if (isDisabled)
232
- this.open.set(false);
233
- }
234
432
  // Template handlers
235
433
  onRowClick(flat, event) {
236
- if (this.isDisabled() || flat.node.disabled)
434
+ if (this.disabled() || flat.node.disabled)
237
435
  return;
238
436
  if (flat.hasChildren && event.target.closest('.wr-tree__toggle')) {
239
437
  this.toggleExpanded(flat.node.id);
240
438
  return;
241
439
  }
242
- this.focusIndex(this.flat().indexOf(flat));
440
+ this.focusIndex(flat.index);
243
441
  this.select(flat.node.id, event.ctrlKey || event.metaKey);
244
442
  }
245
443
  onToggleClick(node, event) {
246
444
  event.stopPropagation();
247
- if (this.isDisabled() || node.disabled)
445
+ if (this.disabled() || node.disabled)
248
446
  return;
249
447
  this.toggleExpanded(node.id);
250
448
  }
251
449
  onKeydown(event) {
252
- if (this.isDisabled())
450
+ if (this.disabled())
253
451
  return;
254
452
  const flat = this.flat();
255
453
  const i = this.focusedIndex();
@@ -308,13 +506,17 @@ class WrTree {
308
506
  }
309
507
  // Overlay-mode trigger handlers
310
508
  onTriggerClick() {
311
- if (this.isDisabled())
509
+ if (this.disabled())
312
510
  return;
313
511
  this.open.update(v => !v);
314
512
  }
513
+ /** Trigger blur — mark the bound field touched. */
514
+ onBlur() {
515
+ this.touch.emit();
516
+ }
315
517
  removeChip(id, event) {
316
518
  event.stopPropagation();
317
- if (this.isDisabled())
519
+ if (this.disabled())
318
520
  return;
319
521
  const next = this.selected().filter(x => x !== id);
320
522
  this.selected.set(next);
@@ -322,16 +524,10 @@ class WrTree {
322
524
  }
323
525
  clearSelection(event) {
324
526
  event.stopPropagation();
325
- if (this.isDisabled())
527
+ if (this.disabled())
326
528
  return;
327
529
  this.selected.set([]);
328
- if (this.isMulti()) {
329
- this.onChange([]);
330
- }
331
- else {
332
- this.onChange(null);
333
- }
334
- this.onTouched();
530
+ this.emit();
335
531
  }
336
532
  // Selection / expansion plumbing
337
533
  toggleExpanded(id) {
@@ -368,7 +564,7 @@ class WrTree {
368
564
  }
369
565
  this.selected.set([...set]);
370
566
  }
371
- // Overlay mode: propagate to CVA, close on single-mode pick.
567
+ // Overlay mode: propagate to the bound value, close on single-mode pick.
372
568
  if (this.isOverlay()) {
373
569
  this.emit();
374
570
  if (mode === 'single' && this.selected().length > 0) {
@@ -377,17 +573,27 @@ class WrTree {
377
573
  }
378
574
  }
379
575
  emit() {
380
- this.onTouched();
576
+ this.touch.emit();
381
577
  if (this.isMulti()) {
382
- this.onChange(this.selected());
578
+ this.value.set(this.selected());
383
579
  }
384
580
  else {
385
- this.onChange(this.selected()[0] ?? null);
581
+ this.value.set(this.selected()[0] ?? null);
386
582
  }
387
583
  }
388
584
  focusIndex(i) {
389
585
  this.focusedIndex.set(i);
390
- // Defer to next frame so the DOM has updated row classes/tabindex.
586
+ if (this.virtualized()) {
587
+ // Managed-focus (aria-activedescendant): focus stays on the list container.
588
+ // Setting `scrollTop` synchronously materializes row `i` in the SAME change
589
+ // detection pass, so the id referenced by `aria-activedescendant` is present
590
+ // — no rAF/microtask race, no "points at an absent id" gap.
591
+ this.ensureVisible(i);
592
+ this.listElement?.focus();
593
+ return;
594
+ }
595
+ // Non-virtual roving tabindex: defer so the DOM has updated tabindex, then
596
+ // move focus to the row element.
391
597
  queueMicrotask(() => {
392
598
  const root = this.overlayRef?.overlayElement ?? this.host.nativeElement;
393
599
  const row = root.querySelector(`[data-tree-index="${i}"]`);
@@ -429,6 +635,10 @@ class WrTree {
429
635
  panelClass: 'wr-tree-overlay',
430
636
  });
431
637
  this.overlayRef.attach(new TemplatePortal(tpl, this.vcr));
638
+ // Virtual mode drives keyboard nav via aria-activedescendant on the list
639
+ // container, so it must hold focus once the panel is attached.
640
+ if (this.virtualized())
641
+ queueMicrotask(() => this.listElement?.focus());
432
642
  this.overlayRef
433
643
  .outsidePointerEvents()
434
644
  .pipe(takeUntilDestroyed(this.destroyRef))
@@ -453,27 +663,13 @@ class WrTree {
453
663
  this.overlayRef.dispose();
454
664
  this.overlayRef = null;
455
665
  }
456
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTree, deps: [], target: i0.ɵɵFactoryTarget.Component });
457
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrTree, isStandalone: true, selector: "wr-tree", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, openOn: { classPropertyName: "openOn", publicName: "openOn", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, maxTagCount: { classPropertyName: "maxTagCount", publicName: "maxTagCount", isSignal: true, isRequired: false, transformFunction: null }, defaultExpandAll: { classPropertyName: "defaultExpandAll", publicName: "defaultExpandAll", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", expanded: "expandedChange" }, host: { properties: { "class": "classes()" } }, providers: [
458
- {
459
- provide: NG_VALUE_ACCESSOR,
460
- // eslint-disable-next-line @angular-eslint/no-forward-ref
461
- useExisting: forwardRef(() => WrTree),
462
- multi: true,
463
- },
464
- ], viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "@if (isOverlay()) {\n <button\n type=\"button\"\n class=\"wr-tree__trigger\"\n role=\"combobox\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'tree'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n (click)=\"onTriggerClick()\"\n (blur)=\"onTouched()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-tree__chips\">\n @for (chip of visibleChips(); track chip.id) {\n <span class=\"wr-tree__chip\">\n <span class=\"wr-tree__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-tree__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.id, $event)\"\n (keydown.enter)=\"removeChip(chip.id, $event)\"\n (keydown.space)=\"removeChip(chip.id, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-tree__chip wr-tree__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n } @else {\n @if (singleLabel(); as label) {\n <span class=\"wr-tree__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n }\n\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-tree__clear\"\n role=\"button\"\n [attr.aria-label]=\"clearLabel\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n (keydown.enter)=\"clearSelection($event)\"\n (keydown.space)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-tree__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n <!-- Tree list lives inside the overlay panel. -->\n <ng-template #panelTpl>\n <div class=\"wr-tree-panel\" [attr.id]=\"panelId\">\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n </div>\n </ng-template>\n} @else {\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n}\n\n<!-- Shared row list \u2014 rendered inline (default) or projected into the\n overlay panel (when openOn=\"overlay\"). -->\n<ng-template #listTpl>\n <!-- Roving tabindex: the tree owns keyboard focus and routes arrow keys\n to its currently-focused row. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <ul class=\"wr-tree__list\" role=\"tree\" (keydown)=\"onKeydown($event)\">\n @for (entry of flat(); track entry.node.id) {\n <!-- Click handler lives on focusable rows; keyboard handling is owned\n by the parent <ul> via the roving-tabindex pattern. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <li\n class=\"wr-tree__row\"\n role=\"treeitem\"\n [class.wr-tree__row--selected]=\"selectedSet().has(entry.node.id)\"\n [class.wr-tree__row--disabled]=\"entry.node.disabled\"\n [attr.aria-level]=\"entry.depth + 1\"\n [attr.aria-expanded]=\"entry.hasChildren ? expandedSet().has(entry.node.id) : null\"\n [attr.aria-selected]=\"selectionMode() === 'none' ? null : selectedSet().has(entry.node.id)\"\n [attr.aria-disabled]=\"entry.node.disabled || isDisabled() || null\"\n [attr.data-tree-index]=\"$index\"\n [attr.tabindex]=\"$index === focusedIndex() ? 0 : -1\"\n [style.--wr-tree-depth]=\"entry.depth\"\n (click)=\"onRowClick(entry, $event)\"\n >\n @if (entry.hasChildren) {\n <button\n type=\"button\"\n class=\"wr-tree__toggle\"\n tabindex=\"-1\"\n [attr.aria-label]=\"expandedSet().has(entry.node.id) ? collapseLabel : expandLabel\"\n (click)=\"onToggleClick(entry.node, $event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M3 1 L7 5 L3 9 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <span class=\"wr-tree__toggle wr-tree__toggle--leaf\" aria-hidden=\"true\"></span>\n }\n <span class=\"wr-tree__label\">{{ entry.node.label }}</span>\n </li>\n }\n </ul>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None });
666
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrTree, deps: [], target: i0.ɵɵFactoryTarget.Component });
667
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrTree, isStandalone: true, selector: "wr-tree", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, openOn: { classPropertyName: "openOn", publicName: "openOn", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, maxTagCount: { classPropertyName: "maxTagCount", publicName: "maxTagCount", isSignal: true, isRequired: false, transformFunction: null }, defaultExpandAll: { classPropertyName: "defaultExpandAll", publicName: "defaultExpandAll", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, viewportHeight: { classPropertyName: "viewportHeight", publicName: "viewportHeight", isSignal: true, isRequired: false, transformFunction: null }, overscan: { classPropertyName: "overscan", publicName: "overscan", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", expanded: "expandedChange", value: "valueChange", touch: "touch" }, host: { properties: { "class": "classes()" } }, viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "@if (isOverlay()) {\n <button\n type=\"button\"\n class=\"wr-tree__trigger\"\n role=\"combobox\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'tree'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n (click)=\"onTriggerClick()\"\n (blur)=\"onBlur()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-tree__chips\">\n @for (chip of visibleChips(); track chip.id) {\n <span class=\"wr-tree__chip\">\n <span class=\"wr-tree__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-tree__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.id, $event)\"\n (keydown.enter)=\"removeChip(chip.id, $event)\"\n (keydown.space)=\"removeChip(chip.id, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-tree__chip wr-tree__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n } @else {\n @if (singleLabel(); as label) {\n <span class=\"wr-tree__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n }\n\n @if (clearable() && hasSelection() && !disabled()) {\n <span\n class=\"wr-tree__clear\"\n role=\"button\"\n [attr.aria-label]=\"clearLabel\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n (keydown.enter)=\"clearSelection($event)\"\n (keydown.space)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-tree__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n <!-- Tree list lives inside the overlay panel. -->\n <ng-template #panelTpl>\n <div class=\"wr-tree-panel\" [class.wr-tree-panel--virtual]=\"virtualized()\" [attr.id]=\"panelId\">\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n </div>\n </ng-template>\n} @else {\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n}\n\n<!-- Shared row list \u2014 rendered inline (default) or projected into the\n overlay panel (when openOn=\"overlay\"). -->\n<ng-template #listTpl>\n <!-- Roving tabindex (non-virtual) / aria-activedescendant (virtual): the tree\n owns keyboard focus and routes arrow keys to its currently-focused row. -->\n <ul\n class=\"wr-tree__list\"\n role=\"tree\"\n [class.wr-tree__list--virtual]=\"virtualized()\"\n [attr.tabindex]=\"virtualized() ? 0 : null\"\n [attr.aria-activedescendant]=\"activeRowId()\"\n [style.max-height]=\"virtualized() ? resolvedViewportHeight() : null\"\n [style.overflow-y]=\"virtualized() ? 'auto' : null\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (virtualized() && virtualWindow().padTop > 0) {\n <li\n class=\"wr-tree__spacer\"\n role=\"presentation\"\n aria-hidden=\"true\"\n [style.height.px]=\"virtualWindow().padTop\"\n ></li>\n }\n @for (entry of windowRows(); track entry.node.id) {\n <!-- Click handler lives on focusable rows; keyboard handling is owned\n by the parent <ul> via the roving-tabindex pattern. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <li\n class=\"wr-tree__row\"\n role=\"treeitem\"\n [attr.id]=\"virtualized() ? rowId(entry.index) : null\"\n [class.wr-tree__row--selected]=\"selectedSet().has(entry.node.id)\"\n [class.wr-tree__row--active]=\"virtualized() && entry.index === focusedIndex()\"\n [class.wr-tree__row--disabled]=\"entry.node.disabled\"\n [attr.aria-level]=\"entry.depth + 1\"\n [attr.aria-setsize]=\"virtualized() ? entry.setsize : null\"\n [attr.aria-posinset]=\"virtualized() ? entry.posinset : null\"\n [attr.aria-expanded]=\"entry.hasChildren ? expandedSet().has(entry.node.id) : null\"\n [attr.aria-selected]=\"selectionMode() === 'none' ? null : selectedSet().has(entry.node.id)\"\n [attr.aria-disabled]=\"entry.node.disabled || disabled() || null\"\n [attr.data-tree-index]=\"entry.index\"\n [attr.tabindex]=\"virtualized() ? null : entry.index === focusedIndex() ? 0 : -1\"\n [style.--wr-tree-depth]=\"entry.depth\"\n (click)=\"onRowClick(entry, $event)\"\n >\n @if (entry.hasChildren) {\n <button\n type=\"button\"\n class=\"wr-tree__toggle\"\n tabindex=\"-1\"\n [attr.aria-label]=\"expandedSet().has(entry.node.id) ? collapseLabel : expandLabel\"\n (click)=\"onToggleClick(entry.node, $event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M3 1 L7 5 L3 9 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <span class=\"wr-tree__toggle wr-tree__toggle--leaf\" aria-hidden=\"true\"></span>\n }\n <span class=\"wr-tree__label\">{{ entry.node.label }}</span>\n </li>\n }\n @if (virtualized() && virtualWindow().padBottom > 0) {\n <li\n class=\"wr-tree__spacer\"\n role=\"presentation\"\n aria-hidden=\"true\"\n [style.height.px]=\"virtualWindow().padBottom\"\n ></li>\n }\n </ul>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None });
465
668
  }
466
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTree, decorators: [{
669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrTree, decorators: [{
467
670
  type: Component,
468
- args: [{ selector: 'wr-tree', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, imports: [NgTemplateOutlet], providers: [
469
- {
470
- provide: NG_VALUE_ACCESSOR,
471
- // eslint-disable-next-line @angular-eslint/no-forward-ref
472
- useExisting: forwardRef(() => WrTree),
473
- multi: true,
474
- },
475
- ], template: "@if (isOverlay()) {\n <button\n type=\"button\"\n class=\"wr-tree__trigger\"\n role=\"combobox\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'tree'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n (click)=\"onTriggerClick()\"\n (blur)=\"onTouched()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-tree__chips\">\n @for (chip of visibleChips(); track chip.id) {\n <span class=\"wr-tree__chip\">\n <span class=\"wr-tree__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-tree__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.id, $event)\"\n (keydown.enter)=\"removeChip(chip.id, $event)\"\n (keydown.space)=\"removeChip(chip.id, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-tree__chip wr-tree__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n } @else {\n @if (singleLabel(); as label) {\n <span class=\"wr-tree__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n }\n\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-tree__clear\"\n role=\"button\"\n [attr.aria-label]=\"clearLabel\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n (keydown.enter)=\"clearSelection($event)\"\n (keydown.space)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-tree__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n <!-- Tree list lives inside the overlay panel. -->\n <ng-template #panelTpl>\n <div class=\"wr-tree-panel\" [attr.id]=\"panelId\">\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n </div>\n </ng-template>\n} @else {\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n}\n\n<!-- Shared row list \u2014 rendered inline (default) or projected into the\n overlay panel (when openOn=\"overlay\"). -->\n<ng-template #listTpl>\n <!-- Roving tabindex: the tree owns keyboard focus and routes arrow keys\n to its currently-focused row. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <ul class=\"wr-tree__list\" role=\"tree\" (keydown)=\"onKeydown($event)\">\n @for (entry of flat(); track entry.node.id) {\n <!-- Click handler lives on focusable rows; keyboard handling is owned\n by the parent <ul> via the roving-tabindex pattern. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <li\n class=\"wr-tree__row\"\n role=\"treeitem\"\n [class.wr-tree__row--selected]=\"selectedSet().has(entry.node.id)\"\n [class.wr-tree__row--disabled]=\"entry.node.disabled\"\n [attr.aria-level]=\"entry.depth + 1\"\n [attr.aria-expanded]=\"entry.hasChildren ? expandedSet().has(entry.node.id) : null\"\n [attr.aria-selected]=\"selectionMode() === 'none' ? null : selectedSet().has(entry.node.id)\"\n [attr.aria-disabled]=\"entry.node.disabled || isDisabled() || null\"\n [attr.data-tree-index]=\"$index\"\n [attr.tabindex]=\"$index === focusedIndex() ? 0 : -1\"\n [style.--wr-tree-depth]=\"entry.depth\"\n (click)=\"onRowClick(entry, $event)\"\n >\n @if (entry.hasChildren) {\n <button\n type=\"button\"\n class=\"wr-tree__toggle\"\n tabindex=\"-1\"\n [attr.aria-label]=\"expandedSet().has(entry.node.id) ? collapseLabel : expandLabel\"\n (click)=\"onToggleClick(entry.node, $event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M3 1 L7 5 L3 9 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <span class=\"wr-tree__toggle wr-tree__toggle--leaf\" aria-hidden=\"true\"></span>\n }\n <span class=\"wr-tree__label\">{{ entry.node.label }}</span>\n </li>\n }\n </ul>\n</ng-template>\n" }]
476
- }], ctorParameters: () => [], propDecorators: { nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], openOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOn", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], maxTagCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTagCount", required: false }] }], defaultExpandAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultExpandAll", required: false }] }], panelTpl: [{ type: i0.ViewChild, args: ['panelTpl', { ...{ read: TemplateRef }, isSignal: true }] }] } });
671
+ args: [{ selector: 'wr-tree', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, imports: [NgTemplateOutlet], template: "@if (isOverlay()) {\n <button\n type=\"button\"\n class=\"wr-tree__trigger\"\n role=\"combobox\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'tree'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n (click)=\"onTriggerClick()\"\n (blur)=\"onBlur()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-tree__chips\">\n @for (chip of visibleChips(); track chip.id) {\n <span class=\"wr-tree__chip\">\n <span class=\"wr-tree__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-tree__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.id, $event)\"\n (keydown.enter)=\"removeChip(chip.id, $event)\"\n (keydown.space)=\"removeChip(chip.id, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-tree__chip wr-tree__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n } @else {\n @if (singleLabel(); as label) {\n <span class=\"wr-tree__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-tree__placeholder\">{{ placeholder() }}</span>\n }\n }\n\n @if (clearable() && hasSelection() && !disabled()) {\n <span\n class=\"wr-tree__clear\"\n role=\"button\"\n [attr.aria-label]=\"clearLabel\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n (keydown.enter)=\"clearSelection($event)\"\n (keydown.space)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-tree__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n <!-- Tree list lives inside the overlay panel. -->\n <ng-template #panelTpl>\n <div class=\"wr-tree-panel\" [class.wr-tree-panel--virtual]=\"virtualized()\" [attr.id]=\"panelId\">\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n </div>\n </ng-template>\n} @else {\n <ng-container [ngTemplateOutlet]=\"listTpl\" />\n}\n\n<!-- Shared row list \u2014 rendered inline (default) or projected into the\n overlay panel (when openOn=\"overlay\"). -->\n<ng-template #listTpl>\n <!-- Roving tabindex (non-virtual) / aria-activedescendant (virtual): the tree\n owns keyboard focus and routes arrow keys to its currently-focused row. -->\n <ul\n class=\"wr-tree__list\"\n role=\"tree\"\n [class.wr-tree__list--virtual]=\"virtualized()\"\n [attr.tabindex]=\"virtualized() ? 0 : null\"\n [attr.aria-activedescendant]=\"activeRowId()\"\n [style.max-height]=\"virtualized() ? resolvedViewportHeight() : null\"\n [style.overflow-y]=\"virtualized() ? 'auto' : null\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (virtualized() && virtualWindow().padTop > 0) {\n <li\n class=\"wr-tree__spacer\"\n role=\"presentation\"\n aria-hidden=\"true\"\n [style.height.px]=\"virtualWindow().padTop\"\n ></li>\n }\n @for (entry of windowRows(); track entry.node.id) {\n <!-- Click handler lives on focusable rows; keyboard handling is owned\n by the parent <ul> via the roving-tabindex pattern. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <li\n class=\"wr-tree__row\"\n role=\"treeitem\"\n [attr.id]=\"virtualized() ? rowId(entry.index) : null\"\n [class.wr-tree__row--selected]=\"selectedSet().has(entry.node.id)\"\n [class.wr-tree__row--active]=\"virtualized() && entry.index === focusedIndex()\"\n [class.wr-tree__row--disabled]=\"entry.node.disabled\"\n [attr.aria-level]=\"entry.depth + 1\"\n [attr.aria-setsize]=\"virtualized() ? entry.setsize : null\"\n [attr.aria-posinset]=\"virtualized() ? entry.posinset : null\"\n [attr.aria-expanded]=\"entry.hasChildren ? expandedSet().has(entry.node.id) : null\"\n [attr.aria-selected]=\"selectionMode() === 'none' ? null : selectedSet().has(entry.node.id)\"\n [attr.aria-disabled]=\"entry.node.disabled || disabled() || null\"\n [attr.data-tree-index]=\"entry.index\"\n [attr.tabindex]=\"virtualized() ? null : entry.index === focusedIndex() ? 0 : -1\"\n [style.--wr-tree-depth]=\"entry.depth\"\n (click)=\"onRowClick(entry, $event)\"\n >\n @if (entry.hasChildren) {\n <button\n type=\"button\"\n class=\"wr-tree__toggle\"\n tabindex=\"-1\"\n [attr.aria-label]=\"expandedSet().has(entry.node.id) ? collapseLabel : expandLabel\"\n (click)=\"onToggleClick(entry.node, $event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M3 1 L7 5 L3 9 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n } @else {\n <span class=\"wr-tree__toggle wr-tree__toggle--leaf\" aria-hidden=\"true\"></span>\n }\n <span class=\"wr-tree__label\">{{ entry.node.label }}</span>\n </li>\n }\n @if (virtualized() && virtualWindow().padBottom > 0) {\n <li\n class=\"wr-tree__spacer\"\n role=\"presentation\"\n aria-hidden=\"true\"\n [style.height.px]=\"virtualWindow().padBottom\"\n ></li>\n }\n </ul>\n</ng-template>\n" }]
672
+ }], ctorParameters: () => [], propDecorators: { nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], openOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOn", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], maxTagCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTagCount", required: false }] }], defaultExpandAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultExpandAll", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], viewportHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewportHeight", required: false }] }], overscan: [{ type: i0.Input, args: [{ isSignal: true, alias: "overscan", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }], panelTpl: [{ type: i0.ViewChild, args: ['panelTpl', { ...{ read: TemplateRef }, isSignal: true }] }] } });
477
673
 
478
674
  /**
479
675
  * Generated bundle index. Do not edit.