@novu/react 2.1.1 → 2.2.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.
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1, { ReactNode } from 'react';
3
- import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
3
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, PreferencesFilter, RouterPush } from '@novu/js/ui';
4
4
  export { Notification } from '@novu/js/ui';
5
5
  import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
6
6
 
@@ -23,6 +23,7 @@ type BaseProps = {
23
23
  appearance?: Appearance;
24
24
  localization?: Localization;
25
25
  tabs?: Array<Tab>;
26
+ preferencesFilter?: PreferencesFilter;
26
27
  routerPush?: RouterPush;
27
28
  };
28
29
  type DefaultProps = BaseProps & DefaultInboxProps & {
@@ -89,6 +90,9 @@ declare const useNotifications: (props?: UseNotificationsProps) => {
89
90
  };
90
91
 
91
92
  type UsePreferencesProps = {
93
+ filter?: {
94
+ tags?: string[];
95
+ };
92
96
  onSuccess?: (data: Preference[]) => void;
93
97
  onError?: (error: NovuError) => void;
94
98
  };
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1, { ReactNode } from 'react';
3
- import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
3
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, PreferencesFilter, RouterPush } from '@novu/js/ui';
4
4
  export { Notification } from '@novu/js/ui';
5
5
  import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
6
6
 
@@ -23,6 +23,7 @@ type BaseProps = {
23
23
  appearance?: Appearance;
24
24
  localization?: Localization;
25
25
  tabs?: Array<Tab>;
26
+ preferencesFilter?: PreferencesFilter;
26
27
  routerPush?: RouterPush;
27
28
  };
28
29
  type DefaultProps = BaseProps & DefaultInboxProps & {
@@ -89,6 +90,9 @@ declare const useNotifications: (props?: UseNotificationsProps) => {
89
90
  };
90
91
 
91
92
  type UsePreferencesProps = {
93
+ filter?: {
94
+ tags?: string[];
95
+ };
92
96
  onSuccess?: (data: Preference[]) => void;
93
97
  onError?: (error: NovuError) => void;
94
98
  };
@@ -173,6 +173,7 @@ var Renderer = ({ options, novu, children }) => {
173
173
  novuUI.updateTabs(options.tabs);
174
174
  novuUI.updateOptions(options.options);
175
175
  novuUI.updateRouterPush(options.routerPush);
176
+ novuUI.updatePreferencesFilter(options.preferencesFilter);
176
177
  }, [options]);
177
178
  if (!novuUI) {
178
179
  return null;
@@ -232,6 +233,7 @@ var InboxChild = import_react6.default.memo((props) => {
232
233
  localization,
233
234
  appearance,
234
235
  tabs,
236
+ preferencesFilter,
235
237
  routerPush,
236
238
  applicationIdentifier,
237
239
  subscriberId,
@@ -245,10 +247,21 @@ var InboxChild = import_react6.default.memo((props) => {
245
247
  localization,
246
248
  appearance,
247
249
  tabs,
250
+ preferencesFilter,
248
251
  routerPush,
249
252
  options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl }
250
253
  };
251
- }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);
254
+ }, [
255
+ localization,
256
+ appearance,
257
+ tabs,
258
+ preferencesFilter,
259
+ applicationIdentifier,
260
+ subscriberId,
261
+ subscriberHash,
262
+ backendUrl,
263
+ socketUrl
264
+ ]);
252
265
  if (isWithChildrenProps(props)) {
253
266
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, novu, children: props.children });
254
267
  }
@@ -459,7 +472,7 @@ var usePreferences = (props) => {
459
472
  }, []);
