@untemps/react-vocal 2.0.0-beta.4 → 2.0.0-beta.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/CHANGELOG.md +19 -0
- package/README.md +17 -2
- package/dev/src/index.jsx +11 -3
- package/dist/index.es.js +151 -1276
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/package.json +9 -3
- package/src/components/Vocal.jsx +38 -10
- package/src/components/__tests__/Vocal.test.jsx +152 -15
- package/src/components/__tests__/__snapshots__/Vocal.test.jsx.snap +1 -1
- package/src/hooks/__tests__/useCommands.test.js +28 -2
- package/src/hooks/__tests__/useVocal.test.js +7 -2
- package/src/hooks/useCommands.js +42 -16
- package/src/hooks/useVocal.js +3 -3
- package/vite.config.js +2 -1
- package/vitest.setup.js +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
# [2.0.0-beta.6](https://github.com/untemps/react-vocal/compare/v2.0.0-beta.5...v2.0.0-beta.6) (2026-05-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Add continuous session support ([#118](https://github.com/untemps/react-vocal/issues/118)) ([690ba61](https://github.com/untemps/react-vocal/commit/690ba617746aa28499d7ea2d48751453a652ff5e))
|
|
7
|
+
|
|
8
|
+
# [2.0.0-beta.5](https://github.com/untemps/react-vocal/compare/v2.0.0-beta.4...v2.0.0-beta.5) (2026-05-11)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* Make fuse.js an optional peer dependency ([#117](https://github.com/untemps/react-vocal/issues/117)) ([a1c2a33](https://github.com/untemps/react-vocal/commit/a1c2a337f8d4ba4729c81f0a9b8664bcf914755f))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### BREAKING CHANGES
|
|
17
|
+
|
|
18
|
+
* fuse.js must now be installed separately to enable fuzzy matching for phrase commands.
|
|
19
|
+
|
|
1
20
|
# [2.0.0-beta.4](https://github.com/untemps/react-vocal/compare/v2.0.0-beta.3...v2.0.0-beta.4) (2026-05-10)
|
|
2
21
|
|
|
3
22
|
|
package/README.md
CHANGED
|
@@ -46,6 +46,14 @@ Although the lack of `SpeechGrammar` and `SpeechGrammarList` is handled by the u
|
|
|
46
46
|
yarn add @untemps/react-vocal
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
Fuzzy matching for phrase commands requires [fuse.js](https://fusejs.io/) as an optional peer dependency:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
yarn add fuse.js
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Without fuse.js, phrase commands fall back to case-insensitive exact matching. Single-word commands always use exact matching and never require fuse.js.
|
|
56
|
+
|
|
49
57
|
## Usage
|
|
50
58
|
|
|
51
59
|
### `Vocal` component
|
|
@@ -190,7 +198,11 @@ const commands = {
|
|
|
190
198
|
}
|
|
191
199
|
```
|
|
192
200
|
|
|
193
|
-
The component utilizes a special hook called `useCommands` to respond to the commands.
|
|
201
|
+
The component utilizes a special hook called `useCommands` to respond to the commands.
|
|
202
|
+
The hook performs a fuzzy search to match approximate commands if needed. This allows to fix accidental typos or approximate recognition results.
|
|
203
|
+
To do so the hook uses [fuse.js](https://fusejs.io/) which implements an algorithm to find strings that are approximately equal to a given input. The score precision that distinguishes acceptable command-to-callback mapping from negative matching can be customized in the hook instantiation.
|
|
204
|
+
|
|
205
|
+
fuse.js is an optional peer dependency — install it separately to enable fuzzy matching (see [Installation](#installation)). Without it, phrase commands fall back to case-insensitive exact matching.
|
|
194
206
|
|
|
195
207
|
**Single-word command keys** (e.g. `rouge`, `submit`) use exact case-insensitive lookup. When the recognition returns a multi-word transcript, each word is tried individually so a command fires even when embedded in a phrase (e.g. _"je veux du rouge"_ triggers `rouge`).
|
|
196
208
|
|
|
@@ -212,6 +224,8 @@ The component utilizes a special hook called `useCommands` to respond to the com
|
|
|
212
224
|
| timeout | number | 3000 | Time in ms to wait before discarding the recognition |
|
|
213
225
|
| precision | number | 0.4 | Fuse.js score threshold for **phrase** command keys only (lower = stricter). Single-word commands always use exact lookup. |
|
|
214
226
|
| maxAlternatives | number | 1 | Maximum number of recognition alternatives per segment. Setting this to 3–5 lets the engine surface the correct word as a secondary transcript, which is useful for handling homophones (e.g. _vert_ / _verre_ in French). |
|
|
227
|
+
| continuous | boolean | false | Keep the recognition session open after each result. The session accumulates transcript across segments and stops when the button is clicked again or `silenceTimeout` expires. Commands are not evaluated in continuous mode. |
|
|
228
|
+
| silenceTimeout | number | null | When `continuous` is true, automatically stop the session after this many ms of inactivity following the last recognized result. `null` or `0` disables auto-stop (button click required). |
|
|
215
229
|
| style | object | null | Styles of the root element if className is not specified |
|
|
216
230
|
| className | string | null | Class of the root element |
|
|
217
231
|
| ariaLabel | string | 'start recognition' | Accessible label for the default button |
|
|
@@ -286,7 +300,7 @@ const App = () => {
|
|
|
286
300
|
#### Signature
|
|
287
301
|
|
|
288
302
|
```
|
|
289
|
-
useVocal(lang, grammars, maxAlternatives)
|
|
303
|
+
useVocal(lang, grammars, maxAlternatives, continuous)
|
|
290
304
|
```
|
|
291
305
|
|
|
292
306
|
| Args | Type | Default | Description |
|
|
@@ -294,6 +308,7 @@ useVocal(lang, grammars, maxAlternatives)
|
|
|
294
308
|
| lang | string | 'en-US' | Language understood by the recognition [BCP 47 language tag](https://tools.ietf.org/html/bcp47) |
|
|
295
309
|
| grammars | SpeechGrammarList | null | Grammars understood by the recognition [JSpeech Grammar Format](https://www.w3.org/TR/jsgf/) |
|
|
296
310
|
| maxAlternatives | number | 1 | Maximum number of recognition alternatives per segment |
|
|
311
|
+
| continuous | boolean | false | Keep the recognition session open after each result |
|
|
297
312
|
|
|
298
313
|
---
|
|
299
314
|
|
package/dev/src/index.jsx
CHANGED
|
@@ -13,6 +13,7 @@ const COMMANDS = {
|
|
|
13
13
|
const App = () => {
|
|
14
14
|
const [logs, setLogs] = useState('')
|
|
15
15
|
const [borderColor, setBorderColor] = useState()
|
|
16
|
+
const [continuous, setContinuous] = useState(false)
|
|
16
17
|
|
|
17
18
|
const _log = (value) => setLogs((prev) => `${prev}${prev.length > 0 ? '\n' : ''} ----- ${value}`)
|
|
18
19
|
|
|
@@ -22,8 +23,8 @@ const App = () => {
|
|
|
22
23
|
Object.fromEntries(
|
|
23
24
|
Object.entries(COMMANDS).map(([key, color]) => [
|
|
24
25
|
key,
|
|
25
|
-
(
|
|
26
|
-
_log(`command matched: "${
|
|
26
|
+
(rawInput, commandKey) => {
|
|
27
|
+
_log(`command matched: "${commandKey}" → ${color}`)
|
|
27
28
|
setBorderColor(color)
|
|
28
29
|
},
|
|
29
30
|
])
|
|
@@ -37,12 +38,19 @@ const App = () => {
|
|
|
37
38
|
<Vocal
|
|
38
39
|
lang="fr"
|
|
39
40
|
commands={commands}
|
|
41
|
+
continuous={continuous}
|
|
40
42
|
onStart={() => _log('start')}
|
|
41
43
|
onEnd={() => _log('end')}
|
|
42
|
-
onResult={(result) => _log(`
|
|
44
|
+
onResult={(result) => _log(`transcript: "${result}"`)}
|
|
43
45
|
onError={(e) => _log(`error: ${e.message}`)}
|
|
44
46
|
maxAlternatives={3}
|
|
45
47
|
/>
|
|
48
|
+
<p style={{ fontSize: 12, color: '#666', margin: '8px 0' }}>
|
|
49
|
+
<label style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
50
|
+
<input type="checkbox" checked={continuous} onChange={(e) => setContinuous(e.target.checked)} />
|
|
51
|
+
Mode continu
|
|
52
|
+
</label>
|
|
53
|
+
</p>
|
|
46
54
|
<p style={{ fontSize: 12, color: '#666', margin: '8px 0' }}>
|
|
47
55
|
Commandes :{' '}
|
|
48
56
|
{Object.keys(COMMANDS).map((k, i) => (
|