@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,192 +1,255 @@
1
+ import { _IdGenerator, FocusMonitor, InputModalityDetector, CdkTrapFocus, ConfigurableFocusTrapFactory, FocusTrapFactory, FOCUS_TRAP_INERT_STRATEGY } from '@angular/cdk/a11y';
1
2
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
2
3
  import { Overlay } from '@angular/cdk/overlay';
3
- import { NgTemplateOutlet, AsyncPipe } from '@angular/common';
4
+ import { ScrollDispatcher, CdkScrollable } from '@angular/cdk/scrolling';
5
+ import { NgTemplateOutlet, DOCUMENT } from '@angular/common';
4
6
  import * as i0 from '@angular/core';
5
- import { inject, EventEmitter, Injectable, TemplateRef, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, InjectionToken, ChangeDetectorRef, viewChild, booleanAttribute, numberAttribute, Output, Directive, NgModule } from '@angular/core';
6
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
+ import { inject, signal, computed, untracked, Injectable, InjectionToken, input, TemplateRef, ViewEncapsulation, ChangeDetectionStrategy, Component, RendererStyleFlags2, Injector, NgZone, viewChild, afterNextRender, forwardRef, numberAttribute, EventEmitter, booleanAttribute, Directive, NgModule } from '@angular/core';
8
+ import { takeUntilDestroyed, outputFromObservable } from '@angular/core/rxjs-interop';
7
9
  import { KbqBadgeModule } from '@koobiq/components/badge';
8
10
  import * as i3$1 from '@koobiq/components/button';
9
11
  import { KbqButtonModule } from '@koobiq/components/button';
10
- import * as i1$1 from '@koobiq/components/core';
11
- import { KbqAnimationDurations, DateAdapter, DateFormatter, KbqReadStateDirective, PopUpPlacements, ThemePalette, ruRULocaleData, KbqPopUp, KBQ_LOCALE_SERVICE, applyPopupMargins, KbqOverflowShadowContainer, KbqOverflowShadowTop, KbqOverflowShadowBottom, KbqPopUpTrigger, PopUpTriggers, PopUpSizes, POSITION_TO_CSS_MAP, kbqSiblingPopupProvider, EmptyFocusTrapStrategy } from '@koobiq/components/core';
12
+ import * as i1 from '@koobiq/components/core';
13
+ import { DateAdapter, DateFormatter, KBQ_LOCALE_SERVICE, ruRULocaleData, kbqLocaleConfigurationOverrideProvider, KbqReadStateDirective, PopUpPlacements, KbqPopUp, KbqLocaleOverridesDirective, KBQ_A11Y_LOCALE_CONFIGURATION, applyPopupMargins, KbqOverflowShadowContainer, KbqOverflowShadowTop, KbqOverflowShadowBottom, EmptyFocusTrapStrategy, KbqPopUpTrigger, PopUpTriggers, POSITION_TO_CSS_MAP, PopUpSizes, kbqSiblingPopupProvider } from '@koobiq/components/core';
12
14
  import * as i4 from '@koobiq/components/divider';
13
15
  import { KbqDividerModule } from '@koobiq/components/divider';
14
16
  import * as i5 from '@koobiq/components/dropdown';
15
17
  import { KbqDropdownModule } from '@koobiq/components/dropdown';
16
- import * as i1 from '@koobiq/components/icon';
18
+ import * as i2 from '@koobiq/components/icon';
17
19
  import { KbqIconModule } from '@koobiq/components/icon';
18
20
  import * as i7 from '@koobiq/components/loader-overlay';
19
21
  import { KbqLoaderOverlayModule } from '@koobiq/components/loader-overlay';
20
22
  import * as i8 from '@koobiq/components/progress-spinner';
21
23
  import { KbqProgressSpinnerModule } from '@koobiq/components/progress-spinner';
22
- import * as i2 from '@koobiq/components/scrollbar';
23
- import { KbqScrollbar, KbqScrollbarModule } from '@koobiq/components/scrollbar';
24
+ import { KbqScrollbarViewport } from '@koobiq/components/scrollbar';
24
25
  import * as i6 from '@koobiq/components/tooltip';
25
- import { KbqTooltipTrigger, KbqToolTipModule } from '@koobiq/components/tooltip';
26
- import { combineLatestWith, BehaviorSubject, merge, Subject } from 'rxjs';
27
- import { map, filter, auditTime, distinctUntilChanged, pairwise } from 'rxjs/operators';
28
- import { trigger, state, style, transition, animate } from '@angular/animations';
29
- import { KbqToastService } from '@koobiq/components/toast';
26
+ import { KbqToolTipModule } from '@koobiq/components/tooltip';
27
+ import { Subject, BehaviorSubject, merge } from 'rxjs';
28
+ import { skip, map, filter, auditTime, distinctUntilChanged } from 'rxjs/operators';
29
+ import { KbqToastService, KbqToastStyle } from '@koobiq/components/toast';
30
30
  import * as i3 from '@koobiq/components/title';
31
31
  import { KbqTitleModule } from '@koobiq/components/title';
32
- import { ConfigurableFocusTrapFactory, FocusTrapFactory, FOCUS_TRAP_INERT_STRATEGY } from '@angular/cdk/a11y';
33
-
34
- /** @docs-private */
35
- const KbqNotificationCenterAnimations = {
36
- /** Animation that transitions a tooltip in and out. */
37
- state: trigger('state', [
38
- state('initial', style({
39
- opacity: 0,
40
- transform: 'scale(1, 0.8)'
41
- })),
42
- transition('* => visible', animate('120ms cubic-bezier(0, 0, 0.2, 1)', style({
43
- opacity: 1,
44
- transform: 'scale(1, 1)'
45
- }))),
46
- transition('* => hidden', animate(`${KbqAnimationDurations.Rapid} linear`, style({ opacity: 0 })))
47
- ])
48
- };
49
32
 
33
+ /** Number of unread notifications above which the trigger counter switches to `"99+"`. */
50
34
  const maxUnreadItemsLength = 99;
