import React from 'react'; import { motion } from 'framer-motion'; import { cn } from '../utils/cn'; export interface EmptyStateProps { /** * Title of the empty state * @default 'Không có dữ liệu' */ title?: string; /** * Detailed message explaining the empty state * @default 'Không tìm thấy kết quả nào phù hợp với tiêu chí tìm kiếm.' */ message?: string; /** * Custom icon to display */ icon?: React.ReactNode; /** * Additional CSS class */ className?: string; /** * Whether to animate the empty state * @default true */ animate?: boolean; /** * Animation style for the empty state * @default 'fade-in' */ animationStyle?: 'fade-in' | 'slide-up' | 'scale-in' | 'none'; /** * Custom action button */ action?: React.ReactNode; /** * Icon size * @default 64 */ iconSize?: number | "sm" | "md" | "lg" | "xl"; /** * Disable the icon entirely * @default false */ hideIcon?: boolean; } export function EmptyState({ title = 'Không có dữ liệu', message = 'Không tìm thấy kết quả nào phù hợp với tiêu chí tìm kiếm.', icon, className, animate = true, animationStyle = 'fade-in', action, iconSize = 64, hideIcon = false }: EmptyStateProps): React.ReactElement { // Add a conversion function for the iconSize prop const getIconSizeValue = () => { if (typeof iconSize === 'number') return iconSize; switch(iconSize) { case 'sm': return 32; case 'md': return 48; case 'lg': return 64; case 'xl': return 80; default: return 64; } }; // Animation variants based on style const getAnimationVariants = () => { switch (animationStyle) { case 'slide-up': return { container: { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { when: "beforeChildren", staggerChildren: 0.2 } } }, item: { hidden: { y: 20, opacity: 0 }, visible: { y: 0, opacity: 1 } } }; case 'scale-in': return { container: { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { when: "beforeChildren", staggerChildren: 0.2 } } }, item: { hidden: { scale: 0.8, opacity: 0 }, visible: { scale: 1, opacity: 1 } } }; case 'fade-in': default: return { container: { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { when: "beforeChildren", staggerChildren: 0.1 } } }, item: { hidden: { opacity: 0 }, visible: { opacity: 1 } } }; } }; const { container: containerVariants, item: itemVariants } = getAnimationVariants(); // Default empty state icon const defaultIcon = ( ); // If animations are disabled, render without motion if (!animate || animationStyle === 'none') { return (
{!hideIcon && (
{icon || defaultIcon}
)}

{title}

{message}

{action && (
{action}
)}
); } // With animations return ( {!hideIcon && ( {icon || defaultIcon} )} {title} {message} {action && ( {action} )} ); } export default EmptyState;