@servicetitan/notifications 28.5.0 → 29.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/dist/__tests__/intercept.test.d.ts +2 -0
  2. package/dist/__tests__/intercept.test.d.ts.map +1 -0
  3. package/dist/__tests__/intercept.test.js +13 -0
  4. package/dist/__tests__/intercept.test.js.map +1 -0
  5. package/dist/__tests__/notifications-service.test.d.ts +2 -0
  6. package/dist/__tests__/notifications-service.test.d.ts.map +1 -0
  7. package/dist/__tests__/notifications-service.test.js +42 -0
  8. package/dist/__tests__/notifications-service.test.js.map +1 -0
  9. package/dist/api/notifications.api.d.ts +2 -2
  10. package/dist/api/notifications.api.d.ts.map +1 -1
  11. package/dist/common.d.ts +4 -22
  12. package/dist/common.d.ts.map +1 -1
  13. package/dist/common.js +4 -11
  14. package/dist/common.js.map +1 -1
  15. package/dist/components/__tests__/notifications.test.d.ts +2 -0
  16. package/dist/components/__tests__/notifications.test.d.ts.map +1 -0
  17. package/dist/components/__tests__/notifications.test.js +93 -0
  18. package/dist/components/__tests__/notifications.test.js.map +1 -0
  19. package/dist/components/notifications.d.ts +8 -1
  20. package/dist/components/notifications.d.ts.map +1 -1
  21. package/dist/components/notifications.js +43 -23
  22. package/dist/components/notifications.js.map +1 -1
  23. package/dist/demo/action-button-preview.d.ts.map +1 -1
  24. package/dist/demo/action-button-preview.js +2 -2
  25. package/dist/demo/action-button-preview.js.map +1 -1
  26. package/dist/demo/basic-preview.d.ts.map +1 -1
  27. package/dist/demo/basic-preview.js +1 -1
  28. package/dist/demo/basic-preview.js.map +1 -1
  29. package/dist/demo/container.d.ts +1 -3
  30. package/dist/demo/container.d.ts.map +1 -1
  31. package/dist/demo/container.js.map +1 -1
  32. package/dist/demo/duration-preview.d.ts.map +1 -1
  33. package/dist/demo/duration-preview.js +2 -2
  34. package/dist/demo/duration-preview.js.map +1 -1
  35. package/dist/demo/multiline-message-preview.d.ts.map +1 -1
  36. package/dist/demo/multiline-message-preview.js +2 -2
  37. package/dist/demo/multiline-message-preview.js.map +1 -1
  38. package/dist/demo/prevent-duplicates-preview.d.ts.map +1 -1
  39. package/dist/demo/prevent-duplicates-preview.js +2 -2
  40. package/dist/demo/prevent-duplicates-preview.js.map +1 -1
  41. package/dist/demo/progress-preview.d.ts.map +1 -1
  42. package/dist/demo/progress-preview.js +2 -2
  43. package/dist/demo/progress-preview.js.map +1 -1
  44. package/dist/demo/server-custom-preview.d.ts +1 -1
  45. package/dist/demo/server-custom-preview.d.ts.map +1 -1
  46. package/dist/demo/server-custom-preview.js +21 -7
  47. package/dist/demo/server-custom-preview.js.map +1 -1
  48. package/dist/demo/server-custom.d.ts +0 -1
  49. package/dist/demo/server-custom.d.ts.map +1 -1
  50. package/dist/demo/server-custom.js +25 -21
  51. package/dist/demo/server-custom.js.map +1 -1
  52. package/dist/demo/server-default.d.ts.map +1 -1
  53. package/dist/demo/server-default.js +1 -1
  54. package/dist/demo/server-default.js.map +1 -1
  55. package/dist/demo/status-variations-preview.d.ts.map +1 -1
  56. package/dist/demo/status-variations-preview.js +2 -2
  57. package/dist/demo/status-variations-preview.js.map +1 -1
  58. package/dist/demo/status-variations.d.ts.map +1 -1
  59. package/dist/demo/status-variations.js.map +1 -1
  60. package/dist/index.d.ts +3 -4
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +3 -4
  63. package/dist/index.js.map +1 -1
  64. package/dist/intercept.d.ts +4 -0
  65. package/dist/intercept.d.ts.map +1 -0
  66. package/dist/intercept.js +5 -0
  67. package/dist/intercept.js.map +1 -0
  68. package/dist/notifications-channel.d.ts +2 -6
  69. package/dist/notifications-channel.d.ts.map +1 -1
  70. package/dist/notifications-channel.js.map +1 -1
  71. package/dist/notifications-service.d.ts +10 -8
  72. package/dist/notifications-service.d.ts.map +1 -1
  73. package/dist/notifications-service.js.map +1 -1
  74. package/dist/notifications.stories.d.ts +14 -0
  75. package/dist/notifications.stories.d.ts.map +1 -0
  76. package/dist/notifications.stories.js +20 -0
  77. package/dist/notifications.stories.js.map +1 -0
  78. package/dist/stores/__mocks__/mock-notifications-channel.d.ts +11 -0
  79. package/dist/stores/__mocks__/mock-notifications-channel.d.ts.map +1 -0
  80. package/dist/stores/__mocks__/mock-notifications-channel.js +36 -0
  81. package/dist/stores/__mocks__/mock-notifications-channel.js.map +1 -0
  82. package/dist/stores/__tests__/notifications.store.test.d.ts +2 -0
  83. package/dist/stores/__tests__/notifications.store.test.d.ts.map +1 -0
  84. package/dist/stores/__tests__/notifications.store.test.js +360 -0
  85. package/dist/stores/__tests__/notifications.store.test.js.map +1 -0
  86. package/dist/stores/notifications.store.d.ts +20 -8
  87. package/dist/stores/notifications.store.d.ts.map +1 -1
  88. package/dist/stores/notifications.store.js +156 -45
  89. package/dist/stores/notifications.store.js.map +1 -1
  90. package/dist/utils/__tests__/date-from-string.test.d.ts +2 -0
  91. package/dist/utils/__tests__/date-from-string.test.d.ts.map +1 -0
  92. package/dist/utils/__tests__/date-from-string.test.js +39 -0
  93. package/dist/utils/__tests__/date-from-string.test.js.map +1 -0
  94. package/dist/utils/__tests__/use-compatible-navigate.test.d.ts +2 -0
  95. package/dist/utils/__tests__/use-compatible-navigate.test.d.ts.map +1 -0
  96. package/dist/utils/__tests__/use-compatible-navigate.test.js +27 -0
  97. package/dist/utils/__tests__/use-compatible-navigate.test.js.map +1 -0
  98. package/dist/utils/date-from-string.d.ts.map +1 -0
  99. package/dist/utils/date-from-string.js +19 -0
  100. package/dist/utils/date-from-string.js.map +1 -0
  101. package/package.json +6 -6
  102. package/src/__tests__/intercept.test.ts +18 -0
  103. package/src/__tests__/notifications-service.test.ts +62 -0
  104. package/src/api/notifications.api.ts +2 -2
  105. package/src/common.ts +12 -27
  106. package/src/components/__tests__/notifications.test.tsx +107 -0
  107. package/src/components/notifications.tsx +59 -36
  108. package/src/demo/action-button-preview.tsx +4 -6
  109. package/src/demo/basic-preview.tsx +2 -4
  110. package/src/demo/container.tsx +1 -4
  111. package/src/demo/duration-preview.tsx +4 -6
  112. package/src/demo/multiline-message-preview.tsx +3 -9
  113. package/src/demo/prevent-duplicates-preview.tsx +3 -9
  114. package/src/demo/progress-preview.tsx +3 -9
  115. package/src/demo/server-custom-preview.tsx +17 -14
  116. package/src/demo/server-custom.tsx +30 -29
  117. package/src/demo/server-default.tsx +1 -3
  118. package/src/demo/status-variations-preview.tsx +4 -6
  119. package/src/demo/status-variations.tsx +0 -1
  120. package/src/index.ts +13 -4
  121. package/src/intercept.ts +14 -0
  122. package/src/notifications-channel.ts +2 -6
  123. package/src/notifications-service.ts +14 -42
  124. package/src/stores/__mocks__/mock-notifications-channel.ts +31 -0
  125. package/src/stores/__tests__/notifications.store.test.ts +458 -0
  126. package/src/stores/notifications.store.ts +178 -53
  127. package/src/utils/__tests__/date-from-string.test.ts +53 -0
  128. package/src/utils/__tests__/use-compatible-navigate.test.ts +43 -0
  129. package/src/utils/date-from-string.ts +22 -0
  130. package/dist/components/__tests__/container.test.d.ts +0 -2
  131. package/dist/components/__tests__/container.test.d.ts.map +0 -1
  132. package/dist/components/__tests__/container.test.js +0 -59
  133. package/dist/components/__tests__/container.test.js.map +0 -1
  134. package/dist/components/container.d.ts +0 -3
  135. package/dist/components/container.d.ts.map +0 -1
  136. package/dist/components/container.js +0 -26
  137. package/dist/components/container.js.map +0 -1
  138. package/dist/components/default-notification.d.ts +0 -7
  139. package/dist/components/default-notification.d.ts.map +0 -1
  140. package/dist/components/default-notification.js +0 -26
  141. package/dist/components/default-notification.js.map +0 -1
  142. package/dist/components/default-notification.module.css +0 -3
  143. package/dist/components/no-ssr.d.ts +0 -5
  144. package/dist/components/no-ssr.d.ts.map +0 -1
  145. package/dist/components/no-ssr.js +0 -9
  146. package/dist/components/no-ssr.js.map +0 -1
  147. package/dist/components/notifications-unwrapped.d.ts +0 -3
  148. package/dist/components/notifications-unwrapped.d.ts.map +0 -1
  149. package/dist/components/notifications-unwrapped.js +0 -27
  150. package/dist/components/notifications-unwrapped.js.map +0 -1
  151. package/dist/components/shadow-dom.d.ts +0 -3
  152. package/dist/components/shadow-dom.d.ts.map +0 -1
  153. package/dist/components/shadow-dom.js +0 -41
  154. package/dist/components/shadow-dom.js.map +0 -1
  155. package/dist/components/use-style-sheets.d.ts +0 -2
  156. package/dist/components/use-style-sheets.d.ts.map +0 -1
  157. package/dist/components/use-style-sheets.js +0 -15
  158. package/dist/components/use-style-sheets.js.map +0 -1
  159. package/dist/create-element.d.ts +0 -2
  160. package/dist/create-element.d.ts.map +0 -1
  161. package/dist/create-element.js +0 -8
  162. package/dist/create-element.js.map +0 -1
  163. package/dist/date-from-string.d.ts.map +0 -1
  164. package/dist/date-from-string.js +0 -27
  165. package/dist/date-from-string.js.map +0 -1
  166. package/dist/register.d.ts +0 -3
  167. package/dist/register.d.ts.map +0 -1
  168. package/dist/register.js +0 -5
  169. package/dist/register.js.map +0 -1
  170. package/src/components/__tests__/container.test.tsx +0 -71
  171. package/src/components/container.tsx +0 -35
  172. package/src/components/default-notification.module.css +0 -3
  173. package/src/components/default-notification.module.css.d.ts +0 -4
  174. package/src/components/default-notification.tsx +0 -59
  175. package/src/components/no-ssr.tsx +0 -11
  176. package/src/components/notifications-unwrapped.tsx +0 -51
  177. package/src/components/shadow-dom.tsx +0 -53
  178. package/src/components/use-style-sheets.ts +0 -19
  179. package/src/create-element.ts +0 -12
  180. package/src/date-from-string.ts +0 -30
  181. package/src/register.ts +0 -6
  182. /package/dist/{date-from-string.d.ts → utils/date-from-string.d.ts} +0 -0
