@epicbagel/saas-kit 1.10.0 → 1.11.1

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.
Files changed (42) hide show
  1. package/README.md +21 -3
  2. package/dist/{chunk-VBKJXNEL.js → chunk-5OF6D3GH.js} +4 -3
  3. package/dist/chunk-D47AMKT4.cjs +293 -0
  4. package/dist/chunk-EDEN7TAL.js +293 -0
  5. package/dist/{chunk-M2ZNC3TK.js → chunk-HLAHOVEI.js} +98 -2
  6. package/dist/{chunk-KUG4ONYC.js → chunk-KF4X37DP.js} +40 -27
  7. package/dist/{chunk-XB2D4NQK.cjs → chunk-NKWHDI4C.cjs} +4 -3
  8. package/dist/{chunk-UW67GSZ4.cjs → chunk-YMI3X2YL.cjs} +38 -25
  9. package/dist/{chunk-O6F3LVZY.cjs → chunk-ZZ7ICQR2.cjs} +120 -24
  10. package/dist/hooks/use-dictation.cjs +2 -2
  11. package/dist/hooks/use-dictation.d.cts +5 -0
  12. package/dist/hooks/use-dictation.d.ts +5 -0
  13. package/dist/hooks/use-dictation.js +1 -1
  14. package/dist/primitives/agent-audio-visualizer-bar.cjs +2 -2
  15. package/dist/primitives/agent-audio-visualizer-bar.d.cts +1 -1
  16. package/dist/primitives/agent-audio-visualizer-bar.d.ts +1 -1
  17. package/dist/primitives/agent-audio-visualizer-bar.js +1 -1
  18. package/dist/primitives/alert.d.cts +1 -1
  19. package/dist/primitives/alert.d.ts +1 -1
  20. package/dist/primitives/badge.d.cts +1 -1
  21. package/dist/primitives/badge.d.ts +1 -1
  22. package/dist/primitives/bubble.d.cts +1 -1
  23. package/dist/primitives/bubble.d.ts +1 -1
  24. package/dist/primitives/button.d.cts +2 -2
  25. package/dist/primitives/button.d.ts +2 -2
  26. package/dist/primitives/chat.cjs +15 -15
  27. package/dist/primitives/chat.d.cts +2 -2
  28. package/dist/primitives/chat.d.ts +2 -2
  29. package/dist/primitives/chat.js +10 -10
  30. package/dist/primitives/dictation-provider.cjs +2 -2
  31. package/dist/primitives/dictation-provider.js +1 -1
  32. package/dist/primitives/voice-dictation-button.cjs +5 -3
  33. package/dist/primitives/voice-dictation-button.d.cts +9 -11
  34. package/dist/primitives/voice-dictation-button.d.ts +9 -11
  35. package/dist/primitives/voice-dictation-button.js +4 -2
  36. package/dist/primitives/voice-session-controls.cjs +3 -3
  37. package/dist/primitives/voice-session-controls.d.cts +3 -1
  38. package/dist/primitives/voice-session-controls.d.ts +3 -1
  39. package/dist/primitives/voice-session-controls.js +2 -2
  40. package/package.json +1 -1
  41. package/dist/chunk-HTCW6AEH.cjs +0 -223
  42. package/dist/chunk-KWV5KTOA.js +0 -223
@@ -12,13 +12,101 @@ function DictationProvider({ transcribe, scopeKey, children }) {
12
12
  }
13
13
  var EMPTY = { state: "idle", transcript: "", interimTranscript: "", error: null, canRetry: false };
14
14
  var MIME_TYPES = ["audio/webm;codecs=opus", "audio/mp4", "audio/ogg;codecs=opus", "audio/webm"];
