{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "speaker",
  "title": "Speaker",
  "description": "A text-to-speech speaker button component.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/flowui/components/speaker.tsx",
      "content": "// This component provides a speaker icon that, when clicked, uses the Web Speech API to read aloud the provided text\r\n// in the specified language.\r\n\r\n\"use client\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Volume2 } from \"lucide-react\";\r\nimport { useCallback, useEffect, useState } from \"react\";\r\n\r\ntype SpeakerProps = {\r\n    text: string;\r\n    lang?: string;\r\n    className?: string;\r\n};\r\n\r\nconst Speaker = ({ text, lang = 'en-IN', className }: SpeakerProps) => {\r\n    const [isSupported] = useState<boolean>(() => {\r\n        return typeof window !== 'undefined' && 'speechSynthesis' in window;\r\n    });\r\n  \r\n    const [voice, setVoice] = useState<SpeechSynthesisVoice | null>(null);\r\n\r\n    useEffect(() => {\r\n        if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\r\n\r\n            const setPreferredVoice = () => {\r\n                const voices = window.speechSynthesis.getVoices();\r\n                if(voices.length === 0) return;\r\n\r\n                // Try to find a specific, high-quality voice\r\n                const preferredVoice = voices.find(\r\n                    (v) => v.lang === lang && v.name.includes('Google')\r\n                ) || voices.find((v) => v.lang.startsWith(lang.split('-')[0])); // Fallback to any voice with the same language prefix\r\n\r\n                if (preferredVoice) {\r\n                    setVoice(preferredVoice);\r\n                }\r\n            };\r\n\r\n            window.speechSynthesis.addEventListener('voiceschanged', setPreferredVoice);\r\n            setPreferredVoice();\r\n\r\n            return () => {\r\n                window.speechSynthesis.removeEventListener('voiceschanged', setPreferredVoice);\r\n            };\r\n        }\r\n    }, []);\r\n\r\n    const speakText = useCallback(() => {\r\n        if (!isSupported) {\r\n            console.error('Web Speech API is not supported.');\r\n            return;\r\n        }\r\n\r\n        // 1. Cancel any currently speaking utterance\r\n        window.speechSynthesis.cancel(); \r\n\r\n        // 2. Create the utterance\r\n        const utterance = new SpeechSynthesisUtterance(`${text}`);\r\n\r\n        // 3. Apply the preferred voice if available\r\n        if (voice) {\r\n            utterance.voice = voice;\r\n        }\r\n\r\n        // 4. Set other optional properties\r\n        utterance.pitch = 1;\r\n        utterance.rate = 1;\r\n        utterance.lang = lang;\r\n\r\n        // 5. Speak the text\r\n        window.speechSynthesis.speak(utterance);\r\n    }, [isSupported, voice, text, lang]);\r\n\r\n    if (!isSupported) {\r\n        return null;\r\n    }\r\n\r\n    return (\r\n        <Volume2\r\n            onClick={speakText}\r\n            className={cn(\"size-6\",className)}\r\n        />\r\n    )\r\n}\r\n\r\nexport default Speaker;",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}