35
+ /** Suffix appended to a generated id so items ingested within the same millisecond stay distinct. */
36
+ let uniqueIdCounter = 0;
37
+ /** State and commands of the notification center: the list itself, its modes, and the removal events. */
51
38
  class KbqNotificationCenterService {
52
- /** Notification items */
39
+ /**
40
+ * The notifications, as a snapshot: reading them does not make an `effect()` or a `computed()` depend on the
41
+ * list, so an effect can read and reassign it. Follow `changes` to react to updates.
42
+ */
53
43
  get items() {
54
- return this.originalItems.value;
44
+ return this.currentItems();
55
45
  }
56
46
  set items(values) {
57
- this.originalItems.next(this.setReadState(this.setIds(values)));
58
- }
59
- /** Number of unread notifications */
60
- get unreadItemsCounter() {
61
- return this.originalItems.pipe(map((items) => items.filter((item) => item.read === false).length)).pipe(combineLatestWith(this.onRead), map(([value]) => {
62
- if (value < maxUnreadItemsLength) {
63
- return value ? value.toString() : '';
64
- }
65
- else {
66
- return `${maxUnreadItemsLength}+`;
67
- }
68
- }));
47
+ this.setItems(this.setReadState(this.setIds(values)));
69
48
  }
70
- /** true if there are no notifications. */
49
+ /** Whether there are no notifications. A snapshot, like `items`. */
71
50
  get isEmpty() {
72
- return this.originalItems.value.length === 0;
51
+ return this.currentItems().length === 0;
73
52
  }
74
53
  constructor() {
75
- /** @docs-private */
76
54
  this.adapter = inject(DateAdapter);
77
- /** @docs-private */
78
55
  this.formatter = inject(DateFormatter);
79
- /** @docs-private */
80
56
  this.toastService = inject(KbqToastService);
57
+ this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
58
+ /** Parsed `date` per item. Keyed by the item itself, so no consumer-owned object is written to. */
59
+ this.parsedDates = new WeakMap();
60
+ this._silentMode = signal(false, ...(ngDevMode ? [{ debugName: "_silentMode" }] : /* istanbul ignore next */ []));
61
+ this._loadingMode = signal(false, ...(ngDevMode ? [{ debugName: "_loadingMode" }] : /* istanbul ignore next */ []));
62
+ this._errorMode = signal(false, ...(ngDevMode ? [{ debugName: "_errorMode" }] : /* istanbul ignore next */ []));
63
+ this._loadingMore = signal(false, ...(ngDevMode ? [{ debugName: "_loadingMore" }] : /* istanbul ignore next */ []));
64
+ this._loadMoreErrorMode = signal(false, ...(ngDevMode ? [{ debugName: "_loadMoreErrorMode" }] : /* istanbul ignore next */ []));
65
+ this._hasMore = signal(true, ...(ngDevMode ? [{ debugName: "_hasMore" }] : /* istanbul ignore next */ []));
66
+ this.originalItems = signal([], ...(ngDevMode ? [{ debugName: "originalItems" }] : /* istanbul ignore next */ []));
67
+ /**
68
+ * Bumped on every `onRead` emission: `read` is flipped in place on the consumer's object, so the list
69
+ * itself does not change when a notification is read.
70
+ */
71
+ this.readVersion = signal(0, ...(ngDevMode ? [{ debugName: "readVersion" }] : /* istanbul ignore next */ []));
72
+ /**
73
+ * Read state of each notification a view follows, as last reported by `onRead` or a list update. One per
74
+ * item, so that reading a notification refreshes its own row only.
75
+ */
76
+ this.readStates = new WeakMap();
77
+ /** Pinged by every state setter; `changes` merges it with `onRead`. */
78
+ this.stateChanges = new Subject();
81
79
  /** @docs-private */
82
- this.silentMode = new BehaviorSubject(false);
80
+ this.silentMode = this._silentMode.asReadonly();
83
81
  /** @docs-private */
84
- this.loadingMode = new BehaviorSubject(false);
82
+ this.loadingMode = this._loadingMode.asReadonly();
85
83
  /** @docs-private */
86
- this.errorMode = new BehaviorSubject(false);
84
+ this.errorMode = this._errorMode.asReadonly();
87
85
  /**
88
86
  * Whether the bottom "load more" spinner is shown while the next page is being loaded.
89
87
  * Note: this is the infinite-scroll indicator and is distinct from `loadingMode`,
90
- * which renders the full-screen loader instead of the list.
88
+ * which renders the full-screen loader instead of the list. Set it with `setLoadingMore()`.
91
89
  */
92
- this.loadingMore = new BehaviorSubject(false);
90
+ this.loadingMore = this._loadingMore.asReadonly();
93
91
  /**
94
92
  * Whether the bottom "load more" error row (with a retry button) is shown.
95
93
  * Distinct from `errorMode`, which replaces the whole list with the full-screen error state.
94
+ * Set it with `setLoadMoreErrorMode()`.
96
95
  */
97
- this.loadMoreErrorMode = new BehaviorSubject(false);
96
+ this.loadMoreErrorMode = this._loadMoreErrorMode.asReadonly();
98
97
  /**
99
98
  * Whether there are more notifications to load. While `true`, scrolling to the bottom
100
- * emits `onNextPage`; set it to `false` to stop further infinite-scroll requests.
99
+ * emits `onNextPage`; set it to `false` with `setHasMore()` to stop further infinite-scroll requests.
101
100
  */
102
- this.hasMore = new BehaviorSubject(true);
103
- /** @docs-private */
101
+ this.hasMore = this._hasMore.asReadonly();
102
+ /** Emits a notification the moment it flips from unread to read. */
104
103
  this.onRead = new BehaviorSubject(null);
105
104
  /** Triggers an event when the user presses the reload button. */
106
- this.onReload = new EventEmitter();
105
+ this.onReload = new Subject();
107
106
  /** Triggers an event when the list is scrolled to the bottom and the next page should be loaded. */
108
- this.onNextPage = new EventEmitter();
107
+ this.onNextPage = new Subject();
109
108
  /** Triggers an event when an item, a group, or all notifications are removed. */
110
- this.onDelete = new EventEmitter();
111
- this.originalItems = new BehaviorSubject([]);
109
+ this.onDelete = new Subject();
112
110
  /**
113
111
  * Grouped notifications, always ordered from newest to oldest: day groups are sorted by date
114
- * descending, and notifications within each day are sorted by date descending.
112
+ * descending, and notifications within each day are sorted by date descending. Notifications whose
113
+ * `date` the adapter cannot parse keep their raw value as a group heading and sort last.
114
+ *
115
115
  * @docs-private
116
116
  */
117
- this.groupedItems = this.originalItems.pipe(map((items) => {
117
+ this.groupedItems = computed(() => {
118
+ // The day headings are localized, so a runtime `setLocale()` has to rebuild them.
119
+ this.localeService?.localeId();
118
120
  const result = {};
119
- items.forEach((item) => this.makeGroup(item, result));
121
+ this.originalItems().forEach((item) => this.makeGroup(item, result));
120
122
  const groups = Object.values(result);
121
123
  // Newest notifications first within each day.
122
124
  groups.forEach((group) => group.items.sort(this.compareByDateDesc));
123
125
  // Newest day first.
124
126
  return groups.sort((a, b) => this.compareByDateDesc(a.items[0], b.items[0]));
125
- }));
126
- /** Emits an event whenever the changes. */
127
- this.changes = merge(this.silentMode, this.loadingMode, this.errorMode, this.loadingMore, this.loadMoreErrorMode, this.hasMore, this.originalItems, this.onRead);
127
+ }, ...(ngDevMode ? [{ debugName: "groupedItems" }] : /* istanbul ignore next */ []));
128
+ /**
129
+ * Emits whenever any part of the center's state changes. Carries no payload — it is a ping — and
130
+ * emits nothing on subscription.
131
+ */
132
+ this.changes = merge(this.stateChanges,
133
+ // The replayed current value is not a change.
134
+ this.onRead.pipe(skip(1))).pipe(map(() => undefined));
135
+ /**
136
+ * Number of unread notifications, formatted for the trigger badge: empty while nothing is unread,
137
+ * and `"99+"` above `maxUnreadItemsLength`.
138
+ */
139
+ this.unreadItemsCounter = computed(() => {
140
+ this.readVersion();
141
+ const value = this.originalItems().filter((item) => item.read === false).length;
142
+ if (value > maxUnreadItemsLength) {
143
+ return `${maxUnreadItemsLength}+`;
144
+ }
145
+ return value ? value.toString() : '';
146
+ }, ...(ngDevMode ? [{ debugName: "unreadItemsCounter" }] : /* istanbul ignore next */ []));
147
+ /**
148
+ * Whether there are no notifications, for the center's own view to follow.
149
+ *
150
+ * @internal
151
+ */
152
+ this.empty = computed(() => this.originalItems().length === 0, ...(ngDevMode ? [{ debugName: "empty" }] : /* istanbul ignore next */ []));
128
153
  this.makeGroup = (item, groups) => {
129
- const parsedDate = this.adapter.parse(item.date, '');
130
- const groupId = this.adapter.format(parsedDate, 'yyyyMMdd');
131
- const groupTitle = this.formatter.absoluteLongDate(parsedDate);
154
+ const { groupId, source, value } = this.getParsedDate(item);
132
155
  if (groups[groupId]) {
133
156
  groups[groupId].items.push(item);
134
157
  }
135
158
  else {
136
159
  groups[groupId] = {
137
- title: groupTitle,
160
+ id: groupId,
161
+ // Formatted on every recomputation rather than cached with the parsed value: the heading is
162
+ // localized, and a cached one would leave the group in the locale it was built in while
163
+ // a group created afterwards renders in the current one.
164
+ title: value === null ? source : this.formatter.absoluteLongDate(value),
138
165
  items: [item]
139
166
  };
140
167
  }
141
168
  };
142
- /** Compares two notifications by date so the newest comes first. */
169
+ /** Compares two notifications by date so the newest comes first; unparsable dates sort last. */
143
170
  this.compareByDateDesc = (a, b) => {
144
- const parsedA = this.adapter.parse(a.date, '');
145
- const parsedB = this.adapter.parse(b.date, '');
146
- if (!parsedA || !parsedB) {
147
- return 0;
171
+ const parsedA = this.getParsedDate(a).value;
172
+ const parsedB = this.getParsedDate(b).value;
173
+ if (parsedA === null || parsedB === null) {
174
+ return Number(parsedA === null) - Number(parsedB === null);
148
175
  }
149
176
  return this.adapter.compareDateTime(parsedB, parsedA);
150
177
  };
178
+ this.onRead.pipe(takeUntilDestroyed()).subscribe((item) => {
179
+ this.readVersion.update((version) => version + 1);
180
+ if (item)
181
+ this.syncReadState(item);
182
+ });
151
183
  this.toastService?.read.pipe(takeUntilDestroyed()).subscribe((toastData) => {
152
- const item = this.items.find((item) => item.id === toastData?.id);
184
+ const item = this.currentItems().find((item) => item.id === toastData?.id);
153
185
  if (item && !item.read) {
154
186
  item.read = true;
155
- this.onRead.next(toastData);
187
+ this.onRead.next(item);
156
188
  }
157
189
  });
158
190
  }
191
+ /**
192
+ * Whether a notification is read, for a view to follow: `read` is flipped in place on the consumer's object,
193
+ * so a view handed that object is not told.
194
+ *
195
+ * @internal
196
+ */
197
+ isRead(item) {
198
+ let state = this.readStates.get(item);
199
+ if (!state) {
200
+ state = signal(!!item.read);
201
+ this.readStates.set(item, state);
202
+ }
203
+ // Followed for the dependency only: a view rendered anew shows the object as it is, even after a flip
204
+ // nothing reported.
205
+ state();
206
+ return !!item.read;
207
+ }
159
208
  /** Set silent mode */
160
209
  setSilentMode(value) {
161
- this.silentMode.next(value);
210
+ this._silentMode.set(value);
211
+ this.notify();
162
212
  }
163
213
  /** Set loading mode */
164
214
  setLoadingMode(value) {
165
- this.loadingMode.next(value);
215
+ this._loadingMode.set(value);
216
+ this.notify();
166
217
  }
167
218
  /** Set error mode */
168
219
  setErrorMode(value) {
169
- this.errorMode.next(value);
220
+ this._errorMode.set(value);
221
+ this.notify();
170
222
  }
171
223
  /** Set the bottom "load more" spinner visibility. */
172
224
  setLoadingMore(value) {
173
- this.loadingMore.next(value);
225
+ this._loadingMore.set(value);
226
+ this.notify();
174
227
  }
175
228
  /** Set the bottom "load more" error state visibility. */
176
229
  setLoadMoreErrorMode(value) {
177
- this.loadMoreErrorMode.next(value);
230
+ this._loadMoreErrorMode.set(value);
231
+ this.notify();
178
232
  }
179
233
  /** Set whether there are more notifications to load via infinite scroll. */
180
234
  setHasMore(value) {
181
- this.hasMore.next(value);
235
+ this._hasMore.set(value);
236
+ this.notify();
182
237
  }
183
- /** Push new notification item in center */
238
+ /**
239
+ * Adds a notification to the list and, unless silent mode is on, shows it as a toast.
240
+ * Re-pushing the very same notification object is a no-op: a duplicate would show a second toast
241
+ * and produce a colliding list key. A different notification carrying an `id` the list already
242
+ * uses is added under a freshly generated one instead of being dropped.
243
+ */
184
244
  push(item) {
185
- this.setReadState(this.setIds([item]));
186
- if (!this.silentMode.value) {
245
+ if (this.currentItems().includes(item)) {
246
+ return;
247
+ }
248
+ this.setReadState(this.setIds([item], this.currentItems()));
249
+ if (!untracked(this.silentMode)) {
187
250
  item.toastId = this.toastService.show(item).id;
188
251
  }
189
- return this.originalItems.next([...this.originalItems.value, item]);
252
+ this.setItems([...this.currentItems(), item]);
190
253
  }
191
254
  /** Hides the toast that corresponds to the given notification item. */
192
255
  hideToast(item) {
@@ -196,67 +259,188 @@ class KbqNotificationCenterService {
196
259
  this.toastService.hide(item.toastId);
197
260
  item.toastId = undefined;
198
261
  }
199
- /** Remove notification item */
262
+ /** Removes a notification. Removing one that is not in the list is a no-op and emits nothing. */
200
263
  remove(removedItem) {
264
+ if (!this.currentItems().includes(removedItem)) {
265
+ return;
266
+ }
201
267
  this.hideToast(removedItem);
202
- this.originalItems.next(this.originalItems.value.filter((item) => removedItem !== item));
203
- this.onDelete.emit({ type: 'item', items: [removedItem] });
268
+ this.setItems(this.currentItems().filter((item) => removedItem !== item));
269
+ untracked(() => this.onDelete.next({ type: 'item', items: [removedItem] }));
204
270
  }
205
- /** Remove group of notification items */
271
+ /**
272
+ * Removes a whole day group. Only the notifications that are actually in the list are removed and
273
+ * reported; a group holding none of them — a stale reference kept from an earlier `groupedItems`
274
+ * value — is a no-op and emits nothing.
275
+ */
206
276
  removeGroup(group) {
207
- group.items.forEach((item) => this.hideToast(item));
208
- this.originalItems.next(this.originalItems.value.filter((item) => !group.items.includes(item)));
209
- this.onDelete.emit({ type: 'group', items: [...group.items] });
277
+ const removedItems = group.items.filter((item) => this.currentItems().includes(item));
278
+ if (removedItems.length === 0) {
279
+ return;
280
+ }
281
+ removedItems.forEach((item) => this.hideToast(item));
282
+ this.setItems(this.currentItems().filter((item) => !removedItems.includes(item)));
283
+ untracked(() => this.onDelete.next({ type: 'group', items: removedItems }));
210
284
  }
211
- /** Remove all notification items */
285
+ /** Removes every notification. Removing from an already empty list is a no-op and emits nothing. */
212
286
  removeAll() {
213
- const items = this.originalItems.value;
287
+ const items = this.currentItems();
288
+ if (items.length === 0) {
289
+ return;
290
+ }
214
291
  items.forEach((item) => this.hideToast(item));
215
- this.originalItems.next([]);
216
- this.onDelete.emit({ type: 'all', items });
292
+ this.setItems([]);
293
+ untracked(() => this.onDelete.next({ type: 'all', items }));
217
294
  }
218
- setIds(items) {
219
- items.forEach((item) => (item.id = item.id ?? new Date().getTime().toString()));
295
+ /**
296
+ * The list as the commands see it: untracked, so a command called from a reactive context does not
297
+ * make it depend on the list it is about to write.
298
+ */
299
+ currentItems() {
300
+ return untracked(this.originalItems);
301
+ }
302
+ setItems(items) {
303
+ this.originalItems.set(items);
304
+ // The list may be handed back with `read` flipped in place.
305
+ items.forEach((item) => this.syncReadState(item));
306
+ this.notify();
307
+ }
308
+ /** Tells the view of `item` its read state, which refreshes it only when the state has changed. */
309
+ syncReadState(item) {
310
+ this.readStates.get(item)?.set(!!item.read);
311
+ }
312
+ /**
313
+ * `changes` subscribers run synchronously, inside whatever called the command: untracked, so a command called
314
+ * from an `effect()` does not make it depend on the signals they read.
315
+ */
316
+ notify() {
317
+ untracked(() => this.stateChanges.next());
318
+ }
319
+ /**
320
+ * Parses a notification's `date` once and remembers the result.
321
+ *
322
+ * `DateAdapter.parse` returns `null` for anything it does not recognise, and both the Luxon and the
323
+ * Moment adapter throw when a `null` is passed on to `format`, so every derived value is resolved
324
+ * here behind a single validity check.
325
+ */
326
+ getParsedDate(item) {
327
+ const source = String(item.date ?? '');
328
+ const cached = this.parsedDates.get(item);
329
+ if (cached?.source === source) {
330
+ return cached;
331
+ }
332
+ const parsed = this.adapter.parse(source, '');
333
+ const isValid = parsed !== null && this.adapter.isValid(parsed);
334
+ const entry = isValid
335
+ ? {
336
+ source,
337
+ // Built from adapter accessors instead of a format string: format tokens are not
338
+ // portable, e.g. `'yyyyMMdd'` keys every day of a week identically under Moment.
339
+ groupId: `date:${this.adapter.getYear(parsed)}-${this.adapter.getMonth(parsed)}-${this.adapter.getDate(parsed)}`,
340
+ value: parsed
341
+ }
342
+ : { source, groupId: `raw:${source}`, value: null };
343
+ this.parsedDates.set(item, entry);
344
+ return entry;
345
+ }
346
+ /**
347
+ * Fills in the missing ids of `items` and re-keys the ones already taken, so that every ingested
348
+ * notification ends up with an id of its own.
349
+ *
350
+ * @param existing notifications `items` is joining, whose ids are therefore taken as well; empty
351
+ * when the list is being replaced wholesale.
352
+ */
353
+ setIds(items, existing = []) {
354
+ const takenIds = new Set(existing.map((item) => item.id));
355
+ items.forEach((item) => {
356
+ // A supplied id is taken on trust only while it is free: a backend that repeats one across
357
+ // pages would otherwise collide on the list's track key and on the toast-to-item lookup in
358
+ // the constructor. `Date.now()` alone collides for every item ingested in the same tick.
359
+ if (item.id === undefined || takenIds.has(item.id)) {
360
+ item.id = `${Date.now()}-${uniqueIdCounter++}`;
361
+ }
362
+ takenIds.add(item.id);
363
+ });
220
364
  return items;
221
365
  }
222
366
  setReadState(items) {
223
367
  items.forEach((item) => (item.read = item.read ?? false));
224
368
  return items;
225
369
  }
226
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
227
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterService, providedIn: 'root' }); }
370
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
371
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterService, providedIn: 'root' }); }
228
372
  }
229
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterService, decorators: [{
373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterService, decorators: [{
230
374
  type: Injectable,
231
375
  args: [{ providedIn: 'root' }]
232
376
  }], ctorParameters: () => [] });
233
377
 
234
- let id = 0;
378
+ /** Default configuration of notification-center. */
379
+ const KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION = ruRULocaleData.notificationCenter;
380
+ /** Injection Token for providing configuration of notification-center. */
381
+ const KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION = new InjectionToken('KbqNotificationCenterLocaleConfiguration', {
382
+ factory: () => KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION
383
+ });
384
+ /**
385
+ * Utility provider for `KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION`. Only the strings you pass are overridden; the
386
+ * rest keep following the active locale.
387
+ */
388
+ const kbqNotificationCenterLocaleConfigurationProvider = (configuration) => kbqLocaleConfigurationOverrideProvider('notificationCenter', configuration);
389
+ /** @deprecated Use {@link KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION}. Will be removed in 22.0.0. */
390
+ const KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION = KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION;
391
+ /** @deprecated Use {@link KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION}. Will be removed in 22.0.0. */
392
+ const KBQ_NOTIFICATION_CENTER_CONFIGURATION = KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION;
393
+ /**
394
+ * Narrow contract a `kbq-notification-item` consumes from the panel that renders it, instead of
395
+ * injecting the panel component itself.
396
+ */
397
+ const KBQ_NOTIFICATION_CENTER_PANEL = new InjectionToken('KbqNotificationCenterPanel');
398
+
235
399
  /** @docs-private */
