import React, { useMemo, type ComponentPropsWithoutRef, type ReactNode } from 'react'; import { tv, type VariantProps } from 'tailwind-variants'; import { type ReactNodeExcluded } from '../../types'; import { cn } from '../../utils/cn'; import { Avatar, type AvatarProps } from '../avatar'; import { Button, ButtonClose, type ButtonProps } from '../button'; import { AlertCircleIcon, CheckCircleIcon, FeaturedIcon } from '../icons'; import { Show } from '../utility'; export interface NotificationActionProps extends React.HTMLAttributes { confirmLabel?: string; cancelLabel?: string; actionBtnProps?: ButtonProps; cancelBtnProps?: ButtonProps; hideConfirm?: boolean; hideCancel?: boolean; onConfirm?: () => void; onCancel?: () => void; } const NotificationAction = React.forwardRef((props, ref) => { const { className, confirmLabel = 'Confirm', cancelLabel = 'Dismiss', hideConfirm = false, hideCancel = false, onConfirm, onCancel, actionBtnProps, cancelBtnProps, children, ...etc } = props; return (
{!hideCancel ? ( ) : null} {!hideConfirm ? ( ) : null} {children}
); }); export interface NotificationContentProps extends Pick, 'className'> { title?: ReactNode; description?: ReactNode; } const NotificationContent = React.forwardRef( ({ className, title, description, ...props }, ref) => { return (
{title}
{description}
); } ); const notificationVariants = tv({ base: 'border-border bg-background relative flex w-full gap-4 overflow-hidden rounded-xl border p-4 shadow-lg [@media(min-width:37.5rem)]:w-[370px] [@media(min-width:48rem)]:w-[400px]', variants: { variant: { none: '', icon: '', image: 'p-0', avatar: '', }, }, defaultVariants: { variant: 'icon', }, compoundVariants: [], }); export interface NotificationProps extends NotificationContentProps, VariantProps { hideCloseIcon?: boolean; onClose?: () => void; icon?: 'success' | 'warning' | 'error' | ReactNodeExcluded; src?: string; avatarProps?: AvatarProps; imgProps?: ComponentPropsWithoutRef<'img'>; actionProps?: NotificationActionProps; children?: ReactNode; } const Notification = React.forwardRef((props, ref) => { const { className, variant = 'icon', onClose, hideCloseIcon, imgProps, title, description, avatarProps, src, icon, actionProps, children, ...etc } = props; const renderIcon = useMemo(() => { if (variant === 'avatar') { return ; } if (variant !== 'icon') return null; switch (icon) { case 'success': return ; case 'warning': return ; case 'error': return ; default: return ( {icon} ); } }, [variant, icon, src, avatarProps]); return (
{!hideCloseIcon ? : null}
{children} {actionProps !== undefined ? ( { actionProps.onCancel?.(); onClose?.(); }} onConfirm={() => { actionProps.onConfirm?.(); onClose?.(); }} /> ) : null}
{renderIcon}
{children} {actionProps !== undefined ? ( { actionProps.onCancel?.(); onClose?.(); }} onConfirm={() => { actionProps.onConfirm?.(); onClose?.(); }} /> ) : null}
); }); export { Notification, NotificationAction, notificationVariants };