import { cn } from '@cherrystudio/ui/utils' import { cva } from 'class-variance-authority' import { Loader2Icon } from 'lucide-react' import { type ReactNode, type SVGProps, useCallback, useMemo } from 'react' import { toast as sonnerToast, Toaster as Sonner, type ToasterProps } from 'sonner' const InfoIcon = ({ className }: SVGProps) => (
) const WarningIcon = ({ className }: SVGProps) => ( ) const SuccessIcon = ({ className }: SVGProps) => (
) const ErrorIcon = ({ className }: SVGProps) => (
) const CloseIcon = ({ className }: SVGProps) => ( ) interface ToastProps { id: string | number type: 'info' | 'warning' | 'error' | 'success' | 'loading' title: string description?: string coloredMessage?: string coloredBackground?: boolean dismissable?: boolean onDismiss?: () => void button?: { icon?: ReactNode label: string onClick: () => void } link?: { label: string href?: string onClick?: () => void } promise?: Promise } function toast(props: Omit) { return sonnerToast.custom((id) => ) } interface QuickApiProps extends Omit {} interface QuickLoadingProps extends QuickApiProps { promise: ToastProps['promise'] } toast.info = (props: QuickApiProps) => { toast({ type: 'info', ...props }) } toast.success = (props: QuickApiProps) => { toast({ type: 'success', ...props }) } toast.warning = (props: QuickApiProps) => { toast({ type: 'warning', ...props }) } toast.error = (props: QuickApiProps) => { toast({ type: 'error', ...props }) } toast.loading = (props: QuickLoadingProps) => { toast({ type: 'loading', ...props }) } toast.dismiss = (id: ToastProps['id']) => { sonnerToast.dismiss(id) } const toastColorVariants = cva(undefined, { variants: { type: { info: 'text-blue-500', warning: 'text-warning-base', error: 'text-error-base', success: 'text-success-base', loading: 'text-foreground-muted' } } }) const toastBgColorVariants = cva(undefined, { variants: { type: { info: 'bg-blue-50 border-blue-400', warning: 'bg-warning-bg border-warning-base', error: 'bg-error-bg border-error-base', success: 'bg-success-bg border-success-base', loading: undefined } } }) function Toast({ id, type, title, description, coloredMessage, coloredBackground, dismissable, onDismiss, button, link }: ToastProps) { const icon = useMemo(() => { switch (type) { case 'info': return case 'error': return case 'loading': return case 'success': return case 'warning': return } }, [type]) const handleDismiss = useCallback(() => { sonnerToast.dismiss(id) onDismiss?.() }, [id, onDismiss]) return (
{dismissable && ( )}
{icon}
{title}

{coloredMessage && {coloredMessage} } {description}

{link && ( // FIXME: missing typography/typography components/p/letter-spacing )}
{button !== undefined && ( )}
) } const Toaster = ({ ...props }: ToasterProps) => { return } export { toast, Toaster }