236
400
  class KbqNotificationItemComponent {
401
+ // `KbqToastService` used to write these defaults into the item handed to `push()`; it now leaves the
402
+ // caller's object untouched, so the row resolves them itself instead of rendering an unstyled,
403
+ // icon-less notification.
237
404
  get style() {
238
- return {
239
- [`kbq-notification-item_${this.data.style}`]: !!this.data.style
240
- };
405
+ return this.data.style || KbqToastStyle.Contrast;
406
+ }
407
+ get icon() {
408
+ return this.data.icon ?? true;
409
+ }
410
+ get read() {
411
+ return this.service.isRead(this.data);
241
412
  }
242
- // TODO: Skipped for migration because:
243
- // Accessor inputs cannot be migrated as they are too complex.
244
413
  get data() {
245
414
  return this._data;
246
415
  }
247
416
  set data(value) {
248
417
  this._data = value;
249
- this.time = this.adapter.format(this.adapter.parse(value.date, ''), 'HH:mm');
418
+ this.context = { $implicit: value };
419
+ // Through `style`, so an item pushed without one still gets the contrast modifier rather than
420
+ // no class at all.
421
+ this.styleClass = `kbq-notification-item_${this.style}`;
422
+ // `DateAdapter.parse` returns null for anything it does not recognise, and every adapter throws
423
+ // when that null reaches `format` — which would take the whole panel down with it.
424
+ const parsed = this.adapter.parse(value.date, '');
425
+ this.time = parsed !== null && this.adapter.isValid(parsed) ? this.adapter.format(parsed, 'HH:mm') : '';
426
+ }
427
+ ngOnChanges(changes) {
428
+ // A bound input is handed to its member; unbound, it leaves what code wrote.
429
+ if (changes['dataInput']) {
430
+ const data = this.dataInput();
431
+ if (data !== undefined)
432
+ this.data = data;
433
+ }
250
434
  }
251
435
  constructor() {
252
436
  this.adapter = inject(DateAdapter);
253
437
  this.service = inject(KbqNotificationCenterService);
254
438
  this.readStateDirective = inject(KbqReadStateDirective, { host: true });
255
- this.center = inject(KbqNotificationCenterComponent, { host: true });
256
- this.popUpPlacements = PopUpPlacements;
257
- this.themePalette = ThemePalette;
258
- this.id = id++;
259
- this.$implicit = this;
439
+ this.panel = inject(KBQ_NOTIFICATION_CENTER_PANEL);
440
+ /** Style modifier class of the host, recomputed with `data` instead of allocated on every check. */
441
+ this.styleClass = '';
442
+ /** @docs-private */
443
+ this.dataInput = input(undefined, { ...(ngDevMode ? { debugName: "dataInput" } : /* istanbul ignore next */ {}), alias: 'data' });
260
444
  this.readStateDirective.read
261
445
  .pipe(filter((value) => value), takeUntilDestroyed())
262
446
  .subscribe(() => {
@@ -267,30 +451,33 @@ class KbqNotificationItemComponent {
267
451
  this.service.onRead.next(this.data);
268
452
  });
269
453
  }
454
+ /** Removes this notification, keeping keyboard focus inside the panel once the button unmounts. */
455
+ remove() {
456
+ this.panel.restoreFocusAfterRemove();
457
+ this.service.remove(this.data);
458
+ }
270
459
  isTemplateRef(value) {
271
460
  return value instanceof TemplateRef;
272
461
  }
273
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
274
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqNotificationItemComponent, isStandalone: true, selector: "kbq-notification-item", inputs: { data: "data" }, host: { attributes: { "data-testid": "kbq-notification-item" }, properties: { "class": "style" }, classAttribute: "kbq-notification-item" }, hostDirectives: [{ directive: i1$1.KbqReadStateDirective }], ngImport: i0, template: "@if (data.icon) {\n <div class=\"kbq-notification-item__icon-container layout-row layout-align-start-start\">\n @if (data.icon === true) {\n @switch (data.style) {\n @case ('contrast') {\n <i\n kbq-icon=\"kbq-circle-info_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('success') {\n <i\n kbq-icon=\"kbq-circle-check_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('warning') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('error') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n }\n } @else if (isTemplateRef(data.icon)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.icon)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n }\n </div>\n}\n\n<div class=\"kbq-notification-item__container\">\n @if (data.title) {\n <div\n kbq-title\n class=\"kbq-notification-item__title\"\n [class.kbq-notification-item__title_with-content]=\"data.caption || data.content\"\n >\n @if (isTemplateRef(data.title)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.title)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n <p data-testid=\"kbq-notification-item-title\">{{ data.title }}</p>\n }\n\n <div\n class=\"kbq-notification-item-time\"\n data-testid=\"kbq-notification-item-time\"\n [class.kbq-notification-item-time_read]=\"data.read\"\n >\n <div class=\"kbq-notification-item-time__value\" data-testid=\"kbq-notification-item-time-value\">\n {{ time }}\n </div>\n <i class=\"kbq-notification-item-time__state\" kbq-icon=\"kbq-circle-xs_16\" [color]=\"'theme'\"></i>\n </div>\n </div>\n }\n\n @if (data.caption) {\n <div\n kbq-title\n [class.kbq-notification-item__text]=\"data.title\"\n [class.kbq-notification-item__title]=\"!data.title\"\n >\n @if (isTemplateRef(data.caption)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.caption)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.caption }}\n }\n </div>\n }\n\n @if (data.content) {\n <div class=\"kbq-notification-item__content\">\n @if (isTemplateRef(data.content)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.content)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.content }}\n }\n </div>\n }\n\n @if (data.actions) {\n <div class=\"kbq-notification-item__actions\">\n @if (isTemplateRef(data.actions)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.actions)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.actions }}\n }\n </div>\n }\n</div>\n\n<button\n kbq-button\n class=\"kbq-notification-item__remove-button\"\n data-testid=\"kbq-notification-item-remove-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltipArrow]=\"false\"\n [kbqTooltip]=\"center.localeData.remove\"\n [kbqPlacement]=\"popUpPlacements.Right\"\n (click)=\"service.remove(data)\"\n>\n <i kbq-icon=\"kbq-trash_16\"></i>\n</button>\n", styles: [".kbq-notification-item{display:flex;box-sizing:border-box;position:relative;border-radius:var(--kbq-size-s);height:auto;margin-left:var(--kbq-size-m);margin-right:var(--kbq-size-m)}.kbq-notification-item:hover .kbq-notification-item-time,.kbq-notification-item:focus-within .kbq-notification-item-time{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button,.kbq-notification-item:focus-within .kbq-notification-item__remove-button{display:block}.kbq-notification-item__icon-container{flex-shrink:0;box-sizing:content-box;width:var(--kbq-size-l);max-width:var(--kbq-size-l);height:var(--kbq-size-l);max-height:var(--kbq-size-l);margin-right:var(--kbq-size-s);padding-left:var(--kbq-size-m);padding-top:14px}.kbq-notification-item__container{display:flex;flex-direction:column;flex:1;padding-top:var(--kbq-size-m);padding-right:var(--kbq-size-s);padding-bottom:var(--kbq-size-m);overflow:hidden}.kbq-notification-item__title{display:flex;flex-direction:row;justify-content:space-between;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title>p{margin:0;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title.kbq-notification-item__title_with-content{margin-bottom:var(--kbq-size-xxs)}.kbq-notification-item-time{display:flex;flex-direction:row;height:var(--kbq-size-xl);align-items:center;padding-left:22px}.kbq-notification-item-time .kbq-notification-item-time__value{margin-right:var(--kbq-size-3xs)}.kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__state{visibility:hidden;order:-1}.kbq-notification-item__text{display:flex;flex:1;align-items:center}.kbq-notification-item__content{display:flex;flex-direction:column;white-space:pre-wrap}.kbq-notification-item__actions{display:flex;padding-top:var(--kbq-size-s);gap:var(--kbq-size-m)}.kbq-notification-item__remove-button{position:absolute;top:var(--kbq-size-xs);right:var(--kbq-size-s);display:none}.kbq-notification-item{background:var(--kbq-background-card)}.kbq-notification-item .kbq-notification-item__title{color:var(--kbq-foreground-contrast)}.kbq-notification-item .kbq-notification-item__text,.kbq-notification-item .kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__value{color:var(--kbq-foreground-contrast-secondary)}.kbq-notification-item:hover{background:var(--kbq-states-background-transparent-hover)}.kbq-notification-item{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-notification-item .kbq-notification-item-time{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"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i1.KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }, { kind: "ngmodule", type: KbqTitleModule }, { kind: "directive", type: i3.KbqTitleDirective, selector: "[kbq-title]", inputs: ["kbq-title"], exportAs: ["kbqTitle"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "directive", type: KbqTooltipTrigger, selector: "[kbqTooltip]", inputs: ["kbqTooltipScrollStrategy", "forDisabledComponent", "ignoreTooltipPointerEvents", "kbqTooltipSingleInstance", "hideWithTimeout", "kbqVisible", "kbqPlacement", "kbqRelativeToPointer", "kbqPlacementPriority", "kbqTooltip", "kbqTooltipDisabled", "kbqEnterDelay", "kbqLeaveDelay", "kbqTrigger", "kbqTooltipClass", "kbqTooltipContext", "kbqTooltipColor", "kbqTooltipArrow", "kbqTooltipOffset", "kbqTooltipModifier", "kbqTooltipHeader"], outputs: ["kbqPlacementChange", "kbqVisibleChange"], exportAs: ["kbqTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
462
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
463
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: KbqNotificationItemComponent, isStandalone: true, selector: "kbq-notification-item", inputs: { dataInput: { classPropertyName: "dataInput", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-testid": "kbq-notification-item" }, properties: { "class": "styleClass" }, classAttribute: "kbq-notification-item" }, usesOnChanges: true, hostDirectives: [{ directive: i1.KbqReadStateDirective }], ngImport: i0, template: "@if (icon) {\n <div class=\"kbq-notification-item__icon-container layout-row layout-align-start-start\">\n @if (icon === true) {\n @switch (style) {\n @case ('contrast') {\n <i\n kbq-icon=\"kbq-circle-info_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'contrast'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('success') {\n <i\n kbq-icon=\"kbq-circle-check_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'success'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('warning') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'warning'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('error') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'error'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n }\n } @else if (isTemplateRef(icon)) {\n <ng-container [ngTemplateOutlet]=\"$any(icon)\" [ngTemplateOutletContext]=\"context\" />\n }\n </div>\n}\n\n<div class=\"kbq-notification-item__container\">\n @if (data.title) {\n <div\n kbq-title\n class=\"kbq-notification-item__title\"\n [class.kbq-notification-item__title_with-content]=\"data.caption || data.content\"\n >\n @if (isTemplateRef(data.title)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.title)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n <p data-testid=\"kbq-notification-item-title\">{{ data.title }}</p>\n }\n\n @if (!read) {\n <!-- Unread is otherwise conveyed by the dot below alone. It sits outside the time block\n because that block is visually hidden while the row is hovered or focused, which would\n take the text out of the accessibility tree with it. -->\n <span class=\"cdk-visually-hidden\">{{ panel.localeConfiguration().unread }}</span>\n }\n\n <div\n class=\"kbq-notification-item-time\"\n data-testid=\"kbq-notification-item-time\"\n [class.kbq-notification-item-time_read]=\"read\"\n >\n <div class=\"kbq-notification-item-time__value\" data-testid=\"kbq-notification-item-time-value\">\n {{ time }}\n </div>\n <i\n class=\"kbq-notification-item-time__state\"\n kbq-icon=\"kbq-circle-xs_16\"\n aria-hidden=\"true\"\n [color]=\"'theme'\"\n ></i>\n </div>\n </div>\n }\n\n @if (data.caption) {\n <div\n kbq-title\n [class.kbq-notification-item__text]=\"data.title\"\n [class.kbq-notification-item__title]=\"!data.title\"\n >\n @if (isTemplateRef(data.caption)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.caption)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.caption }}\n }\n </div>\n }\n\n @if (data.content) {\n <div class=\"kbq-notification-item__content\">\n @if (isTemplateRef(data.content)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.content)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.content }}\n }\n </div>\n }\n\n @if (data.actions) {\n <div class=\"kbq-notification-item__actions\">\n @if (isTemplateRef(data.actions)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.actions)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.actions }}\n }\n </div>\n }\n</div>\n\n<button\n kbq-button\n class=\"kbq-notification-item__remove-button\"\n data-testid=\"kbq-notification-item-remove-button\"\n [attr.aria-label]=\"panel.localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"remove()\"\n>\n <i kbq-icon=\"kbq-trash_16\"></i>\n</button>\n", styles: [".kbq-notification-item{display:flex;box-sizing:border-box;position:relative;border-radius:var(--kbq-size-s)}@supports (corner-shape: squircle){.kbq-notification-item{corner-shape:squircle;border-radius:clamp(var(--kbq-size-s) * 1.85,var(--kbq-size-s) * 2.3 - 3.6px,var(--kbq-size-s) * 2)}}.kbq-notification-item{height:auto;margin-left:var(--kbq-size-m);margin-right:var(--kbq-size-m)}.kbq-notification-item:hover .kbq-notification-item-time,.kbq-notification-item:focus-within .kbq-notification-item-time{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button,.kbq-notification-item:focus-within .kbq-notification-item__remove-button{opacity:1;pointer-events:auto}.kbq-notification-item__icon-container{flex-shrink:0;box-sizing:content-box;width:var(--kbq-size-l);max-width:var(--kbq-size-l);height:var(--kbq-size-l);max-height:var(--kbq-size-l);margin-right:var(--kbq-size-s);padding-left:var(--kbq-size-m);padding-top:var(--kbq-notification-center-size-item-icon-padding-top)}.kbq-notification-item__container{display:flex;flex-direction:column;flex:1;padding-top:var(--kbq-size-m);padding-right:var(--kbq-size-s);padding-bottom:var(--kbq-size-m);overflow:hidden}.kbq-notification-item__title{display:flex;flex-direction:row;justify-content:space-between;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title>p{margin:0;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title.kbq-notification-item__title_with-content{margin-bottom:var(--kbq-size-xxs)}.kbq-notification-item-time{display:flex;flex-direction:row;height:var(--kbq-size-xl);align-items:center;padding-left:var(--kbq-notification-center-size-item-time-padding-left)}.kbq-notification-item-time .kbq-notification-item-time__value{margin-right:var(--kbq-size-3xs)}.kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__state{visibility:hidden;order:-1}.kbq-notification-item__text{display:flex;flex:1;align-items:center}.kbq-notification-item__content{display:flex;flex-direction:column;white-space:pre-wrap}.kbq-notification-item__actions{display:flex;padding-top:var(--kbq-size-s);gap:var(--kbq-size-m)}.kbq-notification-item__remove-button{position:absolute;top:var(--kbq-size-xs);right:var(--kbq-size-s);display:block;opacity:0;pointer-events:none}.kbq-notification-item{background:var(--kbq-background-card)}.kbq-notification-item .kbq-notification-item__title{color:var(--kbq-foreground-contrast)}.kbq-notification-item .kbq-notification-item__text,.kbq-notification-item .kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__value{color:var(--kbq-foreground-contrast-secondary)}.kbq-notification-item:hover,.kbq-notification-item:focus-within{background:var(--kbq-states-background-transparent-hover)}.kbq-notification-item{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-notification-item .kbq-notification-item-time{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"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i2.KbqIcon, selector: "[kbq-icon]", inputs: ["aria-hidden", "iconSize", "autoColor", "kbq-icon"] }, { kind: "ngmodule", type: KbqTitleModule }, { kind: "directive", type: i3.KbqTitleDirective, selector: "[kbq-title]", inputs: ["kbq-title", "ignoreTooltipPointerEvents"], exportAs: ["kbqTitle"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
275
464
  }
276
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationItemComponent, decorators: [{
465
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationItemComponent, decorators: [{
277
466
  type: Component,
278
467
  args: [{ selector: 'kbq-notification-item', imports: [
279
468
  NgTemplateOutlet,
280
469
  KbqIconModule,
281
470
  KbqTitleModule,
282
- KbqButtonModule,
283
- KbqTooltipTrigger
471
+ KbqButtonModule
284
472
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
285
473
  class: 'kbq-notification-item',
286
- '[class]': 'style',
474
+ '[class]': 'styleClass',
287
475
  'data-testid': 'kbq-notification-item'
288
- }, hostDirectives: [KbqReadStateDirective], template: "@if (data.icon) {\n <div class=\"kbq-notification-item__icon-container layout-row layout-align-start-start\">\n @if (data.icon === true) {\n @switch (data.style) {\n @case ('contrast') {\n <i\n kbq-icon=\"kbq-circle-info_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('success') {\n <i\n kbq-icon=\"kbq-circle-check_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('warning') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('error') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n }\n } @else if (isTemplateRef(data.icon)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.icon)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n }\n </div>\n}\n\n<div class=\"kbq-notification-item__container\">\n @if (data.title) {\n <div\n kbq-title\n class=\"kbq-notification-item__title\"\n [class.kbq-notification-item__title_with-content]=\"data.caption || data.content\"\n >\n @if (isTemplateRef(data.title)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.title)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n <p data-testid=\"kbq-notification-item-title\">{{ data.title }}</p>\n }\n\n <div\n class=\"kbq-notification-item-time\"\n data-testid=\"kbq-notification-item-time\"\n [class.kbq-notification-item-time_read]=\"data.read\"\n >\n <div class=\"kbq-notification-item-time__value\" data-testid=\"kbq-notification-item-time-value\">\n {{ time }}\n </div>\n <i class=\"kbq-notification-item-time__state\" kbq-icon=\"kbq-circle-xs_16\" [color]=\"'theme'\"></i>\n </div>\n </div>\n }\n\n @if (data.caption) {\n <div\n kbq-title\n [class.kbq-notification-item__text]=\"data.title\"\n [class.kbq-notification-item__title]=\"!data.title\"\n >\n @if (isTemplateRef(data.caption)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.caption)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.caption }}\n }\n </div>\n }\n\n @if (data.content) {\n <div class=\"kbq-notification-item__content\">\n @if (isTemplateRef(data.content)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.content)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.content }}\n }\n </div>\n }\n\n @if (data.actions) {\n <div class=\"kbq-notification-item__actions\">\n @if (isTemplateRef(data.actions)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.actions)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.actions }}\n }\n </div>\n }\n</div>\n\n<button\n kbq-button\n class=\"kbq-notification-item__remove-button\"\n data-testid=\"kbq-notification-item-remove-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltipArrow]=\"false\"\n [kbqTooltip]=\"center.localeData.remove\"\n [kbqPlacement]=\"popUpPlacements.Right\"\n (click)=\"service.remove(data)\"\n>\n <i kbq-icon=\"kbq-trash_16\"></i>\n</button>\n", styles: [".kbq-notification-item{display:flex;box-sizing:border-box;position:relative;border-radius:var(--kbq-size-s);height:auto;margin-left:var(--kbq-size-m);margin-right:var(--kbq-size-m)}.kbq-notification-item:hover .kbq-notification-item-time,.kbq-notification-item:focus-within .kbq-notification-item-time{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button,.kbq-notification-item:focus-within .kbq-notification-item__remove-button{display:block}.kbq-notification-item__icon-container{flex-shrink:0;box-sizing:content-box;width:var(--kbq-size-l);max-width:var(--kbq-size-l);height:var(--kbq-size-l);max-height:var(--kbq-size-l);margin-right:var(--kbq-size-s);padding-left:var(--kbq-size-m);padding-top:14px}.kbq-notification-item__container{display:flex;flex-direction:column;flex:1;padding-top:var(--kbq-size-m);padding-right:var(--kbq-size-s);padding-bottom:var(--kbq-size-m);overflow:hidden}.kbq-notification-item__title{display:flex;flex-direction:row;justify-content:space-between;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title>p{margin:0;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title.kbq-notification-item__title_with-content{margin-bottom:var(--kbq-size-xxs)}.kbq-notification-item-time{display:flex;flex-direction:row;height:var(--kbq-size-xl);align-items:center;padding-left:22px}.kbq-notification-item-time .kbq-notification-item-time__value{margin-right:var(--kbq-size-3xs)}.kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__state{visibility:hidden;order:-1}.kbq-notification-item__text{display:flex;flex:1;align-items:center}.kbq-notification-item__content{display:flex;flex-direction:column;white-space:pre-wrap}.kbq-notification-item__actions{display:flex;padding-top:var(--kbq-size-s);gap:var(--kbq-size-m)}.kbq-notification-item__remove-button{position:absolute;top:var(--kbq-size-xs);right:var(--kbq-size-s);display:none}.kbq-notification-item{background:var(--kbq-background-card)}.kbq-notification-item .kbq-notification-item__title{color:var(--kbq-foreground-contrast)}.kbq-notification-item .kbq-notification-item__text,.kbq-notification-item .kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__value{color:var(--kbq-foreground-contrast-secondary)}.kbq-notification-item:hover{background:var(--kbq-states-background-transparent-hover)}.kbq-notification-item{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-notification-item .kbq-notification-item-time{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"] }]
289
- }], ctorParameters: () => [], propDecorators: { data: [{
290
- type: Input
291
- }] } });
476
+ }, hostDirectives: [KbqReadStateDirective], template: "@if (icon) {\n <div class=\"kbq-notification-item__icon-container layout-row layout-align-start-start\">\n @if (icon === true) {\n @switch (style) {\n @case ('contrast') {\n <i\n kbq-icon=\"kbq-circle-info_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'contrast'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('success') {\n <i\n kbq-icon=\"kbq-circle-check_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'success'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('warning') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'warning'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('error') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'error'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n }\n } @else if (isTemplateRef(icon)) {\n <ng-container [ngTemplateOutlet]=\"$any(icon)\" [ngTemplateOutletContext]=\"context\" />\n }\n </div>\n}\n\n<div class=\"kbq-notification-item__container\">\n @if (data.title) {\n <div\n kbq-title\n class=\"kbq-notification-item__title\"\n [class.kbq-notification-item__title_with-content]=\"data.caption || data.content\"\n >\n @if (isTemplateRef(data.title)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.title)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n <p data-testid=\"kbq-notification-item-title\">{{ data.title }}</p>\n }\n\n @if (!read) {\n <!-- Unread is otherwise conveyed by the dot below alone. It sits outside the time block\n because that block is visually hidden while the row is hovered or focused, which would\n take the text out of the accessibility tree with it. -->\n <span class=\"cdk-visually-hidden\">{{ panel.localeConfiguration().unread }}</span>\n }\n\n <div\n class=\"kbq-notification-item-time\"\n data-testid=\"kbq-notification-item-time\"\n [class.kbq-notification-item-time_read]=\"read\"\n >\n <div class=\"kbq-notification-item-time__value\" data-testid=\"kbq-notification-item-time-value\">\n {{ time }}\n </div>\n <i\n class=\"kbq-notification-item-time__state\"\n kbq-icon=\"kbq-circle-xs_16\"\n aria-hidden=\"true\"\n [color]=\"'theme'\"\n ></i>\n </div>\n </div>\n }\n\n @if (data.caption) {\n <div\n kbq-title\n [class.kbq-notification-item__text]=\"data.title\"\n [class.kbq-notification-item__title]=\"!data.title\"\n >\n @if (isTemplateRef(data.caption)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.caption)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.caption }}\n }\n </div>\n }\n\n @if (data.content) {\n <div class=\"kbq-notification-item__content\">\n @if (isTemplateRef(data.content)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.content)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.content }}\n }\n </div>\n }\n\n @if (data.actions) {\n <div class=\"kbq-notification-item__actions\">\n @if (isTemplateRef(data.actions)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.actions)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.actions }}\n }\n </div>\n }\n</div>\n\n<button\n kbq-button\n class=\"kbq-notification-item__remove-button\"\n data-testid=\"kbq-notification-item-remove-button\"\n [attr.aria-label]=\"panel.localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"remove()\"\n>\n <i kbq-icon=\"kbq-trash_16\"></i>\n</button>\n", styles: [".kbq-notification-item{display:flex;box-sizing:border-box;position:relative;border-radius:var(--kbq-size-s)}@supports (corner-shape: squircle){.kbq-notification-item{corner-shape:squircle;border-radius:clamp(var(--kbq-size-s) * 1.85,var(--kbq-size-s) * 2.3 - 3.6px,var(--kbq-size-s) * 2)}}.kbq-notification-item{height:auto;margin-left:var(--kbq-size-m);margin-right:var(--kbq-size-m)}.kbq-notification-item:hover .kbq-notification-item-time,.kbq-notification-item:focus-within .kbq-notification-item-time{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button,.kbq-notification-item:focus-within .kbq-notification-item__remove-button{opacity:1;pointer-events:auto}.kbq-notification-item__icon-container{flex-shrink:0;box-sizing:content-box;width:var(--kbq-size-l);max-width:var(--kbq-size-l);height:var(--kbq-size-l);max-height:var(--kbq-size-l);margin-right:var(--kbq-size-s);padding-left:var(--kbq-size-m);padding-top:var(--kbq-notification-center-size-item-icon-padding-top)}.kbq-notification-item__container{display:flex;flex-direction:column;flex:1;padding-top:var(--kbq-size-m);padding-right:var(--kbq-size-s);padding-bottom:var(--kbq-size-m);overflow:hidden}.kbq-notification-item__title{display:flex;flex-direction:row;justify-content:space-between;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title>p{margin:0;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title.kbq-notification-item__title_with-content{margin-bottom:var(--kbq-size-xxs)}.kbq-notification-item-time{display:flex;flex-direction:row;height:var(--kbq-size-xl);align-items:center;padding-left:var(--kbq-notification-center-size-item-time-padding-left)}.kbq-notification-item-time .kbq-notification-item-time__value{margin-right:var(--kbq-size-3xs)}.kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__state{visibility:hidden;order:-1}.kbq-notification-item__text{display:flex;flex:1;align-items:center}.kbq-notification-item__content{display:flex;flex-direction:column;white-space:pre-wrap}.kbq-notification-item__actions{display:flex;padding-top:var(--kbq-size-s);gap:var(--kbq-size-m)}.kbq-notification-item__remove-button{position:absolute;top:var(--kbq-size-xs);right:var(--kbq-size-s);display:block;opacity:0;pointer-events:none}.kbq-notification-item{background:var(--kbq-background-card)}.kbq-notification-item .kbq-notification-item__title{color:var(--kbq-foreground-contrast)}.kbq-notification-item .kbq-notification-item__text,.kbq-notification-item .kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__value{color:var(--kbq-foreground-contrast-secondary)}.kbq-notification-item:hover,.kbq-notification-item:focus-within{background:var(--kbq-states-background-transparent-hover)}.kbq-notification-item{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-notification-item .kbq-notification-item-time{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"] }]
477
+ }], ctorParameters: () => [], propDecorators: { dataInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
292
478
 
293
479
  const defaultOffsetX = 8;
480
+ const defaultPlacement = PopUpPlacements.Right;
294
481
  /** Rate-limit window (ms) for the scroll-to-bottom check that drives infinite scroll. */
295
482
  const SCROLLED_TO_BOTTOM_AUDIT_TIME = 100;
296
483
  /**
@@ -304,13 +491,18 @@ const SCROLLED_TO_BOTTOM_AUDIT_TIME = 100;
304
491
  * 100% zoom one device pixel is wider than one CSS pixel, which scales the residual by ~1/zoom and
305
492
  * pushes it past 1. 2px covers zoom down to 50% and is imperceptible as a trigger threshold.
306
493
  *
307
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight
494
+ * See [`Element.scrollHeight`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight) on MDN.
308
495
  */
309
496
  const SCROLLED_TO_BOTTOM_TOLERANCE = 2;
310
- /**default configuration of notification-center */
311
- const KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION = ruRULocaleData.notificationCenter;
312
- /** Injection Token for providing configuration of notification-center */
313
- const KBQ_NOTIFICATION_CENTER_CONFIGURATION = new InjectionToken('KbqNotificationCenterConfiguration');
497
+ /** Custom property the panel height is published through, so the stylesheet stays the single owner. */
498
+ const POPOVER_HEIGHT_PROPERTY = '--kbq-notification-center-popover-height';
499
+ /** Delete buttons of the day groups and of the individual notifications. */
500
+ const REMOVE_BUTTON_SELECTOR = '.kbq-notification-center-sub-header__button, .kbq-notification-item__remove-button';
501
+ /**
502
+ * Rate-limit window (ms) the reposition scroll strategy runs on. The panel re-applies its
503
+ * stick-to-window styles on the same window, so the two stay in step.
504
+ */
505
+ const SCROLL_REPOSITION_THROTTLE = 20;
314
506
  /** @docs-private */
315
507
  const KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY = new InjectionToken('kbq-notification-center-scroll-strategy', {
316
508
  providedIn: 'root',
@@ -318,59 +510,92 @@ const KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY = new InjectionToken('kbq-notifica
318
510
  });
319
511
  /** @docs-private */
320
512
  function kbqNotificationCenterScrollStrategyFactory(overlay) {
321
- return () => overlay.scrollStrategies.reposition({ scrollThrottle: 20 });
513
+ return () => overlay.scrollStrategies.reposition({ scrollThrottle: SCROLL_REPOSITION_THROTTLE });
322
514
  }
323
515
  /** @docs-private */
324
- const KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY_FACTORY_PROVIDER = {
325
- provide: KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY,
326
- deps: [Overlay],
327
- useFactory: kbqNotificationCenterScrollStrategyFactory
328
- };
329
- /** @docs-private */
330
516
  class KbqNotificationCenterComponent extends KbqPopUp {
331
- /** localized data
332
- * @docs-private */
333
- get localeData() {
334
- return this.configuration;
517
+ /**
518
+ * Text of the panel's single live region. The panel keeps one persistent region and only changes
519
+ * its text, because a region inserted together with its content is not reliably announced.
520
+ *
521
+ * @docs-private
522
+ */
523
+ get statusMessage() {
524
+ // Branch in the template's own order, or the region announces a state that is not on screen:
525
+ // the full-screen error wins over everything, then the full-screen loader, then the bottom
526
+ // spinner, then the bottom error row, and only an otherwise idle empty list reads as empty.
527
+ if (this.service.errorMode()) {
528
+ return this.localeConfiguration().failedToLoadNotifications;
529
+ }
530
+ if (this.service.loadingMode() || this.service.loadingMore()) {
531
+ return this.localeConfiguration().loadingMore;
532
+ }
533
+ if (this.service.loadMoreErrorMode()) {
534
+ return this.localeConfiguration().failedToLoadNotifications;
535
+ }
536
+ return this.service.empty() ? this.localeConfiguration().noNotifications : '';
335
537
  }
336
538
  get popoverHeight() {
337
539
  return this._popoverHeight;
338
540
  }
339
541
  set popoverHeight(value) {
340
542
  this._popoverHeight = value;
341
- this.elementRef.nativeElement.style.height = value;
543
+ if (value) {
544
+ this.renderer.setStyle(this.elementRef.nativeElement, POPOVER_HEIGHT_PROPERTY, value, RendererStyleFlags2.DashCase);
545
+ }
546
+ else {
547
+ this.renderer.removeStyle(this.elementRef.nativeElement, POPOVER_HEIGHT_PROPERTY, RendererStyleFlags2.DashCase);
548
+ }
342
549
  }
343
550
  constructor() {
344
551
  super();
345
552
  /** @docs-private */
346
- this.changeDetectorRef = inject(ChangeDetectorRef);
347
- /** @docs-private */
348
- this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
349
- /** @docs-private */
350
- this.dateAdapter = inject(DateAdapter);
351
- /** @docs-private */
352
553
  this.service = inject(KbqNotificationCenterService);
353
- this.externalConfiguration = inject(KBQ_NOTIFICATION_CENTER_CONFIGURATION, { optional: true });
354
- /** Distance in pixels from the bottom of the list at which the next page is requested.
355
- * @docs-private */
554
+ this.injector = inject(Injector);
555
+ this.ngZone = inject(NgZone);
556
+ this.idGenerator = inject(_IdGenerator);
557
+ this.scrollDispatcher = inject(ScrollDispatcher);
558
+ this.document = inject(DOCUMENT);
559
+ this.focusMonitor = inject(FocusMonitor);
560
+ this.inputModalityDetector = inject(InputModalityDetector);
561
+ this.carrier = inject(KbqLocaleOverridesDirective, { self: true });
562
+ /**
563
+ * Accessible names for the icon-only toolbar buttons.
564
+ *
565
+ * @docs-private
566
+ */
567
+ this.a11yLocaleConfiguration = this.carrier.read('a11y', KBQ_A11Y_LOCALE_CONFIGURATION);
568
+ /**
569
+ * Localized strings of the notification center.
570
+ *
571
+ * Read through a signal so that a runtime `setLocale()` reaches `KbqNotificationItemComponent`, which
572
+ * renders these strings from its own `OnPush` view: a `markForCheck()` here would mark this component
573
+ * only, never the already-rendered items.
574
+ */
575
+ this.localeConfiguration = this.carrier.read('notificationCenter', KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION);
576
+ /**
577
+ * Id of the panel heading, referenced by the host's `aria-labelledby`.
578
+ *
579
+ * @docs-private
580
+ */
581
+ this.titleId = this.idGenerator.getId('kbq-notification-center-title-');
582
+ /**
583
+ * Distance in pixels from the bottom of the list at which the next page is requested.
584
+ *
585
+ * @docs-private
586
+ */
356
587
  this.scrolledToBottomOffset = 0;
357
- /** Emits on every scroll of the list container; drives the scroll-to-bottom check. */
358
- this.scroll$ = new Subject();
588
+ /** Re-measures the list outside of a scroll event: on first render and whenever the state changes. */
589
+ /** Whether a re-measurement is already queued for the next render. */
590
+ this.scrolledToBottomRecheckPending = false;
591
+ this.scrolledToBottomRecheck = new Subject();
359
592
  /** @docs-private */
360
593
  this.prefix = 'kbq-notification-center';
361
594
  /** @docs-private */
362
595
  this.isTrapFocus = false;
363
596
  this.switcher = viewChild.required('notificationSwitcher');
364
597
  /** Scrollable list container; used to measure scroll position for infinite scroll. */
365
- this.scrollContainer = viewChild.required(KbqScrollbar);
366
- this.updateLocaleParams = () => {
367
- this.configuration = this.externalConfiguration || this.localeService?.getParams('notificationCenter');
368
- this.changeDetectorRef.markForCheck();
369
- };
370
- this.localeService?.changes.pipe(takeUntilDestroyed()).subscribe(this.updateLocaleParams);
371
- if (!this.localeService) {
372
- this.initDefaultParams();
373
- }
598
+ this.scrollContainer = viewChild.required(KbqScrollbarViewport);
374
599
  }
375
600
  ngAfterViewInit() {
376
601
  this.visibleChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((state) => {
@@ -379,21 +604,90 @@ class KbqNotificationCenterComponent extends KbqPopUp {
379
604
  }
380
605
  this.setStickPosition();
381
606
  });
607
+ // The reposition scroll strategy rewrites the pane's top/left/bottom/right on every scroll the
608
+ // application makes — including the panel's own list, which is a registered `CdkScrollable` —
609
+ // wiping the manual styles `setStickPosition()` writes. This subscription is created after the
610
+ // strategy has been enabled (`OverlayRef.attach()` runs before the panel's first change
611
+ // detection), so on the same audit window it re-applies them behind the strategy.
612
+ // The panel is also rendered on its own, without a trigger, so the guard covers more than the
613
+ // absent `stickToWindow`.
614
+ this.scrollDispatcher
615
+ .scrolled(SCROLL_REPOSITION_THROTTLE)
616
+ .pipe(filter(() => !!this.trigger?.stickToWindow), takeUntilDestroyed(this.destroyRef))
617
+ .subscribe(() => this.setStickPosition());
382
618
  this.service.changes
383
619
  .pipe(takeUntilDestroyed(this.destroyRef))
384
- .subscribe(() => this.changeDetectorRef.markForCheck());
385
- this.switcher().focus();
620
+ .subscribe(() => this.scheduleScrolledToBottomCheck());
621
+ // Focused with the modality the user actually opened the panel with, so a keyboard-driven open
622
+ // keeps its focus ring while a click does not. Not `KbqButton.focusViaKeyboard()`, which hardcodes
623
+ // `'keyboard'` and paints the ring on the toggle for a mouse user, and not FocusMonitor's own last
624
+ // origin, which reports `program` for a click landing outside its detection window (same rule as
625
+ // `KbqBasePipe.currentFocusOrigin`).
626
+ const switcher = this.switcher();
627
+ // Mirrors `focusViaKeyboard()`'s own early return, which this no longer goes through.
628
+ if (!switcher.disabled) {
629
+ this.focusMonitor.focusVia(switcher.getHostElement(), this.inputModalityDetector.mostRecentModality ?? 'program');
630
+ }
386
631
  this.subscribeToScrolledToBottom();
387
632
  this.subscribeToRevealLoadMoreRow();
633
+ // A first page too short to overflow the viewport produces no scroll event at all, so measure
634
+ // once the panel has rendered or infinite scroll would never start.
635
+ this.scheduleScrolledToBottomCheck();
636
+ }
637
+ /**
638
+ * Removes a whole day group, keeping keyboard focus inside the panel.
639
+ *
640
+ * @docs-private
641
+ */
642
+ removeGroup(group) {
643
+ this.restoreFocusAfterRemove();
644
+ this.service.removeGroup(group);
645
+ }
646
+ /**
647
+ * Removes every notification, keeping keyboard focus inside the panel.
648
+ *
649
+ * @docs-private
650
+ */
651
+ removeAll() {
652
+ this.restoreFocusAfterRemove();
653
+ this.service.removeAll();
654
+ }
655
+ /**
656
+ * Moves focus to a surviving delete button — or to the list container when the last one is gone —
657
+ * once the removal has rendered. Without it, focus falls back to `<body>` and the Escape handler
658
+ * and the rest of the panel become unreachable.
659
+ */
660
+ restoreFocusAfterRemove() {
661
+ // Read before the removal renders, while the activated button is still in the DOM: its place in
662
+ // document order is what decides where focus goes next. Asking for the first match afterwards
663
+ // would always answer with the first day group's "delete this day" button, wherever the user
664
+ // actually was — a destructive control they never aimed at, hidden behind that group's own
665
+ // sticky header.
666
+ const removedIndex = this.getRemoveButtons().indexOf(this.document.activeElement);
667
+ afterNextRender(() => {
668
+ const survivors = this.getRemoveButtons();
669
+ // The button that took the removed one's place, or the last one before it. A removal
670
+ // that did not start from a delete button — or that took the last one with it — falls
671
+ // back to the list container, which keeps the panel operable without parking focus on
672
+ // an arbitrary destructive control.
673
+ const survivor = removedIndex < 0 ? undefined : survivors[removedIndex] || survivors[survivors.length - 1];
674
+ if (survivor) {
675
+ survivor.focus();
676
+ }
677
+ else {
678
+ this.focusScrollContainer();
679
+ }
680
+ }, { injector: this.injector });
388
681
  }
389
- /** Handles the list container scroll: feeds the scroll-to-bottom check that drives infinite scroll.
390
- * Overflow shadows are handled declaratively by the `kbqOverflowShadow*` directives.
391
- * @docs-private */
392
- onContainerScroll() {
393
- this.scroll$.next();
682
+ /** Delete buttons of the day groups and of the individual notifications, in document order. */
683
+ getRemoveButtons() {
684
+ return Array.from(this.elementRef.nativeElement.querySelectorAll(REMOVE_BUTTON_SELECTOR));
394
685
  }
395
- /** Retries loading the next page from the bottom error row.
396
- * @docs-private */
686
+ /**
687
+ * Retries loading the next page from the bottom error row.
688
+ *
689
+ * @docs-private
690
+ */
397
691
  retryLoadMore() {
398
692
  // The retry button is about to unmount; keep keyboard focus inside the panel instead of
399
693
  // letting it fall back to <body>.
@@ -401,57 +695,88 @@ class KbqNotificationCenterComponent extends KbqPopUp {
401
695
  // Clear the bottom error state here so the spinner and the error row can never be shown at
402
696
  // the same time, regardless of what the consumer's `onNextPage` handler does.
403
697
  this.service.setLoadMoreErrorMode(false);
404
- this.service.onNextPage.emit();
698
+ this.service.onNextPage.next();
405
699
  }
406
700
  /**
407
701
  * Requests the next page (via `service.onNextPage`) once the list is scrolled to within
408
702
  * `scrolledToBottomOffset` pixels of the bottom. Two triggers feed it: the user scrolling, and a
409
- * page finishing loading. The latter keeps paging when a freshly loaded page is too short to
410
- * overflow the viewport — otherwise no further scroll event would fire and pagination would
411
- * stall. Suppressed while a load is in flight, errored, or when there is nothing more to load.
703
+ * re-measurement after the panel's state has rendered. The latter keeps paging when a freshly
704
+ * loaded page is too short to overflow the viewport — otherwise no further scroll event would fire
705
+ * and pagination would stall. Suppressed while a load is in flight, errored, or when there is
706
+ * nothing more to load.
412
707
  */
413
708
  subscribeToScrolledToBottom() {
414
- const scrolledToBottom$ = this.scroll$.pipe(auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), map(() => this.isScrolledToBottom()), distinctUntilChanged(), filter(Boolean));
415
- // Re-measure once a load completes (and the appended items have rendered): if the list still
416
- // sits at the bottom, continue paging instead of waiting for a scroll event that never comes.
417
- const loadCompleted$ = this.service.loadingMore.pipe(distinctUntilChanged(), pairwise(), filter(([wasLoading, isLoading]) => wasLoading && !isLoading), auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), filter(() => this.isScrolledToBottom()));
418
- merge(scrolledToBottom$, loadCompleted$)
709
+ const scrolledToBottom$ = this.scrollContainer().scrollChanges.pipe(auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), map(() => this.isScrolledToBottom()), distinctUntilChanged(), filter(Boolean));
710
+ // Deliberately without `distinctUntilChanged`: a re-measurement that finds the list still at
711
+ // the bottom must keep paging even though the previous measurement said the same.
712
+ const rechecked$ = this.scrolledToBottomRecheck.pipe(auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), filter(() => this.isScrolledToBottom()));
713
+ merge(scrolledToBottom$, rechecked$)
419
714
  .pipe(takeUntilDestroyed(this.destroyRef))
420
- .subscribe(() => this.requestNextPage());
715
+ // `scrollChanges` is `CdkScrollable.elementScrolled()` and emits outside Angular's zone, so
716
+ // re-enter before touching consumer-facing state.
717
+ .subscribe(() => this.ngZone.run(() => this.requestNextPage()));
421
718
  }
422
- /** Whether the list is scrolled to within `scrolledToBottomOffset` pixels of the bottom.
423
- * Sub-pixel measurement error is absorbed by `SCROLLED_TO_BOTTOM_TOLERANCE`. */
719
+ /** Queues a re-measurement for after the next render, when the DOM reflects the new state. */
720
+ scheduleScrolledToBottomCheck() {
721
+ // At most one pending re-measurement: `requestNextPage` flips the service's own loading flags,
722
+ // which ping `changes` in turn, so an unguarded schedule feeds itself for as long as the list
723
+ // reports it is at the bottom — each render callback queueing the next one.
724
+ if (this.scrolledToBottomRecheckPending) {
725
+ return;
726
+ }
727
+ this.scrolledToBottomRecheckPending = true;
728
+ afterNextRender(() => {
729
+ this.scrolledToBottomRecheckPending = false;
730
+ this.scrolledToBottomRecheck.next();
731
+ }, { injector: this.injector });
732
+ }
733
+ /**
734
+ * Whether the list is scrolled to within `scrolledToBottomOffset` pixels of the bottom.
735
+ * Sub-pixel measurement error is absorbed by `SCROLLED_TO_BOTTOM_TOLERANCE`.
736
+ */
424
737
  isScrolledToBottom() {
425
- const { scrollTop, clientHeight, scrollHeight } = this.scrollContainer().contentElement().nativeElement;
738
+ const { scrollTop, clientHeight, scrollHeight } = this.scrollContainer().getNativeElement();
739
+ // A container that has not been laid out yet has no bottom to reach. Without this guard the
740
+ // all-zero measurement reads as "at the bottom" and requests page after page into nothing.
741
+ if (clientHeight === 0) {
742
+ return false;
743
+ }
426
744
  return scrollHeight - scrollTop - clientHeight <= this.scrolledToBottomOffset + SCROLLED_TO_BOTTOM_TOLERANCE;
427
745
  }
428
746
  /** Emits `onNextPage` unless a load is already in flight, errored, or there is nothing more to load. */
429
747
  requestNextPage() {
430
- if (this.service.hasMore.value && !this.service.loadingMore.value && !this.service.loadMoreErrorMode.value) {
431
- this.service.onNextPage.emit();
748
+ if (this.service.hasMore() && !this.service.loadingMore() && !this.service.loadMoreErrorMode()) {
749
+ this.service.onNextPage.next();
432
750
  }
433
751
  }
434
752
  /**
435
753
  * Reveals the bottom "load more" spinner / error row when it first appears. Both rows are appended
436
754
  * below the last item and can land outside the viewport (the next page is requested while the user
437
755
  * is up to `scrolledToBottomOffset` px above the true bottom). Only a genuine false->true transition
438
- * reveals the row: the BehaviorSubject's replayed current value is ignored (`pairwise` needs two
439
- * emissions), so the panel always opens scrolled to the top — reopening it while a load-more error
440
- * is still set never jumps to the bottom.
756
+ * after the panel opened reveals the row, so the panel always opens scrolled to the top — reopening
757
+ * it while a load-more error is still set never jumps to the bottom.
441
758
  */
442
759
  subscribeToRevealLoadMoreRow() {
443
- const reveal = (source) => source.pipe(distinctUntilChanged(), pairwise(), filter(([wasShown, isShown]) => !wasShown && isShown), auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME));
444
- merge(reveal(this.service.loadingMore), reveal(this.service.loadMoreErrorMode))
760
+ const reveal = (isShown) => {
761
+ let wasShown = isShown();
762
+ return this.service.changes.pipe(filter(() => {
763
+ const shown = isShown();
764
+ const appeared = shown && !wasShown;
765
+ wasShown = shown;
766
+ return appeared;
767
+ }), auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME));
768
+ };
769
+ merge(reveal(() => this.service.loadingMore()), reveal(() => this.service.loadMoreErrorMode()))
445
770
  .pipe(takeUntilDestroyed(this.destroyRef))
446
771
  .subscribe(() => this.scrollToBottom());
447
772
  }
448
773
  /** Scrolls the list container to its bottom so a freshly-appended bottom row becomes visible. */
449
774
  scrollToBottom() {
450
- const { scrollHeight } = this.scrollContainer().contentElement().nativeElement;
775
+ const { scrollHeight } = this.scrollContainer().getNativeElement();
451
776
  this.scrollContainer().scrollTo({ top: scrollHeight });
452
777
  }
453
778
  focusScrollContainer() {
454
- const element = this.scrollContainer().contentElement().nativeElement;
779
+ const element = this.scrollContainer().getNativeElement();
455
780
  // tabindex -1 keeps the container out of the Tab order while allowing programmatic focus.
456
781
  element.setAttribute('tabindex', '-1');
457
782
  element.focus({ preventScroll: true });
@@ -464,70 +789,100 @@ class KbqNotificationCenterComponent extends KbqPopUp {
464
789
  updateTrapFocus(isTrapFocus) {
465
790
  this.isTrapFocus = isTrapFocus;
466
791
  }
467
- /** @docs-private */
468
- escapeHandler() {
792
+ /**
793
+ * Closes the panel on `Escape` inside it, unless a control there spent the key closing a popup of its own.
794
+ *
795
+ * @docs-private
796
+ */
797
+ escapeHandler(event) {
798
+ if (event?.defaultPrevented)
799
+ return;
800
+ // Spent, so that a container closing on Escape underneath, such as a sidepanel, stays open.
801
+ event?.preventDefault();
469
802
  this.hide(0);
470
803
  }
471
- initDefaultParams() {
472
- this.configuration = KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION;
473
- }
474
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
475
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqNotificationCenterComponent, isStandalone: true, selector: "kbq-notification-center", host: { listeners: { "keydown.escape": "escapeHandler()" }, properties: { "class.kbq-notification-center_popover": "popoverMode" }, classAttribute: "kbq-notification-center" }, viewQueries: [{ propertyName: "switcher", first: true, predicate: ["notificationSwitcher"], descendants: true, isSignal: true }, { propertyName: "scrollContainer", first: true, predicate: KbqScrollbar, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\">{{ localeData.notifications }}</div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [kbqTooltip]=\"service.silentMode.value ? localeData.doNotDisturb : localeData.showPopUpNotifications\"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.isEmpty) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"service.removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n</div>\n\n<div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbq-scrollbar\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n (onScroll)=\"onContainerScroll()\"\n>\n @if (!service.errorMode.value) {\n @if (!service.loadingMode.value) {\n @for (group of service.groupedItems | async; track group) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeData.remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"service.removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore.value) {\n <div class=\"kbq-notification-center-empty-container\" data-testid=\"kbq-notification-center-empty\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeData.noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore.value) {\n <div\n class=\"kbq-notification-center-load-more\"\n data-testid=\"kbq-notification-center-load-more\"\n role=\"status\"\n [attr.aria-label]=\"localeData.loadingMore\"\n >\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n }\n\n @if (service.loadMoreErrorMode.value) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n role=\"alert\"\n >\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" [transparent]=\"true\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.emit()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n</div>\n\n<kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i kbq-icon=\"{{ !service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.doNotDisturb }}\n </button>\n</kbq-dropdown>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:400px;height:100vh;box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-size-xs);height:calc(100vh - 48px);box-shadow:var(--kbq-shadow-popup)}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:100;display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{display:flex}.kbq-notification-center-container{height:100%;border-radius:inherit;padding-bottom:var(--kbq-size-xl)}.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:smooth}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:26px 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center,.kbq-notification-center-sub-header{background:var(--kbq-background-card)}.kbq-notification-center:not(.kbq-notification-center_popover),.kbq-notification-center-sub-header:not(.kbq-notification-center_popover){border-right-color:var(--kbq-line-contrast-less);border-left-color:var(--kbq-line-contrast-less)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-foreground-error)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n"], dependencies: [{ kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i1.KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }, { kind: "component", type: i1.KbqIconItem, selector: "[kbq-icon-item]", inputs: ["kbq-icon-item", "fade", "big"] }, { kind: "ngmodule", type: KbqBadgeModule }, { kind: "ngmodule", type: KbqScrollbarModule }, { kind: "component", type: i2.KbqScrollbar, selector: "kbq-scrollbar, [kbq-scrollbar]", inputs: ["initializationTarget", "options", "events", "defer"], outputs: ["onInitialize", "onUpdate", "onDestroy", "onScroll"], exportAs: ["kbqScrollbar"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "directive", type: i3$1.KbqButtonDropdownTrigger, selector: "[kbq-button][kbqDropdownTriggerFor]" }, { kind: "ngmodule", type: KbqDividerModule }, { kind: "component", type: i4.KbqDivider, selector: "kbq-divider", inputs: ["vertical", "paddings"] }, { kind: "ngmodule", type: KbqDropdownModule }, { kind: "component", type: i5.KbqDropdown, selector: "kbq-dropdown", inputs: ["navigationWithWrap", "xPosition", "yPosition", "overlapTriggerY", "overlapTriggerX", "hasBackdrop", "class", "backdropClass", "panelWidth", "panelMinWidth", "panelMaxWidth", "safeArea"], outputs: ["closed"], exportAs: ["kbqDropdown"] }, { kind: "component", type: i5.KbqDropdownItem, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: ["disabled", "progress"], exportAs: ["kbqDropdownItem"] }, { kind: "directive", type: i5.KbqDropdownTrigger, selector: "[kbqDropdownTriggerFor]", inputs: ["offsetX", "offsetY", "kbqDropdownTriggerData", "openByArrowDown", "demoteOverlay", "kbqDropdownTriggerRestoreFocus", "kbqDropdownTriggerFor"], outputs: ["dropdownOpened", "dropdownClosed"], exportAs: ["kbqDropdownTrigger"] }, { kind: "ngmodule", type: KbqToolTipModule }, { kind: "directive", type: i6.KbqTooltipTrigger, selector: "[kbqTooltip]", inputs: ["kbqTooltipScrollStrategy", "forDisabledComponent", "ignoreTooltipPointerEvents", "kbqTooltipSingleInstance", "hideWithTimeout", "kbqVisible", "kbqPlacement", "kbqRelativeToPointer", "kbqPlacementPriority", "kbqTooltip", "kbqTooltipDisabled", "kbqEnterDelay", "kbqLeaveDelay", "kbqTrigger", "kbqTooltipClass", "kbqTooltipContext", "kbqTooltipColor", "kbqTooltipArrow", "kbqTooltipOffset", "kbqTooltipModifier", "kbqTooltipHeader"], outputs: ["kbqPlacementChange", "kbqVisibleChange"], exportAs: ["kbqTooltip"] }, { kind: "component", type: KbqNotificationItemComponent, selector: "kbq-notification-item", inputs: ["data"] }, { kind: "ngmodule", type: KbqLoaderOverlayModule }, { kind: "component", type: i7.KbqLoaderOverlay, selector: "kbq-loader-overlay", inputs: ["text", "caption", "size", "transparent", "card"] }, { kind: "ngmodule", type: KbqProgressSpinnerModule }, { kind: "component", type: i8.KbqProgressSpinner, selector: "kbq-progress-spinner", inputs: ["id", "value", "mode", "size"] }, { kind: "directive", type: KbqOverflowShadowContainer, selector: "[kbqOverflowShadowContainer]", inputs: ["debounce"], exportAs: ["kbqOverflowShadowContainer"] }, { kind: "directive", type: KbqOverflowShadowTop, selector: "[kbqOverflowShadowTop]", inputs: ["kbqOverflowShadowTop", "shadow"], exportAs: ["kbqOverflowShadowTop"] }, { kind: "directive", type: KbqOverflowShadowBottom, selector: "[kbqOverflowShadowBottom]", inputs: ["kbqOverflowShadowBottom", "shadow"], exportAs: ["kbqOverflowShadowBottom"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [KbqNotificationCenterAnimations.state], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
804
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
805
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: KbqNotificationCenterComponent, isStandalone: true, selector: "kbq-notification-center", host: { attributes: { "role": "dialog" }, listeners: { "keydown.escape": "escapeHandler($any($event))" }, properties: { "attr.id": "panelId", "attr.aria-labelledby": "titleId", "class.kbq-notification-center_popover": "popoverMode" }, classAttribute: "kbq-notification-center" }, providers: [
806
+ // The panel traps focus, so it needs a configurable trap even when it is imported standalone —
807
+ // these used to be reachable only through KbqNotificationCenterModule.
808
+ { provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
809
+ { provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
810
+ { provide: KBQ_NOTIFICATION_CENTER_PANEL, useExisting: forwardRef((() => KbqNotificationCenterComponent)) }
811
+ ], viewQueries: [{ propertyName: "switcher", first: true, predicate: ["notificationSwitcher"], descendants: true, isSignal: true }, { propertyName: "scrollContainer", first: true, predicate: KbqScrollbarViewport, descendants: true, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.KbqLocaleOverridesDirective }], ngImport: i0, template: "<!-- `display: contents` keeps the trap out of the panel's flex layout while still scoping the focus trap\nto everything the panel renders. -->\n<div class=\"kbq-notification-center__trap\" [cdkTrapFocus]=\"isTrapFocus\">\n <div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\" [id]=\"titleId\">\n {{ localeConfiguration().notifications }}\n </div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [attr.aria-label]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltip]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode() ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.empty()) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().removeAll\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().removeAll\"\n [kbqPlacement]=\"'bottom'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().close\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n </div>\n\n <!-- One persistent live region for the whole panel: a region inserted together with its text is\n not reliably announced, so only the text below ever changes. -->\n <div class=\"cdk-visually-hidden\" data-testid=\"kbq-notification-center-status\" role=\"status\" aria-live=\"polite\">\n {{ statusMessage }}\n </div>\n\n <div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbqScrollbarViewport\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [class.kbq-animations-disabled]=\"animationsDisabled\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n >\n @if (!service.errorMode()) {\n @if (!service.loadingMode()) {\n @for (group of service.groupedItems(); track group.id) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [attr.aria-label]=\"localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item.id) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore() && !service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-empty-container\"\n data-testid=\"kbq-notification-center-empty\"\n >\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeConfiguration().noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore()) {\n <div class=\"kbq-notification-center-load-more\" data-testid=\"kbq-notification-center-load-more\">\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n } @else if (service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n >\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.next()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n </div>\n\n <!-- `class` is KbqDropdown's own input: it moves the class onto the panel rendered in the overlay,\n which is where the check-mark width token has to be declared to reach the marks. -->\n <kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\" class=\"kbq-notification-center-switcher\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"service.silentMode()\"\n ></i>\n {{ localeConfiguration().showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"!service.silentMode()\"\n ></i>\n {{ localeConfiguration().doNotDisturb }}\n </button>\n </kbq-dropdown>\n</div>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:var(--kbq-notification-center-size-container-width);height:var(--kbq-notification-center-popover-height, 100vh);box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-notification-center-size-container-border-radius)}@supports (corner-shape: squircle){.kbq-notification-center.kbq-notification-center_popover{corner-shape:squircle;border-radius:clamp(var(--kbq-notification-center-size-container-border-radius) * 1.85,var(--kbq-notification-center-size-container-border-radius) * 2.3 - 3.6px,var(--kbq-notification-center-size-container-border-radius) * 2)}}.kbq-notification-center.kbq-notification-center_popover{height:var(--kbq-notification-center-popover-height, calc(100vh - var(--kbq-notification-center-size-navbar-height)));box-shadow:var(--kbq-notification-center-container-shadow)}.kbq-notification-center__trap{display:contents}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-switcher__mark{min-width:var(--kbq-notification-center-size-switcher-mark-width)}.kbq-notification-center-switcher__mark.kbq-notification-center-switcher__mark_hidden{visibility:hidden}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:var(--kbq-notification-center-sub-header-z-index);display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:flex;opacity:0;pointer-events:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{opacity:1;pointer-events:auto}.kbq-notification-center-container{--kbq-scrollbar-track-z-index: calc(var(--kbq-notification-center-sub-header-z-index) + 1);height:100%;overflow:auto;border-radius:inherit;corner-shape:inherit;padding-bottom:var(--kbq-size-xl);scroll-padding-top:var(--kbq-notification-center-size-sub-header-height);scroll-behavior:smooth}.kbq-notification-center-container.kbq-animations-disabled{scroll-behavior:auto}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit;corner-shape:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:var(--kbq-notification-center-size-load-more-padding-vertical) 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center{background:var(--kbq-notification-center-container-background)}.kbq-notification-center:not(.kbq-notification-center_popover){border-right-color:var(--kbq-notification-center-container-border-color);border-left-color:var(--kbq-notification-center-container-border-color)}.kbq-notification-center-sub-header{background:var(--kbq-notification-center-container-background)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-notification-center-error-text-color)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n", ".kbq-notification-center{--kbq-notification-center-size-container-width: 400px;--kbq-notification-center-size-navbar-height: var(--kbq-size-5xl);--kbq-notification-center-size-container-border-radius: var(--kbq-size-xs);--kbq-notification-center-sub-header-z-index: 2;--kbq-notification-center-size-sub-header-height: calc(var(--kbq-size-s) * 2 + var(--kbq-size-xl));--kbq-notification-center-size-item-icon-padding-top: calc(var(--kbq-size-m) + var(--kbq-size-3xs));--kbq-notification-center-size-item-time-padding-left: calc(var(--kbq-size-xl) + var(--kbq-size-3xs));--kbq-notification-center-size-load-more-padding-vertical: calc(var(--kbq-size-xxl) + var(--kbq-size-3xs));--kbq-notification-center-container-background: var(--kbq-background-card);--kbq-notification-center-container-border-color: var(--kbq-line-contrast-less);--kbq-notification-center-container-shadow: var(--kbq-shadow-popup);--kbq-notification-center-error-text-color: var(--kbq-foreground-error)}.kbq-notification-center-switcher{--kbq-notification-center-size-switcher-mark-width: var(--kbq-size-l)}\n"], dependencies: [{ kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i2.KbqIcon, selector: "[kbq-icon]", inputs: ["aria-hidden", "iconSize", "autoColor", "kbq-icon"] }, { kind: "component", type: i2.KbqIconItem, selector: "[kbq-icon-item]", inputs: ["kbq-icon-item", "fade", "big"] }, { kind: "ngmodule", type: KbqBadgeModule }, { kind: "directive", type: KbqScrollbarViewport, selector: "[kbqScrollbarViewport]", inputs: ["kbqScrollbarMode", "kbqScrollbarHideDelay"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "directive", type: i3$1.KbqButtonDropdownTrigger, selector: "[kbq-button][kbqDropdownTriggerFor]" }, { kind: "ngmodule", type: KbqDividerModule }, { kind: "component", type: i4.KbqDivider, selector: "kbq-divider", inputs: ["vertical", "paddings", "decorative", "length"] }, { kind: "ngmodule", type: KbqDropdownModule }, { kind: "component", type: i5.KbqDropdown, selector: "kbq-dropdown", inputs: ["activeDescendantNavigation", "navigationWithWrap", "xPosition", "yPosition", "overlapTriggerY", "overlapTriggerX", "hasBackdrop", "class", "backdropClass", "panelWidth", "panelMinWidth", "panelMaxWidth", "safeArea"], outputs: ["xPositionChange", "yPositionChange", "overlapTriggerYChange", "overlapTriggerXChange", "closed"], exportAs: ["kbqDropdown"] }, { kind: "component", type: i5.KbqDropdownItem, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: ["disabled", "progress"], exportAs: ["kbqDropdownItem"] }, { kind: "directive", type: i5.KbqDropdownTrigger, selector: "[kbqDropdownTriggerFor]", inputs: ["offsetX", "offsetY", "kbqDropdownTriggerData", "openByArrowDown", "kbqDropdownTriggerOrigin", "kbqDropdownTriggerAutoFocus", "kbqDropdownTriggerRestoreFocus", "kbqDropdownTriggerFor"], outputs: ["offsetXChange", "openByArrowDownChange", "kbqDropdownTriggerRestoreFocusChange", "dropdownOpened", "dropdownClosed"], exportAs: ["kbqDropdownTrigger"] }, { kind: "ngmodule", type: KbqToolTipModule }, { kind: "directive", type: i6.KbqTooltipTrigger, selector: "[kbqTooltip]", inputs: ["kbqTooltipScrollStrategy", "forDisabledComponent", "ignoreTooltipPointerEvents", "kbqTooltipSingleInstance", "kbqTrigger", "hideWithTimeout", "kbqEnterDelay", "kbqLeaveDelay", "kbqRelativeToPointer", "kbqRelativeToCaret", "kbqRelativeToCaretVertical", "kbqTooltip", "kbqTooltipHeader", "kbqTooltipModifier", "kbqTooltipContext", "kbqTooltipClass", "kbqTooltipColor", "kbqTooltipArrow", "kbqTooltipOffset", "kbqTooltipDisabled", "kbqPlacementPriority", "kbqPlacement", "kbqVisible"], outputs: ["kbqPlacementChange", "kbqVisibleChange"], exportAs: ["kbqTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: KbqNotificationItemComponent, selector: "kbq-notification-item", inputs: ["data"] }, { kind: "ngmodule", type: KbqLoaderOverlayModule }, { kind: "component", type: i7.KbqLoaderOverlay, selector: "kbq-loader-overlay", inputs: ["text", "caption", "size", "surface", "transparent", "card"] }, { kind: "ngmodule", type: KbqProgressSpinnerModule }, { kind: "component", type: i8.KbqProgressSpinner, selector: "kbq-progress-spinner", inputs: ["id", "value", "mode", "size"] }, { kind: "directive", type: KbqOverflowShadowContainer, selector: "[kbqOverflowShadowContainer]", inputs: ["debounce"], exportAs: ["kbqOverflowShadowContainer"] }, { kind: "directive", type: KbqOverflowShadowTop, selector: "[kbqOverflowShadowTop]", inputs: ["kbqOverflowShadowTop", "shadow"], exportAs: ["kbqOverflowShadowTop"] }, { kind: "directive", type: KbqOverflowShadowBottom, selector: "[kbqOverflowShadowBottom]", inputs: ["kbqOverflowShadowBottom", "shadow"], exportAs: ["kbqOverflowShadowBottom"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
476
812
  }
477
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterComponent, decorators: [{
813
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterComponent, decorators: [{
478
814
  type: Component,
479
815
  args: [{ selector: 'kbq-notification-center', imports: [
480
816
  KbqIconModule,
481
817
  KbqBadgeModule,
482
- KbqScrollbarModule,
818
+ KbqScrollbarViewport,
483
819
  KbqButtonModule,
484
820
  KbqDividerModule,
485
821
  KbqDropdownModule,
486
822
  KbqToolTipModule,
487
- AsyncPipe,
823
+ CdkTrapFocus,
488
824
  KbqNotificationItemComponent,
489
825
  KbqLoaderOverlayModule,
490
826
  KbqProgressSpinnerModule,
491
827
  KbqOverflowShadowContainer,
492
828
  KbqOverflowShadowTop,
493
829
  KbqOverflowShadowBottom
830
+ ], providers: [
831
+ // The panel traps focus, so it needs a configurable trap even when it is imported standalone —
832
+ // these used to be reachable only through KbqNotificationCenterModule.
833
+ { provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
834
+ { provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
835
+ { provide: KBQ_NOTIFICATION_CENTER_PANEL, useExisting: forwardRef((() => KbqNotificationCenterComponent)) }
494
836
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
495
837
  class: 'kbq-notification-center',
838
+ role: 'dialog',
839
+ '[attr.id]': 'panelId',
840
+ '[attr.aria-labelledby]': 'titleId',
496
841
  '[class.kbq-notification-center_popover]': 'popoverMode',
497
- '(keydown.escape)': 'escapeHandler()'
498
- }, animations: [KbqNotificationCenterAnimations.state], preserveWhitespaces: false, template: "<div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\">{{ localeData.notifications }}</div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [kbqTooltip]=\"service.silentMode.value ? localeData.doNotDisturb : localeData.showPopUpNotifications\"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.isEmpty) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"service.removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n</div>\n\n<div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbq-scrollbar\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n (onScroll)=\"onContainerScroll()\"\n>\n @if (!service.errorMode.value) {\n @if (!service.loadingMode.value) {\n @for (group of service.groupedItems | async; track group) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeData.remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"service.removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore.value) {\n <div class=\"kbq-notification-center-empty-container\" data-testid=\"kbq-notification-center-empty\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeData.noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore.value) {\n <div\n class=\"kbq-notification-center-load-more\"\n data-testid=\"kbq-notification-center-load-more\"\n role=\"status\"\n [attr.aria-label]=\"localeData.loadingMore\"\n >\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n }\n\n @if (service.loadMoreErrorMode.value) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n role=\"alert\"\n >\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" [transparent]=\"true\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.emit()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n</div>\n\n<kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i kbq-icon=\"{{ !service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.doNotDisturb }}\n </button>\n</kbq-dropdown>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:400px;height:100vh;box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-size-xs);height:calc(100vh - 48px);box-shadow:var(--kbq-shadow-popup)}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:100;display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{display:flex}.kbq-notification-center-container{height:100%;border-radius:inherit;padding-bottom:var(--kbq-size-xl)}.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:smooth}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:26px 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center,.kbq-notification-center-sub-header{background:var(--kbq-background-card)}.kbq-notification-center:not(.kbq-notification-center_popover),.kbq-notification-center-sub-header:not(.kbq-notification-center_popover){border-right-color:var(--kbq-line-contrast-less);border-left-color:var(--kbq-line-contrast-less)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-foreground-error)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n"] }]
499
- }], ctorParameters: () => [], propDecorators: { switcher: [{ type: i0.ViewChild, args: ['notificationSwitcher', { isSignal: true }] }], scrollContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqScrollbar), { isSignal: true }] }] } });
842
+ '(keydown.escape)': 'escapeHandler($any($event))'
843
+ }, hostDirectives: [KbqLocaleOverridesDirective], preserveWhitespaces: false, template: "<!-- `display: contents` keeps the trap out of the panel's flex layout while still scoping the focus trap\nto everything the panel renders. -->\n<div class=\"kbq-notification-center__trap\" [cdkTrapFocus]=\"isTrapFocus\">\n <div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\" [id]=\"titleId\">\n {{ localeConfiguration().notifications }}\n </div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [attr.aria-label]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltip]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode() ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.empty()) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().removeAll\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().removeAll\"\n [kbqPlacement]=\"'bottom'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().close\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n </div>\n\n <!-- One persistent live region for the whole panel: a region inserted together with its text is\n not reliably announced, so only the text below ever changes. -->\n <div class=\"cdk-visually-hidden\" data-testid=\"kbq-notification-center-status\" role=\"status\" aria-live=\"polite\">\n {{ statusMessage }}\n </div>\n\n <div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbqScrollbarViewport\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [class.kbq-animations-disabled]=\"animationsDisabled\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n >\n @if (!service.errorMode()) {\n @if (!service.loadingMode()) {\n @for (group of service.groupedItems(); track group.id) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [attr.aria-label]=\"localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item.id) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore() && !service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-empty-container\"\n data-testid=\"kbq-notification-center-empty\"\n >\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeConfiguration().noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore()) {\n <div class=\"kbq-notification-center-load-more\" data-testid=\"kbq-notification-center-load-more\">\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n } @else if (service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n >\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.next()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n </div>\n\n <!-- `class` is KbqDropdown's own input: it moves the class onto the panel rendered in the overlay,\n which is where the check-mark width token has to be declared to reach the marks. -->\n <kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\" class=\"kbq-notification-center-switcher\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"service.silentMode()\"\n ></i>\n {{ localeConfiguration().showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"!service.silentMode()\"\n ></i>\n {{ localeConfiguration().doNotDisturb }}\n </button>\n </kbq-dropdown>\n</div>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:var(--kbq-notification-center-size-container-width);height:var(--kbq-notification-center-popover-height, 100vh);box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-notification-center-size-container-border-radius)}@supports (corner-shape: squircle){.kbq-notification-center.kbq-notification-center_popover{corner-shape:squircle;border-radius:clamp(var(--kbq-notification-center-size-container-border-radius) * 1.85,var(--kbq-notification-center-size-container-border-radius) * 2.3 - 3.6px,var(--kbq-notification-center-size-container-border-radius) * 2)}}.kbq-notification-center.kbq-notification-center_popover{height:var(--kbq-notification-center-popover-height, calc(100vh - var(--kbq-notification-center-size-navbar-height)));box-shadow:var(--kbq-notification-center-container-shadow)}.kbq-notification-center__trap{display:contents}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-switcher__mark{min-width:var(--kbq-notification-center-size-switcher-mark-width)}.kbq-notification-center-switcher__mark.kbq-notification-center-switcher__mark_hidden{visibility:hidden}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:var(--kbq-notification-center-sub-header-z-index);display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:flex;opacity:0;pointer-events:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{opacity:1;pointer-events:auto}.kbq-notification-center-container{--kbq-scrollbar-track-z-index: calc(var(--kbq-notification-center-sub-header-z-index) + 1);height:100%;overflow:auto;border-radius:inherit;corner-shape:inherit;padding-bottom:var(--kbq-size-xl);scroll-padding-top:var(--kbq-notification-center-size-sub-header-height);scroll-behavior:smooth}.kbq-notification-center-container.kbq-animations-disabled{scroll-behavior:auto}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit;corner-shape:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:var(--kbq-notification-center-size-load-more-padding-vertical) 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center{background:var(--kbq-notification-center-container-background)}.kbq-notification-center:not(.kbq-notification-center_popover){border-right-color:var(--kbq-notification-center-container-border-color);border-left-color:var(--kbq-notification-center-container-border-color)}.kbq-notification-center-sub-header{background:var(--kbq-notification-center-container-background)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-notification-center-error-text-color)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n", ".kbq-notification-center{--kbq-notification-center-size-container-width: 400px;--kbq-notification-center-size-navbar-height: var(--kbq-size-5xl);--kbq-notification-center-size-container-border-radius: var(--kbq-size-xs);--kbq-notification-center-sub-header-z-index: 2;--kbq-notification-center-size-sub-header-height: calc(var(--kbq-size-s) * 2 + var(--kbq-size-xl));--kbq-notification-center-size-item-icon-padding-top: calc(var(--kbq-size-m) + var(--kbq-size-3xs));--kbq-notification-center-size-item-time-padding-left: calc(var(--kbq-size-xl) + var(--kbq-size-3xs));--kbq-notification-center-size-load-more-padding-vertical: calc(var(--kbq-size-xxl) + var(--kbq-size-3xs));--kbq-notification-center-container-background: var(--kbq-background-card);--kbq-notification-center-container-border-color: var(--kbq-line-contrast-less);--kbq-notification-center-container-shadow: var(--kbq-shadow-popup);--kbq-notification-center-error-text-color: var(--kbq-foreground-error)}.kbq-notification-center-switcher{--kbq-notification-center-size-switcher-mark-width: var(--kbq-size-l)}\n"] }]
844
+ }], ctorParameters: () => [], propDecorators: { switcher: [{ type: i0.ViewChild, args: ['notificationSwitcher', { isSignal: true }] }], scrollContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqScrollbarViewport), { isSignal: true }] }] } });
500
845
  class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
501
- /** Number of unread notifications */
846
+ /** Number of unread notifications, formatted for the trigger badge. */
502
847
  get unreadItemsCounter() {
503
848
  return this.service.unreadItemsCounter;
504
849
  }
505
850
  /** Use popover or not */
506
- // TODO: Skipped for migration because:
507
- // Accessor inputs cannot be migrated as they are too complex.
508
851
  get popoverMode() {
509
852
  return this._popoverMode;
510
853
  }
511
854
  set popoverMode(value) {
855
+ if (value === this._popoverMode) {
856
+ return;
857
+ }
512
858
  this._popoverMode = value;
513
- this.placement = PopUpPlacements.Bottom;
514
- this.updatePlacementPriority(['bottomCenter', 'bottomLeft', 'bottomRight']);
859
+ // The placement in force before the mode took over is remembered rather than assumed: a consumer
860
+ // may have bound one of its own, and turning the mode off used to leave the popover placement
861
+ // behind for good.
862
+ if (value) {
863
+ this.placementBeforePopoverMode = { placement: this.placement, priority: this.placementPriority };
864
+ this.placement = PopUpPlacements.Bottom;
865
+ this.updatePlacementPriority(['bottomCenter', 'bottomLeft', 'bottomRight']);
866
+ }
867
+ else if (this.placementBeforePopoverMode) {
868
+ this.placement = this.placementBeforePopoverMode.placement;
869
+ this.updatePlacementPriority(this.placementBeforePopoverMode.priority);
870
+ this.placementBeforePopoverMode = null;
871
+ }
515
872
  }
516
- /** Set height of popover. Default is calc(100vh - 48px). 48px - height of navbar */
517
- // TODO: Skipped for migration because:
518
- // Accessor inputs cannot be migrated as they are too complex.
873
+ /** Set height of popover. Default is `calc(100vh - <navbar height>)`. */
519
874
  get popoverHeight() {
520
875
  return this._popoverHeight;
521
876
  }
522
877
  set popoverHeight(value) {
523
878
  this._popoverHeight = value;
524
- if (this.instance?.popoverHeight) {
879
+ // Guarding on the open panel, not on its current height: the previous `instance?.popoverHeight`
880
+ // check made the first set a no-op and made clearing the height impossible.
881
+ if (this.instance) {
525
882
  this.instance.popoverHeight = value;
526
883
  }
527
884
  }
528
885
  /** Whether the trigger is disabled. */
529
- // TODO: Skipped for migration because:
530
- // Accessor inputs cannot be migrated as they are too complex.
531
886
  get disabled() {
532
887
  return this._disabled;
533
888
  }
@@ -544,64 +899,103 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
544
899
  /** @docs-private */
545
900
  get overlayConfig() {
546
901
  const defaultPanelClass = 'kbq-notification-center__panel';
902
+ const panelClass = this.panelClass();
547
903
  return {
548
- panelClass: this.panelClass ? [defaultPanelClass, this.panelClass] : defaultPanelClass,
549
- hasBackdrop: this.hasBackdrop,
550
- backdropClass: this.backdropClass
904
+ panelClass: panelClass ? [defaultPanelClass, panelClass] : defaultPanelClass,
905
+ hasBackdrop: false,
906
+ backdropClass: this.backdropClass()
551
907
  };
552
908
  }
909
+ ngOnChanges(changes) {
910
+ // A bound input is handed to its member, a bound `undefined` as the member's default; unbound, it leaves
911
+ // what code wrote.
912
+ if (changes['placementInput']) {
913
+ this.placement = this.placementInput() ?? defaultPlacement;
914
+ }
915
+ if (changes['popoverModeInput']) {
916
+ const popoverMode = this.popoverModeInput();
917
+ if (popoverMode !== undefined)
918
+ this.popoverMode = popoverMode;
919
+ }
920
+ if (changes['popoverHeightInput']) {
921
+ this.popoverHeight = this.popoverHeightInput() ?? '';
922
+ }
923
+ if (changes['stickToWindowInput']) {
924
+ this.stickToWindow = this.stickToWindowInput();
925
+ }
926
+ if (changes['containerInput']) {
927
+ this.container = this.containerInput();
928
+ }
929
+ if (changes['disabledInput']) {
930
+ const disabled = this.disabledInput();
931
+ if (disabled !== undefined)
932
+ this.disabled = disabled;
933
+ }
934
+ }
553
935
  constructor() {
554
936
  super();
555
937
  /** @docs-private */
556
938
  this.scrollStrategy = inject(KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY);
557
939
  /** @docs-private */
558
940
  this.service = inject(KbqNotificationCenterService);
559
- // not used
560
- /** @docs-private */
941
+ /**
942
+ * Id handed to the panel so `aria-controls` can point at it while it is open.
943
+ *
944
+ * @docs-private
945
+ */
946
+ this.panelId = inject(_IdGenerator).getId('kbq-notification-center-panel-');
947
+ /**
948
+ * Not used.
949
+ *
950
+ * @docs-private
951
+ */
561
952
  this.arrow = false;
562
- /** @docs-private */
563
- this.hasBackdrop = false;
564
- /** @docs-private */
565
- this.size = PopUpSizes.Medium;
566
953
  /** Placement of popUp */
567
- // TODO: Skipped for migration because:
568
- // Your application code writes to the input. This prevents migration.
569
- this.placement = PopUpPlacements.Right;
954
+ this.placement = defaultPlacement;
570
955
  /** Class that will be used in the background */
571
- // TODO: Skipped for migration because:
572
- // Class of this input is referenced in the signature of another class.
573
- this.backdropClass = 'cdk-overlay-transparent-backdrop';
956
+ this.backdropClass = input('cdk-overlay-transparent-backdrop', ...(ngDevMode ? [{ debugName: "backdropClass" }] : /* istanbul ignore next */ []));
957
+ /** Class that will be used in the panel */
958
+ this.panelClass = input('', { ...(ngDevMode ? { debugName: "panelClass" } : /* istanbul ignore next */ {}), alias: 'kbqNotificationCenterPanelClass' });
574
959
  /** Offset of popUp */
575
- // TODO: Skipped for migration because:
576
- // Class of this input is referenced in the signature of another class.
577
- this.offset = defaultOffsetX;
960
+ this.offset = input(defaultOffsetX, { ...(ngDevMode ? { debugName: "offset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
578
961
  /** Distance in pixels from the bottom of the list at which the next page is requested via `onNextPage`. */
579
- this.scrolledToBottomOffset = 0;
962
+ this.scrolledToBottomOffset = input(0, { ...(ngDevMode ? { debugName: "scrolledToBottomOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
963
+ /** Placement and priority in force before `popoverMode` replaced them. */
964
+ this.placementBeforePopoverMode = null;
580
965
  this._popoverMode = false;
581
966
  /** Emits a change event whenever the placement state changes. */
582
967
  this.placementChange = new EventEmitter();
968
+ /** @docs-private */
969
+ this.placementChangeOutput = outputFromObservable(this.placementChange, { alias: 'kbqPlacementChange' });
583
970
  /** Emits a change event whenever the visible state changes. */
584
971
  this.visibleChange = new EventEmitter();
585
972
  /** @docs-private */
973
+ this.visibleChangeOutput = outputFromObservable(this.visibleChange, { alias: 'kbqVisibleChange' });
974
+ /** @docs-private */
586
975
  this.trigger = `${PopUpTriggers.Click}, ${PopUpTriggers.Keydown}`;
587
976
  /** @docs-private */
588
977
  this.originSelector = '.kbq-notification-center';
978
+ /** @docs-private */
979
+ this.placementInput = input(undefined, { ...(ngDevMode ? { debugName: "placementInput" } : /* istanbul ignore next */ {}), alias: 'kbqNotificationCenterPlacement' });
980
+ /** @docs-private */
981
+ this.popoverModeInput = input(undefined, { ...(ngDevMode ? { debugName: "popoverModeInput" } : /* istanbul ignore next */ {}), alias: 'popoverMode',
982
+ transform: booleanAttribute });
983
+ /** @docs-private */
984
+ this.popoverHeightInput = input(undefined, { ...(ngDevMode ? { debugName: "popoverHeightInput" } : /* istanbul ignore next */ {}), alias: 'popoverHeight' });
985
+ /** @docs-private */
986
+ this.stickToWindowInput = input(undefined, { ...(ngDevMode ? { debugName: "stickToWindowInput" } : /* istanbul ignore next */ {}), alias: 'stickToWindow' });
987
+ /** @docs-private */
988
+ this.containerInput = input(undefined, { ...(ngDevMode ? { debugName: "containerInput" } : /* istanbul ignore next */ {}), alias: 'container' });
989
+ /** @docs-private */
990
+ this.disabledInput = input(undefined, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled',
991
+ transform: booleanAttribute });
589
992
  this.updatePlacementPriority(['right', 'rightBottom', 'rightTop']);
590
993
  }
591
994
  ngAfterContentInit() {
995
+ // On close, return focus to the trigger. Suppressing the close on an inner scroll lives in
996
+ // `closingActions()`, so no per-visibility subscription is needed here.
592
997
  this.visibleChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((visible) => {
593
- if (visible) {
594
- // eslint-disable-next-line rxjs-x/no-nested-subscribe
595
- this.preventClosingByInnerScrollSubscription = this.closingActions().subscribe((event) => {
596
- if (event && event['scrollDispatcher']) {
597
- this.instance.setStickPosition();
598
- event['kbqPopoverPreventHide'] = true;
599
- event['type'] = 'click';
600
- }
601
- });
602
- }
603
- else {
604
- this.preventClosingByInnerScrollSubscription?.unsubscribe();
998
+ if (!visible) {
605
999
  this.focus();
606
1000
  }
607
1001
  });
@@ -610,22 +1004,24 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
610
1004
  updateData() {
611
1005
  if (!this.instance)
612
1006
  return;
613
- this.instance.header = this.header;
1007
+ this.instance.panelId = this.panelId;
614
1008
  this.instance.content = this.content;
615
1009
  this.instance.arrow = this.arrow;
616
- this.instance.offset = this.offset;
617
- this.instance.footer = this.footer;
1010
+ this.instance.offset = this.offset();
618
1011
  this.instance.popoverMode = this.popoverMode;
619
1012
  this.instance.popoverHeight = this.popoverHeight;
620
- this.instance.scrolledToBottomOffset = this.scrolledToBottomOffset;
1013
+ this.instance.scrolledToBottomOffset = this.scrolledToBottomOffset();
621
1014
  this.instance.updateTrapFocus(this.trigger !== PopUpTriggers.Focus);
1015
+ this.instance.detectChanges();
622
1016
  if (this.isOpen) {
623
1017
  this.updatePosition(true);
624
1018
  }
625
1019
  }
626
- /** Updates the current position.
1020
+ /**
1021
+ * Updates the current position.
627
1022
  *
628
- * @docs-private */
1023
+ * @docs-private
1024
+ */
629
1025
  updatePosition(reapplyPosition = false) {
630
1026
  this.overlayRef = this.createOverlay();
631
1027
  const position = this.overlayRef.getConfig().positionStrategy
@@ -643,84 +1039,58 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
643
1039
  updateClassMap(newPlacement = this.placement) {
644
1040
  if (!this.instance)
645
1041
  return;
646
- this.instance.updateClassMap(POSITION_TO_CSS_MAP[newPlacement], this.customClass, this.size);
647
- this.instance.markForCheck();
1042
+ this.instance.updateClassMap(POSITION_TO_CSS_MAP[newPlacement], this.customClass, PopUpSizes.Medium);
648
1043
  }
649
1044
  /** @docs-private */
650
1045
  closingActions() {
651
- return merge(this.overlayRef.outsidePointerEvents(), this.overlayRef.backdropClick(), this.scrollDispatcher.scrolled());
1046
+ return merge(this.overlayRef.outsidePointerEvents(), this.overlayRef.backdropClick(),
1047
+ // Only a scroll outside the panel should close it. The list viewport is a `CdkScrollable`,
1048
+ // so its own scrolling reaches the root `ScrollDispatcher` too — filtering it out here is
1049
+ // what keeps the panel open, instead of tagging the shared scrollable with a "prevent hide"
1050
+ // flag that would then follow it around the whole application.
1051
+ this.scrollDispatcher.scrolled().pipe(filter((scrollable) => !this.isInnerScroll(scrollable))));
652
1052
  }
653
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
654
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.30", type: KbqNotificationCenterTrigger, isStandalone: true, selector: "[kbqNotificationCenterTrigger]", inputs: { placement: ["kbqNotificationCenterPlacement", "placement"], backdropClass: "backdropClass", panelClass: ["kbqNotificationCenterPanelClass", "panelClass"], offset: ["offset", "offset", numberAttribute], scrolledToBottomOffset: ["scrolledToBottomOffset", "scrolledToBottomOffset", numberAttribute], popoverMode: ["popoverMode", "popoverMode", booleanAttribute], popoverHeight: "popoverHeight", disabled: ["disabled", "disabled", booleanAttribute], stickToWindow: "stickToWindow", container: "container" }, outputs: { placementChange: "kbqPlacementChange", visibleChange: "kbqVisibleChange" }, host: { properties: { "class.kbq-notification-center_open": "isOpen", "class.kbq-active": "hasClickTrigger && isOpen" } }, providers: [kbqSiblingPopupProvider(KbqNotificationCenterTrigger)], exportAs: ["kbqNotificationCenterTrigger"], usesInheritance: true, ngImport: i0 }); }
1053
+ /** Whether a `ScrollDispatcher` emission originates from inside this panel's own scrollable content. */
1054
+ isInnerScroll(scrollable) {
1055
+ return (scrollable instanceof CdkScrollable &&
1056
+ !!scrollable.getElementRef().nativeElement.closest('.kbq-notification-center'));
1057
+ }
1058
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1059
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.25", type: KbqNotificationCenterTrigger, isStandalone: true, selector: "[kbqNotificationCenterTrigger]", inputs: { backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "kbqNotificationCenterPanelClass", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, scrolledToBottomOffset: { classPropertyName: "scrolledToBottomOffset", publicName: "scrolledToBottomOffset", isSignal: true, isRequired: false, transformFunction: null }, placementInput: { classPropertyName: "placementInput", publicName: "kbqNotificationCenterPlacement", isSignal: true, isRequired: false, transformFunction: null }, popoverModeInput: { classPropertyName: "popoverModeInput", publicName: "popoverMode", isSignal: true, isRequired: false, transformFunction: null }, popoverHeightInput: { classPropertyName: "popoverHeightInput", publicName: "popoverHeight", isSignal: true, isRequired: false, transformFunction: null }, stickToWindowInput: { classPropertyName: "stickToWindowInput", publicName: "stickToWindow", isSignal: true, isRequired: false, transformFunction: null }, containerInput: { classPropertyName: "containerInput", publicName: "container", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { placementChangeOutput: "kbqPlacementChange", visibleChangeOutput: "kbqVisibleChange" }, host: { properties: { "class.kbq-notification-center_open": "isOpen", "class.kbq-active": "hasClickTrigger && isOpen", "attr.aria-expanded": "isOpen", "attr.aria-controls": "isOpen ? panelId : null" } }, providers: [kbqSiblingPopupProvider(KbqNotificationCenterTrigger)], exportAs: ["kbqNotificationCenterTrigger"], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
655
1060
  }
656
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterTrigger, decorators: [{
1061
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterTrigger, decorators: [{
657
1062
  type: Directive,
658
1063
  args: [{
659
1064
  selector: '[kbqNotificationCenterTrigger]',
660
1065
  providers: [kbqSiblingPopupProvider(KbqNotificationCenterTrigger)],
661
1066
  host: {
662
1067
  '[class.kbq-notification-center_open]': 'isOpen',
663
- '[class.kbq-active]': 'hasClickTrigger && isOpen'
1068
+ '[class.kbq-active]': 'hasClickTrigger && isOpen',
1069
+ '[attr.aria-expanded]': 'isOpen',
1070
+ '[attr.aria-controls]': 'isOpen ? panelId : null'
664
1071
  },
665
1072
  exportAs: 'kbqNotificationCenterTrigger'
666
1073
  }]
667
- }], ctorParameters: () => [], propDecorators: { placement: [{
668
- type: Input,
669
- args: ['kbqNotificationCenterPlacement']
670
- }], backdropClass: [{
671
- type: Input
672
- }], panelClass: [{
673
- type: Input,
674
- args: ['kbqNotificationCenterPanelClass']
675
- }], offset: [{
676
- type: Input,
677
- args: [{ transform: numberAttribute }]
678
- }], scrolledToBottomOffset: [{
679
- type: Input,
680
- args: [{ transform: numberAttribute }]
681
- }], popoverMode: [{
682
- type: Input,
683
- args: [{ transform: booleanAttribute }]
684
- }], popoverHeight: [{
685
- type: Input
686
- }], disabled: [{
687
- type: Input,
688
- args: [{ transform: booleanAttribute }]
689
- }], stickToWindow: [{
690
- type: Input
691
- }], container: [{
692
- type: Input
693
- }], placementChange: [{
694
- type: Output,
695
- args: ['kbqPlacementChange']
696
- }], visibleChange: [{
697
- type: Output,
698
- args: ['kbqVisibleChange']
699
- }] } });
1074
+ }], ctorParameters: () => [], propDecorators: { backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "kbqNotificationCenterPanelClass", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], scrolledToBottomOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrolledToBottomOffset", required: false }] }], placementChangeOutput: [{ type: i0.Output, args: ["kbqPlacementChange"] }], visibleChangeOutput: [{ type: i0.Output, args: ["kbqVisibleChange"] }], placementInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "kbqNotificationCenterPlacement", required: false }] }], popoverModeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverMode", required: false }] }], popoverHeightInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverHeight", required: false }] }], stickToWindowInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickToWindow", required: false }] }], containerInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
700
1075
 
1076
+ /**
1077
+ * Compatibility wrapper around the standalone notification center. Importing
1078
+ * `KbqNotificationCenterTrigger` directly is equivalent.
1079
+ */
701
1080
  class KbqNotificationCenterModule {
702
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
703
- /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterModule, imports: [KbqNotificationCenterComponent,
1081
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1082
+ /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, imports: [KbqNotificationCenterComponent,
704
1083
  KbqNotificationCenterTrigger], exports: [KbqNotificationCenterComponent,
705
1084
  KbqNotificationCenterTrigger] }); }
706
- /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterModule, providers: [
707
- { provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
708
- { provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
709
- KbqNotificationCenterService
710
- ], imports: [KbqNotificationCenterComponent] }); }
1085
+ /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, imports: [KbqNotificationCenterComponent] }); }
711
1086
  }
