@tpitre/story-ui 4.16.6 → 4.16.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceCanvas.d.ts","sourceRoot":"","sources":["../../../../templates/StoryUI/voice/VoiceCanvas.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAwE,MAAM,OAAO,CAAC;AAY7F,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAID,eAAO,MAAM,WAAW,4FA6uBtB,CAAC"}
1
+ {"version":3,"file":"VoiceCanvas.d.ts","sourceRoot":"","sources":["../../../../templates/StoryUI/voice/VoiceCanvas.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAwE,MAAM,OAAO,CAAC;AAY7F,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAID,eAAO,MAAM,WAAW,4FAowBtB,CAAC"}
@@ -59,6 +59,7 @@ export const VoiceCanvas = React.forwardRef(function VoiceCanvas({ apiBase, prov
59
59
  const audioCheckRef = useRef(null);
60
60
  const audioStreamRef = useRef(null);
61
61
  const stopListeningRef = useRef(() => { });
62
+ const startListeningRef = useRef(() => { });
62
63
  const currentCodeRef = useRef(currentCode);
63
64
  currentCodeRef.current = currentCode;
64
65
  // Incremented on every new generation to prevent stale finally blocks from
@@ -90,6 +91,18 @@ export const VoiceCanvas = React.forwardRef(function VoiceCanvas({ apiBase, prov
90
91
  // Stamp this generation so stale finally blocks from aborted requests
91
92
  // don't clobber the state of a newer in-flight request.
92
93
  const genId = ++generationCounterRef.current;
94
+ // Pause voice recognition while the LLM is thinking so the user can
95
+ // talk freely without triggering new requests or aborting this one.
96
+ // The mic resumes automatically when generation completes.
97
+ const wasListening = isListeningRef.current;
98
+ if (wasListening && recognitionRef.current) {
99
+ try {
100
+ recognitionRef.current.stop();
101
+ }
102
+ catch { /* already stopped */ }
103
+ recognitionRef.current = null;
104
+ // Keep isListeningRef.current = true so we know to resume later
105
+ }
93
106
  setIsGenerating(true);
94
107
  setStatusText('Thinking...');
95
108
  setErrorMessage('');
@@ -179,6 +192,15 @@ export const VoiceCanvas = React.forwardRef(function VoiceCanvas({ apiBase, prov
179
192
  if (generationCounterRef.current === genId) {
180
193
  setIsGenerating(false);
181
194
  abortRef.current = null;
195
+ // Resume voice recognition if it was active before generation started.
196
+ // This lets the user keep talking hands-free across multiple edits.
197
+ if (wasListening && isListeningRef.current) {
198
+ setTimeout(() => {
199
+ if (isListeningRef.current && !recognitionRef.current) {
200
+ startListeningRef.current();
201
+ }
202
+ }, 300);
203
+ }
182
204
  }
183
205
  }
184
206
  }, [apiBase, provider, model, storyReady, sendCodeToIframe, onError]);
@@ -456,6 +478,7 @@ export const VoiceCanvas = React.forwardRef(function VoiceCanvas({ apiBase, prov
456
478
  setIsListening(false);
457
479
  }
458
480
  }, [clear, undo, redo, scheduleIntent, saveStory]);
481
+ startListeningRef.current = startListening;
459
482
  // ── Voice: stop ────────────────────────────────────────────────
460
483
  const stopListening = useCallback(() => {
461
484
  isListeningRef.current = false;
@@ -93,6 +93,7 @@ function VoiceCanvas({
93
93
  const audioCheckRef = useRef<ReturnType<typeof setTimeout> | null>(null);
94
94
  const audioStreamRef = useRef<MediaStream | null>(null);
95
95
  const stopListeningRef = useRef<() => void>(() => {});
96
+ const startListeningRef = useRef<() => void>(() => {});
96
97
  const currentCodeRef = useRef(currentCode);
97
98
  currentCodeRef.current = currentCode;
98
99
  // Incremented on every new generation to prevent stale finally blocks from
@@ -129,6 +130,16 @@ function VoiceCanvas({
129
130
  // don't clobber the state of a newer in-flight request.
130
131
  const genId = ++generationCounterRef.current;
131
132
 
133
+ // Pause voice recognition while the LLM is thinking so the user can
134
+ // talk freely without triggering new requests or aborting this one.
135
+ // The mic resumes automatically when generation completes.
136
+ const wasListening = isListeningRef.current;
137
+ if (wasListening && recognitionRef.current) {
138
+ try { recognitionRef.current.stop(); } catch { /* already stopped */ }
139
+ recognitionRef.current = null;
140
+ // Keep isListeningRef.current = true so we know to resume later
141
+ }
142
+
132
143
  setIsGenerating(true);
133
144
  setStatusText('Thinking...');
134
145
  setErrorMessage('');
@@ -227,6 +238,16 @@ function VoiceCanvas({
227
238
  if (generationCounterRef.current === genId) {
228
239
  setIsGenerating(false);
229
240
  abortRef.current = null;
241
+
242
+ // Resume voice recognition if it was active before generation started.
243
+ // This lets the user keep talking hands-free across multiple edits.
244
+ if (wasListening && isListeningRef.current) {
245
+ setTimeout(() => {
246
+ if (isListeningRef.current && !recognitionRef.current) {
247
+ startListeningRef.current();
248
+ }
249
+ }, 300);
250
+ }
230
251
  }
231
252
  }
232
253
  }, [apiBase, provider, model, storyReady, sendCodeToIframe, onError]);
@@ -495,6 +516,8 @@ function VoiceCanvas({
495
516
  }
496
517
  }, [clear, undo, redo, scheduleIntent, saveStory]);
497
518
 
519
+ startListeningRef.current = startListening;
520
+
498
521
  // ── Voice: stop ────────────────────────────────────────────────
499
522
 
500
523
  const stopListening = useCallback(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpitre/story-ui",
3
- "version": "4.16.6",
3
+ "version": "4.16.7",
4
4
  "description": "AI-powered Storybook story generator with dynamic component discovery",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -93,6 +93,7 @@ function VoiceCanvas({
93
93
  const audioCheckRef = useRef<ReturnType<typeof setTimeout> | null>(null);
94
94
  const audioStreamRef = useRef<MediaStream | null>(null);
95
95
  const stopListeningRef = useRef<() => void>(() => {});
96
+ const startListeningRef = useRef<() => void>(() => {});
96
97
  const currentCodeRef = useRef(currentCode);
97
98
  currentCodeRef.current = currentCode;
98
99
  // Incremented on every new generation to prevent stale finally blocks from
@@ -129,6 +130,16 @@ function VoiceCanvas({
129
130
  // don't clobber the state of a newer in-flight request.
130
131
  const genId = ++generationCounterRef.current;
131
132
 
133
+ // Pause voice recognition while the LLM is thinking so the user can
134
+ // talk freely without triggering new requests or aborting this one.
135
+ // The mic resumes automatically when generation completes.
136
+ const wasListening = isListeningRef.current;
137
+ if (wasListening && recognitionRef.current) {
138
+ try { recognitionRef.current.stop(); } catch { /* already stopped */ }
139
+ recognitionRef.current = null;
140
+ // Keep isListeningRef.current = true so we know to resume later
141
+ }
142
+
132
143
  setIsGenerating(true);
133
144
  setStatusText('Thinking...');
134
145
  setErrorMessage('');
@@ -227,6 +238,16 @@ function VoiceCanvas({
227
238
  if (generationCounterRef.current === genId) {
228
239
  setIsGenerating(false);
229
240
  abortRef.current = null;
241
+
242
+ // Resume voice recognition if it was active before generation started.
243
+ // This lets the user keep talking hands-free across multiple edits.
244
+ if (wasListening && isListeningRef.current) {
245
+ setTimeout(() => {
246
+ if (isListeningRef.current && !recognitionRef.current) {
247
+ startListeningRef.current();
248
+ }
249
+ }, 300);
250
+ }
230
251
  }
231
252
  }
232
253
  }, [apiBase, provider, model, storyReady, sendCodeToIframe, onError]);
@@ -495,6 +516,8 @@ function VoiceCanvas({
495
516
  }
496
517
  }, [clear, undo, redo, scheduleIntent, saveStory]);
497
518
 
519
+ startListeningRef.current = startListening;
520
+
498
521
  // ── Voice: stop ────────────────────────────────────────────────
499
522
 
500
523
  const stopListening = useCallback(() => {