460
473
  const fetchPreferences = async () => {
461
474
  setIsFetching(true);
462
- const response = await preferences.list();
475
+ const response = await preferences.list(props?.filter);
463
476
  if (response.error) {
464
477
  setError(response.error);
465
478
  onError?.(response.error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/components/Bell.tsx","../../src/utils/createContextAndHook.ts","../../src/context/RenderContext.tsx","../../src/components/Mounter.tsx","../../src/components/Inbox.tsx","../../src/components/Renderer.tsx","../../src/hooks/internal/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx","../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["export * from './components';\nexport * from './hooks';\nexport * from './utils/types';\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { BellRenderer } from '../utils/types';\n\nexport type BellProps = {\n renderBell?: BellRenderer;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { renderBell } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: renderBell ? { renderBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : undefined,\n });\n },\n [renderBell]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { NovuProvider, useNovu, useUnsafeNovu } from './index';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = (props: DefaultInboxProps) => {\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n renderBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;\n const novu = useUnsafeNovu();\n\n if (novu) {\n return <InboxChild {...props} />;\n }\n\n return (\n <NovuProvider\n applicationIdentifier={applicationIdentifier}\n subscriberId={subscriberId}\n subscriberHash={subscriberHash}\n backendUrl={backendUrl}\n socketUrl={socketUrl}\n >\n <InboxChild {...props} />\n </NovuProvider>\n );\n});\n\nexport const InboxChild = React.memo((props: InboxProps) => {\n const {\n localization,\n appearance,\n tabs,\n routerPush,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n } = props;\n const novu = useNovu();\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n routerPush,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);\n\n if (isWithChildrenProps(props)) {\n return (\n <Renderer options={options} novu={novu}>\n {props.children}\n </Renderer>\n );\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options} novu={novu}>\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 { Novu } from '@novu/js';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/internal/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n novu?: Novu;\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, novu, children }: RendererProps) => {\n const optionsRef = useDataRef({ ...options, novu });\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 novuUI.updateRouterPush(options.routerPush);\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 type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { NotificationsRenderer } from '../utils/types';\n\nexport type NotificationProps = {\n renderNotification?: NotificationsRenderer;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo((props: NotificationProps) => {\n const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: {\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n });\n },\n [renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n});\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list();\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["import_react","React","import_react","import_jsx_runtime","React","import_jsx_runtime","React","import_react","import_react","import_react","import_jsx_runtime","novu","ReactDOM","import_jsx_runtime","React","import_react","import_jsx_runtime","React","import_react","import_jsx_runtime","React","import_react","import_jsx_runtime","import_react","import_js","import_react","import_react","import_js","import_react","import_react"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/components/Bell.tsx","../../src/utils/createContextAndHook.ts","../../src/context/RenderContext.tsx","../../src/components/Mounter.tsx","../../src/components/Inbox.tsx","../../src/components/Renderer.tsx","../../src/hooks/internal/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx","../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["export * from './components';\nexport * from './hooks';\nexport * from './utils/types';\n","import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { BellRenderer } from '../utils/types';\n\nexport type BellProps = {\n renderBell?: BellRenderer;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { renderBell } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: renderBell ? { renderBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : undefined,\n });\n },\n [renderBell]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { NovuProvider, useNovu, useUnsafeNovu } from './index';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = (props: DefaultInboxProps) => {\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n renderBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;\n const novu = useUnsafeNovu();\n\n if (novu) {\n return <InboxChild {...props} />;\n }\n\n return (\n <NovuProvider\n applicationIdentifier={applicationIdentifier}\n subscriberId={subscriberId}\n subscriberHash={subscriberHash}\n backendUrl={backendUrl}\n socketUrl={socketUrl}\n >\n <InboxChild {...props} />\n </NovuProvider>\n );\n});\n\nexport const InboxChild = React.memo((props: InboxProps) => {\n const {\n localization,\n appearance,\n tabs,\n preferencesFilter,\n routerPush,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n } = props;\n const novu = useNovu();\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n preferencesFilter,\n routerPush,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [\n localization,\n appearance,\n tabs,\n preferencesFilter,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n ]);\n\n if (isWithChildrenProps(props)) {\n return (\n <Renderer options={options} novu={novu}>\n {props.children}\n </Renderer>\n );\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options} novu={novu}>\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 { Novu } from '@novu/js';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/internal/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n novu?: Novu;\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, novu, children }: RendererProps) => {\n const optionsRef = useDataRef({ ...options, novu });\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 novuUI.updateRouterPush(options.routerPush);\n novuUI.updatePreferencesFilter(options.preferencesFilter);\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 type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { NotificationsRenderer } from '../utils/types';\n\nexport type NotificationProps = {\n renderNotification?: NotificationsRenderer;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo((props: NotificationProps) => {\n const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: {\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n });\n },\n [renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n});\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n filter?: { tags?: string[] };\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list(props?.filter);\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAAkB;;;ACAlB,mBAAkB;AAEX,SAAS,oBAAoB,YAAqB,UAA2D;AAClH,MAAI,CAAC,YAAY;AACf,UAAM,OAAO,aAAa,WAAW,IAAI,MAAM,QAAQ,IAAI,IAAI,MAAM,GAAG,SAAS,WAAW,YAAY;AAAA,EAC1G;AACF;AAYO,IAAM,uBAAuB,CAClC,aACA,YAC8E;AAC9E,QAAM,EAAE,cAAc,oBAAoB,IAAI,WAAW,CAAC;AAC1D,QAAM,MAAM,aAAAC,QAAM,cAA6C,MAAS;AACxE,MAAI,cAAc;AAElB,QAAM,SAAS,MAAM;AACnB,UAAM,MAAM,aAAAA,QAAM,WAAW,GAAG;AAChC,gBAAY,KAAK,wDAAwD;AAEzE,WAAQ,IAAY;AAAA,EACtB;AAEA,QAAM,yBAAyB,MAAM;AACnC,UAAM,MAAM,aAAAA,QAAM,WAAW,GAAG;AAEhC,WAAO,MAAM,IAAI,QAAQ,CAAC;AAAA,EAC5B;AAEA,SAAO,CAAC,KAAK,QAAQ,sBAAsB;AAC7C;;;ACzBS;AAHT,IAAM,CAAC,iBAAiB,kBAAkB,IAAI,qBAA2C,iBAAiB;AAE1G,IAAM,mBAAmB,CAAC,UAAoE;AAC5F,SAAO,4CAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,OAAO,MAAM,MAAM,GAAI,gBAAM,UAAS;AAClF;;;AChBA,IAAAC,gBAAkB;AA6BT,IAAAC,sBAAA;AApBF,SAAS,QAAQ,EAAE,MAAM,GAAiB;AAC/C,QAAM,MAAM,cAAAC,QAAM,OAAuB,IAAI;AAE7C,gBAAAA,QAAM,UAAU,MAAM;AACpB,QAAI;AACJ,UAAM,UAAU,IAAI;AACpB,QAAI,WAAW,OAAO;AACpB,YAAM,kBAAkB,MAAM,OAAO;AACrC,UAAI,iBAAiB;AACnB,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,WAAO,MAAM;AACX,UAAI,WAAW,SAAS;AACtB,gBAAQ,OAAO;AAAA,MACjB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,KAAK,CAAC;AAEf,SAAO,6CAAC,SAAI,KAAU;AACxB;;;AHNS,IAAAC,sBAAA;AAfF,IAAM,OAAO,cAAAC,QAAM,KAAK,CAAC,UAAqB;AACnD,QAAM,EAAE,WAAW,IAAI;AACvB,QAAM,EAAE,QAAQ,aAAa,IAAI,mBAAY;AAE7C,QAAM,QAAQ,cAAAA,QAAM;AAAA,IAClB,CAAC,YAAyB;AACxB,aAAO,OAAO,eAAe;AAAA,QAC3B,MAAM;AAAA,QACN;AAAA,QACA,OAAO,aAAa,EAAE,YAAY,CAAC,IAAI,gBAAgB,aAAa,IAAI,WAAW,WAAW,CAAC,EAAE,IAAI;AAAA,MACvG,CAAC;AAAA,IACH;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,SAAO,6CAAC,WAAQ,OAAc;AAChC,CAAC;;;AIzBD,IAAAC,gBAA+B;;;ACA/B,IAAAC,gBAAwD;AACxD,uBAAqB;AACrB,gBAAuB;;;ACFvB,IAAAC,gBAAuB;AAEhB,IAAM,aAAa,CAAI,SAAY;AACxC,QAAM,UAAM,sBAAO,IAAI;AACvB,MAAI,UAAU;AAEd,SAAO;AACT;;;AD+DI,IAAAC,sBAAA;AArDG,IAAM,WAAW,CAAC,EAAE,SAAS,MAAM,SAAS,MAAqB;AACtE,QAAM,aAAa,WAAW,EAAE,GAAG,SAAS,KAAK,CAAC;AAClD,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAA6B;AACzD,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,wBAAS,oBAAI,IAAiC,CAAC;AAE7F,QAAM,mBAAe;AAAA,IACnB,CAAC,IAAiB,mBAAmC;AACnD,yBAAmB,CAAC,SAAS;AAC3B,cAAM,qBAAqB,IAAI,IAAI,IAAI;AACvC,2BAAmB,IAAI,IAAI,cAAc;AAEzC,eAAO;AAAA,MACT,CAAC;AAED,aAAO,MAAM;AACX,2BAAmB,CAAC,SAAS;AAC3B,gBAAM,qBAAqB,IAAI,IAAI,IAAI;AACvC,6BAAmB,OAAO,EAAE;AAE5B,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,CAAC,kBAAkB;AAAA,EACrB;AAEA,+BAAU,MAAM;AACd,UAAMC,QAAO,IAAI,iBAAO,WAAW,OAAO;AAC1C,cAAUA,KAAI;AAEd,WAAO,MAAM;AACX,MAAAA,MAAK,QAAQ;AAAA,IACf;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,+BAAU,MAAM;AACd,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAEA,WAAO,iBAAiB,QAAQ,UAAU;AAC1C,WAAO,mBAAmB,QAAQ,YAAY;AAC9C,WAAO,WAAW,QAAQ,IAAI;AAC9B,WAAO,cAAc,QAAQ,OAAO;AACpC,WAAO,iBAAiB,QAAQ,UAAU;AAC1C,WAAO,wBAAwB,QAAQ,iBAAiB;AAAA,EAC1D,GAAG,CAAC,OAAO,CAAC;AAEZ,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,SACE,8CAAC,oBAAiB,OAAO,EAAE,cAAc,OAAO,GAC7C;AAAA,KAAC,GAAG,eAAe,EAAE,IAAI,CAAC,CAAC,SAAS,cAAc,MAAM;AACvD,aAAO,iBAAAC,QAAS,aAAa,gBAAgB,OAAO;AAAA,IACtD,CAAC;AAAA,IAEA;AAAA,KACH;AAEJ;;;AD5CS,IAAAC,sBAAA;AAzBT,IAAM,eAAe,CAAC,UAA6B;AACjD,QAAM,EAAE,MAAM,oBAAoB,YAAY,qBAAqB,sBAAsB,uBAAuB,IAC9G;AACF,QAAM,EAAE,QAAQ,aAAa,IAAI,mBAAY;AAE7C,QAAM,QAAQ,cAAAC,QAAM;AAAA,IAClB,CAAC,YAAyB;AACxB,aAAO,OAAO,eAAe;AAAA,QAC3B,MAAM;AAAA,QACN,OAAO;AAAA,UACL;AAAA,UACA,oBAAoB,qBAChB,CAAC,IAAI,iBAAiB,aAAa,IAAI,mBAAmB,YAAY,CAAC,IACvE;AAAA,UACJ,YAAY,aAAa,CAAC,IAAI,gBAAgB,aAAa,IAAI,WAAW,WAAW,CAAC,IAAI;AAAA,UAC1F;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM,oBAAoB,YAAY,qBAAqB,sBAAsB,sBAAsB;AAAA,EAC1G;AAEA,SAAO,6CAAC,WAAQ,OAAc;AAChC;AAEO,IAAM,QAAQ,cAAAA,QAAM,KAAK,CAAC,UAAsB;AACrD,QAAM,EAAE,uBAAuB,cAAc,gBAAgB,YAAY,UAAU,IAAI;AACvF,QAAM,OAAO,cAAc;AAE3B,MAAI,MAAM;AACR,WAAO,6CAAC,cAAY,GAAG,OAAO;AAAA,EAChC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA,uDAAC,cAAY,GAAG,OAAO;AAAA;AAAA,EACzB;AAEJ,CAAC;AAEM,IAAM,aAAa,cAAAA,QAAM,KAAK,CAAC,UAAsB;AAC1D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,OAAO,QAAQ;AAErB,QAAM,cAAU,uBAAQ,MAAM;AAC5B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,EAAE,uBAAuB,cAAc,gBAAgB,YAAY,UAAU;AAAA,IACxF;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,oBAAoB,KAAK,GAAG;AAC9B,WACE,6CAAC,YAAS,SAAkB,MACzB,gBAAM,UACT;AAAA,EAEJ;AAEA,QAAM,EAAE,MAAM,oBAAoB,YAAY,qBAAqB,sBAAsB,uBAAuB,IAC9G;AAEF,SACE,6CAAC,YAAS,SAAkB,MAC1B;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF,GACF;AAEJ,CAAC;AAED,SAAS,oBAAoB,OAA+C;AAC1E,SAAO,cAAc;AACvB;;;AGzHA,IAAAC,gBAAkB;AAcT,IAAAC,sBAAA;AAVF,IAAM,cAAc,MAAM;AAC/B,QAAM,EAAE,OAAO,IAAI,mBAAY;AAE/B,QAAM,QAAQ,cAAAC,QAAM,YAAY,CAAC,YAAyB;AACxD,WAAO,OAAO,eAAe;AAAA,MAC3B,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,SAAO,6CAAC,WAAQ,OAAc;AAChC;;;ACfA,IAAAC,gBAAkB;AAmCT,IAAAC,sBAAA;AAtBF,IAAM,gBAAgB,cAAAC,QAAM,KAAK,CAAC,UAA6B;AACpE,QAAM,EAAE,qBAAqB,sBAAsB,oBAAoB,uBAAuB,IAAI;AAClG,QAAM,EAAE,QAAQ,aAAa,IAAI,mBAAY;AAE7C,QAAM,QAAQ,cAAAA,QAAM;AAAA,IAClB,CAAC,YAAyB;AACxB,aAAO,OAAO,eAAe;AAAA,QAC3B,MAAM;AAAA,QACN;AAAA,QACA,OAAO;AAAA,UACL,oBAAoB,qBAChB,CAAC,IAAI,iBAAiB,aAAa,IAAI,mBAAmB,YAAY,CAAC,IACvE;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,oBAAoB,qBAAqB,sBAAsB,sBAAsB;AAAA,EACxF;AAEA,SAAO,6CAAC,WAAQ,OAAc;AAChC,CAAC;;;ACpCD,gBAAkC;AAClC,IAAAC,gBAA8D;AAsBrD,IAAAC,sBAAA;AAhBT,IAAM,kBAAc,6BAAgC,MAAS;AAEtD,IAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAyB;AACvB,QAAM,WAAO;AAAA,IACX,MAAM,IAAI,eAAK,EAAE,uBAAuB,cAAc,gBAAgB,YAAY,WAAW,SAAS,CAAC;AAAA,IACvG,CAAC,uBAAuB,cAAc,gBAAgB,YAAY,WAAW,QAAQ;AAAA,EACvF;AAEA,SAAO,6CAAC,YAAY,UAAZ,EAAqB,OAAO,MAAO,UAAS;AACtD;AAEO,IAAM,UAAU,MAAM;AAC3B,QAAM,cAAU,0BAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,SAAO;AACT;AAEO,IAAM,gBAAgB,MAAM;AACjC,QAAM,cAAU,0BAAW,WAAW;AAEtC,SAAO;AACT;;;ACvCA,IAAAC,iBAA4C;AAC5C,IAAAC,aAAqG;AAY9F,IAAM,mBAAmB,CAAC,UAAkC;AACjE,QAAM,EAAE,MAAM,MAAM,WAAW,OAAO,OAAO,WAAW,QAAQ,IAAI,SAAS,CAAC;AAC9E,QAAM,gBAAY,uBAAuC,MAAS;AAClE,QAAM,EAAE,eAAe,IAAI,IAAI,IAAI,QAAQ;AAC3C,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA8B;AACtD,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAoB;AAC9C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,IAAI;AAC/C,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAClD,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,SAAS,MAAM;AACrB,QAAM,QAAQ,SAAS,KAAK,SAAS,CAAC,EAAE,KAAK;AAE7C,QAAM,OAAO,CAAC,UAAgD;AAC5D,QAAI,CAAC,MAAM,QAAS,UAAU,WAAW,KAAC,yBAAa,UAAU,SAAS,MAAM,KAAK,MAAM,GAAI;AAC7F;AAAA,IACF;AACA,YAAQ,MAAM,KAAK,aAAa;AAChC,eAAW,MAAM,KAAK,OAAO;AAAA,EAC/B;AAEA,gCAAU,MAAM;AACd,OAAG,8BAA8B,IAAI;AAErC,WAAO,MAAM;AACX,UAAI,8BAA8B,IAAI;AAAA,IACxC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,gCAAU,MAAM;AACd,UAAM,YAAY,EAAE,MAAM,MAAM,SAAS;AACzC,QAAI,UAAU,eAAW,yBAAa,UAAU,SAAS,SAAS,GAAG;AACnE;AAAA,IACF;AAEA,kBAAc,WAAW,EAAE,QAAQ,UAAU,QAAQ,CAAC;AACtD,cAAU,UAAU;AAEpB,uBAAmB,EAAE,SAAS,KAAK,CAAC;AAAA,EACtC,GAAG,CAAC,MAAM,MAAM,QAAQ,CAAC;AAEzB,QAAM,qBAAqB,OAAO,YAAmC;AACnE,QAAI,SAAS,SAAS;AACpB,eAAS,MAAS;AAClB,mBAAa,IAAI;AACjB,oBAAc,KAAK;AAAA,IACrB;AACA,kBAAc,IAAI;AAClB,UAAM,WAAW,MAAM,cAAc,KAAK;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS,UAAU,SAAY;AAAA,IACxC,CAAC;AACD,QAAI,SAAS,OAAO;AAClB,eAAS,SAAS,KAAK;AACvB,gBAAU,SAAS,KAAK;AAAA,IAC1B,OAAO;AACL,kBAAY,SAAS,KAAM,aAAa;AACxC,cAAQ,SAAS,KAAM,aAAa;AACpC,iBAAW,SAAS,KAAM,OAAO;AAAA,IACnC;AACA,iBAAa,KAAK;AAClB,kBAAc,KAAK;AAAA,EACrB;AAEA,QAAM,UAAU,MAAM;AACpB,kBAAc,WAAW,EAAE,QAAQ,EAAE,MAAM,MAAM,SAAS,EAAE,CAAC;AAE7D,WAAO,mBAAmB,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7C;AAEA,QAAM,YAAY,YAAY;AAC5B,QAAI,CAAC,WAAW,WAAY;AAE5B,WAAO,mBAAmB;AAAA,EAC5B;AAEA,QAAM,UAAU,YAAY;AAC1B,WAAO,MAAM,cAAc,QAAQ,EAAE,KAAK,CAAC;AAAA,EAC7C;AAEA,QAAM,aAAa,YAAY;AAC7B,WAAO,MAAM,cAAc,WAAW,EAAE,KAAK,CAAC;AAAA,EAChD;AAEA,QAAM,iBAAiB,YAAY;AACjC,WAAO,MAAM,cAAc,eAAe,EAAE,KAAK,CAAC;AAAA,EACpD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AClHA,IAAAC,iBAAoC;AAiB7B,IAAM,iBAAiB,CAAC,UAAsD;AACnF,QAAM,EAAE,WAAW,QAAQ,IAAI,SAAS,CAAC;AACzC,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAuB;AAC/C,QAAM,EAAE,aAAa,IAAI,IAAI,IAAI,QAAQ;AACzC,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAoB;AAC9C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,IAAI;AAC/C,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAElD,QAAM,OAAO,CAAC,UAAmC;AAC/C,QAAI,CAAC,MAAM,MAAM;AACf;AAAA,IACF;AACA,YAAQ,MAAM,IAAI;AAAA,EACpB;AAEA,gCAAU,MAAM;AACd,qBAAiB;AAEjB,OAAG,4BAA4B,IAAI;AACnC,OAAG,4BAA4B,IAAI;AACnC,OAAG,6BAA6B,IAAI;AAEpC,WAAO,MAAM;AACX,UAAI,4BAA4B,IAAI;AACpC,UAAI,4BAA4B,IAAI;AACpC,UAAI,6BAA6B,IAAI;AAAA,IACvC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,mBAAmB,YAAY;AACnC,kBAAc,IAAI;AAClB,UAAM,WAAW,MAAM,YAAY,KAAK,OAAO,MAAM;AACrD,QAAI,SAAS,OAAO;AAClB,eAAS,SAAS,KAAK;AACvB,gBAAU,SAAS,KAAK;AAAA,IAC1B,OAAO;AACL,kBAAY,SAAS,IAAK;AAAA,IAC5B;AACA,iBAAa,KAAK;AAClB,kBAAc,KAAK;AAAA,EACrB;AAEA,QAAM,UAAU,MAAM;AACpB,gBAAY,MAAM,SAAS;AAE3B,WAAO,iBAAiB;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzEA,IAAAC,iBAAoC;AACpC,IAAAC,aAA0E;;;ACA1E,IAAAC,iBAA0B;;;ACDnB,SAAS,YAAY,IAAY,IAA0B;AAEhE,MAAI,EAAE,WAAW,YAAY;AAE3B,OAAG,EAAE;AACL,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,MAAI,cAAc;AAClB,MAAI;AAEJ,QAAM,UAAU,IAAI,QAAc,CAAC,YAAY;AAC7C,qBAAiB;AAAA,EACnB,CAAC;AAED,YAAU,MAAM,QAAQ,IAAI,MAAM;AAChC,QAAI,CAAC,aAAa;AAChB,SAAG,EAAE;AAAA,IACP;AAEA,WAAO;AAAA,EACT,CAAC;AAED,SAAO,MAAM;AACX,kBAAc;AACd,mBAAe;AAAA,EACjB;AACF;;;AC3BA,IAAAC,iBAAoC;AAE7B,IAAM,wBAAwB,CAAc;AAAA,EACjD;AAAA,EACA;AACF,MAGM;AACJ,QAAM,CAAC,WAAW,QAAI;AAAA,IACpB,OAAO,qBAAqB,cAAc,IAAI,iBAAiB,WAAW,IAAI;AAAA,EAChF;AAEA,QAAM,cAAc,CAAC,SAAY;AAC/B,iBAAa,YAAY,IAAI;AAAA,EAC/B;AAEA,gCAAU,MAAM;AACd,UAAM,WAAW,CAAC,UAA2B;AAC3C,gBAAU,MAAM,IAAI;AAAA,IACtB;AAEA,iBAAa,iBAAiB,WAAW,QAAQ;AAEjD,WAAO,MAAM;AACX,mBAAa,oBAAoB,WAAW,QAAQ;AAAA,IACtD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,YAAY;AACvB;;;AFxBO,IAAM,oBAAoB,CAA6B;AAAA,EAC5D,OAAO;AAAA,EACP,cAAc;AAChB,MAGM;AACJ,QAAM,OAAO,QAAQ;AACrB,QAAM,EAAE,YAAY,IAAI,sBAAsB,EAAE,aAAa,MAAM,cAAc,IAAI,UAAU,CAAC;AAEhG,QAAM,kBAA2C,CAAC,SAAS;AACzD,cAAU,IAAI;AACd,gBAAY,IAAI;AAAA,EAClB;AAEA,gCAAU,MAAM;AACd,UAAM,cAAc,YAAY,MAAM,cAAc,IAAI,MAAM;AAC5D,WAAK,GAAG,gBAAgB,eAAe;AAAA,IACzC,CAAC;AAED,WAAO,MAAM;AACX,WAAK,IAAI,gBAAgB,eAAe;AACxC,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,CAAC;AACP;;;ADPO,IAAM,YAAY,CAAC,UAA2C;AACnE,QAAM,EAAE,SAAS,WAAW,QAAQ,IAAI;AACxC,QAAM,EAAE,cAAc,IAAI,QAAQ;AAClC,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAoB;AAC9C,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAkB;AAC9C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,IAAI;AAC/C,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAElD,QAAM,OAAO,OAAO,iBAAgC;AAClD,UAAM,iBAAiB,UAAW,IAAI,MAAM,QAAQ,MAAM,EAAE,KAAK,MAAS;AAC1E,QAAI,sBAA4C,CAAC;AACjD,QAAI,cAAc;AAEhB,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAM,SAAS,QAAQ,CAAC;AACxB,gBAAI,yBAAa,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;AAG5B,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAM,gBAAgB,eAAe,KAAK,CAAC,UAAM,yBAAa,EAAE,OAAO,MAAM,eAAe,CAAC,GAAG,OAAO,IAAI,CAAC;AAE5G,kBAAU,KAAK,iBAAiB,UAAW,CAAC,CAAC;AAAA,MAC/C;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,gCAAU,MAAM;AACd,aAAS,MAAS;AAClB,iBAAa,IAAI;AACjB,kBAAc,KAAK;AACnB,SAAK;AAAA,EACP,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":["import_react","React","import_react","import_jsx_runtime","React","import_jsx_runtime","React","import_react","import_react","import_react","import_jsx_runtime","novu","ReactDOM","import_jsx_runtime","React","import_react","import_jsx_runtime","React","import_react","import_jsx_runtime","React","import_react","import_jsx_runtime","import_react","import_js","import_react","import_react","import_js","import_react","import_react"]}
@@ -127,6 +127,7 @@ var Renderer = ({ options, novu, children }) => {
127
127
  novuUI.updateTabs(options.tabs);
128
128
  novuUI.updateOptions(options.options);
129
129
  novuUI.updateRouterPush(options.routerPush);
130
+ novuUI.updatePreferencesFilter(options.preferencesFilter);
130
131
  }, [options]);
131
132
  if (!novuUI) {
132
133
  return null;
@@ -186,6 +187,7 @@ var InboxChild = React5.memo((props) => {
186
187
  localization,
187
188
  appearance,
188
189
  tabs,
190
+ preferencesFilter,
189
191
  routerPush,
190
192
  applicationIdentifier,
191
193
  subscriberId,
@@ -199,10 +201,21 @@ var InboxChild = React5.memo((props) => {
199
201
  localization,
200
202
  appearance,
201
203
  tabs,
204
+ preferencesFilter,
202
205
  routerPush,
203
206
  options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl }
204
207
  };
205
- }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);
208
+ }, [
209
+ localization,
210
+ appearance,
211
+ tabs,
212
+ preferencesFilter,
213
+ applicationIdentifier,
214
+ subscriberId,
215
+ subscriberHash,
216
+ backendUrl,
217
+ socketUrl
218
+ ]);
206
219
  if (isWithChildrenProps(props)) {
207
220
  return /* @__PURE__ */ jsx4(Renderer, { options, novu, children: props.children });
208
221
  }
