/** * CanvasLoadingSpinner Component * * Loading spinner overlay for canvas contexts. * Shows during video preparation/buffering. * Includes delay to avoid flashing for quick operations. */ import React, { useState, useEffect } from 'react'; import { PRELOAD_CONFIG } from '../config/preload.config'; interface CanvasLoadingSpinnerProps { /** Whether the spinner is visible */ isVisible: boolean; /** Loading message to display */ message?: string; /** Spinner size */ size?: 'sm' | 'md' | 'lg'; /** Loading progress (0-100) */ progress?: number; /** Z-index for stacking (default: 100) */ zIndex?: number; } const CanvasLoadingSpinner: React.FC = ({ isVisible, message, size = 'md', progress, zIndex = 100, }) => { // Delayed visibility - only show after SPINNER_DELAY_MS const [showSpinner, setShowSpinner] = useState(false); useEffect(() => { if (isVisible) { // Start timer to show spinner after delay const timer = setTimeout(() => { setShowSpinner(true); }, PRELOAD_CONFIG.ui.spinnerDelayMs); return () => clearTimeout(timer); } else { // Hide immediately when loading completes setShowSpinner(false); } }, [isVisible]); if (!showSpinner) return null; const sizeClasses = { sm: 'w-8 h-8 border-2', md: 'w-12 h-12 border-[3px]', lg: 'w-16 h-16 border-4', }; return (
{/* Spinner with subtle shadow for visibility on any background */}
{/* Spinner ring */}
{/* Progress indicator (optional) */} {progress !== undefined && (
{Math.round(progress)}%
)}
{message && (

{message}

)}
); }; export default CanvasLoadingSpinner;