@koobiq/components 20.0.0 → 20.1.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 (192) hide show
  1. package/accordion/accordion-trigger.component.scss +0 -18
  2. package/accordion/accordion.component.scss +9 -2
  3. package/actions-panel/index.d.ts +1 -0
  4. package/alert/_alert-theme.scss +0 -4
  5. package/alert/alert-tokens.scss +4 -4
  6. package/app-switcher/app-switcher-dropdown-app.scss +2 -0
  7. package/breadcrumbs/breadcrumbs.scss +4 -0
  8. package/breadcrumbs/index.d.ts +2 -1
  9. package/button/button-group.scss +42 -2
  10. package/button-toggle/button-toggle.scss +23 -0
  11. package/button-toggle/index.d.ts +3 -1
  12. package/checkbox/checkbox.scss +5 -4
  13. package/clamped-text/index.d.ts +1 -0
  14. package/core/index.d.ts +402 -13
  15. package/core/styles/common/_animation.scss +4 -0
  16. package/core/styles/theming/_components-theming.scss +1 -1
  17. package/core/styles/theming/_scrollbar-theme.scss +4 -0
  18. package/datepicker/_datepicker-theme.scss +1 -1
  19. package/datepicker/datepicker-toggle.scss +3 -3
  20. package/dl/index.d.ts +1 -0
  21. package/dropdown/dropdown.scss +2 -2
  22. package/fesm2022/koobiq-components-accordion.mjs +4 -4
  23. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  24. package/fesm2022/koobiq-components-actions-panel.mjs +14 -5
  25. package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
  26. package/fesm2022/koobiq-components-alert.mjs +2 -2
  27. package/fesm2022/koobiq-components-alert.mjs.map +1 -1
  28. package/fesm2022/koobiq-components-app-switcher.mjs +6 -6
  29. package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
  30. package/fesm2022/koobiq-components-breadcrumbs.mjs +6 -4
  31. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  32. package/fesm2022/koobiq-components-button-toggle.mjs +9 -6
  33. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  34. package/fesm2022/koobiq-components-button.mjs +4 -4
  35. package/fesm2022/koobiq-components-button.mjs.map +1 -1
  36. package/fesm2022/koobiq-components-checkbox.mjs +2 -2
  37. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  38. package/fesm2022/koobiq-components-clamped-text.mjs +4 -0
  39. package/fesm2022/koobiq-components-clamped-text.mjs.map +1 -1
  40. package/fesm2022/koobiq-components-code-block.mjs +4 -0
  41. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  42. package/fesm2022/koobiq-components-core.mjs +449 -112
  43. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  44. package/fesm2022/koobiq-components-datepicker.mjs +5 -5
  45. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  46. package/fesm2022/koobiq-components-dl.mjs +3 -2
  47. package/fesm2022/koobiq-components-dl.mjs.map +1 -1
  48. package/fesm2022/koobiq-components-dropdown.mjs +8 -13
  49. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  50. package/fesm2022/koobiq-components-file-upload.mjs +33 -22
  51. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  52. package/fesm2022/koobiq-components-filter-bar.mjs +974 -758
  53. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  54. package/fesm2022/koobiq-components-flag.mjs +66 -0
  55. package/fesm2022/koobiq-components-flag.mjs.map +1 -0
  56. package/fesm2022/koobiq-components-form-field.mjs +2 -2
  57. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  58. package/fesm2022/koobiq-components-icon.mjs +2 -2
  59. package/fesm2022/koobiq-components-icon.mjs.map +1 -1
  60. package/fesm2022/koobiq-components-inline-edit.mjs +27 -6
  61. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  62. package/fesm2022/koobiq-components-list.mjs +39 -20
  63. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  64. package/fesm2022/koobiq-components-loader-overlay.mjs +2 -2
  65. package/fesm2022/koobiq-components-loader-overlay.mjs.map +1 -1
  66. package/fesm2022/koobiq-components-modal.mjs +9 -5
  67. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  68. package/fesm2022/koobiq-components-navbar.mjs +10 -9
  69. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  70. package/fesm2022/koobiq-components-notification-center.mjs +178 -19
  71. package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
  72. package/fesm2022/koobiq-components-overflow-items.mjs +12 -4
  73. package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
  74. package/fesm2022/koobiq-components-popover.mjs +4 -4
  75. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  76. package/fesm2022/koobiq-components-progress-bar.mjs +2 -2
  77. package/fesm2022/koobiq-components-progress-bar.mjs.map +1 -1
  78. package/fesm2022/koobiq-components-progress-spinner.mjs +2 -2
  79. package/fesm2022/koobiq-components-progress-spinner.mjs.map +1 -1
  80. package/fesm2022/koobiq-components-radio.mjs +3 -7
  81. package/fesm2022/koobiq-components-radio.mjs.map +1 -1
  82. package/fesm2022/koobiq-components-select.mjs +38 -16
  83. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  84. package/fesm2022/koobiq-components-sidebar.mjs +4 -0
  85. package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
  86. package/fesm2022/koobiq-components-sidepanel.mjs +3 -3
  87. package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
  88. package/fesm2022/koobiq-components-skeleton.mjs +2 -2
  89. package/fesm2022/koobiq-components-skeleton.mjs.map +1 -1
  90. package/fesm2022/koobiq-components-split-button.mjs +2 -2
  91. package/fesm2022/koobiq-components-split-button.mjs.map +1 -1
  92. package/fesm2022/koobiq-components-splitter.mjs +6 -2
  93. package/fesm2022/koobiq-components-splitter.mjs.map +1 -1
  94. package/fesm2022/koobiq-components-table.mjs +8 -6
  95. package/fesm2022/koobiq-components-table.mjs.map +1 -1
  96. package/fesm2022/koobiq-components-tabs.mjs +19 -7
  97. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  98. package/fesm2022/koobiq-components-tags.mjs +7 -0
  99. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  100. package/fesm2022/koobiq-components-textarea.mjs +7 -14
  101. package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
  102. package/fesm2022/koobiq-components-time-range.mjs +4 -4
  103. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  104. package/fesm2022/koobiq-components-timezone.mjs +6 -0
  105. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  106. package/fesm2022/koobiq-components-title.mjs +132 -14
  107. package/fesm2022/koobiq-components-title.mjs.map +1 -1
  108. package/fesm2022/koobiq-components-toast.mjs +1 -1
  109. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  110. package/fesm2022/koobiq-components-toggle.mjs +2 -2
  111. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  112. package/fesm2022/koobiq-components-tooltip.mjs +50 -2
  113. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  114. package/fesm2022/koobiq-components-tree-select.mjs +44 -11
  115. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  116. package/fesm2022/koobiq-components-tree.mjs +67 -41
  117. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  118. package/fesm2022/koobiq-components-username.mjs +16 -3
  119. package/fesm2022/koobiq-components-username.mjs.map +1 -1
  120. package/file-upload/file-upload-tokens.scss +1 -0
  121. package/file-upload/index.d.ts +10 -7
  122. package/filter-bar/_filter-bar-theme.scss +86 -0
  123. package/filter-bar/filter-bar-tokens.scss +6 -0
  124. package/filter-bar/filter-bar.scss +10 -4
  125. package/filter-bar/filter-refresher.scss +1 -1
  126. package/filter-bar/filters.scss +23 -19
  127. package/filter-bar/index.d.ts +707 -338
  128. package/filter-bar/pipes/base-pipe.scss +14 -35
  129. package/filter-bar/pipes/pipe-date.scss +20 -14
  130. package/filter-bar/pipes/pipe-multi-tree-select.scss +5 -3
  131. package/filter-bar/pipes/pipe-multiselect.scss +5 -3
  132. package/filter-bar/pipes/pipe-readonly.scss +4 -13
  133. package/filter-bar/pipes/pipe-select.scss +3 -1
  134. package/filter-bar/pipes/pipe-tree-select.scss +3 -1
  135. package/flag/flag.scss +53 -0
  136. package/flag/index.d.ts +44 -0
  137. package/icon/icon-item-tokens.scss +1 -1
  138. package/inline-edit/index.d.ts +5 -0
  139. package/inline-edit/inline-edit.scss +7 -7
  140. package/link/link-tokens.scss +2 -2
  141. package/list/index.d.ts +11 -2
  142. package/loader-overlay/loader-overlay-tokens.scss +1 -1
  143. package/modal/_modal-animation.scss +6 -6
  144. package/modal/_modal-theme.scss +5 -0
  145. package/modal/index.d.ts +3 -1
  146. package/modal/modal.scss +15 -0
  147. package/navbar/index.d.ts +1 -0
  148. package/navbar/navbar-item.scss +9 -0
  149. package/notification-center/_notification-center-theme.scss +2 -1
  150. package/notification-center/index.d.ts +88 -3
  151. package/notification-center/notification-center.scss +42 -4
  152. package/notification-center/notification-item.scss +3 -2
  153. package/overflow-items/index.d.ts +1 -0
  154. package/package.json +7 -3
  155. package/prebuilt-themes/dark-theme.css +1 -1
  156. package/prebuilt-themes/light-theme.css +1 -1
  157. package/prebuilt-themes/theme.css +1 -1
  158. package/progress-bar/progress-bar.scss +4 -0
  159. package/progress-spinner/progress-spinner.scss +5 -1
  160. package/radio/index.d.ts +1 -5
  161. package/radio/radio.scss +18 -4
  162. package/schematics/collection.json +5 -0
  163. package/schematics/migrations/filter-bar-signals/README.md +66 -0
  164. package/schematics/migrations/filter-bar-signals/data.js +72 -0
  165. package/schematics/migrations/filter-bar-signals/index.js +316 -0
  166. package/schematics/migrations/filter-bar-signals/schema.json +20 -0
  167. package/schematics/migrations.json +5 -0
  168. package/schematics/ng-add/index.js +1 -1
  169. package/select/index.d.ts +10 -2
  170. package/sidebar/index.d.ts +1 -0
  171. package/skeleton/skeleton.scss +4 -0
  172. package/split-button/_split-button-theme.scss +2 -2
  173. package/splitter/_splitter-theme.scss +2 -2
  174. package/splitter/index.d.ts +1 -0
  175. package/table/_table-theme.scss +4 -0
  176. package/table/index.d.ts +3 -2
  177. package/tabs/index.d.ts +2 -0
  178. package/tabs/tab-header.scss +1 -0
  179. package/tabs/tabs-tokens.scss +1 -1
  180. package/textarea/index.d.ts +0 -1
  181. package/time-range/time-range.scss +0 -8
  182. package/timepicker/timepicker.scss +2 -2
  183. package/timezone/index.d.ts +1 -0
  184. package/title/index.d.ts +92 -2
  185. package/tooltip/index.d.ts +51 -3
  186. package/tree/_tree-theme.scss +2 -7
  187. package/tree/index.d.ts +19 -4
  188. package/tree/toggle.scss +5 -0
  189. package/tree/tree-option.scss +0 -4
  190. package/tree-select/_tree-select-theme.scss +1 -1
  191. package/tree-select/index.d.ts +9 -2
  192. package/username/index.d.ts +20 -2
