@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
@@ -12,6 +12,8 @@ permissions:
12
12
  jobs:
13
13
  release:
14
14
  runs-on: ubuntu-latest
15
+ env:
16
+ HUSKY: '0'
15
17
  steps:
16
18
  - uses: actions/checkout@v6
17
19
  with:
@@ -0,0 +1 @@
1
+ npx --no -- commitlint --edit "$1"
@@ -0,0 +1 @@
1
+ yarn test:ci && yarn prettier
package/.prettierignore CHANGED
@@ -1,2 +1,3 @@
1
1
  dist/
2
2
  node_modules/
3
+ coverage/
package/.prettierrc CHANGED
@@ -10,7 +10,7 @@
10
10
  {
11
11
  "files": "./**/*.js",
12
12
  "options": {
13
- "parser": "babylon"
13
+ "parser": "babel"
14
14
  }
15
15
  },
16
16
  {
package/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ # [2.0.0-beta.2](https://github.com/untemps/react-vocal/compare/v2.0.0-beta.1...v2.0.0-beta.2) (2026-05-07)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Stabilize event handlers and fix stale prop closures ([#112](https://github.com/untemps/react-vocal/issues/112)) ([69c5c00](https://github.com/untemps/react-vocal/commit/69c5c00ed73e792b6dd91dd6b294163e1c3d00dc))
7
+
8
+ # [2.0.0-beta.1](https://github.com/untemps/react-vocal/compare/v1.7.35...v2.0.0-beta.1) (2026-05-05)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Address review feedback on migration PR ([0dba863](https://github.com/untemps/react-vocal/commit/0dba86374736f8a2a3763ef20073cdb5bc3a4ac8))
14
+ * Commit Vitest snapshots and remove __snapshots__ from gitignore ([e120fda](https://github.com/untemps/react-vocal/commit/e120fda321c5ed553d02262399ead46653b4e002))
15
+ * Fix comment accuracy and trailing blank line in Vocal ([0ffbbc9](https://github.com/untemps/react-vocal/commit/0ffbbc97dcda8c4c1008b5d9259cbc70753d6551))
16
+ * Restore Icon colors broken by React 19 defaultProps removal ([3d50a38](https://github.com/untemps/react-vocal/commit/3d50a38996e1cc2589ac238e30c1b164b3677252))
17
+
18
+
19
+ ### Features
20
+
21
+ * Migrate to Vite, Vitest and React 19 ([#109](https://github.com/untemps/react-vocal/issues/109)) ([29ecf60](https://github.com/untemps/react-vocal/commit/29ecf607d7e4a0eb2ac802b31e6003a225d7fecc))
22
+
23
+
24
+ ### BREAKING CHANGES
25
+
26
+ * Runtime prop validation removed. `Vocal.propTypes` and `Icon.propTypes` have been deleted — React 19 deprecated static propTypes on function components. Consumers relying on development-time prop warnings must migrate to TypeScript or an equivalent static type checker.
27
+ * Node >=20.19.0 required. Vite 8 and jsdom 29 enforce this minimum. Node 18 and 19 are no longer supported for development or CI.
28
+ * `background: none` replaced by `backgroundColor: transparent` on the default button. The shorthand previously reset all background sub-properties (image, gradient…); the longhand only resets the color. Impact is minimal for most users but visible if a custom style prop relied on the implicit background-image reset.
29
+
1
30
  ## [1.7.35](https://github.com/untemps/react-vocal/compare/v1.7.34...v1.7.35) (2026-05-03)
2
31
 
3
32
  ## [1.7.34](https://github.com/untemps/react-vocal/compare/v1.7.33...v1.7.34) (2026-05-03)
package/CLAUDE.md CHANGED
@@ -5,23 +5,23 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
5
5
  ## Commands
6
6
 
7
7
  ```bash
8
- yarn test # watch mode
8
+ yarn test # watch mode (Vitest)
9
9
  yarn test:ci # CI mode with coverage (also runs in pre-commit hook)
10
- yarn build # build CJS + ES + UMD to dist/
10
+ yarn build # build CJS + ES + UMD to dist/ (Vite library mode)
11
11
  yarn dev # dev server at http://localhost:10001/ (separate dev/ package)
12
- yarn prettier # format all JS files and stage changes
12
+ yarn prettier # format all JS files and stage tracked changes
13
13
  ```
14
14
 
15
15
  Run a single test file:
16
16
  ```bash
17
- yarn jest src/hooks/__tests__/useVocal.test.js
17
+ yarn vitest src/hooks/__tests__/useVocal.test.js
18
18
  ```
19
19
 
20
- Build formats are driven by `BABEL_ENV`: `cjs` → `dist/index.js`, `es` → `dist/index.es.js`, `umd` → `dist/index.umd.js`.
20
+ Build formats defined in `vite.config.js` `build.lib`: `cjs` → `dist/index.js`, `es` → `dist/index.es.js`, `umd` → `dist/index.umd.js`.
21
21
 
22
22
  ## Architecture
23
23
 
24
- This is a React library wrapping the [Web Speech API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API) via `@untemps/vocal` (the `SpeechRecognitionWrapper` class).
24
+ React library wrapping the [Web Speech API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API) via `@untemps/vocal` (the `SpeechRecognitionWrapper` class).
25
25
 
26
26
  ### Public API (`src/index.js`)
27
27
 
@@ -37,18 +37,22 @@ This is a React library wrapping the [Web Speech API](https://developer.mozilla.
37
37
  | `useCommands` | Fuzzy-matches a speech result string against a `commands` map using **fuse.js** (default score threshold `0.4` — lower = stricter). Keys are lowercased. |
38
38
  | `useTimeout` | Manages the recognition timeout: starts on `start` event, pauses on `speechstart`, restarts on `speechend`, fires `_onEnd` on expiry. |
39
39
 
40
- ### Component (`src/components/Vocal.js`)
40
+ ### Component (`src/components/Vocal.jsx`)
41
41
 
42
42
  Composes the three hooks above. Three render modes depending on `children`:
43
43
  - **function** `(start, stop, isStarted) => element` — full control
44
44
  - **React element** — receives `onClick` injected via `cloneElement`
45
45
  - **no children** — renders the default `<Icon>` button
46
46
 
47
+ All props have default values in the function signature (React 19: `defaultProps` no longer applied to function components). No `propTypes` — removed as deprecated in React 19.
48
+
47
49
  The `__rsInstance` prop (undocumented) injects a custom `SpeechRecognitionWrapper` instance, used exclusively in tests.
48
50
 
49
51
  ### Testing
50
52
 
51
- `jest/jest.setup.js` globally mocks `SpeechRecognition`, `Permissions`, `MediaDevices`, and `SpeechGrammarList`. The mock exposes a custom `say(sentence)` method that fires the full `speechstart → result/nomatch → speechend` event sequence synchronously — use it to simulate recognition in tests.
53
+ `vitest.setup.js` globally mocks `SpeechRecognition`, `Permissions`, `MediaDevices`, and `SpeechGrammarList`. The mock exposes a custom `say(sentence)` method that fires the full `speechstart → result/nomatch → speechend` event sequence synchronously — use it to simulate recognition in tests.
54
+
55
+ Vitest globals are enabled (`globals: true`) — `describe`, `it`, `expect`, `vi` available without imports in test files.
52
56
 
53
57
  ## Commit convention
54
58
 
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  ---
9
9
 
10
10
  [![npm](https://img.shields.io/npm/v/@untemps/react-vocal?style=for-the-badge)](https://www.npmjs.com/package/@untemps/react-vocal)
11
- [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/untemps/react-vocal/index.yml?style=for-the-badge)](https://github.com/untemps/react-vocal/actions)
11
+ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/untemps/react-vocal/publish.yml?style=for-the-badge)](https://github.com/untemps/react-vocal/actions)
12
12
  [![Codecov](https://img.shields.io/codecov/c/github/untemps/react-vocal?style=for-the-badge)](https://codecov.io/gh/untemps/react-vocal)
13
13
 
14
14
  ## Links
@@ -35,6 +35,11 @@ For example, browsers on iOS 14.5, the `SpeechGrammar` and `SpeechGrammarList` a
35
35
 
36
36
  Although the lack of `SpeechGrammar` and `SpeechGrammarList` is handled by the underlaying `@untemps/vocal` library, you need to deal with `Permissions` by yourself.
37
37
 
38
+ ## Requirements
39
+
40
+ - React >= 16.13.1
41
+ - Node >= 20.19.0
42
+
38
43
  ## Installation
39
44
 
40
45
  ```bash
@@ -201,21 +206,23 @@ See [fuze.js scoring theory](https://fusejs.io/concepts/scoring-theory.html) for
201
206
 
202
207
  #### `Vocal` component API
203
208
 
204
- | Props | Type | Default | Description |
205
- | ------------- | ----------------- | ------- | ----------------------------------------------------------------------------------------------- |
206
- | commands | object | null | Callbacks to be triggered when specified commands are detected by the recognition |
207
- | lang | string | 'en-US' | Language understood by the recognition [BCP 47 language tag](https://tools.ietf.org/html/bcp47) |
208
- | grammars | SpeechGrammarList | null | Grammars understood by the recognition [JSpeech Grammar Format](https://www.w3.org/TR/jsgf/) |
209
- | timeout | number | 3000 | Time in ms to wait before discarding the recognition |
210
- | style | object | null | Styles of the root element if className is not specified |
211
- | className | string | null | Class of the root element |
212
- | onStart | func | null | Handler called when the recognition starts |
213
- | onEnd | func | null | Handler called when the recognition ends |
214
- | onSpeechStart | func | null | Handler called when the speech starts |
215
- | onSpeechEnd | func | null | Handler called when the speech ends |
216
- | onResult | func | null | Handler called when a result is recognized |
217
- | onError | func | null | Handler called when an error occurs |
218
- | onNoMatch | func | null | Handler called when no result can be recognized |
209
+ | Props | Type | Default | Description |
210
+ | ------------- | ----------------- | -------------------- | ----------------------------------------------------------------------------------------------- |
211
+ | commands | object | null | Callbacks to be triggered when specified commands are detected by the recognition |
212
+ | lang | string | 'en-US' | Language understood by the recognition [BCP 47 language tag](https://tools.ietf.org/html/bcp47) |
213
+ | grammars | SpeechGrammarList | null | Grammars understood by the recognition [JSpeech Grammar Format](https://www.w3.org/TR/jsgf/) |
214
+ | timeout | number | 3000 | Time in ms to wait before discarding the recognition |
215
+ | style | object | null | Styles of the root element if className is not specified |
216
+ | className | string | null | Class of the root element |
217
+ | ariaLabel | string | 'start recognition' | Accessible label for the default button |
218
+ | outlineStyle | string | '2px solid' | Focus outline style applied to the default button |
219
+ | onStart | func | null | Handler called when the recognition starts |
220
+ | onEnd | func | null | Handler called when the recognition ends |
221
+ | onSpeechStart | func | null | Handler called when the speech starts |
222
+ | onSpeechEnd | func | null | Handler called when the speech ends |
223
+ | onResult | func | null | Handler called when a result is recognized |
224
+ | onError | func | null | Handler called when an error occurs |
225
+ | onNoMatch | func | null | Handler called when no result can be recognized |
219
226
 
220
227
  ### `useVocal` hook
221
228
 
package/dev/index.html ADDED
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta name="theme-color" content="#000000" />
7
+ <meta name="description" content="react-vocal" />
8
+ <title>react-vocal</title>
9
+ <style>
10
+ * {
11
+ font-family: Arial, sans-serif;
12
+ font-size: 12px;
13
+ }
14
+ body {
15
+ padding: 32px;
16
+ }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <noscript>You need to enable JavaScript to run this app.</noscript>
21
+ <div id="root"></div>
22
+ <script type="module" src="/src/index.jsx"></script>
23
+ </body>
24
+ </html>
package/dev/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "name": "react-vocal-demo",
3
3
  "version": "1.0.0",
4
- "main": "index.js",
5
- "license": "MIT",
6
- "devDependencies": {
7
- "@rollup/plugin-replace": "^2.3.3",
8
- "rollup-plugin-livereload": "^2.0.0",
9
- "rollup-plugin-serve": "^1.0.4"
10
- },
4
+ "private": true,
11
5
  "scripts": {
12
- "start": "rollup -c -w"
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview"
9
+ },
10
+ "dependencies": {
11
+ "react": "^19.2.5",
12
+ "react-dom": "^19.2.5"
13
+ },
14
+ "devDependencies": {
15
+ "@vitejs/plugin-react": "^6.0.1",
16
+ "vite": "^8.0.10"
13
17
  }
14
18
  }
@@ -1,6 +1,5 @@
1
- import 'regenerator-runtime/runtime'
2
1
  import React, { useState } from 'react'
3
- import ReactDOM from 'react-dom'
2
+ import { createRoot } from 'react-dom/client'
4
3
 
5
4
  import Vocal from '../../src'
6
5
 
@@ -43,4 +42,4 @@ const App = () => {
43
42
  )
44
43
  }
45
44
 
46
- ReactDOM.render(<App />, document.getElementById('root'))
45
+ createRoot(document.getElementById('root')).render(<App />)
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ server: {
7
+ port: 10001,
8
+ open: true,
9
+ },
10
+ })