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