@burdenoff/fe-libs 2026.1014.4 → 2026.1014.5

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.
@@ -48,6 +48,8 @@ export interface AvatarCopy {
48
48
  voiceModePaired: string;
49
49
  voiceModeMine: string;
50
50
  voiceModeHint: string;
51
+ /** Why hands-free interrupt is off while the avatar is on (the pilot rule), and that it stays off after: the session's notice, and its control's reason. */
52
+ handsFreeOff: string;
51
53
  problem: (problem: AvatarProblem) => string;
52
54
  }
53
55
  export declare function useAvatarCopy(): AvatarCopy;
@@ -32,6 +32,7 @@ function n() {
32
32
  voiceModePaired: n("avatar.voiceModePaired", "Use this avatar's recommended voice"),
33
33
  voiceModeMine: n("avatar.voiceModeMine", "Keep my current voice"),
34
34
  voiceModeHint: n("avatar.voiceModeHint", "The recommended voice is chosen for this avatar and the language of each reply."),
35
+ handsFreeOff: n("avatar.handsFreeOff", "Hands-free interrupt is off, so the avatar's voice can't interrupt itself. It stays off after you turn the avatar off; turn it back on in More options. You can still tap to interrupt."),
35
36
  problem: (e) => {
36
37
  switch (e) {
37
38
  case "unavailable": return n("avatar.problemUnavailable", "The avatar isn’t available here.");
@@ -227,6 +227,7 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
227
227
  readonly "avatar.consent": "Turning on Avatar shares the assistant's reply audio with LiveKit and Protoface to animate the avatar. This feature does not send your microphone audio to Protoface.";
228
228
  readonly "avatar.consentCancel": "Not now";
229
229
  readonly "avatar.consentConfirm": "Turn on the avatar";
230
+ readonly "avatar.handsFreeOff": "Hands-free interrupt is off, so the avatar's voice can't interrupt itself. It stays off after you turn the avatar off; turn it back on in More options. You can still tap to interrupt.";
230
231
  readonly "avatar.problemAlreadyRunning": "An avatar is already running for you.";
231
232
  readonly "avatar.problemCapacity": "Avatars are busy right now. Try again in a moment.";
232
233
  readonly "avatar.problemConnection": "The connection to the avatar was lost.";
@@ -121,6 +121,7 @@ var m = {
121
121
  "avatar.consent": "Turning on Avatar shares the assistant's reply audio with LiveKit and Protoface to animate the avatar. This feature does not send your microphone audio to Protoface.",
122
122
  "avatar.consentCancel": "Not now",
123
123
  "avatar.consentConfirm": "Turn on the avatar",
124
+ "avatar.handsFreeOff": "Hands-free interrupt is off, so the avatar's voice can't interrupt itself. It stays off after you turn the avatar off; turn it back on in More options. You can still tap to interrupt.",
124
125
  "avatar.problemAlreadyRunning": "An avatar is already running for you.",
125
126
  "avatar.problemCapacity": "Avatars are busy right now. Try again in a moment.",
126
127
  "avatar.problemConnection": "The connection to the avatar was lost.",
@@ -4,14 +4,14 @@ import { useAssistantPageLabel as n } from "../product.js";
4
4
  import { useAssistantTr as r } from "../i18n.js";
5
5
  import { useAssistantStore as i } from "../store.js";
6
6
  import { AssistantSpeechProvider as a } from "./AssistantSpeechProvider.js";
7
- import { AssistantPreviewProvider as o } from "../preview/context.js";
8
- import { useAssistantPreviewBridge as s } from "../preview/useAssistantPreviewBridge.js";
9
- import { AssistantConnectSourceProvider as c } from "./composer/connectSource.js";
10
- import { hasAssistantPreviewSurface as l } from "../preview/types.js";
11
- import { ASSISTANT_OVERLAY_ATTR as u, ASSISTANT_PANEL_ATTR as d, activePanelOverlay as f, escapeDismisses as p, nextPanelOverlays as ee } from "./panelOverlays.js";
12
- import { panelOwnedPreviewBridge as te, useHostedAssistantPreviewBridge as ne } from "../preview/bridgeHostContext.js";
13
- import { AssistantPreviewOverlay as re } from "../preview/AssistantPreviewOverlay.js";
14
- import { LiveAvatarSeamProvider as ie, useLiveAvatarSpeechEngine as ae } from "./assistantLiveAvatarSeam.js";
7
+ import { ASSISTANT_OVERLAY_ATTR as o, ASSISTANT_PANEL_ATTR as s, activePanelOverlay as c, escapeDismisses as l, nextPanelOverlays as u } from "./panelOverlays.js";
8
+ import { LiveAvatarSeamProvider as d, useLiveAvatarSpeechEngine as f } from "./assistantLiveAvatarSeam.js";
9
+ import { AssistantPreviewProvider as p } from "../preview/context.js";
10
+ import { useAssistantPreviewBridge as ee } from "../preview/useAssistantPreviewBridge.js";
11
+ import { AssistantConnectSourceProvider as te } from "./composer/connectSource.js";
12
+ import { hasAssistantPreviewSurface as ne } from "../preview/types.js";
13
+ import { panelOwnedPreviewBridge as re, useHostedAssistantPreviewBridge as ie } from "../preview/bridgeHostContext.js";
14
+ import { AssistantPreviewOverlay as ae } from "../preview/AssistantPreviewOverlay.js";
15
15
  import { AssistantHeader as m } from "./AssistantHeader.js";
16
16
  import { AssistantConversationList as h } from "./AssistantConversationList.js";
17
17
  import { AssistantConversationDeleteDialogProvider as g } from "./conversationDeleteDialog.js";
@@ -26,19 +26,19 @@ import { useMemo as w, useRef as T, useState as E } from "react";
26
26
  import { jsx as D, jsxs as O } from "react/jsx-runtime";
27
27
  //#region src/shared/assistant/ui/AIAssistantPanel.tsx
28
28
  var k = ({ onClose: k, visible: A, docked: j, onToggleDock: M, writeAccess: N, onNavigate: oe, isShellLessTarget: P, connectSourceHref: F, onConnectSource: I, preview: L, liveAvatar: R, serverHistory: z = !1 }) => {
29
- let B = r(), V = ae(R);
29
+ let B = r(), V = f(R);
30
30
  y(z);
31
- let [H, U] = E(!1), W = l(L);
31
+ let [H, U] = E(!1), W = ne(L);
32
32
  H && !W && U(!1);
33
33
  let G = H && W;
34
- s(te(L, ne()));
34
+ ee(re(L, ie()));
35
35
  let K = T(null);
36
36
  e(K);
37
- let { conversations: q, activeConversationId: se, conversationListOpen: J, setConversationListOpen: Y, createConversation: ce } = i(), X = J || G, Z = f({
37
+ let { conversations: q, activeConversationId: se, conversationListOpen: J, setConversationListOpen: Y, createConversation: ce } = i(), X = J || G, Z = c({
38
38
  historyOpen: J,
39
39
  previewOpen: G
40
40
  }), Q = (e) => {
41
- let t = ee({
41
+ let t = u({
42
42
  historyOpen: J,
43
43
  previewOpen: G
44
44
  }, e);
@@ -59,7 +59,7 @@ var k = ({ onClose: k, visible: A, docked: j, onToggleDock: M, writeAccess: N, o
59
59
  return S({
60
60
  panelRef: K,
61
61
  onClose: () => {
62
- if (p({
62
+ if (l({
63
63
  historyOpen: J,
64
64
  previewOpen: G
65
65
  }) === "overlay") {
@@ -71,14 +71,14 @@ var k = ({ onClose: k, visible: A, docked: j, onToggleDock: M, writeAccess: N, o
71
71
  }), /* @__PURE__ */ D(a, {
72
72
  visible: A ?? !0,
73
73
  engine: V,
74
- children: /* @__PURE__ */ D(ie, {
74
+ children: /* @__PURE__ */ D(d, {
75
75
  value: R,
76
- children: /* @__PURE__ */ D(o, {
76
+ children: /* @__PURE__ */ D(p, {
77
77
  value: L,
78
78
  children: /* @__PURE__ */ D(v, {
79
79
  navigate: oe,
80
80
  isShellLessTarget: P,
81
- children: /* @__PURE__ */ D(c, {
81
+ children: /* @__PURE__ */ D(te, {
82
82
  value: F,
83
83
  onOpen: I,
84
84
  children: /* @__PURE__ */ D(g, { children: /* @__PURE__ */ D(_, { children: /* @__PURE__ */ O("div", {
@@ -87,8 +87,8 @@ var k = ({ onClose: k, visible: A, docked: j, onToggleDock: M, writeAccess: N, o
87
87
  role: "complementary",
88
88
  "aria-label": B("panel.ariaLabel", "AI Assistant"),
89
89
  "data-testid": "ai-assistant-panel",
90
- [d]: "",
91
- ...Z ? { [u]: Z } : {},
90
+ [s]: "",
91
+ ...Z ? { [o]: Z } : {},
92
92
  tabIndex: -1,
93
93
  children: [
94
94
  /* @__PURE__ */ D("div", {
@@ -107,7 +107,7 @@ var k = ({ onClose: k, visible: A, docked: j, onToggleDock: M, writeAccess: N, o
107
107
  })
108
108
  }),
109
109
  J && /* @__PURE__ */ D(h, {}),
110
- G && /* @__PURE__ */ D(re, { onClose: () => U(!1) }),
110
+ G && /* @__PURE__ */ D(ae, { onClose: () => U(!1) }),
111
111
  /* @__PURE__ */ D("div", {
112
112
  className: "contents",
113
113
  inert: X || void 0,
@@ -63,6 +63,34 @@ export declare function useLiveAvatarStage(): ComponentType<LiveAvatarStageProps
63
63
  * is to the store `AssistantSpeechProvider` already subscribes to.
64
64
  */
65
65
  export declare function useLiveAvatarSpeechEngine(seam: AssistantLiveAvatarSeam | undefined): SpeechEngine | undefined;
66
+ /**
67
+ * @internal Exported for the assistant's own hands-free wiring (`useVoiceSession`,
68
+ * `AssistantHandsFreeInterruptToggle`); not part of the module's public surface.
69
+ *
70
+ * Whether the live avatar is ON: never without a seam, so false in every app that passes no
71
+ * `liveAvatar`. Read from the ON switch with or without a stage: what it guards is the avatar's
72
+ * voice, not its picture.
73
+ */
74
+ export declare function useLiveAvatarOn(): boolean;
75
+ /**
76
+ * @internal Exported for `AssistantVoiceSession` alone; not part of the module's public surface.
77
+ *
78
+ * ★★ THE PILOT RULE (BOFF-8822), while the avatar's echo reference (P5) is not in: hands-free
79
+ * interrupt is OFF whenever the avatar is ON. The avatar's voice plays on the speakers, where the
80
+ * microphone hears it, and hands-free would take it for the person speaking over the reply: a
81
+ * barge-in that cuts the avatar off.
82
+ * - Switched ON with hands-free on: hands-free is switched OFF in the setting the person sees (and
83
+ * stored, so it stays off), and this returns true until the avatar is OFF again, for the voice
84
+ * session to say why.
85
+ * - While it is ON: a write that turns hands-free back on is turned back at once, its menu control
86
+ * is `aria-disabled` (it keeps its focus) and says why (`AssistantHandsFreeInterruptToggle`), and the voice session's own
87
+ * reading of the setting is OFF whatever it says (`resolveHandsFreeEnabled`).
88
+ * - Switched OFF: hands-free stays OFF. Nothing turns it back on behind the person's back, and the
89
+ * copy (`avatar.handsFreeOff`) says so and where to turn it back on (More options).
90
+ *
91
+ * Without a seam nothing here subscribes to, reads or writes anything.
92
+ */
93
+ export declare function useLiveAvatarHandsFreeGuard(): boolean;
66
94
  /**
67
95
  * The voice view to SHOW, given the one the user CHOSE; and the avatar kept to
68
96
  * the live conversation (`ended`: over, but still on screen to say why it
@@ -1,53 +1,76 @@
1
- import { getSpeechEngine as e, subscribeSpeechEngine as t } from "../speech/createSpeechEngine.js";
2
- import { useAvatarCopy as n } from "../avatar/useAvatarCopy.js";
3
- import { ASSISTANT_VOICE_SESSION_ATTR as r } from "./panelOverlays.js";
4
- import { createContext as i, useContext as a, useEffect as o, useLayoutEffect as s, useMemo as c, useRef as l, useState as u, useSyncExternalStore as d } from "react";
5
- import { VideoOff as f } from "lucide-react";
6
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
1
+ import { useAssistantStore as e } from "../store.js";
2
+ import { getSpeechEngine as t, subscribeSpeechEngine as n } from "../speech/createSpeechEngine.js";
3
+ import { useAvatarCopy as r } from "../avatar/useAvatarCopy.js";
4
+ import { ASSISTANT_VOICE_SESSION_ATTR as i } from "./panelOverlays.js";
5
+ import { createContext as a, useContext as o, useEffect as s, useLayoutEffect as c, useMemo as l, useRef as u, useState as d, useSyncExternalStore as f } from "react";
6
+ import { VideoOff as p } from "lucide-react";
7
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
7
8
  //#region src/shared/assistant/ui/assistantLiveAvatarSeam.tsx
8
- var h = i(null), g = ({ value: e, children: t }) => /* @__PURE__ */ p(h.Provider, {
9
+ var g = a(null), _ = ({ value: e, children: t }) => /* @__PURE__ */ m(g.Provider, {
9
10
  value: e ?? null,
10
11
  children: t
11
12
  });
12
- function _() {
13
- return a(h)?.Stage ?? null;
13
+ function v() {
14
+ return o(g)?.Stage ?? null;
14
15
  }
15
- function v(n) {
16
- let r = d(t, e, e), i = n?.decorateSpeechEngine;
17
- return c(() => i ? i(r) : void 0, [i, r]);
16
+ function y(e) {
17
+ let r = f(n, t, t), i = e?.decorateSpeechEngine;
18
+ return l(() => i ? i(r) : void 0, [i, r]);
18
19
  }
19
- var y = {
20
+ var b = {
20
21
  subscribe: () => () => {},
21
22
  getSnapshot: () => !1,
22
23
  switchOff: () => {},
23
24
  voiceLive: () => {}
24
25
  };
25
- function b(e) {
26
+ function x(e) {
26
27
  return e?.Stage ? e.enabled : void 0;
27
28
  }
28
- function x(e) {
29
- let t = e ?? y;
30
- return d(t.subscribe, t.getSnapshot, t.getSnapshot);
29
+ function S(e) {
30
+ let t = e ?? b;
31
+ return f(t.subscribe, t.getSnapshot, t.getSnapshot);
32
+ }
33
+ function C() {
34
+ return S(o(g)?.enabled);
31
35
  }
32
- function S(e, t) {
33
- let n = a(h);
34
- C(n?.enabled, t);
35
- let r = b(n), i = x(r), [o, s] = u(() => ({
36
+ function w() {
37
+ let t = o(g)?.enabled, [n, r] = d(null);
38
+ return s(() => {
39
+ if (!t) return;
40
+ let n = () => {
41
+ if (!t.getSnapshot()) {
42
+ r(null);
43
+ return;
44
+ }
45
+ let n = e.getState();
46
+ n.handsFreeInterrupt && (n.setHandsFreeInterrupt(!1), r(() => t));
47
+ };
48
+ n();
49
+ let i = t.subscribe(n), a = e.subscribe(n);
50
+ return () => {
51
+ i(), a();
52
+ };
53
+ }, [t]), n !== null && n === t;
54
+ }
55
+ function T(e, t) {
56
+ let n = o(g);
57
+ E(n?.enabled, t);
58
+ let r = x(n), i = S(r), [a, s] = d(() => ({
36
59
  on: i,
37
60
  chosen: e,
38
61
  open: i && e === "mini"
39
62
  }));
40
63
  if (!r) return e;
41
- let c = o.open;
42
- return (o.on !== i || o.chosen !== e) && (c = o.on !== i && i && e === "mini", s({
64
+ let c = a.open;
65
+ return (a.on !== i || a.chosen !== e) && (c = a.on !== i && i && e === "mini", s({
43
66
  on: i,
44
67
  chosen: e,
45
68
  open: c
46
69
  })), c && !t ? "panel" : e;
47
70
  }
48
- function C(e, t) {
49
- let n = l(0);
50
- o(() => {
71
+ function E(e, t) {
72
+ let n = u(0);
73
+ s(() => {
51
74
  if (!e) return;
52
75
  let r = ++n.current, i = (e) => queueMicrotask(() => {
53
76
  n.current === r && e();
@@ -63,38 +86,38 @@ function C(e, t) {
63
86
  });
64
87
  }, [e, t]);
65
88
  }
66
- function w() {
67
- return x(b(a(h)));
89
+ function D() {
90
+ return S(x(o(g)));
68
91
  }
69
- var T = () => {
70
- let e = b(a(h)), t = x(e);
71
- return e && t ? /* @__PURE__ */ p(O, {
92
+ var O = () => {
93
+ let e = x(o(g)), t = S(e);
94
+ return e && t ? /* @__PURE__ */ m(j, {
72
95
  onStop: e.switchOff,
73
96
  isOn: e.getSnapshot
74
97
  }) : null;
75
- }, E = "[data-testid=\"assistant-voice-orb\"]", D = "[data-testid=\"assistant-voice-end\"]", O = ({ onStop: e, isOn: t }) => {
76
- let i = n(), a = l(null), o = l(t);
77
- return s(() => {
98
+ }, k = "[data-testid=\"assistant-voice-orb\"]", A = "[data-testid=\"assistant-voice-end\"]", j = ({ onStop: e, isOn: t }) => {
99
+ let n = r(), a = u(null), o = u(t);
100
+ return c(() => {
78
101
  let e = a.current, t = o.current;
79
102
  return () => {
80
103
  if (!e?.contains(e.ownerDocument.activeElement)) return;
81
- let n = e.closest(`[${r}]`), i = t() ? null : n?.querySelector(E);
82
- (i && !i.hasAttribute("disabled") ? i : n?.querySelector(D))?.focus();
104
+ let n = e.closest(`[${i}]`), r = t() ? null : n?.querySelector(k);
105
+ (r && !r.hasAttribute("disabled") ? r : n?.querySelector(A))?.focus();
83
106
  };
84
- }, []), /* @__PURE__ */ m("div", {
107
+ }, []), /* @__PURE__ */ h("div", {
85
108
  ref: a,
86
109
  className: "absolute bottom-1.5 left-7 flex h-8 max-w-[calc(100%-13.875rem)] items-center gap-1 rounded-full border border-border-default bg-bg-elevated ps-2.5 pe-0.5 text-xs font-medium text-text-secondary rtl:left-auto rtl:right-7",
87
110
  "data-testid": "assistant-voice-avatar",
88
- children: [/* @__PURE__ */ p("span", {
111
+ children: [/* @__PURE__ */ m("span", {
89
112
  className: "truncate",
90
- children: i.stateOn
91
- }), /* @__PURE__ */ p("button", {
113
+ children: n.stateOn
114
+ }), /* @__PURE__ */ m("button", {
92
115
  type: "button",
93
116
  onClick: () => e(),
94
117
  className: "relative flex size-7 shrink-0 items-center justify-center rounded-full transition-colors after:absolute after:-inset-2 after:-ms-1.5 after:me-1.5 hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
95
- "aria-label": i.stop,
118
+ "aria-label": n.stop,
96
119
  "data-testid": "assistant-voice-avatar-stop",
97
- children: /* @__PURE__ */ p(f, {
120
+ children: /* @__PURE__ */ m(p, {
98
121
  className: "size-4",
99
122
  "aria-hidden": "true"
100
123
  })
@@ -102,4 +125,4 @@ var T = () => {
102
125
  });
103
126
  };
104
127
  //#endregion
105
- export { T as LiveAvatarMiniIndicator, g as LiveAvatarSeamProvider, w as useLiveAvatarMiniIndicatorShown, v as useLiveAvatarSpeechEngine, _ as useLiveAvatarStage, S as useLiveAvatarVoiceView };
128
+ export { O as LiveAvatarMiniIndicator, _ as LiveAvatarSeamProvider, w as useLiveAvatarHandsFreeGuard, D as useLiveAvatarMiniIndicatorShown, C as useLiveAvatarOn, y as useLiveAvatarSpeechEngine, v as useLiveAvatarStage, T as useLiveAvatarVoiceView };
@@ -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 { Mic as i } from "lucide-react";
6
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
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 s = () => {
9
- let s = t(), c = n((e) => e.handsFreeInterrupt), l = n((e) => e.setHandsFreeInterrupt);
10
- return !e() && !r() ? null : /* @__PURE__ */ o("label", {
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: s("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."),
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__ */ a(i, {
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__ */ a("span", {
23
+ /* @__PURE__ */ l("span", {
20
24
  className: "flex-1",
21
- children: s("voice.handsFreeLabel", "Hands-free interrupt (beta)")
25
+ children: d("voice.handsFreeLabel", "Hands-free interrupt (beta)")
22
26
  }),
23
- /* @__PURE__ */ a("input", {
27
+ /* @__PURE__ */ l("input", {
24
28
  type: "checkbox",
25
- checked: c,
26
- onChange: (e) => l(e.target.checked),
27
- className: "size-4 accent-current",
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 { s as AssistantHandsFreeInterruptToggle };
48
+ export { d as AssistantHandsFreeInterruptToggle };