112 lines
3.8 KiB
TypeScript
112 lines
3.8 KiB
TypeScript
'use client'
|
|
|
|
interface PlayerControlsProps {
|
|
isPlaying: boolean
|
|
onPlayPause: () => void
|
|
onNext?: () => void
|
|
onPrevious?: () => void
|
|
volume: number
|
|
onVolumeChange: (volume: number) => void
|
|
isShuffle?: boolean
|
|
onShuffleToggle?: () => void
|
|
repeatMode?: 'off' | 'one' | 'all'
|
|
onRepeatToggle?: () => void
|
|
}
|
|
|
|
export function PlayerControls({
|
|
isPlaying,
|
|
onPlayPause,
|
|
onNext,
|
|
onPrevious,
|
|
volume,
|
|
onVolumeChange,
|
|
isShuffle = false,
|
|
onShuffleToggle,
|
|
repeatMode = 'off',
|
|
onRepeatToggle
|
|
}: PlayerControlsProps) {
|
|
return (
|
|
<div className="flex items-center justify-center gap-4">
|
|
{/* Shuffle */}
|
|
{onShuffleToggle && (
|
|
<button
|
|
onClick={onShuffleToggle}
|
|
className={`p-2 rounded transition ${
|
|
isShuffle ? 'text-purple-500' : 'text-zinc-400 hover:text-white'
|
|
}`}
|
|
title="Shuffle"
|
|
>
|
|
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M4 5h2v2H4V5zm0 4h2v2H4V9zm0 4h2v2H4v-2zm12-8h-2V3l3 3-3 3V7h-2c-1.1 0-2 .9-2 2v2c0 .37-.1.7-.29 1-.19.3-.45.54-.75.71l1.42 1.42c.54-.36.98-.85 1.28-1.43.3-.58.46-1.23.46-1.9V9c0-.55.45-1 1-1h2V5zm-6.71 6.71c-.19-.3-.45-.54-.75-.71l-1.42 1.42c.54.36.98.85 1.28 1.43.3.58.46 1.23.46 1.9V17h2v-2.25c0-.67-.16-1.32-.46-1.9-.3-.58-.74-1.07-1.28-1.43l1.42-1.42z" />
|
|
</svg>
|
|
</button>
|
|
)}
|
|
|
|
{/* Previous */}
|
|
{onPrevious && (
|
|
<button
|
|
onClick={onPrevious}
|
|
className="p-2 text-zinc-400 hover:text-white transition"
|
|
title="Previous"
|
|
>
|
|
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M5 4a1 1 0 00-2 0v12a1 1 0 102 0V4zm10.5.8c-.3-.2-.8 0-.8.5v9.4c0 .5.5.7.8.5l5-4.7c.3-.2.3-.6 0-.8l-5-4.9z" />
|
|
</svg>
|
|
</button>
|
|
)}
|
|
|
|
{/* Play/Pause */}
|
|
<button
|
|
onClick={onPlayPause}
|
|
className="w-12 h-12 rounded-full bg-purple-500 hover:bg-purple-600 flex items-center justify-center transition"
|
|
title={isPlaying ? 'Pause' : 'Play'}
|
|
>
|
|
{isPlaying ? (
|
|
<svg className="w-6 h-6 text-white" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M7 4h2v12H7V4zm4 0h2v12h-2V4z" />
|
|
</svg>
|
|
) : (
|
|
<svg className="w-6 h-6 text-white ml-0.5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M6.3 4.1c-.4-.2-.8 0-.8.4v11c0 .4.4.6.8.4l9-5.5c.3-.2.3-.6 0-.8l-9-5.5z" />
|
|
</svg>
|
|
)}
|
|
</button>
|
|
|
|
{/* Next */}
|
|
{onNext && (
|
|
<button
|
|
onClick={onNext}
|
|
className="p-2 text-zinc-400 hover:text-white transition"
|
|
title="Next"
|
|
>
|
|
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M15 4a1 1 0 012 0v12a1 1 0 01-2 0V4zM4.5 4.8c.3-.2.8 0 .8.5v9.4c0 .5-.5.7-.8.5l-5-4.7c-.3-.2-.3-.6 0-.8l5-4.9z" transform="scale(-1, 1) translate(-20, 0)" />
|
|
</svg>
|
|
</button>
|
|
)}
|
|
|
|
{/* Repeat */}
|
|
{onRepeatToggle && (
|
|
<button
|
|
onClick={onRepeatToggle}
|
|
className={`p-2 rounded transition ${
|
|
repeatMode !== 'off' ? 'text-purple-500' : 'text-zinc-400 hover:text-white'
|
|
}`}
|
|
title={`Repeat: ${repeatMode}`}
|
|
>
|
|
{repeatMode === 'one' ? (
|
|
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M4 5v2h12V5h2v4l-3-3-3 3V5h2zm8 10V7h-2v8H8l4 4 4-4h-4z" />
|
|
<text x="10" y="13" fontSize="8" textAnchor="middle" fill="currentColor">1</text>
|
|
</svg>
|
|
) : (
|
|
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M4 5v2h12V5h2l-3-3-3 3h2v2H4zm12 10v-2H4v2H2l3 3 3-3h-2v-2h12z" />
|
|
</svg>
|
|
)}
|
|
</button>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|