@untemps/vocal 2.0.0-beta.20 → 2.0.0-beta.21
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 +17 -0
- package/README.md +0 -16
- package/dist/index.cjs +1 -1
- package/dist/index.es.js +0 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# [2.0.0-beta.21](https://github.com/untemps/vocal/compare/v2.0.0-beta.20...v2.0.0-beta.21) (2026-05-20)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Code Refactoring
|
|
5
|
+
|
|
6
|
+
* Remove once() method ([#87](https://github.com/untemps/vocal/issues/87)) ([3748768](https://github.com/untemps/vocal/commit/3748768c33f61ba170f4ffd09ccba23063e5c8c5))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* vocal.once(eventType, callback) is removed. Consumers relying on it must replace the call with a manual addEventListener + removeEventListener pair:
|
|
12
|
+
const handler = (event, best) => {
|
|
13
|
+
vocal.removeEventListener('result', handler)
|
|
14
|
+
// ...
|
|
15
|
+
}
|
|
16
|
+
vocal.addEventListener('result', handler)
|
|
17
|
+
|
|
1
18
|
# [2.0.0-beta.20](https://github.com/untemps/vocal/compare/v2.0.0-beta.19...v2.0.0-beta.20) (2026-05-20)
|
|
2
19
|
|
|
3
20
|
|
package/README.md
CHANGED
|
@@ -150,22 +150,6 @@ Removes a listener for the given event type.
|
|
|
150
150
|
|
|
151
151
|
Throws if `eventType` is not a valid `EventType`.
|
|
152
152
|
|
|
153
|
-
### `once(eventType, callback)`
|
|
154
|
-
|
|
155
|
-
Registers a one-shot listener that automatically unregisters itself after firing once.
|
|
156
|
-
|
|
157
|
-
| Parameter | Type | Description |
|
|
158
|
-
| --------- | ------------------------------------------------- | ------------------------------------------ |
|
|
159
|
-
| eventType | `EventType` | One of the valid event type strings |
|
|
160
|
-
| callback | `ResultEventHandler \| ErrorEventHandler \| GenericEventHandler` | Callback invoked once when the event fires |
|
|
161
|
-
|
|
162
|
-
```js
|
|
163
|
-
vocal.once('result', (event, bestAlternative, alternatives) => {
|
|
164
|
-
console.log(bestAlternative)
|
|
165
|
-
vocal.stop()
|
|
166
|
-
})
|
|
167
|
-
```
|
|
168
|
-
|
|
169
153
|
### `cleanup()`
|
|
170
154
|
|
|
171
155
|
Stops recognition, removes all registered listeners, and releases the internal `SpeechRecognition` instance. The `Vocal` object cannot be reused after `cleanup()`.
|
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=1e3,n=new Set([`not-allowed`,`service-not-allowed`,`audio-capture`]),r=class r{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!!r._resolveSpeechRecognition()&&!!(0,e.isNavigatorPermissionsSupported)()&&!!(0,e.isNavigatorMediaDevicesSupported)()}static set isSupported(e){throw Error(`You cannot set isSupported directly.`)}_instance=null;_listeners={};_isRecording=!1;_explicitStop=!1;_lastStartedAt=0;_restartTimeoutId=null;_isRestarting=!1;_finalTranscripts=[];_onEnd=e=>{if(this._shouldAutoRestart()){let n=Math.max(0,t-(Date.now()-this._lastStartedAt));this._isRestarting=!0,this._restartTimeoutId=setTimeout(()=>this._restart(),n),e.stopImmediatePropagation();return}this._isRecording=!1};_onStart=e=>{this._isRestarting&&(e.stopImmediatePropagation(),queueMicrotask(()=>{this._isRestarting=!1}))};_onError=e=>{n.has(e.error)&&(this._explicitStop=!0,this._clearRestartTimeout(),this._isRecording=!1)};_onResult=e=>{let t=e,n=t.results?.[t.resultIndex];n?.isFinal&&this._finalTranscripts.push(r._pickBestAlternative(Array.from(n)).transcript)};constructor(e){let t=r._resolveSpeechRecognition();if(!t)throw new DOMException(`SpeechRecognition not supported`,`NOT_SUPPORTED_ERR`);this._instance=new t;let{grammars:n,...i}={...r.defaultOptions,...e??{}},a=this._instance;if(Object.assign(a,i),n)a.grammars=n;else{let e=r._resolveSpeechGrammarList();a.grammars=e?new e:null}this._instance.addEventListener(r.eventTypes.END,this._onEnd),this._instance.addEventListener(r.eventTypes.START,this._onStart),this._instance.addEventListener(r.eventTypes.ERROR,this._onError),this._instance.addEventListener(r.eventTypes.RESULT,this._onResult)}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._explicitStop=!1,this._finalTranscripts=[],this._instance.start(),this._isRecording=!0,this._lastStartedAt=Date.now()}catch(e){if(e instanceof Error&&e.name===`AbortError`)return this;throw e}return this}stop(){return this._instance&&(this._explicitStop=!0,this._clearRestartTimeout(),this._emitAggregatedResult(),this._instance.stop(),this._isRecording=!1),this}abort(){return this._instance&&(this._explicitStop=!0,this._clearRestartTimeout(),this._instance.abort(),this._isRecording=!1,this._finalTranscripts=[]),this}addEventListener(e,t){if(!this._includesEventType(e))throw Error(this._unknownEventTypeMessage(e));if(this._instance){let n=n=>{if(this._isRestarting&&(e===r.eventTypes.END||e===r.eventTypes.START))return;let i=[];if(e===r.eventTypes.RESULT){let e=n;if(e.results?.length>0&&e.resultIndex<e.results.length){let t=Array.from(e.results[e.resultIndex]);i.push(r._pickBestAlternative(t).transcript,t.map(e=>e.transcript))}}t.call(this,n,...i)};this._instance.addEventListener(e,n),this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push({callback:t,handler:n})}return this}removeEventListener(e,t){if(!this._includesEventType(e))throw Error(this._unknownEventTypeMessage(e));let n=this._instance;if(n&&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}
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@untemps/user-permissions-utils`);var t=1e3,n=new Set([`not-allowed`,`service-not-allowed`,`audio-capture`]),r=class r{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!!r._resolveSpeechRecognition()&&!!(0,e.isNavigatorPermissionsSupported)()&&!!(0,e.isNavigatorMediaDevicesSupported)()}static set isSupported(e){throw Error(`You cannot set isSupported directly.`)}_instance=null;_listeners={};_isRecording=!1;_explicitStop=!1;_lastStartedAt=0;_restartTimeoutId=null;_isRestarting=!1;_finalTranscripts=[];_onEnd=e=>{if(this._shouldAutoRestart()){let n=Math.max(0,t-(Date.now()-this._lastStartedAt));this._isRestarting=!0,this._restartTimeoutId=setTimeout(()=>this._restart(),n),e.stopImmediatePropagation();return}this._isRecording=!1};_onStart=e=>{this._isRestarting&&(e.stopImmediatePropagation(),queueMicrotask(()=>{this._isRestarting=!1}))};_onError=e=>{n.has(e.error)&&(this._explicitStop=!0,this._clearRestartTimeout(),this._isRecording=!1)};_onResult=e=>{let t=e,n=t.results?.[t.resultIndex];n?.isFinal&&this._finalTranscripts.push(r._pickBestAlternative(Array.from(n)).transcript)};constructor(e){let t=r._resolveSpeechRecognition();if(!t)throw new DOMException(`SpeechRecognition not supported`,`NOT_SUPPORTED_ERR`);this._instance=new t;let{grammars:n,...i}={...r.defaultOptions,...e??{}},a=this._instance;if(Object.assign(a,i),n)a.grammars=n;else{let e=r._resolveSpeechGrammarList();a.grammars=e?new e:null}this._instance.addEventListener(r.eventTypes.END,this._onEnd),this._instance.addEventListener(r.eventTypes.START,this._onStart),this._instance.addEventListener(r.eventTypes.ERROR,this._onError),this._instance.addEventListener(r.eventTypes.RESULT,this._onResult)}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._explicitStop=!1,this._finalTranscripts=[],this._instance.start(),this._isRecording=!0,this._lastStartedAt=Date.now()}catch(e){if(e instanceof Error&&e.name===`AbortError`)return this;throw e}return this}stop(){return this._instance&&(this._explicitStop=!0,this._clearRestartTimeout(),this._emitAggregatedResult(),this._instance.stop(),this._isRecording=!1),this}abort(){return this._instance&&(this._explicitStop=!0,this._clearRestartTimeout(),this._instance.abort(),this._isRecording=!1,this._finalTranscripts=[]),this}addEventListener(e,t){if(!this._includesEventType(e))throw Error(this._unknownEventTypeMessage(e));if(this._instance){let n=n=>{if(this._isRestarting&&(e===r.eventTypes.END||e===r.eventTypes.START))return;let i=[];if(e===r.eventTypes.RESULT){let e=n;if(e.results?.length>0&&e.resultIndex<e.results.length){let t=Array.from(e.results[e.resultIndex]);i.push(r._pickBestAlternative(t).transcript,t.map(e=>e.transcript))}}t.call(this,n,...i)};this._instance.addEventListener(e,n),this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push({callback:t,handler:n})}return this}removeEventListener(e,t){if(!this._includesEventType(e))throw Error(this._unknownEventTypeMessage(e));let n=this._instance;if(n&&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}cleanup(){return this.stop(),Object.keys(this._listeners).forEach(e=>this.removeEventListener(e)),this._instance?.removeEventListener(r.eventTypes.END,this._onEnd),this._instance?.removeEventListener(r.eventTypes.START,this._onStart),this._instance?.removeEventListener(r.eventTypes.ERROR,this._onError),this._instance?.removeEventListener(r.eventTypes.RESULT,this._onResult),this._instance=null,this}_restart=()=>{this._restartTimeoutId=null;try{this._instance.start(),this._lastStartedAt=Date.now()}catch{this._isRestarting=!1,this._isRecording=!1}};_emitAggregatedResult(){let e=this._finalTranscripts;if(this._finalTranscripts=[],e.length===0)return;let t=e.join(` `).trim(),n=Object.assign([{transcript:t,confidence:1}],{isFinal:!0}),i=Object.assign(new Event(r.eventTypes.RESULT),{resultIndex:0,results:[n]});[...this._listeners[r.eventTypes.RESULT]??[]].forEach(({handler:e})=>e(i))}static _pickBestAlternative(e){return e.reduce((e,t)=>(t.confidence??0)>(e.confidence??0)?t:e)}_shouldAutoRestart(){return!!this._instance&&!this._explicitStop&&this._instance.continuous}_clearRestartTimeout(){this._restartTimeoutId!==null&&(clearTimeout(this._restartTimeoutId),this._restartTimeoutId=null),this._isRestarting=!1}_includesEventType(e){return Object.values(r.eventTypes).includes(e)}_unknownEventTypeMessage(e){return`Unknown event type "${e}". Valid types are: ${Object.values(r.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=r;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.es.js
CHANGED
|
@@ -127,12 +127,6 @@ var r = 1e3, i = new Set([
|
|
|
127
127
|
} else this._listeners[e].forEach(({ handler: t }) => n.removeEventListener(e, t)), delete this._listeners[e];
|
|
128
128
|
return this;
|
|
129
129
|
}
|
|
130
|
-
once(e, t) {
|
|
131
|
-
let n = (...r) => {
|
|
132
|
-
t.call(this, ...r), this.removeEventListener(e, n);
|
|
133
|
-
};
|
|
134
|
-
return this.addEventListener(e, n);
|
|
135
|
-
}
|
|
136
130
|
cleanup() {
|
|
137
131
|
return this.stop(), Object.keys(this._listeners).forEach((e) => this.removeEventListener(e)), this._instance?.removeEventListener(a.eventTypes.END, this._onEnd), this._instance?.removeEventListener(a.eventTypes.START, this._onStart), this._instance?.removeEventListener(a.eventTypes.ERROR, this._onError), this._instance?.removeEventListener(a.eventTypes.RESULT, this._onResult), this._instance = null, this;
|
|
138
132
|
}
|