@novu/react 2.0.0-canary.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.mts +74 -3
- package/dist/client/index.d.ts +74 -3
- package/dist/client/index.js +369 -10
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +369 -10
- package/dist/client/index.mjs.map +1 -1
- package/dist/hooks/index.d.mts +72 -0
- package/dist/hooks/index.d.ts +72 -0
- package/dist/hooks/index.js +349 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +326 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/server/server.d.mts +73 -2
- package/dist/server/server.d.ts +73 -2
- package/dist/server/server.js +334 -2
- package/dist/server/server.js.map +1 -1
- package/dist/server/server.mjs +326 -1
- package/dist/server/server.mjs.map +1 -1
- package/hooks/package.json +5 -0
- package/package.json +27 -10
package/dist/client/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import React$1 from 'react';
|
|
3
|
-
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab } from '@novu/js/ui';
|
|
2
|
+
import React$1, { ReactNode } from 'react';
|
|
3
|
+
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
|
|
4
4
|
export { Notification } from '@novu/js/ui';
|
|
5
|
+
import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
|
|
5
6
|
|
|
6
7
|
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
7
8
|
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
@@ -22,6 +23,7 @@ type BaseProps = {
|
|
|
22
23
|
appearance?: Appearance;
|
|
23
24
|
localization?: Localization;
|
|
24
25
|
tabs?: Array<Tab>;
|
|
26
|
+
routerPush?: RouterPush;
|
|
25
27
|
};
|
|
26
28
|
type DefaultProps = BaseProps & DefaultInboxProps & {
|
|
27
29
|
children?: never;
|
|
@@ -37,6 +39,7 @@ declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_
|
|
|
37
39
|
|
|
38
40
|
type InboxProps = DefaultProps | WithChildrenProps;
|
|
39
41
|
declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
42
|
+
declare const InboxChild: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
40
43
|
|
|
41
44
|
declare const Preferences: () => react_jsx_runtime.JSX.Element;
|
|
42
45
|
|
|
@@ -48,4 +51,72 @@ type NotificationProps = {
|
|
|
48
51
|
};
|
|
49
52
|
declare const Notifications: React$1.MemoExoticComponent<(props: NotificationProps) => react_jsx_runtime.JSX.Element>;
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
type NovuProviderProps = NovuOptions & {
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
};
|
|
57
|
+
declare const NovuProvider: ({ children, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache, }: NovuProviderProps) => react_jsx_runtime.JSX.Element;
|
|
58
|
+
declare const useNovu: () => Novu;
|
|
59
|
+
declare const useUnsafeNovu: () => Novu | undefined;
|
|
60
|
+
|
|
61
|
+
type UseNotificationsProps = {
|
|
62
|
+
tags?: string[];
|
|
63
|
+
read?: boolean;
|
|
64
|
+
archived?: boolean;
|
|
65
|
+
limit?: number;
|
|
66
|
+
onSuccess?: (data: Notification$1[]) => void;
|
|
67
|
+
onError?: (error: NovuError) => void;
|
|
68
|
+
};
|
|
69
|
+
declare const useNotifications: (props?: UseNotificationsProps) => {
|
|
70
|
+
readAll: () => Promise<{
|
|
71
|
+
data?: void | undefined;
|
|
72
|
+
error?: NovuError | undefined;
|
|
73
|
+
}>;
|
|
74
|
+
archiveAll: () => Promise<{
|
|
75
|
+
data?: void | undefined;
|
|
76
|
+
error?: NovuError | undefined;
|
|
77
|
+
}>;
|
|
78
|
+
archiveAllRead: () => Promise<{
|
|
79
|
+
data?: void | undefined;
|
|
80
|
+
error?: NovuError | undefined;
|
|
81
|
+
}>;
|
|
82
|
+
notifications: Notification$1[] | undefined;
|
|
83
|
+
error: NovuError | undefined;
|
|
84
|
+
isLoading: boolean;
|
|
85
|
+
isFetching: boolean;
|
|
86
|
+
refetch: () => Promise<void>;
|
|
87
|
+
fetchMore: () => Promise<void>;
|
|
88
|
+
hasMore: boolean;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type UsePreferencesProps = {
|
|
92
|
+
onSuccess?: (data: Preference[]) => void;
|
|
93
|
+
onError?: (error: NovuError) => void;
|
|
94
|
+
};
|
|
95
|
+
type UsePreferencesResult = {
|
|
96
|
+
preferences?: Preference[];
|
|
97
|
+
error?: NovuError;
|
|
98
|
+
isLoading: boolean;
|
|
99
|
+
isFetching: boolean;
|
|
100
|
+
refetch: () => Promise<void>;
|
|
101
|
+
};
|
|
102
|
+
declare const usePreferences: (props?: UsePreferencesProps) => UsePreferencesResult;
|
|
103
|
+
|
|
104
|
+
type Count = {
|
|
105
|
+
count: number;
|
|
106
|
+
filter: NotificationFilter;
|
|
107
|
+
};
|
|
108
|
+
type UseCountsProps = {
|
|
109
|
+
filters: NotificationFilter[];
|
|
110
|
+
onSuccess?: (data: Count[]) => void;
|
|
111
|
+
onError?: (error: NovuError) => void;
|
|
112
|
+
};
|
|
113
|
+
type UseCountsResult = {
|
|
114
|
+
counts?: Count[];
|
|
115
|
+
error?: NovuError;
|
|
116
|
+
isLoading: boolean;
|
|
117
|
+
isFetching: boolean;
|
|
118
|
+
refetch: () => Promise<void>;
|
|
119
|
+
};
|
|
120
|
+
declare const useCounts: (props: UseCountsProps) => UseCountsResult;
|
|
121
|
+
|
|
122
|
+
export { type BaseProps, Bell, type BellProps, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, InboxChild, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderer, NovuProvider, Preferences, type UseNotificationsProps, type WithChildrenProps, useCounts, useNotifications, useNovu, usePreferences, useUnsafeNovu };
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import React$1 from 'react';
|
|
3
|
-
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab } from '@novu/js/ui';
|
|
2
|
+
import React$1, { ReactNode } from 'react';
|
|
3
|
+
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
|
|
4
4
|
export { Notification } from '@novu/js/ui';
|
|
5
|
+
import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
|
|
5
6
|
|
|
6
7
|
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
7
8
|
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
@@ -22,6 +23,7 @@ type BaseProps = {
|
|
|
22
23
|
appearance?: Appearance;
|
|
23
24
|
localization?: Localization;
|
|
24
25
|
tabs?: Array<Tab>;
|
|
26
|
+
routerPush?: RouterPush;
|
|
25
27
|
};
|
|
26
28
|
type DefaultProps = BaseProps & DefaultInboxProps & {
|
|
27
29
|
children?: never;
|
|
@@ -37,6 +39,7 @@ declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_
|
|
|
37
39
|
|
|
38
40
|
type InboxProps = DefaultProps | WithChildrenProps;
|
|
39
41
|
declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
42
|
+
declare const InboxChild: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
40
43
|
|
|
41
44
|
declare const Preferences: () => react_jsx_runtime.JSX.Element;
|
|
42
45
|
|
|
@@ -48,4 +51,72 @@ type NotificationProps = {
|
|
|
48
51
|
};
|
|
49
52
|
declare const Notifications: React$1.MemoExoticComponent<(props: NotificationProps) => react_jsx_runtime.JSX.Element>;
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
type NovuProviderProps = NovuOptions & {
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
};
|
|
57
|
+
declare const NovuProvider: ({ children, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache, }: NovuProviderProps) => react_jsx_runtime.JSX.Element;
|
|
58
|
+
declare const useNovu: () => Novu;
|
|
59
|
+
declare const useUnsafeNovu: () => Novu | undefined;
|
|
60
|
+
|
|
61
|
+
type UseNotificationsProps = {
|
|
62
|
+
tags?: string[];
|
|
63
|
+
read?: boolean;
|
|
64
|
+
archived?: boolean;
|
|
65
|
+
limit?: number;
|
|
66
|
+
onSuccess?: (data: Notification$1[]) => void;
|
|
67
|
+
onError?: (error: NovuError) => void;
|
|
68
|
+
};
|
|
69
|
+
declare const useNotifications: (props?: UseNotificationsProps) => {
|
|
70
|
+
readAll: () => Promise<{
|
|
71
|
+
data?: void | undefined;
|
|
72
|
+
error?: NovuError | undefined;
|
|
73
|
+
}>;
|
|
74
|
+
archiveAll: () => Promise<{
|
|
75
|
+
data?: void | undefined;
|
|
76
|
+
error?: NovuError | undefined;
|
|
77
|
+
}>;
|
|
78
|
+
archiveAllRead: () => Promise<{
|
|
79
|
+
data?: void | undefined;
|
|
80
|
+
error?: NovuError | undefined;
|
|
81
|
+
}>;
|
|
82
|
+
notifications: Notification$1[] | undefined;
|
|
83
|
+
error: NovuError | undefined;
|
|
84
|
+
isLoading: boolean;
|
|
85
|
+
isFetching: boolean;
|
|
86
|
+
refetch: () => Promise<void>;
|
|
87
|
+
fetchMore: () => Promise<void>;
|
|
88
|
+
hasMore: boolean;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type UsePreferencesProps = {
|
|
92
|
+
onSuccess?: (data: Preference[]) => void;
|
|
93
|
+
onError?: (error: NovuError) => void;
|
|
94
|
+
};
|
|
95
|
+
type UsePreferencesResult = {
|
|
96
|
+
preferences?: Preference[];
|
|
97
|
+
error?: NovuError;
|
|
98
|
+
isLoading: boolean;
|
|
99
|
+
isFetching: boolean;
|
|
100
|
+
refetch: () => Promise<void>;
|
|
101
|
+
};
|
|
102
|
+
declare const usePreferences: (props?: UsePreferencesProps) => UsePreferencesResult;
|
|
103
|
+
|
|
104
|
+
type Count = {
|
|
105
|
+
count: number;
|
|
106
|
+
filter: NotificationFilter;
|
|
107
|
+
};
|
|
108
|
+
type UseCountsProps = {
|
|
109
|
+
filters: NotificationFilter[];
|
|
110
|
+
onSuccess?: (data: Count[]) => void;
|
|
111
|
+
onError?: (error: NovuError) => void;
|
|
112
|
+
};
|
|
113
|
+
type UseCountsResult = {
|
|
114
|
+
counts?: Count[];
|
|
115
|
+
error?: NovuError;
|
|
116
|
+
isLoading: boolean;
|
|
117
|
+
isFetching: boolean;
|
|
118
|
+
refetch: () => Promise<void>;
|
|
119
|
+
};
|
|
120
|
+
declare const useCounts: (props: UseCountsProps) => UseCountsResult;
|
|
121
|
+
|
|
122
|
+
export { type BaseProps, Bell, type BellProps, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, InboxChild, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderer, NovuProvider, Preferences, type UseNotificationsProps, type WithChildrenProps, useCounts, useNotifications, useNovu, usePreferences, useUnsafeNovu };
|
package/dist/client/index.js
CHANGED
|
@@ -32,8 +32,15 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
Bell: () => Bell,
|
|
34
34
|
Inbox: () => Inbox,
|
|
35
|
+
InboxChild: () => InboxChild,
|
|
35
36
|
Notifications: () => Notifications,
|
|
36
|
-
|
|
37
|
+
NovuProvider: () => NovuProvider,
|
|
38
|
+
Preferences: () => Preferences,
|
|
39
|
+
useCounts: () => useCounts,
|
|
40
|
+
useNotifications: () => useNotifications,
|
|
41
|
+
useNovu: () => useNovu,
|
|
42
|
+
usePreferences: () => usePreferences,
|
|
43
|
+
useUnsafeNovu: () => useUnsafeNovu
|
|
37
44
|
});
|
|
38
45
|
module.exports = __toCommonJS(src_exports);
|
|
39
46
|
|
|
@@ -119,7 +126,7 @@ var import_react5 = require("react");
|
|
|
119
126
|
var import_react_dom = __toESM(require("react-dom"));
|
|
120
127
|
var import_ui = require("@novu/js/ui");
|
|
121
128
|
|
|
122
|
-
// src/hooks/useDataRef.ts
|
|
129
|
+
// src/hooks/internal/useDataRef.ts
|
|
123
130
|
var import_react4 = require("react");
|
|
124
131
|
var useDataRef = (data) => {
|
|
125
132
|
const ref = (0, import_react4.useRef)(data);
|
|
@@ -129,8 +136,8 @@ var useDataRef = (data) => {
|
|
|
129
136
|
|
|
130
137
|
// src/components/Renderer.tsx
|
|
131
138
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
132
|
-
var Renderer = ({ options, children }) => {
|
|
133
|
-
const optionsRef = useDataRef(options);
|
|
139
|
+
var Renderer = ({ options, novu, children }) => {
|
|
140
|
+
const optionsRef = useDataRef({ ...options, novu });
|
|
134
141
|
const [novuUI, setNovuUI] = (0, import_react5.useState)();
|
|
135
142
|
const [mountedElements, setMountedElements] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
136
143
|
const mountElement = (0, import_react5.useCallback)(
|
|
@@ -151,10 +158,10 @@ var Renderer = ({ options, children }) => {
|
|
|
151
158
|
[setMountedElements]
|
|
152
159
|
);
|
|
153
160
|
(0, import_react5.useEffect)(() => {
|
|
154
|
-
const
|
|
155
|
-
setNovuUI(
|
|
161
|
+
const novu2 = new import_ui.NovuUI(optionsRef.current);
|
|
162
|
+
setNovuUI(novu2);
|
|
156
163
|
return () => {
|
|
157
|
-
|
|
164
|
+
novu2.unmount();
|
|
158
165
|
};
|
|
159
166
|
}, []);
|
|
160
167
|
(0, import_react5.useEffect)(() => {
|
|
@@ -165,6 +172,7 @@ var Renderer = ({ options, children }) => {
|
|
|
165
172
|
novuUI.updateLocalization(options.localization);
|
|
166
173
|
novuUI.updateTabs(options.tabs);
|
|
167
174
|
novuUI.updateOptions(options.options);
|
|
175
|
+
novuUI.updateRouterPush(options.routerPush);
|
|
168
176
|
}, [options]);
|
|
169
177
|
if (!novuUI) {
|
|
170
178
|
return null;
|
|
@@ -202,20 +210,50 @@ var DefaultInbox = (props) => {
|
|
|
202
210
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Mounter, { mount });
|
|
203
211
|
};
|
|
204
212
|
var Inbox = import_react6.default.memo((props) => {
|
|
205
|
-
const {
|
|
213
|
+
const { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;
|
|
214
|
+
const novu = useUnsafeNovu();
|
|
215
|
+
if (novu) {
|
|
216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InboxChild, { ...props });
|
|
217
|
+
}
|
|
218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
219
|
+
NovuProvider,
|
|
220
|
+
{
|
|
221
|
+
applicationIdentifier,
|
|
222
|
+
subscriberId,
|
|
223
|
+
subscriberHash,
|
|
224
|
+
backendUrl,
|
|
225
|
+
socketUrl,
|
|
226
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InboxChild, { ...props })
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
var InboxChild = import_react6.default.memo((props) => {
|
|
231
|
+
const {
|
|
232
|
+
localization,
|
|
233
|
+
appearance,
|
|
234
|
+
tabs,
|
|
235
|
+
routerPush,
|
|
236
|
+
applicationIdentifier,
|
|
237
|
+
subscriberId,
|
|
238
|
+
subscriberHash,
|
|
239
|
+
backendUrl,
|
|
240
|
+
socketUrl
|
|
241
|
+
} = props;
|
|
242
|
+
const novu = useNovu();
|
|
206
243
|
const options = (0, import_react6.useMemo)(() => {
|
|
207
244
|
return {
|
|
208
245
|
localization,
|
|
209
246
|
appearance,
|
|
210
247
|
tabs,
|
|
248
|
+
routerPush,
|
|
211
249
|
options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl }
|
|
212
250
|
};
|
|
213
251
|
}, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);
|
|
214
252
|
if (isWithChildrenProps(props)) {
|
|
215
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, children: props.children });
|
|
253
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, novu, children: props.children });
|
|
216
254
|
}
|
|
217
255
|
const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } = props;
|
|
218
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
256
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, novu, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
219
257
|
DefaultInbox,
|
|
220
258
|
{
|
|
221
259
|
open,
|
|
@@ -268,4 +306,325 @@ var Notifications = import_react8.default.memo((props) => {
|
|
|
268
306
|
);
|
|
269
307
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Mounter, { mount });
|
|
270
308
|
});
|
|
309
|
+
|
|
310
|
+
// src/hooks/NovuProvider.tsx
|
|
311
|
+
var import_js = require("@novu/js");
|
|
312
|
+
var import_react9 = require("react");
|
|
313
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
314
|
+
var NovuContext = (0, import_react9.createContext)(void 0);
|
|
315
|
+
var NovuProvider = ({
|
|
316
|
+
children,
|
|
317
|
+
applicationIdentifier,
|
|
318
|
+
subscriberId,
|
|
319
|
+
subscriberHash,
|
|
320
|
+
backendUrl,
|
|
321
|
+
socketUrl,
|
|
322
|
+
useCache
|
|
323
|
+
}) => {
|
|
324
|
+
const novu = (0, import_react9.useMemo)(
|
|
325
|
+
() => new import_js.Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),
|
|
326
|
+
[applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]
|
|
327
|
+
);
|
|
328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NovuContext.Provider, { value: novu, children });
|
|
329
|
+
};
|
|
330
|
+
var useNovu = () => {
|
|
331
|
+
const context = (0, import_react9.useContext)(NovuContext);
|
|
332
|
+
if (!context) {
|
|
333
|
+
throw new Error("useNovu must be used within a <NovuProvider />");
|
|
334
|
+
}
|
|
335
|
+
return context;
|
|
336
|
+
};
|
|
337
|
+
var useUnsafeNovu = () => {
|
|
338
|
+
const context = (0, import_react9.useContext)(NovuContext);
|
|
339
|
+
return context;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// src/hooks/useNotifications.ts
|
|
343
|
+
var import_react10 = require("react");
|
|
344
|
+
var import_js2 = require("@novu/js");
|
|
345
|
+
var useNotifications = (props) => {
|
|
346
|
+
const { tags, read, archived = false, limit, onSuccess, onError } = props || {};
|
|
347
|
+
const filterRef = (0, import_react10.useRef)(void 0);
|
|
348
|
+
const { notifications, on, off } = useNovu();
|
|
349
|
+
const [data, setData] = (0, import_react10.useState)();
|
|
350
|
+
const [error, setError] = (0, import_react10.useState)();
|
|
351
|
+
const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
|
|
352
|
+
const [isFetching, setIsFetching] = (0, import_react10.useState)(false);
|
|
353
|
+
const [hasMore, setHasMore] = (0, import_react10.useState)(false);
|
|
354
|
+
const length = data?.length;
|
|
355
|
+
const after = length ? data[length - 1].id : void 0;
|
|
356
|
+
const sync = (event) => {
|
|
357
|
+
if (!event.data || filterRef.current && !(0, import_js2.isSameFilter)(filterRef.current, event.data.filter)) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
setData(event.data.notifications);
|
|
361
|
+
setHasMore(event.data.hasMore);
|
|
362
|
+
};
|
|
363
|
+
(0, import_react10.useEffect)(() => {
|
|
364
|
+
on("notifications.list.updated", sync);
|
|
365
|
+
return () => {
|
|
366
|
+
off("notifications.list.updated", sync);
|
|
367
|
+
};
|
|
368
|
+
}, []);
|
|
369
|
+
(0, import_react10.useEffect)(() => {
|
|
370
|
+
const newFilter = { tags, read, archived };
|
|
371
|
+
if (filterRef.current && (0, import_js2.isSameFilter)(filterRef.current, newFilter)) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
notifications.clearCache({ filter: filterRef.current });
|
|
375
|
+
filterRef.current = newFilter;
|
|
376
|
+
fetchNotifications({ refetch: true });
|
|
377
|
+
}, [tags, read, archived]);
|
|
378
|
+
const fetchNotifications = async (options) => {
|
|
379
|
+
if (options?.refetch) {
|
|
380
|
+
setError(void 0);
|
|
381
|
+
setIsLoading(true);
|
|
382
|
+
setIsFetching(false);
|
|
383
|
+
}
|
|
384
|
+
setIsFetching(true);
|
|
385
|
+
const response = await notifications.list({
|
|
386
|
+
tags,
|
|
387
|
+
read,
|
|
388
|
+
archived,
|
|
389
|
+
limit,
|
|
390
|
+
after: options?.refetch ? void 0 : after
|
|
391
|
+
});
|
|
392
|
+
if (response.error) {
|
|
393
|
+
setError(response.error);
|
|
394
|
+
onError?.(response.error);
|
|
395
|
+
} else {
|
|
396
|
+
onSuccess?.(response.data.notifications);
|
|
397
|
+
setData(response.data.notifications);
|
|
398
|
+
setHasMore(response.data.hasMore);
|
|
399
|
+
}
|
|
400
|
+
setIsLoading(false);
|
|
401
|
+
setIsFetching(false);
|
|
402
|
+
};
|
|
403
|
+
const refetch = () => {
|
|
404
|
+
notifications.clearCache({ filter: { tags, read, archived } });
|
|
405
|
+
return fetchNotifications({ refetch: true });
|
|
406
|
+
};
|
|
407
|
+
const fetchMore = async () => {
|
|
408
|
+
if (!hasMore || isFetching) return;
|
|
409
|
+
return fetchNotifications();
|
|
410
|
+
};
|
|
411
|
+
const readAll = async () => {
|
|
412
|
+
return await notifications.readAll({ tags });
|
|
413
|
+
};
|
|
414
|
+
const archiveAll = async () => {
|
|
415
|
+
return await notifications.archiveAll({ tags });
|
|
416
|
+
};
|
|
417
|
+
const archiveAllRead = async () => {
|
|
418
|
+
return await notifications.archiveAllRead({ tags });
|
|
419
|
+
};
|
|
420
|
+
return {
|
|
421
|
+
readAll,
|
|
422
|
+
archiveAll,
|
|
423
|
+
archiveAllRead,
|
|
424
|
+
notifications: data,
|
|
425
|
+
error,
|
|
426
|
+
isLoading,
|
|
427
|
+
isFetching,
|
|
428
|
+
refetch,
|
|
429
|
+
fetchMore,
|
|
430
|
+
hasMore
|
|
431
|
+
};
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// src/hooks/usePreferences.ts
|
|
435
|
+
var import_react11 = require("react");
|
|
436
|
+
var usePreferences = (props) => {
|
|
437
|
+
const { onSuccess, onError } = props || {};
|
|
438
|
+
const [data, setData] = (0, import_react11.useState)();
|
|
439
|
+
const { preferences, on, off } = useNovu();
|
|
440
|
+
const [error, setError] = (0, import_react11.useState)();
|
|
441
|
+
const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
|
|
442
|
+
const [isFetching, setIsFetching] = (0, import_react11.useState)(false);
|
|
443
|
+
const sync = (event) => {
|
|
444
|
+
if (!event.data) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
setData(event.data);
|
|
448
|
+
};
|
|
449
|
+
(0, import_react11.useEffect)(() => {
|
|
450
|
+
fetchPreferences();
|
|
451
|
+
on("preferences.list.updated", sync);
|
|
452
|
+
on("preferences.list.pending", sync);
|
|
453
|
+
on("preferences.list.resolved", sync);
|
|
454
|
+
return () => {
|
|
455
|
+
off("preferences.list.updated", sync);
|
|
456
|
+
off("preferences.list.pending", sync);
|
|
457
|
+
off("preferences.list.resolved", sync);
|
|
458
|
+
};
|
|
459
|
+
}, []);
|
|
460
|
+
const fetchPreferences = async () => {
|
|
461
|
+
setIsFetching(true);
|
|
462
|
+
const response = await preferences.list();
|
|
463
|
+
if (response.error) {
|
|
464
|
+
setError(response.error);
|
|
465
|
+
onError?.(response.error);
|
|
466
|
+
} else {
|
|
467
|
+
onSuccess?.(response.data);
|
|
468
|
+
}
|
|
469
|
+
setIsLoading(false);
|
|
470
|
+
setIsFetching(false);
|
|
471
|
+
};
|
|
472
|
+
const refetch = () => {
|
|
473
|
+
preferences.cache.clearAll();
|
|
474
|
+
return fetchPreferences();
|
|
475
|
+
};
|
|
476
|
+
return {
|
|
477
|
+
preferences: data,
|
|
478
|
+
error,
|
|
479
|
+
isLoading,
|
|
480
|
+
isFetching,
|
|
481
|
+
refetch
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// src/hooks/useCounts.ts
|
|
486
|
+
var import_react14 = require("react");
|
|
487
|
+
var import_js3 = require("@novu/js");
|
|
488
|
+
|
|
489
|
+
// src/hooks/internal/useWebsocketEvent.ts
|
|
490
|
+
var import_react13 = require("react");
|
|
491
|
+
|
|
492
|
+
// src/utils/requestLock.ts
|
|
493
|
+
function requestLock(id, cb) {
|
|
494
|
+
if (!("locks" in navigator)) {
|
|
495
|
+
cb(id);
|
|
496
|
+
return () => {
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
let isFulfilled = false;
|
|
500
|
+
let promiseResolve;
|
|
501
|
+
const promise = new Promise((resolve) => {
|
|
502
|
+
promiseResolve = resolve;
|
|
503
|
+
});
|
|
504
|
+
navigator.locks.request(id, () => {
|
|
505
|
+
if (!isFulfilled) {
|
|
506
|
+
cb(id);
|
|
507
|
+
}
|
|
508
|
+
return promise;
|
|
509
|
+
});
|
|
510
|
+
return () => {
|
|
511
|
+
isFulfilled = true;
|
|
512
|
+
promiseResolve();
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// src/hooks/internal/useBrowserTabsChannel.ts
|
|
517
|
+
var import_react12 = require("react");
|
|
518
|
+
var useBrowserTabsChannel = ({
|
|
519
|
+
channelName,
|
|
520
|
+
onMessage
|
|
521
|
+
}) => {
|
|
522
|
+
const [tabsChannel] = (0, import_react12.useState)(
|
|
523
|
+
typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(channelName) : void 0
|
|
524
|
+
);
|
|
525
|
+
const postMessage = (data) => {
|
|
526
|
+
tabsChannel?.postMessage(data);
|
|
527
|
+
};
|
|
528
|
+
(0, import_react12.useEffect)(() => {
|
|
529
|
+
const listener = (event) => {
|
|
530
|
+
onMessage(event.data);
|
|
531
|
+
};
|
|
532
|
+
tabsChannel?.addEventListener("message", listener);
|
|
533
|
+
return () => {
|
|
534
|
+
tabsChannel?.removeEventListener("message", listener);
|
|
535
|
+
};
|
|
536
|
+
}, []);
|
|
537
|
+
return { postMessage };
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// src/hooks/internal/useWebsocketEvent.ts
|
|
541
|
+
var useWebSocketEvent = ({
|
|
542
|
+
event: webSocketEvent,
|
|
543
|
+
eventHandler: onMessage
|
|
544
|
+
}) => {
|
|
545
|
+
const novu = useNovu();
|
|
546
|
+
const { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });
|
|
547
|
+
const updateReadCount = (data) => {
|
|
548
|
+
onMessage(data);
|
|
549
|
+
postMessage(data);
|
|
550
|
+
};
|
|
551
|
+
(0, import_react13.useEffect)(() => {
|
|
552
|
+
const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {
|
|
553
|
+
novu.on(webSocketEvent, updateReadCount);
|
|
554
|
+
});
|
|
555
|
+
return () => {
|
|
556
|
+
novu.off(webSocketEvent, updateReadCount);
|
|
557
|
+
resolveLock();
|
|
558
|
+
};
|
|
559
|
+
}, []);
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
// src/hooks/useCounts.ts
|
|
563
|
+
var useCounts = (props) => {
|
|
564
|
+
const { filters, onSuccess, onError } = props;
|
|
565
|
+
const { notifications } = useNovu();
|
|
566
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
567
|
+
const [counts, setCounts] = (0, import_react14.useState)();
|
|
568
|
+
const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
|
|
569
|
+
const [isFetching, setIsFetching] = (0, import_react14.useState)(false);
|
|
570
|
+
const sync = async (notification) => {
|
|
571
|
+
const existingCounts = counts ?? new Array(filters.length).fill(void 0);
|
|
572
|
+
let countFiltersToFetch = [];
|
|
573
|
+
if (notification) {
|
|
574
|
+
for (let i = 0; i < existingCounts.length; i++) {
|
|
575
|
+
const filter = filters[i];
|
|
576
|
+
if ((0, import_js3.areTagsEqual)(filter.tags, notification.tags)) {
|
|
577
|
+
countFiltersToFetch.push(filter);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
countFiltersToFetch = filters;
|
|
582
|
+
}
|
|
583
|
+
if (countFiltersToFetch.length === 0) {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
setIsFetching(true);
|
|
587
|
+
const countsRes = await notifications.count({ filters: countFiltersToFetch });
|
|
588
|
+
setIsFetching(false);
|
|
589
|
+
setIsLoading(false);
|
|
590
|
+
if (countsRes.error) {
|
|
591
|
+
setError(countsRes.error);
|
|
592
|
+
onError?.(countsRes.error);
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const data = countsRes.data;
|
|
596
|
+
onSuccess?.(data.counts);
|
|
597
|
+
setCounts((oldCounts) => {
|
|
598
|
+
const newCounts = [];
|
|
599
|
+
const countsReceived = data.counts;
|
|
600
|
+
for (let i = 0; i < existingCounts.length; i++) {
|
|
601
|
+
const countReceived = countsReceived.find((c) => (0, import_js3.areTagsEqual)(c.filter.tags, existingCounts[i]?.filter.tags));
|
|
602
|
+
newCounts.push(countReceived || oldCounts[i]);
|
|
603
|
+
}
|
|
604
|
+
return newCounts;
|
|
605
|
+
});
|
|
606
|
+
};
|
|
607
|
+
useWebSocketEvent({
|
|
608
|
+
event: "notifications.notification_received",
|
|
609
|
+
eventHandler: (data) => {
|
|
610
|
+
sync(data.result);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
useWebSocketEvent({
|
|
614
|
+
event: "notifications.unread_count_changed",
|
|
615
|
+
eventHandler: () => {
|
|
616
|
+
sync();
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
(0, import_react14.useEffect)(() => {
|
|
620
|
+
setError(void 0);
|
|
621
|
+
setIsLoading(true);
|
|
622
|
+
setIsFetching(false);
|
|
623
|
+
sync();
|
|
624
|
+
}, [JSON.stringify(filters)]);
|
|
625
|
+
const refetch = async () => {
|
|
626
|
+
await sync();
|
|
627
|
+
};
|
|
628
|
+
return { counts, error, refetch, isLoading, isFetching };
|
|
629
|
+
};
|
|
271
630
|
//# sourceMappingURL=index.js.map
|