@koobiq/components 20.4.2 → 21.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 (771) hide show
  1. package/accordion/accordion-trigger.scss +3 -10
  2. package/accordion/accordion.scss +4 -6
  3. package/actions-panel/actions-panel-container.scss +45 -1
  4. package/alert/alert.component.scss +3 -2
  5. package/app-switcher/_app-switcher-theme.scss +0 -4
  6. package/app-switcher/app-switcher-dropdown-app.scss +3 -2
  7. package/app-switcher/app-switcher-dropdown-site.scss +2 -1
  8. package/app-switcher/{kbq-app-switcher-list-item.scss → app-switcher-list-item.scss} +18 -4
  9. package/app-switcher/app-switcher-tokens.scss +15 -0
  10. package/app-switcher/app-switcher.scss +14 -4
  11. package/autocomplete/autocomplete.scss +7 -6
  12. package/badge/badge.component.scss +5 -8
  13. package/breadcrumbs/breadcrumbs.scss +25 -10
  14. package/button/_button-base.scss +30 -7
  15. package/button/_button-theme.scss +16 -0
  16. package/button/button-group.scss +7 -0
  17. package/button/button-tokens.scss +0 -2
  18. package/button/button.scss +34 -2
  19. package/button-toggle/_button-toggle-theme.scss +7 -2
  20. package/button-toggle/button-toggle.scss +65 -15
  21. package/checkbox/_checkbox-theme.scss +4 -3
  22. package/checkbox/checkbox.scss +3 -6
  23. package/clamped-text/clamped-text.scss +6 -2
  24. package/code-block/code-block-tokens.scss +0 -224
  25. package/code-block/code-block.scss +20 -9
  26. package/content-panel/content-panel-aside.scss +3 -2
  27. package/content-panel/content-panel-container.scss +37 -0
  28. package/content-panel/content-panel.scss +4 -3
  29. package/core/highlight/_highlight-theme.scss +3 -1
  30. package/core/option/action-container.scss +2 -2
  31. package/core/option/action.scss +2 -1
  32. package/core/option/option.scss +2 -1
  33. package/core/pop-up/_pop-up.scss +0 -37
  34. package/core/selection/pseudo-checkbox/pseudo-checkbox.scss +5 -10
  35. package/core/styles/_core.scss +3 -0
  36. package/core/styles/_koobiq-theme.scss +5 -6
  37. package/core/styles/common/_animation.scss +44 -16
  38. package/core/styles/common/_groups-mixins.scss +21 -19
  39. package/core/styles/common/_groups.scss +4 -32
  40. package/core/styles/common/_index.scss +0 -2
  41. package/core/styles/common/_link.scss +117 -0
  42. package/core/styles/common/_list.scss +0 -26
  43. package/core/styles/common/_overlay.scss +8 -10
  44. package/core/styles/common/_rtl.scss +0 -14
  45. package/core/styles/common/_select.scss +33 -15
  46. package/core/styles/common/_squircle.scss +63 -0
  47. package/core/styles/common/_tokens.scss +0 -11
  48. package/core/styles/common/_vendor-prefixes.scss +0 -20
  49. package/core/styles/functions/_timing.scss +0 -22
  50. package/core/styles/theming/_scrollbar-theme.scss +6 -1
  51. package/core/styles/theming/_theming.scss +13 -65
  52. package/core/styles/typography/_index.scss +0 -1
  53. package/core/styles/typography/_typography.scss +0 -143
  54. package/core/styles/visual/_body.scss +1 -6
  55. package/core/styles/visual/_layout.scss +0 -12
  56. package/datepicker/calendar-body.scss +3 -1
  57. package/datepicker/calendar-header.scss +0 -1
  58. package/datepicker/datepicker-content.scss +33 -1
  59. package/datepicker/datepicker-toggle.scss +0 -38
  60. package/dl/dl-tokens.scss +10 -0
  61. package/dl/dl.scss +113 -13
  62. package/dropdown/_dropdown-theme.scss +4 -16
  63. package/dropdown/dropdown-item.scss +4 -10
  64. package/dropdown/dropdown.scss +2 -1
  65. package/empty-state/_empty-state-theme.scss +10 -4
  66. package/empty-state/empty-state-tokens.scss +4 -4
  67. package/empty-state/empty-state.scss +4 -0
  68. package/fesm2022/koobiq-components-accordion.mjs +347 -229
  69. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  70. package/fesm2022/koobiq-components-actions-panel.mjs +302 -187
  71. package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
  72. package/fesm2022/koobiq-components-alert.mjs +39 -39
  73. package/fesm2022/koobiq-components-alert.mjs.map +1 -1
  74. package/fesm2022/koobiq-components-app-switcher.mjs +677 -367
  75. package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
  76. package/fesm2022/koobiq-components-autocomplete.mjs +620 -253
  77. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  78. package/fesm2022/koobiq-components-badge.mjs +46 -48
  79. package/fesm2022/koobiq-components-badge.mjs.map +1 -1
  80. package/fesm2022/koobiq-components-breadcrumbs.mjs +221 -169
  81. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  82. package/fesm2022/koobiq-components-button-toggle.mjs +565 -196
  83. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  84. package/fesm2022/koobiq-components-button.mjs +332 -116
  85. package/fesm2022/koobiq-components-button.mjs.map +1 -1
  86. package/fesm2022/koobiq-components-checkbox.mjs +172 -132
  87. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  88. package/fesm2022/koobiq-components-clamped-text.mjs +165 -158
  89. package/fesm2022/koobiq-components-clamped-text.mjs.map +1 -1
  90. package/fesm2022/koobiq-components-code-block.mjs +755 -601
  91. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  92. package/fesm2022/koobiq-components-content-panel.mjs +260 -143
  93. package/fesm2022/koobiq-components-content-panel.mjs.map +1 -1
  94. package/fesm2022/koobiq-components-core.mjs +4342 -1595
  95. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  96. package/fesm2022/koobiq-components-datepicker.mjs +1713 -1606
  97. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  98. package/fesm2022/koobiq-components-divider.mjs +73 -36
  99. package/fesm2022/koobiq-components-divider.mjs.map +1 -1
  100. package/fesm2022/koobiq-components-dl.mjs +447 -89
  101. package/fesm2022/koobiq-components-dl.mjs.map +1 -1
  102. package/fesm2022/koobiq-components-dropdown.mjs +703 -599
  103. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  104. package/fesm2022/koobiq-components-dynamic-translation.mjs +20 -20
  105. package/fesm2022/koobiq-components-dynamic-translation.mjs.map +1 -1
  106. package/fesm2022/koobiq-components-ellipsis-center.mjs +46 -31
  107. package/fesm2022/koobiq-components-ellipsis-center.mjs.map +1 -1
  108. package/fesm2022/koobiq-components-empty-state.mjs +116 -60
  109. package/fesm2022/koobiq-components-empty-state.mjs.map +1 -1
  110. package/fesm2022/koobiq-components-file-upload.mjs +550 -290
  111. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  112. package/fesm2022/koobiq-components-filter-bar.mjs +2810 -2538
  113. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  114. package/fesm2022/koobiq-components-flag.mjs +79 -24
  115. package/fesm2022/koobiq-components-flag.mjs.map +1 -1
  116. package/fesm2022/koobiq-components-form-field.mjs +389 -525
  117. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  118. package/fesm2022/koobiq-components-icon.mjs +366 -136
  119. package/fesm2022/koobiq-components-icon.mjs.map +1 -1
  120. package/fesm2022/koobiq-components-inline-edit.mjs +429 -212
  121. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  122. package/fesm2022/koobiq-components-input.mjs +601 -459
  123. package/fesm2022/koobiq-components-input.mjs.map +1 -1
  124. package/fesm2022/koobiq-components-link-deprecated.mjs +196 -0
  125. package/fesm2022/koobiq-components-link-deprecated.mjs.map +1 -0
  126. package/fesm2022/koobiq-components-link.mjs +328 -125
  127. package/fesm2022/koobiq-components-link.mjs.map +1 -1
  128. package/fesm2022/koobiq-components-list.mjs +583 -433
  129. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  130. package/fesm2022/koobiq-components-loader-overlay.mjs +167 -68
  131. package/fesm2022/koobiq-components-loader-overlay.mjs.map +1 -1
  132. package/fesm2022/koobiq-components-markdown.mjs +55 -78
  133. package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
  134. package/fesm2022/koobiq-components-modal.mjs +853 -475
  135. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  136. package/fesm2022/koobiq-components-navbar.mjs +895 -556
  137. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  138. package/fesm2022/koobiq-components-notification-center.mjs +680 -310
  139. package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
  140. package/fesm2022/koobiq-components-overflow-items.mjs +46 -64
  141. package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
  142. package/fesm2022/koobiq-components-popover.mjs +684 -285
  143. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  144. package/fesm2022/koobiq-components-progress-bar.mjs +87 -33
  145. package/fesm2022/koobiq-components-progress-bar.mjs.map +1 -1
  146. package/fesm2022/koobiq-components-progress-spinner.mjs +52 -43
  147. package/fesm2022/koobiq-components-progress-spinner.mjs.map +1 -1
  148. package/fesm2022/koobiq-components-radio.mjs +450 -231
  149. package/fesm2022/koobiq-components-radio.mjs.map +1 -1
  150. package/fesm2022/koobiq-components-resizer.mjs +127 -21
  151. package/fesm2022/koobiq-components-resizer.mjs.map +1 -1
  152. package/fesm2022/koobiq-components-scrollbar-deprecated.mjs +299 -0
  153. package/fesm2022/koobiq-components-scrollbar-deprecated.mjs.map +1 -0
  154. package/fesm2022/koobiq-components-scrollbar.mjs +745 -222
  155. package/fesm2022/koobiq-components-scrollbar.mjs.map +1 -1
  156. package/fesm2022/koobiq-components-search-expandable.mjs +288 -126
  157. package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
  158. package/fesm2022/koobiq-components-select.mjs +883 -693
  159. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  160. package/fesm2022/koobiq-components-sidebar.mjs +207 -88
  161. package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
  162. package/fesm2022/koobiq-components-sidepanel.mjs +689 -296
  163. package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
  164. package/fesm2022/koobiq-components-skeleton.mjs +815 -41
  165. package/fesm2022/koobiq-components-skeleton.mjs.map +1 -1
  166. package/fesm2022/koobiq-components-split-button.mjs +109 -88
  167. package/fesm2022/koobiq-components-split-button.mjs.map +1 -1
  168. package/fesm2022/koobiq-components-splitter-deprecated.mjs +591 -0
  169. package/fesm2022/koobiq-components-splitter-deprecated.mjs.map +1 -0
  170. package/fesm2022/koobiq-components-splitter.mjs +890 -501
  171. package/fesm2022/koobiq-components-splitter.mjs.map +1 -1
  172. package/fesm2022/koobiq-components-table.mjs +63 -49
  173. package/fesm2022/koobiq-components-table.mjs.map +1 -1
  174. package/fesm2022/koobiq-components-tabs.mjs +1062 -603
  175. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  176. package/fesm2022/koobiq-components-tags.mjs +886 -733
  177. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  178. package/fesm2022/koobiq-components-textarea.mjs +213 -185
  179. package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
  180. package/fesm2022/koobiq-components-time-range.mjs +299 -147
  181. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  182. package/fesm2022/koobiq-components-timepicker.mjs +233 -245
  183. package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
  184. package/fesm2022/koobiq-components-timezone.mjs +344 -142
  185. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  186. package/fesm2022/koobiq-components-title.mjs +229 -145
  187. package/fesm2022/koobiq-components-title.mjs.map +1 -1
  188. package/fesm2022/koobiq-components-toast.mjs +463 -143
  189. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  190. package/fesm2022/koobiq-components-toggle.mjs +177 -130
  191. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  192. package/fesm2022/koobiq-components-tooltip.mjs +657 -214
  193. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  194. package/fesm2022/koobiq-components-top-bar.mjs +61 -32
  195. package/fesm2022/koobiq-components-top-bar.mjs.map +1 -1
  196. package/fesm2022/koobiq-components-tree-select.mjs +719 -488
  197. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  198. package/fesm2022/koobiq-components-tree.mjs +1506 -558
  199. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  200. package/fesm2022/koobiq-components-username.mjs +290 -135
  201. package/fesm2022/koobiq-components-username.mjs.map +1 -1
  202. package/file-upload/dropzone.scss +31 -3
  203. package/file-upload/file-upload-tokens.scss +2 -22
  204. package/file-upload/file-upload.scss +6 -0
  205. package/file-upload/multiple-file-upload.component.scss +14 -12
  206. package/file-upload/single-file-upload.component.scss +3 -2
  207. package/filter-bar/filters.scss +7 -0
  208. package/filter-bar/pipes/base-pipe.scss +3 -3
  209. package/filter-bar/pipes/pipe-date.scss +8 -1
  210. package/flag/flag-tokens.scss +22 -0
  211. package/flag/flag.scss +34 -21
  212. package/form-field/{_fiedset-theme.scss → _fieldset-theme.scss} +1 -5
  213. package/form-field/_form-field-theme.scss +4 -9
  214. package/form-field/cleaner.scss +3 -1
  215. package/form-field/fieldset.scss +3 -4
  216. package/form-field/form-field.scss +26 -21
  217. package/form-field/password-toggle.scss +3 -1
  218. package/icon/_icon-button-theme.scss +7 -0
  219. package/icon/_icon-theme.scss +10 -7
  220. package/icon/icon-button.scss +0 -2
  221. package/icon/icon-tokens.scss +12 -9
  222. package/inline-edit/inline-edit.scss +40 -54
  223. package/input/input.scss +4 -0
  224. package/link/{_link-theme.scss → deprecated/_link-theme.scss} +11 -6
  225. package/link/deprecated/link-tokens.scss +27 -0
  226. package/link/link-tokens.scss +6 -25
  227. package/link/link.scss +137 -0
  228. package/list/list.scss +3 -2
  229. package/loader-overlay/_loader-overlay-theme.scss +19 -10
  230. package/loader-overlay/loader-overlay-tokens.scss +0 -2
  231. package/loader-overlay/loader-overlay.scss +7 -1
  232. package/markdown/_markdown-theme.scss +16 -0
  233. package/markdown/markdown-tokens.scss +5 -0
  234. package/markdown/markdown.scss +2 -1
  235. package/modal/_modal-animation.scss +23 -14
  236. package/modal/modal-tokens.scss +2 -1
  237. package/modal/modal.scss +35 -31
  238. package/navbar/_navbar-item_horizontal.scss +8 -6
  239. package/navbar/_navbar-item_vertical.scss +18 -6
  240. package/navbar/_navbar-theme.scss +9 -1
  241. package/navbar/navbar-brand.scss +8 -6
  242. package/navbar/navbar-divider.scss +1 -1
  243. package/navbar/navbar-item.scss +8 -9
  244. package/navbar/navbar-toggle.scss +3 -3
  245. package/navbar/navbar-tokens.scss +14 -0
  246. package/navbar/navbar.scss +1 -2
  247. package/navbar/vertical-navbar.scss +2 -2
  248. package/notification-center/_notification-center-theme.scss +11 -6
  249. package/notification-center/notification-center-tokens.scss +33 -0
  250. package/notification-center/notification-center.scss +58 -20
  251. package/notification-center/notification-item.scss +15 -6
  252. package/package.json +112 -81
  253. package/popover/popover-tokens.scss +0 -2
  254. package/popover/popover.scss +41 -19
  255. package/prebuilt-themes/theme.css +1 -1
  256. package/progress-bar/_progress-bar-theme.scss +20 -3
  257. package/progress-bar/progress-bar-tokens.scss +3 -0
  258. package/progress-bar/progress-bar.scss +36 -8
  259. package/progress-spinner/progress-spinner.scss +4 -3
  260. package/radio/_radio-theme.scss +21 -4
  261. package/radio/radio-tokens.scss +7 -3
  262. package/radio/radio.scss +55 -8
  263. package/schematics/collection.json +399 -7
  264. package/schematics/migrations/accordion-state-saving-default/README.md +60 -0
  265. package/schematics/migrations/accordion-state-saving-default/data.js +75 -0
  266. package/schematics/migrations/accordion-state-saving-default/index.js +60 -0
  267. package/schematics/migrations/accordion-state-saving-default/schema.json +15 -0
  268. package/schematics/migrations/actions-panel-overlay-container/README.md +35 -0
  269. package/schematics/migrations/actions-panel-overlay-container/data.js +47 -0
  270. package/schematics/migrations/actions-panel-overlay-container/index.js +54 -0
  271. package/schematics/migrations/actions-panel-overlay-container/schema.json +15 -0
  272. package/schematics/migrations/alert-signals/README.md +13 -7
  273. package/schematics/migrations/alert-signals/data.js +3 -0
  274. package/schematics/migrations/alert-signals/index.js +70 -203
  275. package/schematics/migrations/angular-animations-removal/README.md +46 -0
  276. package/schematics/migrations/angular-animations-removal/data.js +150 -0
  277. package/schematics/migrations/angular-animations-removal/index.js +20 -0
  278. package/schematics/migrations/angular-animations-removal/schema.json +15 -0
  279. package/schematics/migrations/app-switcher-signals/README.md +88 -0
  280. package/schematics/migrations/app-switcher-signals/data.js +136 -0
  281. package/schematics/migrations/app-switcher-signals/index.js +365 -0
  282. package/schematics/migrations/app-switcher-signals/schema.json +20 -0
  283. package/schematics/migrations/autocomplete-panel-width-auto/README.md +2 -2
  284. package/schematics/migrations/autocomplete-panel-width-auto/index.js +1 -1
  285. package/schematics/migrations/autocomplete-signals/README.md +92 -0
  286. package/schematics/migrations/autocomplete-signals/data.js +149 -0
  287. package/schematics/migrations/autocomplete-signals/index.js +706 -0
  288. package/schematics/migrations/autocomplete-signals/schema.json +20 -0
  289. package/schematics/migrations/badge-signals/README.md +77 -0
  290. package/schematics/migrations/badge-signals/data.js +109 -0
  291. package/schematics/migrations/badge-signals/index.js +693 -0
  292. package/schematics/migrations/badge-signals/schema.json +20 -0
  293. package/schematics/migrations/button-state-and-styles/README.md +129 -0
  294. package/schematics/migrations/button-state-and-styles/data.js +136 -0
  295. package/schematics/migrations/button-state-and-styles/index.js +220 -0
  296. package/schematics/migrations/button-state-and-styles/schema.json +20 -0
  297. package/schematics/migrations/button-supported-colors/README.md +73 -0
  298. package/schematics/migrations/button-supported-colors/data.js +106 -0
  299. package/schematics/migrations/button-supported-colors/index.js +260 -0
  300. package/schematics/migrations/button-supported-colors/schema.json +20 -0
  301. package/schematics/migrations/button-toggle-signals-and-aria/README.md +137 -0
  302. package/schematics/migrations/button-toggle-signals-and-aria/data.js +200 -0
  303. package/schematics/migrations/button-toggle-signals-and-aria/index.js +496 -0
  304. package/schematics/migrations/button-toggle-signals-and-aria/schema.json +20 -0
  305. package/schematics/migrations/button-truncation/README.md +110 -0
  306. package/schematics/migrations/button-truncation/data.js +88 -0
  307. package/schematics/migrations/button-truncation/index.js +269 -0
  308. package/schematics/migrations/button-truncation/schema.json +20 -0
  309. package/schematics/migrations/checkbox-signals/README.md +76 -0
  310. package/schematics/migrations/checkbox-signals/data.js +114 -0
  311. package/schematics/migrations/checkbox-signals/index.js +634 -0
  312. package/schematics/migrations/checkbox-signals/schema.json +20 -0
  313. package/schematics/migrations/clamped-text-disclosure/README.md +62 -0
  314. package/schematics/migrations/clamped-text-disclosure/data.js +101 -0
  315. package/schematics/migrations/clamped-text-disclosure/index.js +59 -0
  316. package/schematics/migrations/clamped-text-disclosure/schema.json +15 -0
  317. package/schematics/migrations/code-block-signals/README.md +84 -0
  318. package/schematics/migrations/code-block-signals/data.js +121 -0
  319. package/schematics/migrations/code-block-signals/index.js +700 -0
  320. package/schematics/migrations/code-block-signals/schema.json +20 -0
  321. package/schematics/migrations/color-signals/README.md +46 -0
  322. package/schematics/migrations/color-signals/data.js +131 -0
  323. package/schematics/migrations/color-signals/index.js +19 -0
  324. package/schematics/migrations/color-signals/schema.json +20 -0
  325. package/schematics/migrations/core-mixins-removal/README.md +20 -0
  326. package/schematics/migrations/core-mixins-removal/data.js +27 -0
  327. package/schematics/migrations/core-mixins-removal/index.js +17 -0
  328. package/schematics/migrations/core-mixins-removal/schema.json +15 -0
  329. package/schematics/migrations/css-selectors/README.md +2 -2
  330. package/schematics/migrations/css-selectors/index.js +1 -1
  331. package/schematics/migrations/datepicker-signals/README.md +24 -0
  332. package/schematics/migrations/datepicker-signals/data.js +49 -0
  333. package/schematics/migrations/datepicker-signals/index.js +17 -0
  334. package/schematics/migrations/datepicker-signals/schema.json +15 -0
  335. package/schematics/migrations/deprecated-icons/README.md +2 -2
  336. package/schematics/migrations/deprecated-icons/index.js +1 -1
  337. package/schematics/migrations/design-tokens-v4/README.md +75 -0
  338. package/schematics/migrations/design-tokens-v4/index.js +59 -0
  339. package/schematics/migrations/design-tokens-v4/schema.json +15 -0
  340. package/schematics/migrations/divider-signals-and-aria/README.md +47 -0
  341. package/schematics/migrations/divider-signals-and-aria/data.js +62 -0
  342. package/schematics/migrations/divider-signals-and-aria/index.js +211 -0
  343. package/schematics/migrations/divider-signals-and-aria/schema.json +15 -0
  344. package/schematics/migrations/dl-attribute-coercion/README.md +59 -0
  345. package/schematics/migrations/dl-attribute-coercion/data.js +85 -0
  346. package/schematics/migrations/dl-attribute-coercion/index.js +161 -0
  347. package/schematics/migrations/dl-attribute-coercion/schema.json +15 -0
  348. package/schematics/migrations/dl-standalone-names/README.md +49 -0
  349. package/schematics/migrations/dl-standalone-names/data.js +44 -0
  350. package/schematics/migrations/dl-standalone-names/index.js +321 -0
  351. package/schematics/migrations/dl-standalone-names/schema.json +20 -0
  352. package/schematics/migrations/dropdown-demote-overlay/README.md +137 -0
  353. package/schematics/migrations/dropdown-demote-overlay/data.js +84 -0
  354. package/schematics/migrations/dropdown-demote-overlay/index.js +288 -0
  355. package/schematics/migrations/dropdown-demote-overlay/schema.json +20 -0
  356. package/schematics/migrations/dropdown-signals/README.md +83 -0
  357. package/schematics/migrations/dropdown-signals/data.js +152 -0
  358. package/schematics/migrations/dropdown-signals/index.js +19 -0
  359. package/schematics/migrations/dropdown-signals/schema.json +20 -0
  360. package/schematics/migrations/empty-state-error-color/README.md +84 -0
  361. package/schematics/migrations/empty-state-error-color/data.js +85 -0
  362. package/schematics/migrations/empty-state-error-color/index.js +71 -0
  363. package/schematics/migrations/empty-state-error-color/schema.json +15 -0
  364. package/schematics/migrations/empty-state-size-attr/README.md +2 -2
  365. package/schematics/migrations/empty-state-size-attr/index.js +1 -1
  366. package/schematics/migrations/file-upload-cva-and-primitives/README.md +70 -0
  367. package/schematics/migrations/file-upload-cva-and-primitives/data.js +97 -0
  368. package/schematics/migrations/file-upload-cva-and-primitives/index.js +60 -0
  369. package/schematics/migrations/file-upload-cva-and-primitives/schema.json +15 -0
  370. package/schematics/migrations/file-upload-deprecated-outputs/README.md +90 -0
  371. package/schematics/migrations/file-upload-deprecated-outputs/data.js +20 -0
  372. package/schematics/migrations/file-upload-deprecated-outputs/index.js +70 -0
  373. package/schematics/migrations/file-upload-deprecated-outputs/schema.json +20 -0
  374. package/schematics/migrations/filter-bar-rename-action/README.md +183 -0
  375. package/schematics/migrations/filter-bar-rename-action/data.js +151 -0
  376. package/schematics/migrations/filter-bar-rename-action/index.js +177 -0
  377. package/schematics/migrations/filter-bar-rename-action/schema.json +20 -0
  378. package/schematics/migrations/filter-bar-signals/README.md +27 -16
  379. package/schematics/migrations/filter-bar-signals/data.js +1 -2
  380. package/schematics/migrations/filter-bar-signals/index.js +100 -195
  381. package/schematics/migrations/filter-bar-state-saving-default/README.md +53 -0
  382. package/schematics/migrations/filter-bar-state-saving-default/data.js +87 -0
  383. package/schematics/migrations/filter-bar-state-saving-default/index.js +61 -0
  384. package/schematics/migrations/filter-bar-state-saving-default/schema.json +15 -0
  385. package/schematics/migrations/flag-inner-html/README.md +67 -0
  386. package/schematics/migrations/flag-inner-html/data.js +58 -0
  387. package/schematics/migrations/flag-inner-html/index.js +61 -0
  388. package/schematics/migrations/flag-inner-html/schema.json +15 -0
  389. package/schematics/migrations/form-field-signals/README.md +125 -0
  390. package/schematics/migrations/form-field-signals/data.js +288 -0
  391. package/schematics/migrations/form-field-signals/index.js +382 -0
  392. package/schematics/migrations/form-field-signals/schema.json +20 -0
  393. package/schematics/migrations/icon-semantics-and-api/README.md +65 -0
  394. package/schematics/migrations/icon-semantics-and-api/data.js +97 -0
  395. package/schematics/migrations/icon-semantics-and-api/index.js +64 -0
  396. package/schematics/migrations/icon-semantics-and-api/schema.json +15 -0
  397. package/schematics/migrations/icons-replacement/README.md +5 -5
  398. package/schematics/migrations/icons-replacement/index.js +1 -1
  399. package/schematics/migrations/inline-edit-a11y-and-types/README.md +82 -0
  400. package/schematics/migrations/inline-edit-a11y-and-types/data.js +117 -0
  401. package/schematics/migrations/inline-edit-a11y-and-types/index.js +97 -0
  402. package/schematics/migrations/inline-edit-a11y-and-types/schema.json +20 -0
  403. package/schematics/migrations/input-number-surface/README.md +140 -0
  404. package/schematics/migrations/input-number-surface/data.js +135 -0
  405. package/schematics/migrations/input-number-surface/index.js +292 -0
  406. package/schematics/migrations/input-number-surface/schema.json +20 -0
  407. package/schematics/migrations/input-signals/README.md +20 -0
  408. package/schematics/migrations/input-signals/data.js +30 -0
  409. package/schematics/migrations/input-signals/index.js +17 -0
  410. package/schematics/migrations/input-signals/schema.json +15 -0
  411. package/schematics/migrations/link-deprecated-path/README.md +144 -0
  412. package/schematics/migrations/link-deprecated-path/index.js +19 -0
  413. package/schematics/migrations/link-deprecated-path/schema.json +20 -0
  414. package/schematics/migrations/link-signals/README.md +71 -0
  415. package/schematics/migrations/link-signals/data.js +116 -0
  416. package/schematics/migrations/link-signals/index.js +415 -0
  417. package/schematics/migrations/link-signals/schema.json +20 -0
  418. package/schematics/migrations/list-signals/README.md +22 -0
  419. package/schematics/migrations/list-signals/data.js +35 -0
  420. package/schematics/migrations/list-signals/index.js +17 -0
  421. package/schematics/migrations/list-signals/schema.json +15 -0
  422. package/schematics/migrations/list-tree-multiple-input/README.md +105 -0
  423. package/schematics/migrations/list-tree-multiple-input/data.js +74 -0
  424. package/schematics/migrations/list-tree-multiple-input/index.js +221 -0
  425. package/schematics/migrations/list-tree-multiple-input/schema.json +20 -0
  426. package/schematics/migrations/loader-overlay-signals/README.md +62 -0
  427. package/schematics/migrations/loader-overlay-signals/data.js +101 -0
  428. package/schematics/migrations/loader-overlay-signals/index.js +697 -0
  429. package/schematics/migrations/loader-overlay-signals/schema.json +20 -0
  430. package/schematics/migrations/loader-overlay-size-attr/README.md +2 -2
  431. package/schematics/migrations/loader-overlay-size-attr/index.js +1 -1
  432. package/schematics/migrations/locale-configuration-providers/README.md +163 -0
  433. package/schematics/migrations/locale-configuration-providers/data.js +257 -0
  434. package/schematics/migrations/locale-configuration-providers/index.js +294 -0
  435. package/schematics/migrations/locale-configuration-providers/schema.json +20 -0
  436. package/schematics/migrations/mandatory-peer-dependencies/README.md +70 -0
  437. package/schematics/migrations/mandatory-peer-dependencies/index.js +42 -0
  438. package/schematics/migrations/mandatory-peer-dependencies/schema.json +15 -0
  439. package/schematics/migrations/markdown-signals/README.md +58 -0
  440. package/schematics/migrations/markdown-signals/data.js +79 -0
  441. package/schematics/migrations/markdown-signals/index.js +639 -0
  442. package/schematics/migrations/markdown-signals/schema.json +20 -0
  443. package/schematics/migrations/modal-dialog-semantics/README.md +106 -0
  444. package/schematics/migrations/modal-dialog-semantics/data.js +110 -0
  445. package/schematics/migrations/modal-dialog-semantics/index.js +58 -0
  446. package/schematics/migrations/modal-dialog-semantics/schema.json +15 -0
  447. package/schematics/migrations/modal-signals/README.md +88 -0
  448. package/schematics/migrations/modal-signals/data.js +132 -0
  449. package/schematics/migrations/modal-signals/index.js +19 -0
  450. package/schematics/migrations/modal-signals/schema.json +20 -0
  451. package/schematics/migrations/navbar-signals-and-aria/README.md +111 -0
  452. package/schematics/migrations/navbar-signals-and-aria/data.js +198 -0
  453. package/schematics/migrations/navbar-signals-and-aria/index.js +568 -0
  454. package/schematics/migrations/navbar-signals-and-aria/schema.json +20 -0
  455. package/schematics/migrations/new-icons-pack/README.md +10 -10
  456. package/schematics/migrations/new-icons-pack/index.js +1 -1
  457. package/schematics/migrations/notification-center-signals/README.md +67 -0
  458. package/schematics/migrations/notification-center-signals/data.js +66 -0
  459. package/schematics/migrations/notification-center-signals/index.js +61 -0
  460. package/schematics/migrations/notification-center-signals/schema.json +15 -0
  461. package/schematics/migrations/option-signals/README.md +37 -0
  462. package/schematics/migrations/option-signals/data.js +86 -0
  463. package/schematics/migrations/option-signals/index.js +19 -0
  464. package/schematics/migrations/option-signals/schema.json +20 -0
  465. package/schematics/migrations/popover-leave-delay/README.md +51 -0
  466. package/schematics/migrations/popover-leave-delay/data.js +61 -0
  467. package/schematics/migrations/popover-leave-delay/index.js +54 -0
  468. package/schematics/migrations/popover-leave-delay/schema.json +15 -0
  469. package/schematics/migrations/progress-bar-percentage-and-aria/README.md +54 -0
  470. package/schematics/migrations/progress-bar-percentage-and-aria/data.js +76 -0
  471. package/schematics/migrations/progress-bar-percentage-and-aria/index.js +58 -0
  472. package/schematics/migrations/progress-bar-percentage-and-aria/schema.json +15 -0
  473. package/schematics/migrations/progress-spinner-signals/README.md +72 -0
  474. package/schematics/migrations/progress-spinner-signals/data.js +83 -0
  475. package/schematics/migrations/progress-spinner-signals/index.js +694 -0
  476. package/schematics/migrations/progress-spinner-signals/schema.json +20 -0
  477. package/schematics/migrations/query-list-signals/README.md +32 -0
  478. package/schematics/migrations/query-list-signals/data.js +70 -0
  479. package/schematics/migrations/query-list-signals/index.js +17 -0
  480. package/schematics/migrations/query-list-signals/schema.json +15 -0
  481. package/schematics/migrations/radio-signals-and-aria/README.md +82 -0
  482. package/schematics/migrations/radio-signals-and-aria/data.js +163 -0
  483. package/schematics/migrations/radio-signals-and-aria/index.js +39 -0
  484. package/schematics/migrations/radio-signals-and-aria/schema.json +20 -0
  485. package/schematics/migrations/read-state-dwell-handlers/README.md +125 -0
  486. package/schematics/migrations/read-state-dwell-handlers/data.js +45 -0
  487. package/schematics/migrations/read-state-dwell-handlers/index.js +215 -0
  488. package/schematics/migrations/read-state-dwell-handlers/schema.json +20 -0
  489. package/schematics/migrations/scrollbar-deprecated-path/README.md +128 -0
  490. package/schematics/migrations/scrollbar-deprecated-path/index.js +20 -0
  491. package/schematics/migrations/scrollbar-deprecated-path/schema.json +20 -0
  492. package/schematics/migrations/select-signal-inputs/README.md +61 -0
  493. package/schematics/migrations/select-signal-inputs/data.js +99 -0
  494. package/schematics/migrations/select-signal-inputs/index.js +57 -0
  495. package/schematics/migrations/select-signal-inputs/schema.json +15 -0
  496. package/schematics/migrations/sidepanel-non-modal-behavior/README.md +57 -0
  497. package/schematics/migrations/sidepanel-non-modal-behavior/data.js +111 -0
  498. package/schematics/migrations/sidepanel-non-modal-behavior/index.js +57 -0
  499. package/schematics/migrations/sidepanel-non-modal-behavior/schema.json +15 -0
  500. package/schematics/migrations/signal-inputs-subclasses/README.md +28 -0
  501. package/schematics/migrations/signal-inputs-subclasses/data.js +69 -0
  502. package/schematics/migrations/signal-inputs-subclasses/index.js +17 -0
  503. package/schematics/migrations/signal-inputs-subclasses/schema.json +15 -0
  504. package/schematics/migrations/split-button-optional-disabled/README.md +47 -0
  505. package/schematics/migrations/split-button-optional-disabled/data.js +53 -0
  506. package/schematics/migrations/split-button-optional-disabled/index.js +57 -0
  507. package/schematics/migrations/split-button-optional-disabled/schema.json +15 -0
  508. package/schematics/migrations/splitter-deprecated-path/README.md +136 -0
  509. package/schematics/migrations/splitter-deprecated-path/index.js +20 -0
  510. package/schematics/migrations/splitter-deprecated-path/schema.json +20 -0
  511. package/schematics/migrations/state-saving-default/README.md +67 -0
  512. package/schematics/migrations/state-saving-default/data.js +88 -0
  513. package/schematics/migrations/state-saving-default/index.js +62 -0
  514. package/schematics/migrations/state-saving-default/schema.json +15 -0
  515. package/schematics/migrations/table-cell-content/README.md +55 -0
  516. package/schematics/migrations/table-cell-content/data.js +66 -0
  517. package/schematics/migrations/table-cell-content/index.js +66 -0
  518. package/schematics/migrations/table-cell-content/schema.json +15 -0
  519. package/schematics/migrations/tabs-signals-and-aria/README.md +93 -0
  520. package/schematics/migrations/tabs-signals-and-aria/data.js +139 -0
  521. package/schematics/migrations/tabs-signals-and-aria/index.js +65 -0
  522. package/schematics/migrations/tabs-signals-and-aria/schema.json +15 -0
  523. package/schematics/migrations/tag-list-cleaner/README.md +58 -0
  524. package/schematics/migrations/tag-list-cleaner/data.js +42 -0
  525. package/schematics/migrations/tag-list-cleaner/index.js +196 -0
  526. package/schematics/migrations/tag-list-cleaner/schema.json +20 -0
  527. package/schematics/migrations/tag-slots/README.md +41 -0
  528. package/schematics/migrations/tag-slots/index.js +190 -0
  529. package/schematics/migrations/tag-slots/schema.json +20 -0
  530. package/schematics/migrations/tags-signals/README.md +85 -0
  531. package/schematics/migrations/tags-signals/data.js +103 -0
  532. package/schematics/migrations/tags-signals/index.js +673 -0
  533. package/schematics/migrations/tags-signals/schema.json +20 -0
  534. package/schematics/migrations/textarea-signals/README.md +72 -0
  535. package/schematics/migrations/textarea-signals/data.js +121 -0
  536. package/schematics/migrations/textarea-signals/index.js +379 -0
  537. package/schematics/migrations/textarea-signals/schema.json +20 -0
  538. package/schematics/migrations/time-range-title-for/README.md +164 -0
  539. package/schematics/migrations/time-range-title-for/data.js +139 -0
  540. package/schematics/migrations/time-range-title-for/index.js +163 -0
  541. package/schematics/migrations/time-range-title-for/schema.json +20 -0
  542. package/schematics/migrations/timepicker-signals/README.md +78 -0
  543. package/schematics/migrations/timepicker-signals/data.js +82 -0
  544. package/schematics/migrations/timepicker-signals/index.js +709 -0
  545. package/schematics/migrations/timepicker-signals/schema.json +20 -0
  546. package/schematics/migrations/timezone-grouping-utils/README.md +73 -0
  547. package/schematics/migrations/timezone-grouping-utils/data.js +101 -0
  548. package/schematics/migrations/timezone-grouping-utils/index.js +64 -0
  549. package/schematics/migrations/timezone-grouping-utils/schema.json +15 -0
  550. package/schematics/migrations/title-encapsulation/README.md +49 -0
  551. package/schematics/migrations/title-encapsulation/data.js +69 -0
  552. package/schematics/migrations/title-encapsulation/index.js +57 -0
  553. package/schematics/migrations/title-encapsulation/schema.json +15 -0
  554. package/schematics/migrations/toast-stack-and-defaults/README.md +102 -0
  555. package/schematics/migrations/toast-stack-and-defaults/data.js +79 -0
  556. package/schematics/migrations/toast-stack-and-defaults/index.js +53 -0
  557. package/schematics/migrations/toast-stack-and-defaults/schema.json +15 -0
  558. package/schematics/migrations/tooltip-pointer-events-and-types/README.md +53 -0
  559. package/schematics/migrations/tooltip-pointer-events-and-types/data.js +89 -0
  560. package/schematics/migrations/tooltip-pointer-events-and-types/index.js +60 -0
  561. package/schematics/migrations/tooltip-pointer-events-and-types/schema.json +15 -0
  562. package/schematics/migrations/top-bar-container-selectors/README.md +111 -0
  563. package/schematics/migrations/top-bar-container-selectors/data.js +56 -0
  564. package/schematics/migrations/top-bar-container-selectors/index.js +84 -0
  565. package/schematics/migrations/top-bar-container-selectors/schema.json +20 -0
  566. package/schematics/migrations/tree-select-signals/README.md +61 -0
  567. package/schematics/migrations/tree-select-signals/data.js +106 -0
  568. package/schematics/migrations/tree-select-signals/index.js +58 -0
  569. package/schematics/migrations/tree-select-signals/schema.json +15 -0
  570. package/schematics/migrations/tree-signals/README.md +82 -0
  571. package/schematics/migrations/tree-signals/data.js +123 -0
  572. package/schematics/migrations/tree-signals/index.js +54 -0
  573. package/schematics/migrations/tree-signals/schema.json +15 -0
  574. package/schematics/migrations/tree-state-saving-default/README.md +66 -0
  575. package/schematics/migrations/tree-state-saving-default/data.js +78 -0
  576. package/schematics/migrations/tree-state-saving-default/index.js +60 -0
  577. package/schematics/migrations/tree-state-saving-default/schema.json +15 -0
  578. package/schematics/migrations/username-pipe-injection/README.md +59 -0
  579. package/schematics/migrations/username-pipe-injection/data.js +78 -0
  580. package/schematics/migrations/username-pipe-injection/index.js +58 -0
  581. package/schematics/migrations/username-pipe-injection/schema.json +15 -0
  582. package/schematics/migrations/v20-upgrade/README.md +36 -16
  583. package/schematics/migrations/v20-upgrade/data.js +124 -77
  584. package/schematics/migrations/v20-upgrade/index.js +6 -213
  585. package/schematics/migrations/v21-upgrade/README.md +271 -0
  586. package/schematics/migrations/v21-upgrade/data.js +1371 -0
  587. package/schematics/migrations/v21-upgrade/index.js +94 -0
  588. package/schematics/migrations/v21-upgrade/schema.json +20 -0
  589. package/schematics/migrations/zoneless-change-detection/README.md +30 -0
  590. package/schematics/migrations/zoneless-change-detection/data.js +29 -0
  591. package/schematics/migrations/zoneless-change-detection/index.js +20 -0
  592. package/schematics/migrations/zoneless-change-detection/schema.json +15 -0
  593. package/schematics/migrations.json +392 -2
  594. package/schematics/ng-add/index.js +515 -14
  595. package/schematics/ng-add/schema.json +15 -0
  596. package/schematics/utils/deprecated-path-migration.js +61 -0
  597. package/schematics/utils/package-config.js +9 -105
  598. package/scrollbar/{_scrollbar-component-theme.scss → deprecated/_scrollbar-component-theme.scss} +1 -1
  599. package/scrollbar/{scrollbar.component.scss → deprecated/scrollbar.component.scss} +1 -1
  600. package/scrollbar/native-scrollbar.scss +68 -0
  601. package/scrollbar/scrollbar-tokens.scss +13 -22
  602. package/scrollbar/scrollbar-track.scss +94 -0
  603. package/scrollbar/scrollbar-viewport.scss +33 -0
  604. package/scrollbar/scrollbar.scss +24 -0
  605. package/search-expandable/search-expandable-tokens.scss +4 -0
  606. package/search-expandable/search-expandable.scss +4 -2
  607. package/select/_select-theme.scss +3 -16
  608. package/select/select.scss +0 -6
  609. package/sidebar/sidebar.scss +20 -0
  610. package/sidepanel/_sidepanel-theme.scss +1 -1
  611. package/sidepanel/sidepanel-tokens.scss +7 -1
  612. package/sidepanel/sidepanel.scss +41 -5
  613. package/skeleton/skeleton-presets.scss +350 -0
  614. package/skeleton/skeleton-tokens.scss +127 -0
  615. package/skeleton/skeleton.scss +53 -45
  616. package/split-button/_split-button-theme.scss +4 -4
  617. package/split-button/split-button.scss +2 -6
  618. package/splitter/{_splitter-theme.scss → deprecated/_splitter-theme.scss} +1 -1
  619. package/splitter/deprecated/splitter.scss +51 -0
  620. package/splitter/splitter-tokens.scss +19 -0
  621. package/splitter/splitter.scss +148 -28
  622. package/table/_table-theme.scss +13 -12
  623. package/table/table-tokens.scss +8 -0
  624. package/table/table.scss +47 -22
  625. package/tabs/_tabs-common.scss +14 -14
  626. package/tabs/_tabs-theme.scss +4 -5
  627. package/tabs/tab-body.scss +49 -1
  628. package/tabs/tab-header.scss +2 -1
  629. package/tags/tag-list.scss +4 -0
  630. package/tags/tag.scss +19 -1
  631. package/time-range/time-range.scss +9 -0
  632. package/timezone/timezone-option.component.scss +4 -7
  633. package/timezone/timezone-select.component.scss +3 -0
  634. package/toast/_toast-theme.scss +1 -4
  635. package/toast/toast-container.component.scss +19 -13
  636. package/toast/toast-tokens.scss +12 -6
  637. package/toast/toast.component.scss +42 -19
  638. package/toggle/_toggle-theme.scss +4 -10
  639. package/toggle/toggle.scss +67 -26
  640. package/tooltip/_tooltip-theme.scss +7 -1
  641. package/tooltip/tooltip-tokens.scss +1 -2
  642. package/tooltip/tooltip.scss +55 -9
  643. package/top-bar/top-bar-tokens.scss +13 -2
  644. package/top-bar/top-bar.scss +24 -19
  645. package/tree/_tree-theme.scss +0 -1
  646. package/tree/toggle.scss +5 -9
  647. package/tree/tree-option.scss +2 -4
  648. package/tree/tree-tokens.scss +2 -1
  649. package/tree/tree.scss +3 -5
  650. package/tree-select/_tree-select-theme.scss +4 -15
  651. package/tree-select/tree-select-tokens.scss +16 -0
  652. package/tree-select/tree-select.scss +0 -6
  653. package/{accordion/index.d.ts → types/koobiq-components-accordion.d.ts} +102 -84
  654. package/{actions-panel/index.d.ts → types/koobiq-components-actions-panel.d.ts} +44 -59
  655. package/{alert/index.d.ts → types/koobiq-components-alert.d.ts} +8 -3
  656. package/types/koobiq-components-app-switcher.d.ts +406 -0
  657. package/types/koobiq-components-autocomplete.d.ts +443 -0
  658. package/{badge/index.d.ts → types/koobiq-components-badge.d.ts} +25 -20
  659. package/{breadcrumbs/index.d.ts → types/koobiq-components-breadcrumbs.d.ts} +97 -46
  660. package/types/koobiq-components-button-toggle.d.ts +340 -0
  661. package/types/koobiq-components-button.d.ts +296 -0
  662. package/types/koobiq-components-checkbox.d.ts +172 -0
  663. package/types/koobiq-components-clamped-text.d.ts +184 -0
  664. package/{code-block/index.d.ts → types/koobiq-components-code-block.d.ts} +114 -79
  665. package/{content-panel/index.d.ts → types/koobiq-components-content-panel.d.ts} +81 -25
  666. package/{core/index.d.ts → types/koobiq-components-core.d.ts} +2827 -865
  667. package/{datepicker/index.d.ts → types/koobiq-components-datepicker.d.ts} +161 -116
  668. package/types/koobiq-components-divider.d.ts +43 -0
  669. package/types/koobiq-components-dl.d.ts +235 -0
  670. package/{dropdown/index.d.ts → types/koobiq-components-dropdown.d.ts} +245 -239
  671. package/types/koobiq-components-ellipsis-center.d.ts +85 -0
  672. package/types/koobiq-components-empty-state.d.ts +106 -0
  673. package/{file-upload/index.d.ts → types/koobiq-components-file-upload.d.ts} +214 -107
  674. package/{filter-bar/index.d.ts → types/koobiq-components-filter-bar.d.ts} +410 -495
  675. package/types/koobiq-components-flag.d.ts +68 -0
  676. package/{form-field/index.d.ts → types/koobiq-components-form-field.d.ts} +167 -191
  677. package/types/koobiq-components-icon.d.ts +333 -0
  678. package/{inline-edit/index.d.ts → types/koobiq-components-inline-edit.d.ts} +109 -46
  679. package/types/koobiq-components-input.d.ts +477 -0
  680. package/types/koobiq-components-link-deprecated.d.ts +101 -0
  681. package/types/koobiq-components-link.d.ts +176 -0
  682. package/{list/index.d.ts → types/koobiq-components-list.d.ts} +162 -99
  683. package/types/koobiq-components-loader-overlay.d.ts +101 -0
  684. package/{markdown/index.d.ts → types/koobiq-components-markdown.d.ts} +16 -24
  685. package/types/koobiq-components-modal.d.ts +666 -0
  686. package/types/koobiq-components-navbar.d.ts +569 -0
  687. package/types/koobiq-components-notification-center.d.ts +500 -0
  688. package/{overflow-items/index.d.ts → types/koobiq-components-overflow-items.d.ts} +8 -22
  689. package/types/koobiq-components-popover.d.ts +468 -0
  690. package/types/koobiq-components-progress-bar.d.ts +67 -0
  691. package/{progress-spinner/index.d.ts → types/koobiq-components-progress-spinner.d.ts} +33 -10
  692. package/types/koobiq-components-radio.d.ts +294 -0
  693. package/{resizer/index.d.ts → types/koobiq-components-resizer.d.ts} +37 -2
  694. package/{scrollbar/index.d.ts → types/koobiq-components-scrollbar-deprecated.d.ts} +18 -1
  695. package/types/koobiq-components-scrollbar.d.ts +154 -0
  696. package/types/koobiq-components-search-expandable.d.ts +164 -0
  697. package/{select/index.d.ts → types/koobiq-components-select.d.ts} +360 -167
  698. package/types/koobiq-components-sidebar.d.ts +152 -0
  699. package/types/koobiq-components-sidepanel.d.ts +436 -0
  700. package/types/koobiq-components-skeleton.d.ts +234 -0
  701. package/types/koobiq-components-split-button.d.ts +65 -0
  702. package/{splitter/index.d.ts → types/koobiq-components-splitter-deprecated.d.ts} +44 -1
  703. package/types/koobiq-components-splitter.d.ts +406 -0
  704. package/types/koobiq-components-table.d.ts +44 -0
  705. package/types/koobiq-components-tabs.d.ts +888 -0
  706. package/{tags/index.d.ts → types/koobiq-components-tags.d.ts} +249 -133
  707. package/types/koobiq-components-textarea.d.ts +178 -0
  708. package/{time-range/index.d.ts → types/koobiq-components-time-range.d.ts} +135 -62
  709. package/types/koobiq-components-timepicker.d.ts +223 -0
  710. package/types/koobiq-components-timezone.d.ts +266 -0
  711. package/types/koobiq-components-title.d.ts +184 -0
  712. package/types/koobiq-components-toast.d.ts +289 -0
  713. package/types/koobiq-components-toggle.d.ts +121 -0
  714. package/types/koobiq-components-tooltip.d.ts +610 -0
  715. package/types/koobiq-components-top-bar.d.ts +61 -0
  716. package/types/koobiq-components-tree-select.d.ts +667 -0
  717. package/types/koobiq-components-tree.d.ts +1290 -0
  718. package/types/koobiq-components-username.d.ts +340 -0
  719. package/username/_username-theme.scss +35 -0
  720. package/username/username.scss +10 -34
  721. package/app-switcher/index.d.ts +0 -276
  722. package/autocomplete/index.d.ts +0 -286
  723. package/button/index.d.ts +0 -153
  724. package/button-toggle/index.d.ts +0 -162
  725. package/checkbox/index.d.ts +0 -163
  726. package/clamped-text/index.d.ts +0 -146
  727. package/core/styles/_tokens.scss +0 -7
  728. package/core/styles/common/_clearfix.scss +0 -13
  729. package/core/styles/common/_popup.scss +0 -6
  730. package/core/styles/functions/_index.scss +0 -3
  731. package/core/styles/functions/_number.scss +0 -60
  732. package/core/styles/functions/_string.scss +0 -18
  733. package/core/styles/theming/scrollbar-tokens.scss +0 -25
  734. package/core/styles/typography/_typography-utils.scss +0 -84
  735. package/divider/index.d.ts +0 -20
  736. package/dl/index.d.ts +0 -45
  737. package/ellipsis-center/index.d.ts +0 -71
  738. package/empty-state/index.d.ts +0 -45
  739. package/flag/index.d.ts +0 -44
  740. package/icon/index.d.ts +0 -200
  741. package/input/index.d.ts +0 -354
  742. package/link/index.d.ts +0 -56
  743. package/loader-overlay/index.d.ts +0 -57
  744. package/modal/index.d.ts +0 -339
  745. package/navbar/index.d.ts +0 -372
  746. package/notification-center/index.d.ts +0 -323
  747. package/popover/index.d.ts +0 -182
  748. package/prebuilt-themes/dark-theme.css +0 -1
  749. package/prebuilt-themes/light-theme.css +0 -1
  750. package/progress-bar/index.d.ts +0 -31
  751. package/radio/index.d.ts +0 -203
  752. package/search-expandable/index.d.ts +0 -101
  753. package/sidebar/index.d.ts +0 -94
  754. package/sidepanel/index.d.ts +0 -272
  755. package/skeleton/index.d.ts +0 -26
  756. package/split-button/index.d.ts +0 -46
  757. package/table/index.d.ts +0 -25
  758. package/tabs/index.d.ts +0 -677
  759. package/textarea/index.d.ts +0 -138
  760. package/timepicker/index.d.ts +0 -197
  761. package/timezone/index.d.ts +0 -125
  762. package/title/index.d.ts +0 -139
  763. package/toast/index.d.ts +0 -178
  764. package/toggle/index.d.ts +0 -104
  765. package/tooltip/index.d.ts +0 -335
  766. package/top-bar/index.d.ts +0 -33
  767. package/tree/index.d.ts +0 -802
  768. package/tree-select/index.d.ts +0 -475
  769. package/username/index.d.ts +0 -194
  770. /package/{dynamic-translation/index.d.ts → types/koobiq-components-dynamic-translation.d.ts} +0 -0
  771. /package/{index.d.ts → types/koobiq-components.d.ts} +0 -0
