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,13 @@
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 { isPlatformBrowser } from '@angular/common';
4
5
  import * as i0 from '@angular/core';
5
- import { InjectionToken, input, inject, ElementRef, computed, effect, DestroyRef, ViewEncapsulation, Component, signal, viewChild, TemplateRef, ViewContainerRef, forwardRef } from '@angular/core';
6
+ import { InjectionToken, input, inject, ElementRef, computed, effect, DestroyRef, ViewEncapsulation, Component, signal, model, output, contentChildren, viewChild, TemplateRef, ViewContainerRef, PLATFORM_ID, forwardRef } from '@angular/core';
6
7
  import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
- import { NG_VALUE_ACCESSOR } from '@angular/forms';
8
8
  import { debounceTime, switchMap, of, isObservable, from, finalize } from 'rxjs';
9
9
  import { useI18nText, useI18nFormatter } from 'ngwr/i18n';
10
10
  import { WR_OVERLAY, WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet } from 'ngwr/overlay';
11
- import { noop } from 'ngwr/utils';
12
11
 
13
12
  /**
14
13
  * @license
@@ -120,10 +119,10 @@ class WrOption {
120
119
  return;
121
120
  this.parent.selectOption(this.value());
122
121
  }
123
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrOption, deps: [], target: i0.ɵɵFactoryTarget.Component });
124
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: WrOption, isStandalone: true, selector: "wr-option", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, listeners: { "click": "onClick()" }, properties: { "attr.id": "id", "class": "classes()", "attr.aria-selected": "selected()", "attr.aria-disabled": "disabled() ? true : null" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
122
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrOption, deps: [], target: i0.ɵɵFactoryTarget.Component });
123
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: WrOption, isStandalone: true, selector: "wr-option", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, listeners: { "click": "onClick()" }, properties: { "attr.id": "id", "class": "classes()", "attr.aria-selected": "selected()", "attr.aria-disabled": "disabled() ? true : null" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
125
124
  }
126
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrOption, decorators: [{
125
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrOption, decorators: [{
127
126
  type: Component,
128
127
  args: [{
129
128
  selector: 'wr-option',
@@ -161,20 +160,22 @@ let listboxUid = 0;
161
160
  * - `'tag'` — free-text + chips with `[separators]` / `[validate]` /
162
161
  * `[allowDuplicates]`. Replaces `<wr-chips-input>`.
163
162
  *
164
- * Implements `ControlValueAccessor` — usable with `[(ngModel)]`,
165
- * `formControl`, or `formControlName`.
163
+ * A signal-forms native control: it implements `FormValueControl<unknown>`, so
164
+ * `[formField]` binds straight to its `value` model — no
165
+ * `ControlValueAccessor` in between. `[(value)]` works standalone, and classic
166
+ * `[(ngModel)]` / reactive forms keep working through Angular's bridge.
166
167
  *
167
168
  * @example
168
169
  * ```html
169
- * <!-- Single -->
170
- * <wr-select placeholder="Pick a size" [(ngModel)]="size">
170
+ * <!-- Single (signal forms) -->
171
+ * <wr-select placeholder="Pick a size" [formField]="form.size">
171
172
  * <wr-option value="sm">Small</wr-option>
172
173
  * <wr-option value="md">Medium</wr-option>
173
174
  * <wr-option value="lg">Large</wr-option>
174
175
  * </wr-select>
175
176
  *
176
- * <!-- Multi -->
177
- * <wr-select mode="multi" placeholder="Pick tags" [(ngModel)]="tags">
177
+ * <!-- Multi (standalone two-way binding) -->
178
+ * <wr-select mode="multi" placeholder="Pick tags" [(value)]="tags">
178
179
  * <wr-option value="ts">TypeScript</wr-option>
179
180
  * <wr-option value="ng">Angular</wr-option>
180
181
  * </wr-select>
@@ -183,7 +184,7 @@ let listboxUid = 0;
183
184
  * The legacy `[multi]="true"` boolean is still accepted but is now an
184
185
  * alias for `[mode]="'multi'"` — prefer the explicit mode.
185
186
  *
186
- * @see https://ngwr.dev/components/select
187
+ * @see https://ngwr.dev/reference/components/select
187
188
  */
