{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "music-player",
  "type": "registry:block",
  "title": "Music player",
  "description": "Music player",
  "files": [
    {
      "path": "components/usages/musicplayerusage.tsx",
      "content": "import { MusicPlayer } from \"@/registry/open-source/music-player\";\n\nexport default function Demo() {\n    return (\n        <MusicPlayer\n            src=\"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"\n            coverArt=\"https://i.scdn.co/image/ab67616d0000b27315ebbedaacef61af244262a8\"\n            className=\"w-full max-w-sm\"\n        />\n    );\n}",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/musicplayerusage.tsx",
      "content": "import { MusicPlayer } from \"@/registry/open-source/music-player\";\n\nexport default function Demo() {\n    return (\n        <MusicPlayer\n            src=\"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"\n            coverArt=\"https://i.scdn.co/image/ab67616d0000b27315ebbedaacef61af244262a8\"\n            className=\"w-full max-w-sm\"\n        />\n    );\n}",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/music-player.tsx",
      "content": "\"use client\";\n\nimport React, { useRef, useState, useEffect } from \"react\";\nimport { cn } from \"@/registry/utilities/cn\";\nimport { motion } from \"motion/react\";\n\nexport interface MusicPlayerProps extends React.HTMLAttributes<HTMLDivElement> {\n    /** The source URL of the audio file or YouTube video */\n    src: string;\n    /** The URL of the album cover image */\n    coverArt: string;\n    /** Whether to auto-play the audio when loaded */\n    autoPlay?: boolean;\n}\n\nexport function MusicPlayer({\n    className,\n    src,\n    coverArt,\n    autoPlay = false,\n    ...props\n}: MusicPlayerProps) {\n    const [isPlaying, setIsPlaying] = useState(autoPlay);\n    const audioRef = useRef<HTMLAudioElement | null>(null);\n    const iframeRef = useRef<HTMLIFrameElement | null>(null);\n\n    // Extract YouTube ID if it's a YouTube URL\n    const getYoutubeId = (url: string) => {\n        const match = url.match(\n            /(?:youtu\\.be\\/|youtube\\.com\\/(?:embed\\/|v\\/|watch\\?v=|watch\\?.+&v=))([^&?]+)/\n        );\n        return match ? match[1] : null;\n    };\n\n    const youtubeId = src ? getYoutubeId(src) : null;\n\n    useEffect(() => {\n        if (isPlaying) {\n            if (youtubeId && iframeRef.current?.contentWindow) {\n                iframeRef.current.contentWindow.postMessage(\n                    JSON.stringify({ event: \"command\", func: \"playVideo\", args: [] }),\n                    \"*\"\n                );\n            } else {\n                audioRef.current?.play().catch(() => setIsPlaying(false));\n            }\n        } else {\n            if (youtubeId && iframeRef.current?.contentWindow) {\n                iframeRef.current.contentWindow.postMessage(\n                    JSON.stringify({ event: \"command\", func: \"pauseVideo\", args: [] }),\n                    \"*\"\n                );\n            } else {\n                audioRef.current?.pause();\n            }\n        }\n    }, [isPlaying, youtubeId]);\n\n    const togglePlay = () => {\n        setIsPlaying(!isPlaying);\n    };\n\n    return (\n        <div\n            className={cn(\"relative inline-flex flex-col items-center\", className)}\n            {...props}\n        >\n            {youtubeId ? (\n                <iframe\n                    ref={iframeRef}\n                    className=\"hidden\"\n                    src={`https://www.youtube.com/embed/${youtubeId}?enablejsapi=1&autoplay=${autoPlay ? 1 : 0\n                        }&controls=0`}\n                    allow=\"autoplay\"\n                />\n            ) : (\n                <audio\n                    ref={audioRef}\n                    src={src}\n                    onEnded={() => setIsPlaying(false)}\n                    className=\"hidden\"\n                />\n            )}\n\n            <div\n                className=\"relative cursor-pointer select-none h-64 w-64 md:h-80 md:w-80\"\n                onClick={togglePlay}\n                title={isPlaying ? \"Pause\" : \"Play\"}\n            >\n                {/* Tonearm */}\n                <motion.div\n                    className=\"absolute z-20 top-[-5%] right-[-10%] sm:top-[-8%] sm:right-[-15%] origin-top-right w-[60%] h-[15%] pointer-events-none\"\n                    initial={{ rotate: 10 }}\n                    animate={{ rotate: isPlaying ? -20 : 10 }}\n                    transition={{ duration: 0.5, ease: \"easeInOut\" }}\n                >\n                    {/* Tonearm base */}\n                    <div className=\"absolute top-0 right-0 w-8 h-8 md:w-10 md:h-10 rounded-full bg-zinc-400 dark:bg-zinc-600 shadow-md transform translate-x-1/2 -translate-y-1/2 border-4 border-zinc-200 dark:border-zinc-800 z-10\" />\n                    {/* Tonearm stick & Needle */}\n                    <div className=\"absolute top-0 right-[10px] sm:right-[15px] w-[90%] h-2 md:h-3 bg-zinc-400 dark:bg-zinc-500 rounded-full origin-right -rotate-12 shadow-sm flex items-center justify-start\">\n                        {/* Needle */}\n                        <div className=\"w-4 h-4 md:w-5 md:h-5 bg-zinc-800 dark:bg-zinc-300 rounded-full shadow-md transform -translate-x-1/2\" />\n                    </div>\n                </motion.div>\n\n                {/* Record Disc */}\n                <div\n                    className={cn(\n                        \"relative w-full h-full rounded-full border-4 sm:border-8 border-black/10 dark:border-white/10 shadow-xl overflow-hidden shadow-black/30 bg-black animate-spin\"\n                    )}\n                    style={{\n                        animationDuration: \"4s\",\n                        animationPlayState: isPlaying ? \"running\" : \"paused\",\n                    }}\n                >\n                    {/* Album Cover Background */}\n                    <div\n                        className=\"absolute inset-0 bg-cover bg-center opacity-90 transition-opacity\"\n                        style={{ backgroundImage: `url(${coverArt})` }}\n                    />\n\n                    {/* Grooves Overlay (Multiple dark gradient rings) */}\n                    <div\n                        className=\"absolute inset-0 rounded-full border border-black/20\"\n                        style={{\n                            background:\n                                \"radial-gradient(circle, transparent 20%, rgba(0,0,0,0.4) 21%, transparent 22%, transparent 35%, rgba(0,0,0,0.5) 36%, transparent 37%, transparent 50%, rgba(0,0,0,0.3) 51%, transparent 52%, transparent 65%, rgba(0,0,0,0.6) 66%, transparent 67%, transparent 80%, rgba(0,0,0,0.4) 81%, transparent 82%)\",\n                        }}\n                    />\n\n                    {/* Glare effect */}\n                    <div\n                        className=\"absolute inset-0 rounded-full pointer-events-none\"\n                        style={{\n                            background:\n                                \"linear-gradient(135deg, rgba(255,255,255,0.4) 0%, transparent 40%, transparent 60%, rgba(255,255,255,0.2) 100%)\",\n                        }}\n                    />\n\n                    {/* Center Hole and Label Area */}\n                    <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-1/3 h-1/3 rounded-full bg-zinc-900 border border-zinc-700 shadow-inner flex items-center justify-center\">\n                        {/* The very center pin hole */}\n                        <div className=\"w-3 h-3 md:w-4 md:h-4 bg-zinc-300 dark:bg-zinc-600 rounded-full shadow-inner border border-black/40\" />\n                    </div>\n                </div>\n            </div>\n        </div>\n    );\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}