@untemps/react-vocal 1.7.29 → 1.7.31

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.
@@ -0,0 +1,30 @@
1
+ name: "Publish package"
2
+ on:
3
+ push:
4
+ branches:
5
+ - main
6
+ - beta
7
+ permissions:
8
+ contents: write
9
+ id-token: write
10
+ pull-requests: write
11
+ issues: write
12
+ jobs:
13
+ release:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v6
17
+ with:
18
+ fetch-depth: 0
19
+ - uses: actions/setup-node@v6
20
+ with:
21
+ node-version: '24'
22
+ - run: yarn install --frozen-lockfile
23
+ - run: yarn test:ci
24
+ - run: yarn build
25
+ - run: npx semantic-release
26
+ env:
27
+ GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
28
+ - uses: codecov/codecov-action@v5
29
+ with:
30
+ files: coverage/lcov.info
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [1.7.31](https://github.com/untemps/react-vocal/compare/v1.7.30...v1.7.31) (2026-05-03)
2
+
3
+ ## [1.7.30](https://github.com/untemps/react-vocal/compare/v1.7.29...v1.7.30) (2025-12-08)
4
+
1
5
  ## [1.7.29](https://github.com/untemps/react-vocal/compare/v1.7.28...v1.7.29) (2025-12-08)
2
6
 
3
7
  ## [1.7.28](https://github.com/untemps/react-vocal/compare/v1.7.27...v1.7.28) (2024-12-13)
package/CLAUDE.md ADDED
@@ -0,0 +1,55 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ yarn test # watch mode
9
+ yarn test:ci # CI mode with coverage (also runs in pre-commit hook)
10
+ yarn build # build CJS + ES + UMD to dist/
11
+ yarn dev # dev server at http://localhost:10001/ (separate dev/ package)
12
+ yarn prettier # format all JS files and stage changes
13
+ ```
14
+
15
+ Run a single test file:
16
+ ```bash
17
+ yarn jest src/hooks/__tests__/useVocal.test.js
18
+ ```
19
+
20
+ Build formats are driven by `BABEL_ENV`: `cjs` → `dist/index.js`, `es` → `dist/index.es.js`, `umd` → `dist/index.umd.js`.
21
+
22
+ ## Architecture
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).
25
+
26
+ ### Public API (`src/index.js`)
27
+
28
+ - **`Vocal`** (default export) — the component
29
+ - **`useVocal`** — named export, the hook
30
+ - **`isSupported`** — boolean re-exported from `@untemps/vocal`
31
+
32
+ ### Hook layer (`src/hooks/`)
33
+
34
+ | Hook | Role |
35
+ |------|------|
36
+ | `useVocal` | Creates/manages a `SpeechRecognitionWrapper` instance in a ref. Returns `[ref, { start, stop, abort, subscribe, unsubscribe, clean }]`. Instance is re-created when `lang` or `grammars` change. |
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
+ | `useTimeout` | Manages the recognition timeout: starts on `start` event, pauses on `speechstart`, restarts on `speechend`, fires `_onEnd` on expiry. |
39
+
40
+ ### Component (`src/components/Vocal.js`)
41
+
42
+ Composes the three hooks above. Three render modes depending on `children`:
43
+ - **function** `(start, stop, isStarted) => element` — full control
44
+ - **React element** — receives `onClick` injected via `cloneElement`
45
+ - **no children** — renders the default `<Icon>` button
46
+
47
+ The `__rsInstance` prop (undocumented) injects a custom `SpeechRecognitionWrapper` instance, used exclusively in tests.
48
+
49
+ ### Testing
50
+
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.
52
+
53
+ ## Commit convention
54
+
55
+ Angular Conventional Commits (`feat`, `fix`, `chore`, `docs`, etc.). Enforced by commitlint on `commit-msg` hook.
@@ -3,9 +3,11 @@ import { toBeInTheDocument, toHaveAttribute, toHaveStyle } from '@testing-librar
3
3
 
4
4
  expect.extend({ toBeInTheDocument, toHaveAttribute, toHaveStyle })
5
5
 
6
- global.navigator = {
7
- userAgent: 'node.js',
8
- }
6
+ Object.defineProperty(global, 'navigator', {
7
+ value: { userAgent: 'node.js' },
8
+ writable: true,
9
+ configurable: true,
10
+ })
9
11
  global.PermissionStatus = jest.fn(() => ({
10
12
  state: 'granted',
11
13
  addEventListener: jest.fn(),
@@ -14,11 +16,19 @@ const status = new PermissionStatus()
14
16
  global.Permissions = jest.fn(() => ({
15
17
  query: jest.fn().mockResolvedValue(status),
16
18
  }))
17
- global.navigator.permissions = new Permissions()
19
+ Object.defineProperty(global.navigator, 'permissions', {
20
+ value: new Permissions(),
21
+ writable: true,
22
+ configurable: true,
23
+ })
18
24
  global.MediaDevices = jest.fn(() => ({
19
25
  getUserMedia: jest.fn().mockResolvedValue('foo'),
20
26
  }))
21
- global.navigator.mediaDevices = new MediaDevices()
27
+ Object.defineProperty(global.navigator, 'mediaDevices', {
28
+ value: new MediaDevices(),
29
+ writable: true,
30
+ configurable: true,
31
+ })
22
32
  global.SpeechGrammarList = jest.fn(() => ({
23
33
  length: 0,
24
34
  }))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@untemps/react-vocal",
3
- "version": "1.7.29",
3
+ "version": "1.7.31",
4
4
  "author": "Vincent Le Badezet <v.lebadezet@untemps.net>",
5
5
  "repository": "git@github.com:untemps/react-vocal.git",
6
6
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  "main": "dist/index.js",
24
24
  "module": "dist/index.es.js",
25
25
  "engines": {
26
- "node": ">=14"
26
+ "node": ">=18.0.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@babel/cli": "^7.12.10",
@@ -38,9 +38,9 @@
38
38
  "@rollup/plugin-babel": "^5.2.2",
39
39
  "@rollup/plugin-commonjs": "^17.0.0",
40
40
  "@rollup/plugin-node-resolve": "^11.0.1",
41
- "@semantic-release/changelog": "^6.0.1",
41
+ "@semantic-release/changelog": "^6.0.3",
42
42
  "@semantic-release/git": "^10.0.1",
43
- "@semantic-release/github": "^8.0.4",
43
+ "@semantic-release/github": "^12.0.6",
44
44
  "@testing-library/dom": "^7.29.0",
45
45
  "@testing-library/jest-dom": "^5.11.6",
46
46
  "@testing-library/react": "^11.2.2",
@@ -60,8 +60,8 @@
60
60
  "rollup": "^2.35.1",
61
61
  "rollup-plugin-sizes": "^1.0.4",
62
62
  "rollup-plugin-terser": "^7.0.2",
63
- "rollup-plugin-visualizer": "^4.2.0",
64
- "semantic-release": "^19.0.3"
63
+ "rollup-plugin-visualizer": "^5.14.0",
64
+ "semantic-release": "^25.0.3"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "react": "^16.13.1",
@@ -87,7 +87,11 @@
87
87
  },
88
88
  "release": {
89
89
  "branches": [
90
- "main"
90
+ "main",
91
+ {
92
+ "name": "beta",
93
+ "prerelease": true
94
+ }
91
95
  ],
92
96
  "plugins": [
93
97
  [
@@ -1,23 +0,0 @@
1
- name: "deploy"
2
- on:
3
- push:
4
- branches:
5
- - main
6
- jobs:
7
- release:
8
- runs-on: ubuntu-latest
9
- steps:
10
- - uses: actions/checkout@v2
11
- - uses: actions/setup-node@v1
12
- with:
13
- node-version: '14'
14
- - run: yarn install
15
- - run: yarn test:ci
16
- - run: yarn build
17
- - run: npx semantic-release
18
- env:
19
- GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
20
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
21
- - uses: codecov/codecov-action@v1
22
- with:
23
- file: coverage/lcov.info
@@ -1,21 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`Icon matches snapshot 1`] = `
4
- <DocumentFragment>
5
- <svg
6
- data-testid="__icon-root__"
7
- height="100%"
8
- viewBox="0 0 24 24"
9
- width="100%"
10
- xmlns="http://www.w3.org/2000/svg"
11
- >
12
- <g>
13
- <path
14
- d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"
15
- data-testid="__icon-path__"
16
- fill="black"
17
- />
18
- </g>
19
- </svg>
20
- </DocumentFragment>
21
- `;
@@ -1,28 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`Vocal matches snapshot 1`] = `
4
- <DocumentFragment>
5
- <button
6
- aria-label="start recognition"
7
- data-testid="__vocal-root__"
8
- role="button"
9
- style="width: 24px; height: 24px; background: none; padding: 0px; cursor: pointer;"
10
- >
11
- <svg
12
- data-testid="__icon-root__"
13
- height="100%"
14
- viewBox="0 0 24 24"
15
- width="100%"
16
- xmlns="http://www.w3.org/2000/svg"
17
- >
18
- <g>
19
- <path
20
- d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"
21
- data-testid="__icon-path__"
22
- fill="black"
23
- />
24
- </g>
25
- </svg>
26
- </button>
27
- </DocumentFragment>
28
- `;