@neuronection/assistant-ui 0.46.0 → 0.48.0
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/CHANGELOG.md +26 -0
- package/dist/chat-message.d.ts +6 -0
- package/dist/chat-message.js +1 -1
- package/dist/chat-transcript.js +1 -1
- package/dist/{chunk-EAJU4LFG.js → chunk-C5JZCCU7.js} +6 -3
- package/dist/chunk-C5JZCCU7.js.map +1 -0
- package/dist/{chunk-DICEYHOB.js → chunk-CYK3ZLAB.js} +29 -10
- package/dist/chunk-CYK3ZLAB.js.map +1 -0
- package/dist/chunk-WY5TO6R4.js +415 -0
- package/dist/chunk-WY5TO6R4.js.map +1 -0
- package/dist/{chunk-MTFHU6QY.js → chunk-XOODPYJ3.js} +3 -3
- package/dist/{chunk-MTFHU6QY.js.map → chunk-XOODPYJ3.js.map} +1 -1
- package/dist/index.d.ts +20 -10
- package/dist/index.js +4 -4
- package/dist/profile-switcher.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/user-menu.d.ts +14 -10
- package/dist/user-menu.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-C5OAZ2AW.js +0 -303
- package/dist/chunk-C5OAZ2AW.js.map +0 -1
- package/dist/chunk-DICEYHOB.js.map +0 -1
- package/dist/chunk-EAJU4LFG.js.map +0 -1
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { Input } from './chunk-GQDW6BBO.js';
|
|
2
|
+
import { Popover, PopoverTrigger, PopoverContent } from './chunk-VX3EQRSM.js';
|
|
3
|
+
import { Button } from './chunk-4WBBF5LH.js';
|
|
4
|
+
import { cn } from './chunk-RVVXVTH3.js';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { UserRound, ChevronDown, Pencil, Star, Trash2, Plus, Check } from 'lucide-react';
|
|
7
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
var defaultLabels = {
|
|
10
|
+
trigger: "Switch profile",
|
|
11
|
+
panelTitle: "Profiles",
|
|
12
|
+
currentBadge: "Current",
|
|
13
|
+
defaultBadge: "Default",
|
|
14
|
+
newProfile: "New profile",
|
|
15
|
+
newProfilePlaceholder: "Profile name",
|
|
16
|
+
create: "Create",
|
|
17
|
+
rename: (name) => `Rename ${name}`,
|
|
18
|
+
renamePlaceholder: "Profile name",
|
|
19
|
+
renameSubmit: "Save",
|
|
20
|
+
setDefault: (name) => `Make ${name} the default profile`,
|
|
21
|
+
delete: (name) => `Delete ${name}`,
|
|
22
|
+
cancel: "Cancel",
|
|
23
|
+
loading: "Loading profiles\u2026",
|
|
24
|
+
empty: "No profiles yet"
|
|
25
|
+
};
|
|
26
|
+
function ProfileAvatar({
|
|
27
|
+
profile,
|
|
28
|
+
size = "sm"
|
|
29
|
+
}) {
|
|
30
|
+
const letter = (profile.name.trim()[0] ?? "?").toUpperCase();
|
|
31
|
+
return /* @__PURE__ */ jsx(
|
|
32
|
+
"span",
|
|
33
|
+
{
|
|
34
|
+
"aria-hidden": true,
|
|
35
|
+
className: cn(
|
|
36
|
+
"flex shrink-0 items-center justify-center rounded-full font-semibold ring-1 ring-[var(--as-border)]",
|
|
37
|
+
size === "md" ? "size-8 text-xs" : "size-6 text-[10px]"
|
|
38
|
+
),
|
|
39
|
+
style: profile.color ? { backgroundColor: `${profile.color}22`, color: profile.color } : {
|
|
40
|
+
backgroundColor: "var(--as-secondary)",
|
|
41
|
+
color: "var(--as-muted-fg)"
|
|
42
|
+
},
|
|
43
|
+
children: profile.color ? letter : /* @__PURE__ */ jsx(UserRound, { className: size === "md" ? "size-4" : "size-3.5" })
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function ProfileRowBadges({
|
|
48
|
+
isCurrent,
|
|
49
|
+
isDefault,
|
|
50
|
+
currentBadge,
|
|
51
|
+
defaultBadge
|
|
52
|
+
}) {
|
|
53
|
+
if (!isCurrent && !isDefault) return null;
|
|
54
|
+
return /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
|
|
55
|
+
isCurrent ? /* @__PURE__ */ jsxs(
|
|
56
|
+
"span",
|
|
57
|
+
{
|
|
58
|
+
className: "inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium",
|
|
59
|
+
style: {
|
|
60
|
+
backgroundColor: "color-mix(in srgb, var(--as-accent) 12%, transparent)",
|
|
61
|
+
color: "var(--as-accent)"
|
|
62
|
+
},
|
|
63
|
+
children: [
|
|
64
|
+
/* @__PURE__ */ jsx(Check, { "aria-hidden": true, className: "size-3" }),
|
|
65
|
+
currentBadge
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
) : null,
|
|
69
|
+
isDefault ? /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-[var(--as-secondary)] px-1.5 py-0.5 text-[10px] font-medium text-[var(--as-muted-fg)]", children: defaultBadge }) : null
|
|
70
|
+
] });
|
|
71
|
+
}
|
|
72
|
+
var ProfileSwitcher = React.forwardRef(
|
|
73
|
+
function ProfileSwitcher2({
|
|
74
|
+
profiles,
|
|
75
|
+
currentId,
|
|
76
|
+
onSelect,
|
|
77
|
+
onCreate,
|
|
78
|
+
onRename,
|
|
79
|
+
onDelete,
|
|
80
|
+
onSetDefault,
|
|
81
|
+
loading = false,
|
|
82
|
+
error = null,
|
|
83
|
+
align = "start",
|
|
84
|
+
labels,
|
|
85
|
+
icons,
|
|
86
|
+
className
|
|
87
|
+
}, ref) {
|
|
88
|
+
const merged = { ...defaultLabels, ...labels };
|
|
89
|
+
const TriggerIcon = icons?.trigger ?? UserRound;
|
|
90
|
+
const CreateIcon = icons?.create ?? Plus;
|
|
91
|
+
const RenameIcon = icons?.rename ?? Pencil;
|
|
92
|
+
const SetDefaultIcon = icons?.setDefault ?? Star;
|
|
93
|
+
const DeleteIcon = icons?.delete ?? Trash2;
|
|
94
|
+
const EmptyIcon = icons?.empty ?? UserRound;
|
|
95
|
+
const [open, setOpen] = React.useState(false);
|
|
96
|
+
const [draftName, setDraftName] = React.useState("");
|
|
97
|
+
const [renamingId, setRenamingId] = React.useState(null);
|
|
98
|
+
const [renameDraft, setRenameDraft] = React.useState("");
|
|
99
|
+
const renameInputRef = React.useRef(null);
|
|
100
|
+
const current = profiles.find((profile) => profile.id === currentId) ?? profiles[0] ?? null;
|
|
101
|
+
const close = React.useCallback(() => {
|
|
102
|
+
setOpen(false);
|
|
103
|
+
setRenamingId(null);
|
|
104
|
+
setDraftName("");
|
|
105
|
+
}, []);
|
|
106
|
+
React.useEffect(() => {
|
|
107
|
+
if (renamingId !== null) {
|
|
108
|
+
renameInputRef.current?.focus();
|
|
109
|
+
renameInputRef.current?.select();
|
|
110
|
+
}
|
|
111
|
+
}, [renamingId]);
|
|
112
|
+
const startRename = (profile) => {
|
|
113
|
+
setRenamingId(profile.id);
|
|
114
|
+
setRenameDraft(profile.name);
|
|
115
|
+
};
|
|
116
|
+
const submitRename = async (profile) => {
|
|
117
|
+
const name = renameDraft.trim();
|
|
118
|
+
if (!name || name === profile.name) {
|
|
119
|
+
setRenamingId(null);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
await onRename(profile, name);
|
|
123
|
+
setRenamingId(null);
|
|
124
|
+
};
|
|
125
|
+
const submitCreate = async (event) => {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
const name = draftName.trim();
|
|
128
|
+
if (!name) return;
|
|
129
|
+
await onCreate(name);
|
|
130
|
+
setDraftName("");
|
|
131
|
+
};
|
|
132
|
+
const onListKeyDown = (event) => {
|
|
133
|
+
const rows = Array.from(
|
|
134
|
+
event.currentTarget.querySelectorAll("[data-profile-row]")
|
|
135
|
+
);
|
|
136
|
+
if (rows.length === 0) return;
|
|
137
|
+
const index = rows.indexOf(document.activeElement);
|
|
138
|
+
let next = -1;
|
|
139
|
+
if (event.key === "ArrowDown") next = index < 0 ? 0 : Math.min(index + 1, rows.length - 1);
|
|
140
|
+
else if (event.key === "ArrowUp")
|
|
141
|
+
next = index < 0 ? rows.length - 1 : Math.max(index - 1, 0);
|
|
142
|
+
else if (event.key === "Home") next = 0;
|
|
143
|
+
else if (event.key === "End") next = rows.length - 1;
|
|
144
|
+
if (next >= 0) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
rows[next]?.focus();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
return /* @__PURE__ */ jsx("div", { ref, "data-as": "profile-switcher", className: cn("inline-block", className), children: /* @__PURE__ */ jsxs(
|
|
150
|
+
Popover,
|
|
151
|
+
{
|
|
152
|
+
open,
|
|
153
|
+
onOpenChange: (next) => {
|
|
154
|
+
setOpen(next);
|
|
155
|
+
if (!next) {
|
|
156
|
+
setRenamingId(null);
|
|
157
|
+
setDraftName("");
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
children: [
|
|
161
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
162
|
+
"button",
|
|
163
|
+
{
|
|
164
|
+
type: "button",
|
|
165
|
+
"aria-haspopup": "dialog",
|
|
166
|
+
"aria-label": merged.trigger,
|
|
167
|
+
"data-testid": "profile-trigger",
|
|
168
|
+
className: "flex cursor-pointer items-center gap-2 rounded-full p-0.5 pr-2 transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]",
|
|
169
|
+
children: [
|
|
170
|
+
current ? /* @__PURE__ */ jsx(ProfileAvatar, { profile: current, size: "md" }) : /* @__PURE__ */ jsx(
|
|
171
|
+
"span",
|
|
172
|
+
{
|
|
173
|
+
"aria-hidden": true,
|
|
174
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-full ring-1 ring-[var(--as-border)]",
|
|
175
|
+
children: /* @__PURE__ */ jsx(TriggerIcon, { className: "size-4 text-[var(--as-muted-fg)]" })
|
|
176
|
+
}
|
|
177
|
+
),
|
|
178
|
+
/* @__PURE__ */ jsx("span", { className: "max-w-32 truncate text-sm font-medium", children: current ? current.name : merged.empty }),
|
|
179
|
+
/* @__PURE__ */ jsx(
|
|
180
|
+
ChevronDown,
|
|
181
|
+
{
|
|
182
|
+
"aria-hidden": true,
|
|
183
|
+
className: "size-3.5 text-[var(--as-muted-fg)] transition-transform duration-150 [[data-state=open]>&]:rotate-180"
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
) }),
|
|
189
|
+
/* @__PURE__ */ jsxs(
|
|
190
|
+
PopoverContent,
|
|
191
|
+
{
|
|
192
|
+
align,
|
|
193
|
+
role: "dialog",
|
|
194
|
+
"aria-label": merged.panelTitle,
|
|
195
|
+
className: "w-80 p-1.5 shadow-[var(--as-shadow-pop)] backdrop-blur-xl",
|
|
196
|
+
onEscapeKeyDown: (event) => {
|
|
197
|
+
if (renamingId !== null) event.preventDefault();
|
|
198
|
+
},
|
|
199
|
+
children: [
|
|
200
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-2 pb-1 pt-1", children: [
|
|
201
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]", children: merged.panelTitle }),
|
|
202
|
+
profiles.length > 0 ? /* @__PURE__ */ jsx("span", { className: "text-[11px] tabular-nums text-[var(--as-muted-fg)]", children: profiles.length }) : null
|
|
203
|
+
] }),
|
|
204
|
+
loading ? /* @__PURE__ */ jsx(
|
|
205
|
+
"p",
|
|
206
|
+
{
|
|
207
|
+
className: "as-anim-fade px-2 py-3 text-sm text-[var(--as-muted-fg)]",
|
|
208
|
+
role: "status",
|
|
209
|
+
children: merged.loading
|
|
210
|
+
}
|
|
211
|
+
) : profiles.length === 0 ? /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 px-2 py-3 text-sm text-[var(--as-muted-fg)]", children: [
|
|
212
|
+
/* @__PURE__ */ jsx(EmptyIcon, { "aria-hidden": true, className: "size-4" }),
|
|
213
|
+
merged.empty
|
|
214
|
+
] }) : /* @__PURE__ */ jsx(
|
|
215
|
+
"ul",
|
|
216
|
+
{
|
|
217
|
+
className: "max-h-72 space-y-0.5 overflow-y-auto",
|
|
218
|
+
onKeyDown: onListKeyDown,
|
|
219
|
+
children: profiles.map((profile) => {
|
|
220
|
+
const isCurrent = current !== null && profile.id === current.id;
|
|
221
|
+
return /* @__PURE__ */ jsx(
|
|
222
|
+
"li",
|
|
223
|
+
{
|
|
224
|
+
className: "flex items-center gap-1 rounded-[var(--as-radius-sm)] px-0.5 py-0.5 hover:bg-[var(--as-secondary)]",
|
|
225
|
+
children: renamingId === profile.id ? /* @__PURE__ */ jsxs(
|
|
226
|
+
"form",
|
|
227
|
+
{
|
|
228
|
+
className: "flex w-full items-center gap-1 py-0.5",
|
|
229
|
+
onSubmit: (event) => {
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
void submitRename(profile);
|
|
232
|
+
},
|
|
233
|
+
children: [
|
|
234
|
+
/* @__PURE__ */ jsx(
|
|
235
|
+
Input,
|
|
236
|
+
{
|
|
237
|
+
ref: renameInputRef,
|
|
238
|
+
"aria-label": merged.rename(profile.name),
|
|
239
|
+
placeholder: merged.renamePlaceholder,
|
|
240
|
+
value: renameDraft,
|
|
241
|
+
onChange: (event) => setRenameDraft(event.target.value),
|
|
242
|
+
onKeyDown: (event) => {
|
|
243
|
+
if (event.key === "Escape") {
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
setRenamingId(null);
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
className: "h-8 flex-1"
|
|
249
|
+
}
|
|
250
|
+
),
|
|
251
|
+
/* @__PURE__ */ jsx(
|
|
252
|
+
Button,
|
|
253
|
+
{
|
|
254
|
+
type: "submit",
|
|
255
|
+
size: "sm",
|
|
256
|
+
className: "h-8",
|
|
257
|
+
disabled: !renameDraft.trim(),
|
|
258
|
+
"aria-label": merged.renameSubmit,
|
|
259
|
+
children: merged.renameSubmit
|
|
260
|
+
}
|
|
261
|
+
),
|
|
262
|
+
/* @__PURE__ */ jsx(
|
|
263
|
+
Button,
|
|
264
|
+
{
|
|
265
|
+
type: "button",
|
|
266
|
+
size: "sm",
|
|
267
|
+
variant: "ghost",
|
|
268
|
+
className: "h-8",
|
|
269
|
+
"aria-label": merged.cancel,
|
|
270
|
+
onClick: () => setRenamingId(null),
|
|
271
|
+
children: merged.cancel
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
277
|
+
/* @__PURE__ */ jsxs(
|
|
278
|
+
"button",
|
|
279
|
+
{
|
|
280
|
+
type: "button",
|
|
281
|
+
"aria-current": isCurrent || void 0,
|
|
282
|
+
"data-profile-row": true,
|
|
283
|
+
"data-testid": `profile-option-${profile.id}`,
|
|
284
|
+
className: "flex min-w-0 flex-1 cursor-pointer items-center gap-2.5 rounded-[var(--as-radius-sm)] px-1.5 py-1.5 text-left text-sm outline-none transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] aria-current:bg-[color-mix(in_srgb,var(--as-accent)_8%,transparent)]",
|
|
285
|
+
onClick: () => {
|
|
286
|
+
onSelect(profile);
|
|
287
|
+
close();
|
|
288
|
+
},
|
|
289
|
+
children: [
|
|
290
|
+
/* @__PURE__ */ jsx(ProfileAvatar, { profile, size: "md" }),
|
|
291
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate font-medium", children: profile.name }),
|
|
292
|
+
/* @__PURE__ */ jsx(
|
|
293
|
+
ProfileRowBadges,
|
|
294
|
+
{
|
|
295
|
+
isCurrent,
|
|
296
|
+
isDefault: Boolean(profile.is_default),
|
|
297
|
+
currentBadge: merged.currentBadge,
|
|
298
|
+
defaultBadge: merged.defaultBadge
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
),
|
|
304
|
+
/* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-0.5 pr-0.5", children: [
|
|
305
|
+
/* @__PURE__ */ jsx(
|
|
306
|
+
Button,
|
|
307
|
+
{
|
|
308
|
+
type: "button",
|
|
309
|
+
size: "icon",
|
|
310
|
+
variant: "ghost",
|
|
311
|
+
className: "size-7 rounded-[var(--as-radius-sm)]",
|
|
312
|
+
"aria-label": merged.rename(profile.name),
|
|
313
|
+
title: merged.rename(profile.name),
|
|
314
|
+
onClick: () => startRename(profile),
|
|
315
|
+
children: /* @__PURE__ */ jsx(RenameIcon, { "aria-hidden": true })
|
|
316
|
+
}
|
|
317
|
+
),
|
|
318
|
+
onSetDefault && !profile.is_default ? /* @__PURE__ */ jsx(
|
|
319
|
+
Button,
|
|
320
|
+
{
|
|
321
|
+
type: "button",
|
|
322
|
+
size: "icon",
|
|
323
|
+
variant: "ghost",
|
|
324
|
+
className: "size-7 rounded-[var(--as-radius-sm)]",
|
|
325
|
+
"aria-label": merged.setDefault(profile.name),
|
|
326
|
+
title: merged.setDefault(profile.name),
|
|
327
|
+
onClick: () => void onSetDefault(profile),
|
|
328
|
+
children: /* @__PURE__ */ jsx(SetDefaultIcon, { "aria-hidden": true })
|
|
329
|
+
}
|
|
330
|
+
) : null,
|
|
331
|
+
/* @__PURE__ */ jsx(
|
|
332
|
+
Button,
|
|
333
|
+
{
|
|
334
|
+
type: "button",
|
|
335
|
+
size: "icon",
|
|
336
|
+
variant: "ghost",
|
|
337
|
+
className: "size-7 rounded-[var(--as-radius-sm)] hover:text-[var(--as-danger)]",
|
|
338
|
+
"aria-label": merged.delete(profile.name),
|
|
339
|
+
title: merged.delete(profile.name),
|
|
340
|
+
onClick: () => void onDelete(profile),
|
|
341
|
+
children: /* @__PURE__ */ jsx(DeleteIcon, { "aria-hidden": true })
|
|
342
|
+
}
|
|
343
|
+
)
|
|
344
|
+
] })
|
|
345
|
+
] })
|
|
346
|
+
},
|
|
347
|
+
profile.id
|
|
348
|
+
);
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
),
|
|
352
|
+
error ? /* @__PURE__ */ jsx(
|
|
353
|
+
"p",
|
|
354
|
+
{
|
|
355
|
+
role: "alert",
|
|
356
|
+
className: "mx-1 mt-1 rounded-[var(--as-radius-sm)] bg-[color-mix(in_srgb,var(--as-danger)_10%,transparent)] px-2 py-1 text-xs text-[var(--as-danger)]",
|
|
357
|
+
children: error
|
|
358
|
+
}
|
|
359
|
+
) : null,
|
|
360
|
+
/* @__PURE__ */ jsxs(
|
|
361
|
+
"form",
|
|
362
|
+
{
|
|
363
|
+
className: "mt-1 flex items-center gap-1.5 border-t border-[var(--as-border)] p-1.5 pt-2",
|
|
364
|
+
onSubmit: (event) => {
|
|
365
|
+
void submitCreate(event);
|
|
366
|
+
},
|
|
367
|
+
children: [
|
|
368
|
+
/* @__PURE__ */ jsxs("div", { className: "relative min-w-0 flex-1", children: [
|
|
369
|
+
/* @__PURE__ */ jsx(
|
|
370
|
+
CreateIcon,
|
|
371
|
+
{
|
|
372
|
+
"aria-hidden": true,
|
|
373
|
+
className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-[var(--as-muted-fg)]"
|
|
374
|
+
}
|
|
375
|
+
),
|
|
376
|
+
/* @__PURE__ */ jsx(
|
|
377
|
+
Input,
|
|
378
|
+
{
|
|
379
|
+
"aria-label": merged.newProfile,
|
|
380
|
+
placeholder: merged.newProfilePlaceholder,
|
|
381
|
+
value: draftName,
|
|
382
|
+
onChange: (event) => setDraftName(event.target.value),
|
|
383
|
+
className: "h-8 pl-8"
|
|
384
|
+
}
|
|
385
|
+
)
|
|
386
|
+
] }),
|
|
387
|
+
/* @__PURE__ */ jsxs(
|
|
388
|
+
Button,
|
|
389
|
+
{
|
|
390
|
+
type: "submit",
|
|
391
|
+
size: "sm",
|
|
392
|
+
className: "h-8 gap-1 px-2.5",
|
|
393
|
+
disabled: !draftName.trim(),
|
|
394
|
+
"aria-label": merged.create,
|
|
395
|
+
children: [
|
|
396
|
+
/* @__PURE__ */ jsx(CreateIcon, { "aria-hidden": true }),
|
|
397
|
+
merged.create
|
|
398
|
+
]
|
|
399
|
+
}
|
|
400
|
+
)
|
|
401
|
+
]
|
|
402
|
+
}
|
|
403
|
+
)
|
|
404
|
+
]
|
|
405
|
+
}
|
|
406
|
+
)
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
) });
|
|
410
|
+
}
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
export { ProfileSwitcher };
|
|
414
|
+
//# sourceMappingURL=chunk-WY5TO6R4.js.map
|
|
415
|
+
//# sourceMappingURL=chunk-WY5TO6R4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/profile-switcher/ProfileSwitcher.tsx"],"names":["ProfileSwitcher"],"mappings":"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","file":"chunk-WY5TO6R4.js","sourcesContent":["import * as React from 'react'\nimport {\n Check,\n ChevronDown,\n Pencil,\n Plus,\n Star,\n Trash2,\n UserRound,\n type LucideIcon,\n} from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport { Input } from '../input/Input'\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover/Popover'\n\nexport interface ProfileItem {\n id: string\n name: string\n is_default?: boolean\n color?: string | null\n}\n\nexport interface ProfileSwitcherLabels {\n trigger: string\n panelTitle: string\n currentBadge: string\n defaultBadge: string\n newProfile: string\n newProfilePlaceholder: string\n create: string\n rename: (name: string) => string\n renamePlaceholder: string\n renameSubmit: string\n setDefault: (name: string) => string\n delete: (name: string) => string\n cancel: string\n loading: string\n empty: string\n}\n\nexport interface ProfileSwitcherIcons {\n trigger?: LucideIcon\n create?: LucideIcon\n rename?: LucideIcon\n setDefault?: LucideIcon\n delete?: LucideIcon\n empty?: LucideIcon\n}\n\nexport interface ProfileSwitcherProps {\n profiles: ProfileItem[]\n currentId: string | null\n onSelect: (profile: ProfileItem) => void\n onCreate: (name: string) => void | Promise<unknown>\n onRename: (profile: ProfileItem, name: string) => void | Promise<unknown>\n onDelete: (profile: ProfileItem) => void | Promise<unknown>\n /** When given, rows expose a \"make Default\" action (identity-auth §12). */\n onSetDefault?: (profile: ProfileItem) => void | Promise<unknown>\n loading?: boolean\n error?: string | null\n align?: 'start' | 'end'\n labels?: Partial<ProfileSwitcherLabels>\n icons?: ProfileSwitcherIcons\n className?: string\n}\n\nconst defaultLabels: ProfileSwitcherLabels = {\n trigger: 'Switch profile',\n panelTitle: 'Profiles',\n currentBadge: 'Current',\n defaultBadge: 'Default',\n newProfile: 'New profile',\n newProfilePlaceholder: 'Profile name',\n create: 'Create',\n rename: (name) => `Rename ${name}`,\n renamePlaceholder: 'Profile name',\n renameSubmit: 'Save',\n setDefault: (name) => `Make ${name} the default profile`,\n delete: (name) => `Delete ${name}`,\n cancel: 'Cancel',\n loading: 'Loading profiles…',\n empty: 'No profiles yet',\n}\n\nfunction ProfileAvatar({\n profile,\n size = 'sm',\n}: {\n profile: ProfileItem\n size?: 'sm' | 'md'\n}) {\n const letter = (profile.name.trim()[0] ?? '?').toUpperCase()\n return (\n <span\n aria-hidden\n className={cn(\n 'flex shrink-0 items-center justify-center rounded-full font-semibold ring-1 ring-[var(--as-border)]',\n size === 'md' ? 'size-8 text-xs' : 'size-6 text-[10px]',\n )}\n style={\n profile.color\n ? { backgroundColor: `${profile.color}22`, color: profile.color }\n : {\n backgroundColor: 'var(--as-secondary)',\n color: 'var(--as-muted-fg)',\n }\n }\n >\n {profile.color ? (\n letter\n ) : (\n <UserRound className={size === 'md' ? 'size-4' : 'size-3.5'} />\n )}\n </span>\n )\n}\n\n/** Status pills on a row: accent \"Current\" when active, muted \"Default\". */\nfunction ProfileRowBadges({\n isCurrent,\n isDefault,\n currentBadge,\n defaultBadge,\n}: {\n isCurrent: boolean\n isDefault: boolean\n currentBadge: string\n defaultBadge: string\n}) {\n if (!isCurrent && !isDefault) return null\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {isCurrent ? (\n <span\n className=\"inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium\"\n style={{\n backgroundColor: 'color-mix(in srgb, var(--as-accent) 12%, transparent)',\n color: 'var(--as-accent)',\n }}\n >\n <Check aria-hidden className=\"size-3\" />\n {currentBadge}\n </span>\n ) : null}\n {isDefault ? (\n <span className=\"inline-flex items-center rounded-full bg-[var(--as-secondary)] px-1.5 py-0.5 text-[10px] font-medium text-[var(--as-muted-fg)]\">\n {defaultBadge}\n </span>\n ) : null}\n </span>\n )\n}\n\nexport const ProfileSwitcher = React.forwardRef<HTMLDivElement, ProfileSwitcherProps>(\n function ProfileSwitcher(\n {\n profiles,\n currentId,\n onSelect,\n onCreate,\n onRename,\n onDelete,\n onSetDefault,\n loading = false,\n error = null,\n align = 'start',\n labels,\n icons,\n className,\n },\n ref,\n ) {\n const merged = { ...defaultLabels, ...labels }\n const TriggerIcon = icons?.trigger ?? UserRound\n const CreateIcon = icons?.create ?? Plus\n const RenameIcon = icons?.rename ?? Pencil\n const SetDefaultIcon = icons?.setDefault ?? Star\n const DeleteIcon = icons?.delete ?? Trash2\n const EmptyIcon = icons?.empty ?? UserRound\n\n const [open, setOpen] = React.useState(false)\n const [draftName, setDraftName] = React.useState('')\n const [renamingId, setRenamingId] = React.useState<string | null>(null)\n const [renameDraft, setRenameDraft] = React.useState('')\n const renameInputRef = React.useRef<HTMLInputElement>(null)\n\n const current = profiles.find((profile) => profile.id === currentId) ?? profiles[0] ?? null\n\n const close = React.useCallback(() => {\n setOpen(false)\n setRenamingId(null)\n setDraftName('')\n }, [])\n\n React.useEffect(() => {\n if (renamingId !== null) {\n renameInputRef.current?.focus()\n renameInputRef.current?.select()\n }\n }, [renamingId])\n\n const startRename = (profile: ProfileItem) => {\n setRenamingId(profile.id)\n setRenameDraft(profile.name)\n }\n\n const submitRename = async (profile: ProfileItem) => {\n const name = renameDraft.trim()\n if (!name || name === profile.name) {\n setRenamingId(null)\n return\n }\n await onRename(profile, name)\n setRenamingId(null)\n }\n\n const submitCreate = async (event: React.FormEvent) => {\n event.preventDefault()\n const name = draftName.trim()\n if (!name) return\n await onCreate(name)\n setDraftName('')\n }\n\n // Roving arrows: ↓/↑ (and Home/End) walk the profile rows without\n // leaving the panel; Tab keeps the DOM order (select → actions).\n const onListKeyDown = (event: React.KeyboardEvent<HTMLUListElement>) => {\n const rows = Array.from(\n event.currentTarget.querySelectorAll<HTMLButtonElement>('[data-profile-row]'),\n )\n if (rows.length === 0) return\n const index = rows.indexOf(document.activeElement as HTMLButtonElement)\n let next = -1\n if (event.key === 'ArrowDown') next = index < 0 ? 0 : Math.min(index + 1, rows.length - 1)\n else if (event.key === 'ArrowUp')\n next = index < 0 ? rows.length - 1 : Math.max(index - 1, 0)\n else if (event.key === 'Home') next = 0\n else if (event.key === 'End') next = rows.length - 1\n if (next >= 0) {\n event.preventDefault()\n rows[next]?.focus()\n }\n }\n\n return (\n <div ref={ref} data-as=\"profile-switcher\" className={cn('inline-block', className)}>\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next)\n if (!next) {\n setRenamingId(null)\n setDraftName('')\n }\n }}\n >\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-label={merged.trigger}\n data-testid=\"profile-trigger\"\n className=\"flex cursor-pointer items-center gap-2 rounded-full p-0.5 pr-2 transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n {current ? (\n <ProfileAvatar profile={current} size=\"md\" />\n ) : (\n <span\n aria-hidden\n className=\"flex size-8 shrink-0 items-center justify-center rounded-full ring-1 ring-[var(--as-border)]\"\n >\n <TriggerIcon className=\"size-4 text-[var(--as-muted-fg)]\" />\n </span>\n )}\n <span className=\"max-w-32 truncate text-sm font-medium\">\n {current ? current.name : merged.empty}\n </span>\n <ChevronDown\n aria-hidden\n className=\"size-3.5 text-[var(--as-muted-fg)] transition-transform duration-150 [[data-state=open]>&]:rotate-180\"\n />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align={align}\n role=\"dialog\"\n aria-label={merged.panelTitle}\n className=\"w-80 p-1.5 shadow-[var(--as-shadow-pop)] backdrop-blur-xl\"\n onEscapeKeyDown={(event) => {\n // Escape cancels an inline rename first, closes the panel\n // only on the second press.\n if (renamingId !== null) event.preventDefault()\n }}\n >\n <div className=\"flex items-center justify-between px-2 pb-1 pt-1\">\n <span className=\"text-[11px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]\">\n {merged.panelTitle}\n </span>\n {profiles.length > 0 ? (\n <span className=\"text-[11px] tabular-nums text-[var(--as-muted-fg)]\">\n {profiles.length}\n </span>\n ) : null}\n </div>\n {loading ? (\n <p\n className=\"as-anim-fade px-2 py-3 text-sm text-[var(--as-muted-fg)]\"\n role=\"status\"\n >\n {merged.loading}\n </p>\n ) : profiles.length === 0 ? (\n <p className=\"flex items-center gap-2 px-2 py-3 text-sm text-[var(--as-muted-fg)]\">\n <EmptyIcon aria-hidden className=\"size-4\" />\n {merged.empty}\n </p>\n ) : (\n <ul\n className=\"max-h-72 space-y-0.5 overflow-y-auto\"\n onKeyDown={onListKeyDown}\n >\n {profiles.map((profile) => {\n const isCurrent = current !== null && profile.id === current.id\n return (\n <li\n key={profile.id}\n className=\"flex items-center gap-1 rounded-[var(--as-radius-sm)] px-0.5 py-0.5 hover:bg-[var(--as-secondary)]\"\n >\n {renamingId === profile.id ? (\n <form\n className=\"flex w-full items-center gap-1 py-0.5\"\n onSubmit={(event) => {\n event.preventDefault()\n void submitRename(profile)\n }}\n >\n <Input\n ref={renameInputRef}\n aria-label={merged.rename(profile.name)}\n placeholder={merged.renamePlaceholder}\n value={renameDraft}\n onChange={(event) => setRenameDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n setRenamingId(null)\n }\n }}\n className=\"h-8 flex-1\"\n />\n <Button\n type=\"submit\"\n size=\"sm\"\n className=\"h-8\"\n disabled={!renameDraft.trim()}\n aria-label={merged.renameSubmit}\n >\n {merged.renameSubmit}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-8\"\n aria-label={merged.cancel}\n onClick={() => setRenamingId(null)}\n >\n {merged.cancel}\n </Button>\n </form>\n ) : (\n <>\n <button\n type=\"button\"\n aria-current={isCurrent || undefined}\n data-profile-row\n data-testid={`profile-option-${profile.id}`}\n className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-2.5 rounded-[var(--as-radius-sm)] px-1.5 py-1.5 text-left text-sm outline-none transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] aria-current:bg-[color-mix(in_srgb,var(--as-accent)_8%,transparent)]\"\n onClick={() => {\n onSelect(profile)\n close()\n }}\n >\n <ProfileAvatar profile={profile} size=\"md\" />\n <span className=\"min-w-0 flex-1 truncate font-medium\">\n {profile.name}\n </span>\n <ProfileRowBadges\n isCurrent={isCurrent}\n isDefault={Boolean(profile.is_default)}\n currentBadge={merged.currentBadge}\n defaultBadge={merged.defaultBadge}\n />\n </button>\n <span className=\"flex shrink-0 items-center gap-0.5 pr-0.5\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"ghost\"\n className=\"size-7 rounded-[var(--as-radius-sm)]\"\n aria-label={merged.rename(profile.name)}\n title={merged.rename(profile.name)}\n onClick={() => startRename(profile)}\n >\n <RenameIcon aria-hidden />\n </Button>\n {onSetDefault && !profile.is_default ? (\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"ghost\"\n className=\"size-7 rounded-[var(--as-radius-sm)]\"\n aria-label={merged.setDefault(profile.name)}\n title={merged.setDefault(profile.name)}\n onClick={() => void onSetDefault(profile)}\n >\n <SetDefaultIcon aria-hidden />\n </Button>\n ) : null}\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"ghost\"\n className=\"size-7 rounded-[var(--as-radius-sm)] hover:text-[var(--as-danger)]\"\n aria-label={merged.delete(profile.name)}\n title={merged.delete(profile.name)}\n onClick={() => void onDelete(profile)}\n >\n <DeleteIcon aria-hidden />\n </Button>\n </span>\n </>\n )}\n </li>\n )\n })}\n </ul>\n )}\n {error ? (\n <p\n role=\"alert\"\n className=\"mx-1 mt-1 rounded-[var(--as-radius-sm)] bg-[color-mix(in_srgb,var(--as-danger)_10%,transparent)] px-2 py-1 text-xs text-[var(--as-danger)]\"\n >\n {error}\n </p>\n ) : null}\n <form\n className=\"mt-1 flex items-center gap-1.5 border-t border-[var(--as-border)] p-1.5 pt-2\"\n onSubmit={(event) => {\n void submitCreate(event)\n }}\n >\n <div className=\"relative min-w-0 flex-1\">\n <CreateIcon\n aria-hidden\n className=\"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-[var(--as-muted-fg)]\"\n />\n <Input\n aria-label={merged.newProfile}\n placeholder={merged.newProfilePlaceholder}\n value={draftName}\n onChange={(event) => setDraftName(event.target.value)}\n className=\"h-8 pl-8\"\n />\n </div>\n <Button\n type=\"submit\"\n size=\"sm\"\n className=\"h-8 gap-1 px-2.5\"\n disabled={!draftName.trim()}\n aria-label={merged.create}\n >\n <CreateIcon aria-hidden />\n {merged.create}\n </Button>\n </form>\n </PopoverContent>\n </Popover>\n </div>\n )\n },\n)\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MarkdownSurface } from './chunk-HQ3X5SVR.js';
|
|
2
|
-
import { ChatMessage } from './chunk-
|
|
2
|
+
import { ChatMessage } from './chunk-C5JZCCU7.js';
|
|
3
3
|
import { cn } from './chunk-RVVXVTH3.js';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { ArrowDown } from 'lucide-react';
|
|
@@ -169,5 +169,5 @@ var ChatTranscript = React.forwardRef(
|
|
|
169
169
|
);
|
|
170
170
|
|
|
171
171
|
export { ChatTranscript };
|
|
172
|
-
//# sourceMappingURL=chunk-
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
172
|
+
//# sourceMappingURL=chunk-XOODPYJ3.js.map
|
|
173
|
+
//# sourceMappingURL=chunk-XOODPYJ3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/chat-transcript/ChatTranscript.tsx"],"names":["ChatTranscript"],"mappings":"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","file":"chunk-MTFHU6QY.js","sourcesContent":["import * as React from 'react'\nimport { ArrowDown } from 'lucide-react'\nimport { useVirtualizer } from '@tanstack/react-virtual'\n\nimport { cn } from '../../lib/utils'\nimport { ChatMessage } from '../chat-message/ChatMessage'\nimport { MarkdownSurface } from '../chat-markdown/MarkdownSurface'\nimport type { ChatMessageView } from '../chat-core/types'\n\nexport interface ChatTranscriptLabels {\n log: string\n scrollToBottom: string\n empty: string\n replied: string\n}\n\nexport interface ChatTranscriptProps {\n items: ChatMessageView[]\n /** Override the default `ChatMessage` + `MarkdownSurface` rendering. */\n renderItem?: (message: ChatMessageView, index: number) => React.ReactNode\n /** Streaming tail — the live turn bubble (or any node). */\n live?: React.ReactNode\n emptyState?: React.ReactNode\n /** Stick to bottom while the user hasn't scrolled away. Default true. */\n autoScroll?: boolean\n /** Distance from the bottom that still counts as \"at the bottom\". Default 120 px. */\n scrollThresholdPx?: number\n /** Virtualize long transcripts (dynamic row measurement). Default false. */\n virtualized?: boolean\n labels?: Partial<ChatTranscriptLabels>\n className?: string\n}\n\nfunction defaultRenderItem(message: ChatMessageView) {\n return (\n <ChatMessage\n role={message.role}\n status={message.status}\n content={<MarkdownSurface value={message.content} streaming={message.status === 'streaming'} />}\n variants={message.variants}\n />\n )\n}\n\n/**\n * The conversation list: `role=\"log\"` with polite turn-completion\n * announcements, stick-to-bottom auto-scroll with a jump-to-latest pill,\n * optional virtualization for thousand-message threads.\n */\nexport const ChatTranscript = React.forwardRef<HTMLDivElement, ChatTranscriptProps>(\n function ChatTranscript(\n {\n items,\n renderItem = defaultRenderItem,\n live,\n emptyState,\n autoScroll = true,\n scrollThresholdPx = 120,\n virtualized = false,\n labels,\n className,\n },\n ref,\n ) {\n const scrollRef = React.useRef<HTMLDivElement | null>(null)\n const atBottomRef = React.useRef(true)\n const lastScrollTopRef = React.useRef(0)\n const lastTouchYRef = React.useRef<number | null>(null)\n const [showJump, setShowJump] = React.useState(false)\n const [announcement, setAnnouncement] = React.useState('')\n const previousCountRef = React.useRef(-1)\n\n const onScroll = () => {\n const element = scrollRef.current\n if (element === null) {\n return\n }\n const distance = element.scrollHeight - element.scrollTop - element.clientHeight\n const goingUp = element.scrollTop < lastScrollTopRef.current\n lastScrollTopRef.current = element.scrollTop\n const atBottom = distance <= scrollThresholdPx && !(goingUp && distance > 0)\n atBottomRef.current = atBottom\n setShowJump(element.scrollHeight > element.clientHeight && !atBottom)\n }\n\n /**\n * Fast streams re-pin the bottom on every render (rAF), which erases\n * a partial upward scroll before it can cross `scrollThresholdPx` —\n * so user scroll-up INTENT cancels stickiness synchronously here\n * (wheel up, touch drag up, scroll-up keys), and any upward scroll\n * event with distance left also breaks it. Scrolling back to the\n * bottom (or the jump pill) re-arms the follow.\n */\n const cancelStick = () => {\n const element = scrollRef.current\n if (element === null) {\n return\n }\n atBottomRef.current = false\n setShowJump(element.scrollHeight > element.clientHeight)\n }\n\n const onWheel = (event: React.WheelEvent<HTMLDivElement>) => {\n if (event.deltaY < 0) {\n cancelStick()\n }\n }\n\n const onTouchStart = (event: React.TouchEvent<HTMLDivElement>) => {\n lastTouchYRef.current = event.touches[0]?.clientY ?? null\n }\n\n const onTouchMove = (event: React.TouchEvent<HTMLDivElement>) => {\n const y = event.touches[0]?.clientY\n if (y === undefined) {\n return\n }\n if (lastTouchYRef.current !== null && y > lastTouchYRef.current) {\n cancelStick()\n }\n lastTouchYRef.current = y\n }\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (\n event.key === 'ArrowUp' ||\n event.key === 'PageUp' ||\n event.key === 'Home' ||\n (event.key === ' ' && event.shiftKey)\n ) {\n cancelStick()\n }\n }\n\n React.useEffect(() => {\n const element = scrollRef.current\n if (element === null || !autoScroll || !atBottomRef.current) {\n return\n }\n const frame = requestAnimationFrame(() => {\n element.scrollTop = element.scrollHeight\n })\n return () => cancelAnimationFrame(frame)\n })\n\n React.useEffect(() => {\n if (previousCountRef.current === -1) {\n previousCountRef.current = items.length\n return\n }\n if (items.length > previousCountRef.current) {\n const added = items[items.length - 1]\n previousCountRef.current = items.length\n if (added && added.role !== 'user') {\n setAnnouncement(labels?.replied ?? 'Assistant replied')\n }\n return\n }\n previousCountRef.current = items.length\n }, [items, labels])\n\n const scrollToBottom = () => {\n const element = scrollRef.current\n if (element !== null) {\n element.scrollTo({ top: element.scrollHeight, behavior: 'smooth' })\n }\n }\n\n const rowCount = items.length + (live !== undefined ? 1 : 0)\n const virtualizer = useVirtualizer({\n count: virtualized ? rowCount : 0,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => 120,\n overscan: 8,\n initialRect: { width: 480, height: 600 },\n })\n\n return (\n <div ref={ref} data-as=\"chat-transcript\" className={cn('relative min-h-0 flex-1', className)}>\n <div\n ref={scrollRef}\n onScroll={onScroll}\n onWheel={onWheel}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onKeyDown={onKeyDown}\n role=\"log\"\n aria-label={labels?.log ?? 'Conversation'}\n aria-busy={live !== undefined}\n className=\"h-full overflow-y-auto overscroll-contain px-1 py-2\"\n >\n {items.length === 0 && live === undefined ? (\n <div className=\"flex h-full min-h-40 items-center justify-center p-4 text-sm text-[var(--as-muted-fg)]\">\n {emptyState ?? (labels?.empty ?? 'Start the conversation')}\n </div>\n ) : virtualized ? (\n <div style={{ height: virtualizer.getTotalSize(), position: 'relative' }}>\n {virtualizer.getVirtualItems().map((row) => {\n const isLive = row.index >= items.length\n const node = isLive ? live : renderItem(items[row.index]!, row.index)\n return (\n <div\n key={row.key}\n data-index={row.index}\n ref={virtualizer.measureElement}\n style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${row.start}px)` }}\n className=\"px-2 py-1.5\"\n >\n {node}\n </div>\n )\n })}\n </div>\n ) : (\n <div className=\"flex flex-col gap-3 px-2\">\n {items.map((message, index) => (\n <div key={message.id}>{renderItem(message, index)}</div>\n ))}\n {live !== undefined ? <div data-as=\"chat-transcript-live\">{live}</div> : null}\n </div>\n )}\n </div>\n <div aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </div>\n {showJump ? (\n <button\n type=\"button\"\n onClick={scrollToBottom}\n aria-label={labels?.scrollToBottom ?? 'Scroll to latest'}\n title={labels?.scrollToBottom ?? 'Scroll to latest'}\n className=\"absolute bottom-3 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-fg)] shadow-[var(--as-shadow-2)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <ArrowDown className=\"size-4\" aria-hidden />\n </button>\n ) : null}\n </div>\n )\n },\n)\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/chat-transcript/ChatTranscript.tsx"],"names":["ChatTranscript"],"mappings":"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","file":"chunk-XOODPYJ3.js","sourcesContent":["import * as React from 'react'\nimport { ArrowDown } from 'lucide-react'\nimport { useVirtualizer } from '@tanstack/react-virtual'\n\nimport { cn } from '../../lib/utils'\nimport { ChatMessage } from '../chat-message/ChatMessage'\nimport { MarkdownSurface } from '../chat-markdown/MarkdownSurface'\nimport type { ChatMessageView } from '../chat-core/types'\n\nexport interface ChatTranscriptLabels {\n log: string\n scrollToBottom: string\n empty: string\n replied: string\n}\n\nexport interface ChatTranscriptProps {\n items: ChatMessageView[]\n /** Override the default `ChatMessage` + `MarkdownSurface` rendering. */\n renderItem?: (message: ChatMessageView, index: number) => React.ReactNode\n /** Streaming tail — the live turn bubble (or any node). */\n live?: React.ReactNode\n emptyState?: React.ReactNode\n /** Stick to bottom while the user hasn't scrolled away. Default true. */\n autoScroll?: boolean\n /** Distance from the bottom that still counts as \"at the bottom\". Default 120 px. */\n scrollThresholdPx?: number\n /** Virtualize long transcripts (dynamic row measurement). Default false. */\n virtualized?: boolean\n labels?: Partial<ChatTranscriptLabels>\n className?: string\n}\n\nfunction defaultRenderItem(message: ChatMessageView) {\n return (\n <ChatMessage\n role={message.role}\n status={message.status}\n content={<MarkdownSurface value={message.content} streaming={message.status === 'streaming'} />}\n variants={message.variants}\n />\n )\n}\n\n/**\n * The conversation list: `role=\"log\"` with polite turn-completion\n * announcements, stick-to-bottom auto-scroll with a jump-to-latest pill,\n * optional virtualization for thousand-message threads.\n */\nexport const ChatTranscript = React.forwardRef<HTMLDivElement, ChatTranscriptProps>(\n function ChatTranscript(\n {\n items,\n renderItem = defaultRenderItem,\n live,\n emptyState,\n autoScroll = true,\n scrollThresholdPx = 120,\n virtualized = false,\n labels,\n className,\n },\n ref,\n ) {\n const scrollRef = React.useRef<HTMLDivElement | null>(null)\n const atBottomRef = React.useRef(true)\n const lastScrollTopRef = React.useRef(0)\n const lastTouchYRef = React.useRef<number | null>(null)\n const [showJump, setShowJump] = React.useState(false)\n const [announcement, setAnnouncement] = React.useState('')\n const previousCountRef = React.useRef(-1)\n\n const onScroll = () => {\n const element = scrollRef.current\n if (element === null) {\n return\n }\n const distance = element.scrollHeight - element.scrollTop - element.clientHeight\n const goingUp = element.scrollTop < lastScrollTopRef.current\n lastScrollTopRef.current = element.scrollTop\n const atBottom = distance <= scrollThresholdPx && !(goingUp && distance > 0)\n atBottomRef.current = atBottom\n setShowJump(element.scrollHeight > element.clientHeight && !atBottom)\n }\n\n /**\n * Fast streams re-pin the bottom on every render (rAF), which erases\n * a partial upward scroll before it can cross `scrollThresholdPx` —\n * so user scroll-up INTENT cancels stickiness synchronously here\n * (wheel up, touch drag up, scroll-up keys), and any upward scroll\n * event with distance left also breaks it. Scrolling back to the\n * bottom (or the jump pill) re-arms the follow.\n */\n const cancelStick = () => {\n const element = scrollRef.current\n if (element === null) {\n return\n }\n atBottomRef.current = false\n setShowJump(element.scrollHeight > element.clientHeight)\n }\n\n const onWheel = (event: React.WheelEvent<HTMLDivElement>) => {\n if (event.deltaY < 0) {\n cancelStick()\n }\n }\n\n const onTouchStart = (event: React.TouchEvent<HTMLDivElement>) => {\n lastTouchYRef.current = event.touches[0]?.clientY ?? null\n }\n\n const onTouchMove = (event: React.TouchEvent<HTMLDivElement>) => {\n const y = event.touches[0]?.clientY\n if (y === undefined) {\n return\n }\n if (lastTouchYRef.current !== null && y > lastTouchYRef.current) {\n cancelStick()\n }\n lastTouchYRef.current = y\n }\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (\n event.key === 'ArrowUp' ||\n event.key === 'PageUp' ||\n event.key === 'Home' ||\n (event.key === ' ' && event.shiftKey)\n ) {\n cancelStick()\n }\n }\n\n React.useEffect(() => {\n const element = scrollRef.current\n if (element === null || !autoScroll || !atBottomRef.current) {\n return\n }\n const frame = requestAnimationFrame(() => {\n element.scrollTop = element.scrollHeight\n })\n return () => cancelAnimationFrame(frame)\n })\n\n React.useEffect(() => {\n if (previousCountRef.current === -1) {\n previousCountRef.current = items.length\n return\n }\n if (items.length > previousCountRef.current) {\n const added = items[items.length - 1]\n previousCountRef.current = items.length\n if (added && added.role !== 'user') {\n setAnnouncement(labels?.replied ?? 'Assistant replied')\n }\n return\n }\n previousCountRef.current = items.length\n }, [items, labels])\n\n const scrollToBottom = () => {\n const element = scrollRef.current\n if (element !== null) {\n element.scrollTo({ top: element.scrollHeight, behavior: 'smooth' })\n }\n }\n\n const rowCount = items.length + (live !== undefined ? 1 : 0)\n const virtualizer = useVirtualizer({\n count: virtualized ? rowCount : 0,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => 120,\n overscan: 8,\n initialRect: { width: 480, height: 600 },\n })\n\n return (\n <div ref={ref} data-as=\"chat-transcript\" className={cn('relative min-h-0 flex-1', className)}>\n <div\n ref={scrollRef}\n onScroll={onScroll}\n onWheel={onWheel}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onKeyDown={onKeyDown}\n role=\"log\"\n aria-label={labels?.log ?? 'Conversation'}\n aria-busy={live !== undefined}\n className=\"h-full overflow-y-auto overscroll-contain px-1 py-2\"\n >\n {items.length === 0 && live === undefined ? (\n <div className=\"flex h-full min-h-40 items-center justify-center p-4 text-sm text-[var(--as-muted-fg)]\">\n {emptyState ?? (labels?.empty ?? 'Start the conversation')}\n </div>\n ) : virtualized ? (\n <div style={{ height: virtualizer.getTotalSize(), position: 'relative' }}>\n {virtualizer.getVirtualItems().map((row) => {\n const isLive = row.index >= items.length\n const node = isLive ? live : renderItem(items[row.index]!, row.index)\n return (\n <div\n key={row.key}\n data-index={row.index}\n ref={virtualizer.measureElement}\n style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${row.start}px)` }}\n className=\"px-2 py-1.5\"\n >\n {node}\n </div>\n )\n })}\n </div>\n ) : (\n <div className=\"flex flex-col gap-3 px-2\">\n {items.map((message, index) => (\n <div key={message.id}>{renderItem(message, index)}</div>\n ))}\n {live !== undefined ? <div data-as=\"chat-transcript-live\">{live}</div> : null}\n </div>\n )}\n </div>\n <div aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </div>\n {showJump ? (\n <button\n type=\"button\"\n onClick={scrollToBottom}\n aria-label={labels?.scrollToBottom ?? 'Scroll to latest'}\n title={labels?.scrollToBottom ?? 'Scroll to latest'}\n className=\"absolute bottom-3 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-fg)] shadow-[var(--as-shadow-2)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <ArrowDown className=\"size-4\" aria-hidden />\n </button>\n ) : null}\n </div>\n )\n },\n)\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1067,11 +1067,7 @@ interface UserMenuIcons {
|
|
|
1067
1067
|
interface UserMenuProps {
|
|
1068
1068
|
/** Structured identity — rendered in the trigger and the panel header. */
|
|
1069
1069
|
user?: UserMenuUser;
|
|
1070
|
-
/**
|
|
1071
|
-
name?: string;
|
|
1072
|
-
email?: string;
|
|
1073
|
-
avatarUrl?: string;
|
|
1074
|
-
/** Fallback disc text when no avatarUrl; derived from `name` when omitted. */
|
|
1070
|
+
/** Fallback disc text when no avatarUrl; derived from `user.name` when omitted. */
|
|
1075
1071
|
initials?: string;
|
|
1076
1072
|
/** Badge text for the role (app-translated); falls back to `user.role`. */
|
|
1077
1073
|
roleBadge?: string;
|
|
@@ -1082,20 +1078,27 @@ interface UserMenuProps {
|
|
|
1082
1078
|
switcher?: React.ReactNode;
|
|
1083
1079
|
/** Status pill rendered under the identity block (e.g. "Synced"). */
|
|
1084
1080
|
status?: UserMenuStatus;
|
|
1085
|
-
/** Controlled theme preference — checked state of the theme
|
|
1081
|
+
/** Controlled theme preference — checked state of the theme items. */
|
|
1086
1082
|
theme?: UserMenuTheme;
|
|
1087
1083
|
onThemeChange?: (theme: UserMenuTheme) => void;
|
|
1088
1084
|
/**
|
|
1089
|
-
* Labels for the theme
|
|
1090
|
-
*
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
1085
|
+
* Labels for the theme options — with all three (`light`/`dark`/`system`)
|
|
1086
|
+
* they render as a checkable "Theme" submenu whose trigger shows the
|
|
1087
|
+
* active theme (mirroring the Languages submenu); fewer labels render as
|
|
1088
|
+
* inline checkable rows (provide `dark` only for a single "Dark Mode"
|
|
1089
|
+
* toggle row).
|
|
1093
1090
|
*/
|
|
1094
1091
|
themeLabels?: {
|
|
1095
1092
|
light?: string;
|
|
1096
1093
|
dark?: string;
|
|
1097
1094
|
system?: string;
|
|
1098
1095
|
};
|
|
1096
|
+
/**
|
|
1097
|
+
* Layout of the theme section. `'auto'` (default) renders the submenu
|
|
1098
|
+
* when all three labels are present and inline rows otherwise;
|
|
1099
|
+
* `'submenu'` / `'inline'` force the layout regardless of label count.
|
|
1100
|
+
*/
|
|
1101
|
+
themeLayout?: 'auto' | 'submenu' | 'inline';
|
|
1099
1102
|
/** Controlled language — checked state of the language rows. */
|
|
1100
1103
|
language?: string;
|
|
1101
1104
|
onLanguageChange?: (id: string) => void;
|
|
@@ -1112,6 +1115,7 @@ interface UserMenuProps {
|
|
|
1112
1115
|
openMenu?: string;
|
|
1113
1116
|
account?: string;
|
|
1114
1117
|
language?: string;
|
|
1118
|
+
theme?: string;
|
|
1115
1119
|
};
|
|
1116
1120
|
icons?: UserMenuIcons;
|
|
1117
1121
|
className?: string;
|
|
@@ -2377,6 +2381,12 @@ interface ChatMessageActions {
|
|
|
2377
2381
|
onRetry?: () => void;
|
|
2378
2382
|
/** Extra icon actions (app-specific). */
|
|
2379
2383
|
extras?: ChatMessageAction[];
|
|
2384
|
+
/**
|
|
2385
|
+
* Extra node rendered inside the error card next to the Retry button —
|
|
2386
|
+
* e.g. an "Open AI settings" link when the error is a not-configured
|
|
2387
|
+
* failure. Rendered only while the error card is visible.
|
|
2388
|
+
*/
|
|
2389
|
+
errorExtra?: React.ReactNode;
|
|
2380
2390
|
}
|
|
2381
2391
|
interface ChatMessageLabels {
|
|
2382
2392
|
copy: string;
|