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.
- package/dist/hooks/useVoiceRecognition.d.ts +20 -0
- package/dist/hooks/useVoiceRecognition.js +37 -20
- package/package.json +2 -1
- package/react-native-voice.podspec +1 -1
- package/src/NativeVoiceAndroid.ts +28 -0
- package/src/NativeVoiceIOS.ts +24 -0
- package/src/VoiceModuleTypes.ts +64 -0
- package/src/VoiceUtilTypes.ts +46 -0
- package/src/components/MicIcon.tsx +208 -0
- package/src/components/VoiceMicrophone.tsx +356 -0
- package/src/components/index.ts +11 -0
- package/src/hooks/index.ts +5 -0
- package/src/hooks/useVoiceRecognition.ts +384 -0
- package/src/index.ts +523 -0
|
@@ -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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
+
"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;
|