@@ -1,48 +1,48 @@
1
+ import { toast, toastProps } from '@servicetitan/anvil2';
1
2
  import { injectable, inject, optional } from '@servicetitan/react-ioc';
2
-
3
- import { observable, computed, action, runInAction, comparer, makeObservable } from 'mobx';
4
-
5
- import { NotificationsChannel, NOTIFICATIONS_CHANNEL_TOKEN } from '../notifications-channel';
3
+ import { action, runInAction, comparer, makeObservable } from 'mobx';
6
4
 
7
5
  import {
6
+ DefaultServerNotificationPayload,
8
7
  NotificationsApi,
9
8
  Notification as ServerNotification,
10
- NotificationProcessStatus,
9
+ NotificationProcessStatus as ServerNotificationStatus,
11
10
  } from '../api/notifications.api';
12
-
13
- import {
14
- isNewer,
15
- Notification,
16
- NotificationMapper,
17
- toClientNotification,
18
- DEFAULT_CLIENT_NOTIFICATION_TYPE,
19
- DefaultNotificationOptions,
20
- } from '../common';
21
- import { dateFromString } from '../date-from-string';
11
+ import { DefaultNotificationOptions, Notification, Status, isLinkAction, isNewer } from '../common';
12
+ import { NotificationInterceptor } from '../intercept';
13
+ import { NotificationsChannel, NOTIFICATIONS_CHANNEL_TOKEN } from '../notifications-channel';
14
+ import { dateFromString } from '../utils/date-from-string';
22
15
 
