import { type CSSProperties, type HTMLAttributes } from 'react'; import { useReducedMotion } from '../../hooks/useReducedMotion'; export interface SkeletonBlockProps extends HTMLAttributes { width?: number | string; height?: number | string; rounded?: 'sm' | 'md' | 'lg' | 'xl' | 'full'; animated?: boolean; } export interface LoadingProgressBarProps { progress?: number; label?: string; } export interface LoadingFallbackProps { label?: string; detail?: string; progress?: number; compact?: boolean; } const roundedClass = { sm: 'rounded', md: 'rounded-md', lg: 'rounded-lg', xl: 'rounded-xl', full: 'rounded-full', }; export function SkeletonBlock({ width = '100%', height = 16, rounded = 'md', animated = true, className, style, ...props }: SkeletonBlockProps): JSX.Element { const reduceMotion = useReducedMotion(); const blockStyle: CSSProperties = { width, height, ...style, }; return ( ); } export function LoadingProgressBar({ progress, label = 'Loading', }: LoadingProgressBarProps): JSX.Element { const reduceMotion = useReducedMotion(); const hasProgress = typeof progress === 'number' && Number.isFinite(progress); const safeProgress = hasProgress ? Math.min(100, Math.max(0, progress)) : 42; return ( {label} {hasProgress ? {Math.round(safeProgress)}% : null} ); } export function ViewerLoadingFallback({ label = 'Preparing 3D machine', detail = 'Loading geometry, materials, annotations, and animation controllers.', progress, compact = false, }: LoadingFallbackProps): JSX.Element { return ( {label} {detail} ); } export function RouteLoadingFallback({ label = 'Loading Mechanica', detail = 'Assembling the explorer workspace.', progress, }: LoadingFallbackProps): JSX.Element { return ( ); } export function CatalogueSkeleton({ count = 8 }: { count?: number }): JSX.Element { return ( {Array.from({ length: count }, (_, index) => ( ))} ); } export function PanelSkeleton({ titleWidth = '60%', rows = 6, }: { titleWidth?: number | string; rows?: number; }): JSX.Element { return ( ); } export function LoadingOverlay({ label = 'Loading', progress, }: Pick): JSX.Element { return ( ); } function cx(...classes: Array): string { return classes.filter(Boolean).join(' '); }
{label}
{detail}