@@ -17,14 +17,16 @@ import * as i1 from '@koobiq/components/icon';
17
17
  import { KbqIconModule } from '@koobiq/components/icon';
18
18
  import * as i7 from '@koobiq/components/loader-overlay';
19
19
  import { KbqLoaderOverlayModule } from '@koobiq/components/loader-overlay';
20
+ import * as i8 from '@koobiq/components/progress-spinner';
21
+ import { KbqProgressSpinnerModule } from '@koobiq/components/progress-spinner';
20
22
  import * as i2 from '@koobiq/components/scrollbar';
21
- import { KbqScrollbarModule } from '@koobiq/components/scrollbar';
23
+ import { KbqScrollbar, KbqScrollbarModule } from '@koobiq/components/scrollbar';
22
24
  import * as i6 from '@koobiq/components/tooltip';
23
25
  import { KbqTooltipTrigger, KbqToolTipModule } from '@koobiq/components/tooltip';
24
- import { combineLatestWith, BehaviorSubject, merge } from 'rxjs';
26
+ import { combineLatestWith, BehaviorSubject, merge, Subject } from 'rxjs';
27
+ import { map, filter, auditTime, distinctUntilChanged, pairwise } from 'rxjs/operators';
25
28
  import { trigger, state, transition, style, animate } from '@angular/animations';
