import { Loader2 } from 'lucide-react'; import { cn } from '@/lib/utils'; /** * LoadingSpinnerProps - Propriétés du composant LoadingSpinner * * @interface LoadingSpinnerProps */ interface LoadingSpinnerProps { /** * Taille du spinner * * - `sm`: Petit (h-4 w-4 en inline, h-4 w-4 en block) * - `md`: Moyen (h-5 w-5 en inline, h-8 w-8 en block) - par défaut * - `lg`: Grand (h-6 w-6 en inline, h-12 w-12 en block) * * @default 'md' */ size?: 'sm' | 'md' | 'lg'; /** * Classes CSS personnalisées */ className?: string; /** * Texte à afficher sous le spinner (ignoré en mode inline) * * @example * ```tsx * * ``` */ text?: string; /** * Mode inline pour boutons et éléments compacts. * Rend uniquement l'icône sans conteneur. */ inline?: boolean; /** * Variant visuel (uniquement en mode inline) */ variant?: 'default' | 'muted' | 'white' | 'current'; /** * Label d'accessibilité */ 'aria-label'?: string; } /** * LoadingSpinner - Composant de spinner de chargement * * Composant de spinner animé pour indiquer un état de chargement. * Inclut un texte optionnel et supporte plusieurs tailles. * * @example * ```tsx * // Spinner simple * * * // Spinner avec texte * * * // Spinner de grande taille * * ``` * * @component * @param {LoadingSpinnerProps} props - Propriétés du composant * @returns {JSX.Element} Spinner animé avec texte optionnel */ const variantClasses = { default: 'text-primary', muted: 'text-muted-foreground', white: 'text-foreground', current: 'text-current', } as const; const blockSizeClasses = { sm: 'h-4 w-4', md: 'h-8 w-8', lg: 'h-12 w-12', }; const inlineSizeClasses = { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6', }; export function LoadingSpinner({ size = 'md', className, text, inline = false, variant = 'default', 'aria-label': ariaLabel = 'Chargement en cours', }: LoadingSpinnerProps) { if (inline) { return ( <>