@@ -1,18 +1,19 @@
1
1
  import { SelectionModel, DataSource } from '@angular/cdk/collections';
2
2
  import { BehaviorSubject, merge, Observable, of, Subject, asyncScheduler } from 'rxjs';
3
- import { escapeRegExp, KbqPseudoCheckbox, KbqOptionActionComponent, kbqFocusAndReveal, kbqGetElementHeight, kbqFocusOptionActionOnTab, hasModifierKey, KbqActionContainer, KBQ_TITLE_TEXT_REF, KBQ_OPTION_ACTION_PARENT, getSelectAllState, MultipleMode, ruRULocaleData, KBQ_LOCALE_SERVICE, FocusKeyManager, SPACE, LEFT_ARROW, RIGHT_ARROW, isVerticalMovement, isSelectAll, isCopy, TAB, DOWN_ARROW, UP_ARROW, ENTER, HOME, END, PAGE_UP, PAGE_DOWN, toggleSelectAll, getKbqSelectNonArrayValueError, KbqPseudoCheckboxModule } from '@koobiq/components/core';
3
+ import * as i1 from '@koobiq/components/core';
4
+ import { escapeRegExp, KbqStateSaving, KbqPseudoCheckbox, KbqOptionActionComponent, kbqFocusAndReveal, kbqGetElementHeight, kbqFocusOptionActionOnTab, hasModifierKey, KbqActionContainer, KBQ_TITLE_TEXT_REF, KBQ_OPTION_ACTION_PARENT, MultipleMode, getSelectAllState, kbqQueryListFrom, KbqLocaleOverridesDirective, KBQ_SELECT_LOCALE_CONFIGURATION, kbqOptionalNumberAttribute, kbqSelectAllHandlerTransform, resolveMultipleMode, FocusKeyManager, kbqLeaveTabOrderOnTabOut, SPACE, LEFT_ARROW, RIGHT_ARROW, isVerticalMovement, isSelectAll, isCopy, TAB, DOWN_ARROW, UP_ARROW, ENTER, HOME, END, PAGE_UP, PAGE_DOWN, toggleSelectAll, getKbqSelectNonArrayValueError, KbqPseudoCheckboxModule } from '@koobiq/components/core';
4
5
  import { take, map, delay } from 'rxjs/operators';
5
6
  import * as i0 from '@angular/core';
6
- import { inject, TemplateRef, input, Directive, ViewContainerRef, ChangeDetectorRef, IterableDiffers, DestroyRef, Input, ContentChildren, ViewChild, ElementRef, booleanAttribute, ViewEncapsulation, ChangeDetectionStrategy, Component, InjectionToken, NgZone, contentChild, output, EventEmitter, ContentChild, Renderer2, forwardRef, HostAttributeToken, QueryList, viewChild, signal, effect, Output, NgModule } from '@angular/core';
7
+ import { signal, inject, TemplateRef, input, Directive, ViewContainerRef, IterableDiffers, ChangeDetectorRef, viewChild, contentChildren, DestroyRef, effect, untracked, isDevMode, ElementRef, booleanAttribute, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, InjectionToken, EnvironmentInjector, contentChild, linkedSignal, output, EventEmitter, afterNextRender, Renderer2, forwardRef, Injector, QueryList, NgModule } from '@angular/core';
7
8
  import { Directionality } from '@angular/cdk/bidi';
8
9
  import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
9
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
+ import { takeUntilDestroyed, toSignal, outputFromObservable } from '@angular/core/rxjs-interop';
11
+ import { _getFocusedElementPierceShadowDom, Platform } from '@angular/cdk/platform';
10
12
  import { KbqDropdownTrigger } from '@koobiq/components/dropdown';
11
13
  import { KbqTooltipTrigger } from '@koobiq/components/tooltip';
12
14
  import { KbqIcon, KbqIconModule } from '@koobiq/components/icon';
13
15
  import { FocusMonitor } from '@angular/cdk/a11y';
14
16
  import { Clipboard } from '@angular/cdk/clipboard';
15
- import { Platform } from '@angular/cdk/platform';
16
17
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
17
18
  import { KBQ_FORM_FIELD } from '@koobiq/components/form-field';
18
19
  import { AsyncScheduler } from 'rxjs/internal/scheduler/AsyncScheduler';
@@ -78,6 +79,11 @@ class BaseTreeControl {
78
79
  }
79
80
 
80
81
  const kbqTreeSelectAllValue = 'selectAll';