26
29
  import { KbqToastService } from '@koobiq/components/toast';
27
- import { map, filter } from 'rxjs/operators';
28
30
  import * as i3 from '@koobiq/components/title';
29
31
  import { KbqTitleModule } from '@koobiq/components/title';
30
32
  import { ConfigurableFocusTrapFactory, FocusTrapFactory, FOCUS_TRAP_INERT_STRATEGY } from '@angular/cdk/a11y';
@@ -82,25 +84,53 @@ class KbqNotificationCenterService {
82
84
  this.loadingMode = new BehaviorSubject(false);
83
85
  /** @docs-private */
84
86
  this.errorMode = new BehaviorSubject(false);
87
+ /**
88
+ * Whether the bottom "load more" spinner is shown while the next page is being loaded.
89
+ * Note: this is the infinite-scroll indicator and is distinct from `loadingMode`,
90
+ * which renders the full-screen loader instead of the list.
91
+ */
92
+ this.loadingMore = new BehaviorSubject(false);
93
+ /**
94
+ * Whether the bottom "load more" error row (with a retry button) is shown.
95
+ * Distinct from `errorMode`, which replaces the whole list with the full-screen error state.
96
+ */
97
+ this.loadMoreErrorMode = new BehaviorSubject(false);
98
+ /**
99
+ * 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.
101
+ */
102
+ this.hasMore = new BehaviorSubject(true);
85
103
  /** @docs-private */
86
104
  this.onRead = new BehaviorSubject(null);
87
105
  /** Triggers an event when the user presses the reload button. */
88
106
  this.onReload = new EventEmitter();
107
+ /** Triggers an event when the list is scrolled to the bottom and the next page should be loaded. */
108
+ this.onNextPage = new EventEmitter();
109
+ /** Triggers an event when an item, a group, or all notifications are removed. */
110
+ this.onDelete = new EventEmitter();
89
111
  this.originalItems = new BehaviorSubject([]);
90
- /** @docs-private */
112
+ /**
113
+ * 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.
115
+ * @docs-private
116
+ */
91
117
  this.groupedItems = this.originalItems.pipe(map((items) => {
92
118
  const result = {};
93
- items.map((item) => this.makeGroup(item, result));
94
- return Object.values(result).reverse();
119
+ items.forEach((item) => this.makeGroup(item, result));
120
+ const groups = Object.values(result);
121
+ // Newest notifications first within each day.
122
+ groups.forEach((group) => group.items.sort(this.compareByDateDesc));
123
+ // Newest day first.
124
+ return groups.sort((a, b) => this.compareByDateDesc(a.items[0], b.items[0]));
95
125
  }));
96
126
  /** Emits an event whenever the changes. */
97
- this.changes = merge(this.silentMode, this.loadingMode, this.errorMode, this.originalItems, this.onRead);
127
+ this.changes = merge(this.silentMode, this.loadingMode, this.errorMode, this.loadingMore, this.loadMoreErrorMode, this.hasMore, this.originalItems, this.onRead);
98
128
  this.makeGroup = (item, groups) => {
99
129
  const parsedDate = this.adapter.parse(item.date, '');
100
130
  const groupId = this.adapter.format(parsedDate, 'yyyyMMdd');
101
131
  const groupTitle = this.formatter.absoluteLongDate(parsedDate);
102
132
  if (groups[groupId]) {
103
- groups[groupId].items.unshift(item);
133
+ groups[groupId].items.push(item);
104
134
  }
105
135
  else {
106
136
  groups[groupId] = {
@@ -109,6 +139,15 @@ class KbqNotificationCenterService {
109
139
  };
110
140
  }
111
141
  };
142
+ /** Compares two notifications by date so the newest comes first. */
143
+ 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;
148
+ }
149
+ return this.adapter.compareDateTime(parsedB, parsedA);
150
+ };
112
151
  this.toastService?.read.pipe(takeUntilDestroyed()).subscribe((toastData) => {
113
152
  const item = this.items.find((item) => item.id === toastData?.id);
114
153
  if (item && !item.read) {
@@ -129,25 +168,52 @@ class KbqNotificationCenterService {
129
168
  setErrorMode(value) {
130
169
  this.errorMode.next(value);
131
170
  }
171
+ /** Set the bottom "load more" spinner visibility. */
172
+ setLoadingMore(value) {
173
+ this.loadingMore.next(value);
174
+ }
175
+ /** Set the bottom "load more" error state visibility. */
176
+ setLoadMoreErrorMode(value) {
177
+ this.loadMoreErrorMode.next(value);
178
+ }
179
+ /** Set whether there are more notifications to load via infinite scroll. */
180
+ setHasMore(value) {
181
+ this.hasMore.next(value);
182
+ }
132
183
  /** Push new notification item in center */
133
184
  push(item) {
134
185
  this.setReadState(this.setIds([item]));
135
186
  if (!this.silentMode.value) {
136
- this.toastService.show(item);
187
+ item.toastId = this.toastService.show(item).id;
137
188
  }
138
189
  return this.originalItems.next([...this.originalItems.value, item]);
139
190
  }
191
+ /** Hides the toast that corresponds to the given notification item. */
192
+ hideToast(item) {
193
+ if (item.toastId === undefined) {
194
+ return;
195
+ }
196
+ this.toastService.hide(item.toastId);
197
+ item.toastId = undefined;
198
+ }
140
199
  /** Remove notification item */
141
200
  remove(removedItem) {
201
+ this.hideToast(removedItem);
142
202
  this.originalItems.next(this.originalItems.value.filter((item) => removedItem !== item));
203
+ this.onDelete.emit({ type: 'item', items: [removedItem] });
143
204
  }
144
205
  /** Remove group of notification items */
145
206
  removeGroup(group) {
207
+ group.items.forEach((item) => this.hideToast(item));
146
208
  this.originalItems.next(this.originalItems.value.filter((item) => !group.items.includes(item)));
209
+ this.onDelete.emit({ type: 'group', items: [...group.items] });
147
210
  }
148
211
  /** Remove all notification items */
149
212
  removeAll() {
213
+ const items = this.originalItems.value;
214
+ items.forEach((item) => this.hideToast(item));
150
215
  this.originalItems.next([]);
216
+ this.onDelete.emit({ type: 'all', items });
151
217
  }
152
218
  setIds(items) {
153
219
  items.forEach((item) => (item.id = item.id ?? new Date().getTime().toString()));
@@ -194,6 +260,9 @@ class KbqNotificationItemComponent {
194
260
  this.readStateDirective.read
195
261
  .pipe(filter((value) => value), takeUntilDestroyed())
196
262
  .subscribe(() => {
263
+ if (this.data.read) {
264
+ return;
265
+ }
197
266
  this.data.read = true;
198
267
  this.service.onRead.next(this.data);
199
268
  });
@@ -202,7 +271,7 @@ class KbqNotificationItemComponent {
202
271
  return value instanceof TemplateRef;
203
272
  }
204
273
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqNotificationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
205
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: KbqNotificationItemComponent, isStandalone: true, selector: "kbq-notification-item", inputs: { data: "data" }, host: { 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.title }}</p>\n }\n\n <div class=\"kbq-notification-item-time\" [class.kbq-notification-item-time_read]=\"data.read\">\n <div class=\"kbq-notification-item-time__value\">{{ time }}</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 [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{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button{display:block}.kbq-notification-item__icon-container{flex-shrink:0;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-l);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{display:none}.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]", 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: ["forDisabledComponent", "ignoreTooltipPointerEvents", "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 }); }
274
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", 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.title }}</p>\n }\n\n <div class=\"kbq-notification-item-time\" [class.kbq-notification-item-time_read]=\"data.read\">\n <div class=\"kbq-notification-item-time__value\">{{ time }}</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;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{display:none}.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: ["forDisabledComponent", "ignoreTooltipPointerEvents", "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 }); }
206
275
  }
207
276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqNotificationItemComponent, decorators: [{
208
277
  type: Component,
@@ -214,13 +283,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
214
283
  KbqTooltipTrigger
215
284
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
216
285
  class: 'kbq-notification-item',
217
- '[class]': 'style'
218
- }, 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.title }}</p>\n }\n\n <div class=\"kbq-notification-item-time\" [class.kbq-notification-item-time_read]=\"data.read\">\n <div class=\"kbq-notification-item-time__value\">{{ time }}</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 [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{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button{display:block}.kbq-notification-item__icon-container{flex-shrink:0;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-l);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{display:none}.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"] }]
286
+ '[class]': 'style',
287
+ '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.title }}</p>\n }\n\n <div class=\"kbq-notification-item-time\" [class.kbq-notification-item-time_read]=\"data.read\">\n <div class=\"kbq-notification-item-time__value\">{{ time }}</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;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{display:none}.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"] }]
219
289
  }], ctorParameters: () => [], propDecorators: { data: [{
220
290
  type: Input
221
291
  }] } });
