@novu/react 2.0.0-canary.0 → 2.0.0-canary.2
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 +12 -20
- package/dist/client/index.d.ts +12 -20
- package/dist/client/index.js +111 -84
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +27 -33
- package/dist/client/index.mjs.map +1 -1
- package/dist/server/server.d.mts +5 -10
- package/dist/server/server.d.ts +5 -10
- package/package.json +3 -3
package/dist/client/index.d.mts
CHANGED
|
@@ -3,25 +3,12 @@ import React$1 from 'react';
|
|
|
3
3
|
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab } from '@novu/js/ui';
|
|
4
4
|
export { Notification } from '@novu/js/ui';
|
|
5
5
|
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
}) => React$1.ReactNode;
|
|
9
|
-
type BellProps = {
|
|
10
|
-
children?: never | BellRenderProps;
|
|
11
|
-
};
|
|
12
|
-
declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_runtime.JSX.Element>;
|
|
13
|
-
|
|
14
|
-
type NotificationsRenderProps = (args: {
|
|
15
|
-
notification: Notification;
|
|
16
|
-
}) => React.ReactNode;
|
|
6
|
+
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
7
|
+
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
17
8
|
type DefaultInboxProps = {
|
|
18
9
|
open?: boolean;
|
|
19
|
-
renderNotification?:
|
|
20
|
-
|
|
21
|
-
}) => React.ReactNode;
|
|
22
|
-
renderBell?: ({ unreadCount }: {
|
|
23
|
-
unreadCount: number;
|
|
24
|
-
}) => React.ReactNode;
|
|
10
|
+
renderNotification?: NotificationsRenderer;
|
|
11
|
+
renderBell?: BellRenderer;
|
|
25
12
|
onNotificationClick?: NotificationClickHandler;
|
|
26
13
|
onPrimaryActionClick?: NotificationActionClickHandler;
|
|
27
14
|
onSecondaryActionClick?: NotificationActionClickHandler;
|
|
@@ -43,17 +30,22 @@ type WithChildrenProps = BaseProps & {
|
|
|
43
30
|
children: React.ReactNode;
|
|
44
31
|
};
|
|
45
32
|
|
|
33
|
+
type BellProps = {
|
|
34
|
+
renderBell?: BellRenderer;
|
|
35
|
+
};
|
|
36
|
+
declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_runtime.JSX.Element>;
|
|
37
|
+
|
|
46
38
|
type InboxProps = DefaultProps | WithChildrenProps;
|
|
47
39
|
declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
48
40
|
|
|
49
41
|
declare const Preferences: () => react_jsx_runtime.JSX.Element;
|
|
50
42
|
|
|
51
43
|
type NotificationProps = {
|
|
52
|
-
|
|
44
|
+
renderNotification?: NotificationsRenderer;
|
|
53
45
|
onNotificationClick?: NotificationClickHandler;
|
|
54
46
|
onPrimaryActionClick?: NotificationActionClickHandler;
|
|
55
47
|
onSecondaryActionClick?: NotificationActionClickHandler;
|
|
56
48
|
};
|
|
57
|
-
declare const Notifications: React$1.MemoExoticComponent<(
|
|
49
|
+
declare const Notifications: React$1.MemoExoticComponent<(props: NotificationProps) => react_jsx_runtime.JSX.Element>;
|
|
58
50
|
|
|
59
|
-
export { type BaseProps, Bell, type BellProps, type
|
|
51
|
+
export { type BaseProps, Bell, type BellProps, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderer, Preferences, type WithChildrenProps };
|
package/dist/client/index.d.ts
CHANGED
|
@@ -3,25 +3,12 @@ import React$1 from 'react';
|
|
|
3
3
|
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab } from '@novu/js/ui';
|
|
4
4
|
export { Notification } from '@novu/js/ui';
|
|
5
5
|
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
}) => React$1.ReactNode;
|
|
9
|
-
type BellProps = {
|
|
10
|
-
children?: never | BellRenderProps;
|
|
11
|
-
};
|
|
12
|
-
declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_runtime.JSX.Element>;
|
|
13
|
-
|
|
14
|
-
type NotificationsRenderProps = (args: {
|
|
15
|
-
notification: Notification;
|
|
16
|
-
}) => React.ReactNode;
|
|
6
|
+
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
7
|
+
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
17
8
|
type DefaultInboxProps = {
|
|
18
9
|
open?: boolean;
|
|
19
|
-
renderNotification?:
|
|
20
|
-
|
|
21
|
-
}) => React.ReactNode;
|
|
22
|
-
renderBell?: ({ unreadCount }: {
|
|
23
|
-
unreadCount: number;
|
|
24
|
-
}) => React.ReactNode;
|
|
10
|
+
renderNotification?: NotificationsRenderer;
|
|
11
|
+
renderBell?: BellRenderer;
|
|
25
12
|
onNotificationClick?: NotificationClickHandler;
|
|
26
13
|
onPrimaryActionClick?: NotificationActionClickHandler;
|
|
27
14
|
onSecondaryActionClick?: NotificationActionClickHandler;
|
|
@@ -43,17 +30,22 @@ type WithChildrenProps = BaseProps & {
|
|
|
43
30
|
children: React.ReactNode;
|
|
44
31
|
};
|
|
45
32
|
|
|
33
|
+
type BellProps = {
|
|
34
|
+
renderBell?: BellRenderer;
|
|
35
|
+
};
|
|
36
|
+
declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_runtime.JSX.Element>;
|
|
37
|
+
|
|
46
38
|
type InboxProps = DefaultProps | WithChildrenProps;
|
|
47
39
|
declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
48
40
|
|
|
49
41
|
declare const Preferences: () => react_jsx_runtime.JSX.Element;
|
|
50
42
|
|
|
51
43
|
type NotificationProps = {
|
|
52
|
-
|
|
44
|
+
renderNotification?: NotificationsRenderer;
|
|
53
45
|
onNotificationClick?: NotificationClickHandler;
|
|
54
46
|
onPrimaryActionClick?: NotificationActionClickHandler;
|
|
55
47
|
onSecondaryActionClick?: NotificationActionClickHandler;
|
|
56
48
|
};
|
|
57
|
-
declare const Notifications: React$1.MemoExoticComponent<(
|
|
49
|
+
declare const Notifications: React$1.MemoExoticComponent<(props: NotificationProps) => react_jsx_runtime.JSX.Element>;
|
|
58
50
|
|
|
59
|
-
export { type BaseProps, Bell, type BellProps, type
|
|
51
|
+
export { type BaseProps, Bell, type BellProps, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderer, Preferences, type WithChildrenProps };
|
package/dist/client/index.js
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var
|
|
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 name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], 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);
|
|
3
29
|
|
|
4
|
-
// src/
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
Bell: () => Bell,
|
|
34
|
+
Inbox: () => Inbox,
|
|
35
|
+
Notifications: () => Notifications,
|
|
36
|
+
Preferences: () => Preferences
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(src_exports);
|
|
5
39
|
|
|
40
|
+
// src/components/Bell.tsx
|
|
41
|
+
var import_react3 = __toESM(require("react"));
|
|
42
|
+
|
|
43
|
+
// src/utils/createContextAndHook.ts
|
|
44
|
+
var import_react = __toESM(require("react"));
|
|
6
45
|
function assertContextExists(contextVal, msgOrCtx) {
|
|
7
46
|
if (!contextVal) {
|
|
8
47
|
throw typeof msgOrCtx === "string" ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);
|
|
@@ -10,33 +49,33 @@ function assertContextExists(contextVal, msgOrCtx) {
|
|
|
10
49
|
}
|
|
11
50
|
var createContextAndHook = (displayName, options) => {
|
|
12
51
|
const { assertCtxFn = assertContextExists } = options || {};
|
|
13
|
-
const Ctx =
|
|
52
|
+
const Ctx = import_react.default.createContext(void 0);
|
|
14
53
|
Ctx.displayName = displayName;
|
|
15
54
|
const useCtx = () => {
|
|
16
|
-
const ctx =
|
|
55
|
+
const ctx = import_react.default.useContext(Ctx);
|
|
17
56
|
assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);
|
|
18
57
|
return ctx.value;
|
|
19
58
|
};
|
|
20
59
|
const useCtxWithoutGuarantee = () => {
|
|
21
|
-
const ctx =
|
|
60
|
+
const ctx = import_react.default.useContext(Ctx);
|
|
22
61
|
return ctx ? ctx.value : {};
|
|
23
62
|
};
|
|
24
63
|
return [Ctx, useCtx, useCtxWithoutGuarantee];
|
|
25
64
|
};
|
|
26
65
|
|
|
27
66
|
// src/context/RenderContext.tsx
|
|
28
|
-
var
|
|
67
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
29
68
|
var [RendererContext, useRendererContext] = createContextAndHook("RendererContext");
|
|
30
69
|
var RendererProvider = (props) => {
|
|
31
|
-
return /* @__PURE__ */
|
|
70
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RendererContext.Provider, { value: { value: props.value }, children: props.children });
|
|
32
71
|
};
|
|
33
72
|
|
|
34
73
|
// src/components/Mounter.tsx
|
|
35
|
-
|
|
36
|
-
|
|
74
|
+
var import_react2 = __toESM(require("react"));
|
|
75
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
37
76
|
function Mounter({ mount }) {
|
|
38
|
-
const ref =
|
|
39
|
-
|
|
77
|
+
const ref = import_react2.default.useRef(null);
|
|
78
|
+
import_react2.default.useEffect(() => {
|
|
40
79
|
let unmount;
|
|
41
80
|
const element = ref.current;
|
|
42
81
|
if (element && mount) {
|
|
@@ -51,49 +90,50 @@ function Mounter({ mount }) {
|
|
|
51
90
|
}
|
|
52
91
|
};
|
|
53
92
|
}, [ref, mount]);
|
|
54
|
-
return /* @__PURE__ */
|
|
93
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref });
|
|
55
94
|
}
|
|
56
95
|
|
|
57
96
|
// src/components/Bell.tsx
|
|
58
|
-
|
|
59
|
-
var Bell =
|
|
97
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
98
|
+
var Bell = import_react3.default.memo((props) => {
|
|
99
|
+
const { renderBell } = props;
|
|
60
100
|
const { novuUI, mountElement } = useRendererContext();
|
|
61
|
-
const mount =
|
|
101
|
+
const mount = import_react3.default.useCallback(
|
|
62
102
|
(element) => {
|
|
63
103
|
return novuUI.mountComponent({
|
|
64
104
|
name: "Bell",
|
|
65
105
|
element,
|
|
66
|
-
props:
|
|
106
|
+
props: renderBell ? { mountBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : void 0
|
|
67
107
|
});
|
|
68
108
|
},
|
|
69
|
-
[
|
|
109
|
+
[renderBell]
|
|
70
110
|
);
|
|
71
|
-
return /* @__PURE__ */
|
|
111
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Mounter, { mount });
|
|
72
112
|
});
|
|
73
113
|
|
|
74
114
|
// src/components/Inbox.tsx
|
|
75
|
-
|
|
115
|
+
var import_react6 = __toESM(require("react"));
|
|
76
116
|
|
|
77
117
|
// src/components/Renderer.tsx
|
|
78
|
-
|
|
79
|
-
var
|
|
80
|
-
var
|
|
118
|
+
var import_react5 = require("react");
|
|
119
|
+
var import_react_dom = __toESM(require("react-dom"));
|
|
120
|
+
var import_ui = require("@novu/js/ui");
|
|
81
121
|
|
|
82
122
|
// src/hooks/useDataRef.ts
|
|
83
|
-
|
|
123
|
+
var import_react4 = require("react");
|
|
84
124
|
var useDataRef = (data) => {
|
|
85
|
-
const ref =
|
|
125
|
+
const ref = (0, import_react4.useRef)(data);
|
|
86
126
|
ref.current = data;
|
|
87
127
|
return ref;
|
|
88
128
|
};
|
|
89
129
|
|
|
90
130
|
// src/components/Renderer.tsx
|
|
91
|
-
|
|
131
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
92
132
|
var Renderer = ({ options, children }) => {
|
|
93
133
|
const optionsRef = useDataRef(options);
|
|
94
|
-
const [novuUI, setNovuUI] =
|
|
95
|
-
const [mountedElements, setMountedElements] =
|
|
96
|
-
const mountElement =
|
|
134
|
+
const [novuUI, setNovuUI] = (0, import_react5.useState)();
|
|
135
|
+
const [mountedElements, setMountedElements] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
136
|
+
const mountElement = (0, import_react5.useCallback)(
|
|
97
137
|
(el, mountedElement) => {
|
|
98
138
|
setMountedElements((prev) => {
|
|
99
139
|
const newMountedElements = new Map(prev);
|
|
@@ -110,14 +150,14 @@ var Renderer = ({ options, children }) => {
|
|
|
110
150
|
},
|
|
111
151
|
[setMountedElements]
|
|
112
152
|
);
|
|
113
|
-
|
|
114
|
-
const novu = new
|
|
153
|
+
(0, import_react5.useEffect)(() => {
|
|
154
|
+
const novu = new import_ui.NovuUI(optionsRef.current);
|
|
115
155
|
setNovuUI(novu);
|
|
116
156
|
return () => {
|
|
117
157
|
novu.unmount();
|
|
118
158
|
};
|
|
119
159
|
}, []);
|
|
120
|
-
|
|
160
|
+
(0, import_react5.useEffect)(() => {
|
|
121
161
|
if (!novuUI) {
|
|
122
162
|
return;
|
|
123
163
|
}
|
|
@@ -129,33 +169,27 @@ var Renderer = ({ options, children }) => {
|
|
|
129
169
|
if (!novuUI) {
|
|
130
170
|
return null;
|
|
131
171
|
}
|
|
132
|
-
return /* @__PURE__ */
|
|
172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(RendererProvider, { value: { mountElement, novuUI }, children: [
|
|
133
173
|
[...mountedElements].map(([element, mountedElement]) => {
|
|
134
|
-
return
|
|
174
|
+
return import_react_dom.default.createPortal(mountedElement, element);
|
|
135
175
|
}),
|
|
136
176
|
children
|
|
137
177
|
] });
|
|
138
178
|
};
|
|
139
179
|
|
|
140
180
|
// src/components/Inbox.tsx
|
|
141
|
-
|
|
142
|
-
var DefaultInbox = ({
|
|
143
|
-
open,
|
|
144
|
-
renderNotification,
|
|
145
|
-
renderBell,
|
|
146
|
-
onNotificationClick,
|
|
147
|
-
onPrimaryActionClick,
|
|
148
|
-
onSecondaryActionClick
|
|
149
|
-
}) => {
|
|
181
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
182
|
+
var DefaultInbox = (props) => {
|
|
183
|
+
const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } = props;
|
|
150
184
|
const { novuUI, mountElement } = useRendererContext();
|
|
151
|
-
const mount =
|
|
185
|
+
const mount = import_react6.default.useCallback(
|
|
152
186
|
(element) => {
|
|
153
187
|
return novuUI.mountComponent({
|
|
154
188
|
name: "Inbox",
|
|
155
189
|
props: {
|
|
156
190
|
open,
|
|
157
|
-
mountNotification: renderNotification ? (el,
|
|
158
|
-
mountBell: renderBell ? (el,
|
|
191
|
+
mountNotification: renderNotification ? (el, notification) => mountElement(el, renderNotification(notification)) : void 0,
|
|
192
|
+
mountBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : void 0,
|
|
159
193
|
onNotificationClick,
|
|
160
194
|
onPrimaryActionClick,
|
|
161
195
|
onSecondaryActionClick
|
|
@@ -165,11 +199,11 @@ var DefaultInbox = ({
|
|
|
165
199
|
},
|
|
166
200
|
[open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
|
|
167
201
|
);
|
|
168
|
-
return /* @__PURE__ */
|
|
202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Mounter, { mount });
|
|
169
203
|
};
|
|
170
|
-
var Inbox =
|
|
204
|
+
var Inbox = import_react6.default.memo((props) => {
|
|
171
205
|
const { localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;
|
|
172
|
-
const options =
|
|
206
|
+
const options = (0, import_react6.useMemo)(() => {
|
|
173
207
|
return {
|
|
174
208
|
localization,
|
|
175
209
|
appearance,
|
|
@@ -178,10 +212,10 @@ var Inbox = _react2.default.memo((props) => {
|
|
|
178
212
|
};
|
|
179
213
|
}, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);
|
|
180
214
|
if (isWithChildrenProps(props)) {
|
|
181
|
-
return /* @__PURE__ */
|
|
215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, children: props.children });
|
|
182
216
|
}
|
|
183
217
|
const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } = props;
|
|
184
|
-
return /* @__PURE__ */
|
|
218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
185
219
|
DefaultInbox,
|
|
186
220
|
{
|
|
187
221
|
open,
|
|
@@ -198,47 +232,40 @@ function isWithChildrenProps(props) {
|
|
|
198
232
|
}
|
|
199
233
|
|
|
200
234
|
// src/components/Preferences.tsx
|
|
201
|
-
|
|
202
|
-
|
|
235
|
+
var import_react7 = __toESM(require("react"));
|
|
236
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
203
237
|
var Preferences = () => {
|
|
204
238
|
const { novuUI } = useRendererContext();
|
|
205
|
-
const mount =
|
|
239
|
+
const mount = import_react7.default.useCallback((element) => {
|
|
206
240
|
return novuUI.mountComponent({
|
|
207
241
|
name: "Preferences",
|
|
208
242
|
element
|
|
209
243
|
});
|
|
210
244
|
}, []);
|
|
211
|
-
return /* @__PURE__ */
|
|
245
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Mounter, { mount });
|
|
212
246
|
};
|
|
213
247
|
|
|
214
248
|
// src/components/Notifications.tsx
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
var Notifications =
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
exports.Bell = Bell; exports.Inbox = Inbox; exports.Notifications = Notifications; exports.Preferences = Preferences;
|
|
249
|
+
var import_react8 = __toESM(require("react"));
|
|
250
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
251
|
+
var Notifications = import_react8.default.memo((props) => {
|
|
252
|
+
const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;
|
|
253
|
+
const { novuUI, mountElement } = useRendererContext();
|
|
254
|
+
const mount = import_react8.default.useCallback(
|
|
255
|
+
(element) => {
|
|
256
|
+
return novuUI.mountComponent({
|
|
257
|
+
name: "Notifications",
|
|
258
|
+
element,
|
|
259
|
+
props: {
|
|
260
|
+
mountNotification: renderNotification ? (el, notification) => mountElement(el, renderNotification(notification)) : void 0,
|
|
261
|
+
onNotificationClick,
|
|
262
|
+
onPrimaryActionClick,
|
|
263
|
+
onSecondaryActionClick
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
},
|
|
267
|
+
[renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
|
|
268
|
+
);
|
|
269
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Mounter, { mount });
|
|
270
|
+
});
|
|
244
271
|
//# sourceMappingURL=index.js.map
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/pavlotymchuk/projects/js/novu-2/packages/react/dist/client/index.js","../../src/components/Bell.tsx","../../src/utils/createContextAndHook.ts","../../src/context/RenderContext.tsx","../../src/components/Mounter.tsx","../../src/components/Inbox.tsx","../../src/components/Renderer.tsx","../../src/hooks/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx"],"names":[],"mappings":"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","file":"/Users/pavlotymchuk/projects/js/novu-2/packages/react/dist/client/index.js","sourcesContent":[null,"import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\n\nexport type BellRenderProps = ({ unreadCount }: { unreadCount: number }) => React.ReactNode;\n\nexport type BellProps = {\n children?: never | BellRenderProps;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: props.children\n ? { mountBell: (el, { unreadCount }) => mountElement(el, props.children?.({ unreadCount })) }\n : undefined,\n });\n },\n [props.children]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = ({\n open,\n renderNotification,\n renderBell,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n}: DefaultInboxProps) => {\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n mountNotification: renderNotification\n ? (el, { notification }) => mountElement(el, renderNotification({ notification }))\n : undefined,\n mountBell: renderBell ? (el, { unreadCount }) => mountElement(el, renderBell({ unreadCount })) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } =\n props;\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);\n\n if (isWithChildrenProps(props)) {\n return <Renderer options={options}>{props.children}</Renderer>;\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options}>\n <DefaultInbox\n open={open}\n renderNotification={renderNotification}\n renderBell={renderBell}\n onNotificationClick={onNotificationClick}\n onPrimaryActionClick={onPrimaryActionClick}\n onSecondaryActionClick={onSecondaryActionClick}\n />\n </Renderer>\n );\n});\n\nfunction isWithChildrenProps(props: InboxProps): props is WithChildrenProps {\n return 'children' in props;\n}\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport { NovuUI } from '@novu/js/ui';\nimport type { NovuUIOptions } from '@novu/js/ui';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n}>;\n\n/**\n *\n * Renderer component that provides the NovuUI instance and mounts the elements on DOM in a portal\n */\nexport const Renderer = ({ options, children }: RendererProps) => {\n const optionsRef = useDataRef(options);\n const [novuUI, setNovuUI] = useState<NovuUI | undefined>();\n const [mountedElements, setMountedElements] = useState(new Map<HTMLElement, MountedElement>());\n\n const mountElement = useCallback(\n (el: HTMLElement, mountedElement: MountedElement) => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.set(el, mountedElement);\n\n return newMountedElements;\n });\n\n return () => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.delete(el);\n\n return newMountedElements;\n });\n };\n },\n [setMountedElements]\n );\n\n useEffect(() => {\n const novu = new NovuUI(optionsRef.current);\n setNovuUI(novu);\n\n return () => {\n novu.unmount();\n };\n }, []);\n\n useEffect(() => {\n if (!novuUI) {\n return;\n }\n\n novuUI.updateAppearance(options.appearance);\n novuUI.updateLocalization(options.localization);\n novuUI.updateTabs(options.tabs);\n novuUI.updateOptions(options.options);\n }, [options]);\n\n if (!novuUI) {\n return null;\n }\n\n return (\n <RendererProvider value={{ mountElement, novuUI }}>\n {[...mountedElements].map(([element, mountedElement]) => {\n return ReactDOM.createPortal(mountedElement, element);\n })}\n\n {children}\n </RendererProvider>\n );\n};\n","import { useRef } from 'react';\n\nexport const useDataRef = <T>(data: T) => {\n const ref = useRef(data);\n ref.current = data;\n\n return ref;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\n\nexport const Preferences = () => {\n const { novuUI } = useRenderer();\n\n const mount = React.useCallback((element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Preferences',\n element,\n });\n }, []);\n\n return <Mounter mount={mount} />;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { NotificationsRenderProps } from '../utils/types';\nimport { Mounter } from './Mounter';\nimport type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\n\nexport type NotificationProps = {\n children?: never | NotificationsRenderProps;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo(\n ({ children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }: NotificationProps) => {\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: children\n ? {\n mountNotification: (el, { notification }) => mountElement(el, children?.({ notification })),\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n }\n : { onNotificationClick, onPrimaryActionClick, onSecondaryActionClick },\n });\n },\n [children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n }\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/components/Bell.tsx","../../src/utils/createContextAndHook.ts","../../src/context/RenderContext.tsx","../../src/components/Mounter.tsx","../../src/components/Inbox.tsx","../../src/components/Renderer.tsx","../../src/hooks/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx"],"sourcesContent":["export * from './components';\nexport * from './utils/types';\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { BellRenderer } from '../utils/types';\n\nexport type BellProps = {\n renderBell?: BellRenderer;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { renderBell } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: renderBell ? { mountBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : undefined,\n });\n },\n [renderBell]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = (props: DefaultInboxProps) => {\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n mountNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n mountBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } =\n props;\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);\n\n if (isWithChildrenProps(props)) {\n return <Renderer options={options}>{props.children}</Renderer>;\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options}>\n <DefaultInbox\n open={open}\n renderNotification={renderNotification}\n renderBell={renderBell}\n onNotificationClick={onNotificationClick}\n onPrimaryActionClick={onPrimaryActionClick}\n onSecondaryActionClick={onSecondaryActionClick}\n />\n </Renderer>\n );\n});\n\nfunction isWithChildrenProps(props: InboxProps): props is WithChildrenProps {\n return 'children' in props;\n}\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport { NovuUI } from '@novu/js/ui';\nimport type { NovuUIOptions } from '@novu/js/ui';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n}>;\n\n/**\n *\n * Renderer component that provides the NovuUI instance and mounts the elements on DOM in a portal\n */\nexport const Renderer = ({ options, children }: RendererProps) => {\n const optionsRef = useDataRef(options);\n const [novuUI, setNovuUI] = useState<NovuUI | undefined>();\n const [mountedElements, setMountedElements] = useState(new Map<HTMLElement, MountedElement>());\n\n const mountElement = useCallback(\n (el: HTMLElement, mountedElement: MountedElement) => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.set(el, mountedElement);\n\n return newMountedElements;\n });\n\n return () => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.delete(el);\n\n return newMountedElements;\n });\n };\n },\n [setMountedElements]\n );\n\n useEffect(() => {\n const novu = new NovuUI(optionsRef.current);\n setNovuUI(novu);\n\n return () => {\n novu.unmount();\n };\n }, []);\n\n useEffect(() => {\n if (!novuUI) {\n return;\n }\n\n novuUI.updateAppearance(options.appearance);\n novuUI.updateLocalization(options.localization);\n novuUI.updateTabs(options.tabs);\n novuUI.updateOptions(options.options);\n }, [options]);\n\n if (!novuUI) {\n return null;\n }\n\n return (\n <RendererProvider value={{ mountElement, novuUI }}>\n {[...mountedElements].map(([element, mountedElement]) => {\n return ReactDOM.createPortal(mountedElement, element);\n })}\n\n {children}\n </RendererProvider>\n );\n};\n","import { useRef } from 'react';\n\nexport const useDataRef = <T>(data: T) => {\n const ref = useRef(data);\n ref.current = data;\n\n return ref;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\n\nexport const Preferences = () => {\n const { novuUI } = useRenderer();\n\n const mount = React.useCallback((element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Preferences',\n element,\n });\n }, []);\n\n return <Mounter mount={mount} />;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\nimport { NotificationsRenderer } from '../utils/types';\n\nexport type NotificationProps = {\n renderNotification?: NotificationsRenderer;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo((props: NotificationProps) => {\n const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: {\n mountNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n });\n },\n [renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n});\n"],"mappings":"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","names":["import_react","React","import_react","import_jsx_runtime","React","import_jsx_runtime","React","import_react","import_react","import_react","import_jsx_runtime","ReactDOM","import_jsx_runtime","React","import_react","import_jsx_runtime","React","import_react","import_jsx_runtime","React"]}
|
package/dist/client/index.mjs
CHANGED
|
@@ -57,16 +57,17 @@ function Mounter({ mount }) {
|
|
|
57
57
|
// src/components/Bell.tsx
|
|
58
58
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
59
59
|
var Bell = React3.memo((props) => {
|
|
60
|
+
const { renderBell } = props;
|
|
60
61
|
const { novuUI, mountElement } = useRendererContext();
|
|
61
62
|
const mount = React3.useCallback(
|
|
62
63
|
(element) => {
|
|
63
64
|
return novuUI.mountComponent({
|
|
64
65
|
name: "Bell",
|
|
65
66
|
element,
|
|
66
|
-
props:
|
|
67
|
+
props: renderBell ? { mountBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : void 0
|
|
67
68
|
});
|
|
68
69
|
},
|
|
69
|
-
[
|
|
70
|
+
[renderBell]
|
|
70
71
|
);
|
|
71
72
|
return /* @__PURE__ */ jsx3(Mounter, { mount });
|
|
72
73
|
});
|
|
@@ -139,14 +140,8 @@ var Renderer = ({ options, children }) => {
|
|
|
139
140
|
|
|
140
141
|
// src/components/Inbox.tsx
|
|
141
142
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
142
|
-
var DefaultInbox = ({
|
|
143
|
-
open,
|
|
144
|
-
renderNotification,
|
|
145
|
-
renderBell,
|
|
146
|
-
onNotificationClick,
|
|
147
|
-
onPrimaryActionClick,
|
|
148
|
-
onSecondaryActionClick
|
|
149
|
-
}) => {
|
|
143
|
+
var DefaultInbox = (props) => {
|
|
144
|
+
const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } = props;
|
|
150
145
|
const { novuUI, mountElement } = useRendererContext();
|
|
151
146
|
const mount = React5.useCallback(
|
|
152
147
|
(element) => {
|
|
@@ -154,8 +149,8 @@ var DefaultInbox = ({
|
|
|
154
149
|
name: "Inbox",
|
|
155
150
|
props: {
|
|
156
151
|
open,
|
|
157
|
-
mountNotification: renderNotification ? (el,
|
|
158
|
-
mountBell: renderBell ? (el,
|
|
152
|
+
mountNotification: renderNotification ? (el, notification) => mountElement(el, renderNotification(notification)) : void 0,
|
|
153
|
+
mountBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : void 0,
|
|
159
154
|
onNotificationClick,
|
|
160
155
|
onPrimaryActionClick,
|
|
161
156
|
onSecondaryActionClick
|
|
@@ -214,27 +209,26 @@ var Preferences = () => {
|
|
|
214
209
|
// src/components/Notifications.tsx
|
|
215
210
|
import React7 from "react";
|
|
216
211
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
217
|
-
var Notifications = React7.memo(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
);
|
|
212
|
+
var Notifications = React7.memo((props) => {
|
|
213
|
+
const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;
|
|
214
|
+
const { novuUI, mountElement } = useRendererContext();
|
|
215
|
+
const mount = React7.useCallback(
|
|
216
|
+
(element) => {
|
|
217
|
+
return novuUI.mountComponent({
|
|
218
|
+
name: "Notifications",
|
|
219
|
+
element,
|
|
220
|
+
props: {
|
|
221
|
+
mountNotification: renderNotification ? (el, notification) => mountElement(el, renderNotification(notification)) : void 0,
|
|
222
|
+
onNotificationClick,
|
|
223
|
+
onPrimaryActionClick,
|
|
224
|
+
onSecondaryActionClick
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
[renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
|
|
229
|
+
);
|
|
230
|
+
return /* @__PURE__ */ jsx6(Mounter, { mount });
|
|
231
|
+
});
|
|
238
232
|
export {
|
|
239
233
|
Bell,
|
|
240
234
|
Inbox,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/Bell.tsx","../../src/utils/createContextAndHook.ts","../../src/context/RenderContext.tsx","../../src/components/Mounter.tsx","../../src/components/Inbox.tsx","../../src/components/Renderer.tsx","../../src/hooks/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx"],"sourcesContent":["import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\n\nexport type BellRenderProps = ({ unreadCount }: { unreadCount: number }) => React.ReactNode;\n\nexport type BellProps = {\n children?: never | BellRenderProps;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: props.children\n ? { mountBell: (el, { unreadCount }) => mountElement(el, props.children?.({ unreadCount })) }\n : undefined,\n });\n },\n [props.children]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = ({\n open,\n renderNotification,\n renderBell,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n}: DefaultInboxProps) => {\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n mountNotification: renderNotification\n ? (el, { notification }) => mountElement(el, renderNotification({ notification }))\n : undefined,\n mountBell: renderBell ? (el, { unreadCount }) => mountElement(el, renderBell({ unreadCount })) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } =\n props;\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);\n\n if (isWithChildrenProps(props)) {\n return <Renderer options={options}>{props.children}</Renderer>;\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options}>\n <DefaultInbox\n open={open}\n renderNotification={renderNotification}\n renderBell={renderBell}\n onNotificationClick={onNotificationClick}\n onPrimaryActionClick={onPrimaryActionClick}\n onSecondaryActionClick={onSecondaryActionClick}\n />\n </Renderer>\n );\n});\n\nfunction isWithChildrenProps(props: InboxProps): props is WithChildrenProps {\n return 'children' in props;\n}\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport { NovuUI } from '@novu/js/ui';\nimport type { NovuUIOptions } from '@novu/js/ui';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n}>;\n\n/**\n *\n * Renderer component that provides the NovuUI instance and mounts the elements on DOM in a portal\n */\nexport const Renderer = ({ options, children }: RendererProps) => {\n const optionsRef = useDataRef(options);\n const [novuUI, setNovuUI] = useState<NovuUI | undefined>();\n const [mountedElements, setMountedElements] = useState(new Map<HTMLElement, MountedElement>());\n\n const mountElement = useCallback(\n (el: HTMLElement, mountedElement: MountedElement) => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.set(el, mountedElement);\n\n return newMountedElements;\n });\n\n return () => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.delete(el);\n\n return newMountedElements;\n });\n };\n },\n [setMountedElements]\n );\n\n useEffect(() => {\n const novu = new NovuUI(optionsRef.current);\n setNovuUI(novu);\n\n return () => {\n novu.unmount();\n };\n }, []);\n\n useEffect(() => {\n if (!novuUI) {\n return;\n }\n\n novuUI.updateAppearance(options.appearance);\n novuUI.updateLocalization(options.localization);\n novuUI.updateTabs(options.tabs);\n novuUI.updateOptions(options.options);\n }, [options]);\n\n if (!novuUI) {\n return null;\n }\n\n return (\n <RendererProvider value={{ mountElement, novuUI }}>\n {[...mountedElements].map(([element, mountedElement]) => {\n return ReactDOM.createPortal(mountedElement, element);\n })}\n\n {children}\n </RendererProvider>\n );\n};\n","import { useRef } from 'react';\n\nexport const useDataRef = <T>(data: T) => {\n const ref = useRef(data);\n ref.current = data;\n\n return ref;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\n\nexport const Preferences = () => {\n const { novuUI } = useRenderer();\n\n const mount = React.useCallback((element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Preferences',\n element,\n });\n }, []);\n\n return <Mounter mount={mount} />;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { NotificationsRenderProps } from '../utils/types';\nimport { Mounter } from './Mounter';\nimport type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\n\nexport type NotificationProps = {\n children?: never | NotificationsRenderProps;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo(\n ({ children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }: NotificationProps) => {\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: children\n ? {\n mountNotification: (el, { notification }) => mountElement(el, children?.({ notification })),\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n }\n : { onNotificationClick, onPrimaryActionClick, onSecondaryActionClick },\n });\n },\n [children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n }\n);\n"],"mappings":";AAAA,OAAOA,YAAW;;;ACAlB,OAAO,WAAW;AAEX,SAAS,oBAAoB,YAAqB,UAA2D;AAClH,MAAI,CAAC,YAAY;AACf,UAAM,OAAO,aAAa,WAAW,IAAI,MAAM,QAAQ,IAAI,IAAI,MAAM,GAAG,SAAS,WAAW,YAAY;AAAA,EAC1G;AACF;AAYO,IAAM,uBAAuB,CAClC,aACA,YAC8E;AAC9E,QAAM,EAAE,cAAc,oBAAoB,IAAI,WAAW,CAAC;AAC1D,QAAM,MAAM,MAAM,cAA6C,MAAS;AACxE,MAAI,cAAc;AAElB,QAAM,SAAS,MAAM;AACnB,UAAM,MAAM,MAAM,WAAW,GAAG;AAChC,gBAAY,KAAK,wDAAwD;AAEzE,WAAQ,IAAY;AAAA,EACtB;AAEA,QAAM,yBAAyB,MAAM;AACnC,UAAM,MAAM,MAAM,WAAW,GAAG;AAEhC,WAAO,MAAM,IAAI,QAAQ,CAAC;AAAA,EAC5B;AAEA,SAAO,CAAC,KAAK,QAAQ,sBAAsB;AAC7C;;;ACzBS;AAHT,IAAM,CAAC,iBAAiB,kBAAkB,IAAI,qBAA2C,iBAAiB;AAE1G,IAAM,mBAAmB,CAAC,UAAoE;AAC5F,SAAO,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,OAAO,MAAM,MAAM,GAAI,gBAAM,UAAS;AAClF;;;AChBA,OAAOC,YAAW;AA6BT,gBAAAC,YAAA;AApBF,SAAS,QAAQ,EAAE,MAAM,GAAiB;AAC/C,QAAM,MAAMD,OAAM,OAAuB,IAAI;AAE7C,EAAAA,OAAM,UAAU,MAAM;AACpB,QAAI;AACJ,UAAM,UAAU,IAAI;AACpB,QAAI,WAAW,OAAO;AACpB,YAAM,kBAAkB,MAAM,OAAO;AACrC,UAAI,iBAAiB;AACnB,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,WAAO,MAAM;AACX,UAAI,WAAW,SAAS;AACtB,gBAAQ,OAAO;AAAA,MACjB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,KAAK,CAAC;AAEf,SAAO,gBAAAC,KAAC,SAAI,KAAU;AACxB;;;AHJS,gBAAAC,YAAA;AAhBF,IAAM,OAAOC,OAAM,KAAK,CAAC,UAAqB;AACnD,QAAM,EAAE,QAAQ,aAAa,IAAI,mBAAY;AAE7C,QAAM,QAAQA,OAAM;AAAA,IAClB,CAAC,YAAyB;AACxB,aAAO,OAAO,eAAe;AAAA,QAC3B,MAAM;AAAA,QACN;AAAA,QACA,OAAO,MAAM,WACT,EAAE,WAAW,CAAC,IAAI,EAAE,YAAY,MAAM,aAAa,IAAI,MAAM,WAAW,EAAE,YAAY,CAAC,CAAC,EAAE,IAC1F;AAAA,MACN,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM,QAAQ;AAAA,EACjB;AAEA,SAAO,gBAAAD,KAAC,WAAQ,OAAc;AAChC,CAAC;;;AI3BD,OAAOE,UAAS,eAAe;;;ACA/B,SAAgB,aAAa,WAAW,gBAAgB;AACxD,OAAO,cAAc;AACrB,SAAS,cAAc;;;ACFvB,SAAS,cAAc;AAEhB,IAAM,aAAa,CAAI,SAAY;AACxC,QAAM,MAAM,OAAO,IAAI;AACvB,MAAI,UAAU;AAEd,SAAO;AACT;;;AD2DI;AAnDG,IAAM,WAAW,CAAC,EAAE,SAAS,SAAS,MAAqB;AAChE,QAAM,aAAa,WAAW,OAAO;AACrC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA6B;AACzD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,oBAAI,IAAiC,CAAC;AAE7F,QAAM,eAAe;AAAA,IACnB,CAAC,IAAiB,mBAAmC;AACnD,yBAAmB,CAAC,SAAS;AAC3B,cAAM,qBAAqB,IAAI,IAAI,IAAI;AACvC,2BAAmB,IAAI,IAAI,cAAc;AAEzC,eAAO;AAAA,MACT,CAAC;AAED,aAAO,MAAM;AACX,2BAAmB,CAAC,SAAS;AAC3B,gBAAM,qBAAqB,IAAI,IAAI,IAAI;AACvC,6BAAmB,OAAO,EAAE;AAE5B,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,CAAC,kBAAkB;AAAA,EACrB;AAEA,YAAU,MAAM;AACd,UAAM,OAAO,IAAI,OAAO,WAAW,OAAO;AAC1C,cAAU,IAAI;AAEd,WAAO,MAAM;AACX,WAAK,QAAQ;AAAA,IACf;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAEA,WAAO,iBAAiB,QAAQ,UAAU;AAC1C,WAAO,mBAAmB,QAAQ,YAAY;AAC9C,WAAO,WAAW,QAAQ,IAAI;AAC9B,WAAO,cAAc,QAAQ,OAAO;AAAA,EACtC,GAAG,CAAC,OAAO,CAAC;AAEZ,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,SACE,qBAAC,oBAAiB,OAAO,EAAE,cAAc,OAAO,GAC7C;AAAA,KAAC,GAAG,eAAe,EAAE,IAAI,CAAC,CAAC,SAAS,cAAc,MAAM;AACvD,aAAO,SAAS,aAAa,gBAAgB,OAAO;AAAA,IACtD,CAAC;AAAA,IAEA;AAAA,KACH;AAEJ;;;ADpCS,gBAAAC,YAAA;AA9BT,IAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAyB;AACvB,QAAM,EAAE,QAAQ,aAAa,IAAI,mBAAY;AAE7C,QAAM,QAAQC,OAAM;AAAA,IAClB,CAAC,YAAyB;AACxB,aAAO,OAAO,eAAe;AAAA,QAC3B,MAAM;AAAA,QACN,OAAO;AAAA,UACL;AAAA,UACA,mBAAmB,qBACf,CAAC,IAAI,EAAE,aAAa,MAAM,aAAa,IAAI,mBAAmB,EAAE,aAAa,CAAC,CAAC,IAC/E;AAAA,UACJ,WAAW,aAAa,CAAC,IAAI,EAAE,YAAY,MAAM,aAAa,IAAI,WAAW,EAAE,YAAY,CAAC,CAAC,IAAI;AAAA,UACjG;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM,oBAAoB,YAAY,qBAAqB,sBAAsB,sBAAsB;AAAA,EAC1G;AAEA,SAAO,gBAAAD,KAAC,WAAQ,OAAc;AAChC;AAEO,IAAM,QAAQC,OAAM,KAAK,CAAC,UAAsB;AACrD,QAAM,EAAE,cAAc,YAAY,MAAM,uBAAuB,cAAc,gBAAgB,YAAY,UAAU,IACjH;AAEF,QAAM,UAAU,QAAQ,MAAM;AAC5B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,EAAE,uBAAuB,cAAc,gBAAgB,YAAY,UAAU;AAAA,IACxF;AAAA,EACF,GAAG,CAAC,cAAc,YAAY,MAAM,uBAAuB,cAAc,gBAAgB,YAAY,SAAS,CAAC;AAE/G,MAAI,oBAAoB,KAAK,GAAG;AAC9B,WAAO,gBAAAD,KAAC,YAAS,SAAmB,gBAAM,UAAS;AAAA,EACrD;AAEA,QAAM,EAAE,MAAM,oBAAoB,YAAY,qBAAqB,sBAAsB,uBAAuB,IAC9G;AAEF,SACE,gBAAAA,KAAC,YAAS,SACR,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF,GACF;AAEJ,CAAC;AAED,SAAS,oBAAoB,OAA+C;AAC1E,SAAO,cAAc;AACvB;;;AG7EA,OAAOE,YAAW;AAcT,gBAAAC,YAAA;AAVF,IAAM,cAAc,MAAM;AAC/B,QAAM,EAAE,OAAO,IAAI,mBAAY;AAE/B,QAAM,QAAQC,OAAM,YAAY,CAAC,YAAyB;AACxD,WAAO,OAAO,eAAe;AAAA,MAC3B,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,SAAO,gBAAAD,KAAC,WAAQ,OAAc;AAChC;;;ACfA,OAAOE,YAAW;AAmCP,gBAAAC,YAAA;AAtBJ,IAAM,gBAAgBC,OAAM;AAAA,EACjC,CAAC,EAAE,UAAU,qBAAqB,sBAAsB,uBAAuB,MAAyB;AACtG,UAAM,EAAE,QAAQ,aAAa,IAAI,mBAAY;AAE7C,UAAM,QAAQA,OAAM;AAAA,MAClB,CAAC,YAAyB;AACxB,eAAO,OAAO,eAAe;AAAA,UAC3B,MAAM;AAAA,UACN;AAAA,UACA,OAAO,WACH;AAAA,YACE,mBAAmB,CAAC,IAAI,EAAE,aAAa,MAAM,aAAa,IAAI,WAAW,EAAE,aAAa,CAAC,CAAC;AAAA,YAC1F;AAAA,YACA;AAAA,YACA;AAAA,UACF,IACA,EAAE,qBAAqB,sBAAsB,uBAAuB;AAAA,QAC1E,CAAC;AAAA,MACH;AAAA,MACA,CAAC,UAAU,qBAAqB,sBAAsB,sBAAsB;AAAA,IAC9E;AAEA,WAAO,gBAAAD,KAAC,WAAQ,OAAc;AAAA,EAChC;AACF;","names":["React","React","jsx","jsx","React","React","jsx","React","React","jsx","React","React","jsx","React"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/Bell.tsx","../../src/utils/createContextAndHook.ts","../../src/context/RenderContext.tsx","../../src/components/Mounter.tsx","../../src/components/Inbox.tsx","../../src/components/Renderer.tsx","../../src/hooks/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx"],"sourcesContent":["import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { BellRenderer } from '../utils/types';\n\nexport type BellProps = {\n renderBell?: BellRenderer;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { renderBell } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: renderBell ? { mountBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : undefined,\n });\n },\n [renderBell]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = (props: DefaultInboxProps) => {\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n mountNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n mountBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } =\n props;\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);\n\n if (isWithChildrenProps(props)) {\n return <Renderer options={options}>{props.children}</Renderer>;\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options}>\n <DefaultInbox\n open={open}\n renderNotification={renderNotification}\n renderBell={renderBell}\n onNotificationClick={onNotificationClick}\n onPrimaryActionClick={onPrimaryActionClick}\n onSecondaryActionClick={onSecondaryActionClick}\n />\n </Renderer>\n );\n});\n\nfunction isWithChildrenProps(props: InboxProps): props is WithChildrenProps {\n return 'children' in props;\n}\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport { NovuUI } from '@novu/js/ui';\nimport type { NovuUIOptions } from '@novu/js/ui';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n}>;\n\n/**\n *\n * Renderer component that provides the NovuUI instance and mounts the elements on DOM in a portal\n */\nexport const Renderer = ({ options, children }: RendererProps) => {\n const optionsRef = useDataRef(options);\n const [novuUI, setNovuUI] = useState<NovuUI | undefined>();\n const [mountedElements, setMountedElements] = useState(new Map<HTMLElement, MountedElement>());\n\n const mountElement = useCallback(\n (el: HTMLElement, mountedElement: MountedElement) => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.set(el, mountedElement);\n\n return newMountedElements;\n });\n\n return () => {\n setMountedElements((prev) => {\n const newMountedElements = new Map(prev);\n newMountedElements.delete(el);\n\n return newMountedElements;\n });\n };\n },\n [setMountedElements]\n );\n\n useEffect(() => {\n const novu = new NovuUI(optionsRef.current);\n setNovuUI(novu);\n\n return () => {\n novu.unmount();\n };\n }, []);\n\n useEffect(() => {\n if (!novuUI) {\n return;\n }\n\n novuUI.updateAppearance(options.appearance);\n novuUI.updateLocalization(options.localization);\n novuUI.updateTabs(options.tabs);\n novuUI.updateOptions(options.options);\n }, [options]);\n\n if (!novuUI) {\n return null;\n }\n\n return (\n <RendererProvider value={{ mountElement, novuUI }}>\n {[...mountedElements].map(([element, mountedElement]) => {\n return ReactDOM.createPortal(mountedElement, element);\n })}\n\n {children}\n </RendererProvider>\n );\n};\n","import { useRef } from 'react';\n\nexport const useDataRef = <T>(data: T) => {\n const ref = useRef(data);\n ref.current = data;\n\n return ref;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\n\nexport const Preferences = () => {\n const { novuUI } = useRenderer();\n\n const mount = React.useCallback((element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Preferences',\n element,\n });\n }, []);\n\n return <Mounter mount={mount} />;\n};\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\nimport { NotificationsRenderer } from '../utils/types';\n\nexport type NotificationProps = {\n renderNotification?: NotificationsRenderer;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo((props: NotificationProps) => {\n const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: {\n mountNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n });\n },\n [renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n});\n"],"mappings":"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","names":["React","React","jsx","jsx","React","React","jsx","React","React","jsx","React","React","jsx","React"]}
|
package/dist/server/server.d.mts
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab } from '@novu/js/ui';
|
|
2
2
|
export { Notification } from '@novu/js/ui';
|
|
3
3
|
|
|
4
|
-
type
|
|
5
|
-
|
|
6
|
-
}) => React.ReactNode;
|
|
4
|
+
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
5
|
+
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
7
6
|
type DefaultInboxProps = {
|
|
8
7
|
open?: boolean;
|
|
9
|
-
renderNotification?:
|
|
10
|
-
|
|
11
|
-
}) => React.ReactNode;
|
|
12
|
-
renderBell?: ({ unreadCount }: {
|
|
13
|
-
unreadCount: number;
|
|
14
|
-
}) => React.ReactNode;
|
|
8
|
+
renderNotification?: NotificationsRenderer;
|
|
9
|
+
renderBell?: BellRenderer;
|
|
15
10
|
onNotificationClick?: NotificationClickHandler;
|
|
16
11
|
onPrimaryActionClick?: NotificationActionClickHandler;
|
|
17
12
|
onSecondaryActionClick?: NotificationActionClickHandler;
|
|
@@ -44,4 +39,4 @@ declare function Notifications(): void;
|
|
|
44
39
|
declare function Preferences(): void;
|
|
45
40
|
declare function Bell(): void;
|
|
46
41
|
|
|
47
|
-
export { type BaseProps, Bell, type DefaultInboxProps, type DefaultProps, Inbox, Notifications, type
|
|
42
|
+
export { type BaseProps, Bell, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, Notifications, type NotificationsRenderer, Preferences, type WithChildrenProps };
|
package/dist/server/server.d.ts
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab } from '@novu/js/ui';
|
|
2
2
|
export { Notification } from '@novu/js/ui';
|
|
3
3
|
|
|
4
|
-
type
|
|
5
|
-
|
|
6
|
-
}) => React.ReactNode;
|
|
4
|
+
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
5
|
+
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
7
6
|
type DefaultInboxProps = {
|
|
8
7
|
open?: boolean;
|
|
9
|
-
renderNotification?:
|
|
10
|
-
|
|
11
|
-
}) => React.ReactNode;
|
|
12
|
-
renderBell?: ({ unreadCount }: {
|
|
13
|
-
unreadCount: number;
|
|
14
|
-
}) => React.ReactNode;
|
|
8
|
+
renderNotification?: NotificationsRenderer;
|
|
9
|
+
renderBell?: BellRenderer;
|
|
15
10
|
onNotificationClick?: NotificationClickHandler;
|
|
16
11
|
onPrimaryActionClick?: NotificationActionClickHandler;
|
|
17
12
|
onSecondaryActionClick?: NotificationActionClickHandler;
|
|
@@ -44,4 +39,4 @@ declare function Notifications(): void;
|
|
|
44
39
|
declare function Preferences(): void;
|
|
45
40
|
declare function Bell(): void;
|
|
46
41
|
|
|
47
|
-
export { type BaseProps, Bell, type DefaultInboxProps, type DefaultProps, Inbox, Notifications, type
|
|
42
|
+
export { type BaseProps, Bell, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, Notifications, type NotificationsRenderer, Preferences, type WithChildrenProps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novu/react",
|
|
3
|
-
"version": "2.0.0-canary.
|
|
3
|
+
"version": "2.0.0-canary.2",
|
|
4
4
|
"repository": "https://github.com/novuhq/novu",
|
|
5
5
|
"description": "Novu's React SDK for building custom inbox notification experiences",
|
|
6
6
|
"author": "",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
".": {
|
|
17
17
|
"import": {
|
|
18
18
|
"types": "./dist/client/index.d.ts",
|
|
19
|
-
"default": "./dist/server/server.
|
|
19
|
+
"default": "./dist/server/server.mjs"
|
|
20
20
|
},
|
|
21
21
|
"require": {
|
|
22
22
|
"types": "./dist/server/server.d.ts",
|
|
@@ -65,6 +65,6 @@
|
|
|
65
65
|
"react-dom": ">=17"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@novu/js": "^2.0.0-canary.
|
|
68
|
+
"@novu/js": "^2.0.0-canary.1"
|
|
69
69
|
}
|
|
70
70
|
}
|