@@ -413,7 +426,7 @@ var usePreferences = (props) => {
413
426
  }, []);
414
427
  const fetchPreferences = async () => {
415
428
  setIsFetching(true);
416
- const response = await preferences.list();
429
+ const response = await preferences.list(props?.filter);
417
430
  if (response.error) {
418
431
  setError(response.error);
419
432
  onError?.(response.error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Bell.tsx","../../src/utils/createContextAndHook.ts","../../src/context/RenderContext.tsx","../../src/components/Mounter.tsx","../../src/components/Inbox.tsx","../../src/components/Renderer.tsx","../../src/hooks/internal/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx","../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { BellRenderer } from '../utils/types';\n\nexport type BellProps = {\n renderBell?: BellRenderer;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { renderBell } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: renderBell ? { renderBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : undefined,\n });\n },\n [renderBell]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { NovuProvider, useNovu, useUnsafeNovu } from './index';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = (props: DefaultInboxProps) => {\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n renderBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;\n const novu = useUnsafeNovu();\n\n if (novu) {\n return <InboxChild {...props} />;\n }\n\n return (\n <NovuProvider\n applicationIdentifier={applicationIdentifier}\n subscriberId={subscriberId}\n subscriberHash={subscriberHash}\n backendUrl={backendUrl}\n socketUrl={socketUrl}\n >\n <InboxChild {...props} />\n </NovuProvider>\n );\n});\n\nexport const InboxChild = React.memo((props: InboxProps) => {\n const {\n localization,\n appearance,\n tabs,\n routerPush,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n } = props;\n const novu = useNovu();\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n routerPush,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);\n\n if (isWithChildrenProps(props)) {\n return (\n <Renderer options={options} novu={novu}>\n {props.children}\n </Renderer>\n );\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options} novu={novu}>\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 { Novu } from '@novu/js';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/internal/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n novu?: Novu;\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, novu, children }: RendererProps) => {\n const optionsRef = useDataRef({ ...options, novu });\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 novuUI.updateRouterPush(options.routerPush);\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 type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { NotificationsRenderer } from '../utils/types';\n\nexport type NotificationProps = {\n renderNotification?: NotificationsRenderer;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo((props: NotificationProps) => {\n const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: {\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n });\n },\n [renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n});\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list();\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["React","React","jsx","jsx","React","React","novu","jsx","React","React","jsx","React","React","jsx","React","useMemo","jsx","useState","useEffect","useRef","useRef","useState","useEffect","useEffect","useState","useState","useEffect","useEffect","useState","useEffect","useEffect","useState","useEffect","useState","useEffect"]}
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/internal/useDataRef.ts","../../src/components/Preferences.tsx","../../src/components/Notifications.tsx","../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["import React from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { BellRenderer } from '../utils/types';\n\nexport type BellProps = {\n renderBell?: BellRenderer;\n};\n\nexport const Bell = React.memo((props: BellProps) => {\n const { renderBell } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Bell',\n element,\n props: renderBell ? { renderBell: (el, unreadCount) => mountElement(el, renderBell(unreadCount)) } : undefined,\n });\n },\n [renderBell]\n );\n\n return <Mounter mount={mount} />;\n});\n","import React from 'react';\n\nexport function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context<any>): asserts contextVal {\n if (!contextVal) {\n throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`);\n }\n}\n\ntype Options = { assertCtxFn?: (v: unknown, msg: string) => void };\ntype ContextOf<T> = React.Context<{ value: T } | undefined>;\ntype UseCtxFn<T> = () => T;\n\n/**\n * Creates and returns a Context and two hooks that return the context value.\n * The Context type is derived from the type passed in by the user.\n * The first hook returned guarantees that the context exists so the returned value is always CtxValue\n * The second hook makes no guarantees, so the returned value can be CtxValue | undefined\n */\nexport const createContextAndHook = <CtxVal>(\n displayName: string,\n options?: Options\n): [ContextOf<CtxVal>, UseCtxFn<CtxVal>, UseCtxFn<CtxVal | Partial<CtxVal>>] => {\n const { assertCtxFn = assertContextExists } = options || {};\n const Ctx = React.createContext<{ value: CtxVal } | undefined>(undefined);\n Ctx.displayName = displayName;\n\n const useCtx = () => {\n const ctx = React.useContext(Ctx);\n assertCtxFn(ctx, `Component must be wrapped with the <Inbox /> Component`);\n\n return (ctx as any).value as CtxVal;\n };\n\n const useCtxWithoutGuarantee = () => {\n const ctx = React.useContext(Ctx);\n\n return ctx ? ctx.value : {};\n };\n\n return [Ctx, useCtx, useCtxWithoutGuarantee];\n};\n","import React from 'react';\nimport type { NovuUI } from '@novu/js/ui';\nimport { createContextAndHook } from '../utils/createContextAndHook';\n\nexport type MountedElement = React.ReactNode;\nexport type MountedElements = Map<HTMLElement, MountedElement>;\n\ntype RendererContextValue = {\n mountElement: (el: HTMLElement, mountedElement: MountedElement) => () => void;\n novuUI: NovuUI;\n};\n\nconst [RendererContext, useRendererContext] = createContextAndHook<RendererContextValue>('RendererContext');\n\nconst RendererProvider = (props: React.PropsWithChildren<{ value: RendererContextValue }>) => {\n return <RendererContext.Provider value={{ value: props.value }}>{props.children}</RendererContext.Provider>;\n};\n\nexport { useRendererContext as useRenderer, RendererProvider };\n","import React from 'react';\n\ntype MounterProps = {\n mount: (node: HTMLElement) => ((node: HTMLElement) => void) | void;\n};\n\n/**\n * Mounter allows you to mount a component to a DOM node.\n */\nexport function Mounter({ mount }: MounterProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n let unmount: (node: HTMLDivElement) => void | undefined;\n const element = ref.current;\n if (element && mount) {\n const possibleUnmount = mount(element);\n if (possibleUnmount) {\n unmount = possibleUnmount;\n }\n }\n\n return () => {\n if (element && unmount) {\n unmount(element);\n }\n };\n }, [ref, mount]);\n\n return <div ref={ref} />;\n}\n","import React, { useMemo } from 'react';\nimport { useRenderer } from '../context/RenderContext';\nimport { DefaultProps, DefaultInboxProps, WithChildrenProps } from '../utils/types';\nimport { NovuProvider, useNovu, useUnsafeNovu } from './index';\nimport { Mounter } from './Mounter';\nimport { Renderer } from './Renderer';\n\nexport type InboxProps = DefaultProps | WithChildrenProps;\n\nconst DefaultInbox = (props: DefaultInboxProps) => {\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Inbox',\n props: {\n open,\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n renderBell: renderBell ? (el, unreadCount) => mountElement(el, renderBell(unreadCount)) : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n element,\n });\n },\n [open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n};\n\nexport const Inbox = React.memo((props: InboxProps) => {\n const { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;\n const novu = useUnsafeNovu();\n\n if (novu) {\n return <InboxChild {...props} />;\n }\n\n return (\n <NovuProvider\n applicationIdentifier={applicationIdentifier}\n subscriberId={subscriberId}\n subscriberHash={subscriberHash}\n backendUrl={backendUrl}\n socketUrl={socketUrl}\n >\n <InboxChild {...props} />\n </NovuProvider>\n );\n});\n\nexport const InboxChild = React.memo((props: InboxProps) => {\n const {\n localization,\n appearance,\n tabs,\n preferencesFilter,\n routerPush,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n } = props;\n const novu = useNovu();\n\n const options = useMemo(() => {\n return {\n localization,\n appearance,\n tabs,\n preferencesFilter,\n routerPush,\n options: { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl },\n };\n }, [\n localization,\n appearance,\n tabs,\n preferencesFilter,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n ]);\n\n if (isWithChildrenProps(props)) {\n return (\n <Renderer options={options} novu={novu}>\n {props.children}\n </Renderer>\n );\n }\n\n const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } =\n props;\n\n return (\n <Renderer options={options} novu={novu}>\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 { Novu } from '@novu/js';\nimport { MountedElement, RendererProvider } from '../context/RenderContext';\nimport { useDataRef } from '../hooks/internal/useDataRef';\n\ntype RendererProps = React.PropsWithChildren<{\n options: NovuUIOptions;\n novu?: Novu;\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, novu, children }: RendererProps) => {\n const optionsRef = useDataRef({ ...options, novu });\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 novuUI.updateRouterPush(options.routerPush);\n novuUI.updatePreferencesFilter(options.preferencesFilter);\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 type { NotificationClickHandler, NotificationActionClickHandler } from '@novu/js/ui';\nimport { useRenderer } from '../context/RenderContext';\nimport { Mounter } from './Mounter';\nimport { NotificationsRenderer } from '../utils/types';\n\nexport type NotificationProps = {\n renderNotification?: NotificationsRenderer;\n onNotificationClick?: NotificationClickHandler;\n onPrimaryActionClick?: NotificationActionClickHandler;\n onSecondaryActionClick?: NotificationActionClickHandler;\n};\n\nexport const Notifications = React.memo((props: NotificationProps) => {\n const { onNotificationClick, onPrimaryActionClick, renderNotification, onSecondaryActionClick } = props;\n const { novuUI, mountElement } = useRenderer();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n return novuUI.mountComponent({\n name: 'Notifications',\n element,\n props: {\n renderNotification: renderNotification\n ? (el, notification) => mountElement(el, renderNotification(notification))\n : undefined,\n onNotificationClick,\n onPrimaryActionClick,\n onSecondaryActionClick,\n },\n });\n },\n [renderNotification, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick]\n );\n\n return <Mounter mount={mount} />;\n});\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n filter?: { tags?: string[] };\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list(props?.filter);\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["React","React","jsx","jsx","React","React","novu","jsx","React","React","jsx","React","React","jsx","React","useMemo","jsx","useState","useEffect","useRef","useRef","useState","useEffect","useEffect","useState","useState","useEffect","useEffect","useState","useEffect","useEffect","useState","useEffect","useState","useEffect"]}
@@ -33,6 +33,9 @@ declare const useNotifications: (props?: UseNotificationsProps) => {
33
33
  };
34
34
 
35
35
  type UsePreferencesProps = {
36
+ filter?: {
37
+ tags?: string[];
38
+ };
36
39
  onSuccess?: (data: Preference[]) => void;
37
40
  onError?: (error: NovuError) => void;
38
41
  };
@@ -33,6 +33,9 @@ declare const useNotifications: (props?: UseNotificationsProps) => {
33
33
  };
34
34
 
35
35
  type UsePreferencesProps = {
36
+ filter?: {
37
+ tags?: string[];
38
+ };
36
39
  onSuccess?: (data: Preference[]) => void;
37
40
  onError?: (error: NovuError) => void;
38
41
  };
@@ -178,7 +178,7 @@ var usePreferences = (props) => {
178
178
  }, []);
