UNPKG

react-speech-recognition-ui

Version:

A beautiful, production-ready voice transcription package for React applications using the Web Speech API

65 lines (63 loc) 17.2 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react"),e=require("react/jsx-runtime"),F=(n={})=>{const{continuous:c=!0,interimResults:o=!0,language:i="en-US",onResult:s,onError:u,onStart:r,onEnd:d}=n,[h,x]=a.useState(""),[t,b]=a.useState(""),[p,k]=a.useState(!1),[S,y]=a.useState(null),[R,T]=a.useState(0),m=a.useRef(null),w="SpeechRecognition"in window||"webkitSpeechRecognition"in window,L=a.useCallback(()=>{if(!w)return null;const j=window.SpeechRecognition||window.webkitSpeechRecognition,v=new j;return v.continuous=c,v.interimResults=o,v.lang=i,v.onstart=()=>{k(!0),y(null),r==null||r()},v.onresult=C=>{let N="",E="";for(let M=C.resultIndex;M<C.results.length;M++){const $=C.results[M],A=$[0].transcript;$.isFinal?(N+=A,T($[0].confidence)):E+=A}N&&(x(M=>M+N),s==null||s({transcript:N,confidence:R,isFinal:!0,timestamp:Date.now()})),b(E)},v.onerror=C=>{const N=q(C.error);y(N),k(!1),u==null||u(N)},v.onend=()=>{k(!1),b(""),d==null||d()},v},[c,o,i,s,u,r,d,w]),U=a.useCallback(()=>{if(!w){y("Speech recognition is not supported in this browser");return}if(m.current&&m.current.stop(),m.current=L(),m.current)try{m.current.start()}catch{y("Failed to start speech recognition")}},[w,L]),l=a.useCallback(()=>{m.current&&(m.current.stop(),m.current=null)},[]),f=a.useCallback(()=>{l(),x(""),b(""),y(null),T(0)},[l]);return a.useEffect(()=>()=>{m.current&&m.current.stop()},[]),{transcript:h,interimTranscript:t,isListening:p,isSupported:w,error:S,confidence:R,start:U,stop:l,reset:f}},q=n=>{switch(n){case"no-speech":return"No speech was detected. Please try again.";case"audio-capture":return"Audio capture failed. Please check your microphone.";case"not-allowed":return"Microphone access denied. Please grant permission.";case"network":return"Network error occurred. Please check your connection.";default:return"An error occurred during speech recognition."}};/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */var z={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const G=n=>n.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().trim(),g=(n,c)=>{const o=a.forwardRef(({color:i="currentColor",size:s=24,strokeWidth:u=2,absoluteStrokeWidth:r,className:d="",children:h,...x},t)=>a.createElement("svg",{ref:t,...z,width:s,height:s,stroke:i,strokeWidth:r?Number(u)*24/Number(s):u,className:["lucide",`lucide-${G(n)}`,d].join(" "),...x},[...c.map(([b,p])=>a.createElement(b,p)),...Array.isArray(h)?h:[h]]));return o.displayName=`${n}`,o};/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const V=g("Clock",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["polyline",{points:"12 6 12 12 16 14",key:"68esgv"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const H=g("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const B=g("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const K=g("Globe",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const I=g("MicOff",[["line",{x1:"2",x2:"22",y1:"2",y2:"22",key:"a6p6uj"}],["path",{d:"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2",key:"80xlxr"}],["path",{d:"M5 10v2a7 7 0 0 0 12 5",key:"p2k8kg"}],["path",{d:"M15 9.34V5a3 3 0 0 0-5.68-1.33",key:"1gzdoj"}],["path",{d:"M9 9v3a3 3 0 0 0 5.12 2.12",key:"r2i35w"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22",key:"x3vr5v"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const D=g("Mic",[["path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z",key:"131961"}],["path",{d:"M19 10v2a7 7 0 0 1-14 0v-2",key:"1vc78b"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22",key:"x3vr5v"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const W=g("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const J=g("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const O=g("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);/** * @license lucide-react v0.344.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const Z=g("Volume2",[["polygon",{points:"11 5 6 9 2 9 2 15 6 15 11 19 11 5",key:"16drj5"}],["path",{d:"M15.54 8.46a5 5 0 0 1 0 7.07",key:"ltjumu"}],["path",{d:"M19.07 4.93a10 10 0 0 1 0 14.14",key:"1kegas"}]]),_=({onTranscriptChange:n,onResult:c,className:o="",language:i="en-US",continuous:s=!0,interimResults:u=!0,maxHeight:r="400px"})=>{const[d,h]=a.useState([]);a.useState(!1);const x=a.useCallback(l=>{h(f=>[...f,l]),c==null||c(l)},[c]),{transcript:t,interimTranscript:b,isListening:p,isSupported:k,error:S,confidence:y,start:R,stop:T,reset:m}=F({continuous:s,interimResults:u,language:i,onResult:x}),w=a.useCallback(()=>{navigator.clipboard.writeText(t)},[t]),L=a.useCallback(()=>{const l=new Blob([t],{type:"text/plain"}),f=URL.createObjectURL(l),j=document.createElement("a");j.href=f,j.download=`transcription-${new Date().toISOString().split("T")[0]}.txt`,document.body.appendChild(j),j.click(),document.body.removeChild(j),URL.revokeObjectURL(f)},[t]),U=a.useCallback(()=>{if("speechSynthesis"in window&&t){const l=new SpeechSynthesisUtterance(t);l.lang=i,speechSynthesis.speak(l)}},[t,i]);return k?e.jsxs("div",{className:`bg-white border border-gray-200 rounded-xl shadow-lg overflow-hidden ${o}`,children:[e.jsx("div",{className:"bg-gradient-to-r from-blue-600 to-purple-600 p-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-3",children:[e.jsx("div",{className:`p-2 rounded-full ${p?"bg-red-500":"bg-white/20"}`,children:p?e.jsx(D,{className:"h-6 w-6 text-white animate-pulse"}):e.jsx(I,{className:"h-6 w-6 text-white"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-white",children:"Voice Transcriber"}),e.jsx("p",{className:"text-blue-100 text-sm",children:p?"Listening...":"Ready to transcribe"})]})]}),e.jsx("div",{className:"flex items-center space-x-2",children:y>0&&e.jsxs("div",{className:"text-white text-sm",children:["Confidence: ",Math.round(y*100),"%"]})})]})}),e.jsx("div",{className:"p-4 bg-gray-50 border-b border-gray-200",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("button",{onClick:p?T:R,disabled:!!S,className:`flex items-center space-x-2 px-4 py-2 rounded-lg font-medium transition-all duration-200 ${p?"bg-red-500 hover:bg-red-600 text-white":"bg-blue-500 hover:bg-blue-600 text-white"} disabled:opacity-50 disabled:cursor-not-allowed`,children:p?e.jsxs(e.Fragment,{children:[e.jsx(J,{className:"h-4 w-4"}),e.jsx("span",{children:"Stop"})]}):e.jsxs(e.Fragment,{children:[e.jsx(D,{className:"h-4 w-4"}),e.jsx("span",{children:"Start"})]})}),e.jsxs("button",{onClick:m,className:"flex items-center space-x-2 px-4 py-2 bg-gray-500 hover:bg-gray-600 text-white rounded-lg font-medium transition-all duration-200",children:[e.jsx(W,{className:"h-4 w-4"}),e.jsx("span",{children:"Reset"})]})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("button",{onClick:w,disabled:!t,className:"p-2 bg-gray-200 hover:bg-gray-300 rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",title:"Copy transcript",children:e.jsx(H,{className:"h-4 w-4 text-gray-600"})}),e.jsx("button",{onClick:L,disabled:!t,className:"p-2 bg-gray-200 hover:bg-gray-300 rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",title:"Download transcript",children:e.jsx(B,{className:"h-4 w-4 text-gray-600"})}),e.jsx("button",{onClick:U,disabled:!t,className:"p-2 bg-gray-200 hover:bg-gray-300 rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",title:"Speak transcript",children:e.jsx(Z,{className:"h-4 w-4 text-gray-600"})})]})]})}),S&&e.jsx("div",{className:"p-4 bg-red-50 border-b border-red-200",children:e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("div",{className:"h-2 w-2 bg-red-500 rounded-full"}),e.jsx("span",{className:"text-red-700 font-medium",children:S})]})}),e.jsxs("div",{className:"p-6",children:[e.jsx("div",{className:"min-h-[200px] p-4 bg-gray-50 rounded-lg border border-gray-200 overflow-y-auto",style:{maxHeight:r},children:t||b?e.jsxs("div",{className:"space-y-2",children:[t&&e.jsx("div",{className:"text-gray-900 leading-relaxed",children:t}),b&&e.jsx("div",{className:"text-gray-500 italic",children:b})]}):e.jsx("div",{className:"flex items-center justify-center h-full text-gray-500",children:e.jsxs("div",{className:"text-center",children:[e.jsx(D,{className:"h-12 w-12 mx-auto mb-2 text-gray-400"}),e.jsx("p",{children:'Click "Start" to begin transcription'})]})})}),t&&e.jsxs("div",{className:"mt-4 flex items-center justify-between text-sm text-gray-600",children:[e.jsxs("div",{children:["Words: ",t.split(" ").filter(l=>l.length>0).length]}),e.jsxs("div",{children:["Characters: ",t.length]}),e.jsxs("div",{children:["Results: ",d.length]})]})]})]}):e.jsx("div",{className:`p-6 bg-red-50 border border-red-200 rounded-xl ${o}`,children:e.jsxs("div",{className:"flex items-center space-x-3",children:[e.jsx(I,{className:"h-6 w-6 text-red-500"}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold text-red-800",children:"Not Supported"}),e.jsx("p",{className:"text-red-600",children:"Speech recognition is not supported in this browser."})]})]})})},Q=({history:n,onDelete:c,onClear:o,className:i=""})=>{const s=()=>{const r=n.map(t=>`[${new Date(t.timestamp).toLocaleString()}] ${t.transcript}`).join(` `),d=new Blob([r],{type:"text/plain"}),h=URL.createObjectURL(d),x=document.createElement("a");x.href=h,x.download=`transcription-history-${new Date().toISOString().split("T")[0]}.txt`,document.body.appendChild(x),x.click(),document.body.removeChild(x),URL.revokeObjectURL(h)},u=r=>{const d=Math.floor(r/60),h=Math.floor(r%60);return`${d}:${h.toString().padStart(2,"0")}`};return e.jsxs("div",{className:`bg-white border border-gray-200 rounded-xl shadow-lg overflow-hidden ${i}`,children:[e.jsx("div",{className:"bg-gradient-to-r from-green-600 to-blue-600 p-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-3",children:[e.jsx(V,{className:"h-6 w-6 text-white"}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-bold text-white",children:"Transcription History"}),e.jsxs("p",{className:"text-green-100 text-sm",children:[n.length," recordings"]})]})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsxs("button",{onClick:s,disabled:n.length===0,className:"flex items-center space-x-2 px-3 py-1 bg-white/20 hover:bg-white/30 rounded-lg text-white text-sm font-medium transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",children:[e.jsx(B,{className:"h-4 w-4"}),e.jsx("span",{children:"Download All"})]}),e.jsxs("button",{onClick:o,disabled:n.length===0,className:"flex items-center space-x-2 px-3 py-1 bg-red-500/20 hover:bg-red-500/30 rounded-lg text-white text-sm font-medium transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",children:[e.jsx(O,{className:"h-4 w-4"}),e.jsx("span",{children:"Clear All"})]})]})]})}),e.jsx("div",{className:"p-4",children:n.length===0?e.jsxs("div",{className:"text-center py-8 text-gray-500",children:[e.jsx(V,{className:"h-12 w-12 mx-auto mb-2 text-gray-400"}),e.jsx("p",{children:"No transcription history yet"})]}):e.jsx("div",{className:"space-y-3 max-h-96 overflow-y-auto",children:n.map(r=>e.jsx("div",{className:"p-4 bg-gray-50 border border-gray-200 rounded-lg hover:bg-gray-100 transition-colors duration-200",children:e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center space-x-3 mb-2",children:[e.jsx("span",{className:"text-sm text-gray-500",children:new Date(r.timestamp).toLocaleString()}),e.jsx("span",{className:"text-sm text-gray-500",children:u(r.duration)}),e.jsxs("span",{className:"text-sm text-gray-500",children:[Math.round(r.confidence*100),"% confidence"]})]}),e.jsx("p",{className:"text-gray-900 text-sm leading-relaxed",children:r.transcript})]}),e.jsx("button",{onClick:()=>c(r.id),className:"ml-4 p-1 text-gray-400 hover:text-red-500 transition-colors duration-200",children:e.jsx(O,{className:"h-4 w-4"})})]})},r.id))})})]})},P=[{code:"en-US",name:"English (US)",nativeName:"English (US)"},{code:"en-GB",name:"English (UK)",nativeName:"English (UK)"},{code:"es-ES",name:"Spanish",nativeName:"Español"},{code:"fr-FR",name:"French",nativeName:"Français"},{code:"de-DE",name:"German",nativeName:"Deutsch"},{code:"it-IT",name:"Italian",nativeName:"Italiano"},{code:"pt-BR",name:"Portuguese (Brazil)",nativeName:"Português (Brasil)"},{code:"ru-RU",name:"Russian",nativeName:"Русский"},{code:"ja-JP",name:"Japanese",nativeName:"日本語"},{code:"ko-KR",name:"Korean",nativeName:"한국어"},{code:"zh-CN",name:"Chinese (Simplified)",nativeName:"中文 (简体)"},{code:"zh-TW",name:"Chinese (Traditional)",nativeName:"中文 (繁體)"},{code:"ar-SA",name:"Arabic",nativeName:"العربية"},{code:"hi-IN",name:"Hindi",nativeName:"हिन्दी"}],X=({selectedLanguage:n,onLanguageChange:c,className:o=""})=>{const i=P.find(s=>s.code===n);return e.jsxs("div",{className:`bg-white border border-gray-200 rounded-xl shadow-lg overflow-hidden ${o}`,children:[e.jsx("div",{className:"bg-gradient-to-r from-purple-600 to-pink-600 p-4",children:e.jsxs("div",{className:"flex items-center space-x-3",children:[e.jsx(K,{className:"h-6 w-6 text-white"}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-bold text-white",children:"Language Settings"}),e.jsxs("p",{className:"text-purple-100 text-sm",children:["Currently: ",(i==null?void 0:i.nativeName)||"English (US)"]})]})]})}),e.jsxs("div",{className:"p-4",children:[e.jsx("label",{htmlFor:"language-select",className:"block text-sm font-medium text-gray-700 mb-2",children:"Select Language"}),e.jsx("select",{id:"language-select",value:n,onChange:s=>c(s.target.value),className:"w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent bg-white text-gray-900",children:P.map(s=>e.jsxs("option",{value:s.code,children:[s.nativeName," (",s.name,")"]},s.code))}),e.jsx("div",{className:"mt-4 p-3 bg-blue-50 border border-blue-200 rounded-lg",children:e.jsxs("p",{className:"text-sm text-blue-800",children:[e.jsx("strong",{children:"Note:"})," Language support depends on your browser and operating system. Some languages may not be available or may have limited accuracy."]})})]})]})};exports.LanguageSelector=X;exports.TranscriptionHistory=Q;exports.VoiceTranscriber=_;exports.useVoiceTranscription=F; //# sourceMappingURL=index.cjs.js.map