@burdenoff/fe-libs 2026.1002.2 → 2026.1003.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 (29) hide show
  1. package/dist/shared/assistant/ui/AssistantAvatar.d.ts +0 -21
  2. package/dist/shared/assistant/ui/AssistantAvatar.d.ts.map +1 -1
  3. package/dist/shared/assistant/ui/AssistantAvatar.js +13 -7
  4. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts +8 -0
  5. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
  6. package/dist/shared/assistant/ui/AssistantMessageItem.js +60 -58
  7. package/dist/shared/assistant/ui/composer/AssistantComposer.js +117 -117
  8. package/dist/shared/assistant/ui/composer/AssistantVoiceButton.d.ts +8 -0
  9. package/dist/shared/assistant/ui/composer/AssistantVoiceButton.d.ts.map +1 -1
  10. package/dist/shared/assistant/ui/composer/AssistantVoiceButton.js +21 -16
  11. package/dist/shared/assistant/ui/useVoiceSession.d.ts +1 -4
  12. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  13. package/dist/shared/assistant/ui/useVoiceSession.js +117 -114
  14. package/dist/shared/assistant/ui/voice/AssistantVoiceOrb.d.ts.map +1 -1
  15. package/dist/shared/assistant/ui/voice/AssistantVoiceOrb.js +16 -15
  16. package/dist/shared/assistant/ui/voice/VoiceCaption.d.ts.map +1 -1
  17. package/dist/shared/assistant/ui/voice/VoiceCaption.js +1 -1
  18. package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts.map +1 -1
  19. package/dist/shared/assistant/ui/voice/VoiceMiniController.js +35 -30
  20. package/dist/shared/assistant/ui/voice/VoiceStage.d.ts.map +1 -1
  21. package/dist/shared/assistant/ui/voice/VoiceStage.js +38 -37
  22. package/dist/shared/assistant/ui/voice/VoiceWaveform.d.ts +6 -0
  23. package/dist/shared/assistant/ui/voice/VoiceWaveform.d.ts.map +1 -1
  24. package/dist/shared/assistant/ui/voice/VoiceWaveform.js +40 -36
  25. package/dist/shared/assistant/voice/speechPlayback.d.ts +37 -19
  26. package/dist/shared/assistant/voice/speechPlayback.d.ts.map +1 -1
  27. package/dist/shared/assistant/voice/speechPlayback.js +11 -1
  28. package/dist/shared-assistant.js +124 -124
  29. package/package.json +1 -1
@@ -1,184 +1,184 @@
1
1
  import { useI18n as e } from "../../../providers/shell/I18nProvider.js";
2
2
  import { useVoiceInput as t } from "../../voice/useVoiceInput.js";
3
- import { useAssistantTr as ee } from "../../i18n.js";
4
- import { useAssistantStore as n } from "../../store.js";
5
- import { languageDisplayName as r } from "../../voice/speechVoices.js";
6
- import { resolveAssistantLanguage as i } from "../../voice/languages.js";
7
- import { getSendableAttachments as a } from "../../attachments.js";
8
- import { AssistantAttachmentButton as o } from "./AssistantAttachmentButton.js";
9
- import { AssistantAttachmentChips as s } from "./AssistantAttachmentChips.js";
10
- import { AssistantModeSelector as c } from "./AssistantModeSelector.js";
11
- import { AssistantVoiceButton as te } from "./AssistantVoiceButton.js";
12
- import { AssistantVoiceSessionButton as ne } from "../voice/AssistantVoiceSessionButton.js";
13
- import { useAssistantAttachments as re } from "../../useAssistantAttachments.js";
14
- import { useCallback as l, useEffect as ie, useLayoutEffect as u, useMemo as d, useRef as f, useState as p } from "react";
15
- import { ArrowUp as m, Loader2 as h } from "lucide-react";
16
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
3
+ import { useAssistantTr as n } from "../../i18n.js";
4
+ import { useAssistantStore as ee } from "../../store.js";
5
+ import { languageDisplayName as te } from "../../voice/speechVoices.js";
6
+ import { resolveAssistantLanguage as r } from "../../voice/languages.js";
7
+ import { getSendableAttachments as ne } from "../../attachments.js";
8
+ import { AssistantAttachmentButton as re } from "./AssistantAttachmentButton.js";
9
+ import { AssistantAttachmentChips as i } from "./AssistantAttachmentChips.js";
10
+ import { AssistantModeSelector as a } from "./AssistantModeSelector.js";
11
+ import { AssistantVoiceButton as o, ListeningDot as s } from "./AssistantVoiceButton.js";
12
+ import { AssistantVoiceSessionButton as c } from "../voice/AssistantVoiceSessionButton.js";
13
+ import { useAssistantAttachments as l } from "../../useAssistantAttachments.js";
14
+ import { useCallback as u, useEffect as d, useLayoutEffect as ie, useMemo as ae, useRef as f, useState as p } from "react";
15
+ import { ArrowUp as oe, Loader2 as se } from "lucide-react";
16
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
17
17
  //#region src/shared/assistant/ui/composer/AssistantComposer.tsx
