@odx/angular 5.3.4 → 5.4.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 (87) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/components/notification/README.md +3 -0
  3. package/components/notification/index.d.ts +7 -0
  4. package/components/notification/lib/components/index.d.ts +2 -0
  5. package/components/notification/lib/components/notification-center/notification-center.component.d.ts +19 -0
  6. package/components/notification/lib/components/notification-item/notification-item.component.d.ts +37 -0
  7. package/components/notification/lib/directives/index.d.ts +1 -0
  8. package/components/notification/lib/directives/notification-center.directive.d.ts +69 -0
  9. package/components/notification/lib/features/index.d.ts +5 -0
  10. package/components/notification/lib/features/with-browser-notifications.d.ts +17 -0
  11. package/components/notification/lib/features/with-load-notifications.d.ts +18 -0
  12. package/components/notification/lib/features/with-notification-transformer.d.ts +26 -0
  13. package/components/notification/lib/features/with-peristent-notifications.d.ts +63 -0
  14. package/components/notification/lib/features/with-save-notifications.d.ts +11 -0
  15. package/components/notification/lib/helpers/get-notifications-by-tag.d.ts +2 -0
  16. package/components/notification/lib/helpers/index.d.ts +3 -0
  17. package/components/notification/lib/helpers/sort-notifications.d.ts +3 -0
  18. package/components/notification/lib/helpers/to-notification-collection.d.ts +3 -0
  19. package/components/notification/lib/models/index.d.ts +8 -0
  20. package/components/notification/lib/models/notification-action.d.ts +2 -0
  21. package/components/notification/lib/models/notification-collection.d.ts +6 -0
  22. package/components/notification/lib/models/notification-feature.d.ts +5 -0
  23. package/components/notification/lib/models/notification-options.d.ts +7 -0
  24. package/components/notification/lib/models/notification-query.d.ts +2 -0
  25. package/components/notification/lib/models/notification-sort-fn.d.ts +2 -0
  26. package/components/notification/lib/models/notification.d.ts +6 -0
  27. package/components/notification/lib/models/notification.ref.d.ts +9 -0
  28. package/components/notification/lib/notification.config.d.ts +11 -0
  29. package/components/notification/lib/notification.i18n.d.ts +3 -0
  30. package/components/notification/lib/notification.logger.d.ts +3 -0
  31. package/components/notification/lib/notification.service.d.ts +110 -0
  32. package/components/notification/lib/notification.tokens.d.ts +4 -0
  33. package/components/notification/lib/services/index.d.ts +1 -0
  34. package/components/notification/lib/services/notification-center.service.d.ts +69 -0
  35. package/components/notification/testing/README.md +3 -0
  36. package/components/notification/testing/index.d.ts +1 -0
  37. package/components/notification/testing/lib/test-helpers.d.ts +5 -0
  38. package/components/toast/lib/toast.service.d.ts +30 -2
  39. package/esm2022/components/notification/index.mjs +8 -0
  40. package/esm2022/components/notification/lib/components/index.mjs +3 -0
  41. package/esm2022/components/notification/lib/components/notification-center/notification-center.component.mjs +65 -0
  42. package/esm2022/components/notification/lib/components/notification-item/notification-item.component.mjs +65 -0
  43. package/esm2022/components/notification/lib/directives/index.mjs +2 -0
  44. package/esm2022/components/notification/lib/directives/notification-center.directive.mjs +142 -0
  45. package/esm2022/components/notification/lib/features/index.mjs +6 -0
  46. package/esm2022/components/notification/lib/features/with-browser-notifications.mjs +75 -0
  47. package/esm2022/components/notification/lib/features/with-load-notifications.mjs +45 -0
  48. package/esm2022/components/notification/lib/features/with-notification-transformer.mjs +34 -0
  49. package/esm2022/components/notification/lib/features/with-peristent-notifications.mjs +94 -0
  50. package/esm2022/components/notification/lib/features/with-save-notifications.mjs +45 -0
  51. package/esm2022/components/notification/lib/helpers/get-notifications-by-tag.mjs +7 -0
  52. package/esm2022/components/notification/lib/helpers/index.mjs +4 -0
  53. package/esm2022/components/notification/lib/helpers/sort-notifications.mjs +10 -0
  54. package/esm2022/components/notification/lib/helpers/to-notification-collection.mjs +9 -0
  55. package/esm2022/components/notification/lib/models/index.mjs +9 -0
  56. package/esm2022/components/notification/lib/models/notification-action.mjs +2 -0
  57. package/esm2022/components/notification/lib/models/notification-collection.mjs +2 -0
  58. package/esm2022/components/notification/lib/models/notification-feature.mjs +4 -0
  59. package/esm2022/components/notification/lib/models/notification-options.mjs +2 -0
  60. package/esm2022/components/notification/lib/models/notification-query.mjs +2 -0
  61. package/esm2022/components/notification/lib/models/notification-sort-fn.mjs +2 -0
  62. package/esm2022/components/notification/lib/models/notification.mjs +2 -0
  63. package/esm2022/components/notification/lib/models/notification.ref.mjs +2 -0
  64. package/esm2022/components/notification/lib/notification.config.mjs +11 -0
  65. package/esm2022/components/notification/lib/notification.i18n.mjs +11 -0
  66. package/esm2022/components/notification/lib/notification.logger.mjs +3 -0
  67. package/esm2022/components/notification/lib/notification.service.mjs +168 -0
  68. package/esm2022/components/notification/lib/notification.tokens.mjs +7 -0
  69. package/esm2022/components/notification/lib/services/index.mjs +2 -0
  70. package/esm2022/components/notification/lib/services/notification-center.service.mjs +96 -0
  71. package/esm2022/components/notification/odx-angular-components-notification.mjs +5 -0
  72. package/esm2022/components/notification/testing/index.mjs +2 -0
  73. package/esm2022/components/notification/testing/lib/test-helpers.mjs +33 -0
  74. package/esm2022/components/notification/testing/odx-angular-components-notification-testing.mjs +5 -0
  75. package/esm2022/components/toast/lib/components/toast-container/toast-container.component.mjs +6 -6
  76. package/esm2022/components/toast/lib/toast.service.mjs +38 -8
  77. package/esm2022/utils/lib/helpers/array.mjs +24 -1
  78. package/fesm2022/odx-angular-components-notification-testing.mjs +39 -0
  79. package/fesm2022/odx-angular-components-notification-testing.mjs.map +1 -0
  80. package/fesm2022/odx-angular-components-notification.mjs +832 -0
  81. package/fesm2022/odx-angular-components-notification.mjs.map +1 -0
  82. package/fesm2022/odx-angular-components-toast.mjs +42 -11
  83. package/fesm2022/odx-angular-components-toast.mjs.map +1 -1
  84. package/fesm2022/odx-angular-utils.mjs +23 -0
  85. package/fesm2022/odx-angular-utils.mjs.map +1 -1
  86. package/package.json +13 -1
  87. package/utils/lib/helpers/array.d.ts +23 -0
