@novu/react 3.0.0 → 3.0.3

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.
@@ -1,853 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name2 in all)
10
- __defProp(target, name2, { get: all[name2], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
33
- Bell: () => Bell,
34
- Inbox: () => Inbox,
35
- InboxContent: () => InboxContent,
36
- InternalNovuProvider: () => InternalNovuProvider,
37
- Notifications: () => Notifications,
38
- NovuProvider: () => NovuProvider,
39
- Preferences: () => Preferences,
40
- useCounts: () => useCounts,
41
- useNotifications: () => useNotifications,
42
- useNovu: () => useNovu,
43
- usePreferences: () => usePreferences,
44
- useUnsafeNovu: () => useUnsafeNovu
45
- });
46
- module.exports = __toCommonJS(src_exports);
47
-
48
- // src/components/Bell.tsx
49
- var import_react4 = __toESM(require("react"));
50
-
51
- // src/components/Mounter.tsx
52
- var import_react = require("react");
53
- var import_jsx_runtime = require("react/jsx-runtime");
54
- function Mounter({ mount }) {
55
- const ref = (0, import_react.useRef)(null);
56
- (0, import_react.useEffect)(() => {
57
- let unmount;
58
- const element = ref.current;
59
- if (element && mount) {
60
- const possibleUnmount = mount(element);
61
- if (possibleUnmount) {
62
- unmount = possibleUnmount;
63
- }
64
- }
65
- return () => {
66
- if (element && unmount) {
67
- unmount(element);
68
- }
69
- };
70
- }, [ref, mount]);
71
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref });
72
- }
73
-
74
- // src/components/Renderer.tsx
75
- var import_react3 = require("react");
76
- var import_react_dom = require("react-dom");
77
-
78
- // src/utils/createContextAndHook.ts
79
- var import_react2 = __toESM(require("react"));
80
- function assertContextExists(contextVal, msgOrCtx) {
81
- if (!contextVal) {
82
- throw typeof msgOrCtx === "string" ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);
83
- }
84
- }
85
- var createContextAndHook = (displayName, options) => {
86
- const { assertCtxFn = assertContextExists } = options || {};
87
- const Ctx = import_react2.default.createContext(void 0);
88
- Ctx.displayName = displayName;
89
- const useCtx = () => {
90
- const ctx = import_react2.default.useContext(Ctx);
91
- assertCtxFn(ctx, `Component must be wrapped with ${Ctx.displayName}`);
92
- return ctx.value;
93
- };
94
- const useCtxWithoutGuarantee = () => {
95
- const ctx = import_react2.default.useContext(Ctx);
96
- return ctx ? ctx.value : {};
97
- };
98
- return [Ctx, useCtx, useCtxWithoutGuarantee];
99
- };
100
-
101
- // src/context/RendererContext.tsx
102
- var import_jsx_runtime2 = require("react/jsx-runtime");
103
- var [RendererContext, useRendererContext, useUnsafeRendererContext] = createContextAndHook("RendererContext");
104
- var RendererProvider = (props) => {
105
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RendererContext.Provider, { value: { value: props.value }, children: props.children });
106
- };
107
-
108
- // src/components/Renderer.tsx
109
- var import_jsx_runtime3 = require("react/jsx-runtime");
110
- var Renderer = (props) => {
111
- const { children } = props;
112
- const [mountedElements, setMountedElements] = (0, import_react3.useState)(/* @__PURE__ */ new Map());
113
- const mountElement = (0, import_react3.useCallback)(
114
- (el, mountedElement) => {
115
- setMountedElements((prev) => {
116
- const newMountedElements = new Map(prev);
117
- newMountedElements.set(el, mountedElement);
118
- return newMountedElements;
119
- });
120
- return () => {
121
- setMountedElements((prev) => {
122
- const newMountedElements = new Map(prev);
123
- newMountedElements.delete(el);
124
- return newMountedElements;
125
- });
126
- };
127
- },
128
- [setMountedElements]
129
- );
130
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(RendererProvider, { value: { mountElement }, children: [
131
- [...mountedElements].map(([element, mountedElement]) => {
132
- return (0, import_react_dom.createPortal)(mountedElement, element);
133
- }),
134
- children
135
- ] });
136
- };
137
- var withRenderer = (WrappedComponent) => {
138
- const HOC = (props) => {
139
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Renderer, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WrappedComponent, { ...props }) });
140
- };
141
- HOC.displayName = `WithRenderer(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
142
- return HOC;
143
- };
144
-
145
- // src/context/NovuUIContext.tsx
146
- var import_jsx_runtime4 = require("react/jsx-runtime");
147
- var [NovuUIContext, useNovuUIContext, useUnsafeNovuUIContext] = createContextAndHook("NovuUIContext");
148
- var NovuUIProvider = (props) => {
149
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NovuUIContext.Provider, { value: { value: props.value }, children: props.children });
150
- };
151
-
152
- // src/components/Bell.tsx
153
- var import_jsx_runtime5 = require("react/jsx-runtime");
154
- var _Bell = import_react4.default.memo((props) => {
155
- const { renderBell } = props;
156
- const { novuUI } = useNovuUIContext();
157
- const { mountElement } = useRendererContext();
158
- const mount = import_react4.default.useCallback(
159
- (element) => {
160
- return novuUI.mountComponent({
161
- name: "Bell",
162
- element,
163
- props: renderBell ? { renderBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : void 0
164
- });
165
- },
166
- [renderBell]
167
- );
168
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Mounter, { mount });
169
- });
170
- var Bell = withRenderer(_Bell);
171
-
172
- // src/components/Inbox.tsx
173
- var import_react8 = __toESM(require("react"));
174
-
175
- // src/hooks/NovuProvider.tsx
176
- var import_js = require("@novu/js");
177
- var import_react5 = require("react");
178
- var import_jsx_runtime6 = require("react/jsx-runtime");
179
- var version = "2.6.6";
180
- var name = "@novu/react";
181
- var baseUserAgent = `${name}@${version}`;
182
- var NovuContext = (0, import_react5.createContext)(void 0);
183
- var NovuProvider = ({
184
- children,
185
- applicationIdentifier,
186
- subscriberId,
187
- subscriberHash,
188
- backendUrl,
189
- socketUrl,
190
- useCache
191
- }) => {
192
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
193
- InternalNovuProvider,
194
- {
195
- applicationIdentifier,
196
- subscriberId,
197
- subscriberHash,
198
- backendUrl,
199
- socketUrl,
200
- useCache,
201
- userAgentType: "hooks",
202
- children
203
- }
204
- );
205
- };
206
- var InternalNovuProvider = ({
207
- children,
208
- applicationIdentifier,
209
- subscriberId,
210
- subscriberHash,
211
- backendUrl,
212
- socketUrl,
213
- useCache,
214
- userAgentType
215
- }) => {
216
- const novu = (0, import_react5.useMemo)(
217
- () => new import_js.Novu({
218
- applicationIdentifier,
219
- subscriberId,
220
- subscriberHash,
221
- backendUrl,
222
- socketUrl,
223
- useCache,
224
- __userAgent: `${baseUserAgent} ${userAgentType}`
225
- }),
226
- [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache, userAgentType]
227
- );
228
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NovuContext.Provider, { value: novu, children });
229
- };
230
- var useNovu = () => {
231
- const context = (0, import_react5.useContext)(NovuContext);
232
- if (!context) {
233
- throw new Error("useNovu must be used within a <NovuProvider />");
234
- }
235
- return context;
236
- };
237
- var useUnsafeNovu = () => {
238
- const context = (0, import_react5.useContext)(NovuContext);
239
- return context;
240
- };
241
-
242
- // src/components/NovuUI.tsx
243
- var import_ui = require("@novu/js/ui");
244
- var import_react7 = require("react");
245
-
246
- // src/hooks/internal/useDataRef.ts
247
- var import_react6 = require("react");
248
- var useDataRef = (data) => {
249
- const ref = (0, import_react6.useRef)(data);
250
- ref.current = data;
251
- return ref;
252
- };
253
-
254
- // src/components/NovuUI.tsx
255
- var import_jsx_runtime7 = require("react/jsx-runtime");
256
- var NovuUI = ({ options, novu, children }) => {
257
- const optionsRef = useDataRef({ ...options, novu });
258
- const [novuUI, setNovuUI] = (0, import_react7.useState)();
259
- (0, import_react7.useEffect)(() => {
260
- const novu2 = new import_ui.NovuUI(optionsRef.current);
261
- setNovuUI(novu2);
262
- return () => {
263
- novu2.unmount();
264
- };
265
- }, []);
266
- (0, import_react7.useEffect)(() => {
267
- if (!novuUI) {
268
- return;
269
- }
270
- novuUI.updateAppearance(options.appearance);
271
- novuUI.updateLocalization(options.localization);
272
- novuUI.updateTabs(options.tabs);
273
- novuUI.updateOptions(options.options);
274
- novuUI.updateRouterPush(options.routerPush);
275
- }, [options]);
276
- if (!novuUI) {
277
- return null;
278
- }
279
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NovuUIProvider, { value: { novuUI }, children });
280
- };
281
-
282
- // src/components/Inbox.tsx
283
- var import_jsx_runtime8 = require("react/jsx-runtime");
284
- var _DefaultInbox = (props) => {
285
- const {
286
- open,
287
- renderNotification,
288
- renderSubject,
289
- renderBody,
290
- renderBell,
291
- onNotificationClick,
292
- onPrimaryActionClick,
293
- onSecondaryActionClick,
294
- placement,
295
- placementOffset
296
- } = props;
297
- const { novuUI } = useNovuUIContext();
298
- const { mountElement } = useRendererContext();
299
- const mount = import_react8.default.useCallback(
300
- (element) => {
301
- if (renderNotification) {
302
- return novuUI.mountComponent({
303
- name: "Inbox",
304
- props: {
305
- open,
306
- renderNotification: renderNotification ? (el, notification) => mountElement(el, renderNotification(notification)) : void 0,
307
- renderBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : void 0,
308
- onNotificationClick,
309
- onPrimaryActionClick,
310
- onSecondaryActionClick,
311
- placementOffset,
312
- placement
313
- },
314
- element
315
- });
316
- }
317
- return novuUI.mountComponent({
318
- name: "Inbox",
319
- props: {
320
- open,
321
- renderSubject: renderSubject ? (el, notification) => mountElement(el, renderSubject(notification)) : void 0,
322
- renderBody: renderBody ? (el, notification) => mountElement(el, renderBody(notification)) : void 0,
323
- renderBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : void 0,
324
- onNotificationClick,
325
- onPrimaryActionClick,
326
- onSecondaryActionClick,
327
- placementOffset,
328
- placement
329
- },
330
- element
331
- });
332
- },
333
- [
334
- open,
335
- renderNotification,
336
- renderSubject,
337
- renderBody,
338
- renderBell,
339
- onNotificationClick,
340
- onPrimaryActionClick,
341
- onSecondaryActionClick
342
- ]
343
- );
344
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Mounter, { mount });
345
- };
346
- var DefaultInbox = withRenderer(_DefaultInbox);
347
- var Inbox = import_react8.default.memo((props) => {
348
- const { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;
349
- const novu = useUnsafeNovu();
350
- if (novu) {
351
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(InboxChild, { ...props });
352
- }
353
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
354
- InternalNovuProvider,
355
- {
356
- applicationIdentifier,
357
- subscriberId,
358
- subscriberHash,
359
- backendUrl,
360
- socketUrl,
361
- userAgentType: "components",
362
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(InboxChild, { ...props })
363
- }
364
- );
365
- });
366
- var InboxChild = import_react8.default.memo((props) => {
367
- const {
368
- localization,
369
- appearance,
370
- tabs,
371
- preferencesFilter,
372
- routerPush,
373
- applicationIdentifier,
374
- subscriberId,
375
- subscriberHash,
376
- backendUrl,
377
- socketUrl
378
- } = props;
379
- const novu = useNovu();
380
- const options = (0, import_react8.useMemo)(() => {
381
- return {
382
- localization,
383
- appearance,
384
- tabs,
385
- preferencesFilter,
386
- routerPush,
387
- options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl }
388
- };
389
- }, [
390
- localization,
391
- appearance,
392
- tabs,
393
- preferencesFilter,
394
- applicationIdentifier,
395
- subscriberId,
396
- subscriberHash,
397
- backendUrl,
398
- socketUrl
399
- ]);
400
- if (isWithChildrenProps(props)) {
401
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NovuUI, { options, novu, children: props.children });
402
- }
403
- const {
404
- open,
405
- renderNotification,
406
- renderSubject,
407
- renderBody,
408
- renderBell,
409
- onNotificationClick,
410
- onPrimaryActionClick,
411
- onSecondaryActionClick,
412
- placementOffset,
413
- placement
414
- } = props;
415
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NovuUI, { options, novu, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
416
- DefaultInbox,
417
- {
418
- open,
419
- renderNotification,
420
- renderSubject,
421
- renderBody,
422
- renderBell,
423
- onNotificationClick,
424
- onPrimaryActionClick,
425
- onSecondaryActionClick,
426
- placement,
427
- placementOffset
428
- }
429
- ) });
430
- });
431
- function isWithChildrenProps(props) {
432
- return "children" in props;
433
- }
434
-
435
- // src/components/Preferences.tsx
436
- var import_react9 = __toESM(require("react"));
437
- var import_jsx_runtime9 = require("react/jsx-runtime");
438
- var Preferences = () => {
439
- const { novuUI } = useNovuUIContext();
440
- const mount = import_react9.default.useCallback((element) => {
441
- return novuUI.mountComponent({
442
- name: "Preferences",
443
- element
444
- });
445
- }, []);
446
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Mounter, { mount });
447
- };
448
-
449
- // src/components/Notifications.tsx
450
- var import_react10 = __toESM(require("react"));
451
- var import_jsx_runtime10 = require("react/jsx-runtime");
452
- var _Notifications = import_react10.default.memo((props) => {
453
- const {
454
- renderNotification,
455
- renderSubject,
456
- renderBody,
457
- onNotificationClick,
458
- onPrimaryActionClick,
459
- onSecondaryActionClick
460
- } = props;
461
- const { novuUI } = useNovuUIContext();
462
- const { mountElement } = useRendererContext();
463
- const mount = import_react10.default.useCallback(
464
- (element) => {
465
- if (renderNotification) {
466
- return novuUI.mountComponent({
467
- name: "Notifications",
468
- element,
469
- props: {
470
- renderNotification: renderNotification ? (el, notification) => mountElement(el, renderNotification(notification)) : void 0,
471
- onNotificationClick,
472
- onPrimaryActionClick,
473
- onSecondaryActionClick
474
- }
475
- });
476
- }
477
- return novuUI.mountComponent({
478
- name: "Notifications",
479
- element,
480
- props: {
481
- renderSubject: renderSubject ? (el, notification) => mountElement(el, renderSubject(notification)) : void 0,
482
- renderBody: renderBody ? (el, notification) => mountElement(el, renderBody(notification)) : void 0,
483
- onNotificationClick,
484
- onPrimaryActionClick,
485
- onSecondaryActionClick
486
- }
487
- });
488
- },
489
- [renderNotification, renderSubject, renderBody, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
490
- );
491
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Mounter, { mount });
492
- });
493
- var Notifications = withRenderer(_Notifications);
494
-
495
- // src/components/InboxContent.tsx
496
- var import_react11 = __toESM(require("react"));
497
- var import_jsx_runtime11 = require("react/jsx-runtime");
498
- var _InboxContent = import_react11.default.memo((props) => {
499
- const {
500
- onNotificationClick,
501
- onPrimaryActionClick,
502
- renderNotification,
503
- renderSubject,
504
- renderBody,
505
- onSecondaryActionClick,
506
- initialPage,
507
- hideNav
508
- } = props;
509
- const { novuUI } = useNovuUIContext();
510
- const { mountElement } = useRendererContext();
511
- const mount = import_react11.default.useCallback(
512
- (element) => {
513
- if (renderNotification) {
514
- return novuUI.mountComponent({
515
- name: "InboxContent",
516
- element,
517
- props: {
518
- renderNotification: renderNotification ? (el, notification) => mountElement(el, renderNotification(notification)) : void 0,
519
- onNotificationClick,
520
- onPrimaryActionClick,
521
- onSecondaryActionClick,
522
- initialPage,
523
- hideNav
524
- }
525
- });
526
- }
527
- return novuUI.mountComponent({
528
- name: "InboxContent",
529
- element,
530
- props: {
531
- renderSubject: renderSubject ? (el, notification) => mountElement(el, renderSubject(notification)) : void 0,
532
- renderBody: renderBody ? (el, notification) => mountElement(el, renderBody(notification)) : void 0,
533
- onNotificationClick,
534
- onPrimaryActionClick,
535
- onSecondaryActionClick,
536
- initialPage,
537
- hideNav
538
- }
539
- });
540
- },
541
- [renderNotification, renderSubject, renderBody, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
542
- );
543
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Mounter, { mount });
544
- });
545
- var InboxContent = withRenderer(_InboxContent);
546
-
547
- // src/hooks/useNotifications.ts
548
- var import_react12 = require("react");
549
- var import_js2 = require("@novu/js");
550
- var useNotifications = (props) => {
551
- const { tags, read, archived = false, limit, onSuccess, onError } = props || {};
552
- const filterRef = (0, import_react12.useRef)(void 0);
553
- const { notifications, on } = useNovu();
554
- const [data, setData] = (0, import_react12.useState)();
555
- const [error, setError] = (0, import_react12.useState)();
556
- const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
557
- const [isFetching, setIsFetching] = (0, import_react12.useState)(false);
558
- const [hasMore, setHasMore] = (0, import_react12.useState)(false);
559
- const length = data?.length;
560
- const after = length ? data[length - 1].id : void 0;
561
- const sync = (event) => {
562
- if (!event.data || filterRef.current && !(0, import_js2.isSameFilter)(filterRef.current, event.data.filter)) {
563
- return;
564
- }
565
- setData(event.data.notifications);
566
- setHasMore(event.data.hasMore);
567
- };
568
- (0, import_react12.useEffect)(() => {
569
- const cleanup = on("notifications.list.updated", sync);
570
- return () => {
571
- cleanup();
572
- };
573
- }, []);
574
- (0, import_react12.useEffect)(() => {
575
- const newFilter = { tags, read, archived };
576
- if (filterRef.current && (0, import_js2.isSameFilter)(filterRef.current, newFilter)) {
577
- return;
578
- }
579
- notifications.clearCache({ filter: filterRef.current });
580
- filterRef.current = newFilter;
581
- fetchNotifications({ refetch: true });
582
- }, [tags, read, archived]);
583
- const fetchNotifications = async (options) => {
584
- if (options?.refetch) {
585
- setError(void 0);
586
- setIsLoading(true);
587
- setIsFetching(false);
588
- }
589
- setIsFetching(true);
590
- const response = await notifications.list({
591
- tags,
592
- read,
593
- archived,
594
- limit,
595
- after: options?.refetch ? void 0 : after
596
- });
597
- if (response.error) {
598
- setError(response.error);
599
- onError?.(response.error);
600
- } else {
601
- onSuccess?.(response.data.notifications);
602
- setData(response.data.notifications);
603
- setHasMore(response.data.hasMore);
604
- }
605
- setIsLoading(false);
606
- setIsFetching(false);
607
- };
608
- const refetch = () => {
609
- notifications.clearCache({ filter: { tags, read, archived } });
610
- return fetchNotifications({ refetch: true });
611
- };
612
- const fetchMore = async () => {
613
- if (!hasMore || isFetching) return;
614
- return fetchNotifications();
615
- };
616
- const readAll = async () => {
617
- return await notifications.readAll({ tags });
618
- };
619
- const archiveAll = async () => {
620
- return await notifications.archiveAll({ tags });
621
- };
622
- const archiveAllRead = async () => {
623
- return await notifications.archiveAllRead({ tags });
624
- };
625
- return {
626
- readAll,
627
- archiveAll,
628
- archiveAllRead,
629
- notifications: data,
630
- error,
631
- isLoading,
632
- isFetching,
633
- refetch,
634
- fetchMore,
635
- hasMore
636
- };
637
- };
638
-
639
- // src/hooks/usePreferences.ts
640
- var import_react13 = require("react");
641
- var usePreferences = (props) => {
642
- const { onSuccess, onError } = props || {};
643
- const [data, setData] = (0, import_react13.useState)();
644
- const { preferences, on } = useNovu();
645
- const [error, setError] = (0, import_react13.useState)();
646
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
647
- const [isFetching, setIsFetching] = (0, import_react13.useState)(false);
648
- const sync = (event) => {
649
- if (!event.data) {
650
- return;
651
- }
652
- setData(event.data);
653
- };
654
- (0, import_react13.useEffect)(() => {
655
- fetchPreferences();
656
- const listUpdatedCleanup = on("preferences.list.updated", sync);
657
- const listPendingCleanup = on("preferences.list.pending", sync);
658
- const listResolvedCleanup = on("preferences.list.resolved", sync);
659
- return () => {
660
- listUpdatedCleanup();
661
- listPendingCleanup();
662
- listResolvedCleanup();
663
- };
664
- }, []);
665
- const fetchPreferences = async () => {
666
- setIsFetching(true);
667
- const response = await preferences.list(props?.filter);
668
- if (response.error) {
669
- setError(response.error);
670
- onError?.(response.error);
671
- } else {
672
- onSuccess?.(response.data);
673
- }
674
- setIsLoading(false);
675
- setIsFetching(false);
676
- };
677
- const refetch = () => {
678
- preferences.cache.clearAll();
679
- return fetchPreferences();
680
- };
681
- return {
682
- preferences: data,
683
- error,
684
- isLoading,
685
- isFetching,
686
- refetch
687
- };
688
- };
689
-
690
- // src/hooks/useCounts.ts
691
- var import_react16 = require("react");
692
- var import_js3 = require("@novu/js");
693
-
694
- // src/hooks/internal/useWebsocketEvent.ts
695
- var import_react15 = require("react");
696
-
697
- // src/utils/requestLock.ts
698
- function requestLock(id, cb) {
699
- if (!("locks" in navigator)) {
700
- cb(id);
701
- return () => {
702
- };
703
- }
704
- let isFulfilled = false;
705
- let promiseResolve;
706
- const promise = new Promise((resolve) => {
707
- promiseResolve = resolve;
708
- });
709
- navigator.locks.request(id, () => {
710
- if (!isFulfilled) {
711
- cb(id);
712
- }
713
- return promise;
714
- });
715
- return () => {
716
- isFulfilled = true;
717
- promiseResolve();
718
- };
719
- }
720
-
721
- // src/hooks/internal/useBrowserTabsChannel.ts
722
- var import_react14 = require("react");
723
- var useBrowserTabsChannel = ({
724
- channelName,
725
- onMessage
726
- }) => {
727
- const [tabsChannel] = (0, import_react14.useState)(
728
- typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(channelName) : void 0
729
- );
730
- const postMessage = (data) => {
731
- tabsChannel?.postMessage(data);
732
- };
733
- (0, import_react14.useEffect)(() => {
734
- const listener = (event) => {
735
- onMessage(event.data);
736
- };
737
- tabsChannel?.addEventListener("message", listener);
738
- return () => {
739
- tabsChannel?.removeEventListener("message", listener);
740
- };
741
- }, []);
742
- return { postMessage };
743
- };
744
-
745
- // src/hooks/internal/useWebsocketEvent.ts
746
- var useWebSocketEvent = ({
747
- event: webSocketEvent,
748
- eventHandler: onMessage
749
- }) => {
750
- const novu = useNovu();
751
- const { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });
752
- const updateReadCount = (data) => {
753
- onMessage(data);
754
- postMessage(data);
755
- };
756
- (0, import_react15.useEffect)(() => {
757
- let cleanup;
758
- const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {
759
- cleanup = novu.on(webSocketEvent, updateReadCount);
760
- });
761
- return () => {
762
- if (cleanup) {
763
- cleanup();
764
- }
765
- resolveLock();
766
- };
767
- }, []);
768
- };
769
-
770
- // src/hooks/useCounts.ts
771
- var useCounts = (props) => {
772
- const { filters, onSuccess, onError } = props;
773
- const { notifications } = useNovu();
774
- const [error, setError] = (0, import_react16.useState)();
775
- const [counts, setCounts] = (0, import_react16.useState)();
776
- const [isLoading, setIsLoading] = (0, import_react16.useState)(true);
777
- const [isFetching, setIsFetching] = (0, import_react16.useState)(false);
778
- const sync = async (notification) => {
779
- const existingCounts = counts ?? new Array(filters.length).fill(void 0);
780
- let countFiltersToFetch = [];
781
- if (notification) {
782
- for (let i = 0; i < existingCounts.length; i++) {
783
- const filter = filters[i];
784
- if ((0, import_js3.areTagsEqual)(filter.tags, notification.tags)) {
785
- countFiltersToFetch.push(filter);
786
- }
787
- }
788
- } else {
789
- countFiltersToFetch = filters;
790
- }
791
- if (countFiltersToFetch.length === 0) {
792
- return;
793
- }
794
- setIsFetching(true);
795
- const countsRes = await notifications.count({ filters: countFiltersToFetch });
796
- setIsFetching(false);
797
- setIsLoading(false);
798
- if (countsRes.error) {
799
- setError(countsRes.error);
800
- onError?.(countsRes.error);
801
- return;
802
- }
803
- const data = countsRes.data;
804
- onSuccess?.(data.counts);
805
- setCounts((oldCounts) => {
806
- const newCounts = [];
807
- const countsReceived = data.counts;
808
- for (let i = 0; i < existingCounts.length; i++) {
809
- const countReceived = countsReceived.find((c) => (0, import_js3.areTagsEqual)(c.filter.tags, existingCounts[i]?.filter.tags));
810
- newCounts.push(countReceived || oldCounts[i]);
811
- }
812
- return newCounts;
813
- });
814
- };
815
- useWebSocketEvent({
816
- event: "notifications.notification_received",
817
- eventHandler: (data) => {
818
- sync(data.result);
819
- }
820
- });
821
- useWebSocketEvent({
822
- event: "notifications.unread_count_changed",
823
- eventHandler: () => {
824
- sync();
825
- }
826
- });
827
- (0, import_react16.useEffect)(() => {
828
- setError(void 0);
829
- setIsLoading(true);
830
- setIsFetching(false);
831
- sync();
832
- }, [JSON.stringify(filters)]);
833
- const refetch = async () => {
834
- await sync();
835
- };
836
- return { counts, error, refetch, isLoading, isFetching };
837
- };
838
- // Annotate the CommonJS export names for ESM import in node:
839
- 0 && (module.exports = {
840
- Bell,
841
- Inbox,
842
- InboxContent,
843
- InternalNovuProvider,
844
- Notifications,
845
- NovuProvider,
846
- Preferences,
847
- useCounts,
848
- useNotifications,
849
- useNovu,
850
- usePreferences,
851
- useUnsafeNovu
852
- });
853
- //# sourceMappingURL=index.js.map