@untemps/vocal 2.0.0-beta.15 → 2.0.0-beta.17
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.
- package/CHANGELOG.md +19 -0
- package/README.md +17 -2
- package/dist/index.cjs +1 -1
- package/dist/index.es.js +6 -6
- package/dist/index.umd.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
# [2.0.0-beta.17](https://github.com/untemps/vocal/compare/v2.0.0-beta.16...v2.0.0-beta.17) (2026-05-16)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Remove instance getter to prevent implementation leakage ([#77](https://github.com/untemps/vocal/issues/77)) ([93fc58f](https://github.com/untemps/vocal/commit/93fc58f46abe7fadced9c8f512dd69fb4865cd9c))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* vocal.instance is removed. Consumers who accessed the raw SpeechRecognition object must migrate to Vocal API methods.
|
|
12
|
+
|
|
13
|
+
# [2.0.0-beta.16](https://github.com/untemps/vocal/compare/v2.0.0-beta.15...v2.0.0-beta.16) (2026-05-16)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* Add once() method for one-shot event listener registration ([#76](https://github.com/untemps/vocal/issues/76)) ([8179643](https://github.com/untemps/vocal/commit/8179643f159e3ccf690f7ac2d8bd101568c6e5b3))
|
|
19
|
+
|
|
1
20
|
# [2.0.0-beta.15](https://github.com/untemps/vocal/compare/v2.0.0-beta.14...v2.0.0-beta.15) (2026-05-16)
|
|
2
21
|
|
|
3
22
|
|
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ const vocal = new Vocal(options)
|
|
|
34
34
|
vocal.addEventListener('speechstart', (event) => console.log('Vocal starts recording'))
|
|
35
35
|
vocal.addEventListener('speechend', (event) => console.log('Vocal stops recording'))
|
|
36
36
|
vocal.addEventListener('result', (event, bestAlternative, alternatives) => console.log('Vocal catches a result:', bestAlternative, alternatives))
|
|
37
|
-
vocal.addEventListener('error', (
|
|
37
|
+
vocal.addEventListener('error', (event) => console.error(event.error, event.message))
|
|
38
38
|
|
|
39
39
|
// Start recording — rejects on error
|
|
40
40
|
try {
|
|
@@ -90,7 +90,6 @@ Please refer to [this section](https://developer.mozilla.org/en-US/docs/Web/API/
|
|
|
90
90
|
| Getter | Type | Description |
|
|
91
91
|
| ----------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
92
92
|
| isSupported | boolean | Whether the current environment supports the SpeechRecognition Web API (static) |
|
|
93
|
-
| instance | SpeechRecognition \| null | The underlying SpeechRecognition instance |
|
|
94
93
|
| isRecording | boolean | Whether recognition is currently active — `true` after `start()`, `false` after `stop()`, `abort()`, or `end` event |
|
|
95
94
|
|
|
96
95
|
## Methods
|
|
@@ -109,3 +108,19 @@ vocal.start({ signal: controller.signal })
|
|
|
109
108
|
controller.abort()
|
|
110
109
|
```
|
|
111
110
|
|
|
111
|
+
### `once(eventType, callback)`
|
|
112
|
+
|
|
113
|
+
Registers a one-shot listener that automatically unregisters itself after firing once.
|
|
114
|
+
|
|
115
|
+
| Parameter | Type | Description |
|
|
116
|
+
| --------- | ------------------------------------------------- | ------------------------------------------ |
|
|
117
|
+
| eventType | `EventType` | One of the valid event type strings |
|
|
118
|
+
| callback | `ResultEventHandler \| ErrorEventHandler \| GenericEventHandler` | Callback invoked once when the event fires |
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
vocal.once('result', (event, bestAlternative, alternatives) => {
|
|
122
|
+
console.log(bestAlternative)
|
|
123
|
+
vocal.stop()
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@untemps/user-permissions-utils`);var t=class t{static defaultOptions={grammars:null,lang:`en-US`,continuous:!1,interimResults:!1,maxAlternatives:1};static eventTypes={AUDIO_END:`audioend`,AUDIO_START:`audiostart`,END:`end`,ERROR:`error`,NO_MATCH:`nomatch`,RESULT:`result`,SOUND_END:`soundend`,SOUND_START:`soundstart`,SPEECH_END:`speechend`,SPEECH_START:`speechstart`,START:`start`};static get isSupported(){return!!t._resolveSpeechRecognition()&&!!(0,e.isNavigatorPermissionsSupported)()&&!!(0,e.isNavigatorMediaDevicesSupported)()}static set isSupported(e){throw Error(`You cannot set isSupported directly.`)}_instance=null;_listeners=null;_isRecording=!1;_onEnd=()=>{this._isRecording=!1};constructor(e){let n=t._resolveSpeechRecognition();if(!n)throw new DOMException(`SpeechRecognition not supported`,`NOT_SUPPORTED_ERR`);this._instance=new n,this._listeners={};let{grammars:r,...i}={...t.defaultOptions,...e??{}},a=this._instance;if(Object.assign(a,i),r)a.grammars=r;else{let e=t._resolveSpeechGrammarList();a.grammars=e?new e:null}this._instance.addEventListener(`end`,this._onEnd)}get
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@untemps/user-permissions-utils`);var t=class t{static defaultOptions={grammars:null,lang:`en-US`,continuous:!1,interimResults:!1,maxAlternatives:1};static eventTypes={AUDIO_END:`audioend`,AUDIO_START:`audiostart`,END:`end`,ERROR:`error`,NO_MATCH:`nomatch`,RESULT:`result`,SOUND_END:`soundend`,SOUND_START:`soundstart`,SPEECH_END:`speechend`,SPEECH_START:`speechstart`,START:`start`};static get isSupported(){return!!t._resolveSpeechRecognition()&&!!(0,e.isNavigatorPermissionsSupported)()&&!!(0,e.isNavigatorMediaDevicesSupported)()}static set isSupported(e){throw Error(`You cannot set isSupported directly.`)}_instance=null;_listeners=null;_isRecording=!1;_onEnd=()=>{this._isRecording=!1};constructor(e){let n=t._resolveSpeechRecognition();if(!n)throw new DOMException(`SpeechRecognition not supported`,`NOT_SUPPORTED_ERR`);this._instance=new n,this._listeners={};let{grammars:r,...i}={...t.defaultOptions,...e??{}},a=this._instance;if(Object.assign(a,i),r)a.grammars=r;else{let e=t._resolveSpeechGrammarList();a.grammars=e?new e:null}this._instance.addEventListener(`end`,this._onEnd)}get isRecording(){return this._isRecording}set isRecording(e){throw Error(`You cannot set isRecording directly.`)}async start({signal:t}={}){if(this._instance)try{if(!await(0,e.getUserMediaStream)(`microphone`,{audio:!0},{signal:t}))throw Error(`Unable to retrieve the stream from media device`);this._instance.start(),this._isRecording=!0}catch(e){if(e instanceof Error&&e.name===`AbortError`)return this;throw e}return this}stop(){return this._instance&&(this._instance.stop(),this._isRecording=!1),this}abort(){return this._instance&&(this._instance.abort(),this._isRecording=!1),this}addEventListener(e,n){if(!this._includesEventType(e))throw Error(this._unknownEventTypeMessage(e));if(this._instance&&this._listeners){let r=r=>{let i=[];if(e===t.eventTypes.RESULT){let e=r;if(e.results?.length>0&&e.resultIndex<e.results.length){let t=Array.from(e.results[e.resultIndex]),n=t.reduce((e,t)=>(t.confidence??0)>(e.confidence??0)?t:e);i.push(n.transcript,t.map(e=>e.transcript))}}n.call(this,r,...i)};this._instance.addEventListener(e,r),this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push({callback:n,handler:r})}return this}removeEventListener(e,t){if(!this._includesEventType(e))throw Error(this._unknownEventTypeMessage(e));let n=this._instance;if(n&&this._listeners&&this._listeners[e])if(t!==void 0){let r=this._listeners[e].findIndex(e=>e.callback===t);r!==-1&&(n.removeEventListener(e,this._listeners[e][r].handler),this._listeners[e].splice(r,1),this._listeners[e].length===0&&delete this._listeners[e])}else this._listeners[e].forEach(({handler:t})=>n.removeEventListener(e,t)),delete this._listeners[e];return this}once(e,t){let n=(...r)=>{t.call(this,...r),this.removeEventListener(e,n)};return this.addEventListener(e,n)}cleanup(){return this.stop(),Object.keys(this._listeners).forEach(e=>this.removeEventListener(e)),this._instance?.removeEventListener(`end`,this._onEnd),this._instance=null,this}_includesEventType(e){return Object.values(t.eventTypes).includes(e)}_unknownEventTypeMessage(e){return`Unknown event type "${e}". Valid types are: ${Object.values(t.eventTypes).join(`, `)}.`}static _resolveSpeechRecognition(){if(!(typeof window>`u`))return window.SpeechRecognition??window.webkitSpeechRecognition??window.mozSpeechRecognition??window.msSpeechRecognition}static _resolveSpeechGrammarList(){return window.SpeechGrammarList??window.webkitSpeechGrammarList??window.mozSpeechGrammarList??window.msSpeechGrammarList}};exports.Vocal=t;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.es.js
CHANGED
|
@@ -48,12 +48,6 @@ var r = class r {
|
|
|
48
48
|
}
|
|
49
49
|
this._instance.addEventListener("end", this._onEnd);
|
|
50
50
|
}
|
|
51
|
-
get instance() {
|
|
52
|
-
return this._instance;
|
|
53
|
-
}
|
|
54
|
-
set instance(e) {
|
|
55
|
-
throw Error("You cannot set instance directly.");
|
|
56
|
-
}
|
|
57
51
|
get isRecording() {
|
|
58
52
|
return this._isRecording;
|
|
59
53
|
}
|
|
@@ -106,6 +100,12 @@ var r = class r {
|
|
|
106
100
|
} else this._listeners[e].forEach(({ handler: t }) => n.removeEventListener(e, t)), delete this._listeners[e];
|
|
107
101
|
return this;
|
|
108
102
|
}
|
|
103
|
+
once(e, t) {
|
|
104
|
+
let n = (...r) => {
|
|
105
|
+
t.call(this, ...r), this.removeEventListener(e, n);
|
|
106
|
+
};
|
|
107
|
+
return this.addEventListener(e, n);
|
|
108
|
+
}
|
|
109
109
|
cleanup() {
|
|
110
110
|
return this.stop(), Object.keys(this._listeners).forEach((e) => this.removeEventListener(e)), this._instance?.removeEventListener("end", this._onEnd), this._instance = null, this;
|
|
111
111
|
}
|
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`@untemps/user-permissions-utils`)):typeof define==`function`&&define.amd?define([`exports`,`@untemps/user-permissions-utils`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.Vocal={},e.UserPermissionsUtils))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`}),e.Vocal=class e{static defaultOptions={grammars:null,lang:`en-US`,continuous:!1,interimResults:!1,maxAlternatives:1};static eventTypes={AUDIO_END:`audioend`,AUDIO_START:`audiostart`,END:`end`,ERROR:`error`,NO_MATCH:`nomatch`,RESULT:`result`,SOUND_END:`soundend`,SOUND_START:`soundstart`,SPEECH_END:`speechend`,SPEECH_START:`speechstart`,START:`start`};static get isSupported(){return!!e._resolveSpeechRecognition()&&!!(0,t.isNavigatorPermissionsSupported)()&&!!(0,t.isNavigatorMediaDevicesSupported)()}static set isSupported(e){throw Error(`You cannot set isSupported directly.`)}_instance=null;_listeners=null;_isRecording=!1;_onEnd=()=>{this._isRecording=!1};constructor(t){let n=e._resolveSpeechRecognition();if(!n)throw new DOMException(`SpeechRecognition not supported`,`NOT_SUPPORTED_ERR`);this._instance=new n,this._listeners={};let{grammars:r,...i}={...e.defaultOptions,...t??{}},a=this._instance;if(Object.assign(a,i),r)a.grammars=r;else{let t=e._resolveSpeechGrammarList();a.grammars=t?new t:null}this._instance.addEventListener(`end`,this._onEnd)}get
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`@untemps/user-permissions-utils`)):typeof define==`function`&&define.amd?define([`exports`,`@untemps/user-permissions-utils`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.Vocal={},e.UserPermissionsUtils))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`}),e.Vocal=class e{static defaultOptions={grammars:null,lang:`en-US`,continuous:!1,interimResults:!1,maxAlternatives:1};static eventTypes={AUDIO_END:`audioend`,AUDIO_START:`audiostart`,END:`end`,ERROR:`error`,NO_MATCH:`nomatch`,RESULT:`result`,SOUND_END:`soundend`,SOUND_START:`soundstart`,SPEECH_END:`speechend`,SPEECH_START:`speechstart`,START:`start`};static get isSupported(){return!!e._resolveSpeechRecognition()&&!!(0,t.isNavigatorPermissionsSupported)()&&!!(0,t.isNavigatorMediaDevicesSupported)()}static set isSupported(e){throw Error(`You cannot set isSupported directly.`)}_instance=null;_listeners=null;_isRecording=!1;_onEnd=()=>{this._isRecording=!1};constructor(t){let n=e._resolveSpeechRecognition();if(!n)throw new DOMException(`SpeechRecognition not supported`,`NOT_SUPPORTED_ERR`);this._instance=new n,this._listeners={};let{grammars:r,...i}={...e.defaultOptions,...t??{}},a=this._instance;if(Object.assign(a,i),r)a.grammars=r;else{let t=e._resolveSpeechGrammarList();a.grammars=t?new t:null}this._instance.addEventListener(`end`,this._onEnd)}get isRecording(){return this._isRecording}set isRecording(e){throw Error(`You cannot set isRecording directly.`)}async start({signal:e}={}){if(this._instance)try{if(!await(0,t.getUserMediaStream)(`microphone`,{audio:!0},{signal:e}))throw Error(`Unable to retrieve the stream from media device`);this._instance.start(),this._isRecording=!0}catch(e){if(e instanceof Error&&e.name===`AbortError`)return this;throw e}return this}stop(){return this._instance&&(this._instance.stop(),this._isRecording=!1),this}abort(){return this._instance&&(this._instance.abort(),this._isRecording=!1),this}addEventListener(t,n){if(!this._includesEventType(t))throw Error(this._unknownEventTypeMessage(t));if(this._instance&&this._listeners){let r=r=>{let i=[];if(t===e.eventTypes.RESULT){let e=r;if(e.results?.length>0&&e.resultIndex<e.results.length){let t=Array.from(e.results[e.resultIndex]),n=t.reduce((e,t)=>(t.confidence??0)>(e.confidence??0)?t:e);i.push(n.transcript,t.map(e=>e.transcript))}}n.call(this,r,...i)};this._instance.addEventListener(t,r),this._listeners[t]||(this._listeners[t]=[]),this._listeners[t].push({callback:n,handler:r})}return this}removeEventListener(e,t){if(!this._includesEventType(e))throw Error(this._unknownEventTypeMessage(e));let n=this._instance;if(n&&this._listeners&&this._listeners[e])if(t!==void 0){let r=this._listeners[e].findIndex(e=>e.callback===t);r!==-1&&(n.removeEventListener(e,this._listeners[e][r].handler),this._listeners[e].splice(r,1),this._listeners[e].length===0&&delete this._listeners[e])}else this._listeners[e].forEach(({handler:t})=>n.removeEventListener(e,t)),delete this._listeners[e];return this}once(e,t){let n=(...r)=>{t.call(this,...r),this.removeEventListener(e,n)};return this.addEventListener(e,n)}cleanup(){return this.stop(),Object.keys(this._listeners).forEach(e=>this.removeEventListener(e)),this._instance?.removeEventListener(`end`,this._onEnd),this._instance=null,this}_includesEventType(t){return Object.values(e.eventTypes).includes(t)}_unknownEventTypeMessage(t){return`Unknown event type "${t}". Valid types are: ${Object.values(e.eventTypes).join(`, `)}.`}static _resolveSpeechRecognition(){if(!(typeof window>`u`))return window.SpeechRecognition??window.webkitSpeechRecognition??window.mozSpeechRecognition??window.msSpeechRecognition}static _resolveSpeechGrammarList(){return window.SpeechGrammarList??window.webkitSpeechGrammarList??window.mozSpeechGrammarList??window.msSpeechGrammarList}}});
|
|
2
2
|
//# sourceMappingURL=index.umd.js.map
|