// @ts-nocheck import { h, createContext, type FunctionComponent } from 'preact' import { useContext, useReducer } from 'preact/hooks' type MessageType = 'error' | 'info' | 'success' type Payload = { id: number message: string type: MessageType dismiss?: () => void } type Action = { type: typeof NOTIFY | typeof DISMISS payload: Payload } const NotificationsContext = createContext<{ notifications: ANY[] notify: ((message: string, type?: MessageType, timeout?: number) => void) & { error: (message: string, timeout?: number) => void info: (message: string, timeout?: number) => void success: (message: string, timeout?: number) => void } }>() const NOTIFY = 'notify' export const notifyAction = (message: string, type: MessageType): Action => ({ type: NOTIFY, payload: { id: counter++, message, type, }, }) const DISMISS = 'dismiss' export const dismissAction = (id: number) => ({ type: DISMISS, id, }) let counter = 0 export const reducer = (state: Payload[], action: Action) => { switch (action.type) { case NOTIFY: return state.concat(action.payload) case DISMISS: { const index = state.findIndex((notification) => notification.id === action.id) if (index > -1) { return [...state.slice(0, index), ...state.slice(index + 1)] } return state } default: return state } } export const useNotifications = () => useContext(NotificationsContext) export const NotificationsProvider: FunctionComponent<{ defaultTimeout?: number }> = ({ children, defaultTimeout = 0, }) => { const [notifications, dispatch] = useReducer(reducer, []) function notify(message: string, type: MessageType = 'info', timeout = defaultTimeout) { const action = notifyAction(message, type) const dismiss = (action.payload.dismiss = () => dispatch(dismissAction(action.payload.id))) dispatch(action) if (timeout) { setTimeout(dismiss, timeout) } return dismiss } notify.error = (message: string, timeout?: number) => notify(message, 'error', timeout) notify.success = (message: string, timeout?: number) => notify(message, 'success', timeout) notify.info = (message: string, timeout?: number) => notify(message, 'info', timeout) return {children} }