"use client" import * as React from "react" import * as ToastPrimitives from "@radix-ui/react-toast" import { cva, type VariantProps } from "class-variance-authority" import { X, CheckCircle, AlertCircle, AlertTriangle, Info } from "lucide-react" import { cn } from "@/lib/utils" const toastVariants = cva( "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-lg border p-6 pe-8 shadow-lg transition-all data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:animate-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:animate-out", { variants: { variant: { default: "border-border bg-card text-foreground", destructive: "border-destructive bg-destructive text-destructive-foreground", success: "border-success bg-success text-success-foreground", warning: "border-warning bg-warning text-warning-foreground", info: "border-primary bg-primary text-primary-foreground", glass: "glass text-foreground border-border/20", }, size: { default: "max-w-md", sm: "max-w-sm", lg: "max-w-lg", xl: "max-w-xl", full: "max-w-full", }, }, defaultVariants: { variant: "default", size: "default", }, } ) const ToastProvider = ToastPrimitives.Provider const ToastViewport = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) ToastViewport.displayName = ToastPrimitives.Viewport.displayName const Toast = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef & VariantProps & { icon?: React.ReactNode title?: string description?: string action?: React.ReactNode duration?: number } >(({ className, variant, size, icon, title, description, action, duration = 5000, ...props }, ref) => { const [open, setOpen] = React.useState(true) const defaultIcons = { default: , destructive: , success: , warning: , info: , glass: , } const displayIcon = icon || defaultIcons[variant as keyof typeof defaultIcons] || defaultIcons.default return (
{displayIcon && (
{displayIcon}
)}
{title && ( {title} )} {description && ( {description} )}
{action && ( {action} )}
) }) Toast.displayName = ToastPrimitives.Root.displayName const ToastAction = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) ToastAction.displayName = ToastPrimitives.Action.displayName const ToastClose = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) ToastClose.displayName = ToastPrimitives.Close.displayName const ToastTitle = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) ToastTitle.displayName = ToastPrimitives.Title.displayName const ToastDescription = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) ToastDescription.displayName = ToastPrimitives.Description.displayName type ToastProps = React.ComponentPropsWithoutRef type ToastActionElement = React.ReactElement<{ altText: string onClick: () => void }> // Enhanced Toast Hook export function useToast() { const [toasts, setToasts] = React.useState["variant"] duration?: number action?: React.ReactNode icon?: React.ReactNode }>>([]) const toast = React.useCallback( ({ title, description, variant = "default", duration = 5000, action, icon }: Omit) => { const id = Math.random().toString(36).substr(2, 9) setToasts(prev => [...prev, { id, title, description, variant, duration, action, icon, }]) // Auto remove after duration setTimeout(() => { setToasts(prev => prev.filter(toast => toast.id !== id)) }, duration) }, [] ) const success = React.useCallback( (props: Omit) => toast({ ...props, variant: "success" }), [toast] ) const error = React.useCallback( (props: Omit) => toast({ ...props, variant: "destructive" }), [toast] ) const warning = React.useCallback( (props: Omit) => toast({ ...props, variant: "warning" }), [toast] ) const info = React.useCallback( (props: Omit) => toast({ ...props, variant: "info" }), [toast] ) const dismiss = React.useCallback((id: string) => { setToasts(prev => prev.filter(toast => toast.id !== id)) }, []) const dismissAll = React.useCallback(() => { setToasts([]) }, []) return { toast, success, error, warning, info, dismiss, dismissAll, toasts, } } // Toast Container Component export const ToastContainer = ({ children }: { children: React.ReactNode }) => { return ( {children} ) } // Individual Toast Component for use in ToastContainer export const ToastItem = React.forwardRef< HTMLLIElement, { toast: { id: string title?: string description?: string variant?: VariantProps["variant"] duration?: number action?: React.ReactNode icon?: React.ReactNode } onDismiss: (id: string) => void } >(({ toast, onDismiss, ...props }, ref) => { return (
  • { if (!open) { onDismiss(toast.id) } }} {...props} />
  • ) }) ToastItem.displayName = "ToastItem" export { type ToastProps, ToastProvider, ToastViewport, Toast, ToastTitle, ToastDescription, ToastClose, ToastAction, }