enzostvs HF staff commited on
Commit
cb3a187
·
1 Parent(s): a08a11e

add speech recognition

Browse files
module.d.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ declare module "react-speech-recognition";
package-lock.json CHANGED
@@ -22,6 +22,7 @@
22
  "react-dom": "^19.0.0",
23
  "react-icons": "^5.5.0",
24
  "react-markdown": "^10.1.0",
 
25
  "react-toastify": "^11.0.5",
26
  "react-use": "^17.6.0",
27
  "tailwindcss": "^4.0.15"
@@ -31,6 +32,7 @@
31
  "@types/express": "^5.0.1",
32
  "@types/react": "^19.0.10",
33
  "@types/react-dom": "^19.0.4",
 
34
  "@vitejs/plugin-react": "^4.3.4",
35
  "eslint": "^9.21.0",
36
  "eslint-plugin-react-hooks": "^5.1.0",
@@ -1608,6 +1610,12 @@
1608
  "@types/ms": "*"
1609
  }
1610
  },
 
 
 
 
 
 
1611
  "node_modules/@types/estree": {
1612
  "version": "1.0.6",
1613
  "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@@ -1730,6 +1738,15 @@
1730
  "@types/react": "^19.0.0"
1731
  }
1732
  },
 
 
 
 
 
 
 
 
 
1733
  "node_modules/@types/send": {
1734
  "version": "0.17.4",
1735
  "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
@@ -5370,6 +5387,14 @@
5370
  "node": ">=0.10.0"
5371
  }
5372
  },
 
 
 
 
 
 
 
 
5373
  "node_modules/react-toastify": {
5374
  "version": "11.0.5",
5375
  "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz",
 
22
  "react-dom": "^19.0.0",
23
  "react-icons": "^5.5.0",
24
  "react-markdown": "^10.1.0",
25
+ "react-speech-recognition": "^4.0.0",
26
  "react-toastify": "^11.0.5",
27
  "react-use": "^17.6.0",
28
  "tailwindcss": "^4.0.15"
 
32
  "@types/express": "^5.0.1",
33
  "@types/react": "^19.0.10",
34
  "@types/react-dom": "^19.0.4",
35
+ "@types/react-speech-recognition": "^3.9.6",
36
  "@vitejs/plugin-react": "^4.3.4",
37
  "eslint": "^9.21.0",
38
  "eslint-plugin-react-hooks": "^5.1.0",
 
1610
  "@types/ms": "*"
1611
  }
1612
  },
1613
+ "node_modules/@types/dom-speech-recognition": {
1614
+ "version": "0.0.6",
1615
+ "resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.6.tgz",
1616
+ "integrity": "sha512-o7pAVq9UQPJL5RDjO1f/fcpfFHdgiMnR4PoIU2N/ZQrYOS3C5rzdOJMsrpqeBCbii2EE9mERXgqspQqPDdPahw==",
1617
+ "dev": true
1618
+ },
1619
  "node_modules/@types/estree": {
1620
  "version": "1.0.6",
1621
  "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
 
1738
  "@types/react": "^19.0.0"
1739
  }
1740
  },
1741
+ "node_modules/@types/react-speech-recognition": {
1742
+ "version": "3.9.6",
1743
+ "resolved": "https://registry.npmjs.org/@types/react-speech-recognition/-/react-speech-recognition-3.9.6.tgz",
1744
+ "integrity": "sha512-cdzwXIZXWyp8zfM2XI7APDW1rZf4Nz73T4SIS2y+cC7zHnZluCdumYKH6HacxgxJH+zemAq2oXbHWXcyW0eT3A==",
1745
+ "dev": true,
1746
+ "dependencies": {
1747
+ "@types/dom-speech-recognition": "*"
1748
+ }
1749
+ },
1750
  "node_modules/@types/send": {
1751
  "version": "0.17.4",
1752
  "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
 
5387
  "node": ">=0.10.0"
5388
  }
5389
  },