15
+ var SILENCE = [];
16
+ function createAudioLevels() {
17
+ let bands = SILENCE;
18
+ const listeners = /* @__PURE__ */ new Set();
19
+ return {
20
+ subscribe: (listener) => {
21
+ listeners.add(listener);
22
+ return () => {
23
+ listeners.delete(listener);
24
+ };
25
+ },
26
+ getSnapshot: () => bands,
27
+ update: (next) => {
28
+ if (next.length === bands.length && next.every((value, index) => value === bands[index])) return;
29
+ bands = next;
30
+ listeners.forEach((listener) => listener());
31
+ }
32
+ };
33
+ }
34
+ function meterStream(stream, levels, active) {
35
+ let context;
36
+ let source;
37
+ let analyser;
38
+ let frame;
39
+ let stopped = false;
40
+ const stop = () => {
41
+ if (stopped) return;
42
+ stopped = true;
43
+ if (frame !== void 0) cancelAnimationFrame(frame);
44
+ try {
45
+ _optionalChain([source, 'optionalAccess', _2 => _2.disconnect, 'call', _3 => _3()]);
46
+ } catch (e) {
47
+ }
48
+ try {
49
+ _optionalChain([analyser, 'optionalAccess', _4 => _4.disconnect, 'call', _5 => _5()]);
50
+ } catch (e2) {
51
+ }
52
+ try {
53
+ void _optionalChain([context, 'optionalAccess', _6 => _6.close, 'call', _7 => _7(), 'access', _8 => _8.catch, 'call', _9 => _9(() => {
54
+ })]);
55
+ } catch (e3) {
56
+ }
57
+ levels.update(SILENCE);
58
+ };
59
+ try {
60
+ const Constructor = _nullishCoalesce(window.AudioContext, () => ( window.webkitAudioContext));
61
+ if (!Constructor || typeof requestAnimationFrame !== "function") return stop;
62
+ context = new Constructor();
63
+ source = context.createMediaStreamSource(stream);
64
+ analyser = context.createAnalyser();
65
+ analyser.fftSize = 512;
66
+ analyser.smoothingTimeConstant = 0.7;
67
+ source.connect(analyser);
68
+ const bins = new Uint8Array(analyser.frequencyBinCount);
69
+ const binWidth = context.sampleRate / analyser.fftSize;
70
+ const highest = Math.min(8e3, context.sampleRate / 2);
71
+ let sampledAt = -Infinity;
72
+ const sample = (time) => {
73
+ if (stopped) return;
74
+ if (!active()) {
75
+ stop();
76
+ return;
77
+ }
78
+ try {
79
+ if (time - sampledAt >= 40) {
80
+ sampledAt = time;
81
+ analyser.getByteFrequencyData(bins);
82
+ const bands = Array.from({ length: 24 }, (_, index) => {
83
+ const from = Math.min(bins.length - 1, Math.floor(80 * (highest / 80) ** (index / 24) / binWidth));
84
+ const to = Math.min(bins.length, Math.max(from + 1, Math.ceil(80 * (highest / 80) ** ((index + 1) / 24) / binWidth)));
85
+ let total = 0;
86
+ for (let bin = from; bin < to; bin++) total += bins[bin];
87
+ return Math.round(total / (to - from) / 255 * 1e3) / 1e3;
88
+ });
89
+ levels.update(bands);
90
+ }
91
+ frame = requestAnimationFrame(sample);
92
+ } catch (e4) {
93
+ stop();
94
+ }
95
+ };
96
+ if (context.state === "suspended") void context.resume().catch(stop);
97
+ frame = requestAnimationFrame(sample);
98
+ } catch (e5) {
99
+ stop();
100
+ }
101
+ return stop;
102
+ }
15
103
  function recognitionConstructor() {
16
104
  if (typeof window === "undefined") return void 0;
17
105
  const speech = window;
18
106
  return _nullishCoalesce(speech.SpeechRecognition, () => ( speech.webkitSpeechRecognition));
19
107
  }