188
189
  class WrSelect {
189
190
  /** Placeholder shown when no option is selected. Falls back to `select.placeholder`. */
@@ -196,10 +197,18 @@ class WrSelect {
196
197
  resolvedClear = useI18nText(this.clearLabel, 'select.clearSelection', 'Clear selection');
197
198
  /** Per-chip ARIA label — interpolates `{{label}}`. @internal */
198
199
  chipRemoveLabel = useI18nFormatter('select.removeItem', 'Remove {{label}}');
199
- /** Disable the select. Also set by Angular forms via `setDisabledState`. */
200
+ /**
201
+ * Disable the select. Bound automatically from the field's disabled state
202
+ * when used with `[formField]`.
203
+ *
204
+ * @default false
205
+ */
200
206
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
201
207
  /** Pill-shaped corners on the trigger. @default false */
202
208
  rounded = input(false, { ...(ngDevMode ? { debugName: "rounded" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
209
+ /** Control size — shares the `--wr-control-*` contract. @default 'md' */
210
+ size = input('md', /* @ts-ignore */
211
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
203
212
  /**
204
213
  * Present the option panel as a full-width bottom-sheet on small
205
214
  * viewports instead of an anchored dropdown. `undefined` follows the
@@ -274,6 +283,29 @@ class WrSelect {
274
283
  * unmatched query commits the raw text as the form value. @default false
275
284
  */
276
285
  freeText = input(false, { ...(ngDevMode ? { debugName: "freeText" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
286
+ /**
287
+ * Search mode: window the option panel so thousands of `[options]` keep only
288
+ * ~one viewport of rows in the DOM. Opt-in and OFF by default. Engages ONLY on
289
+ * the pure data-array search tier — it silently falls back to the full render
290
+ * when static `<wr-option>` children are projected or the filtered list is
291
+ * empty. While on, rows are plain `role="option"` elements (no `<wr-option>`),
292
+ * navigated via `aria-activedescendant`, selected by value. @default false
293
+ */
294
+ virtualScroll = input(false, { ...(ngDevMode ? { debugName: "virtualScroll" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
295
+ /**
296
+ * Search mode: uniform option-row height in px for the virtual window. `0`
297
+ * (default) measures the first rendered row once and reuses it, so it adapts
298
+ * to the control size. Read only when `virtualScroll` engages. @default 0
299
+ */
300
+ rowHeight = input(0, { ...(ngDevMode ? { debugName: "rowHeight" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, coerceNumberProperty(v, 0)) });
301
+ /**
302
+ * Search mode: height of the virtual scroll viewport — a number (px) or any
303
+ * CSS length. @default 256
304
+ */
305
+ viewportHeight = input(256, /* @ts-ignore */
306
+ ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
307
+ /** Search mode: extra rows kept above/below the virtual viewport. @default 6 */
308
+ overscan = input(6, { ...(ngDevMode ? { debugName: "overscan" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, coerceNumberProperty(v, 6)) });
277
309
  /** Search mode: text shown when the filter / loader returns nothing. Falls back to `select.noResults`. */
278
310
  noResultsText = input(null, /* @ts-ignore */
279
311
  ...(ngDevMode ? [{ debugName: "noResultsText" }] : /* istanbul ignore next */ []));
@@ -323,13 +355,14 @@ class WrSelect {
323
355
  */
324
356
  maxTagCount = input(0, { ...(ngDevMode ? { debugName: "maxTagCount" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, Number(v) || 0) });
325
357
  /**
326
- * Unified value signal. Single mode holds `T | null`; multi mode
327
- * holds `readonly T[]`. Internal — consumers go through `[(ngModel)]`
328
- * or `[formControl]` via CVA.
329
- * @internal
358
+ * Unified value. Single mode holds a scalar (or `null`); multi / tag
359
+ * mode holds `readonly unknown[]`. Bound by `[formField]`, or two-way
360
+ * via `[(value)]`.
330
361
  */
331
- value = signal(null, /* @ts-ignore */
362
+ value = model(null, /* @ts-ignore */
332
363
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
364
+ /** Emitted on blur / commit so a bound field can mark itself touched. */
365
+ touch = output();
333
366
  /** Listbox id used by the trigger's `aria-controls`. */
334
367
  listboxId = `wr-select-listbox-${++listboxUid}`;
335
368
  /** Registered options (insertion order). Internal — distinct from the public `[options]` input. */
@@ -341,6 +374,13 @@ class WrSelect {
341
374
  /** Id of the active option (for `aria-activedescendant`). */
342
375
  activeOptionId = computed(() => {
343
376
  const idx = this.activeIndex();
377
+ if (this.virtualActive()) {
378
+ // Virtual rows aren't registered; the active id is derived from the index,
379
+ // and returned only while the row is inside the rendered window so
380
+ // `aria-activedescendant` never dangles at a recycled element.
381
+ const { start, end } = this.virtualWindow();
382
+ return idx >= start && idx < end ? this.virtualRowId(idx) : null;
383
+ }
344
384
  const list = this.registry();
345
385
  return idx >= 0 && idx < list.length ? list[idx].id : null;
346
386
  }, /* @ts-ignore */
@@ -386,10 +426,8 @@ class WrSelect {
386
426
  return this.value() != null;
387
427
  }, /* @ts-ignore */
388
428
  ...(ngDevMode ? [{ debugName: "hasSelection" }] : /* istanbul ignore next */ []));
389
- disabledFromCva = signal(false, /* @ts-ignore */
390
- ...(ngDevMode ? [{ debugName: "disabledFromCva" }] : /* istanbul ignore next */ []));
391
- /** Effective disabled state — input wins, CVA second. */
392
- isDisabled = computed(() => this.disabled() || this.disabledFromCva(), /* @ts-ignore */
429
+ /** Effective disabled state. Part of {@link WrSelectContext} for child options. */
430
+ isDisabled = computed(() => this.disabled(), /* @ts-ignore */
393
431
  ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
394
432
  classes = computed(() => {
395
433
  const parts = ['wr-select'];
@@ -397,6 +435,9 @@ class WrSelect {
397
435
  parts.push('wr-select--open');
398
436
  if (this.rounded())
399
437
  parts.push('wr-select--rounded');
438
+ const size = this.size();
439
+ if (size !== 'md')
440
+ parts.push(`wr-select--${size}`);
400
441
  if (this.isMulti())
401
442
  parts.push('wr-select--multi');
402
443
  if (this.isTag())
@@ -415,11 +456,117 @@ class WrSelect {
415
456
  */
416
457
  dynamicOptions = computed(() => this.loader() ? this.loadedOptions() : this.options(), /* @ts-ignore */
417
458
  ...(ngDevMode ? [{ debugName: "dynamicOptions" }] : /* istanbul ignore next */ []));
459
+ // --- Virtual scroll (search mode, data-array path) ------------------------
460
+ static FALLBACK_ROW_PX = 34;
461
+ static FALLBACK_VIEWPORT_PX = 256;
462
+ /** Consumer-projected `<wr-option>` children only (NOT the `@for`-rendered ones). */
463
+ projectedOptions = contentChildren(WrOption, /* @ts-ignore */
464
+ ...(ngDevMode ? [{ debugName: "projectedOptions" }] : /* istanbul ignore next */ []));
465
+ /**
466
+ * `dynamicOptions()` narrowed to the current search query. `dynamicOptions()`
467
+ * is intentionally UNFILTERED (projected `<wr-option>` self-hide via CSS), so
468
+ * the virtual path — which renders plain rows that can't self-hide — filters
469
+ * here. Loader results are already query-scoped upstream.
470
+ */
471
+ filteredDynamicOptions = computed(() => {
472
+ const items = this.dynamicOptions();
473
+ if (this.loader())
474
+ return items;
475
+ const q = this.searchQuery().trim().toLowerCase();
476
+ if (!q)
477
+ return items;
478
+ const label = this.displayWith();
479
+ return items.filter(it => label(it).toLowerCase().includes(q));
480
+ }, /* @ts-ignore */
481
+ ...(ngDevMode ? [{ debugName: "filteredDynamicOptions" }] : /* istanbul ignore next */ []));
482
+ /**
483
+ * Virtualization engaged: opt-in, search mode, a non-empty filtered array, and
484
+ * NO projected `<wr-option>` children (those keep the full-render registry path
485
+ * so their DOM-derived labels / selection still work).
486
+ */
487
+ virtualActive = computed(() => this.virtualScroll() &&
488
+ this.isSearch() &&
489
+ this.projectedOptions().length === 0 &&
490
+ this.filteredDynamicOptions().length > 0, /* @ts-ignore */
491
+ ...(ngDevMode ? [{ debugName: "virtualActive" }] : /* istanbul ignore next */ []));
492
+ scrollTop = signal(0, /* @ts-ignore */
493
+ ...(ngDevMode ? [{ debugName: "scrollTop" }] : /* istanbul ignore next */ []));
494
+ viewportPx = signal(0, /* @ts-ignore */
495
+ ...(ngDevMode ? [{ debugName: "viewportPx" }] : /* istanbul ignore next */ []));
496
+ measuredRowPx = signal(0, /* @ts-ignore */
497
+ ...(ngDevMode ? [{ debugName: "measuredRowPx" }] : /* istanbul ignore next */ []));
498
+ /** Effective uniform row height (px). */
499
+ effRowH = computed(() => this.rowHeight() > 0 ? this.rowHeight() : this.measuredRowPx() || WrSelect.FALLBACK_ROW_PX, /* @ts-ignore */
500
+ ...(ngDevMode ? [{ debugName: "effRowH" }] : /* istanbul ignore next */ []));
501
+ fallbackViewportPx = computed(() => {
502
+ const h = this.viewportHeight();
503
+ if (typeof h === 'number')
504
+ return h;
505
+ return /^\d+$/.test(h) ? Number(h) : WrSelect.FALLBACK_VIEWPORT_PX;
506
+ }, /* @ts-ignore */
507
+ ...(ngDevMode ? [{ debugName: "fallbackViewportPx" }] : /* istanbul ignore next */ []));
508
+ /** `viewportHeight` as a CSS length for the inline max-height (bare number → px). */
509
+ resolvedViewportHeight = computed(() => {
510
+ const h = this.viewportHeight();
511
+ return typeof h === 'number' || /^\d+$/.test(h) ? `${h}px` : h;
512
+ }, /* @ts-ignore */
513
+ ...(ngDevMode ? [{ debugName: "resolvedViewportHeight" }] : /* istanbul ignore next */ []));
514
+ /** Rendered window [start,end) + spacer pads (px). */
515
+ virtualWindow = computed(() => {
516
+ const total = this.filteredDynamicOptions().length;
517
+ if (!this.virtualActive() || total === 0)
518
+ return { start: 0, end: total, padTop: 0, padBottom: 0 };
519
+ const h = this.effRowH();
520
+ const vp = this.viewportPx() || this.fallbackViewportPx();
521
+ const over = this.overscan();
522
+ const first = Math.min(Math.floor(this.scrollTop() / h), total - 1);
523
+ const count = Math.ceil(vp / h) + 1;
524
+ const start = Math.max(0, first - over);
525
+ const end = Math.min(total, first + count + over);
526
+ return { start, end, padTop: start * h, padBottom: (total - end) * h };
527
+ }, /* @ts-ignore */
528
+ ...(ngDevMode ? [{ debugName: "virtualWindow" }] : /* istanbul ignore next */ []));
529
+ /** The windowed slice of options, each carrying its absolute index. */
530
+ windowOptions = computed(() => {
531
+ const { start, end } = this.virtualWindow();
532
+ return this.filteredDynamicOptions()
533
+ .slice(start, end)
534
+ .map((item, k) => ({ item, index: start + k }));
535
+ }, /* @ts-ignore */
536
+ ...(ngDevMode ? [{ debugName: "windowOptions" }] : /* istanbul ignore next */ []));
537
+ /** Stable id for a virtual option row at filtered index `i`. */
538
+ virtualRowId(i) {
539
+ return `${this.listboxId}-vopt-${i}`;
540
+ }
541
+ /** The virtual scroll container inside the overlay panel, if attached. */
542
+ get vlistElement() {
543
+ return this.overlayRef?.overlayElement.querySelector('.wr-select-panel__vlist') ?? null;
544
+ }
545
+ /** Scroll filtered index `i` just into view (sets the `scrollTop` signal synchronously). */
546
+ ensureVisible(i) {
547
+ if (!this.virtualActive() || i < 0)
548
+ return;
549
+ const h = this.effRowH();
550
+ const vp = this.viewportPx() || this.fallbackViewportPx();
551
+ const top = i * h;
552
+ const cur = this.scrollTop();
553
+ let next = cur;
554
+ if (top < cur)
555
+ next = top;
556
+ else if (top + h > cur + vp)
557
+ next = top + h - vp;
558
+ if (next !== cur) {
559
+ this.scrollTop.set(next);
560
+ this.vlistElement?.scrollTo({ top: next });
561
+ }
562
+ }
418
563
  /**
419
564
  * Count of registered options that pass the current search filter.
420
565
  * Hides the noResults state when the panel has at least one visible row.
421
566
  */
422
567
  visibleCount = computed(() => {
568
+ if (this.virtualActive())
569
+ return this.filteredDynamicOptions().length;
423
570
  const list = this.registry();
424
571
  if (!this.isSearch())
425
572
  return list.length;
@@ -452,7 +599,7 @@ class WrSelect {
452
599
  return false;
453
600
  return !label.toLowerCase().includes(q);
454
601
  }
455
- panelTpl = viewChild.required('panelTpl', { read: TemplateRef });
602
+ panelTpl = viewChild.required('panelTpl', { ...(ngDevMode ? { debugName: "panelTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
456
603
  /** Tag-mode inline input. Present only when `mode="tag"`. @internal */
457
604
  tagInputEl = viewChild('tagInput', /* @ts-ignore */
458
605
  ...(ngDevMode ? [{ debugName: "tagInputEl" }] : /* istanbul ignore next */ []));
@@ -473,6 +620,13 @@ class WrSelect {
473
620
  this.searchQuery.set(value);
474
621
  if (!this.open())
475
622
  this.open.set(true);
623
+ // A new filter re-tops the virtual window and cursor (the filtered array
624
+ // — hence every index — just changed under `activeIndex`).
625
+ if (this.virtualActive()) {
626
+ this.scrollTop.set(0);
627
+ this.activeIndex.set(this.firstEnabled());
628
+ this.vlistElement?.scrollTo({ top: 0 });
629
+ }
476
630
  }
477
631
  onSearchFocus() {
478
632
  if (this.isDisabled())
@@ -490,12 +644,13 @@ class WrSelect {
490
644
  const q = this.searchQuery().trim();
491
645
  const idx = this.activeIndex();
492
646
  const list = this.registry();
493
- const hasActive = idx >= 0 && idx < list.length && !list[idx].disabled && !this.isOptionHidden(list[idx].getLabel());
647
+ const hasActive = this.virtualActive()
648
+ ? idx >= 0 && idx < this.filteredDynamicOptions().length
649
+ : idx >= 0 && idx < list.length && !list[idx].disabled && !this.isOptionHidden(list[idx].getLabel());
494
650
  if (!hasActive && q) {
495
651
  event.preventDefault();
496
652
  this.value.set(q);
497
- this.onChange(q);
498
- this.onTouched();
653
+ this.touch.emit();
499
654
  this.open.set(false);
500
655
  return;
501
656
  }
@@ -520,9 +675,8 @@ class WrSelect {
520
675
  vcr = inject(ViewContainerRef);
521
676
  scrollStrategies = inject(ScrollStrategyOptions);
522
677
  destroyRef = inject(DestroyRef);
678
+ platformId = inject(PLATFORM_ID);
523
679
  overlayRef = null;
524
- onChange = noop;
525
- onTouched = noop;
526
680
  constructor() {
527
681
  effect(() => {
528
682
  if (this.open()) {
@@ -562,7 +716,70 @@ class WrSelect {
562
716
  return;
563
717
  }
564
718
  const match = list.find(o => o.value === v);
565
- this.selectedLabel.set(match ? match.getLabel() : null);
719
+ if (match) {
720
+ this.selectedLabel.set(match.getLabel());
721
+ return;
722
+ }
723
+ // Search mode: a value picked from a virtualized (or since-unmounted) row
724
+ // has no registered `<wr-option>`, so derive its label from `displayWith`
725
+ // — the same function that rendered the row.
726
+ this.selectedLabel.set(v != null && this.isSearch() ? this.displayWith()(v) : null);
727
+ });
728
+ // Wire the virtual scroll listener + viewport/row measurement while the panel
729
+ // is open and virtualized. Re-runs when the panel opens/closes or the virtual
730
+ // list mounts/unmounts; the microtask defers the DOM read until the overlay
731
+ // portal is attached. Browser-only — the panel never prerenders (overlay).
732
+ effect(onCleanup => {
733
+ if (!isPlatformBrowser(this.platformId))
734
+ return;
735
+ if (!this.open() || !this.virtualActive())
736
+ return;
737
+ let raf = 0;
738
+ let ro = null;
739
+ let el = null;
740
+ const onScroll = () => {
741
+ if (raf)
742
+ return;
743
+ raf = requestAnimationFrame(() => {
744
+ raf = 0;
745
+ if (el)
746
+ this.scrollTop.set(el.scrollTop);
747
+ });
748
+ };
749
+ queueMicrotask(() => {
750
+ el = this.vlistElement;
751
+ if (!el)
752
+ return;
753
+ this.viewportPx.set(el.clientHeight);
754
+ if (this.rowHeight() === 0) {
755
+ const h = el.querySelector('.wr-option')?.offsetHeight ?? 0;
756
+ if (h > 0)
757
+ this.measuredRowPx.set(h);
758
+ }
759
+ // Re-seed the scroll with the now-measured row height + real viewport so
760
+ // a deep pre-selected active row lands correctly on first open (the seed
761
+ // before open used the fallback height). No-op when it's already in view.
762
+ this.ensureVisible(this.activeIndex());
763
+ // Sync the freshly-attached element to the retained signal — seeds the
764
+ // scroll to the active option and avoids a blank panel on reopen.
765
+ if (el.scrollTop !== this.scrollTop())
766
+ el.scrollTop = this.scrollTop();
767
+ el.addEventListener('scroll', onScroll, { passive: true });
768
+ if (typeof ResizeObserver !== 'undefined') {
769
+ ro = new ResizeObserver(() => {
770
+ if (el)
771
+ this.viewportPx.set(el.clientHeight);
772
+ });
773
+ ro.observe(el);
774
+ }
775
+ });
776
+ onCleanup(() => {
777
+ if (raf)
778
+ cancelAnimationFrame(raf);
779
+ if (el)
780
+ el.removeEventListener('scroll', onScroll);
781
+ ro?.disconnect();
782
+ });
566
783
  });
567
784
  }
568
785
  // WrSelectContext
@@ -586,14 +803,12 @@ class WrSelect {
586
803
  next = [...current, value];
587
804
  }
588
805
  this.value.set(next);
589
- this.onChange(next);
590
- this.onTouched();
806
+ this.touch.emit();
591
807
  // Keep the panel open in multi mode so the user can keep picking.
592
808
  return;
593
809
  }
594
810
  this.value.set(value);
595
- this.onChange(value);
596
- this.onTouched();
811
+ this.touch.emit();
597
812
  this.open.set(false);
598
813
  }
599
814
  registerOption(reg) {
@@ -608,8 +823,7 @@ class WrSelect {
608
823
  return;
609
824
  const next = this.asArray(this.value()).filter(v => v !== value);
610
825
  this.value.set(next);
611
- this.onChange(next);
612
- this.onTouched();
826
+ this.touch.emit();
613
827
  }
614
828
  /** Clear every selection (× button). Multi/tag → empty array; search → null. */
615
829
  clearAll(event) {
@@ -618,17 +832,15 @@ class WrSelect {
618
832
  return;
619
833
  if (this.hasChips()) {
620
834
  this.value.set([]);
621
- this.onChange([]);
622
835
  }
623
836
  else if (this.isSearch()) {
624
837
  this.value.set(null);
625
- this.onChange(null);
626
838
  this.searchQuery.set('');
627
839
  }
628
840
  else {
629
841
  return;
630
842
  }
631
- this.onTouched();
843
+ this.touch.emit();
632
844
  }
633
845
  // Tag-mode draft handlers
634
846
  /** Capacity check used by tag mode to refuse the next add. */
@@ -677,7 +889,7 @@ class WrSelect {
677
889
  onTagBlur() {
678
890
  if (this.draft().trim())
679
891
  this.commitDraft();
680
- this.onTouched();
892
+ this.touch.emit();
681
893
  }
682
894
  commitDraft() {
683
895
  const v = this.draft().trim();
@@ -699,28 +911,7 @@ class WrSelect {
699
911
  return;
700
912
  const next = [...existing, value];
701
913
  this.value.set(next);
702
- this.onChange(next);
703
- this.onTouched();
704
- }
705
- // ControlValueAccessor
706
- writeValue(value) {
707
- if (this.hasChips()) {
708
- this.value.set(Array.isArray(value) ? value : []);
709
- }
710
- else {
711
- this.value.set(value);
712
- }
713
- }
714
- registerOnChange(fn) {
715
- this.onChange = fn;
716
- }
717
- registerOnTouched(fn) {
718
- this.onTouched = fn;
719
- }
720
- setDisabledState(isDisabled) {
721
- this.disabledFromCva.set(coerceBooleanProperty(isDisabled));
722
- if (isDisabled)
723
- this.open.set(false);
914
+ this.touch.emit();
724
915
  }
725
916
  // Template handlers
726
917
  onTriggerClick() {
@@ -766,15 +957,24 @@ class WrSelect {
766
957
  case 'Home':
767
958
  event.preventDefault();
768
959
  this.activeIndex.set(this.firstEnabled());
960
+ this.ensureVisible(this.activeIndex());
769
961
  break;
770
962
  case 'End':
771
963
  event.preventDefault();
772
964
  this.activeIndex.set(this.lastEnabled());
965
+ this.ensureVisible(this.activeIndex());
773
966
  break;
774
967
  case 'Enter':
775
968
  case ' ': {
776
969
  event.preventDefault();
777
970
  const idx = this.activeIndex();
971
+ if (this.virtualActive()) {
972
+ // Virtual rows aren't in the DOM to click — select the value directly.
973
+ const list = this.filteredDynamicOptions();
974
+ if (idx >= 0 && idx < list.length)
975
+ this.selectOption(list[idx]);
976
+ break;
977
+ }
778
978
  const list = this.registry();
779
979
  if (idx >= 0 && idx < list.length && !list[idx].disabled) {
780
980
  const id = list[idx].id;
@@ -788,6 +988,13 @@ class WrSelect {
788
988
  }
789
989
  }
790
990
  seedActiveIndex() {
991
+ if (this.virtualActive()) {
992
+ const list = this.filteredDynamicOptions();
993
+ const idx = list.findIndex(it => this.isSelected(it));
994
+ this.activeIndex.set(idx >= 0 ? idx : this.firstEnabled());
995
+ this.ensureVisible(this.activeIndex());
996
+ return;
997
+ }
791
998
  const list = this.registry();
792
999
  let selectedIdx = -1;
793
1000
  if (this.isMulti()) {
@@ -801,6 +1008,17 @@ class WrSelect {
801
1008
  this.activeIndex.set(selectedIdx >= 0 ? selectedIdx : this.firstEnabled());
802
1009
  }
803
1010
  moveActive(delta) {
1011
+ // Virtual rows are never disabled or hidden (the list is already filtered),
1012
+ // so navigation is a plain wrap plus a scroll-into-view.
1013
+ if (this.virtualActive()) {
1014
+ const len = this.filteredDynamicOptions().length;
1015
+ if (len === 0)
1016
+ return;
1017
+ const i = (this.activeIndex() + delta + len) % len;
1018
+ this.activeIndex.set(i);
1019
+ this.ensureVisible(i);
1020
+ return;
1021
+ }
804
1022
  const list = this.registry();
805
1023
  if (list.length === 0)
806
1024
  return;
@@ -816,9 +1034,13 @@ class WrSelect {
816
1034
  }
817
1035
  }
818
1036
  firstEnabled() {
1037
+ if (this.virtualActive())
1038
+ return this.filteredDynamicOptions().length > 0 ? 0 : -1;
819
1039
  return this.registry().findIndex(o => !o.disabled && !this.isOptionHidden(o.getLabel()));
820
1040
  }
821
1041
  lastEnabled() {
1042
+ if (this.virtualActive())
1043
+ return this.filteredDynamicOptions().length - 1;
822
1044
  const list = this.registry();
823
1045
  let found = -1;
824
1046
  list.forEach((o, i) => {
@@ -827,7 +1049,7 @@ class WrSelect {
827
1049
  });
828
1050
  return found;
829
1051
  }
830
- /** Coerce the multi-mode value signal into an array (handles writeValue from non-array). */
1052
+ /** Coerce the multi-mode value into an array (tolerates a scalar or null write). */
831
1053
  asArray(value) {
832
1054
  if (Array.isArray(value))
833
1055
  return value;
@@ -855,7 +1077,14 @@ class WrSelect {
855
1077
  this.overlayRef = this.overlay.create({
856
1078
  positionStrategy,
857
1079
  scrollStrategy: asSheet ? this.scrollStrategies.block() : this.scrollStrategies.reposition(),
858
- width: asSheet ? '100%' : this.host.nativeElement.getBoundingClientRect().width,
1080
+ // Floor the panel at the trigger width (it can still grow for long
1081
+ // options) instead of pinning it. The panel fills this via `width: 100%`,
1082
+ // so the flex overlay pane has no transparent gutter beside a
1083
+ // content-narrow panel — that gutter would otherwise sit "inside" the
1084
+ // overlay and swallow outside-clicks, leaving the panel open. Mirrors how
1085
+ // mat-select sizes its overlay.
1086
+ width: asSheet ? '100%' : undefined,
1087
+ minWidth: asSheet ? undefined : this.host.nativeElement.getBoundingClientRect().width,
859
1088
  hasBackdrop: asSheet,
860
1089
  backdropClass: asSheet ? 'wr-select-backdrop' : undefined,
861
1090
  panelClass: asSheet ? ['wr-select-overlay', 'wr-overlay-sheet'] : 'wr-select-overlay',
@@ -892,37 +1121,25 @@ class WrSelect {
892
1121
  this.overlayRef.dispose();
893
1122
  this.overlayRef = null;
894
1123
  }
895
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
896
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrSelect, isStandalone: true, selector: "wr-select", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null }, loader: { classPropertyName: "loader", publicName: "loader", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, minChars: { classPropertyName: "minChars", publicName: "minChars", isSignal: true, isRequired: false, transformFunction: null }, freeText: { classPropertyName: "freeText", publicName: "freeText", isSignal: true, isRequired: false, transformFunction: null }, noResultsText: { classPropertyName: "noResultsText", publicName: "noResultsText", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, separators: { classPropertyName: "separators", publicName: "separators", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null }, validate: { classPropertyName: "validate", publicName: "validate", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, maxTagCount: { classPropertyName: "maxTagCount", publicName: "maxTagCount", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, providers: [
897
- {
898
- provide: NG_VALUE_ACCESSOR,
899
- // eslint-disable-next-line @angular-eslint/no-forward-ref
900
- useExisting: forwardRef(() => WrSelect),
901
- multi: true,
902
- },
1124
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
1125
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrSelect, isStandalone: true, selector: "wr-select", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null }, loader: { classPropertyName: "loader", publicName: "loader", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, minChars: { classPropertyName: "minChars", publicName: "minChars", isSignal: true, isRequired: false, transformFunction: null }, freeText: { classPropertyName: "freeText", publicName: "freeText", 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 }, noResultsText: { classPropertyName: "noResultsText", publicName: "noResultsText", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, separators: { classPropertyName: "separators", publicName: "separators", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null }, validate: { classPropertyName: "validate", publicName: "validate", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, maxTagCount: { classPropertyName: "maxTagCount", publicName: "maxTagCount", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touch: "touch" }, host: { properties: { "class": "classes()" } }, providers: [
903
1126
  {
904
1127
  provide: WR_SELECT,
905
1128
  // eslint-disable-next-line @angular-eslint/no-forward-ref
906
1129
  useExisting: forwardRef(() => WrSelect),
907
1130
  },
908
- ], viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "tagInputEl", first: true, predicate: ["tagInput"], descendants: true, isSignal: true }, { propertyName: "searchInputEl", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isSearch()) {\n <!-- Search mode: a real text input drives a filtered overlay panel.\n The wrapper isn't itself focusable \u2014 the input is the tabstop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"wr-select__trigger wr-select__trigger--search\" (click)=\"focusSearchInput()\">\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"wr-select__search-input\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"searchDisplay()\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"onSearchFocus()\"\n (keydown)=\"onSearchKey($event)\"\n (blur)=\"onTouched()\"\n />\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 <svg\n class=\"wr-icon__svg wr-select__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 </div>\n} @else if (isTag()) {\n <!-- Tag mode: a focusable input lives inside, so the wrapper itself\n only exists to host chips and forward whitespace clicks to the\n input. Keyboard users tab straight into the input \u2014 no need for a\n separate role. The click handler is a mouse-only convenience. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"wr-select__trigger wr-select__trigger--tag\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"focusTagInput()\"\n >\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n [value]=\"draft()\"\n [disabled]=\"isDisabled() || atCapacity()\"\n [placeholder]=\"hasSelection() ? '' : resolvedPlaceholder()\"\n (input)=\"onTagInput($event)\"\n (keydown)=\"onTagKeydown($event)\"\n (paste)=\"onTagPaste($event)\"\n (blur)=\"onTagBlur()\"\n />\n </span>\n\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKey($event)\"\n (blur)=\"onTouched()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n } @else {\n @if (selectedLabel(); as label) {\n <span class=\"wr-select__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n }\n\n @if (isMulti() && clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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-select__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\n<ng-template #panelTpl>\n <div\n class=\"wr-select-panel\"\n role=\"listbox\"\n [attr.id]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n >\n @if (loading()) {\n <div class=\"wr-select-panel__loading\" aria-busy=\"true\">{{ resolvedLoading() }}</div>\n }\n\n <!-- Dynamic options from [options] or async [loader] (search mode).\n Rendered as wr-option so the standard registration / filter\n pipeline applies uniformly. -->\n @for (item of dynamicOptions(); track $index) {\n <wr-option [value]=\"item\">{{ displayWith()(item) }}</wr-option>\n }\n\n <!-- Projected static options. -->\n <ng-content />\n\n @if (hasNoResults()) {\n <div class=\"wr-select-panel__empty\">{{ resolvedNoResults() }}</div>\n }\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
1131
+ ], queries: [{ propertyName: "projectedOptions", predicate: WrOption, isSignal: true }], viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "tagInputEl", first: true, predicate: ["tagInput"], descendants: true, isSignal: true }, { propertyName: "searchInputEl", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isSearch()) {\n <!-- Search mode: a real text input drives a filtered overlay panel.\n The wrapper isn't itself focusable \u2014 the input is the tabstop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"wr-select__trigger wr-select__trigger--search\" (click)=\"focusSearchInput()\">\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"wr-select__search-input\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"searchDisplay()\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"onSearchFocus()\"\n (keydown)=\"onSearchKey($event)\"\n (blur)=\"touch.emit()\"\n />\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 <svg\n class=\"wr-icon__svg wr-select__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 </div>\n} @else if (isTag()) {\n <!-- Tag mode: a focusable input lives inside, so the wrapper itself\n only exists to host chips and forward whitespace clicks to the\n input. Keyboard users tab straight into the input \u2014 no need for a\n separate role. The click handler is a mouse-only convenience. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"wr-select__trigger wr-select__trigger--tag\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"focusTagInput()\"\n >\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n [value]=\"draft()\"\n [disabled]=\"isDisabled() || atCapacity()\"\n [placeholder]=\"hasSelection() ? '' : resolvedPlaceholder()\"\n (input)=\"onTagInput($event)\"\n (keydown)=\"onTagKeydown($event)\"\n (paste)=\"onTagPaste($event)\"\n (blur)=\"onTagBlur()\"\n />\n </span>\n\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKey($event)\"\n (blur)=\"touch.emit()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n } @else {\n @if (selectedLabel(); as label) {\n <span class=\"wr-select__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n }\n\n @if (isMulti() && clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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-select__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\n<ng-template #panelTpl>\n <div\n class=\"wr-select-panel\"\n [class.wr-select-panel--sm]=\"size() === 'sm'\"\n [class.wr-select-panel--lg]=\"size() === 'lg'\"\n [class.wr-select-panel--virtual]=\"virtualActive()\"\n role=\"listbox\"\n [attr.id]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n >\n @if (loading()) {\n <div class=\"wr-select-panel__loading\" aria-busy=\"true\">{{ resolvedLoading() }}</div>\n }\n\n @if (virtualActive()) {\n <!-- Windowed data-array rows: plain role=\"option\" elements (not <wr-option>),\n navigated via the input's aria-activedescendant, selected by value. -->\n <div class=\"wr-select-panel__vlist\" [style.max-height]=\"resolvedViewportHeight()\">\n @if (virtualWindow().padTop > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padTop\"></div>\n }\n @for (entry of windowOptions(); track entry.index) {\n <!-- Keyboard handled by the search input via aria-activedescendant; the\n row is a pointer target only. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"option\"\n class=\"wr-option\"\n [id]=\"virtualRowId(entry.index)\"\n [class.wr-option--active]=\"entry.index === activeIndex()\"\n [class.wr-option--selected]=\"isSelected(entry.item)\"\n [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\n >\n {{ displayWith()(entry.item) }}\n </div>\n }\n @if (virtualWindow().padBottom > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padBottom\"></div>\n }\n </div>\n } @else {\n <!-- Dynamic options from [options] or async [loader] (search mode).\n Rendered as wr-option so the standard registration / filter\n pipeline applies uniformly. -->\n @for (item of dynamicOptions(); track $index) {\n <wr-option [value]=\"item\">{{ displayWith()(item) }}</wr-option>\n }\n }\n\n <!-- Projected static options \u2014 always present (a conditional `<ng-content>`\n would drop projected content). Empty whenever `virtualActive`. -->\n <ng-content />\n\n @if (hasNoResults()) {\n <div class=\"wr-select-panel__empty\">{{ resolvedNoResults() }}</div>\n }\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
909
1132
  }
910
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrSelect, decorators: [{
1133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrSelect, decorators: [{
911
1134
  type: Component,
912
1135
  args: [{ selector: 'wr-select', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, imports: [WrOption], providers: [
913
- {
914
- provide: NG_VALUE_ACCESSOR,
915
- // eslint-disable-next-line @angular-eslint/no-forward-ref
916
- useExisting: forwardRef(() => WrSelect),
917
- multi: true,
918
- },
919
1136
  {
920
1137
  provide: WR_SELECT,
921
1138
  // eslint-disable-next-line @angular-eslint/no-forward-ref
922
1139
  useExisting: forwardRef(() => WrSelect),
923
1140
  },
924
- ], template: "@if (isSearch()) {\n <!-- Search mode: a real text input drives a filtered overlay panel.\n The wrapper isn't itself focusable \u2014 the input is the tabstop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"wr-select__trigger wr-select__trigger--search\" (click)=\"focusSearchInput()\">\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"wr-select__search-input\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"searchDisplay()\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"onSearchFocus()\"\n (keydown)=\"onSearchKey($event)\"\n (blur)=\"onTouched()\"\n />\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 <svg\n class=\"wr-icon__svg wr-select__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 </div>\n} @else if (isTag()) {\n <!-- Tag mode: a focusable input lives inside, so the wrapper itself\n only exists to host chips and forward whitespace clicks to the\n input. Keyboard users tab straight into the input \u2014 no need for a\n separate role. The click handler is a mouse-only convenience. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"wr-select__trigger wr-select__trigger--tag\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"focusTagInput()\"\n >\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n [value]=\"draft()\"\n [disabled]=\"isDisabled() || atCapacity()\"\n [placeholder]=\"hasSelection() ? '' : resolvedPlaceholder()\"\n (input)=\"onTagInput($event)\"\n (keydown)=\"onTagKeydown($event)\"\n (paste)=\"onTagPaste($event)\"\n (blur)=\"onTagBlur()\"\n />\n </span>\n\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKey($event)\"\n (blur)=\"onTouched()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n } @else {\n @if (selectedLabel(); as label) {\n <span class=\"wr-select__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n }\n\n @if (isMulti() && clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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-select__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\n<ng-template #panelTpl>\n <div\n class=\"wr-select-panel\"\n role=\"listbox\"\n [attr.id]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n >\n @if (loading()) {\n <div class=\"wr-select-panel__loading\" aria-busy=\"true\">{{ resolvedLoading() }}</div>\n }\n\n <!-- Dynamic options from [options] or async [loader] (search mode).\n Rendered as wr-option so the standard registration / filter\n pipeline applies uniformly. -->\n @for (item of dynamicOptions(); track $index) {\n <wr-option [value]=\"item\">{{ displayWith()(item) }}</wr-option>\n }\n\n <!-- Projected static options. -->\n <ng-content />\n\n @if (hasNoResults()) {\n <div class=\"wr-select-panel__empty\">{{ resolvedNoResults() }}</div>\n }\n </div>\n</ng-template>\n" }]
925
- }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], loader: [{ type: i0.Input, args: [{ isSignal: true, alias: "loader", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], minChars: [{ type: i0.Input, args: [{ isSignal: true, alias: "minChars", required: false }] }], freeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "freeText", required: false }] }], noResultsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsText", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], separators: [{ type: i0.Input, args: [{ isSignal: true, alias: "separators", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], maxItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxItems", required: false }] }], maxTagCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTagCount", required: false }] }], panelTpl: [{ type: i0.ViewChild, args: ['panelTpl', { ...{ read: TemplateRef }, isSignal: true }] }], tagInputEl: [{ type: i0.ViewChild, args: ['tagInput', { isSignal: true }] }], searchInputEl: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }] } });
1141
+ ], template: "@if (isSearch()) {\n <!-- Search mode: a real text input drives a filtered overlay panel.\n The wrapper isn't itself focusable \u2014 the input is the tabstop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"wr-select__trigger wr-select__trigger--search\" (click)=\"focusSearchInput()\">\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"wr-select__search-input\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"searchDisplay()\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"onSearchFocus()\"\n (keydown)=\"onSearchKey($event)\"\n (blur)=\"touch.emit()\"\n />\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 <svg\n class=\"wr-icon__svg wr-select__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 </div>\n} @else if (isTag()) {\n <!-- Tag mode: a focusable input lives inside, so the wrapper itself\n only exists to host chips and forward whitespace clicks to the\n input. Keyboard users tab straight into the input \u2014 no need for a\n separate role. The click handler is a mouse-only convenience. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"wr-select__trigger wr-select__trigger--tag\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"focusTagInput()\"\n >\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n [value]=\"draft()\"\n [disabled]=\"isDisabled() || atCapacity()\"\n [placeholder]=\"hasSelection() ? '' : resolvedPlaceholder()\"\n (input)=\"onTagInput($event)\"\n (keydown)=\"onTagKeydown($event)\"\n (paste)=\"onTagPaste($event)\"\n (blur)=\"onTagBlur()\"\n />\n </span>\n\n @if (clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKey($event)\"\n (blur)=\"touch.emit()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip(chip.value, $event)\"\n (keydown.enter)=\"removeChip(chip.value, $event)\"\n (keydown.space)=\"removeChip(chip.value, $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-select__chip wr-select__chip--more\">+{{ extra }} more</span>\n }\n </span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n } @else {\n @if (selectedLabel(); as label) {\n <span class=\"wr-select__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n }\n\n @if (isMulti() && clearable() && hasSelection() && !isDisabled()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n (keydown.enter)=\"clearAll($event)\"\n (keydown.space)=\"clearAll($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-select__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\n<ng-template #panelTpl>\n <div\n class=\"wr-select-panel\"\n [class.wr-select-panel--sm]=\"size() === 'sm'\"\n [class.wr-select-panel--lg]=\"size() === 'lg'\"\n [class.wr-select-panel--virtual]=\"virtualActive()\"\n role=\"listbox\"\n [attr.id]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n >\n @if (loading()) {\n <div class=\"wr-select-panel__loading\" aria-busy=\"true\">{{ resolvedLoading() }}</div>\n }\n\n @if (virtualActive()) {\n <!-- Windowed data-array rows: plain role=\"option\" elements (not <wr-option>),\n navigated via the input's aria-activedescendant, selected by value. -->\n <div class=\"wr-select-panel__vlist\" [style.max-height]=\"resolvedViewportHeight()\">\n @if (virtualWindow().padTop > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padTop\"></div>\n }\n @for (entry of windowOptions(); track entry.index) {\n <!-- Keyboard handled by the search input via aria-activedescendant; the\n row is a pointer target only. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"option\"\n class=\"wr-option\"\n [id]=\"virtualRowId(entry.index)\"\n [class.wr-option--active]=\"entry.index === activeIndex()\"\n [class.wr-option--selected]=\"isSelected(entry.item)\"\n [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\n >\n {{ displayWith()(entry.item) }}\n </div>\n }\n @if (virtualWindow().padBottom > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padBottom\"></div>\n }\n </div>\n } @else {\n <!-- Dynamic options from [options] or async [loader] (search mode).\n Rendered as wr-option so the standard registration / filter\n pipeline applies uniformly. -->\n @for (item of dynamicOptions(); track $index) {\n <wr-option [value]=\"item\">{{ displayWith()(item) }}</wr-option>\n }\n }\n\n <!-- Projected static options \u2014 always present (a conditional `<ng-content>`\n would drop projected content). Empty whenever `virtualActive`. -->\n <ng-content />\n\n @if (hasNoResults()) {\n <div class=\"wr-select-panel__empty\">{{ resolvedNoResults() }}</div>\n }\n </div>\n</ng-template>\n" }]
1142
+ }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], loader: [{ type: i0.Input, args: [{ isSignal: true, alias: "loader", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], minChars: [{ type: i0.Input, args: [{ isSignal: true, alias: "minChars", required: false }] }], freeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "freeText", 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 }] }], noResultsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsText", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], separators: [{ type: i0.Input, args: [{ isSignal: true, alias: "separators", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], maxItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxItems", required: false }] }], maxTagCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTagCount", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }], projectedOptions: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => WrOption), { isSignal: true }] }], panelTpl: [{ type: i0.ViewChild, args: ['panelTpl', { ...{ read: TemplateRef }, isSignal: true }] }], tagInputEl: [{ type: i0.ViewChild, args: ['tagInput', { isSignal: true }] }], searchInputEl: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }] } });
926
1143
 
927
1144
  /**
928
1145
  * @license
@@ -945,10 +1162,10 @@ class WrOptionGroup {
945
1162
  /** Section heading shown above the options. */
946
1163
  label = input.required(/* @ts-ignore */
947
1164
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
948
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrOptionGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
949
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: WrOptionGroup, isStandalone: true, selector: "wr-option-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "role": "group" }, classAttribute: "wr-option-group" }, ngImport: i0, template: "<div class=\"wr-option-group__label\">{{ label() }}</div>\n<ng-content />\n", encapsulation: i0.ViewEncapsulation.None });
1165
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrOptionGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
1166
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: WrOptionGroup, isStandalone: true, selector: "wr-option-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "role": "group" }, classAttribute: "wr-option-group" }, ngImport: i0, template: "<div class=\"wr-option-group__label\">{{ label() }}</div>\n<ng-content />\n", encapsulation: i0.ViewEncapsulation.None });
950
1167
  }
951
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrOptionGroup, decorators: [{
1168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrOptionGroup, decorators: [{
952
1169
  type: Component,
953
1170
  args: [{ selector: 'wr-option-group', encapsulation: ViewEncapsulation.None, host: { class: 'wr-option-group', role: 'group' }, template: "<div class=\"wr-option-group__label\">{{ label() }}</div>\n<ng-content />\n" }]
954
1171
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }] } });