@iota-uz/sdk 0.4.22 → 0.4.24
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/applet/host.cjs +97 -10
- package/dist/applet/host.cjs.map +1 -1
- package/dist/applet/host.d.cts +9 -1
- package/dist/applet/host.d.ts +9 -1
- package/dist/applet/host.mjs +97 -10
- package/dist/applet/host.mjs.map +1 -1
- package/dist/bichat/index.cjs +1309 -379
- package/dist/bichat/index.cjs.map +1 -1
- package/dist/bichat/index.d.cts +1109 -827
- package/dist/bichat/index.d.ts +1109 -827
- package/dist/bichat/index.mjs +1308 -382
- package/dist/bichat/index.mjs.map +1 -1
- package/dist/index.cjs +97 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +97 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/tailwind/compiled.css +1 -1
package/dist/bichat/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import React, { createContext, memo, useRef, useEffect, useCallback, useState, u
|
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import ReactApexChart from 'react-apexcharts';
|
|
4
4
|
import ApexCharts from 'apexcharts';
|
|
5
|
-
import { CaretUp, CaretDown, DotsThreeVertical, Check, Copy, X, Columns, ArrowsIn, ArrowsOut, Warning, ArrowClockwise, Paperclip, PaperPlaneRight, ChartBar, FileText, Lightbulb, CircleNotch, ArrowUUpLeft, PencilSimple, Bookmark, ArrowsClockwise, Archive, Trash, DotsThree, Image, MagnifyingGlass, DownloadSimple, ArrowCounterClockwise, Bug, ArrowUp, ArrowDown, Stack, ImageBroken, CaretLeft, CaretRight, Info, CheckCircle, XCircle, Spinner, WarningCircle, FilePdf, FileXls, FileCsv, FileDoc, FileCode, File as File$1, MagnifyingGlassMinus, MagnifyingGlassPlus, Download, ChatCircleDots, PencilSimpleLine, ArrowLeft, PaperPlaneTilt, ArrowRight, Timer, Lightning, Database, ArrowSquareOut, Wrench, ClockCounterClockwise, Package, Plus, ArrowsCounterClockwise, ChatCircle, Gear, Users, List, CaretLineLeft, CaretLineRight, Code, Table, SpinnerGap, FloppyDisk, Sidebar } from '@phosphor-icons/react';
|
|
5
|
+
import { CaretUp, CaretDown, DotsThreeVertical, Check, Copy, X, Columns, ArrowsIn, ArrowsOut, Warning, ArrowClockwise, Paperclip, PaperPlaneRight, ChartBar, FileText, Lightbulb, CircleNotch, ArrowUUpLeft, PencilSimple, Bookmark, ArrowsClockwise, Archive, Trash, UsersThree, DotsThree, Image, MagnifyingGlass, DownloadSimple, ArrowCounterClockwise, Bug, ArrowUp, ArrowDown, Stack, ImageBroken, CaretLeft, CaretRight, Info, CheckCircle, XCircle, Spinner, WarningCircle, FilePdf, FileXls, FileCsv, FileDoc, FileCode, File as File$1, MagnifyingGlassMinus, MagnifyingGlassPlus, Download, ChatCircleDots, PencilSimpleLine, ArrowLeft, PaperPlaneTilt, ArrowRight, Timer, Lightning, Database, ArrowSquareOut, Wrench, ClockCounterClockwise, Package, Plus, Crown, UserPlus, ArrowsCounterClockwise, ChatCircle, Gear, Users, List, CaretLineLeft, CaretLineRight, Code, Table, SpinnerGap, FloppyDisk, ShareNetwork, Sidebar } from '@phosphor-icons/react';
|
|
6
6
|
import { Prism } from 'react-syntax-highlighter';
|
|
7
7
|
import { vscDarkPlus, vs } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
|
8
8
|
import ReactMarkdown from 'react-markdown';
|
|
@@ -12,7 +12,7 @@ import rehypeKatex from 'rehype-katex';
|
|
|
12
12
|
import { motion, useMotionValue, useTransform, AnimatePresence, MotionConfig, useReducedMotion } from 'framer-motion';
|
|
13
13
|
import 'react-dom/client';
|
|
14
14
|
import { differenceInMinutes, differenceInHours, differenceInDays, format, isSameDay, startOfDay, isToday, isYesterday } from 'date-fns';
|
|
15
|
-
import { Menu, MenuButton, MenuItems, MenuItem, Popover, PopoverButton, PopoverPanel, Dialog, DialogBackdrop, DialogPanel,
|
|
15
|
+
import { Menu, MenuButton, MenuItems, MenuItem, Popover, PopoverButton, PopoverPanel, Dialog, DialogBackdrop, DialogPanel, Transition } from '@headlessui/react';
|
|
16
16
|
import { createPortal } from 'react-dom';
|
|
17
17
|
|
|
18
18
|
var __defProp = Object.defineProperty;
|
|
@@ -1868,7 +1868,7 @@ function pendingQuestionFromInterrupt(interrupt, fallbackTurnId) {
|
|
|
1868
1868
|
options: Array.isArray(question.options) ? question.options.filter((option) => !!option && typeof option.id === "string").map((option) => ({
|
|
1869
1869
|
id: option.id,
|
|
1870
1870
|
label: typeof option.label === "string" ? option.label : "",
|
|
1871
|
-
value:
|
|
1871
|
+
value: option.id
|
|
1872
1872
|
})) : []
|
|
1873
1873
|
})) : [];
|
|
1874
1874
|
return {
|
|
@@ -3012,14 +3012,9 @@ var ChatMachine = class {
|
|
|
3012
3012
|
if (!curSessionId || !curPendingQuestion) {
|
|
3013
3013
|
return;
|
|
3014
3014
|
}
|
|
3015
|
-
const previousTurns = this.state.messaging.turns;
|
|
3016
3015
|
this._updateMessaging({ loading: true });
|
|
3017
3016
|
this._updateSession({ error: null, errorRetryable: false });
|
|
3018
3017
|
const previousPendingQuestion = curPendingQuestion;
|
|
3019
|
-
this._updateMessaging({
|
|
3020
|
-
pendingQuestion: null,
|
|
3021
|
-
turns: applyTurnLifecycleForPendingQuestion(previousTurns, null)
|
|
3022
|
-
});
|
|
3023
3018
|
try {
|
|
3024
3019
|
const result = await this.dataSource.submitQuestionAnswers(
|
|
3025
3020
|
curSessionId,
|
|
@@ -3030,60 +3025,28 @@ var ChatMachine = class {
|
|
|
3030
3025
|
return;
|
|
3031
3026
|
}
|
|
3032
3027
|
if (result.success) {
|
|
3033
|
-
if (
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
});
|
|
3047
|
-
this._updateSession({
|
|
3048
|
-
error: "Failed to fully refresh session. Showing last known messages.",
|
|
3049
|
-
errorRetryable: true
|
|
3050
|
-
});
|
|
3051
|
-
this._updateMessaging({
|
|
3052
|
-
pendingQuestion: fetchResult.pendingQuestion || null,
|
|
3053
|
-
turns: applyTurnLifecycleForPendingQuestion(
|
|
3054
|
-
previousTurns,
|
|
3055
|
-
fetchResult.pendingQuestion || null
|
|
3056
|
-
)
|
|
3057
|
-
});
|
|
3058
|
-
} else {
|
|
3059
|
-
this._setTurnsFromFetch(fetchResult.turns, fetchResult.pendingQuestion || null);
|
|
3060
|
-
}
|
|
3061
|
-
} else {
|
|
3062
|
-
this._updateSession({ error: "Failed to load updated session", errorRetryable: true });
|
|
3063
|
-
}
|
|
3064
|
-
} catch (fetchErr) {
|
|
3065
|
-
if (this.disposed) {
|
|
3066
|
-
return;
|
|
3067
|
-
}
|
|
3068
|
-
const normalized = normalizeRPCError(fetchErr, "Failed to load updated session");
|
|
3069
|
-
this._updateSession({ error: normalized.userMessage, errorRetryable: true });
|
|
3028
|
+
if (result.data) {
|
|
3029
|
+
this._updateSession({ session: result.data.session });
|
|
3030
|
+
this._setTurnsFromFetch(result.data.turns, result.data.pendingQuestion || null);
|
|
3031
|
+
} else if (curSessionId !== "new") {
|
|
3032
|
+
const fetchResult = await this.dataSource.fetchSession(curSessionId);
|
|
3033
|
+
if (this.disposed) {
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
if (fetchResult) {
|
|
3037
|
+
this._updateSession({ session: fetchResult.session });
|
|
3038
|
+
this._setTurnsFromFetch(fetchResult.turns, fetchResult.pendingQuestion || null);
|
|
3039
|
+
} else {
|
|
3040
|
+
this._updateSession({ error: "Failed to load updated session", errorRetryable: true });
|
|
3070
3041
|
}
|
|
3071
3042
|
}
|
|
3072
3043
|
} else {
|
|
3073
|
-
this._updateMessaging({
|
|
3074
|
-
pendingQuestion: previousPendingQuestion,
|
|
3075
|
-
turns: applyTurnLifecycleForPendingQuestion(previousTurns, previousPendingQuestion)
|
|
3076
|
-
});
|
|
3077
3044
|
this._updateSession({ error: result.error || "Failed to submit answers", errorRetryable: false });
|
|
3078
3045
|
}
|
|
3079
3046
|
} catch (err) {
|
|
3080
3047
|
if (this.disposed) {
|
|
3081
3048
|
return;
|
|
3082
3049
|
}
|
|
3083
|
-
this._updateMessaging({
|
|
3084
|
-
pendingQuestion: previousPendingQuestion,
|
|
3085
|
-
turns: applyTurnLifecycleForPendingQuestion(previousTurns, previousPendingQuestion)
|
|
3086
|
-
});
|
|
3087
3050
|
const normalized = normalizeRPCError(err, "Failed to submit answers");
|
|
3088
3051
|
this._updateSession({ error: normalized.userMessage, errorRetryable: normalized.retryable });
|
|
3089
3052
|
} finally {
|
|
@@ -3328,12 +3291,151 @@ function useBranding() {
|
|
|
3328
3291
|
}, [context.extensions?.branding, t]);
|
|
3329
3292
|
return branding;
|
|
3330
3293
|
}
|
|
3331
|
-
function
|
|
3294
|
+
function hashString(str) {
|
|
3295
|
+
let hash = 0;
|
|
3296
|
+
for (let i = 0; i < str.length; i++) {
|
|
3297
|
+
const char = str.charCodeAt(i);
|
|
3298
|
+
hash = (hash << 5) - hash + char;
|
|
3299
|
+
hash = hash & hash;
|
|
3300
|
+
}
|
|
3301
|
+
return Math.abs(hash);
|
|
3302
|
+
}
|
|
3303
|
+
var colorPalette = [
|
|
3304
|
+
{ bg: "bg-blue-500", text: "text-white" },
|
|
3305
|
+
{ bg: "bg-green-500", text: "text-white" },
|
|
3306
|
+
{ bg: "bg-purple-500", text: "text-white" },
|
|
3307
|
+
{ bg: "bg-pink-500", text: "text-white" },
|
|
3308
|
+
{ bg: "bg-indigo-500", text: "text-white" },
|
|
3309
|
+
{ bg: "bg-teal-500", text: "text-white" },
|
|
3310
|
+
{ bg: "bg-orange-500", text: "text-white" },
|
|
3311
|
+
{ bg: "bg-cyan-500", text: "text-white" },
|
|
3312
|
+
{ bg: "bg-amber-500", text: "text-white" },
|
|
3313
|
+
{ bg: "bg-lime-500", text: "text-white" }
|
|
3314
|
+
];
|
|
3315
|
+
var sizeClasses = {
|
|
3316
|
+
xs: "w-6 h-6 text-[10px]",
|
|
3317
|
+
sm: "w-8 h-8 text-xs",
|
|
3318
|
+
md: "w-10 h-10 text-sm",
|
|
3319
|
+
lg: "w-12 h-12 text-base"
|
|
3320
|
+
};
|
|
3321
|
+
function UserAvatar({
|
|
3322
|
+
firstName,
|
|
3323
|
+
lastName,
|
|
3324
|
+
initials: providedInitials,
|
|
3325
|
+
size = "md",
|
|
3326
|
+
className = ""
|
|
3327
|
+
}) {
|
|
3328
|
+
const derivedInitials = (() => {
|
|
3329
|
+
const firstChar = firstName?.trim()?.charAt(0) || "";
|
|
3330
|
+
const lastChar = lastName?.trim()?.charAt(0) || "";
|
|
3331
|
+
const combined = `${firstChar}${lastChar}`.trim();
|
|
3332
|
+
return combined || "U";
|
|
3333
|
+
})();
|
|
3334
|
+
const initials = (providedInitials?.trim() || derivedInitials).toUpperCase();
|
|
3335
|
+
const fullName = `${firstName}${lastName}`;
|
|
3336
|
+
const colorIndex = hashString(fullName) % colorPalette.length;
|
|
3337
|
+
const colors = colorPalette[colorIndex];
|
|
3338
|
+
return /* @__PURE__ */ jsx(
|
|
3339
|
+
"div",
|
|
3340
|
+
{
|
|
3341
|
+
className: `
|
|
3342
|
+
${sizeClasses[size]}
|
|
3343
|
+
${colors.bg}
|
|
3344
|
+
${colors.text}
|
|
3345
|
+
${className}
|
|
3346
|
+
rounded-full
|
|
3347
|
+
flex
|
|
3348
|
+
items-center
|
|
3349
|
+
justify-center
|
|
3350
|
+
font-semibold
|
|
3351
|
+
flex-shrink-0
|
|
3352
|
+
select-none
|
|
3353
|
+
`,
|
|
3354
|
+
"aria-label": `${firstName} ${lastName}`,
|
|
3355
|
+
title: `${firstName} ${lastName}`,
|
|
3356
|
+
children: initials
|
|
3357
|
+
}
|
|
3358
|
+
);
|
|
3359
|
+
}
|
|
3360
|
+
var MemoizedUserAvatar = memo(UserAvatar);
|
|
3361
|
+
MemoizedUserAvatar.displayName = "UserAvatar";
|
|
3362
|
+
var overlapClasses = {
|
|
3363
|
+
xs: "-ml-1.5",
|
|
3364
|
+
sm: "-ml-2"
|
|
3365
|
+
};
|
|
3366
|
+
var badgeSizeClasses = {
|
|
3367
|
+
xs: "w-6 h-6 text-[10px]",
|
|
3368
|
+
sm: "w-8 h-8 text-xs"
|
|
3369
|
+
};
|
|
3370
|
+
function AvatarStackInner({
|
|
3371
|
+
users,
|
|
3372
|
+
max = 3,
|
|
3373
|
+
size = "sm",
|
|
3374
|
+
onClick,
|
|
3375
|
+
className = ""
|
|
3376
|
+
}) {
|
|
3377
|
+
const visible = users.slice(0, max);
|
|
3378
|
+
const overflow = users.length - max;
|
|
3379
|
+
const interactive = typeof onClick === "function";
|
|
3380
|
+
const overlap = overlapClasses[size];
|
|
3381
|
+
const badgeSize = badgeSizeClasses[size];
|
|
3382
|
+
const handleKeyDown = (e) => {
|
|
3383
|
+
if (interactive && (e.key === "Enter" || e.key === " ")) {
|
|
3384
|
+
e.preventDefault();
|
|
3385
|
+
onClick();
|
|
3386
|
+
}
|
|
3387
|
+
};
|
|
3388
|
+
return /* @__PURE__ */ jsxs(
|
|
3389
|
+
"div",
|
|
3390
|
+
{
|
|
3391
|
+
className: `inline-flex items-center ${interactive ? "cursor-pointer transition-opacity hover:opacity-80" : ""} ${className}`,
|
|
3392
|
+
onClick: interactive ? onClick : void 0,
|
|
3393
|
+
onKeyDown: interactive ? handleKeyDown : void 0,
|
|
3394
|
+
role: interactive ? "button" : void 0,
|
|
3395
|
+
tabIndex: interactive ? 0 : void 0,
|
|
3396
|
+
"aria-label": interactive ? `${users.length} members` : void 0,
|
|
3397
|
+
children: [
|
|
3398
|
+
visible.map((user, i) => /* @__PURE__ */ jsx(
|
|
3399
|
+
"div",
|
|
3400
|
+
{
|
|
3401
|
+
className: `${i > 0 ? overlap : ""} ring-2 ring-white dark:ring-gray-900 rounded-full`,
|
|
3402
|
+
style: { zIndex: visible.length - i },
|
|
3403
|
+
children: /* @__PURE__ */ jsx(
|
|
3404
|
+
MemoizedUserAvatar,
|
|
3405
|
+
{
|
|
3406
|
+
firstName: user.firstName,
|
|
3407
|
+
lastName: user.lastName,
|
|
3408
|
+
initials: user.initials,
|
|
3409
|
+
size
|
|
3410
|
+
}
|
|
3411
|
+
)
|
|
3412
|
+
},
|
|
3413
|
+
`${user.firstName}-${user.lastName}-${i}`
|
|
3414
|
+
)),
|
|
3415
|
+
overflow > 0 && /* @__PURE__ */ jsxs(
|
|
3416
|
+
"div",
|
|
3417
|
+
{
|
|
3418
|
+
className: `${overlap} ${badgeSize} rounded-full bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-300 font-medium flex items-center justify-center flex-shrink-0 ring-2 ring-white dark:ring-gray-900`,
|
|
3419
|
+
style: { zIndex: 0 },
|
|
3420
|
+
children: [
|
|
3421
|
+
"+",
|
|
3422
|
+
overflow
|
|
3423
|
+
]
|
|
3424
|
+
}
|
|
3425
|
+
)
|
|
3426
|
+
]
|
|
3427
|
+
}
|
|
3428
|
+
);
|
|
3429
|
+
}
|
|
3430
|
+
var AvatarStack = memo(AvatarStackInner);
|
|
3431
|
+
AvatarStack.displayName = "AvatarStack";
|
|
3432
|
+
function ChatHeader({ session, onBack, readOnly, logoSlot, actionsSlot, members, onMembersClick }) {
|
|
3332
3433
|
const { t } = useTranslation();
|
|
3333
3434
|
const branding = useBranding();
|
|
3334
3435
|
const BackButton = onBack ? /* @__PURE__ */ jsx(
|
|
3335
3436
|
"button",
|
|
3336
3437
|
{
|
|
3438
|
+
type: "button",
|
|
3337
3439
|
onClick: onBack,
|
|
3338
3440
|
className: "cursor-pointer p-2 hover:bg-gray-100 dark:hover:bg-gray-700 active:bg-gray-200 dark:active:bg-gray-600 rounded-lg transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
|
|
3339
3441
|
"aria-label": t("BiChat.Chat.GoBack"),
|
|
@@ -3352,23 +3454,42 @@ function ChatHeader({ session, onBack, readOnly, logoSlot, actionsSlot }) {
|
|
|
3352
3454
|
] }) });
|
|
3353
3455
|
}
|
|
3354
3456
|
const resolvedSessionTitle = session.title?.trim() || t("BiChat.Chat.NewChat");
|
|
3457
|
+
const isGroupSession = Boolean(session.isGroup || session.memberCount && session.memberCount > 1);
|
|
3458
|
+
const memberCount = session.memberCount ?? 0;
|
|
3459
|
+
const stackUsers = members && members.length > 0 ? members : [];
|
|
3355
3460
|
return /* @__PURE__ */ jsx("header", { className: "bichat-header border-b border-gray-200 dark:border-gray-700 px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3356
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
3461
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
3357
3462
|
BackButton,
|
|
3358
3463
|
Logo,
|
|
3359
|
-
/* @__PURE__ */
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3464
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
3465
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
3466
|
+
/* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-[var(--bichat-text)] truncate", children: resolvedSessionTitle }),
|
|
3467
|
+
session.pinned && /* @__PURE__ */ jsx(
|
|
3468
|
+
"svg",
|
|
3469
|
+
{
|
|
3470
|
+
className: "w-4 h-4 text-[var(--bichat-primary)] flex-shrink-0",
|
|
3471
|
+
fill: "currentColor",
|
|
3472
|
+
viewBox: "0 0 20 20",
|
|
3473
|
+
role: "img",
|
|
3474
|
+
"aria-label": t("BiChat.Chat.Pinned"),
|
|
3475
|
+
children: /* @__PURE__ */ jsx("path", { d: "M10 2a1 1 0 011 1v1.323l3.954 1.582 1.599-.8a1 1 0 01.894 1.79l-1.233.616 1.738 5.42a1 1 0 01-.285 1.05A3.989 3.989 0 0115 15a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.715-5.349L11 6.477V16h2a1 1 0 110 2H7a1 1 0 110-2h2V6.477L6.237 7.582l1.715 5.349a1 1 0 01-.285 1.05A3.989 3.989 0 015 15a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.738-5.42-1.233-.617a1 1 0 01.894-1.788l1.599.799L9 4.323V3a1 1 0 011-1z" })
|
|
3476
|
+
}
|
|
3477
|
+
),
|
|
3478
|
+
isGroupSession && stackUsers.length > 0 && /* @__PURE__ */ jsx(
|
|
3479
|
+
AvatarStack,
|
|
3480
|
+
{
|
|
3481
|
+
users: stackUsers,
|
|
3482
|
+
max: 3,
|
|
3483
|
+
size: "xs",
|
|
3484
|
+
onClick: onMembersClick,
|
|
3485
|
+
className: "flex-shrink-0"
|
|
3486
|
+
}
|
|
3487
|
+
)
|
|
3488
|
+
] }),
|
|
3489
|
+
isGroupSession && memberCount > 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400 mt-0.5", children: memberCount === 1 ? t("BiChat.Chat.OneMember") : t("BiChat.Chat.MemberCount").replace("{{count}}", String(memberCount)) })
|
|
3490
|
+
] })
|
|
3370
3491
|
] }),
|
|
3371
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3492
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
|
|
3372
3493
|
readOnly && /* @__PURE__ */ jsx("span", { className: "px-2 py-1 text-xs bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-200 rounded", children: t("BiChat.Chat.ReadOnly") }),
|
|
3373
3494
|
session.status === "archived" && /* @__PURE__ */ jsx("span", { className: "px-2 py-1 text-xs bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded", children: t("BiChat.Chat.Archived") }),
|
|
3374
3495
|
actionsSlot
|
|
@@ -4243,6 +4364,7 @@ function UserMessage({
|
|
|
4243
4364
|
turn,
|
|
4244
4365
|
turnId,
|
|
4245
4366
|
initials = "U",
|
|
4367
|
+
authorName,
|
|
4246
4368
|
slots,
|
|
4247
4369
|
classNames: classNameOverrides,
|
|
4248
4370
|
onCopy,
|
|
@@ -4450,6 +4572,16 @@ function UserMessage({
|
|
|
4450
4572
|
};
|
|
4451
4573
|
return /* @__PURE__ */ jsxs("div", { className: classes.root, children: [
|
|
4452
4574
|
/* @__PURE__ */ jsxs("div", { className: classes.wrapper, children: [
|
|
4575
|
+
authorName && /* @__PURE__ */ jsx(
|
|
4576
|
+
"span",
|
|
4577
|
+
{
|
|
4578
|
+
id: `${turn.id}-author`,
|
|
4579
|
+
role: "note",
|
|
4580
|
+
"aria-label": authorName,
|
|
4581
|
+
className: "mb-1 px-1 text-[11px] text-right text-gray-500 dark:text-gray-400",
|
|
4582
|
+
children: authorName
|
|
4583
|
+
}
|
|
4584
|
+
),
|
|
4453
4585
|
normalizedAttachments.length > 0 && /* @__PURE__ */ jsx("div", { className: classes.attachments, children: renderSlot(
|
|
4454
4586
|
slots?.attachments,
|
|
4455
4587
|
attachmentsSlotProps,
|
|
@@ -4461,20 +4593,28 @@ function UserMessage({
|
|
|
4461
4593
|
}
|
|
4462
4594
|
)
|
|
4463
4595
|
) }),
|
|
4464
|
-
turn.content && /* @__PURE__ */ jsx(
|
|
4465
|
-
|
|
4596
|
+
turn.content && /* @__PURE__ */ jsx(
|
|
4597
|
+
"div",
|
|
4466
4598
|
{
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4599
|
+
ref: bubbleRef,
|
|
4600
|
+
className: classes.bubble,
|
|
4601
|
+
"aria-describedby": authorName ? `${turn.id}-author` : void 0,
|
|
4602
|
+
children: /* @__PURE__ */ jsx("div", { className: classes.content, children: isEditing ? /* @__PURE__ */ jsx(
|
|
4603
|
+
EditForm,
|
|
4604
|
+
{
|
|
4605
|
+
draftContent,
|
|
4606
|
+
onDraftChange: handleDraftChange,
|
|
4607
|
+
onSave: handleEditSave,
|
|
4608
|
+
onCancel: handleEditCancel,
|
|
4609
|
+
onKeyDown: handleEditKeyDown,
|
|
4610
|
+
textareaRef: editTextareaRef,
|
|
4611
|
+
disabled: false,
|
|
4612
|
+
originalContent: turn.content,
|
|
4613
|
+
t
|
|
4614
|
+
}
|
|
4615
|
+
) : renderSlot(slots?.content, contentSlotProps, turn.content) })
|
|
4476
4616
|
}
|
|
4477
|
-
)
|
|
4617
|
+
),
|
|
4478
4618
|
!hideActions && /* @__PURE__ */ jsx("div", { className: `${classes.actions} ${isCopied ? "opacity-100" : ""}`, children: renderSlot(
|
|
4479
4619
|
slots?.actions,
|
|
4480
4620
|
actionsSlotProps,
|
|
@@ -4523,19 +4663,25 @@ function UserTurnView({
|
|
|
4523
4663
|
turn,
|
|
4524
4664
|
slots,
|
|
4525
4665
|
classNames,
|
|
4526
|
-
initials
|
|
4666
|
+
initials,
|
|
4527
4667
|
hideAvatar,
|
|
4528
4668
|
hideActions,
|
|
4529
4669
|
hideTimestamp,
|
|
4530
|
-
allowEdit
|
|
4670
|
+
allowEdit,
|
|
4671
|
+
showAuthorName = false
|
|
4531
4672
|
}) {
|
|
4532
4673
|
const { handleEdit, handleCopy } = useChatMessaging();
|
|
4674
|
+
const author = turn.userTurn.author;
|
|
4675
|
+
const fullName = [author?.firstName || "", author?.lastName || ""].join(" ").trim();
|
|
4676
|
+
const authorName = showAuthorName && fullName.length > 0 ? fullName : void 0;
|
|
4677
|
+
const resolvedInitials = initials ?? author?.initials ?? "U";
|
|
4533
4678
|
return /* @__PURE__ */ jsx(
|
|
4534
4679
|
UserMessage,
|
|
4535
4680
|
{
|
|
4536
4681
|
turn: turn.userTurn,
|
|
4537
4682
|
turnId: turn.id,
|
|
4538
|
-
initials,
|
|
4683
|
+
initials: resolvedInitials,
|
|
4684
|
+
authorName,
|
|
4539
4685
|
slots,
|
|
4540
4686
|
classNames,
|
|
4541
4687
|
onCopy: handleCopy,
|
|
@@ -6517,13 +6663,13 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
6517
6663
|
const currentAnswer = answers[currentQuestion?.id];
|
|
6518
6664
|
const currentOtherText = otherTexts[currentQuestion?.id] || "";
|
|
6519
6665
|
const handleOptionChange = useCallback(
|
|
6520
|
-
(
|
|
6666
|
+
(optionID, checked) => {
|
|
6521
6667
|
if (!currentQuestion) {
|
|
6522
6668
|
return;
|
|
6523
6669
|
}
|
|
6524
6670
|
const questionId = currentQuestion.id;
|
|
6525
6671
|
const existingAnswer = answers[questionId] || { options: [] };
|
|
6526
|
-
const isOtherOption =
|
|
6672
|
+
const isOtherOption = optionID === "__other__";
|
|
6527
6673
|
const isMultiSelect2 = currentQuestion.type === "MULTIPLE_CHOICE";
|
|
6528
6674
|
if (isOtherOption) {
|
|
6529
6675
|
setAnswers({
|
|
@@ -6538,14 +6684,14 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
6538
6684
|
let newOptions;
|
|
6539
6685
|
if (isMultiSelect2) {
|
|
6540
6686
|
if (!checked) {
|
|
6541
|
-
newOptions = existingAnswer.options.filter((o) => o !==
|
|
6542
|
-
} else if (existingAnswer.options.includes(
|
|
6687
|
+
newOptions = existingAnswer.options.filter((o) => o !== optionID);
|
|
6688
|
+
} else if (existingAnswer.options.includes(optionID)) {
|
|
6543
6689
|
newOptions = existingAnswer.options;
|
|
6544
6690
|
} else {
|
|
6545
|
-
newOptions = [...existingAnswer.options,
|
|
6691
|
+
newOptions = [...existingAnswer.options, optionID];
|
|
6546
6692
|
}
|
|
6547
6693
|
} else {
|
|
6548
|
-
newOptions = checked ? [
|
|
6694
|
+
newOptions = checked ? [optionID] : [];
|
|
6549
6695
|
}
|
|
6550
6696
|
setAnswers({
|
|
6551
6697
|
...answers,
|
|
@@ -6636,7 +6782,7 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
6636
6782
|
const options = (currentQuestion.options || []).filter((option) => Boolean(option && typeof option.label === "string")).map((option, index) => ({
|
|
6637
6783
|
id: option.id || `${currentQuestion.id}-option-${index}`,
|
|
6638
6784
|
label: option.label,
|
|
6639
|
-
value: option.value || option.
|
|
6785
|
+
value: option.value || option.id || `${currentQuestion.id}-option-${index}`
|
|
6640
6786
|
}));
|
|
6641
6787
|
const isOtherSelected = currentAnswer?.customText !== void 0;
|
|
6642
6788
|
const canProceed = isCurrentAnswerValid();
|
|
@@ -6684,7 +6830,7 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
6684
6830
|
] }),
|
|
6685
6831
|
/* @__PURE__ */ jsxs("div", { className: "px-4 pb-2 space-y-1.5", children: [
|
|
6686
6832
|
options.map((option) => {
|
|
6687
|
-
const isSelected = currentAnswer?.options.includes(option.
|
|
6833
|
+
const isSelected = currentAnswer?.options.includes(option.id) || false;
|
|
6688
6834
|
return /* @__PURE__ */ jsxs(
|
|
6689
6835
|
"label",
|
|
6690
6836
|
{
|
|
@@ -6712,7 +6858,7 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
6712
6858
|
name: `question-${currentQuestion.id}`,
|
|
6713
6859
|
value: option.value,
|
|
6714
6860
|
checked: isSelected,
|
|
6715
|
-
onChange: (e) => handleOptionChange(option.
|
|
6861
|
+
onChange: (e) => handleOptionChange(option.id, e.target.checked),
|
|
6716
6862
|
className: "sr-only"
|
|
6717
6863
|
}
|
|
6718
6864
|
),
|
|
@@ -8530,7 +8676,7 @@ function StreamingBubble({ content, normalizedContent }) {
|
|
|
8530
8676
|
}
|
|
8531
8677
|
function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readOnly }) {
|
|
8532
8678
|
const { t } = useTranslation();
|
|
8533
|
-
const { currentSessionId, fetching } = useChatSession();
|
|
8679
|
+
const { session, currentSessionId, fetching } = useChatSession();
|
|
8534
8680
|
const {
|
|
8535
8681
|
turns,
|
|
8536
8682
|
streamingContent,
|
|
@@ -8545,6 +8691,7 @@ function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readO
|
|
|
8545
8691
|
() => streamingContent ? normalizeStreamingMarkdown(streamingContent) : "",
|
|
8546
8692
|
[streamingContent]
|
|
8547
8693
|
);
|
|
8694
|
+
const showAuthorNames = Boolean(session?.isGroup);
|
|
8548
8695
|
const showEphemeral = showActivityTrace || showTypingIndicator;
|
|
8549
8696
|
return /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-h-0", children: [
|
|
8550
8697
|
/* @__PURE__ */ jsx("div", { ref: containerRef, className: "h-full overflow-y-auto overflow-x-hidden px-4 py-6", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto space-y-6", children: [
|
|
@@ -8554,6 +8701,10 @@ function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readO
|
|
|
8554
8701
|
const prevDate = index > 0 ? new Date(turns[index - 1].createdAt) : null;
|
|
8555
8702
|
const showDateSeparator = !!prevDate && !isSameDay(turnDate, prevDate);
|
|
8556
8703
|
const isLast = index === turns.length - 1;
|
|
8704
|
+
const userTurnProps = {
|
|
8705
|
+
allowEdit: readOnly ? false : isLast,
|
|
8706
|
+
showAuthorName: showAuthorNames
|
|
8707
|
+
};
|
|
8557
8708
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
8558
8709
|
showDateSeparator && /* @__PURE__ */ jsx(DateSeparator, { date: turnDate }),
|
|
8559
8710
|
/* @__PURE__ */ jsx(
|
|
@@ -8563,7 +8714,7 @@ function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readO
|
|
|
8563
8714
|
isLastTurn: isLast,
|
|
8564
8715
|
renderUserTurn,
|
|
8565
8716
|
renderAssistantTurn,
|
|
8566
|
-
userTurnProps
|
|
8717
|
+
userTurnProps,
|
|
8567
8718
|
assistantTurnProps: readOnly ? { allowRegenerate: false } : void 0
|
|
8568
8719
|
}
|
|
8569
8720
|
)
|
|
@@ -10769,47 +10920,665 @@ function SessionArtifactsPanel({
|
|
|
10769
10920
|
}
|
|
10770
10921
|
);
|
|
10771
10922
|
}
|
|
10923
|
+
var DialogContext = createContext(null);
|
|
10924
|
+
var FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
10925
|
+
function InlineDialog({ open, onClose, className, children }) {
|
|
10926
|
+
const containerRef = useRef(null);
|
|
10927
|
+
const previousFocusRef = useRef(null);
|
|
10928
|
+
useEffect(() => {
|
|
10929
|
+
if (!open) {
|
|
10930
|
+
return;
|
|
10931
|
+
}
|
|
10932
|
+
previousFocusRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
10933
|
+
const container = containerRef.current;
|
|
10934
|
+
if (!container) {
|
|
10935
|
+
return;
|
|
10936
|
+
}
|
|
10937
|
+
const getFocusable = () => Array.from(
|
|
10938
|
+
container.querySelectorAll(FOCUSABLE_SELECTOR)
|
|
10939
|
+
);
|
|
10940
|
+
const handler = (e) => {
|
|
10941
|
+
if (e.key === "Escape") {
|
|
10942
|
+
onClose();
|
|
10943
|
+
return;
|
|
10944
|
+
}
|
|
10945
|
+
if (e.key !== "Tab") {
|
|
10946
|
+
return;
|
|
10947
|
+
}
|
|
10948
|
+
const focusable = getFocusable();
|
|
10949
|
+
if (focusable.length === 0) {
|
|
10950
|
+
e.preventDefault();
|
|
10951
|
+
container.focus();
|
|
10952
|
+
return;
|
|
10953
|
+
}
|
|
10954
|
+
const first = focusable[0];
|
|
10955
|
+
const last = focusable[focusable.length - 1];
|
|
10956
|
+
if (e.shiftKey && document.activeElement === first) {
|
|
10957
|
+
e.preventDefault();
|
|
10958
|
+
last.focus();
|
|
10959
|
+
} else if (!e.shiftKey && document.activeElement === last) {
|
|
10960
|
+
e.preventDefault();
|
|
10961
|
+
first.focus();
|
|
10962
|
+
}
|
|
10963
|
+
};
|
|
10964
|
+
(getFocusable()[0] ?? container)?.focus();
|
|
10965
|
+
container.addEventListener("keydown", handler);
|
|
10966
|
+
return () => {
|
|
10967
|
+
container.removeEventListener("keydown", handler);
|
|
10968
|
+
previousFocusRef.current?.focus();
|
|
10969
|
+
};
|
|
10970
|
+
}, [open, onClose]);
|
|
10971
|
+
if (!open) {
|
|
10972
|
+
return null;
|
|
10973
|
+
}
|
|
10974
|
+
return /* @__PURE__ */ jsx(DialogContext.Provider, { value: onClose, children: /* @__PURE__ */ jsx(
|
|
10975
|
+
"div",
|
|
10976
|
+
{
|
|
10977
|
+
ref: containerRef,
|
|
10978
|
+
className,
|
|
10979
|
+
onClick: onClose,
|
|
10980
|
+
tabIndex: -1,
|
|
10981
|
+
children
|
|
10982
|
+
}
|
|
10983
|
+
) });
|
|
10984
|
+
}
|
|
10985
|
+
function InlineDialogBackdrop(props) {
|
|
10986
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", ...props });
|
|
10987
|
+
}
|
|
10988
|
+
function InlineDialogPanel({
|
|
10989
|
+
children,
|
|
10990
|
+
onClick,
|
|
10991
|
+
...rest
|
|
10992
|
+
}) {
|
|
10993
|
+
const ref = useRef(null);
|
|
10994
|
+
useEffect(() => {
|
|
10995
|
+
if (!ref.current) {
|
|
10996
|
+
return;
|
|
10997
|
+
}
|
|
10998
|
+
const target = ref.current.querySelector("[data-autofocus]") ?? ref.current.querySelector(
|
|
10999
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
11000
|
+
);
|
|
11001
|
+
target?.focus();
|
|
11002
|
+
}, []);
|
|
11003
|
+
return /* @__PURE__ */ jsx(
|
|
11004
|
+
"div",
|
|
11005
|
+
{
|
|
11006
|
+
ref,
|
|
11007
|
+
role: "dialog",
|
|
11008
|
+
"aria-modal": "true",
|
|
11009
|
+
onClick: (e) => {
|
|
11010
|
+
e.stopPropagation();
|
|
11011
|
+
onClick?.(e);
|
|
11012
|
+
},
|
|
11013
|
+
...rest,
|
|
11014
|
+
children
|
|
11015
|
+
}
|
|
11016
|
+
);
|
|
11017
|
+
}
|
|
11018
|
+
function InlineDialogTitle(props) {
|
|
11019
|
+
return /* @__PURE__ */ jsx("h2", { ...props });
|
|
11020
|
+
}
|
|
11021
|
+
function InlineDialogDescription(props) {
|
|
11022
|
+
return /* @__PURE__ */ jsx("p", { ...props });
|
|
11023
|
+
}
|
|
10772
11024
|
|
|
10773
|
-
// ui/src/bichat/components/
|
|
11025
|
+
// ui/src/bichat/components/SessionMembersModal.tsx
|
|
10774
11026
|
init_useTranslation();
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
11027
|
+
init_useTranslation();
|
|
11028
|
+
function ConfirmModalBase({
|
|
11029
|
+
isOpen,
|
|
11030
|
+
title,
|
|
11031
|
+
message,
|
|
11032
|
+
onConfirm,
|
|
11033
|
+
onCancel,
|
|
11034
|
+
confirmText,
|
|
11035
|
+
cancelText,
|
|
11036
|
+
isDanger = false
|
|
10781
11037
|
}) {
|
|
10782
11038
|
const { t } = useTranslation();
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
11039
|
+
const resolvedConfirmText = confirmText?.trim() ? confirmText : t("BiChat.Common.Confirm");
|
|
11040
|
+
const resolvedCancelText = cancelText?.trim() ? cancelText : t("BiChat.Common.Cancel");
|
|
11041
|
+
return /* @__PURE__ */ jsxs(InlineDialog, { open: isOpen, onClose: onCancel, className: "relative z-40", children: [
|
|
11042
|
+
/* @__PURE__ */ jsx(InlineDialogBackdrop, { className: "fixed inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm transition-opacity duration-200" }),
|
|
11043
|
+
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxs(InlineDialogPanel, { className: "bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/30 max-w-sm w-full overflow-hidden", children: [
|
|
11044
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 pt-6 pb-5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
|
|
11045
|
+
isDanger && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 flex items-center justify-center w-10 h-10 rounded-xl bg-red-50 dark:bg-red-950/40 border border-red-200/60 dark:border-red-800/40", children: /* @__PURE__ */ jsx(WarningCircle, { size: 22, weight: "duotone", className: "text-red-600 dark:text-red-400" }) }),
|
|
11046
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
11047
|
+
/* @__PURE__ */ jsx(InlineDialogTitle, { className: "text-base font-semibold text-gray-900 dark:text-gray-100 leading-snug", children: title }),
|
|
11048
|
+
/* @__PURE__ */ jsx(InlineDialogDescription, { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 leading-relaxed", children: message })
|
|
11049
|
+
] })
|
|
11050
|
+
] }) }),
|
|
11051
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2.5 px-6 pb-5", children: [
|
|
11052
|
+
/* @__PURE__ */ jsx(
|
|
11053
|
+
"button",
|
|
10794
11054
|
{
|
|
10795
|
-
|
|
10796
|
-
|
|
11055
|
+
type: "button",
|
|
11056
|
+
onClick: onCancel,
|
|
11057
|
+
...isDanger ? { "data-autofocus": true } : {},
|
|
11058
|
+
className: "cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700/60 hover:bg-gray-200 dark:hover:bg-gray-700 active:bg-gray-250 dark:active:bg-gray-600 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11059
|
+
"data-testid": "confirm-modal-cancel",
|
|
11060
|
+
children: resolvedCancelText
|
|
10797
11061
|
}
|
|
10798
|
-
)
|
|
10799
|
-
/* @__PURE__ */
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10812
|
-
|
|
11062
|
+
),
|
|
11063
|
+
/* @__PURE__ */ jsx(
|
|
11064
|
+
"button",
|
|
11065
|
+
{
|
|
11066
|
+
type: "button",
|
|
11067
|
+
...!isDanger ? { "data-autofocus": true } : {},
|
|
11068
|
+
onClick: onConfirm,
|
|
11069
|
+
className: [
|
|
11070
|
+
"cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-white",
|
|
11071
|
+
"transition-all duration-150 shadow-sm hover:shadow",
|
|
11072
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11073
|
+
isDanger ? "bg-red-600 hover:bg-red-700 active:bg-red-800 focus-visible:ring-red-500/50" : "bg-primary-600 hover:bg-primary-700 active:bg-primary-800 focus-visible:ring-primary-500/50"
|
|
11074
|
+
].join(" "),
|
|
11075
|
+
"data-testid": "confirm-modal-confirm",
|
|
11076
|
+
children: resolvedConfirmText
|
|
11077
|
+
}
|
|
11078
|
+
)
|
|
11079
|
+
] })
|
|
11080
|
+
] }) })
|
|
11081
|
+
] });
|
|
11082
|
+
}
|
|
11083
|
+
var ConfirmModal = memo(ConfirmModalBase);
|
|
11084
|
+
ConfirmModal.displayName = "ConfirmModal";
|
|
11085
|
+
var ConfirmModal_default = ConfirmModal;
|
|
11086
|
+
var ROLES = ["editor", "viewer"];
|
|
11087
|
+
function RoleSegmentedControl({
|
|
11088
|
+
value,
|
|
11089
|
+
onChange,
|
|
11090
|
+
disabled,
|
|
11091
|
+
size = "md",
|
|
11092
|
+
t
|
|
11093
|
+
}) {
|
|
11094
|
+
const btnBase = size === "sm" ? "px-2 py-0.5 text-[11px]" : "px-3 py-1 text-xs";
|
|
11095
|
+
const currentIndex = ROLES.indexOf(value);
|
|
11096
|
+
const handleKeyDown = (e) => {
|
|
11097
|
+
if (disabled) {
|
|
11098
|
+
return;
|
|
11099
|
+
}
|
|
11100
|
+
let nextIndex = null;
|
|
11101
|
+
if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
11102
|
+
e.preventDefault();
|
|
11103
|
+
nextIndex = currentIndex <= 0 ? ROLES.length - 1 : currentIndex - 1;
|
|
11104
|
+
} else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
11105
|
+
e.preventDefault();
|
|
11106
|
+
nextIndex = currentIndex >= ROLES.length - 1 ? 0 : currentIndex + 1;
|
|
11107
|
+
}
|
|
11108
|
+
if (nextIndex !== null) {
|
|
11109
|
+
const nextRole = ROLES[nextIndex];
|
|
11110
|
+
onChange(nextRole);
|
|
11111
|
+
const target = e.currentTarget.querySelector(`[data-role="${nextRole}"]`);
|
|
11112
|
+
target?.focus();
|
|
11113
|
+
}
|
|
11114
|
+
};
|
|
11115
|
+
return /* @__PURE__ */ jsx(
|
|
11116
|
+
"div",
|
|
11117
|
+
{
|
|
11118
|
+
role: "radiogroup",
|
|
11119
|
+
"aria-label": t("BiChat.Share.RoleLabel"),
|
|
11120
|
+
className: "inline-flex rounded-lg border border-gray-200 dark:border-gray-700 p-0.5 bg-gray-50 dark:bg-gray-800/50",
|
|
11121
|
+
onKeyDown: handleKeyDown,
|
|
11122
|
+
children: ROLES.map((role) => /* @__PURE__ */ jsx(
|
|
11123
|
+
"button",
|
|
11124
|
+
{
|
|
11125
|
+
type: "button",
|
|
11126
|
+
role: "radio",
|
|
11127
|
+
"aria-checked": value === role,
|
|
11128
|
+
tabIndex: value === role ? 0 : -1,
|
|
11129
|
+
"data-role": role,
|
|
11130
|
+
disabled,
|
|
11131
|
+
onClick: () => onChange(role),
|
|
11132
|
+
className: `${btnBase} cursor-pointer rounded-md font-medium transition-all duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 disabled:opacity-50 disabled:cursor-not-allowed ${value === role ? "bg-primary-600 text-white shadow-sm" : "text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100"}`,
|
|
11133
|
+
children: role === "editor" ? t("BiChat.Share.RoleEditor") : t("BiChat.Share.RoleViewer")
|
|
11134
|
+
},
|
|
11135
|
+
role
|
|
11136
|
+
))
|
|
11137
|
+
}
|
|
11138
|
+
);
|
|
11139
|
+
}
|
|
11140
|
+
function MemberSkeleton() {
|
|
11141
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-xl px-3 py-2.5", "aria-hidden": "true", children: [
|
|
11142
|
+
/* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-gray-200 dark:bg-gray-700 animate-pulse flex-shrink-0" }),
|
|
11143
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1.5", children: [
|
|
11144
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-28 rounded bg-gray-200 dark:bg-gray-700 animate-pulse" }),
|
|
11145
|
+
/* @__PURE__ */ jsx("div", { className: "h-2.5 w-16 rounded bg-gray-100 dark:bg-gray-800 animate-pulse" })
|
|
11146
|
+
] }),
|
|
11147
|
+
/* @__PURE__ */ jsx("div", { className: "h-6 w-16 rounded-lg bg-gray-200 dark:bg-gray-700 animate-pulse" })
|
|
11148
|
+
] });
|
|
11149
|
+
}
|
|
11150
|
+
function SessionMembersModal({ isOpen, sessionId, dataSource, onClose }) {
|
|
11151
|
+
const headingId = useId();
|
|
11152
|
+
const { t } = useTranslation();
|
|
11153
|
+
const statusTimerRef = useRef();
|
|
11154
|
+
const [loading, setLoading] = useState(false);
|
|
11155
|
+
const [saving, setSaving] = useState(false);
|
|
11156
|
+
const [error, setError] = useState(null);
|
|
11157
|
+
const [users, setUsers] = useState([]);
|
|
11158
|
+
const [members, setMembers] = useState([]);
|
|
11159
|
+
const [selectedUser, setSelectedUser] = useState(null);
|
|
11160
|
+
const [selectedRole, setSelectedRole] = useState("editor");
|
|
11161
|
+
const [query, setQuery] = useState("");
|
|
11162
|
+
const [confirmRemove, setConfirmRemove] = useState(null);
|
|
11163
|
+
const [statusMessage, setStatusMessage] = useState(null);
|
|
11164
|
+
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
11165
|
+
const [dropdownHighlightIndex, setDropdownHighlightIndex] = useState(0);
|
|
11166
|
+
const dropdownOptionRefs = useRef([]);
|
|
11167
|
+
const canManageMembers = Boolean(
|
|
11168
|
+
dataSource.listUsers && dataSource.listSessionMembers && dataSource.addSessionMember && dataSource.updateSessionMemberRole && dataSource.removeSessionMember
|
|
11169
|
+
);
|
|
11170
|
+
const refresh = useCallback(async () => {
|
|
11171
|
+
if (!sessionId || !canManageMembers) {
|
|
11172
|
+
return;
|
|
11173
|
+
}
|
|
11174
|
+
setLoading(true);
|
|
11175
|
+
setError(null);
|
|
11176
|
+
try {
|
|
11177
|
+
const [usersData, membersData] = await Promise.all([
|
|
11178
|
+
dataSource.listUsers(),
|
|
11179
|
+
dataSource.listSessionMembers(sessionId)
|
|
11180
|
+
]);
|
|
11181
|
+
setUsers(usersData);
|
|
11182
|
+
setMembers(membersData);
|
|
11183
|
+
} catch {
|
|
11184
|
+
setError(t("BiChat.Share.LoadFailed"));
|
|
11185
|
+
} finally {
|
|
11186
|
+
setLoading(false);
|
|
11187
|
+
}
|
|
11188
|
+
}, [canManageMembers, dataSource, sessionId, t]);
|
|
11189
|
+
useEffect(() => {
|
|
11190
|
+
if (!isOpen) {
|
|
11191
|
+
return;
|
|
11192
|
+
}
|
|
11193
|
+
void refresh();
|
|
11194
|
+
}, [isOpen, refresh]);
|
|
11195
|
+
useEffect(() => {
|
|
11196
|
+
if (!isOpen) {
|
|
11197
|
+
setQuery("");
|
|
11198
|
+
setSelectedUser(null);
|
|
11199
|
+
setSelectedRole("editor");
|
|
11200
|
+
setError(null);
|
|
11201
|
+
setConfirmRemove(null);
|
|
11202
|
+
setStatusMessage(null);
|
|
11203
|
+
setDropdownOpen(false);
|
|
11204
|
+
setDropdownHighlightIndex(0);
|
|
11205
|
+
}
|
|
11206
|
+
}, [isOpen]);
|
|
11207
|
+
const memberIDs = useMemo(() => new Set(members.map((m) => m.user.id)), [members]);
|
|
11208
|
+
const availableUsers = useMemo(
|
|
11209
|
+
() => users.filter((user) => !memberIDs.has(user.id)),
|
|
11210
|
+
[users, memberIDs]
|
|
11211
|
+
);
|
|
11212
|
+
const filteredUsers = useMemo(() => {
|
|
11213
|
+
if (!query.trim()) {
|
|
11214
|
+
return availableUsers;
|
|
11215
|
+
}
|
|
11216
|
+
const q = query.toLowerCase();
|
|
11217
|
+
return availableUsers.filter(
|
|
11218
|
+
(u) => u.firstName.toLowerCase().includes(q) || u.lastName.toLowerCase().includes(q) || `${u.firstName} ${u.lastName}`.toLowerCase().includes(q)
|
|
11219
|
+
);
|
|
11220
|
+
}, [availableUsers, query]);
|
|
11221
|
+
useEffect(() => {
|
|
11222
|
+
setDropdownHighlightIndex(
|
|
11223
|
+
(i) => Math.min(Math.max(0, i), Math.max(0, filteredUsers.length - 1))
|
|
11224
|
+
);
|
|
11225
|
+
}, [filteredUsers.length]);
|
|
11226
|
+
useEffect(() => () => clearTimeout(statusTimerRef.current), []);
|
|
11227
|
+
const flashStatus = useCallback((msg) => {
|
|
11228
|
+
clearTimeout(statusTimerRef.current);
|
|
11229
|
+
setStatusMessage(msg);
|
|
11230
|
+
statusTimerRef.current = setTimeout(() => setStatusMessage(null), 3e3);
|
|
11231
|
+
}, []);
|
|
11232
|
+
const handleAdd = useCallback(async () => {
|
|
11233
|
+
if (!sessionId || !selectedUser || !dataSource.addSessionMember) {
|
|
11234
|
+
return;
|
|
11235
|
+
}
|
|
11236
|
+
setSaving(true);
|
|
11237
|
+
setError(null);
|
|
11238
|
+
try {
|
|
11239
|
+
await dataSource.addSessionMember(sessionId, selectedUser.id, selectedRole);
|
|
11240
|
+
setSelectedUser(null);
|
|
11241
|
+
setQuery("");
|
|
11242
|
+
flashStatus(t("BiChat.Share.MemberAdded"));
|
|
11243
|
+
await refresh();
|
|
11244
|
+
} catch {
|
|
11245
|
+
setError(t("BiChat.Share.AddFailed"));
|
|
11246
|
+
} finally {
|
|
11247
|
+
setSaving(false);
|
|
11248
|
+
}
|
|
11249
|
+
}, [sessionId, selectedUser, selectedRole, dataSource.addSessionMember, refresh, t, flashStatus]);
|
|
11250
|
+
const handleUpdateRole = useCallback(async (userId, role) => {
|
|
11251
|
+
if (!sessionId || !dataSource.updateSessionMemberRole) {
|
|
11252
|
+
return;
|
|
11253
|
+
}
|
|
11254
|
+
setSaving(true);
|
|
11255
|
+
setError(null);
|
|
11256
|
+
try {
|
|
11257
|
+
await dataSource.updateSessionMemberRole(sessionId, userId, role);
|
|
11258
|
+
await refresh();
|
|
11259
|
+
} catch {
|
|
11260
|
+
setError(t("BiChat.Share.UpdateFailed"));
|
|
11261
|
+
} finally {
|
|
11262
|
+
setSaving(false);
|
|
11263
|
+
}
|
|
11264
|
+
}, [sessionId, dataSource.updateSessionMemberRole, refresh]);
|
|
11265
|
+
const handleRemove = useCallback(async (userId) => {
|
|
11266
|
+
if (!sessionId || !dataSource.removeSessionMember) {
|
|
11267
|
+
return;
|
|
11268
|
+
}
|
|
11269
|
+
setSaving(true);
|
|
11270
|
+
setError(null);
|
|
11271
|
+
try {
|
|
11272
|
+
await dataSource.removeSessionMember(sessionId, userId);
|
|
11273
|
+
flashStatus(t("BiChat.Share.MemberRemoved"));
|
|
11274
|
+
await refresh();
|
|
11275
|
+
} catch {
|
|
11276
|
+
setError(t("BiChat.Share.RemoveFailed"));
|
|
11277
|
+
} finally {
|
|
11278
|
+
setSaving(false);
|
|
11279
|
+
}
|
|
11280
|
+
}, [sessionId, dataSource.removeSessionMember, refresh, flashStatus]);
|
|
11281
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11282
|
+
/* @__PURE__ */ jsxs(InlineDialog, { open: isOpen, onClose, className: "relative z-40", children: [
|
|
11283
|
+
/* @__PURE__ */ jsx(InlineDialogBackdrop, { className: "fixed inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm transition-opacity duration-200" }),
|
|
11284
|
+
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxs(
|
|
11285
|
+
InlineDialogPanel,
|
|
11286
|
+
{
|
|
11287
|
+
"aria-labelledby": headingId,
|
|
11288
|
+
className: "bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/30 max-w-md w-full",
|
|
11289
|
+
children: [
|
|
11290
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 pt-5 pb-4", children: [
|
|
11291
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
11292
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-9 h-9 rounded-xl bg-primary-50 dark:bg-primary-950/40 border border-primary-200/60 dark:border-primary-800/40", children: /* @__PURE__ */ jsx(UsersThree, { size: 18, weight: "duotone", className: "text-primary-600 dark:text-primary-400" }) }),
|
|
11293
|
+
/* @__PURE__ */ jsx(InlineDialogTitle, { id: headingId, className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: t("BiChat.Share.Title") })
|
|
11294
|
+
] }),
|
|
11295
|
+
/* @__PURE__ */ jsx(
|
|
11296
|
+
"button",
|
|
11297
|
+
{
|
|
11298
|
+
type: "button",
|
|
11299
|
+
onClick: onClose,
|
|
11300
|
+
className: "rounded-lg p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 dark:hover:text-gray-300 dark:hover:bg-gray-700 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
|
|
11301
|
+
"aria-label": t("BiChat.Common.Close"),
|
|
11302
|
+
children: /* @__PURE__ */ jsx(X, { size: 18 })
|
|
11303
|
+
}
|
|
11304
|
+
)
|
|
11305
|
+
] }),
|
|
11306
|
+
/* @__PURE__ */ jsxs("div", { className: "px-6 pb-5 space-y-4", children: [
|
|
11307
|
+
!canManageMembers && /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-amber-200 bg-amber-50 px-3 py-2.5 text-xs text-amber-700 dark:border-amber-800/60 dark:bg-amber-900/20 dark:text-amber-300", children: t("BiChat.Share.Unsupported") }),
|
|
11308
|
+
error && /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-red-200 bg-red-50 px-3 py-2.5 text-xs text-red-700 dark:border-red-800/60 dark:bg-red-900/20 dark:text-red-300", children: error }),
|
|
11309
|
+
/* @__PURE__ */ jsx("div", { "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: statusMessage }),
|
|
11310
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
11311
|
+
/* @__PURE__ */ jsxs("h3", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400", children: [
|
|
11312
|
+
t("BiChat.Share.Members"),
|
|
11313
|
+
!loading && members.length > 0 ? ` (${members.length})` : ""
|
|
11314
|
+
] }),
|
|
11315
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto -mx-1 px-1 space-y-1", children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11316
|
+
/* @__PURE__ */ jsx(MemberSkeleton, {}),
|
|
11317
|
+
/* @__PURE__ */ jsx(MemberSkeleton, {}),
|
|
11318
|
+
/* @__PURE__ */ jsx(MemberSkeleton, {})
|
|
11319
|
+
] }) : members.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-8 text-gray-400 dark:text-gray-500", children: [
|
|
11320
|
+
/* @__PURE__ */ jsx(UsersThree, { size: 32, weight: "thin", className: "mb-2" }),
|
|
11321
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: t("BiChat.Share.Empty") })
|
|
11322
|
+
] }) : members.map((member) => /* @__PURE__ */ jsxs(
|
|
11323
|
+
"div",
|
|
11324
|
+
{
|
|
11325
|
+
className: "flex items-center gap-3 rounded-xl px-3 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700/40",
|
|
11326
|
+
children: [
|
|
11327
|
+
/* @__PURE__ */ jsx(
|
|
11328
|
+
MemoizedUserAvatar,
|
|
11329
|
+
{
|
|
11330
|
+
firstName: member.user.firstName,
|
|
11331
|
+
lastName: member.user.lastName,
|
|
11332
|
+
initials: member.user.initials,
|
|
11333
|
+
size: "sm"
|
|
11334
|
+
}
|
|
11335
|
+
),
|
|
11336
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "truncate text-sm font-medium text-gray-900 dark:text-gray-100", children: [
|
|
11337
|
+
member.user.firstName,
|
|
11338
|
+
" ",
|
|
11339
|
+
member.user.lastName
|
|
11340
|
+
] }) }),
|
|
11341
|
+
member.role === "owner" ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-amber-50 dark:bg-amber-900/20 border border-amber-200/60 dark:border-amber-800/40 px-2.5 py-0.5 text-[11px] font-medium text-amber-700 dark:text-amber-300", children: [
|
|
11342
|
+
/* @__PURE__ */ jsx(Crown, { size: 12, weight: "duotone" }),
|
|
11343
|
+
t("BiChat.Share.RoleOwner")
|
|
11344
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
|
|
11345
|
+
/* @__PURE__ */ jsx(
|
|
11346
|
+
RoleSegmentedControl,
|
|
11347
|
+
{
|
|
11348
|
+
value: member.role,
|
|
11349
|
+
onChange: (role) => handleUpdateRole(member.user.id, role),
|
|
11350
|
+
disabled: saving,
|
|
11351
|
+
size: "sm",
|
|
11352
|
+
t
|
|
11353
|
+
}
|
|
11354
|
+
),
|
|
11355
|
+
/* @__PURE__ */ jsx(
|
|
11356
|
+
"button",
|
|
11357
|
+
{
|
|
11358
|
+
type: "button",
|
|
11359
|
+
disabled: saving,
|
|
11360
|
+
onClick: () => setConfirmRemove(member),
|
|
11361
|
+
className: "cursor-pointer rounded-lg p-1.5 text-gray-400 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500/50",
|
|
11362
|
+
"aria-label": `${t("BiChat.Share.Remove")} ${member.user.firstName} ${member.user.lastName}`,
|
|
11363
|
+
children: /* @__PURE__ */ jsx(Trash, { size: 14 })
|
|
11364
|
+
}
|
|
11365
|
+
)
|
|
11366
|
+
] })
|
|
11367
|
+
]
|
|
11368
|
+
},
|
|
11369
|
+
member.user.id
|
|
11370
|
+
)) })
|
|
11371
|
+
] }),
|
|
11372
|
+
canManageMembers && /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-gray-200 dark:border-gray-700 p-3 space-y-3", children: [
|
|
11373
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400", children: t("BiChat.Share.AddMember") }),
|
|
11374
|
+
/* @__PURE__ */ jsxs(
|
|
11375
|
+
"div",
|
|
11376
|
+
{
|
|
11377
|
+
className: "relative",
|
|
11378
|
+
onBlur: (e) => {
|
|
11379
|
+
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
11380
|
+
setDropdownOpen(false);
|
|
11381
|
+
}
|
|
11382
|
+
},
|
|
11383
|
+
children: [
|
|
11384
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
11385
|
+
/* @__PURE__ */ jsx(
|
|
11386
|
+
MagnifyingGlass,
|
|
11387
|
+
{
|
|
11388
|
+
size: 14,
|
|
11389
|
+
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 dark:text-gray-500"
|
|
11390
|
+
}
|
|
11391
|
+
),
|
|
11392
|
+
/* @__PURE__ */ jsx(
|
|
11393
|
+
"input",
|
|
11394
|
+
{
|
|
11395
|
+
type: "text",
|
|
11396
|
+
className: "w-full rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800/60 pl-8 pr-3 py-2 text-sm text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 transition-colors focus:border-primary-400 dark:focus:border-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500/20",
|
|
11397
|
+
placeholder: t("BiChat.Share.SearchUsers"),
|
|
11398
|
+
value: selectedUser ? `${selectedUser.firstName} ${selectedUser.lastName}` : query,
|
|
11399
|
+
onFocus: () => {
|
|
11400
|
+
setDropdownOpen(true);
|
|
11401
|
+
setDropdownHighlightIndex(0);
|
|
11402
|
+
if (selectedUser) {
|
|
11403
|
+
setSelectedUser(null);
|
|
11404
|
+
setQuery("");
|
|
11405
|
+
}
|
|
11406
|
+
},
|
|
11407
|
+
onChange: (e) => {
|
|
11408
|
+
setQuery(e.target.value);
|
|
11409
|
+
setSelectedUser(null);
|
|
11410
|
+
setDropdownOpen(true);
|
|
11411
|
+
setDropdownHighlightIndex(0);
|
|
11412
|
+
},
|
|
11413
|
+
onKeyDown: (e) => {
|
|
11414
|
+
if (!dropdownOpen || filteredUsers.length === 0) {
|
|
11415
|
+
if (e.key === "Escape") {
|
|
11416
|
+
setDropdownOpen(false);
|
|
11417
|
+
}
|
|
11418
|
+
return;
|
|
11419
|
+
}
|
|
11420
|
+
if (e.key === "Escape") {
|
|
11421
|
+
e.preventDefault();
|
|
11422
|
+
setDropdownOpen(false);
|
|
11423
|
+
setDropdownHighlightIndex(0);
|
|
11424
|
+
return;
|
|
11425
|
+
}
|
|
11426
|
+
if (e.key === "ArrowDown") {
|
|
11427
|
+
e.preventDefault();
|
|
11428
|
+
const next = (dropdownHighlightIndex + 1) % filteredUsers.length;
|
|
11429
|
+
setDropdownHighlightIndex(next);
|
|
11430
|
+
setTimeout(() => dropdownOptionRefs.current[next]?.focus(), 0);
|
|
11431
|
+
return;
|
|
11432
|
+
}
|
|
11433
|
+
if (e.key === "ArrowUp") {
|
|
11434
|
+
e.preventDefault();
|
|
11435
|
+
const next = dropdownHighlightIndex <= 0 ? filteredUsers.length - 1 : dropdownHighlightIndex - 1;
|
|
11436
|
+
setDropdownHighlightIndex(next);
|
|
11437
|
+
setTimeout(() => dropdownOptionRefs.current[next]?.focus(), 0);
|
|
11438
|
+
return;
|
|
11439
|
+
}
|
|
11440
|
+
if (e.key === "Enter") {
|
|
11441
|
+
e.preventDefault();
|
|
11442
|
+
const user = filteredUsers[dropdownHighlightIndex];
|
|
11443
|
+
if (user) {
|
|
11444
|
+
setSelectedUser(user);
|
|
11445
|
+
setQuery("");
|
|
11446
|
+
setDropdownOpen(false);
|
|
11447
|
+
}
|
|
11448
|
+
}
|
|
11449
|
+
}
|
|
11450
|
+
}
|
|
11451
|
+
)
|
|
11452
|
+
] }),
|
|
11453
|
+
dropdownOpen && !selectedUser && /* @__PURE__ */ jsx("div", { className: "absolute z-10 mt-1 max-h-48 w-full overflow-auto rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-lg py-1", children: filteredUsers.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-sm text-gray-500 dark:text-gray-400", children: availableUsers.length === 0 ? t("BiChat.Share.NoUsersAvailable") : t("BiChat.Share.NoSearchResults") }) : filteredUsers.map((user, index) => /* @__PURE__ */ jsxs(
|
|
11454
|
+
"button",
|
|
11455
|
+
{
|
|
11456
|
+
type: "button",
|
|
11457
|
+
ref: (el) => {
|
|
11458
|
+
dropdownOptionRefs.current[index] = el;
|
|
11459
|
+
},
|
|
11460
|
+
className: `flex w-full items-center gap-2.5 px-3 py-2 cursor-pointer transition-colors hover:bg-primary-50 dark:hover:bg-primary-900/20 ${index === dropdownHighlightIndex ? "bg-primary-50 dark:bg-primary-900/20" : ""}`,
|
|
11461
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
11462
|
+
onClick: () => {
|
|
11463
|
+
setSelectedUser(user);
|
|
11464
|
+
setQuery("");
|
|
11465
|
+
setDropdownOpen(false);
|
|
11466
|
+
},
|
|
11467
|
+
children: [
|
|
11468
|
+
/* @__PURE__ */ jsx(
|
|
11469
|
+
MemoizedUserAvatar,
|
|
11470
|
+
{
|
|
11471
|
+
firstName: user.firstName,
|
|
11472
|
+
lastName: user.lastName,
|
|
11473
|
+
initials: user.initials,
|
|
11474
|
+
size: "xs"
|
|
11475
|
+
}
|
|
11476
|
+
),
|
|
11477
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-900 dark:text-gray-100", children: [
|
|
11478
|
+
user.firstName,
|
|
11479
|
+
" ",
|
|
11480
|
+
user.lastName
|
|
11481
|
+
] })
|
|
11482
|
+
]
|
|
11483
|
+
},
|
|
11484
|
+
user.id
|
|
11485
|
+
)) })
|
|
11486
|
+
]
|
|
11487
|
+
}
|
|
11488
|
+
),
|
|
11489
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
11490
|
+
/* @__PURE__ */ jsx(
|
|
11491
|
+
RoleSegmentedControl,
|
|
11492
|
+
{
|
|
11493
|
+
value: selectedRole,
|
|
11494
|
+
onChange: setSelectedRole,
|
|
11495
|
+
disabled: saving,
|
|
11496
|
+
t
|
|
11497
|
+
}
|
|
11498
|
+
),
|
|
11499
|
+
/* @__PURE__ */ jsxs(
|
|
11500
|
+
"button",
|
|
11501
|
+
{
|
|
11502
|
+
type: "button",
|
|
11503
|
+
onClick: handleAdd,
|
|
11504
|
+
disabled: saving || !selectedUser,
|
|
11505
|
+
className: "inline-flex cursor-pointer items-center gap-1.5 rounded-xl bg-primary-600 px-3.5 py-2 text-sm font-medium text-white shadow-sm transition-all duration-150 hover:bg-primary-700 hover:shadow active:bg-primary-800 disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11506
|
+
children: [
|
|
11507
|
+
/* @__PURE__ */ jsx(UserPlus, { size: 14 }),
|
|
11508
|
+
t("BiChat.Share.Add")
|
|
11509
|
+
]
|
|
11510
|
+
}
|
|
11511
|
+
)
|
|
11512
|
+
] })
|
|
11513
|
+
] })
|
|
11514
|
+
] })
|
|
11515
|
+
]
|
|
11516
|
+
}
|
|
11517
|
+
) })
|
|
11518
|
+
] }),
|
|
11519
|
+
/* @__PURE__ */ jsx(
|
|
11520
|
+
ConfirmModal,
|
|
11521
|
+
{
|
|
11522
|
+
isOpen: !!confirmRemove,
|
|
11523
|
+
isDanger: true,
|
|
11524
|
+
title: t("BiChat.Share.RemoveConfirmTitle"),
|
|
11525
|
+
message: confirmRemove ? t("BiChat.Share.RemoveConfirmMessage").replace(
|
|
11526
|
+
"{{name}}",
|
|
11527
|
+
`${confirmRemove.user.firstName} ${confirmRemove.user.lastName}`
|
|
11528
|
+
) : "",
|
|
11529
|
+
confirmText: t("BiChat.Share.Remove"),
|
|
11530
|
+
onConfirm: () => {
|
|
11531
|
+
if (confirmRemove) {
|
|
11532
|
+
void handleRemove(confirmRemove.user.id);
|
|
11533
|
+
}
|
|
11534
|
+
setConfirmRemove(null);
|
|
11535
|
+
},
|
|
11536
|
+
onCancel: () => setConfirmRemove(null)
|
|
11537
|
+
}
|
|
11538
|
+
)
|
|
11539
|
+
] });
|
|
11540
|
+
}
|
|
11541
|
+
|
|
11542
|
+
// ui/src/bichat/components/StreamError.tsx
|
|
11543
|
+
init_useTranslation();
|
|
11544
|
+
function StreamError({
|
|
11545
|
+
error,
|
|
11546
|
+
onRetry,
|
|
11547
|
+
onRegenerate,
|
|
11548
|
+
onDismiss,
|
|
11549
|
+
compact = false
|
|
11550
|
+
}) {
|
|
11551
|
+
const { t } = useTranslation();
|
|
11552
|
+
return /* @__PURE__ */ jsxs(
|
|
11553
|
+
motion.div,
|
|
11554
|
+
{
|
|
11555
|
+
initial: { opacity: 0, y: 10 },
|
|
11556
|
+
animate: { opacity: 1, y: 0 },
|
|
11557
|
+
exit: { opacity: 0, y: -10 },
|
|
11558
|
+
className: `flex items-start gap-3 ${compact ? "px-3 py-2.5" : "px-4 py-3"} bg-red-50 dark:bg-red-950/40 border border-red-200/80 dark:border-red-900/60 rounded-xl shadow-sm`,
|
|
11559
|
+
role: "alert",
|
|
11560
|
+
children: [
|
|
11561
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 mt-0.5 flex items-center justify-center w-7 h-7 rounded-full bg-red-100 dark:bg-red-900/40", children: /* @__PURE__ */ jsx(
|
|
11562
|
+
Warning,
|
|
11563
|
+
{
|
|
11564
|
+
className: "w-4 h-4 text-red-600 dark:text-red-400",
|
|
11565
|
+
weight: "fill"
|
|
11566
|
+
}
|
|
11567
|
+
) }),
|
|
11568
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
11569
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-red-800 dark:text-red-200 leading-snug", children: t("BiChat.Error.Generic") }),
|
|
11570
|
+
/* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-red-600/80 dark:text-red-400/70 break-words leading-relaxed", children: error }),
|
|
11571
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
11572
|
+
onRetry && /* @__PURE__ */ jsxs(
|
|
11573
|
+
"button",
|
|
11574
|
+
{
|
|
11575
|
+
onClick: onRetry,
|
|
11576
|
+
className: "cursor-pointer inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-white bg-red-600 hover:bg-red-700 active:bg-red-800 dark:bg-red-700 dark:hover:bg-red-600 rounded-lg transition-colors shadow-sm",
|
|
11577
|
+
type: "button",
|
|
11578
|
+
children: [
|
|
11579
|
+
/* @__PURE__ */ jsx(ArrowClockwise, { className: "w-3.5 h-3.5" }),
|
|
11580
|
+
t("BiChat.StreamError.Retry")
|
|
11581
|
+
]
|
|
10813
11582
|
}
|
|
10814
11583
|
),
|
|
10815
11584
|
onRegenerate && /* @__PURE__ */ jsxs(
|
|
@@ -10897,7 +11666,8 @@ function ChatSessionCore({
|
|
|
10897
11666
|
updateQueueItem
|
|
10898
11667
|
} = useChatInput();
|
|
10899
11668
|
const isArchived = session?.status === "archived";
|
|
10900
|
-
const
|
|
11669
|
+
const accessReadOnly = session?.access ? !session.access.canWrite : false;
|
|
11670
|
+
const effectiveReadOnly = Boolean(readOnly ?? isReadOnly) || isArchived || accessReadOnly;
|
|
10901
11671
|
const [restoring, setRestoring] = useState(false);
|
|
10902
11672
|
const handleRestore = useCallback(async () => {
|
|
10903
11673
|
if (!session?.id) {
|
|
@@ -10918,6 +11688,8 @@ function ChatSessionCore({
|
|
|
10918
11688
|
const [artifactsPanelExpanded, setArtifactsPanelExpanded] = useState(
|
|
10919
11689
|
artifactsPanelDefaultExpanded
|
|
10920
11690
|
);
|
|
11691
|
+
const [membersModalOpen, setMembersModalOpen] = useState(false);
|
|
11692
|
+
const [headerMembers, setHeaderMembers] = useState(null);
|
|
10921
11693
|
const [artifactsPanelWidth, setArtifactsPanelWidth] = useState(ARTIFACTS_PANEL_WIDTH_DEFAULT);
|
|
10922
11694
|
const [isResizingArtifactsPanel, setIsResizingArtifactsPanel] = useState(false);
|
|
10923
11695
|
const layoutContainerRef = useRef(null);
|
|
@@ -10952,6 +11724,25 @@ function ChatSessionCore({
|
|
|
10952
11724
|
} catch {
|
|
10953
11725
|
}
|
|
10954
11726
|
}, [artifactsPanelStorageKey, showArtifactsPanel]);
|
|
11727
|
+
useEffect(() => {
|
|
11728
|
+
if (!session?.id || !dataSource.listSessionMembers) {
|
|
11729
|
+
setHeaderMembers(null);
|
|
11730
|
+
return;
|
|
11731
|
+
}
|
|
11732
|
+
let cancelled = false;
|
|
11733
|
+
dataSource.listSessionMembers(session.id).then((members) => {
|
|
11734
|
+
if (!cancelled) {
|
|
11735
|
+
setHeaderMembers(members.map((m) => m.user));
|
|
11736
|
+
}
|
|
11737
|
+
}).catch(() => {
|
|
11738
|
+
if (!cancelled) {
|
|
11739
|
+
setHeaderMembers(null);
|
|
11740
|
+
}
|
|
11741
|
+
});
|
|
11742
|
+
return () => {
|
|
11743
|
+
cancelled = true;
|
|
11744
|
+
};
|
|
11745
|
+
}, [session?.id, dataSource.listSessionMembers]);
|
|
10955
11746
|
const handleArtifactsResizeStart = useCallback(() => {
|
|
10956
11747
|
setIsResizingArtifactsPanel(true);
|
|
10957
11748
|
}, []);
|
|
@@ -11040,9 +11831,27 @@ function ChatSessionCore({
|
|
|
11040
11831
|
window.dispatchEvent(new CustomEvent("bichat:artifacts-panel-expanded", { detail: { expanded: true } }));
|
|
11041
11832
|
}
|
|
11042
11833
|
}
|
|
11043
|
-
};
|
|
11044
|
-
const
|
|
11045
|
-
|
|
11834
|
+
};
|
|
11835
|
+
const canShowShareButton = Boolean(
|
|
11836
|
+
session?.access?.canManageMembers && dataSource.listUsers && dataSource.listSessionMembers && dataSource.addSessionMember && dataSource.updateSessionMemberRole && dataSource.removeSessionMember
|
|
11837
|
+
);
|
|
11838
|
+
const shareButton = canShowShareButton ? /* @__PURE__ */ jsxs(
|
|
11839
|
+
"button",
|
|
11840
|
+
{
|
|
11841
|
+
type: "button",
|
|
11842
|
+
onClick: () => setMembersModalOpen(true),
|
|
11843
|
+
className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-xs font-medium text-gray-500 transition-all duration-150 hover:bg-gray-100 hover:text-gray-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200",
|
|
11844
|
+
"aria-label": t("BiChat.Share.Title"),
|
|
11845
|
+
title: t("BiChat.Share.Title"),
|
|
11846
|
+
children: [
|
|
11847
|
+
/* @__PURE__ */ jsx(ShareNetwork, { className: "h-4 w-4" }),
|
|
11848
|
+
t("BiChat.Share.Button")
|
|
11849
|
+
]
|
|
11850
|
+
}
|
|
11851
|
+
) : null;
|
|
11852
|
+
const headerActions = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11853
|
+
shareButton,
|
|
11854
|
+
showArtifactsControls && /* @__PURE__ */ jsxs(
|
|
11046
11855
|
"button",
|
|
11047
11856
|
{
|
|
11048
11857
|
type: "button",
|
|
@@ -11062,7 +11871,7 @@ function ChatSessionCore({
|
|
|
11062
11871
|
}
|
|
11063
11872
|
),
|
|
11064
11873
|
actionsSlot
|
|
11065
|
-
] })
|
|
11874
|
+
] });
|
|
11066
11875
|
return /* @__PURE__ */ jsxs(
|
|
11067
11876
|
"main",
|
|
11068
11877
|
{
|
|
@@ -11075,7 +11884,9 @@ function ChatSessionCore({
|
|
|
11075
11884
|
onBack,
|
|
11076
11885
|
readOnly: effectiveReadOnly,
|
|
11077
11886
|
logoSlot,
|
|
11078
|
-
actionsSlot: headerActions
|
|
11887
|
+
actionsSlot: headerActions,
|
|
11888
|
+
members: headerMembers ?? (session?.owner ? [session.owner] : void 0),
|
|
11889
|
+
onMembersClick: canShowShareButton ? () => setMembersModalOpen(true) : void 0
|
|
11079
11890
|
}
|
|
11080
11891
|
),
|
|
11081
11892
|
error && /* @__PURE__ */ jsx(
|
|
@@ -11272,6 +12083,15 @@ function ChatSessionCore({
|
|
|
11272
12083
|
) })
|
|
11273
12084
|
]
|
|
11274
12085
|
}
|
|
12086
|
+
),
|
|
12087
|
+
canShowShareButton && /* @__PURE__ */ jsx(
|
|
12088
|
+
SessionMembersModal,
|
|
12089
|
+
{
|
|
12090
|
+
isOpen: membersModalOpen,
|
|
12091
|
+
sessionId: session?.id,
|
|
12092
|
+
dataSource,
|
|
12093
|
+
onClose: () => setMembersModalOpen(false)
|
|
12094
|
+
}
|
|
11275
12095
|
)
|
|
11276
12096
|
]
|
|
11277
12097
|
}
|
|
@@ -11294,7 +12114,7 @@ function ChatSession(props) {
|
|
|
11294
12114
|
// ui/src/bichat/index.ts
|
|
11295
12115
|
init_MarkdownRenderer();
|
|
11296
12116
|
init_ChartCard();
|
|
11297
|
-
var
|
|
12117
|
+
var sizeClasses2 = {
|
|
11298
12118
|
sm: {
|
|
11299
12119
|
container: "py-6 px-3",
|
|
11300
12120
|
title: "text-sm",
|
|
@@ -11319,7 +12139,7 @@ function EmptyState({
|
|
|
11319
12139
|
className = "",
|
|
11320
12140
|
size = "md"
|
|
11321
12141
|
}) {
|
|
11322
|
-
const sizes =
|
|
12142
|
+
const sizes = sizeClasses2[size];
|
|
11323
12143
|
const prefersReducedMotion2 = useReducedMotion();
|
|
11324
12144
|
const duration = prefersReducedMotion2 ? 0 : 0.4;
|
|
11325
12145
|
return /* @__PURE__ */ jsx(
|
|
@@ -11379,7 +12199,7 @@ MemoizedEmptyState.displayName = "EmptyState";
|
|
|
11379
12199
|
|
|
11380
12200
|
// ui/src/bichat/components/EditableText.tsx
|
|
11381
12201
|
init_useTranslation();
|
|
11382
|
-
var
|
|
12202
|
+
var sizeClasses3 = {
|
|
11383
12203
|
sm: "text-sm",
|
|
11384
12204
|
md: "text-base",
|
|
11385
12205
|
lg: "text-lg"
|
|
@@ -11450,7 +12270,7 @@ var EditableText = forwardRef(
|
|
|
11450
12270
|
const handleBlur = () => {
|
|
11451
12271
|
handleSave();
|
|
11452
12272
|
};
|
|
11453
|
-
const sizeClass =
|
|
12273
|
+
const sizeClass = sizeClasses3[size];
|
|
11454
12274
|
if (isEditing) {
|
|
11455
12275
|
return /* @__PURE__ */ jsx(
|
|
11456
12276
|
"div",
|
|
@@ -11510,7 +12330,7 @@ var MemoizedEditableText = memo(EditableText);
|
|
|
11510
12330
|
|
|
11511
12331
|
// ui/src/bichat/components/SearchInput.tsx
|
|
11512
12332
|
init_useTranslation();
|
|
11513
|
-
var
|
|
12333
|
+
var sizeClasses4 = {
|
|
11514
12334
|
sm: {
|
|
11515
12335
|
container: "py-1.5 pl-8 pr-8 text-xs",
|
|
11516
12336
|
icon: 14,
|
|
@@ -11543,7 +12363,7 @@ function SearchInput({
|
|
|
11543
12363
|
const resolvedPlaceholder = placeholder ?? t("BiChat.Common.Search");
|
|
11544
12364
|
const resolvedAriaLabel = ariaLabel ?? t("BiChat.Common.Search");
|
|
11545
12365
|
const inputRef = useRef(null);
|
|
11546
|
-
const sizes =
|
|
12366
|
+
const sizes = sizeClasses4[size];
|
|
11547
12367
|
useEffect(() => {
|
|
11548
12368
|
if (autoFocus && inputRef.current) {
|
|
11549
12369
|
inputRef.current.focus();
|
|
@@ -11970,134 +12790,6 @@ function ToastContainer({ toasts, onDismiss, dismissLabel }) {
|
|
|
11970
12790
|
}
|
|
11971
12791
|
);
|
|
11972
12792
|
}
|
|
11973
|
-
|
|
11974
|
-
// ui/src/bichat/components/ConfirmModal.tsx
|
|
11975
|
-
init_useTranslation();
|
|
11976
|
-
function ConfirmModalBase({
|
|
11977
|
-
isOpen,
|
|
11978
|
-
title,
|
|
11979
|
-
message,
|
|
11980
|
-
onConfirm,
|
|
11981
|
-
onCancel,
|
|
11982
|
-
confirmText,
|
|
11983
|
-
cancelText,
|
|
11984
|
-
isDanger = false
|
|
11985
|
-
}) {
|
|
11986
|
-
const { t } = useTranslation();
|
|
11987
|
-
const resolvedConfirmText = confirmText?.trim() ? confirmText : t("BiChat.Common.Confirm");
|
|
11988
|
-
const resolvedCancelText = cancelText?.trim() ? cancelText : t("BiChat.Common.Cancel");
|
|
11989
|
-
return /* @__PURE__ */ jsxs(Dialog, { open: isOpen, onClose: onCancel, className: "relative z-40", children: [
|
|
11990
|
-
/* @__PURE__ */ jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm transition-opacity duration-200" }),
|
|
11991
|
-
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxs(DialogPanel, { className: "bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/30 max-w-sm w-full overflow-hidden", children: [
|
|
11992
|
-
/* @__PURE__ */ jsx("div", { className: "px-6 pt-6 pb-5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3.5", children: [
|
|
11993
|
-
isDanger && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 flex items-center justify-center w-10 h-10 rounded-xl bg-red-50 dark:bg-red-950/40 border border-red-200/60 dark:border-red-800/40", children: /* @__PURE__ */ jsx(WarningCircle, { size: 22, weight: "duotone", className: "text-red-600 dark:text-red-400" }) }),
|
|
11994
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
11995
|
-
/* @__PURE__ */ jsx(DialogTitle, { className: "text-base font-semibold text-gray-900 dark:text-gray-100 leading-snug", children: title }),
|
|
11996
|
-
/* @__PURE__ */ jsx(Description, { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 leading-relaxed", children: message })
|
|
11997
|
-
] })
|
|
11998
|
-
] }) }),
|
|
11999
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2.5 px-6 pb-5", children: [
|
|
12000
|
-
/* @__PURE__ */ jsx(
|
|
12001
|
-
"button",
|
|
12002
|
-
{
|
|
12003
|
-
type: "button",
|
|
12004
|
-
onClick: onCancel,
|
|
12005
|
-
...isDanger ? { "data-autofocus": true } : {},
|
|
12006
|
-
className: "cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700/60 hover:bg-gray-200 dark:hover:bg-gray-700 active:bg-gray-250 dark:active:bg-gray-600 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
12007
|
-
"data-testid": "confirm-modal-cancel",
|
|
12008
|
-
children: resolvedCancelText
|
|
12009
|
-
}
|
|
12010
|
-
),
|
|
12011
|
-
/* @__PURE__ */ jsx(
|
|
12012
|
-
"button",
|
|
12013
|
-
{
|
|
12014
|
-
type: "button",
|
|
12015
|
-
...!isDanger ? { "data-autofocus": true } : {},
|
|
12016
|
-
onClick: onConfirm,
|
|
12017
|
-
className: [
|
|
12018
|
-
"cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-white",
|
|
12019
|
-
"transition-all duration-150 shadow-sm hover:shadow",
|
|
12020
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
12021
|
-
isDanger ? "bg-red-600 hover:bg-red-700 active:bg-red-800 focus-visible:ring-red-500/50" : "bg-primary-600 hover:bg-primary-700 active:bg-primary-800 focus-visible:ring-primary-500/50"
|
|
12022
|
-
].join(" "),
|
|
12023
|
-
"data-testid": "confirm-modal-confirm",
|
|
12024
|
-
children: resolvedConfirmText
|
|
12025
|
-
}
|
|
12026
|
-
)
|
|
12027
|
-
] })
|
|
12028
|
-
] }) })
|
|
12029
|
-
] });
|
|
12030
|
-
}
|
|
12031
|
-
var ConfirmModal = memo(ConfirmModalBase);
|
|
12032
|
-
ConfirmModal.displayName = "ConfirmModal";
|
|
12033
|
-
var ConfirmModal_default = ConfirmModal;
|
|
12034
|
-
function hashString(str) {
|
|
12035
|
-
let hash = 0;
|
|
12036
|
-
for (let i = 0; i < str.length; i++) {
|
|
12037
|
-
const char = str.charCodeAt(i);
|
|
12038
|
-
hash = (hash << 5) - hash + char;
|
|
12039
|
-
hash = hash & hash;
|
|
12040
|
-
}
|
|
12041
|
-
return Math.abs(hash);
|
|
12042
|
-
}
|
|
12043
|
-
var colorPalette = [
|
|
12044
|
-
{ bg: "bg-blue-500", text: "text-white" },
|
|
12045
|
-
{ bg: "bg-green-500", text: "text-white" },
|
|
12046
|
-
{ bg: "bg-purple-500", text: "text-white" },
|
|
12047
|
-
{ bg: "bg-pink-500", text: "text-white" },
|
|
12048
|
-
{ bg: "bg-indigo-500", text: "text-white" },
|
|
12049
|
-
{ bg: "bg-teal-500", text: "text-white" },
|
|
12050
|
-
{ bg: "bg-orange-500", text: "text-white" },
|
|
12051
|
-
{ bg: "bg-cyan-500", text: "text-white" },
|
|
12052
|
-
{ bg: "bg-amber-500", text: "text-white" },
|
|
12053
|
-
{ bg: "bg-lime-500", text: "text-white" }
|
|
12054
|
-
];
|
|
12055
|
-
var sizeClasses4 = {
|
|
12056
|
-
sm: "w-8 h-8 text-xs",
|
|
12057
|
-
md: "w-10 h-10 text-sm",
|
|
12058
|
-
lg: "w-12 h-12 text-base"
|
|
12059
|
-
};
|
|
12060
|
-
function UserAvatar({
|
|
12061
|
-
firstName,
|
|
12062
|
-
lastName,
|
|
12063
|
-
initials: providedInitials,
|
|
12064
|
-
size = "md",
|
|
12065
|
-
className = ""
|
|
12066
|
-
}) {
|
|
12067
|
-
const derivedInitials = (() => {
|
|
12068
|
-
const firstChar = firstName?.trim()?.charAt(0) || "";
|
|
12069
|
-
const lastChar = lastName?.trim()?.charAt(0) || "";
|
|
12070
|
-
const combined = `${firstChar}${lastChar}`.trim();
|
|
12071
|
-
return combined || "U";
|
|
12072
|
-
})();
|
|
12073
|
-
const initials = (providedInitials?.trim() || derivedInitials).toUpperCase();
|
|
12074
|
-
const fullName = `${firstName}${lastName}`;
|
|
12075
|
-
const colorIndex = hashString(fullName) % colorPalette.length;
|
|
12076
|
-
const colors = colorPalette[colorIndex];
|
|
12077
|
-
return /* @__PURE__ */ jsx(
|
|
12078
|
-
"div",
|
|
12079
|
-
{
|
|
12080
|
-
className: `
|
|
12081
|
-
${sizeClasses4[size]}
|
|
12082
|
-
${colors.bg}
|
|
12083
|
-
${colors.text}
|
|
12084
|
-
${className}
|
|
12085
|
-
rounded-full
|
|
12086
|
-
flex
|
|
12087
|
-
items-center
|
|
12088
|
-
justify-center
|
|
12089
|
-
font-semibold
|
|
12090
|
-
flex-shrink-0
|
|
12091
|
-
select-none
|
|
12092
|
-
`,
|
|
12093
|
-
"aria-label": `${firstName} ${lastName}`,
|
|
12094
|
-
title: `${firstName} ${lastName}`,
|
|
12095
|
-
children: initials
|
|
12096
|
-
}
|
|
12097
|
-
);
|
|
12098
|
-
}
|
|
12099
|
-
var MemoizedUserAvatar = memo(UserAvatar);
|
|
12100
|
-
MemoizedUserAvatar.displayName = "UserAvatar";
|
|
12101
12793
|
function PermissionGuard({
|
|
12102
12794
|
permissions,
|
|
12103
12795
|
mode = "all",
|
|
@@ -12539,6 +13231,11 @@ var SessionItem = memo(
|
|
|
12539
13231
|
const isTitleGenerating = !session.title?.trim();
|
|
12540
13232
|
const displayTitle = isTitleGenerating ? t("BiChat.Common.Generating") : session.title ?? t("BiChat.Common.Untitled");
|
|
12541
13233
|
const lastActivity = formatRelativeTime(session.updatedAt, t);
|
|
13234
|
+
const accessRole = session.access?.role ?? "owner";
|
|
13235
|
+
const roleLabel = accessRole === "editor" ? t("BiChat.Share.RoleEditor") : accessRole === "viewer" ? t("BiChat.Share.RoleViewer") : accessRole === "read_all" ? t("BiChat.Share.RoleReadOnly") : "";
|
|
13236
|
+
const visibilityLabel = session.isGroup ? t("BiChat.Sidebar.GroupChat") : accessRole === "editor" || accessRole === "viewer" ? t("BiChat.Sidebar.SharedWithYou") : "";
|
|
13237
|
+
const isGroupOrShared = Boolean(session.isGroup || session.memberCount && session.memberCount > 1);
|
|
13238
|
+
const metaParts = [lastActivity, visibilityLabel, roleLabel].filter(Boolean);
|
|
12542
13239
|
const { handlers: longPressHandlers } = useLongPress({
|
|
12543
13240
|
delay: 500,
|
|
12544
13241
|
onLongPress: (e) => {
|
|
@@ -12680,17 +13377,23 @@ var SessionItem = memo(
|
|
|
12680
13377
|
"data-testid": `${testIdPrefix}-session-${session.id}`,
|
|
12681
13378
|
...longPressHandlers,
|
|
12682
13379
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
12683
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
12684
|
-
/* @__PURE__ */ jsx(
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
|
|
12692
|
-
|
|
12693
|
-
|
|
13380
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 min-w-0 flex-1", children: [
|
|
13381
|
+
isGroupOrShared && /* @__PURE__ */ jsx(UsersThree, { size: 14, weight: "duotone", className: "text-primary-500 dark:text-primary-400 mt-1 flex-shrink-0" }),
|
|
13382
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
13383
|
+
/* @__PURE__ */ jsx(
|
|
13384
|
+
MemoizedEditableText,
|
|
13385
|
+
{
|
|
13386
|
+
ref: editableTitleRef,
|
|
13387
|
+
value: displayTitle,
|
|
13388
|
+
onSave: (newTitle) => onRename?.(newTitle),
|
|
13389
|
+
isLoading: isTitleGenerating
|
|
13390
|
+
}
|
|
13391
|
+
),
|
|
13392
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[11px] text-gray-400 dark:text-gray-500 truncate mt-0.5", children: [
|
|
13393
|
+
metaParts.join(" \u2022 "),
|
|
13394
|
+
isGroupOrShared && session.memberCount && session.memberCount > 0 && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center ml-1 rounded-full bg-primary-50 dark:bg-primary-900/30 px-1.5 text-[10px] font-medium text-primary-600 dark:text-primary-400", children: session.memberCount })
|
|
13395
|
+
] })
|
|
13396
|
+
] })
|
|
12694
13397
|
] }),
|
|
12695
13398
|
!isTouch && hasContextMenu && /* @__PURE__ */ jsxs(Menu, { children: [
|
|
12696
13399
|
/* @__PURE__ */ jsx(
|
|
@@ -13044,24 +13747,23 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
|
|
|
13044
13747
|
setOffset((prev) => prev + limit);
|
|
13045
13748
|
}
|
|
13046
13749
|
}, [fetching, hasMore]);
|
|
13047
|
-
const
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13750
|
+
const loadMoreNodeRef = useRef(null);
|
|
13751
|
+
const loadMoreRef = useCallback((node) => {
|
|
13752
|
+
loadMoreNodeRef.current = node;
|
|
13753
|
+
}, []);
|
|
13754
|
+
useEffect(() => {
|
|
13755
|
+
const node = loadMoreNodeRef.current;
|
|
13756
|
+
if (!node || fetching || !hasMore) {
|
|
13757
|
+
return;
|
|
13758
|
+
}
|
|
13759
|
+
const observer = new IntersectionObserver((entries) => {
|
|
13760
|
+
if (entries[0].isIntersecting) {
|
|
13761
|
+
handleLoadMore();
|
|
13051
13762
|
}
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
}
|
|
13057
|
-
},
|
|
13058
|
-
{ threshold: 0.1 }
|
|
13059
|
-
);
|
|
13060
|
-
observer.observe(node);
|
|
13061
|
-
return () => observer.disconnect();
|
|
13062
|
-
},
|
|
13063
|
-
[fetching, hasMore, handleLoadMore]
|
|
13064
|
-
);
|
|
13763
|
+
}, { threshold: 0.1 });
|
|
13764
|
+
observer.observe(node);
|
|
13765
|
+
return () => observer.disconnect();
|
|
13766
|
+
}, [fetching, hasMore, handleLoadMore]);
|
|
13065
13767
|
const derivedUsers = useMemo(() => {
|
|
13066
13768
|
if (dataSource.listUsers) {
|
|
13067
13769
|
return users;
|
|
@@ -13119,57 +13821,61 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
|
|
|
13119
13821
|
role: "list",
|
|
13120
13822
|
"aria-label": t("BiChat.AllChats.OrganizationChatSessions"),
|
|
13121
13823
|
children: [
|
|
13122
|
-
chats.map((chat) =>
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
|
|
13824
|
+
chats.map((chat) => {
|
|
13825
|
+
const owner = chat.owner ?? {
|
|
13826
|
+
firstName: "",
|
|
13827
|
+
lastName: "",
|
|
13828
|
+
initials: "U"
|
|
13829
|
+
};
|
|
13830
|
+
const ownerName = [owner.firstName, owner.lastName].filter(Boolean).join(" ");
|
|
13831
|
+
return /* @__PURE__ */ jsx(
|
|
13832
|
+
motion.div,
|
|
13833
|
+
{
|
|
13834
|
+
initial: { opacity: 0, y: -10 },
|
|
13835
|
+
animate: { opacity: 1, y: 0 },
|
|
13836
|
+
exit: { opacity: 0, y: -10 },
|
|
13837
|
+
children: /* @__PURE__ */ jsx(
|
|
13838
|
+
"div",
|
|
13839
|
+
{
|
|
13840
|
+
role: "link",
|
|
13841
|
+
tabIndex: 0,
|
|
13842
|
+
onClick: () => onSessionSelect(chat.id),
|
|
13843
|
+
onKeyDown: (e) => {
|
|
13844
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
13845
|
+
e.preventDefault();
|
|
13846
|
+
onSessionSelect(chat.id);
|
|
13847
|
+
}
|
|
13848
|
+
},
|
|
13849
|
+
className: `
|
|
13141
13850
|
block px-3 py-2 rounded-lg transition-smooth group cursor-pointer
|
|
13142
13851
|
${chat.id === activeSessionId ? "bg-primary-50/50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 border-l-4 border-primary-400 dark:border-primary-600" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 border-l-4 border-transparent"}
|
|
13143
13852
|
`,
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
|
|
13148
|
-
|
|
13149
|
-
|
|
13150
|
-
|
|
13151
|
-
|
|
13152
|
-
|
|
13153
|
-
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
chat.
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
chat.status === "archived" && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 mt-1 px-2 py-0.5 bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 rounded-full text-xs", children: [
|
|
13163
|
-
/* @__PURE__ */ jsx(Archive, { size: 12, className: "w-3 h-3" }),
|
|
13164
|
-
t("BiChat.Chat.Archived")
|
|
13853
|
+
"aria-current": chat.id === activeSessionId ? "page" : void 0,
|
|
13854
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
13855
|
+
/* @__PURE__ */ jsx(
|
|
13856
|
+
MemoizedUserAvatar,
|
|
13857
|
+
{
|
|
13858
|
+
firstName: owner.firstName,
|
|
13859
|
+
lastName: owner.lastName,
|
|
13860
|
+
initials: owner.initials,
|
|
13861
|
+
size: "sm"
|
|
13862
|
+
}
|
|
13863
|
+
),
|
|
13864
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
13865
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: chat.title || t("BiChat.Common.Untitled") }),
|
|
13866
|
+
ownerName && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 truncate", children: ownerName }),
|
|
13867
|
+
chat.status === "archived" && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 mt-1 px-2 py-0.5 bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 rounded-full text-xs", children: [
|
|
13868
|
+
/* @__PURE__ */ jsx(Archive, { size: 12, className: "w-3 h-3" }),
|
|
13869
|
+
t("BiChat.Chat.Archived")
|
|
13870
|
+
] })
|
|
13165
13871
|
] })
|
|
13166
13872
|
] })
|
|
13167
|
-
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
)
|
|
13873
|
+
}
|
|
13874
|
+
)
|
|
13875
|
+
},
|
|
13876
|
+
chat.id
|
|
13877
|
+
);
|
|
13878
|
+
}),
|
|
13173
13879
|
hasMore && /* @__PURE__ */ jsx("div", { ref: loadMoreRef, className: "py-4 text-center", children: fetching ? /* @__PURE__ */ jsx(SessionSkeleton, { count: 2 }) : /* @__PURE__ */ jsx(
|
|
13174
13880
|
"button",
|
|
13175
13881
|
{
|
|
@@ -13939,19 +14645,22 @@ function Sidebar2({
|
|
|
13939
14645
|
animate: "visible",
|
|
13940
14646
|
role: "list",
|
|
13941
14647
|
"aria-label": t("BiChat.Sidebar.PinnedChats"),
|
|
13942
|
-
children: pinnedSessions.map((session) =>
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
14648
|
+
children: pinnedSessions.map((session) => {
|
|
14649
|
+
const canWrite = session.access?.canWrite ?? true;
|
|
14650
|
+
return /* @__PURE__ */ jsx(
|
|
14651
|
+
SessionItem_default,
|
|
14652
|
+
{
|
|
14653
|
+
session,
|
|
14654
|
+
isActive: session.id === activeSessionId,
|
|
14655
|
+
onSelect: () => handleSessionSelect(session.id),
|
|
14656
|
+
onArchive: canWrite ? () => handleSessionArchive(session.id) : void 0,
|
|
14657
|
+
onPin: canWrite ? () => handleSessionPin(session.id, session.pinned) : void 0,
|
|
14658
|
+
onRename: canWrite ? (newTitle) => handleSessionRename(session.id, newTitle) : void 0,
|
|
14659
|
+
onRegenerateTitle: canWrite ? () => handleSessionRegenerateTitle(session.id) : void 0
|
|
14660
|
+
},
|
|
14661
|
+
session.id
|
|
14662
|
+
);
|
|
14663
|
+
})
|
|
13955
14664
|
}
|
|
13956
14665
|
),
|
|
13957
14666
|
/* @__PURE__ */ jsx("div", { className: "border-b border-gray-200 dark:border-gray-700 my-3" })
|
|
@@ -13973,19 +14682,22 @@ function Sidebar2({
|
|
|
13973
14682
|
animate: "visible",
|
|
13974
14683
|
role: "list",
|
|
13975
14684
|
"aria-label": `${group.name} chats`,
|
|
13976
|
-
children: group.sessions.map((session) =>
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
14685
|
+
children: group.sessions.map((session) => {
|
|
14686
|
+
const canWrite = session.access?.canWrite ?? true;
|
|
14687
|
+
return /* @__PURE__ */ jsx(
|
|
14688
|
+
SessionItem_default,
|
|
14689
|
+
{
|
|
14690
|
+
session,
|
|
14691
|
+
isActive: session.id === activeSessionId,
|
|
14692
|
+
onSelect: () => handleSessionSelect(session.id),
|
|
14693
|
+
onArchive: canWrite ? () => handleSessionArchive(session.id) : void 0,
|
|
14694
|
+
onPin: canWrite ? () => handleSessionPin(session.id, session.pinned) : void 0,
|
|
14695
|
+
onRename: canWrite ? (newTitle) => handleSessionRename(session.id, newTitle) : void 0,
|
|
14696
|
+
onRegenerateTitle: canWrite ? () => handleSessionRegenerateTitle(session.id) : void 0
|
|
14697
|
+
},
|
|
14698
|
+
session.id
|
|
14699
|
+
);
|
|
14700
|
+
})
|
|
13989
14701
|
}
|
|
13990
14702
|
)
|
|
13991
14703
|
] }, group.name)),
|
|
@@ -14861,12 +15573,12 @@ function QuestionStep({
|
|
|
14861
15573
|
const data = selectedAnswers[question.id] || { };
|
|
14862
15574
|
setOtherText(data.customText || "");
|
|
14863
15575
|
}, [question.id]);
|
|
14864
|
-
const handleOptionClick = (
|
|
15576
|
+
const handleOptionClick = (optionID) => {
|
|
14865
15577
|
if (isMultiSelect) {
|
|
14866
|
-
const newOptions = selectedOptions.includes(
|
|
15578
|
+
const newOptions = selectedOptions.includes(optionID) ? selectedOptions.filter((a) => a !== optionID) : [...selectedOptions, optionID];
|
|
14867
15579
|
onAnswer({ options: newOptions, customText: otherText || void 0 });
|
|
14868
15580
|
} else {
|
|
14869
|
-
onAnswer({ options: [
|
|
15581
|
+
onAnswer({ options: [optionID], customText: otherText || void 0 });
|
|
14870
15582
|
}
|
|
14871
15583
|
};
|
|
14872
15584
|
const handleOtherTextChange = (text) => {
|
|
@@ -14880,11 +15592,11 @@ function QuestionStep({
|
|
|
14880
15592
|
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white mb-2", children: question.text }) }),
|
|
14881
15593
|
isMultiSelect && /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-500 italic", children: t("BiChat.Question.SelectMulti") }),
|
|
14882
15594
|
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: (question.options || []).map((option) => {
|
|
14883
|
-
const isSelected = selectedOptions.includes(option.
|
|
15595
|
+
const isSelected = selectedOptions.includes(option.id);
|
|
14884
15596
|
return /* @__PURE__ */ jsx(
|
|
14885
15597
|
"button",
|
|
14886
15598
|
{
|
|
14887
|
-
onClick: () => handleOptionClick(option.
|
|
15599
|
+
onClick: () => handleOptionClick(option.id),
|
|
14888
15600
|
className: `
|
|
14889
15601
|
cursor-pointer relative p-4 text-left border-2 rounded-lg transition-all
|
|
14890
15602
|
${isSelected ? "border-primary-500 bg-white dark:bg-gray-800" : "border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 hover:border-gray-300 dark:hover:border-gray-600"}
|
|
@@ -14952,6 +15664,7 @@ function ConfirmationStep({
|
|
|
14952
15664
|
const answerData = answers[question.id] || { options: [] };
|
|
14953
15665
|
const selectedOptions = answerData.options || [];
|
|
14954
15666
|
const customText = answerData.customText;
|
|
15667
|
+
const optionLabelByID = new Map((question.options || []).map((option) => [option.id, option.label]));
|
|
14955
15668
|
const hasAnswer = selectedOptions.length > 0 || !!customText;
|
|
14956
15669
|
return /* @__PURE__ */ jsxs(
|
|
14957
15670
|
"div",
|
|
@@ -14964,7 +15677,7 @@ function ConfirmationStep({
|
|
|
14964
15677
|
"span",
|
|
14965
15678
|
{
|
|
14966
15679
|
className: "inline-flex items-center px-3 py-1 rounded-lg text-sm font-medium border border-primary-500 bg-primary-500/10 text-primary-600 dark:border-primary-400 dark:bg-primary-400/10 dark:text-primary-400",
|
|
14967
|
-
children: option
|
|
15680
|
+
children: optionLabelByID.get(option) || option
|
|
14968
15681
|
},
|
|
14969
15682
|
option
|
|
14970
15683
|
)),
|
|
@@ -16145,6 +16858,76 @@ function useScrollToBottom(items) {
|
|
|
16145
16858
|
scrollToBottom
|
|
16146
16859
|
};
|
|
16147
16860
|
}
|
|
16861
|
+
function useHttpDataSourceConfigFromApplet(options) {
|
|
16862
|
+
return useMemo(() => {
|
|
16863
|
+
const ctx = typeof window !== "undefined" ? window.__APPLET_CONTEXT__ : void 0;
|
|
16864
|
+
if (!ctx) {
|
|
16865
|
+
throw new Error(
|
|
16866
|
+
"Applet context not found. Ensure window.__APPLET_CONTEXT__ is injected by the backend."
|
|
16867
|
+
);
|
|
16868
|
+
}
|
|
16869
|
+
const rpcEndpoint = ctx.config?.rpcUIEndpoint ?? "/rpc";
|
|
16870
|
+
const streamEndpoint = ctx.config?.streamEndpoint ?? "/stream";
|
|
16871
|
+
const csrfToken = ctx.session?.csrfToken ?? (typeof window !== "undefined" ? window.__CSRF_TOKEN__ : void 0) ?? "";
|
|
16872
|
+
const isDev = typeof import.meta.env?.DEV === "boolean" && import.meta.env?.DEV;
|
|
16873
|
+
if (!csrfToken && isDev) {
|
|
16874
|
+
console.warn(
|
|
16875
|
+
"[useHttpDataSourceConfigFromApplet] CSRF token is empty \u2014 requests may be rejected by the server."
|
|
16876
|
+
);
|
|
16877
|
+
}
|
|
16878
|
+
return {
|
|
16879
|
+
baseUrl: "",
|
|
16880
|
+
rpcEndpoint,
|
|
16881
|
+
streamEndpoint,
|
|
16882
|
+
csrfToken,
|
|
16883
|
+
timeout: options?.timeout ?? 12e4
|
|
16884
|
+
};
|
|
16885
|
+
}, [options?.timeout]);
|
|
16886
|
+
}
|
|
16887
|
+
var SESSION_PATH_REGEX = /\/session\/([^/]+)/;
|
|
16888
|
+
function useBichatRouter({
|
|
16889
|
+
navigate,
|
|
16890
|
+
pathname,
|
|
16891
|
+
onNavigate
|
|
16892
|
+
}) {
|
|
16893
|
+
const activeSessionId = useMemo(
|
|
16894
|
+
() => pathname.match(SESSION_PATH_REGEX)?.[1],
|
|
16895
|
+
[pathname]
|
|
16896
|
+
);
|
|
16897
|
+
const maybeClose = useCallback(() => {
|
|
16898
|
+
onNavigate?.();
|
|
16899
|
+
}, [onNavigate]);
|
|
16900
|
+
const onSessionSelect = useCallback(
|
|
16901
|
+
(sessionId) => {
|
|
16902
|
+
if (sessionId) {
|
|
16903
|
+
navigate(`/session/${sessionId}`);
|
|
16904
|
+
} else {
|
|
16905
|
+
navigate("/");
|
|
16906
|
+
}
|
|
16907
|
+
maybeClose();
|
|
16908
|
+
},
|
|
16909
|
+
[navigate, maybeClose]
|
|
16910
|
+
);
|
|
16911
|
+
const onNewChat = useCallback(() => {
|
|
16912
|
+
navigate("/");
|
|
16913
|
+
maybeClose();
|
|
16914
|
+
}, [navigate, maybeClose]);
|
|
16915
|
+
const onArchivedView = useCallback(() => {
|
|
16916
|
+
navigate("/archived");
|
|
16917
|
+
maybeClose();
|
|
16918
|
+
}, [navigate, maybeClose]);
|
|
16919
|
+
const onBack = useCallback(() => {
|
|
16920
|
+
navigate("/");
|
|
16921
|
+
maybeClose();
|
|
16922
|
+
}, [navigate, maybeClose]);
|
|
16923
|
+
return {
|
|
16924
|
+
activeSessionId,
|
|
16925
|
+
onSessionSelect,
|
|
16926
|
+
onNewChat,
|
|
16927
|
+
onArchivedView,
|
|
16928
|
+
onBack
|
|
16929
|
+
};
|
|
16930
|
+
}
|
|
16148
16931
|
|
|
16149
16932
|
// ui/src/bichat/index.ts
|
|
16150
16933
|
init_IotaContext();
|
|
@@ -16448,10 +17231,59 @@ function resolveArtifactName(artifact) {
|
|
|
16448
17231
|
}
|
|
16449
17232
|
return `${label} artifact`;
|
|
16450
17233
|
}
|
|
17234
|
+
function mapSessionUser(rawUser) {
|
|
17235
|
+
if (!isRecord2(rawUser)) {
|
|
17236
|
+
return void 0;
|
|
17237
|
+
}
|
|
17238
|
+
const rawId = rawUser.id;
|
|
17239
|
+
const id = readNonEmptyString(rawId) ?? (typeof rawId === "number" && Number.isFinite(rawId) ? String(rawId) : null);
|
|
17240
|
+
if (!id) {
|
|
17241
|
+
return void 0;
|
|
17242
|
+
}
|
|
17243
|
+
const firstName = readString2(rawUser.firstName);
|
|
17244
|
+
const lastName = readString2(rawUser.lastName);
|
|
17245
|
+
const initials = readNonEmptyString(rawUser.initials) || `${firstName.charAt(0)}${lastName.charAt(0)}`.trim().toUpperCase() || "U";
|
|
17246
|
+
return {
|
|
17247
|
+
id,
|
|
17248
|
+
firstName,
|
|
17249
|
+
lastName,
|
|
17250
|
+
initials
|
|
17251
|
+
};
|
|
17252
|
+
}
|
|
17253
|
+
function mapSessionAccess(rawAccess) {
|
|
17254
|
+
if (!isRecord2(rawAccess)) {
|
|
17255
|
+
return void 0;
|
|
17256
|
+
}
|
|
17257
|
+
const role = readString2(rawAccess.role).toLowerCase();
|
|
17258
|
+
const source = readString2(rawAccess.source).toLowerCase();
|
|
17259
|
+
const normalizedRole = role === "owner" || role === "editor" || role === "viewer" || role === "read_all" ? role : "none";
|
|
17260
|
+
const normalizedSource = source === "owner" || source === "member" || source === "permission" ? source : "none";
|
|
17261
|
+
const canRead = rawAccess.canRead === true || rawAccess.canRead === "true";
|
|
17262
|
+
const canWrite = rawAccess.canWrite === true || rawAccess.canWrite === "true";
|
|
17263
|
+
const canManageMembers = rawAccess.canManageMembers === true || rawAccess.canManageMembers === "true";
|
|
17264
|
+
if (normalizedRole === "none" && normalizedSource === "none" && !canRead && !canWrite && !canManageMembers) {
|
|
17265
|
+
return void 0;
|
|
17266
|
+
}
|
|
17267
|
+
return {
|
|
17268
|
+
role: normalizedRole,
|
|
17269
|
+
source: normalizedSource,
|
|
17270
|
+
canRead,
|
|
17271
|
+
canWrite,
|
|
17272
|
+
canManageMembers
|
|
17273
|
+
};
|
|
17274
|
+
}
|
|
16451
17275
|
function toSession(session) {
|
|
16452
17276
|
return {
|
|
16453
|
-
|
|
16454
|
-
|
|
17277
|
+
id: readString2(session.id),
|
|
17278
|
+
title: readString2(session.title),
|
|
17279
|
+
status: session.status === "archived" ? "archived" : "active",
|
|
17280
|
+
pinned: Boolean(session.pinned),
|
|
17281
|
+
createdAt: readString2(session.createdAt),
|
|
17282
|
+
updatedAt: readString2(session.updatedAt),
|
|
17283
|
+
owner: mapSessionUser(session.owner),
|
|
17284
|
+
isGroup: Boolean(session.isGroup),
|
|
17285
|
+
memberCount: typeof session.memberCount === "number" ? session.memberCount : void 0,
|
|
17286
|
+
access: mapSessionAccess(session.access)
|
|
16455
17287
|
};
|
|
16456
17288
|
}
|
|
16457
17289
|
function toSessionArtifact(artifact) {
|
|
@@ -16725,6 +17557,7 @@ function sanitizeConversationTurn(rawTurn, index, fallbackSessionID) {
|
|
|
16725
17557
|
id: userTurnID,
|
|
16726
17558
|
content: readString2(rawTurn.userTurn.content),
|
|
16727
17559
|
attachments: sanitizeUserAttachments(rawTurn.userTurn.attachments, turnID),
|
|
17560
|
+
author: mapSessionUser(rawTurn.userTurn.author),
|
|
16728
17561
|
createdAt: readString2(rawTurn.userTurn.createdAt, createdAt)
|
|
16729
17562
|
},
|
|
16730
17563
|
assistantTurn: sanitizeAssistantTurn(rawTurn.assistantTurn, createdAt, turnID),
|
|
@@ -16793,10 +17626,11 @@ function sanitizePendingQuestion(rawPendingQuestion, sessionID) {
|
|
|
16793
17626
|
return true;
|
|
16794
17627
|
}).map((option, optionIndex) => {
|
|
16795
17628
|
const label = readString2(option.label);
|
|
17629
|
+
const id = readString2(option.id, `${questionID}-opt-${optionIndex}`);
|
|
16796
17630
|
return {
|
|
16797
|
-
id
|
|
17631
|
+
id,
|
|
16798
17632
|
label,
|
|
16799
|
-
value:
|
|
17633
|
+
value: id
|
|
16800
17634
|
};
|
|
16801
17635
|
}) : [];
|
|
16802
17636
|
return {
|
|
@@ -17216,6 +18050,68 @@ async function clearSessionHistory(callRPC, sessionId) {
|
|
|
17216
18050
|
async function compactSessionHistory(callRPC, sessionId) {
|
|
17217
18051
|
return callRPC("bichat.session.compact", { id: sessionId });
|
|
17218
18052
|
}
|
|
18053
|
+
async function listUsers(callRPC) {
|
|
18054
|
+
const data = await callRPC("bichat.user.list", {});
|
|
18055
|
+
return data.users.map((user) => ({
|
|
18056
|
+
id: String(user.id),
|
|
18057
|
+
firstName: user.firstName || "",
|
|
18058
|
+
lastName: user.lastName || "",
|
|
18059
|
+
initials: user.initials || ""
|
|
18060
|
+
}));
|
|
18061
|
+
}
|
|
18062
|
+
async function listAllSessions(callRPC, options) {
|
|
18063
|
+
const data = await callRPC("bichat.session.listAll", {
|
|
18064
|
+
limit: options?.limit ?? 50,
|
|
18065
|
+
offset: options?.offset ?? 0,
|
|
18066
|
+
includeArchived: options?.includeArchived ?? false,
|
|
18067
|
+
userId: options?.userId ?? null
|
|
18068
|
+
});
|
|
18069
|
+
return {
|
|
18070
|
+
sessions: data.sessions.map(toSession),
|
|
18071
|
+
total: typeof data.total === "number" ? data.total : data.sessions.length,
|
|
18072
|
+
hasMore: Boolean(data.hasMore)
|
|
18073
|
+
};
|
|
18074
|
+
}
|
|
18075
|
+
async function listSessionMembers(callRPC, sessionId) {
|
|
18076
|
+
const data = await callRPC("bichat.session.members.list", { sessionId });
|
|
18077
|
+
return data.members.map((member) => ({
|
|
18078
|
+
user: {
|
|
18079
|
+
id: String(member.user.id),
|
|
18080
|
+
firstName: member.user.firstName,
|
|
18081
|
+
lastName: member.user.lastName,
|
|
18082
|
+
initials: member.user.initials
|
|
18083
|
+
},
|
|
18084
|
+
role: (() => {
|
|
18085
|
+
const normalizedRole = (member.role || "").toLowerCase();
|
|
18086
|
+
if (normalizedRole === "owner") {
|
|
18087
|
+
return "owner";
|
|
18088
|
+
}
|
|
18089
|
+
if (normalizedRole === "editor") {
|
|
18090
|
+
return "editor";
|
|
18091
|
+
}
|
|
18092
|
+
return "viewer";
|
|
18093
|
+
})(),
|
|
18094
|
+
createdAt: member.createdAt,
|
|
18095
|
+
updatedAt: member.updatedAt
|
|
18096
|
+
}));
|
|
18097
|
+
}
|
|
18098
|
+
async function addSessionMember(callRPC, sessionId, userId, role) {
|
|
18099
|
+
await callRPC("bichat.session.members.add", {
|
|
18100
|
+
sessionId,
|
|
18101
|
+
userId,
|
|
18102
|
+
role: role.toUpperCase()
|
|
18103
|
+
});
|
|
18104
|
+
}
|
|
18105
|
+
async function updateSessionMemberRole(callRPC, sessionId, userId, role) {
|
|
18106
|
+
await callRPC("bichat.session.members.updateRole", {
|
|
18107
|
+
sessionId,
|
|
18108
|
+
userId,
|
|
18109
|
+
role: role.toUpperCase()
|
|
18110
|
+
});
|
|
18111
|
+
}
|
|
18112
|
+
async function removeSessionMember(callRPC, sessionId, userId) {
|
|
18113
|
+
await callRPC("bichat.session.members.remove", { sessionId, userId });
|
|
18114
|
+
}
|
|
17219
18115
|
|
|
17220
18116
|
// ui/src/bichat/utils/sseParser.ts
|
|
17221
18117
|
function* processDataLines(lines) {
|
|
@@ -17774,12 +18670,19 @@ async function submitQuestionAnswers(callRPC, sessionId, questionId, answers) {
|
|
|
17774
18670
|
flatAnswers[qId] = answerData.options.join(", ");
|
|
17775
18671
|
}
|
|
17776
18672
|
}
|
|
17777
|
-
await callRPC("bichat.question.submit", {
|
|
18673
|
+
const result = await callRPC("bichat.question.submit", {
|
|
17778
18674
|
sessionId,
|
|
17779
18675
|
checkpointId: questionId,
|
|
17780
18676
|
answers: flatAnswers
|
|
17781
18677
|
});
|
|
17782
|
-
return {
|
|
18678
|
+
return {
|
|
18679
|
+
success: true,
|
|
18680
|
+
data: {
|
|
18681
|
+
session: toSession(result.session),
|
|
18682
|
+
turns: normalizeTurns(sanitizeConversationTurns(result.turns, sessionId)),
|
|
18683
|
+
pendingQuestion: sanitizePendingQuestion(result.pendingQuestion, sessionId)
|
|
18684
|
+
}
|
|
18685
|
+
};
|
|
17783
18686
|
} catch (err) {
|
|
17784
18687
|
return { success: false, error: err instanceof Error ? err.message : "Unknown error" };
|
|
17785
18688
|
}
|
|
@@ -17821,7 +18724,12 @@ async function uploadSessionArtifacts(callRPC, sessionId, files, uploadFileFn) {
|
|
|
17821
18724
|
const data = await callRPC("bichat.session.uploadArtifacts", {
|
|
17822
18725
|
sessionId,
|
|
17823
18726
|
attachments: uploads.map((upload) => ({
|
|
17824
|
-
|
|
18727
|
+
id: String(upload.id),
|
|
18728
|
+
filename: upload.name,
|
|
18729
|
+
uploadId: upload.id,
|
|
18730
|
+
mimeType: upload.mimetype || "application/octet-stream",
|
|
18731
|
+
sizeBytes: upload.size,
|
|
18732
|
+
url: upload.url
|
|
17825
18733
|
}))
|
|
17826
18734
|
});
|
|
17827
18735
|
return {
|
|
@@ -17948,6 +18856,24 @@ var HttpDataSource = class {
|
|
|
17948
18856
|
async compactSessionHistory(sessionId) {
|
|
17949
18857
|
return compactSessionHistory(this.boundCallRPC, sessionId);
|
|
17950
18858
|
}
|
|
18859
|
+
async listUsers() {
|
|
18860
|
+
return listUsers(this.boundCallRPC);
|
|
18861
|
+
}
|
|
18862
|
+
async listAllSessions(options) {
|
|
18863
|
+
return listAllSessions(this.boundCallRPC, options);
|
|
18864
|
+
}
|
|
18865
|
+
async listSessionMembers(sessionId) {
|
|
18866
|
+
return listSessionMembers(this.boundCallRPC, sessionId);
|
|
18867
|
+
}
|
|
18868
|
+
async addSessionMember(sessionId, userId, role) {
|
|
18869
|
+
return addSessionMember(this.boundCallRPC, sessionId, userId, role);
|
|
18870
|
+
}
|
|
18871
|
+
async updateSessionMemberRole(sessionId, userId, role) {
|
|
18872
|
+
return updateSessionMemberRole(this.boundCallRPC, sessionId, userId, role);
|
|
18873
|
+
}
|
|
18874
|
+
async removeSessionMember(sessionId, userId) {
|
|
18875
|
+
return removeSessionMember(this.boundCallRPC, sessionId, userId);
|
|
18876
|
+
}
|
|
17951
18877
|
// -------------------------------------------------------------------------
|
|
17952
18878
|
// Message transport (delegates to MessageTransport)
|
|
17953
18879
|
// -------------------------------------------------------------------------
|
|
@@ -18070,6 +18996,6 @@ function createHttpDataSource(config) {
|
|
|
18070
18996
|
return new HttpDataSource(config);
|
|
18071
18997
|
}
|
|
18072
18998
|
|
|
18073
|
-
export { ATTACHMENT_ACCEPT_ATTRIBUTE, ActionButton, ActivityTrace, Alert_default as Alert, AllChatsList, ArchiveBanner_default as ArchiveBanner, ArchivedChatList, AssistantMessage, AssistantTurnView, MemoizedAttachmentGrid as AttachmentGrid, AttachmentPreview_default as AttachmentPreview, AttachmentUpload_default as AttachmentUpload, Avatar, BiChatLayout, Bubble, CHART_VISUAL, ChartCard, ChatHeader, ChatMachine, ChatSession, ChatSessionProvider, MemoizedCodeBlock as CodeBlock, CodeOutputsPanel, CompactionDoodle, ConfigProvider, ConfirmModal, ConfirmationStep, DateGroupHeader, DebugPanel, DefaultErrorContent, DownloadCard, MemoizedEditableText as EditableText, MemoizedEmptyState as EmptyState, ErrorBoundary, HttpDataSource, ImageModal, InlineQuestionForm, InteractiveTableCard, IotaContextProvider, ListItemSkeleton, MemoizedLoadingSpinner as LoadingSpinner, MemoizedMarkdownRenderer as MarkdownRenderer, MessageActions, MessageInput, MessageList, MessageRole, PermissionGuard, QuestionForm, QuestionStep, RateLimiter, RetryActionArea, ScreenReaderAnnouncer, ScrollToBottomButton, MemoizedSearchInput as SearchInput, SessionArtifactList, SessionArtifactPreview, SessionArtifactsPanel, SessionItem_default as SessionItem, SessionSkeleton, Sidebar2 as Sidebar, MemoizedSkeleton as Skeleton, SkeletonAvatar, SkeletonCard, SkeletonGroup, SkeletonText, SkipLink, Slot, SourcesPanel, StreamError, StreamingCursor, SystemMessage, TabbedChartGroup, TabbedTableGroup, TableExportButton, TableWithExport, ThemeProvider, Toast, ToastContainer, TouchContextMenu, Turn, TurnBubble, MemoizedTypingIndicator as TypingIndicator, MemoizedUserAvatar as UserAvatar, MemoizedUserFilter as UserFilter, UserMessage, UserTurnView, WelcomeContent, addCSRFHeader, backdropVariants, buttonVariants, convertToBase64, createDataUrl, createHeadersWithCSRF, createHttpDataSource, darkTheme, dropdownVariants, errorMessageVariants, fadeInUpVariants, fadeInVariants, floatingButtonVariants, formatFileSize, getCSRFToken, getFileVisual, getToolLabel, getValidChildren, groupSessionsByDate, groupSteps, hasPermission, isImageMimeType, isPermissionDeniedError, lightTheme, listItemVariants, messageContainerVariants, messageVariants, parseBichatStream, parseBichatStreamEvents, parseSSEStream, scaleFadeVariants, sessionItemVariants, staggerContainerVariants, toErrorDisplay, typingDotVariants, useActionButtonContext, useAttachments, useAutoScroll, useAvatarContext, useBubbleContext, useChatInput, useChatMessaging, useChatSession, useConfig, useDataTable, useFocusTrap, useImageGallery, useIotaContext, useKeyboardShortcuts, useLongPress, useMarkdownCopy, useMessageActions, useModalLock, useOptionalChatMessaging, useRequiredConfig, useScrollToBottom, useSidebarState, useStreaming2 as useStreaming, useTheme, useToast, useTranslation, useTurnContext, validateAttachmentFile, validateFileCount, validateImageFile, verbTransitionVariants };
|
|
18999
|
+
export { ATTACHMENT_ACCEPT_ATTRIBUTE, ActionButton, ActivityTrace, Alert_default as Alert, AllChatsList, ArchiveBanner_default as ArchiveBanner, ArchivedChatList, AssistantMessage, AssistantTurnView, MemoizedAttachmentGrid as AttachmentGrid, AttachmentPreview_default as AttachmentPreview, AttachmentUpload_default as AttachmentUpload, Avatar, AvatarStack, BiChatLayout, Bubble, CHART_VISUAL, ChartCard, ChatHeader, ChatMachine, ChatSession, ChatSessionProvider, MemoizedCodeBlock as CodeBlock, CodeOutputsPanel, CompactionDoodle, ConfigProvider, ConfirmModal, ConfirmationStep, DateGroupHeader, DebugPanel, DefaultErrorContent, DownloadCard, MemoizedEditableText as EditableText, MemoizedEmptyState as EmptyState, ErrorBoundary, HttpDataSource, ImageModal, InlineQuestionForm, InteractiveTableCard, IotaContextProvider, ListItemSkeleton, MemoizedLoadingSpinner as LoadingSpinner, MemoizedMarkdownRenderer as MarkdownRenderer, MessageActions, MessageInput, MessageList, MessageRole, PermissionGuard, QuestionForm, QuestionStep, RateLimiter, RetryActionArea, ScreenReaderAnnouncer, ScrollToBottomButton, MemoizedSearchInput as SearchInput, SessionArtifactList, SessionArtifactPreview, SessionArtifactsPanel, SessionItem_default as SessionItem, SessionMembersModal, SessionSkeleton, Sidebar2 as Sidebar, MemoizedSkeleton as Skeleton, SkeletonAvatar, SkeletonCard, SkeletonGroup, SkeletonText, SkipLink, Slot, SourcesPanel, StreamError, StreamingCursor, SystemMessage, TabbedChartGroup, TabbedTableGroup, TableExportButton, TableWithExport, ThemeProvider, Toast, ToastContainer, TouchContextMenu, Turn, TurnBubble, MemoizedTypingIndicator as TypingIndicator, MemoizedUserAvatar as UserAvatar, MemoizedUserFilter as UserFilter, UserMessage, UserTurnView, WelcomeContent, addCSRFHeader, backdropVariants, buttonVariants, convertToBase64, createDataUrl, createHeadersWithCSRF, createHttpDataSource, darkTheme, dropdownVariants, errorMessageVariants, fadeInUpVariants, fadeInVariants, floatingButtonVariants, formatFileSize, getCSRFToken, getFileVisual, getToolLabel, getValidChildren, groupSessionsByDate, groupSteps, hasPermission, isImageMimeType, isPermissionDeniedError, lightTheme, listItemVariants, messageContainerVariants, messageVariants, parseBichatStream, parseBichatStreamEvents, parseSSEStream, scaleFadeVariants, sessionItemVariants, staggerContainerVariants, toErrorDisplay, typingDotVariants, useActionButtonContext, useAttachments, useAutoScroll, useAvatarContext, useBichatRouter, useBubbleContext, useChatInput, useChatMessaging, useChatSession, useConfig, useDataTable, useFocusTrap, useHttpDataSourceConfigFromApplet, useImageGallery, useIotaContext, useKeyboardShortcuts, useLongPress, useMarkdownCopy, useMessageActions, useModalLock, useOptionalChatMessaging, useRequiredConfig, useScrollToBottom, useSidebarState, useStreaming2 as useStreaming, useTheme, useToast, useTranslation, useTurnContext, validateAttachmentFile, validateFileCount, validateImageFile, verbTransitionVariants };
|
|
18074
19000
|
//# sourceMappingURL=index.mjs.map
|
|
18075
19001
|
//# sourceMappingURL=index.mjs.map
|