'use client'; /** * Global toast API - can be imported directly like Sonner * import { toast } from 'vyrn'; */ import React from 'react'; import { getToastStore } from './toastStore'; import { ToastProps, ToastType } from '../types'; type ToastFunction = { (content: React.ReactNode, options?: Partial>): string; // Default type success: ( content: React.ReactNode, options?: Partial> ) => string; error: ( content: React.ReactNode, options?: Partial> ) => string; info: ( content: React.ReactNode, options?: Partial> ) => string; warning: ( content: React.ReactNode, options?: Partial> ) => string; default: ( content: React.ReactNode, options?: Partial> ) => string; custom: ( content: React.ReactNode, options?: Partial> ) => string; promise: ( promise: Promise | (() => Promise), options: { loading?: React.ReactNode; success?: React.ReactNode | ((data: T) => React.ReactNode); error?: React.ReactNode | ((error: any) => React.ReactNode); description?: React.ReactNode; duration?: number; onSuccess?: (data: T) => void; onError?: (error: any) => void; cancel?: { label: string; onClick?: () => void; }; } ) => string; loading: ( content: React.ReactNode, options?: Partial> ) => string; dismiss: (id: string) => void; update: (id: string, updates: Partial>) => void; clearAll: () => void; }; const createToastFunction = (): ToastFunction => { const baseToast = ( content: React.ReactNode, options?: Partial>, type: ToastType = 'default' ): string => { const store = getToastStore(); return store.addToast({ content, type, ...options, }); }; const toastFn = baseToast as ToastFunction; // Add type-specific methods toastFn.success = (content: React.ReactNode, options?: Partial>) => { return baseToast(content, options, 'success'); }; toastFn.error = (content: React.ReactNode, options?: Partial>) => { return baseToast(content, options, 'error'); }; toastFn.info = (content: React.ReactNode, options?: Partial>) => { return baseToast(content, options, 'info'); }; toastFn.warning = (content: React.ReactNode, options?: Partial>) => { return baseToast(content, options, 'warning'); }; toastFn.default = (content: React.ReactNode, options?: Partial>) => { return baseToast(content, options, 'default'); }; toastFn.custom = (content: React.ReactNode, options?: Partial>) => { return baseToast(content, options, 'custom'); }; // Promise-based toast toastFn.promise = ( promise: Promise | (() => Promise), options: { loading?: React.ReactNode; success?: React.ReactNode | ((data: T) => React.ReactNode); error?: React.ReactNode | ((error: any) => React.ReactNode); description?: React.ReactNode; duration?: number; onSuccess?: (data: T) => void; onError?: (error: any) => void; cancel?: { label: string; onClick?: () => void; }; } ): string => { const store = getToastStore(); const promiseFn = typeof promise === 'function' ? promise() : promise; const loadingId = store.addToast({ content: options.loading || 'Loading...', description: options.description, type: 'info', status: 'loading', duration: 0, cancel: options.cancel, }); promiseFn .then((data) => { const successContent = typeof options.success === 'function' ? options.success(data) : options.success || 'Success!'; store.updateToast(loadingId, { content: successContent, type: 'success', status: 'success', duration: options.duration || 3000, cancel: undefined, }); options.onSuccess?.(data); }) .catch((error) => { const errorContent = typeof options.error === 'function' ? options.error(error) : options.error || 'Something went wrong'; store.updateToast(loadingId, { content: errorContent, type: 'error', status: 'error', duration: options.duration || 5000, cancel: undefined, }); options.onError?.(error); }); return loadingId; }; // Loading toast toastFn.loading = ( content: React.ReactNode, options?: Partial> ): string => { return baseToast(content, { ...options, status: 'loading', duration: 0 }, 'info'); }; // Utility methods toastFn.dismiss = (id: string) => { const store = getToastStore(); store.removeToast(id); }; toastFn.update = (id: string, updates: Partial>) => { const store = getToastStore(); store.updateToast(id, updates); }; toastFn.clearAll = () => { const store = getToastStore(); store.clearAllToasts(); }; return toastFn; }; // Export the toast function export const toast = createToastFunction();