import React, { forwardRef, HTMLAttributes } from 'react'; import { cn } from '../../lib/utils'; // Loading sizes type LoadingSize = 'sm' | 'md' | 'lg' | 'xl'; // Loading variants type LoadingVariant = 'primary' | 'secondary' | 'neutral' | 'contrast'; // Loading props interface interface LoadingProps extends HTMLAttributes { size?: LoadingSize; variant?: LoadingVariant; overlay?: boolean; text?: string; fullscreen?: boolean; } // Helper function to get size styles const getSizeStyles = (size: LoadingSize) => { switch (size) { case 'sm': return 'w-4 h-4 border-2'; case 'md': return 'w-8 h-8 border-4'; case 'lg': return 'w-12 h-12 border-4'; case 'xl': return 'w-16 h-16 border-4'; default: return 'w-8 h-8 border-4'; } }; // Helper function to get variant styles const getVariantStyles = (variant: LoadingVariant) => { switch (variant) { case 'primary': return 'border-primary'; case 'secondary': return 'border-secondary'; case 'neutral': return 'border-gray-300'; case 'contrast': return 'border-white'; default: return 'border-primary'; } }; // Helper function to get text size const getTextSize = (size: LoadingSize) => { switch (size) { case 'sm': return 'text-sm'; case 'md': return 'text-base'; case 'lg': return 'text-lg'; case 'xl': return 'text-xl'; default: return 'text-base'; } }; // Main Loading Component export const Loading = forwardRef( ({ size = 'md', variant = 'primary', overlay = false, text, fullscreen = false, className = '', ...props }, ref) => { const spinner = ( ); if (overlay) { return ( {spinner} {text && ( {text} )} ); } return ( {spinner} {text && ( {text} )} ); } ); Loading.displayName = 'Loading'; // Loading Button Component interface LoadingButtonProps extends HTMLAttributes { size?: LoadingSize; variant?: LoadingVariant; text?: string; } export const LoadingButton = forwardRef( ({ size = 'md', variant = 'primary', text = 'Loading...', className = '', ...props }, ref) => { return ( {text} ); } ); LoadingButton.displayName = 'LoadingButton'; // Loading Skeleton Component interface LoadingSkeletonProps extends HTMLAttributes { width?: string | number; height?: string | number; rounded?: boolean; className?: string; } export const LoadingSkeleton = forwardRef( ({ width = '100%', height = '1rem', rounded = false, className = '', ...props }, ref) => { // Convert numeric values to Tailwind width classes const getWidthClass = (width: string | number) => { if (typeof width === 'number') { if (width <= 32) return 'w-8'; if (width <= 64) return 'w-16'; if (width <= 128) return 'w-32'; if (width <= 192) return 'w-48'; if (width <= 256) return 'w-64'; return 'w-full'; } return width === '100%' ? 'w-full' : width; }; // Convert numeric values to Tailwind height classes const getHeightClass = (height: string | number) => { if (typeof height === 'number') { if (height <= 8) return 'h-2'; if (height <= 16) return 'h-4'; if (height <= 24) return 'h-6'; if (height <= 32) return 'h-8'; if (height <= 48) return 'h-12'; if (height <= 64) return 'h-16'; return 'h-auto'; } return height === '1rem' ? 'h-4' : height; }; return ( ); } ); LoadingSkeleton.displayName = 'LoadingSkeleton'; // Export types for external use export type { LoadingProps, LoadingSize, LoadingVariant, LoadingButtonProps, LoadingSkeletonProps };