23
16
  const EVENT_NAME = 'NotificationEvent';
17
+ const CLIENT_NOTIFICATION_TYPE = 'ClientNotification';
18
+ const CLIENT_NOTIFICATION_VERSION = 1;
19
+ const DAY_INTERVAL = 24 * 60 * 60 * 1000;
24
20
 
25
21
  interface ClosedNotification {
26
- status: NotificationProcessStatus;
22
+ status: ServerNotificationStatus;
27
23
  timestamp: number;
28
24
  }
29
25
 
30
- const DAY_INTERVAL = 24 * 60 * 60 * 1000;
26
+ interface ClientNotification extends Notification<DefaultNotificationOptions> {
27
+ toastId?: string;
28
+ }
29
+
30
+ type NavigateCallback = (path: string) => void;
31
+
32
+ type ToastMethod = 'info' | 'success' | 'warning' | 'danger';
31
33
 
32
34
  @injectable()
33
35
  export class NotificationsStore {
34
- static types = new Map<string, NotificationMapper>();
35
-
36
- @observable
37
- private innerNotifications = new Map<number, Notification>();
36
+ static readonly interceptors = new Map<string, NotificationInterceptor>();
38
37
 
39
38
  private index = -1;
40
-
41
39
  private userId = 0;
42
-
43
40
  private intervalId?: number;
44
41
 
45
- private closedNotifications = new Map<number, ClosedNotification>();
42
+ private readonly notifications = new Map<number, ClientNotification>();
43
+ private readonly closedNotifications = new Map<number, ClosedNotification>();
44
+
45
+ #navigate?: NavigateCallback;
46
46
 
47
47
  constructor(
48
48
  @inject(NotificationsApi) @optional() private readonly notificationsApi?: NotificationsApi,
@@ -53,17 +53,24 @@ export class NotificationsStore {
53
53
  makeObservable(this);
54
54
  }
55
55
 
56
- static register = (type: string, mapper: NotificationMapper) =>
57
- NotificationsStore.types.set(type, mapper);
58
-
59
- @computed get notifications() {
60
- return Array.from(this.innerNotifications.values());
56
+ static intercept(type: string, fn?: NotificationInterceptor) {
57
+ if (fn) {
58
+ NotificationsStore.interceptors.set(type, fn);
59
+ } else {
60
+ NotificationsStore.interceptors.delete(type);
61
+ }
61
62
  }
62
63
 
63
64
  private get publisher() {
64
- if (this.notificationsChannel) {
65
- return this.notificationsChannel();
66
- }
65
+ return this.notificationsChannel?.();
66
+ }
67
+
68
+ get navigate(): NavigateCallback | undefined {
69
+ return this.#navigate;
70
+ }
71
+
72
+ set navigate(fn: NavigateCallback) {
73
+ this.#navigate = fn;
67
74
  }
68
75
 
69
76
  initialize = async (userId: number) => {
@@ -98,33 +105,38 @@ export class NotificationsStore {
98
105
 
99
106
  @action
100
107
  add = (options: DefaultNotificationOptions, preventDuplicates?: boolean) => {
101
- const notification = {
108
+ const notification: ClientNotification = {
102
109
  id: this.index,
103
110
  userId: this.userId,
104
- type: DEFAULT_CLIENT_NOTIFICATION_TYPE,
105
- status: NotificationProcessStatus.Info,
111
+ type: CLIENT_NOTIFICATION_TYPE,
112
+ status: ServerNotificationStatus.Info,
106
113
  isRead: false,
107
114
  createdOn: new Date(),
108
115
  modifiedOn: new Date(),
109
- version: NotificationProcessStatus.Info,
110
- payload: options,
116
+ version: CLIENT_NOTIFICATION_VERSION,
117
+ payload: { ...options },
111
118
  };
112
119
 
113
- if (
114
- !preventDuplicates ||
115
- !this.notifications.some(
116
- n => n.id < 0 && comparer.structural(n.payload, notification.payload)
117
- )
118
- ) {
119
- this.innerNotifications.set(notification.id, notification);
120
- this.index -= 1;
120
+ if (preventDuplicates) {
121
+ if (
122
+ [...this.notifications.values()].some(({ payload }) =>
123
+ comparer.structural(payload, notification.payload)
124
+ )
125
+ ) {
126
+ return;
127
+ }
128
+ this.notifications.set(notification.id, notification);
121
129
  }
130
+
131
+ const method = this.getToastMethod(notification);
132
+ notification.toastId = toast[method](this.getToastProps(notification));
133
+ this.index -= 1;
122
134
  };
123
135
 
124
136
  @action
125
137
  read = (notification: Notification) => {
126
138
  if (notification.id > 0) {
127
- if (notification.status === NotificationProcessStatus.InProgress) {
139
+ if (notification.status === ServerNotificationStatus.InProgress) {
128
140
  this.closedNotifications.set(notification.id, {
129
141
  status: notification.status,
130
142
  timestamp: Date.now(),
@@ -140,16 +152,15 @@ export class NotificationsStore {
140
152
  }
141
153
  }
142
154
 
143
- this.innerNotifications.delete(notification.id);
155
+ this.notifications.delete(notification.id);
144
156
  };
145
157
 
146
158
  @action
147
- private onPublisherEvent = (notification: ServerNotification) => {
159
+ private readonly onPublisherEvent = (notification: ServerNotification) => {
148
160
  if (notification.userId !== this.userId) {
149
161
  return;
150
162
  }
151
163
 
152
- // FIXME: FAR-385
153
164
  this.updateIfNewer({
154
165
  ...notification,
155
166
  createdOn: dateFromString(notification.createdOn),
@@ -166,9 +177,7 @@ export class NotificationsStore {
166
177
  }
167
178
 
168
179
  private updateIfNewer(notification: ServerNotification) {
169
- const existing = this.innerNotifications.get(notification.id);
170
180
  const closed = this.closedNotifications.get(notification.id);
171
-
172
181
  if (closed) {
173
182
  if (closed.status === notification.status) {
174
183
  return;
@@ -177,8 +186,124 @@ export class NotificationsStore {
177
186
  this.closedNotifications.delete(notification.id);
178
187
  }
179
188
 
180
- if (!existing || isNewer(existing, notification)) {
181
- this.innerNotifications.set(notification.id, toClientNotification(notification));
189
+ const clientNotification = this.toClientNotification(notification);
190
+ if (!clientNotification) {
191
+ return;
192
+ }
193
+
194
+ const existing = this.notifications.get(notification.id);
195
+ if (existing) {
196
+ if (!isNewer(existing, notification)) {
197
+ return;
198
+ }
199
+ if (
200
+ notification.status === existing.status ||
201
+ notification.status === ServerNotificationStatus.InProgress
202
+ ) {
203
+ toast.update(existing.toastId!, this.getToastProps(clientNotification));
204
+ return;
205
+ }
206
+ toast.dismiss(existing.toastId);
207
+ }
208
+
209
+ const method = this.getToastMethod(clientNotification);
210
+ clientNotification.toastId = toast[method](this.getToastProps(clientNotification));
211
+ this.notifications.set(notification.id, clientNotification);
212
+ }
213
+
214
+ private getToastMethod({ payload: { status } }: ClientNotification): ToastMethod {
215
+ switch (status) {
216
+ case Status.Success:
217
+ return 'success';
218
+ case Status.Error:
219
+ return 'danger';
220
+ case Status.Warning:
221
+ return 'warning';
222
+ default:
223
+ return 'info';
224
+ }
225
+ }
226
+
227
+ private getToastProps(notification: ClientNotification): toastProps {
228
+ const { action, duration, message = '', progress, title } = notification.payload;
229
+ return {
230
+ actions: this.getToastActions(notification),
231
+ duration: action ? false : duration,
232
+ message,
233
+ onClose: () => this.handleClose(notification),
234
+ progress,
235
+ title,
236
+ };
237
+ }
238
+
239
+ private getToastActions(notification: ClientNotification): toastProps['actions'] | undefined {
240
+ const { action } = notification.payload;
241
+ if (!action) {
242
+ return;
243
+ }
244
+
245
+ return {
246
+ primary: {
247
+ label: action.label,
248
+ onClick: () => this.handleClick(notification),
249
+ },
250
+ };
251
+ }
252
+
253
+ private handleClick({ payload: { action }, toastId }: ClientNotification) {
254
+ if (action) {
255
+ if (isLinkAction(action)) {
256
+ if (action.external) {
257
+ window.open(action.link);
258
+ } else {
259
+ this.navigate?.(action.link);
260
+ }
261
+ } else {
262
+ action.onClick();
263
+ }
264
+ }
265
+
266
+ toast.dismiss(toastId);
267
+ }
268
+
269
+ private handleClose(notification: Notification) {
270
+ this.read(notification);
271
+ }
272
+
273
+ private toClientNotification(
274
+ serverNotification: ServerNotification
275
+ ): ClientNotification | undefined {
276
+ const result: Notification<DefaultServerNotificationPayload> = {
277
+ ...serverNotification,
278
+ payload: {
279
+ ...JSON.parse(serverNotification.payload ?? '{}'),
280
+ status: this.toClientStatus(serverNotification.status),
281
+ },
282
+ };
283
+
284
+ const interceptor = NotificationsStore.interceptors.get(serverNotification.type);
285
+ if (!interceptor) {
286
+ return result;
287
+ }
288
+
289
+ const dismiss = () => {
290
+ const toastId = this.notifications.get(result.id)?.toastId;
291
+ if (toastId) {
292
+ toast.dismiss(toastId);
293
+ }
294
+ };
295
+
296
+ return interceptor(result, dismiss);
297
+ }
298
+
299
+ private toClientStatus(status: ServerNotificationStatus) {
300
+ switch (status) {
301
+ case ServerNotificationStatus.Success:
302
+ return Status.Success;
303
+ case ServerNotificationStatus.Failure:
304
+ return Status.Error;
305
+ default:
306
+ return Status.Info;
182
307
  }
183
308
  }
184
309
  }
@@ -0,0 +1,53 @@
1
+ import { dateFromString } from '../date-from-string';
2
+
3
+ describe(dateFromString.name, () => {
4
+ let value: string | Date;
5
+
6
+ const subject = () => dateFromString(value);
7
+
8
+ describe('with Date value', () => {
9
+ beforeEach(() => (value = new Date()));
10
+
11
+ test('returns value', () => {
12
+ expect(subject()).toBe(value);
13
+ });
14
+ });
15
+
16
+ describe('with a ISO date string', () => {
17
+ const date = new Date(2025, 1, 3, 14, 15, 9, 265);
18
+
19
+ beforeEach(() => (value = date.toISOString()));
20
+
21
+ test('converts string to date', () => {
22
+ expect(subject()).toEqual(date);
23
+ });
24
+ });
25
+
26
+ describe('with a .NET date string', () => {
27
+ const now = Date.now();
28
+
29
+ beforeEach(() => (value = `/Date(${now})/`));
30
+
31
+ function itConvertsStringToDate() {
32
+ test('converts string to date', () => {
33
+ expect(subject()).toEqual(new Date(now));
34
+ });
35
+ }
36
+
37
+ itConvertsStringToDate();
38
+
39
+ describe('when date has optional local offset', () => {
40
+ beforeEach(() => (value = `/Date(${now}-0500)/`));
41
+
42
+ itConvertsStringToDate();
43
+ });
44
+ });
45
+
46
+ describe('with unrecognized value', () => {
47
+ beforeEach(() => (value = 'foo'));
48
+
49
+ test('throws error', () => {
50
+ expect(subject).toThrow('Incorrect date format');
51
+ });
52
+ });
53
+ });
@@ -0,0 +1,43 @@
1
+ import { renderHook } from '@testing-library/react';
2
+ import * as ReactRouterDOM from 'react-router-dom';
3
+
4
+ import { useCompatibleNavigate } from '../use-compatible-navigate';
5
+
6
+ jest.mock('react-router-dom', () => ({
7
+ useHistory: jest.fn(),
8
+ useNavigate: jest.fn(),
9
+ }));
10
+
11
+ describe(useCompatibleNavigate.name, () => {
12
+ const subject = () => renderHook(() => useCompatibleNavigate());
13
+
14
+ describe('when useNavigate exists', () => {
15
+ const navigate = jest.fn();
16
+
17
+ beforeEach(() =>
18
+ jest.mocked((ReactRouterDOM as any).useNavigate).mockReturnValue(navigate)
19
+ );
20
+
21
+ test('returns useNavigate result', () => {
22
+ const {
23
+ result: { current: value },
24
+ } = subject();
25
+
26
+ expect(value).toBe(navigate);
27
+ });
28
+
29
+ describe('when useHistory exists', () => {
30
+ const history: any = { push: jest.fn() };
31
+
32
+ beforeEach(() => jest.mocked(ReactRouterDOM.useHistory).mockReturnValue(history));
33
+
34
+ test('returns history.push', () => {
35
+ const {
36
+ result: { current: value },
37
+ } = subject();
38
+
39
+ expect(value).toBe(history.push);
40
+ });
41
+ });
42
+ });
43
+ });
@@ -0,0 +1,22 @@
1
+ const dateISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[.,]\d+)?Z?$/i;
2
+ const dateNet = /\/Date\((-?\d+)(?:[+-]\d+)?\)\//i;
3
+
4
+ export function dateFromString(date: string | Date) {
5
+ if (typeof date === 'object') {
6
+ return date;
7
+ }
8
+
9
+ if (dateISO.test(date)) {
10
+ const d = date.split(/\D+/).map(s => +s);
11
+ return new Date(Date.UTC(d[0], --d[1], d[2], d[3], d[4], d[5], d[6]));
12
+ }
13
+
14
+ if (dateNet.test(date)) {
15
+ const parsedDate = dateNet.exec(date);
16
+ if (parsedDate !== null) {
17
+ return new Date(parseInt(parsedDate[1], 10));
18
+ }
19
+ }
20
+
21
+ throw new Error('Incorrect date format');
22
+ }
@@ -1,2 +0,0 @@
1
- import '@testing-library/jest-dom';
2
- //# sourceMappingURL=container.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"container.test.d.ts","sourceRoot":"","sources":["../../../src/components/__tests__/container.test.tsx"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
@@ -1,59 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { jsx as _jsx } from "react/jsx-runtime";
11
- import '@testing-library/jest-dom';
12
- import { render, waitFor, within } from '@testing-library/react';
13
- import { Container } from '../container';
14
- describe('[notifications] Container', () => {
15
- beforeEach(() => {
16
- var _a;
17
- (_a = document.getElementById('servicetitan-notifications')) === null || _a === void 0 ? void 0 : _a.remove();
18
- });
19
- const subject = (children) => {
20
- return render(_jsx(Container, { children: children }));
21
- };
22
- test('renders #servicetitan-notifications.initialized > .ToastGroup', () => __awaiter(void 0, void 0, void 0, function* () {
23
- subject();
24
- yield waitFor(() => expect(document.querySelectorAll('#servicetitan-notifications.initialized > .ToastGroup')).toHaveLength(1));
25
- }));
26
- test('renders children within .ToastGroup', () => __awaiter(void 0, void 0, void 0, function* () {
27
- subject(_jsx("button", { children: "Foo" }));
28
- yield waitFor(() => {
29
- expect(within(document.querySelector('#servicetitan-notifications.initialized > .ToastGroup')).getByRole('button', { name: 'Foo' })).toBeInTheDocument();
30
- });
31
- }));
32
- describe('when #servicetitan-notifications already exists', () => {
33
- let container;
34
- beforeEach(() => {
35
- container = document.createElement('div');
36
- container.setAttribute('id', 'servicetitan-notifications');
37
- document.body.appendChild(container);
38
- });
39
- test('creates .ToastGroup within existing container', () => __awaiter(void 0, void 0, void 0, function* () {
40
- subject();
41
- yield waitFor(() => {
42
- expect(container.querySelectorAll('.ToastGroup')).toHaveLength(1);
43
- });
44
- }));
45
- describe('when .ToastGroup already exists', () => {
46
- let toastGroup;
47
- beforeEach(() => {
48
- toastGroup = document.createElement('div');
49
- toastGroup.classList.add('ToastGroup');
50
- container.appendChild(toastGroup);
51
- });
52
- test('renders children inside existing ToastGroup', () => {
53
- subject(_jsx("button", { children: "Baz" }));
54
- expect(within(toastGroup).getByRole('button', { name: 'Baz' })).toBeInTheDocument();
55
- });
56
- });
57
- });
58
- });
59
- //# sourceMappingURL=container.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"container.test.js","sourceRoot":"","sources":["../../../src/components/__tests__/container.test.tsx"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACvC,UAAU,CAAC,GAAG,EAAE;;QACZ,MAAA,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,0CAAE,MAAM,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,CAAC,QAAoB,EAAE,EAAE;QACrC,OAAO,MAAM,CAAC,KAAC,SAAS,cAAE,QAAQ,GAAa,CAAC,CAAC;IACrD,CAAC,CAAC;IAEF,IAAI,CAAC,+DAA+D,EAAE,GAAS,EAAE;QAC7E,OAAO,EAAE,CAAC;QAEV,MAAM,OAAO,CAAC,GAAG,EAAE,CACf,MAAM,CACF,QAAQ,CAAC,gBAAgB,CAAC,uDAAuD,CAAC,CACrF,CAAC,YAAY,CAAC,CAAC,CAAC,CACpB,CAAC;IACN,CAAC,CAAA,CAAC,CAAC;IAEH,IAAI,CAAC,qCAAqC,EAAE,GAAS,EAAE;QACnD,OAAO,CAAC,mCAAoB,CAAC,CAAC;QAE9B,MAAM,OAAO,CAAC,GAAG,EAAE;YACf,MAAM,CACF,MAAM,CACF,QAAQ,CAAC,aAAa,CAAC,uDAAuD,CAAE,CACnF,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CACzC,CAAC,iBAAiB,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;IACP,CAAC,CAAA,CAAC,CAAC;IAEH,QAAQ,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC7D,IAAI,SAAsB,CAAC;QAE3B,UAAU,CAAC,GAAG,EAAE;YACZ,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC1C,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;YAC3D,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,+CAA+C,EAAE,GAAS,EAAE;YAC7D,OAAO,EAAE,CAAC;YAEV,MAAM,OAAO,CAAC,GAAG,EAAE;gBACf,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC,CAAC,CAAC;QACP,CAAC,CAAA,CAAC,CAAC;QAEH,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;YAC7C,IAAI,UAAuB,CAAC;YAE5B,UAAU,CAAC,GAAG,EAAE;gBACZ,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAC3C,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBACvC,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;gBACrD,OAAO,CAAC,mCAAoB,CAAC,CAAC;gBAE9B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACxF,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -1,3 +0,0 @@
1
- import { FC, PropsWithChildren } from 'react';
2
- export declare const Container: FC<PropsWithChildren>;
3
- //# sourceMappingURL=container.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/components/container.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAY,iBAAiB,EAAuB,MAAM,OAAO,CAAC;AAK7E,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAwB3C,CAAC"}
@@ -1,26 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Toast } from '@servicetitan/design-system';
3
- import { Fragment, useEffect, useState } from 'react';
4
- import { createPortal } from 'react-dom';
5
- import { createElement } from '../create-element';
6
- export const Container = ({ children }) => {
7
- const [container] = useState(() => {
8
- var _a;
9
- return ((_a = document.getElementById('servicetitan-notifications')) !== null && _a !== void 0 ? _a : document.body.appendChild(createElement('div', { id: 'servicetitan-notifications' })));
10
- });
11
- const [toastGroup, setToastGroup] = useState(() => findToastGroup(container));
12
- const [foundGroup] = useState(() => !!toastGroup);
13
- useEffect(() => {
14
- if (!toastGroup) {
15
- setToastGroup(findToastGroup(container));
16
- // This stops old code running in MFE from rendering duplicate Toast.Group
17
- container.classList.add('initialized');
18
- }
19
- }, [container, toastGroup]);
20
- return (_jsxs(Fragment, { children: [foundGroup ? null : _jsx(Toast.Group, { portal: container }), toastGroup ? createPortal(children, toastGroup) : null] }));
21
- };
22
- function findToastGroup(parent) {
23
- var _a;
24
- return (_a = parent.getElementsByClassName('ToastGroup')[0]) !== null && _a !== void 0 ? _a : null;
25
- }
26
- //# sourceMappingURL=container.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/components/container.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAM,QAAQ,EAAqB,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,CAAC,MAAM,SAAS,GAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC7D,MAAM,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;;QAC9B,OAAO,CACH,MAAA,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,mCACrD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,4BAA4B,EAAE,CAAC,CAAC,CACxF,CAAC;IACN,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9E,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,aAAa,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;YACzC,0EAA0E;YAC1E,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3C,CAAC;IACL,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAE5B,OAAO,CACH,MAAC,QAAQ,eACJ,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,KAAK,CAAC,KAAK,IAAC,MAAM,EAAE,SAAS,GAAI,EACtD,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,IAChD,CACd,CAAC;AACN,CAAC,CAAC;AAEF,SAAS,cAAc,CAAC,MAAmB;;IACvC,OAAO,MAAA,MAAM,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,mCAAI,IAAI,CAAC;AAClE,CAAC"}
@@ -1,7 +0,0 @@
1
- import { FC } from 'react';
2
- import { DefaultNotificationOptions } from '../common';
3
- export interface DefaultNotificationProps extends DefaultNotificationOptions {
4
- onClose(): void;
5
- }
6
- export declare const DefaultNotification: FC<DefaultNotificationProps>;
7
- //# sourceMappingURL=default-notification.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"default-notification.d.ts","sourceRoot":"","sources":["../../src/components/default-notification.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAK3B,OAAO,EAAE,0BAA0B,EAAwB,MAAM,WAAW,CAAC;AAI7E,MAAM,WAAW,wBAAyB,SAAQ,0BAA0B;IACxE,OAAO,IAAI,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,wBAAwB,CA6C5D,CAAC"}
@@ -1,26 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Toast, ProgressBar } from '@servicetitan/design-system';
3
- import { useCompatibleNavigate } from '../utils/use-compatible-navigate';
4
- import { Status, isLinkAction } from '../common';
5
- import * as Styles from './default-notification.module.css';
6
- export const DefaultNotification = ({ status = Status.Info, title, message, duration, progress, action, onClose, }) => {
7
- const navigate = useCompatibleNavigate();
8
- const handleActionClick = () => {
9
- if (action) {
10
- if (isLinkAction(action)) {
11
- if (action.external) {
12
- window.open(action.link);
13
- }
14
- else {
15
- navigate(action.link);
16
- }
17
- }
18
- else {
19
- action.onClick();
20
- }
21
- }
22
- onClose();
23
- };
24
- return (_jsxs(Toast, { portal: false, status: status, title: title, duration: duration, primaryActionName: action === null || action === void 0 ? void 0 : action.label, onPrimaryActionClick: handleActionClick, className: Styles.defaultNotification, onClose: onClose, children: [_jsx("div", { className: Styles.message, children: message }), progress != null && (_jsx(ProgressBar, { progress: progress, small: true, blue: true, className: message && 'm-t-1' }))] }));
25
- };
26
- //# sourceMappingURL=default-notification.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"default-notification.js","sourceRoot":"","sources":["../../src/components/default-notification.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAEjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAA8B,MAAM,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE7E,OAAO,KAAK,MAAM,MAAM,mCAAmC,CAAC;AAM5D,MAAM,CAAC,MAAM,mBAAmB,GAAiC,CAAC,EAC9D,MAAM,GAAG,MAAM,CAAC,IAAI,EACpB,KAAK,EACL,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,OAAO,GACV,EAAE,EAAE;IACD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IAEzC,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC3B,IAAI,MAAM,EAAE,CAAC;YACT,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvB,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;oBAClB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;qBAAM,CAAC;oBACJ,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,OAAO,EAAE,CAAC;YACrB,CAAC;QACL,CAAC;QAED,OAAO,EAAE,CAAC;IACd,CAAC,CAAC;IAEF,OAAO,CACH,MAAC,KAAK,IACF,MAAM,EAAE,KAAK,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,iBAAiB,EAAE,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,EAChC,oBAAoB,EAAE,iBAAiB,EACvC,SAAS,EAAE,MAAM,CAAC,mBAAmB,EACrC,OAAO,EAAE,OAAO,aAEhB,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,YAAG,OAAO,GAAO,EAE9C,QAAQ,IAAI,IAAI,IAAI,CACjB,KAAC,WAAW,IAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,QAAC,IAAI,QAAC,SAAS,EAAE,OAAO,IAAI,OAAO,GAAI,CAChF,IACG,CACX,CAAC;AACN,CAAC,CAAC"}
@@ -1,3 +0,0 @@
1
- .default-notification .message {
2
- white-space: pre-line;
3
- }
@@ -1,5 +0,0 @@
1
- /// <reference types="react" />
2
- export declare const NoSSR: ({ children }: {
3
- children: JSX.Element;
4
- }) => JSX.Element | null;
5
- //# sourceMappingURL=no-ssr.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-ssr.d.ts","sourceRoot":"","sources":["../../src/components/no-ssr.tsx"],"names":[],"mappings":";AAEA,eAAO,MAAM,KAAK,iBAAkB;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,uBAQ5D,CAAC"}
@@ -1,9 +0,0 @@
1
- import { useState, useEffect } from 'react';
2
- export const NoSSR = ({ children }) => {
3
- const [isMounted, setIsMounted] = useState(false);
4
- useEffect(() => {
5
- setIsMounted(true);
6
- }, []);
7
- return isMounted ? children : null;
8
- };
9
- //# sourceMappingURL=no-ssr.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-ssr.js","sourceRoot":"","sources":["../../src/components/no-ssr.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,QAAQ,EAA6B,EAAE,EAAE;IAC7D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACX,YAAY,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC,CAAC"}
@@ -1,3 +0,0 @@
1
- import { FC } from 'react';
2
- export declare const NotificationsUnwrapped: FC;
3
- //# sourceMappingURL=notifications-unwrapped.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notifications-unwrapped.d.ts","sourceRoot":"","sources":["../../src/components/notifications-unwrapped.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,EAAE,EAAE,MAAM,OAAO,CAAC;AAatC,eAAO,MAAM,sBAAsB,EAAE,EAqCnC,CAAC"}
@@ -1,27 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useEffect } from 'react';
3
- import { useDependencies, useOptionalDependencies } from '@servicetitan/react-ioc';
4
- import { IS_WEB_COMPONENT_TOKEN } from '@servicetitan/web-components';
5
- import { observer } from 'mobx-react';
6
- import { NotificationsStore } from '../stores/notifications.store';
7
- import { ShadowDOM } from './shadow-dom';
8
- import { Container } from './container';
9
- import { NoSSR } from './no-ssr';
10
- export const NotificationsUnwrapped = observer(() => {
11
- const [isWebComponent] = useOptionalDependencies(IS_WEB_COMPONENT_TOKEN);
12
- const [store] = useDependencies(NotificationsStore);
13
- useEffect(() => {
14
- return () => store.dispose();
15
- }, [store]);
16
- return (_jsx(NoSSR, { children: _jsx(Container, { children: store.notifications.map(notification => {
17
- const Component = NotificationsStore.types.get(notification.type);
18
- if (!Component) {
19
- return null;
20
- }
21
- const handleClose = () => {
22
- store.read(notification);
23
- };
24
- return isWebComponent ? (_jsx(ShadowDOM, { children: _jsx(Component, { notification: notification, onClose: handleClose }) }, `${notification.id}_${notification.status}`)) : (_jsx(Component, { notification: notification, onClose: handleClose }, `${notification.id}_${notification.status}`));
25
- }) }) }));
26
- });
27
- //# sourceMappingURL=notifications-unwrapped.js.map