5390
+ "node_modules/react-speech-recognition": {
5391
+ "version": "4.0.0",
5392
+ "resolved": "https://registry.npmjs.org/react-speech-recognition/-/react-speech-recognition-4.0.0.tgz",
5393
+ "integrity": "sha512-hz1OsRhjAW70rOMVXN84PR+1L2I1j8xS1TXpwpd4vlDaRY9i/LbAaxEklqscgObECTTuyxNeGBdVdcq/pX3bqQ==",
5394
+ "peerDependencies": {
5395
+ "react": ">=16.8.0"
5396
+ }
5397
+ },
5398
  "node_modules/react-toastify": {
5399
  "version": "11.0.5",
5400
  "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz",
package.json CHANGED
@@ -25,6 +25,7 @@
25
  "react-dom": "^19.0.0",
26
  "react-icons": "^5.5.0",
27
  "react-markdown": "^10.1.0",
 
28
  "react-toastify": "^11.0.5",
29
  "react-use": "^17.6.0",
30
  "tailwindcss": "^4.0.15"
@@ -34,6 +35,7 @@
34
  "@types/express": "^5.0.1",
35
  "@types/react": "^19.0.10",
36
  "@types/react-dom": "^19.0.4",
 
37
  "@vitejs/plugin-react": "^4.3.4",
38
  "eslint": "^9.21.0",
39
  "eslint-plugin-react-hooks": "^5.1.0",
 
25
  "react-dom": "^19.0.0",
26
  "react-icons": "^5.5.0",
27
  "react-markdown": "^10.1.0",
28
+ "react-speech-recognition": "^4.0.0",
29
  "react-toastify": "^11.0.5",
30
  "react-use": "^17.6.0",
31
  "tailwindcss": "^4.0.15"
 
35
  "@types/express": "^5.0.1",
36
  "@types/react": "^19.0.10",
37
  "@types/react-dom": "^19.0.4",
38
+ "@types/react-speech-recognition": "^3.9.6",
39
  "@vitejs/plugin-react": "^4.3.4",
40
  "eslint": "^9.21.0",
41
  "eslint-plugin-react-hooks": "^5.1.0",
src/components/App.tsx CHANGED
@@ -23,8 +23,6 @@ function App() {
23
  const [htmlStorage, , removeHtmlStorage] = useLocalStorage("html_content");
24
  const remix = useSearchParam("remix");
25
 
26
- console.log("REMIX => ", remix);
27
-
28
  const preview = useRef<HTMLDivElement>(null);
29
  const editor = useRef<HTMLDivElement>(null);
30
  const resizer = useRef<HTMLDivElement>(null);
 
23
  const [htmlStorage, , removeHtmlStorage] = useLocalStorage("html_content");
24
  const remix = useSearchParam("remix");
25
 
 
 
26
  const preview = useRef<HTMLDivElement>(null);
27
  const editor = useRef<HTMLDivElement>(null);
28
  const resizer = useRef<HTMLDivElement>(null);
src/components/ask-ai/ask-ai.tsx CHANGED
@@ -1,3 +1,4 @@
 
1
  import { useState } from "react";
2
  import { RiSparkling2Fill } from "react-icons/ri";
3
  import { GrSend } from "react-icons/gr";
@@ -10,6 +11,7 @@ import Login from "../login/login";
10
  import { defaultHTML } from "./../../../utils/consts";
11
  import SuccessSound from "./../../assets/success.mp3";
12
  import Settings from "../settings/settings";
 
13
 
14
  function AskAI({
15
  html,
@@ -166,6 +168,7 @@ function AskAI({
166
  }}
167
  />
168
  <div className="flex items-center justify-end gap-2">
 
169
  <Settings
170
  provider={provider as string}
171
  onChange={setProvider}
 
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
  import { useState } from "react";
3
  import { RiSparkling2Fill } from "react-icons/ri";
4
  import { GrSend } from "react-icons/gr";
 
11
  import { defaultHTML } from "./../../../utils/consts";
12
  import SuccessSound from "./../../assets/success.mp3";
13
  import Settings from "../settings/settings";
14
+ import SpeechPrompt from "../speech-prompt/speech-prompt";
15
 
16
  function AskAI({
17
  html,
 
168
  }}
169
  />
170
  <div className="flex items-center justify-end gap-2">
171
+ <SpeechPrompt setPrompt={setPrompt} />
172
  <Settings
173
  provider={provider as string}
174
  onChange={setProvider}
src/components/speech-prompt/speech-prompt.tsx ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import classNames from "classnames";
2
+ import { FaMicrophone } from "react-icons/fa";
3
+ import SpeechRecognition, {
4
+ useSpeechRecognition,
5
+ } from "react-speech-recognition";
6
+ import { useUpdateEffect } from "react-use";
7
+
8
+ function SpeechPrompt({
9
+ setPrompt,
10
+ }: {
11
+ setPrompt: React.Dispatch<React.SetStateAction<string>>;
12
+ }) {
13
+ const { transcript, listening, browserSupportsSpeechRecognition } =
14
+ useSpeechRecognition();
15
+
16
+ const startListening = () =>
17
+ SpeechRecognition.startListening({ continuous: true });
18
+
19
+ if (!browserSupportsSpeechRecognition) {
20
+ return null;
21
+ }
22
+
23
+ // eslint-disable-next-line react-hooks/rules-of-hooks
24
+ useUpdateEffect(() => {
25
+ if (transcript) setPrompt(transcript);
26
+ }, [transcript]);
27
+
28
+ return (
29
+ <button
30
+ className={classNames(
31
+ "flex cursor-pointer flex-none items-center justify-center rounded-full text-sm font-semibold size-8 text-center bg-gray-800 hover:bg-gray-700 text-white shadow-sm dark:shadow-highlight/20 disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed disabled:hover:bg-gray-300",
32
+ {
33
+ "animate-pulse !bg-orange-500": listening,
34
+ }
35
+ )}
36
+ onTouchStart={startListening}
37
+ onMouseDown={startListening}
38
+ onTouchEnd={SpeechRecognition.stopListening}
39
+ onMouseUp={SpeechRecognition.stopListening}
40
+ >
41
+ <FaMicrophone className="text-base" />
42
+ </button>
43
+ );
44
+ }
45
+
46
+ export default SpeechPrompt;