18
- var v = 200, y = ({ writeAccessDenied: y = !1, onSend: b, disabled: x = !1, readOnly: ae = !1, placeholder: oe, mode: se, availableModes: S, attachmentCharsPerFile: ce, onModeChange: le, auto: ue, onStartVoiceSession: C, onDraftStart: w }) => {
19
- let T = ee(), { locale: E } = e(), D = x || ae, O = f(null), [k, A] = p(""), [j, M] = p(!1), N = f(0), { attachments: P, isBusy: F, preparingCount: I, sendBlocker: L, rejection: R, addFiles: z, remove: B, retry: V, clear: H, clearRejection: de, canAddMore: fe } = re({ perFileChars: ce }), U = k.trim() !== "" || P.length > 0, W = f(!1);
20
- ie(() => {
21
- U && !W.current ? (W.current = !0, w?.()) : U || (W.current = !1);
22
- }, [U, w]);
23
- let pe = l((e) => {
24
- A((t) => t ? `${t.replace(/\s+$/, "")} ${e}` : e);
25
- }, []), G = n((e) => e.assistantLanguage), K = t({
18
+ var g = 200, _ = ({ writeAccessDenied: _ = !1, onSend: v, disabled: y = !1, readOnly: b = !1, placeholder: ce, mode: le, availableModes: x, attachmentCharsPerFile: S, onModeChange: C, auto: ue, onStartVoiceSession: w, onDraftStart: T }) => {
19
+ let E = n(), { locale: D } = e(), O = y || b, k = f(null), [A, j] = p(""), [M, N] = p(!1), P = f(0), { attachments: F, isBusy: I, preparingCount: L, sendBlocker: R, rejection: z, addFiles: B, remove: V, retry: H, clear: U, clearRejection: de, canAddMore: fe } = l({ perFileChars: S }), W = A.trim() !== "" || F.length > 0, G = f(!1);
20
+ d(() => {
21
+ W && !G.current ? (G.current = !0, T?.()) : W || (G.current = !1);
22
+ }, [W, T]);
23
+ let pe = u((e) => {
24
+ j((t) => t ? `${t.replace(/\s+$/, "")} ${e}` : e);
25
+ }, []), K = ee((e) => e.assistantLanguage), q = t({
26
26
  onFinalize: pe,
27
- language: d(() => i(G, E), [G, E]).tag
28
- }), me = oe ?? T("composer.placeholder", "Ask me anything…"), q = k.trim(), J = a(P), Y = P.filter((e) => e.status === "error"), X = (q.length > 0 || J.length > 0) && !D && L === null;
29
- u(() => {
30
- let e = O.current;
31
- e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, v)}px`);
32
- }, [k]);
33
- let Z = l(() => {
34
- X && (K.isActive && K.stop(), b(k.trim(), J), A(""), H());
27
+ language: ae(() => r(K, D), [K, D]).tag
28
+ }), me = ce ?? E("composer.placeholder", "Ask me anything…"), J = A.trim(), Y = ne(F), X = F.filter((e) => e.status === "error"), Z = (J.length > 0 || Y.length > 0) && !O && R === null;
29
+ ie(() => {
30
+ let e = k.current;
31
+ e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, g)}px`);
32
+ }, [A]);
33
+ let Q = u(() => {
34
+ Z && (q.isActive && q.stop(), v(A.trim(), Y), j(""), U());
35
35
  }, [
36
- X,
37
- b,
38
- k,
39
- J,
40
- H,
41
- K
42
- ]), he = l((e) => {
43
- e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Z());
44
- }, [Z]), ge = l((e) => {
36
+ Z,
37
+ v,
38
+ A,
39
+ Y,
40
+ U,
41
+ q
42
+ ]), he = u((e) => {
43
+ e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Q());
44
+ }, [Q]), ge = u((e) => {
45
45
  let t = Array.from(e.clipboardData?.files ?? []);
46
- t.length !== 0 && (e.preventDefault(), z(t));
47
- }, [z]), _e = l((e) => {
48
- Array.from(e.dataTransfer?.types ?? []).includes("Files") && (N.current += 1, M(!0));
49
- }, []), Q = l(() => {
50
- N.current = Math.max(0, N.current - 1), N.current === 0 && M(!1);
51
- }, []), ve = l((e) => {
46
+ t.length !== 0 && (e.preventDefault(), B(t));
47
+ }, [B]), _e = u((e) => {
48
+ Array.from(e.dataTransfer?.types ?? []).includes("Files") && (P.current += 1, N(!0));
49
+ }, []), ve = u(() => {
50
+ P.current = Math.max(0, P.current - 1), P.current === 0 && N(!1);
51
+ }, []), ye = u((e) => {
52
52
  Array.from(e.dataTransfer?.types ?? []).includes("Files") && e.preventDefault();
53
- }, []), ye = l((e) => {
54
- e.preventDefault(), N.current = 0, M(!1), z(e.dataTransfer?.files ?? null);
55
- }, [z]), be = (e) => {
53
+ }, []), be = u((e) => {
54
+ e.preventDefault(), P.current = 0, N(!1), B(e.dataTransfer?.files ?? null);
55
+ }, [B]), xe = (e) => {
56
56
  switch (e) {
57
- case "too-many": return T("attachments.tooMany", "You can attach up to {{max}} files per message.", { max: 5 });
58
- case "too-large": return T("attachments.tooLarge", "That file is larger than 10 MB.");
59
- case "empty": return T("attachments.empty", "That file is empty.");
60
- case "unreadable": return T("attachments.unreadable", "That file could not be read.");
61
- case "unsupported-image": return T("attachments.unsupportedImage", "This device can't read that image format, so it can't be resized to send. Save it as JPEG and try again.");
57
+ case "too-many": return E("attachments.tooMany", "You can attach up to {{max}} files per message.", { max: 5 });
58
+ case "too-large": return E("attachments.tooLarge", "That file is larger than 10 MB.");
59
+ case "empty": return E("attachments.empty", "That file is empty.");
60
+ case "unreadable": return E("attachments.unreadable", "That file could not be read.");
61
+ case "unsupported-image": return E("attachments.unsupportedImage", "This device can't read that image format, so it can't be resized to send. Save it as JPEG and try again.");
62
62
  }
63
63
  }, $ = (() => {
64
- switch (K.error) {
65
- case "not-allowed": return T("voice.denied", "Microphone access is blocked. Allow it in your browser settings to dictate.");
66
- case "audio-capture": return T("voice.noMic", "No microphone was found.");
67
- case "network": return T("voice.network", "Speech recognition is offline right now.");
68
- case "language-not-supported": return T("voice.languageNotSupported", "This browser cannot recognise spoken {{language}}. Try a different browser, or type instead.", { language: r(K.language, E) });
69
- case "unknown": return T("voice.failed", "Dictation stopped unexpectedly.");
64
+ switch (q.error) {
65
+ case "not-allowed": return E("voice.denied", "Microphone access is blocked. Allow it in your browser settings to dictate.");
66
+ case "audio-capture": return E("voice.noMic", "No microphone was found.");
67
+ case "network": return E("voice.network", "Speech recognition is offline right now.");
68
+ case "language-not-supported": return E("voice.languageNotSupported", "This browser cannot recognise spoken {{language}}. Try a different browser, or type instead.", { language: te(q.language, D) });
69
+ case "unknown": return E("voice.failed", "Dictation stopped unexpectedly.");
70
70
  default: return null;
71
71
  }
72
72
  })();
73
- return /* @__PURE__ */ _("div", {
73
+ return /* @__PURE__ */ h("div", {
74
74
  className: "flex-shrink-0 px-3 pb-3 pt-1.5",
75
75
  children: [
76
- /* @__PURE__ */ _("div", {
76
+ /* @__PURE__ */ h("div", {
77
77
  onDragEnter: _e,
78
- onDragLeave: Q,
79
- onDragOver: ve,
80
- onDrop: ye,
81
- className: `rounded-2xl border p-2 shadow-sm transition-colors focus-within:border-action-primary-bg focus-within:ring-2 focus-within:ring-action-primary-bg/15 ${j ? "border-action-primary-bg border-dashed bg-action-primary-bg/5" : "border-border-default bg-bg-sunken"}`,
78
+ onDragLeave: ve,
79
+ onDragOver: ye,
80
+ onDrop: be,
81
+ className: `rounded-2xl border p-2 shadow-sm transition-colors focus-within:border-action-primary-bg focus-within:ring-2 focus-within:ring-action-primary-bg/15 ${M ? "border-action-primary-bg border-dashed bg-action-primary-bg/5" : "border-border-default bg-bg-sunken"}`,
82
82
  "data-testid": "assistant-composer",
83
83
  children: [
84
- /* @__PURE__ */ g(s, {
85
- attachments: P,
86
- onRemove: B,
87
- onRetry: V,
88
- disabled: D,
89
- preparingCount: I
84
+ /* @__PURE__ */ m(i, {
85
+ attachments: F,
86
+ onRemove: V,
87
+ onRetry: H,
88
+ disabled: O,
89
+ preparingCount: L
90
90
  }),
91
- /* @__PURE__ */ _("div", {
91
+ /* @__PURE__ */ h("div", {
92
92
  className: "flex items-end gap-2",
93
93
  children: [
94
- /* @__PURE__ */ g(o, {
95
- onFiles: z,
94
+ /* @__PURE__ */ m(re, {
95
+ onFiles: B,
96
96
  canAddMore: fe,
97
- disabled: D,
97
+ disabled: O,
98
98
  showLabel: !0
99
99
  }),
100
- /* @__PURE__ */ g("textarea", {
101
- ref: O,
102
- value: k,
103
- onChange: (e) => A(e.target.value),
100
+ /* @__PURE__ */ m("textarea", {
101
+ ref: k,
102
+ value: A,
103
+ onChange: (e) => j(e.target.value),
104
104
  onKeyDown: he,
105
105
  onPaste: ge,
106
- disabled: D,
107
- placeholder: j ? T("composer.dropHere", "Drop files to attach") : me,
106
+ disabled: O,
107
+ placeholder: M ? E("composer.dropHere", "Drop files to attach") : me,
108
108
  rows: 1,
109
109
  className: "min-h-[36px] flex-1 resize-none self-center bg-transparent px-1 py-2 text-[15px] leading-relaxed text-text-primary placeholder:text-text-muted focus:outline-none disabled:opacity-50",
110
- "aria-label": T("chatInput.ariaLabel", "Message input"),
110
+ "aria-label": E("chatInput.ariaLabel", "Message input"),
111
111
  "data-testid": "assistant-input"
112
112
  }),
113
- K.isSupported && /* @__PURE__ */ g(te, {
114
- isListening: K.isListening,
115
- isStarting: K.isStarting,
116
- onToggle: K.toggle,
117
- disabled: D
113
+ q.isSupported && /* @__PURE__ */ m(o, {
114
+ isListening: q.isListening,
115
+ isStarting: q.isStarting,
116
+ onToggle: q.toggle,
117
+ disabled: O
118
118
  }),
119
- C && q.length === 0 && P.length === 0 && !K.isActive ? /* @__PURE__ */ g(ne, {
120
- onStart: C,
121
- disabled: D
122
- }) : /* @__PURE__ */ g("button", {
119
+ w && J.length === 0 && F.length === 0 && !q.isActive ? /* @__PURE__ */ m(c, {
120
+ onStart: w,
121
+ disabled: O
122
+ }) : /* @__PURE__ */ m("button", {
123
123
  type: "button",
124
- onClick: Z,
125
- disabled: !X,
126
- className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full shadow-sm transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${X ? "bg-action-primary-bg text-action-primary-text hover:scale-105 hover:bg-action-primary-bg-hover" : "bg-bg-elevated text-text-muted"}`,
127
- "aria-label": T("chatInput.send", "Send message"),
124
+ onClick: Q,
125
+ disabled: !Z,
126
+ className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full shadow-sm transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${Z ? "bg-action-primary-bg text-action-primary-text hover:scale-105 hover:bg-action-primary-bg-hover" : "bg-bg-elevated text-text-muted"}`,
127
+ "aria-label": E("chatInput.send", "Send message"),
128
128
  "data-testid": "assistant-send",
129
- children: x || F ? /* @__PURE__ */ g(h, { className: "size-4 motion-safe:animate-spin" }) : /* @__PURE__ */ g(m, { className: "size-4" })
129
+ children: y || I ? /* @__PURE__ */ m(se, { className: "size-4 motion-safe:animate-spin" }) : /* @__PURE__ */ m(oe, { className: "size-4" })
130
130
  })
131
131
  ]
132
132
  }),
133
- S.length > 1 && /* @__PURE__ */ g("div", {
133
+ x.length > 1 && /* @__PURE__ */ m("div", {
134
134
  className: "mt-2 px-0.5",
135
- children: /* @__PURE__ */ g(c, {
136
- mode: se,
137
- availableModes: S,
138
- onModeChange: le,
139
- disabled: D,
135
+ children: /* @__PURE__ */ m(a, {
136
+ mode: le,
137
+ availableModes: x,
138
+ onModeChange: C,
139
+ disabled: O,
140
140
  auto: ue
141
141
  })
142
142
  })
143
143
  ]
144
144
  }),
145
- y ? /* @__PURE__ */ g("p", {
145
+ _ ? /* @__PURE__ */ m("p", {
146
146
  className: "mt-1.5 px-1 text-center text-[11px] text-status-warning",
147
147
  "data-testid": "assistant-write-access-warning",
148
- children: T("composer.writeAccessDenied", "Changes may not save — your role in this workspace does not currently allow edits. You can still plan and review an action.")
148
+ children: E("composer.writeAccessDenied", "Changes may not save — your role in this workspace does not currently allow edits. You can still plan and review an action.")
149
149
  }) : null,
150
- /* @__PURE__ */ g("div", {
150
+ /* @__PURE__ */ m("div", {
151
151
  className: "mt-1.5 px-1 text-center text-[11px]",
152
152
  "aria-live": "polite",
153
- children: K.isStarting && !K.isListening ? /* @__PURE__ */ g("p", {
153
+ children: q.isStarting && !q.isListening ? /* @__PURE__ */ m("p", {
154
154
  className: "text-text-muted",
155
155
  "data-testid": "assistant-voice-starting",
156
- children: T("voice.starting", "Starting the microphone…")
157
- }) : K.isListening ? /* @__PURE__ */ _("p", {
156
+ children: E("voice.starting", "Starting the microphone…")
157
+ }) : q.isListening ? /* @__PURE__ */ h("p", {
158
158
  className: "text-status-error-text",
159
159
  "data-testid": "assistant-voice-status",
160
- children: [/* @__PURE__ */ g("span", { className: "mr-1 inline-block size-1.5 rounded-full bg-status-error-text align-middle motion-safe:animate-pulse" }), K.interim || T("voice.listening", "Listening… speak now, tap the square to stop")]
161
- }) : $ ? /* @__PURE__ */ g("p", {
160
+ children: [/* @__PURE__ */ m(s, {}), q.interim || E("voice.listening", "Listening… speak now, tap the square to stop")]
161
+ }) : $ ? /* @__PURE__ */ m("p", {
162
162
  className: "text-status-error-text",
163
163
  "data-testid": "assistant-voice-error",
164
164
  children: $
165
- }) : R ? /* @__PURE__ */ g("button", {
165
+ }) : z ? /* @__PURE__ */ m("button", {
166
166
  type: "button",
167
167
  onClick: de,
168
168
  className: "text-status-error-text underline-offset-2 hover:underline",
169
169
  "data-testid": "assistant-attachment-rejection",
170
- children: be(R)
171
- }) : L === "failed" ? /* @__PURE__ */ g("p", {
170
+ children: xe(z)
171
+ }) : R === "failed" ? /* @__PURE__ */ m("p", {
172
172
  className: "text-status-error-text",
173
173
  "data-testid": "assistant-attachment-blocked",
174
- children: Y.length === 1 ? T("attachments.blockedOne", "{{name}} didn't upload. Retry or remove it before sending.", { name: Y[0].filename }) : T("attachments.blockedMany", "{{count}} attachments didn't upload. Retry or remove them before sending.", { count: Y.length })
175
- }) : /* @__PURE__ */ g("p", {
174
+ children: X.length === 1 ? E("attachments.blockedOne", "{{name}} didn't upload. Retry or remove it before sending.", { name: X[0].filename }) : E("attachments.blockedMany", "{{count}} attachments didn't upload. Retry or remove them before sending.", { count: X.length })
175
+ }) : /* @__PURE__ */ m("p", {
176
176
  className: "text-text-muted",
177
- children: T("composer.hint", "Enter to send · Shift+Enter for newline · drag or paste files to attach")
177
+ children: E("composer.hint", "Enter to send · Shift+Enter for newline · drag or paste files to attach")
178
178
  })
179
179
  })
180
180
  ]
181
181
  });
182
182
  };
183
183
  //#endregion
184
- export { y as AssistantComposer };
184
+ export { _ as AssistantComposer };
@@ -6,6 +6,14 @@ interface Props {
6
6
  onToggle: () => void;
7
7
  disabled?: boolean;
8
8
  }
9
+ /**
10
+ * The red "live" dot beside the dictation status line.
11
+ *
12
+ * ★ Pulses only when neither reduced-motion signal is on (BOFF-8566):
13
+ * `motion-safe:` alone sees just the device preference, never the app's own
14
+ * Reduce motion setting.
15
+ */
16
+ export declare const ListeningDot: FC;
9
17
  /**
10
18
  * Microphone control in the composer — real speech-to-text (Workstream 2),
11
19
  * driven by `useVoiceInput`. While listening it becomes a stop button with a
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantVoiceButton.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantVoiceButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC,UAAU,KAAK;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CAmD1C,CAAC"}
1
+ {"version":3,"file":"AssistantVoiceButton.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantVoiceButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAKhC,UAAU,KAAK;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,EAY1B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CAgE1C,CAAC"}
@@ -1,24 +1,29 @@
1
1
  import { useAssistantTr as e } from "../../i18n.js";
2
- import { Mic as t, Square as n } from "lucide-react";
3
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
2
+ import { usePrefersReducedMotion as t } from "../usePrefersReducedMotion.js";
3
+ import { Mic as n, Square as r } from "lucide-react";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
5
  //#region src/shared/assistant/ui/composer/AssistantVoiceButton.tsx
5
- var a = ({ isListening: a, isStarting: o = !1, onToggle: s, disabled: c = !1 }) => {
6
- let l = e(), u = a ? l("composer.voiceStop", "Stop dictation") : o ? l("composer.voiceStarting", "Starting the microphone — tap to cancel") : l("composer.voiceStart", "Dictate a message");
7
- return /* @__PURE__ */ r("button", {
6
+ var o = () => /* @__PURE__ */ i("span", {
7
+ "aria-hidden": "true",
8
+ "data-testid": "assistant-listening-dot",
9
+ className: "mr-1 inline-block size-1.5 rounded-full bg-status-error-text align-middle" + (t() ? "" : " motion-safe:animate-pulse")
10
+ }), s = ({ isListening: o, isStarting: s = !1, onToggle: c, disabled: l = !1 }) => {
11
+ let u = e(), d = t(), f = o ? u("composer.voiceStop", "Stop dictation") : s ? u("composer.voiceStarting", "Starting the microphone — tap to cancel") : u("composer.voiceStart", "Dictate a message");
12
+ return /* @__PURE__ */ i("button", {
8
13
  type: "button",
9
- onClick: s,
10
- disabled: c,
11
- title: u,
12
- "aria-label": u,
13
- "aria-pressed": a || o,
14
- className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full border transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong disabled:cursor-not-allowed disabled:opacity-50 ${a ? "border-status-error-text/40 bg-status-error-bg/10 text-status-error-text" : o ? "border-border-strong bg-bg-elevated text-text-secondary" : "border-border-subtle bg-bg-elevated text-text-secondary hover:bg-bg-sunken hover:text-text-primary"}`,
14
+ onClick: c,
15
+ disabled: l,
16
+ title: f,
17
+ "aria-label": f,
18
+ "aria-pressed": o || s,
19
+ className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full border transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong disabled:cursor-not-allowed disabled:opacity-50 ${o ? "border-status-error-text/40 bg-status-error-bg/10 text-status-error-text" : s ? "border-border-strong bg-bg-elevated text-text-secondary" : "border-border-subtle bg-bg-elevated text-text-secondary hover:bg-bg-sunken hover:text-text-primary"}`,
15
20
  "data-testid": "assistant-voice",
16
- "data-state": a ? "listening" : o ? "starting" : "idle",
17
- children: o && !a ? /* @__PURE__ */ r(t, { className: "size-4 motion-safe:animate-pulse opacity-70" }) : a ? /* @__PURE__ */ i("span", {
21
+ "data-state": o ? "listening" : s ? "starting" : "idle",
22
+ children: s && !o ? /* @__PURE__ */ i(n, { className: "size-4 opacity-70" + (d ? "" : " motion-safe:animate-pulse") }) : o ? /* @__PURE__ */ a("span", {
18
23
  className: "relative flex items-center justify-center",
19
- children: [/* @__PURE__ */ r("span", { className: "absolute inline-flex size-7 rounded-full bg-status-error-bg/20 motion-safe:animate-ping" }), /* @__PURE__ */ r(n, { className: "relative size-3 fill-current" })]
20
- }) : /* @__PURE__ */ r(t, { className: "size-4" })
24
+ children: [/* @__PURE__ */ i("span", { className: "absolute inline-flex size-7 rounded-full bg-status-error-bg/20" + (d ? "" : " motion-safe:animate-ping") }), /* @__PURE__ */ i(r, { className: "relative size-3 fill-current" })]
25
+ }) : /* @__PURE__ */ i(n, { className: "size-4" })
21
26
  });
22
27
  };
23
28
  //#endregion
24
- export { a as AssistantVoiceButton };
29
+ export { s as AssistantVoiceButton, o as ListeningDot };
@@ -85,10 +85,7 @@ export declare function useVoiceSession({ onSubmit, latestReply, language }: Opt
85
85
  * component and a second speech consumer would be a second way for the two
86
86
  * to disagree about what is playing.
87
87
  */
88
- spokenChunks: {
89
- chunks: string[];
90
- index: number;
91
- } | null;
88
+ spokenChunks: import('..').CaptionChunks | null;
92
89
  /** Whether the microphone is genuinely capturing right now. */
93
90
  capturing: boolean;
94
91
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAgBL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAEvE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B;AAMD,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,MAAM,EAAE,eAAe,KACpB,IAAI,CAAC;IACV;;;;OAIG;IACH,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,OAAO;;IAouBtE,qEAAqE;;IAErE;;;;;;;OAOG;;;;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,sDAAsD;;;;uCAzDvC,MAAM;;;IAgErB,0EAA0E;qBArpB1C,iBAAiB;IAupBjD;;;OAGG;+BArqBuC,OAAO;IAuqBjD;;;OAGG;0BApoBE,iBAAiB;EAgqB3B"}
1
+ {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGpE,OAAO,EAgBL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAEvE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B;AAMD,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,MAAM,EAAE,eAAe,KACpB,IAAI,CAAC;IACV;;;;OAIG;IACH,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,OAAO;;IA+uBtE,qEAAqE;;IAErE;;;;;;;OAOG;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,sDAAsD;;;;uCApEvC,MAAM;;;IA2ErB,0EAA0E;qBAhqB1C,iBAAiB;IAkqBjD;;;OAGG;+BAhrBuC,OAAO;IAkrBjD;;;OAGG;0BA/oBE,iBAAiB;EA2qB3B"}