222
292
 
223
293
  const defaultOffsetX = 8;
294
+ /** Rate-limit window (ms) for the scroll-to-bottom check that drives infinite scroll. */
295
+ const SCROLLED_TO_BOTTOM_AUDIT_TIME = 100;
224
296
  /**default configuration of notification-center */
225
297
  const KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION = ruRULocaleData.notificationCenter;
226
298
  /** Injection Token for providing configuration of notification-center */
@@ -262,11 +334,18 @@ class KbqNotificationCenterComponent extends KbqPopUp {
262
334
  /** @docs-private */
263
335
  this.service = inject(KbqNotificationCenterService);
264
336
  this.externalConfiguration = inject(KBQ_NOTIFICATION_CENTER_CONFIGURATION, { optional: true });
337
+ /** Distance in pixels from the bottom of the list at which the next page is requested.
338
+ * @docs-private */
339
+ this.scrolledToBottomOffset = 0;
340
+ /** Emits on every scroll of the list container; drives the scroll-to-bottom check. */
341
+ this.scroll$ = new Subject();
265
342
  /** @docs-private */
266
343
  this.prefix = 'kbq-notification-center';
267
344
  /** @docs-private */
268
345
  this.isTrapFocus = false;
269
346
  this.switcher = viewChild.required('notificationSwitcher');
347
+ /** Scrollable list container; used to measure scroll position for infinite scroll. */
348
+ this.scrollContainer = viewChild.required(KbqScrollbar);
270
349
  this.updateLocaleParams = () => {
271
350
  this.configuration = this.externalConfiguration || this.localeService?.getParams('notificationCenter');
272
351
  this.changeDetectorRef.markForCheck();
@@ -277,14 +356,87 @@ class KbqNotificationCenterComponent extends KbqPopUp {
277
356
  }
278
357
  }
279
358
  ngAfterViewInit() {
280
- this.visibleChange.subscribe((state) => {
359
+ this.visibleChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((state) => {
281
360
  if (this.offset !== null && state) {
282
361
  applyPopupMargins(this.renderer, this.elementRef.nativeElement, this.prefix, `${this.offset.toString()}px`);
283
362
  }
284
363
  this.setStickPosition();
285
364
  });
286
- this.service.changes.subscribe(() => this.changeDetectorRef.markForCheck());
365
+ this.service.changes
366
+ .pipe(takeUntilDestroyed(this.destroyRef))
367
+ .subscribe(() => this.changeDetectorRef.markForCheck());
287
368
  this.switcher().focus();
369
+ this.subscribeToScrolledToBottom();
370
+ this.subscribeToRevealLoadMoreRow();
371
+ }
372
+ /** Handles the list container scroll: feeds the scroll-to-bottom check that drives infinite scroll.
373
+ * Overflow shadows are handled declaratively by the `kbqOverflowShadow*` directives.
374
+ * @docs-private */
375
+ onContainerScroll() {
376
+ this.scroll$.next();
377
+ }
378
+ /** Retries loading the next page from the bottom error row.
379
+ * @docs-private */
380
+ retryLoadMore() {
381
+ // The retry button is about to unmount; keep keyboard focus inside the panel instead of
382
+ // letting it fall back to <body>.
383
+ this.focusScrollContainer();
384
+ // Clear the bottom error state here so the spinner and the error row can never be shown at
385
+ // the same time, regardless of what the consumer's `onNextPage` handler does.
386
+ this.service.setLoadMoreErrorMode(false);
387
+ this.service.onNextPage.emit();
388
+ }
389
+ /**
390
+ * Requests the next page (via `service.onNextPage`) once the list is scrolled to within
391
+ * `scrolledToBottomOffset` pixels of the bottom. Two triggers feed it: the user scrolling, and a
392
+ * page finishing loading. The latter keeps paging when a freshly loaded page is too short to
393
+ * overflow the viewport — otherwise no further scroll event would fire and pagination would
394
+ * stall. Suppressed while a load is in flight, errored, or when there is nothing more to load.
395
+ */
396
+ subscribeToScrolledToBottom() {
397
+ const scrolledToBottom$ = this.scroll$.pipe(auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), map(() => this.isScrolledToBottom()), distinctUntilChanged(), filter(Boolean));
398
+ // Re-measure once a load completes (and the appended items have rendered): if the list still
399
+ // sits at the bottom, continue paging instead of waiting for a scroll event that never comes.
400
+ const loadCompleted$ = this.service.loadingMore.pipe(distinctUntilChanged(), pairwise(), filter(([wasLoading, isLoading]) => wasLoading && !isLoading), auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), filter(() => this.isScrolledToBottom()));
401
+ merge(scrolledToBottom$, loadCompleted$)
402
+ .pipe(takeUntilDestroyed(this.destroyRef))
403
+ .subscribe(() => this.requestNextPage());
404
+ }
405
+ /** Whether the list is scrolled to within `scrolledToBottomOffset` pixels of the bottom. */
406
+ isScrolledToBottom() {
407
+ const { scrollTop, clientHeight, scrollHeight } = this.scrollContainer().contentElement().nativeElement;
408
+ return scrollHeight - scrollTop - clientHeight <= this.scrolledToBottomOffset;
409
+ }
410
+ /** Emits `onNextPage` unless a load is already in flight, errored, or there is nothing more to load. */
411
+ requestNextPage() {
412
+ if (this.service.hasMore.value && !this.service.loadingMore.value && !this.service.loadMoreErrorMode.value) {
413
+ this.service.onNextPage.emit();
414
+ }
415
+ }
416
+ /**
417
+ * Reveals the bottom "load more" spinner / error row when it first appears. Both rows are appended
418
+ * below the last item and can land outside the viewport (the next page is requested while the user
419
+ * is up to `scrolledToBottomOffset` px above the true bottom). Only a genuine false->true transition
420
+ * reveals the row: the BehaviorSubject's replayed current value is ignored (`pairwise` needs two
421
+ * emissions), so the panel always opens scrolled to the top — reopening it while a load-more error
422
+ * is still set never jumps to the bottom.
423
+ */
424
+ subscribeToRevealLoadMoreRow() {
425
+ const reveal = (source) => source.pipe(distinctUntilChanged(), pairwise(), filter(([wasShown, isShown]) => !wasShown && isShown), auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME));
426
+ merge(reveal(this.service.loadingMore), reveal(this.service.loadMoreErrorMode))
427
+ .pipe(takeUntilDestroyed(this.destroyRef))
428
+ .subscribe(() => this.scrollToBottom());
429
+ }
430
+ /** Scrolls the list container to its bottom so a freshly-appended bottom row becomes visible. */
431
+ scrollToBottom() {
432
+ const { scrollHeight } = this.scrollContainer().contentElement().nativeElement;
433
+ this.scrollContainer().scrollTo({ top: scrollHeight });
434
+ }
435
+ focusScrollContainer() {
436
+ const element = this.scrollContainer().contentElement().nativeElement;
437
+ // tabindex -1 keeps the container out of the Tab order while allowing programmatic focus.
438
+ element.setAttribute('tabindex', '-1');
439
+ element.focus({ preventScroll: true });
288
440
  }
