@novu/react 3.7.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/Bell.cjs +2 -2
- package/dist/cjs/components/Bell.cjs.map +1 -1
- package/dist/cjs/components/Bell.d.cts +1 -1
- package/dist/cjs/components/Inbox.cjs +2 -2
- package/dist/cjs/components/Inbox.cjs.map +1 -1
- package/dist/cjs/components/Inbox.d.cts +1 -1
- package/dist/cjs/components/InboxContent.cjs +2 -2
- package/dist/cjs/components/InboxContent.cjs.map +1 -1
- package/dist/cjs/components/InboxContent.d.cts +1 -1
- package/dist/cjs/components/Notifications.cjs +2 -2
- package/dist/cjs/components/Notifications.cjs.map +1 -1
- package/dist/cjs/components/Notifications.d.cts +1 -1
- package/dist/cjs/components/NovuUI.cjs +1 -1
- package/dist/cjs/components/NovuUI.cjs.map +1 -1
- package/dist/cjs/components/Preferences.cjs +1 -1
- package/dist/cjs/components/Preferences.cjs.map +1 -1
- package/dist/cjs/components/index.cjs +6 -6
- package/dist/cjs/components/index.cjs.map +1 -1
- package/dist/cjs/components/index.d.cts +5 -5
- package/dist/cjs/context/NovuUIContext.cjs.map +1 -1
- package/dist/cjs/context/NovuUIContext.d.cts +1 -1
- package/dist/cjs/hooks/NovuProvider.cjs +1 -1
- package/dist/cjs/hooks/NovuProvider.cjs.map +1 -1
- package/dist/cjs/hooks/index.cjs +4 -4
- package/dist/cjs/hooks/index.cjs.map +1 -1
- package/dist/cjs/hooks/index.d.cts +3 -3
- package/dist/cjs/hooks/internal/useWebsocketEvent.cjs +1 -1
- package/dist/cjs/hooks/internal/useWebsocketEvent.cjs.map +1 -1
- package/dist/cjs/hooks/useCounts.cjs +13 -9
- package/dist/cjs/hooks/useCounts.cjs.map +1 -1
- package/dist/cjs/hooks/useNotifications.cjs +61 -48
- package/dist/cjs/hooks/useNotifications.cjs.map +1 -1
- package/dist/cjs/hooks/useNotifications.d.cts +1 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +5 -5
- package/dist/cjs/server/index.cjs.map +1 -1
- package/dist/cjs/server/index.d.cts +4 -4
- package/dist/cjs/utils/appearance.cjs.map +1 -1
- package/dist/cjs/utils/appearance.d.cts +3 -3
- package/dist/cjs/utils/types.cjs.map +1 -1
- package/dist/cjs/utils/types.d.cts +1 -1
- package/dist/esm/components/Bell.d.ts +1 -1
- package/dist/esm/components/Bell.js +2 -2
- package/dist/esm/components/Bell.js.map +1 -1
- package/dist/esm/components/Inbox.d.ts +1 -1
- package/dist/esm/components/Inbox.js +2 -2
- package/dist/esm/components/Inbox.js.map +1 -1
- package/dist/esm/components/InboxContent.d.ts +1 -1
- package/dist/esm/components/InboxContent.js +2 -2
- package/dist/esm/components/InboxContent.js.map +1 -1
- package/dist/esm/components/Notifications.d.ts +1 -1
- package/dist/esm/components/Notifications.js +2 -2
- package/dist/esm/components/Notifications.js.map +1 -1
- package/dist/esm/components/NovuUI.js +1 -1
- package/dist/esm/components/NovuUI.js.map +1 -1
- package/dist/esm/components/Preferences.js +1 -1
- package/dist/esm/components/Preferences.js.map +1 -1
- package/dist/esm/components/index.d.ts +5 -5
- package/dist/esm/components/index.js +3 -3
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/context/NovuUIContext.d.ts +1 -1
- package/dist/esm/context/NovuUIContext.js.map +1 -1
- package/dist/esm/hooks/NovuProvider.js +2 -2
- package/dist/esm/hooks/NovuProvider.js.map +1 -1
- package/dist/esm/hooks/index.d.ts +3 -3
- package/dist/esm/hooks/index.js +2 -2
- package/dist/esm/hooks/index.js.map +1 -1
- package/dist/esm/hooks/internal/useWebsocketEvent.js +1 -1
- package/dist/esm/hooks/internal/useWebsocketEvent.js.map +1 -1
- package/dist/esm/hooks/useCounts.js +13 -9
- package/dist/esm/hooks/useCounts.js.map +1 -1
- package/dist/esm/hooks/useNotifications.d.ts +1 -2
- package/dist/esm/hooks/useNotifications.js +62 -49
- package/dist/esm/hooks/useNotifications.js.map +1 -1
- package/dist/esm/index.d.ts +5 -5
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server/index.d.ts +4 -4
- package/dist/esm/server/index.js.map +1 -1
- package/dist/esm/utils/appearance.d.ts +3 -3
- package/dist/esm/utils/appearance.js.map +1 -1
- package/dist/esm/utils/types.d.ts +1 -1
- package/package.json +3 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
export { InternalNovuProvider, NovuProvider, NovuProviderProps, useNovu, useUnsafeNovu } from '../hooks/NovuProvider.js';
|
|
1
2
|
export { Bell, BellProps } from './Bell.js';
|
|
2
3
|
export { Inbox, InboxProps } from './Inbox.js';
|
|
3
|
-
export { Preferences } from './Preferences.js';
|
|
4
|
-
export { NotificationProps, Notifications } from './Notifications.js';
|
|
5
4
|
export { InboxContent, InboxContentProps } from './InboxContent.js';
|
|
6
|
-
export {
|
|
5
|
+
export { NotificationProps, Notifications } from './Notifications.js';
|
|
6
|
+
export { Preferences } from './Preferences.js';
|
|
7
|
+
import 'react/jsx-runtime';
|
|
8
|
+
import '@novu/js';
|
|
7
9
|
import 'react';
|
|
8
10
|
import '../utils/types.js';
|
|
9
11
|
import '@novu/js/ui';
|
|
10
|
-
import '@novu/js';
|
|
11
|
-
import 'react/jsx-runtime';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/components/index.ts
|
|
2
|
+
export * from "../hooks/NovuProvider.js";
|
|
2
3
|
export * from "./Bell.js";
|
|
3
4
|
export * from "./Inbox.js";
|
|
4
|
-
export * from "./Preferences.js";
|
|
5
|
-
export * from "./Notifications.js";
|
|
6
5
|
export * from "./InboxContent.js";
|
|
7
|
-
export * from "
|
|
6
|
+
export * from "./Notifications.js";
|
|
7
|
+
export * from "./Preferences.js";
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/index.ts"],"sourcesContent":["export * from '
|
|
1
|
+
{"version":3,"sources":["../../../src/components/index.ts"],"sourcesContent":["export * from '../hooks/NovuProvider';\nexport * from './Bell';\nexport * from './Inbox';\nexport * from './InboxContent';\nexport * from './Notifications';\nexport * from './Preferences';\n"],"mappings":";AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/context/NovuUIContext.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/context/NovuUIContext.tsx"],"sourcesContent":["import type { NovuUI } from '@novu/js/ui';\nimport React from 'react';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\ntype NovuUIContextValue = {\n novuUI: NovuUI;\n};\n\nconst [NovuUIContext, useNovuUIContext, useUnsafeNovuUIContext] =\n createContextAndHook<NovuUIContextValue>('NovuUIContext');\n\nconst NovuUIProvider = (props: React.PropsWithChildren<{ value: NovuUIContextValue }>) => {\n return <NovuUIContext.Provider value={{ value: props.value }}>{props.children}</NovuUIContext.Provider>;\n};\n\nexport { useNovuUIContext as useNovuUI, useUnsafeNovuUIContext as useUnsafeNovuUI, NovuUIProvider };\n"],"mappings":";AAEA,SAAS,4BAA4B;AAU5B;AAJT,IAAM,CAAC,eAAe,kBAAkB,sBAAsB,IAC5D,qBAAyC,eAAe;AAE1D,IAAM,iBAAiB,CAAC,UAAkE;AACxF,SAAO,oBAAC,cAAc,UAAd,EAAuB,OAAO,EAAE,OAAO,MAAM,MAAM,GAAI,gBAAM,UAAS;AAChF;","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/hooks/NovuProvider.tsx
|
|
2
2
|
import { Novu } from "@novu/js";
|
|
3
3
|
import { buildSubscriber } from "@novu/js/internal";
|
|
4
|
-
import { createContext, useContext,
|
|
4
|
+
import { createContext, useContext, useEffect, useMemo } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
|
-
var version = "3.
|
|
6
|
+
var version = "3.8.0";
|
|
7
7
|
var name = "@novu/react";
|
|
8
8
|
var baseUserAgent = `${name}@${version}`;
|
|
9
9
|
var NovuContext = createContext(void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/NovuProvider.tsx"],"sourcesContent":["import { Novu, NovuOptions } from '@novu/js';\nimport { buildSubscriber } from '@novu/js/internal';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/NovuProvider.tsx"],"sourcesContent":["import { Novu, NovuOptions } from '@novu/js';\nimport { buildSubscriber } from '@novu/js/internal';\nimport { createContext, ReactNode, useContext, useEffect, useMemo } from 'react';\n\n// @ts-ignore\nconst version = PACKAGE_VERSION;\n// @ts-ignore\nconst name = PACKAGE_NAME;\nconst baseUserAgent = `${name}@${version}`;\n\nexport type NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = (props: NovuProviderProps) => {\n const { subscriberId, ...propsWithoutSubscriberId } = props;\n const subscriberObj = buildSubscriber({ subscriberId, subscriber: props.subscriber });\n const applicationIdentifier = propsWithoutSubscriberId.applicationIdentifier\n ? propsWithoutSubscriberId.applicationIdentifier\n : '';\n\n const providerProps: NovuProviderProps = {\n ...propsWithoutSubscriberId,\n applicationIdentifier,\n subscriber: subscriberObj,\n };\n\n return (\n <InternalNovuProvider {...providerProps} applicationIdentifier={applicationIdentifier} userAgentType=\"hooks\">\n {props.children}\n </InternalNovuProvider>\n );\n};\n\n/**\n * @internal Should be used internally not to be exposed outside of the library\n * This is needed to differentiate between the hooks and components user agents\n * Better to use this internally to avoid confusion.\n */\nexport const InternalNovuProvider = (props: NovuProviderProps & { userAgentType: 'components' | 'hooks' }) => {\n const applicationIdentifier = props.applicationIdentifier || '';\n const subscriberObj = buildSubscriber({ subscriberId: props.subscriberId, subscriber: props.subscriber });\n\n const { children, subscriberId, subscriberHash, backendUrl, apiUrl, socketUrl, useCache, userAgentType } = props;\n\n const novu = useMemo(\n () =>\n new Novu({\n applicationIdentifier,\n subscriberHash,\n backendUrl,\n apiUrl,\n socketUrl,\n useCache,\n __userAgent: `${baseUserAgent} ${userAgentType}`,\n subscriber: subscriberObj,\n }),\n [applicationIdentifier, subscriberHash, backendUrl, apiUrl, socketUrl, useCache, userAgentType]\n );\n\n useEffect(() => {\n novu.changeSubscriber({\n subscriber: subscriberObj,\n subscriberHash: props.subscriberHash,\n });\n }, [subscriberObj.subscriberId, props.subscriberHash, novu]);\n\n return <NovuContext.Provider value={novu}>{children}</NovuContext.Provider>;\n};\n\nexport const useNovu = () => {\n const context = useContext(NovuContext);\n if (!context) {\n throw new Error('useNovu must be used within a <NovuProvider />');\n }\n\n return context;\n};\n\nexport const useUnsafeNovu = () => {\n const context = useContext(NovuContext);\n\n return context;\n};\n"],"mappings":";AAAA,SAAS,YAAyB;AAClC,SAAS,uBAAuB;AAChC,SAAS,eAA0B,YAAY,WAAW,eAAe;AA4BrE;AAzBJ,IAAM,UAAU;AAEhB,IAAM,OAAO;AACb,IAAM,gBAAgB,GAAG,IAAI,IAAI,OAAO;AAMxC,IAAM,cAAc,cAAgC,MAAS;AAEtD,IAAM,eAAe,CAAC,UAA6B;AACxD,QAAM,EAAE,cAAc,GAAG,yBAAyB,IAAI;AACtD,QAAM,gBAAgB,gBAAgB,EAAE,cAAc,YAAY,MAAM,WAAW,CAAC;AACpF,QAAM,wBAAwB,yBAAyB,wBACnD,yBAAyB,wBACzB;AAEJ,QAAM,gBAAmC;AAAA,IACvC,GAAG;AAAA,IACH;AAAA,IACA,YAAY;AAAA,EACd;AAEA,SACE,oBAAC,wBAAsB,GAAG,eAAe,uBAA8C,eAAc,SAClG,gBAAM,UACT;AAEJ;AAOO,IAAM,uBAAuB,CAAC,UAAyE;AAC5G,QAAM,wBAAwB,MAAM,yBAAyB;AAC7D,QAAM,gBAAgB,gBAAgB,EAAE,cAAc,MAAM,cAAc,YAAY,MAAM,WAAW,CAAC;AAExG,QAAM,EAAE,UAAU,cAAc,gBAAgB,YAAY,QAAQ,WAAW,UAAU,cAAc,IAAI;AAE3G,QAAM,OAAO;AAAA,IACX,MACE,IAAI,KAAK;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,GAAG,aAAa,IAAI,aAAa;AAAA,MAC9C,YAAY;AAAA,IACd,CAAC;AAAA,IACH,CAAC,uBAAuB,gBAAgB,YAAY,QAAQ,WAAW,UAAU,aAAa;AAAA,EAChG;AAEA,YAAU,MAAM;AACd,SAAK,iBAAiB;AAAA,MACpB,YAAY;AAAA,MACZ,gBAAgB,MAAM;AAAA,IACxB,CAAC;AAAA,EACH,GAAG,CAAC,cAAc,cAAc,MAAM,gBAAgB,IAAI,CAAC;AAE3D,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAO,MAAO,UAAS;AACtD;AAEO,IAAM,UAAU,MAAM;AAC3B,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,SAAO;AACT;AAEO,IAAM,gBAAgB,MAAM;AACjC,QAAM,UAAU,WAAW,WAAW;AAEtC,SAAO;AACT;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
export { NovuProvider, useNovu } from './NovuProvider.js';
|
|
2
|
+
export { UseCountsProps, UseCountsResult, useCounts } from './useCounts.js';
|
|
1
3
|
export { UseNotificationsProps, UseNotificationsResult, useNotifications } from './useNotifications.js';
|
|
2
4
|
export { UsePreferencesProps, UsePreferencesResult, usePreferences } from './usePreferences.js';
|
|
3
|
-
export { UseCountsProps, UseCountsResult, useCounts } from './useCounts.js';
|
|
4
|
-
export { NovuProvider, useNovu } from './NovuProvider.js';
|
|
5
|
-
import '@novu/js';
|
|
6
5
|
import 'react/jsx-runtime';
|
|
6
|
+
import '@novu/js';
|
|
7
7
|
import 'react';
|
package/dist/esm/hooks/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/hooks/index.ts
|
|
2
|
+
import { NovuProvider, useNovu } from "./NovuProvider.js";
|
|
3
|
+
export * from "./useCounts.js";
|
|
2
4
|
export * from "./useNotifications.js";
|
|
3
5
|
export * from "./usePreferences.js";
|
|
4
|
-
export * from "./useCounts.js";
|
|
5
|
-
import { NovuProvider, useNovu } from "./NovuProvider.js";
|
|
6
6
|
export {
|
|
7
7
|
NovuProvider,
|
|
8
8
|
useNovu
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/index.ts"],"sourcesContent":["export
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/index.ts"],"sourcesContent":["export { NovuProvider, useNovu } from './NovuProvider';\nexport * from './useCounts';\nexport * from './useNotifications';\nexport * from './usePreferences';\n"],"mappings":";AAAA,SAAS,cAAc,eAAe;AACtC,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/hooks/internal/useWebsocketEvent.ts
|
|
2
2
|
import { useEffect } from "react";
|
|
3
|
-
import { useNovu } from "../NovuProvider.js";
|
|
4
3
|
import { requestLock } from "../../utils/requestLock.js";
|
|
4
|
+
import { useNovu } from "../NovuProvider.js";
|
|
5
5
|
import { useBrowserTabsChannel } from "./useBrowserTabsChannel.js";
|
|
6
6
|
var useWebSocketEvent = ({
|
|
7
7
|
event: webSocketEvent,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/hooks/internal/useWebsocketEvent.ts"],"sourcesContent":["import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../src/hooks/internal/useWebsocketEvent.ts"],"sourcesContent":["import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { requestLock } from '../../utils/requestLock';\nimport { useNovu } from '../NovuProvider';\nimport { useBrowserTabsChannel } from './useBrowserTabsChannel';\n\nexport const useWebSocketEvent = <E extends SocketEventNames>({\n event: webSocketEvent,\n eventHandler: onMessage,\n}: {\n event: E;\n eventHandler: (args: Events[E]) => void;\n}) => {\n const novu = useNovu();\n const channelName = `nv_ws_connection:a=${novu.applicationIdentifier}:s=${novu.subscriberId}:e=${webSocketEvent}`;\n\n const { postMessage } = useBrowserTabsChannel({\n channelName,\n onMessage,\n });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n let cleanup: () => void;\n const resolveLock = requestLock(channelName, () => {\n cleanup = novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n if (cleanup) {\n cleanup();\n }\n\n resolveLock();\n };\n }, []);\n};\n"],"mappings":";AACA,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AACxB,SAAS,6BAA6B;AAE/B,IAAM,oBAAoB,CAA6B;AAAA,EAC5D,OAAO;AAAA,EACP,cAAc;AAChB,MAGM;AACJ,QAAM,OAAO,QAAQ;AACrB,QAAM,cAAc,sBAAsB,KAAK,qBAAqB,MAAM,KAAK,YAAY,MAAM,cAAc;AAE/G,QAAM,EAAE,YAAY,IAAI,sBAAsB;AAAA,IAC5C;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,kBAA2C,CAAC,SAAS;AACzD,cAAU,IAAI;AACd,gBAAY,IAAI;AAAA,EAClB;AAEA,YAAU,MAAM;AACd,QAAI;AACJ,UAAM,cAAc,YAAY,aAAa,MAAM;AACjD,gBAAU,KAAK,GAAG,gBAAgB,eAAe;AAAA,IACnD,CAAC;AAED,WAAO,MAAM;AACX,UAAI,SAAS;AACX,gBAAQ;AAAA,MACV;AAEA,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,CAAC;AACP;","names":[]}
|
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
// src/hooks/useCounts.ts
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
2
|
import { areTagsEqual, isSameFilter } from "@novu/js";
|
|
4
|
-
import {
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
5
4
|
import { useWebSocketEvent } from "./internal/useWebsocketEvent.js";
|
|
5
|
+
import { useNovu } from "./NovuProvider.js";
|
|
6
6
|
var useCounts = (props) => {
|
|
7
7
|
const { filters, onSuccess, onError } = props;
|
|
8
8
|
const { notifications } = useNovu();
|
|
9
|
+
const filtersRef = useRef(filters);
|
|
9
10
|
const [error, setError] = useState();
|
|
10
11
|
const [counts, setCounts] = useState();
|
|
11
12
|
const [isLoading, setIsLoading] = useState(true);
|
|
12
13
|
const [isFetching, setIsFetching] = useState(false);
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
filtersRef.current = filters;
|
|
15
|
+
const sync = async (notification, overrideFilters) => {
|
|
16
|
+
const currentFilters = overrideFilters || filtersRef.current;
|
|
17
|
+
const existingCounts = currentFilters.map((filter) => ({ count: 0, filter }));
|
|
15
18
|
let countFiltersToFetch = [];
|
|
16
19
|
if (notification) {
|
|
17
20
|
for (let i = 0; i < existingCounts.length; i++) {
|
|
18
|
-
const filter =
|
|
21
|
+
const filter = currentFilters[i];
|
|
19
22
|
if (areTagsEqual(filter.tags, notification.tags)) {
|
|
20
23
|
countFiltersToFetch.push(filter);
|
|
21
24
|
}
|
|
22
25
|
}
|
|
23
26
|
} else {
|
|
24
|
-
countFiltersToFetch =
|
|
27
|
+
countFiltersToFetch = currentFilters;
|
|
25
28
|
}
|
|
26
29
|
if (countFiltersToFetch.length === 0) {
|
|
27
30
|
return;
|
|
@@ -41,8 +44,9 @@ var useCounts = (props) => {
|
|
|
41
44
|
const newCounts = [];
|
|
42
45
|
const countsReceived = data.counts;
|
|
43
46
|
for (let i = 0; i < existingCounts.length; i++) {
|
|
44
|
-
const
|
|
45
|
-
const
|
|
47
|
+
const existingFilter = existingCounts[i].filter;
|
|
48
|
+
const countReceived = countsReceived.find((c) => isSameFilter(c.filter, existingFilter));
|
|
49
|
+
const count = countReceived || oldCounts?.[i];
|
|
46
50
|
if (count) {
|
|
47
51
|
newCounts.push(count);
|
|
48
52
|
}
|
|
@@ -66,7 +70,7 @@ var useCounts = (props) => {
|
|
|
66
70
|
setError(void 0);
|
|
67
71
|
setIsLoading(true);
|
|
68
72
|
setIsFetching(false);
|
|
69
|
-
sync();
|
|
73
|
+
sync(void 0, filters);
|
|
70
74
|
}, [JSON.stringify(filters)]);
|
|
71
75
|
const refetch = async () => {
|
|
72
76
|
await sync();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/useCounts.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useCounts.ts"],"sourcesContent":["import { areTagsEqual, isSameFilter, Notification, NotificationFilter, NovuError } from '@novu/js';\nimport { useEffect, useRef, useState } from 'react';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\nimport { useNovu } from './NovuProvider';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\n/**\n * Props for the useCounts hook.\n *\n * @example\n * ```tsx\n * // Count unread notifications\n * const { counts } = useCounts({\n * filters: [{ read: false }]\n * });\n *\n * // Count unseen notifications with specific tags\n * const { counts } = useCounts({\n * filters: [{ seen: false, tags: ['important'] }]\n * });\n *\n * // Count seen but unread notifications\n * const { counts } = useCounts({\n * filters: [{ seen: true, read: false }]\n * });\n * ```\n */\nexport type UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport type UseCountsResult = {\n counts?: Count[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const useCounts = (props: UseCountsProps): UseCountsResult => {\n const { filters, onSuccess, onError } = props;\n const { notifications } = useNovu();\n const filtersRef = useRef<NotificationFilter[]>(filters);\n const [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n // Keep ref up to date\n filtersRef.current = filters;\n\n const sync = async (notification?: Notification, overrideFilters?: NotificationFilter[]) => {\n const currentFilters = overrideFilters || filtersRef.current;\n const existingCounts = currentFilters.map((filter) => ({ count: 0, filter }));\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = currentFilters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = currentFilters;\n }\n\n if (countFiltersToFetch.length === 0) {\n return;\n }\n\n setIsFetching(true);\n const countsRes = await notifications.count({ filters: countFiltersToFetch });\n setIsFetching(false);\n setIsLoading(false);\n if (countsRes.error) {\n setError(countsRes.error);\n onError?.(countsRes.error);\n\n return;\n }\n const data = countsRes.data!;\n onSuccess?.(data.counts);\n\n setCounts((oldCounts) => {\n const newCounts: Count[] = [];\n const countsReceived = data.counts;\n\n for (let i = 0; i < existingCounts.length; i++) {\n const existingFilter = existingCounts[i].filter;\n const countReceived = countsReceived.find((c) => isSameFilter(c.filter, existingFilter));\n const count = countReceived || oldCounts?.[i];\n if (count) {\n newCounts.push(count);\n }\n }\n\n return newCounts;\n });\n };\n\n useWebSocketEvent({\n event: 'notifications.notification_received',\n eventHandler: (data) => {\n sync(data.result);\n },\n });\n\n useWebSocketEvent({\n event: 'notifications.unread_count_changed',\n eventHandler: () => {\n sync();\n },\n });\n\n useEffect(() => {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n sync(undefined, filters);\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n"],"mappings":";AAAA,SAAS,cAAc,oBAAiE;AACxF,SAAS,WAAW,QAAQ,gBAAgB;AAC5C,SAAS,yBAAyB;AAClC,SAAS,eAAe;AA0CjB,IAAM,YAAY,CAAC,UAA2C;AACnE,QAAM,EAAE,SAAS,WAAW,QAAQ,IAAI;AACxC,QAAM,EAAE,cAAc,IAAI,QAAQ;AAClC,QAAM,aAAa,OAA6B,OAAO;AACvD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB;AAC9C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAkB;AAC9C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAC/C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAGlD,aAAW,UAAU;AAErB,QAAM,OAAO,OAAO,cAA6B,oBAA2C;AAC1F,UAAM,iBAAiB,mBAAmB,WAAW;AACrD,UAAM,iBAAiB,eAAe,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,EAAE;AAC5E,QAAI,sBAA4C,CAAC;AACjD,QAAI,cAAc;AAChB,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAM,SAAS,eAAe,CAAC;AAC/B,YAAI,aAAa,OAAO,MAAM,aAAa,IAAI,GAAG;AAChD,8BAAoB,KAAK,MAAM;AAAA,QACjC;AAAA,MACF;AAAA,IACF,OAAO;AACL,4BAAsB;AAAA,IACxB;AAEA,QAAI,oBAAoB,WAAW,GAAG;AACpC;AAAA,IACF;AAEA,kBAAc,IAAI;AAClB,UAAM,YAAY,MAAM,cAAc,MAAM,EAAE,SAAS,oBAAoB,CAAC;AAC5E,kBAAc,KAAK;AACnB,iBAAa,KAAK;AAClB,QAAI,UAAU,OAAO;AACnB,eAAS,UAAU,KAAK;AACxB,gBAAU,UAAU,KAAK;AAEzB;AAAA,IACF;AACA,UAAM,OAAO,UAAU;AACvB,gBAAY,KAAK,MAAM;AAEvB,cAAU,CAAC,cAAc;AACvB,YAAM,YAAqB,CAAC;AAC5B,YAAM,iBAAiB,KAAK;AAE5B,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAM,iBAAiB,eAAe,CAAC,EAAE;AACzC,cAAM,gBAAgB,eAAe,KAAK,CAAC,MAAM,aAAa,EAAE,QAAQ,cAAc,CAAC;AACvF,cAAM,QAAQ,iBAAiB,YAAY,CAAC;AAC5C,YAAI,OAAO;AACT,oBAAU,KAAK,KAAK;AAAA,QACtB;AAAA,MACF;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,oBAAkB;AAAA,IAChB,OAAO;AAAA,IACP,cAAc,CAAC,SAAS;AACtB,WAAK,KAAK,MAAM;AAAA,IAClB;AAAA,EACF,CAAC;AAED,oBAAkB;AAAA,IAChB,OAAO;AAAA,IACP,cAAc,MAAM;AAClB,WAAK;AAAA,IACP;AAAA,EACF,CAAC;AAED,YAAU,MAAM;AACd,aAAS,MAAS;AAClB,iBAAa,IAAI;AACjB,kBAAc,KAAK;AACnB,SAAK,QAAW,OAAO;AAAA,EACzB,GAAG,CAAC,KAAK,UAAU,OAAO,CAAC,CAAC;AAE5B,QAAM,UAAU,YAAY;AAC1B,UAAM,KAAK;AAAA,EACb;AAEA,SAAO,EAAE,QAAQ,OAAO,SAAS,WAAW,WAAW;AACzD;","names":[]}
|
|
@@ -16,9 +16,8 @@ import { Notification, NovuError } from '@novu/js';
|
|
|
16
16
|
* tags: ['important']
|
|
17
17
|
* });
|
|
18
18
|
*
|
|
19
|
-
* // Get
|
|
19
|
+
* // Get notifications (auto-updates in real time when new notifications arrive)
|
|
20
20
|
* const { notifications } = useNotifications({
|
|
21
|
-
* seen: true,
|
|
22
21
|
* read: false
|
|
23
22
|
* });
|
|
24
23
|
* ```
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/hooks/useNotifications.ts
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { checkNotificationMatchesFilter, isSameFilter } from "@novu/js";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { useWebSocketEvent } from "./internal/useWebsocketEvent.js";
|
|
4
5
|
import { useNovu } from "./NovuProvider.js";
|
|
5
6
|
var useNotifications = (props) => {
|
|
6
7
|
const {
|
|
@@ -15,7 +16,8 @@ var useNotifications = (props) => {
|
|
|
15
16
|
onError
|
|
16
17
|
} = props || {};
|
|
17
18
|
const filterRef = useRef(void 0);
|
|
18
|
-
const { notifications
|
|
19
|
+
const { notifications } = useNovu();
|
|
20
|
+
const getCurrentFilter = useCallback(() => filterRef.current || { tags, data: dataFilter }, [tags, dataFilter]);
|
|
19
21
|
const [data, setData] = useState();
|
|
20
22
|
const [error, setError] = useState();
|
|
21
23
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -23,19 +25,53 @@ var useNotifications = (props) => {
|
|
|
23
25
|
const [hasMore, setHasMore] = useState(false);
|
|
24
26
|
const length = data?.length;
|
|
25
27
|
const after = length ? data[length - 1].id : void 0;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
useWebSocketEvent({
|
|
29
|
+
event: "notifications.unread_count_changed",
|
|
30
|
+
eventHandler: () => {
|
|
31
|
+
void refetch();
|
|
29
32
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
});
|
|
34
|
+
useWebSocketEvent({
|
|
35
|
+
event: "notifications.unseen_count_changed",
|
|
36
|
+
eventHandler: () => {
|
|
37
|
+
void refetch();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
useWebSocketEvent({
|
|
41
|
+
event: "notifications.notification_received",
|
|
42
|
+
eventHandler: ({ result: notification }) => {
|
|
43
|
+
const currentFilter = getCurrentFilter();
|
|
44
|
+
const matches = checkNotificationMatchesFilter(notification, currentFilter);
|
|
45
|
+
if (matches) void refetch();
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const fetchNotifications = useCallback(
|
|
49
|
+
async (options) => {
|
|
50
|
+
if (options?.refetch) {
|
|
51
|
+
setError(void 0);
|
|
52
|
+
setIsLoading(true);
|
|
53
|
+
setIsFetching(false);
|
|
54
|
+
}
|
|
55
|
+
setIsFetching(true);
|
|
56
|
+
const currentFilter = getCurrentFilter();
|
|
57
|
+
const response = await notifications.list({
|
|
58
|
+
...currentFilter,
|
|
59
|
+
limit,
|
|
60
|
+
after: options?.refetch ? void 0 : after
|
|
61
|
+
});
|
|
62
|
+
if (response.error) {
|
|
63
|
+
setError(response.error);
|
|
64
|
+
onError?.(response.error);
|
|
65
|
+
} else if (response.data) {
|
|
66
|
+
onSuccess?.(response.data.notifications);
|
|
67
|
+
setData(response.data.notifications);
|
|
68
|
+
setHasMore(response.data.hasMore);
|
|
69
|
+
}
|
|
70
|
+
setIsLoading(false);
|
|
71
|
+
setIsFetching(false);
|
|
72
|
+
},
|
|
73
|
+
[notifications, getCurrentFilter, limit, after, onError, onSuccess]
|
|
74
|
+
);
|
|
39
75
|
useEffect(() => {
|
|
40
76
|
const newFilter = { tags, data: dataFilter, read, archived, snoozed, seen };
|
|
41
77
|
if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {
|
|
@@ -44,37 +80,10 @@ var useNotifications = (props) => {
|
|
|
44
80
|
notifications.clearCache({ filter: filterRef.current });
|
|
45
81
|
filterRef.current = newFilter;
|
|
46
82
|
fetchNotifications({ refetch: true });
|
|
47
|
-
}, [tags, dataFilter, read, archived, snoozed, seen]);
|
|
48
|
-
const fetchNotifications = async (options) => {
|
|
49
|
-
if (options?.refetch) {
|
|
50
|
-
setError(void 0);
|
|
51
|
-
setIsLoading(true);
|
|
52
|
-
setIsFetching(false);
|
|
53
|
-
}
|
|
54
|
-
setIsFetching(true);
|
|
55
|
-
const response = await notifications.list({
|
|
56
|
-
tags,
|
|
57
|
-
data: dataFilter,
|
|
58
|
-
read,
|
|
59
|
-
archived,
|
|
60
|
-
snoozed,
|
|
61
|
-
seen,
|
|
62
|
-
limit,
|
|
63
|
-
after: options?.refetch ? void 0 : after
|
|
64
|
-
});
|
|
65
|
-
if (response.error) {
|
|
66
|
-
setError(response.error);
|
|
67
|
-
onError?.(response.error);
|
|
68
|
-
} else {
|
|
69
|
-
onSuccess?.(response.data.notifications);
|
|
70
|
-
setData(response.data.notifications);
|
|
71
|
-
setHasMore(response.data.hasMore);
|
|
72
|
-
}
|
|
73
|
-
setIsLoading(false);
|
|
74
|
-
setIsFetching(false);
|
|
75
|
-
};
|
|
83
|
+
}, [tags, dataFilter, read, archived, snoozed, seen, notifications, fetchNotifications]);
|
|
76
84
|
const refetch = () => {
|
|
77
|
-
|
|
85
|
+
const filter = getCurrentFilter();
|
|
86
|
+
notifications.clearCache({ filter });
|
|
78
87
|
return fetchNotifications({ refetch: true });
|
|
79
88
|
};
|
|
80
89
|
const fetchMore = async () => {
|
|
@@ -82,16 +91,20 @@ var useNotifications = (props) => {
|
|
|
82
91
|
return fetchNotifications();
|
|
83
92
|
};
|
|
84
93
|
const readAll = async () => {
|
|
85
|
-
|
|
94
|
+
const { tags: tags2, data: data2 } = getCurrentFilter();
|
|
95
|
+
return await notifications.readAll({ tags: tags2, data: data2 });
|
|
86
96
|
};
|
|
87
97
|
const seenAll = async () => {
|
|
88
|
-
|
|
98
|
+
const { tags: tags2, data: data2 } = getCurrentFilter();
|
|
99
|
+
return await notifications.seenAll({ tags: tags2, data: data2 });
|
|
89
100
|
};
|
|
90
101
|
const archiveAll = async () => {
|
|
91
|
-
|
|
102
|
+
const { tags: tags2, data: data2 } = getCurrentFilter();
|
|
103
|
+
return await notifications.archiveAll({ tags: tags2, data: data2 });
|
|
92
104
|
};
|
|
93
105
|
const archiveAllRead = async () => {
|
|
94
|
-
|
|
106
|
+
const { tags: tags2, data: data2 } = getCurrentFilter();
|
|
107
|
+
return await notifications.archiveAllRead({ tags: tags2, data: data2 });
|
|
95
108
|
};
|
|
96
109
|
return {
|
|
97
110
|
readAll,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/useNotifications.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useNotifications.ts"],"sourcesContent":["import { checkNotificationMatchesFilter, isSameFilter, Notification, NotificationFilter, NovuError } from '@novu/js';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\nimport { useNovu } from './NovuProvider';\n\n/**\n * Props for the useNotifications hook.\n *\n * @example\n * ```tsx\n * // Get unread notifications\n * const { notifications } = useNotifications({\n * read: false\n * });\n *\n * // Get unseen notifications with specific tags\n * const { notifications } = useNotifications({\n * seen: false,\n * tags: ['important']\n * });\n *\n * // Get notifications (auto-updates in real time when new notifications arrive)\n * const { notifications } = useNotifications({\n * read: false\n * });\n * ```\n */\nexport type UseNotificationsProps = {\n tags?: string[];\n data?: Record<string, unknown>;\n read?: boolean;\n archived?: boolean;\n snoozed?: boolean;\n seen?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport type UseNotificationsResult = {\n notifications?: Notification[];\n error?: NovuError;\n isLoading: boolean;\n isFetching: boolean;\n hasMore: boolean;\n readAll: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n seenAll: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n archiveAll: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n archiveAllRead: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n refetch: () => Promise<void>;\n fetchMore: () => Promise<void>;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps): UseNotificationsResult => {\n const {\n tags,\n data: dataFilter,\n read,\n archived = false,\n snoozed = false,\n seen,\n limit,\n onSuccess,\n onError,\n } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications } = useNovu();\n\n const getCurrentFilter = useCallback(() => filterRef.current || { tags, data: dataFilter }, [tags, dataFilter]);\n const [data, setData] = useState<Array<Notification>>();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n const [hasMore, setHasMore] = useState(false);\n const length = data?.length;\n const after = length ? data[length - 1].id : undefined;\n\n useWebSocketEvent({\n event: 'notifications.unread_count_changed',\n eventHandler: () => {\n void refetch();\n },\n });\n\n useWebSocketEvent({\n event: 'notifications.unseen_count_changed',\n eventHandler: () => {\n void refetch();\n },\n });\n\n useWebSocketEvent({\n event: 'notifications.notification_received',\n eventHandler: ({ result: notification }) => {\n const currentFilter = getCurrentFilter();\n const matches = checkNotificationMatchesFilter(notification, currentFilter);\n if (matches) void refetch();\n },\n });\n\n const fetchNotifications = useCallback(\n async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n\n const currentFilter = getCurrentFilter();\n\n const response = await notifications.list({\n ...currentFilter,\n limit,\n after: options?.refetch ? undefined : after,\n });\n\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else if (response.data) {\n onSuccess?.(response.data.notifications);\n setData(response.data.notifications);\n setHasMore(response.data.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n },\n [notifications, getCurrentFilter, limit, after, onError, onSuccess]\n );\n\n useEffect(() => {\n const newFilter = { tags, data: dataFilter, read, archived, snoozed, seen };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, dataFilter, read, archived, snoozed, seen, notifications, fetchNotifications]);\n\n const refetch = () => {\n const filter = getCurrentFilter();\n notifications.clearCache({ filter });\n return fetchNotifications({ refetch: true });\n };\n\n const fetchMore = async () => {\n if (!hasMore || isFetching) return;\n\n return fetchNotifications();\n };\n\n const readAll = async () => {\n const { tags, data } = getCurrentFilter();\n return await notifications.readAll({ tags, data });\n };\n\n const seenAll = async () => {\n const { tags, data } = getCurrentFilter();\n return await notifications.seenAll({ tags, data });\n };\n\n const archiveAll = async () => {\n const { tags, data } = getCurrentFilter();\n return await notifications.archiveAll({ tags, data });\n };\n\n const archiveAllRead = async () => {\n const { tags, data } = getCurrentFilter();\n return await notifications.archiveAllRead({ tags, data });\n };\n\n return {\n readAll,\n seenAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n"],"mappings":"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","names":["tags","data"]}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export { ChannelPreference, ChannelType, EventHandler, Events, FiltersCountResponse, InboxNotification, ListNotificationsResponse, Notification, NotificationFilter, NotificationStatus, NovuError, NovuOptions, Preference, PreferenceLevel, PreferencesResponse, SocketEventNames, WebSocketEvent } from '@novu/js';
|
|
2
2
|
export { Appearance, AppearanceKey, ElementStyles, Elements, Localization, LocalizationKey, NotificationActionClickHandler, NotificationClickHandler, NotificationRenderer, PreferenceGroups, PreferencesFilter, RouterPush, Tab, Variables } from '@novu/js/ui';
|
|
3
|
+
export { NovuProvider, NovuProviderProps, useNovu } from './hooks/NovuProvider.js';
|
|
3
4
|
export { Bell, BellProps } from './components/Bell.js';
|
|
4
5
|
export { Inbox, InboxProps } from './components/Inbox.js';
|
|
5
|
-
export { Preferences } from './components/Preferences.js';
|
|
6
|
-
export { NotificationProps, Notifications } from './components/Notifications.js';
|
|
7
6
|
export { InboxContent, InboxContentProps } from './components/InboxContent.js';
|
|
8
|
-
export {
|
|
7
|
+
export { NotificationProps, Notifications } from './components/Notifications.js';
|
|
8
|
+
export { Preferences } from './components/Preferences.js';
|
|
9
|
+
export { UseCountsProps, UseCountsResult, useCounts } from './hooks/useCounts.js';
|
|
9
10
|
export { UseNotificationsProps, UseNotificationsResult, useNotifications } from './hooks/useNotifications.js';
|
|
10
11
|
export { UsePreferencesProps, UsePreferencesResult, usePreferences } from './hooks/usePreferences.js';
|
|
11
|
-
export { UseCountsProps, UseCountsResult, useCounts } from './hooks/useCounts.js';
|
|
12
12
|
export { BaseProps, BellRenderer, BodyRenderer, DefaultInboxProps, DefaultProps, NoRendererProps, NotificationRendererProps, NotificationsRenderer, SubjectBodyRendererProps, SubjectRenderer, WithChildrenProps } from './utils/types.js';
|
|
13
|
-
import 'react';
|
|
14
13
|
import 'react/jsx-runtime';
|
|
14
|
+
import 'react';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { Bell, Inbox, InboxContent, Notifications, NovuProvider, Preferences } from "./components/index.js";
|
|
3
|
+
import { useCounts, useNotifications, useNovu, usePreferences } from "./hooks/index.js";
|
|
4
4
|
export {
|
|
5
5
|
Bell,
|
|
6
6
|
Inbox,
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export type {\n
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export type {\n ChannelPreference,\n ChannelType,\n EventHandler,\n Events,\n FiltersCountResponse,\n InboxNotification,\n ListNotificationsResponse,\n Notification,\n NotificationFilter,\n NotificationStatus,\n NovuError,\n NovuOptions,\n Preference,\n PreferenceLevel,\n PreferencesResponse,\n SocketEventNames,\n WebSocketEvent,\n} from '@novu/js';\n\nexport type {\n Appearance,\n AppearanceKey,\n ElementStyles,\n Elements,\n Localization,\n LocalizationKey,\n NotificationActionClickHandler,\n NotificationClickHandler,\n NotificationRenderer,\n PreferenceGroups,\n PreferencesFilter,\n RouterPush,\n Tab,\n Variables,\n} from '@novu/js/ui';\nexport type { BellProps, InboxContentProps, InboxProps, NotificationProps, NovuProviderProps } from './components';\nexport { Bell, Inbox, InboxContent, Notifications, NovuProvider, Preferences } from './components';\nexport type {\n UseCountsProps,\n UseCountsResult,\n UseNotificationsProps,\n UseNotificationsResult,\n UsePreferencesProps,\n UsePreferencesResult,\n} from './hooks';\nexport { useCounts, useNotifications, useNovu, usePreferences } from './hooks';\n\nexport type {\n BaseProps,\n BellRenderer,\n BodyRenderer,\n DefaultInboxProps,\n DefaultProps,\n NoRendererProps,\n NotificationRendererProps,\n NotificationsRenderer,\n SubjectBodyRendererProps,\n SubjectRenderer,\n WithChildrenProps,\n} from './utils/types';\n"],"mappings":";AAqCA,SAAS,MAAM,OAAO,cAAc,eAAe,cAAc,mBAAmB;AASpF,SAAS,WAAW,kBAAkB,SAAS,sBAAsB;","names":[]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { InboxProps } from '../components/Inbox.js';
|
|
3
|
+
import { NovuProviderProps } from '../hooks/NovuProvider.js';
|
|
4
|
+
import { UseCountsProps, UseCountsResult } from '../hooks/useCounts.js';
|
|
2
5
|
import { UseNotificationsProps, UseNotificationsResult } from '../hooks/useNotifications.js';
|
|
3
6
|
import { UsePreferencesProps, UsePreferencesResult } from '../hooks/usePreferences.js';
|
|
4
|
-
import { UseCountsProps, UseCountsResult } from '../hooks/useCounts.js';
|
|
5
|
-
import { NovuProviderProps } from '../hooks/NovuProvider.js';
|
|
6
|
-
import { InboxProps } from '../components/Inbox.js';
|
|
7
7
|
export { ChannelPreference, ChannelType, FiltersCountResponse, InboxNotification, ListNotificationsResponse, Notification, NotificationFilter, NotificationStatus, NovuError, NovuOptions, Preference, PreferenceLevel } from '@novu/js';
|
|
8
8
|
export { Appearance, AppearanceKey, ElementStyles, Elements, Localization, LocalizationKey, NotificationActionClickHandler, NotificationClickHandler, NotificationRenderer, PreferenceGroups, PreferencesFilter, RouterPush, Tab, Variables } from '@novu/js/ui';
|
|
9
9
|
export { BellProps } from '../components/Bell.js';
|
|
10
|
-
export { NotificationProps } from '../components/Notifications.js';
|
|
11
10
|
export { InboxContentProps } from '../components/InboxContent.js';
|
|
11
|
+
export { NotificationProps } from '../components/Notifications.js';
|
|
12
12
|
export { BaseProps, BellRenderer, BodyRenderer, DefaultInboxProps, DefaultProps, NoRendererProps, NotificationRendererProps, NotificationsRenderer, SubjectBodyRendererProps, SubjectRenderer, WithChildrenProps } from '../utils/types.js';
|
|
13
13
|
import 'react';
|
|
14
14
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/index.tsx"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../../src/server/index.tsx"],"sourcesContent":["import type { InboxProps } from '../components/Inbox';\nimport { ShadowRootDetector } from '../components/ShadowRootDetector';\nimport type {\n UseNotificationsProps,\n UseNotificationsResult,\n UsePreferencesProps,\n UsePreferencesResult,\n} from '../hooks';\nimport type { NovuProviderProps } from '../hooks/NovuProvider';\nimport type { UseCountsProps, UseCountsResult } from '../hooks/useCounts';\n\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(props: InboxProps) {\n return <ShadowRootDetector />;\n}\n\nexport function InboxContent() {}\n\nexport function Notifications() {}\n\nexport function Preferences() {}\n\nexport function Bell() {}\n\nexport function NovuProvider(props: NovuProviderProps) {}\n\nexport function useNovu() {\n return null;\n}\n\nexport function useCounts(_: UseCountsProps): UseCountsResult {\n return {\n isLoading: false,\n isFetching: false,\n refetch: () => Promise.resolve(),\n };\n}\n\nexport function useNotifications(_: UseNotificationsProps): UseNotificationsResult {\n return {\n isLoading: false,\n isFetching: false,\n hasMore: false,\n readAll: () => Promise.resolve({ data: undefined, error: undefined }),\n seenAll: () => Promise.resolve({ data: undefined, error: undefined }),\n archiveAll: () => Promise.resolve({ data: undefined, error: undefined }),\n archiveAllRead: () => Promise.resolve({ data: undefined, error: undefined }),\n refetch: () => Promise.resolve(),\n fetchMore: () => Promise.resolve(),\n };\n}\n\nexport function usePreferences(_: UsePreferencesProps): UsePreferencesResult {\n return {\n isLoading: false,\n isFetching: false,\n refetch: () => Promise.resolve(),\n };\n}\n\nexport type {\n ChannelPreference,\n ChannelType,\n FiltersCountResponse,\n InboxNotification,\n ListNotificationsResponse,\n Notification,\n NotificationFilter,\n NotificationStatus,\n NovuError,\n NovuOptions,\n Preference,\n PreferenceLevel,\n} from '@novu/js';\n\nexport type {\n Appearance,\n AppearanceKey,\n ElementStyles,\n Elements,\n Localization,\n LocalizationKey,\n NotificationActionClickHandler,\n NotificationClickHandler,\n NotificationRenderer,\n PreferenceGroups,\n PreferencesFilter,\n RouterPush,\n Tab,\n Variables,\n} from '@novu/js/ui';\n\nexport type { BellProps, InboxContentProps, InboxProps, NotificationProps, NovuProviderProps } from '../components';\n\nexport type {\n UseCountsProps,\n UseCountsResult,\n UseNotificationsProps,\n UseNotificationsResult,\n UsePreferencesProps,\n UsePreferencesResult,\n} from '../hooks';\n\nexport type {\n BaseProps,\n BellRenderer,\n BodyRenderer,\n DefaultInboxProps,\n DefaultProps,\n NoRendererProps,\n NotificationRendererProps,\n NotificationsRenderer,\n SubjectBodyRendererProps,\n SubjectRenderer,\n WithChildrenProps,\n} from '../utils/types';\n"],"mappings":";AACA,SAAS,0BAA0B;AAiB1B;AADF,SAAS,MAAM,OAAmB;AACvC,SAAO,oBAAC,sBAAmB;AAC7B;AAEO,SAAS,eAAe;AAAC;AAEzB,SAAS,gBAAgB;AAAC;AAE1B,SAAS,cAAc;AAAC;AAExB,SAAS,OAAO;AAAC;AAEjB,SAAS,aAAa,OAA0B;AAAC;AAEjD,SAAS,UAAU;AACxB,SAAO;AACT;AAEO,SAAS,UAAU,GAAoC;AAC5D,SAAO;AAAA,IACL,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS,MAAM,QAAQ,QAAQ;AAAA,EACjC;AACF;AAEO,SAAS,iBAAiB,GAAkD;AACjF,SAAO;AAAA,IACL,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,SAAS,MAAM,QAAQ,QAAQ,EAAE,MAAM,QAAW,OAAO,OAAU,CAAC;AAAA,IACpE,SAAS,MAAM,QAAQ,QAAQ,EAAE,MAAM,QAAW,OAAO,OAAU,CAAC;AAAA,IACpE,YAAY,MAAM,QAAQ,QAAQ,EAAE,MAAM,QAAW,OAAO,OAAU,CAAC;AAAA,IACvE,gBAAgB,MAAM,QAAQ,QAAQ,EAAE,MAAM,QAAW,OAAO,OAAU,CAAC;AAAA,IAC3E,SAAS,MAAM,QAAQ,QAAQ;AAAA,IAC/B,WAAW,MAAM,QAAQ,QAAQ;AAAA,EACnC;AACF;AAEO,SAAS,eAAe,GAA8C;AAC3E,SAAO;AAAA,IACL,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS,MAAM,QAAQ,QAAQ;AAAA,EACjC;AACF;","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Appearance } from '@novu/js/ui';
|
|
2
|
-
import { ReactAppearance } from './types.js';
|
|
3
2
|
import { MountedElement } from '../context/RendererContext.js';
|
|
4
|
-
import '
|
|
5
|
-
import 'react';
|
|
3
|
+
import { ReactAppearance } from './types.js';
|
|
6
4
|
import 'react/jsx-runtime';
|
|
5
|
+
import 'react';
|
|
6
|
+
import '@novu/js';
|
|
7
7
|
|
|
8
8
|
declare function adaptAppearanceForJs(appearance: ReactAppearance, mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void): Appearance | undefined;
|
|
9
9
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/appearance.ts"],"sourcesContent":["import type { Appearance as JsAppearance,
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/appearance.ts"],"sourcesContent":["import type { IconKey, IconRenderer, Appearance as JsAppearance, IconOverrides as JsIconOverrides } from '@novu/js/ui';\nimport { MountedElement } from '../context/RendererContext';\nimport type { ReactAppearance, ReactIconRenderer } from './types';\n\nexport function adaptAppearanceForJs(\n appearance: ReactAppearance,\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void\n): JsAppearance | undefined {\n if (!appearance) {\n return undefined;\n }\n\n const jsAppearance: JsAppearance = JSON.parse(JSON.stringify(appearance));\n\n if (appearance.icons) {\n const jsIcons: JsIconOverrides = {};\n const reactIcons = appearance.icons;\n const iconKeys = Object.keys(reactIcons) as IconKey[];\n\n for (const iconKey of iconKeys) {\n const reactRenderer = reactIcons[iconKey];\n\n if (reactRenderer) {\n jsIcons[iconKey] = (el: HTMLDivElement, props: { class?: string }) => {\n return mountElement(el, reactRenderer(props));\n };\n }\n }\n\n // JsAppearance also has .icons directly (from JsTheme part of JsAppearance)\n jsAppearance.icons = jsIcons;\n } else {\n // If original didn't have icons, ensure the clone doesn't either\n delete jsAppearance.icons;\n }\n\n return jsAppearance;\n}\n"],"mappings":";AAIO,SAAS,qBACd,YACA,cAC0B;AAC1B,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,QAAM,eAA6B,KAAK,MAAM,KAAK,UAAU,UAAU,CAAC;AAExE,MAAI,WAAW,OAAO;AACpB,UAAM,UAA2B,CAAC;AAClC,UAAM,aAAa,WAAW;AAC9B,UAAM,WAAW,OAAO,KAAK,UAAU;AAEvC,eAAW,WAAW,UAAU;AAC9B,YAAM,gBAAgB,WAAW,OAAO;AAExC,UAAI,eAAe;AACjB,gBAAQ,OAAO,IAAI,CAAC,IAAoB,UAA8B;AACpE,iBAAO,aAAa,IAAI,cAAc,KAAK,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAGA,iBAAa,QAAQ;AAAA,EACvB,OAAO;AAEL,WAAO,aAAa;AAAA,EACtB;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Notification, IconKey, Theme, NotificationClickHandler, NotificationActionClickHandler, InboxProps, Localization, Tab, PreferencesFilter, PreferenceGroups, RouterPush } from '@novu/js/ui';
|
|
2
1
|
import { Subscriber } from '@novu/js';
|
|
2
|
+
import { Notification, IconKey, Theme, NotificationClickHandler, NotificationActionClickHandler, InboxProps, Localization, Tab, PreferencesFilter, PreferenceGroups, RouterPush } from '@novu/js/ui';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
|
|
5
5
|
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novu/react",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/novuhq/novu",
|
|
@@ -131,8 +131,9 @@
|
|
|
131
131
|
"scripts": {
|
|
132
132
|
"build:watch": "tsup --watch",
|
|
133
133
|
"build": "tsup && pnpm run check-exports",
|
|
134
|
-
"lint": "eslint src",
|
|
135
134
|
"check-exports": "attw --pack .",
|
|
135
|
+
"check": "biome check .",
|
|
136
|
+
"check:fix": "biome check --write .",
|
|
136
137
|
"publish:rc": "pnpm publish --tag rc"
|
|
137
138
|
}
|
|
138
139
|
}
|