{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "wave-player",
  "title": "Wave Player",
  "description": "Full-featured wave player with play/pause, volume control, seek bar and optional title.",
  "dependencies": [
    "wavesurfer.js",
    "lucide-react"
  ],
  "registryDependencies": [
    "@waves-cn/wave-cn",
    "button",
    "card",
    "slider"
  ],
  "files": [
    {
      "path": "src/registry/components/wave-player.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Button } from \"@/components/ui/button\";\nimport { Slider } from \"@/components/ui/slider\";\nimport { Play, Pause, Volume2, VolumeX, RotateCcw } from \"lucide-react\";\nimport WavesurferPlayer, { formatTime, useWavePlayer } from \"@/lib/wave-cn\";\n\nexport interface WavePlayerProps {\n  /** Audio source URL */\n  src: string;\n  /** Optional title shown above the waveform */\n  title?: string;\n  /** Initial volume (0–1) */\n  defaultVolume?: number;\n  /** Audio bar color. Accepts any CSS value including var(--*) tokens @default \"var(--muted-foreground)\" */\n  waveColor?: string;\n  /** Progress bar color. Accepts any CSS value including var(--*) tokens @default \"var(--primary)\" */\n  progressColor?: string;\n  /** Waveform bar width in px @default 3 */\n  barWidth?: number;\n  /** Waveform bar gap in px @default 2 */\n  barGap?: number;\n  /** Rounded borders for bars @default 2 */\n  barRadius?: number;\n  /** Waveform height in px @default 64 */\n  waveHeight?: number;\n  /** Minimum pixels per second (zoom level) @default 1 */\n  minPxPerSec?: number;\n  /** Autoplay on mount */\n  autoPlay?: boolean;\n  /** Called when playback starts */\n  onPlay?: () => void;\n  /** Called when playback pauses */\n  onPause?: () => void;\n  /** Called when playback finishes */\n  onFinish?: () => void;\n  /** Called with current time on every audio process tick */\n  onTimeUpdate?: (currentTime: number, duration: number) => void;\n  className?: string;\n}\n\nexport function WavePlayer({\n  src,\n  title,\n  defaultVolume = 0.8,\n  waveColor,\n  progressColor,\n  barWidth,\n  barGap,\n  barRadius,\n  waveHeight,\n  minPxPerSec,\n  autoPlay = false,\n  onPlay,\n  onPause,\n  onFinish,\n  onTimeUpdate,\n  className,\n}: WavePlayerProps) {\n  const player = useWavePlayer({\n    defaultVolume,\n    autoPlay,\n    onPlay,\n    onPause,\n    onFinish,\n    onTimeUpdate,\n  });\n  const {\n    isReady,\n    isPlaying,\n    currentTime,\n    duration,\n    progress,\n    volume,\n    isMuted,\n    togglePlay,\n    restart,\n    toggleMute,\n    seek,\n    setVolume,\n  } = player;\n\n  const handleSeek = React.useCallback(([v]: number[]) => seek(v), [seek]);\n  const handleVolume = React.useCallback(\n    ([v]: number[]) => setVolume(v),\n    [setVolume],\n  );\n\n  // ── Render\n  return (\n    <Card\n      className={cn(\n        \"w-full px-0 border-0 rounded-none bg-transparent\",\n        className,\n      )}\n    >\n      <CardContent className=\" border-0 px-0 space-y-3\">\n        {title && (\n          <p className=\"text-sm font-medium text-foreground truncate\">\n            {title}\n          </p>\n        )}\n\n        <div className=\"relative w-full rounded-sm overflow-hidden bg-muted/40\">\n          <WavesurferPlayer\n            url={src}\n            waveColor={waveColor}\n            progressColor={progressColor}\n            height={waveHeight}\n            barWidth={barWidth}\n            barGap={barGap}\n            barRadius={barRadius}\n            minPxPerSec={minPxPerSec}\n            dragToSeek\n            {...player.handlers}\n          />\n        </div>\n\n        <div className=\"flex items-center gap-2\">\n          <span className=\"text-[11px] tabular-nums text-muted-foreground w-10 text-right shrink-0\">\n            {formatTime(currentTime)}\n          </span>\n          <Slider\n            className=\"flex-1\"\n            value={[progress]}\n            min={0}\n            max={1}\n            step={0.001}\n            disabled={!isReady}\n            onValueChange={handleSeek}\n            aria-label=\"Seek\"\n          />\n          <span className=\"text-[11px] tabular-nums text-muted-foreground w-10 shrink-0\">\n            {formatTime(duration)}\n          </span>\n        </div>\n\n        <div className=\"flex items-center justify-between gap-3\">\n          <div className=\"flex items-center gap-1.5\">\n            <Button\n              size=\"icon\"\n              variant=\"ghost\"\n              className=\"h-8 w-8 text-muted-foreground hover:text-foreground\"\n              disabled={!isReady}\n              onClick={restart}\n              aria-label=\"Restart\"\n            >\n              <RotateCcw size={15} />\n            </Button>\n            <Button\n              size=\"icon\"\n              variant=\"secondary\"\n              className=\"h-9 w-9\"\n              disabled={!isReady}\n              onClick={togglePlay}\n              aria-label={isPlaying ? \"Pause\" : \"Play\"}\n            >\n              {isPlaying ? <Pause size={17} /> : <Play size={17} />}\n            </Button>\n          </div>\n\n          <div className=\"flex items-center gap-2 w-36\">\n            <Button\n              size=\"icon\"\n              variant=\"ghost\"\n              className=\"h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground\"\n              onClick={toggleMute}\n              aria-label={isMuted ? \"Unmute\" : \"Mute\"}\n            >\n              {isMuted ? <VolumeX size={15} /> : <Volume2 size={15} />}\n            </Button>\n            <Slider\n              value={[isMuted ? 0 : volume]}\n              min={0}\n              max={1}\n              step={0.01}\n              onValueChange={handleVolume}\n              aria-label=\"Volume\"\n            />\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport default WavePlayer;\n",
      "type": "registry:component",
      "target": "components/waves-cn/wave-player.tsx"
    }
  ],
  "type": "registry:component"
}