20
108
  function microphoneError(reason) {
21
- const name = _optionalChain([reason, 'optionalAccess', _ => _.name]);
109
+ const name = _optionalChain([reason, 'optionalAccess', _10 => _10.name]);
22
110
  if (name === "NotAllowedError" || name === "SecurityError") return "Microphone access is blocked. Allow it in your browser and try again.";
23
111
  if (name === "NotFoundError" || name === "NotReadableError") return "The microphone is unavailable. Check your microphone and try again.";
24
112
  return "Recording could not start. Check your microphone and try again.";
@@ -29,8 +117,13 @@ function recognitionError(code) {
29
117
  if (code === "no-speech") return "No speech was detected. Try again.";
30
118
  return "Speech recognition stopped. Try again.";
31
119
  }
120
+ function releaseMeter(session) {
121
+ _optionalChain([session, 'access', _11 => _11.stopMeter, 'optionalCall', _12 => _12()]);
122
+ session.stopMeter = void 0;
123
+ }
32
124
  function releaseTracks(session) {
33
- _optionalChain([session, 'access', _2 => _2.stream, 'optionalAccess', _3 => _3.getTracks, 'call', _4 => _4(), 'access', _5 => _5.forEach, 'call', _6 => _6((track) => track.stop())]);
125
+ releaseMeter(session);
126
+ _optionalChain([session, 'access', _13 => _13.stream, 'optionalAccess', _14 => _14.getTracks, 'call', _15 => _15(), 'access', _16 => _16.forEach, 'call', _17 => _17((track) => track.stop())]);
34
127
  session.stream = void 0;
35
128
  }
36
129
  function dispose(session) {
@@ -44,7 +137,7 @@ function dispose(session) {
44
137
  if (recorder.state !== "inactive") {
45
138
  try {
46
139
  recorder.stop();
47
- } catch (e) {
140
+ } catch (e6) {
48
141
  }
49
142
  }
50
143
  }
@@ -55,7 +148,7 @@ function dispose(session) {
55
148
  recognition.onend = null;
56
149
  try {
57
150
  recognition.abort();
58
- } catch (e2) {
151
+ } catch (e7) {
59
152
  }
60
153
  }
61
154
  releaseTracks(session);
@@ -64,9 +157,9 @@ function dispose(session) {
64
157
  }
65
158
  function useDictation({ lang = "en-US", continuous = true, onTranscript } = {}) {
66
159
  const provider = _react.useContext.call(void 0, DictationContext);
67
- const transcribe = _nullishCoalesce(_optionalChain([provider, 'optionalAccess', _7 => _7.transcribe]), () => ( null));
68
- const scope = _nullishCoalesce(_optionalChain([provider, 'optionalAccess', _8 => _8.scope]), () => ( null));
69
- const scopeGeneration = _nullishCoalesce(_optionalChain([provider, 'optionalAccess', _9 => _9.generation]), () => ( 0));
160
+ const transcribe = _nullishCoalesce(_optionalChain([provider, 'optionalAccess', _18 => _18.transcribe]), () => ( null));
161
+ const scope = _nullishCoalesce(_optionalChain([provider, 'optionalAccess', _19 => _19.scope]), () => ( null));
162
+ const scopeGeneration = _nullishCoalesce(_optionalChain([provider, 'optionalAccess', _20 => _20.generation]), () => ( 0));
70
163
  const [snapshot, setSnapshot] = _react.useState.call(void 0, EMPTY);
71
164
  const [supported, setSupported] = _react.useState.call(void 0, false);
72
165
  const current = _react.useRef.call(void 0, null);
@@ -76,7 +169,7 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
76
169
  activeScope.current = scope;
77
170
  callback.current = onTranscript;
78
171
  _react.useEffect.call(void 0, () => {
79
- setSupported(transcribe ? typeof navigator !== "undefined" && !!_optionalChain([navigator, 'access', _10 => _10.mediaDevices, 'optionalAccess', _11 => _11.getUserMedia]) && typeof MediaRecorder !== "undefined" : typeof recognitionConstructor() === "function");
172
+ setSupported(transcribe ? typeof navigator !== "undefined" && !!_optionalChain([navigator, 'access', _21 => _21.mediaDevices, 'optionalAccess', _22 => _22.getUserMedia]) && typeof MediaRecorder !== "undefined" : typeof recognitionConstructor() === "function");
80
173
  }, [transcribe]);
81
174
  const cancel = _react.useCallback.call(void 0, () => {
82
175
  const session = current.current;
@@ -97,9 +190,9 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
97
190
  if (session) dispose(session);
98
191
  };
99
192
  }, []);
100
- const isCurrent = _react.useCallback.call(void 0, (session) => mounted.current && current.current === session && session.scope === activeScope.current && session.scopeGeneration === (_nullishCoalesce(_optionalChain([session, 'access', _12 => _12.scope, 'optionalAccess', _13 => _13.current, 'access', _14 => _14.generation]), () => ( 0))) && !session.controller.signal.aborted, []);
193
+ const isCurrent = _react.useCallback.call(void 0, (session) => mounted.current && current.current === session && session.scope === activeScope.current && session.scopeGeneration === (_nullishCoalesce(_optionalChain([session, 'access', _23 => _23.scope, 'optionalAccess', _24 => _24.current, 'access', _25 => _25.generation]), () => ( 0))) && !session.controller.signal.aborted, []);
101
194
  const start = _react.useCallback.call(void 0, async () => {
102
- if (scope !== activeScope.current || scopeGeneration !== (_nullishCoalesce(_optionalChain([scope, 'optionalAccess', _15 => _15.current, 'access', _16 => _16.generation]), () => ( 0)))) return;
195
+ if (scope !== activeScope.current || scopeGeneration !== (_nullishCoalesce(_optionalChain([scope, 'optionalAccess', _26 => _26.current, 'access', _27 => _27.generation]), () => ( 0)))) return;
103
196
  if (current.current && isCurrent(current.current) && ["requesting", "recording", "transcribing"].includes(current.current.phase)) return;
104
197
  cancel();
105
198
  let resolveCapture;
@@ -123,20 +216,21 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
123
216
  nativeEnded: false,
124
217
  transcript: "",
125
218
  interim: "",
126
- notified: /* @__PURE__ */ new Set()
219
+ notified: /* @__PURE__ */ new Set(),
220
+ audioLevels: transcribe ? createAudioLevels() : void 0
127
221
  };
128
222
  current.current = session;
129
223
  setSnapshot({ ...EMPTY, state: "requesting" });
130
224
  if (transcribe) {
131
225
  try {
132
- if (!_optionalChain([navigator, 'access', _17 => _17.mediaDevices, 'optionalAccess', _18 => _18.getUserMedia]) || typeof MediaRecorder === "undefined") throw new Error("unsupported");
226
+ if (!_optionalChain([navigator, 'access', _28 => _28.mediaDevices, 'optionalAccess', _29 => _29.getUserMedia]) || typeof MediaRecorder === "undefined") throw new Error("unsupported");
133
227
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
134
228
  if (!isCurrent(session)) {
135
229
  stream.getTracks().forEach((track) => track.stop());
136
230
  return;
137
231
  }
138
232
  session.stream = stream;
139
- const mimeType = MIME_TYPES.find((mime) => _optionalChain([MediaRecorder, 'access', _19 => _19.isTypeSupported, 'optionalCall', _20 => _20(mime)]));
233
+ const mimeType = MIME_TYPES.find((mime) => _optionalChain([MediaRecorder, 'access', _30 => _30.isTypeSupported, 'optionalCall', _31 => _31(mime)]));
140
234
  const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
141
235
  session.recorder = recorder;
142
236
  recorder.ondataavailable = (event) => {
@@ -148,7 +242,7 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
148
242
  session.resolveCapture(null);
149
243
  return;
150
244
  }
151
- const type = recorder.mimeType || _optionalChain([session, 'access', _21 => _21.chunks, 'access', _22 => _22[0], 'optionalAccess', _23 => _23.type]) || mimeType || "audio/webm";
245
+ const type = recorder.mimeType || _optionalChain([session, 'access', _32 => _32.chunks, 'access', _33 => _33[0], 'optionalAccess', _34 => _34.type]) || mimeType || "audio/webm";
152
246
  const blob = new Blob(session.chunks, { type });
153
247
  session.blob = blob;
154
248
  session.chunks = [];
@@ -163,6 +257,7 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
163
257
  };
164
258
  recorder.start();
165
259
  session.phase = "recording";
260
+ session.stopMeter = meterStream(stream, session.audioLevels, () => isCurrent(session) && session.phase === "recording");
166
261
  setSnapshot({ ...EMPTY, state: "recording" });
167
262
  } catch (error) {
168
263
  releaseTracks(session);
@@ -200,7 +295,7 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
200
295
  session.transcript = final.join(" ");
201
296
  session.interim = interim.join(" ");
202
297
  setSnapshot((previous) => ({ ...previous, transcript: session.transcript, interimTranscript: session.interim }));
203
- if (chunks.length) _optionalChain([callback, 'access', _24 => _24.current, 'optionalCall', _25 => _25(chunks.join(" "))]);
298
+ if (chunks.length) _optionalChain([callback, 'access', _35 => _35.current, 'optionalCall', _36 => _36(chunks.join(" "))]);
204
299
  };
205
300
  recognition.onend = () => {
206
301
  session.nativeEnded = true;
@@ -228,20 +323,21 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
228
323
  }, [cancel, continuous, isCurrent, lang, scope, scopeGeneration, transcribe]);
229
324
  const finish = _react.useCallback.call(void 0, async (session) => {
230
325
  if (!isCurrent(session)) return null;
326
+ releaseMeter(session);
231
327
  session.phase = "transcribing";
232
328
  setSnapshot((previous) => ({ ...previous, state: "transcribing", error: null, canRetry: false }));
233
329
  if (!session.transcribe) {
234
330
  if (!session.nativeEnded) {
235
331
  session.nativeTimer = setTimeout(() => {
236
332
  try {
237
- _optionalChain([session, 'access', _26 => _26.recognition, 'optionalAccess', _27 => _27.abort, 'call', _28 => _28()]);
238
- } catch (e3) {
333
+ _optionalChain([session, 'access', _37 => _37.recognition, 'optionalAccess', _38 => _38.abort, 'call', _39 => _39()]);
334
+ } catch (e8) {
239
335
  }
240
336
  session.resolveNativeEnd();
241
337
  }, 1e3);
242
338
  try {
243
- _optionalChain([session, 'access', _29 => _29.recognition, 'optionalAccess', _30 => _30.stop, 'call', _31 => _31()]);
244
- } catch (e4) {
339
+ _optionalChain([session, 'access', _40 => _40.recognition, 'optionalAccess', _41 => _41.stop, 'call', _42 => _42()]);
340
+ } catch (e9) {
245
341
  session.resolveNativeEnd();
246
342
  }
247
343
  await session.nativeEnd;
@@ -256,7 +352,7 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
256
352
  let text;
257
353
  try {
258
354
  if (!session.blob) {
259
- if (_optionalChain([session, 'access', _32 => _32.recorder, 'optionalAccess', _33 => _33.state]) !== "inactive") _optionalChain([session, 'access', _34 => _34.recorder, 'optionalAccess', _35 => _35.stop, 'call', _36 => _36()]);
355
+ if (_optionalChain([session, 'access', _43 => _43.recorder, 'optionalAccess', _44 => _44.state]) !== "inactive") _optionalChain([session, 'access', _45 => _45.recorder, 'optionalAccess', _46 => _46.stop, 'call', _47 => _47()]);
260
356
  const blob = await session.capture;
261
357
  if (!isCurrent(session) || !blob) return null;
262
358
  session.blob = blob;
@@ -270,13 +366,13 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
270
366
  releaseTracks(session);
271
367
  session.phase = "error";
272
368
  const message = error instanceof Error && error.message ? error.message : "Transcription failed. Try again.";
273
- setSnapshot({ ...EMPTY, state: "error", error: message, canRetry: !!_optionalChain([session, 'access', _37 => _37.blob, 'optionalAccess', _38 => _38.size]) });
369
+ setSnapshot({ ...EMPTY, state: "error", error: message, canRetry: !!_optionalChain([session, 'access', _48 => _48.blob, 'optionalAccess', _49 => _49.size]) });
274
370
  return null;
275
371
  }
276
372
  session.transcript = text;
277
373
  session.phase = "ready";
278
374
  setSnapshot({ ...EMPTY, state: "ready", transcript: text });
279
- _optionalChain([callback, 'access', _39 => _39.current, 'optionalCall', _40 => _40(text)]);
375
+ _optionalChain([callback, 'access', _50 => _50.current, 'optionalCall', _51 => _51(text)]);
280
376
  return text;
281
377
  }, [isCurrent]);
282
378
  const stop = _react.useCallback.call(void 0, () => {
@@ -301,13 +397,13 @@ function useDictation({ lang = "en-US", continuous = true, onTranscript } = {})
301
397
  cancel();
302
398
  return Promise.resolve(null);
303
399
  }
304
- if (!_optionalChain([session, 'optionalAccess', _41 => _41.transcribe]) || !_optionalChain([session, 'access', _42 => _42.blob, 'optionalAccess', _43 => _43.size])) return Promise.resolve(null);
400
+ if (!_optionalChain([session, 'optionalAccess', _52 => _52.transcribe]) || !_optionalChain([session, 'access', _53 => _53.blob, 'optionalAccess', _54 => _54.size])) return Promise.resolve(null);
305
401
  if (session.phase !== "error") return _nullishCoalesce(session.finish, () => ( Promise.resolve(null)));
306
402
  session.finish = finish(session);
307
403
  return session.finish;
308
404
  }, [cancel, finish, isCurrent]);
309
405
  const visibleSnapshot = current.current && !isCurrent(current.current) ? EMPTY : snapshot;
310
- return { ...visibleSnapshot, supported, start, stop, retry, cancel };
406
+ return { ...visibleSnapshot, audioLevels: current.current && isCurrent(current.current) ? current.current.audioLevels : void 0, supported, start, stop, retry, cancel };
311
407
  }
312
408
 
313
409
 
@@ -3,8 +3,8 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkO6F3LVZYcjs = require('../chunk-O6F3LVZY.cjs');
6
+ var _chunkZZ7ICQR2cjs = require('../chunk-ZZ7ICQR2.cjs');
7
7
 
8
8
 
9
9
 
10
- exports.DictationProvider = _chunkO6F3LVZYcjs.DictationProvider; exports.useDictation = _chunkO6F3LVZYcjs.useDictation;
10
+ exports.DictationProvider = _chunkZZ7ICQR2cjs.DictationProvider; exports.useDictation = _chunkZZ7ICQR2cjs.useDictation;
@@ -43,6 +43,11 @@ interface DictationCapture {
43
43
  interimTranscript: string;
44
44
  error: string | null;
45
45
  canRetry: boolean;
46
+ /** Live bands from the recording stream. Native speech recognition exposes no audio meter. */
47
+ audioLevels?: {
48
+ subscribe: (listener: () => void) => () => void;
49
+ getSnapshot: () => number[];
50
+ };
46
51
  start: () => Promise<void>;
47
52
  /** Returns null on cancellation/failure; concurrent stops share one transcription. */
48
53
  stop: () => Promise<string | null>;
@@ -43,6 +43,11 @@ interface DictationCapture {
43
43
  interimTranscript: string;
44
44
  error: string | null;
45
45
  canRetry: boolean;
46
+ /** Live bands from the recording stream. Native speech recognition exposes no audio meter. */
47
+ audioLevels?: {
48
+ subscribe: (listener: () => void) => () => void;
49
+ getSnapshot: () => number[];
50
+ };
46
51
  start: () => Promise<void>;
47
52
  /** Returns null on cancellation/failure; concurrent stops share one transcription. */
48
53
  stop: () => Promise<string | null>;
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  DictationProvider,
5
5
  useDictation
6
- } from "../chunk-M2ZNC3TK.js";
6
+ } from "../chunk-HLAHOVEI.js";
7
7
  export {
8
8
  DictationProvider,
9
9
  useDictation
@@ -5,7 +5,7 @@
5
5
 
6
6
 
7
7
 
8
- var _chunkXB2D4NQKcjs = require('../chunk-XB2D4NQK.cjs');
8
+ var _chunkNKWHDI4Ccjs = require('../chunk-NKWHDI4C.cjs');
9
9
  require('../chunk-KWLSBTB2.cjs');
10
10
  require('../chunk-2BSFYU22.cjs');
11
11
 
@@ -13,4 +13,4 @@ require('../chunk-2BSFYU22.cjs');
13
13
 
14
14
 
15
15
 
16
- exports.AgentAudioVisualizerBar = _chunkXB2D4NQKcjs.AgentAudioVisualizerBar; exports.AgentAudioVisualizerBarElementVariants = _chunkXB2D4NQKcjs.AgentAudioVisualizerBarElementVariants; exports.AgentAudioVisualizerBarVariants = _chunkXB2D4NQKcjs.AgentAudioVisualizerBarVariants; exports.normalizeVolumeBands = _chunkXB2D4NQKcjs.normalizeVolumeBands;
16
+ exports.AgentAudioVisualizerBar = _chunkNKWHDI4Ccjs.AgentAudioVisualizerBar; exports.AgentAudioVisualizerBarElementVariants = _chunkNKWHDI4Ccjs.AgentAudioVisualizerBarElementVariants; exports.AgentAudioVisualizerBarVariants = _chunkNKWHDI4Ccjs.AgentAudioVisualizerBarVariants; exports.normalizeVolumeBands = _chunkNKWHDI4Ccjs.normalizeVolumeBands;
@@ -57,7 +57,7 @@ interface AgentAudioVisualizerBarProps {
57
57
  /**
58
58
  * A bar-style audio visualizer that responds to agent state and audio levels.
59
59
  * Displays animated bars that react to the current agent state (connecting, thinking, speaking, etc.)
60
- * and audio volume when speaking.
60
+ * and audio volume when speaking or listening with supplied microphone bands.
61
61
  *
62
62
  * @extends ComponentProps<'div'>
63
63
  *
@@ -57,7 +57,7 @@ interface AgentAudioVisualizerBarProps {
57
57
  /**
58
58
  * A bar-style audio visualizer that responds to agent state and audio levels.
59
59
  * Displays animated bars that react to the current agent state (connecting, thinking, speaking, etc.)
60
- * and audio volume when speaking.
60
+ * and audio volume when speaking or listening with supplied microphone bands.
61
61
  *
62
62
  * @extends ComponentProps<'div'>
63
63
  *
@@ -5,7 +5,7 @@ import {
5
5
  AgentAudioVisualizerBarElementVariants,
6
6
  AgentAudioVisualizerBarVariants,
7
7
  normalizeVolumeBands
8
- } from "../chunk-VBKJXNEL.js";
8
+ } from "../chunk-5OF6D3GH.js";
9
9
  import "../chunk-G6SRSWXB.js";
10
10
  import "../chunk-GJ7S3L6R.js";
11
11
  export {
@@ -4,7 +4,7 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const alertVariants: (props?: ({
7
- variant?: "success" | "default" | "destructive" | "warning" | null | undefined;
7
+ variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface AlertProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof alertVariants> {
10
10
  marginBottom?: "none" | "md";
@@ -4,7 +4,7 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const alertVariants: (props?: ({
7
- variant?: "success" | "default" | "destructive" | "warning" | null | undefined;
7
+ variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface AlertProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof alertVariants> {
10
10
  marginBottom?: "none" | "md";
@@ -4,7 +4,7 @@ import { VariantProps } from 'class-variance-authority';
4
4
  import { ElementType } from 'react';
5
5
 
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "neutral" | "error" | "success" | "default" | "secondary" | "destructive" | "outline" | "warning" | "info" | null | undefined;
7
+ variant?: "default" | "secondary" | "destructive" | "outline" | "success" | "warning" | "error" | "info" | "neutral" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
10
10
  weight?: "normal" | "semibold" | "bold";
@@ -4,7 +4,7 @@ import { VariantProps } from 'class-variance-authority';
4
4
  import { ElementType } from 'react';
5
5
 
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "neutral" | "error" | "success" | "default" | "secondary" | "destructive" | "outline" | "warning" | "info" | null | undefined;
7
+ variant?: "default" | "secondary" | "destructive" | "outline" | "success" | "warning" | "error" | "info" | "neutral" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
10
10
  weight?: "normal" | "semibold" | "bold";
@@ -5,7 +5,7 @@ import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare function BubbleGroup({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
7
7
  declare const bubbleVariants: (props?: ({
8
- variant?: "default" | "muted" | "ghost" | "secondary" | "destructive" | "outline" | "tinted" | null | undefined;
8
+ variant?: "default" | "muted" | "secondary" | "destructive" | "outline" | "ghost" | "tinted" | null | undefined;
9
9
  } & class_variance_authority_types.ClassProp) | undefined) => string;
10
10
  declare function Bubble({ variant, align, className, ...props }: React.ComponentProps<"div"> & VariantProps<typeof bubbleVariants> & {
11
11
  align?: "start" | "end";
@@ -5,7 +5,7 @@ import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare function BubbleGroup({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
7
7
  declare const bubbleVariants: (props?: ({
8
- variant?: "default" | "muted" | "ghost" | "secondary" | "destructive" | "outline" | "tinted" | null | undefined;
8
+ variant?: "default" | "muted" | "secondary" | "destructive" | "outline" | "ghost" | "tinted" | null | undefined;
9
9
  } & class_variance_authority_types.ClassProp) | undefined) => string;
10
10
  declare function Bubble({ variant, align, className, ...props }: React.ComponentProps<"div"> & VariantProps<typeof bubbleVariants> & {
11
11
  align?: "start" | "end";
@@ -4,8 +4,8 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const buttonVariants: (props?: ({
7
- variant?: "link" | "default" | "ghost" | "secondary" | "destructive" | "outline" | "outline-muted" | "quiet" | "ghost-destructive" | "link-muted" | "inverted" | "status-error" | "status-warning" | "status-muted" | null | undefined;
8
- size?: "filter" | "status" | "toolbar" | "sm" | "lg" | "default" | "micro" | "tone" | "compact" | "hero" | "icon" | "icon-lg" | "icon-sm" | "icon-md" | "icon-xs" | "icon-compact" | "icon-micro" | "bare" | "voice-sm" | "voice" | "suggestion" | null | undefined;
7
+ variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "outline-muted" | "ghost" | "quiet" | "ghost-destructive" | "link-muted" | "inverted" | "status-error" | "status-warning" | "status-muted" | null | undefined;
8
+ size?: "filter" | "status" | "toolbar" | "sm" | "lg" | "default" | "micro" | "compact" | "hero" | "icon" | "icon-lg" | "icon-sm" | "icon-md" | "icon-xs" | "icon-compact" | "icon-micro" | "bare" | "voice-sm" | "voice" | "suggestion" | "tone" | null | undefined;
9
9
  width?: "auto" | "full" | "responsive" | null | undefined;
10
10
  align?: "center" | "start" | null | undefined;
11
11
  shrink?: boolean | null | undefined;
@@ -4,8 +4,8 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const buttonVariants: (props?: ({
7
- variant?: "link" | "default" | "ghost" | "secondary" | "destructive" | "outline" | "outline-muted" | "quiet" | "ghost-destructive" | "link-muted" | "inverted" | "status-error" | "status-warning" | "status-muted" | null | undefined;
8
- size?: "filter" | "status" | "toolbar" | "sm" | "lg" | "default" | "micro" | "tone" | "compact" | "hero" | "icon" | "icon-lg" | "icon-sm" | "icon-md" | "icon-xs" | "icon-compact" | "icon-micro" | "bare" | "voice-sm" | "voice" | "suggestion" | null | undefined;
7
+ variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "outline-muted" | "ghost" | "quiet" | "ghost-destructive" | "link-muted" | "inverted" | "status-error" | "status-warning" | "status-muted" | null | undefined;
8
+ size?: "filter" | "status" | "toolbar" | "sm" | "lg" | "default" | "micro" | "compact" | "hero" | "icon" | "icon-lg" | "icon-sm" | "icon-md" | "icon-xs" | "icon-compact" | "icon-micro" | "bare" | "voice-sm" | "voice" | "suggestion" | "tone" | null | undefined;
9
9
  width?: "auto" | "full" | "responsive" | null | undefined;
10
10
  align?: "center" | "start" | null | undefined;
11
11
  shrink?: boolean | null | undefined;
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
 
4
4
 
5
- var _chunkUW67GSZ4cjs = require('../chunk-UW67GSZ4.cjs');
5
+ var _chunkYMI3X2YLcjs = require('../chunk-YMI3X2YL.cjs');
6
6
 
7
7
 
8
8
 
@@ -10,7 +10,7 @@ var _chunkUW67GSZ4cjs = require('../chunk-UW67GSZ4.cjs');
10
10
  var _chunk2BTDBZYNcjs = require('../chunk-2BTDBZYN.cjs');
11
11
 
12
12
 
13
- var _chunkHTCW6AEHcjs = require('../chunk-HTCW6AEH.cjs');
13
+ var _chunkD47AMKT4cjs = require('../chunk-D47AMKT4.cjs');
14
14
 
15
15
 
16
16
 
@@ -75,7 +75,7 @@ var _chunkFYRQFEU4cjs = require('../chunk-FYRQFEU4.cjs');
75
75
 
76
76
  var _chunk2KFZQJH5cjs = require('../chunk-2KFZQJH5.cjs');
77
77
  require('../chunk-PQUSJEXL.cjs');
78
- require('../chunk-XB2D4NQK.cjs');
78
+ require('../chunk-NKWHDI4C.cjs');
79
79
 
80
80
 
81
81
  var _chunkJDEXZGIYcjs = require('../chunk-JDEXZGIY.cjs');
@@ -86,7 +86,7 @@ require('../chunk-2BSFYU22.cjs');
86
86
 
87
87
 
88
88
  var _chunk4LXN6GLZcjs = require('../chunk-4LXN6GLZ.cjs');
89
- require('../chunk-O6F3LVZY.cjs');
89
+ require('../chunk-ZZ7ICQR2.cjs');
90
90
 
91
91
 
92
92
  var _chunkR35FT53Gcjs = require('../chunk-R35FT53G.cjs');
@@ -465,7 +465,7 @@ function ChatInput({
465
465
  className
466
466
  ),
467
467
  children: [
468
- liveVoiceActive && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk7LDJAXRXcjs.InputGroupAddon, { align: "block-start", className: "w-full border-b border-border", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUW67GSZ4cjs.VoiceSessionControls, { ...voiceSession }) }),
468
+ liveVoiceActive && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk7LDJAXRXcjs.InputGroupAddon, { align: "block-start", className: "w-full cursor-default border-b border-border p-0 [.border-b]:pb-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYMI3X2YLcjs.VoiceSessionControls, { ...voiceSession }) }),
469
469
  attachments.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
470
470
  ChatAttachmentList,
471
471
  {
@@ -489,11 +489,10 @@ function ChatInput({
489
489
  },
490
490
  placeholder,
491
491
  rows: compact ? 1 : composerSize.rows,
492
- wrap: compact ? "off" : void 0,
493
492
  disabled: isDisabled,
494
493
  autoFocus,
495
494
  className: _chunkKWLSBTB2cjs.cn.call(void 0,
496
- compact ? "h-[44px] min-h-[44px] max-h-[44px] min-w-0 field-sizing-fixed overflow-hidden whitespace-nowrap text-ellipsis" : composerSize.minHeight,
495
+ compact ? "min-h-[44px] max-h-24 min-w-0" : composerSize.minHeight,
497
496
  // Grows with the text, then scrolls rather than pushing the thread away.
498
497
  "leading-relaxed disabled:opacity-70 placeholder:text-sm",
499
498
  !compact && "max-h-48",
@@ -504,14 +503,14 @@ function ChatInput({
504
503
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
505
504
  _chunk7LDJAXRXcjs.InputGroupAddon,
506
505
  {
507
- align: compact ? "inline-end" : "block-end",
506
+ align: "block-end",
508
507
  "data-slot": "chat-input-actions",
509
508
  onClick: (event) => {
510
509
  if (!event.currentTarget.contains(event.target)) return;
511
510
  if (!event.target.closest("button")) _optionalChain([ref, 'access', _3 => _3.current, 'optionalAccess', _4 => _4.focus, 'call', _5 => _5()]);
512
511
  },
513
512
  className: _chunkKWLSBTB2cjs.cn.call(void 0,
514
- compact ? "shrink-0 gap-0 p-1" : "gap-2",
513
+ compact ? "gap-1 px-2 pb-2 pt-0" : "gap-2",
515
514
  !compact && (spacious ? "px-5 pb-5 pt-1" : "border-t border-border px-3 py-2.5")
516
515
  ),
517
516
  children: [
@@ -539,9 +538,10 @@ function ChatInput({
539
538
  className: _chunkKWLSBTB2cjs.cn.call(void 0, "min-w-0 flex-1 truncate px-1 text-center text-xs font-normal text-muted-foreground sm:px-2 sm:text-sm", compact && "hidden"),
540
539
  children: helperText
541
540
  }
542
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: compact ? "hidden" : "flex-1" }),
541
+ ) : null,
542
+ (!helperText || compact) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1" }),
543
543
  voice && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
544
- _chunkHTCW6AEHcjs.VoiceDictationButton,
544
+ _chunkD47AMKT4cjs.VoiceDictationButton,
545
545
  {
546
546
  size: "icon",
547
547
  title: voiceTitle,
@@ -555,7 +555,7 @@ function ChatInput({
555
555
  )
556
556
  }
557
557
  ),
558
- voiceSession && !liveVoiceActive && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUW67GSZ4cjs.VoiceSessionControls, { ...voiceSession, disabled: voiceSession.disabled || isDisabled }),
558
+ voiceSession && !liveVoiceActive && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYMI3X2YLcjs.VoiceSessionControls, { ...voiceSession, disabled: voiceSession.disabled || isDisabled }),
559
559
  submitLabel ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
560
560
  _chunkJDEXZGIYcjs.Button,
561
561
  {
@@ -614,9 +614,9 @@ function VoiceHero({
614
614
  }) {
615
615
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-5 py-6", children: [
616
616
  voiceSession ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
617
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUW67GSZ4cjs.VoiceSessionControls, { ...voiceSession, size: "hero" }),
617
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYMI3X2YLcjs.VoiceSessionControls, { ...voiceSession, size: "hero" }),
618
618
  voice && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
619
- _chunkHTCW6AEHcjs.VoiceDictationButton,
619
+ _chunkD47AMKT4cjs.VoiceDictationButton,
620
620
  {
621
621
  size: "icon",
622
622
  title: voiceTitle,
@@ -626,7 +626,7 @@ function VoiceHero({
626
626
  }
627
627
  )
628
628
  ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
629
- _chunkHTCW6AEHcjs.VoiceDictationButton,
629
+ _chunkD47AMKT4cjs.VoiceDictationButton,
630
630
  {
631
631
  size: "lg",
632
632
  title: voiceTitle,
@@ -187,7 +187,7 @@ interface ChatInputProps {
187
187
  /** Visual density for the complete composer surface. */
188
188
  appearance?: "default" | "spacious";
189
189
  /**
190
- * Fold an empty, unfocused composer into one row. Focusing its textarea
190
+ * Fold an empty, unfocused composer into a short text row and control bar. Focusing its textarea
191
191
  * expands it; drafts and staged files always keep it expanded. Chat enables
192
192
  * this only for an active mobile conversation with `mobileCompactComposer`.
193
193
  */
@@ -326,7 +326,7 @@ interface ChatProps {
326
326
  composerAppearance?: ChatInputProps["appearance"];
327
327
  /**
328
328
  * On phones (below 768px), fold an active conversation's empty composer
329
- * into one row until its textarea is focused. Drafts and files stay
329
+ * into a short text row above its controls until the textarea is focused. Drafts and files stay
330
330
  * expanded. Desktop and the new-conversation composer are unchanged.
331
331
  */
332
332
  mobileCompactComposer?: boolean;
@@ -187,7 +187,7 @@ interface ChatInputProps {
187
187
  /** Visual density for the complete composer surface. */
188
188
  appearance?: "default" | "spacious";
189
189
  /**
190
- * Fold an empty, unfocused composer into one row. Focusing its textarea
190
+ * Fold an empty, unfocused composer into a short text row and control bar. Focusing its textarea
191
191
  * expands it; drafts and staged files always keep it expanded. Chat enables
192
192
  * this only for an active mobile conversation with `mobileCompactComposer`.
193
193
  */
@@ -326,7 +326,7 @@ interface ChatProps {
326
326
  composerAppearance?: ChatInputProps["appearance"];
327
327
  /**
328
328
  * On phones (below 768px), fold an active conversation's empty composer
329
- * into one row until its textarea is focused. Drafts and files stay
329
+ * into a short text row above its controls until the textarea is focused. Drafts and files stay
330
330
  * expanded. Desktop and the new-conversation composer are unchanged.
331
331
  */
332
332
  mobileCompactComposer?: boolean;