"use client"
import { PauseIcon, PlayIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import {
AudioPlayerButton,
AudioPlayerDuration,
AudioPlayerProgress,
AudioPlayerProvider,
AudioPlayerSpeed,
AudioPlayerTime,
exampleTracks,
useAudioPlayer,
} from "@/components/ui/audio-player"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { ScrollArea } from "@/components/ui/scroll-area"
interface Track {
id: string
name: string
url: string
}
export default function AudioPlayer() {
return (
<AudioPlayerProvider<Track>>
<AudioPlayerDemo />
</AudioPlayerProvider>
)
}
const AudioPlayerDemo = () => {
return (
<Card className="w-full overflow-hidden p-0">
<div className="flex flex-col lg:h-[180px] lg:flex-row">
<div className="bg-muted/50 flex flex-col overflow-hidden lg:h-full lg:w-64">
<ScrollArea className="h-48 w-full lg:h-full">
<div className="space-y-1 p-3">
{exampleTracks.map((song, index) => (
<SongListItem
key={song.id}
song={song}
trackNumber={index + 1}
/>
))}
</div>
</ScrollArea>
</div>
<Player />
</div>
</Card>
)
}
const Player = () => {
const player = useAudioPlayer<Track>()
return (
<div className="flex flex-1 items-center p-4 sm:p-6">
<div className="mx-auto w-full max-w-2xl">
<div className="mb-4">
<h3 className="text-base font-semibold sm:text-lg">
{player.activeItem?.data?.name ?? "No track selected"}
</h3>
</div>
<div className="flex items-center gap-3 sm:gap-4">
<AudioPlayerButton
variant="outline"
size="default"
className="h-12 w-12 shrink-0 sm:h-10 sm:w-10"
disabled={!player.activeItem}
/>
<div className="flex flex-1 items-center gap-2 sm:gap-3">
<AudioPlayerTime className="text-xs tabular-nums" />
<AudioPlayerProgress className="flex-1" />
<AudioPlayerDuration className="text-xs tabular-nums" />
<AudioPlayerSpeed variant="ghost" size="icon" />
</div>
</div>
</div>
</div>
)
}
const SongListItem = ({
song,
trackNumber,
}: {
song: Track
trackNumber: number
}) => {
const player = useAudioPlayer<Track>()
const isActive = player.isItemActive(song.id)
const isCurrentlyPlaying = isActive && player.isPlaying
return (
<div className="group/song relative">
<Button
variant={isActive ? "secondary" : "ghost"}
size="sm"
className={cn(
"h-10 w-full justify-start px-3 font-normal sm:h-9 sm:px-2",
isActive && "bg-secondary"
)}
onClick={() => {
if (isCurrentlyPlaying) {
player.pause()
} else {
player.play({
id: song.id,
src: song.url,
data: song,
})
}
}}
>
<div className="flex w-full items-center gap-3">
<div className="flex w-5 shrink-0 items-center justify-center">
{isCurrentlyPlaying ? (
<PauseIcon className="h-4 w-4 sm:h-3.5 sm:w-3.5" />
) : (
<>
<span className="text-muted-foreground/60 text-sm tabular-nums group-hover/song:invisible">
{trackNumber}
</span>
<PlayIcon className="invisible absolute h-4 w-4 group-hover/song:visible sm:h-3.5 sm:w-3.5" />
</>
)}
</div>
<span className="truncate text-left text-sm">{song.name}</span>
</div>
</Button>
</div>
)
}