feat: 🎸 add useSpeech hook

This commit is contained in:
streamich 2018-10-28 11:26:23 +01:00
parent 0a6811d5da
commit 3b971a2297
8 changed files with 82 additions and 6 deletions

View File

@ -47,6 +47,7 @@
<br/>
- [__UI__](./docs/UI.md)
- [`useAudio`](./docs/useAudio.md) &mdash; plays audio and exposes its controls.
- [`useSpeech`](./docs/useSpeech.md) &mdash; synthesizes speech from text string.
<br/>
<br/>
- [__Animations__](./docs/Animations.md)

18
docs/useSpeech.md Normal file
View File

@ -0,0 +1,18 @@
# `useSpeech`
React UI hook that synthesizes human voice that speaks a given string.
## Usage
```jsx
import {useSpeech} from 'react-use';
const Demo = () => {
const state = useSpeech('Hello world!');
return (
<pre>{JSON.stringify(state, null, 2)}</pre>
);
};
```

View File

@ -0,0 +1,16 @@
import {storiesOf} from '@storybook/react';
import * as React from 'react';
import {useSpeech} from '..';
const Demo = () => {
const state = useSpeech('Hello world!');
return (
<pre>{JSON.stringify(state, null, 2)}</pre>
);
};
storiesOf('useSpeech', module)
.add('Example', () =>
<Demo/>
)

View File

@ -22,6 +22,7 @@ import useOrientation from './useOrientation';
import useRaf from './useRaf';
import useSetState from './useSetState';
import useSize from './useSize';
import useSpeech from './useSpeech';
import useSpring from './useSpring';
import useTimeout from './useTimeout';
import useTitle from './useTitle';
@ -55,6 +56,7 @@ export {
useRaf,
useSetState,
useSize,
useSpeech,
useSpring,
useTimeout,
useTitle,

View File

@ -12,3 +12,6 @@ export const useRef: UseRef = (React as any).useRef;
export type UseCallback = <T extends ((...args: any[]) => any)>(callback: T, args: any[]) => T;
export const useCallback: UseCallback = (React as any).useCallback;
export type UseMemo = <T>(fn: Function, args: any[]) => T;
export const useMemo: UseMemo = (React as any).useMemo;

View File

@ -1,6 +1,6 @@
import {useEffect} from './react';
const useLifecycles = (mount, unmount) => {
const useLifecycles = (mount, unmount?) => {
useEffect(() => {
if (mount) mount();
return () => {

View File

@ -1,9 +1,5 @@
import {useEffect} from './react';
const useMount = (mount) => {
useEffect(() => {
if (mount) mount();
}, []);
};
const useMount = (mount) => useEffect(mount, []);
export default useMount;

40
src/useSpeech.ts Normal file
View File

@ -0,0 +1,40 @@
import {useRef} from './react';
import useSetState from './useSetState';
import useMount from './useMount';
export interface SpeechState {
isPlaying: boolean;
volume: number;
}
export interface SpeechOptions {
lang?: any;
pitch?: number;
rate?: number;
voice?: any;
volume?: number;
}
const useSpeech = (text: string, opts: SpeechOptions = {}): SpeechState => {
const [state, setState] = useSetState<SpeechState>({
isPlaying: false,
volume: opts.volume || 1,
});
const uterranceRef = useRef<SpeechSynthesisUtterance | null>(null);
useMount(() => {
const utterance = new SpeechSynthesisUtterance(text);
utterance.volume = opts.volume || 1;
utterance.onstart = () => setState({isPlaying: true});
utterance.onresume = () => setState({isPlaying: true});
utterance.onend = () => setState({isPlaying: false});
utterance.onpause = () => setState({isPlaying: false});
uterranceRef.current = utterance;
window.speechSynthesis.speak(uterranceRef.current);
});
return state;
};
export default useSpeech;