@navsi.ai/sdk 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-BM6443KF.js +2 -0
- package/dist/chunk-BM6443KF.js.map +1 -0
- package/dist/chunk-EL7YGOTY.js +2 -0
- package/dist/{chunk-427NHGTX.js.map → chunk-EL7YGOTY.js.map} +1 -1
- package/dist/chunk-NVT44CWP.js +548 -0
- package/dist/chunk-NVT44CWP.js.map +1 -0
- package/dist/components/index.js +1 -1
- package/dist/hooks/index.d.ts +47 -1
- package/dist/hooks/index.js +1 -1
- package/dist/index.d.ts +21 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/dist/chunk-427NHGTX.js +0 -2
- package/dist/chunk-CSYGGJ3Q.js +0 -548
- package/dist/chunk-CSYGGJ3Q.js.map +0 -1
- package/dist/chunk-ZCUOPOFP.js +0 -2
- package/dist/chunk-ZCUOPOFP.js.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {createContext,useContext,useMemo,useState,useRef,useEffect,useCallback}from'react';var F=createContext(null);function d(){let e=useContext(F);if(!e)throw new Error("useChatbotContext must be used within a ChatbotProvider");return e}function J(){let e=d();return {widgetConfig:e.widgetConfig,voiceLanguage:e.voiceLanguage,setVoiceLanguage:e.setVoiceLanguage,messages:e.messages,sendMessage:e.sendMessage,clearMessages:e.clearMessages,mode:e.mode,setMode:e.setMode,isWidgetOpen:e.isWidgetOpen,setWidgetOpen:e.setWidgetOpen,isConnected:e.isConnected,connect:e.connect,disconnect:e.disconnect,executeAction:e.executeAction,registerServerAction:e.registerServerAction,stopExecution:e.stopExecution,isExecuting:e.isExecuting,error:e.error,clearError:e.clearError}}function X(){let e=d(),l=e.executionState?{current:e.executionState.currentIndex,total:e.executionState.totalCommands,percentage:e.executionState.totalCommands>0?Math.round(e.executionState.currentIndex/e.executionState.totalCommands*100):0,description:e.executionState.description}:null;return {isExecuting:e.isExecuting,executionState:e.executionState,currentCommand:e.executionState?.currentCommand,progress:l}}function ne(){let e=d();return {connectionState:e.connectionState,isConnected:e.connectionState==="connected",isConnecting:e.connectionState==="connecting",isReconnecting:e.connectionState==="reconnecting",connect:e.connect,disconnect:e.disconnect}}function D(){if(typeof window>"u")return null;let e=window;return e.SpeechRecognition??e.webkitSpeechRecognition??null}var H=typeof navigator<"u"&&"brave"in navigator;function Y(e){switch(e){case "network":return typeof navigator<"u"&&!navigator.onLine?"You appear to be offline \u2014 voice needs a network connection.":H?"Brave may block speech services. Disable Shields or try Chrome/Edge.":typeof window<"u"&&window.location.protocol!=="https:"&&!["localhost","127.0.0.1"].includes(window.location.hostname)?"Microphone access requires HTTPS.":"Network error \u2014 check mic permissions and reload.";case "not-allowed":case "service-not-allowed":return "Microphone permission is blocked.";case "no-speech":return "No speech detected \u2014 try again.";case "audio-capture":return "No microphone found.";case "aborted":return "";default:return `Voice error: ${e}`}}function _(e){return e.replace(/\*\*(.*?)\*\*/g,"$1").replace(/[*_~`#]/g,"").replace(/\[([^\]]+)\]\([^)]+\)/g,"$1").replace(/\n{2,}/g,". ").trim()}function re({lang:e,onTranscript:l,silenceMs:R=1200,autoSpeak:E=true}){let g=useMemo(D,[]),[x,p]=useState(false),[L,w]=useState(""),[V,f]=useState(null),[U,h]=useState(false),i=useRef(null),s=useRef(""),S=useRef(null),y=useRef(l),m=useRef(e),M=useRef(false),t=useRef(true);y.current=l,m.current=e,useEffect(()=>{if(M.current||typeof window>"u"||!("speechSynthesis"in window))return;M.current=true;let n=new SpeechSynthesisUtterance("");n.volume=0,window.speechSynthesis.speak(n);},[]);let c=useCallback(()=>{S.current&&(clearTimeout(S.current),S.current=null);},[]),C=useCallback(()=>{let n=s.current.trim();s.current="",t.current&&(w(""),n&&y.current(n));},[]),k=useCallback(()=>{if(!g)return null;if(i.current)return i.current.lang=m.current,i.current;let n=new g;return n.continuous=true,n.interimResults=true,n.maxAlternatives=1,n.lang=m.current,n.onstart=()=>{t.current&&(p(true),f(null),w(""),s.current="",typeof window<"u"&&"speechSynthesis"in window&&window.speechSynthesis.cancel());},n.onresult=r=>{if(!t.current)return;let o="";for(let b=r.resultIndex;b<r.results.length;b++){let A=r.results[b],W=A[0]?.transcript??"";A.isFinal?s.current=(s.current+" "+W).trim():o+=W;}w(s.current?s.current:o.trim()),c(),S.current=setTimeout(()=>{t.current&&(i.current?.stop(),C(),p(false));},R);},n.onerror=r=>{if(!t.current)return;let o=Y(r.error);o&&f(o),["not-allowed","service-not-allowed","audio-capture"].includes(r.error)&&(c(),p(false));},n.onend=()=>{t.current&&(c(),C(),p(false));},i.current=n,n},[g,c,C,R]),O=useCallback(()=>{if(x)return;f(null);let n=k();if(!n){f("Voice input is not supported in this browser.");return}try{n.start();}catch{}},[x,k]),T=useCallback(()=>{c();try{i.current?.stop();}catch{}},[c]),P=useCallback(n=>{if(typeof window>"u"||!("speechSynthesis"in window)||!E)return;let r=_(n);if(!r)return;window.speechSynthesis.cancel();let o=new SpeechSynthesisUtterance(r);o.lang=m.current,o.onstart=()=>{t.current&&h(true);},o.onend=()=>{t.current&&h(false);},o.onerror=()=>{t.current&&h(false);},window.speechSynthesis.speak(o);},[E]),B=useCallback(()=>{typeof window<"u"&&"speechSynthesis"in window&&window.speechSynthesis.cancel(),t.current&&h(false);},[]);return useEffect(()=>(t.current=true,()=>{t.current=false,c(),i.current?.abort(),i.current=null,typeof window<"u"&&"speechSynthesis"in window&&window.speechSynthesis.cancel();}),[c]),{isSupported:!!g,isListening:x,transcript:L,error:V,start:O,stop:T,speak:P,cancelSpeech:B,isSpeaking:U}}export{F as a,d as b,J as c,X as d,ne as e,re as f};//# sourceMappingURL=chunk-BM6443KF.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-BM6443KF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context/chatbot-context.tsx","../src/hooks/useChatbot.ts","../src/hooks/useActionExecution.ts","../src/hooks/useWebSocket.ts","../src/hooks/useVoice.ts"],"names":["ChatbotContext","createContext","useChatbotContext","context","useContext","useChatbot","useActionExecution","progress","useWebSocket","getRecognitionCtor","w","isBrave","friendlyError","code","stripMarkdown","text","useVoice","lang","onTranscript","silenceMs","autoSpeak","Ctor","useMemo","isListening","setIsListening","useState","transcript","setTranscript","error","setError","isSpeaking","setIsSpeaking","recRef","useRef","finalBuf","silenceTimer","onTranscriptRef","langRef","ttsWarm","mountedRef","useEffect","u","clearSilence","useCallback","flushTranscript","getOrCreateRec","rec","ev","interim","i","seg","msg","start","stop","speak","clean","cancelSpeech"],"mappings":"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","file":"chunk-BM6443KF.js","sourcesContent":["/**\n * Chatbot Context\n * \n * React context for chatbot state and functionality.\n */\n\nimport { createContext, useContext } from 'react';\nimport type {\n Message,\n ChatMode,\n ConnectionState,\n ServerAction,\n ExecutionState,\n WidgetConfig,\n} from '@navsi.ai/shared';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ChatbotContextValue {\n /** Widget styling and copy (from admin / API). Applied by ChatbotWidget. */\n widgetConfig: Partial<WidgetConfig> | null;\n\n // State\n messages: Message[];\n mode: ChatMode;\n connectionState: ConnectionState;\n isExecuting: boolean;\n executionState: ExecutionState | null;\n error: Error | null;\n\n // Widget visibility (persists across navigation)\n isWidgetOpen: boolean;\n setWidgetOpen: (open: boolean) => void;\n\n /** User-selected voice/response language (e.g. 'en-US', 'hi-IN'). Overrides widgetConfig.voiceLanguage when set. */\n voiceLanguage: string | undefined;\n setVoiceLanguage: (lang: string | undefined) => void;\n\n // Actions\n sendMessage: (content: string) => void;\n setMode: (mode: ChatMode) => void;\n executeAction: (actionId: string, params?: Record<string, unknown>) => Promise<unknown>;\n registerServerAction: (action: ServerAction) => void;\n clearMessages: () => void;\n clearError: () => void;\n stopExecution: () => void;\n\n // Connection\n connect: () => void;\n disconnect: () => void;\n isConnected: boolean;\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nexport const ChatbotContext = createContext<ChatbotContextValue | null>(null);\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to access chatbot context\n * Must be used within ChatbotProvider\n */\nexport function useChatbotContext(): ChatbotContextValue {\n const context = useContext(ChatbotContext);\n\n if (!context) {\n throw new Error('useChatbotContext must be used within a ChatbotProvider');\n }\n\n return context;\n}\n","/**\n * useChatbot Hook\n * \n * Main hook for accessing chatbot functionality.\n * Provides simplified API for common operations.\n */\n\nimport { useChatbotContext } from '../context/chatbot-context.js';\nimport type { ChatMode, ServerAction, Message, WidgetConfig } from '@navsi.ai/shared';\n\nexport interface UseChatbotReturn {\n /** Widget styling/copy from admin (or options). Use in ChatbotWidget. */\n widgetConfig: Partial<WidgetConfig> | null;\n\n /** Effective voice/response language (user-selected or config). Use for STT/TTS and locale. */\n voiceLanguage: string | undefined;\n setVoiceLanguage: (lang: string | undefined) => void;\n\n // Messages\n messages: Message[];\n sendMessage: (content: string) => void;\n clearMessages: () => void;\n\n // Mode\n mode: ChatMode;\n setMode: (mode: ChatMode) => void;\n\n // Widget visibility (persists across navigation)\n isWidgetOpen: boolean;\n setWidgetOpen: (open: boolean) => void;\n\n // Connection\n isConnected: boolean;\n connect: () => void;\n disconnect: () => void;\n\n // Actions\n executeAction: (actionId: string, params?: Record<string, unknown>) => Promise<unknown>;\n registerServerAction: (action: ServerAction) => void;\n stopExecution: () => void;\n\n // State\n isExecuting: boolean;\n error: Error | null;\n clearError: () => void;\n}\n\n/**\n * Main hook for chatbot functionality\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { \n * messages, \n * sendMessage, \n * isConnected,\n * mode,\n * setMode,\n * } = useChatbot();\n * \n * return (\n * <div>\n * <button onClick={() => sendMessage('Hello!')}>\n * Send\n * </button>\n * <button onClick={() => startVoice()}>\n * Start Voice\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useChatbot(): UseChatbotReturn {\n const context = useChatbotContext();\n\n return {\n widgetConfig: context.widgetConfig,\n voiceLanguage: context.voiceLanguage,\n setVoiceLanguage: context.setVoiceLanguage,\n // Messages\n messages: context.messages,\n sendMessage: context.sendMessage,\n clearMessages: context.clearMessages,\n\n // Mode\n mode: context.mode,\n setMode: context.setMode,\n\n // Widget visibility\n isWidgetOpen: context.isWidgetOpen,\n setWidgetOpen: context.setWidgetOpen,\n\n // Connection\n isConnected: context.isConnected,\n connect: context.connect,\n disconnect: context.disconnect,\n\n // Actions\n executeAction: context.executeAction,\n registerServerAction: context.registerServerAction,\n stopExecution: context.stopExecution,\n\n // State\n isExecuting: context.isExecuting,\n error: context.error,\n clearError: context.clearError,\n };\n}\n","/**\n * useActionExecution Hook\n * \n * Hook for monitoring action execution state.\n */\n\nimport { useChatbotContext } from '../context/chatbot-context.js';\nimport type { ExecutionState } from '@navsi.ai/shared';\n\nexport interface UseActionExecutionReturn {\n isExecuting: boolean;\n executionState: ExecutionState | null;\n currentCommand: ExecutionState['currentCommand'] | undefined;\n progress: {\n current: number;\n total: number;\n percentage: number;\n /** Optional human-readable description of the current step */\n description?: string;\n } | null;\n}\n\n/**\n * Hook for monitoring action execution\n */\nexport function useActionExecution(): UseActionExecutionReturn {\n const context = useChatbotContext();\n\n const progress = context.executionState\n ? {\n current: context.executionState.currentIndex,\n total: context.executionState.totalCommands,\n percentage: context.executionState.totalCommands > 0\n ? Math.round((context.executionState.currentIndex / context.executionState.totalCommands) * 100)\n : 0,\n description: context.executionState.description,\n }\n : null;\n\n return {\n isExecuting: context.isExecuting,\n executionState: context.executionState,\n currentCommand: context.executionState?.currentCommand,\n progress,\n };\n}\n","/**\n * useWebSocket Hook\n * \n * Hook for managing WebSocket connection state.\n */\n\nimport { useChatbotContext } from '../context/chatbot-context.js';\nimport type { ConnectionState } from '@navsi.ai/shared';\n\nexport interface UseWebSocketReturn {\n connectionState: ConnectionState;\n isConnected: boolean;\n isConnecting: boolean;\n isReconnecting: boolean;\n connect: () => void;\n disconnect: () => void;\n}\n\n/**\n * Hook for WebSocket connection management\n */\nexport function useWebSocket(): UseWebSocketReturn {\n const context = useChatbotContext();\n\n return {\n connectionState: context.connectionState,\n isConnected: context.connectionState === 'connected',\n isConnecting: context.connectionState === 'connecting',\n isReconnecting: context.connectionState === 'reconnecting',\n connect: context.connect,\n disconnect: context.disconnect,\n };\n}\n","/**\n * useVoice Hook — Low-latency STT + TTS for the Navsi chatbot.\n *\n * Design goals:\n * • Fast start: reuses a single SpeechRecognition instance across activations.\n * • Low latency: fires an auto-send after a configurable silence gap so the\n * user doesn't have to wait for the browser's default end-of-speech timeout.\n * • Clean separation: all voice state is encapsulated here; ChatbotWidget\n * only consumes the returned API.\n * • TTS warm-up: a silent utterance is queued once so the first real TTS play\n * doesn't incur a cold-start delay.\n *\n * Only depends on the Web Speech API — no extra packages.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\n// ---------------------------------------------------------------------------\n// Web Speech API type shims (not all TS libs ship these)\n// ---------------------------------------------------------------------------\n\ntype SpeechRecognitionCtor = new () => SpeechRecognitionInstance;\n\ninterface SpeechRecognitionInstance extends EventTarget {\n continuous: boolean;\n interimResults: boolean;\n maxAlternatives: number;\n lang: string;\n onstart: ((ev: Event) => void) | null;\n onend: ((ev: Event) => void) | null;\n onerror: ((ev: SpeechRecognitionErrorEvent) => void) | null;\n onresult: ((ev: SpeechRecognitionResultEvent) => void) | null;\n start: () => void;\n stop: () => void;\n abort: () => void;\n}\n\ninterface SpeechRecognitionErrorEvent extends Event {\n error: string;\n}\n\ninterface SpeechRecognitionResultEvent extends Event {\n resultIndex: number;\n results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionResultList {\n length: number;\n [index: number]: SpeechRecognitionResultItem;\n}\n\ninterface SpeechRecognitionResultItem {\n isFinal: boolean;\n length: number;\n [index: number]: { transcript: string };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getRecognitionCtor(): SpeechRecognitionCtor | null {\n if (typeof window === 'undefined') return null;\n const w = window as Window & {\n SpeechRecognition?: SpeechRecognitionCtor;\n webkitSpeechRecognition?: SpeechRecognitionCtor;\n };\n return w.SpeechRecognition ?? w.webkitSpeechRecognition ?? null;\n}\n\nconst isBrave = typeof navigator !== 'undefined' && 'brave' in navigator;\n\nfunction friendlyError(code: string): string {\n switch (code) {\n case 'network': {\n if (typeof navigator !== 'undefined' && !navigator.onLine)\n return 'You appear to be offline — voice needs a network connection.';\n if (isBrave)\n return 'Brave may block speech services. Disable Shields or try Chrome/Edge.';\n if (\n typeof window !== 'undefined' &&\n window.location.protocol !== 'https:' &&\n !['localhost', '127.0.0.1'].includes(window.location.hostname)\n )\n return 'Microphone access requires HTTPS.';\n return 'Network error — check mic permissions and reload.';\n }\n case 'not-allowed':\n case 'service-not-allowed':\n return 'Microphone permission is blocked.';\n case 'no-speech':\n return 'No speech detected — try again.';\n case 'audio-capture':\n return 'No microphone found.';\n case 'aborted':\n return ''; // intentional abort — don't show an error\n default:\n return `Voice error: ${code}`;\n }\n}\n\n/** Strip markdown formatting so TTS reads clean text. */\nfunction stripMarkdown(text: string): string {\n return text\n .replace(/\\*\\*(.*?)\\*\\*/g, '$1') // bold\n .replace(/[*_~`#]/g, '') // residual markers\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1') // links → label only\n .replace(/\\n{2,}/g, '. ') // paragraph breaks → pause\n .trim();\n}\n\n// ---------------------------------------------------------------------------\n// Public API types\n// ---------------------------------------------------------------------------\n\nexport interface UseVoiceOptions {\n /** BCP-47 language for STT & TTS (e.g. 'en-US'). */\n lang: string;\n /** Called with the final transcript when the user finishes speaking. */\n onTranscript: (text: string) => void;\n /** Milliseconds of silence before auto-sending (default 1200). */\n silenceMs?: number;\n /** Whether TTS should speak new assistant messages triggered by voice input. */\n autoSpeak?: boolean;\n}\n\nexport interface UseVoiceReturn {\n /** Whether the Web Speech API is available in this browser. */\n isSupported: boolean;\n /** Whether the mic is currently active / recording. */\n isListening: boolean;\n /** Live interim transcript while recording. */\n transcript: string;\n /** Human-readable error, or null. */\n error: string | null;\n /** Start recording. No-op if already listening. */\n start: () => void;\n /** Stop recording (fires onTranscript if there is accumulated text). */\n stop: () => void;\n /** Speak text aloud via TTS. */\n speak: (text: string) => void;\n /** Cancel any ongoing TTS playback. */\n cancelSpeech: () => void;\n /** Whether TTS is currently speaking. */\n isSpeaking: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useVoice({\n lang,\n onTranscript,\n silenceMs = 1200,\n autoSpeak = true,\n}: UseVoiceOptions): UseVoiceReturn {\n // ---- constructor (stable across renders) ----\n const Ctor = useMemo(getRecognitionCtor, []);\n\n // ---- state exposed to consumers ----\n const [isListening, setIsListening] = useState(false);\n const [transcript, setTranscript] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [isSpeaking, setIsSpeaking] = useState(false);\n\n // ---- internal refs ----\n const recRef = useRef<SpeechRecognitionInstance | null>(null);\n const finalBuf = useRef(''); // accumulated final fragments\n const silenceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const onTranscriptRef = useRef(onTranscript); // always-current callback\n const langRef = useRef(lang);\n const ttsWarm = useRef(false);\n const mountedRef = useRef(true);\n\n // Keep refs in sync without causing re-renders.\n onTranscriptRef.current = onTranscript;\n langRef.current = lang;\n\n // ---- TTS warm-up (run once after mount) ----\n useEffect(() => {\n if (ttsWarm.current) return;\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) return;\n ttsWarm.current = true;\n // A zero-length utterance warms up the synth engine so the first real\n // utterance plays without the browser's cold-start pause.\n const u = new SpeechSynthesisUtterance('');\n u.volume = 0;\n window.speechSynthesis.speak(u);\n }, []);\n\n // ---- helpers ----\n const clearSilence = useCallback(() => {\n if (silenceTimer.current) {\n clearTimeout(silenceTimer.current);\n silenceTimer.current = null;\n }\n }, []);\n\n const flushTranscript = useCallback(() => {\n const text = finalBuf.current.trim();\n finalBuf.current = '';\n if (!mountedRef.current) return;\n setTranscript('');\n if (text) onTranscriptRef.current(text);\n }, []);\n\n // ---- SpeechRecognition lifecycle ----\n\n /**\n * Lazily create (or reconfigure) a single SpeechRecognition instance.\n * Reusing the same instance avoids the ~300 ms startup cost of calling\n * `new SpeechRecognition()` each time.\n */\n const getOrCreateRec = useCallback((): SpeechRecognitionInstance | null => {\n if (!Ctor) return null;\n if (recRef.current) {\n // Just update the language — all handlers are already attached.\n recRef.current.lang = langRef.current;\n return recRef.current;\n }\n\n const rec = new Ctor();\n rec.continuous = true; // keep listening until explicitly stopped\n rec.interimResults = true;\n rec.maxAlternatives = 1;\n rec.lang = langRef.current;\n\n rec.onstart = () => {\n if (!mountedRef.current) return;\n setIsListening(true);\n setError(null);\n setTranscript('');\n finalBuf.current = '';\n // Cancel any ongoing TTS so the mic doesn't pick it up.\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\n window.speechSynthesis.cancel();\n }\n };\n\n rec.onresult = (ev: SpeechRecognitionResultEvent) => {\n if (!mountedRef.current) return;\n let interim = '';\n for (let i = ev.resultIndex; i < ev.results.length; i++) {\n const seg = ev.results[i];\n const text = seg[0]?.transcript ?? '';\n if (seg.isFinal) {\n finalBuf.current = (finalBuf.current + ' ' + text).trim();\n } else {\n interim += text;\n }\n }\n\n // Show the most relevant text to the user immediately.\n setTranscript(finalBuf.current ? finalBuf.current : interim.trim());\n\n // ---- silence-based auto-send ----\n // Every time we get a result reset the silence timer. When no new\n // results arrive for `silenceMs` we automatically flush.\n clearSilence();\n silenceTimer.current = setTimeout(() => {\n if (!mountedRef.current) return;\n // Stop the recognizer — `onend` will fire but with an empty buffer\n // because we already flushed.\n recRef.current?.stop();\n flushTranscript();\n setIsListening(false);\n }, silenceMs);\n };\n\n rec.onerror = (ev: SpeechRecognitionErrorEvent) => {\n if (!mountedRef.current) return;\n const msg = friendlyError(ev.error);\n if (msg) setError(msg);\n // For fatal errors, stop listening.\n if (['not-allowed', 'service-not-allowed', 'audio-capture'].includes(ev.error)) {\n clearSilence();\n setIsListening(false);\n }\n };\n\n rec.onend = () => {\n if (!mountedRef.current) return;\n clearSilence();\n // Flush anything remaining (e.g. the browser decided to stop early).\n flushTranscript();\n setIsListening(false);\n };\n\n recRef.current = rec;\n return rec;\n }, [Ctor, clearSilence, flushTranscript, silenceMs]);\n\n // ---- public: start / stop ----\n\n const start = useCallback(() => {\n if (isListening) return;\n setError(null);\n const rec = getOrCreateRec();\n if (!rec) {\n setError('Voice input is not supported in this browser.');\n return;\n }\n try {\n rec.start();\n } catch {\n // Already started — ignore.\n }\n }, [isListening, getOrCreateRec]);\n\n const stop = useCallback(() => {\n clearSilence();\n try {\n recRef.current?.stop();\n } catch {\n // Already stopped — ignore.\n }\n }, [clearSilence]);\n\n // ---- public: TTS ----\n\n const speak = useCallback(\n (text: string) => {\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) return;\n if (!autoSpeak) return;\n const clean = stripMarkdown(text);\n if (!clean) return;\n window.speechSynthesis.cancel();\n const u = new SpeechSynthesisUtterance(clean);\n u.lang = langRef.current;\n u.onstart = () => { if (mountedRef.current) setIsSpeaking(true); };\n u.onend = () => { if (mountedRef.current) setIsSpeaking(false); };\n u.onerror = () => { if (mountedRef.current) setIsSpeaking(false); };\n window.speechSynthesis.speak(u);\n },\n [autoSpeak],\n );\n\n const cancelSpeech = useCallback(() => {\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\n window.speechSynthesis.cancel();\n }\n if (mountedRef.current) setIsSpeaking(false);\n }, []);\n\n // ---- cleanup on unmount ----\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n clearSilence();\n recRef.current?.abort();\n recRef.current = null;\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\n window.speechSynthesis.cancel();\n }\n };\n }, [clearSilence]);\n\n return {\n isSupported: !!Ctor,\n isListening,\n transcript,\n error,\n start,\n stop,\n speak,\n cancelSpeech,\n isSpeaking,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-EL7YGOTY.js"}
|