289
441
  /** @docs-private */
290
442
  updateClassMap(placement, customClass, size) {
@@ -302,7 +454,7 @@ class KbqNotificationCenterComponent extends KbqPopUp {
302
454
  this.configuration = KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION;
303
455
  }
304
456
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqNotificationCenterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
305
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", 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 }], 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 #dropdownTrigger=\"kbqDropdownTrigger\"\n kbq-button\n class=\"kbq-notification-center-title__button\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [kbqTooltip]=\"service.silentMode.value ? localeData.doNotDisturb : localeData.showPopUpNotifications\"\n [kbqTooltipArrow]=\"false\"\n [kbqTooltipOffset]=\"4\"\n [kbqTooltipDisabled]=\"dropdownTrigger.opened\"\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 [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 [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 [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\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 [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 [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeData.remove\"\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 <div class=\"kbq-notification-center-empty-container\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeData.noNotifications }}\n </div>\n }\n } @else {\n <kbq-loader-overlay [transparent]=\"true\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeData.failedToLoadNotifications }}\n <button kbq-button [kbqStyle]=\"'transparent'\" [color]=\"'theme'\" (click)=\"service.onReload.emit()\">\n {{ localeData.repeat }}\n </button>\n </div>\n }\n</div>\n\n<kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\">\n <button kbq-dropdown-item (click)=\"service.setSilentMode(false)\">\n <i kbq-icon=\"{{ !service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.showPopUpNotifications }}\n </button>\n <button kbq-dropdown-item (click)=\"service.setSilentMode(true)\">\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-xl) 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-xxl)}.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{display:flex}.kbq-notification-center-container{height:100%;border-radius:inherit;padding-bottom:var(--kbq-size-m)}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit}.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{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"], outputs: ["closed"], exportAs: ["kbqDropdown"] }, { kind: "component", type: i5.KbqDropdownItem, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: ["disabled"], 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: ["forDisabledComponent", "ignoreTooltipPointerEvents", "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: "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 }); }
457
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", 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 #dropdownTrigger=\"kbqDropdownTrigger\"\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 [kbqTooltipDisabled]=\"dropdownTrigger.opened\"\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"], outputs: ["closed"], exportAs: ["kbqDropdown"] }, { kind: "component", type: i5.KbqDropdownItem, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: ["disabled"], 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: ["forDisabledComponent", "ignoreTooltipPointerEvents", "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 }); }
306
458
  }
307
459
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqNotificationCenterComponent, decorators: [{
308
460
  type: Component,
@@ -317,6 +469,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
317
469
  AsyncPipe,
318
470
  KbqNotificationItemComponent,
319
471
  KbqLoaderOverlayModule,
472
+ KbqProgressSpinnerModule,
320
473
  KbqOverflowShadowContainer,
321
474
  KbqOverflowShadowTop,
322
475
  KbqOverflowShadowBottom
@@ -324,8 +477,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
324
477
  class: 'kbq-notification-center',
325
478
  '[class.kbq-notification-center_popover]': 'popoverMode',
326
479
  '(keydown.escape)': 'escapeHandler()'
327
- }, 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 #dropdownTrigger=\"kbqDropdownTrigger\"\n kbq-button\n class=\"kbq-notification-center-title__button\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [kbqTooltip]=\"service.silentMode.value ? localeData.doNotDisturb : localeData.showPopUpNotifications\"\n [kbqTooltipArrow]=\"false\"\n [kbqTooltipOffset]=\"4\"\n [kbqTooltipDisabled]=\"dropdownTrigger.opened\"\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 [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 [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 [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\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 [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 [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeData.remove\"\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 <div class=\"kbq-notification-center-empty-container\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeData.noNotifications }}\n </div>\n }\n } @else {\n <kbq-loader-overlay [transparent]=\"true\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeData.failedToLoadNotifications }}\n <button kbq-button [kbqStyle]=\"'transparent'\" [color]=\"'theme'\" (click)=\"service.onReload.emit()\">\n {{ localeData.repeat }}\n </button>\n </div>\n }\n</div>\n\n<kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\">\n <button kbq-dropdown-item (click)=\"service.setSilentMode(false)\">\n <i kbq-icon=\"{{ !service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.showPopUpNotifications }}\n </button>\n <button kbq-dropdown-item (click)=\"service.setSilentMode(true)\">\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-xl) 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-xxl)}.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{display:flex}.kbq-notification-center-container{height:100%;border-radius:inherit;padding-bottom:var(--kbq-size-m)}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit}.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{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"] }]
328
- }], ctorParameters: () => [], propDecorators: { switcher: [{ type: i0.ViewChild, args: ['notificationSwitcher', { isSignal: true }] }] } });
480
+ }, 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 #dropdownTrigger=\"kbqDropdownTrigger\"\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 [kbqTooltipDisabled]=\"dropdownTrigger.opened\"\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"] }]
481
+ }], ctorParameters: () => [], propDecorators: { switcher: [{ type: i0.ViewChild, args: ['notificationSwitcher', { isSignal: true }] }], scrollContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqScrollbar), { isSignal: true }] }] } });
329
482
  class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
