@burdenoff/fe-libs 2026.1024.3 → 2026.1026.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 (33) hide show
  1. package/dist/shared/assistant/avatar/live/LiveAvatarMinutes.d.ts +24 -0
  2. package/dist/shared/assistant/avatar/live/LiveAvatarMinutes.js +161 -0
  3. package/dist/shared/assistant/avatar/live/LiveAvatarStage.js +95 -74
  4. package/dist/shared/assistant/avatar/live/LiveAvatarTabView.d.ts +6 -0
  5. package/dist/shared/assistant/avatar/live/LiveAvatarTabView.js +195 -172
  6. package/dist/shared/assistant/avatar/live/avatarPorts.d.ts +9 -0
  7. package/dist/shared/assistant/avatar/live/avatarSessionClient.d.ts +77 -1
  8. package/dist/shared/assistant/avatar/live/avatarSessionClient.js +193 -72
  9. package/dist/shared/assistant/avatar/live/avatarTransport.d.ts +25 -3
  10. package/dist/shared/assistant/avatar/live/avatarTransport.js +29 -2
  11. package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.d.ts +35 -4
  12. package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.js +136 -79
  13. package/dist/shared/assistant/avatar/live/liveAvatarController.d.ts +79 -3
  14. package/dist/shared/assistant/avatar/live/liveAvatarController.js +424 -245
  15. package/dist/shared/assistant/avatar/live/liveAvatarMinutesView.d.ts +127 -0
  16. package/dist/shared/assistant/avatar/live/liveAvatarMinutesView.js +168 -0
  17. package/dist/shared/assistant/avatar/live/liveAvatarStatus.d.ts +3 -0
  18. package/dist/shared/assistant/avatar/live/liveAvatarStatus.js +11 -7
  19. package/dist/shared/assistant/avatar/live/liveKitAvatarRoom.js +6 -1
  20. package/dist/shared/assistant/avatar/useAvatarCopy.d.ts +127 -2
  21. package/dist/shared/assistant/avatar/useAvatarCopy.js +116 -7
  22. package/dist/shared/assistant/i18nManifest.d.ts +32 -1
  23. package/dist/shared/assistant/i18nManifest.js +55 -24
  24. package/dist/shared/assistant/index.d.ts +2 -0
  25. package/dist/shared/assistant/ui/AssistantChatArea.js +17 -17
  26. package/dist/shared/assistant/ui/AssistantMarkdownRenderer.d.ts +5 -2
  27. package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +11 -3
  28. package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.js +78 -76
  29. package/dist/shared/assistant/ui/avatar/avatarAskGate.d.ts +2 -0
  30. package/dist/shared/assistant/ui/avatar/avatarAskGate.js +1 -0
  31. package/dist/shared/events/index.d.ts +2 -1
  32. package/dist/shared-assistant.js +227 -225
  33. package/package.json +1 -1
@@ -2,164 +2,174 @@ import { HOSTED_SPEAKERS as e, isHostedSpeaker as t } from "../../speech/hostedV
2
2
  import { useAvatarCopy as n } from "../useAvatarCopy.js";
3
3
  import { useAssistantSpeech as ee } from "../../ui/AssistantSpeechProvider.js";
4
4
  import { resolveAvatarVoiceMode as te } from "../avatarPreferences.js";
5
+ import { avatarMinutesRefusal as ne } from "./avatarSessionClient.js";
5
6
  import "./liveAvatarController.js";
6
- import { liveAvatarStatusText as ne } from "./liveAvatarStatus.js";
7
- import { AvatarFace as re } from "./AvatarFace.js";
8
- import { hostedAvatarVoice as r } from "./avatarVoice.js";
9
- import { useCallback as i, useEffect as a, useId as o, useLayoutEffect as ie, useRef as s, useState as c, useSyncExternalStore as l } from "react";
10
- import { Volume2 as u } from "lucide-react";
11
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
7
+ import { liveAvatarMinutesActive as re, liveAvatarMinutesBlockStart as ie } from "./liveAvatarMinutesView.js";
8
+ import { liveAvatarStatusText as ae } from "./liveAvatarStatus.js";
9
+ import { AvatarFace as r } from "./AvatarFace.js";
10
+ import { hostedAvatarVoice as i } from "./avatarVoice.js";
11
+ import { LiveAvatarMinutes as oe } from "./LiveAvatarMinutes.js";
12
+ import { useCallback as se, useEffect as a, useId as o, useLayoutEffect as ce, useRef as s, useState as c, useSyncExternalStore as le } from "react";
13
+ import { Volume2 as ue } from "lucide-react";
14
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
12
15
  //#region src/shared/assistant/avatar/live/LiveAvatarTabView.tsx
