@novu/react 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # Novu's React SDK for building custom inbox notification experiences.
2
+
3
+ Novu provides the `@novu/react` a React library that helps to add a fully functioning Inbox to your web application in minutes. Let's do a quick recap on how you can easily use it in your application.
4
+ See full documentation [here](https://docs.novu.co/inbox/react/get-started).
5
+
6
+ ## Installation
7
+
8
+ - Install `@novu/react` npm package in your react app
9
+
10
+ ```bash
11
+ npm install @novu/react
12
+ ```
13
+
14
+ ## Getting Started
15
+
16
+ - Add the below code in the app.tsx file
17
+
18
+ ```jsx
19
+ import { Inbox } from '@novu/react';
20
+
21
+ function Novu() {
22
+ return (
23
+ <Inbox
24
+ options={{
25
+ subscriberId: 'SUBSCRIBER_ID',
26
+ applicationIdentifier: 'APPLICATION_IDENTIFIER',
27
+ }}
28
+ />
29
+ );
30
+ }
31
+ ```
32
+
33
+ ## Use your own backend and socket URL
34
+
35
+ By default, Novu's hosted services for API and socket are used. If you want, you can override them and configure your own.
36
+
37
+ ```tsx
38
+ import { Inbox } from '@novu/react';
39
+
40
+ function Novu() {
41
+ return (
42
+ <Inbox
43
+ options={{
44
+ backendUrl: 'YOUR_BACKEND_URL',
45
+ socketUrl: 'YOUR_SOCKET_URL',
46
+ subscriberId: 'SUBSCRIBER_ID',
47
+ applicationIdentifier: 'APPLICATION_IDENTIFIER',
48
+ }}
49
+ />
50
+ );
51
+ }
52
+ ```
53
+
54
+ ## Controlled Inbox
55
+
56
+ You can use the `open` prop to manage the Inbox popover open state.
57
+
58
+ ```jsx
59
+ import { Inbox } from '@novu/react';
60
+
61
+ function Novu() {
62
+ const [open, setOpen] = useState(false);
63
+
64
+ return (
65
+ <div>
66
+ <Inbox
67
+ options={{
68
+ subscriberId: 'SUBSCRIBER_ID',
69
+ applicationIdentifier: 'APPLICATION_IDENTIFIER',
70
+ }}
71
+ open={isOpen}
72
+ />
73
+ <button onClick={() => setOpen(true)}>Open Inbox</button>
74
+ <button onClick={() => setOpen(false)}>Close Inbox</button>
75
+ </div>
76
+ );
77
+ }
78
+ ```
79
+
80
+ ## Localization
81
+
82
+ You can pass the `localization` prop to the Inbox component to change the language of the Inbox.
83
+
84
+ ```jsx
85
+ import { Inbox } from '@novu/react';
86
+
87
+ function Novu() {
88
+ return (
89
+ <Inbox
90
+ options={{
91
+ subscriberId: 'SUBSCRIBER_ID',
92
+ applicationIdentifier: 'APPLICATION_IDENTIFIER',
93
+ }}
94
+ localization={{
95
+ 'inbox.status.archived': 'Archived',
96
+ 'inbox.status.unread': 'Unread',
97
+ 'inbox.status.options.archived': 'Archived',
98
+ 'inbox.status.options.unread': 'Unread',
99
+ 'inbox.status.options.unreadRead': 'Unread/Read',
100
+ 'inbox.status.unreadRead': 'Unread/Read',
101
+ 'inbox.title': 'Inbox',
102
+ 'notifications.emptyNotice': 'No notifications',
103
+ locale: 'en-US',
104
+ }}
105
+ />
106
+ );
107
+ }
108
+ ```
109
+
110
+ ## HMAC Encryption
111
+
112
+ When Novu's user adds the Inbox to their application they are required to pass a `subscriberId` which identifies the user's end-customer, and the application Identifier which is acted as a public key to communicate with the notification feed API.
113
+
114
+ A malicious actor can access the user feed by accessing the API and passing another `subscriberId` using the public application identifier.
115
+
116
+ HMAC encryption will make sure that a `subscriberId` is encrypted using the secret API key, and those will prevent malicious actors from impersonating users.
117
+
118
+ ### Enabling HMAC Encryption
119
+
120
+ In order to enable Hash-Based Message Authentication Codes, you need to visit the admin panel In-App settings page and enable HMAC encryption for your environment.
121
+
122
+ <Frame caption="How to enable HMAC encryption for In-App Inbox">
123
+ <img src="/images/notification-center/client/react/get-started/hmac-encryption-enable.png" />
124
+ </Frame>
125
+
126
+ 1. Next step would be to generate an HMAC encrypted subscriberId on your backend:
127
+
128
+ ```jsx
129
+ import { createHmac } from 'crypto';
130
+
131
+ const hmacHash = createHmac('sha256', process.env.NOVU_API_KEY).update(subscriberId).digest('hex');
132
+ ```
133
+
134
+ 2. Then pass the created HMAC to your client side application forward it to the component:
135
+
136
+ ```jsx
137
+ <Inbox
138
+ subscriberId={'SUBSCRIBER_ID_PLAIN_VALUE'}
139
+ subscriberHash={'SUBSCRIBER_ID_HASH_VALUE'}
140
+ applicationIdentifier={'APPLICATION_IDENTIFIER'}
141
+ />
142
+ ```
143
+
144
+ > Note: If HMAC encryption is active in In-App provider settings and `subscriberHash`
145
+ > along with `subscriberId` is not provided, then Inbox will not load
@@ -0,0 +1,50 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, BaseNovuUIOptions } from '@novu/js/ui';
4
+ export { Notification } from '@novu/js/ui';
5
+
6
+ type BellRenderProps = ({ unreadCount }: {
7
+ unreadCount: number;
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;
17
+ type DefaultInboxProps = {
18
+ open?: boolean;
19
+ renderNotification?: (args: {
20
+ notification: Notification;
21
+ }) => React.ReactNode;
22
+ renderBell?: ({ unreadCount }: {
23
+ unreadCount: number;
24
+ }) => React.ReactNode;
25
+ onNotificationClick?: NotificationClickHandler;
26
+ onPrimaryActionClick?: NotificationActionClickHandler;
27
+ onSecondaryActionClick?: NotificationActionClickHandler;
28
+ };
29
+ type BaseProps = BaseNovuUIOptions;
30
+ type DefaultProps = BaseProps & DefaultInboxProps & {
31
+ children?: never;
32
+ };
33
+ type WithChildrenProps = BaseProps & {
34
+ children: React.ReactNode;
35
+ };
36
+
37
+ type InboxProps = DefaultProps | WithChildrenProps;
38
+ declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
39
+
40
+ declare const Preferences: () => react_jsx_runtime.JSX.Element;
41
+
42
+ type NotificationProps = {
43
+ children?: never | NotificationsRenderProps;
44
+ onNotificationClick?: NotificationClickHandler;
45
+ onPrimaryActionClick?: NotificationActionClickHandler;
46
+ onSecondaryActionClick?: NotificationActionClickHandler;
47
+ };
48
+ declare const Notifications: React$1.MemoExoticComponent<({ children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }: NotificationProps) => react_jsx_runtime.JSX.Element>;
49
+
50
+ export { type BaseProps, Bell, type BellProps, type BellRenderProps, type DefaultInboxProps, type DefaultProps, Inbox, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderProps, Preferences, type WithChildrenProps };
@@ -0,0 +1,50 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, BaseNovuUIOptions } from '@novu/js/ui';
4
+ export { Notification } from '@novu/js/ui';
5
+
6
+ type BellRenderProps = ({ unreadCount }: {
7
+ unreadCount: number;
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;
17
+ type DefaultInboxProps = {
18
+ open?: boolean;
19
+ renderNotification?: (args: {
20
+ notification: Notification;
21
+ }) => React.ReactNode;
22
+ renderBell?: ({ unreadCount }: {
23
+ unreadCount: number;
24
+ }) => React.ReactNode;
25
+ onNotificationClick?: NotificationClickHandler;
26
+ onPrimaryActionClick?: NotificationActionClickHandler;
27
+ onSecondaryActionClick?: NotificationActionClickHandler;
28
+ };
29
+ type BaseProps = BaseNovuUIOptions;
30
+ type DefaultProps = BaseProps & DefaultInboxProps & {
31
+ children?: never;
32
+ };
33
+ type WithChildrenProps = BaseProps & {
34
+ children: React.ReactNode;
35
+ };
36
+
37
+ type InboxProps = DefaultProps | WithChildrenProps;
38
+ declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
39
+
40
+ declare const Preferences: () => react_jsx_runtime.JSX.Element;
41
+
42
+ type NotificationProps = {
43
+ children?: never | NotificationsRenderProps;
44
+ onNotificationClick?: NotificationClickHandler;
45
+ onPrimaryActionClick?: NotificationActionClickHandler;
46
+ onSecondaryActionClick?: NotificationActionClickHandler;
47
+ };
48
+ declare const Notifications: React$1.MemoExoticComponent<({ children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }: NotificationProps) => react_jsx_runtime.JSX.Element>;
49
+
50
+ export { type BaseProps, Bell, type BellProps, type BellRenderProps, type DefaultInboxProps, type DefaultProps, Inbox, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderProps, Preferences, type WithChildrenProps };
@@ -0,0 +1,244 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/components/Bell.tsx
2
+ var _react = require('react'); var _react2 = _interopRequireDefault(_react);
3
+
4
+ // src/utils/createContextAndHook.ts
5
+
6
+ function assertContextExists(contextVal, msgOrCtx) {
7
+ if (!contextVal) {
8
+ throw typeof msgOrCtx === "string" ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);
9
+ }
10
+ }
11
+ var createContextAndHook = (displayName, options) => {
12
+ const { assertCtxFn = assertContextExists } = options || {};
13
+ const Ctx = _react2.default.createContext(void 0);
14
+ Ctx.displayName = displayName;
15
+ const useCtx = () => {
16
+ const ctx = _react2.default.useContext(Ctx);
17
+ assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);
18
+ return ctx.value;
19
+ };
20
+ const useCtxWithoutGuarantee = () => {
21
+ const ctx = _react2.default.useContext(Ctx);
22
+ return ctx ? ctx.value : {};
23
+ };
24
+ return [Ctx, useCtx, useCtxWithoutGuarantee];
25
+ };
26
+
27
+ // src/context/RenderContext.tsx
28
+ var _jsxruntime = require('react/jsx-runtime');
29
+ var [RendererContext, useRendererContext] = createContextAndHook("RendererContext");
30
+ var RendererProvider = (props) => {
31
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RendererContext.Provider, { value: { value: props.value }, children: props.children });
32
+ };
33
+
34
+ // src/components/Mounter.tsx
35
+
36
+
37
+ function Mounter({ mount }) {
38
+ const ref = _react2.default.useRef(null);
39
+ _react2.default.useEffect(() => {
40
+ let unmount;
41
+ const element = ref.current;
42
+ if (element && mount) {
43
+ const possibleUnmount = mount(element);
44
+ if (possibleUnmount) {
45
+ unmount = possibleUnmount;
46
+ }
47
+ }
48
+ return () => {
49
+ if (element && unmount) {
50
+ unmount(element);
51
+ }
52
+ };
53
+ }, [ref, mount]);
54
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref });
55
+ }
56
+
57
+ // src/components/Bell.tsx
58
+
59
+ var Bell = _react2.default.memo((props) => {
60
+ const { novuUI, mountElement } = useRendererContext();
61
+ const mount = _react2.default.useCallback(
62
+ (element) => {
63
+ return novuUI.mountComponent({
64
+ name: "Bell",
65
+ element,
66
+ props: props.children ? { mountBell: (el, { unreadCount }) => mountElement(el, _optionalChain([props, 'access', _ => _.children, 'optionalCall', _2 => _2({ unreadCount })])) } : void 0
67
+ });
68
+ },
69
+ [props.children]
70
+ );
71
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Mounter, { mount });
72
+ });
73
+
74
+ // src/components/Inbox.tsx
75
+
76
+
77
+ // src/components/Renderer.tsx
78
+
79
+ var _reactdom = require('react-dom'); var _reactdom2 = _interopRequireDefault(_reactdom);
80
+ var _ui = require('@novu/js/ui');
81
+
82
+ // src/hooks/useDataRef.ts
83
+
84
+ var useDataRef = (data) => {
85
+ const ref = _react.useRef.call(void 0, data);
86
+ ref.current = data;
87
+ return ref;
88
+ };
89
+
90
+ // src/components/Renderer.tsx
91
+
92
+ var Renderer = ({ options, children }) => {
93
+ const optionsRef = useDataRef(options);
94
+ const [novuUI, setNovuUI] = _react.useState.call(void 0, );
95
+ const [mountedElements, setMountedElements] = _react.useState.call(void 0, /* @__PURE__ */ new Map());
96
+ const mountElement = _react.useCallback.call(void 0,
97
+ (el, mountedElement) => {
98
+ setMountedElements((prev) => {
99
+ const newMountedElements = new Map(prev);
100
+ newMountedElements.set(el, mountedElement);
101
+ return newMountedElements;
102
+ });
103
+ return () => {
104
+ setMountedElements((prev) => {
105
+ const newMountedElements = new Map(prev);
106
+ newMountedElements.delete(el);
107
+ return newMountedElements;
108
+ });
109
+ };
110
+ },
111
+ [setMountedElements]
112
+ );
113
+ _react.useEffect.call(void 0, () => {
114
+ const novu = new (0, _ui.NovuUI)(optionsRef.current);
115
+ setNovuUI(novu);
116
+ return () => {
117
+ novu.unmount();
118
+ };
119
+ }, []);
120
+ _react.useEffect.call(void 0, () => {
121
+ if (!novuUI) {
122
+ return;
123
+ }
124
+ novuUI.updateAppearance(options.appearance);
125
+ novuUI.updateLocalization(options.localization);
126
+ novuUI.updateTabs(options.tabs);
127
+ novuUI.updateOptions(options.options);
128
+ }, [options]);
129
+ if (!novuUI) {
130
+ return null;
131
+ }
132
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, RendererProvider, { value: { mountElement, novuUI }, children: [
133
+ [...mountedElements].map(([element, mountedElement]) => {
134
+ return _reactdom2.default.createPortal(mountedElement, element);
135
+ }),
136
+ children
137
+ ] });
138
+ };
139
+
140
+ // src/components/Inbox.tsx
141
+
142
+ var DefaultInbox = ({
143
+ open,
144
+ renderNotification,
145
+ renderBell,
146
+ onNotificationClick,
147
+ onPrimaryActionClick,
148
+ onSecondaryActionClick
149
+ }) => {
150
+ const { novuUI, mountElement } = useRendererContext();
151
+ const mount = _react2.default.useCallback(
152
+ (element) => {
153
+ return novuUI.mountComponent({
154
+ name: "Inbox",
155
+ props: {
156
+ open,
157
+ mountNotification: renderNotification ? (el, { notification }) => mountElement(el, renderNotification({ notification })) : void 0,
158
+ mountBell: renderBell ? (el, { unreadCount }) => mountElement(el, renderBell({ unreadCount })) : void 0,
159
+ onNotificationClick,
160
+ onPrimaryActionClick,
161
+ onSecondaryActionClick
162
+ },
163
+ element
164
+ });
165
+ },
166
+ [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
167
+ );
168
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Mounter, { mount });
169
+ };
170
+ var Inbox = _react2.default.memo((props) => {
171
+ if (isWithChildrenProps(props)) {
172
+ const { children, ...options2 } = props;
173
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Renderer, { options: options2, children });
174
+ }
175
+ const {
176
+ open,
177
+ renderNotification,
178
+ renderBell,
179
+ onNotificationClick,
180
+ onPrimaryActionClick,
181
+ onSecondaryActionClick,
182
+ ...options
183
+ } = props;
184
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Renderer, { options, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
185
+ DefaultInbox,
186
+ {
187
+ open,
188
+ renderNotification,
189
+ renderBell,
190
+ onNotificationClick,
191
+ onPrimaryActionClick,
192
+ onSecondaryActionClick
193
+ }
194
+ ) });
195
+ });
196
+ function isWithChildrenProps(props) {
197
+ return "children" in props;
198
+ }
199
+
200
+ // src/components/Preferences.tsx
201
+
202
+
203
+ var Preferences = () => {
204
+ const { novuUI } = useRendererContext();
205
+ const mount = _react2.default.useCallback((element) => {
206
+ return novuUI.mountComponent({
207
+ name: "Preferences",
208
+ element
209
+ });
210
+ }, []);
211
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Mounter, { mount });
212
+ };
213
+
214
+ // src/components/Notifications.tsx
215
+
216
+
217
+ var Notifications = _react2.default.memo(
218
+ ({ children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }) => {
219
+ const { novuUI, mountElement } = useRendererContext();
220
+ const mount = _react2.default.useCallback(
221
+ (element) => {
222
+ return novuUI.mountComponent({
223
+ name: "Notifications",
224
+ element,
225
+ props: children ? {
226
+ mountNotification: (el, { notification }) => mountElement(el, _optionalChain([children, 'optionalCall', _3 => _3({ notification })])),
227
+ onNotificationClick,
228
+ onPrimaryActionClick,
229
+ onSecondaryActionClick
230
+ } : { onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }
231
+ });
232
+ },
233
+ [children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
234
+ );
235
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Mounter, { mount });
236
+ }
237
+ );
238
+
239
+
240
+
241
+
242
+
243
+ exports.Bell = Bell; exports.Inbox = Inbox; exports.Notifications = Notifications; exports.Preferences = Preferences;
244
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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 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 if (isWithChildrenProps(props)) {\n const { children, ...options } = props;\n\n return <Renderer options={options}>{children}</Renderer>;\n }\n\n const {\n open,\n renderNotification,\n renderBell,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n ...options\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"]}
@@ -0,0 +1,244 @@
1
+ // src/components/Bell.tsx
2
+ import React3 from "react";
3
+
4
+ // src/utils/createContextAndHook.ts
5
+ import React from "react";
6
+ function assertContextExists(contextVal, msgOrCtx) {
7
+ if (!contextVal) {
8
+ throw typeof msgOrCtx === "string" ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);
9
+ }
10
+ }
11
+ var createContextAndHook = (displayName, options) => {
12
+ const { assertCtxFn = assertContextExists } = options || {};
13
+ const Ctx = React.createContext(void 0);
14
+ Ctx.displayName = displayName;
15
+ const useCtx = () => {
16
+ const ctx = React.useContext(Ctx);
17
+ assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);
18
+ return ctx.value;
19
+ };
20
+ const useCtxWithoutGuarantee = () => {
21
+ const ctx = React.useContext(Ctx);
22
+ return ctx ? ctx.value : {};
23
+ };
24
+ return [Ctx, useCtx, useCtxWithoutGuarantee];
25
+ };
26
+
27
+ // src/context/RenderContext.tsx
28
+ import { jsx } from "react/jsx-runtime";
29
+ var [RendererContext, useRendererContext] = createContextAndHook("RendererContext");
30
+ var RendererProvider = (props) => {
31
+ return /* @__PURE__ */ jsx(RendererContext.Provider, { value: { value: props.value }, children: props.children });
32
+ };
33
+
34
+ // src/components/Mounter.tsx
35
+ import React2 from "react";
36
+ import { jsx as jsx2 } from "react/jsx-runtime";
37
+ function Mounter({ mount }) {
38
+ const ref = React2.useRef(null);
39
+ React2.useEffect(() => {
40
+ let unmount;
41
+ const element = ref.current;
42
+ if (element && mount) {
43
+ const possibleUnmount = mount(element);
44
+ if (possibleUnmount) {
45
+ unmount = possibleUnmount;
46
+ }
47
+ }
48
+ return () => {
49
+ if (element && unmount) {
50
+ unmount(element);
51
+ }
52
+ };
53
+ }, [ref, mount]);
54
+ return /* @__PURE__ */ jsx2("div", { ref });
55
+ }
56
+
57
+ // src/components/Bell.tsx
58
+ import { jsx as jsx3 } from "react/jsx-runtime";
59
+ var Bell = React3.memo((props) => {
60
+ const { novuUI, mountElement } = useRendererContext();
61
+ const mount = React3.useCallback(
62
+ (element) => {
63
+ return novuUI.mountComponent({
64
+ name: "Bell",
65
+ element,
66
+ props: props.children ? { mountBell: (el, { unreadCount }) => mountElement(el, props.children?.({ unreadCount })) } : void 0
67
+ });
68
+ },
69
+ [props.children]
70
+ );
71
+ return /* @__PURE__ */ jsx3(Mounter, { mount });
72
+ });
73
+
74
+ // src/components/Inbox.tsx
75
+ import React5 from "react";
76
+
77
+ // src/components/Renderer.tsx
78
+ import { useCallback, useEffect, useState } from "react";
79
+ import ReactDOM from "react-dom";
80
+ import { NovuUI } from "@novu/js/ui";
81
+
82
+ // src/hooks/useDataRef.ts
83
+ import { useRef } from "react";
84
+ var useDataRef = (data) => {
85
+ const ref = useRef(data);
86
+ ref.current = data;
87
+ return ref;
88
+ };
89
+
90
+ // src/components/Renderer.tsx
91
+ import { jsxs } from "react/jsx-runtime";
92
+ var Renderer = ({ options, children }) => {
93
+ const optionsRef = useDataRef(options);
94
+ const [novuUI, setNovuUI] = useState();
95
+ const [mountedElements, setMountedElements] = useState(/* @__PURE__ */ new Map());
96
+ const mountElement = useCallback(
97
+ (el, mountedElement) => {
98
+ setMountedElements((prev) => {
99
+ const newMountedElements = new Map(prev);
100
+ newMountedElements.set(el, mountedElement);
101
+ return newMountedElements;
102
+ });
103
+ return () => {
104
+ setMountedElements((prev) => {
105
+ const newMountedElements = new Map(prev);
106
+ newMountedElements.delete(el);
107
+ return newMountedElements;
108
+ });
109
+ };
110
+ },
111
+ [setMountedElements]
112
+ );
113
+ useEffect(() => {
114
+ const novu = new NovuUI(optionsRef.current);
115
+ setNovuUI(novu);
116
+ return () => {
117
+ novu.unmount();
118
+ };
119
+ }, []);
120
+ useEffect(() => {
121
+ if (!novuUI) {
122
+ return;
123
+ }
124
+ novuUI.updateAppearance(options.appearance);
125
+ novuUI.updateLocalization(options.localization);
126
+ novuUI.updateTabs(options.tabs);
127
+ novuUI.updateOptions(options.options);
128
+ }, [options]);
129
+ if (!novuUI) {
130
+ return null;
131
+ }
132
+ return /* @__PURE__ */ jsxs(RendererProvider, { value: { mountElement, novuUI }, children: [
133
+ [...mountedElements].map(([element, mountedElement]) => {
134
+ return ReactDOM.createPortal(mountedElement, element);
135
+ }),
136
+ children
137
+ ] });
138
+ };
139
+
140
+ // src/components/Inbox.tsx
141
+ import { jsx as jsx4 } from "react/jsx-runtime";
142
+ var DefaultInbox = ({
143
+ open,
144
+ renderNotification,
145
+ renderBell,
146
+ onNotificationClick,
147
+ onPrimaryActionClick,
148
+ onSecondaryActionClick
149
+ }) => {
150
+ const { novuUI, mountElement } = useRendererContext();
151
+ const mount = React5.useCallback(
152
+ (element) => {
153
+ return novuUI.mountComponent({
154
+ name: "Inbox",
155
+ props: {
156
+ open,
157
+ mountNotification: renderNotification ? (el, { notification }) => mountElement(el, renderNotification({ notification })) : void 0,
158
+ mountBell: renderBell ? (el, { unreadCount }) => mountElement(el, renderBell({ unreadCount })) : void 0,
159
+ onNotificationClick,
160
+ onPrimaryActionClick,
161
+ onSecondaryActionClick
162
+ },
163
+ element
164
+ });
165
+ },
166
+ [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
167
+ );
168
+ return /* @__PURE__ */ jsx4(Mounter, { mount });
169
+ };
170
+ var Inbox = React5.memo((props) => {
171
+ if (isWithChildrenProps(props)) {
172
+ const { children, ...options2 } = props;
173
+ return /* @__PURE__ */ jsx4(Renderer, { options: options2, children });
174
+ }
175
+ const {
176
+ open,
177
+ renderNotification,
178
+ renderBell,
179
+ onNotificationClick,
180
+ onPrimaryActionClick,
181
+ onSecondaryActionClick,
182
+ ...options
183
+ } = props;
184
+ return /* @__PURE__ */ jsx4(Renderer, { options, children: /* @__PURE__ */ jsx4(
185
+ DefaultInbox,
186
+ {
187
+ open,
188
+ renderNotification,
189
+ renderBell,
190
+ onNotificationClick,
191
+ onPrimaryActionClick,
192
+ onSecondaryActionClick
193
+ }
194
+ ) });
195
+ });
196
+ function isWithChildrenProps(props) {
197
+ return "children" in props;
198
+ }
199
+
200
+ // src/components/Preferences.tsx
201
+ import React6 from "react";
202
+ import { jsx as jsx5 } from "react/jsx-runtime";
203
+ var Preferences = () => {
204
+ const { novuUI } = useRendererContext();
205
+ const mount = React6.useCallback((element) => {
206
+ return novuUI.mountComponent({
207
+ name: "Preferences",
208
+ element
209
+ });
210
+ }, []);
211
+ return /* @__PURE__ */ jsx5(Mounter, { mount });
212
+ };
213
+
214
+ // src/components/Notifications.tsx
215
+ import React7 from "react";
216
+ import { jsx as jsx6 } from "react/jsx-runtime";
217
+ var Notifications = React7.memo(
218
+ ({ children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }) => {
219
+ const { novuUI, mountElement } = useRendererContext();
220
+ const mount = React7.useCallback(
221
+ (element) => {
222
+ return novuUI.mountComponent({
223
+ name: "Notifications",
224
+ element,
225
+ props: children ? {
226
+ mountNotification: (el, { notification }) => mountElement(el, children?.({ notification })),
227
+ onNotificationClick,
228
+ onPrimaryActionClick,
229
+ onSecondaryActionClick
230
+ } : { onNotificationClick, onPrimaryActionClick, onSecondaryActionClick }
231
+ });
232
+ },
233
+ [children, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]
234
+ );
235
+ return /* @__PURE__ */ jsx6(Mounter, { mount });
236
+ }
237
+ );
238
+ export {
239
+ Bell,
240
+ Inbox,
241
+ Notifications,
242
+ Preferences
243
+ };
244
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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 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 if (isWithChildrenProps(props)) {\n const { children, ...options } = props;\n\n return <Renderer options={options}>{children}</Renderer>;\n }\n\n const {\n open,\n renderNotification,\n renderBell,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n ...options\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":"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","names":["React","React","jsx","jsx","React","React","jsx","React","options","React","jsx","React","React","jsx","React"]}
@@ -0,0 +1,38 @@
1
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, BaseNovuUIOptions } from '@novu/js/ui';
2
+ export { Notification } from '@novu/js/ui';
3
+
4
+ type NotificationsRenderProps = (args: {
5
+ notification: Notification;
6
+ }) => React.ReactNode;
7
+ type DefaultInboxProps = {
8
+ open?: boolean;
9
+ renderNotification?: (args: {
10
+ notification: Notification;
11
+ }) => React.ReactNode;
12
+ renderBell?: ({ unreadCount }: {
13
+ unreadCount: number;
14
+ }) => React.ReactNode;
15
+ onNotificationClick?: NotificationClickHandler;
16
+ onPrimaryActionClick?: NotificationActionClickHandler;
17
+ onSecondaryActionClick?: NotificationActionClickHandler;
18
+ };
19
+ type BaseProps = BaseNovuUIOptions;
20
+ type DefaultProps = BaseProps & DefaultInboxProps & {
21
+ children?: never;
22
+ };
23
+ type WithChildrenProps = BaseProps & {
24
+ children: React.ReactNode;
25
+ };
26
+
27
+ /**
28
+ * Exporting all components from the components folder
29
+ * as empty functions to fix build errors in SSR
30
+ * This will be replaced with actual components
31
+ * when we implement the SSR components in @novu/js/ui
32
+ */
33
+ declare function Inbox(): void;
34
+ declare function Notifications(): void;
35
+ declare function Preferences(): void;
36
+ declare function Bell(): void;
37
+
38
+ export { type BaseProps, Bell, type DefaultInboxProps, type DefaultProps, Inbox, Notifications, type NotificationsRenderProps, Preferences, type WithChildrenProps };
@@ -0,0 +1,38 @@
1
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, BaseNovuUIOptions } from '@novu/js/ui';
2
+ export { Notification } from '@novu/js/ui';
3
+
4
+ type NotificationsRenderProps = (args: {
5
+ notification: Notification;
6
+ }) => React.ReactNode;
7
+ type DefaultInboxProps = {
8
+ open?: boolean;
9
+ renderNotification?: (args: {
10
+ notification: Notification;
11
+ }) => React.ReactNode;
12
+ renderBell?: ({ unreadCount }: {
13
+ unreadCount: number;
14
+ }) => React.ReactNode;
15
+ onNotificationClick?: NotificationClickHandler;
16
+ onPrimaryActionClick?: NotificationActionClickHandler;
17
+ onSecondaryActionClick?: NotificationActionClickHandler;
18
+ };
19
+ type BaseProps = BaseNovuUIOptions;
20
+ type DefaultProps = BaseProps & DefaultInboxProps & {
21
+ children?: never;
22
+ };
23
+ type WithChildrenProps = BaseProps & {
24
+ children: React.ReactNode;
25
+ };
26
+
27
+ /**
28
+ * Exporting all components from the components folder
29
+ * as empty functions to fix build errors in SSR
30
+ * This will be replaced with actual components
31
+ * when we implement the SSR components in @novu/js/ui
32
+ */
33
+ declare function Inbox(): void;
34
+ declare function Notifications(): void;
35
+ declare function Preferences(): void;
36
+ declare function Bell(): void;
37
+
38
+ export { type BaseProps, Bell, type DefaultInboxProps, type DefaultProps, Inbox, Notifications, type NotificationsRenderProps, Preferences, type WithChildrenProps };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/server.ts
21
+ var server_exports = {};
22
+ __export(server_exports, {
23
+ Bell: () => Bell,
24
+ Inbox: () => Inbox,
25
+ Notifications: () => Notifications,
26
+ Preferences: () => Preferences
27
+ });
28
+ module.exports = __toCommonJS(server_exports);
29
+ function Inbox() {
30
+ }
31
+ function Notifications() {
32
+ }
33
+ function Preferences() {
34
+ }
35
+ function Bell() {
36
+ }
37
+ // Annotate the CommonJS export names for ESM import in node:
38
+ 0 && (module.exports = {
39
+ Bell,
40
+ Inbox,
41
+ Notifications,
42
+ Preferences
43
+ });
44
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server.ts"],"sourcesContent":["export * from './utils/types';\n/**\n * Exporting all components from the components folder\n * as empty functions to fix build errors in SSR\n * This will be replaced with actual components\n * when we implement the SSR components in @novu/js/ui\n */\nexport function Inbox() {}\nexport function Notifications() {}\nexport function Preferences() {}\nexport function Bell() {}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,QAAQ;AAAC;AAClB,SAAS,gBAAgB;AAAC;AAC1B,SAAS,cAAc;AAAC;AACxB,SAAS,OAAO;AAAC;","names":[]}
@@ -0,0 +1,16 @@
1
+ // src/server.ts
2
+ function Inbox() {
3
+ }
4
+ function Notifications() {
5
+ }
6
+ function Preferences() {
7
+ }
8
+ function Bell() {
9
+ }
10
+ export {
11
+ Bell,
12
+ Inbox,
13
+ Notifications,
14
+ Preferences
15
+ };
16
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server.ts"],"sourcesContent":["export * from './utils/types';\n/**\n * Exporting all components from the components folder\n * as empty functions to fix build errors in SSR\n * This will be replaced with actual components\n * when we implement the SSR components in @novu/js/ui\n */\nexport function Inbox() {}\nexport function Notifications() {}\nexport function Preferences() {}\nexport function Bell() {}\n"],"mappings":";AAOO,SAAS,QAAQ;AAAC;AAClB,SAAS,gBAAgB;AAAC;AAC1B,SAAS,cAAc;AAAC;AACxB,SAAS,OAAO;AAAC;","names":[]}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@novu/react",
3
+ "version": "2.0.0-alpha.0",
4
+ "repository": "https://github.com/novuhq/novu",
5
+ "description": "Novu's React SDK for building custom inbox notification experiences",
6
+ "author": "",
7
+ "license": "ISC",
8
+ "main": "dist/server/server.js",
9
+ "module": "dist/client/index.mjs",
10
+ "types": "dist/client/index.d.ts",
11
+ "browser": {
12
+ "./dist/server/server.js": "./dist/client/index.js",
13
+ "./dist/server/server.mjs": "./dist/client/index.mjs"
14
+ },
15
+ "exports": {
16
+ ".": {
17
+ "import": {
18
+ "types": "./dist/client/index.d.ts",
19
+ "default": "./dist/server/server.js"
20
+ },
21
+ "require": {
22
+ "types": "./dist/server/server.d.ts",
23
+ "default": "./dist/server/server.js"
24
+ }
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "dist/client/**/*",
30
+ "dist/server/**/*"
31
+ ],
32
+ "sideEffects": false,
33
+ "private": false,
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "scripts": {
38
+ "build:watch": "tsup --watch",
39
+ "build": "tsup",
40
+ "lint": "eslint --ext .ts,.tsx src"
41
+ },
42
+ "browserslist": {
43
+ "production": [
44
+ ">0.2%",
45
+ "not dead",
46
+ "not op_mini all"
47
+ ],
48
+ "development": [
49
+ "last 1 chrome version",
50
+ "last 1 firefox version",
51
+ "last 1 safari version"
52
+ ]
53
+ },
54
+ "devDependencies": {
55
+ "@types/node": "^20.14.12",
56
+ "@types/react": "^18.3.3",
57
+ "@types/react-dom": "^18.3.0",
58
+ "react": "^18.3.1",
59
+ "react-dom": "^18.3.1",
60
+ "tsup": "^8.2.1",
61
+ "typescript": "4.9.5"
62
+ },
63
+ "peerDependencies": {
64
+ "react": ">=17",
65
+ "react-dom": ">=17"
66
+ },
67
+ "dependencies": {
68
+ "@novu/js": "^2.0.0-alpha.0"
69
+ }
70
+ }