@untemps/react-vocal 2.0.0-beta.15 → 2.0.0-beta.16

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 CHANGED
@@ -1,3 +1,10 @@
1
+ # [2.0.0-beta.16](https://github.com/untemps/react-vocal/compare/v2.0.0-beta.15...v2.0.0-beta.16) (2026-05-24)
2
+
3
+
4
+ ### Features
5
+
6
+ * Export useCommands and fix README result callback examples ([#158](https://github.com/untemps/react-vocal/issues/158)) ([990636a](https://github.com/untemps/react-vocal/commit/990636a3d7b3a7981629b0172318ae9bc739abf8))
7
+
1
8
  # [2.0.0-beta.15](https://github.com/untemps/react-vocal/compare/v2.0.0-beta.14...v2.0.0-beta.15) (2026-05-24)
2
9
 
3
10
 
package/README.md CHANGED
@@ -23,10 +23,12 @@ far (see [caniuse](https://caniuse.com/#search=SpeechRecognition)). If the API i
23
23
  won't display anything.
24
24
 
25
25
  This component intends to catch a speech result as soon as possible. This can be a good fit for vocal commands or search
26
- field filling. For now on it does not support continuous speech (see [Roadmap](#roadmap) below).
27
- That means either a result is caught and returned or timeout is reached and the recognition is discarded.
28
- The `stop` function returned by children-as-function mechanism allows to prematurely discard the recognition before
29
- timeout elapses.
26
+ field filling. It also supports a continuous mode (`continuous` prop) for real-time transcription and always-on voice
27
+ command use cases see the `Vocal` component API table for details.
28
+
29
+ In single-shot mode (the default), either a result is caught and returned or the timeout is reached and the recognition
30
+ is discarded. The `stop` function returned by children-as-function mechanism allows to prematurely discard the
31
+ recognition before the timeout elapses.
30
32
 
31
33
  ### Special cases
32
34
 
@@ -282,10 +284,10 @@ const App = () => {
282
284
  setResult('')
283
285
  }
284
286
 
285
- const _onVocalResult = (result) => {
287
+ const _onVocalResult = (_event, bestAlternative) => {
286
288
  setIsListening(false)
287
289
 
288
- setResult(result)
290
+ setResult(bestAlternative)
289
291
  }
290
292
 
291
293
  const _onVocalError = (e) => {
@@ -359,6 +361,57 @@ const [, { start }] = useVocal('en-US')
359
361
  start({ signal: controller.signal })
360
362
  ```
361
363
 
364
+ ### `useCommands` hook
365
+
366
+ The `useCommands` hook is the same command-matching primitive used internally by the `Vocal` component. Export it directly when you build a custom UI on top of `useVocal` and want to reuse the matching logic instead of re-implementing it.
367
+
368
+ #### Basic usage
369
+
370
+ ```javascript
371
+ import { useVocal, useCommands } from '@untemps/react-vocal'
372
+
373
+ const App = () => {
374
+ const commands = {
375
+ rouge: () => setBorderColor('red'),
376
+ bleu: () => setBorderColor('blue'),
377
+ }
378
+ const triggerCommand = useCommands(commands)
379
+
380
+ const [, { start, subscribe }] = useVocal('fr-FR')
381
+
382
+ const _onResult = (_event, bestAlternative) => {
383
+ triggerCommand(bestAlternative)
384
+ }
385
+
386
+ const _onClick = () => {
387
+ subscribe('result', _onResult)
388
+ start()
389
+ }
390
+
391
+ return <button onClick={_onClick}>Listen</button>
392
+ }
393
+ ```
394
+
395
+ #### Signature
396
+
397
+ ```
398
+ useCommands(commands, precision)
399
+ ```
400
+
401
+ | Args | Type | Default | Description |
402
+ | --------- | ------ | ------- | -------------------------------------------------------------------------------------------------------- |
403
+ | commands | object | null | A `{ key: callback }` map. Keys are lowercased internally. Callbacks receive `(rawInput, commandKey)`. |
404
+ | precision | number | 0.4 | Fuse.js score threshold for **phrase** command keys only (lower = stricter). Single-word keys use exact lookup. |
405
+
406
+ #### Return value
407
+
408
+ `useCommands` returns a `triggerCommand(rawInput)` function. Passing a transcript runs it against the commands map and invokes the matching callback if any, returning its result. Returns `null` when no command matches.
409
+
410
+ Matching rules:
411
+
412
+ - **Single-word keys** (e.g. `rouge`, `submit`): exact case-insensitive lookup, with each word of the input tried individually so a key fires even when embedded in a phrase (`je veux du rouge` triggers `rouge`).
413
+ - **Phrase keys** (e.g. `change the background color`): Fuse.js fuzzy matching against the joined transcript, gated by `precision`. fuse.js is loaded lazily; if it's not installed, the hook falls back to substring matching.
414
+
362
415
  ### Browser support flag
363
416
 
364
417
  #### Basic usage
@@ -416,4 +469,3 @@ Contributions are warmly welcomed:
416
469
  ## Roadmap
417
470
 
418
471
  - Add a connector management to plug external speech-to-text services in
419
- - Support continuous speech
package/dist/index.cjs CHANGED
@@ -3,5 +3,5 @@ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{val
3
3
  <%s {...props} />
4
4
  React keys must be passed directly to JSX without using spread:
5
5
  let props = %s;
6
- <%s key={someKey} {...props} />`,o,p,m,p),L[p+o]=!0)}if(p=null,i!==void 0&&(r(i),p=``+i),s(n)&&(r(n.key),p=``+n.key),`key`in n)for(var h in i={},n)h!==`key`&&(i[h]=n[h]);else i=n;return p&&c(i,typeof e==`function`?e.displayName||e.name||`Unknown`:e),u(e,p,i,a(),l,d)}function f(e){p(e)?e._store&&(e._store.validated=1):typeof e==`object`&&e&&e.$$typeof===E&&(e._payload.status===`fulfilled`?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e==`object`&&!!e&&e.$$typeof===h}var m=require(`react`),h=Symbol.for(`react.transitional.element`),g=Symbol.for(`react.portal`),_=Symbol.for(`react.fragment`),v=Symbol.for(`react.strict_mode`),y=Symbol.for(`react.profiler`),b=Symbol.for(`react.consumer`),x=Symbol.for(`react.context`),S=Symbol.for(`react.forward_ref`),C=Symbol.for(`react.suspense`),w=Symbol.for(`react.suspense_list`),T=Symbol.for(`react.memo`),E=Symbol.for(`react.lazy`),D=Symbol.for(`react.activity`),O=Symbol.for(`react.client.reference`),k=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,A=Object.prototype.hasOwnProperty,j=Array.isArray,M=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(e){return e()}};var N,P={},F=m.react_stack_bottom_frame.bind(m,o)(),I=M(i(o)),L={};e.Fragment=_,e.jsx=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!1,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)},e.jsxs=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!0,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)}})()})),w=e(((e,t)=>{process.env.NODE_ENV===`production`?t.exports=S():t.exports=C()}))(),T=({color:e=`black`,activeColor:t=`red`,isActive:n=!1})=>(0,w.jsx)(`svg`,{"data-testid":`__icon-root__`,xmlns:`http://www.w3.org/2000/svg`,width:`100%`,height:`100%`,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,w.jsxs)(`g`,{children:[(0,w.jsx)(`path`,{"data-testid":`__icon-path__`,fill:e,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`}),n&&(0,w.jsx)(`circle`,{"data-testid":`__icon-active__`,fill:t,cx:`16`,cy:`4`,r:`4`})]})}),E=(e,t)=>{for(let n of e)for(let e of n)if(t(e.transcript??``)!==null)return},D=({children:e,commands:n=null,lang:r=`en-US`,grammars:i=null,timeout:a=3e3,silenceTimeout:o=null,precision:s=.4,maxAlternatives:c=1,continuous:l=!1,ariaLabel:u=`start recognition`,style:d=null,className:f=null,outlineStyle:p=`2px solid`,onStart:m=null,onEnd:h=null,onSpeechStart:_=null,onSpeechEnd:S=null,onResult:C=null,onError:D=null,onNoMatch:O=null,signal:k=null,__rsInstance:A=null})=>{let j=(0,t.useRef)(null),M=(0,t.useMemo)(()=>g(),[]),[,{start:N,stop:P,subscribe:F,unsubscribe:I,isRecording:L}]=y(r,i,c,l,A),ee=x(n,s),R=(0,t.useRef)({onStart:null,onEnd:null,onSpeechStart:null,onSpeechEnd:null,onResult:null,onError:null,onNoMatch:null});R.current={onStart:m,onEnd:h,onSpeechStart:_,onSpeechEnd:S,onResult:C,onError:D,onNoMatch:O};let z=(0,t.useRef)(l);z.current=l;let B=(0,t.useRef)(ee);B.current=ee;let V=(0,t.useRef)(null),H=(0,t.useRef)(null),U=(0,t.useRef)(!1),W=(0,t.useRef)(o);W.current=o;let G=(0,t.useCallback)(()=>H.current?.(),[]),[K,q]=b(G,a),[te,J]=b(G,o??0),Y=(0,t.useCallback)(()=>{try{P()}catch(e){R.current.onError?.(e),V.current?.()}},[P]),ne=(0,t.useCallback)(e=>{K(),R.current.onStart?.(e)},[K]),re=(0,t.useCallback)(e=>{q(),R.current.onSpeechStart?.(e)},[q]),ie=(0,t.useCallback)(e=>{K(),z.current&&(W.current??0)>0&&te(),R.current.onSpeechEnd?.(e)},[K,te]),ae=(0,t.useCallback)((e,t)=>{q(),z.current||(E(e.results===void 0?[]:Array.from(e.results,e=>Array.from(e)),B.current),Y()),R.current.onResult?.(t,e)},[q,Y]),X=(0,t.useCallback)(e=>{Y(),R.current.onError?.(e)},[Y]),oe=(0,t.useCallback)(e=>{q(),Y(),R.current.onNoMatch?.(e)},[q,Y]),Z=(0,t.useCallback)(e=>{if(!U.current){U.current=!0,q(),J();try{Y(),V.current?.()}finally{U.current=!1,R.current.onEnd?.(e)}}},[q,J,Y]);H.current=Z;let Q=(0,t.useMemo)(()=>({start:ne,end:Z,speechstart:re,speechend:ie,result:ae,error:X,nomatch:oe}),[ne,Z,re,ie,ae,X,oe]);V.current=()=>Object.entries(Q).forEach(([e,t])=>I?.(e,t));let $=(0,t.useCallback)(()=>{try{J(),Object.entries(Q).forEach(([e,t])=>F(e,t)),N({signal:k??void 0})?.catch?.(X)}catch(e){X(e)}},[Q,F,N,J,X,k]),se=(0,t.useCallback)(()=>{!f&&p&&j.current&&(j.current.style.outline=p)},[f,p]),ce=(0,t.useCallback)(()=>{!f&&p&&j.current&&(j.current.style.outline=`none`)},[f,p]);return M?v(e)?e($,Y,L):(0,t.isValidElement)(e)?(0,t.cloneElement)(e,{...!L&&{onClick:$}}):(0,w.jsx)(`button`,{"data-testid":`__vocal-root__`,ref:j,"aria-label":u,"aria-pressed":L,style:f?void 0:{width:24,height:24,backgroundColor:`transparent`,border:`none`,padding:0,cursor:!l&&L?`default`:`pointer`,...d??{}},className:f??void 0,onFocus:se,onBlur:ce,onClick:L?Y:$,children:(0,w.jsx)(T,{isActive:L,color:`#aaa`})}):null};exports.default=D,exports.isSupported=g,exports.useVocal=y;
6
+ <%s key={someKey} {...props} />`,o,p,m,p),L[p+o]=!0)}if(p=null,i!==void 0&&(r(i),p=``+i),s(n)&&(r(n.key),p=``+n.key),`key`in n)for(var h in i={},n)h!==`key`&&(i[h]=n[h]);else i=n;return p&&c(i,typeof e==`function`?e.displayName||e.name||`Unknown`:e),u(e,p,i,a(),l,d)}function f(e){p(e)?e._store&&(e._store.validated=1):typeof e==`object`&&e&&e.$$typeof===E&&(e._payload.status===`fulfilled`?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e==`object`&&!!e&&e.$$typeof===h}var m=require(`react`),h=Symbol.for(`react.transitional.element`),g=Symbol.for(`react.portal`),_=Symbol.for(`react.fragment`),v=Symbol.for(`react.strict_mode`),y=Symbol.for(`react.profiler`),b=Symbol.for(`react.consumer`),x=Symbol.for(`react.context`),S=Symbol.for(`react.forward_ref`),C=Symbol.for(`react.suspense`),w=Symbol.for(`react.suspense_list`),T=Symbol.for(`react.memo`),E=Symbol.for(`react.lazy`),D=Symbol.for(`react.activity`),O=Symbol.for(`react.client.reference`),k=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,A=Object.prototype.hasOwnProperty,j=Array.isArray,M=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(e){return e()}};var N,P={},F=m.react_stack_bottom_frame.bind(m,o)(),I=M(i(o)),L={};e.Fragment=_,e.jsx=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!1,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)},e.jsxs=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!0,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)}})()})),w=e(((e,t)=>{process.env.NODE_ENV===`production`?t.exports=S():t.exports=C()}))(),T=({color:e=`black`,activeColor:t=`red`,isActive:n=!1})=>(0,w.jsx)(`svg`,{"data-testid":`__icon-root__`,xmlns:`http://www.w3.org/2000/svg`,width:`100%`,height:`100%`,viewBox:`0 0 24 24`,"aria-hidden":`true`,children:(0,w.jsxs)(`g`,{children:[(0,w.jsx)(`path`,{"data-testid":`__icon-path__`,fill:e,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`}),n&&(0,w.jsx)(`circle`,{"data-testid":`__icon-active__`,fill:t,cx:`16`,cy:`4`,r:`4`})]})}),E=(e,t)=>{for(let n of e)for(let e of n)if(t(e.transcript??``)!==null)return},D=({children:e,commands:n=null,lang:r=`en-US`,grammars:i=null,timeout:a=3e3,silenceTimeout:o=null,precision:s=.4,maxAlternatives:c=1,continuous:l=!1,ariaLabel:u=`start recognition`,style:d=null,className:f=null,outlineStyle:p=`2px solid`,onStart:m=null,onEnd:h=null,onSpeechStart:_=null,onSpeechEnd:S=null,onResult:C=null,onError:D=null,onNoMatch:O=null,signal:k=null,__rsInstance:A=null})=>{let j=(0,t.useRef)(null),M=(0,t.useMemo)(()=>g(),[]),[,{start:N,stop:P,subscribe:F,unsubscribe:I,isRecording:L}]=y(r,i,c,l,A),ee=x(n,s),R=(0,t.useRef)({onStart:null,onEnd:null,onSpeechStart:null,onSpeechEnd:null,onResult:null,onError:null,onNoMatch:null});R.current={onStart:m,onEnd:h,onSpeechStart:_,onSpeechEnd:S,onResult:C,onError:D,onNoMatch:O};let z=(0,t.useRef)(l);z.current=l;let B=(0,t.useRef)(ee);B.current=ee;let V=(0,t.useRef)(null),H=(0,t.useRef)(null),U=(0,t.useRef)(!1),W=(0,t.useRef)(o);W.current=o;let G=(0,t.useCallback)(()=>H.current?.(),[]),[K,q]=b(G,a),[te,J]=b(G,o??0),Y=(0,t.useCallback)(()=>{try{P()}catch(e){R.current.onError?.(e),V.current?.()}},[P]),ne=(0,t.useCallback)(e=>{K(),R.current.onStart?.(e)},[K]),re=(0,t.useCallback)(e=>{q(),R.current.onSpeechStart?.(e)},[q]),ie=(0,t.useCallback)(e=>{K(),z.current&&(W.current??0)>0&&te(),R.current.onSpeechEnd?.(e)},[K,te]),ae=(0,t.useCallback)((e,t)=>{q(),z.current||(E(e.results===void 0?[]:Array.from(e.results,e=>Array.from(e)),B.current),Y()),R.current.onResult?.(t,e)},[q,Y]),X=(0,t.useCallback)(e=>{Y(),R.current.onError?.(e)},[Y]),oe=(0,t.useCallback)(e=>{q(),Y(),R.current.onNoMatch?.(e)},[q,Y]),Z=(0,t.useCallback)(e=>{if(!U.current){U.current=!0,q(),J();try{Y(),V.current?.()}finally{U.current=!1,R.current.onEnd?.(e)}}},[q,J,Y]);H.current=Z;let Q=(0,t.useMemo)(()=>({start:ne,end:Z,speechstart:re,speechend:ie,result:ae,error:X,nomatch:oe}),[ne,Z,re,ie,ae,X,oe]);V.current=()=>Object.entries(Q).forEach(([e,t])=>I?.(e,t));let $=(0,t.useCallback)(()=>{try{J(),Object.entries(Q).forEach(([e,t])=>F(e,t)),N({signal:k??void 0})?.catch?.(X)}catch(e){X(e)}},[Q,F,N,J,X,k]),se=(0,t.useCallback)(()=>{!f&&p&&j.current&&(j.current.style.outline=p)},[f,p]),ce=(0,t.useCallback)(()=>{!f&&p&&j.current&&(j.current.style.outline=`none`)},[f,p]);return M?v(e)?e($,Y,L):(0,t.isValidElement)(e)?(0,t.cloneElement)(e,{...!L&&{onClick:$}}):(0,w.jsx)(`button`,{"data-testid":`__vocal-root__`,ref:j,"aria-label":u,"aria-pressed":L,style:f?void 0:{width:24,height:24,backgroundColor:`transparent`,border:`none`,padding:0,cursor:!l&&L?`default`:`pointer`,...d??{}},className:f??void 0,onFocus:se,onBlur:ce,onClick:L?Y:$,children:(0,w.jsx)(T,{isActive:L,color:`#aaa`})}):null};exports.default=D,exports.isSupported=g,exports.useCommands=x,exports.useVocal=y;
7
7
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -19,6 +19,8 @@ export declare type OnResultCallback = (bestAlternative: string, event: SpeechRe
19
19
 
20
20
  export declare type TriggerCommand = (rawInput: string) => unknown;
21
21
 
22
+ export declare const useCommands: (commands?: CommandsMap | null, precision?: number) => TriggerCommand;
23
+
22
24
  export declare const useVocal: (lang?: string, grammars?: SpeechGrammarList | null, maxAlternatives?: number, continuous?: boolean, __rsInstance?: VocalInstance | null) => UseVocalReturn;
23
25
 
24
26
  export declare interface UseVocalActions {
package/dist/index.es.js CHANGED
@@ -452,7 +452,7 @@ var s = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t
452
452
  }), N = (e, t) => {
453
453
  for (let n of e) for (let e of n) if (t(e.transcript ?? "") !== null) return;
454
454
  }, P = ({ children: r, commands: o = null, lang: s = "en-US", grammars: c = null, timeout: l = 3e3, silenceTimeout: u = null, precision: d = .4, maxAlternatives: f = 1, continuous: p = !1, ariaLabel: m = "start recognition", style: h = null, className: g = null, outlineStyle: _ = "2px solid", onStart: v = null, onEnd: y = null, onSpeechStart: b = null, onSpeechEnd: x = null, onResult: S = null, onError: w = null, onNoMatch: k = null, signal: A = null, __rsInstance: P = null }) => {
455
- let F = a(null), I = i(() => C(), []), [, { start: L, stop: R, subscribe: ee, unsubscribe: te, isRecording: z }] = E(s, c, f, p, P), B = O(o, d), V = a({
455
+ let F = a(null), I = i(() => C(), []), [, { start: L, stop: R, subscribe: ee, unsubscribe: te, isRecording: z }] = E(s, c, f, p, P), ne = O(o, d), B = a({
456
456
  onStart: null,
457
457
  onEnd: null,
458
458
  onSpeechStart: null,
@@ -461,7 +461,7 @@ var s = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t
461
461
  onError: null,
462
462
  onNoMatch: null
463
463
  });
464
- V.current = {
464
+ B.current = {
465
465
  onStart: v,
466
466
  onEnd: y,
467
467
  onSpeechStart: b,
@@ -470,37 +470,37 @@ var s = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t
470
470
  onError: w,
471
471
  onNoMatch: k
472
472
  };
473
- let H = a(p);
474
- H.current = p;
475
- let U = a(B);
476
- U.current = B;
477
- let W = a(null), ne = a(null), G = a(!1), re = a(u);
473
+ let V = a(p);
474
+ V.current = p;
475
+ let H = a(ne);
476
+ H.current = ne;
477
+ let U = a(null), W = a(null), G = a(!1), re = a(u);
478
478
  re.current = u;
479
- let ie = n(() => ne.current?.(), []), [K, q] = D(ie, l), [ae, J] = D(ie, u ?? 0), Y = n(() => {
479
+ let ie = n(() => W.current?.(), []), [K, q] = D(ie, l), [ae, J] = D(ie, u ?? 0), Y = n(() => {
480
480
  try {
481
481
  R();
482
482
  } catch (e) {
483
- V.current.onError?.(e), W.current?.();
483
+ B.current.onError?.(e), U.current?.();
484
484
  }
485
485
  }, [R]), oe = n((e) => {
486
- K(), V.current.onStart?.(e);
486
+ K(), B.current.onStart?.(e);
487
487
  }, [K]), se = n((e) => {
488
- q(), V.current.onSpeechStart?.(e);
488
+ q(), B.current.onSpeechStart?.(e);
489
489
  }, [q]), ce = n((e) => {
490
- K(), H.current && (re.current ?? 0) > 0 && ae(), V.current.onSpeechEnd?.(e);
490
+ K(), V.current && (re.current ?? 0) > 0 && ae(), B.current.onSpeechEnd?.(e);
491
491
  }, [K, ae]), le = n((e, t) => {
492
- q(), H.current || (N(e.results === void 0 ? [] : Array.from(e.results, (e) => Array.from(e)), U.current), Y()), V.current.onResult?.(t, e);
492
+ q(), V.current || (N(e.results === void 0 ? [] : Array.from(e.results, (e) => Array.from(e)), H.current), Y()), B.current.onResult?.(t, e);
493
493
  }, [q, Y]), X = n((e) => {
494
- Y(), V.current.onError?.(e);
494
+ Y(), B.current.onError?.(e);
495
495
  }, [Y]), ue = n((e) => {
496
- q(), Y(), V.current.onNoMatch?.(e);
496
+ q(), Y(), B.current.onNoMatch?.(e);
497
497
  }, [q, Y]), Z = n((e) => {
498
498
  if (!G.current) {
499
499
  G.current = !0, q(), J();
500
500
  try {
501
- Y(), W.current?.();
501
+ Y(), U.current?.();
502
502
  } finally {
503
- G.current = !1, V.current.onEnd?.(e);
503
+ G.current = !1, B.current.onEnd?.(e);
504
504
  }
505
505
  }
506
506
  }, [
@@ -508,7 +508,7 @@ var s = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t
508
508
  J,
509
509
  Y
510
510
  ]);
511
- ne.current = Z;
511
+ W.current = Z;
512
512
  let Q = i(() => ({
513
513
  start: oe,
514
514
  end: Z,
@@ -526,7 +526,7 @@ var s = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t
526
526
  X,
527
527
  ue
528
528
  ]);
529
- W.current = () => Object.entries(Q).forEach(([e, t]) => te?.(e, t));
529
+ U.current = () => Object.entries(Q).forEach(([e, t]) => te?.(e, t));
530
530
  let $ = n(() => {
531
531
  try {
532
532
  J(), Object.entries(Q).forEach(([e, t]) => ee(e, t)), L({ signal: A ?? void 0 })?.catch?.(X);
@@ -570,6 +570,6 @@ var s = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t
570
570
  }) : null;
571
571
  };
572
572
  //#endregion
573
- export { P as default, C as isSupported, E as useVocal };
573
+ export { P as default, C as isSupported, O as useCommands, E as useVocal };
574
574
 
575
575
  //# sourceMappingURL=index.es.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@untemps/react-vocal",
3
- "version": "2.0.0-beta.15",
3
+ "version": "2.0.0-beta.16",
4
4
  "author": "Vincent Le Badezet <v.lebadezet@untemps.net>",
5
5
  "repository": "git@github.com:untemps/react-vocal.git",
6
6
  "license": "MIT",