@untemps/react-vocal 1.7.35 → 2.0.0-beta.2

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.
Files changed (40) hide show
  1. package/.github/workflows/publish.yml +2 -0
  2. package/.husky/commit-msg +1 -0
  3. package/.husky/pre-commit +1 -0
  4. package/.prettierignore +1 -0
  5. package/.prettierrc +1 -1
  6. package/CHANGELOG.md +29 -0
  7. package/CLAUDE.md +12 -8
  8. package/README.md +23 -16
  9. package/dev/index.html +24 -0
  10. package/dev/package.json +12 -8
  11. package/dev/src/{index.js → index.jsx} +2 -3
  12. package/dev/vite.config.js +10 -0
  13. package/dev/yarn.lock +296 -172
  14. package/dist/index.es.js +2182 -2
  15. package/dist/index.es.js.map +1 -0
  16. package/dist/index.js +9 -2
  17. package/dist/index.js.map +1 -0
  18. package/dist/index.umd.js +9 -2
  19. package/dist/index.umd.js.map +1 -0
  20. package/package.json +27 -60
  21. package/src/components/{Icon.js → Icon.jsx} +1 -14
  22. package/src/components/Vocal.jsx +206 -0
  23. package/src/components/__tests__/{Icon.test.js → Icon.test.jsx} +0 -4
  24. package/src/components/__tests__/{Vocal.test.js → Vocal.test.jsx} +175 -18
  25. package/src/components/__tests__/{VocalWithMockedUseVocal.test.js → VocalWithMockedUseVocal.test.jsx} +11 -13
  26. package/src/components/__tests__/__snapshots__/Icon.test.jsx.snap +21 -0
  27. package/src/components/__tests__/__snapshots__/Vocal.test.jsx.snap +28 -0
  28. package/src/hooks/__tests__/useCommands.test.js +1 -1
  29. package/src/hooks/__tests__/useTimeout.test.js +6 -6
  30. package/src/hooks/__tests__/useVocal.test.js +15 -15
  31. package/src/hooks/useTimeout.js +0 -2
  32. package/src/hooks/useVocal.js +0 -2
  33. package/vite.config.js +35 -0
  34. package/vitest.setup.js +74 -0
  35. package/babel.config.js +0 -12
  36. package/dev/babel.config.js +0 -4
  37. package/dev/rollup.config.js +0 -29
  38. package/jest/jest.setup.js +0 -72
  39. package/rollup.config.js +0 -42
  40. package/src/components/Vocal.js +0 -235
