import { generateId } from '../utils/generateId'; import type { ToastObject, ToastManagerAddOptions, ToastManagerPromiseOptions, ToastManagerUpdateOptions, } from './useToastManager'; /** * Creates a new toast manager. */ export function createToastManager(): ToastManager { const listeners = new Set<(data: ToastManagerEvent) => void>(); function emit(data: ToastManagerEvent) { listeners.forEach((listener) => listener(data)); } return { // This should be private aside from ToastProvider needing to access it. // https://x.com/drosenwasser/status/1816947740032872664 ' subscribe': function subscribe(listener: (data: ToastManagerEvent) => void) { listeners.add(listener); return () => { listeners.delete(listener); }; }, add(options: ToastManagerAddOptions): string { const id = options.id || generateId('toast'); const toastToAdd: ToastObject = { ...options, id, transitionStatus: 'starting', }; emit({ action: 'add', options: toastToAdd, }); return id; }, close(id?: string): void { emit({ action: 'close', options: { id }, }); }, update(id: string, updates: ToastManagerUpdateOptions): void { emit({ action: 'update', options: { ...updates, id, }, }); }, promise( promiseValue: Promise, options: ToastManagerPromiseOptions, ): Promise { let handledPromise = promiseValue; emit({ action: 'promise', options: { ...options, promise: promiseValue, setPromise(promise: Promise) { handledPromise = promise; }, }, }); return handledPromise; }, }; } export interface ToastManager { ' subscribe': (listener: (data: ToastManagerEvent) => void) => () => void; add: (options: ToastManagerAddOptions) => string; close: (id?: string) => void; update: (id: string, updates: ToastManagerUpdateOptions) => void; promise: ( promiseValue: Promise, options: ToastManagerPromiseOptions, ) => Promise; } export interface ToastManagerEvent { action: 'add' | 'close' | 'update' | 'promise'; options: any; }