@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.
- package/dist/shared/assistant/avatar/live/LiveAvatarMinutes.d.ts +24 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarMinutes.js +161 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarStage.js +95 -74
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.d.ts +6 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.js +195 -172
- package/dist/shared/assistant/avatar/live/avatarPorts.d.ts +9 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.d.ts +77 -1
- package/dist/shared/assistant/avatar/live/avatarSessionClient.js +193 -72
- package/dist/shared/assistant/avatar/live/avatarTransport.d.ts +25 -3
- package/dist/shared/assistant/avatar/live/avatarTransport.js +29 -2
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.d.ts +35 -4
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.js +136 -79
- package/dist/shared/assistant/avatar/live/liveAvatarController.d.ts +79 -3
- package/dist/shared/assistant/avatar/live/liveAvatarController.js +424 -245
- package/dist/shared/assistant/avatar/live/liveAvatarMinutesView.d.ts +127 -0
- package/dist/shared/assistant/avatar/live/liveAvatarMinutesView.js +168 -0
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.d.ts +3 -0
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.js +11 -7
- package/dist/shared/assistant/avatar/live/liveKitAvatarRoom.js +6 -1
- package/dist/shared/assistant/avatar/useAvatarCopy.d.ts +127 -2
- package/dist/shared/assistant/avatar/useAvatarCopy.js +116 -7
- package/dist/shared/assistant/i18nManifest.d.ts +32 -1
- package/dist/shared/assistant/i18nManifest.js +55 -24
- package/dist/shared/assistant/index.d.ts +2 -0
- package/dist/shared/assistant/ui/AssistantChatArea.js +17 -17
- package/dist/shared/assistant/ui/AssistantMarkdownRenderer.d.ts +5 -2
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +11 -3
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.js +78 -76
- package/dist/shared/assistant/ui/avatar/avatarAskGate.d.ts +2 -0
- package/dist/shared/assistant/ui/avatar/avatarAskGate.js +1 -0
- package/dist/shared/events/index.d.ts +2 -1
- package/dist/shared-assistant.js +227 -225
- package/package.json +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FC, RefObject } from 'react';
|
|
2
|
+
import { AssistantNavigate } from '../../ui/AssistantMarkdownRenderer';
|
|
3
|
+
import { LiveAvatarController, LiveAvatarSnapshot } from './liveAvatarController';
|
|
4
|
+
import { LiveAvatarMinutesPurchase } from './liveAvatarMinutesView';
|
|
5
|
+
/** How often the session's time left is redrawn while it runs (DESIGN 3.10: every 15 s). */
|
|
6
|
+
export declare const LIVE_AVATAR_MINUTES_REDRAW_MS = 15000;
|
|
7
|
+
export interface LiveAvatarMinutesProps {
|
|
8
|
+
readonly controller: LiveAvatarController;
|
|
9
|
+
/** The snapshot the tab read (one subscription per view). */
|
|
10
|
+
readonly snapshot: LiveAvatarSnapshot;
|
|
11
|
+
/** The host's purchase access (`LiveAvatarSeamOptions.minutesPurchase`). Absent: nobody is offered a purchase here. */
|
|
12
|
+
readonly minutesPurchase?: LiveAvatarMinutesPurchase | undefined;
|
|
13
|
+
/** The panel's navigator. Absent or null: nothing opens billing. */
|
|
14
|
+
readonly navigate?: AssistantNavigate | null | undefined;
|
|
15
|
+
/** Wall-clock milliseconds. */
|
|
16
|
+
readonly now: () => number;
|
|
17
|
+
/** The id of the region's words: a Turn on the minutes hold back is described by them. */
|
|
18
|
+
readonly textId: string;
|
|
19
|
+
/** The tab's view, focusable: it takes the focus when a control here goes while it holds it. A ref the tab keeps (stable). */
|
|
20
|
+
readonly viewRef: RefObject<HTMLElement | null>;
|
|
21
|
+
/** How often the session's time left is redrawn. Tests pass their own. */
|
|
22
|
+
readonly redrawMs?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const LiveAvatarMinutes: FC<LiveAvatarMinutesProps>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { useAvatarCopy as e } from "../useAvatarCopy.js";
|
|
2
|
+
import { LIVE_AVATAR_MINUTES_REFRESH_MS as t, LIVE_AVATAR_REQUEST_TIMEOUT_MS as n } from "./liveAvatarController.js";
|
|
3
|
+
import { LIVE_AVATAR_MINUTES_PLANS_PATH as r, liveAvatarMinutesView as i } from "./liveAvatarMinutesView.js";
|
|
4
|
+
import { useCallback as a, useEffect as o, useId as ee, useRef as s, useState as c } from "react";
|
|
5
|
+
import { ChevronDown as l } from "lucide-react";
|
|
6
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
7
|
+
//#region src/shared/assistant/avatar/live/LiveAvatarMinutes.tsx
|
|
8
|
+
var f = 15e3, p = t + n, m = "text-xs text-text-muted", h = "focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong", g = `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 ${h}`, _ = `inline-flex min-h-11 items-center gap-1 self-start rounded-lg text-xs font-medium text-text-secondary transition-colors hover:text-text-primary ${h}`, te = { status: "absent" }, v = { status: "asking" }, y = { status: "failed" };
|
|
9
|
+
function b(e) {
|
|
10
|
+
if (typeof e != "object" || !e || !("canPurchase" in e)) return y;
|
|
11
|
+
let { canPurchase: t } = e;
|
|
12
|
+
return typeof t == "boolean" ? {
|
|
13
|
+
status: "answered",
|
|
14
|
+
access: { canPurchase: t }
|
|
15
|
+
} : y;
|
|
16
|
+
}
|
|
17
|
+
var x = { status: "idle" }, S = ({ controller: t, snapshot: n, minutesPurchase: h, navigate: S, now: C, textId: w, viewRef: T, redrawMs: E = f }) => {
|
|
18
|
+
let D = e(), O = ee(), [k, A] = c(!1), j = s(!0);
|
|
19
|
+
o(() => (j.current = !0, () => {
|
|
20
|
+
j.current = !1;
|
|
21
|
+
}), []);
|
|
22
|
+
let M = a((e) => {
|
|
23
|
+
if (e !== null) return () => {
|
|
24
|
+
e.contains(e.ownerDocument.activeElement) && T.current?.focus();
|
|
25
|
+
};
|
|
26
|
+
}, [T]), N = h !== void 0 && S != null, [P, F] = c(x), I = s(null), L = n.minutes === null;
|
|
27
|
+
o(() => {
|
|
28
|
+
L && (I.current = null, F(x));
|
|
29
|
+
}, [L]);
|
|
30
|
+
let [R, z] = c(null), B = s(n.minutes?.balance?.availableMinutes ?? 0), V = s(n.purchase);
|
|
31
|
+
o(() => {
|
|
32
|
+
let e = V.current;
|
|
33
|
+
V.current = n.purchase, n.purchase === "checking" && e !== "checking" ? (B.current = n.minutes?.balance?.availableMinutes ?? 0, z(null)) : n.purchase === "idle" && e === "checking" && z({
|
|
34
|
+
kind: (n.minutes?.balance?.availableMinutes ?? 0) > B.current ? "seen" : "not-seen",
|
|
35
|
+
minutes: n.minutes
|
|
36
|
+
});
|
|
37
|
+
}, [n.purchase, n.minutes]);
|
|
38
|
+
let H = R !== null && R.minutes === n.minutes ? R.kind : null, [U, W] = c(null), [G, K] = c(null), q = U !== null && U.minutes === n.minutes, J = G !== null && G.minutes === n.minutes;
|
|
39
|
+
o(() => {
|
|
40
|
+
if (U === null) return;
|
|
41
|
+
if (!q) {
|
|
42
|
+
W(null), K({ minutes: n.minutes });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
let e = setTimeout(() => W(null), p);
|
|
46
|
+
return () => clearTimeout(e);
|
|
47
|
+
}, [
|
|
48
|
+
U,
|
|
49
|
+
q,
|
|
50
|
+
n.minutes
|
|
51
|
+
]);
|
|
52
|
+
let Y = n.phase === "ready" && !n.closing && n.sessionEndsAt !== null, [, X] = c(0);
|
|
53
|
+
o(() => {
|
|
54
|
+
if (!Y) return;
|
|
55
|
+
let e = setInterval(() => X((e) => e + 1), E);
|
|
56
|
+
return () => clearInterval(e);
|
|
57
|
+
}, [Y, E]);
|
|
58
|
+
let Z = i({
|
|
59
|
+
snapshot: n,
|
|
60
|
+
access: N ? P.status === "idle" ? v : P : te,
|
|
61
|
+
purchaseOutcome: H,
|
|
62
|
+
rechecked: J,
|
|
63
|
+
now: C()
|
|
64
|
+
}, D), Q = N && Z !== null && Z.wantsAccess, $ = Z?.action ?? null;
|
|
65
|
+
o(() => {
|
|
66
|
+
if (!Q || P.status !== "idle" || I.current !== null || h === void 0) return;
|
|
67
|
+
let e = Symbol("access");
|
|
68
|
+
I.current = e, F(v);
|
|
69
|
+
let t = (t) => {
|
|
70
|
+
!j.current || I.current !== e || (I.current = null, F(t));
|
|
71
|
+
};
|
|
72
|
+
Promise.resolve().then(() => h.access()).then((e) => t(b(e)), () => t(y));
|
|
73
|
+
}, [
|
|
74
|
+
Q,
|
|
75
|
+
P.status,
|
|
76
|
+
h
|
|
77
|
+
]);
|
|
78
|
+
let ne = a((e) => {
|
|
79
|
+
S && (z(null), Promise.resolve(S(e, "person", { surface: "avatar-minutes" })).catch(() => void 0));
|
|
80
|
+
}, [S]);
|
|
81
|
+
if (Z === null) return null;
|
|
82
|
+
let re = (e) => {
|
|
83
|
+
switch (e) {
|
|
84
|
+
case "see-plans":
|
|
85
|
+
ne(r);
|
|
86
|
+
return;
|
|
87
|
+
case "check-again":
|
|
88
|
+
if (q) return;
|
|
89
|
+
W({ minutes: n.minutes }), K(null), t.refreshMinutes();
|
|
90
|
+
return;
|
|
91
|
+
case "check-purchase-again":
|
|
92
|
+
t.checkMinutesPurchase();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}, ie = (e) => {
|
|
96
|
+
switch (e) {
|
|
97
|
+
case "see-plans": return D.minutes.seePlans;
|
|
98
|
+
case "check-again": return q ? D.minutes.checking : D.minutes.checkAgain;
|
|
99
|
+
case "check-purchase-again": return D.minutes.checkAgain;
|
|
100
|
+
}
|
|
101
|
+
}, ae = D.minutes.howCounted(Z.staleSeconds);
|
|
102
|
+
return /* @__PURE__ */ d("div", {
|
|
103
|
+
ref: M,
|
|
104
|
+
className: "flex flex-col gap-1.5",
|
|
105
|
+
"data-testid": "assistant-avatar-tab-minutes",
|
|
106
|
+
"data-state": Z.state,
|
|
107
|
+
children: [
|
|
108
|
+
/* @__PURE__ */ d("div", {
|
|
109
|
+
id: w,
|
|
110
|
+
className: "flex flex-col gap-0.5",
|
|
111
|
+
children: [Z.headline === null ? null : /* @__PURE__ */ u("p", {
|
|
112
|
+
className: "text-sm text-text-primary",
|
|
113
|
+
"data-testid": "assistant-avatar-tab-minutes-headline",
|
|
114
|
+
children: Z.headline
|
|
115
|
+
}), Z.details.map((e) => /* @__PURE__ */ u("p", {
|
|
116
|
+
className: m,
|
|
117
|
+
"data-testid": "assistant-avatar-tab-minutes-detail",
|
|
118
|
+
children: e
|
|
119
|
+
}, e))]
|
|
120
|
+
}),
|
|
121
|
+
$ === null ? null : /* @__PURE__ */ u("button", {
|
|
122
|
+
ref: M,
|
|
123
|
+
type: "button",
|
|
124
|
+
onClick: () => re($),
|
|
125
|
+
"aria-disabled": $ === "check-again" && q,
|
|
126
|
+
className: g,
|
|
127
|
+
"data-testid": "assistant-avatar-tab-minutes-action",
|
|
128
|
+
"data-action": $,
|
|
129
|
+
children: ie($)
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ d("button", {
|
|
132
|
+
type: "button",
|
|
133
|
+
onClick: () => A((e) => !e),
|
|
134
|
+
"aria-expanded": k,
|
|
135
|
+
"aria-controls": O,
|
|
136
|
+
className: _,
|
|
137
|
+
"data-testid": "assistant-avatar-tab-minutes-how",
|
|
138
|
+
children: [/* @__PURE__ */ u("span", { children: D.minutes.howCountedTitle }), /* @__PURE__ */ u(l, {
|
|
139
|
+
className: `size-4 shrink-0 transition-transform ${k ? "rotate-180" : ""}`,
|
|
140
|
+
"aria-hidden": "true"
|
|
141
|
+
})]
|
|
142
|
+
}),
|
|
143
|
+
/* @__PURE__ */ u("ul", {
|
|
144
|
+
id: O,
|
|
145
|
+
hidden: !k,
|
|
146
|
+
className: "flex list-disc flex-col gap-1 ps-5 text-xs text-text-secondary",
|
|
147
|
+
"data-testid": "assistant-avatar-tab-minutes-how-text",
|
|
148
|
+
children: ae.map((e) => /* @__PURE__ */ u("li", { children: e }, e))
|
|
149
|
+
}),
|
|
150
|
+
/* @__PURE__ */ u("p", {
|
|
151
|
+
className: "sr-only",
|
|
152
|
+
"aria-live": "polite",
|
|
153
|
+
"aria-atomic": "true",
|
|
154
|
+
"data-testid": "assistant-avatar-tab-minutes-live",
|
|
155
|
+
children: Z.announcement ?? ""
|
|
156
|
+
})
|
|
157
|
+
]
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
//#endregion
|
|
161
|
+
export { f as LIVE_AVATAR_MINUTES_REDRAW_MS, S as LiveAvatarMinutes };
|
|
@@ -1,145 +1,166 @@
|
|
|
1
1
|
import { useAvatarCopy as e } from "../useAvatarCopy.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { liveAvatarMinutesBlockStart as t, liveAvatarMinutesView as n } from "./liveAvatarMinutesView.js";
|
|
3
|
+
import { liveAvatarStatusText as r } from "./liveAvatarStatus.js";
|
|
4
|
+
import { useCallback as i, useEffect as a, useId as o, useRef as s, useSyncExternalStore as c } from "react";
|
|
5
|
+
import { Video as l, VideoOff as u, Volume2 as d } from "lucide-react";
|
|
6
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
6
7
|
//#region src/shared/assistant/avatar/live/LiveAvatarStage.tsx
|
|
7
|
-
var
|
|
8
|
-
let
|
|
8
|
+
var m = "inline-flex h-8 items-center gap-1.5 rounded-full border border-border-default bg-bg-elevated px-3 text-xs font-medium text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong aria-disabled:cursor-default aria-disabled:opacity-60", h = "inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-full border px-3 text-xs font-medium transition-colors focus-within:ring-2 focus-within:ring-border-strong", g = "inline-flex h-8 items-center rounded-full bg-action-primary-bg px-3 text-xs font-medium text-action-primary-text transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong aria-disabled:cursor-default aria-disabled:opacity-60", _ = ({ controller: _, expanded: v, fallback: y, avatarNames: b }) => {
|
|
9
|
+
let x = e(), S = o(), C = o(), w = o(), T = o(), E = s(null), D = s(null), O = i((e) => {
|
|
9
10
|
e?.focus();
|
|
10
|
-
}, []),
|
|
11
|
-
|
|
12
|
-
}), []),
|
|
13
|
-
|
|
14
|
-
let { phase:
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
}, []), k = i((e) => (D.current = e, () => {
|
|
12
|
+
D.current = null, document.activeElement === e && E.current?.focus();
|
|
13
|
+
}), []), A = c(_.subscribe, _.getSnapshot, _.getSnapshot);
|
|
14
|
+
a(() => (_.setStageMounted(!0), () => _.setStageMounted(!1)), [_]);
|
|
15
|
+
let { phase: j } = A, M = j === "starting" || j === "connecting" || j === "ready" || j === "ending", N = j === "checking" || j === "ending", P = Date.now(), F = A.retryAt !== null && A.retryAt > P, I = r(A, x, P), L = n({
|
|
16
|
+
snapshot: A,
|
|
17
|
+
access: { status: "absent" },
|
|
18
|
+
now: P
|
|
19
|
+
}, x)?.stageLines ?? [], R = t(A, P), z = F || R, B = F ? `${S} ${C}` : R ? [
|
|
20
|
+
S,
|
|
21
|
+
I === null ? null : C,
|
|
22
|
+
L.length > 0 ? T : null
|
|
23
|
+
].filter((e) => e !== null).join(" ") : S, V = (e, t) => b?.[e] ?? `${x.chooserLabel} ${t + 1}`;
|
|
24
|
+
return /* @__PURE__ */ p("div", {
|
|
25
|
+
ref: E,
|
|
17
26
|
tabIndex: -1,
|
|
18
27
|
className: "flex flex-col items-center gap-2 focus:outline-none",
|
|
19
28
|
"data-testid": "assistant-live-avatar",
|
|
20
29
|
children: [
|
|
21
|
-
|
|
22
|
-
className: `relative overflow-hidden rounded-2xl border border-border-subtle bg-bg-sunken ${
|
|
30
|
+
M ? /* @__PURE__ */ p("div", {
|
|
31
|
+
className: `relative overflow-hidden rounded-2xl border border-border-subtle bg-bg-sunken ${v ? "size-64" : "size-40"}`,
|
|
23
32
|
"data-testid": "assistant-live-avatar-frame",
|
|
24
|
-
"data-phase":
|
|
33
|
+
"data-phase": j,
|
|
25
34
|
children: [
|
|
26
|
-
/* @__PURE__ */
|
|
27
|
-
ref:
|
|
28
|
-
className: `size-full object-cover ${
|
|
29
|
-
"aria-label":
|
|
30
|
-
autoPlay: !0,
|
|
35
|
+
/* @__PURE__ */ f("video", {
|
|
36
|
+
ref: _.attachVideo,
|
|
37
|
+
className: `size-full object-cover ${A.videoReady && !A.videoBlocked ? "" : "invisible"}`,
|
|
38
|
+
"aria-label": x.stageLabel,
|
|
31
39
|
muted: !0,
|
|
32
40
|
playsInline: !0,
|
|
33
41
|
"data-testid": "assistant-live-avatar-video"
|
|
34
42
|
}),
|
|
35
|
-
|
|
43
|
+
A.videoReady && !A.videoBlocked || j === "ready" && A.videoBlocked ? null : /* @__PURE__ */ f("p", {
|
|
36
44
|
className: "absolute inset-0 flex items-center justify-center p-3 text-center text-xs text-text-muted",
|
|
37
|
-
children:
|
|
45
|
+
children: j === "ending" ? x.stateEnding : j === "connecting" ? x.stageWaiting : x.stateStarting
|
|
38
46
|
}),
|
|
39
|
-
|
|
47
|
+
A.audioBlocked ? /* @__PURE__ */ p("button", {
|
|
40
48
|
type: "button",
|
|
41
|
-
onClick: () =>
|
|
49
|
+
onClick: () => _.resumeAudio(),
|
|
42
50
|
className: "absolute inset-x-2 bottom-2 inline-flex items-center justify-center gap-1.5 rounded-xl bg-bg-elevated px-2 py-1.5 text-xs font-medium text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
|
|
43
51
|
"data-testid": "assistant-live-avatar-sound",
|
|
44
|
-
children: [/* @__PURE__ */
|
|
52
|
+
children: [/* @__PURE__ */ f(d, {
|
|
45
53
|
className: "size-4 shrink-0",
|
|
46
54
|
"aria-hidden": "true"
|
|
47
|
-
}), /* @__PURE__ */
|
|
55
|
+
}), /* @__PURE__ */ f("span", { children: x.problem("playback-blocked") })]
|
|
48
56
|
}) : null
|
|
49
57
|
]
|
|
50
|
-
}) :
|
|
51
|
-
|
|
52
|
-
ref:
|
|
58
|
+
}) : y,
|
|
59
|
+
A.offered || M ? /* @__PURE__ */ p("button", {
|
|
60
|
+
ref: k,
|
|
53
61
|
type: "button",
|
|
54
62
|
onClick: () => {
|
|
55
|
-
|
|
63
|
+
N || (M ? _.switchOff() : j === "choosing" ? _.cancelChoice() : _.requestOn());
|
|
56
64
|
},
|
|
57
|
-
className:
|
|
58
|
-
"aria-pressed":
|
|
59
|
-
title:
|
|
60
|
-
"aria-disabled":
|
|
65
|
+
className: m,
|
|
66
|
+
"aria-pressed": M,
|
|
67
|
+
title: x.toggleHint,
|
|
68
|
+
"aria-disabled": N,
|
|
61
69
|
"data-testid": "assistant-live-avatar-toggle",
|
|
62
|
-
children: [
|
|
70
|
+
children: [f(M ? u : l, {
|
|
63
71
|
className: "size-4",
|
|
64
72
|
"aria-hidden": "true"
|
|
65
|
-
}), /* @__PURE__ */
|
|
73
|
+
}), /* @__PURE__ */ f("span", { children: x.toggle })]
|
|
66
74
|
}) : null,
|
|
67
|
-
|
|
75
|
+
j === "choosing" ? /* @__PURE__ */ p("fieldset", {
|
|
68
76
|
className: "flex max-w-xs flex-col gap-2 rounded-xl border border-border-default bg-bg-elevated p-3 text-start",
|
|
69
77
|
"data-testid": "assistant-live-avatar-consent",
|
|
70
78
|
children: [
|
|
71
|
-
/* @__PURE__ */
|
|
79
|
+
/* @__PURE__ */ f("legend", {
|
|
72
80
|
className: "sr-only",
|
|
73
|
-
children:
|
|
81
|
+
children: x.toggle
|
|
74
82
|
}),
|
|
75
|
-
|
|
83
|
+
A.avatars.length > 1 ? /* @__PURE__ */ p("fieldset", {
|
|
76
84
|
className: "flex flex-wrap gap-1.5",
|
|
77
85
|
"data-testid": "assistant-live-avatar-chooser",
|
|
78
|
-
children: [/* @__PURE__ */
|
|
86
|
+
children: [/* @__PURE__ */ f("legend", {
|
|
79
87
|
className: "sr-only",
|
|
80
|
-
children:
|
|
81
|
-
}),
|
|
82
|
-
let n = e ===
|
|
83
|
-
return /* @__PURE__ */
|
|
84
|
-
className: `${
|
|
85
|
-
title: n ?
|
|
86
|
-
children: [/* @__PURE__ */
|
|
88
|
+
children: x.chooserTitle
|
|
89
|
+
}), A.avatars.map((e, t) => {
|
|
90
|
+
let n = e === A.selectedAvatarId, r = V(e, t);
|
|
91
|
+
return /* @__PURE__ */ p("label", {
|
|
92
|
+
className: `${h} ${n ? "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"}`,
|
|
93
|
+
title: n ? x.chooserSelected(r) : x.chooserOption(r),
|
|
94
|
+
children: [/* @__PURE__ */ f("input", {
|
|
87
95
|
type: "radio",
|
|
88
|
-
name:
|
|
96
|
+
name: w,
|
|
89
97
|
value: e,
|
|
90
98
|
checked: n,
|
|
91
|
-
onChange: () =>
|
|
99
|
+
onChange: () => _.selectAvatar(e),
|
|
92
100
|
className: "sr-only",
|
|
93
101
|
"data-avatar-id": e
|
|
94
102
|
}), r]
|
|
95
103
|
}, e);
|
|
96
104
|
})]
|
|
97
105
|
}) : null,
|
|
98
|
-
/* @__PURE__ */
|
|
99
|
-
ref:
|
|
100
|
-
id:
|
|
106
|
+
/* @__PURE__ */ f("p", {
|
|
107
|
+
ref: O,
|
|
108
|
+
id: S,
|
|
101
109
|
tabIndex: -1,
|
|
102
110
|
className: "text-xs text-text-secondary focus:outline-none",
|
|
103
111
|
"data-testid": "assistant-live-avatar-disclosure",
|
|
104
|
-
children:
|
|
112
|
+
children: x.consent
|
|
105
113
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
114
|
+
L.length > 0 ? /* @__PURE__ */ f("div", {
|
|
115
|
+
id: T,
|
|
116
|
+
className: "flex flex-col gap-0.5 text-xs text-text-secondary",
|
|
117
|
+
"data-testid": "assistant-live-avatar-minutes",
|
|
118
|
+
children: L.map((e) => /* @__PURE__ */ f("p", {
|
|
119
|
+
"data-testid": "assistant-live-avatar-minutes-line",
|
|
120
|
+
children: e
|
|
121
|
+
}, e))
|
|
122
|
+
}) : null,
|
|
123
|
+
/* @__PURE__ */ p("div", {
|
|
107
124
|
className: "flex justify-end gap-2",
|
|
108
|
-
children: [/* @__PURE__ */
|
|
125
|
+
children: [/* @__PURE__ */ f("button", {
|
|
109
126
|
type: "button",
|
|
110
127
|
onClick: () => {
|
|
111
|
-
|
|
128
|
+
D.current?.focus(), _.cancelChoice();
|
|
112
129
|
},
|
|
113
|
-
className:
|
|
114
|
-
children:
|
|
115
|
-
}), /* @__PURE__ */
|
|
130
|
+
className: m,
|
|
131
|
+
children: x.consentCancel
|
|
132
|
+
}), /* @__PURE__ */ f("button", {
|
|
116
133
|
type: "button",
|
|
117
134
|
onClick: () => {
|
|
118
|
-
if (
|
|
119
|
-
|
|
135
|
+
if (F) {
|
|
136
|
+
_.recheckRetry();
|
|
120
137
|
return;
|
|
121
138
|
}
|
|
122
|
-
|
|
139
|
+
if (R) {
|
|
140
|
+
A.retryAt !== null && _.recheckRetry();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
D.current?.focus(), _.confirm();
|
|
123
144
|
},
|
|
124
|
-
"aria-describedby":
|
|
125
|
-
"aria-disabled":
|
|
126
|
-
className:
|
|
127
|
-
disabled:
|
|
145
|
+
"aria-describedby": B,
|
|
146
|
+
"aria-disabled": z,
|
|
147
|
+
className: g,
|
|
148
|
+
disabled: A.selectedAvatarId === null,
|
|
128
149
|
"data-testid": "assistant-live-avatar-confirm",
|
|
129
|
-
children:
|
|
150
|
+
children: x.consentConfirm
|
|
130
151
|
})]
|
|
131
152
|
})
|
|
132
153
|
]
|
|
133
154
|
}) : null,
|
|
134
|
-
/* @__PURE__ */
|
|
135
|
-
id:
|
|
136
|
-
className:
|
|
155
|
+
/* @__PURE__ */ f("p", {
|
|
156
|
+
id: C,
|
|
157
|
+
className: I === null ? "sr-only" : "max-w-xs text-center text-xs text-text-muted",
|
|
137
158
|
role: "status",
|
|
138
159
|
"data-testid": "assistant-live-avatar-status",
|
|
139
|
-
children:
|
|
160
|
+
children: I ?? ""
|
|
140
161
|
})
|
|
141
162
|
]
|
|
142
163
|
});
|
|
143
164
|
};
|
|
144
165
|
//#endregion
|
|
145
|
-
export {
|
|
166
|
+
export { _ as LiveAvatarStageView };
|
|
@@ -5,6 +5,7 @@ import { LiveAvatarTabProps } from '../../ui/assistantLiveAvatarSeam';
|
|
|
5
5
|
import { AvatarVoiceDefault, AvatarVoicePreference } from '../avatarPreferences';
|
|
6
6
|
import { LiveAvatarVoices } from './avatarVoice';
|
|
7
7
|
import { LiveAvatarController } from './liveAvatarController';
|
|
8
|
+
import { LiveAvatarMinutesPurchase } from './liveAvatarMinutesView';
|
|
8
9
|
/** The person's avatar voice choice: read by the engine decorator per reply, written by the tab's select. STABLE. */
|
|
9
10
|
export interface LiveAvatarVoiceStore {
|
|
10
11
|
getState(): AvatarVoicePreference;
|
|
@@ -24,6 +25,11 @@ export interface LiveAvatarTabViewProps extends LiveAvatarTabProps {
|
|
|
24
25
|
readonly voiceStore: LiveAvatarVoiceStore;
|
|
25
26
|
/** Wall-clock milliseconds: the retry time and the Turn off guard. Tests pass their own. */
|
|
26
27
|
readonly now?: () => number;
|
|
28
|
+
/**
|
|
29
|
+
* ★ BOFF-9446: the host's purchase access (`LiveAvatarSeamOptions.minutesPurchase`, copied once by the seam). Absent: nobody is
|
|
30
|
+
* offered "See plans" here.
|
|
31
|
+
*/
|
|
32
|
+
readonly minutesPurchase?: LiveAvatarMinutesPurchase;
|
|
27
33
|
}
|
|
28
34
|
/** A voice name as the person reads it: a hosted voice by its speaker ("Kore"), any other by its own name. */
|
|
29
35
|
export declare function avatarVoiceDisplayName(name: string): string;
|