@@ -1,235 +0,0 @@
1
- import React, { cloneElement, isValidElement, useRef, useState } from 'react'
2
- import PropTypes from 'prop-types'
3
- import { Vocal as SpeechRecognitionWrapper } from '@untemps/vocal'
4
- import { isFunction } from '@untemps/utils/function/isFunction'
5
-
6
- import useVocal from '../hooks/useVocal'
7
- import useTimeout from '../hooks/useTimeout'
8
- import useCommands from '../hooks/useCommands'
9
-
10
- import Icon from './Icon'
11
-
12
- const Vocal = ({
13
- children,
14
- commands,
15
- lang,
16
- grammars,
17
- timeout,
18
- ariaLabel,
19
- style,
20
- className,
21
- outlineStyle,
22
- onStart,
23
- onEnd,
24
- onSpeechStart,
25
- onSpeechEnd,
26
- onResult,
27
- onError,
28
- onNoMatch,
29
- __rsInstance,
30
- }) => {
31
- const buttonRef = useRef(null)
32
- const [isListening, setIsListening] = useState(false)
33
-
34
- const [, { start, stop, subscribe, unsubscribe }] = useVocal(lang, grammars, __rsInstance)
35
- const triggerCommand = useCommands(commands)
36
-
37
- const _onEnd = (e) => {
38
- stopTimer()
39
- stopRecognition()
40
-
41
- unsubscribe('start', _onStart)
42
- unsubscribe('end', _onEnd)
43
- unsubscribe('speechstart', _onSpeechStart)
44
- unsubscribe('speechend', _onSpeechEnd)
45
- unsubscribe('result', _onResult)
46
- unsubscribe('error', _onError)
47
- unsubscribe('nomatch', _onNoMatch)
48
-
49
- !!onEnd && onEnd(e)
50
- }
51
-
52
- const [startTimer, stopTimer] = useTimeout(_onEnd, timeout)
53
-
54
- const startRecognition = () => {
55
- try {
56
- setIsListening(true)
57
-
58
- subscribe('start', _onStart)
59
- subscribe('end', _onEnd)
60
- subscribe('speechstart', _onSpeechStart)
61
- subscribe('speechend', _onSpeechEnd)
62
- subscribe('result', _onResult)
63
- subscribe('error', _onError)
64
- subscribe('nomatch', _onNoMatch)
65
-
66
- start()
67
- } catch (error) {
68
- _onError(error)
69
- }
70
- }
71
-
72
- const stopRecognition = () => {
73
- try {
74
- setIsListening(false)
75
-
76
- stop()
77
- } catch (error) {
78
- !!onError && onError(error)
79
- }
80
- }
81
-
82
- const _onClick = () => {
83
- startRecognition()
84
- }
85
-
86
- const _onFocus = () => {
87
- if (!className && outlineStyle) {
88
- buttonRef.current.style.outline = outlineStyle
89
- }
90
- }
91
-
92
- const _onBlur = () => {
93
- if (!className && outlineStyle) {
94
- buttonRef.current.style.outline = 'none'
95
- }
96
- }
97
-
98
- const _onStart = (e) => {
99
- startTimer()
100
-
101
- !!onStart && onStart(e)
102
- }
103
-
104
- const _onSpeechStart = (e) => {
105
- stopTimer()
106
-
107
- !!onSpeechStart && onSpeechStart(e)
108
- }
109
-
110
- const _onSpeechEnd = (e) => {
111
- startTimer()
112
-
113
- !!onSpeechEnd && onSpeechEnd(e)
114
- }
115
-
116
- const _onResult = (event, result) => {
117
- stopTimer()
118
- stopRecognition()
119
-
120
- triggerCommand(result)
121
-
122
- !!onResult && onResult(result, event)
123
- }
124
-
125
- const _onError = (error) => {
126
- stopRecognition()
127
-
128
- !!onError && onError(error)
129
- }
130
-
131
- const _onNoMatch = (e) => {
132
- stopTimer()
133
- stopRecognition()
134
-
135
- !!onNoMatch && onNoMatch(e)
136
- }
137
-
138
- const _renderDefault = () => (
139
- <button
140
- data-testid="__vocal-root__"
141
- ref={buttonRef}
142
- role="button"
143
- aria-label={ariaLabel}
144
- style={
145
- className
146
- ? null
147
- : {
148
- width: 24,
149
- height: 24,
150
- background: 'none',
151
- border: 'none',
152
- padding: 0,
153
- cursor: !isListening ? 'pointer' : 'default',
154
- ...style,
155
- }
156
- }
157
- className={className}
158
- onFocus={_onFocus}
159
- onBlur={_onBlur}
160
- onClick={_onClick}
161
- >
162
- <Icon isActive={isListening} iconColor="#aaa" />
163
- </button>
164
- )
165
-
166
- const _renderChildren = (children) => {
167
- if (SpeechRecognitionWrapper.isSupported) {
168
- if (isFunction(children)) {
169
- return children(startRecognition, stopRecognition, isListening)
170
- } else if (isValidElement(children)) {
171
- return cloneElement(children, {
172
- ...(!isListening && { onClick: _onClick }),
173
- })
174
- } else {
175
- return _renderDefault()
176
- }
177
- }
178
- return null
179
- }
180
-
181
- return _renderChildren(children)
182
- }
183
-
184
- Vocal.propTypes = {
185
- /** Defines callbacks to be triggered when keys are detected by the recognition */
186
- commands: PropTypes.objectOf(PropTypes.func),
187
- /** Defines the language understood by the recognition (https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition/lang) */
188
- lang: PropTypes.string,
189
- /** Defines the grammars understood by the recognition (https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition/grammars) */
190
- grammars: PropTypes.object,
191
- /** Defines the time in ms to wait before discarding the recognition */
192
- timeout: PropTypes.number,
193
- /** Defines the a11y label for the default button */
194
- ariaLabel: PropTypes.string,
195
- /** Defines the styles of the default element if className is not specified */
196
- style: PropTypes.object,
197
- /** Defines the class of the default element */
198
- className: PropTypes.string,
199
- /** Defines the default style of the focus outline. if null the default behaviour is used */
200
- outlineStyle: PropTypes.string,
201
- /** Defines the handler called when the recognition starts */
202
- onStart: PropTypes.func,
203
- /** Defines the handler called when the recognition ends */
204
- onEnd: PropTypes.func,
205
- /** Defines the handler called when the speech starts */
206
- onSpeechStart: PropTypes.func,
207
- /** Defines the handler called when the speech ends */
208
- onSpeechEnd: PropTypes.func,
209
- /** Defines the handler called when a result is returned from te recognition */
210
- onResult: PropTypes.func,
211
- /** Defines the handler called when an error occurs */
212
- onError: PropTypes.func,
213
- /** Defines the handler called when no result can be recognized */
214
- onNoMatch: PropTypes.func,
215
- }
216
-
217
- Vocal.defaultProps = {
218
- commands: null,
219
- lang: 'en-US',
220
- grammars: null,
221
- timeout: 3000,
222
- ariaLabel: 'start recognition',
223
- style: null,
224
- className: null,
225
- outlineStyle: '2px solid',
226
- onStart: null,
227
- onEnd: null,
228
- onSpeechStart: null,
229
- onSpeechEnd: null,
230
- onResult: null,
231
- onError: null,
232
- onNoMatch: null,
233
- }
234
-
235
- export default Vocal