13
- var p = "mine", m = "paired", h = "speaker:", g = /-Chirp3-HD-([A-Za-z]+)$/;
14
- function _(e) {
15
- let n = g.exec(e)?.[1];
16
+ var d = "mine", f = "paired", p = "speaker:", m = /-Chirp3-HD-([A-Za-z]+)$/;
17
+ function de(e) {
18
+ let n = m.exec(e)?.[1];
16
19
  return n !== void 0 && t(n) ? n : e;
17
20
  }
18
- function v(e, t) {
21
+ function fe(e, t) {
19
22
  let n = t.find((e) => e.source === "hosted")?.lang;
20
- return n === void 0 ? null : r(e, n, t);
23
+ return n === void 0 ? null : i(e, n, t);
21
24
  }
22
- var y = "text-xs font-medium text-text-secondary", b = "text-xs text-text-muted", x = "focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong", S = `inline-flex min-h-11 w-full items-center justify-center gap-2 rounded-xl border border-border-default bg-bg-elevated px-4 text-sm font-medium text-text-primary transition-colors hover:bg-bg-raised aria-disabled:cursor-default aria-disabled:opacity-60 aria-disabled:hover:bg-bg-elevated ${x}`, ae = `inline-flex min-h-11 w-full items-center justify-center rounded-xl bg-action-primary-bg px-4 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover aria-disabled:cursor-default aria-disabled:opacity-60 aria-disabled:hover:bg-action-primary-bg ${x}`, oe = "relative inline-flex min-h-11 min-w-0 max-w-full cursor-pointer items-center gap-2 rounded-full border ps-1.5 pe-4 text-sm font-medium transition-colors focus-within:ring-2 focus-within:ring-border-strong", se = "absolute inset-0 m-0 size-full cursor-pointer appearance-none rounded-full opacity-0", C = ({ controller: r, shown: g, voice: C, handsFreeOff: ce, leaveHintId: le, startVoiceRef: ue, askLine: w, avatarNames: de, avatarImages: fe, avatarVoices: pe, defaultAvatarVoiceMode: me, voiceStore: T, now: E = Date.now }) => {
23
- let D = n(), O = ee(), k = o(), he = o(), A = o(), j = o(), M = o(), N = s(null), P = l(r.subscribe, r.getSnapshot, r.getSnapshot), F = l(T.subscribe, T.getState, T.getState);
25
+ var h = "text-xs font-medium text-text-secondary", g = "text-xs text-text-muted", _ = "focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong", v = `inline-flex min-h-11 w-full items-center justify-center gap-2 rounded-xl border border-border-default bg-bg-elevated px-4 text-sm font-medium text-text-primary transition-colors hover:bg-bg-raised aria-disabled:cursor-default aria-disabled:opacity-60 aria-disabled:hover:bg-bg-elevated ${_}`, pe = `inline-flex min-h-11 w-full items-center justify-center rounded-xl bg-action-primary-bg px-4 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover aria-disabled:cursor-default aria-disabled:opacity-60 aria-disabled:hover:bg-action-primary-bg ${_}`, me = "relative inline-flex min-h-11 min-w-0 max-w-full cursor-pointer items-center gap-2 rounded-full border ps-1.5 pe-4 text-sm font-medium transition-colors focus-within:ring-2 focus-within:ring-border-strong", he = "absolute inset-0 m-0 size-full cursor-pointer appearance-none rounded-full opacity-0", y = ({ controller: i, shown: m, voice: y, handsFreeOff: ge, leaveHintId: _e, startVoiceRef: ve, askLine: b, avatarNames: ye, avatarImages: be, avatarVoices: xe, defaultAvatarVoiceMode: Se, voiceStore: x, now: S = Date.now, navigate: Ce, minutesPurchase: we }) => {
26
+ let C = n(), w = ee(), T = o(), Te = o(), E = o(), D = o(), O = o(), k = o(), Ee = o(), A = s(null), j = le(i.subscribe, i.getSnapshot, i.getSnapshot), M = le(x.subscribe, x.getState, x.getState);
24
27
  a(() => {
25
- if (g) return r.setStageMounted(!0), () => r.setStageMounted(!1);
26
- }, [r, g]), a(() => {
27
- let e = r.getSnapshot();
28
- e.phase === "off" && e.avatars.length === 0 && r.requestOn({ start: !1 });
29
- }, [r]);
30
- let { phase: I } = P, L = I === "starting" || I === "connecting" || I === "ready" || I === "ending", [R, z] = c(!1);
31
- R && (I === "off" || I === "choosing" || I === "ready" || I === "ending") && z(!1);
32
- let B = E(), V = P.retryAt !== null && P.retryAt > B, H = ne(P, D, B), U = P.selectedAvatarId, W = (e) => {
33
- let t = P.avatars.indexOf(e);
34
- return de?.[e] ?? (t === -1 ? D.chooserNone : `${D.chooserLabel} ${t + 1}`);
35
- }, G = I === "ready" ? { kind: "turn-off" } : I === "ending" ? { kind: "ending" } : R || I === "starting" || I === "connecting" ? { kind: "starting" } : P.offered ? {
28
+ if (m) return i.setStageMounted(!0), () => i.setStageMounted(!1);
29
+ }, [i, m]), a(() => {
30
+ let e = i.getSnapshot();
31
+ e.phase === "off" && e.avatars.length === 0 && i.requestOn({ start: !1 });
32
+ }, [i]);
33
+ let { phase: N } = j, P = N === "starting" || N === "connecting" || N === "ready" || N === "ending", [De, F] = c(!1);
34
+ De && (N === "off" || N === "choosing" || N === "ready" || N === "ending") && F(!1);
35
+ let I = S(), L = j.retryAt !== null && j.retryAt > I, R = ae(j, C, I), Oe = re(j), z = ie(j, I), B = z && R !== null, V = j.selectedAvatarId, H = (e) => {
36
+ let t = j.avatars.indexOf(e);
37
+ return ye?.[e] ?? (t === -1 ? C.chooserNone : `${C.chooserLabel} ${t + 1}`);
38
+ }, U = N === "ready" ? { kind: "turn-off" } : N === "ending" ? { kind: "ending" } : De || N === "starting" || N === "connecting" ? { kind: "starting" } : j.offered ? {
36
39
  kind: "turn-on",
37
- ready: !V && U !== null && (I === "choosing" || I === "off" && P.avatars.includes(U))
38
- } : null, K = s(null), ge = G?.kind === "turn-off";
39
- ie(() => {
40
- K.current = ge ? E() : null;
41
- }, [ge, E]);
42
- let _e = i((e) => {
40
+ ready: !L && !z && V !== null && (N === "choosing" || N === "off" && j.avatars.includes(V))
41
+ } : null, W = s(null), G = U?.kind === "turn-off";
42
+ ce(() => {
43
+ W.current = G ? S() : null;
44
+ }, [G, S]);
45
+ let ke = se((e) => {
43
46
  if (e !== null) return () => {
44
- e.ownerDocument.activeElement === e && N.current?.focus();
47
+ e.ownerDocument.activeElement === e && A.current?.focus();
45
48
  };
46
- }, []), ve = () => {
47
- if (G !== null) switch (G.kind) {
48
- case "turn-on":
49
- if (!G.ready || U === null) {
50
- V && r.recheckRetry();
49
+ }, []), Ae = () => {
50
+ if (U !== null) switch (U.kind) {
51
+ case "turn-on": {
52
+ if (!U.ready || V === null) {
53
+ (L || j.retryAt !== null) && i.recheckRetry();
51
54
  return;
52
55
  }
53
- z(!0), I === "choosing" ? r.confirm() : r.requestOn({
56
+ F(!0);
57
+ let e = ne(j.minutes)?.problem;
58
+ if (N === "choosing" && !(e === "minutes-in-use" || e === "minutes-in-use-self")) {
59
+ i.confirm();
60
+ return;
61
+ }
62
+ N === "choosing" && i.cancelChoice(), i.requestOn({
54
63
  start: !0,
55
- avatarId: U
64
+ avatarId: V
56
65
  });
57
66
  return;
67
+ }
58
68
  case "turn-off": {
59
- let e = K.current;
60
- if (e !== null && E() - e < 1e3) return;
61
- r.switchOff();
69
+ let e = W.current;
70
+ if (e !== null && S() - e < 1e3) return;
71
+ i.switchOff();
62
72
  return;
63
73
  }
64
74
  case "starting":
65
75
  case "ending": return;
66
76
  }
67
- }, ye = te(F, me), q = U === null ? null : pe.get(U) ?? null, J = ye === "speaker" && F.avatarSpeaker !== null ? `${h}${F.avatarSpeaker}` : ye === "paired" && q !== null ? m : p, be = J === m ? q : J.startsWith(h) ? F.avatarSpeaker : null, Y = J === p ? O.activeVoiceName : be === null ? null : v(be, O.voiceChoices)?.name ?? null, xe = O.speakingMessageId !== null || O.spokenChunks !== null, Se = Y !== null && !C.live && !xe, Ce = O.activeVoiceName ? D.voiceModeMineNamed(_(O.activeVoiceName)) : D.voiceModeMine, we = (e) => {
68
- if (e === p || e === m) {
69
- T.setVoiceMode(e);
77
+ }, K = te(M, Se), q = V === null ? null : xe.get(V) ?? null, J = K === "speaker" && M.avatarSpeaker !== null ? `${p}${M.avatarSpeaker}` : K === "paired" && q !== null ? f : d, je = J === f ? q : J.startsWith(p) ? M.avatarSpeaker : null, Y = J === d ? w.activeVoiceName : je === null ? null : fe(je, w.voiceChoices)?.name ?? null, Me = w.speakingMessageId !== null || w.spokenChunks !== null, Ne = Y !== null && !y.live && !Me, Pe = w.activeVoiceName ? C.voiceModeMineNamed(de(w.activeVoiceName)) : C.voiceModeMine, Fe = (e) => {
78
+ if (e === d || e === f) {
79
+ x.setVoiceMode(e);
70
80
  return;
71
81
  }
72
82
  let n = e.slice(8);
73
- e.startsWith(h) && t(n) && T.setAvatarSpeaker(n);
74
- }, Te = I === "ending" ? D.stateEnding : I === "connecting" || I === "ready" ? D.stageWaiting : I === "starting" ? D.stateStarting : D.stateOff, [Ee, De] = c(() => /* @__PURE__ */ new Set()), Oe = i((e) => {
75
- De((t) => t.has(e) ? t : new Set(t).add(e));
76
- }, []), ke = (e) => {
77
- let t = fe?.get(e);
78
- return t === void 0 || Ee.has(t) ? null : t;
79
- }, X = !L && U !== null ? ke(U) : null, Z = L ? null : w === void 0 ? C.impossible ? D.askNeedsVoice : null : w === "by-typing" ? D.askByTyping : w === "needs-voice" ? D.askNeedsVoice : w === "nothing" ? D.askNothing : null, Ae = I === "off" && P.avatars.length === 0 && P.offered, [Q, je] = c(!1), $ = Ae && (Q || P.problem !== null);
80
- return $ !== Q && je($), /* @__PURE__ */ f("div", {
81
- ref: N,
83
+ e.startsWith(p) && t(n) && x.setAvatarSpeaker(n);
84
+ }, Ie = N === "ending" ? C.stateEnding : N === "connecting" || N === "ready" ? C.stageWaiting : N === "starting" ? C.stateStarting : C.stateOff, [Le, Re] = c(() => /* @__PURE__ */ new Set()), ze = se((e) => {
85
+ Re((t) => t.has(e) ? t : new Set(t).add(e));
86
+ }, []), Be = (e) => {
87
+ let t = be?.get(e);
88
+ return t === void 0 || Le.has(t) ? null : t;
89
+ }, X = !P && V !== null ? Be(V) : null, Z = P ? null : b === void 0 ? y.impossible ? C.askNeedsVoice : null : b === "by-typing" ? C.askByTyping : b === "needs-voice" ? C.askNeedsVoice : b === "nothing" ? C.askNothing : null, Ve = N === "off" && j.avatars.length === 0 && j.offered, [Q, He] = c(!1), $ = Ve && (Q || j.problem !== null);
90
+ return $ !== Q && He($), /* @__PURE__ */ u("div", {
91
+ ref: A,
82
92
  tabIndex: -1,
83
93
  className: "flex min-h-full shrink-0 flex-col gap-3 focus:outline-none",
84
94
  "data-testid": "assistant-avatar-tab-view",
85
95
  children: [
86
- /* @__PURE__ */ d("div", {
96
+ /* @__PURE__ */ l("div", {
87
97
  className: "flex max-h-80 min-h-[7.5rem] grow basis-30 justify-center",
88
- children: /* @__PURE__ */ f("div", {
98
+ children: /* @__PURE__ */ u("div", {
89
99
  className: "relative aspect-square h-full max-w-full overflow-hidden rounded-2xl border border-border-subtle bg-bg-sunken",
90
100
  "data-testid": "assistant-avatar-tab-frame",
91
- "data-phase": I,
101
+ "data-phase": N,
92
102
  children: [
93
- L ? /* @__PURE__ */ d("video", {
94
- ref: r.attachVideo,
95
- className: `size-full object-cover ${P.videoReady ? "" : "invisible"}`,
96
- "aria-label": D.stageLabel,
97
- autoPlay: !0,
103
+ P ? /* @__PURE__ */ l("video", {
104
+ ref: i.attachVideo,
105
+ className: `size-full object-cover ${j.videoReady && !j.videoBlocked ? "" : "invisible"}`,
106
+ "aria-label": C.stageLabel,
98
107
  muted: !0,
99
108
  playsInline: !0,
100
109
  "data-testid": "assistant-avatar-tab-video"
101
110
  }) : null,
102
- X !== null && U !== null ? /* @__PURE__ */ d(re, {
111
+ X !== null && V !== null ? /* @__PURE__ */ l(r, {
103
112
  size: "frame",
104
- name: W(U),
113
+ name: H(V),
105
114
  src: X,
106
- onError: Oe
115
+ onError: ze
107
116
  }) : null,
108
- L && P.videoReady ? null : /* @__PURE__ */ d("p", {
117
+ P && j.videoReady && !j.videoBlocked || N === "ready" && j.videoBlocked ? null : /* @__PURE__ */ l("p", {
109
118
  className: X === null ? "absolute inset-0 flex items-center justify-center p-3 text-center text-sm text-text-secondary" : "absolute inset-x-0 bottom-0 bg-bg-elevated/90 px-3 py-1.5 text-center text-xs text-text-secondary",
110
119
  "data-testid": "assistant-avatar-tab-frame-text",
111
- children: Te
120
+ children: Ie
112
121
  }),
113
- P.audioBlocked ? /* @__PURE__ */ f("button", {
122
+ j.audioBlocked ? /* @__PURE__ */ u("button", {
114
123
  type: "button",
115
- onClick: () => r.resumeAudio(),
116
- className: `absolute inset-x-2 bottom-2 inline-flex min-h-11 items-center justify-center gap-1.5 rounded-xl bg-bg-elevated px-3 text-xs font-medium text-text-primary ${x}`,
124
+ onClick: () => i.resumeAudio(),
125
+ className: `absolute inset-x-2 bottom-2 inline-flex min-h-11 items-center justify-center gap-1.5 rounded-xl bg-bg-elevated px-3 text-xs font-medium text-text-primary ${_}`,
117
126
  "data-testid": "assistant-avatar-tab-sound",
118
- children: [/* @__PURE__ */ d(u, {
127
+ children: [/* @__PURE__ */ l(ue, {
119
128
  className: "size-4 shrink-0",
120
129
  "aria-hidden": "true"
121
- }), /* @__PURE__ */ d("span", { children: D.problem("playback-blocked") })]
130
+ }), /* @__PURE__ */ l("span", { children: C.problem("playback-blocked") })]
122
131
  }) : null
123
132
  ]
124
133
  })
125
134
  }),
126
- /* @__PURE__ */ d("p", {
127
- className: H === null ? "sr-only" : "text-center text-sm text-text-secondary",
135
+ /* @__PURE__ */ l("p", {
136
+ id: B ? Ee : void 0,
137
+ className: R === null ? "sr-only" : "text-center text-sm text-text-secondary",
128
138
  role: "status",
129
139
  "data-testid": "assistant-avatar-tab-status",
130
- children: H ?? ""
140
+ children: R ?? ""
131
141
  }),
132
- P.avatars.length > 1 && !L ? /* @__PURE__ */ f("fieldset", {
142
+ j.avatars.length > 1 && !P ? /* @__PURE__ */ u("fieldset", {
133
143
  className: "flex min-w-0 flex-col gap-1.5",
134
144
  "data-testid": "assistant-avatar-tab-chooser",
135
- children: [/* @__PURE__ */ d("legend", {
136
- className: y,
137
- children: D.chooserTitle
138
- }), /* @__PURE__ */ d("div", {
145
+ children: [/* @__PURE__ */ l("legend", {
146
+ className: h,
147
+ children: C.chooserTitle
148
+ }), /* @__PURE__ */ l("div", {
139
149
  className: "flex flex-wrap gap-2",
140
- children: P.avatars.map((e) => {
141
- let t = e === U, n = W(e);
142
- return /* @__PURE__ */ f("label", {
143
- className: `${oe} ${t ? "border-transparent bg-action-primary-bg text-action-primary-text" : "border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-raised hover:text-text-primary"}`,
144
- title: t ? D.chooserSelected(n) : D.chooserOption(n),
150
+ children: j.avatars.map((e) => {
151
+ let t = e === V, n = H(e);
152
+ return /* @__PURE__ */ u("label", {
153
+ className: `${me} ${t ? "border-transparent bg-action-primary-bg text-action-primary-text" : "border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-raised hover:text-text-primary"}`,
154
+ title: t ? C.chooserSelected(n) : C.chooserOption(n),
145
155
  children: [
146
- /* @__PURE__ */ d("input", {
156
+ /* @__PURE__ */ l("input", {
147
157
  type: "radio",
148
- name: he,
158
+ name: Te,
149
159
  value: e,
150
160
  checked: t,
151
- onChange: () => r.selectAvatar(e),
152
- className: se,
161
+ onChange: () => i.selectAvatar(e),
162
+ className: he,
153
163
  "data-avatar-id": e
154
164
  }),
155
- /* @__PURE__ */ d(re, {
165
+ /* @__PURE__ */ l(r, {
156
166
  size: "pill",
157
167
  name: n,
158
- src: ke(e),
168
+ src: Be(e),
159
169
  selected: t,
160
- onError: Oe
170
+ onError: ze
161
171
  }),
162
- /* @__PURE__ */ d("span", {
172
+ /* @__PURE__ */ l("span", {
163
173
  className: "truncate",
164
174
  children: n
165
175
  })
@@ -167,142 +177,155 @@ var y = "text-xs font-medium text-text-secondary", b = "text-xs text-text-muted"
167
177
  }, e);
168
178
  })
169
179
  })]
170
- }) : P.avatars.length > 0 && U !== null ? /* @__PURE__ */ f("div", {
180
+ }) : j.avatars.length > 0 && V !== null ? /* @__PURE__ */ u("div", {
171
181
  className: "flex flex-col gap-0.5",
172
182
  "data-testid": "assistant-avatar-tab-chosen",
173
- children: [/* @__PURE__ */ f("p", {
183
+ children: [/* @__PURE__ */ u("p", {
174
184
  className: "flex min-w-0 items-baseline gap-2 text-sm",
175
- children: [/* @__PURE__ */ d("span", {
176
- className: y,
177
- children: D.chooserLabel
178
- }), /* @__PURE__ */ d("span", {
185
+ children: [/* @__PURE__ */ l("span", {
186
+ className: h,
187
+ children: C.chooserLabel
188
+ }), /* @__PURE__ */ l("span", {
179
189
  className: "truncate text-text-primary",
180
- children: W(U)
190
+ children: H(V)
181
191
  })]
182
- }), L && P.avatars.length > 1 ? /* @__PURE__ */ d("p", {
183
- className: b,
184
- children: D.chooserLocked
192
+ }), P && j.avatars.length > 1 ? /* @__PURE__ */ l("p", {
193
+ className: g,
194
+ children: C.chooserLocked
185
195
  }) : null]
186
- }) : I === "choosing" ? /* @__PURE__ */ d("p", {
187
- className: b,
196
+ }) : N === "choosing" ? /* @__PURE__ */ l("p", {
197
+ className: g,
188
198
  "data-testid": "assistant-avatar-tab-empty",
189
- children: D.chooserEmpty
199
+ children: C.chooserEmpty
190
200
  }) : null,
191
- /* @__PURE__ */ f("div", {
201
+ /* @__PURE__ */ u("div", {
192
202
  className: "flex flex-col gap-1",
193
203
  children: [
194
- /* @__PURE__ */ d("label", {
195
- htmlFor: A,
196
- className: y,
197
- children: D.voiceModeLabel
204
+ /* @__PURE__ */ l("label", {
205
+ htmlFor: E,
206
+ className: h,
207
+ children: C.voiceModeLabel
198
208
  }),
199
- /* @__PURE__ */ f("div", {
209
+ /* @__PURE__ */ u("div", {
200
210
  className: "flex items-center gap-2",
201
- children: [/* @__PURE__ */ f("select", {
202
- id: A,
211
+ children: [/* @__PURE__ */ u("select", {
212
+ id: E,
203
213
  value: J,
204
- onChange: (e) => we(e.target.value),
205
- "aria-describedby": j,
206
- className: `min-h-11 min-w-0 flex-1 rounded-xl border border-border-default bg-bg-elevated px-3 text-sm text-text-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary ${x}`,
214
+ onChange: (e) => Fe(e.target.value),
215
+ "aria-describedby": D,
216
+ className: `min-h-11 min-w-0 flex-1 rounded-xl border border-border-default bg-bg-elevated px-3 text-sm text-text-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary ${_}`,
207
217
  "data-testid": "assistant-avatar-tab-voice",
208
218
  children: [
209
- /* @__PURE__ */ d("option", {
210
- value: p,
211
- children: Ce
219
+ /* @__PURE__ */ l("option", {
220
+ value: d,
221
+ children: Pe
212
222
  }),
213
- q === null ? null : /* @__PURE__ */ d("option", {
214
- value: m,
215
- children: D.voiceModeDefaultNamed(q)
223
+ q === null ? null : /* @__PURE__ */ l("option", {
224
+ value: f,
225
+ children: C.voiceModeDefaultNamed(q)
216
226
  }),
217
- e.map((e) => /* @__PURE__ */ d("option", {
218
- value: `${h}${e}`,
227
+ e.map((e) => /* @__PURE__ */ l("option", {
228
+ value: `${p}${e}`,
219
229
  children: e
220
230
  }, e))
221
231
  ]
222
- }), /* @__PURE__ */ d("button", {
232
+ }), /* @__PURE__ */ l("button", {
223
233
  type: "button",
224
234
  onClick: () => {
225
- Se && Y !== null && O.previewVoice(Y);
235
+ Ne && Y !== null && w.previewVoice(Y);
226
236
  },
227
- "aria-disabled": !Se,
228
- "aria-label": D.hearVoice,
229
- title: D.hearVoice,
230
- className: `inline-flex size-11 shrink-0 items-center justify-center rounded-xl border border-border-default bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary aria-disabled:cursor-default aria-disabled:opacity-60 ${x}`,
237
+ "aria-disabled": !Ne,
238
+ "aria-label": C.hearVoice,
239
+ title: C.hearVoice,
240
+ className: `inline-flex size-11 shrink-0 items-center justify-center rounded-xl border border-border-default bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary aria-disabled:cursor-default aria-disabled:opacity-60 ${_}`,
231
241
  "data-testid": "assistant-avatar-tab-hear",
232
- children: /* @__PURE__ */ d(u, {
242
+ children: /* @__PURE__ */ l(ue, {
233
243
  className: "size-5",
234
244
  "aria-hidden": "true"
235
245
  })
236
246
  })]
237
247
  }),
238
- /* @__PURE__ */ d("p", {
239
- id: j,
240
- className: b,
241
- children: D.voiceModeHint
248
+ /* @__PURE__ */ l("p", {
249
+ id: D,
250
+ className: g,
251
+ children: C.voiceModeHint
242
252
  })
243
253
  ]
244
254
  }),
245
- L ? null : /* @__PURE__ */ d("p", {
246
- id: k,
255
+ Oe ? /* @__PURE__ */ l(oe, {
256
+ controller: i,
257
+ snapshot: j,
258
+ minutesPurchase: we,
259
+ navigate: Ce,
260
+ now: S,
261
+ textId: k,
262
+ viewRef: A
263
+ }) : null,
264
+ P ? null : /* @__PURE__ */ l("p", {
265
+ id: T,
247
266
  className: "text-xs text-text-secondary",
248
267
  "data-testid": "assistant-avatar-tab-disclosure",
249
- children: D.consent
268
+ children: C.consent
250
269
  }),
251
- G === null ? null : /* @__PURE__ */ d("button", {
252
- ref: _e,
270
+ U === null ? null : /* @__PURE__ */ l("button", {
271
+ ref: ke,
253
272
  type: "button",
254
- onClick: ve,
255
- "aria-disabled": G.kind === "turn-on" ? !G.ready : G.kind !== "turn-off",
256
- "aria-describedby": G.kind === "turn-on" ? k : void 0,
257
- className: G.kind === "turn-off" ? S : ae,
273
+ onClick: Ae,
274
+ "aria-disabled": U.kind === "turn-on" ? !U.ready : U.kind !== "turn-off",
275
+ "aria-describedby": U.kind === "turn-on" ? z ? [
276
+ T,
277
+ B ? Ee : null,
278
+ k
279
+ ].filter((e) => e !== null).join(" ") : T : void 0,
280
+ className: U.kind === "turn-off" ? v : pe,
258
281
  "data-testid": "assistant-avatar-tab-switch",
259
- "data-slot": G.kind,
260
- children: G.kind === "turn-off" ? D.stop : G.kind === "starting" ? D.turnOnStarting : G.kind === "ending" ? D.stateEnding : D.consentConfirm
282
+ "data-slot": U.kind,
283
+ children: U.kind === "turn-off" ? C.stop : U.kind === "starting" ? C.turnOnStarting : U.kind === "ending" ? C.stateEnding : C.consentConfirm
261
284
  }),
262
- $ ? /* @__PURE__ */ d("button", {
285
+ $ ? /* @__PURE__ */ l("button", {
263
286
  type: "button",
264
- onClick: () => r.requestOn({ start: !1 }),
265
- className: S,
287
+ onClick: () => i.requestOn({ start: !1 }),
288
+ className: v,
266
289
  "data-testid": "assistant-avatar-tab-retry",
267
- children: D.chooserRetry
290
+ children: C.chooserRetry
268
291
  }) : null,
269
- C.live ? null : /* @__PURE__ */ f("div", {
292
+ y.live ? null : /* @__PURE__ */ u("div", {
270
293
  className: "flex flex-col gap-1",
271
- children: [/* @__PURE__ */ d("button", {
272
- ref: ue,
294
+ children: [/* @__PURE__ */ l("button", {
295
+ ref: ve,
273
296
  type: "button",
274
297
  onClick: () => {
275
- C.blocked === null && C.start();
298
+ y.blocked === null && y.start();
276
299
  },
277
- "aria-disabled": C.blocked !== null,
278
- "aria-describedby": C.blocked === null ? void 0 : M,
279
- className: S,
300
+ "aria-disabled": y.blocked !== null,
301
+ "aria-describedby": y.blocked === null ? void 0 : O,
302
+ className: v,
280
303
  "data-testid": "assistant-avatar-tab-start-voice",
281
- children: D.startVoice
282
- }), C.blocked === null ? Z === null ? null : /* @__PURE__ */ d("p", {
283
- className: b,
304
+ children: C.startVoice
305
+ }), y.blocked === null ? Z === null ? null : /* @__PURE__ */ l("p", {
306
+ className: g,
284
307
  "data-testid": "assistant-avatar-tab-ask-note",
285
308
  children: Z
286
- }) : /* @__PURE__ */ d("p", {
287
- id: M,
288
- className: b,
309
+ }) : /* @__PURE__ */ l("p", {
310
+ id: O,
311
+ className: g,
289
312
  "data-testid": "assistant-avatar-tab-voice-blocked",
290
- children: Z === null ? C.blocked : `${C.blocked} ${Z}`
313
+ children: Z === null ? y.blocked : `${y.blocked} ${Z}`
291
314
  })]
292
315
  }),
293
- ce && !P.voiceLive ? /* @__PURE__ */ d("p", {
294
- className: b,
316
+ ge && !j.voiceLive ? /* @__PURE__ */ l("p", {
317
+ className: g,
295
318
  "data-testid": "assistant-avatar-tab-hands-free",
296
- children: D.handsFreeOff
319
+ children: C.handsFreeOff
297
320
  }) : null,
298
- L && !P.heldByVoice ? /* @__PURE__ */ d("p", {
299
- id: le,
300
- className: b,
321
+ P && !j.heldByVoice ? /* @__PURE__ */ l("p", {
322
+ id: _e,
323
+ className: g,
301
324
  "data-testid": "assistant-avatar-tab-leave-hint",
302
- children: D.tabLeaveHint
325
+ children: C.tabLeaveHint
303
326
  }) : null
304
327
  ]
305
328
  });
306
329
  };
307
330
  //#endregion
308
- export { C as LiveAvatarTabView, v as avatarPreviewVoice, _ as avatarVoiceDisplayName };
331
+ export { y as LiveAvatarTabView, fe as avatarPreviewVoice, de as avatarVoiceDisplayName };
@@ -63,4 +63,13 @@ export interface AvatarRoom {
63
63
  startAudio(): Promise<void>;
64
64
  /** Whether the browser currently lets remote audio play (false until a user gesture while autoplay is blocked). */
65
65
  canPlaybackAudio(): boolean;
66
+ /**
67
+ * ★ BOFF-9696: the browser refused (false) or allowed again (true) the avatar's VIDEO. iOS in Low Power Mode refuses even a muted
68
+ * inline video until a user gesture. Optional: a room without it never reports a refused video.
69
+ */
70
+ onVideoPlaybackChanged?(handler: (canPlay: boolean) => void): AvatarUnsubscribe;
71
+ /** Start the refused video after a user gesture: the video twin of startAudio. */
72
+ startVideo?(): Promise<void>;
73
+ /** Whether the browser currently lets the remote video play. */
74
+ canPlaybackVideo?(): boolean;
66
75
  }