179
179
  const fetchPreferences = async () => {
180
180
  setIsFetching(true);
181
- const response = await preferences.list();
181
+ const response = await preferences.list(props?.filter);
182
182
  if (response.error) {
183
183
  setError(response.error);
184
184
  onError?.(response.error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/index.ts","../../src/hooks/useNotifications.ts","../../src/hooks/NovuProvider.tsx","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["export * from './useNotifications';\nexport * from './usePreferences';\nexport * from './useCounts';\nexport { NovuProvider, useNovu } from './NovuProvider';\n","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list();\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["import_react","import_js","import_react","import_react","import_js","import_react","import_react"]}
1
+ {"version":3,"sources":["../../src/hooks/index.ts","../../src/hooks/useNotifications.ts","../../src/hooks/NovuProvider.tsx","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["export * from './useNotifications';\nexport * from './usePreferences';\nexport * from './useCounts';\nexport { NovuProvider, useNovu } from './NovuProvider';\n","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n filter?: { tags?: string[] };\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list(props?.filter);\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["import_react","import_js","import_react","import_react","import_js","import_react","import_react"]}
@@ -148,7 +148,7 @@ var usePreferences = (props) => {
148
148
  }, []);
149
149
  const fetchPreferences = async () => {
150
150
  setIsFetching(true);
151
- const response = await preferences.list();
151
+ const response = await preferences.list(props?.filter);
152
152
  if (response.error) {
153
153
  setError(response.error);
154
154
  onError?.(response.error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/useNotifications.ts","../../src/hooks/NovuProvider.tsx","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list();\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["useEffect","useState","useState","useEffect","useEffect","useState","useEffect","useEffect","useState","useEffect","useState","useEffect"]}
1
+ {"version":3,"sources":["../../src/hooks/useNotifications.ts","../../src/hooks/NovuProvider.tsx","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts"],"sourcesContent":["import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n filter?: { tags?: string[] };\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list(props?.filter);\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["useEffect","useState","useState","useEffect","useEffect","useState","useEffect","useEffect","useState","useEffect","useState","useEffect"]}
@@ -1,4 +1,4 @@
1
- import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
1
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, PreferencesFilter, RouterPush } from '@novu/js/ui';
2
2
  export { Notification } from '@novu/js/ui';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
@@ -23,6 +23,7 @@ type BaseProps = {
23
23
  appearance?: Appearance;
24
24
  localization?: Localization;
25
25
  tabs?: Array<Tab>;
26
+ preferencesFilter?: PreferencesFilter;
26
27
  routerPush?: RouterPush;
27
28
  };
28
29
  type DefaultProps = BaseProps & DefaultInboxProps & {
@@ -69,6 +70,9 @@ declare const useNotifications: (props?: UseNotificationsProps) => {
69
70
  };
70
71
 
71
72
  type UsePreferencesProps = {
73
+ filter?: {
74
+ tags?: string[];
75
+ };
72
76
  onSuccess?: (data: Preference[]) => void;
73
77
  onError?: (error: NovuError) => void;
74
78
  };
@@ -1,4 +1,4 @@
1
- import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
1
+ import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, PreferencesFilter, RouterPush } from '@novu/js/ui';
2
2
  export { Notification } from '@novu/js/ui';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
@@ -23,6 +23,7 @@ type BaseProps = {
23
23
  appearance?: Appearance;
24
24
  localization?: Localization;
25
25
  tabs?: Array<Tab>;
26
+ preferencesFilter?: PreferencesFilter;
26
27
  routerPush?: RouterPush;
27
28
  };
28
29
  type DefaultProps = BaseProps & DefaultInboxProps & {
@@ -69,6 +70,9 @@ declare const useNotifications: (props?: UseNotificationsProps) => {
69
70
  };
70
71
 
71
72
  type UsePreferencesProps = {
73
+ filter?: {
74
+ tags?: string[];
75
+ };
72
76
  onSuccess?: (data: Preference[]) => void;
73
77
  onError?: (error: NovuError) => void;
74
78
  };
@@ -180,7 +180,7 @@ var usePreferences = (props) => {
180
180
  }, []);
181
181
  const fetchPreferences = async () => {
182
182
  setIsFetching(true);
183
- const response = await preferences.list();
183
+ const response = await preferences.list(props == null ? void 0 : props.filter);
184
184
  if (response.error) {
185
185
  setError(response.error);
186
186
  onError == null ? void 0 : onError(response.error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server.ts","../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.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\n//Hooks\nexport { NovuProvider } from './index';\nexport * from './hooks';\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list();\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["import_react","import_js","import_react","import_react","import_js","import_react","import_react"]}
1
+ {"version":3,"sources":["../../src/server.ts","../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.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\n//Hooks\nexport { NovuProvider } from './index';\nexport * from './hooks';\n","import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n filter?: { tags?: string[] };\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list(props?.filter);\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n"],"mappings":"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","names":["import_react","import_js","import_react","import_react","import_js","import_react","import_react"]}
@@ -146,7 +146,7 @@ var usePreferences = (props) => {
146
146
  }, []);
147
147
  const fetchPreferences = async () => {
148
148
  setIsFetching(true);
149
- const response = await preferences.list();
149
+ const response = await preferences.list(props == null ? void 0 : props.filter);
150
150
  if (response.error) {
151
151
  setError(response.error);
152
152
  onError == null ? void 0 : onError(response.error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts","../../src/server.ts"],"sourcesContent":["import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list();\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n","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\n//Hooks\nexport { NovuProvider } from './index';\nexport * from './hooks';\n"],"mappings":"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","names":["useEffect","useState","useState","useEffect","useEffect","useState","useEffect","useEffect","useState","useEffect","useState","useEffect"]}
1
+ {"version":3,"sources":["../../src/hooks/NovuProvider.tsx","../../src/hooks/useNotifications.ts","../../src/hooks/usePreferences.ts","../../src/hooks/useCounts.ts","../../src/hooks/internal/useWebsocketEvent.ts","../../src/utils/requestLock.ts","../../src/hooks/internal/useBrowserTabsChannel.ts","../../src/server.ts"],"sourcesContent":["import { Novu, NovuOptions } from '@novu/js';\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\n\ntype NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = ({\n children,\n applicationIdentifier,\n subscriberId,\n subscriberHash,\n backendUrl,\n socketUrl,\n useCache,\n}: NovuProviderProps) => {\n const novu = useMemo(\n () => new Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),\n [applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]\n );\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","import { useState, useEffect, useRef } from 'react';\nimport { ListNotificationsResponse, Notification, NovuError, isSameFilter, NotificationFilter } from '@novu/js';\nimport { useNovu } from './NovuProvider';\n\nexport type UseNotificationsProps = {\n tags?: string[];\n read?: boolean;\n archived?: boolean;\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps) => {\n const { tags, read, archived = false, limit, onSuccess, onError } = props || {};\n const filterRef = useRef<NotificationFilter | undefined>(undefined);\n const { notifications, on, off } = useNovu();\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 const sync = (event: { data?: ListNotificationsResponse }) => {\n if (!event.data || (filterRef.current && !isSameFilter(filterRef.current, event.data.filter))) {\n return;\n }\n setData(event.data.notifications);\n setHasMore(event.data.hasMore);\n };\n\n useEffect(() => {\n on('notifications.list.updated', sync);\n\n return () => {\n off('notifications.list.updated', sync);\n };\n }, []);\n\n useEffect(() => {\n const newFilter = { tags, read, archived };\n if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {\n return;\n }\n\n notifications.clearCache({ filter: filterRef.current });\n filterRef.current = newFilter;\n\n fetchNotifications({ refetch: true });\n }, [tags, read, archived]);\n\n const fetchNotifications = async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n const response = await notifications.list({\n tags,\n read,\n archived,\n limit,\n after: options?.refetch ? undefined : after,\n });\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!.notifications);\n setData(response.data!.notifications);\n setHasMore(response.data!.hasMore);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n notifications.clearCache({ filter: { tags, read, archived } });\n\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 return await notifications.readAll({ tags });\n };\n\n const archiveAll = async () => {\n return await notifications.archiveAll({ tags });\n };\n\n const archiveAllRead = async () => {\n return await notifications.archiveAllRead({ tags });\n };\n\n return {\n readAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n","import { NovuError, Preference } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\ntype UsePreferencesProps = {\n filter?: { tags?: string[] };\n onSuccess?: (data: Preference[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype UsePreferencesResult = {\n preferences?: Preference[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const usePreferences = (props?: UsePreferencesProps): UsePreferencesResult => {\n const { onSuccess, onError } = props || {};\n const [data, setData] = useState<Preference[]>();\n const { preferences, on, off } = useNovu();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = (event: { data?: Preference[] }) => {\n if (!event.data) {\n return;\n }\n setData(event.data);\n };\n\n useEffect(() => {\n fetchPreferences();\n\n on('preferences.list.updated', sync);\n on('preferences.list.pending', sync);\n on('preferences.list.resolved', sync);\n\n return () => {\n off('preferences.list.updated', sync);\n off('preferences.list.pending', sync);\n off('preferences.list.resolved', sync);\n };\n }, []);\n\n const fetchPreferences = async () => {\n setIsFetching(true);\n const response = await preferences.list(props?.filter);\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else {\n onSuccess?.(response.data!);\n }\n setIsLoading(false);\n setIsFetching(false);\n };\n\n const refetch = () => {\n preferences.cache.clearAll();\n\n return fetchPreferences();\n };\n\n return {\n preferences: data,\n error,\n isLoading,\n isFetching,\n refetch,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { Notification, NotificationFilter, NovuError, areTagsEqual } from '@novu/js';\nimport { useNovu } from './NovuProvider';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\ntype UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\ntype 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 [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification) => {\n const existingCounts = counts ?? (new Array(filters.length).fill(undefined) as (Count | undefined)[]);\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = filters[i];\n if (areTagsEqual(filter.tags, notification.tags)) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = filters;\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 // eslint-disable-next-line no-plusplus\n for (let i = 0; i < existingCounts.length; i++) {\n const countReceived = countsReceived.find((c) => areTagsEqual(c.filter.tags, existingCounts[i]?.filter.tags));\n\n newCounts.push(countReceived || oldCounts![i]);\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();\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n","import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { useNovu } from '../NovuProvider';\nimport { requestLock } from '../../utils/requestLock';\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 { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {\n novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n novu.off(webSocketEvent, updateReadCount);\n resolveLock();\n };\n }, []);\n};\n","export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!('locks' in navigator)) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n","import { useEffect, useState } from 'react';\n\nexport const useBrowserTabsChannel = <T = unknown>({\n channelName,\n onMessage,\n}: {\n channelName: string;\n onMessage: (args: T) => void;\n}) => {\n const [tabsChannel] = useState(\n typeof BroadcastChannel !== 'undefined' ? new BroadcastChannel(channelName) : undefined\n );\n\n const postMessage = (data: T) => {\n tabsChannel?.postMessage(data);\n };\n\n useEffect(() => {\n const listener = (event: MessageEvent<T>) => {\n onMessage(event.data);\n };\n\n tabsChannel?.addEventListener('message', listener);\n\n return () => {\n tabsChannel?.removeEventListener('message', listener);\n };\n }, []);\n\n return { postMessage };\n};\n","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\n//Hooks\nexport { NovuProvider } from './index';\nexport * from './hooks';\n"],"mappings":"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","names":["useEffect","useState","useState","useEffect","useEffect","useState","useEffect","useEffect","useState","useEffect","useState","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@novu/react",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "repository": "https://github.com/novuhq/novu",
5
5
  "description": "Novu's React SDK for building custom inbox notification experiences",
6
6
  "author": "",
@@ -50,7 +50,8 @@
50
50
  "build:watch": "tsup --watch",
51
51
  "build": "tsup && pnpm run check-exports",
52
52
  "lint": "eslint src",
53
- "check-exports": "attw --pack ."
53
+ "check-exports": "attw --pack .",
54
+ "release:preview": "pnpx pkg-pr-new publish"
54
55
  },
55
56
  "browserslist": {
56
57
  "production": [
@@ -70,7 +71,7 @@
70
71
  "@types/react": "*",
71
72
  "@types/react-dom": "*",
72
73
  "tsup": "^8.2.1",
73
- "typescript": "4.9.5"
74
+ "typescript": "5.6.2"
74
75
  },
75
76
  "peerDependencies": {
76
77
  "react": ">=17",
@@ -82,6 +83,6 @@
82
83
  }
83
84
  },
84
85
  "dependencies": {
85
- "@novu/js": "^2.1.1"
86
+ "@novu/js": "^2.2.0"
86
87
  }
87
88
  }