330
483
  /** Number of unread notifications */
331
484
  get unreadItemsCounter() {
@@ -404,6 +557,8 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
404
557
  // TODO: Skipped for migration because:
405
558
  // Class of this input is referenced in the signature of another class.
406
559
  this.offset = defaultOffsetX;
560
+ /** Distance in pixels from the bottom of the list at which the next page is requested via `onNextPage`. */
561
+ this.scrolledToBottomOffset = 0;
407
562
  this._popoverMode = false;
408
563
  /** Emits a change event whenever the placement state changes. */
409
564
  this.placementChange = new EventEmitter();
@@ -428,7 +583,7 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
428
583
  });
429
584
  }
430
585
  else {
431
- this.preventClosingByInnerScrollSubscription.unsubscribe();
586
+ this.preventClosingByInnerScrollSubscription?.unsubscribe();
432
587
  this.focus();
433
588
  }
434
589
  });
@@ -444,6 +599,7 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
444
599
  this.instance.footer = this.footer;
445
600
  this.instance.popoverMode = this.popoverMode;
446
601
  this.instance.popoverHeight = this.popoverHeight;
602
+ this.instance.scrolledToBottomOffset = this.scrolledToBottomOffset;
447
603
  this.instance.updateTrapFocus(this.trigger !== PopUpTriggers.Focus);