712
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqNotificationCenterModule, decorators: [{
1087
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, decorators: [{
713
1088
  type: NgModule,
714
1089
  args: [{
715
1090
  imports: [
716
1091
  KbqNotificationCenterComponent,
717
1092
  KbqNotificationCenterTrigger
718
1093
  ],
719
- providers: [
720
- { provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
721
- { provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
722
- KbqNotificationCenterService
723
- ],
724
1094
  exports: [
725
1095
  KbqNotificationCenterComponent,
726
1096
  KbqNotificationCenterTrigger
@@ -732,5 +1102,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
732
1102
  * Generated bundle index. Do not edit.
733
1103
  */
734
1104
 
735
- export { KBQ_NOTIFICATION_CENTER_CONFIGURATION, KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION, KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY, KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY_FACTORY_PROVIDER, KbqNotificationCenterAnimations, KbqNotificationCenterComponent, KbqNotificationCenterModule, KbqNotificationCenterService, KbqNotificationCenterTrigger, kbqNotificationCenterScrollStrategyFactory, maxUnreadItemsLength };
1105
+ export { KBQ_NOTIFICATION_CENTER_CONFIGURATION, KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION, KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION, KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION, KBQ_NOTIFICATION_CENTER_PANEL, KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY, KbqNotificationCenterComponent, KbqNotificationCenterModule, KbqNotificationCenterService, KbqNotificationCenterTrigger, kbqNotificationCenterLocaleConfigurationProvider, kbqNotificationCenterScrollStrategyFactory, maxUnreadItemsLength };
736
1106
  //# sourceMappingURL=koobiq-components-notification-center.mjs.map