@@ -0,0 +1,832 @@
1
+ import { __decorate } from 'tslib';
2
+ import { trigger, transition, useAnimation } from '@angular/animations';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i0 from '@angular/core';
6
+ import { makeEnvironmentProviders, InjectionToken, inject, Injector, runInInjectionContext, Injectable, signal, computed, ENVIRONMENT_INITIALIZER, EventEmitter, Component, ViewEncapsulation, ChangeDetectionStrategy, Input, Output, DestroyRef, Directive } from '@angular/core';
7
+ import { LetDirective } from '@ngrx/component';
8
+ import { collapse } from '@odx/angular/animations';
9
+ import { InteractiveDirective } from '@odx/angular/cdk/a11y';
10
+ import { DynamicViewDirective } from '@odx/angular/cdk/dynamic-view';
11
+ import { ActionGroupComponent } from '@odx/angular/components/action-group';
12
+ import * as i1$1 from '@odx/angular/components/badge';
13
+ import { BadgeDirective } from '@odx/angular/components/badge';
14
+ import { ButtonComponent } from '@odx/angular/components/button';
15
+ import * as i2$1 from '@odx/angular/components/dropdown';
16
+ import { DropdownModule, DropdownDirective } from '@odx/angular/components/dropdown';
17
+ import { IconComponent } from '@odx/angular/components/icon';
18
+ import * as i3 from '@odx/angular/components/list';
19
+ import { ListModule } from '@odx/angular/components/list';
20
+ import { Logger, deepmerge, CSSComponent } from '@odx/angular/internal';
21
+ import { provideTranslations, TranslatePipe } from '@odx/angular/internal/translate';
22
+ import { isFunction, createConfigTokens, orderBy, Queue, getUniqueId, isString, injectElement, trackById, Position } from '@odx/angular/utils';
23
+ import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
24
+ import { tap, map, shareReplay, filter, switchMap, isObservable, of, combineLatest, from, firstValueFrom, merge, startWith } from 'rxjs';
25
+ import { LocalizationService } from '@odx/angular/localization';
26
+ import { AvatarComponent } from '@odx/angular/components/avatar';
27
+ import * as i2 from '@odx/angular';
28
+ import { DisabledController } from '@odx/angular';
29
+
30
+ var notificationI18n = {
31
+ en: {
32
+ title: 'Notifications',
33
+ dismissAll: 'Dismiss all',
34
+ },
35
+ de: {
36
+ title: 'Benachrichtigungen',
37
+ dismissAll: 'Alle entfernen',
38
+ },
39
+ };
40
+
41
+ function getNotificationsByTags(...tags) {
42
+ const cachedTags = new Set(tags.filter(Boolean));
43
+ return ({ options }) => {
44
+ return cachedTags.size < 1 || options.tags.every((tag) => cachedTags.has(tag));
45
+ };
46
+ }
47
+
48
+ function sortNotifications(sortFn) {
49
+ return (source$) => source$.pipe(tap((values) => {
50
+ if (!isFunction(sortFn))
51
+ return;
52
+ values.sort(sortFn);
53
+ }));
54
+ }
55
+
56
+ function toNotificationCollection() {
57
+ return (source$) => source$.pipe(map((notificationRefs) => ({
58
+ values: notificationRefs,
59
+ count: notificationRefs.length,
60
+ isEmpty: notificationRefs.length === 0,
61
+ })));
62
+ }
63
+
64
+ const { NotificationConfig, NotificationDefaultConfig, injectNotificationConfig, provideNotificationConfig } = createConfigTokens('Notification', '@odx/angular/components/notification', {
65
+ options: { icon: 'core::globe', tags: [], dismissable: true },
66
+ sortFn: orderBy('createdAt', 'DESC'),
67
+ defaultIdPrefix: 'odx-notifications',
68
+ });
69
+ function provideNotifications(config, ...features) {
70
+ return makeEnvironmentProviders([provideNotificationConfig(config ?? {}), features]);
71
+ }
72
+
73
+ var logger = new Logger('@odx/angular/components/notification');
74
+
75
+ const ODX_NOTIFICATION_QUEUE = new InjectionToken('@odx/angular/component/notifications::Queue', {
76
+ providedIn: 'root',
77
+ factory: () => new Queue(),
78
+ });
79
+
80
+ class NotificationService {
81
+ constructor() {
82
+ this.config = injectNotificationConfig();
83
+ this.localizationService = inject(LocalizationService);
84
+ this.queue = inject(ODX_NOTIFICATION_QUEUE);
85
+ this.injector = inject(Injector);
86
+ this.notifications$ = this.queue.value$.pipe(sortNotifications(this.config.sortFn), toNotificationCollection(), shareReplay({ bufferSize: 1, refCount: true }));
87
+ this.unseenNotifications$ = this.notifications$.pipe(map((collection) => collection.values.filter(({ hasBeenSeen }) => !hasBeenSeen)), toNotificationCollection(), shareReplay({ bufferSize: 1, refCount: true }));
88
+ this.onNotificationAdd$ = this.queue.onAdd$;
89
+ this.onNotificationRemove$ = this.queue.onRemove$;
90
+ this.onNotificationUpdate$ = this.queue.onUpdate$;
91
+ this.onNotificationSeen$ = this.queue.onUpdate$.pipe(filter(({ hasBeenSeen }) => hasBeenSeen));
92
+ }
93
+ /**
94
+ * Fetches notifications filtered by a specified query and optionally sorted by a custom sort function.
95
+ *
96
+ * @param {NotificationQuery} query - A function or object to filter notifications.
97
+ * @param {NotificationSortFn} [sortFn] - An optional sorting function to order the filtered notifications.
98
+ * @returns {Observable<NotificationCollection>} An observable stream of the filtered (and optionally sorted) notification collection.
99
+ * @example
100
+ * // Fetch notifications with a specific tag, sorted by creation date
101
+ * const sortedNotifications$ = notificationService.getNotificationsBy$(
102
+ * notification => notification.tags.includes('important'),
103
+ * (a, b) => b.createdAt - a.createdAt
104
+ * );
105
+ */
106
+ getNotificationsBy$(query, sortFn) {
107
+ return this.queue.value$.pipe(map((notifications) => notifications.filter(query)), sortNotifications(sortFn), toNotificationCollection(), shareReplay({ bufferSize: 1, refCount: true }));
108
+ }
109
+ /**
110
+ * Loads a list of notifications into the service.
111
+ *
112
+ * @param {NotificationRef[]} refs - An array of notification references to be loaded.
113
+ * @example
114
+ * // Load multiple notifications at once
115
+ * notificationService.load([
116
+ * { id: '1', item: { title: 'Notification 1' }, options: {dismissable: true, icon: 'plus', tags: ['important']}, hasBeenSeen: false, createdAt: Date.now() },
117
+ * { id: '2', item: { title: 'Notification 2' }, options: {dismissable: true, icon: 'plus', tags: ['important']}, hasBeenSeen: false, createdAt: Date.now() }
118
+ * ]);
119
+ */
120
+ load(refs) {
121
+ this.queue.addMany(refs);
122
+ }
123
+ /**
124
+ * Creates a new notification and adds it to the notification queue.
125
+ *
126
+ * @param {Notification} item - The notification to create.
127
+ * @param {Partial<NotificationOptions>} [options] - Optional settings for the notification.
128
+ * @example
129
+ * // Create a new notification with custom options
130
+ * notificationService.create(
131
+ * { title: 'New Notification' },
132
+ * { dismissable: true, icon: 'plus', tags: ['important'] }
133
+ * );
134
+ */
135
+ create(item, options) {
136
+ this.queue.add({
137
+ id: item.id ?? getUniqueId(this.config.defaultIdPrefix),
138
+ createdAt: Date.now(),
139
+ item,
140
+ options: this.resolveOptions(options),
141
+ hasBeenSeen: false,
142
+ });
143
+ }
144
+ /**
145
+ * Marks a specific notification as seen.
146
+ *
147
+ * @param {NotificationRef} notificationRef - The reference to the notification to mark as seen.
148
+ * @example
149
+ * // Mark a notification as seen by its reference
150
+ * notificationService.markAsSeen(notificationRef);
151
+ */
152
+ markAsSeen(notificationRef) {
153
+ if (notificationRef.hasBeenSeen)
154
+ return;
155
+ this.queue.add({ ...notificationRef, hasBeenSeen: true });
156
+ }
157
+ /**
158
+ * Marks all notifications that match a specific query as seen.
159
+ *
160
+ * @param {NotificationQuery} query - The query to match notifications to mark as seen.
161
+ * @example
162
+ * // Mark all notifications with a specific tag as seen
163
+ * notificationService.markAsSeenBy(notification => notification.tags.includes('important'));
164
+ */
165
+ markAsSeenBy(query) {
166
+ for (const notificationRef of this.queue.toArray().filter(query)) {
167
+ this.markAsSeen(notificationRef);
168
+ }
169
+ }
170
+ /**
171
+ * Dismisses a specific notification.
172
+ *
173
+ * @param {NotificationRef} notificationRef - The reference to the notification to dismiss.
174
+ * @example
175
+ * // Dismiss a notification by its reference
176
+ * notificationService.dismiss(notificationRef);
177
+ */
178
+ dismiss(notificationRef) {
179
+ if (!notificationRef.options.dismissable)
180
+ return;
181
+ this.queue.remove(notificationRef);
182
+ }
183
+ /**
184
+ * Dismisses all notifications that match a specific query.
185
+ *
186
+ * @param {NotificationQuery} query - The query to match notifications to dismiss.
187
+ * @example
188
+ * // Dismiss all notifications with a specific tag
189
+ * notificationService.dismissBy(notification => notification.tags.includes('expired'));
190
+ */
191
+ dismissBy(query) {
192
+ for (const item of this.queue.toArray().filter(query)) {
193
+ this.dismiss(item);
194
+ }
195
+ }
196
+ /**
197
+ * Dismisses all notifications.
198
+ *
199
+ * @example
200
+ * // Dismiss all notifications
201
+ * notificationService.dismissAll();
202
+ */
203
+ dismissAll() {
204
+ this.queue.clear();
205
+ }
206
+ /**
207
+ * Executes the action associated with a specific notification.
208
+ *
209
+ * @param {NotificationRef} notificationRef - The reference to the notification whose action to execute.
210
+ * @example
211
+ * // Execute action for a notification
212
+ * notificationService.executeAction(notificationRef);
213
+ */
214
+ executeAction(notificationRef) {
215
+ if (!notificationRef.options.action)
216
+ return;
217
+ const actionFn = this.config.actionMap?.[notificationRef.options.action];
218
+ if (!isFunction(actionFn)) {
219
+ logger.warn(`Cannot find action ${notificationRef.options.action} for notification reference: ${notificationRef}`);
220
+ return;
221
+ }
222
+ runInInjectionContext(this.injector, () => actionFn(notificationRef));
223
+ }
224
+ resolveOptions(options) {
225
+ return deepmerge(this.config.options, options ?? {}, {
226
+ icon: options?.icon ?? this.config.tagToIconMap?.[options?.tags?.[0] ?? ''] ?? this.config.options.icon,
227
+ language: options?.language ?? this.localizationService.getActiveLanguage(),
228
+ });
229
+ }
230
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
231
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationService, providedIn: 'root' }); }
232
+ }
233
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationService, decorators: [{
234
+ type: Injectable,
235
+ args: [{ providedIn: 'root' }]
236
+ }] });
237
+
238
+ /**
239
+ * A service for managing the notification center. This service provides functionalities
240
+ * to filter, sort, and manage actions on notifications.
241
+ */
242
+ class NotificationCenterService {
243
+ constructor() {
244
+ this.currentTag = signal(null);
245
+ this.currentSortFn = signal(undefined);
246
+ this.notificationService = inject(NotificationService);
247
+ this.notificationQuery = computed(() => getNotificationsByTags(this.currentTag()));
248
+ this.title = signal(null);
249
+ this.title$ = toObservable(this.title).pipe(switchMap((title) => (isObservable(title) ? title : of(title))), shareReplay({ bufferSize: 1, refCount: true }));
250
+ this.notifications$ = combineLatest([toObservable(this.notificationQuery), toObservable(this.currentSortFn)]).pipe(switchMap(([query, sortFn]) => this.notificationService.getNotificationsBy$(query, sortFn)));
251
+ this.unseenNotifications$ = this.notifications$.pipe(map((collection) => collection.values.filter(({ hasBeenSeen }) => !hasBeenSeen)), toNotificationCollection());
252
+ this.onNotificationAdd$ = this.queryEvent(this.notificationService.onNotificationAdd$);
253
+ this.onNotificationUpdate$ = this.queryEvent(this.notificationService.onNotificationUpdate$);
254
+ this.onNotificationRemove$ = this.queryEvent(this.notificationService.onNotificationRemove$);
255
+ this.onNotificationSeen$ = this.queryEvent(this.notificationService.onNotificationSeen$);
256
+ }
257
+ /**
258
+ * Sets the title for the notification center. The title can be static text or an observable for dynamic content.
259
+ *
260
+ * @param {DynamicTextContent | null} [value] - The title content for the notification center.
261
+ */
262
+ setTitle(value) {
263
+ this.title.set(value ?? null);
264
+ }
265
+ /**
266
+ * Sets the current tag to filter notifications. Only notifications with this tag will be included.
267
+ *
268
+ * @param {string | null} [value] - The tag to filter notifications by.
269
+ */
270
+ setTag(value) {
271
+ this.currentTag.set(value ?? null);
272
+ }
273
+ /**
274
+ * Sets the sort function used to order the notifications.
275
+ *
276
+ * @param {NotificationSortFn} [value] - The sort function to apply to the notifications.
277
+ */
278
+ setSortFn(value) {
279
+ this.currentSortFn.set(value);
280
+ }
281
+ /**
282
+ * Marks a given notification as seen. This does not remove the notification but updates its seen status.
283
+ *
284
+ * @param {NotificationRef} notificationRef - The reference to the notification to be marked as seen.
285
+ */
286
+ markAsSeen(notificationRef) {
287
+ this.notificationService.markAsSeen(notificationRef);
288
+ }
289
+ /**
290
+ * Marks all current filtered notifications as seen.
291
+ */
292
+ markAllAsSeen() {
293
+ this.notificationService.markAsSeenBy(this.notificationQuery());
294
+ }
295
+ /**
296
+ * Dismisses a specific notification.
297
+ *
298
+ * @param {NotificationRef} notificationRef - The reference to the notification to dismiss.
299
+ */
300
+ dismiss(notificationRef) {
301
+ this.notificationService.dismiss(notificationRef);
302
+ }
303
+ /**
304
+ * Dismisses all notifications that match the current filter criteria.
305
+ */
306
+ dismissAll() {
307
+ this.notificationService.dismissBy(this.notificationQuery());
308
+ }
309
+ /**
310
+ * Executes the action associated with a specific notification and marks it as seen.
311
+ *
312
+ * @param {NotificationRef} notificationRef - The reference to the notification whose action to execute.
313
+ */
314
+ executeAction(notificationRef) {
315
+ this.markAsSeen(notificationRef);
316
+ this.notificationService.executeAction(notificationRef);
317
+ }
318
+ queryEvent(source$) {
319
+ return combineLatest([source$, toObservable(this.notificationQuery)]).pipe(filter(([notificationRef, query]) => query(notificationRef)), map(([notificationRef]) => notificationRef));
320
+ }
321
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationCenterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
322
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationCenterService }); }
323
+ }
324
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationCenterService, decorators: [{
325
+ type: Injectable
326
+ }] });
327
+
328
+ function makeNotificationFeature(provider) {
329
+ return provider;
330
+ }
331
+
332
+ /**
333
+ * Loads notifications using the provided `loadFn`. This function abstracts over the differences
334
+ * between synchronous notifications, promises, and observables, providing a uniform Observable output.
335
+ * @function loadNotifications
336
+ * @param {LoadNotificationsFn} [loadFn] - An optional function to load notifications.
337
+ * @returns {Observable<NotificationRef[]>} An Observable stream of notification references.
338
+ */
339
+ function loadNotifications(loadFn) {
340
+ const notifications = loadFn?.();
341
+ if (isObservable(notifications)) {
342
+ return notifications;
343
+ }
344
+ if (notifications instanceof Promise) {
345
+ return from(notifications);
346
+ }
347
+ return of(notifications ?? []);
348
+ }
349
+ /**
350
+ * Integrates notification loading into the application environment. This function uses the Angular
351
+ * `ENVIRONMENT_INITIALIZER` to ensure that notifications are loaded as part of the application's
352
+ * initialization process.
353
+ * @function withLoadNotifications
354
+ * @param {LoadNotificationsFn} loadFn - The function to load notifications.
355
+ * @returns {NotificationFeature} A notification feature configured to load notifications at startup.
356
+ */
357
+ function withLoadNotifications(loadFn) {
358
+ return makeNotificationFeature([
359
+ {
360
+ provide: ENVIRONMENT_INITIALIZER,
361
+ useFactory: () => {
362
+ const notificationService = inject(NotificationService);
363
+ const notifications$ = loadNotifications(loadFn);
364
+ return () => {
365
+ notifications$.subscribe((notificationRefs) => notificationService.load(notificationRefs));
366
+ };
367
+ },
368
+ multi: true,
369
+ },
370
+ ]);
371
+ }
372
+
373
+ /**
374
+ * Asynchronously saves notifications using the provided save function. It handles Observable and Promise results seamlessly.
375
+ * @async
376
+ * @function saveNotifications
377
+ * @param {NotificationRef[]} notifications - The notifications to be saved.
378
+ * @param {SaveNotificationsFn} [saveFn] - Optional custom save function.
379
+ * @returns {Promise<void>} A promise that resolves when the save operation is complete.
380
+ */
381
+ async function saveNotifications(notifications, saveFn) {
382
+ const save = saveFn?.(notifications);
383
+ if (isObservable(save)) {
384
+ await firstValueFrom(save);
385
+ }
386
+ else if (save instanceof Promise) {
387
+ await save;
388
+ }
389
+ }
390
+ /**
391
+ * Configures the application to automatically save notifications using a specified save function.
392
+ * This setup integrates with Angular's environment initialization process to ensure notifications are saved as needed.
393
+ * @function withSaveNotifications
394
+ * @param {SaveNotificationsFn} saveFn - The function to save notifications.
395
+ * @returns {NotificationFeature} A notification feature configured to automatically save notifications.
396
+ */
397
+ function withSaveNotifications(saveFn) {
398
+ return makeNotificationFeature([
399
+ {
400
+ provide: ENVIRONMENT_INITIALIZER,
401
+ useFactory: () => {
402
+ const injector = inject(Injector);
403
+ const notificationService = inject(NotificationService);
404
+ const saveFnWithContext = (notifications) => runInInjectionContext(injector, () => saveFn(notifications));
405
+ return () => {
406
+ notificationService.notifications$.subscribe(({ values }) => saveNotifications(values, saveFnWithContext));
407
+ };
408
+ },
409
+ multi: true,
410
+ },
411
+ ]);
412
+ }
413
+
414
+ /**
415
+ * Implementation of NotificationSerializer for persistent storage.
416
+ * @class PersistentNotificationSerializer
417
+ * @implements {NotificationSerializer}
418
+ */
419
+ class PersistentNotificationSerializer {
420
+ /**
421
+ * Serializes an array of NotificationRef objects into a string.
422
+ * @function serialize
423
+ * @memberof NotificationSerializer
424
+ * @param {NotificationRef[]} value - The notification references to serialize.
425
+ * @returns {Promise<string>} A promise that resolves to the serialized string representation of notification references.
426
+ */
427
+ async serialize(value) {
428
+ const serializedNotifications = await Promise.all(value.map(async (ref) => deepmerge(ref, {
429
+ item: {
430
+ title: await this.serializeDynamicTextContent(ref.item.title),
431
+ description: await this.serializeDynamicTextContent(ref.item.description),
432
+ },
433
+ })));
434
+ return JSON.stringify(serializedNotifications);
435
+ }
436
+ /**
437
+ * Deserializes a string into an array of NotificationRef objects.
438
+ * @function deserialize
439
+ * @memberof NotificationSerializer
440
+ * @param {string} value - The string representation of notification references to deserialize.
441
+ * @returns {Promise<NotificationRef[]>} A promise that resolves to the deserialized notification references.
442
+ */
443
+ async deserialize(value) {
444
+ return JSON.parse(value);
445
+ }
446
+ async serializeDynamicTextContent(content) {
447
+ if (!content)
448
+ return '';
449
+ if (isString(content))
450
+ return content;
451
+ return firstValueFrom(content).catch(() => '');
452
+ }
453
+ }
454
+ /**
455
+ * Initializes and returns a function for loading persistent notifications.
456
+ * @function initPersistentNotifications
457
+ * @param {WithPersistentNotificationsStorageOptions} options - The storage options including serializer and storage key.
458
+ * @returns {LoadNotificationsFn} A function to load notifications from storage.
459
+ */
460
+ function initPersistentNotifications({ storage, storageKey, serializer, idTransformer, }) {
461
+ return async () => {
462
+ const storedValue = storage.getItem(storageKey);
463
+ if (!storedValue)
464
+ return [];
465
+ const notificationRefs = await serializer.deserialize(storedValue);
466
+ if (isFunction(idTransformer)) {
467
+ for (const notificationRef of notificationRefs) {
468
+ notificationRef.item.id = notificationRef.id = idTransformer(notificationRef);
469
+ }
470
+ }
471
+ return notificationRefs;
472
+ };
473
+ }
474
+ /**
475
+ * Returns a function for persisting notifications.
476
+ * @function persistNotifications
477
+ * @param {WithPersistentNotificationsStorageOptions} options - The storage options including serializer and storage key.
478
+ * @returns {SaveNotificationsFn} A function to save notifications to storage.
479
+ */
480
+ function persistNotifications({ storage, storageKey, serializer }) {
481
+ return async (notificationRefs) => {
482
+ storage.setItem(storageKey, await serializer.serialize(notificationRefs));
483
+ };
484
+ }
485
+ /**
486
+ * Configures the application to use persistent notifications, automatically loading from and saving to the configured storage.
487
+ * @function withPersistentNotifications
488
+ * @param {Partial<WithPersistentNotificationsOptions>} [options] - Optional configuration for persistent notifications.
489
+ * @returns {NotificationFeature} A notification feature configured for persistence.
490
+ */
491
+ function withPersistentNotifications(options) {
492
+ const storageOptions = {
493
+ storageKey: options?.storageOptions?.storageKey ?? '@odx/angular/components/notification::Storage',
494
+ storage: options?.storageOptions?.storage ?? localStorage,
495
+ serializer: options?.storageOptions?.serializer ?? new PersistentNotificationSerializer(),
496
+ };
497
+ const initFn = options?.initFn ?? initPersistentNotifications(storageOptions);
498
+ const saveFn = options?.saveFn ?? persistNotifications(storageOptions);
499
+ return makeNotificationFeature([withLoadNotifications(initFn), withSaveNotifications(saveFn)]);
500
+ }
501
+
502
+ /**
503
+ * Requests permission to display browser notifications and returns a boolean indicating whether permission was granted.
504
+ * @async
505
+ * @function requestBrowserNotificationPermissions
506
+ * @returns {Promise<boolean>} A promise that resolves to `true` if permission is granted, otherwise `false`.
507
+ */
508
+ async function requestBrowserNotificationPermissions() {
509
+ if (!('Notification' in window))
510
+ return false;
511
+ if (Notification.permission === 'granted')
512
+ return true;
513
+ if (Notification.permission === 'denied')
514
+ return false;
515
+ const permission = await Notification.requestPermission();
516
+ return permission === 'granted';
517
+ }
518
+ /**
519
+ * Creates a function responsible for sending out browser notifications with the given options.
520
+ * @function sendBrowserNotification
521
+ * @param {NotificationSerializer} serializer - The serializer to use for notification data.
522
+ * @param {BrowserNotificationExtras} [options] - Additional options for the browser notification.
523
+ * @returns {SendBrowserNotificationFn} A function to send browser notifications.
524
+ */
525
+ function sendBrowserNotification(serializer, options) {
526
+ return async (notificationRef) => {
527
+ if (!('Notification' in window))
528
+ return;
529
+ const [notificationObj] = await serializer.deserialize(await serializer.serialize([notificationRef]));
530
+ if (!notificationObj || notificationObj.hasBeenSeen)
531
+ return;
532
+ const { createdAt, item } = notificationObj;
533
+ new Notification(item.title, {
534
+ tag: notificationRef.options.tags?.[0],
535
+ lang: notificationRef.options.language,
536
+ ...options,
537
+ body: item.description,
538
+ timestamp: createdAt,
539
+ });
540
+ };
541
+ }
542
+ /**
543
+ * Configures the application to send browser notifications, using Angular's `ENVIRONMENT_INITIALIZER` for setup.
544
+ * @function withBrowserNotifications
545
+ * @param {WithBrowserNotificationsOptions} [options] - Optional configuration for browser notifications.
546
+ * @returns {NotificationFeature} A notification feature for integration into the application environment.
547
+ */
548
+ function withBrowserNotifications(options) {
549
+ return makeNotificationFeature([
550
+ {
551
+ provide: ENVIRONMENT_INITIALIZER,
552
+ useFactory: () => {
553
+ const isEnabled = options?.isEnabled ?? true;
554
+ if (!isEnabled)
555
+ return () => void 0;
556
+ const notificationService = inject(NotificationService);
557
+ const serializer = new PersistentNotificationSerializer();
558
+ const sendBrowserNotificationFn = options?.sendFn ?? sendBrowserNotification(serializer, options?.extras);
559
+ return async () => {
560
+ if (!isEnabled)
561
+ return;
562
+ const permissionsGranted = await requestBrowserNotificationPermissions();
563
+ if (!permissionsGranted)
564
+ return;
565
+ notificationService.onNotificationAdd$.subscribe(sendBrowserNotificationFn);
566
+ };
567
+ },
568
+ multi: true,
569
+ },
570
+ ]);
571
+ }
572
+
573
+ /**
574
+ * An InjectionToken for the NotificationTransformFn. This token can be used to inject
575
+ * a custom notification transformation function into the Angular DI system.
576
+ * @type {InjectionToken<NotificationTransformFn>}
577
+ */
578
+ const ODX_NOTIFICATION_TRANSFORMER = new InjectionToken('@odx/angular/components/notification::NotificationTransformer');
579
+ /**
580
+ * Attempts to inject a NotificationTransformFn from the Angular DI system.
581
+ * If no provider is found, it returns null.
582
+ * @function injectNotificationTransform
583
+ * @returns {NotificationTransformFn | null} The injected NotificationTransformFn, or null if not provided.
584
+ */
585
+ function injectNotificationTransform() {
586
+ return inject(ODX_NOTIFICATION_TRANSFORMER, { optional: true });
587
+ }
588
+ /**
589
+ * Configures a notification transformation function to be used within the application.
590
+ * This function provides a mechanism to globally apply transformations to notifications
591
+ * before they are processed or displayed.
592
+ * @function withNotificationTransform
593
+ * @param {NotificationTransformFn} transformFn - The function to transform notifications.
594
+ * @returns {NotificationFeature} A NotificationFeature configured with the provided transformation function.
595
+ */
596
+ function withNotificationTransform(transformFn) {
597
+ return makeNotificationFeature([
598
+ {
599
+ provide: ODX_NOTIFICATION_TRANSFORMER,
600
+ useValue: transformFn,
601
+ },
602
+ ]);
603
+ }
604
+
605
+ /**
606
+ * A component for displaying notifications.
607
+ * Supports customization through dynamic transformation of notification data.
608
+ * Utilizes the OnPush change detection strategy for better performance in large applications.
609
+ *
610
+ * @component
611
+ */
612
+ let NotificationItemComponent = class NotificationItemComponent {
613
+ constructor() {
614
+ this.transformNotification = injectNotificationTransform();
615
+ this.element = injectElement();
616
+ /**
617
+ * An event emitter for dismissing the notification.
618
+ * It emits the notification reference that was dismissed.
619
+ */
620
+ this.dismiss = new EventEmitter();
621
+ }
622
+ /**
623
+ * Input property to set the notification. On setting, it transforms the notification for display.
624
+ * This transformation can be a custom logic provided through dependency injection.
625
+ *
626
+ * @param value NotificationRef - The notification object to be displayed.
627
+ */
628
+ set notification(value) {
629
+ this._notificationRef = value;
630
+ this.transformedNotification = this.transformNotification?.(value) ?? of(value);
631
+ }
632
+ /**
633
+ * Getter for the notification property.
634
+ *
635
+ * @returns NotificationRef - The current notification reference stored in the component.
636
+ */
637
+ get notification() {
638
+ return this._notificationRef;
639
+ }
640
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
641
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NotificationItemComponent, isStandalone: true, selector: "odx-notification-item", inputs: { notification: "notification" }, outputs: { dismiss: "dismiss" }, ngImport: i0, template: "<ng-template [ngIf]=\"transformedNotification | async\" let-ref>\n <odx-avatar class=\"odx-notification-item__avatar odx-no-margin\">\n <odx-icon [identifier]=\"ref.options.icon\" />\n </odx-avatar>\n <div class=\"odx-notification-item__title\">\n <ng-template [odxDynamicView]=\"ref.item.title\" />\n </div>\n <div class=\"odx-notification-item__description\" *ngIf=\"ref.item.description as description\">\n <ng-template [odxDynamicView]=\"ref.item.description\" />\n </div>\n</ng-template>\n<odx-action-group class=\"odx-notification-item__actions odx-no-margin\">\n <button odxButton class=\"odx-no-margin\" (click)=\"dismiss.next(notification)\" *ngIf=\"notification.options.dismissable\">\n <odx-icon name=\"close\" iconSet=\"core\"></odx-icon>\n </button>\n</odx-action-group>\n", dependencies: [{ kind: "component", type: AvatarComponent, selector: "odx-avatar", inputs: ["size", "variant"] }, { kind: "component", type: ActionGroupComponent, selector: "odx-action-group", inputs: ["reverse"] }, { kind: "component", type: ButtonComponent, selector: "button[odxButton], a[odxButton]", inputs: ["variant", "size"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "directive", type: DynamicViewDirective, selector: "ng-template[odxDynamicView]", inputs: ["odxDynamicView", "odxDynamicViewInjector", "odxDynamicViewContext"] }, { kind: "component", type: IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet", "identifier"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
642
+ };
643
+ NotificationItemComponent = __decorate([
644
+ CSSComponent('notification-item')
645
+ ], NotificationItemComponent);
646
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationItemComponent, decorators: [{
647
+ type: Component,
648
+ args: [{ selector: 'odx-notification-item', standalone: true, imports: [AvatarComponent, ActionGroupComponent, ButtonComponent, CommonModule, DynamicViewDirective, IconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template [ngIf]=\"transformedNotification | async\" let-ref>\n <odx-avatar class=\"odx-notification-item__avatar odx-no-margin\">\n <odx-icon [identifier]=\"ref.options.icon\" />\n </odx-avatar>\n <div class=\"odx-notification-item__title\">\n <ng-template [odxDynamicView]=\"ref.item.title\" />\n </div>\n <div class=\"odx-notification-item__description\" *ngIf=\"ref.item.description as description\">\n <ng-template [odxDynamicView]=\"ref.item.description\" />\n </div>\n</ng-template>\n<odx-action-group class=\"odx-notification-item__actions odx-no-margin\">\n <button odxButton class=\"odx-no-margin\" (click)=\"dismiss.next(notification)\" *ngIf=\"notification.options.dismissable\">\n <odx-icon name=\"close\" iconSet=\"core\"></odx-icon>\n </button>\n</odx-action-group>\n" }]
649
+ }], propDecorators: { notification: [{
650
+ type: Input,
651
+ args: [{ required: true }]
652
+ }], dismiss: [{
653
+ type: Output
654
+ }] } });
655
+
656
+ /**
657
+ * A component for displaying and managing a list of notifications. It integrates various sub-components and directives to provide a rich user interface for notification interaction. Supports animations for notification transitions and leverages Angular's change detection strategies for performance.
658
+ *
659
+ * @CSSComponent 'notification-center' - Specifies the CSS class for styling the notification center component.
660
+ */
661
+ let NotificationCenterComponent = class NotificationCenterComponent {
662
+ constructor() {
663
+ this.notificationCenterService = inject(NotificationCenterService);
664
+ this.trackById = trackById;
665
+ this.element = injectElement();
666
+ }
667
+ ngOnDestroy() {
668
+ this.notificationCenterService.markAllAsSeen();
669
+ }
670
+ isMuted({ options, hasBeenSeen }) {
671
+ return hasBeenSeen && !options.action;
672
+ }
673
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationCenterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
674
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NotificationCenterComponent, isStandalone: true, selector: "odx-notification-center", providers: [provideTranslations(notificationI18n)], ngImport: i0, template: "<ng-template [ngIf]=\"notificationCenterService.notifications$ | async\" let-notifications>\n <h3 class=\"odx-notification-center__header\" *ngrxLet=\"notificationCenterService.title$ | async as title\">\n <ng-template [odxDynamicView]=\"title ?? ('title' | odxTranslate | async)\"></ng-template>\n </h3>\n <odx-list class=\"odx-notification-center__content\">\n <odx-list-item\n @notificationAnimation\n [muted]=\"isMuted(notification)\"\n [selected]=\"!notification.hasBeenSeen\"\n (click)=\"notificationCenterService.executeAction(notification)\"\n *ngFor=\"let notification of notifications.values; trackBy: trackById\"\n >\n <odx-notification-item [notification]=\"notification\" (dismiss)=\"notificationCenterService.dismiss(notification)\" />\n </odx-list-item>\n </odx-list>\n <div class=\"odx-notification-center__footer\">\n <button odxButton [disabled]=\"false\" (click)=\"notificationCenterService.dismissAll()\">\n {{ 'dismissAll' | odxTranslate | async }}\n </button>\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "directive", type: LetDirective, selector: "[ngrxLet]", inputs: ["ngrxLet", "ngrxLetSuspenseTpl"] }, { kind: "component", type: ButtonComponent, selector: "button[odxButton], a[odxButton]", inputs: ["variant", "size"] }, { kind: "directive", type: DynamicViewDirective, selector: "ng-template[odxDynamicView]", inputs: ["odxDynamicView", "odxDynamicViewInjector", "odxDynamicViewContext"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "directive", type: i2.DisabledController, selector: "[disabled]", inputs: ["disabled"] }, { kind: "pipe", type: TranslatePipe, name: "odxTranslate" }, { kind: "component", type: NotificationItemComponent, selector: "odx-notification-item", inputs: ["notification"], outputs: ["dismiss"] }, { kind: "ngmodule", type: ListModule }, { kind: "component", type: i3.ListComponent, selector: "odx-list" }, { kind: "component", type: i3.ListItemComponent, selector: "odx-list-item, [odxListItem]", inputs: ["danger", "muted", "selected"] }], animations: [trigger('notificationAnimation', [transition(':leave', useAnimation(collapse, { delay: 150 }))])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
675
+ };
676
+ NotificationCenterComponent = __decorate([
677
+ CSSComponent('notification-center')
678
+ ], NotificationCenterComponent);
679
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationCenterComponent, decorators: [{
680
+ type: Component,
681
+ args: [{ selector: 'odx-notification-center', standalone: true, imports: [
682
+ CommonModule,
683
+ LetDirective,
684
+ ActionGroupComponent,
685
+ BadgeDirective,
686
+ ButtonComponent,
687
+ DynamicViewDirective,
688
+ IconComponent,
689
+ DropdownModule,
690
+ TranslatePipe,
691
+ NotificationItemComponent,
692
+ InteractiveDirective,
693
+ ListModule,
694
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [provideTranslations(notificationI18n)], animations: [trigger('notificationAnimation', [transition(':leave', useAnimation(collapse, { delay: 150 }))])], template: "<ng-template [ngIf]=\"notificationCenterService.notifications$ | async\" let-notifications>\n <h3 class=\"odx-notification-center__header\" *ngrxLet=\"notificationCenterService.title$ | async as title\">\n <ng-template [odxDynamicView]=\"title ?? ('title' | odxTranslate | async)\"></ng-template>\n </h3>\n <odx-list class=\"odx-notification-center__content\">\n <odx-list-item\n @notificationAnimation\n [muted]=\"isMuted(notification)\"\n [selected]=\"!notification.hasBeenSeen\"\n (click)=\"notificationCenterService.executeAction(notification)\"\n *ngFor=\"let notification of notifications.values; trackBy: trackById\"\n >\n <odx-notification-item [notification]=\"notification\" (dismiss)=\"notificationCenterService.dismiss(notification)\" />\n </odx-list-item>\n </odx-list>\n <div class=\"odx-notification-center__footer\">\n <button odxButton [disabled]=\"false\" (click)=\"notificationCenterService.dismissAll()\">\n {{ 'dismissAll' | odxTranslate | async }}\n </button>\n </div>\n</ng-template>\n" }]
695
+ }] });
696
+
697
+ /**
698
+ * A directive that provides an interface for managing notifications.
699
+ * It allows configuring a notification center with dynamic content, sorting, and badge display functionalities.
700
+ */
701
+ class NotificationCenterDirective {
702
+ constructor() {
703
+ this.badgeDirective = inject(BadgeDirective, { self: true });
704
+ this.destroyRef = inject(DestroyRef);
705
+ this.disabledController = DisabledController.inject();
706
+ this.dropdownDirective = inject(DropdownDirective, { self: true });
707
+ this.notificationCenterService = inject(NotificationCenterService, { self: true });
708
+ this.dropdownStateChange$ = merge(this.dropdownDirective.beforeOpen, this.dropdownDirective.beforeClose).pipe(startWith(void 0));
709
+ this.badgeValue$ = this.notificationCenterService.unseenNotifications$.pipe(switchMap(({ count }) => this.dropdownStateChange$.pipe(map(() => this.formatBadgeValue(count)))));
710
+ /**
711
+ * An event that is emitted when a new notification is added.
712
+ * Listeners can use this event to react to new notifications being added to the notification center.
713
+ */
714
+ // eslint-disable-next-line @angular-eslint/no-output-rename
715
+ this.notificationAdd = this.notificationCenterService.onNotificationAdd$;
716
+ /**
717
+ * An event that is emitted when a notification is updated.
718
+ * This can be used to react to changes in notifications, such as their read status or content updates.
719
+ */
720
+ // eslint-disable-next-line @angular-eslint/no-output-rename
721
+ this.notificationUpdate = this.notificationCenterService.onNotificationUpdate$;
722
+ /**
723
+ * An event that is emitted when a notification is removed from the notification center.
724
+ * Use this event to handle the removal of notifications, such as cleaning up resources or updating UI elements.
725
+ */
726
+ // eslint-disable-next-line @angular-eslint/no-output-rename
727
+ this.notificationRemove = this.notificationCenterService.onNotificationRemove$;
728
+ /**
729
+ * An event that is emitted when a notification is marked as seen.
730
+ * This event can be used to perform actions when the user acknowledges a notification.
731
+ */
732
+ // eslint-disable-next-line @angular-eslint/no-output-rename
733
+ this.notificationSeen = this.notificationCenterService.onNotificationSeen$;
734
+ }
735
+ /**
736
+ * Sets the tag for filtering notifications. Only notifications with this tag will be shown in the notification center.
737
+ * @param value The tag value to filter notifications. If null, all notifications are shown.
738
+ */
739
+ set tag(value) {
740
+ this.notificationCenterService.setTag(value);
741
+ }
742
+ /**
743
+ * Sets the title of the notification center. The title can be dynamic and change based on the application state.
744
+ * @param value The title content, which can be a string or an Observable returning a string. Allows for dynamic titles.
745
+ */
746
+ set title(value) {
747
+ this.notificationCenterService.setTitle(value);
748
+ }
749
+ /**
750
+ * Sets the sorting function used to order notifications within the notification center.
751
+ * @param value A function that compares two notifications and returns the sort order.
752
+ *
753
+ * @example
754
+ * sortFfn = (a: NotificationRef, b: NotificationRef) => {
755
+ if (a.createdAt < b.createdAt) return -1;
756
+ if (a.createdAt > b.createdAt) return 1;
757
+ return 0;
758
+ };
759
+ */
760
+ set sortFn(value) {
761
+ this.notificationCenterService.setSortFn(value);
762
+ }
763
+ ngOnInit() {
764
+ this.badgeDirective.position = Position.BOTTOM;
765
+ this.badgeDirective.offset = 6;
766
+ this.dropdownDirective.content = NotificationCenterComponent;
767
+ this.dropdownDirective.options = {
768
+ containerClass: 'odx-notification-center-overlay',
769
+ position: Position.BOTTOM_END,
770
+ enableFallback: false,
771
+ };
772
+ }
773
+ ngAfterViewInit() {
774
+ merge(this.handleBadgeUpdates(), this.handleDropdownUpdates()).pipe(takeUntilDestroyed(this.destroyRef)).subscribe();
775
+ }
776
+ formatBadgeValue(value) {
777
+ return this.dropdownDirective.isOpen || value === 0 ? null : value.toFixed(0);
778
+ }
779
+ handleBadgeUpdates() {
780
+ return this.badgeValue$.pipe(tap((value) => {
781
+ this.badgeDirective.value = value;
782
+ this.badgeDirective.ngOnChanges();
783
+ }));
784
+ }
785
+ handleDropdownUpdates() {
786
+ return this.notificationCenterService.notifications$.pipe(tap(({ isEmpty }) => {
787
+ this.disabledController?.setDisabledState(isEmpty);
788
+ if (!isEmpty)
789
+ return;
790
+ this.dropdownDirective.close();
791
+ }));
792
+ }
793
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationCenterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
794
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: NotificationCenterDirective, isStandalone: true, selector: "[odxNotificationCenter]", inputs: { tag: ["odxNotificationCenter", "tag"], title: ["odxNotificationCenterTitle", "title"], sortFn: ["odxNotificationCenterSortFn", "sortFn"] }, outputs: { notificationAdd: "odxNotificationCenterAdd", notificationUpdate: "odxNotificationCenterUpdate", notificationRemove: "odxNotificationCenterRemove", notificationSeen: "odxNotificationCenterSeen" }, providers: [NotificationCenterService], hostDirectives: [{ directive: i1$1.BadgeDirective, inputs: ["odxBadgeVariant", "odxNotificationCenterBadgeVariant"] }, { directive: i2$1.DropdownDirective }], ngImport: i0 }); }
795
+ }
796
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NotificationCenterDirective, decorators: [{
797
+ type: Directive,
798
+ args: [{
799
+ standalone: true,
800
+ selector: '[odxNotificationCenter]',
801
+ hostDirectives: [{ directive: BadgeDirective, inputs: ['odxBadgeVariant:odxNotificationCenterBadgeVariant'] }, DropdownDirective],
802
+ providers: [NotificationCenterService],
803
+ }]
804
+ }], propDecorators: { tag: [{
805
+ type: Input,
806
+ args: ['odxNotificationCenter']
807
+ }], title: [{
808
+ type: Input,
809
+ args: ['odxNotificationCenterTitle']
810
+ }], sortFn: [{
811
+ type: Input,
812
+ args: ['odxNotificationCenterSortFn']
813
+ }], notificationAdd: [{
814
+ type: Output,
815
+ args: ['odxNotificationCenterAdd']
816
+ }], notificationUpdate: [{
817
+ type: Output,
818
+ args: ['odxNotificationCenterUpdate']
819
+ }], notificationRemove: [{
820
+ type: Output,
821
+ args: ['odxNotificationCenterRemove']
822
+ }], notificationSeen: [{
823
+ type: Output,
824
+ args: ['odxNotificationCenterSeen']
825
+ }] } });
826
+
827
+ /**
828
+ * Generated bundle index. Do not edit.
829
+ */
830
+
831
+ export { NotificationCenterComponent, NotificationCenterDirective, NotificationConfig, NotificationDefaultConfig, NotificationItemComponent, NotificationService, ODX_NOTIFICATION_QUEUE, ODX_NOTIFICATION_TRANSFORMER, PersistentNotificationSerializer, initPersistentNotifications, injectNotificationConfig, injectNotificationTransform, makeNotificationFeature, persistNotifications, provideNotificationConfig, provideNotifications, withBrowserNotifications, withLoadNotifications, withNotificationTransform, withPersistentNotifications, withSaveNotifications };
832
+ //# sourceMappingURL=odx-angular-components-notification.mjs.map