{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "card-shove-2",
  "type": "registry:block",
  "title": "Card Shove 2",
  "author": "Kenney <https://kenney.nl>",
  "description": "A distinct, firm sound of a virtual card being shoved, implying a more forceful or confident action.",
  "files": [
    {
      "path": "registry/soundcn/sounds/card-shove-2/card-shove-2.ts",
      "content": "import type { SoundAsset } from \"@/lib/sound-types\";\n\nexport const cardShove2Sound: SoundAsset = {\n  name: \"card-shove-2\",\n  dataUri: \"data:audio/mpeg;base64,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\",\n  duration: 0.767,\n  format: \"mp3\",\n  license: \"CC0\",\n  author: \"Kenney\",\n};\n",
      "type": "registry:lib"
    },
    {
      "path": "registry/soundcn/lib/sound-types.ts",
      "content": "export interface SoundAsset {\r\n  /** Unique identifier for the sound */\r\n  name: string;\r\n  /** Base64-encoded data URI (data:audio/mpeg;base64,...) */\r\n  dataUri: string;\r\n  /** Duration in seconds */\r\n  duration: number;\r\n  /** Audio format */\r\n  format: \"mp3\" | \"wav\" | \"ogg\";\r\n  /** License identifier */\r\n  license: \"CC0\" | \"OGA-BY\" | \"MIT\";\r\n  /** Original author/creator */\r\n  author: string;\r\n}\r\n\r\nexport interface UseSoundOptions {\r\n  /** Volume level from 0 to 1. Default: 1 */\r\n  volume?: number;\r\n  /** Playback speed multiplier. Default: 1 */\r\n  playbackRate?: number;\r\n  /** If true, calling play() stops current playback first. Default: false */\r\n  interrupt?: boolean;\r\n  /** If false, play() does nothing. Useful for user preferences. Default: true */\r\n  soundEnabled?: boolean;\r\n  /** Called when playback starts */\r\n  onPlay?: () => void;\r\n  /** Called when playback ends naturally */\r\n  onEnd?: () => void;\r\n  /** Called when pause() is called */\r\n  onPause?: () => void;\r\n  /** Called when stop() is called */\r\n  onStop?: () => void;\r\n}\r\n\r\nexport type PlayFunction = (overrides?: {\r\n  volume?: number;\r\n  playbackRate?: number;\r\n}) => void;\r\n\r\nexport interface SoundControls {\r\n  stop: () => void;\r\n  pause: () => void;\r\n  isPlaying: boolean;\r\n  duration: number | null;\r\n  sound: SoundAsset;\r\n}\r\n\r\nexport type UseSoundReturn = readonly [PlayFunction, SoundControls];\r\n",
      "type": "registry:lib"
    },
    {
      "path": "registry/soundcn/lib/sound-engine.ts",
      "content": "let audioContext: AudioContext | null = null;\nconst bufferCache = new Map<string, AudioBuffer>();\n\nexport function getAudioContext(): AudioContext {\n  if (!audioContext) {\n    audioContext = new AudioContext();\n  }\n  return audioContext;\n}\n\nexport async function decodeAudioData(dataUri: string): Promise<AudioBuffer> {\n  const cached = bufferCache.get(dataUri);\n  if (cached) return cached;\n\n  const ctx = getAudioContext();\n  const base64 = dataUri.split(\",\")[1];\n  const binaryString = atob(base64);\n  const bytes = new Uint8Array(binaryString.length);\n  for (let i = 0; i < binaryString.length; i++) {\n    bytes[i] = binaryString.charCodeAt(i);\n  }\n\n  const audioBuffer = await ctx.decodeAudioData(bytes.buffer.slice(0));\n  bufferCache.set(dataUri, audioBuffer);\n  return audioBuffer;\n}\n\nexport interface PlaySoundOptions {\n  volume?: number;\n  playbackRate?: number;\n  onEnd?: () => void;\n}\n\nexport interface SoundPlayback {\n  stop: () => void;\n}\n\nexport async function playSound(\n  dataUri: string,\n  options: PlaySoundOptions = {}\n): Promise<SoundPlayback> {\n  const { volume = 1, playbackRate = 1, onEnd } = options;\n  const ctx = getAudioContext();\n  if (ctx.state === \"suspended\") {\n    await ctx.resume();\n  }\n\n  const buffer = await decodeAudioData(dataUri);\n  const source = ctx.createBufferSource();\n  const gain = ctx.createGain();\n\n  source.buffer = buffer;\n  source.playbackRate.value = playbackRate;\n  gain.gain.value = volume;\n\n  source.connect(gain);\n  gain.connect(ctx.destination);\n\n  source.onended = () => {\n    onEnd?.();\n  };\n\n  source.start(0);\n\n  return {\n    stop: () => {\n      try {\n        source.stop();\n      } catch {\n        // No-op if already stopped.\n      }\n    },\n  };\n}\n",
      "type": "registry:lib"
    }
  ],
  "meta": {
    "duration": 0.767,
    "format": "mp3",
    "sizeKb": 7,
    "license": "CC0",
    "tags": [
      "card",
      "shove",
      "2"
    ],
    "keywords": [
      "card",
      "shove",
      "push",
      "move",
      "reposition",
      "discard",
      "game",
      "ui",
      "distinct",
      "firm",
      "forceful",
      "paper",
      "interaction",
      "feedback",
      "slide",
      "reorder",
      "flick",
      "action",
      "confident",
      "emphatic",
      "bold",
      "strong"
    ]
  },
  "categories": [
    "card"
  ]
}