@burdenoff/fe-libs 2026.1014.4 → 2026.1015.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.
- package/dist/shared/assistant/avatar/avatarPreferences.d.ts +61 -14
- package/dist/shared/assistant/avatar/avatarPreferences.js +54 -21
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.d.ts +33 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.js +278 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.d.ts +5 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.js +25 -6
- package/dist/shared/assistant/avatar/live/avatarVoice.d.ts +43 -0
- package/dist/shared/assistant/avatar/live/avatarVoice.js +45 -0
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.d.ts +21 -1
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.js +74 -24
- package/dist/shared/assistant/avatar/live/liveAvatarController.d.ts +47 -8
- package/dist/shared/assistant/avatar/live/liveAvatarController.js +244 -161
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.d.ts +2 -2
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.js +11 -4
- package/dist/shared/assistant/avatar/useAvatarCopy.d.ts +52 -21
- package/dist/shared/assistant/avatar/useAvatarCopy.js +93 -48
- package/dist/shared/assistant/i18nManifest.d.ts +24 -2
- package/dist/shared/assistant/i18nManifest.js +24 -2
- package/dist/shared/assistant/index.d.ts +5 -0
- package/dist/shared/assistant/speech/hostedVoiceCatalogue.d.ts +19 -0
- package/dist/shared/assistant/speech/hostedVoiceCatalogue.js +25 -18
- package/dist/shared/assistant/ui/AIAssistantPanel.js +136 -103
- package/dist/shared/assistant/ui/AssistantAvatarTabs.d.ts +10 -0
- package/dist/shared/assistant/ui/AssistantAvatarTabs.js +48 -0
- package/dist/shared/assistant/ui/AssistantChatArea.js +1260 -1199
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +165 -5
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.js +141 -59
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.d.ts +13 -0
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.js +70 -0
- package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +18 -0
- package/dist/shared/assistant/ui/composer/AssistantComposer.js +121 -102
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.d.ts +9 -0
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.js +28 -14
- package/dist/shared/assistant/ui/panelOverlays.d.ts +24 -3
- package/dist/shared/assistant/ui/panelOverlays.js +11 -10
- package/dist/shared/assistant/ui/useVoiceSession.js +234 -233
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +6 -0
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +161 -149
- package/dist/shared/assistant/ui/voice/VoiceMiniController.js +7 -7
- package/dist/shared/assistant/ui/voice/VoiceStage.js +7 -7
- package/dist/shared/assistant/ui/voice/voiceStartGate.d.ts +57 -0
- package/dist/shared/assistant/ui/voice/voiceStartGate.js +9 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.d.ts +7 -1
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.js +2 -2
- package/dist/shared-assistant.js +259 -254
- package/package.json +1 -1
|
@@ -14,53 +14,72 @@ import { AssistantVoiceButton as ae, ListeningDot as oe } from "./AssistantVoice
|
|
|
14
14
|
import { AssistantVoiceSessionButton as se } from "../voice/AssistantVoiceSessionButton.js";
|
|
15
15
|
import { useAssistantAttachments as ce } from "../../useAssistantAttachments.js";
|
|
16
16
|
import { useCallback as s, useEffect as c, useLayoutEffect as le, useMemo as ue, useRef as l, useState as u } from "react";
|
|
17
|
-
import { ArrowUp as de, Loader2 as
|
|
18
|
-
import { jsx as
|
|
17
|
+
import { ArrowUp as de, Loader2 as fe } from "lucide-react";
|
|
18
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
19
19
|
//#region src/shared/assistant/ui/composer/AssistantComposer.tsx
|
|
20
|
-
var
|
|
21
|
-
let b = r(), { locale: x } = e(), S =
|
|
20
|
+
var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, readOnly: me = !1, placeholder: he, mode: ge, availableModes: g, attachmentCharsPerFile: _e, onModeChange: ve, auto: ye, onStartVoiceSession: be, onDraftStart: _, suspendDictation: v = !1, onVoiceStateChange: y }) => {
|
|
21
|
+
let b = r(), { locale: x } = e(), S = h || me, C = l(null), [w, T] = u(""), [E, D] = u(!1), [O, xe] = u(!1), k = l(!1), [A, j] = u(null), M = l(0), { attachments: N, isBusy: Se, preparingCount: Ce, sendBlocker: P, rejection: F, addFiles: I, remove: we, retry: Te, clear: L, clearRejection: Ee, canAddMore: De, commit: R, cancelCommit: z } = ce({ perFileChars: _e }), B = w.trim() !== "" || N.length > 0, V = l(!1);
|
|
22
22
|
c(() => {
|
|
23
|
-
|
|
24
|
-
}, [
|
|
25
|
-
let
|
|
23
|
+
B && !V.current ? (V.current = !0, _?.()) : B || (V.current = !1);
|
|
24
|
+
}, [B, _]);
|
|
25
|
+
let H = s((e) => {
|
|
26
26
|
T((t) => t ? `${t.replace(/\s+$/, "")} ${e}` : e);
|
|
27
27
|
}, []), U = i((e) => e.assistantLanguage), W = n({
|
|
28
|
-
onFinalize:
|
|
28
|
+
onFinalize: H,
|
|
29
29
|
language: ue(() => te(U, x), [U, x]).tag
|
|
30
|
-
}),
|
|
31
|
-
|
|
30
|
+
}), G = W.isActive, K = W.interim, q = W.stop;
|
|
31
|
+
c(() => {
|
|
32
|
+
!v || !G || (K.trim() !== "" && H(K.trim()), q());
|
|
33
|
+
}, [
|
|
34
|
+
v,
|
|
35
|
+
G,
|
|
36
|
+
K,
|
|
37
|
+
q,
|
|
38
|
+
H
|
|
39
|
+
]), c(() => {
|
|
40
|
+
y?.({
|
|
41
|
+
committing: O,
|
|
42
|
+
dictating: G
|
|
43
|
+
});
|
|
44
|
+
}, [
|
|
45
|
+
y,
|
|
46
|
+
O,
|
|
47
|
+
G
|
|
48
|
+
]);
|
|
49
|
+
let Oe = he ?? b("composer.placeholder", "Ask me anything…"), ke = w.trim(), J = a(N), Y = N.filter((e) => e.status === "error"), X = (ke.length > 0 || J.length > 0) && !S && !O && P === null, Ae = J.some((e) => !e.fileId && !e.inlineOnly), je = l(S);
|
|
50
|
+
je.current = S;
|
|
32
51
|
let Z = l(!0);
|
|
33
52
|
c(() => (Z.current = !0, () => {
|
|
34
53
|
Z.current = !1;
|
|
35
54
|
}), []), le(() => {
|
|
36
55
|
let e = C.current;
|
|
37
|
-
e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight,
|
|
56
|
+
e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, pe)}px`);
|
|
38
57
|
}, [w]);
|
|
39
58
|
let Q = s(async () => {
|
|
40
|
-
if (!
|
|
59
|
+
if (!X || k.current) return;
|
|
41
60
|
W.isActive && W.stop();
|
|
42
61
|
let e = w.trim();
|
|
43
|
-
if (
|
|
44
|
-
|
|
62
|
+
if (j(null), !Ae) {
|
|
63
|
+
m(e, J), T(""), L();
|
|
45
64
|
return;
|
|
46
65
|
}
|
|
47
66
|
let t = i.getState().activeConversationId;
|
|
48
|
-
|
|
67
|
+
k.current = !0, xe(!0);
|
|
49
68
|
try {
|
|
50
|
-
let n = await
|
|
69
|
+
let n = await R();
|
|
51
70
|
if (!Z.current) {
|
|
52
71
|
n.ok && await n.rollback();
|
|
53
72
|
return;
|
|
54
73
|
}
|
|
55
74
|
if (!n.ok) {
|
|
56
|
-
n.cancelled ||
|
|
75
|
+
n.cancelled || j({
|
|
57
76
|
kind: "failed",
|
|
58
77
|
failures: n.failures
|
|
59
78
|
});
|
|
60
79
|
return;
|
|
61
80
|
}
|
|
62
|
-
if (
|
|
63
|
-
await n.rollback(), Z.current &&
|
|
81
|
+
if (je.current) {
|
|
82
|
+
await n.rollback(), Z.current && j({
|
|
64
83
|
kind: "busy",
|
|
65
84
|
failures: []
|
|
66
85
|
});
|
|
@@ -68,52 +87,52 @@ var fe = 200, m = ({ writeAccessDenied: m = !1, onSend: h, disabled: g = !1, rea
|
|
|
68
87
|
}
|
|
69
88
|
let r = i.getState();
|
|
70
89
|
if (!(r.activeConversationId === t && (t === null || r.conversations.some((e) => e.id === t)))) {
|
|
71
|
-
await n.rollback(), Z.current &&
|
|
90
|
+
await n.rollback(), Z.current && j({
|
|
72
91
|
kind: "moved",
|
|
73
92
|
failures: []
|
|
74
93
|
});
|
|
75
94
|
return;
|
|
76
95
|
}
|
|
77
|
-
|
|
96
|
+
m(e, a(n.attachments)), n.handedOver(), T(""), L();
|
|
78
97
|
} finally {
|
|
79
|
-
|
|
98
|
+
k.current = !1, Z.current && xe(!1);
|
|
80
99
|
}
|
|
81
100
|
}, [
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
z,
|
|
85
|
-
h,
|
|
86
|
-
w,
|
|
87
|
-
K,
|
|
101
|
+
X,
|
|
102
|
+
Ae,
|
|
88
103
|
R,
|
|
104
|
+
m,
|
|
105
|
+
w,
|
|
106
|
+
J,
|
|
107
|
+
L,
|
|
89
108
|
W
|
|
90
|
-
]),
|
|
91
|
-
|
|
92
|
-
}, [
|
|
109
|
+
]), Me = s(() => {
|
|
110
|
+
z(), C.current?.focus();
|
|
111
|
+
}, [z]);
|
|
93
112
|
c(() => {
|
|
94
|
-
|
|
95
|
-
}, [
|
|
96
|
-
let
|
|
113
|
+
j(null);
|
|
114
|
+
}, [N.length]);
|
|
115
|
+
let Ne = (e) => {
|
|
97
116
|
if (e.kind === "busy") return b("attachments.saveBusy", "The assistant started another reply, so nothing was sent. Your message and files are still here.");
|
|
98
117
|
if (e.kind === "moved") return b("attachments.saveMoved", "You switched conversations while the files were being saved, so nothing was sent. Your message and files are still here.");
|
|
99
118
|
let { failures: t } = e;
|
|
100
119
|
if (t.some((e) => e.code === o.quotaExceeded || e.code === o.quotaNotProvisioned)) return `${b("attachments.quotaFull", "File storage is full or not set up for this workspace, so the attachments couldn't be saved. Nothing was sent.")} ${b("attachments.retrySend", "Press Send to try again, or remove the file.")}`;
|
|
101
|
-
let n = t[0], r =
|
|
120
|
+
let n = t[0], r = N.find((e) => e.id === n?.id)?.filename ?? "";
|
|
102
121
|
return `${t.length <= 1 ? b("attachments.saveFailedOne", "{{name}} couldn't be saved, so nothing was sent.", { name: r }) : b("attachments.saveFailedMany", "{{count}} attachments couldn't be saved, so nothing was sent.", { count: t.length })} ${b("attachments.retrySend", "Press Send to try again, or remove the file.")}`;
|
|
103
|
-
},
|
|
122
|
+
}, Pe = s((e) => {
|
|
104
123
|
e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Q());
|
|
105
|
-
}, [Q]),
|
|
124
|
+
}, [Q]), Fe = s((e) => {
|
|
106
125
|
let t = Array.from(e.clipboardData?.files ?? []);
|
|
107
|
-
t.length !== 0 && (e.preventDefault(),
|
|
108
|
-
}, [
|
|
109
|
-
Array.from(e.dataTransfer?.types ?? []).includes("Files") && (
|
|
110
|
-
}, []),
|
|
111
|
-
|
|
112
|
-
}, []),
|
|
126
|
+
t.length !== 0 && (e.preventDefault(), I(t));
|
|
127
|
+
}, [I]), Ie = s((e) => {
|
|
128
|
+
Array.from(e.dataTransfer?.types ?? []).includes("Files") && (M.current += 1, D(!0));
|
|
129
|
+
}, []), Le = s(() => {
|
|
130
|
+
M.current = Math.max(0, M.current - 1), M.current === 0 && D(!1);
|
|
131
|
+
}, []), Re = s((e) => {
|
|
113
132
|
Array.from(e.dataTransfer?.types ?? []).includes("Files") && e.preventDefault();
|
|
114
|
-
}, []),
|
|
115
|
-
e.preventDefault(),
|
|
116
|
-
}, [
|
|
133
|
+
}, []), ze = s((e) => {
|
|
134
|
+
e.preventDefault(), M.current = 0, D(!1), I(e.dataTransfer?.files ?? null);
|
|
135
|
+
}, [I]), Be = (e) => {
|
|
117
136
|
switch (e) {
|
|
118
137
|
case "too-many": return b("attachments.tooMany", "You can attach up to {{max}} files per message.", { max: 5 });
|
|
119
138
|
case "too-large": return b("attachments.tooLarge", "That file is larger than 10 MB.");
|
|
@@ -122,7 +141,7 @@ var fe = 200, m = ({ writeAccessDenied: m = !1, onSend: h, disabled: g = !1, rea
|
|
|
122
141
|
case "unsupported-image": return b("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.");
|
|
123
142
|
case "too-large-to-save": return b("attachments.tooLargeToSave", "That file is over 5 MB, so it can't be saved to Files, and no text could be read from it.");
|
|
124
143
|
}
|
|
125
|
-
},
|
|
144
|
+
}, $ = (() => {
|
|
126
145
|
switch (W.error) {
|
|
127
146
|
case "not-allowed": return b("voice.denied", "Microphone access is blocked. Allow it in your browser settings to dictate.");
|
|
128
147
|
case "audio-capture": return b("voice.noMic", "No microphone was found.");
|
|
@@ -132,136 +151,136 @@ var fe = 200, m = ({ writeAccessDenied: m = !1, onSend: h, disabled: g = !1, rea
|
|
|
132
151
|
default: return null;
|
|
133
152
|
}
|
|
134
153
|
})();
|
|
135
|
-
return /* @__PURE__ */
|
|
154
|
+
return /* @__PURE__ */ f("div", {
|
|
136
155
|
className: "flex-shrink-0 px-3 pb-3 pt-1.5",
|
|
137
156
|
children: [
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
-
onDragEnter:
|
|
140
|
-
onDragLeave:
|
|
141
|
-
onDragOver:
|
|
142
|
-
onDrop:
|
|
157
|
+
/* @__PURE__ */ f("div", {
|
|
158
|
+
onDragEnter: Ie,
|
|
159
|
+
onDragLeave: Le,
|
|
160
|
+
onDragOver: Re,
|
|
161
|
+
onDrop: ze,
|
|
143
162
|
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 ${E ? "border-action-primary-bg border-dashed bg-action-primary-bg/5" : "border-border-default bg-bg-sunken"}`,
|
|
144
163
|
"data-testid": "assistant-composer",
|
|
145
164
|
children: [
|
|
146
|
-
/* @__PURE__ */
|
|
147
|
-
attachments:
|
|
148
|
-
onRemove:
|
|
149
|
-
onRetry:
|
|
165
|
+
/* @__PURE__ */ d(re, {
|
|
166
|
+
attachments: N,
|
|
167
|
+
onRemove: we,
|
|
168
|
+
onRetry: Te,
|
|
150
169
|
disabled: S || O,
|
|
151
|
-
preparingCount:
|
|
170
|
+
preparingCount: Ce
|
|
152
171
|
}),
|
|
153
|
-
/* @__PURE__ */
|
|
172
|
+
/* @__PURE__ */ f("div", {
|
|
154
173
|
className: "flex items-end gap-2",
|
|
155
174
|
children: [
|
|
156
|
-
/* @__PURE__ */
|
|
157
|
-
onFiles:
|
|
158
|
-
canAddMore:
|
|
175
|
+
/* @__PURE__ */ d(ne, {
|
|
176
|
+
onFiles: I,
|
|
177
|
+
canAddMore: De,
|
|
159
178
|
disabled: S || O,
|
|
160
179
|
showLabel: !0
|
|
161
180
|
}),
|
|
162
|
-
/* @__PURE__ */
|
|
181
|
+
/* @__PURE__ */ d("textarea", {
|
|
163
182
|
ref: C,
|
|
164
183
|
value: w,
|
|
165
184
|
onChange: (e) => T(e.target.value),
|
|
166
|
-
onKeyDown:
|
|
167
|
-
onPaste:
|
|
185
|
+
onKeyDown: Pe,
|
|
186
|
+
onPaste: Fe,
|
|
168
187
|
disabled: S,
|
|
169
188
|
readOnly: O,
|
|
170
189
|
"aria-busy": O || void 0,
|
|
171
|
-
placeholder: E ? b("composer.dropHere", "Drop files to attach") :
|
|
190
|
+
placeholder: E ? b("composer.dropHere", "Drop files to attach") : Oe,
|
|
172
191
|
rows: 1,
|
|
173
192
|
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",
|
|
174
193
|
"aria-label": b("chatInput.ariaLabel", "Message input"),
|
|
175
194
|
"data-testid": "assistant-input"
|
|
176
195
|
}),
|
|
177
|
-
W.isSupported && /* @__PURE__ */
|
|
196
|
+
W.isSupported && /* @__PURE__ */ d(ae, {
|
|
178
197
|
isListening: W.isListening,
|
|
179
198
|
isStarting: W.isStarting,
|
|
180
199
|
onToggle: W.toggle,
|
|
181
200
|
disabled: S || O
|
|
182
201
|
}),
|
|
183
|
-
|
|
184
|
-
onStart:
|
|
202
|
+
be && ke.length === 0 && N.length === 0 && !W.isActive ? /* @__PURE__ */ d(se, {
|
|
203
|
+
onStart: be,
|
|
185
204
|
disabled: S || O
|
|
186
|
-
}) : /* @__PURE__ */
|
|
205
|
+
}) : /* @__PURE__ */ d("button", {
|
|
187
206
|
type: "button",
|
|
188
207
|
onClick: () => void Q(),
|
|
189
|
-
disabled: !
|
|
190
|
-
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 ${
|
|
208
|
+
disabled: !X,
|
|
209
|
+
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"}`,
|
|
191
210
|
"aria-label": b("chatInput.send", "Send message"),
|
|
192
211
|
"data-testid": "assistant-send",
|
|
193
|
-
children:
|
|
212
|
+
children: h || Se || O ? /* @__PURE__ */ d(fe, { className: "size-4 motion-safe:animate-spin" }) : /* @__PURE__ */ d(de, { className: "size-4" })
|
|
194
213
|
})
|
|
195
214
|
]
|
|
196
215
|
}),
|
|
197
|
-
|
|
216
|
+
g.length > 1 && /* @__PURE__ */ d("div", {
|
|
198
217
|
className: "mt-2 px-0.5",
|
|
199
|
-
children: /* @__PURE__ */
|
|
200
|
-
mode:
|
|
201
|
-
availableModes:
|
|
202
|
-
onModeChange:
|
|
218
|
+
children: /* @__PURE__ */ d(ie, {
|
|
219
|
+
mode: ge,
|
|
220
|
+
availableModes: g,
|
|
221
|
+
onModeChange: ve,
|
|
203
222
|
disabled: S || O,
|
|
204
|
-
auto:
|
|
223
|
+
auto: ye
|
|
205
224
|
})
|
|
206
225
|
})
|
|
207
226
|
]
|
|
208
227
|
}),
|
|
209
|
-
|
|
228
|
+
p ? /* @__PURE__ */ d("p", {
|
|
210
229
|
className: "mt-1.5 px-1 text-center text-[11px] text-status-warning",
|
|
211
230
|
"data-testid": "assistant-write-access-warning",
|
|
212
231
|
children: b("composer.writeAccessDenied", "Changes may not save — your role in this workspace does not currently allow edits. You can still plan and review an action.")
|
|
213
232
|
}) : null,
|
|
214
|
-
/* @__PURE__ */
|
|
233
|
+
/* @__PURE__ */ d("div", {
|
|
215
234
|
className: "mt-1.5 px-1 text-center text-[11px]",
|
|
216
235
|
"aria-live": "polite",
|
|
217
|
-
children: O ? /* @__PURE__ */
|
|
218
|
-
onDismiss:
|
|
219
|
-
children: /* @__PURE__ */
|
|
236
|
+
children: O ? /* @__PURE__ */ d(t, {
|
|
237
|
+
onDismiss: Me,
|
|
238
|
+
children: /* @__PURE__ */ f("p", {
|
|
220
239
|
className: "flex items-center justify-center gap-2 text-text-muted",
|
|
221
240
|
"data-testid": "assistant-commit-status",
|
|
222
241
|
children: [
|
|
223
|
-
/* @__PURE__ */
|
|
242
|
+
/* @__PURE__ */ d(fe, {
|
|
224
243
|
className: "size-3 motion-safe:animate-spin",
|
|
225
244
|
"aria-hidden": "true"
|
|
226
245
|
}),
|
|
227
|
-
/* @__PURE__ */
|
|
228
|
-
/* @__PURE__ */
|
|
246
|
+
/* @__PURE__ */ d("span", { children: b("attachments.saving", "Saving your attachments…") }),
|
|
247
|
+
/* @__PURE__ */ d("button", {
|
|
229
248
|
type: "button",
|
|
230
|
-
onClick:
|
|
249
|
+
onClick: Me,
|
|
231
250
|
className: "rounded text-text-primary underline underline-offset-2 hover:text-action-primary-bg focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
|
|
232
251
|
"data-testid": "assistant-commit-cancel",
|
|
233
252
|
children: b("attachments.cancelSaving", "Cancel")
|
|
234
253
|
})
|
|
235
254
|
]
|
|
236
255
|
})
|
|
237
|
-
}) :
|
|
256
|
+
}) : A ? /* @__PURE__ */ d("p", {
|
|
238
257
|
className: "text-status-error-text",
|
|
239
258
|
role: "alert",
|
|
240
259
|
"data-testid": "assistant-commit-failed",
|
|
241
|
-
children:
|
|
242
|
-
}) : W.isStarting && !W.isListening ? /* @__PURE__ */
|
|
260
|
+
children: Ne(A)
|
|
261
|
+
}) : W.isStarting && !W.isListening ? /* @__PURE__ */ d("p", {
|
|
243
262
|
className: "text-text-muted",
|
|
244
263
|
"data-testid": "assistant-voice-starting",
|
|
245
264
|
children: b("voice.starting", "Starting the microphone…")
|
|
246
|
-
}) : W.isListening ? /* @__PURE__ */
|
|
265
|
+
}) : W.isListening ? /* @__PURE__ */ f("p", {
|
|
247
266
|
className: "text-status-error-text",
|
|
248
267
|
"data-testid": "assistant-voice-status",
|
|
249
|
-
children: [/* @__PURE__ */
|
|
250
|
-
}) :
|
|
268
|
+
children: [/* @__PURE__ */ d(oe, {}), W.interim || b("voice.listening", "Listening… speak now, tap the square to stop")]
|
|
269
|
+
}) : $ ? /* @__PURE__ */ d("p", {
|
|
251
270
|
className: "text-status-error-text",
|
|
252
271
|
"data-testid": "assistant-voice-error",
|
|
253
|
-
children:
|
|
254
|
-
}) :
|
|
272
|
+
children: $
|
|
273
|
+
}) : F ? /* @__PURE__ */ d("button", {
|
|
255
274
|
type: "button",
|
|
256
|
-
onClick:
|
|
275
|
+
onClick: Ee,
|
|
257
276
|
className: "text-status-error-text underline-offset-2 hover:underline",
|
|
258
277
|
"data-testid": "assistant-attachment-rejection",
|
|
259
|
-
children:
|
|
260
|
-
}) :
|
|
278
|
+
children: Be(F)
|
|
279
|
+
}) : P === "failed" ? /* @__PURE__ */ d("p", {
|
|
261
280
|
className: "text-status-error-text",
|
|
262
281
|
"data-testid": "assistant-attachment-blocked",
|
|
263
|
-
children:
|
|
264
|
-
}) : /* @__PURE__ */
|
|
282
|
+
children: Y.length === 1 ? b("attachments.blockedOne", "{{name}} didn't upload. Retry or remove it before sending.", { name: Y[0].filename }) : b("attachments.blockedMany", "{{count}} attachments didn't upload. Retry or remove them before sending.", { count: Y.length })
|
|
283
|
+
}) : /* @__PURE__ */ d("p", {
|
|
265
284
|
className: "text-text-muted",
|
|
266
285
|
children: b("composer.hint", "Enter to send · Shift+Enter for newline · drag or paste files to attach")
|
|
267
286
|
})
|
|
@@ -270,4 +289,4 @@ var fe = 200, m = ({ writeAccessDenied: m = !1, onSend: h, disabled: g = !1, rea
|
|
|
270
289
|
});
|
|
271
290
|
};
|
|
272
291
|
//#endregion
|
|
273
|
-
export {
|
|
292
|
+
export { p as AssistantComposer };
|
|
@@ -12,5 +12,14 @@ import { FC } from 'react';
|
|
|
12
12
|
* name (WCAG 2.5.3) and it is reachable by keyboard and speech control. Renders
|
|
13
13
|
* nothing where this browser can neither capture nor recognise speech: a
|
|
14
14
|
* setting that cannot do anything is not offered.
|
|
15
|
+
*
|
|
16
|
+
* ★ BOFF-8822, the avatar pilot: while a live avatar is ON this is OFF and
|
|
17
|
+
* cannot be switched on (`useLiveAvatarHandsFreeGuard`), and it stays OFF after
|
|
18
|
+
* the avatar is turned off until the person turns it back on here. The checkbox
|
|
19
|
+
* is `aria-disabled` and described by the reason, which is shown under it.
|
|
20
|
+
* Never `disabled`: the More menu has no roving focus, so a disabled checkbox
|
|
21
|
+
* drops out of the Tab order and keyboard and screen-reader users would skip
|
|
22
|
+
* the control and the reason with it (the avatar toggle keeps its focus the
|
|
23
|
+
* same way). Without an avatar it is exactly what it was.
|
|
15
24
|
*/
|
|
16
25
|
export declare const AssistantHandsFreeInterruptToggle: FC;
|
|
@@ -2,33 +2,47 @@ import { isSpeechRecognitionSupported as e } from "../../voice/useVoiceInput.js"
|
|
|
2
2
|
import { useAssistantTr as t } from "../../i18n.js";
|
|
3
3
|
import { useAssistantStore as n } from "../../store.js";
|
|
4
4
|
import { isMicCaptureSupported as r } from "../../voice/handsfree/micCapture.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { useAvatarCopy as i } from "../../avatar/useAvatarCopy.js";
|
|
6
|
+
import { useLiveAvatarOn as a } from "../assistantLiveAvatarSeam.js";
|
|
7
|
+
import { useId as o } from "react";
|
|
8
|
+
import { Mic as s } from "lucide-react";
|
|
9
|
+
import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
7
10
|
//#region src/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.tsx
|
|
8
|
-
var
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
+
var d = () => {
|
|
12
|
+
let d = t(), f = i(), p = a(), m = o(), h = n((e) => e.handsFreeInterrupt), g = n((e) => e.setHandsFreeInterrupt);
|
|
13
|
+
if (!e() && !r()) return null;
|
|
14
|
+
let _ = /* @__PURE__ */ u("label", {
|
|
11
15
|
className: "flex items-center gap-2.5 px-3 py-2 text-xs text-text-primary focus-within:ring-2 focus-within:ring-inset focus-within:ring-border-strong",
|
|
12
|
-
title:
|
|
16
|
+
title: d("voice.handsFreeHint", "Let the assistant listen while it answers, so you can speak over it to correct it. Works best with headphones. You can always tap to interrupt."),
|
|
13
17
|
"data-testid": "assistant-hands-free-interrupt",
|
|
14
18
|
children: [
|
|
15
|
-
/* @__PURE__ */
|
|
19
|
+
/* @__PURE__ */ l(s, {
|
|
16
20
|
className: "size-3.5 flex-shrink-0 text-text-secondary",
|
|
17
21
|
"aria-hidden": "true"
|
|
18
22
|
}),
|
|
19
|
-
/* @__PURE__ */
|
|
23
|
+
/* @__PURE__ */ l("span", {
|
|
20
24
|
className: "flex-1",
|
|
21
|
-
children:
|
|
25
|
+
children: d("voice.handsFreeLabel", "Hands-free interrupt (beta)")
|
|
22
26
|
}),
|
|
23
|
-
/* @__PURE__ */
|
|
27
|
+
/* @__PURE__ */ l("input", {
|
|
24
28
|
type: "checkbox",
|
|
25
|
-
checked:
|
|
26
|
-
onChange: (e) =>
|
|
27
|
-
|
|
29
|
+
checked: h,
|
|
30
|
+
onChange: (e) => {
|
|
31
|
+
p || g(e.target.checked);
|
|
32
|
+
},
|
|
33
|
+
"aria-disabled": p ? "true" : void 0,
|
|
34
|
+
"aria-describedby": p ? m : void 0,
|
|
35
|
+
className: p ? "size-4 accent-current aria-disabled:cursor-default aria-disabled:opacity-60" : "size-4 accent-current",
|
|
28
36
|
"data-testid": "assistant-hands-free-interrupt-checkbox"
|
|
29
37
|
})
|
|
30
38
|
]
|
|
31
39
|
});
|
|
40
|
+
return p ? /* @__PURE__ */ u(c, { children: [_, /* @__PURE__ */ l("p", {
|
|
41
|
+
id: m,
|
|
42
|
+
className: "px-3 pb-2 text-[11px] text-text-muted",
|
|
43
|
+
"data-testid": "assistant-hands-free-interrupt-avatar",
|
|
44
|
+
children: f.handsFreeOff
|
|
45
|
+
})] }) : _;
|
|
32
46
|
};
|
|
33
47
|
//#endregion
|
|
34
|
-
export {
|
|
48
|
+
export { d as AssistantHandsFreeInterruptToggle };
|
|
@@ -33,6 +33,20 @@ export declare const NO_PANEL_OVERLAY: PanelOverlayState;
|
|
|
33
33
|
* other one swaps to it. There is deliberately no way to express "both".
|
|
34
34
|
*/
|
|
35
35
|
export declare function nextPanelOverlays(current: PanelOverlayState, toggled: "history" | "preview"): PanelOverlayState;
|
|
36
|
+
/**
|
|
37
|
+
* The overlay slot, plus the Avatar tab (BOFF-9341) where the panel offers it.
|
|
38
|
+
*
|
|
39
|
+
* ★★ The tab is NOT part of the slot. It is a view of the chat area drawn
|
|
40
|
+
* under History and the preview (`AssistantAvatarTab`, `z-[5]` below their
|
|
41
|
+
* `z-10`, the voice strip's `z-20` and the transcript drawer's `z-30`), so
|
|
42
|
+
* History can open OVER it and closing History shows it again. Escape backs
|
|
43
|
+
* out one layer at a time: the transcript drawer, the voice session, the tab,
|
|
44
|
+
* then the panel.
|
|
45
|
+
*/
|
|
46
|
+
export interface PanelLayerState extends PanelOverlayState {
|
|
47
|
+
/** The Avatar tab is the view on screen; absent where the panel offers none. */
|
|
48
|
+
readonly avatarOpen?: boolean;
|
|
49
|
+
}
|
|
36
50
|
/**
|
|
37
51
|
* What Escape should dismiss.
|
|
38
52
|
*
|
|
@@ -44,7 +58,7 @@ export declare function nextPanelOverlays(current: PanelOverlayState, toggled: "
|
|
|
44
58
|
* Escape is "back out of the thing I just opened"; here it destroyed a
|
|
45
59
|
* conversation instead.
|
|
46
60
|
*/
|
|
47
|
-
export declare function escapeDismisses(current:
|
|
61
|
+
export declare function escapeDismisses(current: PanelLayerState): "overlay" | "tab" | "panel";
|
|
48
62
|
/**
|
|
49
63
|
* Attribute marking the assistant panel's root element.
|
|
50
64
|
*
|
|
@@ -94,9 +108,16 @@ export declare const ASSISTANT_VOICE_SESSION_ATTR = "data-assistant-voice-sessio
|
|
|
94
108
|
* comes first. The panel backs out of it, as `escapeDismisses` says, and marks
|
|
95
109
|
* the key handled so the session does not also act on it.
|
|
96
110
|
*/
|
|
97
|
-
export declare function voiceSessionOwnsEscape(panel: Pick<Element, "hasAttribute" | "querySelector">): boolean;
|
|
111
|
+
export declare function voiceSessionOwnsEscape(panel: Pick<Element, "hasAttribute" | "querySelector"> & Partial<Pick<Element, "getAttribute">>): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* `data-assistant-overlay` while the Avatar tab is the view on screen and no
|
|
114
|
+
* overlay covers it (BOFF-9341): the panel then owns an Escape pressed with
|
|
115
|
+
* focus on `<body>` (a control in the tab that unmounted itself on click), so
|
|
116
|
+
* it selects Chat again instead of the host closing the whole assistant.
|
|
117
|
+
*/
|
|
118
|
+
export declare const AVATAR_TAB_OVERLAY = "avatar";
|
|
98
119
|
/** Which overlay is showing, as the attribute value — `null` when none is. */
|
|
99
|
-
export declare function activePanelOverlay(current:
|
|
120
|
+
export declare function activePanelOverlay(current: PanelLayerState): "history" | "preview" | typeof AVATAR_TAB_OVERLAY | null;
|
|
100
121
|
/**
|
|
101
122
|
* Is `active` the panel itself, or inside it?
|
|
102
123
|
*
|
|
@@ -10,24 +10,25 @@ function t(t, n) {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
function n(e) {
|
|
13
|
-
return e.historyOpen || e.previewOpen ? "overlay" : "panel";
|
|
13
|
+
return e.historyOpen || e.previewOpen ? "overlay" : e.avatarOpen === !0 ? "tab" : "panel";
|
|
14
14
|
}
|
|
15
15
|
var r = "data-assistant-panel", i = "data-assistant-overlay", a = "data-assistant-voice-session";
|
|
16
16
|
function o(e) {
|
|
17
|
-
return e.hasAttribute("data-assistant-overlay") ? !1 : e.querySelector(`[${a}]`) !== null;
|
|
17
|
+
return e.hasAttribute("data-assistant-overlay") && e.getAttribute?.("data-assistant-overlay") !== "avatar" ? !1 : e.querySelector(`[${a}]`) !== null;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
var s = "avatar";
|
|
20
|
+
function c(e) {
|
|
21
|
+
return e.historyOpen ? "history" : e.previewOpen ? "preview" : e.avatarOpen === !0 ? s : null;
|
|
21
22
|
}
|
|
22
|
-
function
|
|
23
|
+
function l(e, t) {
|
|
23
24
|
return !e || !t ? !1 : e === t || e.contains(t);
|
|
24
25
|
}
|
|
25
|
-
function
|
|
26
|
+
function u(e = document) {
|
|
26
27
|
let t = e.activeElement;
|
|
27
|
-
return Array.from(e.querySelectorAll(`[${r}]`)).some((n) =>
|
|
28
|
+
return Array.from(e.querySelectorAll(`[${r}]`)).some((n) => d(n, t, e.body));
|
|
28
29
|
}
|
|
29
|
-
function
|
|
30
|
-
return e ?
|
|
30
|
+
function d(e, t, n) {
|
|
31
|
+
return e ? l(e, t) ? !0 : (t === null || t === n) && e.hasAttribute("data-assistant-overlay") : !1;
|
|
31
32
|
}
|
|
32
33
|
//#endregion
|
|
33
|
-
export { i as ASSISTANT_OVERLAY_ATTR, r as ASSISTANT_PANEL_ATTR, a as ASSISTANT_VOICE_SESSION_ATTR, e as NO_PANEL_OVERLAY,
|
|
34
|
+
export { i as ASSISTANT_OVERLAY_ATTR, r as ASSISTANT_PANEL_ATTR, a as ASSISTANT_VOICE_SESSION_ATTR, s as AVATAR_TAB_OVERLAY, e as NO_PANEL_OVERLAY, c as activePanelOverlay, u as assistantPanelOwnsEscape, n as escapeDismisses, l as focusIsInsidePanel, t as nextPanelOverlays, d as panelOwnsEscape, o as voiceSessionOwnsEscape };
|