UNPKG

react-toastify

Version:
1 lines 11.3 kB
{"version":3,"sources":["../../src/addons/use-notification-center/useNotificationCenter.ts"],"sourcesContent":["import { useState, useEffect, useRef } from 'react';\nimport { toast, ToastItem, Id } from 'react-toastify';\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;\n\nexport interface NotificationCenterItem<Data = {}> extends Optional<ToastItem<Data>, 'content' | 'data' | 'status'> {\n read: boolean;\n createdAt: number;\n}\n\nexport type SortFn<Data> = (l: NotificationCenterItem<Data>, r: NotificationCenterItem<Data>) => number;\n\nexport type FilterFn<Data = {}> = (item: NotificationCenterItem<Data>) => boolean;\n\nexport interface UseNotificationCenterParams<Data = {}> {\n /**\n * initial data to rehydrate the notification center\n */\n data?: NotificationCenterItem<Data>[];\n\n /**\n * By default, the notifications are sorted from the newest to the oldest using\n * the `createdAt` field. Use this to provide your own sort function\n *\n * Usage:\n * ```\n * // old notifications first\n * useNotificationCenter({\n * sort: ((l, r) => l.createdAt - r.createdAt)\n * })\n * ```\n */\n sort?: SortFn<Data>;\n\n /**\n * Keep the toast that meets the condition specified in the callback function.\n *\n * Usage:\n * ```\n * // keep only the toasts when hidden is set to false\n * useNotificationCenter({\n * filter: item => item.data.hidden === false\n * })\n * ```\n */\n filter?: FilterFn<Data>;\n}\n\nexport interface UseNotificationCenter<Data> {\n /**\n * Contains all the notifications\n */\n notifications: NotificationCenterItem<Data>[];\n\n /**\n * Clear all notifications\n */\n clear(): void;\n\n /**\n * Mark all notification as read\n */\n markAllAsRead(): void;\n\n /**\n * Mark all notification as read or not.\n *\n * Usage:\n * ```\n * markAllAsRead(false) // mark all notification as not read\n *\n * markAllAsRead(true) // same as calling markAllAsRead()\n * ```\n */\n markAllAsRead(read?: boolean): void;\n\n /**\n * Mark one or more notifications as read.\n *\n * Usage:\n * ```\n * markAsRead(\"anId\")\n * markAsRead([\"a\",\"list\", \"of\", \"id\"])\n * ```\n */\n markAsRead(id: Id | Id[]): void;\n\n /**\n * Mark one or more notifications as read.The second parameter let you mark the notification as read or not.\n *\n * Usage:\n * ```\n * markAsRead(\"anId\", false)\n * markAsRead([\"a\",\"list\", \"of\", \"id\"], false)\n *\n * markAsRead(\"anId\", true) // same as markAsRead(\"anId\")\n * ```\n */\n markAsRead(id: Id | Id[], read?: boolean): void;\n\n /**\n * Remove one or more notifications\n *\n * Usage:\n * ```\n * remove(\"anId\")\n * remove([\"a\",\"list\", \"of\", \"id\"])\n * ```\n */\n remove(id: Id | Id[]): void;\n\n /**\n * Push a notification to the notification center.\n * Returns null when an item with the given id already exists\n *\n * Usage:\n * ```\n * const id = add({id: \"id\", content: \"test\", data: { foo: \"hello\" } })\n *\n * // Return the id of the notification, generate one if none provided\n * const id = add({ data: {title: \"a title\", text: \"some text\"} })\n * ```\n */\n add(item: Partial<NotificationCenterItem<Data>>): Id | null;\n\n /**\n * Update the notification that match the id\n * Returns null when no matching notification found\n *\n * Usage:\n * ```\n * const id = update(\"anId\", {content: \"test\", data: { foo: \"hello\" } })\n *\n * // It's also possible to update the id\n * const id = update(\"anId\"m { id:\"anotherOne\", data: {title: \"a title\", text: \"some text\"} })\n * ```\n */\n update(id: Id, item: Partial<NotificationCenterItem<Data>>): Id | null;\n\n /**\n * Retrieve one or more notifications\n *\n * Usage:\n * ```\n * find(\"anId\")\n * find([\"a\",\"list\", \"of\", \"id\"])\n * ```\n */\n find(id: Id): NotificationCenterItem<Data> | undefined;\n\n /**\n * Retrieve one or more notifications\n *\n * Usage:\n * ```\n * find(\"anId\")\n * find([\"a\",\"list\", \"of\", \"id\"])\n * ```\n */\n find(id: Id[]): NotificationCenterItem<Data>[] | undefined;\n\n /**\n * Retrieve the count for unread notifications\n */\n unreadCount: number;\n\n /**\n * Sort notifications using the newly provided function\n *\n * Usage:\n * ```\n * // old notifications first\n * sort((l, r) => l.createdAt - r.createdAt)\n * ```\n */\n sort(sort: SortFn<Data>): void;\n}\n\nexport function useNotificationCenter<Data = {}>(\n params: UseNotificationCenterParams<Data> = {}\n): UseNotificationCenter<Data> {\n const sortFn = useRef(params.sort || defaultSort);\n const filterFn = useRef(params.filter || null);\n const [notifications, setNotifications] = useState<NotificationCenterItem<Data>[]>(() => {\n if (params.data) {\n return filterFn.current\n ? params.data.filter(filterFn.current).sort(sortFn.current)\n : [...params.data].sort(sortFn.current);\n }\n return [];\n });\n\n useEffect(() => {\n return toast.onChange(item => {\n if (item.status === 'added' || item.status === 'updated') {\n const newItem = decorate(item as NotificationCenterItem<Data>);\n if (filterFn.current && !filterFn.current(newItem)) return;\n\n setNotifications(prev => {\n let nextState: NotificationCenterItem<Data>[] = [];\n const updateIdx = prev.findIndex(v => v.id === newItem.id);\n\n if (updateIdx !== -1) {\n nextState = prev.slice();\n Object.assign(nextState[updateIdx], newItem, {\n createdAt: Date.now()\n });\n } else if (prev.length === 0) {\n nextState = [newItem];\n } else {\n nextState = [newItem, ...prev];\n }\n return nextState.sort(sortFn.current);\n });\n }\n });\n }, []);\n\n const remove = (id: Id | Id[]) => {\n setNotifications(prev => prev.filter(Array.isArray(id) ? v => !id.includes(v.id) : v => v.id !== id));\n };\n\n const clear = () => {\n setNotifications([]);\n };\n\n const markAllAsRead = (read = true) => {\n setNotifications(prev =>\n prev.map(v => {\n v.read = read;\n return v;\n })\n );\n };\n\n const markAsRead = (id: Id | Id[], read = true) => {\n let map = (v: NotificationCenterItem<Data>) => {\n if (v.id === id) v.read = read;\n return v;\n };\n\n if (Array.isArray(id)) {\n map = v => {\n if (id.includes(v.id)) v.read = read;\n return v;\n };\n }\n\n setNotifications(prev => prev.map(map));\n };\n\n const find = (id: Id | Id[]) => {\n return Array.isArray(id) ? notifications.filter(v => id.includes(v.id)) : notifications.find(v => v.id === id);\n };\n\n const add = (item: Partial<NotificationCenterItem<Data>>) => {\n if (notifications.find(v => v.id === item.id)) return null;\n\n const newItem = decorate(item);\n\n setNotifications(prev => [...prev, newItem].sort(sortFn.current));\n\n return newItem.id;\n };\n\n const update = (id: Id, item: Partial<NotificationCenterItem<Data>>) => {\n const index = notifications.findIndex(v => v.id === id);\n\n if (index !== -1) {\n setNotifications(prev => {\n const nextState = [...prev];\n Object.assign(nextState[index], item, {\n createdAt: item.createdAt || Date.now()\n });\n\n return nextState.sort(sortFn.current);\n });\n\n return item.id as Id;\n }\n\n return null;\n };\n\n const sort = (compareFn: SortFn<Data>) => {\n sortFn.current = compareFn;\n setNotifications(prev => prev.slice().sort(compareFn));\n };\n\n return {\n notifications,\n clear,\n markAllAsRead,\n markAsRead,\n add,\n update,\n remove,\n // @ts-ignore fixme: overloading issue\n find,\n sort,\n get unreadCount() {\n return notifications.reduce((prev, cur) => (!cur.read ? prev + 1 : prev), 0);\n }\n };\n}\n\nexport function decorate<Data>(item: NotificationCenterItem<Data> | Partial<NotificationCenterItem<Data>>) {\n if (item.id == null) item.id = Date.now().toString(36).substring(2, 9);\n if (!item.createdAt) item.createdAt = Date.now();\n if (item.read == null) item.read = false;\n return item as NotificationCenterItem<Data>;\n}\n\n// newest to oldest\nfunction defaultSort<Data>(l: NotificationCenterItem<Data>, r: NotificationCenterItem<Data>) {\n return r.createdAt - l.createdAt;\n}\n"],"mappings":"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","names":["useState","useEffect","useRef","toast","useNotificationCenter","params","sortFn","defaultSort","filterFn","notifications","setNotifications","item","newItem","decorate","prev","nextState","updateIdx","v","read","id","map","index","compareFn","cur","l","r"]}