82
+ /**
83
+ * Default first stage of the filter pipeline: keeps the nodes whose view value matches the query.
84
+ *
85
+ * @docs-private
86
+ */
81
87
  class FilterByViewValue {
82
88
  constructor(control) {
83
89
  this.control = control;
@@ -95,6 +101,12 @@ class FilterByViewValue {
95
101
  return this.result;
96
102
  }
97
103
  }
104
+ /**
105
+ * Default last stage of the filter pipeline: re-adds the ancestors of every matched node so the
106
+ * matches stay reachable in the rendered hierarchy.
107
+ *
108
+ * @docs-private
109
+ */
98
110
  class FilterParentsForNodes {
99
111
  constructor(control) {
100
112
  this.control = control;
@@ -124,6 +136,7 @@ class FilterByValues {
124
136
  this.result = Array.from(new Set([...(prevFilter?.result || []), ...found]));
125
137
  return this.result;
126
138
  }
139
+ // TODO: nothing in the library uses it; kept as public API at the DS-2196 review. Document or deprecate it.
127
140
  getValues() {
128
141
  return this.values;
129
142
  }
@@ -159,6 +172,7 @@ class FlatTreeControl extends BaseTreeControl {
159
172
  this.isDisabled = isDisabled;
160
173
  this.setFilters(new FilterByViewValue(this), new FilterParentsForNodes(this));
161
174
  }
175
+ // TODO: nothing in the library uses it; kept as public API at the DS-2196 review. Document or deprecate it.
162
176
  getFilters() {
163
177
  return this.filters;
164
178
  }
@@ -194,14 +208,32 @@ class FlatTreeControl extends BaseTreeControl {
194
208
  expandAll() {
195
209
  this.expansionModel.select(...this.dataNodes);
196
210
  }
197
- getParents(node, result) {
198
- if (node.parent) {
199
- result.unshift(node.parent);
200
- return this.getParents(node.parent, result);
201
- }
202
- else {
211
+ /**
212
+ * Ancestors of a data node, outermost first.
213
+ *
214
+ * Derived from `dataNodes` rather than from a `parent` back-reference: the flattened nodes are in
215
+ * depth-first order, so scanning backwards from the node, the first node of a smaller level is its
216
+ * parent, and repeating with that level yields the whole chain. A data node whose shape carries no
217
+ * `parent` therefore resolves just as well as one that does.
218
+ *
219
+ * @param result Collector the ancestors are prepended to. Provided so callers can accumulate into
220
+ * an existing array; a fresh one is used when omitted.
221
+ */
222
+ getParents(node, result = []) {
223
+ const startIndex = this.dataNodes?.indexOf(node) ?? -1;
224
+ if (startIndex === -1) {
203
225
  return result;
204
226
  }
227
+ let level = this.getLevel(node);
228
+ for (let i = startIndex - 1; i >= 0 && level > 0; i--) {
229
+ const candidate = this.dataNodes[i];
230
+ const candidateLevel = this.getLevel(candidate);
231
+ if (candidateLevel < level) {
232
+ result.unshift(candidate);
233
+ level = candidateLevel;
234
+ }
235
+ }
236
+ return result;
205
237
  }
206
238
  hasValue(value) {
207
239
  return this.dataNodes?.find((node) => this.compareValues(this.getValue(node), value));
@@ -237,7 +269,13 @@ class FlatTreeControl extends BaseTreeControl {
237
269
 
238
270
  /** Nested tree control. Able to expand/collapse a subtree recursively for NestedNode type. */
239
271
  class NestedTreeControl extends BaseTreeControl {
240
- /** Construct with nested tree function getChildren. */
272
+ /**
273
+ * Construct with nested tree function getChildren.
274
+ *
275
+ * @param getChildren Must emit **synchronously** (e.g. `of(children)` or a `BehaviorSubject`).
276
+ * `getDescendants` walks the tree with `take(1)` and returns as soon as the recursion unwinds, so
277
+ * an asynchronous source yields an incomplete — usually empty — descendant list.
278
+ */
241
279
  constructor(getChildren) {
242
280
  super();
243
281
  this.getChildren = getChildren;
@@ -278,33 +316,41 @@ class NestedTreeControl extends BaseTreeControl {
278
316
  * Transform nested nodes of type `T` to flattened nodes of type `F`.
279
317
  *
280
318
  * For example, the input data of type `T` is nested, and contains its children data:
281
- * SomeNode: {
319
+ *
320
+ * ```ts
321
+ * SomeNode: {
282
322
  * key: 'Fruits',
283
323
  * children: [
284
- * NodeOne: {
285
- * key: 'Apple',
286
- * },
287
- * NodeTwo: {
288
- * key: 'Pear',
289
- * }
290
- * ]
291
- * }
292
- * After flattener flatten the tree, the structure will become
293
- * SomeNode: {
294
- * key: 'Fruits',
295
- * expandable: true,
296
- * level: 1
297
- * },
298
- * NodeOne: {
299
- * key: 'Apple',
300
- * expandable: false,
301
- * level: 2
302
- * },
303
- * NodeTwo: {
304
- * key: 'Pear',
305
- * expandable: false,
306
- * level: 2
324
+ * NodeOne: {
325
+ * key: 'Apple'
326
+ * },
327
+ * NodeTwo: {
328
+ * key: 'Pear'
329
+ * }
330
+ * ]
331
+ * }
332
+ * ```
333
+ *
334
+ * After flattener flatten the tree, the structure will become
335
+ *
336
+ * ```ts
337
+ * SomeNode: {
338
+ * key: 'Fruits',
339
+ * expandable: true,
340
+ * level: 1
341
+ * },
342
+ * NodeOne: {
343
+ * key: 'Apple',
344
+ * expandable: false,
345
+ * level: 2
346
+ * },
347
+ * NodeTwo: {
348
+ * key: 'Pear',
349
+ * expandable: false,
350
+ * level: 2
307
351
  * }
352
+ * ```
353
+ *
308
354
  * and the output flattened type is `F` with additional information.
309
355
  */
310
356
  class KbqTreeFlattener {
@@ -314,6 +360,7 @@ class KbqTreeFlattener {
314
360
  this.isExpandable = isExpandable;
315
361
  this.getChildren = getChildren;
316
362
  }
363
+ /** @docs-private */
317
364
  flattenNode(node, level, resultNodes, parent) {
318
365
  const flatNode = this.transformFunction(node, level, parent);
319
366
  resultNodes.push(flatNode);
@@ -332,6 +379,7 @@ class KbqTreeFlattener {
332
379
  }
333
380
  return resultNodes;
334
381
  }
382
+ /** @docs-private */
335
383
  flattenChildren(children, level, resultNodes, parent) {
336
384
  children.forEach((child) => {
337
385
  this.flattenNode(child, level + 1, resultNodes, parent);
@@ -379,15 +427,15 @@ var KbqTreeDataSourceChangeTypes;
379
427
  * Data source for flat tree.
380
428
  * The data source need to handle expansion/collapsion of the tree node and change the data feed
381
429
  * to `KbqTree`.
382
- * The nested tree nodes of type `T` are flattened through `MсTreeFlattener`, and converted
430
+ * The nested tree nodes of type `T` are flattened through `KbqTreeFlattener`, and converted
383
431
  * to type `F` for `KbqTree` to consume.
384
432
  */
385
433
  class KbqTreeFlatDataSource extends DataSource {
386
434
  get data() {
387
- return this._data.value;
435
+ return this._data();
388
436
  }
389
437
  set data(value) {
390
- this._data.next(value);
438
+ this._data.set(value);
391
439
  this.flattenedData.next(this.treeFlattener.flattenNodes(this.data));
392
440
  this.treeControl.dataNodes = this.flattenedData.value;
393
441
  }
@@ -398,7 +446,12 @@ class KbqTreeFlatDataSource extends DataSource {
398
446
  this.flattenedData = new BehaviorSubject([]);
399
447
  this.expandedData = new BehaviorSubject([]);
400
448
  this.filteredData = new BehaviorSubject([]);
401
- this._data = new BehaviorSubject(initialData);
449
+ this._data = signal([], ...(ngDevMode ? [{ debugName: "_data" }] : /* istanbul ignore next */ []));
450
+ this._data.set(initialData);
451
+ // The setter flattens the data for the tree.
452
+ if (initialData.length) {
453
+ this.data = initialData;
454
+ }
402
455
  }
403
456
  connect(collectionViewer) {
404
457
  return merge(collectionViewer.viewChange, this.treeControl.expansionModel.changed.pipe(map((value) => ({ type: KbqTreeDataSourceChangeTypes.Expansion, value }))), this.treeControl.filterValue.pipe(map((value) => ({ type: KbqTreeDataSourceChangeTypes.Filter, value }))), this.flattenedData).pipe(map((changeObj) => {
@@ -465,12 +518,12 @@ class KbqTreeNodeOutletContext {
465
518
  class KbqTreeNodeDef {
466
519
  constructor() {
467
520
  this.template = inject(TemplateRef);
468
- this.data = input(undefined, ...(ngDevMode ? [{ debugName: "data", alias: 'kbqTreeNode' }] : [{ alias: 'kbqTreeNode' }]));
521
+ this.data = input(undefined, { ...(ngDevMode ? { debugName: "data" } : /* istanbul ignore next */ {}), alias: 'kbqTreeNode' });
469
522
  }
470
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
471
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.30", type: KbqTreeNodeDef, isStandalone: true, selector: "[kbqTreeNodeDef]", inputs: { when: { classPropertyName: "when", publicName: "kbqTreeNodeDefWhen", isSignal: false, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "kbqTreeNode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
523
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
524
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.25", type: KbqTreeNodeDef, isStandalone: true, selector: "[kbqTreeNodeDef]", inputs: { when: { classPropertyName: "when", publicName: "kbqTreeNodeDefWhen", isSignal: false, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "kbqTreeNode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
472
525
  }
473
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeDef, decorators: [{
526
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeDef, decorators: [{
474
527
  type: Directive,
475
528
  args: [{
476
529
  selector: '[kbqTreeNodeDef]',
@@ -481,12 +534,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
481
534
  class KbqTreeNodeOutlet {
482
535
  constructor() {
483
536
  this.viewContainer = inject(ViewContainerRef);
484
- this.changeDetectorRef = inject(ChangeDetectorRef);
485
537
  }
486
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
487
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqTreeNodeOutlet, isStandalone: true, selector: "[kbqTreeNodeOutlet]", ngImport: i0 }); }
538
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
539
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: KbqTreeNodeOutlet, isStandalone: true, selector: "[kbqTreeNodeOutlet]", ngImport: i0 }); }
488
540
  }
489
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeOutlet, decorators: [{
541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeOutlet, decorators: [{
490
542
  type: Directive,
491
543
  args: [{
492
544
  selector: '[kbqTreeNodeOutlet]'
@@ -495,6 +547,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
495
547
 
496
548
  /**
497
549
  * Returns an error to be thrown when there is no usable data.
550
+ *
498
551
  * @docs-private
499
552
  */
500
553
  function getTreeNoValidDataSourceError() {
@@ -502,6 +555,7 @@ function getTreeNoValidDataSourceError() {
502
555
  }
503
556
  /**
504
557
  * Returns an error to be thrown when there are multiple nodes that are missing a when function.
558
+ *
505
559
  * @docs-private
506
560
  */
507
561
  function getTreeMultipleDefaultNodeDefsError() {
@@ -509,6 +563,7 @@ function getTreeMultipleDefaultNodeDefsError() {
509
563
  }
510
564
  /**
511
565
  * Returns an error to be thrown when there are no matching node defs for a particular set of data.
566
+ *
512
567
  * @docs-private
513
568
  */
514
569
  function getTreeMissingMatchingNodeDefError() {
@@ -516,62 +571,165 @@ function getTreeMissingMatchingNodeDefError() {
516
571
  }
517
572
  /**
518
573
  * Returns an error to be thrown when there are tree control.
574
+ *
519
575
  * @docs-private
520
576
  */
521
577
  function getTreeControlMissingError() {
522
578
  return Error(`Could not find a tree control for the tree.`);
523
579
  }
524
580
  /**
525
- * Returns an error to be thrown when tree control did not implement functions for flat/nested node.
581
+ * Returns an error to be thrown when the selection mode of a tree is changed while its `SelectionModel`
582
+ * belongs to a host `KbqTreeSelect`.
583
+ *
526
584
  * @docs-private
527
585
  */
528
- function getTreeControlFunctionsMissingError() {
529
- return Error(`Could not find functions for nested/flat tree in tree control.`);
586
+ function getKbqTreeSelectionOwnedMultipleError() {
587
+ return Error('Cannot change the multiplicity of `multiple` on a `kbq-tree-selection` rendered inside a ' +
588
+ '`kbq-tree-select`: the select owns the selection model. Set `multiple` on the select instead.');
530
589
  }
531
590
 
591
+ /**
592
+ * Coerces a raw persisted payload into a `KbqTreeState`, returning `null` for anything unrecognizable.
593
+ *
594
+ * Web storage is origin-wide and user-writable, so a payload is never trusted — without this, an entry
595
+ * such as `{"a": null}` would reach `hasValue()` while restoring.
596
+ */
597
+ const normalizeTreeState = (parsed) => {
598
+ if (!Array.isArray(parsed))
599
+ return null;
600
+ const values = parsed.filter((value) => typeof value === 'string');
601
+ // An array that held nothing usable is somebody else's payload, not "nothing was expanded" — the
602
+ // difference matters, because only the second one is a state worth keeping.
603
+ return values.length || !parsed.length ? values : null;
604
+ };
605
+ /**
606
+ * Rendering core of the tree.
607
+ *
608
+ * Originally forked from `@angular/cdk/tree` and maintained independently since: the node/outlet
609
+ * contract, the option-based selection model and the filtering pipeline have all diverged, so
610
+ * `@angular/cdk/tree` is deliberately not a dependency of this package and upstream fixes have to be
611
+ * ported by hand.
612
+ *
613
+ * `C` narrows the tree control a concrete tree accepts, and so the type its `treeControl` binding is checked against.
614
+ */
532
615
  class KbqTreeBase {
616
+ /** Controls the expanded state and holds the data nodes of the tree. */
617
+ get treeControl() {
618
+ return this.treeControlInput();
619
+ }
620
+ /** {@link treeControl} as state saving reads it: by node value, which only a `FlatTreeControl` has. */
621
+ get flatTreeControl() {
622
+ const treeControl = this.treeControl;
623
+ return treeControl;
624
+ }
625
+ /** Outlet within the tree's template where the data nodes are inserted. */
626
+ get nodeOutlet() {
627
+ return this.nodeOutletQuery();
628
+ }
629
+ /**
630
+ * Provides a stream containing the latest data array to render. Influenced by the tree's
631
+ * stream of view window (what dataNodes are currently on screen).
632
+ * Data source can be an observable of data array, or a data array to render.
633
+ */
634
+ get dataSource() {
635
+ return this._dataSource;
636
+ }
533
637
  constructor() {
534
638
  this.differs = inject(IterableDiffers);
535
639
  this.changeDetectorRef = inject(ChangeDetectorRef);
640
+ /**
641
+ * Persistence of the expanded state, applied as a host directive by the concrete tree components.
642
+ * Optional because `KbqTreeBase` is exported: a tree without the directive persists nothing.
643
+ */
644
+ this.stateSaving = inject(KbqStateSaving, { optional: true });
645
+ /** @docs-private */
646
+ this.treeControlInput = input(undefined, { ...(ngDevMode ? { debugName: "treeControlInput" } : /* istanbul ignore next */ {}), alias: 'treeControl' });
536
647
  /**
537
648
  * Tracking function that will be used to check the differences in data changes. Used similarly
538
649
  * to `ngFor` `trackBy` function. Optimize node operations by identifying a node based on its data
539
650
  * relative to the function to know if a node should be added/removed/moved.
540
651
  * Accepts a function that takes two parameters, `index` and `item`.
652
+ *
653
+ * Views are reused for nodes the function reports as unchanged, which a data source that rebuilds
654
+ * its node objects on every emission — a flattener among them — otherwise cannot get.
541
655
  */
542
- this.trackBy = input(undefined, ...(ngDevMode ? [{ debugName: "trackBy" }] : []));
543
- // TODO(tinayuangao): Setup a listener for scrolling, emit the calculated view to viewChange.
544
- // Remove the MAX_VALUE in viewChange
656
+ this.trackBy = input(undefined, ...(ngDevMode ? [{ debugName: "trackBy" }] : /* istanbul ignore next */ []));
657
+ this.nodeOutletQuery = viewChild(KbqTreeNodeOutlet, ...(ngDevMode ? [{ debugName: "nodeOutletQuery" }] : /* istanbul ignore next */ []));
658
+ /** The tree node template for the tree */
659
+ this.nodeDefs = contentChildren(KbqTreeNodeDef, ...(ngDevMode ? [{ debugName: "nodeDefs" }] : /* istanbul ignore next */ []));
545
660
  /**
546
661
  * Stream containing the latest information on what rows are being displayed on screen.
547
662
  * Can be used by the data source to as a heuristic of what data should be provided.
663
+ *
664
+ * The tree renders every expanded node eagerly, so the window is the whole data set; a data source
665
+ * cannot use it to page or virtualize. Windowing would have to emit a real range from a scroll
666
+ * listener here first.
548
667
  */
549
668
  this.viewChange = new BehaviorSubject({ start: 0, end: Number.MAX_VALUE });
550
669
  /** Level of nodes */
551
670
  this.levels = new Map();
671
+ /** Most recently constructed node of this tree, see `registerNode`. */
672
+ this.recentNode = null;
673
+ /** Node rendered for a given outlet context, so a reused view can be handed its new data. */
674
+ this.nodesByContext = new WeakMap();
675
+ /**
676
+ * Values from the persisted state whose node has not appeared in `treeControl.dataNodes` yet —
677
+ * applied as the nodes show up, and dropped the first time each node is seen.
678
+ */
679
+ this.pendingValues = new Set();
680
+ /** The `dataNodes` the last restore ran against, so an unchanged list is not walked again. */
681
+ this.lastRestoredDataNodes = null;
682
+ /**
683
+ * Whether the persisted state has been read. `KbqTreeSelect` calls `ngAfterContentInit()` by hand on
684
+ * the tree it projects into its panel, and a second read would resurrect values the user dismissed.
685
+ */
686
+ this.hasRead = false;
687
+ /** Whether the dev-mode warnings below have already been logged, so each is logged once. */
688
+ this.warnedAboutTreeControl = false;
689
+ this.warnedAboutValues = false;
690
+ /** @docs-private */
691
+ this.dataSourceInput = input(undefined, { ...(ngDevMode ? { debugName: "dataSourceInput" } : /* istanbul ignore next */ {}), alias: 'dataSource' });
692
+ this._dataSource = null;
552
693
  this.destroyRef = inject(DestroyRef);
553
- }
554
- /**
555
- * Provides a stream containing the latest data array to render. Influenced by the tree's
556
- * stream of view window (what dataNodes are currently on screen).
557
- * Data source can be an observable of data array, or a data array to render.
558
- */
559
- // TODO: Skipped for migration because:
560
- // Accessor inputs cannot be migrated as they are too complex.
561
- get dataSource() {
562
- return this._dataSource;
563
- }
564
- set dataSource(dataSource) {
565
- if (this._dataSource !== dataSource) {
566
- this.switchDataSource(dataSource);
567
- }
694
+ /** Whether `ngAfterContentChecked` has run, i.e. the node definitions the first render needs are resolved. */
695
+ this.contentChecked = false;
696
+ // Switching the source drops the rendered nodes and resubscribes, which a bound value alone does not do. A
697
+ // binding back to `undefined` clears the tree as `null` does; an unbound input equals the initial `null`.
698
+ effect(() => {
699
+ const dataSource = this.dataSourceInput() ?? null;
700
+ untracked(() => {
701
+ if (dataSource !== this._dataSource)
702
+ this.switchDataSource(dataSource);
703
+ });
704
+ });
568
705
  }
569
706
  ngOnInit() {
570
- this.dataDiffer = this.differs.find([]).create(this.trackBy());
707
+ this.dataDiffer = this.createDataDiffer();
571
708
  if (!this.treeControl) {
572
709
  throw getTreeControlMissingError();
573
710
  }
574
711
  }
712
+ ngAfterContentInit() {
713
+ // Before `ngAfterContentChecked` connects the data source, so the restored nodes are expanded
714
+ // ahead of the first render rather than causing a second one.
715
+ if (this.hasRead || !this.persists)
716
+ return;
717
+ this.hasRead = true;
718
+ // The state lives under the new key now, so restore from it.
719
+ this.stateSaving.keyChanges.subscribe(() => this.restoreState());
720
+ this.restoreState();
721
+ }
722
+ /** Reads the persisted expansion and applies it. Runs while initializing, and again on a key change. */
723
+ restoreState() {
724
+ if (!this.persists)
725
+ return;
726
+ const savedState = this.stateSaving.read(normalizeTreeState);
727
+ this.pendingValues = new Set(savedState ?? []);
728
+ // The memo that keeps one batch of nodes from being examined twice. A restore from another key
729
+ // has new values to match against the same nodes, so it has to be allowed to look again.
730
+ this.lastRestoredDataNodes = null;
731
+ this.restorePending();
732
+ }
575
733
  ngOnDestroy() {
576
734
  this.nodeOutlet.viewContainer.clear();
577
735
  if (this._dataSource && typeof this.dataSource.disconnect === 'function') {
@@ -583,20 +741,65 @@ class KbqTreeBase {
583
741
  }
584
742
  }
585
743
  ngAfterContentChecked() {
586
- const defaultNodeDefs = this.nodeDefs.filter((def) => !def.when);
744
+ const defaultNodeDefs = this.nodeDefs().filter((def) => !def.when);
587
745
  if (defaultNodeDefs.length > 1) {
588
746
  throw getTreeMultipleDefaultNodeDefsError();
589
747
  }
590
748
  this.defaultNodeDef = defaultNodeDefs[0];
591
- if (this.dataSource && this.nodeDefs && !this.dataSubscription) {
749
+ this.contentChecked = true;
750
+ if (this.dataSource && this.nodeDefs().length && !this.dataSubscription) {
592
751
  this.observeRenderChanges();
593
752
  }
594
753
  }
754
+ /**
755
+ * Persists the values of the currently expanded nodes.
756
+ *
757
+ * Called for every expansion and collapse a user performs. Expansion driven by the application —
758
+ * `treeControl.expandAll()`, or writing to `expansionModel` — is not persisted; call this to record it.
759
+ *
760
+ * A no-op while a filter is active: what is expanded then is the result set, not a chosen state.
761
+ */
762
+ saveState() {
763
+ // Untracked, as in `clearSavedState()`: called from a consumer's `effect()`, the inputs read on the way would
764
+ // make the effect run again whenever they change.
765
+ untracked(() => {
766
+ if (!this.persists || this.treeControl.filterValue.value?.length)
767
+ return;
768
+ this.stateSaving.write(this.expandedValues());
769
+ });
770
+ }
771
+ /**
772
+ * Removes the state persisted for this tree.
773
+ *
774
+ * Persistence itself stays on — the next expansion is written again.
775
+ */
776
+ clearSavedState() {
777
+ untracked(() => this.stateSaving?.clear());
778
+ }
779
+ /**
780
+ * Whether state is currently persisted for this tree — restored on init, or written since.
781
+ * Always `false` while `useStateSaving` is unset, and `false` again after `clearSavedState()`.
782
+ */
783
+ get hasSavedState() {
784
+ return this.stateSaving?.state != null;
785
+ }
595
786
  /** Check for changes made in the data and render each change (node added/removed/moved). */
596
787
  renderNodeChanges(data, dataDiffer = this.dataDiffer, viewContainer = this.nodeOutlet.viewContainer, parentData) {
788
+ if (this.applyNodeChanges(data, dataDiffer, viewContainer, parentData)) {
789
+ this.changeDetectorRef.detectChanges();
790
+ }
791
+ }
792
+ /**
793
+ * Applies the data changes to the view container without running change detection, and reports
794
+ * whether anything moved. Split out of `renderNodeChanges` so a subclass can update the state its
795
+ * own template reads before the single change-detection pass, instead of running a second one.
796
+ *
797
+ * @docs-private
798
+ */
799
+ applyNodeChanges(data, dataDiffer, viewContainer, parentData) {
597
800
  const changes = dataDiffer.diff(data);
598
801
  if (!changes) {
599
- return;
802
+ return false;
600
803
  }
601
804
  changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
602
805
  if (item.previousIndex == null) {
@@ -611,7 +814,30 @@ class KbqTreeBase {
611
814
  viewContainer.move(view, currentIndex);
612
815
  }
613
816
  });
614
- this.changeDetectorRef.detectChanges();
817
+ // A node kept its identity but is a different object — what a data source that rebuilds its
818
+ // nodes on every emission produces, a flattener among them. The view is reused, so the object
819
+ // it and its `KbqTreeNode` still hold is gone from `dataNodes`, and every lookup keyed on the
820
+ // node reference (`getDescendants`, `isExpanded`, the selection) would miss it.
821
+ changes.forEachIdentityChange((record) => {
822
+ this.refreshNodeData(viewContainer, record.currentIndex, record.item);
823
+ });
824
+ return true;
825
+ }
826
+ refreshNodeData(viewContainer, index, nodeData) {
827
+ const view = viewContainer.get(index);
828
+ if (!view) {
829
+ return;
830
+ }
831
+ const { context } = view;
832
+ const previousData = context.$implicit;
833
+ context.$implicit = nodeData;
834
+ this.levels.delete(previousData);
835
+ this.levels.set(nodeData, context.level);
836
+ const node = this.nodesByContext.get(context);
837
+ if (node) {
838
+ node.data = nodeData;
839
+ node.refresh();
840
+ }
615
841
  }
616
842
  /**
617
843
  * Finds the matching node definition that should be used for this node data. If there is only
@@ -620,10 +846,11 @@ class KbqTreeBase {
620
846
  * definition.
621
847
  */
622
848
  getNodeDef(data, i) {
623
- if (this.nodeDefs.length === 1) {
624
- return this.nodeDefs.first;
849
+ const nodeDefs = this.nodeDefs();
850
+ if (nodeDefs.length === 1) {
851
+ return nodeDefs[0];
625
852
  }
626
- const nodeDef = this.nodeDefs.find((def) => def.when && def.when(i, data)) || this.defaultNodeDef;
853
+ const nodeDef = nodeDefs.find((def) => def.when && def.when(i, data)) || this.defaultNodeDef;
627
854
  if (!nodeDef) {
628
855
  throw getTreeMissingMatchingNodeDefError();
629
856
  }
@@ -637,6 +864,7 @@ class KbqTreeBase {
637
864
  const node = this.getNodeDef(nodeData, index);
638
865
  // Node context that will be provided to created embedded view
639
866
  const context = new KbqTreeNodeOutletContext(nodeData);
867
+ context.index = index;
640
868
  // If the tree is flat tree, then use the `getLevel` function in flat tree control
641
869
  // Otherwise, use the level of parent node.
642
870
  const treeControl = this.treeControl;
@@ -653,12 +881,100 @@ class KbqTreeBase {
653
881
  // Use default tree nodeOutlet, or nested node's nodeOutlet
654
882
  const container = viewContainer ? viewContainer : this.nodeOutlet.viewContainer;
655
883
  container.createEmbeddedView(node.template, context, index);
656
- // Set the data to just created `KbqTreeNode`.
657
- // The `KbqTreeNode` created from `createEmbeddedView` will be saved in static variable
658
- // `mostRecentTreeNode`. We get it from static variable and pass the node data to it.
659
- if (KbqTreeNode.mostRecentTreeNode) {
660
- KbqTreeNode.mostRecentTreeNode.data = nodeData;
884
+ // The `KbqTreeNode` instantiated by `createEmbeddedView` registers itself here on construction,
885
+ // which is the only handle onto it — the embedded view exposes its context, not its directives.
886
+ // It is remembered against that context so a later re-render can reach it again.
887
+ if (this.recentNode) {
888
+ this.recentNode.data = nodeData;
889
+ this.nodesByContext.set(context, this.recentNode);
890
+ this.recentNode = null;
891
+ }
892
+ }
893
+ /**
894
+ * Called by a `KbqTreeNode` while it is being constructed, so `insertNode` can hand it its data.
895
+ *
896
+ * @docs-private
897
+ */
898
+ registerNode(node) {
899
+ this.recentNode = node;
900
+ }
901
+ /** Whether this tree reads and writes its expanded state at all. */
902
+ get persists() {
903
+ if (!this.stateSaving?.useStateSaving())
904
+ return false;
905
+ // A tree that is not in the document has no stable key — the default resolver derives one from
906
+ // the path to `<body>`. That is the ordinary state of a tree projected into an overlay, such as
907
+ // the one `kbq-tree-select` renders into its panel, whose expansion is transient UI rather than
908
+ // a setting worth carrying to the next visit.
909
+ if (!this.stateSaving.host?.isConnected)
910
+ return false;
911
+ if (typeof this.flatTreeControl.getValue !== 'function') {
912
+ if (isDevMode() && !this.warnedAboutTreeControl) {
913
+ this.warnedAboutTreeControl = true;
914
+ // eslint-disable-next-line no-console
915
+ console.warn('kbq-tree: state saving is enabled, but the tree control has no `getValue`. ' +
916
+ 'Expansion is persisted by node value, and a node object does not survive a ' +
917
+ 'reload, so nothing is persisted. Use `FlatTreeControl`, or unset ' +
918
+ '`useStateSaving`.');
919
+ }
920
+ return false;
921
+ }
922
+ return true;
923
+ }
924
+ /**
925
+ * Expands every pending value whose node is present, and stops tracking it.
926
+ *
927
+ * Idempotent, and safe to call on every render: the pending set only shrinks, so a tree that has
928
+ * restored everything does no work at all.
929
+ */
930
+ restorePending() {
931
+ if (!this.pendingValues.size)
932
+ return;
933
+ const currentNodes = this.treeControl.dataNodes;
934
+ // Nothing new to match against. Deliberately does not record an empty list, so the first real
935
+ // batch of an asynchronously loaded tree is still examined.
936
+ if (currentNodes === this.lastRestoredDataNodes || !currentNodes?.length)
937
+ return;
938
+ this.lastRestoredDataNodes = currentNodes;
939
+ const treeControl = this.flatTreeControl;
940
+ const found = [];
941
+ for (const value of this.pendingValues) {
942
+ const node = treeControl.hasValue(value);
943
+ if (node) {
944
+ found.push(node);
945
+ this.pendingValues.delete(value);
946
+ }
947
+ }
948
+ // Straight at the model rather than through `expand()`, which is a no-op while a filter is
949
+ // active — restoring must not depend on what the user happens to be searching for.
950
+ if (found.length) {
951
+ this.stateSaving.applying(() => treeControl.expansionModel.select(...found));
952
+ }
953
+ }
954
+ /** The values of the nodes that are currently expanded, plus the ones still waiting to appear. */
955
+ expandedValues() {
956
+ const treeControl = this.flatTreeControl;
957
+ const expanded = [];
958
+ let skipped = false;
959
+ for (const node of treeControl.expansionModel.selected) {
960
+ const value = treeControl.getValue(node);
961
+ if (typeof value === 'string') {
962
+ expanded.push(value);
963
+ }
964
+ else {
965
+ skipped = true;
966
+ }
661
967
  }
968
+ if (skipped && isDevMode() && !this.warnedAboutValues) {
969
+ this.warnedAboutValues = true;
970
+ // eslint-disable-next-line no-console
971
+ console.warn('kbq-tree: `getValue` returned a value that is not a string for at least one node. ' +
972
+ 'Expansion is persisted as JSON keyed by that value, so those nodes are left out.');
973
+ }
974
+ // Union with what is still pending: on a tree whose data arrives in batches the expanded nodes
975
+ // are only part of what was saved, and writing the snapshot alone would drop every branch that
976
+ // has not been loaded yet.
977
+ return [...new Set([...expanded, ...this.pendingValues])];
662
978
  }
663
979
  /** Set up a subscription for the data provided by the data source. */
664
980
  observeRenderChanges() {
@@ -675,9 +991,15 @@ class KbqTreeBase {
675
991
  dataStream = of(this._dataSource);
676
992
  }
677
993
  if (dataStream) {
678
- this.dataSubscription = dataStream
679
- .pipe(takeUntilDestroyed(this.destroyRef))
680
- .subscribe((data) => this.renderNodeChanges(data));
994
+ this.dataSubscription = dataStream.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data) => {
995
+ this.renderNodeChanges(data);
996
+ // On a microtask, and only while something is still pending: expanding re-enters this
997
+ // very subscription — the flat data source merges `expansionModel.changed` — and
998
+ // `renderNodeChanges` has just run `detectChanges()`.
999
+ if (this.pendingValues.size) {
1000
+ Promise.resolve().then(() => this.restorePending());
1001
+ }
1002
+ });
681
1003
  }
682
1004
  else {
683
1005
  throw getTreeNoValidDataSourceError();
@@ -696,35 +1018,45 @@ class KbqTreeBase {
696
1018
  this.dataSubscription.unsubscribe();
697
1019
  this.dataSubscription = null;
698
1020
  }
699
- // Remove the all dataNodes if there is now no data source
700
- if (!dataSource) {
701
- this.nodeOutlet.viewContainer.clear();
702
- }
1021
+ // Every rendered node belongs to the previous source, so none of them survives the switch. The
1022
+ // differ is reset below and no longer reports them as removals, which makes these two the only
1023
+ // things that drop the old nodes — for a null source and for a replacement source alike. Left
1024
+ // to the differ, `levels` would keep an entry, and with it a strong reference, for every node
1025
+ // of every source the tree has ever been given.
1026
+ this.nodeOutlet.viewContainer.clear();
1027
+ this.levels.clear();
703
1028
  this._dataSource = dataSource;
704
- if (this.nodeDefs) {
1029
+ // The differ remembers the nodes of the previous source. Left in place, the first diff against
1030
+ // the new source is computed as a delta from data that is no longer rendered, so views are
1031
+ // reused for unrelated nodes or dropped entirely.
1032
+ this.dataDiffer = this.createDataDiffer();
1033
+ // Not before the first `ngAfterContentChecked`: that is where the default node definition is resolved,
1034
+ // and a render ahead of it finds no definition for the nodes and throws, taking the subscription down
1035
+ // with it and leaving the tree permanently empty. The initial render is picked up there; a later
1036
+ // source swap is observed here right away.
1037
+ if (dataSource && this.contentChecked && this.nodeDefs().length) {
705
1038
  this.observeRenderChanges();
706
1039
  }
707
1040
  }
708
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
709
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.30", type: KbqTreeBase, isStandalone: true, inputs: { treeControl: { classPropertyName: "treeControl", publicName: "treeControl", isSignal: false, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: false, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "nodeDefs", predicate: KbqTreeNodeDef }], viewQueries: [{ propertyName: "nodeOutlet", first: true, predicate: KbqTreeNodeOutlet, descendants: true, static: true }], ngImport: i0 }); }
1041
+ createDataDiffer() {
1042
+ return this.differs.find([]).create(this.trackBy());
1043
+ }
1044
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1045
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.25", type: KbqTreeBase, isStandalone: true, inputs: { treeControlInput: { classPropertyName: "treeControlInput", publicName: "treeControl", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, dataSourceInput: { classPropertyName: "dataSourceInput", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "nodeDefs", predicate: KbqTreeNodeDef, isSignal: true }], viewQueries: [{ propertyName: "nodeOutletQuery", first: true, predicate: KbqTreeNodeOutlet, descendants: true, isSignal: true }], ngImport: i0 }); }
710
1046
  }
711
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeBase, decorators: [{
1047
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeBase, decorators: [{
712
1048
  type: Directive
713
- }], propDecorators: { treeControl: [{
714
- type: Input
715
- }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], nodeOutlet: [{
716
- type: ViewChild,
717
- args: [KbqTreeNodeOutlet, { static: true }]
718
- }], nodeDefs: [{
719
- type: ContentChildren,
720
- args: [KbqTreeNodeDef]
721
- }], dataSource: [{
722
- type: Input
723
- }] } });
1049
+ }], ctorParameters: () => [], propDecorators: { treeControlInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeControl", required: false }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], nodeOutletQuery: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqTreeNodeOutlet), { isSignal: true }] }], nodeDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => KbqTreeNodeDef), { isSignal: true }] }], dataSourceInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }] } });
1050
+ // `KbqTree` declares `role="tree"`, whose owned elements have to be `treeitem`s — and a bare
1051
+ // `kbq-tree-node` is the only kind of row it can render, since `KbqTreeOption` needs a parent only
1052
+ // `KbqTreeSelection` provides. The nodes are rendered flat into a single outlet, so the depth an AT
1053
+ // reports comes from `aria-level` rather than from the DOM.
724
1054
  class KbqTreeNode {
725
1055
  /**
726
- * The most recently created `KbqTreeNode`. We save it in static variable so we can retrieve it
727
- * in `KbqTree` and set the data to it.
1056
+ * The most recently created `KbqTreeNode`, across every tree on the page.
1057
+ *
1058
+ * @deprecated Kept for backwards compatibility only — the tree hands a node its data through
1059
+ * `KbqTreeBase.registerNode`, which is scoped to the tree that owns the node. Will be removed in 22.0.0.
728
1060
  */
729
1061
  static { this.mostRecentTreeNode = null; }
730
1062
  get data() {
@@ -744,89 +1076,100 @@ class KbqTreeNode {
744
1076
  this.elementRef = inject(ElementRef);
745
1077
  this.tree = inject(KbqTreeBase);
746
1078
  this.destroyed = new Subject();
1079
+ /**
1080
+ * Emits after the tree reused this node's view for a different data object, so a directive on the
1081
+ * same element can re-derive what it computed from the previous one.
1082
+ *
1083
+ * @docs-private
1084
+ */
1085
+ this.refreshed = new Subject();
747
1086
  KbqTreeNode.mostRecentTreeNode = this;
1087
+ this.tree.registerNode(this);
748
1088
  }
749
1089
  ngOnDestroy() {
750
1090
  this.destroyed.next();
751
1091
  this.destroyed.complete();
1092
+ this.refreshed.complete();
1093
+ }
1094
+ /**
1095
+ * Called by the tree once `data` has been replaced on a reused view. State a subclass derived from
1096
+ * the previous node — its value, its level — is stale at this point and has to be recomputed.
1097
+ *
1098
+ * @docs-private
1099
+ */
1100
+ refresh() {
1101
+ this.refreshed.next();
752
1102
  }
753
1103
  focus() {
754
1104
  this.elementRef.nativeElement.focus();
755
1105
  }
756
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNode, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
757
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqTreeNode, isStandalone: true, selector: "kbq-tree-node", exportAs: ["kbqTreeNode"], ngImport: i0 }); }
1106
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNode, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1107
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: KbqTreeNode, isStandalone: true, selector: "kbq-tree-node", host: { attributes: { "role": "treeitem" }, properties: { "attr.aria-level": "level + 1" } }, exportAs: ["kbqTreeNode"], ngImport: i0 }); }
758
1108
  }
759
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNode, decorators: [{
1109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNode, decorators: [{
760
1110
  type: Directive,
761
1111
  args: [{
762
1112
  selector: 'kbq-tree-node',
1113
+ host: {
1114
+ role: 'treeitem',
1115
+ '[attr.aria-level]': 'level + 1'
1116
+ },
763
1117
  exportAs: 'kbqTreeNode'
764
1118
  }]
765
1119
  }], ctorParameters: () => [] });
766
1120
 
767
1121
  /** @docs-private */
768
1122
  class KbqTreeNodeToggleBaseDirective {
769
- // TODO: Skipped for migration because:
770
- // Accessor inputs cannot be migrated as they are too complex.
771
- get recursive() {
772
- return this._recursive;
773
- }
774
- set recursive(value) {
775
- this._recursive = coerceBooleanProperty(value);
1123
+ constructor() {
1124
+ this.tree = inject(KbqTreeBase);
1125
+ this.treeNode = inject(KbqTreeNode);
1126
+ this.node = input(undefined, ...(ngDevMode ? [{ debugName: "node" }] : /* istanbul ignore next */ []));
1127
+ /** Whether toggling expands or collapses the whole subtree instead of the node alone. */
1128
+ this.recursive = input(false, { ...(ngDevMode ? { debugName: "recursive" } : /* istanbul ignore next */ {}), alias: 'kbqTreeNodeToggleRecursive', transform: booleanAttribute });
1129
+ /**
1130
+ * Backing input of `disabled`. Bind through the `disabled` attribute; read the `disabled` getter,
1131
+ * which also reports the toggle disabled while a filter is active.
1132
+ *
1133
+ * @docs-private
1134
+ */
1135
+ this.disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled', transform: booleanAttribute });
1136
+ /** Set while a filter is active: filtering already decides what is expanded. */
1137
+ this.filterDisabled = toSignal(this.tree.treeControl.filterValue.pipe(map((value) => !!value?.length)), { initialValue: false });
1138
+ this.disabledState = computed(() => this.disabledInput() || this.filterDisabled(), ...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
776
1139
  }
777
- // TODO: Skipped for migration because:
778
- // Accessor inputs cannot be migrated as they are too complex.
779
1140
  get disabled() {
780
- return this._disabled;
781
- }
782
- set disabled(value) {
783
- if (value !== this.disabled) {
784
- this._disabled = value;
785
- }
1141
+ return this.disabledState();
786
1142
  }
787
1143
  get iconState() {
788
1144
  return this.tree.treeControl.isExpanded(this.node());
789
1145
  }
790
- constructor() {
791
- this.tree = inject(KbqTreeBase);
792
- this.treeNode = inject(KbqTreeNode);
793
- this.node = input(undefined, ...(ngDevMode ? [{ debugName: "node" }] : []));
794
- this._recursive = false;
795
- this._disabled = false;
796
- this.tree.treeControl.filterValue.subscribe((value) => (this.disabled = !!value?.length));
797
- }
798
1146
  toggle(event) {
799
1147
  if (this.disabled)
800
1148
  return;
801
- if (this.recursive) {
1149
+ if (this.recursive()) {
802
1150
  this.tree.treeControl.toggleDescendants(this.treeNode.data);
803
1151
  }
804
1152
  else {
805
1153
  this.tree.treeControl.toggle(this.treeNode.data);
806
1154
  }
1155
+ this.tree.saveState();
807
1156
  event.stopPropagation();
808
1157
  }
809
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeToggleBaseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
810
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.30", type: KbqTreeNodeToggleBaseDirective, isStandalone: true, inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: false, transformFunction: null }, recursive: { classPropertyName: "recursive", publicName: "kbqTreeNodeToggleRecursive", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, ngImport: i0 }); }
1158
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeToggleBaseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1159
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.25", type: KbqTreeNodeToggleBaseDirective, isStandalone: true, inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: false, transformFunction: null }, recursive: { classPropertyName: "recursive", publicName: "kbqTreeNodeToggleRecursive", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
811
1160
  }
812
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeToggleBaseDirective, decorators: [{
1161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeToggleBaseDirective, decorators: [{
813
1162
  type: Directive
814
- }], ctorParameters: () => [], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: false }] }], recursive: [{
815
- type: Input,
816
- args: ['kbqTreeNodeToggleRecursive']
817
- }], disabled: [{
818
- type: Input,
819
- args: [{ transform: booleanAttribute }]
820
- }] } });
1163
+ }], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: false }] }], recursive: [{ type: i0.Input, args: [{ isSignal: true, alias: "kbqTreeNodeToggleRecursive", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
821
1164
  class KbqTreeNodeToggleComponent extends KbqTreeNodeToggleBaseDirective {
822
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeToggleComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
823
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.30", type: KbqTreeNodeToggleComponent, isStandalone: true, selector: "kbq-tree-node-toggle", host: { listeners: { "click": "toggle($event)" }, properties: { "class.kbq-expanded": "iconState", "attr.disabled": "disabled || null" }, classAttribute: "kbq-tree-node-toggle" }, exportAs: ["kbqTreeNodeToggle"], usesInheritance: true, ngImport: i0, template: `
1165
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeToggleComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1166
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: KbqTreeNodeToggleComponent, isStandalone: true, selector: "kbq-tree-node-toggle", host: { attributes: { "aria-hidden": "true" }, listeners: { "click": "toggle($event)" }, properties: { "class.kbq-expanded": "iconState", "attr.disabled": "disabled || null", "attr.aria-disabled": "disabled || null" }, classAttribute: "kbq-tree-node-toggle" }, exportAs: ["kbqTreeNodeToggle"], usesInheritance: true, ngImport: i0, template: `
824
1167
  <ng-content>
825
1168
  <i kbq-icon="kbq-chevron-down-s_16" [color]="'contrast-fade'"></i>
826
1169
  </ng-content>
827
- `, isInline: true, styles: [".kbq-tree-node-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;height:100%;padding-left:var(--kbq-tree-size-toggle-padding);padding-right:var(--kbq-tree-size-toggle-padding);cursor:pointer}.kbq-tree-node-toggle .kbq-icon{transform:rotate(-90deg)}.kbq-tree-node-toggle.kbq-expanded .kbq-icon{transform:rotate(0)}.kbq-tree-node-toggle[disabled]{cursor:default}.kbq-tree-node-toggle[disabled] .kbq-icon{color:var(--kbq-tree-states-disabled-tree-toggle-color)}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "component", type: KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1170
+ `, isInline: true, styles: [".kbq-tree-node-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;height:100%;cursor:pointer}.kbq-tree-node-toggle .kbq-icon{transform:rotate(-90deg)}.kbq-tree-node-toggle.kbq-expanded .kbq-icon{transform:rotate(0)}.kbq-tree-node-toggle[disabled]{cursor:default}.kbq-tree-node-toggle[disabled] .kbq-icon{color:var(--kbq-tree-states-disabled-tree-toggle-color)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "component", type: KbqIcon, selector: "[kbq-icon]", inputs: ["aria-hidden", "iconSize", "autoColor", "kbq-icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
828
1171
  }
829
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeToggleComponent, decorators: [{
1172
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeToggleComponent, decorators: [{
830
1173
  type: Component,
831
1174
  args: [{ selector: 'kbq-tree-node-toggle', imports: [KbqIcon], template: `
832
1175
  <ng-content>
@@ -834,16 +1177,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
834
1177
  </ng-content>
835
1178
  `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
836
1179
  class: 'kbq-tree-node-toggle',
1180
+ // The expanded state is announced on the owning `treeitem` through `aria-expanded`, and the
1181
+ // Left/Right arrow keys drive it, so exposing the chevron as a second control would only add
1182
+ // a duplicate stop for assistive tech.
1183
+ 'aria-hidden': 'true',
837
1184
  '[class.kbq-expanded]': 'iconState',
838
1185
  '[attr.disabled]': 'disabled || null',
1186
+ '[attr.aria-disabled]': 'disabled || null',
839
1187
  '(click)': 'toggle($event)'
840
- }, exportAs: 'kbqTreeNodeToggle', styles: [".kbq-tree-node-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;height:100%;padding-left:var(--kbq-tree-size-toggle-padding);padding-right:var(--kbq-tree-size-toggle-padding);cursor:pointer}.kbq-tree-node-toggle .kbq-icon{transform:rotate(-90deg)}.kbq-tree-node-toggle.kbq-expanded .kbq-icon{transform:rotate(0)}.kbq-tree-node-toggle[disabled]{cursor:default}.kbq-tree-node-toggle[disabled] .kbq-icon{color:var(--kbq-tree-states-disabled-tree-toggle-color)}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
1188
+ }, exportAs: 'kbqTreeNodeToggle', styles: [".kbq-tree-node-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;height:100%;cursor:pointer}.kbq-tree-node-toggle .kbq-icon{transform:rotate(-90deg)}.kbq-tree-node-toggle.kbq-expanded .kbq-icon{transform:rotate(0)}.kbq-tree-node-toggle[disabled]{cursor:default}.kbq-tree-node-toggle[disabled] .kbq-icon{color:var(--kbq-tree-states-disabled-tree-toggle-color)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
841
1189
  }] });
1190
+ // No ARIA on this host: the directive is routinely applied to the `kbq-tree-option` element itself,
1191
+ // where the option already owns `role`, `aria-disabled` and the rest of the treeitem semantics.
842
1192
  class KbqTreeNodeToggleDirective extends KbqTreeNodeToggleBaseDirective {
843
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeToggleDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
844
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqTreeNodeToggleDirective, isStandalone: true, selector: "[kbq-tree-node-toggle], [kbqTreeNodeToggle]", host: { listeners: { "click": "toggle($event)" }, properties: { "attr.disabled": "disabled || null" } }, exportAs: ["kbqTreeNodeToggle"], usesInheritance: true, ngImport: i0 }); }
1193
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeToggleDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1194
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: KbqTreeNodeToggleDirective, isStandalone: true, selector: "[kbq-tree-node-toggle], [kbqTreeNodeToggle]", host: { listeners: { "click": "toggle($event)" }, properties: { "attr.disabled": "disabled || null" } }, exportAs: ["kbqTreeNodeToggle"], usesInheritance: true, ngImport: i0 }); }
845
1195
  }
846
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodeToggleDirective, decorators: [{
1196
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodeToggleDirective, decorators: [{
847
1197
  type: Directive,
848
1198
  args: [{
849
1199
  selector: '[kbq-tree-node-toggle], [kbqTreeNodeToggle]',
@@ -857,24 +1207,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
857
1207
 
858
1208
  /** Injection token used to provide the parent component to options. */
859
1209
  const KBQ_TREE_OPTION_PARENT_COMPONENT = new InjectionToken('KBQ_TREE_OPTION_PARENT_COMPONENT');
860
- /**
861
- * Represents a change event for a tree option.
862
- *
863
- * @param source - The tree option that has been modified or selected.
864
- * @param isUserInput - DEPRECATED Will be removed in version 20.
865
- */
1210
+ /** Represents a change event for a tree option. */
866
1211
  class KbqTreeOptionChange {
867
- constructor(source, isUserInput = false) {
1212
+ constructor(
1213
+ /** The tree option that has been modified or selected. */
1214
+ source) {
868
1215
  this.source = source;
869
- this.isUserInput = isUserInput;
870
1216
  }
871
1217
  }
872
1218
  let uniqueIdCounter = 0;
1219
+ const samePredicates = (a, b) => a.disabled === b.disabled && a.expanded === b.expanded;
873
1220
  class KbqTreeOption extends KbqTreeNode {
1221
+ /** Container of the option text, measured by `kbq-title`. */
1222
+ get parentTextElement() {
1223
+ return this.titleContainer();
1224
+ }
874
1225
  // Same element as `parentTextElement` — `.kbq-option-text` clips the text, so it is measured against itself.
875
1226
  get textElement() {
876
1227
  return this.parentTextElement;
877
1228
  }
1229
+ // Getters rather than the signal queries themselves: `KbqOptionActionComponent` reads the triggers as
1230
+ // directive instances through KBQ_OPTION_ACTION_PARENT — see #DS-5079.
1231
+ /** Tooltip trigger projected into the option. */
1232
+ get tooltipTrigger() {
1233
+ return this.tooltipTriggerQuery();
1234
+ }
1235
+ /** Dropdown trigger projected into the option. */
1236
+ get dropdownTrigger() {
1237
+ return this.dropdownTriggerQuery();
1238
+ }
878
1239
  get externalPseudoCheckbox() {
879
1240
  return !!this.pseudoCheckbox();
880
1241
  }
@@ -884,34 +1245,23 @@ class KbqTreeOption extends KbqTreeNode {
884
1245
  set value(value) {
885
1246
  this._value = value;
886
1247
  }
887
- // TODO: Skipped for migration because:
888
- // Accessor inputs cannot be migrated as they are too complex.
1248
+ /** Whether the option is disabled: through its own input, the tree, or the tree control's `isDisabled`. */
889
1249
  get disabled() {
890
1250
  if (this.selectAllRow()) {
891
- return this._disabled || this.tree.disabled;
892
- }
893
- return this._disabled || this.tree.disabled || this.tree.treeControl.isDisabled(this.data);
894
- }
895
- set disabled(value) {
896
- const newValue = coerceBooleanProperty(value);
897
- if (newValue !== this._disabled) {
898
- this._disabled = newValue;
1251
+ return this.disabledInput() || this.tree.disabled;
899
1252
  }
1253
+ return this.disabledInput() || this.tree.disabled || this.tree.treeControl.isDisabled(this.data);
900
1254
  }
901
- // TODO: Skipped for migration because:
902
- // Accessor inputs cannot be migrated as they are too complex.
1255
+ /** Whether the option renders a pseudo-checkbox. Falls back to the tree's own mode until bound. */
903
1256
  get showCheckbox() {
904
- return this._showCheckbox !== undefined ? this._showCheckbox : this.tree.showCheckbox;
905
- }
906
- set showCheckbox(value) {
907
- this._showCheckbox = coerceBooleanProperty(value);
1257
+ return this.showCheckboxInput() ?? this.tree.showCheckbox;
908
1258
  }
909
1259
  get selected() {
910
- return this._selected;
1260
+ return this.selectedState();
911
1261
  }
912
1262
  set selected(value) {
913
1263
  const isSelected = coerceBooleanProperty(value);
914
- if (isSelected !== this._selected) {
1264
+ if (isSelected !== this.selectedState()) {
915
1265
  this.setSelected(isSelected);
916
1266
  }
917
1267
  }
@@ -922,6 +1272,12 @@ class KbqTreeOption extends KbqTreeNode {
922
1272
  // TODO: Add input property alternative for node envs.
923
1273
  return (this.getHostElement().textContent || '').trim();
924
1274
  }
1275
+ get hasFocus() {
1276
+ return this.focused();
1277
+ }
1278
+ set hasFocus(value) {
1279
+ this.focused.set(value);
1280
+ }
925
1281
  get isExpandable() {
926
1282
  if (this.selectAllRow()) {
927
1283
  return false;
@@ -938,28 +1294,84 @@ class KbqTreeOption extends KbqTreeNode {
938
1294
  get isToggleInDefaultPlace() {
939
1295
  return !!(this.toggleElementDirective() || this.toggleElementComponent());
940
1296
  }
1297
+ get checkboxState() {
1298
+ return this.checkbox();
1299
+ }
1300
+ set checkboxState(value) {
1301
+ this.checkbox.set(value);
1302
+ }
1303
+ /**
1304
+ * `aria-expanded` of the row as of the last check, reported for every branch and omitted on a leaf.
1305
+ *
1306
+ * Deliberately not `isExpandable`, which also asks whether the toggle is operable: filtering
1307
+ * disables every toggle while leaving the matched branches expanded, and a branch that stops
1308
+ * reporting `aria-expanded` is announced as a leaf while its children are on screen.
1309
+ */
1310
+ get ariaExpanded() {
1311
+ // The one tracked read of `predicates`, which subscribes the row to the signals the predicates read: the
1312
+ // other bindings read the snapshot `ngDoCheck` takes along with it, as a second read of this row's own signal
1313
+ // would walk the producers of every row checked before it.
1314
+ return this.predicates().expanded;
1315
+ }
1316
+ /**
1317
+ * `aria-checked` of the row: tri-state for a checkbox option, and the "select all" state for the
1318
+ * row that drives it. `null` for a plain option, which reports `aria-selected` instead.
1319
+ */
1320
+ get ariaChecked() {
1321
+ // The checkbox state is read here rather than in `ngDoCheck`: this read is what brings the row back once the
1322
+ // state changes.
1323
+ return this.checkedCheckboxRow ? this.toAriaChecked(this.checkboxState) : this.checkedSelectAllState;
1324
+ }
1325
+ /** `aria-selected` of the row as of the last check. Options with a checkbox report `aria-checked` instead. */
1326
+ get ariaSelected() {
1327
+ return this.checkedAriaSelected;
1328
+ }
941
1329
  constructor() {
942
1330
  const tree = inject(KBQ_TREE_OPTION_PARENT_COMPONENT);
943
1331
  super();
944
1332
  this.changeDetectorRef = inject(ChangeDetectorRef);
945
- this.ngZone = inject(NgZone);
1333
+ this.environmentInjector = inject(EnvironmentInjector);
946
1334
  this.destroyRef = inject(DestroyRef);
947
- this.onFocus = new Subject();
948
- this.onBlur = new Subject();
1335
+ this.focusEvents = new Subject();
1336
+ this.blurEvents = new Subject();
1337
+ /** Emits when the option takes focus. */
1338
+ this.onFocus = this.focusEvents.asObservable();
1339
+ /** Emits when the option loses focus. */
1340
+ this.onBlur = this.blurEvents.asObservable();
949
1341
  this.preventBlur = false;
950
- this.toggleElementDirective = contentChild(KbqTreeNodeToggleDirective, ...(ngDevMode ? [{ debugName: "toggleElementDirective" }] : []));
951
- this.toggleElementComponent = contentChild(KbqTreeNodeToggleComponent, ...(ngDevMode ? [{ debugName: "toggleElementComponent" }] : []));
952
- this.pseudoCheckbox = contentChild(KbqPseudoCheckbox, ...(ngDevMode ? [{ debugName: "pseudoCheckbox" }] : []));
953
- this.actionButton = contentChild(KbqOptionActionComponent, ...(ngDevMode ? [{ debugName: "actionButton" }] : []));
954
- this.checkboxThirdState = input(false, ...(ngDevMode ? [{ debugName: "checkboxThirdState" }] : []));
955
- this._disabled = false;
1342
+ this.titleContainer = viewChild('kbqTitleContainer', ...(ngDevMode ? [{ debugName: "titleContainer" }] : /* istanbul ignore next */ []));
1343
+ this.toggleElementDirective = contentChild(KbqTreeNodeToggleDirective, ...(ngDevMode ? [{ debugName: "toggleElementDirective" }] : /* istanbul ignore next */ []));
1344
+ this.toggleElementComponent = contentChild(KbqTreeNodeToggleComponent, ...(ngDevMode ? [{ debugName: "toggleElementComponent" }] : /* istanbul ignore next */ []));
1345
+ this.pseudoCheckbox = contentChild(KbqPseudoCheckbox, ...(ngDevMode ? [{ debugName: "pseudoCheckbox" }] : /* istanbul ignore next */ []));
1346
+ this.actionButton = contentChild(KbqOptionActionComponent, ...(ngDevMode ? [{ debugName: "actionButton" }] : /* istanbul ignore next */ []));
1347
+ this.tooltipTriggerQuery = contentChild(KbqTooltipTrigger, ...(ngDevMode ? [{ debugName: "tooltipTriggerQuery" }] : /* istanbul ignore next */ []));
1348
+ this.dropdownTriggerQuery = contentChild(KbqDropdownTrigger, ...(ngDevMode ? [{ debugName: "dropdownTriggerQuery" }] : /* istanbul ignore next */ []));
1349
+ this.checkboxThirdState = input(false, ...(ngDevMode ? [{ debugName: "checkboxThirdState" }] : /* istanbul ignore next */ []));
1350
+ /** @docs-private */
1351
+ this.disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled',
1352
+ transform: booleanAttribute });
1353
+ /**
1354
+ * `disabled` as of the last check, which the host bindings read: the tree control's `isDisabled` predicate gives
1355
+ * no notice of a change and may be costly, so a check asks it once.
1356
+ */
1357
+ this.checkedDisabled = false;
1358
+ /**
1359
+ * What the tree control's `isDisabled` and `isExpandable` say about the row. Derived, so a predicate reading a
1360
+ * signal brings the row back once that signal changes; `ngDoCheck` sets it on every check for one reading plain
1361
+ * state. Read by a single host binding, see `ariaExpanded`.
1362
+ */
1363
+ this.predicates = linkedSignal(() => this.resolvePredicates(), { ...(ngDevMode ? { debugName: "predicates" } : /* istanbul ignore next */ {}), equal: samePredicates });
1364
+ // Values of the ARIA host bindings as of the last check, resolved by `ngDoCheck`.
1365
+ this.checkedAriaSelected = null;
1366
+ this.checkedSelectAllState = null;
1367
+ this.checkedCheckboxRow = false;
956
1368
  /**
957
1369
  * Whether the option can be selected by user interaction (click, keyboard, select all).
958
1370
  * A non-selectable option remains focusable, navigable and expandable.
959
1371
  * Programmatic selection (`setSelected`, `select`, value accessor) is not affected.
960
1372
  * Options that are not rendered (e.g. collapsed) are not checked by "select all".
961
1373
  */
962
- this.selectable = input(true, ...(ngDevMode ? [{ debugName: "selectable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
1374
+ this.selectable = input(true, { ...(ngDevMode ? { debugName: "selectable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
963
1375
  /**
964
1376
  * Whether this option is the tree's "select all" row rather than a rendered data node.
965
1377
  *
@@ -967,41 +1379,78 @@ class KbqTreeOption extends KbqTreeNode {
967
1379
  * (`getValue`, `isDisabled`, `isExpandable`, descendants) is skipped — those accessors belong to the
968
1380
  * consumer and must never be handed a node their data source has never seen. Its checkbox state and
969
1381
  * selection are driven from the outside instead.
1382
+ *
970
1383
  * @docs-private
971
1384
  */
972
- this.selectAllRow = input(false, ...(ngDevMode ? [{ debugName: "selectAllRow", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
973
- this.onSelectionChange = output();
1385
+ this.selectAllRow = input(false, { ...(ngDevMode ? { debugName: "selectAllRow" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1386
+ /** @docs-private */
1387
+ this.showCheckboxInput = input(undefined, { ...(ngDevMode ? { debugName: "showCheckboxInput" } : /* istanbul ignore next */ {}), alias: 'showCheckbox',
1388
+ transform: booleanAttribute });
1389
+ /** Emits whenever the selected state of the option changes. */
1390
+ this.selectionChange = output();
1391
+ /** @deprecated Use `selectionChange` instead. Will be removed in 22.0.0. */
1392
+ this.onSelectionChange = output({ alias: 'onSelectionChange' });
1393
+ // Not an `output()`: `KbqTreeSelect` merges this stream with rxjs, which an `OutputEmitterRef`
1394
+ // cannot feed without wrapping every call site in `outputToObservable`.
974
1395
  this.userInteraction = new EventEmitter();
975
- this._selected = false;
1396
+ this.selectedState = signal(false, ...(ngDevMode ? [{ debugName: "selectedState" }] : /* istanbul ignore next */ []));
976
1397
  this._id = `kbq-tree-option-${uniqueIdCounter++}`;
977
- this.hasFocus = false;
1398
+ this.focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
1399
+ this.checkbox = signal('unchecked', ...(ngDevMode ? [{ debugName: "checkbox" }] : /* istanbul ignore next */ []));
978
1400
  this.updateCheckboxState = () => {
979
1401
  if (this.selectAllRow())
980
1402
  return;
981
- if (this.checkboxThirdState() && this.isExpandable) {
982
- if (this.descendantsAllSelected()) {
983
- this.checkboxState = 'checked';
984
- }
985
- else if (this.descendantsPartiallySelected()) {
986
- this.checkboxState = 'indeterminate';
987
- }
988
- else {
989
- this.checkboxState = this.selected ? 'checked' : 'unchecked';
990
- }
991
- }
992
- else {
993
- this.checkboxState = this.selected ? 'checked' : 'unchecked';
994
- }
1403
+ this.syncCheckboxState();
995
1404
  this.updateParentsCheckboxState(this.data);
996
1405
  };
997
1406
  this.tree = tree;
998
1407
  }
1408
+ ngDoCheck() {
1409
+ // Asked once per check, for a predicate reading plain state; a set to an equal value does nothing.
1410
+ const predicates = this.resolvePredicates();
1411
+ this.predicates.set(predicates);
1412
+ if (predicates.disabled !== this.checkedDisabled) {
1413
+ this.checkedDisabled = predicates.disabled;
1414
+ this.changeDetectorRef.markForCheck();
1415
+ }
1416
+ // Resolved here, untracked: a tree checks its rows under the one reactive consumer of its view, where a signal
1417
+ // read again costs a walk over every signal read before it. The host bindings read each signal of the row once
1418
+ // (`selected`, `checkboxState`, `predicates`, the mode through `tree.multiple`), which brings the row back here
1419
+ // on a change.
1420
+ if (this.selectAllRow()) {
1421
+ this.checkedAriaSelected = null;
1422
+ this.checkedCheckboxRow = false;
1423
+ this.checkedSelectAllState = this.toAriaChecked(this.tree.selectAllState);
1424
+ }
1425
+ else {
1426
+ const showCheckbox = this.showCheckbox;
1427
+ this.checkedAriaSelected = showCheckbox ? null : this.selected;
1428
+ this.checkedCheckboxRow = showCheckbox;
1429
+ this.checkedSelectAllState = null;
1430
+ }
1431
+ }
999
1432
  ngAfterContentInit() {
1000
1433
  if (this.selectAllRow())
1001
1434
  return;
1002
- Promise.resolve().then(this.updateCheckboxState);
1435
+ // Its own state only: rendering a row changes no ancestor's, and the tree recomputes every row once the data
1436
+ // nodes change.
1437
+ Promise.resolve().then(() => this.syncCheckboxState());
1003
1438
  this.value = this.tree.treeControl.getValue(this.data);
1004
1439
  }
1440
+ /**
1441
+ * The value and the checkbox state were derived from the node this view held before it was reused,
1442
+ * and `ngAfterContentInit` does not run again. A stale `value` drops the row out of the tree's
1443
+ * `renderedOptions`, so it renders but can no longer be focused, selected or copied.
1444
+ *
1445
+ * @docs-private
1446
+ */
1447
+ refresh() {
1448
+ super.refresh();
1449
+ if (this.selectAllRow())
1450
+ return;
1451
+ this.value = this.tree.treeControl.getValue(this.data);
1452
+ this.markForCheck();
1453
+ }
1005
1454
  descendantsAllSelected() {
1006
1455
  const descendants = this.tree.treeControl.getDescendants(this.data);
1007
1456
  return descendants.every((child) => this.tree?.selectionModel.isSelected(child));
@@ -1011,116 +1460,143 @@ class KbqTreeOption extends KbqTreeNode {
1011
1460
  return descendants.some((child) => this.tree?.selectionModel.isSelected(child));
1012
1461
  }
1013
1462
  updateParentsCheckboxState(node) {
1014
- this.tree.treeControl.getParents(node, []).forEach((parent) => {
1015
- const parentOption = this.tree.unorderedOptions.find((option) => option.data === parent);
1016
- parentOption?.updateCheckboxState();
1463
+ const parents = new Set(this.tree.treeControl.getParents(node, []));
1464
+ if (!parents.size)
1465
+ return;
1466
+ // Each ancestor reads its state off the selection rather than off its children, so recomputing it is enough.
1467
+ this.tree.unorderedOptions.forEach((option) => {
1468
+ if (parents.has(option.data))
1469
+ option.syncCheckboxState();
1017
1470
  });
1018
1471
  }
1019
1472
  toggle() {
1020
- this.selected = !this.selected;
1473
+ // Untracked, like the other imperative methods: called from a consumer's `effect()`, the state read on the
1474
+ // way — `selected`, focus, `disabled`, the inputs — would make the effect run again whenever it changes.
1475
+ untracked(() => (this.selected = !this.selected));
1021
1476
  }
1022
1477
  setSelected(selected) {
1023
- if (this.selectAllRow() || this._selected === selected || !this.tree.selectionModel) {
1024
- return;
1025
- }
1026
- this._selected = selected;
1027
- if (selected) {
1028
- this.tree.selectionModel.select(this.data);
1029
- }
1030
- else {
1031
- this.tree.selectionModel.deselect(this.data);
1032
- }
1033
- if (this.showCheckbox) {
1034
- this.updateCheckboxState();
1035
- }
1036
- this.markForCheck();
1478
+ untracked(() => {
1479
+ if (this.selectAllRow() || this.selectedState() === selected || !this.tree.selectionModel) {
1480
+ return;
1481
+ }
1482
+ this.selectedState.set(selected);
1483
+ if (selected) {
1484
+ this.tree.selectionModel.select(this.data);
1485
+ }
1486
+ else {
1487
+ this.tree.selectionModel.deselect(this.data);
1488
+ }
1489
+ if (this.showCheckbox) {
1490
+ this.updateCheckboxState();
1491
+ }
1492
+ });
1037
1493
  }
1038
1494
  focus(focusOrigin) {
1039
- if (focusOrigin === 'program' || this.disabled || this.actionButton()?.hasFocus)
1040
- return;
1041
- // With the pointer already on this node, revealing it would shift the tree out from under it.
1042
- kbqFocusAndReveal(this.elementRef.nativeElement, focusOrigin === 'mouse');
1043
- if (!this.hasFocus) {
1044
- this.onFocus.next({ option: this });
1045
- Promise.resolve().then(() => {
1046
- this.hasFocus = true;
1047
- this.markForCheck();
1048
- });
1049
- }
1495
+ untracked(() => {
1496
+ if (focusOrigin === 'program' || this.disabled || this.actionButton()?.hasFocus)
1497
+ return;
1498
+ // With the pointer already on this node, revealing it would shift the tree out from under it.
1499
+ kbqFocusAndReveal(this.elementRef.nativeElement, focusOrigin === 'mouse');
1500
+ if (!this.hasFocus) {
1501
+ this.focusEvents.next({ option: this });
1502
+ Promise.resolve().then(() => {
1503
+ this.hasFocus = true;
1504
+ this.markForCheck();
1505
+ });
1506
+ }
1507
+ });
1050
1508
  }
1051
1509
  blur() {
1052
1510
  if (this.preventBlur) {
1053
1511
  return;
1054
1512
  }
1055
- // When animations are enabled, Angular may end up removing the option from the DOM a little
1056
- // earlier than usual, causing it to be blurred and throwing off the logic in the tree
1057
- // that moves focus not the next item. To work around the issue, we defer marking the option
1058
- // as not focused until the next time the zone stabilizes.
1059
- this.ngZone.onStable
1060
- .asObservable()
1061
- .pipe(take(1))
1062
- .subscribe(() => {
1063
- this.ngZone.run(() => {
1064
- if (this.actionButton()?.hasFocus || this.tree.optionShouldHoldFocusOnBlur) {
1065
- return;
1066
- }
1067
- this.hasFocus = false;
1068
- this.onBlur.next({ option: this });
1069
- });
1070
- });
1513
+ // Deferred until the focus has settled: whatever takes it — this option's action button, or another option,
1514
+ // which marks itself focused on a microtask — records it only after this blur. Reported before that, the move
1515
+ // reads as the focus leaving the options: the option would drop its focused state while its own action button
1516
+ // holds the focus, and the tree its active option.
1517
+ afterNextRender(() => {
1518
+ // Focus can be back by the time this runs (a blur and a focus in the same task): then nothing was lost.
1519
+ if (_getFocusedElementPierceShadowDom() === this.elementRef.nativeElement)
1520
+ return;
1521
+ if (this.actionButton()?.hasFocus || this.tree.optionShouldHoldFocusOnBlur) {
1522
+ return;
1523
+ }
1524
+ this.hasFocus = false;
1525
+ this.blurEvents.next({ option: this });
1526
+ },
1527
+ // The environment injector, not the option's: an option removed while focused is blurred as its view is
1528
+ // destroyed, and the tree still has to hear about it to move focus.
1529
+ { injector: this.environmentInjector });
1071
1530
  }
1072
1531
  /** @docs-private */
1073
1532
  getHeight() {
1074
1533
  return kbqGetElementHeight(this.elementRef.nativeElement);
1075
1534
  }
1535
+ /**
1536
+ * Label the key manager's type-ahead matches against.
1537
+ *
1538
+ * The "select all" row is navigable but is not a data node, and its label is a localized phrase —
1539
+ * answering type-ahead with it would hijack every query starting with that letter.
1540
+ *
1541
+ * @docs-private
1542
+ */
1543
+ getLabel() {
1544
+ return this.selectAllRow() ? '' : this.viewValue;
1545
+ }
1076
1546
  select(setFocus = true) {
1077
- if (this.selectAllRow() || this._selected) {
1078
- return;
1079
- }
1080
- this._selected = true;
1081
- if (setFocus && !this.hasFocus) {
1082
- this.focus();
1083
- }
1084
- this.updateCheckboxState();
1085
- this.markForCheck();
1086
- this.emitSelectionChangeEvent();
1547
+ untracked(() => {
1548
+ if (this.selectAllRow() || this.selectedState()) {
1549
+ return;
1550
+ }
1551
+ this.selectedState.set(true);
1552
+ if (setFocus && !this.hasFocus) {
1553
+ this.focus();
1554
+ }
1555
+ this.updateCheckboxState();
1556
+ this.emitSelectionChangeEvent();
1557
+ });
1087
1558
  }
1088
1559
  deselect() {
1089
- if (this.selectAllRow() || !this._selected) {
1090
- return;
1091
- }
1092
- this._selected = false;
1093
- this.updateCheckboxState();
1094
- this.markForCheck();
1095
- this.emitSelectionChangeEvent();
1560
+ untracked(() => {
1561
+ if (this.selectAllRow() || !this.selectedState()) {
1562
+ return;
1563
+ }
1564
+ this.selectedState.set(false);
1565
+ this.updateCheckboxState();
1566
+ this.emitSelectionChangeEvent();
1567
+ });
1096
1568
  }
1097
1569
  onKeydown($event) {
1098
1570
  kbqFocusOptionActionOnTab($event, this.actionButton());
1099
1571
  }
1100
1572
  selectViaInteraction($event) {
1101
- if (this.disabled || !this.selectable()) {
1102
- return;
1103
- }
1104
- this.markForCheck();
1105
- this.userInteraction.emit();
1106
- const shiftKey = $event ? hasModifierKey($event, 'shiftKey') : false;
1107
- // ctrlKey is for Windows, metaKey is for MacOS
1108
- const ctrlKey = $event ? hasModifierKey($event, 'ctrlKey', 'metaKey') : false;
1109
- this.tree.setSelectedOptionsByClick(this, shiftKey, ctrlKey);
1573
+ untracked(() => {
1574
+ if (this.disabled || !this.selectable()) {
1575
+ return;
1576
+ }
1577
+ this.userInteraction.emit();
1578
+ const shiftKey = $event ? hasModifierKey($event, 'shiftKey') : false;
1579
+ // ctrlKey is for Windows, metaKey is for MacOS
1580
+ const ctrlKey = $event ? hasModifierKey($event, 'ctrlKey', 'metaKey') : false;
1581
+ this.tree.setSelectedOptionsByClick(this, shiftKey, ctrlKey);
1582
+ });
1110
1583
  }
1111
1584
  emitSelectionChangeEvent() {
1112
1585
  // The tree can still hold an option whose node was re-rendered away until it rebuilds its list.
1113
1586
  if (this.destroyRef.destroyed)
1114
1587
  return;
1115
- this.onSelectionChange.emit(new KbqTreeOptionChange(this));
1588
+ const event = new KbqTreeOptionChange(this);
1589
+ this.selectionChange.emit(event);
1590
+ this.onSelectionChange.emit(event);
1116
1591
  }
1117
1592
  getHostElement() {
1118
1593
  return this.elementRef.nativeElement;
1119
1594
  }
1120
1595
  markForCheck() {
1121
1596
  this.changeDetectorRef.markForCheck();
1597
+ // Its own state only: after a selection, data or mode change the tree calls this on every option.
1122
1598
  if (this.showCheckbox) {
1123
- this.updateCheckboxState();
1599
+ this.syncCheckboxState();
1124
1600
  }
1125
1601
  }
1126
1602
  /** @docs-private */
@@ -1129,14 +1605,44 @@ class KbqTreeOption extends KbqTreeNode {
1129
1605
  return;
1130
1606
  this.focus('mouse');
1131
1607
  }
1132
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeOption, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1133
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqTreeOption, isStandalone: true, selector: "kbq-tree-option", inputs: { checkboxThirdState: { classPropertyName: "checkboxThirdState", publicName: "checkboxThirdState", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selectAllRow: { classPropertyName: "selectAllRow", publicName: "selectAllRow", isSignal: true, isRequired: false, transformFunction: null }, showCheckbox: { classPropertyName: "showCheckbox", publicName: "showCheckbox", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onSelectionChange: "onSelectionChange" }, host: { listeners: { "focusin": "focus()", "mouseenter": "onMouseenter()", "blur": "blur()", "click": "selectViaInteraction($event)", "keydown": "onKeydown($event)" }, properties: { "class.kbq-tree-option_multiple": "tree.multiple", "class.kbq-selected": "selected", "class.kbq-focused": "hasFocus", "class.kbq-disabled": "disabled", "class.kbq-action-button-focused": "actionButton()?.active", "attr.id": "id", "attr.tabindex": "-1", "attr.disabled": "disabled || null" }, classAttribute: "kbq-tree-option" }, providers: [
1608
+ /** Recomputes the option's own checkbox state, leaving its ancestors as they are. */
1609
+ syncCheckboxState() {
1610
+ if (this.selectAllRow())
1611
+ return;
1612
+ if (this.checkboxThirdState() && this.isExpandable) {
1613
+ // One descendant walk, not two: `getDescendants` is a linear scan of the whole data set, and
1614
+ // the roll-up runs this method for every ancestor.
1615
+ const descendants = this.tree.treeControl.getDescendants(this.data);
1616
+ const selectedCount = descendants.filter((child) => this.tree.selectionModel.isSelected(child)).length;
1617
+ if (selectedCount === descendants.length) {
1618
+ this.checkboxState = 'checked';
1619
+ }
1620
+ else if (selectedCount > 0) {
1621
+ this.checkboxState = 'indeterminate';
1622
+ }
1623
+ else {
1624
+ this.checkboxState = this.selected ? 'checked' : 'unchecked';
1625
+ }
1626
+ }
1627
+ else {
1628
+ this.checkboxState = this.selected ? 'checked' : 'unchecked';
1629
+ }
1630
+ }
1631
+ toAriaChecked(state) {
1632
+ return state === 'indeterminate' ? 'mixed' : `${state === 'checked'}`;
1633
+ }
1634
+ resolvePredicates() {
1635
+ const branch = !this.selectAllRow() && this.tree.treeControl.isExpandable(this.data);
1636
+ return { disabled: this.disabled, expanded: branch ? this.isExpanded : null };
1637
+ }
1638
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeOption, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1639
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: KbqTreeOption, isStandalone: true, selector: "kbq-tree-option", inputs: { checkboxThirdState: { classPropertyName: "checkboxThirdState", publicName: "checkboxThirdState", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selectAllRow: { classPropertyName: "selectAllRow", publicName: "selectAllRow", isSignal: true, isRequired: false, transformFunction: null }, showCheckboxInput: { classPropertyName: "showCheckboxInput", publicName: "showCheckbox", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", onSelectionChange: "onSelectionChange" }, host: { attributes: { "role": "treeitem" }, listeners: { "focusin": "focus()", "mouseenter": "onMouseenter()", "blur": "blur()", "click": "selectViaInteraction($event)", "keydown": "onKeydown($event)" }, properties: { "class.kbq-tree-option_multiple": "tree.multiple", "class.kbq-selected": "selected", "class.kbq-focused": "hasFocus", "class.kbq-disabled": "checkedDisabled", "class.kbq-action-button-focused": "actionButton()?.active", "attr.id": "id", "attr.tabindex": "-1", "attr.aria-disabled": "checkedDisabled || null", "attr.aria-expanded": "ariaExpanded", "attr.aria-checked": "ariaChecked", "attr.aria-selected": "ariaSelected" }, classAttribute: "kbq-tree-option" }, providers: [
1134
1640
  { provide: KbqTreeNode, useExisting: KbqTreeOption },
1135
1641
  { provide: KBQ_TITLE_TEXT_REF, useExisting: KbqTreeOption },
1136
1642
  { provide: KBQ_OPTION_ACTION_PARENT, useExisting: KbqTreeOption }
1137
- ], queries: [{ propertyName: "toggleElementDirective", first: true, predicate: KbqTreeNodeToggleDirective, descendants: true, isSignal: true }, { propertyName: "toggleElementComponent", first: true, predicate: KbqTreeNodeToggleComponent, descendants: true, isSignal: true }, { propertyName: "pseudoCheckbox", first: true, predicate: KbqPseudoCheckbox, descendants: true, isSignal: true }, { propertyName: "actionButton", first: true, predicate: KbqOptionActionComponent, descendants: true, isSignal: true }, { propertyName: "tooltipTrigger", first: true, predicate: KbqTooltipTrigger, descendants: true }, { propertyName: "dropdownTrigger", first: true, predicate: KbqDropdownTrigger, descendants: true }], viewQueries: [{ propertyName: "parentTextElement", first: true, predicate: ["kbqTitleContainer"], descendants: true }], exportAs: ["kbqTreeOption"], usesInheritance: true, ngImport: i0, template: "<ng-content select=\"kbq-tree-node-toggle, [kbq-tree-node-toggle], [kbqTreeNodeToggle]\" />\n\n@if (externalPseudoCheckbox) {\n <ng-content select=\"kbq-pseudo-checkbox\" />\n} @else if (showCheckbox) {\n <kbq-pseudo-checkbox [disabled]=\"disabled\" [state]=\"checkboxState\" />\n}\n\n<ng-content select=\"kbq-checkbox\" />\n\n<ng-content select=\"[kbq-icon]\" />\n\n<ng-content select=\"kbq-progress-spinner\" />\n\n<span #kbqTitleContainer class=\"kbq-option-text\">\n <ng-content />\n</span>\n\n@if (actionButton()) {\n <kbq-action-container>\n <ng-content select=\"kbq-option-action\" />\n </kbq-action-container>\n}\n", styles: ["@keyframes kbq-progress{0%{background-position:0 0}to{background-position:64px 0}}.kbq-progress{position:relative}.kbq-progress:after{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite}@media(prefers-reduced-motion:reduce){.kbq-progress:after{animation:none}}.kbq-group{display:flex;flex-direction:row}.kbq-group_justified>.kbq-group-item{width:100%}.kbq-group .kbq-group-item+.kbq-group-item{margin-left:calc(-1 * var(--kbq-size-border-width))}.kbq-group>.kbq-group-item:first-child:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-bottom-right-radius:0;border-top-right-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-bottom-left-radius:0;border-top-left-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-vertical-group{display:flex;flex-direction:column}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child){border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-right-radius:var(--kbq-size-border-radius)}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-left-radius:var(--kbq-size-border-radius)}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-vertical-group .kbq-group-item+.kbq-group-item{margin-top:calc(-1 * var(--kbq-size-border-width))}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-bottom-right-radius:0;border-bottom-left-radius:0}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-top-right-radius:0;border-top-left-radius:0}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-no-select,.kbq-tree-option{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.kbq-tree-option:not(.kbq-disabled):hover .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-action-container{display:flex}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option:not(.kbq-disabled).kbq-focused .kbq-action-container{display:flex}.kbq-tree-option{position:relative;box-sizing:border-box;display:flex;align-items:center;min-height:32px;overflow-wrap:break-word;border-width:var(--kbq-tree-size-container-focus-outline-width);border-style:solid;border-color:transparent;border-radius:var(--kbq-tree-option-border-radius);padding-top:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));padding-right:calc(var(--kbq-tree-size-container-padding-right) - var(--kbq-tree-size-container-focus-outline-width));padding-bottom:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));gap:var(--kbq-tree-size-container-content-gap-horizontal)}.kbq-tree-option .kbq-option-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-tree-option .kbq-option-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-tree-option .kbq-option-text:empty{display:none}.kbq-tree-option .kbq-option-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-top:var(--kbq-list-size-text-padding-vertical, 0);padding-bottom:var(--kbq-list-size-text-padding-vertical, 0)}.kbq-tree-option:has(.kbq-option-caption)>[kbq-tree-node-toggle],.kbq-tree-option:has(.kbq-option-caption)>[kbqTreeNodeToggle],.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle,.kbq-tree-option:has(.kbq-option-caption)>.kbq-pseudo-checkbox,.kbq-tree-option:has(.kbq-option-caption)>kbq-checkbox,.kbq-tree-option:has(.kbq-option-caption)>[kbq-icon],.kbq-tree-option:has(.kbq-option-caption)>kbq-progress-spinner{align-self:flex-start;margin-top:var(--kbq-size-3xs)}.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle{height:var(--kbq-typography-text-normal-line-height);margin-top:0}.kbq-tree-option:focus{outline:none}.kbq-tree-option:not(.kbq-disabled){cursor:pointer}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused):has(+:is(.kbq-checked,.kbq-selected,.kbq-focused)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused)+:is(.kbq-checked,.kbq-selected,.kbq-focused){border-top-left-radius:0;border-top-right-radius:0}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "component", type: KbqPseudoCheckbox, selector: "kbq-pseudo-checkbox", inputs: ["big", "state", "disabled"] }, { kind: "component", type: KbqActionContainer, selector: "kbq-action-container", exportAs: ["kbqActionContainer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1643
+ ], queries: [{ propertyName: "toggleElementDirective", first: true, predicate: KbqTreeNodeToggleDirective, descendants: true, isSignal: true }, { propertyName: "toggleElementComponent", first: true, predicate: KbqTreeNodeToggleComponent, descendants: true, isSignal: true }, { propertyName: "pseudoCheckbox", first: true, predicate: KbqPseudoCheckbox, descendants: true, isSignal: true }, { propertyName: "actionButton", first: true, predicate: KbqOptionActionComponent, descendants: true, isSignal: true }, { propertyName: "tooltipTriggerQuery", first: true, predicate: KbqTooltipTrigger, descendants: true, isSignal: true }, { propertyName: "dropdownTriggerQuery", first: true, predicate: KbqDropdownTrigger, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "titleContainer", first: true, predicate: ["kbqTitleContainer"], descendants: true, isSignal: true }], exportAs: ["kbqTreeOption"], usesInheritance: true, ngImport: i0, template: "<ng-content select=\"kbq-tree-node-toggle, [kbq-tree-node-toggle], [kbqTreeNodeToggle]\" />\n\n@if (externalPseudoCheckbox) {\n <ng-content select=\"kbq-pseudo-checkbox\" />\n} @else if (showCheckbox) {\n <kbq-pseudo-checkbox [disabled]=\"disabled\" [state]=\"checkboxState\" />\n}\n\n<ng-content select=\"kbq-checkbox\" />\n\n<ng-content select=\"[kbq-icon]\" />\n\n<ng-content select=\"kbq-progress-spinner\" />\n\n<span #kbqTitleContainer class=\"kbq-option-text\">\n <ng-content />\n</span>\n\n@if (actionButton()) {\n <kbq-action-container>\n <ng-content select=\"kbq-option-action\" />\n </kbq-action-container>\n}\n", styles: ["@charset \"UTF-8\";.kbq-group{display:flex;flex-direction:row}.kbq-group_justified>.kbq-group-item{width:100%}.kbq-group .kbq-group-item+.kbq-group-item{margin-inline-start:calc(-1 * var(--kbq-size-border-width))}.kbq-group>.kbq-group-item:first-child:not(:last-child){border-start-end-radius:0;border-end-end-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child){border-start-start-radius:0;border-end-start-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-start-end-radius:0;border-end-end-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-start-start-radius:0;border-end-start-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-vertical-group{display:flex;flex-direction:column}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child){border-end-start-radius:0;border-end-end-radius:0;border-start-end-radius:var(--kbq-size-border-radius)}@supports (corner-shape: squircle){.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child){corner-shape:squircle;border-start-end-radius:clamp(var(--kbq-size-border-radius) * 1.85,var(--kbq-size-border-radius) * 2.3 - 3.6px,var(--kbq-size-border-radius) * 2)}}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child){border-start-start-radius:0;border-start-end-radius:0;border-end-start-radius:var(--kbq-size-border-radius)}@supports (corner-shape: squircle){.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child){corner-shape:squircle;border-end-start-radius:clamp(var(--kbq-size-border-radius) * 1.85,var(--kbq-size-border-radius) * 2.3 - 3.6px,var(--kbq-size-border-radius) * 2)}}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-vertical-group .kbq-group-item+.kbq-group-item{margin-top:calc(-1 * var(--kbq-size-border-width))}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-end-start-radius:0;border-end-end-radius:0}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-start-start-radius:0;border-start-end-radius:0}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-tree-option{-webkit-user-select:none;user-select:none}.kbq-tree-option:not(.kbq-disabled):hover .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-action-container{display:flex}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option:not(.kbq-disabled).kbq-focused .kbq-action-container{display:flex}.kbq-tree-option{position:relative;box-sizing:border-box;display:flex;align-items:center;min-height:32px;overflow-wrap:break-word;border-width:var(--kbq-tree-size-container-focus-outline-width);border-style:solid;border-color:transparent;border-radius:var(--kbq-tree-option-border-radius)}@supports (corner-shape: squircle){.kbq-tree-option{corner-shape:squircle;border-radius:clamp(var(--kbq-tree-option-border-radius) * 1.85,var(--kbq-tree-option-border-radius) * 2.3 - 3.6px,var(--kbq-tree-option-border-radius) * 2)}}.kbq-tree-option{padding-top:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));padding-right:calc(var(--kbq-tree-size-container-padding-right) - var(--kbq-tree-size-container-focus-outline-width));padding-bottom:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));gap:var(--kbq-tree-size-container-content-gap-horizontal)}.kbq-tree-option .kbq-option-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-tree-option .kbq-option-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-tree-option .kbq-option-text:empty{display:none}.kbq-tree-option .kbq-option-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-tree-option:has(.kbq-option-caption)>[kbq-tree-node-toggle],.kbq-tree-option:has(.kbq-option-caption)>[kbqTreeNodeToggle],.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle,.kbq-tree-option:has(.kbq-option-caption)>.kbq-pseudo-checkbox,.kbq-tree-option:has(.kbq-option-caption)>kbq-checkbox,.kbq-tree-option:has(.kbq-option-caption)>[kbq-icon],.kbq-tree-option:has(.kbq-option-caption)>kbq-progress-spinner{align-self:flex-start;margin-top:var(--kbq-size-3xs)}.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle{height:var(--kbq-typography-text-normal-line-height);margin-top:0}.kbq-tree-option:focus{outline:none}.kbq-tree-option:not(.kbq-disabled){cursor:pointer}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused):has(+:is(.kbq-checked,.kbq-selected,.kbq-focused)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused)+:is(.kbq-checked,.kbq-selected,.kbq-focused){border-top-left-radius:0;border-top-right-radius:0}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "component", type: KbqPseudoCheckbox, selector: "kbq-pseudo-checkbox", inputs: ["big", "state", "disabled"] }, { kind: "component", type: KbqActionContainer, selector: "kbq-action-container", exportAs: ["kbqActionContainer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1138
1644
  }
1139
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeOption, decorators: [{
1645
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeOption, decorators: [{
1140
1646
  type: Component,
1141
1647
  args: [{ selector: 'kbq-tree-option', imports: [
1142
1648
  KbqPseudoCheckbox,
@@ -1147,34 +1653,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
1147
1653
  { provide: KBQ_OPTION_ACTION_PARENT, useExisting: KbqTreeOption }
1148
1654
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
1149
1655
  class: 'kbq-tree-option',
1656
+ // The "select all" row is a treeitem too: `role="checkbox"` would be an invalid child of
1657
+ // `role="tree"`, and `aria-checked` already carries its state.
1658
+ role: 'treeitem',
1150
1659
  '[class.kbq-tree-option_multiple]': 'tree.multiple',
1151
1660
  '[class.kbq-selected]': 'selected',
1152
1661
  '[class.kbq-focused]': 'hasFocus',
1153
- '[class.kbq-disabled]': 'disabled',
1662
+ '[class.kbq-disabled]': 'checkedDisabled',
1154
1663
  '[class.kbq-action-button-focused]': 'actionButton()?.active',
1155
1664
  '[attr.id]': 'id',
1156
1665
  '[attr.tabindex]': '-1',
1157
- '[attr.disabled]': 'disabled || null',
1666
+ '[attr.aria-disabled]': 'checkedDisabled || null',
1667
+ '[attr.aria-expanded]': 'ariaExpanded',
1668
+ // `aria-level` comes from `KbqTreeNode`: a second binding here would read `level` twice.
1669
+ '[attr.aria-checked]': 'ariaChecked',
1670
+ '[attr.aria-selected]': 'ariaSelected',
1158
1671
  '(focusin)': 'focus()',
1159
1672
  '(mouseenter)': 'onMouseenter()',
1160
1673
  '(blur)': 'blur()',
1161
1674
  '(click)': 'selectViaInteraction($event)',
1162
1675
  '(keydown)': 'onKeydown($event)'
1163
- }, exportAs: 'kbqTreeOption', template: "<ng-content select=\"kbq-tree-node-toggle, [kbq-tree-node-toggle], [kbqTreeNodeToggle]\" />\n\n@if (externalPseudoCheckbox) {\n <ng-content select=\"kbq-pseudo-checkbox\" />\n} @else if (showCheckbox) {\n <kbq-pseudo-checkbox [disabled]=\"disabled\" [state]=\"checkboxState\" />\n}\n\n<ng-content select=\"kbq-checkbox\" />\n\n<ng-content select=\"[kbq-icon]\" />\n\n<ng-content select=\"kbq-progress-spinner\" />\n\n<span #kbqTitleContainer class=\"kbq-option-text\">\n <ng-content />\n</span>\n\n@if (actionButton()) {\n <kbq-action-container>\n <ng-content select=\"kbq-option-action\" />\n </kbq-action-container>\n}\n", styles: ["@keyframes kbq-progress{0%{background-position:0 0}to{background-position:64px 0}}.kbq-progress{position:relative}.kbq-progress:after{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite}@media(prefers-reduced-motion:reduce){.kbq-progress:after{animation:none}}.kbq-group{display:flex;flex-direction:row}.kbq-group_justified>.kbq-group-item{width:100%}.kbq-group .kbq-group-item+.kbq-group-item{margin-left:calc(-1 * var(--kbq-size-border-width))}.kbq-group>.kbq-group-item:first-child:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-bottom-right-radius:0;border-top-right-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-bottom-left-radius:0;border-top-left-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-vertical-group{display:flex;flex-direction:column}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child){border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-right-radius:var(--kbq-size-border-radius)}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-left-radius:var(--kbq-size-border-radius)}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-vertical-group .kbq-group-item+.kbq-group-item{margin-top:calc(-1 * var(--kbq-size-border-width))}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-bottom-right-radius:0;border-bottom-left-radius:0}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-top-right-radius:0;border-top-left-radius:0}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-no-select,.kbq-tree-option{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.kbq-tree-option:not(.kbq-disabled):hover .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-action-container{display:flex}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option:not(.kbq-disabled).kbq-focused .kbq-action-container{display:flex}.kbq-tree-option{position:relative;box-sizing:border-box;display:flex;align-items:center;min-height:32px;overflow-wrap:break-word;border-width:var(--kbq-tree-size-container-focus-outline-width);border-style:solid;border-color:transparent;border-radius:var(--kbq-tree-option-border-radius);padding-top:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));padding-right:calc(var(--kbq-tree-size-container-padding-right) - var(--kbq-tree-size-container-focus-outline-width));padding-bottom:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));gap:var(--kbq-tree-size-container-content-gap-horizontal)}.kbq-tree-option .kbq-option-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-tree-option .kbq-option-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-tree-option .kbq-option-text:empty{display:none}.kbq-tree-option .kbq-option-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-top:var(--kbq-list-size-text-padding-vertical, 0);padding-bottom:var(--kbq-list-size-text-padding-vertical, 0)}.kbq-tree-option:has(.kbq-option-caption)>[kbq-tree-node-toggle],.kbq-tree-option:has(.kbq-option-caption)>[kbqTreeNodeToggle],.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle,.kbq-tree-option:has(.kbq-option-caption)>.kbq-pseudo-checkbox,.kbq-tree-option:has(.kbq-option-caption)>kbq-checkbox,.kbq-tree-option:has(.kbq-option-caption)>[kbq-icon],.kbq-tree-option:has(.kbq-option-caption)>kbq-progress-spinner{align-self:flex-start;margin-top:var(--kbq-size-3xs)}.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle{height:var(--kbq-typography-text-normal-line-height);margin-top:0}.kbq-tree-option:focus{outline:none}.kbq-tree-option:not(.kbq-disabled){cursor:pointer}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused):has(+:is(.kbq-checked,.kbq-selected,.kbq-focused)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused)+:is(.kbq-checked,.kbq-selected,.kbq-focused){border-top-left-radius:0;border-top-right-radius:0}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
1164
- }], ctorParameters: () => [], propDecorators: { parentTextElement: [{
1165
- type: ViewChild,
1166
- args: ['kbqTitleContainer']
1167
- }], toggleElementDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqTreeNodeToggleDirective), { isSignal: true }] }], toggleElementComponent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqTreeNodeToggleComponent), { isSignal: true }] }], pseudoCheckbox: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqPseudoCheckbox), { isSignal: true }] }], actionButton: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqOptionActionComponent), { isSignal: true }] }], tooltipTrigger: [{
1168
- type: ContentChild,
1169
- args: [KbqTooltipTrigger]
1170
- }], dropdownTrigger: [{
1171
- type: ContentChild,
1172
- args: [KbqDropdownTrigger]
1173
- }], checkboxThirdState: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkboxThirdState", required: false }] }], disabled: [{
1174
- type: Input
1175
- }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selectAllRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllRow", required: false }] }], showCheckbox: [{
1176
- type: Input
1177
- }], onSelectionChange: [{ type: i0.Output, args: ["onSelectionChange"] }] } });
1676
+ }, exportAs: 'kbqTreeOption', template: "<ng-content select=\"kbq-tree-node-toggle, [kbq-tree-node-toggle], [kbqTreeNodeToggle]\" />\n\n@if (externalPseudoCheckbox) {\n <ng-content select=\"kbq-pseudo-checkbox\" />\n} @else if (showCheckbox) {\n <kbq-pseudo-checkbox [disabled]=\"disabled\" [state]=\"checkboxState\" />\n}\n\n<ng-content select=\"kbq-checkbox\" />\n\n<ng-content select=\"[kbq-icon]\" />\n\n<ng-content select=\"kbq-progress-spinner\" />\n\n<span #kbqTitleContainer class=\"kbq-option-text\">\n <ng-content />\n</span>\n\n@if (actionButton()) {\n <kbq-action-container>\n <ng-content select=\"kbq-option-action\" />\n </kbq-action-container>\n}\n", styles: ["@charset \"UTF-8\";.kbq-group{display:flex;flex-direction:row}.kbq-group_justified>.kbq-group-item{width:100%}.kbq-group .kbq-group-item+.kbq-group-item{margin-inline-start:calc(-1 * var(--kbq-size-border-width))}.kbq-group>.kbq-group-item:first-child:not(:last-child){border-start-end-radius:0;border-end-end-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child){border-start-start-radius:0;border-end-start-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-start-end-radius:0;border-end-end-radius:0}.kbq-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-start-start-radius:0;border-end-start-radius:0}.kbq-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-vertical-group{display:flex;flex-direction:column}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child){border-end-start-radius:0;border-end-end-radius:0;border-start-end-radius:var(--kbq-size-border-radius)}@supports (corner-shape: squircle){.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child){corner-shape:squircle;border-start-end-radius:clamp(var(--kbq-size-border-radius) * 1.85,var(--kbq-size-border-radius) * 2.3 - 3.6px,var(--kbq-size-border-radius) * 2)}}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child){border-start-start-radius:0;border-start-end-radius:0;border-end-start-radius:var(--kbq-size-border-radius)}@supports (corner-shape: squircle){.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child){corner-shape:squircle;border-end-start-radius:clamp(var(--kbq-size-border-radius) * 1.85,var(--kbq-size-border-radius) * 2.3 - 3.6px,var(--kbq-size-border-radius) * 2)}}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child){border-radius:0}.kbq-vertical-group .kbq-group-item+.kbq-group-item{margin-top:calc(-1 * var(--kbq-size-border-width))}.kbq-vertical-group>.kbq-group-item:first-child:not(:last-child) .kbq-form-field__container{border-end-start-radius:0;border-end-end-radius:0}.kbq-vertical-group>.kbq-group-item:last-child:not(:first-child) .kbq-form-field__container{border-start-start-radius:0;border-start-end-radius:0}.kbq-vertical-group>.kbq-group-item:not(:first-child):not(:last-child) .kbq-form-field__container{border-radius:0}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-tree-option{-webkit-user-select:none;user-select:none}.kbq-tree-option:not(.kbq-disabled):hover .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-action-container,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-action-container{display:flex}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option:not(.kbq-disabled).kbq-focused .kbq-action-container{display:flex}.kbq-tree-option{position:relative;box-sizing:border-box;display:flex;align-items:center;min-height:32px;overflow-wrap:break-word;border-width:var(--kbq-tree-size-container-focus-outline-width);border-style:solid;border-color:transparent;border-radius:var(--kbq-tree-option-border-radius)}@supports (corner-shape: squircle){.kbq-tree-option{corner-shape:squircle;border-radius:clamp(var(--kbq-tree-option-border-radius) * 1.85,var(--kbq-tree-option-border-radius) * 2.3 - 3.6px,var(--kbq-tree-option-border-radius) * 2)}}.kbq-tree-option{padding-top:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));padding-right:calc(var(--kbq-tree-size-container-padding-right) - var(--kbq-tree-size-container-focus-outline-width));padding-bottom:calc(var(--kbq-tree-size-container-padding-vertical) - var(--kbq-tree-size-container-focus-outline-width));gap:var(--kbq-tree-size-container-content-gap-horizontal)}.kbq-tree-option .kbq-option-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-tree-option .kbq-option-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-tree-option .kbq-option-text:empty{display:none}.kbq-tree-option .kbq-option-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-tree-option:has(.kbq-option-caption)>[kbq-tree-node-toggle],.kbq-tree-option:has(.kbq-option-caption)>[kbqTreeNodeToggle],.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle,.kbq-tree-option:has(.kbq-option-caption)>.kbq-pseudo-checkbox,.kbq-tree-option:has(.kbq-option-caption)>kbq-checkbox,.kbq-tree-option:has(.kbq-option-caption)>[kbq-icon],.kbq-tree-option:has(.kbq-option-caption)>kbq-progress-spinner{align-self:flex-start;margin-top:var(--kbq-size-3xs)}.kbq-tree-option:has(.kbq-option-caption)>.kbq-tree-node-toggle{height:var(--kbq-typography-text-normal-line-height);margin-top:0}.kbq-tree-option:focus{outline:none}.kbq-tree-option:not(.kbq-disabled){cursor:pointer}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused):has(+:is(.kbq-checked,.kbq-selected,.kbq-focused)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-tree-option:is(.kbq-checked,.kbq-selected,.kbq-focused)+:is(.kbq-checked,.kbq-selected,.kbq-focused){border-top-left-radius:0;border-top-right-radius:0}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
1677
+ }], ctorParameters: () => [], propDecorators: { titleContainer: [{ type: i0.ViewChild, args: ['kbqTitleContainer', { isSignal: true }] }], toggleElementDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqTreeNodeToggleDirective), { isSignal: true }] }], toggleElementComponent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqTreeNodeToggleComponent), { isSignal: true }] }], pseudoCheckbox: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqPseudoCheckbox), { isSignal: true }] }], actionButton: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqOptionActionComponent), { isSignal: true }] }], tooltipTriggerQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqTooltipTrigger), { isSignal: true }] }], dropdownTriggerQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqDropdownTrigger), { isSignal: true }] }], checkboxThirdState: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkboxThirdState", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selectAllRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllRow", required: false }] }], showCheckboxInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCheckbox", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], onSelectionChange: [{ type: i0.Output, args: ["onSelectionChange"] }] } });
1178
1678
 
1179
1679
  /** Regex used to split a string on its CSS units. */
1180
1680
  const cssUnitPattern = /([A-Za-z%]+)$/;
@@ -1185,49 +1685,65 @@ class KbqTreeNodePadding {
1185
1685
  set level(value) {
1186
1686
  this.setLevelInput(value);
1187
1687
  }
1188
- // TODO: Skipped for migration because:
1189
- // Accessor inputs cannot be migrated as they are too complex.
1190
- get indent() {
1191
- return this._indent;
1192
- }
1193
- set indent(indent) {
1194
- this.setIndentInput(indent);
1195
- }
1196
1688
  get leftPadding() {
1197
- return (this.withIcon ? 0 : this.iconWidth) + this._indent;
1689
+ return (this.withIcon ? 0 : this.iconWidth) + this.parsedIndent().value;
1198
1690
  }
1199
1691
  get leftPaddingForFirstLevel() {
1200
1692
  const border = 2;
1201
- return (this.withIcon ? 0 : this.iconWidth) + this._indent - border;
1693
+ return (this.withIcon ? 0 : this.iconWidth) + this.parsedIndent().value - border;
1694
+ }
1695
+ /** CSS units used for the indentation value. */
1696
+ get indentUnits() {
1697
+ return this.parsedIndent().units;
1202
1698
  }
1203
1699
  constructor() {
1204
1700
  this.treeNode = inject(KbqTreeNode);
1205
1701
  this.tree = inject(KbqTreeBase);
1206
1702
  this.renderer = inject(Renderer2);
1207
1703
  this.element = inject(ElementRef);
1208
- this.option = inject(KbqTreeOption);
1704
+ // Optional so the directive also works on a bare `kbq-tree-node`, which has no option around it.
1705
+ this.option = inject(KbqTreeOption, { optional: true });
1209
1706
  this.dir = inject(Directionality, { optional: true });
1210
- this._indent = 12;
1211
- /** CSS units used for the indentation value. */
1212
- this.indentUnits = 'px';
1707
+ /** Indentation added per nesting level. Accepts a bare number (px) or a value with CSS units. */
1708
+ this.indent = input(12, { ...(ngDevMode ? { debugName: "indent" } : /* istanbul ignore next */ {}), alias: 'kbqTreeNodePaddingIndent' });
1709
+ this.parsedIndent = computed(() => {
1710
+ const indent = this.indent();
1711
+ if (typeof indent !== 'string') {
1712
+ return { value: coerceNumberProperty(indent), units: 'px' };
1713
+ }
1714
+ const [value, units] = indent.split(cssUnitPattern);
1715
+ return { value: coerceNumberProperty(value), units: units || 'px' };
1716
+ }, ...(ngDevMode ? [{ debugName: "parsedIndent" }] : /* istanbul ignore next */ []));
1717
+ /**
1718
+ * Horizontal room a toggle takes up in a row: its own 16px box plus the option's 8px `gap`. A node
1719
+ * without a toggle reserves the same amount so its content lines up with a sibling that has one —
1720
+ * which is why widening the toggle itself pushes every branch row out of line.
1721
+ */
1213
1722
  this.iconWidth = 24;
1214
1723
  this.dir?.change?.pipe(takeUntilDestroyed()).subscribe(() => this.setPadding());
1724
+ // The node the padding was computed from is gone once its view is reused, and the replacement
1725
+ // can sit at a different level.
1726
+ this.treeNode.refreshed.pipe(takeUntilDestroyed()).subscribe(() => this.setPadding());
1727
+ effect(() => {
1728
+ this.parsedIndent();
1729
+ this.setPadding();
1730
+ });
1215
1731
  }
1216
1732
  ngAfterViewInit() {
1217
- this.withIcon = this.option.isToggleInDefaultPlace;
1733
+ this.withIcon = this.option?.isToggleInDefaultPlace ?? false;
1218
1734
  this.setPadding();
1219
1735
  }
1220
1736
  paddingIndent() {
1221
1737
  const treeControl = this.tree.treeControl;
1222
1738
  const nodeLevel = this.treeNode.data && treeControl.getLevel ? treeControl.getLevel(this.treeNode.data) : 0;
1223
1739
  const level = this.level || nodeLevel;
1224
- return level > 0 ? `${level * this._indent + this.leftPadding}px` : `${this.leftPaddingForFirstLevel}px`;
1740
+ const { value, units } = this.parsedIndent();
1741
+ return level > 0 ? `${level * value + this.leftPadding}${units}` : `${this.leftPaddingForFirstLevel}${units}`;
1225
1742
  }
1226
1743
  /**
1227
1744
  * This has been extracted to a util because of TS 4 and VE.
1228
1745
  * View Engine doesn't support property rename inheritance.
1229
1746
  * TS 4.0 doesn't allow properties to override accessors or vice-versa.
1230
- * @docs-private
1231
1747
  */
1232
1748
  setLevelInput(value) {
1233
1749
  // Set to null as the fallback value so that _setPadding can fall back to the node level if the
@@ -1236,58 +1752,40 @@ class KbqTreeNodePadding {
1236
1752
  this._level = coerceNumberProperty(value, null);
1237
1753
  this.setPadding();
1238
1754
  }
1239
- /**
1240
- * This has been extracted to a util because of TS 4 and VE.
1241
- * View Engine doesn't support property rename inheritance.
1242
- * TS 4.0 doesn't allow properties to override accessors or vice-versa.
1243
- * @docs-private
1244
- */
1245
- setIndentInput(indent) {
1246
- let value = indent;
1247
- let units = 'px';
1248
- if (typeof indent === 'string') {
1249
- const parts = indent.split(cssUnitPattern);
1250
- value = parts[0];
1251
- units = parts[1] || units;
1252
- }
1253
- this.indentUnits = units;
1254
- this._indent = coerceNumberProperty(value);
1255
- this.setPadding();
1256
- }
1257
1755
  setPadding() {
1258
1756
  const padding = this.paddingIndent();
1259
1757
  const paddingProp = this.dir?.value === 'rtl' ? 'paddingRight' : 'paddingLeft';
1260
1758
  this.renderer.setStyle(this.element.nativeElement, paddingProp, padding);
1261
1759
  }
1262
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodePadding, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1263
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqTreeNodePadding, isStandalone: true, selector: "[kbqTreeNodePadding]", inputs: { indent: ["kbqTreeNodePaddingIndent", "indent"] }, exportAs: ["kbqTreeNodePadding"], ngImport: i0 }); }
1760
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodePadding, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1761
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.25", type: KbqTreeNodePadding, isStandalone: true, selector: "[kbqTreeNodePadding]", inputs: { indent: { classPropertyName: "indent", publicName: "kbqTreeNodePaddingIndent", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["kbqTreeNodePadding"], ngImport: i0 }); }
1264
1762
  }
1265
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeNodePadding, decorators: [{
1763
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeNodePadding, decorators: [{
1266
1764
  type: Directive,
1267
1765
  args: [{
1268
1766
  selector: '[kbqTreeNodePadding]',
1269
1767
  exportAs: 'kbqTreeNodePadding'
1270
1768
  }]
1271
- }], ctorParameters: () => [], propDecorators: { indent: [{
1272
- type: Input,
1273
- args: ['kbqTreeNodePaddingIndent']
1274
- }] } });
1769
+ }], ctorParameters: () => [], propDecorators: { indent: [{ type: i0.Input, args: [{ isSignal: true, alias: "kbqTreeNodePaddingIndent", required: false }] }] } });
1275
1770
 
1276
1771
  class KbqTree extends KbqTreeBase {
1277
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTree, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1278
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.30", type: KbqTree, isStandalone: true, selector: "kbq-tree", host: { classAttribute: "kbq-tree" }, exportAs: ["kbqTree"], usesInheritance: true, ngImport: i0, template: `
1772
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTree, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1773
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: KbqTree, isStandalone: true, selector: "kbq-tree", host: { attributes: { "role": "tree" }, classAttribute: "kbq-tree" }, providers: [{ provide: KbqTreeBase, useExisting: KbqTree }], exportAs: ["kbqTree"], usesInheritance: true, hostDirectives: [{ directive: i1.KbqStateSaving, inputs: ["useStateSaving", "useStateSaving", "stateSavingKey", "stateSavingKey"] }], ngImport: i0, template: `
1279
1774
  <ng-container kbqTreeNodeOutlet />
1280
- `, isInline: true, styles: [".kbq-tree{display:block}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "directive", type: KbqTreeNodeOutlet, selector: "[kbqTreeNodeOutlet]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1775
+ `, isInline: true, styles: [".kbq-tree{display:block}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "directive", type: KbqTreeNodeOutlet, selector: "[kbqTreeNodeOutlet]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1281
1776
  }
1282
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTree, decorators: [{
1777
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTree, decorators: [{
1283
1778
  type: Component,
1284
1779
  args: [{ selector: 'kbq-tree', imports: [
1285
1780
  KbqTreeNodeOutlet
1286
1781
  ], template: `
1287
1782
  <ng-container kbqTreeNodeOutlet />
1288
- `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
1289
- class: 'kbq-tree'
1290
- }, exportAs: 'kbqTree', styles: [".kbq-tree{display:block}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
1783
+ `, providers: [{ provide: KbqTreeBase, useExisting: KbqTree }], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
1784
+ class: 'kbq-tree',
1785
+ role: 'tree'
1786
+ }, hostDirectives: [
1787
+ { directive: KbqStateSaving, inputs: ['useStateSaving', 'stateSavingKey'] }
1788
+ ], exportAs: 'kbqTree', styles: [".kbq-tree{display:block}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
1291
1789
  }] });
1292
1790
 
1293
1791
  const KBQ_SELECTION_TREE_VALUE_ACCESSOR = {
@@ -1295,6 +1793,8 @@ const KBQ_SELECTION_TREE_VALUE_ACCESSOR = {
1295
1793
  useExisting: forwardRef(() => KbqTreeSelection),
1296
1794
  multi: true
1297
1795
  };
1796
+ /** How long the key manager collects keystrokes before matching them against the option labels. */
1797
+ const typeAheadDebounce = 200;
1298
1798
  class KbqTreeSelectAllEvent {
1299
1799
  constructor(source, options) {
1300
1800
  this.source = source;
@@ -1330,13 +1830,36 @@ class KbqTreeSelectionChange {
1330
1830
  }
1331
1831
  }
1332
1832
  class KbqTreeSelection extends KbqTreeBase {
1333
- // TODO: Skipped for migration because:
1334
- // Accessor inputs cannot be migrated as they are too complex.
1833
+ /**
1834
+ * Accessible name written to the host.
1835
+ *
1836
+ * The host is the very element the consumer writes, and a host binding runs after their own
1837
+ * `[attr.aria-label]` binding on that element — an unset input reporting `null` would erase the name
1838
+ * they just set, because `[attr.]` never reaches the aliased input. Whatever is already on the
1839
+ * element therefore stands in for an unset input.
1840
+ */
1841
+ get resolvedAriaLabel() {
1842
+ return this.ariaLabel() || this.elementRef.nativeElement.getAttribute('aria-label');
1843
+ }
1844
+ /** Labelling element of the host. Falls back to the element's own attribute, see `resolvedAriaLabel`. */
1845
+ get resolvedAriaLabelledby() {
1846
+ return this.ariaLabelledby() || this.elementRef.nativeElement.getAttribute('aria-labelledby');
1847
+ }
1848
+ get unorderedOptions() {
1849
+ return this.unorderedOptionsList();
1850
+ }
1851
+ /**
1852
+ * Whether clicking a node clears the rest of the selection. Defaults to `true`, and to `false` for
1853
+ * `multiple="checkbox"`.
1854
+ *
1855
+ * Assigning it — from a template binding or imperatively, as `KbqTreeSelect` does — replaces the
1856
+ * derived default, so a later {@link multiple} change leaves the value alone.
1857
+ */
1335
1858
  get autoSelect() {
1336
- return this._autoSelect;
1859
+ return this.autoSelectState() ?? this.mode() !== MultipleMode.CHECKBOX;
1337
1860
  }
1338
1861
  set autoSelect(value) {
1339
- this._autoSelect = coerceBooleanProperty(value);
1862
+ this.autoSelectState.set(coerceBooleanProperty(value));
1340
1863
  }
1341
1864
  get optionFocusChanges() {
1342
1865
  return merge(...this.renderedOptions.map((option) => option.onFocus));
@@ -1344,16 +1867,56 @@ class KbqTreeSelection extends KbqTreeBase {
1344
1867
  get optionBlurChanges() {
1345
1868
  return merge(...this.renderedOptions.map((option) => option.onBlur));
1346
1869
  }
1870
+ /**
1871
+ * Selection mode of the tree.
1872
+ *
1873
+ * `checkbox` renders a checkbox in every node, `keyboard` selects without one. A bare `multiple` and
1874
+ * `true` both mean `checkbox`; `single`, `false` and an absent attribute mean single selection. The mode
1875
+ * can be changed at any time — narrowing it to single selection keeps the first selected node and
1876
+ * reports the shortened value through the `ControlValueAccessor`.
1877
+ *
1878
+ * A tree rendered inside a `kbq-tree-select` shares its `SelectionModel` with the select, so the
1879
+ * select decides how many nodes may be selected: switching this input between single and multiple
1880
+ * selection there throws. Switching between `checkbox` and `keyboard` only changes the presentation
1881
+ * and is allowed.
1882
+ *
1883
+ * The getter reports whether more than one node can be selected; read {@link multipleMode} for the mode
1884
+ * itself.
1885
+ */
1347
1886
  get multiple() {
1348
- return !!this.multipleMode;
1887
+ return !!this.mode();
1888
+ }
1889
+ /** Resolved selection mode, or `null` when only one node can be selected. */
1890
+ get multipleMode() {
1891
+ return this.mode();
1349
1892
  }
1350
- // TODO: Skipped for migration because:
1351
- // Accessor inputs cannot be migrated as they are too complex.
1893
+ set multipleMode(value) {
1894
+ this.setMultipleMode(value);
1895
+ }
1896
+ /**
1897
+ * Whether the last selected node can be deselected.
1898
+ * Derived from the mode until assigned, like {@link autoSelect}.
1899
+ */
1352
1900
  get noUnselectLast() {
1353
- return this._noUnselectLast;
1901
+ return this.noUnselectLastState() ?? this.mode() !== MultipleMode.CHECKBOX;
1354
1902
  }
1355
1903
  set noUnselectLast(value) {
1356
- this._noUnselectLast = coerceBooleanProperty(value);
1904
+ this.noUnselectLastState.set(coerceBooleanProperty(value));
1905
+ }
1906
+ /**
1907
+ * Whether typing printable characters moves the focus to the next option whose label starts with
1908
+ * them. On by default.
1909
+ *
1910
+ * Turn it off wherever the tree shares its keystrokes with a text field: an embedder such as
1911
+ * `KbqTreeSelect` routes everything the user types — the search query included — into this key
1912
+ * manager, and type-ahead would move the active option out from under the query.
1913
+ */
1914
+ get typeAhead() {
1915
+ return this.typeAheadState();
1916
+ }
1917
+ // Written imperatively by `KbqTreeSelect`, like `autoSelect` and `noUnselectLast`.
1918
+ set typeAhead(value) {
1919
+ this.typeAheadState.set(value);
1357
1920
  }
1358
1921
  /**
1359
1922
  * Whether to render the "select all" master checkbox above the nodes. Multiple selection only.
@@ -1361,11 +1924,10 @@ class KbqTreeSelection extends KbqTreeBase {
1361
1924
  * Enabling it also makes Ctrl/Cmd + A a two-way toggle, so the shortcut and the checkbox never
1362
1925
  * disagree (`selectAllToggle` is implied).
1363
1926
  */
1364
- // Written imperatively by `KbqTreeSelect`, like `autoSelect` and `noUnselectLast`, so it cannot be a
1365
- // signal input; the signal behind it is what keeps the template in step.
1366
1927
  get selectAll() {
1367
1928
  return this.selectAllEnabled();
1368
1929
  }
1930
+ // Written imperatively by `KbqTreeSelect`, like `autoSelect` and `noUnselectLast`.
1369
1931
  set selectAll(value) {
1370
1932
  this.selectAllEnabled.set(value);
1371
1933
  }
@@ -1384,6 +1946,10 @@ class KbqTreeSelection extends KbqTreeBase {
1384
1946
  get selectAllState() {
1385
1947
  return getSelectAllState(this.selectAllAdapter);
1386
1948
  }
1949
+ /** Label of the "select all" row. Follows the active locale. */
1950
+ get selectAllText() {
1951
+ return this.localeConfiguration().selectAll;
1952
+ }
1387
1953
  /**
1388
1954
  * Data nodes "select all" acts on, and the ones its checkbox state is derived from.
1389
1955
  *
@@ -1391,11 +1957,8 @@ class KbqTreeSelection extends KbqTreeBase {
1391
1957
  * is looking at, and selecting them would contradict a master checkbox that can only report on what
1392
1958
  * is on screen. Without a filter the whole data set qualifies, collapsed branches included.
1393
1959
  */
1394
- // `any`, not `unknown`: `treeControl`/`selectionModel` are themselves `any`-typed data-node generics
1395
- // pre-dating this feature (`KbqTreeBase<any>`, `SelectionModel<SelectionModelOption>`), so `unknown`
1396
- // here would only relocate the unsafety into a cast at every call site, not remove it.
1397
1960
  get selectAllTargets() {
1398
- // `treeControl` is an `@Input`, so it is still unset on the change-detection pass that sets it:
1961
+ // `treeControl` is an input, so it is still unset on the change-detection pass that sets it:
1399
1962
  // a consumer reading `allOptionsSelected`/`selectAllState` off a template reference — which is
1400
1963
  // exactly how the docs suggest swapping the trigger label — would otherwise get a TypeError
1401
1964
  // before the tree is wired up. Nothing is selectable yet at that point, so an empty set is right.
@@ -1422,29 +1985,16 @@ class KbqTreeSelection extends KbqTreeBase {
1422
1985
  setSelected: (node, selected) => selected ? this.selectionModel.select(node) : this.selectionModel.deselect(node)
1423
1986
  };
1424
1987
  }
1425
- // TODO: Skipped for migration because:
1426
- // Accessor inputs cannot be migrated as they are too complex.
1988
+ /** Whether the tree is disabled, bound with `[disabled]` or set by a form control. */
1427
1989
  get disabled() {
1428
- return this._disabled;
1429
- }
1430
- set disabled(rawValue) {
1431
- const value = coerceBooleanProperty(rawValue);
1432
- if (this._disabled !== value) {
1433
- this._disabled = value;
1434
- this.markOptionsForCheck();
1435
- }
1990
+ return this.disabledState();
1436
1991
  }
1437
- // TODO: Skipped for migration because:
1438
- // Accessor inputs cannot be migrated as they are too complex.
1992
+ /** Tab index of the tree, `-1` while it is disabled. */
1439
1993
  get tabIndex() {
1440
- return this.disabled ? -1 : this._tabIndex;
1441
- }
1442
- set tabIndex(value) {
1443
- this._tabIndex = value;
1444
- this.userTabIndex = value;
1994
+ return this.disabled ? -1 : this.tabIndexState();
1445
1995
  }
1446
1996
  get showCheckbox() {
1447
- return this.multipleMode === MultipleMode.CHECKBOX;
1997
+ return this.mode() === MultipleMode.CHECKBOX;
1448
1998
  }
1449
1999
  get isEmpty() {
1450
2000
  return this.sortedNodes.length === 0;
@@ -1457,13 +2007,23 @@ class KbqTreeSelection extends KbqTreeBase {
1457
2007
  get nodesCount() {
1458
2008
  return this.sortedNodes.length;
1459
2009
  }
2010
+ /**
2011
+ * Whether the tree is changing the selection model itself — to a value the form wrote, or onto the nodes of
2012
+ * reloaded data — rather than acting on the user. A host sharing the model, such as `KbqTreeSelect`, reports
2013
+ * no such change.
2014
+ *
2015
+ * @docs-private
2016
+ */
2017
+ get syncingSelection() {
2018
+ return this.writingValue;
2019
+ }
1460
2020
  constructor() {
1461
- const multiple = inject(new HostAttributeToken('multiple'), { optional: true });
1462
2021
  super();
1463
2022
  this.elementRef = inject(ElementRef);
1464
2023
  this.scheduler = inject(AsyncScheduler);
1465
2024
  this.clipboard = inject(Clipboard, { optional: true });
1466
2025
  this.platform = inject(Platform);
2026
+ this.injector = inject(Injector);
1467
2027
  this.focusMonitor = inject(FocusMonitor);
1468
2028
  /**
1469
2029
  * Whether this tree-selection is rendered inside a select panel (enables option
@@ -1473,38 +2033,116 @@ class KbqTreeSelection extends KbqTreeBase {
1473
2033
  */
1474
2034
  this.inSelect = !!inject(KBQ_FORM_FIELD, { optional: true, host: true });
1475
2035
  this.renderedOptions = new QueryList();
2036
+ /**
2037
+ * Accessible name of the tree. Set it whenever the tree has no visible label of its own; a tree
2038
+ * embedded in a `kbq-tree-select` is labelled by the select instead.
2039
+ */
2040
+ this.ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
2041
+ /** Id of the element that labels the tree, for when the label is rendered next to it. */
2042
+ this.ariaLabelledby = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabelledby" } : /* istanbul ignore next */ {}), alias: 'aria-labelledby' });
1476
2043
  this.resetFocusedItemOnBlur = true;
1477
- this.multipleMode = null;
1478
2044
  this.userTabIndex = null;
1479
2045
  // this parameter used when select has a search field
1480
2046
  this.optionShouldHoldFocusOnBlur = false;
2047
+ /**
2048
+ * Whether the tree acts on keyboard input itself. Turned off by an embedding host that owns the
2049
+ * keyboard, such as `KbqTreeSelect`.
2050
+ */
2051
+ this.ownsKeyboard = true;
1481
2052
  /** Reference to the built-in "select all" row, rendered only while `selectAll` is on. */
1482
- this.selectAllOption = viewChild(KbqTreeOption, ...(ngDevMode ? [{ debugName: "selectAllOption" }] : []));
2053
+ this.selectAllOption = viewChild(KbqTreeOption, ...(ngDevMode ? [{ debugName: "selectAllOption" }] : /* istanbul ignore next */ []));
2054
+ this.unorderedOptionsQuery = contentChildren(KbqTreeOption, ...(ngDevMode ? [{ debugName: "unorderedOptionsQuery" }] : /* istanbul ignore next */ []));
2055
+ this.unorderedOptionsList = kbqQueryListFrom(this.unorderedOptionsQuery);
1483
2056
  this.navigationChange = output();
2057
+ /**
2058
+ * Emits when the selection changes. A stream rather than an `output()`: `KbqTreeSelect` pipes it with rxjs.
2059
+ */
1484
2060
  this.selectionChange = new EventEmitter();
1485
- this.onSelectAll = output();
2061
+ /** @docs-private */
2062
+ this.selectionChangeOutput = outputFromObservable(this.selectionChange, { alias: 'selectionChange' });
2063
+ /** Emits after "select all" ran, with the options it could act on. */
2064
+ this.selectAllChange = output();
2065
+ /** @deprecated Use `selectAllChange` instead. Will be removed in 22.0.0. */
2066
+ this.onSelectAll = output({ alias: 'onSelectAll' });
2067
+ /**
2068
+ * Emits when the active option is copied with Ctrl/Cmd + C. Subscribing replaces the built-in
2069
+ * clipboard handler, so the event has to stay an `EventEmitter`: the decision is made by reading
2070
+ * `observed`, which `OutputEmitterRef` does not have. A template listener subscribes to it through
2071
+ * the output below.
2072
+ */
2073
+ this.copyChange = new EventEmitter();
2074
+ /** @docs-private */
2075
+ this.copyChangeOutput = outputFromObservable(this.copyChange, { alias: 'copyChange' });
2076
+ /** @deprecated Use `copyChange` instead. Will be removed in 22.0.0. */
1486
2077
  this.onCopy = new EventEmitter();
2078
+ /** @docs-private */
2079
+ this.onCopyOutput = outputFromObservable(this.onCopy, { alias: 'onCopy' });
1487
2080
  this.sortedNodes = [];
1488
2081
  this.lastSyncedDataNodes = null;
1489
- this._autoSelect = true;
1490
- this._noUnselectLast = true;
2082
+ /** @docs-private */
2083
+ this.autoSelectInput = input(undefined, { ...(ngDevMode ? { debugName: "autoSelectInput" } : /* istanbul ignore next */ {}), alias: 'autoSelect',
2084
+ transform: booleanAttribute });
2085
+ /** `undefined` while the value is derived from the mode. Written by `KbqTreeSelect` as well. */
2086
+ this.autoSelectState = linkedSignal(() => this.autoSelectInput(), ...(ngDevMode ? [{ debugName: "autoSelectState" }] : /* istanbul ignore next */ []));
2087
+ /** @docs-private */
2088
+ this.multipleInput = input(undefined, { ...(ngDevMode ? { debugName: "multipleInput" } : /* istanbul ignore next */ {}), alias: 'multiple' });
2089
+ /**
2090
+ * Backing signal of {@link multipleMode}. A signal rather than a field because the mode is also written
2091
+ * from inside the component and by `KbqTreeSelect`: options read it through `multiple` and
2092
+ * `showCheckbox`, and only a signal read re-runs their `OnPush` views and host bindings.
2093
+ */
2094
+ this.mode = signal(null, ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
2095
+ /** @docs-private */
2096
+ this.noUnselectLastInput = input(undefined, { ...(ngDevMode ? { debugName: "noUnselectLastInput" } : /* istanbul ignore next */ {}), alias: 'noUnselectLast',
2097
+ transform: booleanAttribute });
2098
+ /** `undefined` while the value is derived from the mode. Written by `KbqTreeSelect` as well. */
2099
+ this.noUnselectLastState = linkedSignal(() => this.noUnselectLastInput(), ...(ngDevMode ? [{ debugName: "noUnselectLastState" }] : /* istanbul ignore next */ []));
2100
+ /** @docs-private */
2101
+ this.typeAheadInput = input(true, { ...(ngDevMode ? { debugName: "typeAheadInput" } : /* istanbul ignore next */ {}), alias: 'typeAhead',
2102
+ transform: booleanAttribute });
2103
+ this.typeAheadState = linkedSignal(() => this.typeAheadInput(), ...(ngDevMode ? [{ debugName: "typeAheadState" }] : /* istanbul ignore next */ []));
1491
2104
  /** When `true`, a repeated Ctrl/Cmd+A deselects all options. Off by default (Ctrl+A only selects). */
1492
- this.selectAllToggle = input(false, ...(ngDevMode ? [{ debugName: "selectAllToggle", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
1493
- this.selectAllEnabled = signal(false, ...(ngDevMode ? [{ debugName: "selectAllEnabled" }] : []));
1494
- /** Label of the "select all" row. Kept in step with the locale service. */
1495
- this.selectAllText = ruRULocaleData.select.selectAll;
1496
- this._disabled = false;
1497
- this._tabIndex = 0;
1498
- this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
1499
- /** Updates locale parameters from the locale service. */
1500
- this.updateLocaleParams = () => {
1501
- // Locale data registered by a consumer through `KBQ_LOCALE_DATA`/`addLocale` may predate this key.
1502
- this.selectAllText = this.localeService?.getParams('select')?.selectAll ?? ruRULocaleData.select.selectAll;
1503
- this.changeDetectorRef.markForCheck();
1504
- };
1505
- /** `View -> model callback called when value changes` */
2105
+ this.selectAllToggle = input(false, { ...(ngDevMode ? { debugName: "selectAllToggle" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2106
+ /** @docs-private */
2107
+ this.selectAllInput = input(false, { ...(ngDevMode ? { debugName: "selectAllInput" } : /* istanbul ignore next */ {}), alias: 'selectAll',
2108
+ transform: booleanAttribute });
2109
+ this.selectAllEnabled = linkedSignal(() => this.selectAllInput(), ...(ngDevMode ? [{ debugName: "selectAllEnabled" }] : /* istanbul ignore next */ []));
2110
+ this.localeConfiguration = inject(KbqLocaleOverridesDirective, { self: true }).read('select', KBQ_SELECT_LOCALE_CONFIGURATION);
2111
+ /** @docs-private */
2112
+ this.disabledInput = input(undefined, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled',
2113
+ transform: booleanAttribute });
2114
+ this.disabledState = signal(false, ...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
2115
+ /** @docs-private */
2116
+ this.tabIndexInput = input(undefined, { ...(ngDevMode ? { debugName: "tabIndexInput" } : /* istanbul ignore next */ {}), alias: 'tabIndex',
2117
+ transform: kbqOptionalNumberAttribute });
2118
+ this.tabIndexState = signal(0, ...(ngDevMode ? [{ debugName: "tabIndexState" }] : /* istanbul ignore next */ []));
2119
+ this.selectionModelSubscription = null;
2120
+ /** Whether a value report is queued for the end of the current tick. Cleared by `writeValue` to cancel it. */
2121
+ this.pendingValueReport = false;
2122
+ /** Backs {@link syncingSelection}: a change of the selection made by code is no change to report back. */
2123
+ this.writingValue = false;
2124
+ /**
2125
+ * The last value the form wrote while some of the nodes it names were not in the data yet. Applied again as the
2126
+ * data changes, until every node is found or the selection is reported to the form.
2127
+ */
2128
+ this.unresolvedValue = null;
2129
+ this.destroyed = false;
2130
+ /** `treeControl.dataNodes` the options' checkbox states were last recomputed against. */
2131
+ this.checkboxSyncedDataNodes = null;
2132
+ /** @docs-private */
2133
+ this.selectAllHandlerInput = input(undefined, { ...(ngDevMode ? { debugName: "selectAllHandlerInput" } : /* istanbul ignore next */ {}), alias: 'selectAllHandler',
2134
+ transform: kbqSelectAllHandlerTransform });
2135
+ /**
2136
+ * Called when the value changes. Needed to properly implement `ControlValueAccessor`.
2137
+ *
2138
+ * @docs-private
2139
+ */
1506
2140
  this.onChange = () => { };
1507
- /** `View -> model callback called when select has been touched` */
2141
+ /**
2142
+ * Called when the control is blurred. Needed to properly implement `ControlValueAccessor`.
2143
+ *
2144
+ * @docs-private
2145
+ */
1508
2146
  this.onTouched = () => { };
1509
2147
  this.updateRenderedOptions = () => {
1510
2148
  const orderedOptions = [];
@@ -1516,7 +2154,10 @@ class KbqTreeSelection extends KbqTreeBase {
1516
2154
  orderedOptions.push(selectAllOption);
1517
2155
  }
1518
2156
  this.sortedNodes.forEach((node) => {
1519
- const found = this.unorderedOptions.find((option) => option.value === this.treeControl.getValue(node));
2157
+ // By node first: nodes do not have to carry distinct values, and a value match would hand every node with
2158
+ // the same value the first option holding it.
2159
+ const found = this.unorderedOptions.find((option) => option.data === node) ??
2160
+ this.unorderedOptions.find((option) => option.value === this.treeControl.getValue(node));
1520
2161
  if (found) {
1521
2162
  orderedOptions.push(found);
1522
2163
  }
@@ -1525,24 +2166,45 @@ class KbqTreeSelection extends KbqTreeBase {
1525
2166
  this.renderedOptions.notifyOnChanges();
1526
2167
  this.updateScrollSize();
1527
2168
  };
1528
- if (multiple === MultipleMode.CHECKBOX || multiple === MultipleMode.KEYBOARD) {
1529
- this.multipleMode = multiple;
1530
- }
1531
- else if (multiple !== null) {
1532
- this.multipleMode = MultipleMode.CHECKBOX;
1533
- }
1534
- if (this.multipleMode === MultipleMode.CHECKBOX) {
1535
- this.autoSelect = false;
1536
- this.noUnselectLast = false;
1537
- }
1538
- this.selectionModel = new SelectionModel(this.multiple);
1539
- this.localeService?.changes.pipe(takeUntilDestroyed()).subscribe(this.updateLocaleParams);
2169
+ this.destroyRef.onDestroy(() => (this.destroyed = true));
2170
+ // Single selection until the `multiple` input says otherwise. A model has to exist this early
2171
+ // because `KbqTreeOption.setSelected` refuses to touch the selection without one, and a static
2172
+ // `multiple` attribute reaches the input right after the constructor, before any node exists.
2173
+ this.selectionModel = this.ownSelectionModel = new SelectionModel(false);
2174
+ effect(() => {
2175
+ this.multipleInput();
2176
+ untracked(() => this.applyMultipleInput());
2177
+ });
2178
+ effect(() => {
2179
+ this.disabledInput();
2180
+ untracked(() => this.applyDisabledInput());
2181
+ });
2182
+ // Unbound, the input leaves the default, which follows the rendered options; bound back to `undefined` or
2183
+ // `null`, it restores that default.
2184
+ effect(() => {
2185
+ const tabIndex = this.tabIndexInput();
2186
+ untracked(() => {
2187
+ if (tabIndex !== undefined) {
2188
+ this.userTabIndex = tabIndex;
2189
+ this.tabIndexState.set(tabIndex);
2190
+ }
2191
+ else if (this.userTabIndex !== null) {
2192
+ this.userTabIndex = null;
2193
+ this.updateTabIndex();
2194
+ }
2195
+ });
2196
+ });
2197
+ effect(() => {
2198
+ this.typeAheadState();
2199
+ untracked(() => this.applyTypeAhead());
2200
+ });
1540
2201
  // `unorderedOptions.changes` never fires for the "select all" row — it is a view child — so the
1541
2202
  // rendered list has to be rebuilt whenever the view query resolves or drops it.
1542
2203
  effect(() => {
1543
2204
  this.selectAllOption();
1544
2205
  if (this.renderedOptions) {
1545
- this.updateRenderedOptions();
2206
+ // Untracked: the options are read too, and their changes come through `unorderedOptions.changes`.
2207
+ untracked(() => this.updateRenderedOptions());
1546
2208
  }
1547
2209
  });
1548
2210
  }
@@ -1550,14 +2212,144 @@ class KbqTreeSelection extends KbqTreeBase {
1550
2212
  toggleSelectAll() {
1551
2213
  this.selectAllOptions(true);
1552
2214
  }
2215
+ /**
2216
+ * Sets the mode from the `multiple` binding, once per bound value: an unbound input leaves what
2217
+ * `KbqTreeSelect` or the {@link multipleMode} setter wrote, and a value bound back to `undefined` means
2218
+ * single selection.
2219
+ *
2220
+ * Called by an effect, and by `writeValue` ahead of it: a forms directive on this element writes the
2221
+ * value from its own `ngOnChanges`, which runs before any effect of the view.
2222
+ */
2223
+ applyMultipleInput() {
2224
+ const multiple = this.multipleInput();
2225
+ if (multiple === this.appliedMultipleInput)
2226
+ return;
2227
+ this.appliedMultipleInput = multiple;
2228
+ this.setMultipleMode(resolveMultipleMode(multiple));
2229
+ }
2230
+ /**
2231
+ * Sets the disabled state from the `disabled` binding, once per bound value, so that whichever of the binding
2232
+ * and the form control changed last wins. An unbound input leaves what the form control wrote.
2233
+ *
2234
+ * Called by an effect, and by `setDisabledState` ahead of it: a forms directive on this element calls that
2235
+ * from its own `ngOnChanges`, after the binding is set but before any effect of the view runs.
2236
+ */
2237
+ applyDisabledInput() {
2238
+ const disabled = this.disabledInput();
2239
+ if (disabled === this.appliedDisabledInput)
2240
+ return;
2241
+ this.appliedDisabledInput = disabled;
2242
+ this.disabledState.set(!!disabled);
2243
+ }
2244
+ /**
2245
+ * Applies a new selection mode, rebuilding the `SelectionModel` when the multiplicity itself changes —
2246
+ * CDK freezes that flag at construction, so the model has to be replaced rather than reconfigured.
2247
+ */
2248
+ setMultipleMode(next) {
2249
+ if (next === this.mode()) {
2250
+ return;
2251
+ }
2252
+ const rebuildNeeded = this.selectionModel.isMultipleSelection() !== !!next;
2253
+ // `KbqTreeSelect` hands the tree its own model and subscribes to it as well, so the multiplicity is
2254
+ // the select's to decide; replacing a model we do not own would drop those subscriptions. Thrown
2255
+ // rather than ignored: Angular caches the bound value either way, so a silently dropped write
2256
+ // leaves the binding and the tree permanently out of step with no way to retry.
2257
+ if (rebuildNeeded && this.selectionModel !== this.ownSelectionModel) {
2258
+ throw getKbqTreeSelectionOwnedMultipleError();
2259
+ }
2260
+ this.mode.set(next);
2261
+ // While the checkbox is hidden, the options leave its state as it was.
2262
+ if (next === MultipleMode.CHECKBOX)
2263
+ this.scheduleCheckboxSync(true);
2264
+ if (rebuildNeeded) {
2265
+ this.rebuildSelectionModel(!!next);
2266
+ }
2267
+ }
2268
+ /** Replaces the `SelectionModel` with one of the given multiplicity, keeping what the new one can hold. */
2269
+ rebuildSelectionModel(multiple) {
2270
+ // Copied because CDK hands back its own cached array.
2271
+ const selected = [...this.selectionModel.selected];
2272
+ // Narrowing keeps one node: the first selected one in render order, falling back to the model's own
2273
+ // order when every selected node sits inside a collapsed branch and is therefore not rendered.
2274
+ // Asked of the model rather than of the option, whose mirror is only re-synced a macrotask later.
2275
+ const rendered = this.renderedOptions?.find((option) => this.selectionModel.isSelected(option.data))?.data;
2276
+ const kept = multiple ? selected : selected.slice(0, 1);
2277
+ if (!multiple && rendered !== undefined && selected.includes(rendered)) {
2278
+ kept[0] = rendered;
2279
+ }
2280
+ const dropped = selected.filter((node) => !kept.includes(node));
2281
+ const droppedOptions = (this.renderedOptions?.toArray() ?? []).filter((option) => dropped.includes(option.data));
2282
+ // `initiallySelectedValues` seeds the model without emitting.
2283
+ this.selectionModel = this.ownSelectionModel = new SelectionModel(multiple, kept);
2284
+ this.bindSelectionModel();
2285
+ // Reconciles both directions against the model that is actually in use now, so no node is left
2286
+ // painted by a stale mirror — a node whose option was created while it was already selected has
2287
+ // one, and so does every node the narrowing just dropped.
2288
+ this.renderedOptions?.forEach((option) => option.setSelected(this.selectionModel.isSelected(option.data)));
2289
+ if (droppedOptions.length) {
2290
+ // The nodes lost their selection without going through the model, so nothing else would
2291
+ // announce it.
2292
+ this.selectionChange.emit(new KbqTreeSelectionChange(this, droppedOptions[0], droppedOptions));
2293
+ }
2294
+ // Reported on every multiplicity change, not only when the selection shrank: `getSelectedValues`
2295
+ // returns a bare value in single selection and an array in multiple, so widening changes the shape
2296
+ // the form control has to hold even though nothing was dropped.
2297
+ this.scheduleValueReport();
2298
+ }
2299
+ /**
2300
+ * Reports the value once the current change-detection pass is over: a bound `[multiple]` is written
2301
+ * during change detection, and reporting straight back to the form control there would raise
2302
+ * "Expression has changed after it was checked". Coalesced so that several mode changes in one tick
2303
+ * produce one notification, and dropped if the form writes a value or the tree is gone by the time it runs.
2304
+ */
2305
+ scheduleValueReport() {
2306
+ if (this.pendingValueReport) {
2307
+ return;
2308
+ }
2309
+ this.pendingValueReport = true;
2310
+ Promise.resolve().then(() => {
2311
+ if (!this.pendingValueReport)
2312
+ return;
2313
+ this.pendingValueReport = false;
2314
+ if (!this.destroyed) {
2315
+ this.reportValue();
2316
+ }
2317
+ });
2318
+ }
2319
+ /** Reports the selection to the form, which then holds it instead of a value still waiting for its nodes. */
2320
+ reportValue() {
2321
+ this.unresolvedValue = null;
2322
+ this.onChange(this.getSelectedValues());
2323
+ }
2324
+ /** (Re)points the change subscription at the current {@link selectionModel}. */
2325
+ bindSelectionModel() {
2326
+ this.selectionModelSubscription?.unsubscribe();
2327
+ this.selectionModelSubscription = this.selectionModel.changed
2328
+ .pipe(takeUntilDestroyed(this.destroyRef))
2329
+ .subscribe(() => {
2330
+ if (!this.writingValue) {
2331
+ this.reportValue();
2332
+ }
2333
+ this.renderedOptions.notifyOnChanges();
2334
+ // The "select all" row renders the selection state.
2335
+ this.changeDetectorRef.markForCheck();
2336
+ });
2337
+ }
1553
2338
  ngAfterContentInit() {
2339
+ super.ngAfterContentInit();
1554
2340
  if (this.platform.isBrowser) {
1555
- this.unorderedOptions.changes.subscribe(this.updateRenderedOptions);
2341
+ this.unorderedOptions.changes
2342
+ .pipe(takeUntilDestroyed(this.destroyRef))
2343
+ .subscribe(this.updateRenderedOptions);
1556
2344
  }
1557
2345
  this.keyManager = new FocusKeyManager(this.renderedOptions)
1558
2346
  .withVerticalOrientation(true)
1559
2347
  .withHorizontalOrientation(null);
2348
+ this.applyTypeAhead();
1560
2349
  this.keyManager.change.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
2350
+ // `aria-activedescendant` is bound to the active option, and nothing else in this view
2351
+ // changes when the key manager moves.
2352
+ this.changeDetectorRef.markForCheck();
1561
2353
  if (this.keyManager.activeItem) {
1562
2354
  this.emitNavigationEvent(this.keyManager.activeItem);
1563
2355
  // todo need check this logic
@@ -1566,11 +2358,8 @@ class KbqTreeSelection extends KbqTreeBase {
1566
2358
  }
1567
2359
  }
1568
2360
  });
1569
- this.keyManager.tabOut.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.allowFocusEscape());
1570
- this.selectionModel.changed.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
1571
- this.onChange(this.getSelectedValues());
1572
- this.renderedOptions.notifyOnChanges();
1573
- });
2361
+ kbqLeaveTabOrderOnTabOut(this.keyManager.tabOut, this.elementRef.nativeElement, () => this.tabIndex, this.destroyRef);
2362
+ this.bindSelectionModel();
1574
2363
  this.renderedOptions.changes
1575
2364
  .pipe(delay(0, this.scheduler), takeUntilDestroyed(this.destroyRef))
1576
2365
  .subscribe((options) => {
@@ -1590,11 +2379,38 @@ class KbqTreeSelection extends KbqTreeBase {
1590
2379
  });
1591
2380
  });
1592
2381
  }
2382
+ /**
2383
+ * Rebuilds the tree around a selection model owned by an embedding host, such as `KbqTreeSelect`.
2384
+ *
2385
+ * The host has to take the model over before the tree starts reacting to it, and re-running
2386
+ * `ngAfterContentInit()` is not a way to do that: neither `unorderedOptions` nor `renderedOptions` is
2387
+ * ever re-created, so a second run would only leave a second set of subscribers on both — every options
2388
+ * change handled twice, and the whole option sweep run twice per emission. Only the subscription that
2389
+ * depends on the model has to move, which is exactly what `bindSelectionModel` does.
2390
+ */
2391
+ initializeForEmbedding(selectionModel) {
2392
+ this.selectionModel = selectionModel;
2393
+ this.bindSelectionModel();
2394
+ }
2395
+ ngAfterContentChecked() {
2396
+ // Syncs the list here so `changes` emits after the projected items are bound and before the host bindings.
2397
+ this.unorderedOptionsList();
2398
+ super.ngAfterContentChecked();
2399
+ }
1593
2400
  ngAfterViewInit() {
1594
- this.focusMonitor.monitor(this.elementRef, true);
2401
+ // Reports the focus leaving only when it lands outside the tree (or nowhere): the host hands it to an option
2402
+ // on entry, and options hand it on to each other or to their action buttons, none of which blurs the tree.
2403
+ this.focusMonitor
2404
+ .monitor(this.elementRef, true)
2405
+ .pipe(takeUntilDestroyed(this.destroyRef))
2406
+ .subscribe((origin) => {
2407
+ if (!origin)
2408
+ this.blur();
2409
+ });
1595
2410
  }
1596
2411
  ngOnDestroy() {
1597
2412
  super.ngOnDestroy();
2413
+ this.dropSubscriptions();
1598
2414
  this.focusMonitor.stopMonitoring(this.elementRef);
1599
2415
  }
1600
2416
  focus($event) {
@@ -1610,17 +2426,45 @@ class KbqTreeSelection extends KbqTreeBase {
1610
2426
  }
1611
2427
  this.keyManager.setFocusOrigin('program');
1612
2428
  }
2429
+ /** @docs-private */
1613
2430
  highlightSelectedOption() {
1614
- this.renderedOptions.find((item) => item.data === this.selectionModel.selected[0])?.focus();
2431
+ untracked(() => {
2432
+ // The selection can hold nodes that are not rendered — collapsed branches, or references left
2433
+ // over from a data replacement. Falling back keeps `focus()` from ending with nothing focused
2434
+ // at all, since it already took the branch that skips `setFirstItemActive`.
2435
+ const target = this.renderedOptions.find((item) => item.data === this.selectionModel.selected[0]) ??
2436
+ this.keyManager.activeItem;
2437
+ if (target) {
2438
+ target.focus();
2439
+ }
2440
+ else {
2441
+ this.keyManager.setFirstItemActive();
2442
+ }
2443
+ });
1615
2444
  }
1616
2445
  blur() {
1617
- if (!this.hasFocusedOption() && this.resetFocusedItemOnBlur) {
1618
- this.keyManager.setActiveItem(-1);
1619
- }
1620
- this.onTouched();
1621
- this.changeDetectorRef.markForCheck();
2446
+ untracked(() => {
2447
+ if (!this.hasFocusedOption() && this.resetFocusedItemOnBlur) {
2448
+ this.keyManager.setActiveItem(-1);
2449
+ }
2450
+ this.onTouched();
2451
+ this.changeDetectorRef.markForCheck();
2452
+ });
1622
2453
  }
2454
+ /**
2455
+ * Host listener for keyboard input.
2456
+ *
2457
+ * Does nothing while an embedding host owns the keyboard — `KbqTreeSelect` routes every key through
2458
+ * its own panel handler and calls back into `handleKeydown` for the parts it delegates, so without
2459
+ * this guard the same event would be acted on twice.
2460
+ */
1623
2461
  onKeyDown(event) {
2462
+ if (!this.ownsKeyboard)
2463
+ return;
2464
+ this.handleKeydown(event);
2465
+ }
2466
+ /** Runs the tree's own keyboard handling, whether or not it owns the keyboard. */
2467
+ handleKeydown(event) {
1624
2468
  this.keyManager.setFocusOrigin('keyboard');
1625
2469
  const keyCode = event.keyCode;
1626
2470
  if ([SPACE, LEFT_ARROW, RIGHT_ARROW].includes(keyCode) || isVerticalMovement(event)) {
@@ -1642,14 +2486,22 @@ class KbqTreeSelection extends KbqTreeBase {
1642
2486
  const activeItem = this.keyManager.activeItem;
1643
2487
  if (activeItem.isExpandable && activeItem.isExpanded) {
1644
2488
  this.treeControl.collapse(activeItem.data);
2489
+ this.saveState();
1645
2490
  }
1646
2491
  else {
1647
2492
  this.setActiveParentOption(activeItem);
1648
2493
  }
1649
2494
  return;
1650
2495
  }
1651
- else if (keyCode === RIGHT_ARROW && this.keyManager.activeItem?.isExpandable) {
1652
- this.treeControl.expand(this.keyManager.activeItem.data);
2496
+ else if (keyCode === RIGHT_ARROW && this.keyManager.activeItem) {
2497
+ const activeItem = this.keyManager.activeItem;
2498
+ if (activeItem.isExpandable && !activeItem.isExpanded) {
2499
+ this.treeControl.expand(activeItem.data);
2500
+ this.saveState();
2501
+ }
2502
+ else if (activeItem.isExpandable) {
2503
+ this.setActiveFirstChildOption(activeItem);
2504
+ }
1653
2505
  return;
1654
2506
  }
1655
2507
  else if (keyCode === DOWN_ARROW) {
@@ -1674,12 +2526,26 @@ class KbqTreeSelection extends KbqTreeBase {
1674
2526
  else if (keyCode === PAGE_DOWN) {
1675
2527
  this.keyManager.setNextPageItemActive();
1676
2528
  }
2529
+ else {
2530
+ // Whatever is left is either a printable character, which the key manager turns into a
2531
+ // type-ahead query, or a key nothing here reacts to. Every key handled above returns or is
2532
+ // matched before this point, so the manager only ever sees the leftovers.
2533
+ //
2534
+ // Ctrl/Cmd/Alt combinations are the application's shortcuts, not text: the key manager feeds
2535
+ // its letter stream from the `default` branch without a modifier guard of its own, so Ctrl+S
2536
+ // would otherwise type-ahead to the first option starting with "S" and move focus there.
2537
+ if (!hasModifierKey(event, 'ctrlKey', 'metaKey', 'altKey')) {
2538
+ this.keyManager.onKeydown(event);
2539
+ }
2540
+ return;
2541
+ }
1677
2542
  if (this.keyManager.activeItem && isVerticalMovement(event)) {
1678
2543
  this.setSelectedOptionsByKey(this.keyManager.activeItem, hasModifierKey(event, 'shiftKey'),
1679
2544
  // ctrlKey is for Windows, metaKey is for MacOS
1680
2545
  hasModifierKey(event, 'ctrlKey', 'metaKey'));
1681
2546
  }
1682
2547
  }
2548
+ /** @docs-private */
1683
2549
  updateScrollSize() {
1684
2550
  if (!this.renderedOptions.first) {
1685
2551
  return;
@@ -1692,6 +2558,7 @@ class KbqTreeSelection extends KbqTreeBase {
1692
2558
  }
1693
2559
  this.keyManager.withScrollSize(Math.floor(this.getHeight() / optionHeight));
1694
2560
  }
2561
+ /** @docs-private */
1695
2562
  setSelectedOptionsByKey(option, shiftKey, ctrlKey) {
1696
2563
  if (shiftKey && this.multiple) {
1697
2564
  this.selectActiveOptions();
@@ -1708,6 +2575,7 @@ class KbqTreeSelection extends KbqTreeBase {
1708
2575
  this.emitChangeEvent(option);
1709
2576
  }
1710
2577
  }
2578
+ /** @docs-private */
1711
2579
  setSelectedOptionsByClick(option, shiftKey, ctrlKey) {
1712
2580
  if (option.disabled || !option.selectable()) {
1713
2581
  return;
@@ -1734,6 +2602,7 @@ class KbqTreeSelection extends KbqTreeBase {
1734
2602
  }
1735
2603
  this.emitChangeEvent(option);
1736
2604
  }
2605
+ /** @docs-private */
1737
2606
  selectActiveOptions() {
1738
2607
  const options = this.renderedOptions.toArray();
1739
2608
  let fromIndex = this.keyManager.previousActiveItemIndex;
@@ -1758,9 +2627,7 @@ class KbqTreeSelection extends KbqTreeBase {
1758
2627
  renderedOption.setSelected(selectedOptionState);
1759
2628
  });
1760
2629
  }
1761
- setFocusedOption(option) {
1762
- this.keyManager.setActiveItem(option);
1763
- }
2630
+ /** @docs-private */
1764
2631
  toggleFocusedOption() {
1765
2632
  const focusedOption = this.keyManager.activeItem;
1766
2633
  // The row is not selectable, so nothing below would act on it. Handling it here covers both focus
@@ -1776,14 +2643,47 @@ class KbqTreeSelection extends KbqTreeBase {
1776
2643
  this.emitChangeEvent(focusedOption);
1777
2644
  }
1778
2645
  }
2646
+ /** @docs-private */
1779
2647
  renderNodeChanges(data, dataDiffer = this.dataDiffer, viewContainer = this.nodeOutlet.viewContainer, parentData) {
1780
- super.renderNodeChanges(data, dataDiffer, viewContainer, parentData);
2648
+ // Not `super.renderNodeChanges`: that would run change detection over this very view before
2649
+ // `sortedNodes` is refreshed, so the "select all" row — which is rendered off `isEmpty` — would
2650
+ // need a second pass to catch up. One pass, after the state its template reads is current.
2651
+ const changed = this.applyNodeChanges(data, dataDiffer, viewContainer, parentData);
1781
2652
  this.sortedNodes = this.getSortedNodes(viewContainer);
1782
- this.nodeOutlet.changeDetectorRef.detectChanges();
2653
+ this.changeDetectorRef.detectChanges();
2654
+ this.scheduleCheckboxSync(false);
2655
+ // The "select all" row is rendered ahead of what its state reads: new rows bind their inputs after it and join
2656
+ // `renderedOptions` only once bound, and `KbqTreeFlatDataSource` assigns `dataNodes` after it emits. Nothing
2657
+ // else in the tree reads that state but the checkbox sync above, so a tree without the row is done in this one
2658
+ // pass. Marked for check, which reaches the views above too: a template reading `allOptionsSelected` by
2659
+ // reference reads the same state.
2660
+ if (!this.showSelectAll)
2661
+ return;
2662
+ const dataNodes = this.treeControl.dataNodes;
2663
+ afterNextRender(() => {
2664
+ if (changed || this.treeControl.dataNodes !== dataNodes)
2665
+ this.changeDetectorRef.markForCheck();
2666
+ }, { injector: this.injector });
2667
+ }
2668
+ /**
2669
+ * Recomputes every option's checkbox state where no selection change follows to do it: after `dataNodes` is
2670
+ * replaced, which moves the descendants a branch counts, and once a hidden checkbox appears. A microtask later, as
2671
+ * a flat data source assigns `dataNodes` only after it emits.
2672
+ */
2673
+ scheduleCheckboxSync(force) {
2674
+ Promise.resolve().then(() => {
2675
+ const dataNodes = this.treeControl?.dataNodes ?? null;
2676
+ if (this.destroyed || (!force && dataNodes === this.checkboxSyncedDataNodes))
2677
+ return;
2678
+ this.checkboxSyncedDataNodes = dataNodes;
2679
+ this.unorderedOptions.forEach((option) => option.markForCheck());
2680
+ });
1783
2681
  }
2682
+ /** @docs-private */
1784
2683
  emitNavigationEvent(option) {
1785
2684
  this.navigationChange.emit(new KbqTreeNavigationChange(this, option));
1786
2685
  }
2686
+ /** @docs-private */
1787
2687
  emitChangeEvent(option) {
1788
2688
  this.selectionChange.emit(new KbqTreeSelectionChange(this, option, [option]));
1789
2689
  }
@@ -1792,46 +2692,51 @@ class KbqTreeSelection extends KbqTreeBase {
1792
2692
  * which toggles the selection of all non-disabled, selectable options.
1793
2693
  */
1794
2694
  get selectAllHandler() {
1795
- return this._selectAllHandler;
1796
- }
1797
- set selectAllHandler(fn) {
1798
- if (typeof fn !== 'function') {
1799
- throw Error('`selectAllHandler` must be a function.');
1800
- }
1801
- this._selectAllHandler = fn;
2695
+ return this.selectAllHandlerInput() ?? this.defaultSelectAllHandler;
1802
2696
  }
1803
- _selectAllHandler(event, tree) {
2697
+ defaultSelectAllHandler(event, tree) {
1804
2698
  event.preventDefault();
1805
2699
  tree.selectAllOptions();
1806
2700
  }
1807
- selectAllOptions(allowDeselect = this.selectAll || this.selectAllToggle()) {
1808
- // The row's own `(click)` and the Ctrl/Cmd + A shortcut both funnel through here, so this is the
1809
- // single place to refuse acting while the whole tree is disabled — mirrors the guard every other
1810
- // row already gets via `KbqTreeOption.selectViaInteraction()`.
1811
- if (this.disabled)
1812
- return;
1813
- // Selection is applied at the data-node level (incl. collapsed/non-rendered nodes unless a filter
1814
- // is active), while the emitted events carry the selectable rendered options.
1815
- const selectableOptions = this.renderedOptions.filter((option) => !option.disabled && option.selectable());
1816
- // `toggleSelectAll` returns the data nodes whose selection actually flipped — the source of
1817
- // truth, unlike the cached `option.selected` which lags until change detection.
1818
- const changed = toggleSelectAll(this.selectAllAdapter, { allowDeselect });
1819
- const changedData = new Set(changed);
1820
- const changedOptions = selectableOptions.filter((option) => changedData.has(option.data));
1821
- // Skip `selectionChange` on a no-op (e.g. Ctrl+A while everything is already selected and
1822
- // `allowDeselect` is off) so `KbqTreeSelectionChange.option` is never `undefined`.
1823
- if (changedOptions.length > 0) {
1824
- this.selectionChange.emit(new KbqTreeSelectionChange(this, changedOptions[0], changedOptions));
1825
- }
1826
- this.onSelectAll.emit(new KbqTreeSelectAllEvent(this, selectableOptions));
2701
+ selectAllOptions(allowDeselect) {
2702
+ // Untracked, its default included, like the other imperative methods: called from a consumer's `effect()`,
2703
+ // the state read on the way — the options, `disabled`, the mode, the inputs — would make the effect run
2704
+ // again whenever it changes.
2705
+ untracked(() => {
2706
+ // The row's own `(click)` and the Ctrl/Cmd + A shortcut both funnel through here, so this is the
2707
+ // single place to refuse acting while the whole tree is disabled — mirrors the guard every other
2708
+ // row already gets via `KbqTreeOption.selectViaInteraction()`.
2709
+ if (this.disabled)
2710
+ return;
2711
+ // Selection is applied at the data-node level (incl. collapsed/non-rendered nodes unless a filter
2712
+ // is active), while the emitted events carry the selectable rendered options.
2713
+ const selectableOptions = this.renderedOptions.filter((option) => !option.disabled && option.selectable());
2714
+ // `toggleSelectAll` returns the data nodes whose selection actually flipped — the source of
2715
+ // truth, unlike the cached `option.selected` which lags until change detection.
2716
+ const changed = toggleSelectAll(this.selectAllAdapter, {
2717
+ allowDeselect: allowDeselect ?? (this.selectAll || this.selectAllToggle())
2718
+ });
2719
+ const changedData = new Set(changed);
2720
+ const changedOptions = selectableOptions.filter((option) => changedData.has(option.data));
2721
+ // Skip `selectionChange` on a no-op (e.g. Ctrl+A while everything is already selected and
2722
+ // `allowDeselect` is off) so `KbqTreeSelectionChange.option` is never `undefined`.
2723
+ if (changedOptions.length > 0) {
2724
+ this.selectionChange.emit(new KbqTreeSelectionChange(this, changedOptions[0], changedOptions));
2725
+ }
2726
+ const selectAllEvent = new KbqTreeSelectAllEvent(this, selectableOptions);
2727
+ this.selectAllChange.emit(selectAllEvent);
2728
+ this.onSelectAll.emit(selectAllEvent);
2729
+ });
1827
2730
  }
1828
2731
  copyActiveOption(event) {
1829
2732
  if (!this.keyManager.activeItem)
1830
2733
  return;
1831
2734
  const option = this.keyManager.activeItem;
1832
2735
  option.preventBlur = true;
1833
- if (this.onCopy.observed) {
1834
- this.onCopy.emit(new KbqTreeCopyEvent(this, this.keyManager.activeItem, event));
2736
+ if (this.copyChange.observed || this.onCopy.observed) {
2737
+ const copyEvent = new KbqTreeCopyEvent(this, option, event);
2738
+ this.copyChange.emit(copyEvent);
2739
+ this.onCopy.emit(copyEvent);
1835
2740
  }
1836
2741
  else {
1837
2742
  this.onCopyDefaultHandler();
@@ -1840,20 +2745,44 @@ class KbqTreeSelection extends KbqTreeBase {
1840
2745
  option.preventBlur = false;
1841
2746
  }
1842
2747
  writeValue(value) {
1843
- if (this.multiple && value && !Array.isArray(value)) {
1844
- throw getKbqSelectNonArrayValueError();
1845
- }
1846
- if (value) {
1847
- this.setOptionsFromValues(this.multiple ? value : [value]);
1848
- }
1849
- else {
1850
- this.selectionModel.clear();
2748
+ untracked(() => {
2749
+ this.applyMultipleInput();
2750
+ if (this.multiple && value && !Array.isArray(value)) {
2751
+ throw getKbqSelectNonArrayValueError();
2752
+ }
2753
+ // The form holds the value it writes, so a mode change has nothing left to report.
2754
+ this.pendingValueReport = false;
2755
+ this.applyWrittenValue(value);
2756
+ });
2757
+ }
2758
+ /** Selects the nodes of a value the form wrote, and keeps the value for the data still to come if any is missing. */
2759
+ applyWrittenValue(value) {
2760
+ // A node value can be falsy, `0` or `''`: only a missing value clears the single selection.
2761
+ const values = this.multiple
2762
+ ? Array.isArray(value)
2763
+ ? value
2764
+ : null
2765
+ : value === null || value === undefined
2766
+ ? null
2767
+ : [value];
2768
+ this.syncSelection(() => (values ? this.setOptionsFromValues(values) : this.selectionModel.clear()));
2769
+ this.unresolvedValue = values?.some((item) => !this.treeControl.hasValue(item)) ? { value } : null;
2770
+ }
2771
+ /** Runs a change of the selection made by code, which reports nothing back to the form or to a host. */
2772
+ syncSelection(change) {
2773
+ // Restored rather than cleared: a value written while this one is applied must not end the outer write.
2774
+ const wasWritingValue = this.writingValue;
2775
+ this.writingValue = true;
2776
+ try {
2777
+ change();
2778
+ }
2779
+ finally {
2780
+ this.writingValue = wasWritingValue;
1851
2781
  }
1852
2782
  }
1853
2783
  registerOnChange(fn) {
1854
2784
  this.onChange = fn;
1855
2785
  }
1856
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
1857
2786
  registerOnTouched(fn) {
1858
2787
  this.onTouched = fn;
1859
2788
  }
@@ -1861,20 +2790,28 @@ class KbqTreeSelection extends KbqTreeBase {
1861
2790
  * Sets the disabled state of the control. Implemented as a part of ControlValueAccessor.
1862
2791
  */
1863
2792
  setDisabledState(isDisabled) {
1864
- this._disabled = isDisabled;
1865
- this.changeDetectorRef.markForCheck();
2793
+ untracked(() => {
2794
+ this.applyDisabledInput();
2795
+ this.disabledState.set(isDisabled);
2796
+ });
1866
2797
  }
2798
+ /** @docs-private */
1867
2799
  setOptionsFromValues(values) {
1868
- this.selectionModel.clear();
1869
- const valuesToSelect = values.reduce((result, value) => {
1870
- return this.treeControl.hasValue(value) ? [...result, this.treeControl.hasValue(value)] : [...result];
1871
- }, []);
1872
- this.selectionModel.select(...valuesToSelect);
2800
+ untracked(() => {
2801
+ this.selectionModel.clear();
2802
+ const valuesToSelect = values.reduce((result, value) => {
2803
+ return this.treeControl.hasValue(value) ? [...result, this.treeControl.hasValue(value)] : [...result];
2804
+ }, []);
2805
+ this.selectionModel.select(...valuesToSelect);
2806
+ });
1873
2807
  }
1874
2808
  /**
1875
2809
  * Rebinds orphan node references in selectionModel to current treeControl.dataNodes by value.
1876
2810
  * Needed after dataSource.data is replaced — selectionModel holds references to old node
1877
2811
  * objects, but options render with new ones, so toggle()/isSelected() break on identity.
2812
+ *
2813
+ * A value the form wrote ahead of its nodes is applied again instead, which resolves every node anew.
2814
+ * Either way the selection only follows the data, so nothing is reported.
1878
2815
  */
1879
2816
  syncSelectionModelToDataNodes() {
1880
2817
  const currentNodes = this.treeControl.dataNodes;
@@ -1883,6 +2820,10 @@ class KbqTreeSelection extends KbqTreeBase {
1883
2820
  if (currentNodes === this.lastSyncedDataNodes)
1884
2821
  return;
1885
2822
  this.lastSyncedDataNodes = currentNodes;
2823
+ if (this.unresolvedValue) {
2824
+ this.applyWrittenValue(this.unresolvedValue.value);
2825
+ return;
2826
+ }
1886
2827
  if (this.selectionModel.isEmpty() || !currentNodes?.length)
1887
2828
  return;
1888
2829
  const selected = this.selectionModel.selected;
@@ -1902,23 +2843,23 @@ class KbqTreeSelection extends KbqTreeBase {
1902
2843
  const replacement = this.treeControl.hasValue(this.treeControl.getValue(node));
1903
2844
  return replacement ?? node;
1904
2845
  });
1905
- this.selectionModel.setSelection(...reconciled);
2846
+ this.syncSelection(() => this.selectionModel.setSelection(...reconciled));
1906
2847
  }
2848
+ /** @docs-private */
1907
2849
  getSelectedValues() {
1908
2850
  const selectedValues = this.selectionModel.selected.map((selected) => this.treeControl.getValue(selected));
1909
2851
  return this.multiple ? selectedValues : selectedValues[0];
1910
2852
  }
1911
- getItemHeight() {
1912
- return this.renderedOptions.first ? this.renderedOptions.first.getHeight() : 0;
1913
- }
1914
2853
  setStateChildren(option, state) {
1915
- const valuesToChange = this.treeControl.getDescendants(option.data);
1916
- if (state) {
1917
- this.selectionModel.select(...valuesToChange);
1918
- }
1919
- else {
1920
- this.selectionModel.deselect(...valuesToChange);
1921
- }
2854
+ untracked(() => {
2855
+ const valuesToChange = this.treeControl.getDescendants(option.data);
2856
+ if (state) {
2857
+ this.selectionModel.select(...valuesToChange);
2858
+ }
2859
+ else {
2860
+ this.selectionModel.deselect(...valuesToChange);
2861
+ }
2862
+ });
1922
2863
  }
1923
2864
  onCopyDefaultHandler() {
1924
2865
  this.clipboard?.copy(this.keyManager.activeItem.value);
@@ -1951,11 +2892,37 @@ class KbqTreeSelection extends KbqTreeBase {
1951
2892
  level = option.level;
1952
2893
  }
1953
2894
  }
2895
+ /** `-1` is the key manager's way of keeping the letter stream running but never matching on it. */
2896
+ applyTypeAhead() {
2897
+ this.keyManager?.withTypeAhead(typeAheadDebounce, this.typeAhead ? 0 : -1);
2898
+ }
2899
+ /**
2900
+ * Moves focus to the first child of an already-expanded option — ArrowRight on an expanded node.
2901
+ *
2902
+ * The mirror of `setActiveParentOption`: the first rendered option after the active one is its
2903
+ * first child whenever its level is greater, so nothing has to be re-derived from `treeControl`.
2904
+ * A disabled child cannot take focus, so the walk continues while the options stay inside the
2905
+ * subtree, and stops as soon as the level falls back to the active option's own.
2906
+ */
2907
+ setActiveFirstChildOption(activeOption) {
2908
+ const options = this.renderedOptions.toArray();
2909
+ for (let index = this.keyManager.activeItemIndex + 1; index < options.length; index++) {
2910
+ const option = options[index];
2911
+ if (option.level <= activeOption.level) {
2912
+ return;
2913
+ }
2914
+ if (!option.disabled) {
2915
+ this.keyManager.setActiveItem(index);
2916
+ return;
2917
+ }
2918
+ }
2919
+ }
1954
2920
  getHeight() {
1955
2921
  return kbqGetElementHeight(this.elementRef.nativeElement);
1956
2922
  }
2923
+ /** A tree with nothing rendered leaves the tab order, unless a tab index other than `0` is bound. */
1957
2924
  updateTabIndex() {
1958
- this._tabIndex = this.renderedOptions.length === 0 ? -1 : 0;
2925
+ this.tabIndexState.set(this.userTabIndex || (this.renderedOptions.length === 0 ? -1 : 0));
1959
2926
  }
1960
2927
  getSortedNodes(viewContainer) {
1961
2928
  const array = [];
@@ -1965,15 +2932,6 @@ class KbqTreeSelection extends KbqTreeBase {
1965
2932
  }
1966
2933
  return array;
1967
2934
  }
1968
- allowFocusEscape() {
1969
- if (this._tabIndex !== -1) {
1970
- this._tabIndex = -1;
1971
- setTimeout(() => {
1972
- this._tabIndex = this.userTabIndex || 0;
1973
- this.changeDetectorRef.markForCheck();
1974
- });
1975
- }
1976
- }
1977
2935
  resetOptions() {
1978
2936
  this.dropSubscriptions();
1979
2937
  this.listenToOptionsFocus();
@@ -1996,10 +2954,20 @@ class KbqTreeSelection extends KbqTreeBase {
1996
2954
  this.keyManager.updateActiveItem(index);
1997
2955
  }
1998
2956
  });
1999
- this.optionBlurSubscription = this.optionBlurChanges.subscribe(() => this.blur());
2957
+ // Moving the active option blurs the one being left, so an option blur alone does not mean the
2958
+ // options lost the focus — and resetting here would drop the active option the key manager has just
2959
+ // set, because `KbqTreeOption.hasFocus` is cleared synchronously but only raised a microtask later, so
2960
+ // `hasFocusedOption()` reports nothing focused for the whole move. Only a blur of the option the
2961
+ // key manager still points at is the focus actually leaving the options.
2962
+ this.optionBlurSubscription = this.optionBlurChanges.subscribe(({ option }) => {
2963
+ if (option === this.keyManager.activeItem && !this.hasFocusedOption() && this.resetFocusedItemOnBlur) {
2964
+ this.keyManager.setActiveItem(-1);
2965
+ }
2966
+ });
2000
2967
  }
2001
2968
  /**
2002
2969
  * Utility to ensure all indexes are valid.
2970
+ *
2003
2971
  * @param index The index to be checked.
2004
2972
  * @returns True if the index is valid for our list of options.
2005
2973
  */
@@ -2010,9 +2978,6 @@ class KbqTreeSelection extends KbqTreeBase {
2010
2978
  hasFocusedOption() {
2011
2979
  return this.renderedOptions.some((option) => option.hasFocus);
2012
2980
  }
2013
- markOptionsForCheck() {
2014
- this.renderedOptions.forEach((option) => option.markForCheck());
2015
- }
2016
2981
  updateOptionsFocus() {
2017
2982
  this.renderedOptions.filter((option) => option.hasFocus).forEach((option) => (option.hasFocus = false));
2018
2983
  }
@@ -2025,28 +2990,27 @@ class KbqTreeSelection extends KbqTreeBase {
2025
2990
  }
2026
2991
  return $event.relatedTarget.classList.contains('kbq-tree-option');
2027
2992
  }
2028
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeSelection, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2029
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqTreeSelection, isStandalone: true, selector: "kbq-tree-selection", inputs: { treeControl: { classPropertyName: "treeControl", publicName: "treeControl", isSignal: false, isRequired: false, transformFunction: null }, autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: false, isRequired: false, transformFunction: null }, noUnselectLast: { classPropertyName: "noUnselectLast", publicName: "noUnselectLast", isSignal: false, isRequired: false, transformFunction: null }, selectAllToggle: { classPropertyName: "selectAllToggle", publicName: "selectAllToggle", isSignal: true, isRequired: false, transformFunction: null }, selectAll: { classPropertyName: "selectAll", publicName: "selectAll", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: false, isRequired: false, transformFunction: null }, selectAllHandler: { classPropertyName: "selectAllHandler", publicName: "selectAllHandler", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { navigationChange: "navigationChange", selectionChange: "selectionChange", onSelectAll: "onSelectAll", onCopy: "onCopy" }, host: { listeners: { "blur": "blur()", "focus": "focus($event)", "keydown": "onKeyDown($event)", "window:resize": "updateScrollSize()" }, properties: { "attr.tabindex": "tabIndex", "attr.disabled": "disabled || null" }, classAttribute: "kbq-tree-selection" }, providers: [
2993
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeSelection, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2994
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: KbqTreeSelection, isStandalone: true, selector: "kbq-tree-selection", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, autoSelectInput: { classPropertyName: "autoSelectInput", publicName: "autoSelect", isSignal: true, isRequired: false, transformFunction: null }, multipleInput: { classPropertyName: "multipleInput", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, noUnselectLastInput: { classPropertyName: "noUnselectLastInput", publicName: "noUnselectLast", isSignal: true, isRequired: false, transformFunction: null }, typeAheadInput: { classPropertyName: "typeAheadInput", publicName: "typeAhead", isSignal: true, isRequired: false, transformFunction: null }, selectAllToggle: { classPropertyName: "selectAllToggle", publicName: "selectAllToggle", isSignal: true, isRequired: false, transformFunction: null }, selectAllInput: { classPropertyName: "selectAllInput", publicName: "selectAll", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, tabIndexInput: { classPropertyName: "tabIndexInput", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, selectAllHandlerInput: { classPropertyName: "selectAllHandlerInput", publicName: "selectAllHandler", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navigationChange: "navigationChange", selectionChangeOutput: "selectionChange", selectAllChange: "selectAllChange", onSelectAll: "onSelectAll", copyChangeOutput: "copyChange", onCopyOutput: "onCopy" }, host: { attributes: { "role": "tree" }, listeners: { "focus": "focus($event)", "keydown": "onKeyDown($event)", "window:resize": "updateScrollSize()" }, properties: { "attr.tabindex": "tabIndex", "attr.disabled": "disabled || null", "attr.aria-disabled": "disabled || null", "attr.aria-multiselectable": "multiple || null", "attr.aria-label": "resolvedAriaLabel", "attr.aria-labelledby": "resolvedAriaLabelledby", "attr.aria-activedescendant": "keyManager?.activeItem?.id" }, classAttribute: "kbq-tree-selection" }, providers: [
2030
2995
  KBQ_SELECTION_TREE_VALUE_ACCESSOR,
2031
2996
  { provide: KBQ_TREE_OPTION_PARENT_COMPONENT, useExisting: KbqTreeSelection },
2032
2997
  { provide: KbqTreeBase, useExisting: KbqTreeSelection }
2033
- ], queries: [{ propertyName: "unorderedOptions", predicate: KbqTreeOption }], viewQueries: [{ propertyName: "selectAllOption", first: true, predicate: KbqTreeOption, descendants: true, isSignal: true }, { propertyName: "nodeOutlet", first: true, predicate: KbqTreeNodeOutlet, descendants: true, static: true }], exportAs: ["kbqTreeSelection"], usesInheritance: true, ngImport: i0, template: `
2998
+ ], queries: [{ propertyName: "unorderedOptionsQuery", predicate: KbqTreeOption, isSignal: true }], viewQueries: [{ propertyName: "selectAllOption", first: true, predicate: KbqTreeOption, descendants: true, isSignal: true }], exportAs: ["kbqTreeSelection"], usesInheritance: true, hostDirectives: [{ directive: i1.KbqStateSaving, inputs: ["useStateSaving", "useStateSaving", "stateSavingKey", "stateSavingKey"] }, { directive: i1.KbqLocaleOverridesDirective, inputs: ["kbqLocaleOverrides", "localeOverrides"] }], ngImport: i0, template: `
2034
2999
  @if (showSelectAll) {
2035
- <!-- Every read of selectAllState re-filters the rendered nodes against the data set, and
2036
- allOptionsSelected is that same walk asking whether the state is "checked" — one read
2037
- covers all four. -->
3000
+ <!-- Every read of selectAllState re-filters the rendered nodes against the data set, so the
3001
+ two bindings below share one through @let. The row's own aria-checked host binding walks
3002
+ it a second time: Ivy evaluates that binding after this template, and the option reads
3003
+ the state through KBQ_TREE_OPTION_PARENT_COMPONENT rather than from here. -->
2038
3004
  @let selectAllCheckboxState = selectAllState;
2039
3005
 
3006
+ <!-- role and aria-checked come from the option's own host bindings: a host binding runs
3007
+ after the parent template's, so an override here would be the one that loses. -->
2040
3008
  <kbq-tree-option
2041
3009
  class="kbq-tree-option_select-all"
2042
3010
  kbqTreeNodePadding
2043
3011
  [selectAllRow]="true"
2044
3012
  [selectable]="false"
2045
3013
  [class.kbq-selected]="selectAllCheckboxState === 'checked'"
2046
- [attr.role]="'checkbox'"
2047
- [attr.aria-checked]="
2048
- selectAllCheckboxState === 'indeterminate' ? 'mixed' : selectAllCheckboxState === 'checked'
2049
- "
2050
3014
  (click)="toggleSelectAll()"
2051
3015
  >
2052
3016
  <kbq-pseudo-checkbox [state]="selectAllCheckboxState" />
@@ -2054,9 +3018,9 @@ class KbqTreeSelection extends KbqTreeBase {
2054
3018
  </kbq-tree-option>
2055
3019
  }
2056
3020
  <ng-container kbqTreeNodeOutlet />
2057
- `, isInline: true, styles: [".kbq-tree-selection{display:block}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "directive", type: KbqTreeNodeOutlet, selector: "[kbqTreeNodeOutlet]" }, { kind: "component", type: KbqTreeOption, selector: "kbq-tree-option", inputs: ["checkboxThirdState", "disabled", "selectable", "selectAllRow", "showCheckbox"], outputs: ["onSelectionChange"], exportAs: ["kbqTreeOption"] }, { kind: "directive", type: KbqTreeNodePadding, selector: "[kbqTreeNodePadding]", inputs: ["kbqTreeNodePaddingIndent"], exportAs: ["kbqTreeNodePadding"] }, { kind: "component", type: KbqPseudoCheckbox, selector: "kbq-pseudo-checkbox", inputs: ["big", "state", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3021
+ `, isInline: true, styles: [".kbq-tree-selection{display:block}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "directive", type: KbqTreeNodeOutlet, selector: "[kbqTreeNodeOutlet]" }, { kind: "component", type: KbqTreeOption, selector: "kbq-tree-option", inputs: ["checkboxThirdState", "disabled", "selectable", "selectAllRow", "showCheckbox"], outputs: ["selectionChange", "onSelectionChange"], exportAs: ["kbqTreeOption"] }, { kind: "directive", type: KbqTreeNodePadding, selector: "[kbqTreeNodePadding]", inputs: ["kbqTreeNodePaddingIndent"], exportAs: ["kbqTreeNodePadding"] }, { kind: "component", type: KbqPseudoCheckbox, selector: "kbq-pseudo-checkbox", inputs: ["big", "state", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
2058
3022
  }
2059
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeSelection, decorators: [{
3023
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeSelection, decorators: [{
2060
3024
  type: Component,
2061
3025
  args: [{ selector: 'kbq-tree-selection', imports: [
2062
3026
  KbqTreeNodeOutlet,
@@ -2065,21 +3029,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
2065
3029
  KbqPseudoCheckbox
2066
3030
  ], template: `
2067
3031
  @if (showSelectAll) {
2068
- <!-- Every read of selectAllState re-filters the rendered nodes against the data set, and
2069
- allOptionsSelected is that same walk asking whether the state is "checked" — one read
2070
- covers all four. -->
3032
+ <!-- Every read of selectAllState re-filters the rendered nodes against the data set, so the
3033
+ two bindings below share one through @let. The row's own aria-checked host binding walks
3034
+ it a second time: Ivy evaluates that binding after this template, and the option reads
3035
+ the state through KBQ_TREE_OPTION_PARENT_COMPONENT rather than from here. -->
2071
3036
  @let selectAllCheckboxState = selectAllState;
2072
3037
 
3038
+ <!-- role and aria-checked come from the option's own host bindings: a host binding runs
3039
+ after the parent template's, so an override here would be the one that loses. -->
2073
3040
  <kbq-tree-option
2074
3041
  class="kbq-tree-option_select-all"
2075
3042
  kbqTreeNodePadding
2076
3043
  [selectAllRow]="true"
2077
3044
  [selectable]="false"
2078
3045
  [class.kbq-selected]="selectAllCheckboxState === 'checked'"
2079
- [attr.role]="'checkbox'"
2080
- [attr.aria-checked]="
2081
- selectAllCheckboxState === 'indeterminate' ? 'mixed' : selectAllCheckboxState === 'checked'
2082
- "
2083
3046
  (click)="toggleSelectAll()"
2084
3047
  >
2085
3048
  <kbq-pseudo-checkbox [state]="selectAllCheckboxState" />
@@ -2093,39 +3056,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
2093
3056
  { provide: KbqTreeBase, useExisting: KbqTreeSelection }
2094
3057
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
2095
3058
  class: 'kbq-tree-selection',
3059
+ role: 'tree',
2096
3060
  '[attr.tabindex]': 'tabIndex',
2097
3061
  '[attr.disabled]': 'disabled || null',
2098
- '(blur)': 'blur()',
3062
+ '[attr.aria-disabled]': 'disabled || null',
3063
+ '[attr.aria-multiselectable]': 'multiple || null',
3064
+ '[attr.aria-label]': 'resolvedAriaLabel',
3065
+ '[attr.aria-labelledby]': 'resolvedAriaLabelledby',
3066
+ // The active option takes real DOM focus (`KbqTreeOption.focus`) and is advertised here on top
3067
+ // of that, so an AT that follows either model reports the same row.
3068
+ '[attr.aria-activedescendant]': 'keyManager?.activeItem?.id',
2099
3069
  '(focus)': 'focus($event)',
2100
3070
  '(keydown)': 'onKeyDown($event)',
2101
3071
  '(window:resize)': 'updateScrollSize()'
2102
- }, exportAs: 'kbqTreeSelection', styles: [".kbq-tree-selection{display:block}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-content-gap-vertical: 0px;--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
2103
- }], ctorParameters: () => [], propDecorators: { nodeOutlet: [{
2104
- type: ViewChild,
2105
- args: [KbqTreeNodeOutlet, { static: true }]
2106
- }], selectAllOption: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqTreeOption), { isSignal: true }] }], unorderedOptions: [{
2107
- type: ContentChildren,
2108
- args: [KbqTreeOption]
2109
- }], treeControl: [{
2110
- type: Input
2111
- }], navigationChange: [{ type: i0.Output, args: ["navigationChange"] }], selectionChange: [{
2112
- type: Output
2113
- }], onSelectAll: [{ type: i0.Output, args: ["onSelectAll"] }], onCopy: [{
2114
- type: Output
2115
- }], autoSelect: [{
2116
- type: Input
2117
- }], noUnselectLast: [{
2118
- type: Input
2119
- }], selectAllToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllToggle", required: false }] }], selectAll: [{
2120
- type: Input,
2121
- args: [{ transform: booleanAttribute }]
2122
- }], disabled: [{
2123
- type: Input
2124
- }], tabIndex: [{
2125
- type: Input
2126
- }], selectAllHandler: [{
2127
- type: Input
2128
- }] } });
3072
+ }, hostDirectives: [
3073
+ { directive: KbqStateSaving, inputs: ['useStateSaving', 'stateSavingKey'] },
3074
+ { directive: KbqLocaleOverridesDirective, inputs: ['kbqLocaleOverrides: localeOverrides'] }
3075
+ ], exportAs: 'kbqTreeSelection', styles: [".kbq-tree-selection{display:block}.kbq-tree-selection:focus{outline:none}.kbq-tree-option{--kbq-option-background: var(--kbq-tree-default-container-background);background:var(--kbq-tree-default-container-background)}.kbq-tree-option .kbq-option-text{color:var(--kbq-tree-default-text-color)}.kbq-tree-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-default-action-button-color)}.kbq-tree-option .kbq-option-caption{color:var(--kbq-tree-default-caption-color)}.kbq-tree-option:not(.kbq-disabled):hover,.kbq-tree-option:not(.kbq-disabled).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused{--kbq-option-background: var(--kbq-tree-states-hover-container-background);background:var(--kbq-tree-states-hover-container-background)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-text{color:var(--kbq-tree-states-hover-text-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled):hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-hovered .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-action-button-focused .kbq-option-caption{color:var(--kbq-tree-states-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled):active,.kbq-tree-option:not(.kbq-disabled).kbq-active{--kbq-option-background: var(--kbq-tree-states-active-container-background);background:var(--kbq-tree-states-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected{--kbq-option-background: var(--kbq-tree-states-selected-container-background);background:var(--kbq-tree-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-text{color:var(--kbq-tree-states-selected-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected .kbq-option-caption{color:var(--kbq-tree-states-selected-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-states-selected-hover-container-background);background:var(--kbq-tree-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-text,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-text{color:var(--kbq-tree-states-selected-hover-text-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-action .kbq-icon.kbq-empty,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-selected-hover-action-button-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:hover .kbq-option-caption,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-hovered .kbq-option-caption{color:var(--kbq-tree-states-selected-hover-caption-color)}.kbq-tree-option:not(.kbq-disabled).kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-states-selected-active-container-background);background:var(--kbq-tree-states-selected-active-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected),.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected{--kbq-option-background: var(--kbq-tree-multiple-states-selected-container-background);background:var(--kbq-tree-multiple-states-selected-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):hover,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-hovered,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:hover,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-hovered{--kbq-option-background: var(--kbq-tree-multiple-states-selected-hover-container-background);background:var(--kbq-tree-multiple-states-selected-hover-container-background)}.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected):active,.kbq-tree-option:not(.kbq-disabled).kbq-checked:not(.kbq-selected).kbq-active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected:active,.kbq-tree-option:not(.kbq-disabled).kbq-tree-option_multiple.kbq-selected.kbq-active{--kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background);background:var(--kbq-tree-multiple-states-selected-active-container-background)}.kbq-tree-option.kbq-disabled{--kbq-option-background: var(--kbq-tree-states-disabled-container-background);background:var(--kbq-tree-states-disabled-container-background)}.kbq-tree-option.kbq-disabled .kbq-option-text{color:var(--kbq-tree-states-disabled-text-color)}.kbq-tree-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-tree-states-disabled-action-button-color)}.kbq-tree-option.kbq-disabled .kbq-option-caption{color:var(--kbq-tree-states-disabled-caption-color)}.kbq-tree-option.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-tree-node-toggle .kbq-icon){color:var(--kbq-states-icon-disabled)}.kbq-tree-selection.cdk-keyboard-focused .kbq-tree-option.kbq-focused:not(.kbq-action-button-focused){border-color:var(--kbq-tree-states-focused-focus-outline-color)}.kbq-tree-option{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-option-caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n", ".kbq-tree,.kbq-tree-selection{--kbq-tree-size-indent-level: var(--kbq-size-xxl);--kbq-tree-size-container-padding-right: var(--kbq-size-s);--kbq-tree-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-tree-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-tree-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-tree-size-text-padding-vertical: var(--kbq-size-3xs);--kbq-tree-option-border-radius: var(--kbq-size-border-radius);--kbq-tree-default-container-background: transparent;--kbq-tree-default-text-color: var(--kbq-foreground-contrast);--kbq-tree-default-icon-color: var(--kbq-icon-contrast);--kbq-tree-default-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-tree-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-tree-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-tree-states-selected-container-background: var(--kbq-background-theme-less);--kbq-tree-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-tree-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-tree-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-tree-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-tree-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-tree-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-tree-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-tree-states-selected-hover-tree-toggle-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-action-button-color: var(--kbq-icon-contrast-fade);--kbq-tree-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-tree-states-disabled-container-background: transparent;--kbq-tree-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-tree-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-tree-toggle-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-action-button-color: var(--kbq-states-icon-disabled);--kbq-tree-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
3076
+ }], ctorParameters: () => [], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], selectAllOption: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqTreeOption), { isSignal: true }] }], unorderedOptionsQuery: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => KbqTreeOption), { isSignal: true }] }], navigationChange: [{ type: i0.Output, args: ["navigationChange"] }], selectionChangeOutput: [{ type: i0.Output, args: ["selectionChange"] }], selectAllChange: [{ type: i0.Output, args: ["selectAllChange"] }], onSelectAll: [{ type: i0.Output, args: ["onSelectAll"] }], copyChangeOutput: [{ type: i0.Output, args: ["copyChange"] }], onCopyOutput: [{ type: i0.Output, args: ["onCopy"] }], autoSelectInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSelect", required: false }] }], multipleInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], noUnselectLastInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "noUnselectLast", required: false }] }], typeAheadInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "typeAhead", required: false }] }], selectAllToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllToggle", required: false }] }], selectAllInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAll", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], tabIndexInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], selectAllHandlerInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllHandler", required: false }] }] } });
2129
3077
 
2130
3078
  const KBQ_TREE_DIRECTIVES = [
2131
3079
  KbqTreeNodeOutlet,
@@ -2139,8 +3087,8 @@ const KBQ_TREE_DIRECTIVES = [
2139
3087
  KbqTreeNodeToggleDirective
2140
3088
  ];
2141
3089
  class KbqTreeModule {
2142
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2143
- /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeModule, imports: [KbqPseudoCheckboxModule,
3090
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
3091
+ /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeModule, imports: [KbqPseudoCheckboxModule,
2144
3092
  KbqIconModule,
2145
3093
  KbqActionContainer, KbqTreeNodeOutlet,
2146
3094
  KbqTreeNodeDef,
@@ -2159,13 +3107,13 @@ class KbqTreeModule {
2159
3107
  KbqTreeOption,
2160
3108
  KbqTreeNodeToggleComponent,
2161
3109
  KbqTreeNodeToggleDirective] }); }
2162
- /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeModule, providers: [{ provide: AsyncScheduler, useValue: asyncScheduler }], imports: [KbqPseudoCheckboxModule,
3110
+ /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeModule, providers: [{ provide: AsyncScheduler, useValue: asyncScheduler }], imports: [KbqPseudoCheckboxModule,
2163
3111
  KbqIconModule,
2164
3112
  KbqActionContainer, KbqTreeSelection,
2165
3113
  KbqTreeOption,
2166
3114
  KbqTreeNodeToggleComponent] }); }
2167
3115
  }
2168
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqTreeModule, decorators: [{
3116
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqTreeModule, decorators: [{
2169
3117
  type: NgModule,
2170
3118
  args: [{
2171
3119
  imports: [