+ )
}
```
+---
+
#### Custom component
By default, `Vocal` displays an icon with two states:
-- Idle
- ![Idle state](assets/icon-idle.png)
-- Listening
- ![Listening state](assets/icon-listening.png)
+- Idle
+ ![Idle state](assets/icon-idle.png)
+- Listening
+ ![Listening state](assets/icon-listening.png)
But you can provide your own component.
-- With a simple React element:
+- With a simple React element:
```javascript
import Vocal from '@untemps/react-vocal'
const App = () => {
- return (
-
-
-
- )
+ return (
+
+
+
+ )
}
```
@@ -105,129 +107,187 @@ In this case, a `onClick` handler is automatically attached to the component to
Only the first direct descendant of Vocal will receive the `onClick` handler. If you want to use a more complex
hierarchy, use the function syntax below.
-- With a function that returns a React element:
+- With a function that returns a React element:
```javascript
import Vocal from '@untemps/react-vocal'
-const Play = () =>
-
-const Stop = () =>
+const Play = () => (
+
+)
+
+const Stop = () => (
+
+)
const App = () => {
- return (
- {(start, stop, isStarted) => (
-
- )}
- )
+ return (
+
+ {(start, stop, isStarted) => (
+
+ )}
+
+ )
}
```
The following parameters are passed to the function:
-| Arguments | Type | Description |
-| ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------ |
-| start | func | The function used to start the recognition |
-| stop | func | The function used to stop the recognition |
-| isStarted | bool | A flag that indicates whether the recognition is started or not |
+| Arguments | Type | Description |
+| --------- | ---- | --------------------------------------------------------------- |
+| start | func | The function used to start the recognition |
+| stop | func | The function used to stop the recognition |
+| isStarted | bool | A flag that indicates whether the recognition is started or not |
+
+---
+
+#### Commands
-#### API
+The `Vocal` component accepts a `commands` prop to map special recognition results to callbacks.
+That means you can define vocal commands to trigger specific functions.
-| Props | Type | Default | Description |
-| ------------- | ----------------- | ------- | -------------------------------------------------------------------------------------------------- |
-| lang | string | 'en-US' | Language understood by the recognition [BCP 47 language tag](https://tools.ietf.org/html/bcp47) |
-| grammars | SpeechGrammarList | null | Grammars understood by the recognition [JSpeech Grammar Format](https://www.w3.org/TR/jsgf/) |
-| timeout | number | 3000 | Time in ms to wait before discarding the recognition |
-| style | object | null | Styles of the root element if className is not specified |
+```javascript
+const App = () => {
+ return (
+ setBorderColor('red'),
+ }}/>
+ )
+}
+```
+
+`commands` object is a key/pair model where the `key` is the command to be caught by the recognition and the `value` is the callback triggered when the command is detected.
+
+`key` is not case sensitive.
+
+```javascript
+const commands = {
+ submit: () => submitForm(),
+ 'Change the background color': () => setBackgroundColor('red'),
+ 'PLAY MUSIC': play
+}
+```
+
+The component utilizes a special hook called `useCommands` to respond to the commands.
+The hook performs a fuzzy search to match approximate commands if needed. This allows to fix accidental typos or approximate recognition results.
+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 instantiantion.
+
+```javascript
+useCommands(commands, threshold) // threshold is the limit not to exceed to be considered a match
+```
+
+See [fuze.js scoring theory](https://fusejs.io/concepts/scoring-theory.html) for more details.
+
+> :warning: **The `Vocal` component doesn't expose that score yet.** For now on you have to deal with the default value (*0.4*)
+
+---
+
+#### `Vocal` component API
+
+| Props | Type | Default | Description |
+| ------------- | ----------------- | ------- | ----------------------------------------------------------------------------------------------- |
+| commands | object | null | Callbacks to be triggered when specified commands are detected by the recognition |
+| lang | string | 'en-US' | Language understood by the recognition [BCP 47 language tag](https://tools.ietf.org/html/bcp47) |
+| grammars | SpeechGrammarList | null | Grammars understood by the recognition [JSpeech Grammar Format](https://www.w3.org/TR/jsgf/) |
+| timeout | number | 3000 | Time in ms to wait before discarding the recognition |
+| style | object | null | Styles of the root element if className is not specified |
| className | string | null | Class of the root element |
-| onStart | func | null | Handler called when the recognition starts |
-| onEnd | func | null | Handler called when the recognition ends |
-| onSpeechStart | func | null | Handler called when the speech starts |
-| onSpeechEnd | func | null | Handler called when the speech ends |
-| onResult | func | null | Handler called when a result is recognized |
-| onError | func | null | Handler called when an error occurs |
-| onNoMatch | func | null | Handler called when no result can be recognized |
+| onStart | func | null | Handler called when the recognition starts |
+| onEnd | func | null | Handler called when the recognition ends |
+| onSpeechStart | func | null | Handler called when the speech starts |
+| onSpeechEnd | func | null | Handler called when the speech ends |
+| onResult | func | null | Handler called when a result is recognized |
+| onError | func | null | Handler called when an error occurs |
+| onNoMatch | func | null | Handler called when no result can be recognized |
### `useVocal` hook
#### Basic usage
```javascript
-import React, {useState} from 'react'
-import {useVocal} from '@untemps/react-vocal'
+import React, { useState } from 'react'
+import { useVocal } from '@untemps/react-vocal'
import Icon from './Icon'
const App = () => {
- const [isListening, setIsListening] = useState(false)
- const [result, setResult] = useState('')
-
- const [, {start, subscribe}] = useVocal('fr_FR')
-
- const _onButtonClick = () => {
- setIsListening(true)
-
- subscribe('speechstart', _onVocalStart)
- subscribe('result', _onVocalResult)
- subscribe('error', _onVocalError)
- start()
- }
-
- const _onVocalStart = () => {
- setResult('')
- }
-
- const _onVocalResult = (result) => {
- setIsListening(false)
-
- setResult(result)
- }
-
- const _onVocalError = (e) => {
- console.error(e)
- }
-
- return (
-