@timbal-ai/timbal-react 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -13
- package/dist/index.cjs +2635 -727
- package/dist/index.d.cts +325 -150
- package/dist/index.d.ts +325 -150
- package/dist/index.esm.js +2613 -693
- package/dist/styles.css +312 -52
- package/package.json +2 -1
package/dist/index.esm.js
CHANGED
|
@@ -867,6 +867,30 @@ function findParentIdFromAuiParent(messages, auiParentId) {
|
|
|
867
867
|
// src/index.ts
|
|
868
868
|
import { parseSSELine as parseSSELine2 } from "@timbal-ai/timbal-sdk";
|
|
869
869
|
|
|
870
|
+
// src/components/thread.tsx
|
|
871
|
+
import { useEffect as useEffect5 } from "react";
|
|
872
|
+
import {
|
|
873
|
+
ActionBarMorePrimitive,
|
|
874
|
+
ActionBarPrimitive,
|
|
875
|
+
AuiIf as AuiIf2,
|
|
876
|
+
ComposerPrimitive as ComposerPrimitive3,
|
|
877
|
+
ErrorPrimitive,
|
|
878
|
+
MessagePartPrimitive,
|
|
879
|
+
MessagePrimitive as MessagePrimitive2,
|
|
880
|
+
ThreadPrimitive,
|
|
881
|
+
useThread
|
|
882
|
+
} from "@assistant-ui/react";
|
|
883
|
+
import {
|
|
884
|
+
ArrowDownIcon,
|
|
885
|
+
CheckIcon as CheckIcon3,
|
|
886
|
+
CopyIcon as CopyIcon2,
|
|
887
|
+
DownloadIcon,
|
|
888
|
+
MoreHorizontalIcon,
|
|
889
|
+
PencilIcon,
|
|
890
|
+
RefreshCwIcon
|
|
891
|
+
} from "lucide-react";
|
|
892
|
+
import { motion as motion4 } from "motion/react";
|
|
893
|
+
|
|
870
894
|
// src/components/attachment.tsx
|
|
871
895
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
872
896
|
import { XIcon as XIcon2, PlusIcon, FileText } from "lucide-react";
|
|
@@ -1079,87 +1103,170 @@ function AvatarFallback({
|
|
|
1079
1103
|
}
|
|
1080
1104
|
|
|
1081
1105
|
// src/components/tooltip-icon-button.tsx
|
|
1082
|
-
import { forwardRef } from "react";
|
|
1083
|
-
import { Slottable } from "@radix-ui/react-slot";
|
|
1106
|
+
import { forwardRef as forwardRef2 } from "react";
|
|
1084
1107
|
|
|
1085
|
-
// src/ui/button.tsx
|
|
1086
|
-
import
|
|
1108
|
+
// src/ui/timbal-v2-button.tsx
|
|
1109
|
+
import * as React from "react";
|
|
1087
1110
|
import { Slot } from "radix-ui";
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
)
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1111
|
+
|
|
1112
|
+
// src/design/button-tokens.ts
|
|
1113
|
+
var TIMBAL_V2_SIZE_HEIGHT = {
|
|
1114
|
+
xs: "min-h-8 h-8",
|
|
1115
|
+
sm: "min-h-9 h-9",
|
|
1116
|
+
md: "min-h-10 h-10",
|
|
1117
|
+
lg: "min-h-11 h-11"
|
|
1118
|
+
};
|
|
1119
|
+
var TIMBAL_V2_SIZE_ICON = {
|
|
1120
|
+
xs: "min-h-8 min-w-8 size-8",
|
|
1121
|
+
sm: "min-h-8 min-w-8 size-8",
|
|
1122
|
+
md: "min-h-10 min-w-10 size-10",
|
|
1123
|
+
lg: "min-h-11 min-w-11 size-11"
|
|
1124
|
+
};
|
|
1125
|
+
var TIMBAL_V2_SIZE_LABEL_PX = {
|
|
1126
|
+
xs: "px-3",
|
|
1127
|
+
sm: "px-4",
|
|
1128
|
+
md: "px-5",
|
|
1129
|
+
lg: "px-6"
|
|
1130
|
+
};
|
|
1131
|
+
var TIMBAL_V2_FILL = {
|
|
1132
|
+
primary: [
|
|
1133
|
+
"bg-gradient-to-b from-primary-fill-from to-primary-fill-to",
|
|
1134
|
+
"group-hover/tbv2:from-primary-fill-hover-from group-hover/tbv2:to-primary-fill-hover-to",
|
|
1135
|
+
"group-active/tbv2:from-primary-fill-active-from group-active/tbv2:to-primary-fill-active-to"
|
|
1136
|
+
].join(" "),
|
|
1137
|
+
informative: [
|
|
1138
|
+
"bg-primary",
|
|
1139
|
+
"group-active/tbv2:[background-image:linear-gradient(to_top,rgba(0,0,0,0.08),transparent_55%)]"
|
|
1140
|
+
].join(" "),
|
|
1141
|
+
destructive: [
|
|
1142
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to",
|
|
1143
|
+
"group-hover/tbv2:from-destructive-fill-hover-from group-hover/tbv2:to-destructive-fill-hover-to",
|
|
1144
|
+
"group-active/tbv2:from-destructive-fill-active-from group-active/tbv2:to-destructive-fill-active-to"
|
|
1145
|
+
].join(" "),
|
|
1146
|
+
secondary: [
|
|
1147
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to",
|
|
1148
|
+
"group-hover/tbv2:from-secondary-fill-hover-from group-hover/tbv2:to-secondary-fill-hover-to",
|
|
1149
|
+
"group-active/tbv2:from-secondary-fill-active-from group-active/tbv2:to-secondary-fill-active-to"
|
|
1150
|
+
].join(" "),
|
|
1151
|
+
ghost: [
|
|
1152
|
+
"bg-transparent",
|
|
1153
|
+
"group-hover/tbv2:bg-ghost-fill-hover",
|
|
1154
|
+
"group-active/tbv2:bg-ghost-fill-active"
|
|
1155
|
+
].join(" "),
|
|
1156
|
+
link: "bg-transparent"
|
|
1157
|
+
};
|
|
1158
|
+
var TIMBAL_V2_LABEL = {
|
|
1159
|
+
primary: "text-primary-foreground",
|
|
1160
|
+
informative: "text-primary-foreground",
|
|
1161
|
+
destructive: "text-destructive",
|
|
1162
|
+
secondary: "text-foreground",
|
|
1163
|
+
ghost: "text-foreground",
|
|
1164
|
+
link: "text-foreground underline decoration-foreground/25 underline-offset-2 group-hover/tbv2:decoration-foreground/45"
|
|
1165
|
+
};
|
|
1166
|
+
var TIMBAL_V2_BORDER = {
|
|
1167
|
+
primary: "",
|
|
1168
|
+
informative: "border border-foreground/15",
|
|
1169
|
+
destructive: "border border-destructive/45",
|
|
1170
|
+
secondary: "border border-border",
|
|
1171
|
+
ghost: "",
|
|
1172
|
+
link: ""
|
|
1173
|
+
};
|
|
1174
|
+
var TIMBAL_V2_SHADOW = {
|
|
1175
|
+
primary: "shadow-card",
|
|
1176
|
+
informative: "shadow-card",
|
|
1177
|
+
destructive: "shadow-card",
|
|
1178
|
+
secondary: "shadow-card",
|
|
1179
|
+
ghost: "",
|
|
1180
|
+
link: ""
|
|
1181
|
+
};
|
|
1182
|
+
var TIMBAL_V2_SECONDARY_CHROME = [
|
|
1183
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to border border-border shadow-card",
|
|
1184
|
+
"transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
|
|
1185
|
+
"hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to",
|
|
1186
|
+
"active:from-secondary-fill-active-from active:to-secondary-fill-active-to"
|
|
1187
|
+
].join(" ");
|
|
1188
|
+
|
|
1189
|
+
// src/ui/timbal-v2-button.tsx
|
|
1190
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1191
|
+
var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
|
|
1192
|
+
variant = "secondary",
|
|
1193
|
+
size = "sm",
|
|
1194
|
+
isIconOnly = false,
|
|
1195
|
+
isLoading = false,
|
|
1196
|
+
fullWidth = false,
|
|
1122
1197
|
asChild = false,
|
|
1198
|
+
className,
|
|
1199
|
+
disabled,
|
|
1200
|
+
type = "button",
|
|
1201
|
+
children,
|
|
1123
1202
|
...props
|
|
1124
|
-
}) {
|
|
1203
|
+
}, ref) {
|
|
1204
|
+
const isDisabled = disabled || isLoading;
|
|
1125
1205
|
const Comp = asChild ? Slot.Root : "button";
|
|
1126
|
-
|
|
1206
|
+
const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
|
|
1207
|
+
const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : "rounded-full";
|
|
1208
|
+
return /* @__PURE__ */ jsxs3(
|
|
1127
1209
|
Comp,
|
|
1128
1210
|
{
|
|
1129
|
-
|
|
1211
|
+
ref,
|
|
1212
|
+
type: asChild ? void 0 : type,
|
|
1213
|
+
disabled: asChild ? void 0 : isDisabled,
|
|
1214
|
+
"aria-disabled": asChild && isDisabled ? true : void 0,
|
|
1215
|
+
"data-slot": "timbal-v2-button",
|
|
1130
1216
|
"data-variant": variant,
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1217
|
+
className: cn(
|
|
1218
|
+
"group/tbv2 relative box-border inline-flex flex-col items-stretch overflow-hidden border-0 bg-transparent p-0 text-sm font-normal shadow-none transition duration-200 ease-in-out",
|
|
1219
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
|
1220
|
+
sizeClass,
|
|
1221
|
+
radiusClass,
|
|
1222
|
+
TIMBAL_V2_BORDER[variant],
|
|
1223
|
+
TIMBAL_V2_SHADOW[variant],
|
|
1224
|
+
fullWidth && "w-full",
|
|
1225
|
+
isDisabled && "pointer-events-none opacity-50",
|
|
1226
|
+
className
|
|
1227
|
+
),
|
|
1228
|
+
...props,
|
|
1229
|
+
children: [
|
|
1230
|
+
/* @__PURE__ */ jsx5(
|
|
1231
|
+
"span",
|
|
1232
|
+
{
|
|
1233
|
+
"aria-hidden": true,
|
|
1234
|
+
className: cn(
|
|
1235
|
+
"pointer-events-none absolute inset-0 transition duration-200 ease-in-out",
|
|
1236
|
+
TIMBAL_V2_FILL[variant]
|
|
1237
|
+
)
|
|
1238
|
+
}
|
|
1239
|
+
),
|
|
1240
|
+
/* @__PURE__ */ jsx5(
|
|
1241
|
+
"span",
|
|
1242
|
+
{
|
|
1243
|
+
className: cn(
|
|
1244
|
+
"relative z-10 flex min-h-0 flex-1 items-center justify-center gap-1 leading-tight",
|
|
1245
|
+
!isIconOnly && TIMBAL_V2_SIZE_LABEL_PX[size],
|
|
1246
|
+
TIMBAL_V2_LABEL[variant]
|
|
1247
|
+
),
|
|
1248
|
+
children: isLoading ? /* @__PURE__ */ jsx5("span", { className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : children
|
|
1249
|
+
}
|
|
1250
|
+
)
|
|
1251
|
+
]
|
|
1134
1252
|
}
|
|
1135
1253
|
);
|
|
1136
|
-
}
|
|
1254
|
+
});
|
|
1137
1255
|
|
|
1138
1256
|
// src/components/tooltip-icon-button.tsx
|
|
1139
|
-
import { jsx as jsx6, jsxs as
|
|
1140
|
-
var TooltipIconButton =
|
|
1141
|
-
return /* @__PURE__ */
|
|
1142
|
-
/* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */
|
|
1143
|
-
|
|
1144
|
-
{
|
|
1145
|
-
|
|
1146
|
-
size: "icon",
|
|
1147
|
-
...rest,
|
|
1148
|
-
className: cn("aui-button-icon size-6 p-1", className),
|
|
1149
|
-
ref,
|
|
1150
|
-
children: [
|
|
1151
|
-
/* @__PURE__ */ jsx6(Slottable, { children }),
|
|
1152
|
-
/* @__PURE__ */ jsx6("span", { className: "aui-sr-only sr-only", children: tooltip })
|
|
1153
|
-
]
|
|
1154
|
-
}
|
|
1155
|
-
) }),
|
|
1257
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1258
|
+
var TooltipIconButton = forwardRef2(function TooltipIconButton2({ tooltip, side = "bottom", variant = "secondary", children, ...props }, ref) {
|
|
1259
|
+
return /* @__PURE__ */ jsxs4(Tooltip, { children: [
|
|
1260
|
+
/* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(TimbalV2Button, { ref, variant, size: "sm", isIconOnly: true, ...props, children: [
|
|
1261
|
+
children,
|
|
1262
|
+
/* @__PURE__ */ jsx6("span", { className: "sr-only", children: tooltip })
|
|
1263
|
+
] }) }),
|
|
1156
1264
|
/* @__PURE__ */ jsx6(TooltipContent, { side, children: tooltip })
|
|
1157
1265
|
] });
|
|
1158
1266
|
});
|
|
1159
|
-
TooltipIconButton.displayName = "TooltipIconButton";
|
|
1160
1267
|
|
|
1161
1268
|
// src/components/attachment.tsx
|
|
1162
|
-
import { jsx as jsx7, jsxs as
|
|
1269
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1163
1270
|
var useFileSrc = (file) => {
|
|
1164
1271
|
const [src, setSrc] = useState2(void 0);
|
|
1165
1272
|
useEffect2(() => {
|
|
@@ -1205,7 +1312,7 @@ var AttachmentPreview = ({ src }) => {
|
|
|
1205
1312
|
var AttachmentPreviewDialog = ({ children }) => {
|
|
1206
1313
|
const src = useAttachmentSrc();
|
|
1207
1314
|
if (!src) return children;
|
|
1208
|
-
return /* @__PURE__ */
|
|
1315
|
+
return /* @__PURE__ */ jsxs5(Dialog, { children: [
|
|
1209
1316
|
/* @__PURE__ */ jsx7(
|
|
1210
1317
|
DialogTrigger,
|
|
1211
1318
|
{
|
|
@@ -1214,7 +1321,7 @@ var AttachmentPreviewDialog = ({ children }) => {
|
|
|
1214
1321
|
children
|
|
1215
1322
|
}
|
|
1216
1323
|
),
|
|
1217
|
-
/* @__PURE__ */
|
|
1324
|
+
/* @__PURE__ */ jsxs5(DialogContent, { className: "aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:ring-0! [&_svg]:text-background [&>button]:hover:[&_svg]:text-destructive", children: [
|
|
1218
1325
|
/* @__PURE__ */ jsx7(DialogTitle, { className: "aui-sr-only sr-only", children: "Image Attachment Preview" }),
|
|
1219
1326
|
/* @__PURE__ */ jsx7("div", { className: "aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background", children: /* @__PURE__ */ jsx7(AttachmentPreview, { src }) })
|
|
1220
1327
|
] })
|
|
@@ -1223,7 +1330,7 @@ var AttachmentPreviewDialog = ({ children }) => {
|
|
|
1223
1330
|
var AttachmentThumb = () => {
|
|
1224
1331
|
const isImage = useAuiState((s) => s.attachment.type === "image");
|
|
1225
1332
|
const src = useAttachmentSrc();
|
|
1226
|
-
return /* @__PURE__ */
|
|
1333
|
+
return /* @__PURE__ */ jsxs5(Avatar, { className: "aui-attachment-tile-avatar h-full w-full rounded-none", children: [
|
|
1227
1334
|
/* @__PURE__ */ jsx7(
|
|
1228
1335
|
AvatarImage,
|
|
1229
1336
|
{
|
|
@@ -1252,8 +1359,8 @@ var AttachmentUI = () => {
|
|
|
1252
1359
|
throw new Error(`Unknown attachment type: ${type}`);
|
|
1253
1360
|
}
|
|
1254
1361
|
});
|
|
1255
|
-
return /* @__PURE__ */
|
|
1256
|
-
/* @__PURE__ */
|
|
1362
|
+
return /* @__PURE__ */ jsxs5(Tooltip, { children: [
|
|
1363
|
+
/* @__PURE__ */ jsxs5(
|
|
1257
1364
|
AttachmentPrimitive.Root,
|
|
1258
1365
|
{
|
|
1259
1366
|
className: cn(
|
|
@@ -1286,9 +1393,9 @@ var AttachmentRemove = () => {
|
|
|
1286
1393
|
TooltipIconButton,
|
|
1287
1394
|
{
|
|
1288
1395
|
tooltip: "Remove file",
|
|
1289
|
-
className: "aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-
|
|
1396
|
+
className: "aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-card text-foreground opacity-100 shadow-card hover:bg-card! [&_svg]:text-foreground hover:[&_svg]:text-destructive",
|
|
1290
1397
|
side: "top",
|
|
1291
|
-
children: /* @__PURE__ */ jsx7(XIcon2, { className: "aui-attachment-remove-icon size-3
|
|
1398
|
+
children: /* @__PURE__ */ jsx7(XIcon2, { className: "aui-attachment-remove-icon size-3" })
|
|
1292
1399
|
}
|
|
1293
1400
|
) });
|
|
1294
1401
|
};
|
|
@@ -1309,11 +1416,10 @@ var ComposerAddAttachment = () => {
|
|
|
1309
1416
|
{
|
|
1310
1417
|
tooltip: "Add Attachment",
|
|
1311
1418
|
side: "bottom",
|
|
1312
|
-
variant: "
|
|
1313
|
-
|
|
1314
|
-
className: "aui-composer-add-attachment size-8.5 rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30",
|
|
1419
|
+
variant: "secondary",
|
|
1420
|
+
className: "aui-composer-add-attachment shrink-0 text-muted-foreground",
|
|
1315
1421
|
"aria-label": "Add Attachment",
|
|
1316
|
-
children: /* @__PURE__ */ jsx7(PlusIcon, { className: "aui-attachment-add-icon size-
|
|
1422
|
+
children: /* @__PURE__ */ jsx7(PlusIcon, { className: "aui-attachment-add-icon size-4 stroke-[1.5]" })
|
|
1317
1423
|
}
|
|
1318
1424
|
) });
|
|
1319
1425
|
};
|
|
@@ -1344,10 +1450,10 @@ import { createContext as createContext3, useContext as useContext3, useMemo as
|
|
|
1344
1450
|
import { useMemo as useMemo2 } from "react";
|
|
1345
1451
|
|
|
1346
1452
|
// src/artifacts/artifact-card.tsx
|
|
1347
|
-
import { jsx as jsx8, jsxs as
|
|
1453
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1348
1454
|
var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }) => {
|
|
1349
1455
|
const hasHeader = Boolean(title || toolbar);
|
|
1350
|
-
return /* @__PURE__ */
|
|
1456
|
+
return /* @__PURE__ */ jsxs6(
|
|
1351
1457
|
"div",
|
|
1352
1458
|
{
|
|
1353
1459
|
className: cn(
|
|
@@ -1356,7 +1462,7 @@ var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }
|
|
|
1356
1462
|
),
|
|
1357
1463
|
"data-artifact-kind": kind,
|
|
1358
1464
|
children: [
|
|
1359
|
-
hasHeader && /* @__PURE__ */
|
|
1465
|
+
hasHeader && /* @__PURE__ */ jsxs6("div", { className: "aui-artifact-header flex items-center gap-2 border-b border-border/40 bg-muted/30 px-3 py-1.5", children: [
|
|
1360
1466
|
title && /* @__PURE__ */ jsx8("span", { className: "aui-artifact-title flex-1 truncate text-xs font-semibold text-foreground/80", children: title }),
|
|
1361
1467
|
!title && /* @__PURE__ */ jsx8("span", { className: "flex-1" }),
|
|
1362
1468
|
toolbar
|
|
@@ -1368,7 +1474,7 @@ var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }
|
|
|
1368
1474
|
};
|
|
1369
1475
|
|
|
1370
1476
|
// src/artifacts/chart-artifact.tsx
|
|
1371
|
-
import { Fragment, jsx as jsx9, jsxs as
|
|
1477
|
+
import { Fragment, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1372
1478
|
var ChartArtifactView = ({
|
|
1373
1479
|
artifact
|
|
1374
1480
|
}) => {
|
|
@@ -1379,7 +1485,7 @@ var ChartArtifactView = ({
|
|
|
1379
1485
|
if (typeof artifact.dataKey === "string") return [artifact.dataKey];
|
|
1380
1486
|
return inferDataKeys(data, xKey);
|
|
1381
1487
|
}, [artifact.dataKey, data, xKey]);
|
|
1382
|
-
return /* @__PURE__ */ jsx9(ArtifactCard, { title: artifact.title, kind: "chart", children: /* @__PURE__ */
|
|
1488
|
+
return /* @__PURE__ */ jsx9(ArtifactCard, { title: artifact.title, kind: "chart", children: /* @__PURE__ */ jsxs7("div", { className: "aui-artifact-chart p-3", children: [
|
|
1383
1489
|
/* @__PURE__ */ jsx9(
|
|
1384
1490
|
ChartSvg,
|
|
1385
1491
|
{
|
|
@@ -1422,7 +1528,7 @@ var ChartSvg = ({ chartType, data, xKey, dataKeys, unit }) => {
|
|
|
1422
1528
|
const xStep = xCount > 1 ? innerW / (xCount - 1) : innerW;
|
|
1423
1529
|
const xPos = (i) => chartType === "bar" ? PAD.left + innerW * (i + 0.5) / xCount : PAD.left + i * xStep;
|
|
1424
1530
|
const ticks = niceTicks(minV, maxV);
|
|
1425
|
-
return /* @__PURE__ */
|
|
1531
|
+
return /* @__PURE__ */ jsxs7(
|
|
1426
1532
|
"svg",
|
|
1427
1533
|
{
|
|
1428
1534
|
viewBox: `0 0 ${W} ${H}`,
|
|
@@ -1430,7 +1536,7 @@ var ChartSvg = ({ chartType, data, xKey, dataKeys, unit }) => {
|
|
|
1430
1536
|
role: "img",
|
|
1431
1537
|
"aria-label": "Chart",
|
|
1432
1538
|
children: [
|
|
1433
|
-
ticks.map((t, i) => /* @__PURE__ */
|
|
1539
|
+
ticks.map((t, i) => /* @__PURE__ */ jsxs7("g", { children: [
|
|
1434
1540
|
/* @__PURE__ */ jsx9(
|
|
1435
1541
|
"line",
|
|
1436
1542
|
{
|
|
@@ -1538,7 +1644,7 @@ var Area = ({ data, dataKey, xPos, yScale, baseY, color }) => {
|
|
|
1538
1644
|
if (data.length === 0) return null;
|
|
1539
1645
|
const top = data.map((d, i) => `${xPos(i)},${yScale(toNum(d[dataKey]))}`).join(" ");
|
|
1540
1646
|
const path = `M ${xPos(0)},${baseY} L ${top} L ${xPos(data.length - 1)},${baseY} Z`;
|
|
1541
|
-
return /* @__PURE__ */
|
|
1647
|
+
return /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
1542
1648
|
/* @__PURE__ */ jsx9("path", { d: path, fill: color, fillOpacity: 0.18 }),
|
|
1543
1649
|
/* @__PURE__ */ jsx9(Polyline, { data, dataKey, xPos, yScale, color })
|
|
1544
1650
|
] });
|
|
@@ -1588,7 +1694,7 @@ var PieSlice = ({ cx, cy, r, start, end, color, label }) => {
|
|
|
1588
1694
|
const mid = (start + end) / 2;
|
|
1589
1695
|
const lx = cx + Math.sin(mid) * (r * 0.65);
|
|
1590
1696
|
const ly = cy - Math.cos(mid) * (r * 0.65);
|
|
1591
|
-
return /* @__PURE__ */
|
|
1697
|
+
return /* @__PURE__ */ jsxs7("g", { children: [
|
|
1592
1698
|
/* @__PURE__ */ jsx9("path", { d: path, fill: color, stroke: "var(--background, #fff)", strokeWidth: 1 }),
|
|
1593
1699
|
/* @__PURE__ */ jsx9(
|
|
1594
1700
|
"text",
|
|
@@ -1603,7 +1709,7 @@ var PieSlice = ({ cx, cy, r, start, end, color, label }) => {
|
|
|
1603
1709
|
)
|
|
1604
1710
|
] });
|
|
1605
1711
|
};
|
|
1606
|
-
var Legend = ({ dataKeys }) => /* @__PURE__ */ jsx9("div", { className: "aui-artifact-chart-legend mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: dataKeys.map((k, i) => /* @__PURE__ */
|
|
1712
|
+
var Legend = ({ dataKeys }) => /* @__PURE__ */ jsx9("div", { className: "aui-artifact-chart-legend mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: dataKeys.map((k, i) => /* @__PURE__ */ jsxs7("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
1607
1713
|
/* @__PURE__ */ jsx9(
|
|
1608
1714
|
"span",
|
|
1609
1715
|
{
|
|
@@ -1661,89 +1767,208 @@ function formatTick(v, unit) {
|
|
|
1661
1767
|
}
|
|
1662
1768
|
|
|
1663
1769
|
// src/artifacts/question-artifact.tsx
|
|
1664
|
-
import { useState as useState3 } from "react";
|
|
1770
|
+
import { useCallback as useCallback2, useState as useState3 } from "react";
|
|
1665
1771
|
import { useThreadRuntime } from "@assistant-ui/react";
|
|
1666
1772
|
import { CheckIcon } from "lucide-react";
|
|
1667
|
-
|
|
1773
|
+
|
|
1774
|
+
// src/design/classes.ts
|
|
1775
|
+
var studioTopbarPillHeightClass = "h-[var(--studio-chrome-pill-height)] min-h-[var(--studio-chrome-pill-height)]";
|
|
1776
|
+
var studioTopbarIconPillClass = "shrink-0 flex-none size-[var(--studio-chrome-pill-height)] min-h-[var(--studio-chrome-pill-height)] min-w-[var(--studio-chrome-pill-height)]";
|
|
1777
|
+
var studioPlaygroundGradientClass = "bg-gradient-to-b from-playground-from via-playground-via to-playground-to";
|
|
1778
|
+
var studioComposeInputShellClass = cn(
|
|
1779
|
+
"flex w-full flex-col rounded-2xl bg-composer-bg shadow-card-elevated outline-none",
|
|
1780
|
+
"border border-composer-border",
|
|
1781
|
+
"transition-[box-shadow,border-color]",
|
|
1782
|
+
"focus-within:border-composer-border-focus focus-within:ring-2 focus-within:ring-foreground/5"
|
|
1783
|
+
);
|
|
1784
|
+
var studioSecondaryChromeClass = TIMBAL_V2_SECONDARY_CHROME;
|
|
1785
|
+
var studioIntegrationSurfaceSolid = "bg-gradient-to-b from-elevated-from to-elevated-to shadow-card";
|
|
1786
|
+
var studioIntegrationBorder = "border border-border";
|
|
1787
|
+
var studioIntegrationCardClass = cn(
|
|
1788
|
+
"rounded-xl",
|
|
1789
|
+
studioIntegrationSurfaceSolid,
|
|
1790
|
+
studioIntegrationBorder
|
|
1791
|
+
);
|
|
1792
|
+
var studioIntegrationIconTileClass = cn(
|
|
1793
|
+
"flex size-9 shrink-0 items-center justify-center rounded-lg",
|
|
1794
|
+
studioIntegrationSurfaceSolid,
|
|
1795
|
+
studioIntegrationBorder
|
|
1796
|
+
);
|
|
1797
|
+
var studioListRowButtonClass = cn(
|
|
1798
|
+
"flex w-full cursor-pointer items-center gap-3 rounded-xl px-3 py-2.5 text-left",
|
|
1799
|
+
studioIntegrationCardClass,
|
|
1800
|
+
"transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
|
|
1801
|
+
"hover:border-foreground/20",
|
|
1802
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
|
1803
|
+
);
|
|
1804
|
+
var studioComposerIoWellClass = cn(
|
|
1805
|
+
"rounded-lg",
|
|
1806
|
+
studioIntegrationSurfaceSolid,
|
|
1807
|
+
studioIntegrationBorder
|
|
1808
|
+
);
|
|
1809
|
+
var studioToolCardShellClass = cn(
|
|
1810
|
+
studioIntegrationCardClass,
|
|
1811
|
+
"my-2 min-h-0 overflow-hidden"
|
|
1812
|
+
);
|
|
1813
|
+
var studioSidebarPanelClass = cn(
|
|
1814
|
+
"bg-sidebar text-sidebar-foreground",
|
|
1815
|
+
"border border-sidebar-border",
|
|
1816
|
+
"shadow-card-elevated"
|
|
1817
|
+
);
|
|
1818
|
+
var studioSidebarNavItemClass = cn(
|
|
1819
|
+
"flex items-center rounded-lg text-sm",
|
|
1820
|
+
"transition-[color,background-color,box-shadow,border-color] duration-200 ease-in-out",
|
|
1821
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2"
|
|
1822
|
+
);
|
|
1823
|
+
function studioSidebarNavItemLayout(iconOnly) {
|
|
1824
|
+
return iconOnly ? "box-border size-8 min-h-8 min-w-8 shrink-0 justify-center rounded-lg p-0 focus-visible:ring-offset-0" : "w-full gap-2 px-2.5 py-2";
|
|
1825
|
+
}
|
|
1826
|
+
var studioSidebarNavItemSurfaceClass = cn(
|
|
1827
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to text-foreground",
|
|
1828
|
+
"border border-border",
|
|
1829
|
+
"shadow-card"
|
|
1830
|
+
);
|
|
1831
|
+
var studioSidebarNavItemIdleClass = cn(
|
|
1832
|
+
"border border-transparent text-muted-foreground shadow-none",
|
|
1833
|
+
"hover:text-foreground",
|
|
1834
|
+
"hover:bg-gradient-to-b hover:from-elevated-from hover:to-elevated-to",
|
|
1835
|
+
"hover:border-border hover:shadow-card"
|
|
1836
|
+
);
|
|
1837
|
+
var studioSidebarCollapsedRailItemClass = cn(
|
|
1838
|
+
"border border-border shadow-card bg-sidebar-accent"
|
|
1839
|
+
);
|
|
1840
|
+
var studioSidebarCollapsedRailItemIdleClass = cn(
|
|
1841
|
+
studioSidebarCollapsedRailItemClass,
|
|
1842
|
+
"text-muted-foreground hover:text-foreground"
|
|
1843
|
+
);
|
|
1844
|
+
var studioSidebarCollapsedRailItemActiveClass = cn(
|
|
1845
|
+
studioSidebarCollapsedRailItemClass,
|
|
1846
|
+
studioSidebarNavItemSurfaceClass,
|
|
1847
|
+
"text-foreground"
|
|
1848
|
+
);
|
|
1849
|
+
var studioSidebarNavItemActiveClass = studioSidebarNavItemSurfaceClass;
|
|
1850
|
+
var studioTimelineRowButtonClass = "group flex w-full min-w-0 cursor-pointer items-center justify-start rounded-md border-0 bg-transparent py-1 text-left shadow-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2";
|
|
1851
|
+
var studioTimelineTextClass = "text-xs font-normal leading-snug";
|
|
1852
|
+
var studioTimelineActionClass = cn(
|
|
1853
|
+
studioTimelineTextClass,
|
|
1854
|
+
"shrink-0 text-foreground/70 transition-colors duration-150 group-hover:text-foreground/80"
|
|
1855
|
+
);
|
|
1856
|
+
var studioTimelineShimmerActionClass = cn(
|
|
1857
|
+
studioTimelineTextClass,
|
|
1858
|
+
"shrink-0"
|
|
1859
|
+
);
|
|
1860
|
+
var studioTimelineDetailClass = cn(
|
|
1861
|
+
studioTimelineTextClass,
|
|
1862
|
+
"min-w-0 truncate text-muted-foreground transition-colors duration-150"
|
|
1863
|
+
);
|
|
1864
|
+
function studioTimelineChevronClass(expanded) {
|
|
1865
|
+
return cn(
|
|
1866
|
+
"ml-0.5 size-3 min-h-3 min-w-3 shrink-0 transition-all duration-150",
|
|
1867
|
+
expanded ? "rotate-90 text-foreground opacity-60" : "text-muted-foreground opacity-0 group-hover:opacity-70"
|
|
1868
|
+
);
|
|
1869
|
+
}
|
|
1870
|
+
var studioTimelineBodyPadClass = "flex flex-col gap-2 pt-0.5 pb-0.5";
|
|
1871
|
+
var studioArtifactShellClass = cn(
|
|
1872
|
+
studioIntegrationCardClass,
|
|
1873
|
+
"my-2 w-full min-w-0 overflow-hidden"
|
|
1874
|
+
);
|
|
1875
|
+
var studioQuestionOptionClass = "flex w-full items-center gap-2 rounded-lg border border-transparent px-2 py-1.5 text-left text-sm transition-[background-color,border-color,box-shadow] duration-200 hover:bg-muted/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2";
|
|
1876
|
+
var studioQuestionOptionSelectedClass = cn(
|
|
1877
|
+
studioQuestionOptionClass,
|
|
1878
|
+
"border-border bg-accent ring-1 ring-foreground/10"
|
|
1879
|
+
);
|
|
1880
|
+
|
|
1881
|
+
// src/artifacts/question-artifact.tsx
|
|
1882
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1883
|
+
function optionKey(option, index) {
|
|
1884
|
+
const id = option.id?.trim();
|
|
1885
|
+
return id ? id : `__option-${index}`;
|
|
1886
|
+
}
|
|
1887
|
+
var OptionRadio = ({ selected }) => /* @__PURE__ */ jsx10(
|
|
1888
|
+
"span",
|
|
1889
|
+
{
|
|
1890
|
+
className: cn(
|
|
1891
|
+
"flex size-4 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
|
|
1892
|
+
selected ? "border-foreground bg-foreground text-background" : "border-border bg-background"
|
|
1893
|
+
),
|
|
1894
|
+
"aria-hidden": true,
|
|
1895
|
+
children: selected ? /* @__PURE__ */ jsx10(CheckIcon, { className: "size-2.5 stroke-[3]" }) : null
|
|
1896
|
+
}
|
|
1897
|
+
);
|
|
1668
1898
|
var QuestionArtifactView = ({
|
|
1669
1899
|
artifact
|
|
1670
1900
|
}) => {
|
|
1671
1901
|
const runtime = useThreadRuntime();
|
|
1672
1902
|
const [selected, setSelected] = useState3([]);
|
|
1673
|
-
const [
|
|
1903
|
+
const [submittedIds, setSubmittedIds] = useState3(null);
|
|
1674
1904
|
const isMulti = artifact.multi === true;
|
|
1675
|
-
const
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
)
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1905
|
+
const isDisabled = submittedIds !== null;
|
|
1906
|
+
const send = useCallback2(
|
|
1907
|
+
(keys) => {
|
|
1908
|
+
if (keys.length === 0) return;
|
|
1909
|
+
const labels = artifact.options.map((option, index) => ({ option, key: optionKey(option, index) })).filter(({ key }) => keys.includes(key)).map(({ option }) => option.label);
|
|
1910
|
+
setSubmittedIds(keys);
|
|
1911
|
+
runtime.append({
|
|
1912
|
+
role: "user",
|
|
1913
|
+
content: [{ type: "text", text: labels.join(", ") }]
|
|
1914
|
+
});
|
|
1915
|
+
},
|
|
1916
|
+
[artifact.options, runtime]
|
|
1917
|
+
);
|
|
1918
|
+
const onPick = useCallback2(
|
|
1919
|
+
(key) => {
|
|
1920
|
+
if (isDisabled) return;
|
|
1921
|
+
if (!isMulti) {
|
|
1922
|
+
send([key]);
|
|
1923
|
+
return;
|
|
1924
|
+
}
|
|
1925
|
+
setSelected(
|
|
1926
|
+
(prev) => prev.includes(key) ? prev.filter((id) => id !== key) : [...prev, key]
|
|
1927
|
+
);
|
|
1928
|
+
},
|
|
1929
|
+
[isDisabled, isMulti, send]
|
|
1930
|
+
);
|
|
1931
|
+
const onConfirm = useCallback2(() => {
|
|
1932
|
+
send(selected);
|
|
1933
|
+
}, [selected, send]);
|
|
1934
|
+
return /* @__PURE__ */ jsx10("div", { className: studioArtifactShellClass, "data-artifact-kind": "question", children: /* @__PURE__ */ jsxs8("div", { className: "px-2.5 py-2", children: [
|
|
1935
|
+
artifact.prompt ? /* @__PURE__ */ jsx10("p", { className: "mb-2 text-sm font-normal leading-snug text-foreground", children: artifact.prompt }) : null,
|
|
1936
|
+
/* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-0.5", role: "list", children: artifact.options.map((option, index) => {
|
|
1937
|
+
const key = optionKey(option, index);
|
|
1938
|
+
const isSelected = submittedIds ? submittedIds.includes(key) : isMulti && selected.includes(key);
|
|
1939
|
+
return /* @__PURE__ */ jsxs8(
|
|
1701
1940
|
"button",
|
|
1702
1941
|
{
|
|
1703
1942
|
type: "button",
|
|
1943
|
+
role: "listitem",
|
|
1704
1944
|
disabled: isDisabled,
|
|
1705
|
-
onClick: () => onPick(
|
|
1945
|
+
onClick: () => onPick(key),
|
|
1706
1946
|
className: cn(
|
|
1707
|
-
|
|
1708
|
-
"
|
|
1709
|
-
isSelected && "border-primary/60 bg-primary/5",
|
|
1710
|
-
isDisabled && "cursor-not-allowed opacity-60 hover:border-border/60 hover:bg-transparent"
|
|
1947
|
+
isSelected ? studioQuestionOptionSelectedClass : studioQuestionOptionClass,
|
|
1948
|
+
isDisabled && (isSelected ? "cursor-default" : "cursor-not-allowed opacity-50")
|
|
1711
1949
|
),
|
|
1712
1950
|
children: [
|
|
1713
|
-
/* @__PURE__ */ jsx10(
|
|
1714
|
-
|
|
1715
|
-
{
|
|
1716
|
-
|
|
1717
|
-
"flex size-4 shrink-0 items-center justify-center rounded-full border",
|
|
1718
|
-
isSelected ? "border-primary bg-primary text-primary-foreground" : "border-border"
|
|
1719
|
-
),
|
|
1720
|
-
"aria-hidden": true,
|
|
1721
|
-
children: isSelected && /* @__PURE__ */ jsx10(CheckIcon, { className: "size-3" })
|
|
1722
|
-
}
|
|
1723
|
-
),
|
|
1724
|
-
/* @__PURE__ */ jsxs7("div", { className: "aui-artifact-question-option-text flex-1", children: [
|
|
1725
|
-
/* @__PURE__ */ jsx10("div", { className: "font-medium text-foreground/90", children: option.label }),
|
|
1726
|
-
option.description && /* @__PURE__ */ jsx10("div", { className: "text-xs text-muted-foreground", children: option.description })
|
|
1951
|
+
/* @__PURE__ */ jsx10(OptionRadio, { selected: isSelected }),
|
|
1952
|
+
/* @__PURE__ */ jsxs8("span", { className: "min-w-0 flex-1 text-left", children: [
|
|
1953
|
+
/* @__PURE__ */ jsx10("span", { className: "block font-normal text-foreground", children: option.label }),
|
|
1954
|
+
option.description ? /* @__PURE__ */ jsx10("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
|
|
1727
1955
|
] })
|
|
1728
1956
|
]
|
|
1729
1957
|
},
|
|
1730
|
-
|
|
1958
|
+
key
|
|
1731
1959
|
);
|
|
1732
1960
|
}) }),
|
|
1733
|
-
isMulti && !
|
|
1734
|
-
|
|
1961
|
+
isMulti && !submittedIds ? /* @__PURE__ */ jsx10("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsx10(
|
|
1962
|
+
TimbalV2Button,
|
|
1735
1963
|
{
|
|
1736
1964
|
type: "button",
|
|
1965
|
+
variant: "primary",
|
|
1737
1966
|
size: "sm",
|
|
1738
1967
|
disabled: selected.length === 0,
|
|
1739
1968
|
onClick: onConfirm,
|
|
1740
1969
|
children: "Confirm"
|
|
1741
1970
|
}
|
|
1742
|
-
) })
|
|
1743
|
-
submitted && /* @__PURE__ */ jsxs7("p", { className: "aui-artifact-question-submitted mt-2 text-xs text-muted-foreground", children: [
|
|
1744
|
-
"Sent: ",
|
|
1745
|
-
submitted
|
|
1746
|
-
] })
|
|
1971
|
+
) }) : null
|
|
1747
1972
|
] }) });
|
|
1748
1973
|
};
|
|
1749
1974
|
|
|
@@ -1782,11 +2007,11 @@ var JsonArtifactView = ({
|
|
|
1782
2007
|
};
|
|
1783
2008
|
|
|
1784
2009
|
// src/artifacts/table-artifact.tsx
|
|
1785
|
-
import { jsx as jsx13, jsxs as
|
|
2010
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1786
2011
|
var TableArtifactView = ({ artifact }) => {
|
|
1787
2012
|
const rows = artifact.rows ?? [];
|
|
1788
2013
|
const columns = artifact.columns ?? deriveColumns(rows);
|
|
1789
|
-
return /* @__PURE__ */ jsx13(ArtifactCard, { title: artifact.title, kind: "table", children: /* @__PURE__ */ jsx13("div", { className: "aui-artifact-table-wrap overflow-x-auto", children: /* @__PURE__ */
|
|
2014
|
+
return /* @__PURE__ */ jsx13(ArtifactCard, { title: artifact.title, kind: "table", children: /* @__PURE__ */ jsx13("div", { className: "aui-artifact-table-wrap overflow-x-auto", children: /* @__PURE__ */ jsxs9("table", { className: "aui-artifact-table w-full border-collapse text-sm", children: [
|
|
1790
2015
|
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsx13("tr", { className: "border-b border-border/40 bg-muted/20", children: columns.map((col) => /* @__PURE__ */ jsx13(
|
|
1791
2016
|
"th",
|
|
1792
2017
|
{
|
|
@@ -1914,32 +2139,87 @@ function useUiCustomNodeRegistry() {
|
|
|
1914
2139
|
}
|
|
1915
2140
|
|
|
1916
2141
|
// src/artifacts/ui/nodes.tsx
|
|
1917
|
-
import { useCallback as
|
|
2142
|
+
import { useCallback as useCallback3 } from "react";
|
|
1918
2143
|
import { motion } from "motion/react";
|
|
1919
2144
|
import { useThreadRuntime as useThreadRuntime2 } from "@assistant-ui/react";
|
|
1920
|
-
|
|
2145
|
+
|
|
2146
|
+
// src/ui/button.tsx
|
|
2147
|
+
import { cva } from "class-variance-authority";
|
|
2148
|
+
import { Slot as Slot2 } from "radix-ui";
|
|
2149
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2150
|
+
var buttonVariants = cva(
|
|
2151
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/30 aria-invalid:border-destructive",
|
|
2152
|
+
{
|
|
2153
|
+
variants: {
|
|
2154
|
+
variant: {
|
|
2155
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2156
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/30",
|
|
2157
|
+
outline: "border border-border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
|
|
2158
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2159
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
2160
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
2161
|
+
},
|
|
2162
|
+
size: {
|
|
2163
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2164
|
+
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
2165
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
2166
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2167
|
+
icon: "size-9",
|
|
2168
|
+
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
2169
|
+
"icon-sm": "size-8",
|
|
2170
|
+
"icon-lg": "size-10"
|
|
2171
|
+
}
|
|
2172
|
+
},
|
|
2173
|
+
defaultVariants: {
|
|
2174
|
+
variant: "default",
|
|
2175
|
+
size: "default"
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
);
|
|
2179
|
+
function Button({
|
|
2180
|
+
className,
|
|
2181
|
+
variant = "default",
|
|
2182
|
+
size = "default",
|
|
2183
|
+
asChild = false,
|
|
2184
|
+
...props
|
|
2185
|
+
}) {
|
|
2186
|
+
const Comp = asChild ? Slot2.Root : "button";
|
|
2187
|
+
return /* @__PURE__ */ jsx15(
|
|
2188
|
+
Comp,
|
|
2189
|
+
{
|
|
2190
|
+
"data-slot": "button",
|
|
2191
|
+
"data-variant": variant,
|
|
2192
|
+
"data-size": size,
|
|
2193
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
2194
|
+
...props
|
|
2195
|
+
}
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
// src/artifacts/ui/nodes.tsx
|
|
2200
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1921
2201
|
var UiNodeView = ({ node }) => {
|
|
1922
2202
|
switch (node.kind) {
|
|
1923
2203
|
case "box":
|
|
1924
|
-
return /* @__PURE__ */
|
|
2204
|
+
return /* @__PURE__ */ jsx16(BoxNode, { node });
|
|
1925
2205
|
case "text":
|
|
1926
|
-
return /* @__PURE__ */
|
|
2206
|
+
return /* @__PURE__ */ jsx16(TextNode, { node });
|
|
1927
2207
|
case "heading":
|
|
1928
|
-
return /* @__PURE__ */
|
|
2208
|
+
return /* @__PURE__ */ jsx16(HeadingNode, { node });
|
|
1929
2209
|
case "badge":
|
|
1930
|
-
return /* @__PURE__ */
|
|
2210
|
+
return /* @__PURE__ */ jsx16(BadgeNode, { node });
|
|
1931
2211
|
case "button":
|
|
1932
|
-
return /* @__PURE__ */
|
|
2212
|
+
return /* @__PURE__ */ jsx16(ButtonNode, { node });
|
|
1933
2213
|
case "toggle":
|
|
1934
|
-
return /* @__PURE__ */
|
|
2214
|
+
return /* @__PURE__ */ jsx16(ToggleNode, { node });
|
|
1935
2215
|
case "slider":
|
|
1936
|
-
return /* @__PURE__ */
|
|
2216
|
+
return /* @__PURE__ */ jsx16(SliderNode, { node });
|
|
1937
2217
|
case "tooltip":
|
|
1938
|
-
return /* @__PURE__ */
|
|
2218
|
+
return /* @__PURE__ */ jsx16(TooltipNode, { node });
|
|
1939
2219
|
case "draggable":
|
|
1940
|
-
return /* @__PURE__ */
|
|
2220
|
+
return /* @__PURE__ */ jsx16(DraggableNode, { node });
|
|
1941
2221
|
case "custom":
|
|
1942
|
-
return /* @__PURE__ */
|
|
2222
|
+
return /* @__PURE__ */ jsx16(CustomNode, { node });
|
|
1943
2223
|
default:
|
|
1944
2224
|
return null;
|
|
1945
2225
|
}
|
|
@@ -1949,7 +2229,7 @@ function useActionRunner() {
|
|
|
1949
2229
|
const dispatch = useUiDispatch();
|
|
1950
2230
|
const runtime = useThreadRuntime2();
|
|
1951
2231
|
const emit = useUiEventEmitter();
|
|
1952
|
-
return
|
|
2232
|
+
return useCallback3(
|
|
1953
2233
|
(actions) => {
|
|
1954
2234
|
if (!actions) return;
|
|
1955
2235
|
const list = Array.isArray(actions) ? actions : [actions];
|
|
@@ -1999,7 +2279,7 @@ var JUSTIFY_CLS = {
|
|
|
1999
2279
|
};
|
|
2000
2280
|
var BoxNode = ({ node }) => {
|
|
2001
2281
|
const dir = node.direction ?? "col";
|
|
2002
|
-
return /* @__PURE__ */
|
|
2282
|
+
return /* @__PURE__ */ jsx16(
|
|
2003
2283
|
"div",
|
|
2004
2284
|
{
|
|
2005
2285
|
className: cn(
|
|
@@ -2014,7 +2294,7 @@ var BoxNode = ({ node }) => {
|
|
|
2014
2294
|
gap: node.gap !== void 0 ? `${node.gap * 0.25}rem` : void 0,
|
|
2015
2295
|
padding: node.padding !== void 0 ? `${node.padding * 0.25}rem` : void 0
|
|
2016
2296
|
},
|
|
2017
|
-
children: node.children?.map((child, i) => /* @__PURE__ */
|
|
2297
|
+
children: node.children?.map((child, i) => /* @__PURE__ */ jsx16(UiNodeView, { node: child }, child.id ?? i))
|
|
2018
2298
|
}
|
|
2019
2299
|
);
|
|
2020
2300
|
};
|
|
@@ -2033,7 +2313,7 @@ var TEXT_WEIGHT = {
|
|
|
2033
2313
|
var TextNode = ({ node }) => {
|
|
2034
2314
|
const state = useUiState();
|
|
2035
2315
|
const value = resolveBindable(node.value, state);
|
|
2036
|
-
return /* @__PURE__ */
|
|
2316
|
+
return /* @__PURE__ */ jsx16(
|
|
2037
2317
|
"span",
|
|
2038
2318
|
{
|
|
2039
2319
|
className: cn(
|
|
@@ -2064,13 +2344,13 @@ var HeadingNode = ({ node }) => {
|
|
|
2064
2344
|
);
|
|
2065
2345
|
switch (level) {
|
|
2066
2346
|
case 1:
|
|
2067
|
-
return /* @__PURE__ */
|
|
2347
|
+
return /* @__PURE__ */ jsx16("h1", { className: cls, children: value });
|
|
2068
2348
|
case 2:
|
|
2069
|
-
return /* @__PURE__ */
|
|
2349
|
+
return /* @__PURE__ */ jsx16("h2", { className: cls, children: value });
|
|
2070
2350
|
case 3:
|
|
2071
|
-
return /* @__PURE__ */
|
|
2351
|
+
return /* @__PURE__ */ jsx16("h3", { className: cls, children: value });
|
|
2072
2352
|
case 4:
|
|
2073
|
-
return /* @__PURE__ */
|
|
2353
|
+
return /* @__PURE__ */ jsx16("h4", { className: cls, children: value });
|
|
2074
2354
|
}
|
|
2075
2355
|
};
|
|
2076
2356
|
var BADGE_TONE = {
|
|
@@ -2083,7 +2363,7 @@ var BADGE_TONE = {
|
|
|
2083
2363
|
var BadgeNode = ({ node }) => {
|
|
2084
2364
|
const state = useUiState();
|
|
2085
2365
|
const value = String(resolveBindable(node.value, state) ?? "");
|
|
2086
|
-
return /* @__PURE__ */
|
|
2366
|
+
return /* @__PURE__ */ jsx16(
|
|
2087
2367
|
"span",
|
|
2088
2368
|
{
|
|
2089
2369
|
className: cn(
|
|
@@ -2100,7 +2380,7 @@ var ButtonNode = ({ node }) => {
|
|
|
2100
2380
|
const run = useActionRunner();
|
|
2101
2381
|
const label = String(resolveBindable(node.label, state) ?? "");
|
|
2102
2382
|
const disabled = node.disabled !== void 0 ? Boolean(resolveBindable(node.disabled, state)) : false;
|
|
2103
|
-
return /* @__PURE__ */
|
|
2383
|
+
return /* @__PURE__ */ jsx16(
|
|
2104
2384
|
Button,
|
|
2105
2385
|
{
|
|
2106
2386
|
variant: node.variant ?? "default",
|
|
@@ -2122,7 +2402,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2122
2402
|
dispatch({ type: "toggle", path: node.binding });
|
|
2123
2403
|
run(node.onChange);
|
|
2124
2404
|
};
|
|
2125
|
-
return /* @__PURE__ */
|
|
2405
|
+
return /* @__PURE__ */ jsxs10(
|
|
2126
2406
|
"label",
|
|
2127
2407
|
{
|
|
2128
2408
|
className: cn(
|
|
@@ -2130,7 +2410,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2130
2410
|
node.className
|
|
2131
2411
|
),
|
|
2132
2412
|
children: [
|
|
2133
|
-
/* @__PURE__ */
|
|
2413
|
+
/* @__PURE__ */ jsx16(
|
|
2134
2414
|
"button",
|
|
2135
2415
|
{
|
|
2136
2416
|
type: "button",
|
|
@@ -2141,7 +2421,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2141
2421
|
"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border transition-colors",
|
|
2142
2422
|
value ? "border-primary bg-primary" : "border-border bg-muted hover:bg-muted/80"
|
|
2143
2423
|
),
|
|
2144
|
-
children: /* @__PURE__ */
|
|
2424
|
+
children: /* @__PURE__ */ jsx16(
|
|
2145
2425
|
"span",
|
|
2146
2426
|
{
|
|
2147
2427
|
className: cn(
|
|
@@ -2153,7 +2433,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2153
2433
|
)
|
|
2154
2434
|
}
|
|
2155
2435
|
),
|
|
2156
|
-
label && /* @__PURE__ */
|
|
2436
|
+
label && /* @__PURE__ */ jsx16("span", { className: "text-foreground/85", children: label })
|
|
2157
2437
|
]
|
|
2158
2438
|
}
|
|
2159
2439
|
);
|
|
@@ -2173,12 +2453,12 @@ var SliderNode = ({ node }) => {
|
|
|
2173
2453
|
const next = Number(e.target.value);
|
|
2174
2454
|
dispatch({ type: "set", path: node.binding, value: next });
|
|
2175
2455
|
};
|
|
2176
|
-
return /* @__PURE__ */
|
|
2177
|
-
(label || showValue) && /* @__PURE__ */
|
|
2178
|
-
label && /* @__PURE__ */
|
|
2179
|
-
showValue && /* @__PURE__ */
|
|
2456
|
+
return /* @__PURE__ */ jsxs10("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
|
|
2457
|
+
(label || showValue) && /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
2458
|
+
label && /* @__PURE__ */ jsx16("span", { children: label }),
|
|
2459
|
+
showValue && /* @__PURE__ */ jsx16("span", { className: "font-mono", children: value })
|
|
2180
2460
|
] }),
|
|
2181
|
-
/* @__PURE__ */
|
|
2461
|
+
/* @__PURE__ */ jsx16(
|
|
2182
2462
|
"input",
|
|
2183
2463
|
{
|
|
2184
2464
|
type: "range",
|
|
@@ -2200,9 +2480,9 @@ var SliderNode = ({ node }) => {
|
|
|
2200
2480
|
var TooltipNode = ({ node }) => {
|
|
2201
2481
|
const state = useUiState();
|
|
2202
2482
|
const content = String(resolveBindable(node.content, state) ?? "");
|
|
2203
|
-
return /* @__PURE__ */
|
|
2204
|
-
/* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2483
|
+
return /* @__PURE__ */ jsx16(TooltipProvider, { children: /* @__PURE__ */ jsxs10(Tooltip, { children: [
|
|
2484
|
+
/* @__PURE__ */ jsx16(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx16("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ jsx16(UiNodeView, { node: node.child }) }) }),
|
|
2485
|
+
/* @__PURE__ */ jsx16(TooltipContent, { side: node.side ?? "top", children: content })
|
|
2206
2486
|
] }) });
|
|
2207
2487
|
};
|
|
2208
2488
|
var DraggableNode = ({ node }) => {
|
|
@@ -2210,7 +2490,7 @@ var DraggableNode = ({ node }) => {
|
|
|
2210
2490
|
const snapBack = node.snapBack ?? true;
|
|
2211
2491
|
const axis = node.axis ?? "both";
|
|
2212
2492
|
const dragProp = axis === "both" ? true : axis;
|
|
2213
|
-
return /* @__PURE__ */
|
|
2493
|
+
return /* @__PURE__ */ jsx16(
|
|
2214
2494
|
motion.div,
|
|
2215
2495
|
{
|
|
2216
2496
|
drag: dragProp,
|
|
@@ -2222,7 +2502,7 @@ var DraggableNode = ({ node }) => {
|
|
|
2222
2502
|
"aui-ui-draggable inline-block cursor-grab touch-none",
|
|
2223
2503
|
node.className
|
|
2224
2504
|
),
|
|
2225
|
-
children: /* @__PURE__ */
|
|
2505
|
+
children: /* @__PURE__ */ jsx16(UiNodeView, { node: node.child })
|
|
2226
2506
|
}
|
|
2227
2507
|
);
|
|
2228
2508
|
};
|
|
@@ -2232,8 +2512,8 @@ var CustomNode = ({ node }) => {
|
|
|
2232
2512
|
const Renderer = registry[node.name];
|
|
2233
2513
|
if (!Renderer) return null;
|
|
2234
2514
|
const resolvedProps = resolveProps(node.props ?? {}, state);
|
|
2235
|
-
const children = node.children?.map((child, i) => /* @__PURE__ */
|
|
2236
|
-
return /* @__PURE__ */
|
|
2515
|
+
const children = node.children?.map((child, i) => /* @__PURE__ */ jsx16(UiNodeView, { node: child }, child.id ?? i));
|
|
2516
|
+
return /* @__PURE__ */ jsx16(Renderer, { props: resolvedProps, children });
|
|
2237
2517
|
};
|
|
2238
2518
|
function resolveProps(props, state) {
|
|
2239
2519
|
const out = {};
|
|
@@ -2244,17 +2524,17 @@ function resolveProps(props, state) {
|
|
|
2244
2524
|
}
|
|
2245
2525
|
|
|
2246
2526
|
// src/artifacts/ui/ui-artifact.tsx
|
|
2247
|
-
import { jsx as
|
|
2527
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2248
2528
|
var UiArtifactView = ({ artifact }) => {
|
|
2249
2529
|
const [state, dispatch] = useReducer(
|
|
2250
2530
|
uiStateReducer,
|
|
2251
2531
|
artifact.initialState ?? {}
|
|
2252
2532
|
);
|
|
2253
|
-
return /* @__PURE__ */
|
|
2533
|
+
return /* @__PURE__ */ jsx17(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ jsx17(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ jsx17("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ jsx17(UiNodeView, { node: artifact.root }) }) }) });
|
|
2254
2534
|
};
|
|
2255
2535
|
|
|
2256
2536
|
// src/artifacts/registry.tsx
|
|
2257
|
-
import { jsx as
|
|
2537
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
2258
2538
|
var defaultArtifactRenderers = {
|
|
2259
2539
|
chart: ChartArtifactView,
|
|
2260
2540
|
question: QuestionArtifactView,
|
|
@@ -2272,7 +2552,7 @@ var ArtifactRegistryProvider = ({ renderers, override, children }) => {
|
|
|
2272
2552
|
if (override) return renderers;
|
|
2273
2553
|
return { ...defaultArtifactRenderers, ...renderers };
|
|
2274
2554
|
}, [renderers, override]);
|
|
2275
|
-
return /* @__PURE__ */
|
|
2555
|
+
return /* @__PURE__ */ jsx18(ArtifactRegistryContext.Provider, { value: merged, children });
|
|
2276
2556
|
};
|
|
2277
2557
|
function useArtifactRegistry() {
|
|
2278
2558
|
return useContext3(ArtifactRegistryContext);
|
|
@@ -2281,7 +2561,7 @@ var ArtifactView = ({ artifact }) => {
|
|
|
2281
2561
|
const registry = useArtifactRegistry();
|
|
2282
2562
|
const Renderer = registry[artifact.type] ?? registry.json;
|
|
2283
2563
|
if (!Renderer) return null;
|
|
2284
|
-
return /* @__PURE__ */
|
|
2564
|
+
return /* @__PURE__ */ jsx18(Renderer, { artifact });
|
|
2285
2565
|
};
|
|
2286
2566
|
|
|
2287
2567
|
// src/artifacts/parse.ts
|
|
@@ -2397,7 +2677,7 @@ import langC from "shiki/langs/c.mjs";
|
|
|
2397
2677
|
import langCpp from "shiki/langs/cpp.mjs";
|
|
2398
2678
|
import themeVitesseDark from "shiki/themes/vitesse-dark.mjs";
|
|
2399
2679
|
import themeVitesseLight from "shiki/themes/vitesse-light.mjs";
|
|
2400
|
-
import { jsx as
|
|
2680
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
2401
2681
|
var SHIKI_THEME_DARK = "vitesse-dark";
|
|
2402
2682
|
var SHIKI_THEME_LIGHT = "vitesse-light";
|
|
2403
2683
|
var highlighterPromise = null;
|
|
@@ -2466,13 +2746,13 @@ var ShikiSyntaxHighlighter = ({
|
|
|
2466
2746
|
try {
|
|
2467
2747
|
const parsed = JSON.parse(code);
|
|
2468
2748
|
if (isArtifact(parsed)) {
|
|
2469
|
-
return /* @__PURE__ */
|
|
2749
|
+
return /* @__PURE__ */ jsx19(ArtifactView, { artifact: parsed });
|
|
2470
2750
|
}
|
|
2471
2751
|
} catch {
|
|
2472
2752
|
}
|
|
2473
2753
|
}
|
|
2474
2754
|
if (html) {
|
|
2475
|
-
return /* @__PURE__ */
|
|
2755
|
+
return /* @__PURE__ */ jsx19(
|
|
2476
2756
|
"div",
|
|
2477
2757
|
{
|
|
2478
2758
|
className: "shiki-wrapper [&>pre]:!m-0 [&>pre]:!rounded-t-none [&>pre]:!rounded-b-lg [&>pre]:!border [&>pre]:!border-t-0 [&>pre]:!border-border/50 [&>pre]:!p-3 [&>pre]:!text-xs [&>pre]:!leading-relaxed [&>pre]:overflow-x-auto",
|
|
@@ -2480,14 +2760,14 @@ var ShikiSyntaxHighlighter = ({
|
|
|
2480
2760
|
}
|
|
2481
2761
|
);
|
|
2482
2762
|
}
|
|
2483
|
-
return /* @__PURE__ */
|
|
2763
|
+
return /* @__PURE__ */ jsx19(Pre, { children: /* @__PURE__ */ jsx19(Code2, { children: code }) });
|
|
2484
2764
|
};
|
|
2485
2765
|
var syntax_highlighter_default = ShikiSyntaxHighlighter;
|
|
2486
2766
|
|
|
2487
2767
|
// src/components/markdown-text.tsx
|
|
2488
|
-
import { jsx as
|
|
2768
|
+
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2489
2769
|
var MarkdownTextImpl = () => {
|
|
2490
|
-
return /* @__PURE__ */
|
|
2770
|
+
return /* @__PURE__ */ jsx20(
|
|
2491
2771
|
MarkdownTextPrimitive,
|
|
2492
2772
|
{
|
|
2493
2773
|
remarkPlugins: [remarkGfm, remarkMath],
|
|
@@ -2508,20 +2788,20 @@ var CodeHeader = ({ language, code }) => {
|
|
|
2508
2788
|
if (!code || isCopied) return;
|
|
2509
2789
|
copyToClipboard(code);
|
|
2510
2790
|
};
|
|
2511
|
-
return /* @__PURE__ */
|
|
2512
|
-
/* @__PURE__ */
|
|
2513
|
-
/* @__PURE__ */
|
|
2791
|
+
return /* @__PURE__ */ jsxs11("div", { className: "aui-code-header flex items-center justify-between rounded-t-lg border border-b-0 border-border/50 bg-code-header-bg px-4 py-2", children: [
|
|
2792
|
+
/* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
|
|
2793
|
+
/* @__PURE__ */ jsx20("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
|
|
2514
2794
|
language
|
|
2515
2795
|
] }),
|
|
2516
|
-
/* @__PURE__ */
|
|
2796
|
+
/* @__PURE__ */ jsxs11(
|
|
2517
2797
|
TooltipIconButton,
|
|
2518
2798
|
{
|
|
2519
2799
|
tooltip: isCopied ? "Copied!" : "Copy",
|
|
2520
2800
|
onClick: onCopy,
|
|
2521
2801
|
className: "transition-colors hover:text-foreground",
|
|
2522
2802
|
children: [
|
|
2523
|
-
!isCopied && /* @__PURE__ */
|
|
2524
|
-
isCopied && /* @__PURE__ */
|
|
2803
|
+
!isCopied && /* @__PURE__ */ jsx20(CopyIcon, { className: "h-3.5 w-3.5" }),
|
|
2804
|
+
isCopied && /* @__PURE__ */ jsx20(CheckIcon2, { className: "h-3.5 w-3.5 text-emerald-500" })
|
|
2525
2805
|
]
|
|
2526
2806
|
}
|
|
2527
2807
|
)
|
|
@@ -2541,7 +2821,7 @@ var useCopyToClipboard = ({
|
|
|
2541
2821
|
return { isCopied, copyToClipboard };
|
|
2542
2822
|
};
|
|
2543
2823
|
var defaultComponents = memoizeMarkdownComponents({
|
|
2544
|
-
h1: ({ className, ...props }) => /* @__PURE__ */
|
|
2824
|
+
h1: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2545
2825
|
"h1",
|
|
2546
2826
|
{
|
|
2547
2827
|
className: cn(
|
|
@@ -2551,7 +2831,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2551
2831
|
...props
|
|
2552
2832
|
}
|
|
2553
2833
|
),
|
|
2554
|
-
h2: ({ className, ...props }) => /* @__PURE__ */
|
|
2834
|
+
h2: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2555
2835
|
"h2",
|
|
2556
2836
|
{
|
|
2557
2837
|
className: cn(
|
|
@@ -2561,7 +2841,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2561
2841
|
...props
|
|
2562
2842
|
}
|
|
2563
2843
|
),
|
|
2564
|
-
h3: ({ className, ...props }) => /* @__PURE__ */
|
|
2844
|
+
h3: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2565
2845
|
"h3",
|
|
2566
2846
|
{
|
|
2567
2847
|
className: cn(
|
|
@@ -2571,7 +2851,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2571
2851
|
...props
|
|
2572
2852
|
}
|
|
2573
2853
|
),
|
|
2574
|
-
h4: ({ className, ...props }) => /* @__PURE__ */
|
|
2854
|
+
h4: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2575
2855
|
"h4",
|
|
2576
2856
|
{
|
|
2577
2857
|
className: cn(
|
|
@@ -2581,7 +2861,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2581
2861
|
...props
|
|
2582
2862
|
}
|
|
2583
2863
|
),
|
|
2584
|
-
h5: ({ className, ...props }) => /* @__PURE__ */
|
|
2864
|
+
h5: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2585
2865
|
"h5",
|
|
2586
2866
|
{
|
|
2587
2867
|
className: cn(
|
|
@@ -2591,7 +2871,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2591
2871
|
...props
|
|
2592
2872
|
}
|
|
2593
2873
|
),
|
|
2594
|
-
h6: ({ className, ...props }) => /* @__PURE__ */
|
|
2874
|
+
h6: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2595
2875
|
"h6",
|
|
2596
2876
|
{
|
|
2597
2877
|
className: cn(
|
|
@@ -2601,7 +2881,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2601
2881
|
...props
|
|
2602
2882
|
}
|
|
2603
2883
|
),
|
|
2604
|
-
p: ({ className, ...props }) => /* @__PURE__ */
|
|
2884
|
+
p: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2605
2885
|
"p",
|
|
2606
2886
|
{
|
|
2607
2887
|
className: cn(
|
|
@@ -2611,7 +2891,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2611
2891
|
...props
|
|
2612
2892
|
}
|
|
2613
2893
|
),
|
|
2614
|
-
a: ({ className, ...props }) => /* @__PURE__ */
|
|
2894
|
+
a: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2615
2895
|
"a",
|
|
2616
2896
|
{
|
|
2617
2897
|
className: cn(
|
|
@@ -2623,7 +2903,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2623
2903
|
...props
|
|
2624
2904
|
}
|
|
2625
2905
|
),
|
|
2626
|
-
blockquote: ({ className, ...props }) => /* @__PURE__ */
|
|
2906
|
+
blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2627
2907
|
"blockquote",
|
|
2628
2908
|
{
|
|
2629
2909
|
className: cn(
|
|
@@ -2633,7 +2913,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2633
2913
|
...props
|
|
2634
2914
|
}
|
|
2635
2915
|
),
|
|
2636
|
-
ul: ({ className, ...props }) => /* @__PURE__ */
|
|
2916
|
+
ul: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2637
2917
|
"ul",
|
|
2638
2918
|
{
|
|
2639
2919
|
className: cn(
|
|
@@ -2643,7 +2923,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2643
2923
|
...props
|
|
2644
2924
|
}
|
|
2645
2925
|
),
|
|
2646
|
-
ol: ({ className, ...props }) => /* @__PURE__ */
|
|
2926
|
+
ol: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2647
2927
|
"ol",
|
|
2648
2928
|
{
|
|
2649
2929
|
className: cn(
|
|
@@ -2653,7 +2933,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2653
2933
|
...props
|
|
2654
2934
|
}
|
|
2655
2935
|
),
|
|
2656
|
-
hr: ({ className, ...props }) => /* @__PURE__ */
|
|
2936
|
+
hr: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2657
2937
|
"hr",
|
|
2658
2938
|
{
|
|
2659
2939
|
className: cn(
|
|
@@ -2663,14 +2943,14 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2663
2943
|
...props
|
|
2664
2944
|
}
|
|
2665
2945
|
),
|
|
2666
|
-
table: ({ className, ...props }) => /* @__PURE__ */
|
|
2946
|
+
table: ({ className, ...props }) => /* @__PURE__ */ jsx20("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ jsx20(
|
|
2667
2947
|
"table",
|
|
2668
2948
|
{
|
|
2669
2949
|
className: cn("aui-md-table w-full border-collapse text-sm", className),
|
|
2670
2950
|
...props
|
|
2671
2951
|
}
|
|
2672
2952
|
) }),
|
|
2673
|
-
th: ({ className, ...props }) => /* @__PURE__ */
|
|
2953
|
+
th: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2674
2954
|
"th",
|
|
2675
2955
|
{
|
|
2676
2956
|
className: cn(
|
|
@@ -2680,7 +2960,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2680
2960
|
...props
|
|
2681
2961
|
}
|
|
2682
2962
|
),
|
|
2683
|
-
td: ({ className, ...props }) => /* @__PURE__ */
|
|
2963
|
+
td: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2684
2964
|
"td",
|
|
2685
2965
|
{
|
|
2686
2966
|
className: cn(
|
|
@@ -2690,7 +2970,7 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2690
2970
|
...props
|
|
2691
2971
|
}
|
|
2692
2972
|
),
|
|
2693
|
-
tr: ({ className, ...props }) => /* @__PURE__ */
|
|
2973
|
+
tr: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2694
2974
|
"tr",
|
|
2695
2975
|
{
|
|
2696
2976
|
className: cn(
|
|
@@ -2700,8 +2980,8 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2700
2980
|
...props
|
|
2701
2981
|
}
|
|
2702
2982
|
),
|
|
2703
|
-
li: ({ className, ...props }) => /* @__PURE__ */
|
|
2704
|
-
sup: ({ className, ...props }) => /* @__PURE__ */
|
|
2983
|
+
li: ({ className, ...props }) => /* @__PURE__ */ jsx20("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
|
|
2984
|
+
sup: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2705
2985
|
"sup",
|
|
2706
2986
|
{
|
|
2707
2987
|
className: cn(
|
|
@@ -2711,11 +2991,11 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2711
2991
|
...props
|
|
2712
2992
|
}
|
|
2713
2993
|
),
|
|
2714
|
-
pre: ({ className, ...props }) => /* @__PURE__ */
|
|
2994
|
+
pre: ({ className, ...props }) => /* @__PURE__ */ jsx20(
|
|
2715
2995
|
"pre",
|
|
2716
2996
|
{
|
|
2717
2997
|
className: cn(
|
|
2718
|
-
"aui-md-pre overflow-x-auto rounded-t-none rounded-b-lg border border-t-0 border-border/50 bg-
|
|
2998
|
+
"aui-md-pre overflow-x-auto rounded-t-none rounded-b-lg border border-t-0 border-border/50 bg-code-block-bg p-4 text-[13px] leading-relaxed",
|
|
2719
2999
|
className
|
|
2720
3000
|
),
|
|
2721
3001
|
...props
|
|
@@ -2723,25 +3003,28 @@ var defaultComponents = memoizeMarkdownComponents({
|
|
|
2723
3003
|
),
|
|
2724
3004
|
code: function Code({ className, ...props }) {
|
|
2725
3005
|
const isCodeBlock = useIsMarkdownCodeBlock();
|
|
2726
|
-
return /* @__PURE__ */
|
|
3006
|
+
return /* @__PURE__ */ jsx20(
|
|
2727
3007
|
"code",
|
|
2728
3008
|
{
|
|
2729
3009
|
className: cn(
|
|
2730
|
-
!isCodeBlock && "aui-md-inline-code rounded-[5px] border border-border/60 bg-muted/60 px-[0.4em] py-[0.15em] font-mono text-[0.85em] font-medium text-foreground/90
|
|
3010
|
+
!isCodeBlock && "aui-md-inline-code rounded-[5px] border border-border/60 bg-muted/60 px-[0.4em] py-[0.15em] font-mono text-[0.85em] font-medium text-foreground/90",
|
|
2731
3011
|
className
|
|
2732
3012
|
),
|
|
2733
3013
|
...props
|
|
2734
3014
|
}
|
|
2735
3015
|
);
|
|
2736
3016
|
},
|
|
2737
|
-
strong: ({ className, ...props }) => /* @__PURE__ */
|
|
2738
|
-
em: ({ className, ...props }) => /* @__PURE__ */
|
|
3017
|
+
strong: ({ className, ...props }) => /* @__PURE__ */ jsx20("strong", { className: cn("font-semibold text-foreground", className), ...props }),
|
|
3018
|
+
em: ({ className, ...props }) => /* @__PURE__ */ jsx20("em", { className: cn("italic", className), ...props }),
|
|
2739
3019
|
CodeHeader
|
|
2740
3020
|
});
|
|
2741
3021
|
|
|
2742
3022
|
// src/components/tool-fallback.tsx
|
|
2743
|
-
import { memo as memo3, useState as useState6 } from "react";
|
|
2744
|
-
import {
|
|
3023
|
+
import { memo as memo3, useMemo as useMemo5, useState as useState6 } from "react";
|
|
3024
|
+
import { ChevronRightIcon } from "lucide-react";
|
|
3025
|
+
import {
|
|
3026
|
+
useAuiState as useAuiState2
|
|
3027
|
+
} from "@assistant-ui/react";
|
|
2745
3028
|
|
|
2746
3029
|
// src/ui/shimmer.tsx
|
|
2747
3030
|
import { motion as motion2 } from "motion/react";
|
|
@@ -2749,7 +3032,7 @@ import {
|
|
|
2749
3032
|
memo as memo2,
|
|
2750
3033
|
useMemo as useMemo4
|
|
2751
3034
|
} from "react";
|
|
2752
|
-
import { jsx as
|
|
3035
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
2753
3036
|
var ShimmerComponent = ({
|
|
2754
3037
|
children,
|
|
2755
3038
|
as: Component = "p",
|
|
@@ -2764,7 +3047,7 @@ var ShimmerComponent = ({
|
|
|
2764
3047
|
() => (children?.length ?? 0) * spread,
|
|
2765
3048
|
[children, spread]
|
|
2766
3049
|
);
|
|
2767
|
-
return /* @__PURE__ */
|
|
3050
|
+
return /* @__PURE__ */ jsx21(
|
|
2768
3051
|
MotionComponent,
|
|
2769
3052
|
{
|
|
2770
3053
|
animate: { backgroundPosition: "0% center" },
|
|
@@ -2789,78 +3072,130 @@ var ShimmerComponent = ({
|
|
|
2789
3072
|
};
|
|
2790
3073
|
var Shimmer = memo2(ShimmerComponent);
|
|
2791
3074
|
|
|
2792
|
-
// src/components/
|
|
2793
|
-
import {
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
3075
|
+
// src/components/motion.tsx
|
|
3076
|
+
import { AnimatePresence, motion as motion3, useReducedMotion } from "motion/react";
|
|
3077
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
3078
|
+
var luxuryEase = [0.16, 1, 0.3, 1];
|
|
3079
|
+
var TOOL_ENTER_MS = 0.78;
|
|
3080
|
+
var TOOL_EXIT_MS = 0.28;
|
|
3081
|
+
function toolPresenceTransition(reduced) {
|
|
3082
|
+
return {
|
|
3083
|
+
enter: {
|
|
3084
|
+
duration: reduced ? 0.35 : TOOL_ENTER_MS,
|
|
3085
|
+
ease: luxuryEase
|
|
3086
|
+
},
|
|
3087
|
+
exit: {
|
|
3088
|
+
duration: reduced ? 0.2 : TOOL_EXIT_MS,
|
|
3089
|
+
ease: [0.4, 0, 1, 1]
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
}
|
|
3093
|
+
function toolMotionState(reduced, entering, variant) {
|
|
3094
|
+
if (reduced) {
|
|
3095
|
+
return entering ? { opacity: 0, y: variant === "executing" ? 8 : 10 } : { opacity: 1, y: 0 };
|
|
2807
3096
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
3097
|
+
if (variant === "executing") {
|
|
3098
|
+
return entering ? { opacity: 0, y: 12 } : { opacity: 1, y: 0 };
|
|
3099
|
+
}
|
|
3100
|
+
return entering ? { opacity: 0, y: 14, filter: "blur(10px)" } : { opacity: 1, y: 0, filter: "blur(0px)" };
|
|
3101
|
+
}
|
|
3102
|
+
function ToolMotion({ children, className, motionKey }) {
|
|
3103
|
+
const reduced = useReducedMotion() ?? false;
|
|
3104
|
+
const { enter, exit } = toolPresenceTransition(reduced);
|
|
3105
|
+
return /* @__PURE__ */ jsx22(
|
|
3106
|
+
motion3.div,
|
|
2810
3107
|
{
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
3108
|
+
className: cn("aui-tool-motion w-full min-w-0", className),
|
|
3109
|
+
initial: toolMotionState(reduced, true, "settled"),
|
|
3110
|
+
animate: toolMotionState(reduced, false, "settled"),
|
|
3111
|
+
exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
|
|
3112
|
+
transition: enter,
|
|
3113
|
+
style: { willChange: "opacity, transform, filter" },
|
|
3114
|
+
children
|
|
3115
|
+
},
|
|
3116
|
+
motionKey
|
|
2816
3117
|
);
|
|
2817
|
-
}
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
3118
|
+
}
|
|
3119
|
+
function ToolPresence({
|
|
3120
|
+
presenceKey,
|
|
3121
|
+
children,
|
|
3122
|
+
className,
|
|
3123
|
+
variant = "settled"
|
|
3124
|
+
}) {
|
|
3125
|
+
const reduced = useReducedMotion() ?? false;
|
|
3126
|
+
const { enter, exit } = toolPresenceTransition(reduced);
|
|
3127
|
+
const enterTransition = variant === "executing" ? { duration: reduced ? 0.3 : 0.52, ease: luxuryEase } : enter;
|
|
3128
|
+
return /* @__PURE__ */ jsx22(AnimatePresence, { mode: "wait", initial: true, children: /* @__PURE__ */ jsx22(
|
|
3129
|
+
motion3.div,
|
|
3130
|
+
{
|
|
3131
|
+
className: cn("aui-tool-presence w-full min-w-0", className),
|
|
3132
|
+
initial: toolMotionState(reduced, true, variant),
|
|
3133
|
+
animate: toolMotionState(reduced, false, variant),
|
|
3134
|
+
exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
|
|
3135
|
+
transition: enterTransition,
|
|
3136
|
+
style: {
|
|
3137
|
+
willChange: variant === "executing" ? "opacity, transform" : "opacity, transform, filter"
|
|
3138
|
+
},
|
|
3139
|
+
children
|
|
3140
|
+
},
|
|
3141
|
+
presenceKey
|
|
3142
|
+
) });
|
|
3143
|
+
}
|
|
3144
|
+
function ToolBodyPresence({
|
|
3145
|
+
open,
|
|
3146
|
+
children,
|
|
3147
|
+
className
|
|
3148
|
+
}) {
|
|
3149
|
+
const reduced = useReducedMotion() ?? false;
|
|
3150
|
+
return /* @__PURE__ */ jsx22(
|
|
2821
3151
|
"div",
|
|
2822
3152
|
{
|
|
2823
3153
|
className: cn(
|
|
2824
|
-
"aui-tool-
|
|
2825
|
-
|
|
3154
|
+
"aui-tool-body grid min-h-0 transition-[grid-template-rows]",
|
|
3155
|
+
open ? reduced ? "duration-200 ease-out" : "duration-[340ms] ease-[cubic-bezier(0.16,1,0.3,1)]" : reduced ? "duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]" : "duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]"
|
|
2826
3156
|
),
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
"
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
/* @__PURE__ */ jsx21(
|
|
2840
|
-
ChevronDownIcon,
|
|
2841
|
-
{
|
|
2842
|
-
className: cn(
|
|
2843
|
-
"size-3.5 shrink-0 transition-transform",
|
|
2844
|
-
open && "rotate-180"
|
|
2845
|
-
)
|
|
2846
|
-
}
|
|
2847
|
-
)
|
|
2848
|
-
]
|
|
2849
|
-
}
|
|
2850
|
-
),
|
|
2851
|
-
open && /* @__PURE__ */ jsxs11("div", { className: "aui-tool-fallback-body grid gap-2 border-t border-border/40 bg-background/50 px-3 py-2.5 text-xs", children: [
|
|
2852
|
-
argsText && argsText !== "{}" && /* @__PURE__ */ jsx21(Section, { label: "Input", value: argsText }),
|
|
2853
|
-
result !== void 0 && result !== null && /* @__PURE__ */ jsx21(Section, { label: "Output", value: formatResult(result) })
|
|
2854
|
-
] })
|
|
2855
|
-
]
|
|
3157
|
+
style: { gridTemplateRows: open ? "1fr" : "0fr" },
|
|
3158
|
+
children: /* @__PURE__ */ jsx22("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx22(
|
|
3159
|
+
"div",
|
|
3160
|
+
{
|
|
3161
|
+
className: cn(
|
|
3162
|
+
className,
|
|
3163
|
+
"transition-opacity",
|
|
3164
|
+
open ? reduced ? "opacity-100 duration-200 ease-out" : "opacity-100 duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] delay-75" : reduced ? "opacity-0 duration-100 ease-in" : "opacity-0 duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]"
|
|
3165
|
+
),
|
|
3166
|
+
children
|
|
3167
|
+
}
|
|
3168
|
+
) })
|
|
2856
3169
|
}
|
|
2857
3170
|
);
|
|
2858
|
-
}
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
// src/components/tool-fallback.tsx
|
|
3174
|
+
import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3175
|
+
function detectRunning({
|
|
3176
|
+
status,
|
|
3177
|
+
result,
|
|
3178
|
+
streamRunning
|
|
3179
|
+
}) {
|
|
3180
|
+
const isError = status?.type === "incomplete" && status.reason !== "cancelled";
|
|
3181
|
+
if (isError) return false;
|
|
3182
|
+
if (status?.type === "running") return true;
|
|
3183
|
+
if (status?.type === "complete") return false;
|
|
3184
|
+
return streamRunning && result === void 0;
|
|
3185
|
+
}
|
|
3186
|
+
function useToolRunning(props) {
|
|
3187
|
+
const { isRunning: streamRunning } = useTimbalRuntime();
|
|
3188
|
+
const partStatus = useAuiState2((s) => s.part.status);
|
|
3189
|
+
return detectRunning({
|
|
3190
|
+
status: partStatus ?? props.status,
|
|
3191
|
+
result: props.result,
|
|
3192
|
+
streamRunning
|
|
3193
|
+
});
|
|
3194
|
+
}
|
|
3195
|
+
function formatToolLabel(toolName) {
|
|
3196
|
+
return toolName.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
|
|
3197
|
+
}
|
|
3198
|
+
function formatToolResult(result) {
|
|
2864
3199
|
if (typeof result === "string") return result;
|
|
2865
3200
|
try {
|
|
2866
3201
|
return JSON.stringify(result, null, 2);
|
|
@@ -2868,26 +3203,166 @@ function formatResult(result) {
|
|
|
2868
3203
|
return String(result);
|
|
2869
3204
|
}
|
|
2870
3205
|
}
|
|
3206
|
+
var TimelineActionLabel = ({ action, detail, shimmer = false }) => /* @__PURE__ */ jsxs12("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
|
|
3207
|
+
action ? shimmer ? /* @__PURE__ */ jsx23(
|
|
3208
|
+
Shimmer,
|
|
3209
|
+
{
|
|
3210
|
+
as: "span",
|
|
3211
|
+
className: cn(studioTimelineShimmerActionClass, "aui-tool-shimmer"),
|
|
3212
|
+
duration: 1.8,
|
|
3213
|
+
spread: 2.5,
|
|
3214
|
+
children: action
|
|
3215
|
+
}
|
|
3216
|
+
) : /* @__PURE__ */ jsx23("span", { className: studioTimelineActionClass, children: action }) : null,
|
|
3217
|
+
detail ? /* @__PURE__ */ jsx23("span", { className: studioTimelineDetailClass, children: detail }) : null
|
|
3218
|
+
] });
|
|
3219
|
+
var TimelineHoverChevron = ({ expanded }) => /* @__PURE__ */ jsx23(
|
|
3220
|
+
ChevronRightIcon,
|
|
3221
|
+
{
|
|
3222
|
+
className: studioTimelineChevronClass(expanded),
|
|
3223
|
+
"aria-hidden": true
|
|
3224
|
+
}
|
|
3225
|
+
);
|
|
3226
|
+
var ToolPanel = ({ toolName, argsText, result, isError }) => {
|
|
3227
|
+
const [open, setOpen] = useState6(false);
|
|
3228
|
+
const detail = formatToolLabel(toolName);
|
|
3229
|
+
const formattedArgs = useMemo5(() => {
|
|
3230
|
+
if (!argsText || argsText === "{}") return null;
|
|
3231
|
+
try {
|
|
3232
|
+
return JSON.stringify(JSON.parse(argsText), null, 2);
|
|
3233
|
+
} catch {
|
|
3234
|
+
return argsText;
|
|
3235
|
+
}
|
|
3236
|
+
}, [argsText]);
|
|
3237
|
+
const formattedResult = useMemo5(() => {
|
|
3238
|
+
if (result === void 0 || result === null) return null;
|
|
3239
|
+
return formatToolResult(result);
|
|
3240
|
+
}, [result]);
|
|
3241
|
+
const hasBody = Boolean(formattedArgs || formattedResult);
|
|
3242
|
+
const action = isError ? "Failed" : "Used";
|
|
3243
|
+
if (!hasBody) {
|
|
3244
|
+
return /* @__PURE__ */ jsx23("div", { className: "aui-tool-row w-full min-w-0", children: /* @__PURE__ */ jsx23(TimelineActionLabel, { action, detail }) });
|
|
3245
|
+
}
|
|
3246
|
+
return /* @__PURE__ */ jsxs12("div", { className: "aui-tool-row w-full min-w-0", children: [
|
|
3247
|
+
/* @__PURE__ */ jsx23(
|
|
3248
|
+
"button",
|
|
3249
|
+
{
|
|
3250
|
+
type: "button",
|
|
3251
|
+
onClick: () => setOpen((v) => !v),
|
|
3252
|
+
"aria-expanded": open,
|
|
3253
|
+
"aria-label": `${action} ${detail}`,
|
|
3254
|
+
className: studioTimelineRowButtonClass,
|
|
3255
|
+
children: /* @__PURE__ */ jsxs12(
|
|
3256
|
+
"span",
|
|
3257
|
+
{
|
|
3258
|
+
className: cn(
|
|
3259
|
+
"inline-flex min-w-0 max-w-full items-center gap-0.5",
|
|
3260
|
+
studioTimelineTextClass,
|
|
3261
|
+
"text-foreground"
|
|
3262
|
+
),
|
|
3263
|
+
children: [
|
|
3264
|
+
/* @__PURE__ */ jsx23(TimelineActionLabel, { action, detail }),
|
|
3265
|
+
/* @__PURE__ */ jsx23(TimelineHoverChevron, { expanded: open })
|
|
3266
|
+
]
|
|
3267
|
+
}
|
|
3268
|
+
)
|
|
3269
|
+
}
|
|
3270
|
+
),
|
|
3271
|
+
/* @__PURE__ */ jsxs12(
|
|
3272
|
+
ToolBodyPresence,
|
|
3273
|
+
{
|
|
3274
|
+
open,
|
|
3275
|
+
className: cn(studioTimelineBodyPadClass, "gap-2"),
|
|
3276
|
+
children: [
|
|
3277
|
+
formattedArgs ? /* @__PURE__ */ jsx23(
|
|
3278
|
+
"div",
|
|
3279
|
+
{
|
|
3280
|
+
className: cn(
|
|
3281
|
+
studioComposerIoWellClass,
|
|
3282
|
+
"max-h-48 overflow-auto px-2.5 py-2"
|
|
3283
|
+
),
|
|
3284
|
+
children: /* @__PURE__ */ jsx23("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedArgs })
|
|
3285
|
+
}
|
|
3286
|
+
) : null,
|
|
3287
|
+
formattedResult ? /* @__PURE__ */ jsx23(
|
|
3288
|
+
"div",
|
|
3289
|
+
{
|
|
3290
|
+
className: cn(
|
|
3291
|
+
studioComposerIoWellClass,
|
|
3292
|
+
"max-h-48 overflow-auto px-2.5 py-2"
|
|
3293
|
+
),
|
|
3294
|
+
children: /* @__PURE__ */ jsx23("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedResult })
|
|
3295
|
+
}
|
|
3296
|
+
) : null
|
|
3297
|
+
]
|
|
3298
|
+
}
|
|
3299
|
+
)
|
|
3300
|
+
] });
|
|
3301
|
+
};
|
|
3302
|
+
var ToolFallbackImpl = ({
|
|
3303
|
+
toolName,
|
|
3304
|
+
argsText,
|
|
3305
|
+
result,
|
|
3306
|
+
status
|
|
3307
|
+
}) => {
|
|
3308
|
+
const isRunning = useToolRunning({ status, result });
|
|
3309
|
+
const isError = status?.type === "incomplete" && status.reason !== "cancelled";
|
|
3310
|
+
const presenceKey = isRunning ? "running" : isError ? "error" : "complete";
|
|
3311
|
+
return /* @__PURE__ */ jsx23(
|
|
3312
|
+
ToolPresence,
|
|
3313
|
+
{
|
|
3314
|
+
presenceKey,
|
|
3315
|
+
variant: isRunning ? "executing" : "settled",
|
|
3316
|
+
className: "py-0.5",
|
|
3317
|
+
children: isRunning ? /* @__PURE__ */ jsx23("div", { className: "aui-tool-running", children: /* @__PURE__ */ jsx23(
|
|
3318
|
+
TimelineActionLabel,
|
|
3319
|
+
{
|
|
3320
|
+
action: "Using",
|
|
3321
|
+
detail: formatToolLabel(toolName),
|
|
3322
|
+
shimmer: true
|
|
3323
|
+
}
|
|
3324
|
+
) }) : /* @__PURE__ */ jsx23(
|
|
3325
|
+
ToolPanel,
|
|
3326
|
+
{
|
|
3327
|
+
toolName,
|
|
3328
|
+
argsText,
|
|
3329
|
+
result,
|
|
3330
|
+
isError
|
|
3331
|
+
}
|
|
3332
|
+
)
|
|
3333
|
+
}
|
|
3334
|
+
);
|
|
3335
|
+
};
|
|
2871
3336
|
var ToolFallback = memo3(
|
|
2872
3337
|
ToolFallbackImpl
|
|
2873
3338
|
);
|
|
2874
3339
|
ToolFallback.displayName = "ToolFallback";
|
|
2875
3340
|
|
|
2876
3341
|
// src/artifacts/tool-artifact.tsx
|
|
2877
|
-
import { jsx as
|
|
3342
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
2878
3343
|
var ToolArtifactFallback = (props) => {
|
|
2879
3344
|
const registry = useArtifactRegistry();
|
|
2880
|
-
const isRunning =
|
|
3345
|
+
const isRunning = useToolRunning({
|
|
3346
|
+
status: props.status,
|
|
3347
|
+
result: props.result
|
|
3348
|
+
});
|
|
2881
3349
|
if (!isRunning) {
|
|
2882
3350
|
const artifact = parseArtifactFromToolResult(props.result);
|
|
2883
3351
|
if (artifact) {
|
|
2884
3352
|
const Renderer = registry[artifact.type];
|
|
2885
3353
|
if (Renderer) {
|
|
2886
|
-
return /* @__PURE__ */
|
|
3354
|
+
return /* @__PURE__ */ jsx24(
|
|
3355
|
+
ToolMotion,
|
|
3356
|
+
{
|
|
3357
|
+
motionKey: `artifact-${artifact.type}`,
|
|
3358
|
+
className: "aui-tool-artifact",
|
|
3359
|
+
children: /* @__PURE__ */ jsx24(Renderer, { artifact })
|
|
3360
|
+
}
|
|
3361
|
+
);
|
|
2887
3362
|
}
|
|
2888
3363
|
}
|
|
2889
3364
|
}
|
|
2890
|
-
return /* @__PURE__ */
|
|
3365
|
+
return /* @__PURE__ */ jsx24(ToolFallback, { ...props });
|
|
2891
3366
|
};
|
|
2892
3367
|
|
|
2893
3368
|
// src/components/composer.tsx
|
|
@@ -2897,7 +3372,7 @@ import {
|
|
|
2897
3372
|
useComposerRuntime
|
|
2898
3373
|
} from "@assistant-ui/react";
|
|
2899
3374
|
import { ArrowUpIcon, SquareIcon } from "lucide-react";
|
|
2900
|
-
import { Fragment as Fragment2, jsx as
|
|
3375
|
+
import { Fragment as Fragment2, jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2901
3376
|
var Composer = ({
|
|
2902
3377
|
placeholder = "Send a message...",
|
|
2903
3378
|
showAttachments = true,
|
|
@@ -2906,21 +3381,24 @@ var Composer = ({
|
|
|
2906
3381
|
noAutoFocus,
|
|
2907
3382
|
className
|
|
2908
3383
|
}) => {
|
|
2909
|
-
return /* @__PURE__ */
|
|
3384
|
+
return /* @__PURE__ */ jsx25(
|
|
2910
3385
|
ComposerPrimitive2.Root,
|
|
2911
3386
|
{
|
|
2912
3387
|
className: cn(
|
|
2913
|
-
"aui-composer-root relative
|
|
3388
|
+
"aui-composer-root relative flex w-full flex-col",
|
|
2914
3389
|
className
|
|
2915
3390
|
),
|
|
2916
|
-
children: /* @__PURE__ */
|
|
3391
|
+
children: /* @__PURE__ */ jsxs13(
|
|
2917
3392
|
ComposerPrimitive2.AttachmentDropzone,
|
|
2918
3393
|
{
|
|
2919
|
-
className:
|
|
3394
|
+
className: cn(
|
|
3395
|
+
studioComposeInputShellClass,
|
|
3396
|
+
"data-[dragging=true]:border-2 data-[dragging=true]:border-dashed data-[dragging=true]:border-primary data-[dragging=true]:bg-accent/50"
|
|
3397
|
+
),
|
|
2920
3398
|
children: [
|
|
2921
|
-
showAttachments && /* @__PURE__ */
|
|
2922
|
-
/* @__PURE__ */
|
|
2923
|
-
/* @__PURE__ */
|
|
3399
|
+
showAttachments && /* @__PURE__ */ jsx25(ComposerAttachments, {}),
|
|
3400
|
+
/* @__PURE__ */ jsx25(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
|
|
3401
|
+
/* @__PURE__ */ jsx25(
|
|
2924
3402
|
ComposerToolbar,
|
|
2925
3403
|
{
|
|
2926
3404
|
showAttachments,
|
|
@@ -2950,11 +3428,11 @@ var ComposerInput = ({
|
|
|
2950
3428
|
el.style.height = "auto";
|
|
2951
3429
|
el.style.height = `${Math.min(el.scrollHeight, 240)}px`;
|
|
2952
3430
|
};
|
|
2953
|
-
return /* @__PURE__ */
|
|
3431
|
+
return /* @__PURE__ */ jsx25(
|
|
2954
3432
|
ComposerPrimitive2.Input,
|
|
2955
3433
|
{
|
|
2956
3434
|
placeholder,
|
|
2957
|
-
className: "aui-composer-input
|
|
3435
|
+
className: "aui-composer-input max-h-60 min-h-14 w-full resize-none bg-transparent px-3 pt-3 pb-1 text-sm outline-none placeholder:text-muted-foreground/70 focus-visible:ring-0",
|
|
2958
3436
|
rows: 1,
|
|
2959
3437
|
autoFocus,
|
|
2960
3438
|
"aria-label": "Message input",
|
|
@@ -2964,37 +3442,35 @@ var ComposerInput = ({
|
|
|
2964
3442
|
);
|
|
2965
3443
|
};
|
|
2966
3444
|
var ComposerToolbar = ({ showAttachments, toolbar, sendTooltip }) => {
|
|
2967
|
-
return /* @__PURE__ */
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
3445
|
+
return /* @__PURE__ */ jsxs13("div", { className: "aui-composer-action-wrapper flex items-center justify-between gap-1 px-2.5 pb-2.5", children: [
|
|
3446
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1", children: [
|
|
3447
|
+
showAttachments && /* @__PURE__ */ jsx25(ComposerAddAttachment, {}),
|
|
3448
|
+
toolbar
|
|
3449
|
+
] }),
|
|
3450
|
+
/* @__PURE__ */ jsx25(ComposerSendOrCancel, { sendTooltip })
|
|
2972
3451
|
] });
|
|
2973
3452
|
};
|
|
2974
3453
|
var ComposerSendOrCancel = ({ sendTooltip }) => {
|
|
2975
|
-
return /* @__PURE__ */
|
|
2976
|
-
/* @__PURE__ */
|
|
3454
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
3455
|
+
/* @__PURE__ */ jsx25(AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ jsx25(ComposerPrimitive2.Send, { asChild: true, children: /* @__PURE__ */ jsx25(
|
|
2977
3456
|
TooltipIconButton,
|
|
2978
3457
|
{
|
|
2979
3458
|
tooltip: sendTooltip,
|
|
2980
|
-
|
|
3459
|
+
variant: "primary",
|
|
2981
3460
|
type: "submit",
|
|
2982
|
-
|
|
2983
|
-
size: "icon",
|
|
2984
|
-
className: "aui-composer-send size-8 rounded-full",
|
|
3461
|
+
className: "aui-composer-send shrink-0 disabled:opacity-30",
|
|
2985
3462
|
"aria-label": "Send message",
|
|
2986
|
-
children: /* @__PURE__ */
|
|
3463
|
+
children: /* @__PURE__ */ jsx25(ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
|
|
2987
3464
|
}
|
|
2988
3465
|
) }) }),
|
|
2989
|
-
/* @__PURE__ */
|
|
2990
|
-
|
|
3466
|
+
/* @__PURE__ */ jsx25(AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ jsx25(ComposerPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx25(
|
|
3467
|
+
TooltipIconButton,
|
|
2991
3468
|
{
|
|
2992
|
-
|
|
2993
|
-
variant: "
|
|
2994
|
-
|
|
2995
|
-
className: "aui-composer-cancel size-8 rounded-full",
|
|
3469
|
+
tooltip: "Stop generating",
|
|
3470
|
+
variant: "primary",
|
|
3471
|
+
className: "aui-composer-cancel shrink-0",
|
|
2996
3472
|
"aria-label": "Stop generating",
|
|
2997
|
-
children: /* @__PURE__ */
|
|
3473
|
+
children: /* @__PURE__ */ jsx25(SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
|
|
2998
3474
|
}
|
|
2999
3475
|
) }) })
|
|
3000
3476
|
] });
|
|
@@ -3003,55 +3479,53 @@ var ComposerSendOrCancel = ({ sendTooltip }) => {
|
|
|
3003
3479
|
// src/components/suggestions.tsx
|
|
3004
3480
|
import {
|
|
3005
3481
|
useEffect as useEffect4,
|
|
3006
|
-
useMemo as
|
|
3482
|
+
useMemo as useMemo6,
|
|
3007
3483
|
useState as useState7
|
|
3008
3484
|
} from "react";
|
|
3009
3485
|
import { useThreadRuntime as useThreadRuntime3 } from "@assistant-ui/react";
|
|
3010
|
-
import {
|
|
3486
|
+
import { ArrowUpIcon as ArrowUpIcon2 } from "lucide-react";
|
|
3487
|
+
import { jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3011
3488
|
var Suggestions = ({
|
|
3012
3489
|
suggestions,
|
|
3013
|
-
layout = "grid",
|
|
3014
3490
|
className
|
|
3015
3491
|
}) => {
|
|
3016
3492
|
const items = useResolvedSuggestions(suggestions);
|
|
3017
3493
|
if (!items || items.length === 0) return null;
|
|
3018
|
-
return /* @__PURE__ */
|
|
3494
|
+
return /* @__PURE__ */ jsx26(
|
|
3019
3495
|
"div",
|
|
3020
3496
|
{
|
|
3021
3497
|
className: cn(
|
|
3022
|
-
"aui-thread-suggestions w-full pb-
|
|
3023
|
-
layout === "grid" ? "grid gap-2 @md:grid-cols-2" : "flex gap-2 overflow-x-auto pb-1 [&::-webkit-scrollbar]:hidden",
|
|
3498
|
+
"aui-thread-suggestions flex w-full flex-col gap-2 pb-2.5",
|
|
3024
3499
|
className
|
|
3025
3500
|
),
|
|
3026
|
-
|
|
3501
|
+
role: "list",
|
|
3502
|
+
"aria-label": "Suggested prompts",
|
|
3503
|
+
children: items.map((suggestion, i) => /* @__PURE__ */ jsx26(SuggestionRow, { suggestion }, (suggestion.prompt ?? suggestion.title) + i))
|
|
3027
3504
|
}
|
|
3028
3505
|
);
|
|
3029
3506
|
};
|
|
3030
|
-
var
|
|
3031
|
-
suggestion,
|
|
3032
|
-
compact
|
|
3033
|
-
}) => {
|
|
3507
|
+
var SuggestionRow = ({ suggestion }) => {
|
|
3034
3508
|
const runtime = useThreadRuntime3();
|
|
3035
3509
|
const onClick = () => {
|
|
3036
3510
|
const text = suggestion.prompt ?? suggestion.title;
|
|
3037
3511
|
runtime.append({ role: "user", content: [{ type: "text", text }] });
|
|
3038
3512
|
};
|
|
3039
|
-
return /* @__PURE__ */
|
|
3040
|
-
|
|
3513
|
+
return /* @__PURE__ */ jsxs14(
|
|
3514
|
+
"button",
|
|
3041
3515
|
{
|
|
3042
|
-
|
|
3516
|
+
type: "button",
|
|
3517
|
+
role: "listitem",
|
|
3043
3518
|
onClick,
|
|
3044
|
-
className: cn(
|
|
3045
|
-
"aui-thread-suggestion h-auto rounded-2xl border text-left text-sm transition-colors hover:bg-muted",
|
|
3046
|
-
compact ? "shrink-0 flex-row items-center gap-2 whitespace-nowrap px-3 py-2" : "w-full flex-wrap items-start justify-start gap-1 px-4 py-3 @md:flex-col"
|
|
3047
|
-
),
|
|
3519
|
+
className: cn("aui-thread-suggestion", studioListRowButtonClass),
|
|
3048
3520
|
children: [
|
|
3049
|
-
|
|
3050
|
-
/* @__PURE__ */
|
|
3051
|
-
|
|
3521
|
+
/* @__PURE__ */ jsx26("span", { className: "aui-thread-suggestion-icon shrink-0 text-muted-foreground", children: suggestion.icon ?? /* @__PURE__ */ jsx26(ArrowUpIcon2, { className: "size-4", strokeWidth: 1.75, "aria-hidden": true }) }),
|
|
3522
|
+
/* @__PURE__ */ jsxs14("span", { className: "aui-thread-suggestion-text min-w-0 flex-1 text-left", children: [
|
|
3523
|
+
/* @__PURE__ */ jsx26("span", { className: "aui-thread-suggestion-text-1 block truncate text-sm font-normal text-foreground", children: suggestion.title }),
|
|
3524
|
+
suggestion.description && /* @__PURE__ */ jsx26("span", { className: "aui-thread-suggestion-text-2 mt-0.5 block truncate text-xs text-muted-foreground", children: suggestion.description })
|
|
3525
|
+
] })
|
|
3052
3526
|
]
|
|
3053
3527
|
}
|
|
3054
|
-
)
|
|
3528
|
+
);
|
|
3055
3529
|
};
|
|
3056
3530
|
function useResolvedSuggestions(source) {
|
|
3057
3531
|
const [resolved, setResolved] = useState7(
|
|
@@ -3076,29 +3550,80 @@ function useResolvedSuggestions(source) {
|
|
|
3076
3550
|
cancelled = true;
|
|
3077
3551
|
};
|
|
3078
3552
|
}, [source]);
|
|
3079
|
-
return
|
|
3553
|
+
return useMemo6(() => resolved, [resolved]);
|
|
3554
|
+
}
|
|
3555
|
+
|
|
3556
|
+
// src/design/theme-sanity.ts
|
|
3557
|
+
var scheduled = false;
|
|
3558
|
+
var warned = false;
|
|
3559
|
+
function isDev() {
|
|
3560
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
3561
|
+
return false;
|
|
3562
|
+
}
|
|
3563
|
+
return true;
|
|
3564
|
+
}
|
|
3565
|
+
function parseLuminance(color) {
|
|
3566
|
+
const value = color.trim();
|
|
3567
|
+
if (!value) return null;
|
|
3568
|
+
const oklch = value.match(/oklch\(\s*([0-9.]+)/i);
|
|
3569
|
+
if (oklch) {
|
|
3570
|
+
const lightness = Number.parseFloat(oklch[1]);
|
|
3571
|
+
if (Number.isFinite(lightness)) return lightness;
|
|
3572
|
+
}
|
|
3573
|
+
const rgb = value.match(/rgba?\(\s*([0-9.]+)[\s,]+([0-9.]+)[\s,]+([0-9.]+)/i);
|
|
3574
|
+
if (rgb) {
|
|
3575
|
+
const r = Number.parseFloat(rgb[1]) / 255;
|
|
3576
|
+
const g = Number.parseFloat(rgb[2]) / 255;
|
|
3577
|
+
const b = Number.parseFloat(rgb[3]) / 255;
|
|
3578
|
+
if ([r, g, b].every(Number.isFinite)) {
|
|
3579
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
const hsl = value.match(/hsla?\(\s*[0-9.]+[\s,]+[0-9.]+%[\s,]+([0-9.]+)%/i);
|
|
3583
|
+
if (hsl) {
|
|
3584
|
+
const lightness = Number.parseFloat(hsl[1]) / 100;
|
|
3585
|
+
if (Number.isFinite(lightness)) return lightness;
|
|
3586
|
+
}
|
|
3587
|
+
return null;
|
|
3588
|
+
}
|
|
3589
|
+
function runCheck() {
|
|
3590
|
+
if (warned) return;
|
|
3591
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
3592
|
+
const root = document.documentElement;
|
|
3593
|
+
const styles = window.getComputedStyle(root);
|
|
3594
|
+
const background = styles.getPropertyValue("--background").trim();
|
|
3595
|
+
if (!background) {
|
|
3596
|
+
warned = true;
|
|
3597
|
+
console.warn(
|
|
3598
|
+
'[@timbal-ai/timbal-react] No `--background` CSS variable found on `<html>`. Did you `import "@timbal-ai/timbal-react/styles.css"` in your app entry? Components rely on semantic tokens (bg-background, text-foreground, \u2026) and will fall back to browser defaults.'
|
|
3599
|
+
);
|
|
3600
|
+
return;
|
|
3601
|
+
}
|
|
3602
|
+
const luminance = parseLuminance(background);
|
|
3603
|
+
if (luminance === null) return;
|
|
3604
|
+
const hasDarkClass = root.classList.contains("dark");
|
|
3605
|
+
const looksDark = luminance < 0.5;
|
|
3606
|
+
if (hasDarkClass !== looksDark) {
|
|
3607
|
+
warned = true;
|
|
3608
|
+
console.warn(
|
|
3609
|
+
`[@timbal-ai/timbal-react] Theme mismatch detected. \`<html>\` has${hasDarkClass ? "" : " no"} \`.dark\` class but the resolved \`--background\` is ${looksDark ? "dark" : "light"} (${background}). This usually means the consumer's CSS overrides \`--background\` only in one mode. Import \`@timbal-ai/timbal-react/styles.css\` for a complete light + dark token set, or declare matching \`:root\` AND \`.dark\` blocks in your own CSS.`
|
|
3610
|
+
);
|
|
3611
|
+
}
|
|
3612
|
+
}
|
|
3613
|
+
function scheduleThemeSanityCheck() {
|
|
3614
|
+
if (scheduled) return;
|
|
3615
|
+
if (!isDev()) return;
|
|
3616
|
+
if (typeof window === "undefined") return;
|
|
3617
|
+
scheduled = true;
|
|
3618
|
+
if (typeof queueMicrotask === "function") {
|
|
3619
|
+
queueMicrotask(() => setTimeout(runCheck, 0));
|
|
3620
|
+
} else {
|
|
3621
|
+
setTimeout(runCheck, 0);
|
|
3622
|
+
}
|
|
3080
3623
|
}
|
|
3081
3624
|
|
|
3082
3625
|
// src/components/thread.tsx
|
|
3083
|
-
import {
|
|
3084
|
-
ActionBarMorePrimitive,
|
|
3085
|
-
ActionBarPrimitive,
|
|
3086
|
-
AuiIf as AuiIf2,
|
|
3087
|
-
ComposerPrimitive as ComposerPrimitive3,
|
|
3088
|
-
ErrorPrimitive,
|
|
3089
|
-
MessagePrimitive as MessagePrimitive2,
|
|
3090
|
-
ThreadPrimitive
|
|
3091
|
-
} from "@assistant-ui/react";
|
|
3092
|
-
import {
|
|
3093
|
-
ArrowDownIcon,
|
|
3094
|
-
CheckIcon as CheckIcon3,
|
|
3095
|
-
CopyIcon as CopyIcon2,
|
|
3096
|
-
DownloadIcon,
|
|
3097
|
-
MoreHorizontalIcon,
|
|
3098
|
-
PencilIcon,
|
|
3099
|
-
RefreshCwIcon
|
|
3100
|
-
} from "lucide-react";
|
|
3101
|
-
import { jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3626
|
+
import { jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3102
3627
|
var Thread = ({
|
|
3103
3628
|
className,
|
|
3104
3629
|
maxWidth = "44rem",
|
|
@@ -3116,13 +3641,16 @@ var Thread = ({
|
|
|
3116
3641
|
const EditComposerSlot = components?.EditComposer ?? EditComposer;
|
|
3117
3642
|
const ScrollToBottomSlot = components?.ScrollToBottom ?? ThreadScrollToBottom;
|
|
3118
3643
|
const SuggestionsSlot = components?.Suggestions ?? Suggestions;
|
|
3119
|
-
|
|
3644
|
+
useEffect5(() => {
|
|
3645
|
+
scheduleThemeSanityCheck();
|
|
3646
|
+
}, []);
|
|
3647
|
+
return /* @__PURE__ */ jsx27(
|
|
3120
3648
|
ArtifactRegistryProvider,
|
|
3121
3649
|
{
|
|
3122
3650
|
renderers: artifacts?.renderers,
|
|
3123
3651
|
override: artifacts?.override,
|
|
3124
|
-
children: /* @__PURE__ */
|
|
3125
|
-
}), children: /* @__PURE__ */
|
|
3652
|
+
children: /* @__PURE__ */ jsx27(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
|
|
3653
|
+
}), children: /* @__PURE__ */ jsx27(
|
|
3126
3654
|
ThreadPrimitive.Root,
|
|
3127
3655
|
{
|
|
3128
3656
|
className: cn(
|
|
@@ -3130,13 +3658,13 @@ var Thread = ({
|
|
|
3130
3658
|
className
|
|
3131
3659
|
),
|
|
3132
3660
|
style: { ["--thread-max-width"]: maxWidth },
|
|
3133
|
-
children: /* @__PURE__ */
|
|
3661
|
+
children: /* @__PURE__ */ jsxs15(
|
|
3134
3662
|
ThreadPrimitive.Viewport,
|
|
3135
3663
|
{
|
|
3136
3664
|
turnAnchor: "bottom",
|
|
3137
3665
|
className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4 pt-4",
|
|
3138
3666
|
children: [
|
|
3139
|
-
/* @__PURE__ */
|
|
3667
|
+
/* @__PURE__ */ jsx27(
|
|
3140
3668
|
WelcomeSlot,
|
|
3141
3669
|
{
|
|
3142
3670
|
config: welcome,
|
|
@@ -3144,7 +3672,7 @@ var Thread = ({
|
|
|
3144
3672
|
Suggestions: SuggestionsSlot
|
|
3145
3673
|
}
|
|
3146
3674
|
),
|
|
3147
|
-
/* @__PURE__ */
|
|
3675
|
+
/* @__PURE__ */ jsx27(
|
|
3148
3676
|
ThreadPrimitive.Messages,
|
|
3149
3677
|
{
|
|
3150
3678
|
components: {
|
|
@@ -3154,9 +3682,9 @@ var Thread = ({
|
|
|
3154
3682
|
}
|
|
3155
3683
|
}
|
|
3156
3684
|
),
|
|
3157
|
-
/* @__PURE__ */
|
|
3158
|
-
/* @__PURE__ */
|
|
3159
|
-
/* @__PURE__ */
|
|
3685
|
+
/* @__PURE__ */ jsxs15(ThreadPrimitive.ViewportFooter, { className: "aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible bg-transparent pb-4 md:pb-6", children: [
|
|
3686
|
+
/* @__PURE__ */ jsx27(ScrollToBottomSlot, {}),
|
|
3687
|
+
/* @__PURE__ */ jsx27(ComposerSlot, { placeholder: composerPlaceholder })
|
|
3160
3688
|
] })
|
|
3161
3689
|
]
|
|
3162
3690
|
}
|
|
@@ -3167,105 +3695,164 @@ var Thread = ({
|
|
|
3167
3695
|
);
|
|
3168
3696
|
};
|
|
3169
3697
|
var ThreadScrollToBottom = () => {
|
|
3170
|
-
return /* @__PURE__ */
|
|
3698
|
+
return /* @__PURE__ */ jsx27(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx27(
|
|
3171
3699
|
TooltipIconButton,
|
|
3172
3700
|
{
|
|
3173
3701
|
tooltip: "Scroll to bottom",
|
|
3174
|
-
variant: "
|
|
3175
|
-
className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center
|
|
3176
|
-
children: /* @__PURE__ */
|
|
3702
|
+
variant: "secondary",
|
|
3703
|
+
className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center disabled:invisible",
|
|
3704
|
+
children: /* @__PURE__ */ jsx27(ArrowDownIcon, { className: "size-4" })
|
|
3177
3705
|
}
|
|
3178
3706
|
) });
|
|
3179
3707
|
};
|
|
3708
|
+
var welcomeStagger = {
|
|
3709
|
+
initial: {},
|
|
3710
|
+
animate: {
|
|
3711
|
+
transition: { staggerChildren: 0.16, delayChildren: 0.12 }
|
|
3712
|
+
}
|
|
3713
|
+
};
|
|
3714
|
+
var welcomeItem = {
|
|
3715
|
+
initial: { opacity: 0, y: 14 },
|
|
3716
|
+
animate: {
|
|
3717
|
+
opacity: 1,
|
|
3718
|
+
y: 0,
|
|
3719
|
+
transition: { duration: 0.9, ease: luxuryEase }
|
|
3720
|
+
}
|
|
3721
|
+
};
|
|
3722
|
+
var welcomeIcon = {
|
|
3723
|
+
initial: { opacity: 0, y: 10, scale: 0.96 },
|
|
3724
|
+
animate: {
|
|
3725
|
+
opacity: 1,
|
|
3726
|
+
y: 0,
|
|
3727
|
+
scale: 1,
|
|
3728
|
+
transition: { duration: 1.1, ease: luxuryEase }
|
|
3729
|
+
}
|
|
3730
|
+
};
|
|
3180
3731
|
var ThreadWelcome = ({
|
|
3181
3732
|
config,
|
|
3182
3733
|
suggestions,
|
|
3183
3734
|
Suggestions: SuggestionsSlot = Suggestions
|
|
3184
3735
|
}) => {
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3736
|
+
const isEmpty = useThread((s) => s.messages.length === 0);
|
|
3737
|
+
if (!isEmpty) return null;
|
|
3738
|
+
return /* @__PURE__ */ jsxs15("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
|
|
3739
|
+
/* @__PURE__ */ jsx27("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ jsxs15(
|
|
3740
|
+
motion4.div,
|
|
3741
|
+
{
|
|
3742
|
+
className: "aui-thread-welcome-message flex flex-col items-center justify-center px-4 text-center",
|
|
3743
|
+
variants: welcomeStagger,
|
|
3744
|
+
initial: "initial",
|
|
3745
|
+
animate: "animate",
|
|
3746
|
+
children: [
|
|
3747
|
+
config?.icon && /* @__PURE__ */ jsx27(motion4.div, { variants: welcomeIcon, className: "mb-5", children: config.icon }),
|
|
3748
|
+
/* @__PURE__ */ jsx27(
|
|
3749
|
+
motion4.h1,
|
|
3750
|
+
{
|
|
3751
|
+
variants: welcomeItem,
|
|
3752
|
+
className: "aui-thread-welcome-message-inner font-semibold text-2xl",
|
|
3753
|
+
children: config?.heading ?? "How can I help you today?"
|
|
3754
|
+
}
|
|
3755
|
+
),
|
|
3756
|
+
/* @__PURE__ */ jsx27(
|
|
3757
|
+
motion4.p,
|
|
3758
|
+
{
|
|
3759
|
+
variants: welcomeItem,
|
|
3760
|
+
className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
|
|
3761
|
+
children: config?.subheading ?? "Send a message to start a conversation."
|
|
3762
|
+
}
|
|
3763
|
+
)
|
|
3764
|
+
]
|
|
3765
|
+
}
|
|
3766
|
+
) }),
|
|
3767
|
+
suggestions && /* @__PURE__ */ jsx27("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ jsx27(SuggestionsSlot, { suggestions }) })
|
|
3768
|
+
] });
|
|
3210
3769
|
};
|
|
3211
3770
|
var MessageError = () => {
|
|
3212
|
-
return /* @__PURE__ */
|
|
3771
|
+
return /* @__PURE__ */ jsx27(MessagePrimitive2.Error, { children: /* @__PURE__ */ jsx27(ErrorPrimitive.Root, { className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm", children: /* @__PURE__ */ jsx27(ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
|
|
3213
3772
|
};
|
|
3214
3773
|
var AssistantMessage = () => {
|
|
3215
|
-
return /* @__PURE__ */
|
|
3774
|
+
return /* @__PURE__ */ jsxs15(
|
|
3216
3775
|
MessagePrimitive2.Root,
|
|
3217
3776
|
{
|
|
3218
3777
|
className: "aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150",
|
|
3219
3778
|
"data-role": "assistant",
|
|
3220
3779
|
children: [
|
|
3221
|
-
/* @__PURE__ */
|
|
3222
|
-
/* @__PURE__ */
|
|
3780
|
+
/* @__PURE__ */ jsxs15("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
|
|
3781
|
+
/* @__PURE__ */ jsx27(
|
|
3223
3782
|
MessagePrimitive2.Parts,
|
|
3224
3783
|
{
|
|
3225
3784
|
components: {
|
|
3226
3785
|
Text: MarkdownText,
|
|
3227
|
-
|
|
3786
|
+
// `Override` (not `Fallback`) replaces the default tool renderer
|
|
3787
|
+
// entirely so we never fall back to the assistant-ui boilerplate.
|
|
3788
|
+
tools: { Override: ToolArtifactFallback }
|
|
3228
3789
|
}
|
|
3229
3790
|
}
|
|
3230
3791
|
),
|
|
3231
|
-
/* @__PURE__ */
|
|
3792
|
+
/* @__PURE__ */ jsx27(MessageError, {})
|
|
3232
3793
|
] }),
|
|
3233
|
-
/* @__PURE__ */
|
|
3794
|
+
/* @__PURE__ */ jsx27("div", { className: "aui-assistant-message-footer mt-0 ml-1 flex", children: /* @__PURE__ */ jsx27(AssistantActionBar, {}) })
|
|
3234
3795
|
]
|
|
3235
3796
|
}
|
|
3236
3797
|
);
|
|
3237
3798
|
};
|
|
3799
|
+
var ASSISTANT_ACTION_ICON_CLASS = cn(
|
|
3800
|
+
"size-6 min-h-6 min-w-6 text-muted-foreground/45 hover:text-muted-foreground/80",
|
|
3801
|
+
// The v2 fill span sits inside `group/tbv2 > span:first-child`. We mute it
|
|
3802
|
+
// here so action-bar buttons read as subtle icons rather than full pills.
|
|
3803
|
+
"[&>span:first-child]:bg-transparent",
|
|
3804
|
+
"[&>span:first-child]:group-hover/tbv2:bg-muted/70"
|
|
3805
|
+
);
|
|
3238
3806
|
var AssistantActionBar = () => {
|
|
3239
|
-
return /* @__PURE__ */
|
|
3807
|
+
return /* @__PURE__ */ jsxs15(
|
|
3240
3808
|
ActionBarPrimitive.Root,
|
|
3241
3809
|
{
|
|
3242
3810
|
hideWhenRunning: true,
|
|
3243
3811
|
autohide: "not-last",
|
|
3244
|
-
|
|
3245
|
-
className: "aui-assistant-action-bar-root col-start-3 row-start-2 -ml-1 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm",
|
|
3812
|
+
className: "aui-assistant-action-bar-root flex items-center gap-0 bg-transparent px-0 py-0.5 text-muted-foreground/60",
|
|
3246
3813
|
children: [
|
|
3247
|
-
/* @__PURE__ */
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3814
|
+
/* @__PURE__ */ jsx27(ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxs15(
|
|
3815
|
+
TooltipIconButton,
|
|
3816
|
+
{
|
|
3817
|
+
tooltip: "Copy",
|
|
3818
|
+
variant: "ghost",
|
|
3819
|
+
className: ASSISTANT_ACTION_ICON_CLASS,
|
|
3820
|
+
children: [
|
|
3821
|
+
/* @__PURE__ */ jsx27(AuiIf2, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ jsx27(CheckIcon3, { className: "size-3" }) }),
|
|
3822
|
+
/* @__PURE__ */ jsx27(AuiIf2, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ jsx27(CopyIcon2, { className: "size-3" }) })
|
|
3823
|
+
]
|
|
3824
|
+
}
|
|
3825
|
+
) }),
|
|
3826
|
+
/* @__PURE__ */ jsx27(ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ jsx27(
|
|
3827
|
+
TooltipIconButton,
|
|
3828
|
+
{
|
|
3829
|
+
tooltip: "Regenerate",
|
|
3830
|
+
variant: "ghost",
|
|
3831
|
+
className: ASSISTANT_ACTION_ICON_CLASS,
|
|
3832
|
+
children: /* @__PURE__ */ jsx27(RefreshCwIcon, { className: "size-3" })
|
|
3833
|
+
}
|
|
3834
|
+
) }),
|
|
3835
|
+
/* @__PURE__ */ jsxs15(ActionBarMorePrimitive.Root, { children: [
|
|
3836
|
+
/* @__PURE__ */ jsx27(ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsx27(
|
|
3254
3837
|
TooltipIconButton,
|
|
3255
3838
|
{
|
|
3256
3839
|
tooltip: "More",
|
|
3257
|
-
|
|
3258
|
-
|
|
3840
|
+
variant: "ghost",
|
|
3841
|
+
className: cn(
|
|
3842
|
+
ASSISTANT_ACTION_ICON_CLASS,
|
|
3843
|
+
"data-[state=open]:text-muted-foreground/80"
|
|
3844
|
+
),
|
|
3845
|
+
children: /* @__PURE__ */ jsx27(MoreHorizontalIcon, { className: "size-3" })
|
|
3259
3846
|
}
|
|
3260
3847
|
) }),
|
|
3261
|
-
/* @__PURE__ */
|
|
3848
|
+
/* @__PURE__ */ jsx27(
|
|
3262
3849
|
ActionBarMorePrimitive.Content,
|
|
3263
3850
|
{
|
|
3264
3851
|
side: "bottom",
|
|
3265
3852
|
align: "start",
|
|
3266
|
-
className: "aui-action-bar-more-content z-50 min-w-
|
|
3267
|
-
children: /* @__PURE__ */
|
|
3268
|
-
/* @__PURE__ */
|
|
3853
|
+
className: "aui-action-bar-more-content z-50 min-w-36 overflow-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-card-elevated",
|
|
3854
|
+
children: /* @__PURE__ */ jsx27(ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ jsxs15(ActionBarMorePrimitive.Item, { className: "aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none hover:bg-muted focus:bg-muted", children: [
|
|
3855
|
+
/* @__PURE__ */ jsx27(DownloadIcon, { className: "size-4 shrink-0" }),
|
|
3269
3856
|
"Export as Markdown"
|
|
3270
3857
|
] }) })
|
|
3271
3858
|
}
|
|
@@ -3275,51 +3862,71 @@ var AssistantActionBar = () => {
|
|
|
3275
3862
|
}
|
|
3276
3863
|
);
|
|
3277
3864
|
};
|
|
3865
|
+
var UserMessageText = () => {
|
|
3866
|
+
return /* @__PURE__ */ jsx27("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ jsx27(MessagePartPrimitive.Text, { smooth: false }) });
|
|
3867
|
+
};
|
|
3278
3868
|
var UserMessage = () => {
|
|
3279
|
-
return /* @__PURE__ */
|
|
3869
|
+
return /* @__PURE__ */ jsxs15(
|
|
3280
3870
|
MessagePrimitive2.Root,
|
|
3281
3871
|
{
|
|
3282
|
-
className: "aui-user-message-root
|
|
3872
|
+
className: "aui-user-message-root mx-auto flex w-full max-w-(--thread-max-width) flex-col items-end gap-2 px-2 py-3",
|
|
3283
3873
|
"data-role": "user",
|
|
3284
3874
|
children: [
|
|
3285
|
-
/* @__PURE__ */
|
|
3286
|
-
/* @__PURE__ */
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3875
|
+
/* @__PURE__ */ jsx27(UserMessageAttachments, {}),
|
|
3876
|
+
/* @__PURE__ */ jsxs15(
|
|
3877
|
+
motion4.div,
|
|
3878
|
+
{
|
|
3879
|
+
className: "aui-user-message-content relative inline-block max-w-[80%] rounded-2xl bg-bubble-user px-4 py-2.5 text-bubble-user-foreground",
|
|
3880
|
+
initial: { opacity: 0, y: 8, scale: 0.99 },
|
|
3881
|
+
animate: { opacity: 1, y: 0, scale: 1 },
|
|
3882
|
+
transition: { duration: 0.65, ease: luxuryEase },
|
|
3883
|
+
children: [
|
|
3884
|
+
/* @__PURE__ */ jsx27(MessagePrimitive2.Parts, { components: { Text: UserMessageText } }),
|
|
3885
|
+
/* @__PURE__ */ jsx27("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ jsx27(UserActionBar, {}) })
|
|
3886
|
+
]
|
|
3887
|
+
}
|
|
3888
|
+
)
|
|
3290
3889
|
]
|
|
3291
3890
|
}
|
|
3292
3891
|
);
|
|
3293
3892
|
};
|
|
3294
3893
|
var UserActionBar = () => {
|
|
3295
|
-
return /* @__PURE__ */
|
|
3894
|
+
return /* @__PURE__ */ jsx27(
|
|
3296
3895
|
ActionBarPrimitive.Root,
|
|
3297
3896
|
{
|
|
3298
3897
|
hideWhenRunning: true,
|
|
3299
3898
|
autohide: "not-last",
|
|
3300
3899
|
className: "aui-user-action-bar-root flex flex-col items-end",
|
|
3301
|
-
children: /* @__PURE__ */
|
|
3900
|
+
children: /* @__PURE__ */ jsx27(ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ jsx27(
|
|
3901
|
+
TooltipIconButton,
|
|
3902
|
+
{
|
|
3903
|
+
tooltip: "Edit",
|
|
3904
|
+
variant: "ghost",
|
|
3905
|
+
className: ASSISTANT_ACTION_ICON_CLASS,
|
|
3906
|
+
children: /* @__PURE__ */ jsx27(PencilIcon, { className: "size-3" })
|
|
3907
|
+
}
|
|
3908
|
+
) })
|
|
3302
3909
|
}
|
|
3303
3910
|
);
|
|
3304
3911
|
};
|
|
3305
3912
|
var EditComposer = () => {
|
|
3306
|
-
return /* @__PURE__ */
|
|
3307
|
-
/* @__PURE__ */
|
|
3913
|
+
return /* @__PURE__ */ jsx27(MessagePrimitive2.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ jsxs15(ComposerPrimitive3.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
|
|
3914
|
+
/* @__PURE__ */ jsx27(
|
|
3308
3915
|
ComposerPrimitive3.Input,
|
|
3309
3916
|
{
|
|
3310
3917
|
className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
|
|
3311
3918
|
autoFocus: true
|
|
3312
3919
|
}
|
|
3313
3920
|
),
|
|
3314
|
-
/* @__PURE__ */
|
|
3315
|
-
/* @__PURE__ */
|
|
3316
|
-
/* @__PURE__ */
|
|
3921
|
+
/* @__PURE__ */ jsxs15("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
|
|
3922
|
+
/* @__PURE__ */ jsx27(ComposerPrimitive3.Cancel, { asChild: true, children: /* @__PURE__ */ jsx27(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
|
|
3923
|
+
/* @__PURE__ */ jsx27(ComposerPrimitive3.Send, { asChild: true, children: /* @__PURE__ */ jsx27(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
|
|
3317
3924
|
] })
|
|
3318
3925
|
] }) });
|
|
3319
3926
|
};
|
|
3320
3927
|
|
|
3321
3928
|
// src/components/chat.tsx
|
|
3322
|
-
import { jsx as
|
|
3929
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
3323
3930
|
function TimbalChat({
|
|
3324
3931
|
workforceId,
|
|
3325
3932
|
baseUrl,
|
|
@@ -3330,7 +3937,7 @@ function TimbalChat({
|
|
|
3330
3937
|
debug,
|
|
3331
3938
|
...threadProps
|
|
3332
3939
|
}) {
|
|
3333
|
-
return /* @__PURE__ */
|
|
3940
|
+
return /* @__PURE__ */ jsx28(
|
|
3334
3941
|
TimbalRuntimeProvider,
|
|
3335
3942
|
{
|
|
3336
3943
|
workforceId,
|
|
@@ -3340,168 +3947,88 @@ function TimbalChat({
|
|
|
3340
3947
|
attachmentsUploadUrl,
|
|
3341
3948
|
attachmentsAccept,
|
|
3342
3949
|
debug,
|
|
3343
|
-
children: /* @__PURE__ */
|
|
3950
|
+
children: /* @__PURE__ */ jsx28(Thread, { ...threadProps })
|
|
3344
3951
|
}
|
|
3345
3952
|
);
|
|
3346
3953
|
}
|
|
3347
3954
|
|
|
3348
|
-
// src/
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
-
|
|
3392
|
-
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
| Set state | \`{ "kind": "set", "path": "foo", "value": 1 }\` | Writes local widget state. |
|
|
3403
|
-
| Toggle boolean | \`{ "kind": "toggle", "path": "enabled" }\` | Flips a boolean at \`path\`. |
|
|
3404
|
-
| Host event | \`{ "kind": "emit", "name": "event-name", "payload": { ... } }\` | Bubbles to the host app (\`onArtifactEvent\` on \`<Thread>\`). |
|
|
3405
|
-
|
|
3406
|
-
### \`ui\` node palette (\`root.kind\`)
|
|
3407
|
-
|
|
3408
|
-
| \`kind\` | Purpose | Key fields |
|
|
3409
|
-
|---|---|---|
|
|
3410
|
-
| \`box\` | Layout container | \`children\`, \`direction\` (\`row\`/\`col\`), \`gap\`, \`padding\`, \`align\`, \`justify\`, \`wrap\` |
|
|
3411
|
-
| \`text\` | Body text | \`value\`, optional \`muted\`, \`size\`, \`weight\` |
|
|
3412
|
-
| \`heading\` | Heading | \`value\`, optional \`level\` (1\u20134) |
|
|
3413
|
-
| \`badge\` | Pill label | \`value\`, optional \`tone\` (\`default\`, \`primary\`, \`success\`, \`warn\`, \`danger\`) |
|
|
3414
|
-
| \`button\` | Clickable button | \`label\`, optional \`variant\`, \`size\`, \`disabled\`, \`onClick\` |
|
|
3415
|
-
| \`toggle\` | Boolean switch | \`binding\` (state path), optional \`label\`, \`onChange\` |
|
|
3416
|
-
| \`slider\` | Numeric range | \`binding\`, optional \`min\`, \`max\`, \`step\`, \`label\`, \`showValue\`, \`onChange\` |
|
|
3417
|
-
| \`tooltip\` | Hover tooltip | \`content\`, \`child\` (single node), optional \`side\` |
|
|
3418
|
-
| \`draggable\` | Drag gesture | \`child\`, optional \`axis\` (\`x\`/\`y\`/\`both\`), \`snapBack\`, \`onDragEnd\` |
|
|
3419
|
-
| \`custom\` | Host-registered widget | \`name\`, optional \`props\`, \`children\` \u2014 only if the app registered that name |
|
|
3420
|
-
|
|
3421
|
-
### Example \`ui\` artifact
|
|
3422
|
-
|
|
3423
|
-
\`\`\`json
|
|
3424
|
-
{
|
|
3425
|
-
"type": "ui",
|
|
3426
|
-
"title": "Configure plan",
|
|
3427
|
-
"initialState": { "qty": 1, "premium": false },
|
|
3428
|
-
"root": {
|
|
3429
|
-
"kind": "box",
|
|
3430
|
-
"direction": "col",
|
|
3431
|
-
"gap": 3,
|
|
3432
|
-
"children": [
|
|
3433
|
-
{ "kind": "heading", "value": "Choose quantity", "level": 3 },
|
|
3434
|
-
{
|
|
3435
|
-
"kind": "tooltip",
|
|
3436
|
-
"content": "Drag to adjust quantity",
|
|
3437
|
-
"child": {
|
|
3438
|
-
"kind": "slider",
|
|
3439
|
-
"binding": "qty",
|
|
3440
|
-
"min": 1,
|
|
3441
|
-
"max": 50,
|
|
3442
|
-
"label": "Quantity",
|
|
3443
|
-
"onChange": { "kind": "emit", "name": "qty-changed" }
|
|
3444
|
-
}
|
|
3445
|
-
},
|
|
3446
|
-
{ "kind": "toggle", "binding": "premium", "label": "Premium support" },
|
|
3447
|
-
{
|
|
3448
|
-
"kind": "button",
|
|
3449
|
-
"label": "Confirm",
|
|
3450
|
-
"onClick": { "kind": "message", "text": { "$bind": "qty" } }
|
|
3451
|
-
}
|
|
3452
|
-
]
|
|
3453
|
-
}
|
|
3454
|
-
}
|
|
3455
|
-
\`\`\`
|
|
3456
|
-
|
|
3457
|
-
### Rules
|
|
3458
|
-
|
|
3459
|
-
- Always set \`type\` to a built-in value above unless the app documented a custom type.
|
|
3460
|
-
- Prefer \`ui\` over \`html\` when actions must bubble to the host chat (\`message\`, \`emit\`).
|
|
3461
|
-
- Prefer \`question\` for simple A/B/C choices; use \`ui\` when you need sliders, toggles, drag, or multi-control layouts.
|
|
3462
|
-
- Keep \`data\` arrays reasonably small (charts/tables).
|
|
3463
|
-
|
|
3464
|
-
### After calling an artifact tool (critical)
|
|
3465
|
-
|
|
3466
|
-
When you call a tool that returns an artifact (\`make_chart\`, \`ask_question\`, \`show_table\`, \`show_html\`, \`make_ui_demo\`, etc.):
|
|
3467
|
-
|
|
3468
|
-
1. **Do not** paste, quote, paraphrase as JSON, or fence the tool return value in your assistant message. The chat UI already renders it from the tool result.
|
|
3469
|
-
2. **Do not** emit a matching \`\`\`timbal-artifact\`\`\` block for the same payload \u2014 pick **one** channel (tool result only).
|
|
3470
|
-
3. Your follow-up text should be **empty**, or at most **one short sentence** (e.g. "Pick an option above." / "Try the controls."). Never include \`type\`, \`options\`, \`data\`, or dict/JSON syntax.
|
|
3471
|
-
4. Treat the widget as visible to the user; refer to it as "above" / "the chart" / "the choices" \u2014 never reproduce its contents.
|
|
3472
|
-
`.trim();
|
|
3473
|
-
|
|
3474
|
-
// src/index.ts
|
|
3475
|
-
import {
|
|
3476
|
-
ThreadPrimitive as ThreadPrimitive2,
|
|
3477
|
-
MessagePrimitive as MessagePrimitive3,
|
|
3478
|
-
ComposerPrimitive as ComposerPrimitive4,
|
|
3479
|
-
ActionBarPrimitive as ActionBarPrimitive2,
|
|
3480
|
-
AssistantRuntimeProvider as AssistantRuntimeProvider2,
|
|
3481
|
-
useThread,
|
|
3482
|
-
useThreadRuntime as useThreadRuntime4,
|
|
3483
|
-
useMessageRuntime,
|
|
3484
|
-
useComposerRuntime as useComposerRuntime2
|
|
3485
|
-
} from "@assistant-ui/react";
|
|
3955
|
+
// src/components/workforce-selector.tsx
|
|
3956
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
3957
|
+
import { jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3958
|
+
var WorkforceSelector = ({
|
|
3959
|
+
workforces,
|
|
3960
|
+
value,
|
|
3961
|
+
onChange,
|
|
3962
|
+
hideWhenSingle = true,
|
|
3963
|
+
className,
|
|
3964
|
+
placeholder = "Select agent"
|
|
3965
|
+
}) => {
|
|
3966
|
+
if (workforces.length === 0) return null;
|
|
3967
|
+
if (hideWhenSingle && workforces.length === 1) return null;
|
|
3968
|
+
return /* @__PURE__ */ jsxs16(
|
|
3969
|
+
"div",
|
|
3970
|
+
{
|
|
3971
|
+
className: cn(
|
|
3972
|
+
"aui-workforce-selector relative inline-flex items-center",
|
|
3973
|
+
studioTopbarPillHeightClass,
|
|
3974
|
+
studioSecondaryChromeClass,
|
|
3975
|
+
"rounded-full",
|
|
3976
|
+
className
|
|
3977
|
+
),
|
|
3978
|
+
children: [
|
|
3979
|
+
/* @__PURE__ */ jsxs16(
|
|
3980
|
+
"select",
|
|
3981
|
+
{
|
|
3982
|
+
className: "aui-workforce-selector-input h-full cursor-pointer appearance-none rounded-full border-none bg-transparent pr-8 pl-3.5 text-sm font-medium text-foreground outline-none focus:outline-none",
|
|
3983
|
+
value,
|
|
3984
|
+
onChange: (e) => onChange(e.target.value),
|
|
3985
|
+
"aria-label": placeholder,
|
|
3986
|
+
children: [
|
|
3987
|
+
!value && /* @__PURE__ */ jsx29("option", { value: "", children: placeholder }),
|
|
3988
|
+
workforces.map((w) => {
|
|
3989
|
+
const id = idOf(w);
|
|
3990
|
+
return /* @__PURE__ */ jsx29("option", { value: id, children: w.name ?? id }, id);
|
|
3991
|
+
})
|
|
3992
|
+
]
|
|
3993
|
+
}
|
|
3994
|
+
),
|
|
3995
|
+
/* @__PURE__ */ jsx29(
|
|
3996
|
+
ChevronDownIcon,
|
|
3997
|
+
{
|
|
3998
|
+
className: "aui-workforce-selector-icon pointer-events-none absolute right-3 size-3.5 text-muted-foreground/70",
|
|
3999
|
+
"aria-hidden": true
|
|
4000
|
+
}
|
|
4001
|
+
)
|
|
4002
|
+
]
|
|
4003
|
+
}
|
|
4004
|
+
);
|
|
4005
|
+
};
|
|
4006
|
+
function idOf(item) {
|
|
4007
|
+
return item.id ?? item.uid ?? item.name ?? "";
|
|
4008
|
+
}
|
|
3486
4009
|
|
|
3487
4010
|
// src/hooks/use-workforces.ts
|
|
3488
|
-
import { useEffect as
|
|
4011
|
+
import { useEffect as useEffect6, useMemo as useMemo7, useRef as useRef2, useState as useState8 } from "react";
|
|
3489
4012
|
function useWorkforces(options = {}) {
|
|
3490
|
-
const { baseUrl = "/api", fetch: fetchFn, pickInitial } = options;
|
|
4013
|
+
const { baseUrl = "/api", fetch: fetchFn, pickInitial, enabled = true } = options;
|
|
3491
4014
|
const [workforces, setWorkforces] = useState8([]);
|
|
3492
4015
|
const [selectedId, setSelectedId] = useState8("");
|
|
3493
|
-
const [isLoading, setIsLoading] = useState8(
|
|
4016
|
+
const [isLoading, setIsLoading] = useState8(enabled);
|
|
3494
4017
|
const [error, setError] = useState8(null);
|
|
3495
4018
|
const fetchFnRef = useRef2(fetchFn ?? authFetch);
|
|
3496
|
-
|
|
4019
|
+
useEffect6(() => {
|
|
3497
4020
|
fetchFnRef.current = fetchFn ?? authFetch;
|
|
3498
4021
|
}, [fetchFn]);
|
|
3499
4022
|
const pickInitialRef = useRef2(pickInitial);
|
|
3500
|
-
|
|
4023
|
+
useEffect6(() => {
|
|
3501
4024
|
pickInitialRef.current = pickInitial;
|
|
3502
4025
|
}, [pickInitial]);
|
|
3503
|
-
const load =
|
|
4026
|
+
const load = useMemo7(() => {
|
|
3504
4027
|
return async () => {
|
|
4028
|
+
if (!enabled) {
|
|
4029
|
+
setIsLoading(false);
|
|
4030
|
+
return;
|
|
4031
|
+
}
|
|
3505
4032
|
setIsLoading(true);
|
|
3506
4033
|
setError(null);
|
|
3507
4034
|
try {
|
|
@@ -3510,9 +4037,9 @@ function useWorkforces(options = {}) {
|
|
|
3510
4037
|
const data = await res.json();
|
|
3511
4038
|
setWorkforces(data);
|
|
3512
4039
|
setSelectedId((current) => {
|
|
3513
|
-
if (current && data.some((w) =>
|
|
4040
|
+
if (current && data.some((w) => idOf2(w) === current)) return current;
|
|
3514
4041
|
const initial = pickInitialRef.current?.(data) ?? data.find((w) => w.type === "agent") ?? data[0];
|
|
3515
|
-
return initial ?
|
|
4042
|
+
return initial ? idOf2(initial) : "";
|
|
3516
4043
|
});
|
|
3517
4044
|
} catch (err) {
|
|
3518
4045
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -3520,12 +4047,12 @@ function useWorkforces(options = {}) {
|
|
|
3520
4047
|
setIsLoading(false);
|
|
3521
4048
|
}
|
|
3522
4049
|
};
|
|
3523
|
-
}, [baseUrl]);
|
|
3524
|
-
|
|
4050
|
+
}, [baseUrl, enabled]);
|
|
4051
|
+
useEffect6(() => {
|
|
3525
4052
|
load();
|
|
3526
4053
|
}, [load]);
|
|
3527
|
-
const selected =
|
|
3528
|
-
() => workforces.find((w) =>
|
|
4054
|
+
const selected = useMemo7(
|
|
4055
|
+
() => workforces.find((w) => idOf2(w) === selectedId),
|
|
3529
4056
|
[workforces, selectedId]
|
|
3530
4057
|
);
|
|
3531
4058
|
return {
|
|
@@ -3538,49 +4065,53 @@ function useWorkforces(options = {}) {
|
|
|
3538
4065
|
refresh: load
|
|
3539
4066
|
};
|
|
3540
4067
|
}
|
|
3541
|
-
function
|
|
4068
|
+
function idOf2(item) {
|
|
3542
4069
|
return item.id ?? item.uid ?? item.name ?? "";
|
|
3543
4070
|
}
|
|
3544
4071
|
|
|
3545
|
-
// src/
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
var
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
4072
|
+
// src/design/tokens.ts
|
|
4073
|
+
var SIDEBAR_WIDTH_PX = 224;
|
|
4074
|
+
var SIDEBAR_WIDTH_COLLAPSED_PX = 52;
|
|
4075
|
+
var SIDEBAR_MOBILE_PX = 272;
|
|
4076
|
+
var SIDEBAR_GAP_PX = 12;
|
|
4077
|
+
var SIDEBAR_CONTENT_GAP_PX = 8;
|
|
4078
|
+
var TOPBAR_GAP_PX = 8;
|
|
4079
|
+
var TOPBAR_HEIGHT_PX = 48;
|
|
4080
|
+
var PILL_HEIGHT_PX = 40;
|
|
4081
|
+
var SIDEBAR_INSET_PX_EXPANDED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
4082
|
+
var SIDEBAR_INSET_PX_COLLAPSED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_COLLAPSED_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
4083
|
+
var px = (n) => `${n / 16}rem`;
|
|
4084
|
+
var SIDEBAR_WIDTH = px(SIDEBAR_WIDTH_PX);
|
|
4085
|
+
var SIDEBAR_WIDTH_COLLAPSED = px(SIDEBAR_WIDTH_COLLAPSED_PX);
|
|
4086
|
+
var SIDEBAR_GAP = px(SIDEBAR_GAP_PX);
|
|
4087
|
+
var SIDEBAR_CONTENT_GAP = px(SIDEBAR_CONTENT_GAP_PX);
|
|
4088
|
+
var TOPBAR_GAP = px(TOPBAR_GAP_PX);
|
|
4089
|
+
var TOPBAR_HEIGHT = px(TOPBAR_HEIGHT_PX);
|
|
4090
|
+
var PILL_HEIGHT = px(PILL_HEIGHT_PX);
|
|
4091
|
+
var SIDEBAR_INSET_EXPANDED = px(SIDEBAR_INSET_PX_EXPANDED);
|
|
4092
|
+
var SIDEBAR_INSET_COLLAPSED = px(SIDEBAR_INSET_PX_COLLAPSED);
|
|
4093
|
+
var studioChromeShellStyle = {
|
|
4094
|
+
"--studio-topbar-gap": TOPBAR_GAP,
|
|
4095
|
+
"--studio-topbar-height": TOPBAR_HEIGHT,
|
|
4096
|
+
"--studio-chrome-pill-height": PILL_HEIGHT,
|
|
4097
|
+
"--studio-inset-top": `calc(${TOPBAR_GAP} + ${TOPBAR_HEIGHT})`,
|
|
4098
|
+
"--studio-sidebar-gap": SIDEBAR_GAP,
|
|
4099
|
+
"--studio-sidebar-width": SIDEBAR_WIDTH,
|
|
4100
|
+
"--studio-sidebar-width-collapsed": SIDEBAR_WIDTH_COLLAPSED,
|
|
4101
|
+
"--studio-sidebar-content-gap": SIDEBAR_CONTENT_GAP,
|
|
4102
|
+
"--studio-inset-left": SIDEBAR_INSET_EXPANDED,
|
|
4103
|
+
"--studio-inset-left-collapsed": SIDEBAR_INSET_COLLAPSED
|
|
4104
|
+
};
|
|
4105
|
+
var STORAGE_KEYS = {
|
|
4106
|
+
sidebarCollapsed: "timbal-studio-sidebar-collapsed"
|
|
4107
|
+
};
|
|
4108
|
+
var DOM_IDS = {
|
|
4109
|
+
sidebarRuntimeAnchor: "timbal-studio-sidebar-runtime-anchor",
|
|
4110
|
+
topbarBrandAnchor: "timbal-studio-topbar-brand-anchor"
|
|
3577
4111
|
};
|
|
3578
|
-
function idOf2(item) {
|
|
3579
|
-
return item.id ?? item.uid ?? item.name ?? "";
|
|
3580
|
-
}
|
|
3581
4112
|
|
|
3582
4113
|
// src/components/chat-shell.tsx
|
|
3583
|
-
import {
|
|
4114
|
+
import { jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3584
4115
|
var TimbalChatShell = ({
|
|
3585
4116
|
workforceId,
|
|
3586
4117
|
brand,
|
|
@@ -3592,54 +4123,62 @@ var TimbalChatShell = ({
|
|
|
3592
4123
|
fetch: fetch2,
|
|
3593
4124
|
...chatProps
|
|
3594
4125
|
}) => {
|
|
3595
|
-
const {
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
} = useWorkforces({ baseUrl, fetch: fetch2 });
|
|
4126
|
+
const { workforces, selectedId, setSelectedId } = useWorkforces({
|
|
4127
|
+
baseUrl,
|
|
4128
|
+
fetch: fetch2
|
|
4129
|
+
});
|
|
3600
4130
|
const effectiveId = workforceId ?? selectedId;
|
|
3601
4131
|
const showSelector = !hideWorkforceSelector && !workforceId && workforces.length > 0;
|
|
3602
|
-
return /* @__PURE__ */
|
|
4132
|
+
return /* @__PURE__ */ jsxs17(
|
|
3603
4133
|
"div",
|
|
3604
4134
|
{
|
|
3605
4135
|
className: cn(
|
|
3606
|
-
"aui-chat-shell flex h-
|
|
4136
|
+
"aui-chat-shell relative flex h-dvh flex-col overflow-hidden bg-background",
|
|
3607
4137
|
className
|
|
3608
4138
|
),
|
|
4139
|
+
style: studioChromeShellStyle,
|
|
3609
4140
|
children: [
|
|
3610
|
-
/* @__PURE__ */
|
|
4141
|
+
/* @__PURE__ */ jsx30(
|
|
4142
|
+
"div",
|
|
4143
|
+
{
|
|
4144
|
+
className: cn(
|
|
4145
|
+
"pointer-events-none absolute inset-0 z-0",
|
|
4146
|
+
studioPlaygroundGradientClass
|
|
4147
|
+
),
|
|
4148
|
+
"aria-hidden": true
|
|
4149
|
+
}
|
|
4150
|
+
),
|
|
4151
|
+
/* @__PURE__ */ jsxs17(
|
|
3611
4152
|
"header",
|
|
3612
4153
|
{
|
|
3613
4154
|
className: cn(
|
|
3614
|
-
"aui-chat-shell-header flex shrink-0 items-center justify-between
|
|
4155
|
+
"aui-chat-shell-header relative z-10 flex shrink-0 items-center justify-between px-4 pt-[var(--studio-topbar-gap)] pb-2",
|
|
3615
4156
|
headerClassName
|
|
3616
4157
|
),
|
|
4158
|
+
style: { minHeight: "var(--studio-topbar-height)" },
|
|
3617
4159
|
children: [
|
|
3618
|
-
/* @__PURE__ */
|
|
4160
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
3619
4161
|
brand,
|
|
3620
|
-
showSelector && /* @__PURE__ */
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
}
|
|
3629
|
-
)
|
|
3630
|
-
] })
|
|
4162
|
+
showSelector && /* @__PURE__ */ jsx30(
|
|
4163
|
+
WorkforceSelector,
|
|
4164
|
+
{
|
|
4165
|
+
workforces,
|
|
4166
|
+
value: selectedId,
|
|
4167
|
+
onChange: setSelectedId
|
|
4168
|
+
}
|
|
4169
|
+
)
|
|
3631
4170
|
] }),
|
|
3632
|
-
/* @__PURE__ */
|
|
4171
|
+
/* @__PURE__ */ jsx30("div", { className: "flex shrink-0 items-center gap-1", children: headerActions })
|
|
3633
4172
|
]
|
|
3634
4173
|
}
|
|
3635
4174
|
),
|
|
3636
|
-
/* @__PURE__ */
|
|
4175
|
+
/* @__PURE__ */ jsx30(
|
|
3637
4176
|
TimbalChat,
|
|
3638
4177
|
{
|
|
3639
4178
|
workforceId: effectiveId,
|
|
3640
4179
|
baseUrl,
|
|
3641
4180
|
fetch: fetch2,
|
|
3642
|
-
className: "min-h-0 flex-1",
|
|
4181
|
+
className: "relative z-10 min-h-0 flex-1 bg-transparent",
|
|
3643
4182
|
...chatProps
|
|
3644
4183
|
},
|
|
3645
4184
|
effectiveId
|
|
@@ -3649,15 +4188,250 @@ var TimbalChatShell = ({
|
|
|
3649
4188
|
);
|
|
3650
4189
|
};
|
|
3651
4190
|
|
|
4191
|
+
// src/components/studio/studio-shell.tsx
|
|
4192
|
+
import {
|
|
4193
|
+
useCallback as useCallback8,
|
|
4194
|
+
useEffect as useEffect10,
|
|
4195
|
+
useMemo as useMemo9,
|
|
4196
|
+
useState as useState13
|
|
4197
|
+
} from "react";
|
|
4198
|
+
import { Menu } from "lucide-react";
|
|
4199
|
+
import { motion as motion10, useReducedMotion as useReducedMotion6 } from "motion/react";
|
|
4200
|
+
|
|
4201
|
+
// src/design/sidebar-motion.ts
|
|
4202
|
+
var STUDIO_SIDEBAR_EASE_ENTER = [0, 0, 0.2, 1];
|
|
4203
|
+
var STUDIO_SIDEBAR_EASE_EXIT = [0.4, 0, 1, 1];
|
|
4204
|
+
var STUDIO_SIDEBAR_EASE = [0.16, 1, 0.3, 1];
|
|
4205
|
+
var STUDIO_SIDEBAR_ENTRIES_OUT_S = 0.1;
|
|
4206
|
+
var STUDIO_SIDEBAR_WIDTH_S = 0.17;
|
|
4207
|
+
var STUDIO_SIDEBAR_ENTRY_ITEM_IN_S = 0.18;
|
|
4208
|
+
var STUDIO_SIDEBAR_STAGGER_S = 0.03;
|
|
4209
|
+
var STUDIO_SIDEBAR_EXPAND_REVEAL_FRAC = 0.5;
|
|
4210
|
+
var STUDIO_SIDEBAR_CONTENT_NUDGE_PX = 6;
|
|
4211
|
+
var studioSidebarEntriesContainerVariants = {
|
|
4212
|
+
hidden: {
|
|
4213
|
+
opacity: 0,
|
|
4214
|
+
transition: {
|
|
4215
|
+
duration: STUDIO_SIDEBAR_ENTRIES_OUT_S,
|
|
4216
|
+
ease: STUDIO_SIDEBAR_EASE_EXIT,
|
|
4217
|
+
staggerChildren: 0
|
|
4218
|
+
}
|
|
4219
|
+
},
|
|
4220
|
+
visible: {
|
|
4221
|
+
opacity: 1,
|
|
4222
|
+
transition: {
|
|
4223
|
+
duration: 0.06,
|
|
4224
|
+
ease: STUDIO_SIDEBAR_EASE_ENTER,
|
|
4225
|
+
staggerChildren: STUDIO_SIDEBAR_STAGGER_S,
|
|
4226
|
+
delayChildren: 0.02
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
};
|
|
4230
|
+
var studioSidebarEntryItemVariants = {
|
|
4231
|
+
hidden: {
|
|
4232
|
+
opacity: 0,
|
|
4233
|
+
x: -STUDIO_SIDEBAR_CONTENT_NUDGE_PX,
|
|
4234
|
+
scale: 0.99
|
|
4235
|
+
},
|
|
4236
|
+
visible: {
|
|
4237
|
+
opacity: 1,
|
|
4238
|
+
x: 0,
|
|
4239
|
+
scale: 1,
|
|
4240
|
+
transition: {
|
|
4241
|
+
duration: STUDIO_SIDEBAR_ENTRY_ITEM_IN_S,
|
|
4242
|
+
ease: STUDIO_SIDEBAR_EASE_ENTER
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4245
|
+
};
|
|
4246
|
+
function studioSidebarEntriesTransition(visible, reduced) {
|
|
4247
|
+
if (reduced) return { duration: 0.01 };
|
|
4248
|
+
return visible ? { duration: 0.06, ease: STUDIO_SIDEBAR_EASE_ENTER } : { duration: STUDIO_SIDEBAR_ENTRIES_OUT_S, ease: STUDIO_SIDEBAR_EASE_EXIT };
|
|
4249
|
+
}
|
|
4250
|
+
function studioSidebarWidthTransition(reduced, direction = "collapse") {
|
|
4251
|
+
if (reduced) return { duration: 0.01 };
|
|
4252
|
+
return {
|
|
4253
|
+
duration: direction === "expand" ? STUDIO_SIDEBAR_WIDTH_S : STUDIO_SIDEBAR_WIDTH_S * 0.94,
|
|
4254
|
+
ease: direction === "expand" ? STUDIO_SIDEBAR_EASE_ENTER : STUDIO_SIDEBAR_EASE_EXIT
|
|
4255
|
+
};
|
|
4256
|
+
}
|
|
4257
|
+
function studioSidebarDrawerTransition(reduced) {
|
|
4258
|
+
if (reduced) return { duration: 0.01 };
|
|
4259
|
+
return {
|
|
4260
|
+
duration: 0.22,
|
|
4261
|
+
ease: STUDIO_SIDEBAR_EASE
|
|
4262
|
+
};
|
|
4263
|
+
}
|
|
4264
|
+
function studioSidebarBackdropTransition(reduced) {
|
|
4265
|
+
if (reduced) return { duration: 0.01 };
|
|
4266
|
+
return { duration: 0.16, ease: STUDIO_SIDEBAR_EASE_EXIT };
|
|
4267
|
+
}
|
|
4268
|
+
|
|
4269
|
+
// src/hooks/use-sidebar-collapse-phase.ts
|
|
4270
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef3, useState as useState9 } from "react";
|
|
4271
|
+
var WIDTH_OVERLAP_FRAC = 0.7;
|
|
4272
|
+
function useSidebarCollapsePhase(collapsed, reducedMotion) {
|
|
4273
|
+
const [widthCollapsed, setWidthCollapsed] = useState9(collapsed);
|
|
4274
|
+
const [entriesVisible, setEntriesVisible] = useState9(true);
|
|
4275
|
+
const collapsedTarget = useRef3(collapsed);
|
|
4276
|
+
const isFirstRender = useRef3(true);
|
|
4277
|
+
const widthTimerRef = useRef3(null);
|
|
4278
|
+
const revealTimerRef = useRef3(null);
|
|
4279
|
+
useEffect7(() => {
|
|
4280
|
+
collapsedTarget.current = collapsed;
|
|
4281
|
+
}, [collapsed]);
|
|
4282
|
+
const clearWidthTimer = () => {
|
|
4283
|
+
if (widthTimerRef.current !== null) {
|
|
4284
|
+
clearTimeout(widthTimerRef.current);
|
|
4285
|
+
widthTimerRef.current = null;
|
|
4286
|
+
}
|
|
4287
|
+
};
|
|
4288
|
+
const clearRevealTimer = () => {
|
|
4289
|
+
if (revealTimerRef.current !== null) {
|
|
4290
|
+
clearTimeout(revealTimerRef.current);
|
|
4291
|
+
revealTimerRef.current = null;
|
|
4292
|
+
}
|
|
4293
|
+
};
|
|
4294
|
+
const applyWidthTarget = useCallback4(() => {
|
|
4295
|
+
const willExpand = !collapsedTarget.current;
|
|
4296
|
+
setWidthCollapsed(collapsedTarget.current);
|
|
4297
|
+
clearRevealTimer();
|
|
4298
|
+
if (willExpand && !reducedMotion) {
|
|
4299
|
+
revealTimerRef.current = setTimeout(
|
|
4300
|
+
() => setEntriesVisible(true),
|
|
4301
|
+
STUDIO_SIDEBAR_WIDTH_S * 1e3 * STUDIO_SIDEBAR_EXPAND_REVEAL_FRAC
|
|
4302
|
+
);
|
|
4303
|
+
}
|
|
4304
|
+
}, [reducedMotion]);
|
|
4305
|
+
useEffect7(() => {
|
|
4306
|
+
clearWidthTimer();
|
|
4307
|
+
clearRevealTimer();
|
|
4308
|
+
if (reducedMotion) {
|
|
4309
|
+
setWidthCollapsed(collapsed);
|
|
4310
|
+
setEntriesVisible(true);
|
|
4311
|
+
return;
|
|
4312
|
+
}
|
|
4313
|
+
if (isFirstRender.current) {
|
|
4314
|
+
isFirstRender.current = false;
|
|
4315
|
+
setWidthCollapsed(collapsed);
|
|
4316
|
+
setEntriesVisible(true);
|
|
4317
|
+
return;
|
|
4318
|
+
}
|
|
4319
|
+
setEntriesVisible(false);
|
|
4320
|
+
widthTimerRef.current = setTimeout(
|
|
4321
|
+
applyWidthTarget,
|
|
4322
|
+
STUDIO_SIDEBAR_ENTRIES_OUT_S * 1e3 * WIDTH_OVERLAP_FRAC
|
|
4323
|
+
);
|
|
4324
|
+
return () => {
|
|
4325
|
+
clearWidthTimer();
|
|
4326
|
+
clearRevealTimer();
|
|
4327
|
+
};
|
|
4328
|
+
}, [collapsed, reducedMotion, applyWidthTarget]);
|
|
4329
|
+
const onEntriesBlurOutComplete = useCallback4(() => {
|
|
4330
|
+
applyWidthTarget();
|
|
4331
|
+
}, [applyWidthTarget]);
|
|
4332
|
+
const onPanelWidthComplete = useCallback4(() => {
|
|
4333
|
+
clearRevealTimer();
|
|
4334
|
+
setEntriesVisible(true);
|
|
4335
|
+
}, []);
|
|
4336
|
+
const isCollapsedRail = widthCollapsed;
|
|
4337
|
+
return {
|
|
4338
|
+
widthCollapsed,
|
|
4339
|
+
isCollapsedRail,
|
|
4340
|
+
entriesVisible,
|
|
4341
|
+
onEntriesBlurOutComplete,
|
|
4342
|
+
onPanelWidthComplete
|
|
4343
|
+
};
|
|
4344
|
+
}
|
|
4345
|
+
|
|
4346
|
+
// src/components/studio/sidebar-backdrop.tsx
|
|
4347
|
+
import { AnimatePresence as AnimatePresence2, motion as motion5, useReducedMotion as useReducedMotion2 } from "motion/react";
|
|
4348
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
4349
|
+
var StudioSidebarBackdrop = ({
|
|
4350
|
+
open,
|
|
4351
|
+
onClose
|
|
4352
|
+
}) => {
|
|
4353
|
+
const reducedMotion = useReducedMotion2();
|
|
4354
|
+
return /* @__PURE__ */ jsx31(AnimatePresence2, { children: open ? /* @__PURE__ */ jsx31(
|
|
4355
|
+
motion5.button,
|
|
4356
|
+
{
|
|
4357
|
+
type: "button",
|
|
4358
|
+
className: "fixed inset-0 z-40 bg-foreground/30 backdrop-blur-[2px] md:hidden",
|
|
4359
|
+
"aria-label": "Close menu",
|
|
4360
|
+
initial: { opacity: 0 },
|
|
4361
|
+
animate: { opacity: 1 },
|
|
4362
|
+
exit: { opacity: 0 },
|
|
4363
|
+
transition: studioSidebarBackdropTransition(!!reducedMotion),
|
|
4364
|
+
onClick: onClose
|
|
4365
|
+
}
|
|
4366
|
+
) : null });
|
|
4367
|
+
};
|
|
4368
|
+
|
|
4369
|
+
// src/components/studio/sidebar-context.tsx
|
|
4370
|
+
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
4371
|
+
var StudioSidebarContext = createContext4({
|
|
4372
|
+
collapsed: false,
|
|
4373
|
+
isMobile: false,
|
|
4374
|
+
isCollapsedRail: false,
|
|
4375
|
+
iconOnlyLayout: false
|
|
4376
|
+
});
|
|
4377
|
+
function useStudioSidebarLayout() {
|
|
4378
|
+
return useContext4(StudioSidebarContext);
|
|
4379
|
+
}
|
|
4380
|
+
|
|
4381
|
+
// src/components/studio/sidebar.tsx
|
|
4382
|
+
import {
|
|
4383
|
+
useCallback as useCallback6,
|
|
4384
|
+
useEffect as useEffect9,
|
|
4385
|
+
useMemo as useMemo8,
|
|
4386
|
+
useState as useState11
|
|
4387
|
+
} from "react";
|
|
4388
|
+
import { motion as motion8, useReducedMotion as useReducedMotion5 } from "motion/react";
|
|
4389
|
+
|
|
4390
|
+
// src/components/studio/sidebar-entries.tsx
|
|
4391
|
+
import { motion as motion6, useReducedMotion as useReducedMotion3 } from "motion/react";
|
|
4392
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
4393
|
+
var StudioSidebarEntries = ({
|
|
4394
|
+
visible,
|
|
4395
|
+
onBlurOutComplete,
|
|
4396
|
+
children,
|
|
4397
|
+
className
|
|
4398
|
+
}) => {
|
|
4399
|
+
const reducedMotion = useReducedMotion3();
|
|
4400
|
+
if (reducedMotion) {
|
|
4401
|
+
return visible ? /* @__PURE__ */ jsx32("div", { className: cn("flex min-h-0 flex-1 flex-col", className), children }) : null;
|
|
4402
|
+
}
|
|
4403
|
+
return /* @__PURE__ */ jsx32(
|
|
4404
|
+
motion6.div,
|
|
4405
|
+
{
|
|
4406
|
+
className: cn("flex min-h-0 flex-1 flex-col", className),
|
|
4407
|
+
initial: false,
|
|
4408
|
+
variants: studioSidebarEntriesContainerVariants,
|
|
4409
|
+
animate: visible ? "visible" : "hidden",
|
|
4410
|
+
transition: studioSidebarEntriesTransition(visible, false),
|
|
4411
|
+
onAnimationComplete: (definition) => {
|
|
4412
|
+
if (definition === "hidden") {
|
|
4413
|
+
onBlurOutComplete();
|
|
4414
|
+
}
|
|
4415
|
+
},
|
|
4416
|
+
style: { pointerEvents: visible ? "auto" : "none" },
|
|
4417
|
+
"aria-hidden": !visible,
|
|
4418
|
+
children
|
|
4419
|
+
}
|
|
4420
|
+
);
|
|
4421
|
+
};
|
|
4422
|
+
|
|
4423
|
+
// src/components/studio/sidebar-footer.tsx
|
|
4424
|
+
import { LogOut } from "lucide-react";
|
|
4425
|
+
|
|
3652
4426
|
// src/auth/provider.tsx
|
|
3653
4427
|
import {
|
|
3654
|
-
createContext as
|
|
3655
|
-
useCallback as
|
|
3656
|
-
useContext as
|
|
3657
|
-
useEffect as
|
|
3658
|
-
useState as
|
|
4428
|
+
createContext as createContext5,
|
|
4429
|
+
useCallback as useCallback5,
|
|
4430
|
+
useContext as useContext5,
|
|
4431
|
+
useEffect as useEffect8,
|
|
4432
|
+
useState as useState10
|
|
3659
4433
|
} from "react";
|
|
3660
|
-
import { jsx as
|
|
4434
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
3661
4435
|
function isInsideIframe() {
|
|
3662
4436
|
try {
|
|
3663
4437
|
return typeof window !== "undefined" && window.self !== window.top;
|
|
@@ -3665,22 +4439,26 @@ function isInsideIframe() {
|
|
|
3665
4439
|
return true;
|
|
3666
4440
|
}
|
|
3667
4441
|
}
|
|
3668
|
-
var SessionContext =
|
|
4442
|
+
var SessionContext = createContext5(void 0);
|
|
3669
4443
|
var useSession = () => {
|
|
3670
|
-
const context =
|
|
4444
|
+
const context = useContext5(SessionContext);
|
|
3671
4445
|
if (context === void 0) {
|
|
3672
4446
|
throw new Error("useSession must be used within a SessionProvider");
|
|
3673
4447
|
}
|
|
3674
4448
|
return context;
|
|
3675
4449
|
};
|
|
4450
|
+
var useOptionalSession = () => {
|
|
4451
|
+
const context = useContext5(SessionContext);
|
|
4452
|
+
return context ?? null;
|
|
4453
|
+
};
|
|
3676
4454
|
var SessionProvider = ({
|
|
3677
4455
|
children,
|
|
3678
4456
|
enabled = true
|
|
3679
4457
|
}) => {
|
|
3680
|
-
const [user, setUser] =
|
|
3681
|
-
const [loading, setLoading] =
|
|
3682
|
-
const [embedded] =
|
|
3683
|
-
|
|
4458
|
+
const [user, setUser] = useState10(null);
|
|
4459
|
+
const [loading, setLoading] = useState10(enabled);
|
|
4460
|
+
const [embedded] = useState10(isInsideIframe);
|
|
4461
|
+
useEffect8(() => {
|
|
3684
4462
|
if (!enabled) {
|
|
3685
4463
|
setLoading(false);
|
|
3686
4464
|
return;
|
|
@@ -3741,7 +4519,7 @@ var SessionProvider = ({
|
|
|
3741
4519
|
messageCleanup?.();
|
|
3742
4520
|
};
|
|
3743
4521
|
}, [enabled, embedded]);
|
|
3744
|
-
const logout =
|
|
4522
|
+
const logout = useCallback5(() => {
|
|
3745
4523
|
clearTokens();
|
|
3746
4524
|
setUser(null);
|
|
3747
4525
|
const returnTo = encodeURIComponent(
|
|
@@ -3751,7 +4529,7 @@ var SessionProvider = ({
|
|
|
3751
4529
|
() => window.location.href = `/api/auth/login?return_to=${returnTo}`
|
|
3752
4530
|
);
|
|
3753
4531
|
}, []);
|
|
3754
|
-
return /* @__PURE__ */
|
|
4532
|
+
return /* @__PURE__ */ jsx33(
|
|
3755
4533
|
SessionContext.Provider,
|
|
3756
4534
|
{
|
|
3757
4535
|
value: {
|
|
@@ -3766,30 +4544,1169 @@ var SessionProvider = ({
|
|
|
3766
4544
|
);
|
|
3767
4545
|
};
|
|
3768
4546
|
|
|
3769
|
-
// src/
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
4547
|
+
// src/components/studio/sidebar-layout.ts
|
|
4548
|
+
function studioSidebarIconOnlyLayout(isMobile, isCollapsedRail) {
|
|
4549
|
+
if (isMobile) return false;
|
|
4550
|
+
return isCollapsedRail;
|
|
4551
|
+
}
|
|
4552
|
+
var studioSidebarCollapsedRailInsetClass = "box-border w-full px-1.5";
|
|
4553
|
+
var studioSidebarCollapsedRailChipRowClass = "flex w-full justify-center";
|
|
4554
|
+
function studioSidebarNavItemClasses(iconOnly, isActive) {
|
|
4555
|
+
if (iconOnly) {
|
|
4556
|
+
return cn(
|
|
4557
|
+
studioSidebarNavItemClass,
|
|
4558
|
+
studioSidebarNavItemLayout(true),
|
|
4559
|
+
isActive ? studioSidebarCollapsedRailItemActiveClass : studioSidebarCollapsedRailItemIdleClass
|
|
4560
|
+
);
|
|
4561
|
+
}
|
|
4562
|
+
return cn(
|
|
4563
|
+
studioSidebarNavItemClass,
|
|
4564
|
+
studioSidebarNavItemLayout(false),
|
|
4565
|
+
isActive ? studioSidebarNavItemActiveClass : studioSidebarNavItemIdleClass
|
|
4566
|
+
);
|
|
4567
|
+
}
|
|
4568
|
+
|
|
4569
|
+
// src/components/studio/sidebar-entry-motion.tsx
|
|
4570
|
+
import { motion as motion7, useReducedMotion as useReducedMotion4 } from "motion/react";
|
|
4571
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
4572
|
+
var StudioSidebarEntryMotion = ({
|
|
3773
4573
|
children,
|
|
3774
|
-
|
|
3775
|
-
enabled = true
|
|
4574
|
+
className
|
|
3776
4575
|
}) => {
|
|
3777
|
-
const
|
|
3778
|
-
if (
|
|
3779
|
-
return children;
|
|
3780
|
-
}
|
|
3781
|
-
if (loading) {
|
|
3782
|
-
return /* @__PURE__ */ jsx30("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ jsx30(Loader2, { className: "w-8 h-8 animate-spin" }) });
|
|
3783
|
-
}
|
|
3784
|
-
if (requireAuth && !isAuthenticated && !isEmbedded) {
|
|
3785
|
-
const returnTo = encodeURIComponent(
|
|
3786
|
-
window.location.pathname + window.location.search
|
|
3787
|
-
);
|
|
3788
|
-
window.location.href = `/api/auth/login?return_to=${returnTo}`;
|
|
3789
|
-
return null;
|
|
4576
|
+
const reducedMotion = useReducedMotion4();
|
|
4577
|
+
if (reducedMotion) {
|
|
4578
|
+
return /* @__PURE__ */ jsx34("div", { className, children });
|
|
3790
4579
|
}
|
|
3791
|
-
return children;
|
|
4580
|
+
return /* @__PURE__ */ jsx34(motion7.div, { variants: studioSidebarEntryItemVariants, className: cn(className), children });
|
|
4581
|
+
};
|
|
4582
|
+
|
|
4583
|
+
// src/components/studio/sidebar-tooltip.tsx
|
|
4584
|
+
import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4585
|
+
var StudioSidebarTooltip = ({
|
|
4586
|
+
label,
|
|
4587
|
+
enabled,
|
|
4588
|
+
children
|
|
4589
|
+
}) => {
|
|
4590
|
+
if (!enabled) return /* @__PURE__ */ jsx35(Fragment3, { children });
|
|
4591
|
+
return /* @__PURE__ */ jsxs18(Tooltip, { children: [
|
|
4592
|
+
/* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children }),
|
|
4593
|
+
/* @__PURE__ */ jsx35(TooltipContent, { side: "right", className: "text-xs", children: label })
|
|
4594
|
+
] });
|
|
3792
4595
|
};
|
|
4596
|
+
|
|
4597
|
+
// src/components/studio/sidebar-footer.tsx
|
|
4598
|
+
import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4599
|
+
function userInitials(name, email) {
|
|
4600
|
+
const fromName = name.trim().split(/\s+/).map((part) => part.charAt(0)).join("").slice(0, 2).toUpperCase();
|
|
4601
|
+
if (fromName) return fromName;
|
|
4602
|
+
return email.charAt(0).toUpperCase() || "?";
|
|
4603
|
+
}
|
|
4604
|
+
var StudioSidebarFooter = ({
|
|
4605
|
+
iconOnlyLayout,
|
|
4606
|
+
showTooltips,
|
|
4607
|
+
onSignOut,
|
|
4608
|
+
emptyCaption = null
|
|
4609
|
+
}) => {
|
|
4610
|
+
const session = useOptionalSession();
|
|
4611
|
+
const user = session?.user ?? null;
|
|
4612
|
+
const handleSignOut = () => {
|
|
4613
|
+
session?.logout();
|
|
4614
|
+
onSignOut?.();
|
|
4615
|
+
};
|
|
4616
|
+
return /* @__PURE__ */ jsx36(StudioSidebarEntryMotion, { children: /* @__PURE__ */ jsx36(
|
|
4617
|
+
"footer",
|
|
4618
|
+
{
|
|
4619
|
+
className: cn(
|
|
4620
|
+
"mt-auto w-full shrink-0 py-2.5",
|
|
4621
|
+
iconOnlyLayout ? studioSidebarCollapsedRailInsetClass : "px-2.5"
|
|
4622
|
+
),
|
|
4623
|
+
children: user ? /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2", children: [
|
|
4624
|
+
iconOnlyLayout ? /* @__PURE__ */ jsx36("div", { className: studioSidebarCollapsedRailChipRowClass, children: /* @__PURE__ */ jsxs19(Avatar, { size: "sm", className: "size-8", children: [
|
|
4625
|
+
user.user_photo_url ? /* @__PURE__ */ jsx36(AvatarImage, { src: user.user_photo_url, alt: user.user_name }) : null,
|
|
4626
|
+
/* @__PURE__ */ jsx36(AvatarFallback, { className: "text-[10px]", children: userInitials(user.user_name, user.user_email) })
|
|
4627
|
+
] }) }) : /* @__PURE__ */ jsxs19("div", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
4628
|
+
/* @__PURE__ */ jsxs19(Avatar, { size: "sm", children: [
|
|
4629
|
+
user.user_photo_url ? /* @__PURE__ */ jsx36(AvatarImage, { src: user.user_photo_url, alt: user.user_name }) : null,
|
|
4630
|
+
/* @__PURE__ */ jsx36(AvatarFallback, { children: userInitials(user.user_name, user.user_email) })
|
|
4631
|
+
] }),
|
|
4632
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0 flex-1", children: [
|
|
4633
|
+
/* @__PURE__ */ jsx36("p", { className: "truncate text-sm font-medium text-foreground", children: user.user_name }),
|
|
4634
|
+
/* @__PURE__ */ jsx36("p", { className: "truncate text-xs text-muted-foreground", children: user.user_email })
|
|
4635
|
+
] })
|
|
4636
|
+
] }),
|
|
4637
|
+
/* @__PURE__ */ jsx36(
|
|
4638
|
+
"div",
|
|
4639
|
+
{
|
|
4640
|
+
className: iconOnlyLayout ? studioSidebarCollapsedRailChipRowClass : void 0,
|
|
4641
|
+
children: /* @__PURE__ */ jsx36(StudioSidebarTooltip, { label: "Sign out", enabled: showTooltips, children: /* @__PURE__ */ jsxs19(
|
|
4642
|
+
"button",
|
|
4643
|
+
{
|
|
4644
|
+
type: "button",
|
|
4645
|
+
onClick: handleSignOut,
|
|
4646
|
+
className: cn(
|
|
4647
|
+
studioSidebarNavItemClasses(iconOnlyLayout, false),
|
|
4648
|
+
iconOnlyLayout && "inline-flex"
|
|
4649
|
+
),
|
|
4650
|
+
"aria-label": "Sign out",
|
|
4651
|
+
children: [
|
|
4652
|
+
/* @__PURE__ */ jsx36(LogOut, { className: "size-3.5 shrink-0" }),
|
|
4653
|
+
!iconOnlyLayout ? "Sign out" : null
|
|
4654
|
+
]
|
|
4655
|
+
}
|
|
4656
|
+
) })
|
|
4657
|
+
}
|
|
4658
|
+
)
|
|
4659
|
+
] }) : !iconOnlyLayout && emptyCaption ? /* @__PURE__ */ jsx36("p", { className: "px-1 text-xs text-muted-foreground", children: emptyCaption }) : null
|
|
4660
|
+
}
|
|
4661
|
+
) });
|
|
4662
|
+
};
|
|
4663
|
+
|
|
4664
|
+
// src/components/studio/sidebar-header.tsx
|
|
4665
|
+
import { ChevronLeft, ChevronRight, X } from "lucide-react";
|
|
4666
|
+
import { jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4667
|
+
var sidebarHeaderClass = "flex h-12 shrink-0 items-center px-2";
|
|
4668
|
+
var toggleButtonClass = cn(
|
|
4669
|
+
"flex shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors",
|
|
4670
|
+
"hover:bg-muted hover:text-foreground",
|
|
4671
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15"
|
|
4672
|
+
);
|
|
4673
|
+
var SidebarToggleButton = ({ ariaLabel, expanded, onClick, children }) => /* @__PURE__ */ jsx37(
|
|
4674
|
+
"button",
|
|
4675
|
+
{
|
|
4676
|
+
type: "button",
|
|
4677
|
+
onClick,
|
|
4678
|
+
className: cn(toggleButtonClass, "size-7"),
|
|
4679
|
+
"aria-label": ariaLabel,
|
|
4680
|
+
"aria-expanded": expanded,
|
|
4681
|
+
children
|
|
4682
|
+
}
|
|
4683
|
+
);
|
|
4684
|
+
var CollapsedBrandToggle = ({
|
|
4685
|
+
onExpand,
|
|
4686
|
+
brand
|
|
4687
|
+
}) => /* @__PURE__ */ jsx37("div", { className: studioSidebarCollapsedRailChipRowClass, children: /* @__PURE__ */ jsx37(StudioSidebarTooltip, { label: "Expand sidebar", enabled: true, children: /* @__PURE__ */ jsxs20(
|
|
4688
|
+
"button",
|
|
4689
|
+
{
|
|
4690
|
+
type: "button",
|
|
4691
|
+
onClick: onExpand,
|
|
4692
|
+
"aria-label": "Expand sidebar",
|
|
4693
|
+
"aria-expanded": false,
|
|
4694
|
+
className: cn(
|
|
4695
|
+
toggleButtonClass,
|
|
4696
|
+
"group relative inline-flex size-8 items-center justify-center overflow-hidden rounded-lg"
|
|
4697
|
+
),
|
|
4698
|
+
children: [
|
|
4699
|
+
/* @__PURE__ */ jsx37(
|
|
4700
|
+
"span",
|
|
4701
|
+
{
|
|
4702
|
+
"aria-hidden": true,
|
|
4703
|
+
className: cn(
|
|
4704
|
+
"pointer-events-none flex items-center justify-center",
|
|
4705
|
+
"transition-[opacity,transform] duration-200 ease-out",
|
|
4706
|
+
"group-hover:scale-90 group-hover:opacity-0"
|
|
4707
|
+
),
|
|
4708
|
+
children: brand
|
|
4709
|
+
}
|
|
4710
|
+
),
|
|
4711
|
+
/* @__PURE__ */ jsx37(
|
|
4712
|
+
ChevronRight,
|
|
4713
|
+
{
|
|
4714
|
+
"aria-hidden": true,
|
|
4715
|
+
className: cn(
|
|
4716
|
+
"pointer-events-none absolute inset-0 m-auto size-4",
|
|
4717
|
+
"opacity-0 transition-[opacity,transform] duration-200 ease-out",
|
|
4718
|
+
"group-hover:opacity-100"
|
|
4719
|
+
)
|
|
4720
|
+
}
|
|
4721
|
+
)
|
|
4722
|
+
]
|
|
4723
|
+
}
|
|
4724
|
+
) }) });
|
|
4725
|
+
var StudioSidebarHeader = ({
|
|
4726
|
+
isCollapsedRail,
|
|
4727
|
+
isMobile,
|
|
4728
|
+
mobileOpen,
|
|
4729
|
+
onToggle,
|
|
4730
|
+
brand
|
|
4731
|
+
}) => {
|
|
4732
|
+
if (isMobile) {
|
|
4733
|
+
return /* @__PURE__ */ jsxs20("header", { className: cn(sidebarHeaderClass, "justify-between gap-2 pr-2"), children: [
|
|
4734
|
+
brand,
|
|
4735
|
+
/* @__PURE__ */ jsx37(
|
|
4736
|
+
SidebarToggleButton,
|
|
4737
|
+
{
|
|
4738
|
+
ariaLabel: "Close menu",
|
|
4739
|
+
expanded: mobileOpen,
|
|
4740
|
+
onClick: onToggle,
|
|
4741
|
+
children: /* @__PURE__ */ jsx37(X, { className: "size-3.5" })
|
|
4742
|
+
}
|
|
4743
|
+
)
|
|
4744
|
+
] });
|
|
4745
|
+
}
|
|
4746
|
+
if (isCollapsedRail) {
|
|
4747
|
+
return /* @__PURE__ */ jsx37(
|
|
4748
|
+
"header",
|
|
4749
|
+
{
|
|
4750
|
+
className: cn(
|
|
4751
|
+
"flex h-12 shrink-0 items-center",
|
|
4752
|
+
studioSidebarCollapsedRailInsetClass
|
|
4753
|
+
),
|
|
4754
|
+
children: /* @__PURE__ */ jsx37(CollapsedBrandToggle, { onExpand: onToggle, brand })
|
|
4755
|
+
}
|
|
4756
|
+
);
|
|
4757
|
+
}
|
|
4758
|
+
return /* @__PURE__ */ jsxs20("header", { className: cn(sidebarHeaderClass, "justify-between gap-1 pr-2"), children: [
|
|
4759
|
+
brand,
|
|
4760
|
+
/* @__PURE__ */ jsx37(
|
|
4761
|
+
SidebarToggleButton,
|
|
4762
|
+
{
|
|
4763
|
+
ariaLabel: "Collapse sidebar",
|
|
4764
|
+
expanded: true,
|
|
4765
|
+
onClick: onToggle,
|
|
4766
|
+
children: /* @__PURE__ */ jsx37(ChevronLeft, { className: "size-4" })
|
|
4767
|
+
}
|
|
4768
|
+
)
|
|
4769
|
+
] });
|
|
4770
|
+
};
|
|
4771
|
+
|
|
4772
|
+
// src/components/studio/sidebar-workforce.ts
|
|
4773
|
+
function workforceItemId(w) {
|
|
4774
|
+
return w.id ?? w.uid ?? w.name ?? "";
|
|
4775
|
+
}
|
|
4776
|
+
function workforceItemLabel(w) {
|
|
4777
|
+
return w.name ?? workforceItemId(w);
|
|
4778
|
+
}
|
|
4779
|
+
function workforceItemInitial(w) {
|
|
4780
|
+
const label = workforceItemLabel(w);
|
|
4781
|
+
return label.charAt(0).toUpperCase() || "?";
|
|
4782
|
+
}
|
|
4783
|
+
|
|
4784
|
+
// src/components/studio/sidebar-nav.tsx
|
|
4785
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
4786
|
+
var StudioSidebarNav = ({
|
|
4787
|
+
workforces,
|
|
4788
|
+
selectedId,
|
|
4789
|
+
onSelect,
|
|
4790
|
+
iconOnlyLayout,
|
|
4791
|
+
showTooltips
|
|
4792
|
+
}) => {
|
|
4793
|
+
if (workforces.length === 0) return null;
|
|
4794
|
+
return /* @__PURE__ */ jsx38(
|
|
4795
|
+
"nav",
|
|
4796
|
+
{
|
|
4797
|
+
className: cn(
|
|
4798
|
+
"flex min-h-0 flex-1 flex-col overflow-y-auto py-1",
|
|
4799
|
+
iconOnlyLayout ? cn(studioSidebarCollapsedRailInsetClass, "gap-1") : "gap-0.5 px-2"
|
|
4800
|
+
),
|
|
4801
|
+
"aria-label": "Agents",
|
|
4802
|
+
children: workforces.map((w) => {
|
|
4803
|
+
const id = workforceItemId(w);
|
|
4804
|
+
const isActive = id === selectedId;
|
|
4805
|
+
const label = workforceItemLabel(w);
|
|
4806
|
+
return /* @__PURE__ */ jsx38(
|
|
4807
|
+
StudioSidebarEntryMotion,
|
|
4808
|
+
{
|
|
4809
|
+
className: iconOnlyLayout ? studioSidebarCollapsedRailChipRowClass : void 0,
|
|
4810
|
+
children: /* @__PURE__ */ jsx38(StudioSidebarTooltip, { label, enabled: showTooltips, children: /* @__PURE__ */ jsx38(
|
|
4811
|
+
"button",
|
|
4812
|
+
{
|
|
4813
|
+
type: "button",
|
|
4814
|
+
onClick: () => onSelect(id),
|
|
4815
|
+
"aria-pressed": isActive,
|
|
4816
|
+
"aria-label": label,
|
|
4817
|
+
className: cn(
|
|
4818
|
+
studioSidebarNavItemClasses(iconOnlyLayout, isActive),
|
|
4819
|
+
iconOnlyLayout && "inline-flex"
|
|
4820
|
+
),
|
|
4821
|
+
children: iconOnlyLayout ? /* @__PURE__ */ jsx38("span", { className: "text-xs font-semibold leading-none", children: workforceItemInitial(w) }) : /* @__PURE__ */ jsx38("span", { className: "min-w-0 truncate", children: label })
|
|
4822
|
+
}
|
|
4823
|
+
) })
|
|
4824
|
+
},
|
|
4825
|
+
id
|
|
4826
|
+
);
|
|
4827
|
+
})
|
|
4828
|
+
}
|
|
4829
|
+
);
|
|
4830
|
+
};
|
|
4831
|
+
|
|
4832
|
+
// src/components/studio/timbal-mark.tsx
|
|
4833
|
+
import { LiquidMetal } from "@paper-design/shaders-react";
|
|
4834
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
4835
|
+
var DEFAULT_SIZE = 64;
|
|
4836
|
+
var TRANSPARENT_BACK = "#00000000";
|
|
4837
|
+
var TIMBAL_SYMBOL_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAYAAAA8AXHiAAAH6ElEQVR4Aeyci7EcNRBFFxIBIgEygUiASCATyASIBOa4rFrZntmPPq1W93218o5nZyTd26dbmnX5fX3TjxyY4IDAmmCqurzdBJYomOKAwJpiqzoVWGJgigMCa4qt6lRgZWHAWKfAMjY8y3ACK0ukjXUKLGPDswwnsLJE2linwDI2PMtwAitLpI11Cixjw+/DxT4SWLHju0ydwHrP+p/euzzE1T8cKr492lsvgfWaXZj733Hp90fL9Pr1EPvn0QTWYcLoF8bS6Pdf/kjQAAnNv7RqVcW6do4q9ffxMe/HW5oXy323boF1zkvzEnDe3RZnS5X6fcRsBdbdRY6oTl1LAJ1s2NDdXaVq3QLr7kapUph8Pxv/iESiDVUqsG63sgQ0b1Rve/6QQEOrVG1DdrCGbFRrQzc5Zh9FlSKppkw5M1gYi8FTjHXaaalSJNTUKWYEC3P5spP3qeY667zsIadVqVpvNrCoUrTag+jHgIRm0z2ka7AGRpzqNG2jOnCeo7uiSi3RnQEszCVjydzRgfPaH1rRbFqlajMig0WVWmpubbThMRvzJVWq1hgVrFKlgKvWG/2YRHLxpBsNrOVLwCJySSBXT7qRwHKxBCwAiypFWzD09ZARwCpVysUScG318E+oUsv3Uleq3gPrqpd1512bO9GWsockqSYO0971zmBR/mnt6ve7k0RC87KvEV61bEewMNftEvCq8Q3XlSqF/obbbW/ZDSz2UWSs2yVgQvjQimb3VarWvgtYZCnm8uRXzz/6MXq3rM47gLXVEjCI9FKlqNCDurTtxjNYxdytloAB4aM6r65S3TK8grXtEtAZEZZ7Wmc362/3BlapUtsuAY0hDVGlau2ewApnbm30g+OyhySpHly210dewKL80/Zyr2+2JBKaQ+4hV4OFudtvVBv4KlUK/Q23+79lJVjso8jYUEvAk5CjFc0hq1StfQVYZCnm8uRXzyX6MXqbq/Nu5liDFX4JOAGgVCkq9MnHMU9ZgVXMDb8EfIYJ1TlNlaq1W4BFlcpoLss9rfY7zfFMsFSl0mD0pdBZYKXaqFa2so+iSpFU1el8hzPAwlgMzuQmeyl0k1ARdf/zrqiRYGGuq/+C9K4Zb11/v5g9JFCh/342+dEosDCWlslOljs0Z3vSfSnGvWCRpRmf+KhSGXW/BBUX9YCFuWQsmUtfGdo3h0g0q0odRjx6tYAFSFnNZXNOlX7kqT47HGgB67jtJnNv+nnkQCtYj/rUZ3LgFggsRdOTAwLLUzQCzUVgBQqmJykCy1M0As1FYAUKpicpAstTNALNRWAFCqYnKTPB8qRTczF2QGAZG55lOIGVJdLGOgWWseFZhhNYWSJtrFNgGRueZTiBlSXSM3We9C2wTkzRqX4HBFa/h+rhxAGBdWKKTvU7ILD6PVQPJw4IrBNTdKrfAYHV76F6OHFAYJ2Ysv+p9QoE1voYhJyBwAoZ1vWiBNb6GIScgcAKGdb1ogTW+hiEnIHAChnW9aIElk0M0o0isNKF3EawwLLxOd0oAitdyN8W/Ndxx9LfmnyMH/aFuX+EVXct7Lfjox+P9vZLFeu5ZcXcf59fGuYKKhRA8Xtmm0QJrGvbqFJd5l537foTKvN3xwzRf7y1vdKC9cSuUqW6zH0yhsePSaSfR0xMYH3qYvcS8Gl32/yNBPrqmC3vx1v/S2DdPRyyBNy72+aIKkUbOuEWsPg970MnsbizUqWGLAGLtbwzPNWpey91NWALWFd97Xh+qrmODSl7SJJqyjQzg0X5p00x1mmnJBKam79GeFVXRrAwd9oS8KrxC64rVQr904f3A9Z0qR8GYB9Fxk5bAj6M4usPtKJ5epWqZWcBiyzFXJ78av3Rj9G7pDpnAMt0CXBCaqlSVOglU4oMVjHXdAlYEsVPB6U6L6lS9TSigkWVWm5ubbTRMcs9zWi462GigaUqdR1r008igbVso2oasS8HYx9FlSKpvvx00ZkHYC2aUduwGIvBbXfveRd7KXSTUO4U7A4W5g79V3l3ETqfEHtIoEL/+RWLz+4MFsbSFltoOjzLHZrdP+nuCBZZmvGJjyVvG927gVWWADLXtFQsHAytVKmt9pC7gEWVwlz3S8BgANG9TZWqte8AVqlSmFzPPfoxiUSbrnPGAJ7BKkuAqtSMyE/u0ytYW21UB8aIfRRViqQa2K19Vx7BwlgMtndj3Ygs8+gmodbNYuDInsDCXH3ZOTC4K7vyAhbZSlvphfXYLHdoDrmHXA0WVWrLx+lOCnnSDa17JViYS8aSuZ1x2uZ2tKL5cZXaRs71RFeARZVKYe5ntrMxD12lar3WYJUqBVz1PKIfk0ipnnStwEqzBHyWISRQxifdmwVYqZaACiyqFK06ledwJlilSqVaAg50qFJp9lKH3tPXLLCymlv2kCTVqeFZTs4Ai/JPC+ThUykkEprDf43w1ImPF4wEC3MzLgGlSqH/o616GwUW+ygyNtMSgFY0q0qd5FEvWGQp5vLkd9J92FPozVidXw5oD1hZlwASiQr9sskZL2wBK+sSgO6UX3a2JEYrWCyBLePtfA/L387zN517C1imE7wYTKedOyCwnAdo1+kJrF0j53zeAst5gHadnsDaNXLO5y2wnAdo1+kJrF0j53zew8ByrlPTM3ZAYBkbnmU4gZUl0sY6BZax4VmGE1hZIm2sU2AZG55lOIGVJdLDdL7W0f8AAAD//x3VUCQAAAAGSURBVAMArsj7LTb9pqMAAAAASUVORK5CYII=";
|
|
4838
|
+
function TimbalMark({
|
|
4839
|
+
className,
|
|
4840
|
+
size = DEFAULT_SIZE,
|
|
4841
|
+
src = TIMBAL_SYMBOL_DATA_URI
|
|
4842
|
+
}) {
|
|
4843
|
+
return /* @__PURE__ */ jsx39(
|
|
4844
|
+
"div",
|
|
4845
|
+
{
|
|
4846
|
+
className: cn("relative shrink-0 bg-transparent", className),
|
|
4847
|
+
style: { width: size, height: size },
|
|
4848
|
+
role: "img",
|
|
4849
|
+
"aria-label": "Timbal",
|
|
4850
|
+
children: /* @__PURE__ */ jsx39(
|
|
4851
|
+
LiquidMetal,
|
|
4852
|
+
{
|
|
4853
|
+
width: size,
|
|
4854
|
+
height: size,
|
|
4855
|
+
image: src,
|
|
4856
|
+
colorBack: TRANSPARENT_BACK,
|
|
4857
|
+
colorTint: "#ffffff",
|
|
4858
|
+
shape: "none",
|
|
4859
|
+
repetition: 2,
|
|
4860
|
+
softness: 0.1,
|
|
4861
|
+
shiftRed: 0.3,
|
|
4862
|
+
shiftBlue: 0.3,
|
|
4863
|
+
distortion: 0.07,
|
|
4864
|
+
contour: 0.4,
|
|
4865
|
+
angle: 70,
|
|
4866
|
+
speed: 1,
|
|
4867
|
+
scale: 0.6,
|
|
4868
|
+
fit: "contain",
|
|
4869
|
+
className: "size-full bg-transparent",
|
|
4870
|
+
style: { background: "transparent" },
|
|
4871
|
+
webGlContextAttributes: {
|
|
4872
|
+
alpha: true,
|
|
4873
|
+
premultipliedAlpha: false
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
)
|
|
4877
|
+
}
|
|
4878
|
+
);
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4881
|
+
// src/components/studio/sidebar.tsx
|
|
4882
|
+
import { jsx as jsx40, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4883
|
+
var DEFAULT_BREAKPOINT_PX = 768;
|
|
4884
|
+
function readPersistedCollapsed(key) {
|
|
4885
|
+
if (!key || typeof window === "undefined") return false;
|
|
4886
|
+
try {
|
|
4887
|
+
return window.localStorage.getItem(key) === "1";
|
|
4888
|
+
} catch {
|
|
4889
|
+
return false;
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
function writePersistedCollapsed(key, collapsed) {
|
|
4893
|
+
if (!key || typeof window === "undefined") return;
|
|
4894
|
+
try {
|
|
4895
|
+
window.localStorage.setItem(key, collapsed ? "1" : "0");
|
|
4896
|
+
} catch {
|
|
4897
|
+
}
|
|
4898
|
+
}
|
|
4899
|
+
var StudioSidebarPanel = ({
|
|
4900
|
+
workforces,
|
|
4901
|
+
selectedId,
|
|
4902
|
+
onSelect,
|
|
4903
|
+
collapsed,
|
|
4904
|
+
onCollapsedChange,
|
|
4905
|
+
isMobile,
|
|
4906
|
+
mobileOpen,
|
|
4907
|
+
onMobileOpenChange,
|
|
4908
|
+
widthCollapsed,
|
|
4909
|
+
entriesVisible,
|
|
4910
|
+
onEntriesBlurOutComplete,
|
|
4911
|
+
onPanelWidthComplete,
|
|
4912
|
+
brand,
|
|
4913
|
+
emptyCaption = null
|
|
4914
|
+
}) => {
|
|
4915
|
+
const reducedMotion = useReducedMotion5();
|
|
4916
|
+
const isCollapsedRail = widthCollapsed && !isMobile;
|
|
4917
|
+
const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
|
|
4918
|
+
const isDrawerOpen = isMobile && mobileOpen;
|
|
4919
|
+
const widthDirection = widthCollapsed ? "collapse" : "expand";
|
|
4920
|
+
const widthTransition = studioSidebarWidthTransition(
|
|
4921
|
+
!!reducedMotion,
|
|
4922
|
+
widthDirection
|
|
4923
|
+
);
|
|
4924
|
+
const handleToggle = () => {
|
|
4925
|
+
if (isMobile) {
|
|
4926
|
+
onMobileOpenChange(false);
|
|
4927
|
+
return;
|
|
4928
|
+
}
|
|
4929
|
+
onCollapsedChange(!collapsed);
|
|
4930
|
+
};
|
|
4931
|
+
const panelWidthPx = isMobile ? SIDEBAR_MOBILE_PX : widthCollapsed ? SIDEBAR_WIDTH_COLLAPSED_PX : SIDEBAR_WIDTH_PX;
|
|
4932
|
+
const brandNode = brand ?? /* @__PURE__ */ jsx40(TimbalMark, { size: 32 });
|
|
4933
|
+
const panel = /* @__PURE__ */ jsxs21(
|
|
4934
|
+
motion8.div,
|
|
4935
|
+
{
|
|
4936
|
+
"data-sidebar-collapsed": isCollapsedRail ? "" : void 0,
|
|
4937
|
+
className: cn(
|
|
4938
|
+
"flex h-full flex-col overflow-hidden",
|
|
4939
|
+
studioSidebarPanelClass,
|
|
4940
|
+
isMobile ? "rounded-none rounded-r-2xl" : "rounded-2xl"
|
|
4941
|
+
),
|
|
4942
|
+
initial: false,
|
|
4943
|
+
animate: { width: panelWidthPx },
|
|
4944
|
+
transition: widthTransition,
|
|
4945
|
+
style: { willChange: entriesVisible ? void 0 : "width" },
|
|
4946
|
+
onAnimationComplete: isMobile || entriesVisible ? void 0 : () => onPanelWidthComplete(),
|
|
4947
|
+
children: [
|
|
4948
|
+
/* @__PURE__ */ jsx40(
|
|
4949
|
+
StudioSidebarHeader,
|
|
4950
|
+
{
|
|
4951
|
+
isCollapsedRail,
|
|
4952
|
+
isMobile,
|
|
4953
|
+
mobileOpen,
|
|
4954
|
+
onToggle: handleToggle,
|
|
4955
|
+
brand: brandNode
|
|
4956
|
+
}
|
|
4957
|
+
),
|
|
4958
|
+
/* @__PURE__ */ jsxs21(
|
|
4959
|
+
StudioSidebarEntries,
|
|
4960
|
+
{
|
|
4961
|
+
visible: entriesVisible,
|
|
4962
|
+
onBlurOutComplete: onEntriesBlurOutComplete,
|
|
4963
|
+
children: [
|
|
4964
|
+
/* @__PURE__ */ jsx40(
|
|
4965
|
+
"div",
|
|
4966
|
+
{
|
|
4967
|
+
id: DOM_IDS.sidebarRuntimeAnchor,
|
|
4968
|
+
className: cn(
|
|
4969
|
+
"min-h-0 shrink-0 empty:hidden",
|
|
4970
|
+
iconOnlyLayout ? "px-1.5 pt-1.5" : "px-2 pt-1.5"
|
|
4971
|
+
)
|
|
4972
|
+
}
|
|
4973
|
+
),
|
|
4974
|
+
/* @__PURE__ */ jsx40(
|
|
4975
|
+
StudioSidebarNav,
|
|
4976
|
+
{
|
|
4977
|
+
workforces,
|
|
4978
|
+
selectedId,
|
|
4979
|
+
onSelect,
|
|
4980
|
+
iconOnlyLayout,
|
|
4981
|
+
showTooltips: isCollapsedRail
|
|
4982
|
+
}
|
|
4983
|
+
),
|
|
4984
|
+
workforces.length === 0 ? /* @__PURE__ */ jsx40("div", { className: "min-h-0 flex-1" }) : null,
|
|
4985
|
+
/* @__PURE__ */ jsx40(
|
|
4986
|
+
StudioSidebarFooter,
|
|
4987
|
+
{
|
|
4988
|
+
iconOnlyLayout,
|
|
4989
|
+
showTooltips: isCollapsedRail,
|
|
4990
|
+
onSignOut: isMobile ? () => onMobileOpenChange(false) : void 0,
|
|
4991
|
+
emptyCaption
|
|
4992
|
+
}
|
|
4993
|
+
)
|
|
4994
|
+
]
|
|
4995
|
+
}
|
|
4996
|
+
)
|
|
4997
|
+
]
|
|
4998
|
+
}
|
|
4999
|
+
);
|
|
5000
|
+
if (isMobile) {
|
|
5001
|
+
return /* @__PURE__ */ jsx40(
|
|
5002
|
+
motion8.aside,
|
|
5003
|
+
{
|
|
5004
|
+
className: "fixed inset-y-0 left-0 z-[60] flex",
|
|
5005
|
+
"aria-label": "Studio navigation",
|
|
5006
|
+
"aria-hidden": !mobileOpen,
|
|
5007
|
+
initial: false,
|
|
5008
|
+
animate: {
|
|
5009
|
+
x: isDrawerOpen ? 0 : -(SIDEBAR_MOBILE_PX + 32)
|
|
5010
|
+
},
|
|
5011
|
+
transition: studioSidebarDrawerTransition(!!reducedMotion),
|
|
5012
|
+
style: { pointerEvents: isDrawerOpen ? "auto" : "none" },
|
|
5013
|
+
children: panel
|
|
5014
|
+
}
|
|
5015
|
+
);
|
|
5016
|
+
}
|
|
5017
|
+
return /* @__PURE__ */ jsx40(
|
|
5018
|
+
"aside",
|
|
5019
|
+
{
|
|
5020
|
+
className: "absolute inset-y-0 left-0 z-[60] flex py-[var(--studio-sidebar-gap)] pl-[var(--studio-sidebar-gap)]",
|
|
5021
|
+
"aria-label": "Studio navigation",
|
|
5022
|
+
children: panel
|
|
5023
|
+
}
|
|
5024
|
+
);
|
|
5025
|
+
};
|
|
5026
|
+
var StudioSidebar = ({
|
|
5027
|
+
workforces: workforcesProp,
|
|
5028
|
+
selectedId: selectedIdProp,
|
|
5029
|
+
onSelect,
|
|
5030
|
+
defaultCollapsed = false,
|
|
5031
|
+
persistKey = STORAGE_KEYS.sidebarCollapsed,
|
|
5032
|
+
mobileBreakpointPx = DEFAULT_BREAKPOINT_PX,
|
|
5033
|
+
brand,
|
|
5034
|
+
emptyCaption,
|
|
5035
|
+
mobileOpen: mobileOpenProp,
|
|
5036
|
+
onMobileOpenChange: onMobileOpenChangeProp
|
|
5037
|
+
}) => {
|
|
5038
|
+
const reducedMotion = useReducedMotion5();
|
|
5039
|
+
const fetched = useWorkforces({ enabled: workforcesProp === void 0 });
|
|
5040
|
+
const workforces = workforcesProp ?? fetched.workforces;
|
|
5041
|
+
const [internalSelected, setInternalSelected] = useState11(
|
|
5042
|
+
selectedIdProp ?? ""
|
|
5043
|
+
);
|
|
5044
|
+
useEffect9(() => {
|
|
5045
|
+
if (selectedIdProp !== void 0) return;
|
|
5046
|
+
if (internalSelected) return;
|
|
5047
|
+
const first = workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name;
|
|
5048
|
+
if (first) setInternalSelected(first);
|
|
5049
|
+
}, [workforces, selectedIdProp, internalSelected]);
|
|
5050
|
+
const selectedId = selectedIdProp ?? internalSelected ?? workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name ?? "";
|
|
5051
|
+
const handleSelect = useCallback6(
|
|
5052
|
+
(id) => {
|
|
5053
|
+
if (selectedIdProp === void 0) setInternalSelected(id);
|
|
5054
|
+
onSelect?.(id);
|
|
5055
|
+
},
|
|
5056
|
+
[selectedIdProp, onSelect]
|
|
5057
|
+
);
|
|
5058
|
+
const [collapsed, setCollapsed] = useState11(() => {
|
|
5059
|
+
const persisted = readPersistedCollapsed(persistKey);
|
|
5060
|
+
return persisted || defaultCollapsed;
|
|
5061
|
+
});
|
|
5062
|
+
const handleCollapsedChange = useCallback6(
|
|
5063
|
+
(next) => {
|
|
5064
|
+
setCollapsed(next);
|
|
5065
|
+
writePersistedCollapsed(persistKey, next);
|
|
5066
|
+
},
|
|
5067
|
+
[persistKey]
|
|
5068
|
+
);
|
|
5069
|
+
const [isMobile, setIsMobile] = useState11(() => {
|
|
5070
|
+
if (typeof window === "undefined") return false;
|
|
5071
|
+
return window.innerWidth < mobileBreakpointPx;
|
|
5072
|
+
});
|
|
5073
|
+
useEffect9(() => {
|
|
5074
|
+
if (typeof window === "undefined") return;
|
|
5075
|
+
const onResize = () => setIsMobile(window.innerWidth < mobileBreakpointPx);
|
|
5076
|
+
onResize();
|
|
5077
|
+
window.addEventListener("resize", onResize);
|
|
5078
|
+
return () => window.removeEventListener("resize", onResize);
|
|
5079
|
+
}, [mobileBreakpointPx]);
|
|
5080
|
+
const [internalMobileOpen, setInternalMobileOpen] = useState11(false);
|
|
5081
|
+
const mobileOpen = mobileOpenProp ?? internalMobileOpen;
|
|
5082
|
+
const setMobileOpen = useCallback6(
|
|
5083
|
+
(next) => {
|
|
5084
|
+
if (mobileOpenProp === void 0) setInternalMobileOpen(next);
|
|
5085
|
+
onMobileOpenChangeProp?.(next);
|
|
5086
|
+
},
|
|
5087
|
+
[mobileOpenProp, onMobileOpenChangeProp]
|
|
5088
|
+
);
|
|
5089
|
+
const effectiveCollapsed = isMobile ? false : collapsed;
|
|
5090
|
+
const {
|
|
5091
|
+
widthCollapsed,
|
|
5092
|
+
entriesVisible: phaseEntriesVisible,
|
|
5093
|
+
onEntriesBlurOutComplete,
|
|
5094
|
+
onPanelWidthComplete
|
|
5095
|
+
} = useSidebarCollapsePhase(effectiveCollapsed, !!reducedMotion);
|
|
5096
|
+
const entriesVisible = isMobile || phaseEntriesVisible;
|
|
5097
|
+
const isCollapsedRail = widthCollapsed && !isMobile;
|
|
5098
|
+
const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
|
|
5099
|
+
const contextValue = useMemo8(
|
|
5100
|
+
() => ({
|
|
5101
|
+
collapsed: effectiveCollapsed,
|
|
5102
|
+
isMobile,
|
|
5103
|
+
isCollapsedRail,
|
|
5104
|
+
iconOnlyLayout
|
|
5105
|
+
}),
|
|
5106
|
+
[effectiveCollapsed, isMobile, isCollapsedRail, iconOnlyLayout]
|
|
5107
|
+
);
|
|
5108
|
+
return /* @__PURE__ */ jsx40(StudioSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx40(
|
|
5109
|
+
StudioSidebarPanel,
|
|
5110
|
+
{
|
|
5111
|
+
workforces,
|
|
5112
|
+
selectedId,
|
|
5113
|
+
onSelect: handleSelect,
|
|
5114
|
+
collapsed: effectiveCollapsed,
|
|
5115
|
+
onCollapsedChange: handleCollapsedChange,
|
|
5116
|
+
isMobile,
|
|
5117
|
+
mobileOpen,
|
|
5118
|
+
onMobileOpenChange: setMobileOpen,
|
|
5119
|
+
widthCollapsed,
|
|
5120
|
+
entriesVisible,
|
|
5121
|
+
onEntriesBlurOutComplete,
|
|
5122
|
+
onPanelWidthComplete,
|
|
5123
|
+
brand,
|
|
5124
|
+
emptyCaption
|
|
5125
|
+
}
|
|
5126
|
+
) });
|
|
5127
|
+
};
|
|
5128
|
+
|
|
5129
|
+
// src/components/studio/sidebar-runtime-portal.tsx
|
|
5130
|
+
import { useCallback as useCallback7, useLayoutEffect, useState as useState12 } from "react";
|
|
5131
|
+
import { createPortal } from "react-dom";
|
|
5132
|
+
import { MessageSquarePlus } from "lucide-react";
|
|
5133
|
+
import { useThread as useThread2 } from "@assistant-ui/react";
|
|
5134
|
+
import { jsx as jsx41, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
5135
|
+
var StudioSidebarRuntimePortal = ({
|
|
5136
|
+
label = "New chat"
|
|
5137
|
+
}) => {
|
|
5138
|
+
const { iconOnlyLayout } = useStudioSidebarLayout();
|
|
5139
|
+
const hasMessages = useThread2((s) => s.messages.length > 0);
|
|
5140
|
+
const { clear } = useTimbalRuntime();
|
|
5141
|
+
const [anchor, setAnchor] = useState12(null);
|
|
5142
|
+
const startNewChat = useCallback7(() => {
|
|
5143
|
+
clear();
|
|
5144
|
+
}, [clear]);
|
|
5145
|
+
useLayoutEffect(() => {
|
|
5146
|
+
setAnchor(document.getElementById(DOM_IDS.sidebarRuntimeAnchor));
|
|
5147
|
+
}, []);
|
|
5148
|
+
if (!anchor || !hasMessages) return null;
|
|
5149
|
+
const button = /* @__PURE__ */ jsxs22(
|
|
5150
|
+
"button",
|
|
5151
|
+
{
|
|
5152
|
+
type: "button",
|
|
5153
|
+
onClick: startNewChat,
|
|
5154
|
+
"aria-label": label,
|
|
5155
|
+
className: studioSidebarNavItemClasses(iconOnlyLayout, false),
|
|
5156
|
+
children: [
|
|
5157
|
+
/* @__PURE__ */ jsx41(MessageSquarePlus, { className: "size-3.5 shrink-0" }),
|
|
5158
|
+
!iconOnlyLayout ? /* @__PURE__ */ jsx41("span", { className: "min-w-0 truncate", children: label }) : null
|
|
5159
|
+
]
|
|
5160
|
+
}
|
|
5161
|
+
);
|
|
5162
|
+
return createPortal(
|
|
5163
|
+
iconOnlyLayout ? /* @__PURE__ */ jsxs22(Tooltip, { children: [
|
|
5164
|
+
/* @__PURE__ */ jsx41(TooltipTrigger, { asChild: true, children: button }),
|
|
5165
|
+
/* @__PURE__ */ jsx41(TooltipContent, { side: "right", className: "text-xs", children: label })
|
|
5166
|
+
] }) : button,
|
|
5167
|
+
anchor
|
|
5168
|
+
);
|
|
5169
|
+
};
|
|
5170
|
+
|
|
5171
|
+
// src/components/studio/welcome.tsx
|
|
5172
|
+
import { motion as motion9 } from "motion/react";
|
|
5173
|
+
import { useThread as useThread3 } from "@assistant-ui/react";
|
|
5174
|
+
import { jsx as jsx42, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
5175
|
+
var luxuryEase2 = [0.16, 1, 0.3, 1];
|
|
5176
|
+
var welcomeStagger2 = {
|
|
5177
|
+
initial: {},
|
|
5178
|
+
animate: {
|
|
5179
|
+
transition: { staggerChildren: 0.16, delayChildren: 0.18 }
|
|
5180
|
+
}
|
|
5181
|
+
};
|
|
5182
|
+
var welcomeItem2 = {
|
|
5183
|
+
initial: { opacity: 0, y: 14 },
|
|
5184
|
+
animate: {
|
|
5185
|
+
opacity: 1,
|
|
5186
|
+
y: 0,
|
|
5187
|
+
transition: { duration: 0.9, ease: luxuryEase2 }
|
|
5188
|
+
}
|
|
5189
|
+
};
|
|
5190
|
+
var welcomeIcon2 = {
|
|
5191
|
+
initial: { opacity: 0, y: 10, scale: 0.96 },
|
|
5192
|
+
animate: {
|
|
5193
|
+
opacity: 1,
|
|
5194
|
+
y: 0,
|
|
5195
|
+
scale: 1,
|
|
5196
|
+
transition: { duration: 1.1, ease: luxuryEase2 }
|
|
5197
|
+
}
|
|
5198
|
+
};
|
|
5199
|
+
var StudioWelcome = ({ config, icon }) => {
|
|
5200
|
+
const isEmpty = useThread3((s) => s.messages.length === 0);
|
|
5201
|
+
if (!isEmpty) return null;
|
|
5202
|
+
const iconNode = icon ?? /* @__PURE__ */ jsx42(
|
|
5203
|
+
TimbalMark,
|
|
5204
|
+
{
|
|
5205
|
+
size: 112,
|
|
5206
|
+
className: "max-md:scale-[0.58] max-md:origin-center"
|
|
5207
|
+
}
|
|
5208
|
+
);
|
|
5209
|
+
return /* @__PURE__ */ jsx42("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: /* @__PURE__ */ jsx42("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ jsxs23(
|
|
5210
|
+
motion9.div,
|
|
5211
|
+
{
|
|
5212
|
+
className: "aui-thread-welcome-message flex flex-col items-center justify-center px-2 text-center sm:px-4",
|
|
5213
|
+
variants: welcomeStagger2,
|
|
5214
|
+
initial: "initial",
|
|
5215
|
+
animate: "animate",
|
|
5216
|
+
children: [
|
|
5217
|
+
/* @__PURE__ */ jsx42(motion9.div, { variants: welcomeIcon2, className: "mb-4 md:mb-5", children: iconNode }),
|
|
5218
|
+
/* @__PURE__ */ jsx42(
|
|
5219
|
+
motion9.h1,
|
|
5220
|
+
{
|
|
5221
|
+
variants: welcomeItem2,
|
|
5222
|
+
className: "aui-thread-welcome-message-inner text-xl font-semibold sm:text-2xl",
|
|
5223
|
+
children: config?.heading ?? "How can I help you today?"
|
|
5224
|
+
}
|
|
5225
|
+
),
|
|
5226
|
+
/* @__PURE__ */ jsx42(
|
|
5227
|
+
motion9.p,
|
|
5228
|
+
{
|
|
5229
|
+
variants: welcomeItem2,
|
|
5230
|
+
className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
|
|
5231
|
+
children: config?.subheading ?? "Send a message to start a conversation."
|
|
5232
|
+
}
|
|
5233
|
+
)
|
|
5234
|
+
]
|
|
5235
|
+
}
|
|
5236
|
+
) }) });
|
|
5237
|
+
};
|
|
5238
|
+
|
|
5239
|
+
// src/components/studio/studio-shell.tsx
|
|
5240
|
+
import { Fragment as Fragment4, jsx as jsx43, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5241
|
+
import { createElement } from "react";
|
|
5242
|
+
var DEFAULT_BREAKPOINT_PX2 = 768;
|
|
5243
|
+
function readPersistedCollapsed2(key) {
|
|
5244
|
+
if (!key || typeof window === "undefined") return false;
|
|
5245
|
+
try {
|
|
5246
|
+
return window.localStorage.getItem(key) === "1";
|
|
5247
|
+
} catch {
|
|
5248
|
+
return false;
|
|
5249
|
+
}
|
|
5250
|
+
}
|
|
5251
|
+
function writePersistedCollapsed2(key, collapsed) {
|
|
5252
|
+
if (!key || typeof window === "undefined") return;
|
|
5253
|
+
try {
|
|
5254
|
+
window.localStorage.setItem(key, collapsed ? "1" : "0");
|
|
5255
|
+
} catch {
|
|
5256
|
+
}
|
|
5257
|
+
}
|
|
5258
|
+
function makeComposerWithPortal(BaseComposer) {
|
|
5259
|
+
const Resolved = BaseComposer ?? Composer;
|
|
5260
|
+
return function StudioComposerWithSidebar(props) {
|
|
5261
|
+
return /* @__PURE__ */ jsxs24(Fragment4, { children: [
|
|
5262
|
+
/* @__PURE__ */ jsx43(StudioSidebarRuntimePortal, {}),
|
|
5263
|
+
/* @__PURE__ */ jsx43(Resolved, { ...props })
|
|
5264
|
+
] });
|
|
5265
|
+
};
|
|
5266
|
+
}
|
|
5267
|
+
var TimbalStudioShell = ({
|
|
5268
|
+
workforceId,
|
|
5269
|
+
workforces: workforcesProp,
|
|
5270
|
+
workforcesFetch,
|
|
5271
|
+
workforcesBaseUrl,
|
|
5272
|
+
brand,
|
|
5273
|
+
headerActions,
|
|
5274
|
+
headerStart,
|
|
5275
|
+
defaultCollapsed = false,
|
|
5276
|
+
persistKey = STORAGE_KEYS.sidebarCollapsed,
|
|
5277
|
+
mobileBreakpointPx = DEFAULT_BREAKPOINT_PX2,
|
|
5278
|
+
sidebarEmptyCaption = null,
|
|
5279
|
+
welcome,
|
|
5280
|
+
components,
|
|
5281
|
+
...chatProps
|
|
5282
|
+
}) => {
|
|
5283
|
+
const reducedMotion = useReducedMotion6();
|
|
5284
|
+
const shouldFetchWorkforces = !workforceId && workforcesProp === void 0;
|
|
5285
|
+
const fetched = useWorkforces({
|
|
5286
|
+
enabled: shouldFetchWorkforces,
|
|
5287
|
+
fetch: workforcesFetch,
|
|
5288
|
+
baseUrl: workforcesBaseUrl
|
|
5289
|
+
});
|
|
5290
|
+
const workforces = workforcesProp ?? fetched.workforces;
|
|
5291
|
+
const [internalSelected, setInternalSelected] = useState13(
|
|
5292
|
+
workforceId ?? ""
|
|
5293
|
+
);
|
|
5294
|
+
useEffect10(() => {
|
|
5295
|
+
if (workforceId) return;
|
|
5296
|
+
if (internalSelected) return;
|
|
5297
|
+
const first = workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name;
|
|
5298
|
+
if (first) setInternalSelected(first);
|
|
5299
|
+
}, [workforces, workforceId, internalSelected]);
|
|
5300
|
+
const activeWorkforceId = workforceId ?? internalSelected ?? fetched.selectedId ?? "";
|
|
5301
|
+
const [collapsed, setCollapsed] = useState13(() => {
|
|
5302
|
+
const persisted = readPersistedCollapsed2(persistKey);
|
|
5303
|
+
return persisted || defaultCollapsed;
|
|
5304
|
+
});
|
|
5305
|
+
const [isMobile, setIsMobile] = useState13(() => {
|
|
5306
|
+
if (typeof window === "undefined") return false;
|
|
5307
|
+
return window.innerWidth < mobileBreakpointPx;
|
|
5308
|
+
});
|
|
5309
|
+
const [mobileSidebarOpen, setMobileSidebarOpen] = useState13(false);
|
|
5310
|
+
useEffect10(() => {
|
|
5311
|
+
if (typeof window === "undefined") return;
|
|
5312
|
+
const onResize = () => setIsMobile(window.innerWidth < mobileBreakpointPx);
|
|
5313
|
+
onResize();
|
|
5314
|
+
window.addEventListener("resize", onResize);
|
|
5315
|
+
return () => window.removeEventListener("resize", onResize);
|
|
5316
|
+
}, [mobileBreakpointPx]);
|
|
5317
|
+
useEffect10(() => {
|
|
5318
|
+
if (!isMobile) setMobileSidebarOpen(false);
|
|
5319
|
+
}, [isMobile]);
|
|
5320
|
+
useEffect10(() => {
|
|
5321
|
+
if (!mobileSidebarOpen) return;
|
|
5322
|
+
const onKeyDown = (e) => {
|
|
5323
|
+
if (e.key === "Escape") setMobileSidebarOpen(false);
|
|
5324
|
+
};
|
|
5325
|
+
window.addEventListener("keydown", onKeyDown);
|
|
5326
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
5327
|
+
}, [mobileSidebarOpen]);
|
|
5328
|
+
const effectiveCollapsed = isMobile ? false : collapsed;
|
|
5329
|
+
const {
|
|
5330
|
+
widthCollapsed,
|
|
5331
|
+
entriesVisible: phaseEntriesVisible,
|
|
5332
|
+
onEntriesBlurOutComplete,
|
|
5333
|
+
onPanelWidthComplete
|
|
5334
|
+
} = useSidebarCollapsePhase(effectiveCollapsed, !!reducedMotion);
|
|
5335
|
+
const entriesVisible = isMobile || phaseEntriesVisible;
|
|
5336
|
+
const isCollapsedRail = widthCollapsed && !isMobile;
|
|
5337
|
+
const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
|
|
5338
|
+
const layoutDirection = widthCollapsed ? "collapse" : "expand";
|
|
5339
|
+
const layoutTransition = studioSidebarWidthTransition(
|
|
5340
|
+
!!reducedMotion,
|
|
5341
|
+
layoutDirection
|
|
5342
|
+
);
|
|
5343
|
+
const desktopInsetPx = widthCollapsed ? SIDEBAR_INSET_PX_COLLAPSED : SIDEBAR_INSET_PX_EXPANDED;
|
|
5344
|
+
const onCollapsedChange = useCallback8(
|
|
5345
|
+
(next) => {
|
|
5346
|
+
setCollapsed(next);
|
|
5347
|
+
writePersistedCollapsed2(persistKey, next);
|
|
5348
|
+
},
|
|
5349
|
+
[persistKey]
|
|
5350
|
+
);
|
|
5351
|
+
const handleSelectWorkforce = useCallback8(
|
|
5352
|
+
(id) => {
|
|
5353
|
+
if (!workforceId) setInternalSelected(id);
|
|
5354
|
+
if (isMobile) setMobileSidebarOpen(false);
|
|
5355
|
+
},
|
|
5356
|
+
[workforceId, isMobile]
|
|
5357
|
+
);
|
|
5358
|
+
const sidebarContext = useMemo9(
|
|
5359
|
+
() => ({
|
|
5360
|
+
collapsed: effectiveCollapsed,
|
|
5361
|
+
isMobile,
|
|
5362
|
+
isCollapsedRail,
|
|
5363
|
+
iconOnlyLayout
|
|
5364
|
+
}),
|
|
5365
|
+
[effectiveCollapsed, isMobile, isCollapsedRail, iconOnlyLayout]
|
|
5366
|
+
);
|
|
5367
|
+
const resolvedComponents = useMemo9(() => {
|
|
5368
|
+
const next = { Welcome: StudioWelcome, ...components };
|
|
5369
|
+
next.Composer = makeComposerWithPortal(components?.Composer);
|
|
5370
|
+
return next;
|
|
5371
|
+
}, [components]);
|
|
5372
|
+
return /* @__PURE__ */ jsx43(StudioSidebarContext.Provider, { value: sidebarContext, children: /* @__PURE__ */ jsxs24(
|
|
5373
|
+
"div",
|
|
5374
|
+
{
|
|
5375
|
+
className: cn(
|
|
5376
|
+
"relative h-dvh overflow-hidden bg-background",
|
|
5377
|
+
isMobile && mobileSidebarOpen && "max-md:overflow-hidden"
|
|
5378
|
+
),
|
|
5379
|
+
style: studioChromeShellStyle,
|
|
5380
|
+
children: [
|
|
5381
|
+
/* @__PURE__ */ jsx43(
|
|
5382
|
+
"div",
|
|
5383
|
+
{
|
|
5384
|
+
className: "pointer-events-none absolute inset-0 z-0 bg-background",
|
|
5385
|
+
"aria-hidden": true
|
|
5386
|
+
}
|
|
5387
|
+
),
|
|
5388
|
+
/* @__PURE__ */ jsx43(
|
|
5389
|
+
"div",
|
|
5390
|
+
{
|
|
5391
|
+
className: cn(
|
|
5392
|
+
"pointer-events-none absolute inset-0 z-0",
|
|
5393
|
+
studioPlaygroundGradientClass
|
|
5394
|
+
),
|
|
5395
|
+
"aria-hidden": true
|
|
5396
|
+
}
|
|
5397
|
+
),
|
|
5398
|
+
/* @__PURE__ */ jsx43(
|
|
5399
|
+
StudioSidebarBackdrop,
|
|
5400
|
+
{
|
|
5401
|
+
open: isMobile && mobileSidebarOpen,
|
|
5402
|
+
onClose: () => setMobileSidebarOpen(false)
|
|
5403
|
+
}
|
|
5404
|
+
),
|
|
5405
|
+
/* @__PURE__ */ jsx43(
|
|
5406
|
+
StudioSidebarPanel,
|
|
5407
|
+
{
|
|
5408
|
+
workforces,
|
|
5409
|
+
selectedId: activeWorkforceId,
|
|
5410
|
+
onSelect: handleSelectWorkforce,
|
|
5411
|
+
collapsed: effectiveCollapsed,
|
|
5412
|
+
onCollapsedChange,
|
|
5413
|
+
isMobile,
|
|
5414
|
+
mobileOpen: mobileSidebarOpen,
|
|
5415
|
+
onMobileOpenChange: setMobileSidebarOpen,
|
|
5416
|
+
widthCollapsed,
|
|
5417
|
+
entriesVisible,
|
|
5418
|
+
onEntriesBlurOutComplete,
|
|
5419
|
+
onPanelWidthComplete,
|
|
5420
|
+
brand,
|
|
5421
|
+
emptyCaption: sidebarEmptyCaption
|
|
5422
|
+
}
|
|
5423
|
+
),
|
|
5424
|
+
/* @__PURE__ */ jsxs24(
|
|
5425
|
+
motion10.header,
|
|
5426
|
+
{
|
|
5427
|
+
className: cn(
|
|
5428
|
+
"absolute top-0 right-0 z-40 flex items-start justify-between gap-2",
|
|
5429
|
+
"px-3 pt-[var(--studio-topbar-gap)] md:px-4",
|
|
5430
|
+
"left-0"
|
|
5431
|
+
),
|
|
5432
|
+
initial: false,
|
|
5433
|
+
animate: { left: isMobile ? 0 : desktopInsetPx },
|
|
5434
|
+
transition: layoutTransition,
|
|
5435
|
+
children: [
|
|
5436
|
+
/* @__PURE__ */ jsxs24(
|
|
5437
|
+
"div",
|
|
5438
|
+
{
|
|
5439
|
+
className: cn(
|
|
5440
|
+
"flex min-w-0 flex-1 items-center gap-2",
|
|
5441
|
+
studioTopbarPillHeightClass
|
|
5442
|
+
),
|
|
5443
|
+
children: [
|
|
5444
|
+
isMobile && !mobileSidebarOpen ? /* @__PURE__ */ jsx43(
|
|
5445
|
+
TimbalV2Button,
|
|
5446
|
+
{
|
|
5447
|
+
variant: "secondary",
|
|
5448
|
+
size: "sm",
|
|
5449
|
+
isIconOnly: true,
|
|
5450
|
+
className: studioTopbarIconPillClass,
|
|
5451
|
+
onClick: () => setMobileSidebarOpen(true),
|
|
5452
|
+
"aria-label": "Open menu",
|
|
5453
|
+
"aria-expanded": false,
|
|
5454
|
+
children: /* @__PURE__ */ jsx43(Menu, { className: "size-4" })
|
|
5455
|
+
}
|
|
5456
|
+
) : null,
|
|
5457
|
+
headerStart
|
|
5458
|
+
]
|
|
5459
|
+
}
|
|
5460
|
+
),
|
|
5461
|
+
headerActions ? /* @__PURE__ */ jsx43("div", { className: "flex shrink-0 items-center gap-1", children: headerActions }) : null
|
|
5462
|
+
]
|
|
5463
|
+
}
|
|
5464
|
+
),
|
|
5465
|
+
/* @__PURE__ */ jsx43(
|
|
5466
|
+
motion10.main,
|
|
5467
|
+
{
|
|
5468
|
+
className: cn(
|
|
5469
|
+
"relative z-10 flex h-full min-w-0 flex-col",
|
|
5470
|
+
"pt-[var(--studio-inset-top)]",
|
|
5471
|
+
"px-3 md:px-0"
|
|
5472
|
+
),
|
|
5473
|
+
initial: false,
|
|
5474
|
+
animate: { paddingLeft: isMobile ? 12 : desktopInsetPx },
|
|
5475
|
+
transition: layoutTransition,
|
|
5476
|
+
children: activeWorkforceId ? /* @__PURE__ */ createElement(
|
|
5477
|
+
TimbalChat,
|
|
5478
|
+
{
|
|
5479
|
+
...chatProps,
|
|
5480
|
+
workforceId: activeWorkforceId,
|
|
5481
|
+
key: activeWorkforceId,
|
|
5482
|
+
welcome,
|
|
5483
|
+
components: resolvedComponents,
|
|
5484
|
+
className: cn("min-h-0 flex-1 bg-transparent", chatProps.className)
|
|
5485
|
+
}
|
|
5486
|
+
) : null
|
|
5487
|
+
}
|
|
5488
|
+
)
|
|
5489
|
+
]
|
|
5490
|
+
}
|
|
5491
|
+
) });
|
|
5492
|
+
};
|
|
5493
|
+
|
|
5494
|
+
// src/components/studio/mode-toggle.tsx
|
|
5495
|
+
import { useCallback as useCallback9, useEffect as useEffect11, useState as useState14 } from "react";
|
|
5496
|
+
import { Moon, Sun } from "lucide-react";
|
|
5497
|
+
import { jsx as jsx44, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
5498
|
+
var ModeToggle = ({
|
|
5499
|
+
theme,
|
|
5500
|
+
setTheme,
|
|
5501
|
+
className,
|
|
5502
|
+
label = "Toggle theme"
|
|
5503
|
+
}) => {
|
|
5504
|
+
const isControlled = theme !== void 0;
|
|
5505
|
+
const [internalIsDark, setInternalIsDark] = useState14(false);
|
|
5506
|
+
useEffect11(() => {
|
|
5507
|
+
if (isControlled) return;
|
|
5508
|
+
if (typeof document === "undefined") return;
|
|
5509
|
+
setInternalIsDark(document.documentElement.classList.contains("dark"));
|
|
5510
|
+
}, [isControlled]);
|
|
5511
|
+
const isDark = isControlled ? theme === "dark" : internalIsDark;
|
|
5512
|
+
const onClick = useCallback9(() => {
|
|
5513
|
+
const next = isDark ? "light" : "dark";
|
|
5514
|
+
if (setTheme) {
|
|
5515
|
+
setTheme(next);
|
|
5516
|
+
return;
|
|
5517
|
+
}
|
|
5518
|
+
if (typeof document === "undefined") return;
|
|
5519
|
+
document.documentElement.classList.toggle("dark", next === "dark");
|
|
5520
|
+
setInternalIsDark(next === "dark");
|
|
5521
|
+
}, [isDark, setTheme]);
|
|
5522
|
+
return /* @__PURE__ */ jsxs25(
|
|
5523
|
+
TimbalV2Button,
|
|
5524
|
+
{
|
|
5525
|
+
variant: "secondary",
|
|
5526
|
+
size: "sm",
|
|
5527
|
+
isIconOnly: true,
|
|
5528
|
+
onClick,
|
|
5529
|
+
className: cn(
|
|
5530
|
+
studioTopbarPillHeightClass,
|
|
5531
|
+
studioTopbarIconPillClass,
|
|
5532
|
+
"relative",
|
|
5533
|
+
className
|
|
5534
|
+
),
|
|
5535
|
+
"aria-label": label,
|
|
5536
|
+
title: label,
|
|
5537
|
+
children: [
|
|
5538
|
+
/* @__PURE__ */ jsx44(Sun, { className: "size-3.5 scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" }),
|
|
5539
|
+
/* @__PURE__ */ jsx44(Moon, { className: "absolute size-3.5 scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" }),
|
|
5540
|
+
/* @__PURE__ */ jsx44("span", { className: "sr-only", children: label })
|
|
5541
|
+
]
|
|
5542
|
+
}
|
|
5543
|
+
);
|
|
5544
|
+
};
|
|
5545
|
+
|
|
5546
|
+
// src/artifacts/agent-instructions.ts
|
|
5547
|
+
var ARTIFACT_AGENT_INSTRUCTIONS = `
|
|
5548
|
+
## Rich artifacts (Timbal chat UI)
|
|
5549
|
+
|
|
5550
|
+
When you need charts, tables, choice widgets, or interactive controls, return a **JSON artifact object** instead of plain prose. The chat UI renders these automatically.
|
|
5551
|
+
|
|
5552
|
+
### Delivery channels (either works)
|
|
5553
|
+
|
|
5554
|
+
1. **Tool result (preferred)** \u2014 return a single JSON object (or a JSON string) from a tool. The object must include a string \`type\` field.
|
|
5555
|
+
2. **Inline markdown fence** \u2014 embed the same JSON inside a fenced block:
|
|
5556
|
+
|
|
5557
|
+
\`\`\`timbal-artifact
|
|
5558
|
+
{"type":"chart","data":[{"month":"Jan","sales":120}]}
|
|
5559
|
+
\`\`\`
|
|
5560
|
+
|
|
5561
|
+
The alias \`\`\`timbal\`\`\` is also accepted.
|
|
5562
|
+
|
|
5563
|
+
### Built-in artifact types
|
|
5564
|
+
|
|
5565
|
+
| \`type\` | Use for |
|
|
5566
|
+
|---|---|
|
|
5567
|
+
| \`chart\` | Bar, line, area, or pie charts. Fields: \`data\`, optional \`chartType\`, \`xKey\`, \`dataKey\`, \`title\`, \`unit\`. |
|
|
5568
|
+
| \`table\` | Tabular data. Fields: \`rows\`, optional \`columns\`, \`title\`. |
|
|
5569
|
+
| \`question\` | In-thread multiple choice. Fields: \`options: [{ id, label, description? }]\`, optional \`prompt\`, \`multi\`. User replies are sent back as a normal user message. |
|
|
5570
|
+
| \`html\` | Custom HTML/CSS/JS in an iframe. Fields: \`content\` (HTML document or fragment), optional \`title\`, \`height\`, \`sandboxed\` (default \`true\`; set \`false\` for unrestricted scripts/CDN). |
|
|
5571
|
+
| \`json\` | Fallback structured view. Fields: \`data\`, optional \`title\`. |
|
|
5572
|
+
| \`ui\` | **Interactive UI** composed from a fixed node palette (hover, click, drag). See below. |
|
|
5573
|
+
|
|
5574
|
+
### When to use \`type: "html"\`
|
|
5575
|
+
|
|
5576
|
+
Use \`html\` when the user wants a **rich visual or interactive page** that does not fit the \`ui\` palette \u2014 e.g. styled layouts, SVG graphics, CSS animations, canvas, small games, calculators, or multi-section mockups. Pass a full HTML document or a body fragment in \`content\`.
|
|
5577
|
+
|
|
5578
|
+
- Inline \`<style>\`, \`<script>\`, SVG, and canvas are supported.
|
|
5579
|
+
- Default \`sandboxed: true\` runs in an isolated iframe with scripts enabled.
|
|
5580
|
+
- Set \`sandboxed: false\` only for trusted content that needs external CDN scripts/styles or full DOM freedom.
|
|
5581
|
+
- Prefer \`ui\` when controls should send chat messages or host events; prefer \`html\` for self-contained mini-apps and visual demos.
|
|
5582
|
+
|
|
5583
|
+
### When to use \`type: "ui"\`
|
|
5584
|
+
|
|
5585
|
+
Use a \`ui\` artifact when the user should **hover, click, drag, or adjust controls** in-thread and those actions should integrate with the chat runtime (messages, \`onArtifactEvent\`). For standalone visual/interactive HTML, use \`html\` instead.
|
|
5586
|
+
|
|
5587
|
+
Each \`ui\` artifact has:
|
|
5588
|
+
|
|
5589
|
+
- \`initialState\` \u2014 optional object seeding local state (per widget instance).
|
|
5590
|
+
- \`root\` \u2014 a single node tree (see node kinds below).
|
|
5591
|
+
- optional \`title\` \u2014 card heading.
|
|
5592
|
+
|
|
5593
|
+
**Bindings:** anywhere a primitive is accepted, you may use \`{ "$bind": "dotted.path" }\` to read from \`initialState\` / local state (e.g. \`{ "$bind": "qty" }\`).
|
|
5594
|
+
|
|
5595
|
+
**Actions:** nodes may attach \`onClick\`, \`onChange\`, or \`onDragEnd\` with one action or an array:
|
|
5596
|
+
|
|
5597
|
+
| Action | Shape | Effect |
|
|
5598
|
+
|---|---|---|
|
|
5599
|
+
| User message | \`{ "kind": "message", "text": "..." }\` or \`{ "kind": "message", "text": { "$bind": "path" } }\` | Sends text as the next user message. |
|
|
5600
|
+
| Set state | \`{ "kind": "set", "path": "foo", "value": 1 }\` | Writes local widget state. |
|
|
5601
|
+
| Toggle boolean | \`{ "kind": "toggle", "path": "enabled" }\` | Flips a boolean at \`path\`. |
|
|
5602
|
+
| Host event | \`{ "kind": "emit", "name": "event-name", "payload": { ... } }\` | Bubbles to the host app (\`onArtifactEvent\` on \`<Thread>\`). |
|
|
5603
|
+
|
|
5604
|
+
### \`ui\` node palette (\`root.kind\`)
|
|
5605
|
+
|
|
5606
|
+
| \`kind\` | Purpose | Key fields |
|
|
5607
|
+
|---|---|---|
|
|
5608
|
+
| \`box\` | Layout container | \`children\`, \`direction\` (\`row\`/\`col\`), \`gap\`, \`padding\`, \`align\`, \`justify\`, \`wrap\` |
|
|
5609
|
+
| \`text\` | Body text | \`value\`, optional \`muted\`, \`size\`, \`weight\` |
|
|
5610
|
+
| \`heading\` | Heading | \`value\`, optional \`level\` (1\u20134) |
|
|
5611
|
+
| \`badge\` | Pill label | \`value\`, optional \`tone\` (\`default\`, \`primary\`, \`success\`, \`warn\`, \`danger\`) |
|
|
5612
|
+
| \`button\` | Clickable button | \`label\`, optional \`variant\`, \`size\`, \`disabled\`, \`onClick\` |
|
|
5613
|
+
| \`toggle\` | Boolean switch | \`binding\` (state path), optional \`label\`, \`onChange\` |
|
|
5614
|
+
| \`slider\` | Numeric range | \`binding\`, optional \`min\`, \`max\`, \`step\`, \`label\`, \`showValue\`, \`onChange\` |
|
|
5615
|
+
| \`tooltip\` | Hover tooltip | \`content\`, \`child\` (single node), optional \`side\` |
|
|
5616
|
+
| \`draggable\` | Drag gesture | \`child\`, optional \`axis\` (\`x\`/\`y\`/\`both\`), \`snapBack\`, \`onDragEnd\` |
|
|
5617
|
+
| \`custom\` | Host-registered widget | \`name\`, optional \`props\`, \`children\` \u2014 only if the app registered that name |
|
|
5618
|
+
|
|
5619
|
+
### Example \`ui\` artifact
|
|
5620
|
+
|
|
5621
|
+
\`\`\`json
|
|
5622
|
+
{
|
|
5623
|
+
"type": "ui",
|
|
5624
|
+
"title": "Configure plan",
|
|
5625
|
+
"initialState": { "qty": 1, "premium": false },
|
|
5626
|
+
"root": {
|
|
5627
|
+
"kind": "box",
|
|
5628
|
+
"direction": "col",
|
|
5629
|
+
"gap": 3,
|
|
5630
|
+
"children": [
|
|
5631
|
+
{ "kind": "heading", "value": "Choose quantity", "level": 3 },
|
|
5632
|
+
{
|
|
5633
|
+
"kind": "tooltip",
|
|
5634
|
+
"content": "Drag to adjust quantity",
|
|
5635
|
+
"child": {
|
|
5636
|
+
"kind": "slider",
|
|
5637
|
+
"binding": "qty",
|
|
5638
|
+
"min": 1,
|
|
5639
|
+
"max": 50,
|
|
5640
|
+
"label": "Quantity",
|
|
5641
|
+
"onChange": { "kind": "emit", "name": "qty-changed" }
|
|
5642
|
+
}
|
|
5643
|
+
},
|
|
5644
|
+
{ "kind": "toggle", "binding": "premium", "label": "Premium support" },
|
|
5645
|
+
{
|
|
5646
|
+
"kind": "button",
|
|
5647
|
+
"label": "Confirm",
|
|
5648
|
+
"onClick": { "kind": "message", "text": { "$bind": "qty" } }
|
|
5649
|
+
}
|
|
5650
|
+
]
|
|
5651
|
+
}
|
|
5652
|
+
}
|
|
5653
|
+
\`\`\`
|
|
5654
|
+
|
|
5655
|
+
### Rules
|
|
5656
|
+
|
|
5657
|
+
- Always set \`type\` to a built-in value above unless the app documented a custom type.
|
|
5658
|
+
- Prefer \`ui\` over \`html\` when actions must bubble to the host chat (\`message\`, \`emit\`).
|
|
5659
|
+
- Prefer \`question\` for simple A/B/C choices; use \`ui\` when you need sliders, toggles, drag, or multi-control layouts.
|
|
5660
|
+
- Keep \`data\` arrays reasonably small (charts/tables).
|
|
5661
|
+
|
|
5662
|
+
### After calling an artifact tool (critical)
|
|
5663
|
+
|
|
5664
|
+
When you call a tool that returns an artifact (\`make_chart\`, \`ask_question\`, \`show_table\`, \`show_html\`, \`make_ui_demo\`, etc.):
|
|
5665
|
+
|
|
5666
|
+
1. **Do not** paste, quote, paraphrase as JSON, or fence the tool return value in your assistant message. The chat UI already renders it from the tool result.
|
|
5667
|
+
2. **Do not** emit a matching \`\`\`timbal-artifact\`\`\` block for the same payload \u2014 pick **one** channel (tool result only).
|
|
5668
|
+
3. Your follow-up text should be **empty**, or at most **one short sentence** (e.g. "Pick an option above." / "Try the controls."). Never include \`type\`, \`options\`, \`data\`, or dict/JSON syntax.
|
|
5669
|
+
4. Treat the widget as visible to the user; refer to it as "above" / "the chart" / "the choices" \u2014 never reproduce its contents.
|
|
5670
|
+
`.trim();
|
|
5671
|
+
|
|
5672
|
+
// src/auth/guard.tsx
|
|
5673
|
+
import { Loader2 } from "lucide-react";
|
|
5674
|
+
import { jsx as jsx45 } from "react/jsx-runtime";
|
|
5675
|
+
var AuthGuard = ({
|
|
5676
|
+
children,
|
|
5677
|
+
requireAuth = false,
|
|
5678
|
+
enabled = true
|
|
5679
|
+
}) => {
|
|
5680
|
+
const { isAuthenticated, loading, isEmbedded } = useSession();
|
|
5681
|
+
if (!enabled) {
|
|
5682
|
+
return children;
|
|
5683
|
+
}
|
|
5684
|
+
if (loading) {
|
|
5685
|
+
return /* @__PURE__ */ jsx45("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ jsx45(Loader2, { className: "w-8 h-8 animate-spin" }) });
|
|
5686
|
+
}
|
|
5687
|
+
if (requireAuth && !isAuthenticated && !isEmbedded) {
|
|
5688
|
+
const returnTo = encodeURIComponent(
|
|
5689
|
+
window.location.pathname + window.location.search
|
|
5690
|
+
);
|
|
5691
|
+
window.location.href = `/api/auth/login?return_to=${returnTo}`;
|
|
5692
|
+
return null;
|
|
5693
|
+
}
|
|
5694
|
+
return children;
|
|
5695
|
+
};
|
|
5696
|
+
|
|
5697
|
+
// src/index.ts
|
|
5698
|
+
import {
|
|
5699
|
+
ThreadPrimitive as ThreadPrimitive2,
|
|
5700
|
+
MessagePrimitive as MessagePrimitive3,
|
|
5701
|
+
ComposerPrimitive as ComposerPrimitive4,
|
|
5702
|
+
ActionBarPrimitive as ActionBarPrimitive2,
|
|
5703
|
+
AuiIf as AuiIf3,
|
|
5704
|
+
AssistantRuntimeProvider as AssistantRuntimeProvider2,
|
|
5705
|
+
useThread as useThread4,
|
|
5706
|
+
useThreadRuntime as useThreadRuntime4,
|
|
5707
|
+
useMessageRuntime,
|
|
5708
|
+
useComposerRuntime as useComposerRuntime2
|
|
5709
|
+
} from "@assistant-ui/react";
|
|
3793
5710
|
export {
|
|
3794
5711
|
ARTIFACT_AGENT_INSTRUCTIONS,
|
|
3795
5712
|
ARTIFACT_FENCE_LANGUAGES,
|
|
@@ -3798,6 +5715,7 @@ export {
|
|
|
3798
5715
|
ArtifactRegistryProvider,
|
|
3799
5716
|
ArtifactView,
|
|
3800
5717
|
AssistantRuntimeProvider2 as AssistantRuntimeProvider,
|
|
5718
|
+
AuiIf3 as AuiIf,
|
|
3801
5719
|
AuthGuard,
|
|
3802
5720
|
Avatar,
|
|
3803
5721
|
AvatarFallback,
|
|
@@ -3805,8 +5723,6 @@ export {
|
|
|
3805
5723
|
Button,
|
|
3806
5724
|
ChartArtifactView,
|
|
3807
5725
|
Composer,
|
|
3808
|
-
ComposerAddAttachment,
|
|
3809
|
-
ComposerAttachments,
|
|
3810
5726
|
ComposerPrimitive4 as ComposerPrimitive,
|
|
3811
5727
|
DEFAULT_UPLOAD_ACCEPT,
|
|
3812
5728
|
Dialog,
|
|
@@ -3820,17 +5736,21 @@ export {
|
|
|
3820
5736
|
JsonArtifactView,
|
|
3821
5737
|
MarkdownText,
|
|
3822
5738
|
MessagePrimitive3 as MessagePrimitive,
|
|
5739
|
+
ModeToggle,
|
|
3823
5740
|
QuestionArtifactView,
|
|
3824
5741
|
SessionProvider,
|
|
3825
5742
|
Shimmer,
|
|
5743
|
+
StudioSidebar,
|
|
5744
|
+
StudioWelcome,
|
|
3826
5745
|
Suggestions,
|
|
3827
|
-
syntax_highlighter_default as SyntaxHighlighter,
|
|
3828
5746
|
TableArtifactView,
|
|
3829
5747
|
Thread,
|
|
3830
5748
|
ThreadPrimitive2 as ThreadPrimitive,
|
|
3831
5749
|
TimbalChat,
|
|
3832
5750
|
TimbalChatShell,
|
|
5751
|
+
TimbalMark,
|
|
3833
5752
|
TimbalRuntimeProvider,
|
|
5753
|
+
TimbalStudioShell,
|
|
3834
5754
|
ToolArtifactFallback,
|
|
3835
5755
|
ToolFallback,
|
|
3836
5756
|
Tooltip,
|
|
@@ -3842,10 +5762,8 @@ export {
|
|
|
3842
5762
|
UiCustomNodeRegistryProvider,
|
|
3843
5763
|
UiEventProvider,
|
|
3844
5764
|
UiNodeView,
|
|
3845
|
-
UserMessageAttachments,
|
|
3846
5765
|
WorkforceSelector,
|
|
3847
5766
|
authFetch,
|
|
3848
|
-
buttonVariants,
|
|
3849
5767
|
clearTokens,
|
|
3850
5768
|
cn,
|
|
3851
5769
|
createDefaultAttachmentAdapter,
|
|
@@ -3871,12 +5789,14 @@ export {
|
|
|
3871
5789
|
useArtifactRegistry,
|
|
3872
5790
|
useComposerRuntime2 as useComposerRuntime,
|
|
3873
5791
|
useMessageRuntime,
|
|
5792
|
+
useOptionalSession,
|
|
3874
5793
|
useResolvedSuggestions,
|
|
3875
5794
|
useSession,
|
|
3876
|
-
useThread,
|
|
5795
|
+
useThread4 as useThread,
|
|
3877
5796
|
useThreadRuntime4 as useThreadRuntime,
|
|
3878
5797
|
useTimbalRuntime,
|
|
3879
5798
|
useTimbalStream,
|
|
5799
|
+
useToolRunning,
|
|
3880
5800
|
useUiCustomNodeRegistry,
|
|
3881
5801
|
useUiDispatch,
|
|
3882
5802
|
useUiEventEmitter,
|