448
604
  if (this.isOpen) {
449
605
  this.updatePosition(true);
@@ -477,7 +633,7 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
477
633
  return merge(this.overlayRef.outsidePointerEvents(), this.overlayRef.backdropClick(), this.scrollDispatcher.scrolled());
478
634
  }
479
635
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqNotificationCenterTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
480
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.25", type: KbqNotificationCenterTrigger, isStandalone: true, selector: "[kbqNotificationCenterTrigger]", inputs: { placement: ["kbqNotificationCenterPlacement", "placement"], backdropClass: "backdropClass", panelClass: ["kbqNotificationCenterPanelClass", "panelClass"], offset: ["offset", "offset", 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" } }, exportAs: ["kbqNotificationCenterTrigger"], usesInheritance: true, ngImport: i0 }); }
636
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.25", 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" } }, exportAs: ["kbqNotificationCenterTrigger"], usesInheritance: true, ngImport: i0 }); }
481
637
  }
482
638
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqNotificationCenterTrigger, decorators: [{
483
639
  type: Directive,
@@ -500,6 +656,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
500
656
  }], offset: [{
501
657
  type: Input,
502
658
  args: [{ transform: numberAttribute }]
659
+ }], scrolledToBottomOffset: [{
660
+ type: Input,
661
+ args: [{ transform: numberAttribute }]
503
662
  }], popoverMode: [{
504
663
  type: Input,
505
664
  args: [{ transform: booleanAttribute }]