react-native-voice-ts 1.0.4 → 1.0.6

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.
@@ -25,10 +25,30 @@ export interface UseVoiceRecognitionOptions {
25
25
  * Callback fired when speech is recognized
26
26
  */
27
27
  onResult?: (text: string) => void;
28
+ /**
29
+ * Callback fired when partial results are available (real-time)
30
+ */
31
+ onPartialResult?: (text: string) => void;
28
32
  /**
29
33
  * Callback fired when an error occurs
30
34
  */
31
35
  onError?: (error: string) => void;
36
+ /**
37
+ * Callback fired when recording starts
38
+ */
39
+ onStart?: () => void;
40
+ /**
41
+ * Callback fired when recording ends
42
+ */
43
+ onEnd?: () => void;
44
+ /**
45
+ * Callback fired when speech is recognized (before results)
46
+ */
47
+ onRecognized?: () => void;
48
+ /**
49
+ * Callback fired when volume changes (0-10)
50
+ */
51
+ onVolumeChanged?: (value: number) => void;
32
52
  }
33
53
  export interface UseVoiceRecognitionReturn {
34
54
  /**
@@ -22,7 +22,7 @@ import Voice from '../index';
22
22
  * ```
23
23
  */
24
24
  export const useVoiceRecognition = (options = {}) => {
25
- const { locale = 'en-US', enablePartialResults = true, continuous = false, maxSilenceDuration = 5000, onResult, onError, } = options;
25
+ const { locale = 'en-US', enablePartialResults = true, continuous = false, maxSilenceDuration = 5000, onResult, onPartialResult, onError, onStart, onEnd, onRecognized, onVolumeChanged, } = options;
26
26
  const [isRecording, setIsRecording] = useState(false);
27
27
  const [results, setResults] = useState([]);
28
28
  const [partialResults, setPartialResults] = useState([]);
@@ -46,9 +46,11 @@ export const useVoiceRecognition = (options = {}) => {
46
46
  if (silenceTimerRef.current) {
47
47
  clearTimeout(silenceTimerRef.current);
48
48
  }
49
+ onStart?.();
49
50
  };
50
51
  Voice.onSpeechEnd = async () => {
51
52
  setIsRecording(false);
53
+ onEnd?.();
52
54
  // In continuous mode, restart listening after results
53
55
  if (continuous && shouldContinueRef.current) {
54
56
  setTimeout(async () => {
@@ -65,6 +67,9 @@ export const useVoiceRecognition = (options = {}) => {
65
67
  }, 100);
66
68
  }
67
69
  };
70
+ Voice.onSpeechRecognized = () => {
71
+ onRecognized?.();
72
+ };
68
73
  Voice.onSpeechError = (e) => {
69
74
  const errorMessage = e.error?.message || 'Unknown error';
70
75
  setError(errorMessage);
@@ -95,27 +100,34 @@ export const useVoiceRecognition = (options = {}) => {
95
100
  }
96
101
  }
97
102
  };
98
- if (enablePartialResults) {
99
- Voice.onSpeechPartialResults = (e) => {
100
- if (e.value && e.value.length > 0) {
101
- setPartialResults(e.value);
102
- // Reset silence timer on partial results (user is speaking)
103
- if (continuous && silenceTimerRef.current) {
104
- clearTimeout(silenceTimerRef.current);
105
- silenceTimerRef.current = setTimeout(async () => {
106
- if (shouldContinueRef.current) {
107
- shouldContinueRef.current = false;
108
- if (silenceTimerRef.current) {
109
- clearTimeout(silenceTimerRef.current);
110
- silenceTimerRef.current = null;
111
- }
112
- await Voice.stop();
103
+ Voice.onSpeechPartialResults = (e) => {
104
+ if (e.value && e.value.length > 0) {
105
+ setPartialResults(e.value);
106
+ const firstPartial = e.value[0];
107
+ if (firstPartial) {
108
+ onPartialResult?.(firstPartial);
109
+ }
110
+ // Reset silence timer on partial results (user is speaking)
111
+ if (continuous && silenceTimerRef.current) {
112
+ clearTimeout(silenceTimerRef.current);
113
+ silenceTimerRef.current = setTimeout(async () => {
114
+ if (shouldContinueRef.current) {
115
+ shouldContinueRef.current = false;
116
+ if (silenceTimerRef.current) {
117
+ clearTimeout(silenceTimerRef.current);
118
+ silenceTimerRef.current = null;
113
119
  }
114
- }, maxSilenceDuration);
115
- }
120
+ await Voice.stop();
121
+ }
122
+ }, maxSilenceDuration);
116
123
  }
117
- };
118
- }
124
+ }
125
+ };
126
+ Voice.onSpeechVolumeChanged = (e) => {
127
+ if (e.value !== undefined) {
128
+ onVolumeChanged?.(e.value);
129
+ }
130
+ };
119
131
  // Cleanup
120
132
  return () => {
121
133
  Voice.destroy().then(Voice.removeAllListeners);
@@ -123,7 +135,12 @@ export const useVoiceRecognition = (options = {}) => {
123
135
  }, [
124
136
  enablePartialResults,
125
137
  onResult,
138
+ onPartialResult,
126
139
  onError,
140
+ onStart,
141
+ onEnd,
142
+ onRecognized,
143
+ onVolumeChanged,
127
144
  continuous,
128
145
  locale,
129
146
  maxSilenceDuration,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-native-voice-ts",
3
3
  "description": "Advanced Speech-to-Text library for React Native with TypeScript support. Features ready-to-use components (VoiceMicrophone), custom hooks (useVoiceRecognition), real-time transcription, multi-language support, and comprehensive voice recognition capabilities for iOS and Android.",
4
- "version": "1.0.4",
4
+ "version": "1.0.6",
5
5
  "author": "Noor Mohammad <noor.jsdivs@gmail.com>",
6
6
  "private": false,
7
7
  "homepage": "https://github.com/noorjsdivs/react-native-voice-ts",
@@ -45,6 +45,7 @@
45
45
  "main": "dist/index.js",
46
46
  "types": "dist/index.d.ts",
47
47
  "files": [
48
+ "src",
48
49
  "dist",
49
50
  "android",
50
51
  "ios",
@@ -4,7 +4,7 @@ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
4
  folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
5
5
 
6
6
  Pod::Spec.new do |s|
7
- s.name = "react-native-voice"
7
+ s.name = "react-native-voice-ts"
8
8
  s.version = package['version']
9
9
  s.summary = package['description']
10
10
  s.license = package['license']
@@ -0,0 +1,28 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+ type SpeechType = {
4
+ EXTRA_LANGUAGE_MODEL: string;
5
+ EXTRA_MAX_RESULTS: string;
6
+ EXTRA_PARTIAL_RESULTS: string;
7
+ REQUEST_PERMISSIONS_AUTO: string;
8
+ RECOGNIZER_ENGINE: string;
9
+ };
10
+ export interface Spec extends TurboModule {
11
+ destroySpeech: (callback: (error: string) => void) => void;
12
+ startSpeech: (
13
+ locale: string,
14
+ opts: SpeechType,
15
+ callback: (error: string) => void,
16
+ ) => void;
17
+ stopSpeech: (callback: (error: string) => void) => void;
18
+ cancelSpeech: (callback: (error: string) => void) => void;
19
+ isSpeechAvailable: (
20
+ callback: (isAvailable: boolean, error: string) => void,
21
+ ) => void;
22
+ getSpeechRecognitionServices(): Promise<string[]>;
23
+ isRecognizing: (callback: (Recognizing: boolean) => void) => void;
24
+ addListener: (eventType: string) => void;
25
+ removeListeners: (count: number) => void;
26
+ }
27
+
28
+ export default TurboModuleRegistry.getEnforcing<Spec>('Voice');
@@ -0,0 +1,24 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export interface Spec extends TurboModule {
5
+ destroySpeech: (callback: (error: string) => void) => void;
6
+ startSpeech: (locale: string, callback: (error: string) => void) => void;
7
+ startTranscription: (
8
+ locale: string,
9
+ callback: (error: string) => void,
10
+ ) => void;
11
+ stopSpeech: (callback: (error: string) => void) => void;
12
+ stopTranscription: (callback: (error: string) => void) => void;
13
+ cancelSpeech: (callback: (error: string) => void) => void;
14
+ cancelTranscription: (callback: (error: string) => void) => void;
15
+ isSpeechAvailable: (
16
+ callback: (isAvailable: boolean, error: string) => void,
17
+ ) => void;
18
+ isRecognizing: (callback: (Recognizing: boolean) => void) => void;
19
+ addListener: (eventType: string) => void;
20
+ removeListeners: (count: number) => void;
21
+ destroyTranscription: (callback: (error: string) => void) => void;
22
+ }
23
+
24
+ export default TurboModuleRegistry.getEnforcing<Spec>('Voice');
@@ -0,0 +1,64 @@
1
+ export type SpeechEvents = {
2
+ onSpeechStart?: (e: SpeechStartEvent) => void;
3
+ onSpeechRecognized?: (e: SpeechRecognizedEvent) => void;
4
+ onSpeechEnd?: (e: SpeechEndEvent) => void;
5
+ onSpeechError?: (e: SpeechErrorEvent) => void;
6
+ onSpeechResults?: (e: SpeechResultsEvent) => void;
7
+ onSpeechPartialResults?: (e: SpeechResultsEvent) => void;
8
+ onSpeechVolumeChanged?: (e: SpeechVolumeChangeEvent) => void;
9
+ };
10
+
11
+ export type TranscriptionEvents = {
12
+ onTranscriptionStart?: (e: TranscriptionStartEvent) => void;
13
+ onTranscriptionEnd?: (e: TranscriptionEndEvent) => void;
14
+ onTranscriptionError?: (e: TranscriptionErrorEvent) => void;
15
+ onTranscriptionResults?: (e: TranscriptionResultsEvent) => void;
16
+ };
17
+
18
+ export type SpeechStartEvent = {
19
+ error?: boolean;
20
+ };
21
+
22
+ export type TranscriptionStartEvent = {
23
+ error?: boolean;
24
+ };
25
+
26
+ export type SpeechRecognizedEvent = {
27
+ isFinal?: boolean;
28
+ };
29
+
30
+ export type SpeechResultsEvent = {
31
+ value?: string[];
32
+ };
33
+
34
+ export type TranscriptionResultsEvent = {
35
+ segments?: string[];
36
+ transcription?: string;
37
+ isFinal?: boolean;
38
+ };
39
+
40
+ export type SpeechErrorEvent = {
41
+ error?: {
42
+ code?: string;
43
+ message?: string;
44
+ };
45
+ };
46
+
47
+ export type TranscriptionErrorEvent = {
48
+ error?: {
49
+ code?: string;
50
+ message?: string;
51
+ };
52
+ };
53
+
54
+ export type SpeechEndEvent = {
55
+ error?: boolean;
56
+ };
57
+
58
+ export type TranscriptionEndEvent = {
59
+ error?: boolean;
60
+ };
61
+
62
+ export type SpeechVolumeChangeEvent = {
63
+ value?: number;
64
+ };
@@ -0,0 +1,46 @@
1
+ /**
2
+ * React Native Voice - Speech Recognition Utility Types
3
+ *
4
+ * This file contains helper types and interfaces for working with
5
+ * speech recognition functionality.
6
+ */
7
+
8
+ export interface VoiceOptions {
9
+ /** Android: Language model type (LANGUAGE_MODEL_FREE_FORM or LANGUAGE_MODEL_WEB_SEARCH) */
10
+ EXTRA_LANGUAGE_MODEL?: string;
11
+ /** Android: Maximum number of results */
12
+ EXTRA_MAX_RESULTS?: number;
13
+ /** Android: Enable partial results */
14
+ EXTRA_PARTIAL_RESULTS?: boolean;
15
+ /** Android: Auto request permissions */
16
+ REQUEST_PERMISSIONS_AUTO?: boolean;
17
+ /** iOS: Detection mode (automatic, manual) */
18
+ iosCategory?: string;
19
+ }
20
+
21
+ export interface RecognitionStats {
22
+ /** Duration of recognition in milliseconds */
23
+ duration: number;
24
+ /** Whether recognition is currently active */
25
+ isActive: boolean;
26
+ /** Last recognized results */
27
+ lastResults: string[];
28
+ /** Start timestamp */
29
+ startTime: number;
30
+ }
31
+
32
+ export interface PermissionResult {
33
+ /** Whether permission was granted */
34
+ granted: boolean;
35
+ /** Error message if permission check failed */
36
+ error?: string;
37
+ }
38
+
39
+ export interface Language {
40
+ /** Language code (e.g., 'en-US') */
41
+ code: string;
42
+ /** Display name */
43
+ name: string;
44
+ /** Whether language is available */
45
+ available: boolean;
46
+ }
@@ -0,0 +1,208 @@
1
+ import React from 'react';
2
+ import Svg, { Path, Line } from 'react-native-svg';
3
+
4
+ export interface MicIconProps {
5
+ size?: number;
6
+ color?: string;
7
+ strokeWidth?: number;
8
+ }
9
+
10
+ /**
11
+ * Standard Microphone Icon (Variant 1)
12
+ * Classic microphone with rounded capsule
13
+ */
14
+ export const MicIcon: React.FC<MicIconProps> = ({
15
+ size = 24,
16
+ color = 'currentColor',
17
+ strokeWidth = 2,
18
+ }) => {
19
+ return (
20
+ <Svg
21
+ width={size}
22
+ height={size}
23
+ viewBox="0 0 24 24"
24
+ fill="none"
25
+ stroke={color}
26
+ strokeWidth={strokeWidth}
27
+ strokeLinecap="round"
28
+ strokeLinejoin="round"
29
+ >
30
+ <Path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" />
31
+ <Path d="M19 10v2a7 7 0 0 1-14 0v-2" />
32
+ <Line x1="12" y1="19" x2="12" y2="22" />
33
+ </Svg>
34
+ );
35
+ };
36
+
37
+ export interface MicOffIconProps {
38
+ size?: number;
39
+ color?: string;
40
+ strokeWidth?: number;
41
+ }
42
+
43
+ /**
44
+ * Standard Microphone Off Icon (Variant 1)
45
+ * Shows microphone with slash through it
46
+ */
47
+ export const MicOffIcon: React.FC<MicOffIconProps> = ({
48
+ size = 24,
49
+ color = 'currentColor',
50
+ strokeWidth = 2,
51
+ }) => {
52
+ return (
53
+ <Svg
54
+ width={size}
55
+ height={size}
56
+ viewBox="0 0 24 24"
57
+ fill="none"
58
+ stroke={color}
59
+ strokeWidth={strokeWidth}
60
+ strokeLinecap="round"
61
+ strokeLinejoin="round"
62
+ >
63
+ <Line x1="2" y1="2" x2="22" y2="22" />
64
+ <Path d="M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" />
65
+ <Path d="M5 10v2a7 7 0 0 0 12 5" />
66
+ <Path d="M15 9.34V5a3 3 0 0 0-5.68-1.33" />
67
+ <Path d="M9 9v3a3 3 0 0 0 5.12 2.12" />
68
+ <Line x1="12" y1="19" x2="12" y2="22" />
69
+ </Svg>
70
+ );
71
+ };
72
+
73
+ /**
74
+ * Filled Microphone Icon (Variant 2)
75
+ * Solid/filled microphone for active state
76
+ */
77
+ export const MicIconFilled: React.FC<MicIconProps> = ({
78
+ size = 24,
79
+ color = 'currentColor',
80
+ strokeWidth = 2,
81
+ }) => {
82
+ return (
83
+ <Svg
84
+ width={size}
85
+ height={size}
86
+ viewBox="0 0 24 24"
87
+ fill={color}
88
+ stroke={color}
89
+ strokeWidth={strokeWidth}
90
+ strokeLinecap="round"
91
+ strokeLinejoin="round"
92
+ >
93
+ <Path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" />
94
+ <Path
95
+ d="M19 10v2a7 7 0 0 1-14 0v-2"
96
+ fill="none"
97
+ stroke={color}
98
+ strokeWidth={strokeWidth}
99
+ />
100
+ <Line
101
+ x1="12"
102
+ y1="19"
103
+ x2="12"
104
+ y2="22"
105
+ fill="none"
106
+ stroke={color}
107
+ strokeWidth={strokeWidth}
108
+ />
109
+ </Svg>
110
+ );
111
+ };
112
+
113
+ /**
114
+ * Filled Microphone Off Icon (Variant 2)
115
+ * Solid microphone with mute indicator
116
+ */
117
+ export const MicOffIconFilled: React.FC<MicOffIconProps> = ({
118
+ size = 24,
119
+ color = 'currentColor',
120
+ strokeWidth = 2,
121
+ }) => {
122
+ return (
123
+ <Svg
124
+ width={size}
125
+ height={size}
126
+ viewBox="0 0 24 24"
127
+ fill="none"
128
+ stroke={color}
129
+ strokeWidth={strokeWidth}
130
+ strokeLinecap="round"
131
+ strokeLinejoin="round"
132
+ >
133
+ <Line x1="2" y1="2" x2="22" y2="22" />
134
+ <Path d="M15 9.34V5a3 3 0 0 0-5.68-1.33" fill={color} />
135
+ <Path d="M9 9v3a3 3 0 0 0 5.12 2.12" fill={color} />
136
+ <Path d="M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" fill="none" />
137
+ <Path d="M5 10v2a7 7 0 0 0 12 5" fill="none" />
138
+ <Line x1="12" y1="19" x2="12" y2="22" />
139
+ </Svg>
140
+ );
141
+ };
142
+
143
+ /**
144
+ * Wave Microphone Icon (Variant 3)
145
+ * Microphone with sound waves
146
+ */
147
+ export const MicIconWave: React.FC<MicIconProps> = ({
148
+ size = 24,
149
+ color = 'currentColor',
150
+ strokeWidth = 2,
151
+ }) => {
152
+ return (
153
+ <Svg
154
+ width={size}
155
+ height={size}
156
+ viewBox="0 0 24 24"
157
+ fill="none"
158
+ stroke={color}
159
+ strokeWidth={strokeWidth}
160
+ strokeLinecap="round"
161
+ strokeLinejoin="round"
162
+ >
163
+ <Path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" />
164
+ <Path d="M19 10v2a7 7 0 0 1-14 0v-2" />
165
+ <Line x1="12" y1="19" x2="12" y2="22" />
166
+ {/* Sound waves */}
167
+ <Path d="M20 7v10" opacity="0.5" />
168
+ <Path d="M23 9v6" opacity="0.3" />
169
+ <Path d="M4 7v10" opacity="0.5" />
170
+ <Path d="M1 9v6" opacity="0.3" />
171
+ </Svg>
172
+ );
173
+ };
174
+
175
+ /**
176
+ * Wave Microphone Off Icon (Variant 3)
177
+ * Microphone with muted waves
178
+ */
179
+ export const MicOffIconWave: React.FC<MicOffIconProps> = ({
180
+ size = 24,
181
+ color = 'currentColor',
182
+ strokeWidth = 2,
183
+ }) => {
184
+ return (
185
+ <Svg
186
+ width={size}
187
+ height={size}
188
+ viewBox="0 0 24 24"
189
+ fill="none"
190
+ stroke={color}
191
+ strokeWidth={strokeWidth}
192
+ strokeLinecap="round"
193
+ strokeLinejoin="round"
194
+ >
195
+ <Line x1="2" y1="2" x2="22" y2="22" />
196
+ <Path d="M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" />
197
+ <Path d="M5 10v2a7 7 0 0 0 12 5" />
198
+ <Path d="M15 9.34V5a3 3 0 0 0-5.68-1.33" />
199
+ <Path d="M9 9v3a3 3 0 0 0 5.12 2.12" />
200
+ <Line x1="12" y1="19" x2="12" y2="22" />
201
+ {/* Muted waves */}
202
+ <Path d="M20 7v4" opacity="0.2" strokeDasharray="2,2" />
203
+ <Path d="M4 7v4" opacity="0.2" strokeDasharray="2,2" />
204
+ </Svg>
205
+ );
206
+ };
207
+
208
+ export default MicIcon;