wavesurf 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +348 -0
- package/dist/index.d.mts +212 -0
- package/dist/index.d.ts +212 -0
- package/dist/index.js +707 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +695 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +395 -0
- package/package.json +65 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context/AudioPlayerContext.tsx","../src/hooks/useLazyLoad.ts","../src/utils/formatTime.ts","../src/components/WaveformPlayer.tsx","../src/components/MiniPlayer.tsx"],"names":["createContext","useRef","useEffect","useState","useCallback","jsx","useContext","WaveSurfer","jsxs","DEFAULT_WAVEFORM_CONFIG"],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport {\n createContext,\n useContext,\n useRef,\n useState,\n useCallback,\n useEffect,\n ReactNode,\n} from 'react';\nimport type {\n Song,\n AudioPlayerState,\n AudioPlayerContextValue,\n AudioPlayerConfig,\n} from '../types';\n\n// Custom event for notifying WaveformPlayers when mini-player starts playing\nexport const MINI_PLAYER_PLAY_EVENT = 'wavesurfer-player-mini-play';\n\nconst AudioPlayerContext = createContext<AudioPlayerContextValue | null>(null);\n\nconst DEFAULT_CONFIG: Required<AudioPlayerConfig> = {\n fadeInEnabled: true,\n fadeInDuration: 3000,\n persistVolume: true,\n storageKey: 'audioPlayerVolume',\n defaultVolume: 1,\n onPlay: () => {},\n onPause: () => {},\n onEnd: () => {},\n onTimeUpdate: () => {},\n};\n\nconst FADE_STEPS = 30; // 30 steps for smooth fade\nconst MIN_FADE_IN_VOLUME = 0.1; // Minimum 10% volume on fade-in so users hear something\n\ninterface AudioPlayerProviderProps {\n children: ReactNode;\n config?: AudioPlayerConfig;\n}\n\nexport function AudioPlayerProvider({\n children,\n config: userConfig,\n}: AudioPlayerProviderProps) {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n const audioRef = useRef<HTMLAudioElement | null>(null);\n const fadeIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const configRef = useRef(config);\n\n // Keep config ref up to date\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n const [state, setState] = useState<AudioPlayerState>({\n currentSong: null,\n isPlaying: false,\n currentTime: 0,\n duration: 0,\n volume: config.defaultVolume,\n displayVolume: config.defaultVolume,\n isFadingIn: false,\n });\n\n // Initialize audio element and load saved volume\n useEffect(() => {\n // Create audio element\n const audio = new Audio();\n audio.preload = 'metadata';\n audioRef.current = audio;\n\n // Load saved volume from localStorage if persistence is enabled\n if (config.persistVolume && typeof window !== 'undefined') {\n const savedVolume = localStorage.getItem(config.storageKey);\n if (savedVolume) {\n const vol = parseFloat(savedVolume);\n if (!isNaN(vol) && vol >= 0 && vol <= 1) {\n setState((s) => ({ ...s, volume: vol, displayVolume: vol }));\n audio.volume = vol;\n }\n }\n }\n\n // Audio event listeners\n const handleTimeUpdate = () => {\n setState((s) => ({ ...s, currentTime: audio.currentTime }));\n configRef.current.onTimeUpdate?.(audio.currentTime);\n };\n\n const handleLoadedMetadata = () => {\n setState((s) => ({ ...s, duration: audio.duration }));\n };\n\n const handleEnded = () => {\n setState((s) => ({ ...s, isPlaying: false, currentTime: 0 }));\n configRef.current.onEnd?.();\n };\n\n const handlePlay = () => {\n setState((s) => ({ ...s, isPlaying: true }));\n };\n\n const handlePause = () => {\n setState((s) => ({ ...s, isPlaying: false }));\n };\n\n audio.addEventListener('timeupdate', handleTimeUpdate);\n audio.addEventListener('loadedmetadata', handleLoadedMetadata);\n audio.addEventListener('ended', handleEnded);\n audio.addEventListener('play', handlePlay);\n audio.addEventListener('pause', handlePause);\n\n return () => {\n // Cleanup\n if (fadeIntervalRef.current) {\n clearInterval(fadeIntervalRef.current);\n }\n audio.removeEventListener('timeupdate', handleTimeUpdate);\n audio.removeEventListener('loadedmetadata', handleLoadedMetadata);\n audio.removeEventListener('ended', handleEnded);\n audio.removeEventListener('play', handlePlay);\n audio.removeEventListener('pause', handlePause);\n audio.pause();\n audio.src = '';\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Clear any existing fade interval\n const clearFade = useCallback(() => {\n if (fadeIntervalRef.current) {\n clearInterval(fadeIntervalRef.current);\n fadeIntervalRef.current = null;\n }\n }, []);\n\n // Fade in volume\n const fadeInVolume = useCallback(\n (targetVolume: number) => {\n if (!audioRef.current) return;\n\n clearFade();\n setState((s) => ({ ...s, isFadingIn: true, displayVolume: 0 }));\n\n const fadeStepDuration = configRef.current.fadeInDuration / FADE_STEPS;\n const volumeStep = targetVolume / FADE_STEPS;\n let currentStep = 0;\n\n fadeIntervalRef.current = setInterval(() => {\n currentStep++;\n const newVolume = Math.min(volumeStep * currentStep, targetVolume);\n if (audioRef.current) {\n audioRef.current.volume = newVolume;\n }\n // Update displayVolume so the slider follows the fade\n setState((s) => ({ ...s, displayVolume: newVolume }));\n\n if (currentStep >= FADE_STEPS) {\n clearFade();\n setState((s) => ({\n ...s,\n isFadingIn: false,\n displayVolume: targetVolume,\n }));\n }\n }, fadeStepDuration);\n },\n [clearFade]\n );\n\n // Play a song with optional fade-in\n const play = useCallback(\n async (song: Song) => {\n if (!audioRef.current) return;\n\n // Stop any current fade-in\n clearFade();\n\n // If it's a different song, load it\n if (state.currentSong?.id !== song.id) {\n audioRef.current.src = song.audioUrl;\n setState((s) => ({\n ...s,\n currentSong: song,\n currentTime: 0,\n duration: song.duration || 0,\n }));\n }\n\n // Determine target volume\n const targetVolume = Math.max(state.volume, MIN_FADE_IN_VOLUME);\n\n // Set initial volume based on fade setting\n if (configRef.current.fadeInEnabled) {\n audioRef.current.volume = 0;\n } else {\n audioRef.current.volume = targetVolume;\n }\n\n try {\n await audioRef.current.play();\n // Dispatch event to pause other players\n if (typeof window !== 'undefined') {\n window.dispatchEvent(\n new CustomEvent(MINI_PLAYER_PLAY_EVENT, { detail: song.id })\n );\n }\n // Start fade-in if enabled\n if (configRef.current.fadeInEnabled) {\n fadeInVolume(targetVolume);\n }\n // Call onPlay callback\n configRef.current.onPlay?.(song);\n } catch {\n // Handle autoplay restrictions silently\n }\n },\n [state.currentSong?.id, state.volume, clearFade, fadeInVolume]\n );\n\n // Pause playback\n const pause = useCallback(() => {\n if (!audioRef.current) return;\n clearFade();\n audioRef.current.pause();\n configRef.current.onPause?.();\n }, [clearFade]);\n\n // Toggle play/pause\n const togglePlay = useCallback(() => {\n if (!audioRef.current || !state.currentSong) return;\n\n if (state.isPlaying) {\n pause();\n } else {\n // Resume with fade-in if enabled\n const targetVolume = Math.max(state.volume, MIN_FADE_IN_VOLUME);\n\n if (configRef.current.fadeInEnabled) {\n audioRef.current.volume = 0;\n }\n\n audioRef.current\n .play()\n .then(() => {\n if (typeof window !== 'undefined') {\n window.dispatchEvent(\n new CustomEvent(MINI_PLAYER_PLAY_EVENT, {\n detail: state.currentSong?.id,\n })\n );\n }\n if (configRef.current.fadeInEnabled) {\n fadeInVolume(targetVolume);\n }\n })\n .catch(() => {\n // Handle autoplay restrictions silently\n });\n }\n }, [state.isPlaying, state.currentSong, state.volume, pause, fadeInVolume]);\n\n // Seek to position\n const seek = useCallback((time: number) => {\n if (!audioRef.current) return;\n audioRef.current.currentTime = time;\n setState((s) => ({ ...s, currentTime: time }));\n }, []);\n\n // Set volume and persist to localStorage\n const setVolume = useCallback(\n (volume: number) => {\n if (!audioRef.current) return;\n\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n // If user manually changes volume during fade, stop the fade\n if (fadeIntervalRef.current) {\n clearFade();\n setState((s) => ({ ...s, isFadingIn: false }));\n }\n\n audioRef.current.volume = clampedVolume;\n\n // Persist to localStorage if enabled\n if (configRef.current.persistVolume && typeof window !== 'undefined') {\n localStorage.setItem(\n configRef.current.storageKey,\n clampedVolume.toString()\n );\n }\n\n setState((s) => ({\n ...s,\n volume: clampedVolume,\n displayVolume: clampedVolume,\n }));\n },\n [clearFade]\n );\n\n // Stop playback and clear song\n const stop = useCallback(() => {\n if (!audioRef.current) return;\n clearFade();\n audioRef.current.pause();\n audioRef.current.currentTime = 0;\n audioRef.current.src = '';\n setState((s) => ({\n ...s,\n currentSong: null,\n isPlaying: false,\n currentTime: 0,\n duration: 0,\n isFadingIn: false,\n }));\n }, [clearFade]);\n\n const value: AudioPlayerContextValue = {\n ...state,\n play,\n pause,\n togglePlay,\n seek,\n setVolume,\n stop,\n };\n\n return (\n <AudioPlayerContext.Provider value={value}>\n {children}\n </AudioPlayerContext.Provider>\n );\n}\n\nexport function useAudioPlayer(): AudioPlayerContextValue {\n const context = useContext(AudioPlayerContext);\n if (!context) {\n throw new Error(\n 'useAudioPlayer must be used within an AudioPlayerProvider'\n );\n }\n return context;\n}\n","'use client';\n\nimport { useRef, useState, useEffect } from 'react';\nimport type { UseLazyLoadResult, UseLazyLoadOptions } from '../types';\n\n/**\n * Hook for lazy loading elements using IntersectionObserver.\n * Returns a ref to attach to the target element and a boolean indicating visibility.\n *\n * @param options - Configuration options for the IntersectionObserver\n * @returns Object containing ref and isVisible state\n *\n * @example\n * const { ref, isVisible } = useLazyLoad();\n *\n * return (\n * <div ref={ref}>\n * {isVisible && <ExpensiveComponent />}\n * </div>\n * );\n */\nexport function useLazyLoad(options?: UseLazyLoadOptions): UseLazyLoadResult {\n const {\n rootMargin = '100px',\n threshold = 0,\n forceVisible = false,\n } = options || {};\n\n const ref = useRef<HTMLDivElement>(null);\n const [isVisible, setIsVisible] = useState(forceVisible);\n\n useEffect(() => {\n if (forceVisible) {\n setIsVisible(true);\n return;\n }\n\n if (!ref.current) return;\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsVisible(true);\n observer.disconnect(); // Only need to detect once\n }\n },\n { rootMargin, threshold }\n );\n\n observer.observe(ref.current);\n\n return () => observer.disconnect();\n }, [rootMargin, threshold, forceVisible]);\n\n return { ref, isVisible };\n}\n","/**\n * Formats seconds into a human-readable time string (M:SS or MM:SS).\n *\n * @param seconds - The number of seconds to format\n * @returns Formatted time string (e.g., \"3:45\" or \"12:05\")\n *\n * @example\n * formatTime(125) // \"2:05\"\n * formatTime(0) // \"0:00\"\n * formatTime(3600) // \"60:00\"\n */\nexport function formatTime(seconds: number): string {\n if (!seconds || isNaN(seconds) || seconds < 0) return '0:00';\n\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n","'use client';\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport WaveSurfer from 'wavesurfer.js';\nimport { useAudioPlayer, MINI_PLAYER_PLAY_EVENT } from '../context/AudioPlayerContext';\nimport { useLazyLoad } from '../hooks/useLazyLoad';\nimport { formatTime } from '../utils/formatTime';\nimport type { WaveformPlayerProps, WaveformConfig } from '../types';\n\nconst DEFAULT_WAVEFORM_CONFIG: Required<WaveformConfig> = {\n waveColor: '#666666',\n progressColor: '#D4AF37',\n cursorColor: '#D4AF37',\n barWidth: 2,\n barGap: 1,\n barRadius: 2,\n height: 60,\n normalize: true,\n};\n\nexport function WaveformPlayer({\n song,\n waveformConfig: userWaveformConfig,\n lazyLoad = true,\n showTime = true,\n className = '',\n renderHeader,\n renderControls,\n}: WaveformPlayerProps) {\n const waveformConfig = { ...DEFAULT_WAVEFORM_CONFIG, ...userWaveformConfig };\n const containerRef = useRef<HTMLDivElement>(null);\n const wavesurferRef = useRef<WaveSurfer | null>(null);\n const [isReady, setIsReady] = useState(false);\n const [totalDuration, setTotalDuration] = useState(song.duration || 0);\n\n // Lazy loading\n const { ref: wrapperRef, isVisible } = useLazyLoad({\n forceVisible: !lazyLoad,\n });\n\n // Get audio player context for global playback control\n const {\n play: contextPlay,\n togglePlay: contextTogglePlay,\n seek: contextSeek,\n currentSong,\n isPlaying: contextIsPlaying,\n currentTime: contextCurrentTime,\n } = useAudioPlayer();\n\n // Check if this song is the currently playing song\n const isThisSongPlaying = currentSong?.id === song.id;\n const isPlaying = isThisSongPlaying && contextIsPlaying;\n const currentTime = isThisSongPlaying ? contextCurrentTime : 0;\n\n // Sync waveform progress with context when this song is playing\n useEffect(() => {\n if (!wavesurferRef.current || !isThisSongPlaying) return;\n\n // Update waveform progress to match context time\n const waveDuration = wavesurferRef.current.getDuration();\n if (waveDuration > 0 && contextCurrentTime >= 0) {\n const progress = contextCurrentTime / waveDuration;\n wavesurferRef.current.seekTo(Math.min(progress, 1));\n }\n }, [contextCurrentTime, isThisSongPlaying]);\n\n // Initialize WaveSurfer - waveform display only (audio plays through context)\n useEffect(() => {\n if (!containerRef.current || !isVisible) return;\n\n const hasPeaks = song.peaks && song.peaks.length > 0;\n\n // Create WaveSurfer for waveform display only (no audio playback)\n const wavesurfer = WaveSurfer.create({\n container: containerRef.current,\n waveColor: waveformConfig.waveColor,\n progressColor: waveformConfig.progressColor,\n cursorColor: waveformConfig.cursorColor,\n barWidth: waveformConfig.barWidth,\n barGap: waveformConfig.barGap,\n barRadius: waveformConfig.barRadius,\n height: waveformConfig.height,\n normalize: waveformConfig.normalize,\n interact: true, // Allow clicking on waveform to seek\n // Only load audio URL if we don't have peaks (needed to generate waveform)\n url: hasPeaks ? undefined : song.audioUrl,\n peaks: hasPeaks ? [song.peaks!] : undefined,\n duration: hasPeaks ? (song.duration || 0) : undefined,\n });\n\n wavesurfer.on('ready', () => {\n setIsReady(true);\n setTotalDuration(wavesurfer.getDuration() || song.duration || 0);\n });\n\n // Handle waveform click for seeking\n wavesurfer.on('interaction', (newTime: number) => {\n // Only seek if this song is currently playing in the context\n if (isThisSongPlaying) {\n contextSeek(newTime);\n }\n });\n\n wavesurfer.on('error', () => {\n // Silently handle errors\n });\n\n wavesurferRef.current = wavesurfer;\n\n // If we have peaks, mark as ready immediately\n if (hasPeaks) {\n setIsReady(true);\n setTotalDuration(song.duration || 0);\n }\n\n return () => {\n try {\n wavesurfer.destroy();\n } catch {\n // Ignore errors when component unmounts\n }\n };\n }, [\n song.audioUrl,\n song.peaks,\n song.duration,\n isVisible,\n isThisSongPlaying,\n contextSeek,\n waveformConfig.waveColor,\n waveformConfig.progressColor,\n waveformConfig.cursorColor,\n waveformConfig.barWidth,\n waveformConfig.barGap,\n waveformConfig.barRadius,\n waveformConfig.height,\n waveformConfig.normalize,\n ]);\n\n // Handle play button click - plays through global context\n const handlePlayClick = useCallback(() => {\n if (!song.id || !song.audioUrl) return;\n\n if (isThisSongPlaying) {\n // This song is already loaded - toggle play/pause\n contextTogglePlay();\n } else {\n // Play this song through the global context\n contextPlay(song);\n }\n }, [song, isThisSongPlaying, contextPlay, contextTogglePlay]);\n\n return (\n <div\n ref={wrapperRef}\n className={`wsp-player ${className}`}\n data-song-id={song.id}\n >\n {/* Custom header or default */}\n {renderHeader ? (\n renderHeader(song, isPlaying)\n ) : (\n <div className=\"wsp-player-header\">\n <h3 className=\"wsp-player-title\">{song.title}</h3>\n {song.artist && (\n <span className=\"wsp-player-artist\">{song.artist}</span>\n )}\n </div>\n )}\n\n {/* Player controls and waveform */}\n <div className=\"wsp-player-controls\">\n {/* Play/Pause button */}\n <button\n onClick={handlePlayClick}\n disabled={!isReady}\n className={`wsp-play-button ${isReady ? 'wsp-play-button--ready' : ''}`}\n aria-label={isPlaying ? 'Pause' : 'Play'}\n >\n {!isReady ? (\n <svg className=\"wsp-icon wsp-icon--spinner\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle\n className=\"wsp-spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"wsp-spinner-head\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n ) : isPlaying ? (\n <svg className=\"wsp-icon\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n ) : (\n <svg className=\"wsp-icon wsp-icon--play\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n )}\n </button>\n\n {/* Waveform container */}\n <div className=\"wsp-waveform-wrapper\">\n <div ref={containerRef} className=\"wsp-waveform\" />\n\n {/* Time display */}\n {showTime && (\n <div className=\"wsp-time-display\">\n <span className=\"wsp-time\">{formatTime(currentTime)}</span>\n <span className=\"wsp-time\">{formatTime(totalDuration)}</span>\n </div>\n )}\n </div>\n\n {/* Custom controls slot */}\n {renderControls && renderControls(song, isPlaying)}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useCallback, useRef, useEffect, useState } from 'react';\nimport WaveSurfer from 'wavesurfer.js';\nimport { useAudioPlayer } from '../context/AudioPlayerContext';\nimport { formatTime } from '../utils/formatTime';\nimport type { MiniPlayerProps, WaveformConfig } from '../types';\n\nconst DEFAULT_WAVEFORM_CONFIG: Required<WaveformConfig> = {\n waveColor: '#666666',\n progressColor: '#D4AF37',\n cursorColor: 'transparent',\n barWidth: 2,\n barGap: 1,\n barRadius: 2,\n height: 40,\n normalize: true,\n};\n\nexport function MiniPlayer({\n position = 'bottom',\n showVolume = true,\n showClose = true,\n onClose,\n className = '',\n waveformConfig: userWaveformConfig,\n}: MiniPlayerProps) {\n const waveformConfig = { ...DEFAULT_WAVEFORM_CONFIG, ...userWaveformConfig };\n\n const {\n currentSong,\n isPlaying,\n currentTime,\n duration,\n displayVolume,\n togglePlay,\n seek,\n setVolume,\n stop,\n } = useAudioPlayer();\n\n const waveformRef = useRef<HTMLDivElement>(null);\n const wavesurferRef = useRef<WaveSurfer | null>(null);\n const [isMobile, setIsMobile] = useState(false);\n const [waveformReady, setWaveformReady] = useState(false);\n const lastSongIdRef = useRef<string | null>(null);\n\n // Detect mobile viewport\n useEffect(() => {\n const checkMobile = () => setIsMobile(window.innerWidth < 640);\n checkMobile();\n window.addEventListener('resize', checkMobile);\n return () => window.removeEventListener('resize', checkMobile);\n }, []);\n\n // Initialize/update WaveSurfer when song changes\n useEffect(() => {\n if (!waveformRef.current || !currentSong) return;\n\n // If same song, don't recreate\n if (lastSongIdRef.current === currentSong.id && wavesurferRef.current) {\n return;\n }\n\n // Destroy previous instance\n if (wavesurferRef.current) {\n wavesurferRef.current.destroy();\n wavesurferRef.current = null;\n }\n\n setWaveformReady(false);\n lastSongIdRef.current = currentSong.id;\n\n const hasPeaks = currentSong.peaks && currentSong.peaks.length > 0;\n\n // Create WaveSurfer - waveform only, no audio (audio plays through context)\n const wavesurfer = WaveSurfer.create({\n container: waveformRef.current,\n waveColor: waveformConfig.waveColor,\n progressColor: waveformConfig.progressColor,\n cursorColor: waveformConfig.cursorColor,\n barWidth: waveformConfig.barWidth,\n barGap: waveformConfig.barGap,\n barRadius: waveformConfig.barRadius,\n height: waveformConfig.height,\n normalize: waveformConfig.normalize,\n interact: true,\n // Use peaks if available, otherwise need audio URL to generate waveform\n url: hasPeaks ? undefined : currentSong.audioUrl,\n peaks: hasPeaks && currentSong.peaks ? [currentSong.peaks] : undefined,\n duration: hasPeaks ? (currentSong.duration || duration || 0) : undefined,\n });\n\n wavesurfer.on('ready', () => {\n setWaveformReady(true);\n });\n\n // Handle click on waveform to seek\n wavesurfer.on('interaction', (newTime: number) => {\n seek(newTime);\n });\n\n wavesurferRef.current = wavesurfer;\n\n // If we have peaks, mark ready immediately\n if (hasPeaks) {\n setWaveformReady(true);\n }\n\n return () => {\n // Don't destroy on every render, only when song actually changes\n };\n }, [\n currentSong?.id,\n currentSong?.audioUrl,\n currentSong?.peaks,\n currentSong?.duration,\n duration,\n seek,\n waveformConfig.waveColor,\n waveformConfig.progressColor,\n waveformConfig.cursorColor,\n waveformConfig.barWidth,\n waveformConfig.barGap,\n waveformConfig.barRadius,\n waveformConfig.height,\n waveformConfig.normalize,\n ]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (wavesurferRef.current) {\n wavesurferRef.current.destroy();\n wavesurferRef.current = null;\n }\n };\n }, []);\n\n // Sync waveform progress with audio context\n useEffect(() => {\n if (!wavesurferRef.current || !waveformReady) return;\n\n const waveDuration = wavesurferRef.current.getDuration();\n if (waveDuration > 0 && currentTime >= 0) {\n const progress = currentTime / waveDuration;\n wavesurferRef.current.seekTo(Math.min(progress, 1));\n }\n }, [currentTime, waveformReady]);\n\n // Handle volume change\n const handleVolumeChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setVolume(parseFloat(e.target.value));\n },\n [setVolume]\n );\n\n // Handle close button\n const handleClose = useCallback(() => {\n stop();\n onClose?.();\n }, [stop, onClose]);\n\n // Don't render if no song is loaded\n if (!currentSong) return null;\n\n // Determine if volume should be shown (respects both prop and mobile detection)\n const shouldShowVolume = showVolume && !isMobile;\n\n const positionClass = position === 'top' ? 'wsp-mini-player--top' : 'wsp-mini-player--bottom';\n\n return (\n <div className={`wsp-mini-player ${positionClass} ${className}`}>\n {/* Main controls */}\n <div className=\"wsp-mini-player-inner\">\n {/* Play/pause button - left */}\n <button\n onClick={togglePlay}\n className=\"wsp-mini-play-button\"\n aria-label={isPlaying ? 'Pause' : 'Play'}\n >\n {isPlaying ? (\n <svg className=\"wsp-mini-icon\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n ) : (\n <svg className=\"wsp-mini-icon wsp-mini-icon--play\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n )}\n </button>\n\n {/* Song info and waveform - center */}\n <div className=\"wsp-mini-content\">\n {/* Song title */}\n <div className=\"wsp-mini-info\">\n <div className=\"wsp-mini-title\">{currentSong.title}</div>\n {currentSong.album && (\n <div className=\"wsp-mini-album\">• {currentSong.album}</div>\n )}\n </div>\n\n {/* Waveform */}\n <div className=\"wsp-mini-waveform-container\">\n <span className=\"wsp-mini-time\">{formatTime(currentTime)}</span>\n <div ref={waveformRef} className=\"wsp-mini-waveform\" />\n <span className=\"wsp-mini-time\">{formatTime(duration)}</span>\n </div>\n </div>\n\n {/* Volume slider - hidden on mobile */}\n {shouldShowVolume && (\n <div className=\"wsp-mini-volume\">\n <button\n onClick={() => setVolume(displayVolume > 0 ? 0 : 1)}\n className=\"wsp-mini-volume-button\"\n aria-label={displayVolume > 0 ? 'Mute' : 'Unmute'}\n >\n {displayVolume === 0 ? (\n <svg className=\"wsp-mini-volume-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2\"\n />\n </svg>\n ) : displayVolume < 0.5 ? (\n <svg className=\"wsp-mini-volume-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15.536 8.464a5 5 0 010 7.072M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z\"\n />\n </svg>\n ) : (\n <svg className=\"wsp-mini-volume-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z\"\n />\n </svg>\n )}\n </button>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n value={displayVolume}\n onChange={handleVolumeChange}\n className=\"wsp-mini-volume-slider\"\n aria-label=\"Volume\"\n />\n </div>\n )}\n\n {/* Close button */}\n {showClose && (\n <button\n onClick={handleClose}\n className=\"wsp-mini-close-button\"\n aria-label=\"Close player\"\n >\n <svg className=\"wsp-mini-close-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n );\n}\n"]}
|