{"version":3,"file":"index-BIlTQ25Q.mjs","sources":["../../src/hooks/useAudioPlayer.ts","../../src/renderers/Audio/index.tsx"],"sourcesContent":["import { useState, useRef, useEffect, useCallback } from 'react';\n\ninterface UseAudioPlayerOptions {\n  url: string;\n  skipSeconds?: number;\n}\n\ninterface UseAudioPlayerReturn {\n  audioRef: React.RefObject<HTMLAudioElement>;\n  isPlaying: boolean;\n  isLoading: boolean;\n  isLoop: boolean;\n  currentTime: number;\n  duration: number;\n  volume: number;\n  isMuted: boolean;\n  error: string | null;\n  togglePlay: () => void;\n  seek: (time: number) => void;\n  skip: (seconds: number) => void;\n  setVolume: (vol: number) => void;\n  toggleMute: () => void;\n  toggleLoop: () => void;\n  formatTime: (time: number) => string;\n}\n\nexport function useAudioPlayer({\n  url,\n}: UseAudioPlayerOptions): UseAudioPlayerReturn {\n  const audioRef = useRef<HTMLAudioElement>(null);\n  const [isPlaying, setIsPlaying] = useState(false);\n  const [isLoading, setIsLoading] = useState(true);\n  const [currentTime, setCurrentTime] = useState(0);\n  const [duration, setDuration] = useState(0);\n  const [volume, setVolumeState] = useState(1);\n  const [isMuted, setIsMuted] = useState(false);\n  const [isLoop, setIsLoop] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n\n  useEffect(() => {\n    const audio = audioRef.current;\n    if (!audio) return;\n\n    // 重置加载状态\n    setIsLoading(true);\n    setError(null);\n\n    const onTimeUpdate = () => {\n      if (!isNaN(audio.currentTime)) {\n        setCurrentTime(audio.currentTime);\n      }\n    };\n\n    const onDurationChange = () => {\n      if (!isNaN(audio.duration) && isFinite(audio.duration)) {\n        setDuration(audio.duration);\n      }\n    };\n\n    const onCanPlay = () => {\n      setIsLoading(false);\n      onDurationChange();\n    };\n\n    const onWaiting = () => setIsLoading(true);\n    const onPlaying = () => {\n      setIsLoading(false);\n      setIsPlaying(true);\n    };\n\n    // 由 audio 事件驱动播放状态，而非手动设置\n    const onPlay = () => setIsPlaying(true);\n    const onPause = () => setIsPlaying(false);\n    const onEnded = () => setIsPlaying(false);\n\n    const onError = () => {\n      setError('音频加载失败');\n      setIsLoading(false);\n    };\n\n    audio.addEventListener('timeupdate', onTimeUpdate);\n    audio.addEventListener('loadedmetadata', onDurationChange);\n    audio.addEventListener('durationchange', onDurationChange);\n    audio.addEventListener('canplay', onCanPlay);\n    audio.addEventListener('waiting', onWaiting);\n    audio.addEventListener('playing', onPlaying);\n    audio.addEventListener('play', onPlay);\n    audio.addEventListener('pause', onPause);\n    audio.addEventListener('ended', onEnded);\n    audio.addEventListener('error', onError);\n\n    // 如果 audio 已经就绪\n    if (audio.readyState >= 3) {\n      setIsLoading(false);\n      onDurationChange();\n    } else if (audio.readyState >= 1) {\n      onDurationChange();\n    }\n\n    return () => {\n      audio.removeEventListener('timeupdate', onTimeUpdate);\n      audio.removeEventListener('loadedmetadata', onDurationChange);\n      audio.removeEventListener('durationchange', onDurationChange);\n      audio.removeEventListener('canplay', onCanPlay);\n      audio.removeEventListener('waiting', onWaiting);\n      audio.removeEventListener('playing', onPlaying);\n      audio.removeEventListener('play', onPlay);\n      audio.removeEventListener('pause', onPause);\n      audio.removeEventListener('ended', onEnded);\n      audio.removeEventListener('error', onError);\n    };\n  }, [url]);\n\n  const togglePlay = useCallback(() => {\n    const audio = audioRef.current;\n    if (!audio) return;\n\n    if (audio.paused) {\n      audio.play().catch(() => {\n        // 浏览器自动播放策略拒绝\n      });\n    } else {\n      audio.pause();\n    }\n  }, []);\n\n  const seek = useCallback((time: number) => {\n    const audio = audioRef.current;\n    if (!audio) return;\n    audio.currentTime = time;\n    setCurrentTime(time);\n  }, []);\n\n  const skip = useCallback(\n    (seconds: number) => {\n      const audio = audioRef.current;\n      if (!audio) return;\n      audio.currentTime = Math.max(\n        0,\n        Math.min(audio.currentTime + seconds, audio.duration || Infinity)\n      );\n    },\n    []\n  );\n\n  const setVolume = useCallback((vol: number) => {\n    const audio = audioRef.current;\n    if (!audio) return;\n    const clamped = Math.max(0, Math.min(1, vol));\n    audio.volume = clamped;\n    setVolumeState(clamped);\n    if (clamped > 0) {\n      audio.muted = false;\n      setIsMuted(false);\n    }\n  }, []);\n\n  const toggleMute = useCallback(() => {\n    const audio = audioRef.current;\n    if (!audio) return;\n    audio.muted = !audio.muted;\n    setIsMuted(audio.muted);\n  }, []);\n\n  const toggleLoop = useCallback(() => {\n    const audio = audioRef.current;\n    if (!audio) return;\n    const next = !audio.loop;\n    audio.loop = next;\n    setIsLoop(next);\n  }, []);\n\n  const formatTime = useCallback((time: number) => {\n    if (!isFinite(time) || isNaN(time) || time < 0) return '0:00';\n    const minutes = Math.floor(time / 60);\n    const seconds = Math.floor(time % 60);\n    return `${minutes}:${seconds.toString().padStart(2, '0')}`;\n  }, []);\n\n  return {\n    audioRef,\n    isPlaying,\n    isLoading,\n    isLoop,\n    currentTime,\n    duration,\n    volume,\n    isMuted,\n    error,\n    togglePlay,\n    seek,\n    skip,\n    setVolume,\n    toggleMute,\n    toggleLoop,\n    formatTime,\n  };\n}\n","import { useState, useRef, useEffect, forwardRef, useImperativeHandle } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { Play, Pause, Volume2, VolumeX, Volume1, SkipBack, SkipForward, Repeat } from 'lucide-react';\nimport { useAudioPlayer } from '../../hooks/useAudioPlayer';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\n/** 文本溢出时自动横向滚动 */\nconst MarqueeText: React.FC<{\n  text: string;\n  className?: string;\n  style?: React.CSSProperties;\n}> = ({ text, className = '', style }) => {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const innerRef = useRef<HTMLDivElement>(null);\n  const [overflow, setOverflow] = useState(false);\n  const [scrollDist, setScrollDist] = useState(0);\n\n  useEffect(() => {\n    const check = () => {\n      const container = containerRef.current;\n      const inner = innerRef.current;\n      if (!container || !inner) return;\n      const cw = container.clientWidth;\n      const tw = inner.scrollWidth;\n      setOverflow(tw > cw);\n      setScrollDist(tw);\n    };\n    check();\n    const observer = new ResizeObserver(check);\n    if (containerRef.current) observer.observe(containerRef.current);\n    return () => observer.disconnect();\n  }, [text]);\n\n  const gap = 60;\n  const totalScroll = scrollDist + gap;\n  const dur = totalScroll / 40;\n\n  return (\n    <div\n      ref={containerRef}\n      className={`rfp-overflow-hidden rfp-whitespace-nowrap ${className}`}\n      style={style}\n    >\n      {overflow ? (\n        <motion.div\n          className=\"rfp-inline-flex rfp-whitespace-nowrap\"\n          animate={{ x: [0, -totalScroll] }}\n          transition={{ duration: dur, repeat: Infinity, ease: 'linear', repeatDelay: 1.5 }}\n        >\n          <span>{text}</span>\n          <span style={{ width: gap }} className=\"rfp-inline-block\" />\n          <span>{text}</span>\n        </motion.div>\n      ) : null}\n      {/* 始终渲染用于测量的隐藏层 */}\n      <div\n        ref={innerRef}\n        className=\"rfp-whitespace-nowrap\"\n        style={overflow ? { position: 'absolute', visibility: 'hidden', pointerEvents: 'none' } : undefined}\n      >\n        {text}\n      </div>\n    </div>\n  );\n};\n\n/** SVG 唱臂组件 */\nconst Tonearm: React.FC<{ isPlaying: boolean }> = ({ isPlaying }) => (\n  <motion.div\n    className=\"rfp-absolute\"\n    style={{\n      top: '-6px',\n      right: '2px',\n      width: '100px',\n      height: '120px',\n      transformOrigin: '76px 16px',\n      zIndex: 5,\n    }}\n    animate={{ rotate: isPlaying ? 16 : 0 }}\n    transition={{ duration: 0.8, ease: [0.4, 0, 0.2, 1] }}\n  >\n    <svg\n      width=\"100\"\n      height=\"120\"\n      viewBox=\"0 0 100 120\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      {/* 底座阴影 */}\n      <circle cx=\"76\" cy=\"16\" r=\"13\" fill=\"rgba(0,0,0,0.3)\" />\n      {/* 底座外圈 */}\n      <circle cx=\"76\" cy=\"16\" r=\"11\" fill=\"url(#baseGrad)\" />\n      {/* 底座内圈 */}\n      <circle cx=\"76\" cy=\"16\" r=\"6\" fill=\"url(#baseInnerGrad)\" />\n      {/* 底座中心轴 */}\n      <circle cx=\"76\" cy=\"16\" r=\"2.5\" fill=\"#222\" stroke=\"#555\" strokeWidth=\"0.5\" />\n\n      {/* 臂杆 */}\n      <path\n        d=\"M74 22 L56 88\"\n        stroke=\"url(#armGrad)\"\n        strokeWidth=\"3.5\"\n        strokeLinecap=\"round\"\n      />\n      {/* 臂杆高光 */}\n      <path\n        d=\"M74.8 22 L56.8 88\"\n        stroke=\"rgba(255,255,255,0.06)\"\n        strokeWidth=\"1\"\n        strokeLinecap=\"round\"\n      />\n\n      {/* 唱头座 (Headshell) */}\n      <rect x=\"50\" y=\"86\" width=\"12\" height=\"7\" rx=\"1.5\" fill=\"url(#headGrad)\" />\n      {/* 唱头 (Cartridge) */}\n      <rect x=\"52.5\" y=\"92\" width=\"7\" height=\"9\" rx=\"1\" fill=\"url(#cartridgeGrad)\" />\n      {/* 唱针 (Stylus) */}\n      <line x1=\"56\" y1=\"101\" x2=\"56\" y2=\"105\" stroke=\"#bbb\" strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n      <circle cx=\"56\" cy=\"105.5\" r=\"0.8\" fill=\"#ddd\" />\n\n      {/* 渐变定义 */}\n      <defs>\n        <radialGradient id=\"baseGrad\" cx=\"40%\" cy=\"35%\">\n          <stop offset=\"0%\" stopColor=\"#555\" />\n          <stop offset=\"100%\" stopColor=\"#1a1a1a\" />\n        </radialGradient>\n        <radialGradient id=\"baseInnerGrad\" cx=\"40%\" cy=\"35%\">\n          <stop offset=\"0%\" stopColor=\"#666\" />\n          <stop offset=\"100%\" stopColor=\"#333\" />\n        </radialGradient>\n        <linearGradient id=\"armGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n          <stop offset=\"0%\" stopColor=\"#555\" />\n          <stop offset=\"50%\" stopColor=\"#444\" />\n          <stop offset=\"100%\" stopColor=\"#333\" />\n        </linearGradient>\n        <linearGradient id=\"headGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n          <stop offset=\"0%\" stopColor=\"#555\" />\n          <stop offset=\"100%\" stopColor=\"#333\" />\n        </linearGradient>\n        <linearGradient id=\"cartridgeGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n          <stop offset=\"0%\" stopColor=\"#444\" />\n          <stop offset=\"100%\" stopColor=\"#222\" />\n        </linearGradient>\n      </defs>\n    </svg>\n  </motion.div>\n);\n\ninterface AudioRendererProps {\n  url: string;\n  fileName: string;\n}\n\nexport const AudioRenderer = forwardRef<RendererHandle, AudioRendererProps>(({ url, fileName }, ref) => {\n  const t = useTranslator();\n  const {\n    audioRef,\n    isPlaying,\n    isLoading,\n    isLoop,\n    currentTime,\n    duration,\n    volume,\n    isMuted,\n    error,\n    togglePlay,\n    seek,\n    skip,\n    setVolume,\n    toggleMute,\n    toggleLoop,\n    formatTime,\n  } = useAudioPlayer({ url });\n\n  const [showVolume, setShowVolume] = useState(false);\n  const [isCompact, setIsCompact] = useState(false);\n  const [controlScale, setControlScale] = useState(1);\n  const [isDragging, setIsDragging] = useState(false);\n  const [dragTime, setDragTime] = useState(0);\n  const containerRef = useRef<HTMLDivElement>(null);\n  const volumeRef = useRef<HTMLDivElement>(null);\n  const volumeTimerRef = useRef<ReturnType<typeof setTimeout>>();\n\n  const displayTime = isDragging ? dragTime : currentTime;\n  const progress = duration > 0 ? displayTime / duration : 0;\n\n  // 监听容器尺寸，自适应调整布局\n  useEffect(() => {\n    const checkSize = () => {\n      if (containerRef.current) {\n        const height = containerRef.current.clientHeight;\n        const width = containerRef.current.clientWidth;\n        // 高度小于 580px 时启用紧凑模式\n        setIsCompact(height < 580);\n        // 控制面板宽度自适应缩放\n        // 基础宽度 448px (max-w-md)，最小视觉宽度 320px，即最小 scale ≈ 0.714\n        const baseWidth = 464; // 448 + 左右各 8px 呼吸空间\n        const minVisualWidth = 320;\n        const minScale = minVisualWidth / baseWidth;\n        const scale = width >= baseWidth\n          ? 1\n          : Math.max(minScale, width / baseWidth);\n        setControlScale(scale);\n      }\n    };\n    checkSize();\n    const observer = new ResizeObserver(checkSize);\n    if (containerRef.current) {\n      observer.observe(containerRef.current);\n    }\n    return () => observer.disconnect();\n  }, []);\n\n  useEffect(() => {\n    const handleClickOutside = (e: MouseEvent) => {\n      if (volumeRef.current && !volumeRef.current.contains(e.target as Node)) {\n        setShowVolume(false);\n      }\n    };\n    if (showVolume) {\n      document.addEventListener('mousedown', handleClickOutside);\n    }\n    return () => document.removeEventListener('mousedown', handleClickOutside);\n  }, [showVolume]);\n\n  const handleVolumeEnter = () => {\n    clearTimeout(volumeTimerRef.current);\n    setShowVolume(true);\n  };\n\n  const handleVolumeLeave = () => {\n    volumeTimerRef.current = setTimeout(() => setShowVolume(false), 300);\n  };\n\n  const VolumeIcon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2;\n\n  // 暴露接口给父组件\n  useImperativeHandle(ref, () => ({\n    getToolbarGroups: () => [],\n  }), []);\n\n  if (error) {\n    return <RendererError message={error} />;\n  }\n\n  // 根据紧凑模式动态计算尺寸\n  const vinylScale = isCompact ? 0.72 : 1;\n  const vinylBase = 260;\n  const vinylHeightBase = 240;\n\n  // 唱片跟随控制面板同步缩放，避免头重脚轻\n  const finalVinylScale = vinylScale * controlScale;\n\n  return (\n    <div\n      ref={containerRef}\n      className={`rfp-flex rfp-flex-col rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-select-none rfp-overflow-auto ${\n        isCompact ? 'rfp-p-3 rfp-gap-3' : 'rfp-p-6 rfp-gap-6'\n      }`}\n    >\n      {/* 唱片机整体 */}\n      <div\n        className=\"rfp-relative rfp-flex-shrink-0\"\n        style={{\n          width: `${vinylBase}px`,\n          height: `${vinylHeightBase}px`,\n          transform: `scale(${finalVinylScale})`,\n          transformOrigin: 'center center',\n          marginTop: isCompact ? `${-(vinylHeightBase * (1 - finalVinylScale)) / 2}px` : 0,\n          marginBottom: isCompact ? `${-(vinylHeightBase * (1 - finalVinylScale)) / 2}px` : 0,\n        }}\n      >\n        {/* 外圈光晕 */}\n        <motion.div\n          className=\"rfp-absolute rfp-rounded-full\"\n          style={{\n            width: '220px',\n            height: '220px',\n            top: '18px',\n            left: '8px',\n            background: 'radial-gradient(circle, rgba(129,140,248,0.12) 0%, transparent 70%)',\n          }}\n          animate={isPlaying ? { scale: [1, 1.08, 1], opacity: [0.5, 1, 0.5] } : { scale: 1, opacity: 0.2 }}\n          transition={isPlaying ? { duration: 3, repeat: Infinity, ease: 'easeInOut' } : { duration: 0.5 }}\n        />\n\n        {/* 唱片主体 */}\n        <div\n          className=\"rfp-absolute rfp-rounded-full rfp-overflow-hidden\"\n          style={{\n            width: '200px',\n            height: '200px',\n            top: '28px',\n            left: '18px',\n            background: `\n              radial-gradient(circle at center, transparent 95%, rgba(30,30,30,0.8) 95.5%, #111 97%),\n              radial-gradient(circle at center, transparent 38%, rgba(50,50,50,0.5) 38.15%, transparent 38.4%),\n              radial-gradient(circle at center, transparent 45%, rgba(50,50,50,0.3) 45.15%, transparent 45.4%),\n              radial-gradient(circle at center, transparent 52%, rgba(50,50,50,0.5) 52.15%, transparent 52.4%),\n              radial-gradient(circle at center, transparent 59%, rgba(50,50,50,0.3) 59.15%, transparent 59.4%),\n              radial-gradient(circle at center, transparent 66%, rgba(50,50,50,0.5) 66.15%, transparent 66.4%),\n              radial-gradient(circle at center, transparent 73%, rgba(50,50,50,0.3) 73.15%, transparent 73.4%),\n              radial-gradient(circle at center, transparent 80%, rgba(50,50,50,0.4) 80.15%, transparent 80.4%),\n              radial-gradient(circle at center, transparent 87%, rgba(50,50,50,0.3) 87.15%, transparent 87.4%),\n              conic-gradient(from 0deg, #1c1c1c, #232323, #1a1a1a, #262626, #1c1c1c, #212121, #1a1a1a, #252525, #1c1c1c, #232323, #1a1a1a, #262626, #1c1c1c)\n            `,\n            boxShadow: isPlaying\n              ? '0 0 36px rgba(129,140,248,0.1), 0 8px 32px rgba(0,0,0,0.4), inset 0 0 20px rgba(0,0,0,0.4)'\n              : '0 8px 32px rgba(0,0,0,0.4), inset 0 0 20px rgba(0,0,0,0.4)',\n            animation: 'rfp-vinyl-spin 8s linear infinite',\n            animationPlayState: isPlaying ? 'running' : 'paused',\n          }}\n        >\n          {/* 中心标签 */}\n          <div\n            className=\"rfp-absolute rfp-rounded-full\"\n            style={{\n              width: '34%',\n              height: '34%',\n              top: '33%',\n              left: '33%',\n              background: 'radial-gradient(circle at 40% 38%, #818cf8, #6366f1, #4f46e5, #4338ca)',\n              boxShadow: 'inset 0 1px 3px rgba(255,255,255,0.25), inset 0 -1px 3px rgba(0,0,0,0.3), 0 0 8px rgba(0,0,0,0.3)',\n            }}\n          >\n            <div\n              className=\"rfp-absolute rfp-inset-0 rfp-rounded-full rfp-opacity-20\"\n              style={{\n                background: `\n                  radial-gradient(circle at center, transparent 30%, rgba(0,0,0,0.3) 31%, transparent 32%),\n                  radial-gradient(circle at center, transparent 50%, rgba(0,0,0,0.2) 51%, transparent 52%),\n                  radial-gradient(circle at center, transparent 70%, rgba(0,0,0,0.3) 71%, transparent 72%),\n                  radial-gradient(circle at center, transparent 88%, rgba(0,0,0,0.2) 89%, transparent 90%)\n                `,\n              }}\n            />\n            <div\n              className=\"rfp-absolute rfp-rounded-full\"\n              style={{\n                width: '14%',\n                height: '14%',\n                top: '43%',\n                left: '43%',\n                background: 'radial-gradient(circle at 40% 40%, #333, #0d0d0d)',\n                boxShadow: 'inset 0 1px 3px rgba(0,0,0,0.9), 0 0 2px rgba(0,0,0,0.5)',\n              }}\n            />\n          </div>\n\n          {isLoading && (\n            <motion.div\n              className=\"rfp-absolute rfp-inset-0 rfp-rounded-full\"\n              style={{ border: '2px solid rgba(129,140,248,0.3)' }}\n              animate={{ scale: [1, 1.02, 1], opacity: [0.3, 0.6, 0.3] }}\n              transition={{ duration: 1.5, repeat: Infinity }}\n            />\n          )}\n        </div>\n\n        {/* 唱臂 */}\n        <Tonearm isPlaying={isPlaying} />\n      </div>\n\n      {/* 文件名 */}\n      <div className={`rfp-text-center rfp-max-w-md rfp-flex-shrink-0 ${isCompact ? 'rfp-px-2' : 'rfp-px-4'}`}>\n        <MarqueeText\n          text={fileName}\n          className={`rfp-font-medium rfp-text-fg-primary ${isCompact ? 'rfp-text-sm' : 'rfp-text-lg'}`}\n        />\n      </div>\n\n      {/* 控制面板 wrapper：按容器宽度整体缩放，保底视觉宽度 320px */}\n      <div\n        className=\"rfp-w-full rfp-flex rfp-justify-center rfp-flex-shrink-0\"\n      >\n        <div\n          className={`rfp-rounded-2xl rfp-border rfp-bg-surface-1 rfp-border-line-weak ${\n            isCompact ? 'rfp-p-3' : 'rfp-p-5'\n          }`}\n          style={{\n            width: '448px',\n            backdropFilter: 'blur(16px)',\n            transform: controlScale < 1 ? `scale(${controlScale})` : undefined,\n            transformOrigin: 'top center',\n            marginBottom: controlScale < 1 ? `${-(1 - controlScale) * 100}px` : undefined,\n          }}\n        >\n        {/* 进度条 */}\n        <div className={isCompact ? 'rfp-mb-3' : 'rfp-mb-5'}>\n          <div className=\"rfp-relative rfp-h-4 rfp-flex rfp-items-center\">\n            <div className=\"rfp-absolute rfp-w-full rfp-h-[5px] rfp-rounded-full rfp-bg-surface-2\" />\n            <div\n              className=\"rfp-absolute rfp-h-[5px] rfp-rounded-full rfp-pointer-events-none\"\n              style={{\n                width: `${progress * 100}%`,\n                background: 'linear-gradient(90deg, var(--fp-accent), var(--fp-accent-hover))',\n                boxShadow: isPlaying ? '0 0 8px rgba(129,140,248,0.4)' : 'none',\n                transition: isDragging ? 'none' : 'width 0.1s linear',\n              }}\n            />\n            <input\n              type=\"range\"\n              min=\"0\"\n              max={duration > 0 ? duration : currentTime || 100}\n              step=\"any\"\n              value={displayTime}\n              onPointerDown={() => {\n                setDragTime(currentTime);\n                setIsDragging(true);\n              }}\n              onChange={(e) => {\n                const value = parseFloat(e.target.value);\n                if (isDragging) {\n                  setDragTime(value);\n                } else {\n                  seek(value);\n                }\n              }}\n              onPointerUp={(e) => {\n                const value = parseFloat((e.target as HTMLInputElement).value);\n                seek(value);\n                setIsDragging(false);\n              }}\n              onPointerCancel={() => setIsDragging(false)}\n              disabled={duration <= 0}\n              aria-label={t('audio.aria.progress')}\n              className=\"audio-slider rfp-absolute rfp-w-full\"\n            />\n          </div>\n          <div className={`rfp-flex rfp-justify-between rfp-text-fg-tertiary ${isCompact ? 'rfp-text-[10px] rfp-mt-1.5' : 'rfp-text-xs rfp-mt-2.5'}`}>\n            <span style={{ fontVariantNumeric: 'tabular-nums' }}>{formatTime(displayTime)}</span>\n            <span style={{ fontVariantNumeric: 'tabular-nums' }}>{duration > 0 ? formatTime(duration) : '--:--'}</span>\n          </div>\n        </div>\n\n        {/* 控制按钮 */}\n        <div className={`rfp-flex rfp-items-center rfp-justify-center ${isCompact ? 'rfp-gap-2' : 'rfp-gap-3'}`}>\n          {/* 循环 */}\n          <motion.button\n            onClick={toggleLoop}\n            whileHover={{ scale: 1.1 }}\n            whileTap={{ scale: 0.92 }}\n            aria-label={isLoop ? t('audio.aria.loop_off') : t('audio.aria.loop_on')}\n            className={`rfp-rounded-full rfp-flex rfp-items-center rfp-justify-center rfp-transition-colors rfp-flex-shrink-0 ${\n              isCompact ? 'rfp-w-8 rfp-h-8' : 'rfp-w-9 rfp-h-9'\n            } ${\n              isLoop\n                ? 'rfp-bg-accent-soft rfp-text-accent'\n                : 'rfp-bg-surface-2 rfp-text-fg-tertiary'\n            }`}\n          >\n            <Repeat className={isCompact ? 'rfp-w-3.5 rfp-h-3.5' : 'rfp-w-4 rfp-h-4'} />\n          </motion.button>\n\n          {/* 后退 */}\n          <motion.button\n            onClick={() => skip(-10)}\n            whileHover={{ scale: 1.1 }}\n            whileTap={{ scale: 0.92 }}\n            aria-label={t('audio.aria.backward_10')}\n            className={`rfp-rounded-full rfp-flex rfp-items-center rfp-justify-center rfp-transition-colors rfp-bg-surface-2 rfp-text-fg-secondary rfp-flex-shrink-0 ${\n              isCompact ? 'rfp-w-9 rfp-h-9' : 'rfp-w-10 rfp-h-10'\n            }`}\n          >\n            <SkipBack className={isCompact ? 'rfp-w-4 rfp-h-4' : 'rfp-w-[18px] rfp-h-[18px]'} />\n          </motion.button>\n\n          {/* 播放/暂停 */}\n          <motion.button\n            onClick={togglePlay}\n            whileHover={{ scale: 1.06 }}\n            whileTap={{ scale: 0.94 }}\n            aria-label={isPlaying ? t('audio.aria.pause') : t('audio.aria.play')}\n            className={`rfp-rounded-full rfp-flex rfp-items-center rfp-justify-center rfp-flex-shrink-0 ${\n              isCompact ? 'rfp-w-12 rfp-h-12' : 'rfp-w-14 rfp-h-14'\n            }`}\n            style={{\n              background: 'linear-gradient(135deg, var(--fp-accent-hover), var(--fp-accent))',\n              color: '#fff',\n              boxShadow: '0 4px 20px rgba(99,102,241,0.35)',\n            }}\n          >\n            {isPlaying ? (\n              <Pause className={isCompact ? 'rfp-w-5 rfp-h-5' : 'rfp-w-6 rfp-h-6'} />\n            ) : (\n              <Play className={isCompact ? 'rfp-w-5 rfp-h-5 rfp-ml-0.5' : 'rfp-w-6 rfp-h-6 rfp-ml-0.5'} />\n            )}\n          </motion.button>\n\n          {/* 前进 */}\n          <motion.button\n            onClick={() => skip(10)}\n            whileHover={{ scale: 1.1 }}\n            whileTap={{ scale: 0.92 }}\n            aria-label={t('audio.aria.forward_10')}\n            className={`rfp-rounded-full rfp-flex rfp-items-center rfp-justify-center rfp-transition-colors rfp-bg-surface-2 rfp-text-fg-secondary rfp-flex-shrink-0 ${\n              isCompact ? 'rfp-w-9 rfp-h-9' : 'rfp-w-10 rfp-h-10'\n            }`}\n          >\n            <SkipForward className={isCompact ? 'rfp-w-4 rfp-h-4' : 'rfp-w-[18px] rfp-h-[18px]'} />\n          </motion.button>\n\n          {/* 音量 */}\n          <div\n            ref={volumeRef}\n            className=\"rfp-relative\"\n            onMouseEnter={handleVolumeEnter}\n            onMouseLeave={handleVolumeLeave}\n          >\n            <motion.button\n              onClick={toggleMute}\n              whileHover={{ scale: 1.1 }}\n              whileTap={{ scale: 0.92 }}\n              aria-label={isMuted ? t('audio.aria.unmute') : t('audio.aria.mute')}\n              className={`rfp-rounded-full rfp-flex rfp-items-center rfp-justify-center rfp-transition-colors rfp-flex-shrink-0 ${\n                isCompact ? 'rfp-w-8 rfp-h-8' : 'rfp-w-9 rfp-h-9'\n              } ${\n                showVolume\n                  ? 'rfp-bg-accent-soft rfp-text-accent'\n                  : 'rfp-bg-surface-2 rfp-text-fg-secondary'\n              }`}\n            >\n              <VolumeIcon className={isCompact ? 'rfp-w-3.5 rfp-h-3.5' : 'rfp-w-4 rfp-h-4'} />\n            </motion.button>\n\n            <AnimatePresence>\n              {showVolume && (\n                <motion.div\n                  initial={{ opacity: 0, scale: 0.95 }}\n                  animate={{ opacity: 1, scale: 1 }}\n                  exit={{ opacity: 0, scale: 0.95 }}\n                  transition={{ duration: 0.12 }}\n                  className=\"rfp-absolute rfp-bottom-full rfp-mb-2 rfp-rounded-xl rfp-p-3 rfp-border rfp-bg-surface-3 rfp-border-line\"\n                  style={{\n                    left: '50%',\n                    marginLeft: '-27px',\n                    backdropFilter: 'blur(16px)',\n                  }}\n                  onMouseEnter={handleVolumeEnter}\n                  onMouseLeave={handleVolumeLeave}\n                >\n                  <div className=\"rfp-flex rfp-flex-col rfp-items-center rfp-gap-2\" style={{ height: '100px' }}>\n                    <div className=\"rfp-relative rfp-flex rfp-items-center rfp-justify-center\" style={{ width: '24px', height: '80px' }}>\n                      <div\n                        className=\"rfp-absolute rfp-rounded-full rfp-bg-surface-2\"\n                        style={{ width: '3px', height: '100%' }}\n                      />\n                      <div\n                        className=\"rfp-absolute rfp-bottom-0 rfp-rounded-full rfp-pointer-events-none\"\n                        style={{\n                          width: '3px',\n                          height: `${(isMuted ? 0 : volume) * 100}%`,\n                          background: 'var(--fp-accent-hover)',\n                          transition: 'height 0.1s linear',\n                        }}\n                      />\n                      <input\n                        type=\"range\"\n                        min=\"0\"\n                        max=\"1\"\n                        step=\"0.01\"\n                        value={isMuted ? 0 : volume}\n                        onChange={(e) => setVolume(parseFloat(e.target.value))}\n                        aria-label={t('audio.aria.volume')}\n                        className=\"volume-slider-vertical rfp-absolute\"\n                        style={{\n                          width: '80px',\n                          height: '24px',\n                          transform: 'rotate(-90deg)',\n                          transformOrigin: 'center center',\n                        }}\n                      />\n                    </div>\n                    <span className=\"rfp-text-[10px] rfp-tabular-nums rfp-text-fg-tertiary\">\n                      {Math.round((isMuted ? 0 : volume) * 100)}\n                    </span>\n                  </div>\n                </motion.div>\n              )}\n            </AnimatePresence>\n          </div>\n        </div>\n      </div>\n      {/* wrapper 闭合 */}\n      </div>\n\n      <audio ref={audioRef} src={url} className=\"rfp-hidden\" />\n    </div>\n  );\n});\n"],"names":["useAudioPlayer","url","audioRef","useRef","isPlaying","setIsPlaying","useState","isLoading","setIsLoading","currentTime","setCurrentTime","duration","setDuration","volume","setVolumeState","isMuted","setIsMuted","isLoop","setIsLoop","error","setError","useEffect","audio","onTimeUpdate","onDurationChange","onCanPlay","onWaiting","onPlaying","onPlay","onPause","onEnded","onError","togglePlay","useCallback","seek","time","skip","seconds","setVolume","vol","clamped","toggleMute","toggleLoop","next","formatTime","minutes","MarqueeText","text","className","style","containerRef","innerRef","overflow","setOverflow","scrollDist","setScrollDist","check","container","inner","cw","tw","observer","gap","totalScroll","dur","jsxs","motion","jsx","Tonearm","AudioRenderer","forwardRef","fileName","ref","t","useTranslator","showVolume","setShowVolume","isCompact","setIsCompact","controlScale","setControlScale","isDragging","setIsDragging","dragTime","setDragTime","volumeRef","volumeTimerRef","displayTime","progress","checkSize","height","width","baseWidth","minScale","scale","handleClickOutside","e","handleVolumeEnter","handleVolumeLeave","VolumeIcon","VolumeX","Volume1","Volume2","useImperativeHandle","RendererError","vinylScale","vinylBase","vinylHeightBase","finalVinylScale","value","Repeat","SkipBack","Pause","Play","SkipForward","AnimatePresence"],"mappings":"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"}