@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.cjs
CHANGED
|
@@ -32,11 +32,12 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ARTIFACT_AGENT_INSTRUCTIONS: () => ARTIFACT_AGENT_INSTRUCTIONS,
|
|
34
34
|
ARTIFACT_FENCE_LANGUAGES: () => ARTIFACT_FENCE_LANGUAGES,
|
|
35
|
-
ActionBarPrimitive: () =>
|
|
35
|
+
ActionBarPrimitive: () => import_react45.ActionBarPrimitive,
|
|
36
36
|
ArtifactCard: () => ArtifactCard,
|
|
37
37
|
ArtifactRegistryProvider: () => ArtifactRegistryProvider,
|
|
38
38
|
ArtifactView: () => ArtifactView,
|
|
39
|
-
AssistantRuntimeProvider: () =>
|
|
39
|
+
AssistantRuntimeProvider: () => import_react45.AssistantRuntimeProvider,
|
|
40
|
+
AuiIf: () => import_react45.AuiIf,
|
|
40
41
|
AuthGuard: () => AuthGuard,
|
|
41
42
|
Avatar: () => Avatar,
|
|
42
43
|
AvatarFallback: () => AvatarFallback,
|
|
@@ -44,9 +45,7 @@ __export(index_exports, {
|
|
|
44
45
|
Button: () => Button,
|
|
45
46
|
ChartArtifactView: () => ChartArtifactView,
|
|
46
47
|
Composer: () => Composer,
|
|
47
|
-
|
|
48
|
-
ComposerAttachments: () => ComposerAttachments,
|
|
49
|
-
ComposerPrimitive: () => import_react26.ComposerPrimitive,
|
|
48
|
+
ComposerPrimitive: () => import_react45.ComposerPrimitive,
|
|
50
49
|
DEFAULT_UPLOAD_ACCEPT: () => DEFAULT_UPLOAD_ACCEPT,
|
|
51
50
|
Dialog: () => Dialog,
|
|
52
51
|
DialogClose: () => DialogClose,
|
|
@@ -58,18 +57,22 @@ __export(index_exports, {
|
|
|
58
57
|
HtmlArtifactView: () => HtmlArtifactView,
|
|
59
58
|
JsonArtifactView: () => JsonArtifactView,
|
|
60
59
|
MarkdownText: () => MarkdownText,
|
|
61
|
-
MessagePrimitive: () =>
|
|
60
|
+
MessagePrimitive: () => import_react45.MessagePrimitive,
|
|
61
|
+
ModeToggle: () => ModeToggle,
|
|
62
62
|
QuestionArtifactView: () => QuestionArtifactView,
|
|
63
63
|
SessionProvider: () => SessionProvider,
|
|
64
64
|
Shimmer: () => Shimmer,
|
|
65
|
+
StudioSidebar: () => StudioSidebar,
|
|
66
|
+
StudioWelcome: () => StudioWelcome,
|
|
65
67
|
Suggestions: () => Suggestions,
|
|
66
|
-
SyntaxHighlighter: () => syntax_highlighter_default,
|
|
67
68
|
TableArtifactView: () => TableArtifactView,
|
|
68
69
|
Thread: () => Thread,
|
|
69
|
-
ThreadPrimitive: () =>
|
|
70
|
+
ThreadPrimitive: () => import_react45.ThreadPrimitive,
|
|
70
71
|
TimbalChat: () => TimbalChat,
|
|
71
72
|
TimbalChatShell: () => TimbalChatShell,
|
|
73
|
+
TimbalMark: () => TimbalMark,
|
|
72
74
|
TimbalRuntimeProvider: () => TimbalRuntimeProvider,
|
|
75
|
+
TimbalStudioShell: () => TimbalStudioShell,
|
|
73
76
|
ToolArtifactFallback: () => ToolArtifactFallback,
|
|
74
77
|
ToolFallback: () => ToolFallback,
|
|
75
78
|
Tooltip: () => Tooltip,
|
|
@@ -81,10 +84,8 @@ __export(index_exports, {
|
|
|
81
84
|
UiCustomNodeRegistryProvider: () => UiCustomNodeRegistryProvider,
|
|
82
85
|
UiEventProvider: () => UiEventProvider,
|
|
83
86
|
UiNodeView: () => UiNodeView,
|
|
84
|
-
UserMessageAttachments: () => UserMessageAttachments,
|
|
85
87
|
WorkforceSelector: () => WorkforceSelector,
|
|
86
88
|
authFetch: () => authFetch,
|
|
87
|
-
buttonVariants: () => buttonVariants,
|
|
88
89
|
clearTokens: () => clearTokens,
|
|
89
90
|
cn: () => cn,
|
|
90
91
|
createDefaultAttachmentAdapter: () => createDefaultAttachmentAdapter,
|
|
@@ -108,14 +109,16 @@ __export(index_exports, {
|
|
|
108
109
|
setRefreshToken: () => setRefreshToken,
|
|
109
110
|
splitMarkdownByArtifacts: () => splitMarkdownByArtifacts,
|
|
110
111
|
useArtifactRegistry: () => useArtifactRegistry,
|
|
111
|
-
useComposerRuntime: () =>
|
|
112
|
-
useMessageRuntime: () =>
|
|
112
|
+
useComposerRuntime: () => import_react45.useComposerRuntime,
|
|
113
|
+
useMessageRuntime: () => import_react45.useMessageRuntime,
|
|
114
|
+
useOptionalSession: () => useOptionalSession,
|
|
113
115
|
useResolvedSuggestions: () => useResolvedSuggestions,
|
|
114
116
|
useSession: () => useSession,
|
|
115
|
-
useThread: () =>
|
|
116
|
-
useThreadRuntime: () =>
|
|
117
|
+
useThread: () => import_react45.useThread,
|
|
118
|
+
useThreadRuntime: () => import_react45.useThreadRuntime,
|
|
117
119
|
useTimbalRuntime: () => useTimbalRuntime,
|
|
118
120
|
useTimbalStream: () => useTimbalStream,
|
|
121
|
+
useToolRunning: () => useToolRunning,
|
|
119
122
|
useUiCustomNodeRegistry: () => useUiCustomNodeRegistry,
|
|
120
123
|
useUiDispatch: () => useUiDispatch,
|
|
121
124
|
useUiEventEmitter: () => useUiEventEmitter,
|
|
@@ -982,6 +985,12 @@ function findParentIdFromAuiParent(messages, auiParentId) {
|
|
|
982
985
|
// src/index.ts
|
|
983
986
|
var import_timbal_sdk2 = require("@timbal-ai/timbal-sdk");
|
|
984
987
|
|
|
988
|
+
// src/components/thread.tsx
|
|
989
|
+
var import_react25 = require("react");
|
|
990
|
+
var import_react26 = require("@assistant-ui/react");
|
|
991
|
+
var import_lucide_react8 = require("lucide-react");
|
|
992
|
+
var import_react27 = require("motion/react");
|
|
993
|
+
|
|
985
994
|
// src/components/attachment.tsx
|
|
986
995
|
var import_react4 = require("react");
|
|
987
996
|
var import_lucide_react2 = require("lucide-react");
|
|
@@ -1189,83 +1198,166 @@ function AvatarFallback({
|
|
|
1189
1198
|
|
|
1190
1199
|
// src/components/tooltip-icon-button.tsx
|
|
1191
1200
|
var import_react3 = require("react");
|
|
1192
|
-
var import_react_slot = require("@radix-ui/react-slot");
|
|
1193
1201
|
|
|
1194
|
-
// src/ui/button.tsx
|
|
1195
|
-
var
|
|
1202
|
+
// src/ui/timbal-v2-button.tsx
|
|
1203
|
+
var React = __toESM(require("react"), 1);
|
|
1196
1204
|
var import_radix_ui4 = require("radix-ui");
|
|
1205
|
+
|
|
1206
|
+
// src/design/button-tokens.ts
|
|
1207
|
+
var TIMBAL_V2_SIZE_HEIGHT = {
|
|
1208
|
+
xs: "min-h-8 h-8",
|
|
1209
|
+
sm: "min-h-9 h-9",
|
|
1210
|
+
md: "min-h-10 h-10",
|
|
1211
|
+
lg: "min-h-11 h-11"
|
|
1212
|
+
};
|
|
1213
|
+
var TIMBAL_V2_SIZE_ICON = {
|
|
1214
|
+
xs: "min-h-8 min-w-8 size-8",
|
|
1215
|
+
sm: "min-h-8 min-w-8 size-8",
|
|
1216
|
+
md: "min-h-10 min-w-10 size-10",
|
|
1217
|
+
lg: "min-h-11 min-w-11 size-11"
|
|
1218
|
+
};
|
|
1219
|
+
var TIMBAL_V2_SIZE_LABEL_PX = {
|
|
1220
|
+
xs: "px-3",
|
|
1221
|
+
sm: "px-4",
|
|
1222
|
+
md: "px-5",
|
|
1223
|
+
lg: "px-6"
|
|
1224
|
+
};
|
|
1225
|
+
var TIMBAL_V2_FILL = {
|
|
1226
|
+
primary: [
|
|
1227
|
+
"bg-gradient-to-b from-primary-fill-from to-primary-fill-to",
|
|
1228
|
+
"group-hover/tbv2:from-primary-fill-hover-from group-hover/tbv2:to-primary-fill-hover-to",
|
|
1229
|
+
"group-active/tbv2:from-primary-fill-active-from group-active/tbv2:to-primary-fill-active-to"
|
|
1230
|
+
].join(" "),
|
|
1231
|
+
informative: [
|
|
1232
|
+
"bg-primary",
|
|
1233
|
+
"group-active/tbv2:[background-image:linear-gradient(to_top,rgba(0,0,0,0.08),transparent_55%)]"
|
|
1234
|
+
].join(" "),
|
|
1235
|
+
destructive: [
|
|
1236
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to",
|
|
1237
|
+
"group-hover/tbv2:from-destructive-fill-hover-from group-hover/tbv2:to-destructive-fill-hover-to",
|
|
1238
|
+
"group-active/tbv2:from-destructive-fill-active-from group-active/tbv2:to-destructive-fill-active-to"
|
|
1239
|
+
].join(" "),
|
|
1240
|
+
secondary: [
|
|
1241
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to",
|
|
1242
|
+
"group-hover/tbv2:from-secondary-fill-hover-from group-hover/tbv2:to-secondary-fill-hover-to",
|
|
1243
|
+
"group-active/tbv2:from-secondary-fill-active-from group-active/tbv2:to-secondary-fill-active-to"
|
|
1244
|
+
].join(" "),
|
|
1245
|
+
ghost: [
|
|
1246
|
+
"bg-transparent",
|
|
1247
|
+
"group-hover/tbv2:bg-ghost-fill-hover",
|
|
1248
|
+
"group-active/tbv2:bg-ghost-fill-active"
|
|
1249
|
+
].join(" "),
|
|
1250
|
+
link: "bg-transparent"
|
|
1251
|
+
};
|
|
1252
|
+
var TIMBAL_V2_LABEL = {
|
|
1253
|
+
primary: "text-primary-foreground",
|
|
1254
|
+
informative: "text-primary-foreground",
|
|
1255
|
+
destructive: "text-destructive",
|
|
1256
|
+
secondary: "text-foreground",
|
|
1257
|
+
ghost: "text-foreground",
|
|
1258
|
+
link: "text-foreground underline decoration-foreground/25 underline-offset-2 group-hover/tbv2:decoration-foreground/45"
|
|
1259
|
+
};
|
|
1260
|
+
var TIMBAL_V2_BORDER = {
|
|
1261
|
+
primary: "",
|
|
1262
|
+
informative: "border border-foreground/15",
|
|
1263
|
+
destructive: "border border-destructive/45",
|
|
1264
|
+
secondary: "border border-border",
|
|
1265
|
+
ghost: "",
|
|
1266
|
+
link: ""
|
|
1267
|
+
};
|
|
1268
|
+
var TIMBAL_V2_SHADOW = {
|
|
1269
|
+
primary: "shadow-card",
|
|
1270
|
+
informative: "shadow-card",
|
|
1271
|
+
destructive: "shadow-card",
|
|
1272
|
+
secondary: "shadow-card",
|
|
1273
|
+
ghost: "",
|
|
1274
|
+
link: ""
|
|
1275
|
+
};
|
|
1276
|
+
var TIMBAL_V2_SECONDARY_CHROME = [
|
|
1277
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to border border-border shadow-card",
|
|
1278
|
+
"transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
|
|
1279
|
+
"hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to",
|
|
1280
|
+
"active:from-secondary-fill-active-from active:to-secondary-fill-active-to"
|
|
1281
|
+
].join(" ");
|
|
1282
|
+
|
|
1283
|
+
// src/ui/timbal-v2-button.tsx
|
|
1197
1284
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1198
|
-
var
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
1205
|
-
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
1206
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
1207
|
-
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
1208
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
1209
|
-
},
|
|
1210
|
-
size: {
|
|
1211
|
-
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
1212
|
-
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
1213
|
-
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
1214
|
-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
1215
|
-
icon: "size-9",
|
|
1216
|
-
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
1217
|
-
"icon-sm": "size-8",
|
|
1218
|
-
"icon-lg": "size-10"
|
|
1219
|
-
}
|
|
1220
|
-
},
|
|
1221
|
-
defaultVariants: {
|
|
1222
|
-
variant: "default",
|
|
1223
|
-
size: "default"
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
);
|
|
1227
|
-
function Button({
|
|
1228
|
-
className,
|
|
1229
|
-
variant = "default",
|
|
1230
|
-
size = "default",
|
|
1285
|
+
var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
|
|
1286
|
+
variant = "secondary",
|
|
1287
|
+
size = "sm",
|
|
1288
|
+
isIconOnly = false,
|
|
1289
|
+
isLoading = false,
|
|
1290
|
+
fullWidth = false,
|
|
1231
1291
|
asChild = false,
|
|
1292
|
+
className,
|
|
1293
|
+
disabled,
|
|
1294
|
+
type = "button",
|
|
1295
|
+
children,
|
|
1232
1296
|
...props
|
|
1233
|
-
}) {
|
|
1297
|
+
}, ref) {
|
|
1298
|
+
const isDisabled = disabled || isLoading;
|
|
1234
1299
|
const Comp = asChild ? import_radix_ui4.Slot.Root : "button";
|
|
1235
|
-
|
|
1300
|
+
const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
|
|
1301
|
+
const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : "rounded-full";
|
|
1302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1236
1303
|
Comp,
|
|
1237
1304
|
{
|
|
1238
|
-
|
|
1305
|
+
ref,
|
|
1306
|
+
type: asChild ? void 0 : type,
|
|
1307
|
+
disabled: asChild ? void 0 : isDisabled,
|
|
1308
|
+
"aria-disabled": asChild && isDisabled ? true : void 0,
|
|
1309
|
+
"data-slot": "timbal-v2-button",
|
|
1239
1310
|
"data-variant": variant,
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1311
|
+
className: cn(
|
|
1312
|
+
"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",
|
|
1313
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
|
1314
|
+
sizeClass,
|
|
1315
|
+
radiusClass,
|
|
1316
|
+
TIMBAL_V2_BORDER[variant],
|
|
1317
|
+
TIMBAL_V2_SHADOW[variant],
|
|
1318
|
+
fullWidth && "w-full",
|
|
1319
|
+
isDisabled && "pointer-events-none opacity-50",
|
|
1320
|
+
className
|
|
1321
|
+
),
|
|
1322
|
+
...props,
|
|
1323
|
+
children: [
|
|
1324
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1325
|
+
"span",
|
|
1326
|
+
{
|
|
1327
|
+
"aria-hidden": true,
|
|
1328
|
+
className: cn(
|
|
1329
|
+
"pointer-events-none absolute inset-0 transition duration-200 ease-in-out",
|
|
1330
|
+
TIMBAL_V2_FILL[variant]
|
|
1331
|
+
)
|
|
1332
|
+
}
|
|
1333
|
+
),
|
|
1334
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1335
|
+
"span",
|
|
1336
|
+
{
|
|
1337
|
+
className: cn(
|
|
1338
|
+
"relative z-10 flex min-h-0 flex-1 items-center justify-center gap-1 leading-tight",
|
|
1339
|
+
!isIconOnly && TIMBAL_V2_SIZE_LABEL_PX[size],
|
|
1340
|
+
TIMBAL_V2_LABEL[variant]
|
|
1341
|
+
),
|
|
1342
|
+
children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : children
|
|
1343
|
+
}
|
|
1344
|
+
)
|
|
1345
|
+
]
|
|
1243
1346
|
}
|
|
1244
1347
|
);
|
|
1245
|
-
}
|
|
1348
|
+
});
|
|
1246
1349
|
|
|
1247
1350
|
// src/components/tooltip-icon-button.tsx
|
|
1248
1351
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1249
|
-
var TooltipIconButton = (0, import_react3.forwardRef)(({
|
|
1352
|
+
var TooltipIconButton = (0, import_react3.forwardRef)(function TooltipIconButton2({ tooltip, side = "bottom", variant = "secondary", children, ...props }, ref) {
|
|
1250
1353
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Tooltip, { children: [
|
|
1251
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1252
|
-
|
|
1253
|
-
{
|
|
1254
|
-
|
|
1255
|
-
size: "icon",
|
|
1256
|
-
...rest,
|
|
1257
|
-
className: cn("aui-button-icon size-6 p-1", className),
|
|
1258
|
-
ref,
|
|
1259
|
-
children: [
|
|
1260
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_slot.Slottable, { children }),
|
|
1261
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "aui-sr-only sr-only", children: tooltip })
|
|
1262
|
-
]
|
|
1263
|
-
}
|
|
1264
|
-
) }),
|
|
1354
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(TimbalV2Button, { ref, variant, size: "sm", isIconOnly: true, ...props, children: [
|
|
1355
|
+
children,
|
|
1356
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sr-only", children: tooltip })
|
|
1357
|
+
] }) }),
|
|
1265
1358
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipContent, { side, children: tooltip })
|
|
1266
1359
|
] });
|
|
1267
1360
|
});
|
|
1268
|
-
TooltipIconButton.displayName = "TooltipIconButton";
|
|
1269
1361
|
|
|
1270
1362
|
// src/components/attachment.tsx
|
|
1271
1363
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
@@ -1395,9 +1487,9 @@ var AttachmentRemove = () => {
|
|
|
1395
1487
|
TooltipIconButton,
|
|
1396
1488
|
{
|
|
1397
1489
|
tooltip: "Remove file",
|
|
1398
|
-
className: "aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-
|
|
1490
|
+
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",
|
|
1399
1491
|
side: "top",
|
|
1400
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.XIcon, { className: "aui-attachment-remove-icon size-3
|
|
1492
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.XIcon, { className: "aui-attachment-remove-icon size-3" })
|
|
1401
1493
|
}
|
|
1402
1494
|
) });
|
|
1403
1495
|
};
|
|
@@ -1418,11 +1510,10 @@ var ComposerAddAttachment = () => {
|
|
|
1418
1510
|
{
|
|
1419
1511
|
tooltip: "Add Attachment",
|
|
1420
1512
|
side: "bottom",
|
|
1421
|
-
variant: "
|
|
1422
|
-
|
|
1423
|
-
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",
|
|
1513
|
+
variant: "secondary",
|
|
1514
|
+
className: "aui-composer-add-attachment shrink-0 text-muted-foreground",
|
|
1424
1515
|
"aria-label": "Add Attachment",
|
|
1425
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.PlusIcon, { className: "aui-attachment-add-icon size-
|
|
1516
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.PlusIcon, { className: "aui-attachment-add-icon size-4 stroke-[1.5]" })
|
|
1426
1517
|
}
|
|
1427
1518
|
) });
|
|
1428
1519
|
};
|
|
@@ -1769,86 +1860,205 @@ function formatTick(v, unit) {
|
|
|
1769
1860
|
var import_react7 = require("react");
|
|
1770
1861
|
var import_react8 = require("@assistant-ui/react");
|
|
1771
1862
|
var import_lucide_react3 = require("lucide-react");
|
|
1863
|
+
|
|
1864
|
+
// src/design/classes.ts
|
|
1865
|
+
var studioTopbarPillHeightClass = "h-[var(--studio-chrome-pill-height)] min-h-[var(--studio-chrome-pill-height)]";
|
|
1866
|
+
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)]";
|
|
1867
|
+
var studioPlaygroundGradientClass = "bg-gradient-to-b from-playground-from via-playground-via to-playground-to";
|
|
1868
|
+
var studioComposeInputShellClass = cn(
|
|
1869
|
+
"flex w-full flex-col rounded-2xl bg-composer-bg shadow-card-elevated outline-none",
|
|
1870
|
+
"border border-composer-border",
|
|
1871
|
+
"transition-[box-shadow,border-color]",
|
|
1872
|
+
"focus-within:border-composer-border-focus focus-within:ring-2 focus-within:ring-foreground/5"
|
|
1873
|
+
);
|
|
1874
|
+
var studioSecondaryChromeClass = TIMBAL_V2_SECONDARY_CHROME;
|
|
1875
|
+
var studioIntegrationSurfaceSolid = "bg-gradient-to-b from-elevated-from to-elevated-to shadow-card";
|
|
1876
|
+
var studioIntegrationBorder = "border border-border";
|
|
1877
|
+
var studioIntegrationCardClass = cn(
|
|
1878
|
+
"rounded-xl",
|
|
1879
|
+
studioIntegrationSurfaceSolid,
|
|
1880
|
+
studioIntegrationBorder
|
|
1881
|
+
);
|
|
1882
|
+
var studioIntegrationIconTileClass = cn(
|
|
1883
|
+
"flex size-9 shrink-0 items-center justify-center rounded-lg",
|
|
1884
|
+
studioIntegrationSurfaceSolid,
|
|
1885
|
+
studioIntegrationBorder
|
|
1886
|
+
);
|
|
1887
|
+
var studioListRowButtonClass = cn(
|
|
1888
|
+
"flex w-full cursor-pointer items-center gap-3 rounded-xl px-3 py-2.5 text-left",
|
|
1889
|
+
studioIntegrationCardClass,
|
|
1890
|
+
"transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
|
|
1891
|
+
"hover:border-foreground/20",
|
|
1892
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
|
1893
|
+
);
|
|
1894
|
+
var studioComposerIoWellClass = cn(
|
|
1895
|
+
"rounded-lg",
|
|
1896
|
+
studioIntegrationSurfaceSolid,
|
|
1897
|
+
studioIntegrationBorder
|
|
1898
|
+
);
|
|
1899
|
+
var studioToolCardShellClass = cn(
|
|
1900
|
+
studioIntegrationCardClass,
|
|
1901
|
+
"my-2 min-h-0 overflow-hidden"
|
|
1902
|
+
);
|
|
1903
|
+
var studioSidebarPanelClass = cn(
|
|
1904
|
+
"bg-sidebar text-sidebar-foreground",
|
|
1905
|
+
"border border-sidebar-border",
|
|
1906
|
+
"shadow-card-elevated"
|
|
1907
|
+
);
|
|
1908
|
+
var studioSidebarNavItemClass = cn(
|
|
1909
|
+
"flex items-center rounded-lg text-sm",
|
|
1910
|
+
"transition-[color,background-color,box-shadow,border-color] duration-200 ease-in-out",
|
|
1911
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2"
|
|
1912
|
+
);
|
|
1913
|
+
function studioSidebarNavItemLayout(iconOnly) {
|
|
1914
|
+
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";
|
|
1915
|
+
}
|
|
1916
|
+
var studioSidebarNavItemSurfaceClass = cn(
|
|
1917
|
+
"bg-gradient-to-b from-elevated-from to-elevated-to text-foreground",
|
|
1918
|
+
"border border-border",
|
|
1919
|
+
"shadow-card"
|
|
1920
|
+
);
|
|
1921
|
+
var studioSidebarNavItemIdleClass = cn(
|
|
1922
|
+
"border border-transparent text-muted-foreground shadow-none",
|
|
1923
|
+
"hover:text-foreground",
|
|
1924
|
+
"hover:bg-gradient-to-b hover:from-elevated-from hover:to-elevated-to",
|
|
1925
|
+
"hover:border-border hover:shadow-card"
|
|
1926
|
+
);
|
|
1927
|
+
var studioSidebarCollapsedRailItemClass = cn(
|
|
1928
|
+
"border border-border shadow-card bg-sidebar-accent"
|
|
1929
|
+
);
|
|
1930
|
+
var studioSidebarCollapsedRailItemIdleClass = cn(
|
|
1931
|
+
studioSidebarCollapsedRailItemClass,
|
|
1932
|
+
"text-muted-foreground hover:text-foreground"
|
|
1933
|
+
);
|
|
1934
|
+
var studioSidebarCollapsedRailItemActiveClass = cn(
|
|
1935
|
+
studioSidebarCollapsedRailItemClass,
|
|
1936
|
+
studioSidebarNavItemSurfaceClass,
|
|
1937
|
+
"text-foreground"
|
|
1938
|
+
);
|
|
1939
|
+
var studioSidebarNavItemActiveClass = studioSidebarNavItemSurfaceClass;
|
|
1940
|
+
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";
|
|
1941
|
+
var studioTimelineTextClass = "text-xs font-normal leading-snug";
|
|
1942
|
+
var studioTimelineActionClass = cn(
|
|
1943
|
+
studioTimelineTextClass,
|
|
1944
|
+
"shrink-0 text-foreground/70 transition-colors duration-150 group-hover:text-foreground/80"
|
|
1945
|
+
);
|
|
1946
|
+
var studioTimelineShimmerActionClass = cn(
|
|
1947
|
+
studioTimelineTextClass,
|
|
1948
|
+
"shrink-0"
|
|
1949
|
+
);
|
|
1950
|
+
var studioTimelineDetailClass = cn(
|
|
1951
|
+
studioTimelineTextClass,
|
|
1952
|
+
"min-w-0 truncate text-muted-foreground transition-colors duration-150"
|
|
1953
|
+
);
|
|
1954
|
+
function studioTimelineChevronClass(expanded) {
|
|
1955
|
+
return cn(
|
|
1956
|
+
"ml-0.5 size-3 min-h-3 min-w-3 shrink-0 transition-all duration-150",
|
|
1957
|
+
expanded ? "rotate-90 text-foreground opacity-60" : "text-muted-foreground opacity-0 group-hover:opacity-70"
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
var studioTimelineBodyPadClass = "flex flex-col gap-2 pt-0.5 pb-0.5";
|
|
1961
|
+
var studioArtifactShellClass = cn(
|
|
1962
|
+
studioIntegrationCardClass,
|
|
1963
|
+
"my-2 w-full min-w-0 overflow-hidden"
|
|
1964
|
+
);
|
|
1965
|
+
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";
|
|
1966
|
+
var studioQuestionOptionSelectedClass = cn(
|
|
1967
|
+
studioQuestionOptionClass,
|
|
1968
|
+
"border-border bg-accent ring-1 ring-foreground/10"
|
|
1969
|
+
);
|
|
1970
|
+
|
|
1971
|
+
// src/artifacts/question-artifact.tsx
|
|
1772
1972
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1973
|
+
function optionKey(option, index) {
|
|
1974
|
+
const id = option.id?.trim();
|
|
1975
|
+
return id ? id : `__option-${index}`;
|
|
1976
|
+
}
|
|
1977
|
+
var OptionRadio = ({ selected }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1978
|
+
"span",
|
|
1979
|
+
{
|
|
1980
|
+
className: cn(
|
|
1981
|
+
"flex size-4 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
|
|
1982
|
+
selected ? "border-foreground bg-foreground text-background" : "border-border bg-background"
|
|
1983
|
+
),
|
|
1984
|
+
"aria-hidden": true,
|
|
1985
|
+
children: selected ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.CheckIcon, { className: "size-2.5 stroke-[3]" }) : null
|
|
1986
|
+
}
|
|
1987
|
+
);
|
|
1773
1988
|
var QuestionArtifactView = ({
|
|
1774
1989
|
artifact
|
|
1775
1990
|
}) => {
|
|
1776
1991
|
const runtime = (0, import_react8.useThreadRuntime)();
|
|
1777
1992
|
const [selected, setSelected] = (0, import_react7.useState)([]);
|
|
1778
|
-
const [
|
|
1993
|
+
const [submittedIds, setSubmittedIds] = (0, import_react7.useState)(null);
|
|
1779
1994
|
const isMulti = artifact.multi === true;
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
)
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1995
|
+
const isDisabled = submittedIds !== null;
|
|
1996
|
+
const send = (0, import_react7.useCallback)(
|
|
1997
|
+
(keys) => {
|
|
1998
|
+
if (keys.length === 0) return;
|
|
1999
|
+
const labels = artifact.options.map((option, index) => ({ option, key: optionKey(option, index) })).filter(({ key }) => keys.includes(key)).map(({ option }) => option.label);
|
|
2000
|
+
setSubmittedIds(keys);
|
|
2001
|
+
runtime.append({
|
|
2002
|
+
role: "user",
|
|
2003
|
+
content: [{ type: "text", text: labels.join(", ") }]
|
|
2004
|
+
});
|
|
2005
|
+
},
|
|
2006
|
+
[artifact.options, runtime]
|
|
2007
|
+
);
|
|
2008
|
+
const onPick = (0, import_react7.useCallback)(
|
|
2009
|
+
(key) => {
|
|
2010
|
+
if (isDisabled) return;
|
|
2011
|
+
if (!isMulti) {
|
|
2012
|
+
send([key]);
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
setSelected(
|
|
2016
|
+
(prev) => prev.includes(key) ? prev.filter((id) => id !== key) : [...prev, key]
|
|
2017
|
+
);
|
|
2018
|
+
},
|
|
2019
|
+
[isDisabled, isMulti, send]
|
|
2020
|
+
);
|
|
2021
|
+
const onConfirm = (0, import_react7.useCallback)(() => {
|
|
2022
|
+
send(selected);
|
|
2023
|
+
}, [selected, send]);
|
|
2024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: studioArtifactShellClass, "data-artifact-kind": "question", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-2.5 py-2", children: [
|
|
2025
|
+
artifact.prompt ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "mb-2 text-sm font-normal leading-snug text-foreground", children: artifact.prompt }) : null,
|
|
2026
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex flex-col gap-0.5", role: "list", children: artifact.options.map((option, index) => {
|
|
2027
|
+
const key = optionKey(option, index);
|
|
2028
|
+
const isSelected = submittedIds ? submittedIds.includes(key) : isMulti && selected.includes(key);
|
|
1805
2029
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1806
2030
|
"button",
|
|
1807
2031
|
{
|
|
1808
2032
|
type: "button",
|
|
2033
|
+
role: "listitem",
|
|
1809
2034
|
disabled: isDisabled,
|
|
1810
|
-
onClick: () => onPick(
|
|
2035
|
+
onClick: () => onPick(key),
|
|
1811
2036
|
className: cn(
|
|
1812
|
-
|
|
1813
|
-
"
|
|
1814
|
-
isSelected && "border-primary/60 bg-primary/5",
|
|
1815
|
-
isDisabled && "cursor-not-allowed opacity-60 hover:border-border/60 hover:bg-transparent"
|
|
2037
|
+
isSelected ? studioQuestionOptionSelectedClass : studioQuestionOptionClass,
|
|
2038
|
+
isDisabled && (isSelected ? "cursor-default" : "cursor-not-allowed opacity-50")
|
|
1816
2039
|
),
|
|
1817
2040
|
children: [
|
|
1818
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1819
|
-
|
|
1820
|
-
{
|
|
1821
|
-
|
|
1822
|
-
"flex size-4 shrink-0 items-center justify-center rounded-full border",
|
|
1823
|
-
isSelected ? "border-primary bg-primary text-primary-foreground" : "border-border"
|
|
1824
|
-
),
|
|
1825
|
-
"aria-hidden": true,
|
|
1826
|
-
children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.CheckIcon, { className: "size-3" })
|
|
1827
|
-
}
|
|
1828
|
-
),
|
|
1829
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "aui-artifact-question-option-text flex-1", children: [
|
|
1830
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "font-medium text-foreground/90", children: option.label }),
|
|
1831
|
-
option.description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-xs text-muted-foreground", children: option.description })
|
|
2041
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(OptionRadio, { selected: isSelected }),
|
|
2042
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "min-w-0 flex-1 text-left", children: [
|
|
2043
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "block font-normal text-foreground", children: option.label }),
|
|
2044
|
+
option.description ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
|
|
1832
2045
|
] })
|
|
1833
2046
|
]
|
|
1834
2047
|
},
|
|
1835
|
-
|
|
2048
|
+
key
|
|
1836
2049
|
);
|
|
1837
2050
|
}) }),
|
|
1838
|
-
isMulti && !
|
|
1839
|
-
|
|
2051
|
+
isMulti && !submittedIds ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2052
|
+
TimbalV2Button,
|
|
1840
2053
|
{
|
|
1841
2054
|
type: "button",
|
|
2055
|
+
variant: "primary",
|
|
1842
2056
|
size: "sm",
|
|
1843
2057
|
disabled: selected.length === 0,
|
|
1844
2058
|
onClick: onConfirm,
|
|
1845
2059
|
children: "Confirm"
|
|
1846
2060
|
}
|
|
1847
|
-
) })
|
|
1848
|
-
submitted && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "aui-artifact-question-submitted mt-2 text-xs text-muted-foreground", children: [
|
|
1849
|
-
"Sent: ",
|
|
1850
|
-
submitted
|
|
1851
|
-
] })
|
|
2061
|
+
) }) : null
|
|
1852
2062
|
] }) });
|
|
1853
2063
|
};
|
|
1854
2064
|
|
|
@@ -2019,29 +2229,84 @@ function useUiCustomNodeRegistry() {
|
|
|
2019
2229
|
var import_react10 = require("react");
|
|
2020
2230
|
var import_react11 = require("motion/react");
|
|
2021
2231
|
var import_react12 = require("@assistant-ui/react");
|
|
2232
|
+
|
|
2233
|
+
// src/ui/button.tsx
|
|
2234
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
2235
|
+
var import_radix_ui5 = require("radix-ui");
|
|
2022
2236
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2237
|
+
var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
2238
|
+
"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",
|
|
2239
|
+
{
|
|
2240
|
+
variants: {
|
|
2241
|
+
variant: {
|
|
2242
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2243
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/30",
|
|
2244
|
+
outline: "border border-border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
|
|
2245
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2246
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
2247
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
2248
|
+
},
|
|
2249
|
+
size: {
|
|
2250
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2251
|
+
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
2252
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
2253
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2254
|
+
icon: "size-9",
|
|
2255
|
+
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
2256
|
+
"icon-sm": "size-8",
|
|
2257
|
+
"icon-lg": "size-10"
|
|
2258
|
+
}
|
|
2259
|
+
},
|
|
2260
|
+
defaultVariants: {
|
|
2261
|
+
variant: "default",
|
|
2262
|
+
size: "default"
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
);
|
|
2266
|
+
function Button({
|
|
2267
|
+
className,
|
|
2268
|
+
variant = "default",
|
|
2269
|
+
size = "default",
|
|
2270
|
+
asChild = false,
|
|
2271
|
+
...props
|
|
2272
|
+
}) {
|
|
2273
|
+
const Comp = asChild ? import_radix_ui5.Slot.Root : "button";
|
|
2274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2275
|
+
Comp,
|
|
2276
|
+
{
|
|
2277
|
+
"data-slot": "button",
|
|
2278
|
+
"data-variant": variant,
|
|
2279
|
+
"data-size": size,
|
|
2280
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
2281
|
+
...props
|
|
2282
|
+
}
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
// src/artifacts/ui/nodes.tsx
|
|
2287
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2023
2288
|
var UiNodeView = ({ node }) => {
|
|
2024
2289
|
switch (node.kind) {
|
|
2025
2290
|
case "box":
|
|
2026
|
-
return /* @__PURE__ */ (0,
|
|
2291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BoxNode, { node });
|
|
2027
2292
|
case "text":
|
|
2028
|
-
return /* @__PURE__ */ (0,
|
|
2293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TextNode, { node });
|
|
2029
2294
|
case "heading":
|
|
2030
|
-
return /* @__PURE__ */ (0,
|
|
2295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(HeadingNode, { node });
|
|
2031
2296
|
case "badge":
|
|
2032
|
-
return /* @__PURE__ */ (0,
|
|
2297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BadgeNode, { node });
|
|
2033
2298
|
case "button":
|
|
2034
|
-
return /* @__PURE__ */ (0,
|
|
2299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ButtonNode, { node });
|
|
2035
2300
|
case "toggle":
|
|
2036
|
-
return /* @__PURE__ */ (0,
|
|
2301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToggleNode, { node });
|
|
2037
2302
|
case "slider":
|
|
2038
|
-
return /* @__PURE__ */ (0,
|
|
2303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SliderNode, { node });
|
|
2039
2304
|
case "tooltip":
|
|
2040
|
-
return /* @__PURE__ */ (0,
|
|
2305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipNode, { node });
|
|
2041
2306
|
case "draggable":
|
|
2042
|
-
return /* @__PURE__ */ (0,
|
|
2307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DraggableNode, { node });
|
|
2043
2308
|
case "custom":
|
|
2044
|
-
return /* @__PURE__ */ (0,
|
|
2309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CustomNode, { node });
|
|
2045
2310
|
default:
|
|
2046
2311
|
return null;
|
|
2047
2312
|
}
|
|
@@ -2101,7 +2366,7 @@ var JUSTIFY_CLS = {
|
|
|
2101
2366
|
};
|
|
2102
2367
|
var BoxNode = ({ node }) => {
|
|
2103
2368
|
const dir = node.direction ?? "col";
|
|
2104
|
-
return /* @__PURE__ */ (0,
|
|
2369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2105
2370
|
"div",
|
|
2106
2371
|
{
|
|
2107
2372
|
className: cn(
|
|
@@ -2116,7 +2381,7 @@ var BoxNode = ({ node }) => {
|
|
|
2116
2381
|
gap: node.gap !== void 0 ? `${node.gap * 0.25}rem` : void 0,
|
|
2117
2382
|
padding: node.padding !== void 0 ? `${node.padding * 0.25}rem` : void 0
|
|
2118
2383
|
},
|
|
2119
|
-
children: node.children?.map((child, i) => /* @__PURE__ */ (0,
|
|
2384
|
+
children: node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: child }, child.id ?? i))
|
|
2120
2385
|
}
|
|
2121
2386
|
);
|
|
2122
2387
|
};
|
|
@@ -2135,7 +2400,7 @@ var TEXT_WEIGHT = {
|
|
|
2135
2400
|
var TextNode = ({ node }) => {
|
|
2136
2401
|
const state = useUiState();
|
|
2137
2402
|
const value = resolveBindable(node.value, state);
|
|
2138
|
-
return /* @__PURE__ */ (0,
|
|
2403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2139
2404
|
"span",
|
|
2140
2405
|
{
|
|
2141
2406
|
className: cn(
|
|
@@ -2166,13 +2431,13 @@ var HeadingNode = ({ node }) => {
|
|
|
2166
2431
|
);
|
|
2167
2432
|
switch (level) {
|
|
2168
2433
|
case 1:
|
|
2169
|
-
return /* @__PURE__ */ (0,
|
|
2434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h1", { className: cls, children: value });
|
|
2170
2435
|
case 2:
|
|
2171
|
-
return /* @__PURE__ */ (0,
|
|
2436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: cls, children: value });
|
|
2172
2437
|
case 3:
|
|
2173
|
-
return /* @__PURE__ */ (0,
|
|
2438
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: cls, children: value });
|
|
2174
2439
|
case 4:
|
|
2175
|
-
return /* @__PURE__ */ (0,
|
|
2440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h4", { className: cls, children: value });
|
|
2176
2441
|
}
|
|
2177
2442
|
};
|
|
2178
2443
|
var BADGE_TONE = {
|
|
@@ -2185,7 +2450,7 @@ var BADGE_TONE = {
|
|
|
2185
2450
|
var BadgeNode = ({ node }) => {
|
|
2186
2451
|
const state = useUiState();
|
|
2187
2452
|
const value = String(resolveBindable(node.value, state) ?? "");
|
|
2188
|
-
return /* @__PURE__ */ (0,
|
|
2453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2189
2454
|
"span",
|
|
2190
2455
|
{
|
|
2191
2456
|
className: cn(
|
|
@@ -2202,7 +2467,7 @@ var ButtonNode = ({ node }) => {
|
|
|
2202
2467
|
const run = useActionRunner();
|
|
2203
2468
|
const label = String(resolveBindable(node.label, state) ?? "");
|
|
2204
2469
|
const disabled = node.disabled !== void 0 ? Boolean(resolveBindable(node.disabled, state)) : false;
|
|
2205
|
-
return /* @__PURE__ */ (0,
|
|
2470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2206
2471
|
Button,
|
|
2207
2472
|
{
|
|
2208
2473
|
variant: node.variant ?? "default",
|
|
@@ -2224,7 +2489,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2224
2489
|
dispatch({ type: "toggle", path: node.binding });
|
|
2225
2490
|
run(node.onChange);
|
|
2226
2491
|
};
|
|
2227
|
-
return /* @__PURE__ */ (0,
|
|
2492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
2228
2493
|
"label",
|
|
2229
2494
|
{
|
|
2230
2495
|
className: cn(
|
|
@@ -2232,7 +2497,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2232
2497
|
node.className
|
|
2233
2498
|
),
|
|
2234
2499
|
children: [
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2500
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2236
2501
|
"button",
|
|
2237
2502
|
{
|
|
2238
2503
|
type: "button",
|
|
@@ -2243,7 +2508,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2243
2508
|
"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border transition-colors",
|
|
2244
2509
|
value ? "border-primary bg-primary" : "border-border bg-muted hover:bg-muted/80"
|
|
2245
2510
|
),
|
|
2246
|
-
children: /* @__PURE__ */ (0,
|
|
2511
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2247
2512
|
"span",
|
|
2248
2513
|
{
|
|
2249
2514
|
className: cn(
|
|
@@ -2255,7 +2520,7 @@ var ToggleNode = ({ node }) => {
|
|
|
2255
2520
|
)
|
|
2256
2521
|
}
|
|
2257
2522
|
),
|
|
2258
|
-
label && /* @__PURE__ */ (0,
|
|
2523
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-foreground/85", children: label })
|
|
2259
2524
|
]
|
|
2260
2525
|
}
|
|
2261
2526
|
);
|
|
@@ -2275,12 +2540,12 @@ var SliderNode = ({ node }) => {
|
|
|
2275
2540
|
const next = Number(e.target.value);
|
|
2276
2541
|
dispatch({ type: "set", path: node.binding, value: next });
|
|
2277
2542
|
};
|
|
2278
|
-
return /* @__PURE__ */ (0,
|
|
2279
|
-
(label || showValue) && /* @__PURE__ */ (0,
|
|
2280
|
-
label && /* @__PURE__ */ (0,
|
|
2281
|
-
showValue && /* @__PURE__ */ (0,
|
|
2543
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
|
|
2544
|
+
(label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
2545
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: label }),
|
|
2546
|
+
showValue && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-mono", children: value })
|
|
2282
2547
|
] }),
|
|
2283
|
-
/* @__PURE__ */ (0,
|
|
2548
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2284
2549
|
"input",
|
|
2285
2550
|
{
|
|
2286
2551
|
type: "range",
|
|
@@ -2302,9 +2567,9 @@ var SliderNode = ({ node }) => {
|
|
|
2302
2567
|
var TooltipNode = ({ node }) => {
|
|
2303
2568
|
const state = useUiState();
|
|
2304
2569
|
const content = String(resolveBindable(node.content, state) ?? "");
|
|
2305
|
-
return /* @__PURE__ */ (0,
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
2307
|
-
/* @__PURE__ */ (0,
|
|
2570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Tooltip, { children: [
|
|
2571
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: node.child }) }) }),
|
|
2572
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipContent, { side: node.side ?? "top", children: content })
|
|
2308
2573
|
] }) });
|
|
2309
2574
|
};
|
|
2310
2575
|
var DraggableNode = ({ node }) => {
|
|
@@ -2312,7 +2577,7 @@ var DraggableNode = ({ node }) => {
|
|
|
2312
2577
|
const snapBack = node.snapBack ?? true;
|
|
2313
2578
|
const axis = node.axis ?? "both";
|
|
2314
2579
|
const dragProp = axis === "both" ? true : axis;
|
|
2315
|
-
return /* @__PURE__ */ (0,
|
|
2580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2316
2581
|
import_react11.motion.div,
|
|
2317
2582
|
{
|
|
2318
2583
|
drag: dragProp,
|
|
@@ -2324,7 +2589,7 @@ var DraggableNode = ({ node }) => {
|
|
|
2324
2589
|
"aui-ui-draggable inline-block cursor-grab touch-none",
|
|
2325
2590
|
node.className
|
|
2326
2591
|
),
|
|
2327
|
-
children: /* @__PURE__ */ (0,
|
|
2592
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: node.child })
|
|
2328
2593
|
}
|
|
2329
2594
|
);
|
|
2330
2595
|
};
|
|
@@ -2334,8 +2599,8 @@ var CustomNode = ({ node }) => {
|
|
|
2334
2599
|
const Renderer = registry[node.name];
|
|
2335
2600
|
if (!Renderer) return null;
|
|
2336
2601
|
const resolvedProps = resolveProps(node.props ?? {}, state);
|
|
2337
|
-
const children = node.children?.map((child, i) => /* @__PURE__ */ (0,
|
|
2338
|
-
return /* @__PURE__ */ (0,
|
|
2602
|
+
const children = node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: child }, child.id ?? i));
|
|
2603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Renderer, { props: resolvedProps, children });
|
|
2339
2604
|
};
|
|
2340
2605
|
function resolveProps(props, state) {
|
|
2341
2606
|
const out = {};
|
|
@@ -2346,17 +2611,17 @@ function resolveProps(props, state) {
|
|
|
2346
2611
|
}
|
|
2347
2612
|
|
|
2348
2613
|
// src/artifacts/ui/ui-artifact.tsx
|
|
2349
|
-
var
|
|
2614
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2350
2615
|
var UiArtifactView = ({ artifact }) => {
|
|
2351
2616
|
const [state, dispatch] = (0, import_react13.useReducer)(
|
|
2352
2617
|
uiStateReducer,
|
|
2353
2618
|
artifact.initialState ?? {}
|
|
2354
2619
|
);
|
|
2355
|
-
return /* @__PURE__ */ (0,
|
|
2620
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(UiNodeView, { node: artifact.root }) }) }) });
|
|
2356
2621
|
};
|
|
2357
2622
|
|
|
2358
2623
|
// src/artifacts/registry.tsx
|
|
2359
|
-
var
|
|
2624
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2360
2625
|
var defaultArtifactRenderers = {
|
|
2361
2626
|
chart: ChartArtifactView,
|
|
2362
2627
|
question: QuestionArtifactView,
|
|
@@ -2374,7 +2639,7 @@ var ArtifactRegistryProvider = ({ renderers, override, children }) => {
|
|
|
2374
2639
|
if (override) return renderers;
|
|
2375
2640
|
return { ...defaultArtifactRenderers, ...renderers };
|
|
2376
2641
|
}, [renderers, override]);
|
|
2377
|
-
return /* @__PURE__ */ (0,
|
|
2642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ArtifactRegistryContext.Provider, { value: merged, children });
|
|
2378
2643
|
};
|
|
2379
2644
|
function useArtifactRegistry() {
|
|
2380
2645
|
return (0, import_react14.useContext)(ArtifactRegistryContext);
|
|
@@ -2383,7 +2648,7 @@ var ArtifactView = ({ artifact }) => {
|
|
|
2383
2648
|
const registry = useArtifactRegistry();
|
|
2384
2649
|
const Renderer = registry[artifact.type] ?? registry.json;
|
|
2385
2650
|
if (!Renderer) return null;
|
|
2386
|
-
return /* @__PURE__ */ (0,
|
|
2651
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Renderer, { artifact });
|
|
2387
2652
|
};
|
|
2388
2653
|
|
|
2389
2654
|
// src/artifacts/parse.ts
|
|
@@ -2499,7 +2764,7 @@ var import_c = __toESM(require("shiki/langs/c.mjs"), 1);
|
|
|
2499
2764
|
var import_cpp = __toESM(require("shiki/langs/cpp.mjs"), 1);
|
|
2500
2765
|
var import_vitesse_dark = __toESM(require("shiki/themes/vitesse-dark.mjs"), 1);
|
|
2501
2766
|
var import_vitesse_light = __toESM(require("shiki/themes/vitesse-light.mjs"), 1);
|
|
2502
|
-
var
|
|
2767
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2503
2768
|
var SHIKI_THEME_DARK = "vitesse-dark";
|
|
2504
2769
|
var SHIKI_THEME_LIGHT = "vitesse-light";
|
|
2505
2770
|
var highlighterPromise = null;
|
|
@@ -2568,13 +2833,13 @@ var ShikiSyntaxHighlighter = ({
|
|
|
2568
2833
|
try {
|
|
2569
2834
|
const parsed = JSON.parse(code);
|
|
2570
2835
|
if (isArtifact(parsed)) {
|
|
2571
|
-
return /* @__PURE__ */ (0,
|
|
2836
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactView, { artifact: parsed });
|
|
2572
2837
|
}
|
|
2573
2838
|
} catch {
|
|
2574
2839
|
}
|
|
2575
2840
|
}
|
|
2576
2841
|
if (html) {
|
|
2577
|
-
return /* @__PURE__ */ (0,
|
|
2842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2578
2843
|
"div",
|
|
2579
2844
|
{
|
|
2580
2845
|
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",
|
|
@@ -2582,14 +2847,14 @@ var ShikiSyntaxHighlighter = ({
|
|
|
2582
2847
|
}
|
|
2583
2848
|
);
|
|
2584
2849
|
}
|
|
2585
|
-
return /* @__PURE__ */ (0,
|
|
2850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Pre, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Code2, { children: code }) });
|
|
2586
2851
|
};
|
|
2587
2852
|
var syntax_highlighter_default = ShikiSyntaxHighlighter;
|
|
2588
2853
|
|
|
2589
2854
|
// src/components/markdown-text.tsx
|
|
2590
|
-
var
|
|
2855
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2591
2856
|
var MarkdownTextImpl = () => {
|
|
2592
|
-
return /* @__PURE__ */ (0,
|
|
2857
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2593
2858
|
import_react_markdown.MarkdownTextPrimitive,
|
|
2594
2859
|
{
|
|
2595
2860
|
remarkPlugins: [import_remark_gfm.default, import_remark_math.default],
|
|
@@ -2610,20 +2875,20 @@ var CodeHeader = ({ language, code }) => {
|
|
|
2610
2875
|
if (!code || isCopied) return;
|
|
2611
2876
|
copyToClipboard(code);
|
|
2612
2877
|
};
|
|
2613
|
-
return /* @__PURE__ */ (0,
|
|
2614
|
-
/* @__PURE__ */ (0,
|
|
2615
|
-
/* @__PURE__ */ (0,
|
|
2878
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("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: [
|
|
2879
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
|
|
2880
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
|
|
2616
2881
|
language
|
|
2617
2882
|
] }),
|
|
2618
|
-
/* @__PURE__ */ (0,
|
|
2883
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
2619
2884
|
TooltipIconButton,
|
|
2620
2885
|
{
|
|
2621
2886
|
tooltip: isCopied ? "Copied!" : "Copy",
|
|
2622
2887
|
onClick: onCopy,
|
|
2623
2888
|
className: "transition-colors hover:text-foreground",
|
|
2624
2889
|
children: [
|
|
2625
|
-
!isCopied && /* @__PURE__ */ (0,
|
|
2626
|
-
isCopied && /* @__PURE__ */ (0,
|
|
2890
|
+
!isCopied && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react4.CopyIcon, { className: "h-3.5 w-3.5" }),
|
|
2891
|
+
isCopied && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react4.CheckIcon, { className: "h-3.5 w-3.5 text-emerald-500" })
|
|
2627
2892
|
]
|
|
2628
2893
|
}
|
|
2629
2894
|
)
|
|
@@ -2643,7 +2908,7 @@ var useCopyToClipboard = ({
|
|
|
2643
2908
|
return { isCopied, copyToClipboard };
|
|
2644
2909
|
};
|
|
2645
2910
|
var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownComponents)({
|
|
2646
|
-
h1: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2911
|
+
h1: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2647
2912
|
"h1",
|
|
2648
2913
|
{
|
|
2649
2914
|
className: cn(
|
|
@@ -2653,7 +2918,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2653
2918
|
...props
|
|
2654
2919
|
}
|
|
2655
2920
|
),
|
|
2656
|
-
h2: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2921
|
+
h2: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2657
2922
|
"h2",
|
|
2658
2923
|
{
|
|
2659
2924
|
className: cn(
|
|
@@ -2663,7 +2928,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2663
2928
|
...props
|
|
2664
2929
|
}
|
|
2665
2930
|
),
|
|
2666
|
-
h3: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2931
|
+
h3: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2667
2932
|
"h3",
|
|
2668
2933
|
{
|
|
2669
2934
|
className: cn(
|
|
@@ -2673,7 +2938,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2673
2938
|
...props
|
|
2674
2939
|
}
|
|
2675
2940
|
),
|
|
2676
|
-
h4: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2941
|
+
h4: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2677
2942
|
"h4",
|
|
2678
2943
|
{
|
|
2679
2944
|
className: cn(
|
|
@@ -2683,7 +2948,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2683
2948
|
...props
|
|
2684
2949
|
}
|
|
2685
2950
|
),
|
|
2686
|
-
h5: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2951
|
+
h5: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2687
2952
|
"h5",
|
|
2688
2953
|
{
|
|
2689
2954
|
className: cn(
|
|
@@ -2693,7 +2958,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2693
2958
|
...props
|
|
2694
2959
|
}
|
|
2695
2960
|
),
|
|
2696
|
-
h6: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2961
|
+
h6: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2697
2962
|
"h6",
|
|
2698
2963
|
{
|
|
2699
2964
|
className: cn(
|
|
@@ -2703,7 +2968,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2703
2968
|
...props
|
|
2704
2969
|
}
|
|
2705
2970
|
),
|
|
2706
|
-
p: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2971
|
+
p: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2707
2972
|
"p",
|
|
2708
2973
|
{
|
|
2709
2974
|
className: cn(
|
|
@@ -2713,7 +2978,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2713
2978
|
...props
|
|
2714
2979
|
}
|
|
2715
2980
|
),
|
|
2716
|
-
a: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2981
|
+
a: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2717
2982
|
"a",
|
|
2718
2983
|
{
|
|
2719
2984
|
className: cn(
|
|
@@ -2725,7 +2990,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2725
2990
|
...props
|
|
2726
2991
|
}
|
|
2727
2992
|
),
|
|
2728
|
-
blockquote: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2993
|
+
blockquote: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2729
2994
|
"blockquote",
|
|
2730
2995
|
{
|
|
2731
2996
|
className: cn(
|
|
@@ -2735,7 +3000,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2735
3000
|
...props
|
|
2736
3001
|
}
|
|
2737
3002
|
),
|
|
2738
|
-
ul: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3003
|
+
ul: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2739
3004
|
"ul",
|
|
2740
3005
|
{
|
|
2741
3006
|
className: cn(
|
|
@@ -2745,7 +3010,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2745
3010
|
...props
|
|
2746
3011
|
}
|
|
2747
3012
|
),
|
|
2748
|
-
ol: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3013
|
+
ol: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2749
3014
|
"ol",
|
|
2750
3015
|
{
|
|
2751
3016
|
className: cn(
|
|
@@ -2755,7 +3020,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2755
3020
|
...props
|
|
2756
3021
|
}
|
|
2757
3022
|
),
|
|
2758
|
-
hr: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3023
|
+
hr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2759
3024
|
"hr",
|
|
2760
3025
|
{
|
|
2761
3026
|
className: cn(
|
|
@@ -2765,14 +3030,14 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2765
3030
|
...props
|
|
2766
3031
|
}
|
|
2767
3032
|
),
|
|
2768
|
-
table: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3033
|
+
table: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2769
3034
|
"table",
|
|
2770
3035
|
{
|
|
2771
3036
|
className: cn("aui-md-table w-full border-collapse text-sm", className),
|
|
2772
3037
|
...props
|
|
2773
3038
|
}
|
|
2774
3039
|
) }),
|
|
2775
|
-
th: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3040
|
+
th: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2776
3041
|
"th",
|
|
2777
3042
|
{
|
|
2778
3043
|
className: cn(
|
|
@@ -2782,7 +3047,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2782
3047
|
...props
|
|
2783
3048
|
}
|
|
2784
3049
|
),
|
|
2785
|
-
td: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3050
|
+
td: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2786
3051
|
"td",
|
|
2787
3052
|
{
|
|
2788
3053
|
className: cn(
|
|
@@ -2792,7 +3057,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2792
3057
|
...props
|
|
2793
3058
|
}
|
|
2794
3059
|
),
|
|
2795
|
-
tr: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3060
|
+
tr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2796
3061
|
"tr",
|
|
2797
3062
|
{
|
|
2798
3063
|
className: cn(
|
|
@@ -2802,8 +3067,8 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2802
3067
|
...props
|
|
2803
3068
|
}
|
|
2804
3069
|
),
|
|
2805
|
-
li: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2806
|
-
sup: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3070
|
+
li: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
|
|
3071
|
+
sup: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2807
3072
|
"sup",
|
|
2808
3073
|
{
|
|
2809
3074
|
className: cn(
|
|
@@ -2813,11 +3078,11 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2813
3078
|
...props
|
|
2814
3079
|
}
|
|
2815
3080
|
),
|
|
2816
|
-
pre: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3081
|
+
pre: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2817
3082
|
"pre",
|
|
2818
3083
|
{
|
|
2819
3084
|
className: cn(
|
|
2820
|
-
"aui-md-pre overflow-x-auto rounded-t-none rounded-b-lg border border-t-0 border-border/50 bg-
|
|
3085
|
+
"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",
|
|
2821
3086
|
className
|
|
2822
3087
|
),
|
|
2823
3088
|
...props
|
|
@@ -2825,30 +3090,31 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
|
|
|
2825
3090
|
),
|
|
2826
3091
|
code: function Code({ className, ...props }) {
|
|
2827
3092
|
const isCodeBlock = (0, import_react_markdown.useIsMarkdownCodeBlock)();
|
|
2828
|
-
return /* @__PURE__ */ (0,
|
|
3093
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2829
3094
|
"code",
|
|
2830
3095
|
{
|
|
2831
3096
|
className: cn(
|
|
2832
|
-
!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
|
|
3097
|
+
!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",
|
|
2833
3098
|
className
|
|
2834
3099
|
),
|
|
2835
3100
|
...props
|
|
2836
3101
|
}
|
|
2837
3102
|
);
|
|
2838
3103
|
},
|
|
2839
|
-
strong: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
2840
|
-
em: ({ className, ...props }) => /* @__PURE__ */ (0,
|
|
3104
|
+
strong: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("strong", { className: cn("font-semibold text-foreground", className), ...props }),
|
|
3105
|
+
em: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("em", { className: cn("italic", className), ...props }),
|
|
2841
3106
|
CodeHeader
|
|
2842
3107
|
});
|
|
2843
3108
|
|
|
2844
3109
|
// src/components/tool-fallback.tsx
|
|
2845
|
-
var
|
|
3110
|
+
var import_react20 = require("react");
|
|
2846
3111
|
var import_lucide_react5 = require("lucide-react");
|
|
3112
|
+
var import_react21 = require("@assistant-ui/react");
|
|
2847
3113
|
|
|
2848
3114
|
// src/ui/shimmer.tsx
|
|
2849
3115
|
var import_react17 = require("motion/react");
|
|
2850
3116
|
var import_react18 = require("react");
|
|
2851
|
-
var
|
|
3117
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2852
3118
|
var ShimmerComponent = ({
|
|
2853
3119
|
children,
|
|
2854
3120
|
as: Component = "p",
|
|
@@ -2863,7 +3129,7 @@ var ShimmerComponent = ({
|
|
|
2863
3129
|
() => (children?.length ?? 0) * spread,
|
|
2864
3130
|
[children, spread]
|
|
2865
3131
|
);
|
|
2866
|
-
return /* @__PURE__ */ (0,
|
|
3132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2867
3133
|
MotionComponent,
|
|
2868
3134
|
{
|
|
2869
3135
|
animate: { backgroundPosition: "0% center" },
|
|
@@ -2888,78 +3154,130 @@ var ShimmerComponent = ({
|
|
|
2888
3154
|
};
|
|
2889
3155
|
var Shimmer = (0, import_react18.memo)(ShimmerComponent);
|
|
2890
3156
|
|
|
2891
|
-
// src/components/
|
|
2892
|
-
var
|
|
2893
|
-
var
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
3157
|
+
// src/components/motion.tsx
|
|
3158
|
+
var import_react19 = require("motion/react");
|
|
3159
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3160
|
+
var luxuryEase = [0.16, 1, 0.3, 1];
|
|
3161
|
+
var TOOL_ENTER_MS = 0.78;
|
|
3162
|
+
var TOOL_EXIT_MS = 0.28;
|
|
3163
|
+
function toolPresenceTransition(reduced) {
|
|
3164
|
+
return {
|
|
3165
|
+
enter: {
|
|
3166
|
+
duration: reduced ? 0.35 : TOOL_ENTER_MS,
|
|
3167
|
+
ease: luxuryEase
|
|
3168
|
+
},
|
|
3169
|
+
exit: {
|
|
3170
|
+
duration: reduced ? 0.2 : TOOL_EXIT_MS,
|
|
3171
|
+
ease: [0.4, 0, 1, 1]
|
|
3172
|
+
}
|
|
3173
|
+
};
|
|
3174
|
+
}
|
|
3175
|
+
function toolMotionState(reduced, entering, variant) {
|
|
3176
|
+
if (reduced) {
|
|
3177
|
+
return entering ? { opacity: 0, y: variant === "executing" ? 8 : 10 } : { opacity: 1, y: 0 };
|
|
2906
3178
|
}
|
|
2907
|
-
|
|
2908
|
-
|
|
3179
|
+
if (variant === "executing") {
|
|
3180
|
+
return entering ? { opacity: 0, y: 12 } : { opacity: 1, y: 0 };
|
|
3181
|
+
}
|
|
3182
|
+
return entering ? { opacity: 0, y: 14, filter: "blur(10px)" } : { opacity: 1, y: 0, filter: "blur(0px)" };
|
|
3183
|
+
}
|
|
3184
|
+
function ToolMotion({ children, className, motionKey }) {
|
|
3185
|
+
const reduced = (0, import_react19.useReducedMotion)() ?? false;
|
|
3186
|
+
const { enter, exit } = toolPresenceTransition(reduced);
|
|
3187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3188
|
+
import_react19.motion.div,
|
|
2909
3189
|
{
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
3190
|
+
className: cn("aui-tool-motion w-full min-w-0", className),
|
|
3191
|
+
initial: toolMotionState(reduced, true, "settled"),
|
|
3192
|
+
animate: toolMotionState(reduced, false, "settled"),
|
|
3193
|
+
exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
|
|
3194
|
+
transition: enter,
|
|
3195
|
+
style: { willChange: "opacity, transform, filter" },
|
|
3196
|
+
children
|
|
3197
|
+
},
|
|
3198
|
+
motionKey
|
|
2915
3199
|
);
|
|
2916
|
-
}
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
3200
|
+
}
|
|
3201
|
+
function ToolPresence({
|
|
3202
|
+
presenceKey,
|
|
3203
|
+
children,
|
|
3204
|
+
className,
|
|
3205
|
+
variant = "settled"
|
|
3206
|
+
}) {
|
|
3207
|
+
const reduced = (0, import_react19.useReducedMotion)() ?? false;
|
|
3208
|
+
const { enter, exit } = toolPresenceTransition(reduced);
|
|
3209
|
+
const enterTransition = variant === "executing" ? { duration: reduced ? 0.3 : 0.52, ease: luxuryEase } : enter;
|
|
3210
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react19.AnimatePresence, { mode: "wait", initial: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3211
|
+
import_react19.motion.div,
|
|
3212
|
+
{
|
|
3213
|
+
className: cn("aui-tool-presence w-full min-w-0", className),
|
|
3214
|
+
initial: toolMotionState(reduced, true, variant),
|
|
3215
|
+
animate: toolMotionState(reduced, false, variant),
|
|
3216
|
+
exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
|
|
3217
|
+
transition: enterTransition,
|
|
3218
|
+
style: {
|
|
3219
|
+
willChange: variant === "executing" ? "opacity, transform" : "opacity, transform, filter"
|
|
3220
|
+
},
|
|
3221
|
+
children
|
|
3222
|
+
},
|
|
3223
|
+
presenceKey
|
|
3224
|
+
) });
|
|
3225
|
+
}
|
|
3226
|
+
function ToolBodyPresence({
|
|
3227
|
+
open,
|
|
3228
|
+
children,
|
|
3229
|
+
className
|
|
3230
|
+
}) {
|
|
3231
|
+
const reduced = (0, import_react19.useReducedMotion)() ?? false;
|
|
3232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2920
3233
|
"div",
|
|
2921
3234
|
{
|
|
2922
3235
|
className: cn(
|
|
2923
|
-
"aui-tool-
|
|
2924
|
-
|
|
3236
|
+
"aui-tool-body grid min-h-0 transition-[grid-template-rows]",
|
|
3237
|
+
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)]"
|
|
2925
3238
|
),
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
"
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2939
|
-
import_lucide_react5.ChevronDownIcon,
|
|
2940
|
-
{
|
|
2941
|
-
className: cn(
|
|
2942
|
-
"size-3.5 shrink-0 transition-transform",
|
|
2943
|
-
open && "rotate-180"
|
|
2944
|
-
)
|
|
2945
|
-
}
|
|
2946
|
-
)
|
|
2947
|
-
]
|
|
2948
|
-
}
|
|
2949
|
-
),
|
|
2950
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("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: [
|
|
2951
|
-
argsText && argsText !== "{}" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Section, { label: "Input", value: argsText }),
|
|
2952
|
-
result !== void 0 && result !== null && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Section, { label: "Output", value: formatResult(result) })
|
|
2953
|
-
] })
|
|
2954
|
-
]
|
|
3239
|
+
style: { gridTemplateRows: open ? "1fr" : "0fr" },
|
|
3240
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3241
|
+
"div",
|
|
3242
|
+
{
|
|
3243
|
+
className: cn(
|
|
3244
|
+
className,
|
|
3245
|
+
"transition-opacity",
|
|
3246
|
+
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)]"
|
|
3247
|
+
),
|
|
3248
|
+
children
|
|
3249
|
+
}
|
|
3250
|
+
) })
|
|
2955
3251
|
}
|
|
2956
3252
|
);
|
|
2957
|
-
}
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3255
|
+
// src/components/tool-fallback.tsx
|
|
3256
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3257
|
+
function detectRunning({
|
|
3258
|
+
status,
|
|
3259
|
+
result,
|
|
3260
|
+
streamRunning
|
|
3261
|
+
}) {
|
|
3262
|
+
const isError = status?.type === "incomplete" && status.reason !== "cancelled";
|
|
3263
|
+
if (isError) return false;
|
|
3264
|
+
if (status?.type === "running") return true;
|
|
3265
|
+
if (status?.type === "complete") return false;
|
|
3266
|
+
return streamRunning && result === void 0;
|
|
3267
|
+
}
|
|
3268
|
+
function useToolRunning(props) {
|
|
3269
|
+
const { isRunning: streamRunning } = useTimbalRuntime();
|
|
3270
|
+
const partStatus = (0, import_react21.useAuiState)((s) => s.part.status);
|
|
3271
|
+
return detectRunning({
|
|
3272
|
+
status: partStatus ?? props.status,
|
|
3273
|
+
result: props.result,
|
|
3274
|
+
streamRunning
|
|
3275
|
+
});
|
|
3276
|
+
}
|
|
3277
|
+
function formatToolLabel(toolName) {
|
|
3278
|
+
return toolName.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
|
|
3279
|
+
}
|
|
3280
|
+
function formatToolResult(result) {
|
|
2963
3281
|
if (typeof result === "string") return result;
|
|
2964
3282
|
try {
|
|
2965
3283
|
return JSON.stringify(result, null, 2);
|
|
@@ -2967,32 +3285,172 @@ function formatResult(result) {
|
|
|
2967
3285
|
return String(result);
|
|
2968
3286
|
}
|
|
2969
3287
|
}
|
|
2970
|
-
var
|
|
3288
|
+
var TimelineActionLabel = ({ action, detail, shimmer = false }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
|
|
3289
|
+
action ? shimmer ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3290
|
+
Shimmer,
|
|
3291
|
+
{
|
|
3292
|
+
as: "span",
|
|
3293
|
+
className: cn(studioTimelineShimmerActionClass, "aui-tool-shimmer"),
|
|
3294
|
+
duration: 1.8,
|
|
3295
|
+
spread: 2.5,
|
|
3296
|
+
children: action
|
|
3297
|
+
}
|
|
3298
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: studioTimelineActionClass, children: action }) : null,
|
|
3299
|
+
detail ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: studioTimelineDetailClass, children: detail }) : null
|
|
3300
|
+
] });
|
|
3301
|
+
var TimelineHoverChevron = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3302
|
+
import_lucide_react5.ChevronRightIcon,
|
|
3303
|
+
{
|
|
3304
|
+
className: studioTimelineChevronClass(expanded),
|
|
3305
|
+
"aria-hidden": true
|
|
3306
|
+
}
|
|
3307
|
+
);
|
|
3308
|
+
var ToolPanel = ({ toolName, argsText, result, isError }) => {
|
|
3309
|
+
const [open, setOpen] = (0, import_react20.useState)(false);
|
|
3310
|
+
const detail = formatToolLabel(toolName);
|
|
3311
|
+
const formattedArgs = (0, import_react20.useMemo)(() => {
|
|
3312
|
+
if (!argsText || argsText === "{}") return null;
|
|
3313
|
+
try {
|
|
3314
|
+
return JSON.stringify(JSON.parse(argsText), null, 2);
|
|
3315
|
+
} catch {
|
|
3316
|
+
return argsText;
|
|
3317
|
+
}
|
|
3318
|
+
}, [argsText]);
|
|
3319
|
+
const formattedResult = (0, import_react20.useMemo)(() => {
|
|
3320
|
+
if (result === void 0 || result === null) return null;
|
|
3321
|
+
return formatToolResult(result);
|
|
3322
|
+
}, [result]);
|
|
3323
|
+
const hasBody = Boolean(formattedArgs || formattedResult);
|
|
3324
|
+
const action = isError ? "Failed" : "Used";
|
|
3325
|
+
if (!hasBody) {
|
|
3326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "aui-tool-row w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimelineActionLabel, { action, detail }) });
|
|
3327
|
+
}
|
|
3328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "aui-tool-row w-full min-w-0", children: [
|
|
3329
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3330
|
+
"button",
|
|
3331
|
+
{
|
|
3332
|
+
type: "button",
|
|
3333
|
+
onClick: () => setOpen((v) => !v),
|
|
3334
|
+
"aria-expanded": open,
|
|
3335
|
+
"aria-label": `${action} ${detail}`,
|
|
3336
|
+
className: studioTimelineRowButtonClass,
|
|
3337
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3338
|
+
"span",
|
|
3339
|
+
{
|
|
3340
|
+
className: cn(
|
|
3341
|
+
"inline-flex min-w-0 max-w-full items-center gap-0.5",
|
|
3342
|
+
studioTimelineTextClass,
|
|
3343
|
+
"text-foreground"
|
|
3344
|
+
),
|
|
3345
|
+
children: [
|
|
3346
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimelineActionLabel, { action, detail }),
|
|
3347
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimelineHoverChevron, { expanded: open })
|
|
3348
|
+
]
|
|
3349
|
+
}
|
|
3350
|
+
)
|
|
3351
|
+
}
|
|
3352
|
+
),
|
|
3353
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3354
|
+
ToolBodyPresence,
|
|
3355
|
+
{
|
|
3356
|
+
open,
|
|
3357
|
+
className: cn(studioTimelineBodyPadClass, "gap-2"),
|
|
3358
|
+
children: [
|
|
3359
|
+
formattedArgs ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3360
|
+
"div",
|
|
3361
|
+
{
|
|
3362
|
+
className: cn(
|
|
3363
|
+
studioComposerIoWellClass,
|
|
3364
|
+
"max-h-48 overflow-auto px-2.5 py-2"
|
|
3365
|
+
),
|
|
3366
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedArgs })
|
|
3367
|
+
}
|
|
3368
|
+
) : null,
|
|
3369
|
+
formattedResult ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3370
|
+
"div",
|
|
3371
|
+
{
|
|
3372
|
+
className: cn(
|
|
3373
|
+
studioComposerIoWellClass,
|
|
3374
|
+
"max-h-48 overflow-auto px-2.5 py-2"
|
|
3375
|
+
),
|
|
3376
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedResult })
|
|
3377
|
+
}
|
|
3378
|
+
) : null
|
|
3379
|
+
]
|
|
3380
|
+
}
|
|
3381
|
+
)
|
|
3382
|
+
] });
|
|
3383
|
+
};
|
|
3384
|
+
var ToolFallbackImpl = ({
|
|
3385
|
+
toolName,
|
|
3386
|
+
argsText,
|
|
3387
|
+
result,
|
|
3388
|
+
status
|
|
3389
|
+
}) => {
|
|
3390
|
+
const isRunning = useToolRunning({ status, result });
|
|
3391
|
+
const isError = status?.type === "incomplete" && status.reason !== "cancelled";
|
|
3392
|
+
const presenceKey = isRunning ? "running" : isError ? "error" : "complete";
|
|
3393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3394
|
+
ToolPresence,
|
|
3395
|
+
{
|
|
3396
|
+
presenceKey,
|
|
3397
|
+
variant: isRunning ? "executing" : "settled",
|
|
3398
|
+
className: "py-0.5",
|
|
3399
|
+
children: isRunning ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "aui-tool-running", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3400
|
+
TimelineActionLabel,
|
|
3401
|
+
{
|
|
3402
|
+
action: "Using",
|
|
3403
|
+
detail: formatToolLabel(toolName),
|
|
3404
|
+
shimmer: true
|
|
3405
|
+
}
|
|
3406
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3407
|
+
ToolPanel,
|
|
3408
|
+
{
|
|
3409
|
+
toolName,
|
|
3410
|
+
argsText,
|
|
3411
|
+
result,
|
|
3412
|
+
isError
|
|
3413
|
+
}
|
|
3414
|
+
)
|
|
3415
|
+
}
|
|
3416
|
+
);
|
|
3417
|
+
};
|
|
3418
|
+
var ToolFallback = (0, import_react20.memo)(
|
|
2971
3419
|
ToolFallbackImpl
|
|
2972
3420
|
);
|
|
2973
3421
|
ToolFallback.displayName = "ToolFallback";
|
|
2974
3422
|
|
|
2975
3423
|
// src/artifacts/tool-artifact.tsx
|
|
2976
|
-
var
|
|
3424
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2977
3425
|
var ToolArtifactFallback = (props) => {
|
|
2978
3426
|
const registry = useArtifactRegistry();
|
|
2979
|
-
const isRunning =
|
|
3427
|
+
const isRunning = useToolRunning({
|
|
3428
|
+
status: props.status,
|
|
3429
|
+
result: props.result
|
|
3430
|
+
});
|
|
2980
3431
|
if (!isRunning) {
|
|
2981
3432
|
const artifact = parseArtifactFromToolResult(props.result);
|
|
2982
3433
|
if (artifact) {
|
|
2983
3434
|
const Renderer = registry[artifact.type];
|
|
2984
3435
|
if (Renderer) {
|
|
2985
|
-
return /* @__PURE__ */ (0,
|
|
3436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3437
|
+
ToolMotion,
|
|
3438
|
+
{
|
|
3439
|
+
motionKey: `artifact-${artifact.type}`,
|
|
3440
|
+
className: "aui-tool-artifact",
|
|
3441
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Renderer, { artifact })
|
|
3442
|
+
}
|
|
3443
|
+
);
|
|
2986
3444
|
}
|
|
2987
3445
|
}
|
|
2988
3446
|
}
|
|
2989
|
-
return /* @__PURE__ */ (0,
|
|
3447
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ToolFallback, { ...props });
|
|
2990
3448
|
};
|
|
2991
3449
|
|
|
2992
3450
|
// src/components/composer.tsx
|
|
2993
|
-
var
|
|
3451
|
+
var import_react22 = require("@assistant-ui/react");
|
|
2994
3452
|
var import_lucide_react6 = require("lucide-react");
|
|
2995
|
-
var
|
|
3453
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2996
3454
|
var Composer = ({
|
|
2997
3455
|
placeholder = "Send a message...",
|
|
2998
3456
|
showAttachments = true,
|
|
@@ -3001,21 +3459,24 @@ var Composer = ({
|
|
|
3001
3459
|
noAutoFocus,
|
|
3002
3460
|
className
|
|
3003
3461
|
}) => {
|
|
3004
|
-
return /* @__PURE__ */ (0,
|
|
3005
|
-
|
|
3462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3463
|
+
import_react22.ComposerPrimitive.Root,
|
|
3006
3464
|
{
|
|
3007
3465
|
className: cn(
|
|
3008
|
-
"aui-composer-root relative
|
|
3466
|
+
"aui-composer-root relative flex w-full flex-col",
|
|
3009
3467
|
className
|
|
3010
3468
|
),
|
|
3011
|
-
children: /* @__PURE__ */ (0,
|
|
3012
|
-
|
|
3469
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3470
|
+
import_react22.ComposerPrimitive.AttachmentDropzone,
|
|
3013
3471
|
{
|
|
3014
|
-
className:
|
|
3472
|
+
className: cn(
|
|
3473
|
+
studioComposeInputShellClass,
|
|
3474
|
+
"data-[dragging=true]:border-2 data-[dragging=true]:border-dashed data-[dragging=true]:border-primary data-[dragging=true]:bg-accent/50"
|
|
3475
|
+
),
|
|
3015
3476
|
children: [
|
|
3016
|
-
showAttachments && /* @__PURE__ */ (0,
|
|
3017
|
-
/* @__PURE__ */ (0,
|
|
3018
|
-
/* @__PURE__ */ (0,
|
|
3477
|
+
showAttachments && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerAttachments, {}),
|
|
3478
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
|
|
3479
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3019
3480
|
ComposerToolbar,
|
|
3020
3481
|
{
|
|
3021
3482
|
showAttachments,
|
|
@@ -3033,7 +3494,7 @@ var ComposerInput = ({
|
|
|
3033
3494
|
placeholder,
|
|
3034
3495
|
autoFocus
|
|
3035
3496
|
}) => {
|
|
3036
|
-
const composer = (0,
|
|
3497
|
+
const composer = (0, import_react22.useComposerRuntime)();
|
|
3037
3498
|
const onKeyDown = (e) => {
|
|
3038
3499
|
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
3039
3500
|
e.preventDefault();
|
|
@@ -3045,11 +3506,11 @@ var ComposerInput = ({
|
|
|
3045
3506
|
el.style.height = "auto";
|
|
3046
3507
|
el.style.height = `${Math.min(el.scrollHeight, 240)}px`;
|
|
3047
3508
|
};
|
|
3048
|
-
return /* @__PURE__ */ (0,
|
|
3049
|
-
|
|
3509
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3510
|
+
import_react22.ComposerPrimitive.Input,
|
|
3050
3511
|
{
|
|
3051
3512
|
placeholder,
|
|
3052
|
-
className: "aui-composer-input
|
|
3513
|
+
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",
|
|
3053
3514
|
rows: 1,
|
|
3054
3515
|
autoFocus,
|
|
3055
3516
|
"aria-label": "Message input",
|
|
@@ -3059,96 +3520,92 @@ var ComposerInput = ({
|
|
|
3059
3520
|
);
|
|
3060
3521
|
};
|
|
3061
3522
|
var ComposerToolbar = ({ showAttachments, toolbar, sendTooltip }) => {
|
|
3062
|
-
return /* @__PURE__ */ (0,
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "aui-composer-action-wrapper flex items-center justify-between gap-1 px-2.5 pb-2.5", children: [
|
|
3524
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
3525
|
+
showAttachments && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerAddAttachment, {}),
|
|
3526
|
+
toolbar
|
|
3527
|
+
] }),
|
|
3528
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerSendOrCancel, { sendTooltip })
|
|
3067
3529
|
] });
|
|
3068
3530
|
};
|
|
3069
3531
|
var ComposerSendOrCancel = ({ sendTooltip }) => {
|
|
3070
|
-
return /* @__PURE__ */ (0,
|
|
3071
|
-
/* @__PURE__ */ (0,
|
|
3532
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
3533
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3072
3534
|
TooltipIconButton,
|
|
3073
3535
|
{
|
|
3074
3536
|
tooltip: sendTooltip,
|
|
3075
|
-
|
|
3537
|
+
variant: "primary",
|
|
3076
3538
|
type: "submit",
|
|
3077
|
-
|
|
3078
|
-
size: "icon",
|
|
3079
|
-
className: "aui-composer-send size-8 rounded-full",
|
|
3539
|
+
className: "aui-composer-send shrink-0 disabled:opacity-30",
|
|
3080
3540
|
"aria-label": "Send message",
|
|
3081
|
-
children: /* @__PURE__ */ (0,
|
|
3541
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react6.ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
|
|
3082
3542
|
}
|
|
3083
3543
|
) }) }),
|
|
3084
|
-
/* @__PURE__ */ (0,
|
|
3085
|
-
|
|
3544
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3545
|
+
TooltipIconButton,
|
|
3086
3546
|
{
|
|
3087
|
-
|
|
3088
|
-
variant: "
|
|
3089
|
-
|
|
3090
|
-
className: "aui-composer-cancel size-8 rounded-full",
|
|
3547
|
+
tooltip: "Stop generating",
|
|
3548
|
+
variant: "primary",
|
|
3549
|
+
className: "aui-composer-cancel shrink-0",
|
|
3091
3550
|
"aria-label": "Stop generating",
|
|
3092
|
-
children: /* @__PURE__ */ (0,
|
|
3551
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react6.SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
|
|
3093
3552
|
}
|
|
3094
3553
|
) }) })
|
|
3095
3554
|
] });
|
|
3096
3555
|
};
|
|
3097
3556
|
|
|
3098
3557
|
// src/components/suggestions.tsx
|
|
3099
|
-
var
|
|
3100
|
-
var
|
|
3101
|
-
var
|
|
3558
|
+
var import_react23 = require("react");
|
|
3559
|
+
var import_react24 = require("@assistant-ui/react");
|
|
3560
|
+
var import_lucide_react7 = require("lucide-react");
|
|
3561
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
3102
3562
|
var Suggestions = ({
|
|
3103
3563
|
suggestions,
|
|
3104
|
-
layout = "grid",
|
|
3105
3564
|
className
|
|
3106
3565
|
}) => {
|
|
3107
3566
|
const items = useResolvedSuggestions(suggestions);
|
|
3108
3567
|
if (!items || items.length === 0) return null;
|
|
3109
|
-
return /* @__PURE__ */ (0,
|
|
3568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3110
3569
|
"div",
|
|
3111
3570
|
{
|
|
3112
3571
|
className: cn(
|
|
3113
|
-
"aui-thread-suggestions w-full pb-
|
|
3114
|
-
layout === "grid" ? "grid gap-2 @md:grid-cols-2" : "flex gap-2 overflow-x-auto pb-1 [&::-webkit-scrollbar]:hidden",
|
|
3572
|
+
"aui-thread-suggestions flex w-full flex-col gap-2 pb-2.5",
|
|
3115
3573
|
className
|
|
3116
3574
|
),
|
|
3117
|
-
|
|
3575
|
+
role: "list",
|
|
3576
|
+
"aria-label": "Suggested prompts",
|
|
3577
|
+
children: items.map((suggestion, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SuggestionRow, { suggestion }, (suggestion.prompt ?? suggestion.title) + i))
|
|
3118
3578
|
}
|
|
3119
3579
|
);
|
|
3120
3580
|
};
|
|
3121
|
-
var
|
|
3122
|
-
|
|
3123
|
-
compact
|
|
3124
|
-
}) => {
|
|
3125
|
-
const runtime = (0, import_react22.useThreadRuntime)();
|
|
3581
|
+
var SuggestionRow = ({ suggestion }) => {
|
|
3582
|
+
const runtime = (0, import_react24.useThreadRuntime)();
|
|
3126
3583
|
const onClick = () => {
|
|
3127
3584
|
const text = suggestion.prompt ?? suggestion.title;
|
|
3128
3585
|
runtime.append({ role: "user", content: [{ type: "text", text }] });
|
|
3129
3586
|
};
|
|
3130
|
-
return /* @__PURE__ */ (0,
|
|
3131
|
-
|
|
3587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3588
|
+
"button",
|
|
3132
3589
|
{
|
|
3133
|
-
|
|
3590
|
+
type: "button",
|
|
3591
|
+
role: "listitem",
|
|
3134
3592
|
onClick,
|
|
3135
|
-
className: cn(
|
|
3136
|
-
"aui-thread-suggestion h-auto rounded-2xl border text-left text-sm transition-colors hover:bg-muted",
|
|
3137
|
-
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"
|
|
3138
|
-
),
|
|
3593
|
+
className: cn("aui-thread-suggestion", studioListRowButtonClass),
|
|
3139
3594
|
children: [
|
|
3140
|
-
|
|
3141
|
-
/* @__PURE__ */ (0,
|
|
3142
|
-
|
|
3595
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "aui-thread-suggestion-icon shrink-0 text-muted-foreground", children: suggestion.icon ?? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react7.ArrowUpIcon, { className: "size-4", strokeWidth: 1.75, "aria-hidden": true }) }),
|
|
3596
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "aui-thread-suggestion-text min-w-0 flex-1 text-left", children: [
|
|
3597
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "aui-thread-suggestion-text-1 block truncate text-sm font-normal text-foreground", children: suggestion.title }),
|
|
3598
|
+
suggestion.description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "aui-thread-suggestion-text-2 mt-0.5 block truncate text-xs text-muted-foreground", children: suggestion.description })
|
|
3599
|
+
] })
|
|
3143
3600
|
]
|
|
3144
3601
|
}
|
|
3145
|
-
)
|
|
3602
|
+
);
|
|
3146
3603
|
};
|
|
3147
3604
|
function useResolvedSuggestions(source) {
|
|
3148
|
-
const [resolved, setResolved] = (0,
|
|
3605
|
+
const [resolved, setResolved] = (0, import_react23.useState)(
|
|
3149
3606
|
() => Array.isArray(source) ? source : void 0
|
|
3150
3607
|
);
|
|
3151
|
-
(0,
|
|
3608
|
+
(0, import_react23.useEffect)(() => {
|
|
3152
3609
|
if (!source) {
|
|
3153
3610
|
setResolved(void 0);
|
|
3154
3611
|
return;
|
|
@@ -3167,13 +3624,80 @@ function useResolvedSuggestions(source) {
|
|
|
3167
3624
|
cancelled = true;
|
|
3168
3625
|
};
|
|
3169
3626
|
}, [source]);
|
|
3170
|
-
return (0,
|
|
3627
|
+
return (0, import_react23.useMemo)(() => resolved, [resolved]);
|
|
3628
|
+
}
|
|
3629
|
+
|
|
3630
|
+
// src/design/theme-sanity.ts
|
|
3631
|
+
var scheduled = false;
|
|
3632
|
+
var warned = false;
|
|
3633
|
+
function isDev() {
|
|
3634
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
3635
|
+
return false;
|
|
3636
|
+
}
|
|
3637
|
+
return true;
|
|
3638
|
+
}
|
|
3639
|
+
function parseLuminance(color) {
|
|
3640
|
+
const value = color.trim();
|
|
3641
|
+
if (!value) return null;
|
|
3642
|
+
const oklch = value.match(/oklch\(\s*([0-9.]+)/i);
|
|
3643
|
+
if (oklch) {
|
|
3644
|
+
const lightness = Number.parseFloat(oklch[1]);
|
|
3645
|
+
if (Number.isFinite(lightness)) return lightness;
|
|
3646
|
+
}
|
|
3647
|
+
const rgb = value.match(/rgba?\(\s*([0-9.]+)[\s,]+([0-9.]+)[\s,]+([0-9.]+)/i);
|
|
3648
|
+
if (rgb) {
|
|
3649
|
+
const r = Number.parseFloat(rgb[1]) / 255;
|
|
3650
|
+
const g = Number.parseFloat(rgb[2]) / 255;
|
|
3651
|
+
const b = Number.parseFloat(rgb[3]) / 255;
|
|
3652
|
+
if ([r, g, b].every(Number.isFinite)) {
|
|
3653
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
const hsl = value.match(/hsla?\(\s*[0-9.]+[\s,]+[0-9.]+%[\s,]+([0-9.]+)%/i);
|
|
3657
|
+
if (hsl) {
|
|
3658
|
+
const lightness = Number.parseFloat(hsl[1]) / 100;
|
|
3659
|
+
if (Number.isFinite(lightness)) return lightness;
|
|
3660
|
+
}
|
|
3661
|
+
return null;
|
|
3662
|
+
}
|
|
3663
|
+
function runCheck() {
|
|
3664
|
+
if (warned) return;
|
|
3665
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
3666
|
+
const root = document.documentElement;
|
|
3667
|
+
const styles = window.getComputedStyle(root);
|
|
3668
|
+
const background = styles.getPropertyValue("--background").trim();
|
|
3669
|
+
if (!background) {
|
|
3670
|
+
warned = true;
|
|
3671
|
+
console.warn(
|
|
3672
|
+
'[@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.'
|
|
3673
|
+
);
|
|
3674
|
+
return;
|
|
3675
|
+
}
|
|
3676
|
+
const luminance = parseLuminance(background);
|
|
3677
|
+
if (luminance === null) return;
|
|
3678
|
+
const hasDarkClass = root.classList.contains("dark");
|
|
3679
|
+
const looksDark = luminance < 0.5;
|
|
3680
|
+
if (hasDarkClass !== looksDark) {
|
|
3681
|
+
warned = true;
|
|
3682
|
+
console.warn(
|
|
3683
|
+
`[@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.`
|
|
3684
|
+
);
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
function scheduleThemeSanityCheck() {
|
|
3688
|
+
if (scheduled) return;
|
|
3689
|
+
if (!isDev()) return;
|
|
3690
|
+
if (typeof window === "undefined") return;
|
|
3691
|
+
scheduled = true;
|
|
3692
|
+
if (typeof queueMicrotask === "function") {
|
|
3693
|
+
queueMicrotask(() => setTimeout(runCheck, 0));
|
|
3694
|
+
} else {
|
|
3695
|
+
setTimeout(runCheck, 0);
|
|
3696
|
+
}
|
|
3171
3697
|
}
|
|
3172
3698
|
|
|
3173
3699
|
// src/components/thread.tsx
|
|
3174
|
-
var
|
|
3175
|
-
var import_lucide_react7 = require("lucide-react");
|
|
3176
|
-
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3700
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3177
3701
|
var Thread = ({
|
|
3178
3702
|
className,
|
|
3179
3703
|
maxWidth = "44rem",
|
|
@@ -3191,27 +3715,30 @@ var Thread = ({
|
|
|
3191
3715
|
const EditComposerSlot = components?.EditComposer ?? EditComposer;
|
|
3192
3716
|
const ScrollToBottomSlot = components?.ScrollToBottom ?? ThreadScrollToBottom;
|
|
3193
3717
|
const SuggestionsSlot = components?.Suggestions ?? Suggestions;
|
|
3194
|
-
|
|
3718
|
+
(0, import_react25.useEffect)(() => {
|
|
3719
|
+
scheduleThemeSanityCheck();
|
|
3720
|
+
}, []);
|
|
3721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3195
3722
|
ArtifactRegistryProvider,
|
|
3196
3723
|
{
|
|
3197
3724
|
renderers: artifacts?.renderers,
|
|
3198
3725
|
override: artifacts?.override,
|
|
3199
|
-
children: /* @__PURE__ */ (0,
|
|
3200
|
-
}), children: /* @__PURE__ */ (0,
|
|
3201
|
-
|
|
3726
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
|
|
3727
|
+
}), children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3728
|
+
import_react26.ThreadPrimitive.Root,
|
|
3202
3729
|
{
|
|
3203
3730
|
className: cn(
|
|
3204
3731
|
"aui-root aui-thread-root @container flex h-full flex-col bg-background",
|
|
3205
3732
|
className
|
|
3206
3733
|
),
|
|
3207
3734
|
style: { ["--thread-max-width"]: maxWidth },
|
|
3208
|
-
children: /* @__PURE__ */ (0,
|
|
3209
|
-
|
|
3735
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3736
|
+
import_react26.ThreadPrimitive.Viewport,
|
|
3210
3737
|
{
|
|
3211
3738
|
turnAnchor: "bottom",
|
|
3212
3739
|
className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4 pt-4",
|
|
3213
3740
|
children: [
|
|
3214
|
-
/* @__PURE__ */ (0,
|
|
3741
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3215
3742
|
WelcomeSlot,
|
|
3216
3743
|
{
|
|
3217
3744
|
config: welcome,
|
|
@@ -3219,8 +3746,8 @@ var Thread = ({
|
|
|
3219
3746
|
Suggestions: SuggestionsSlot
|
|
3220
3747
|
}
|
|
3221
3748
|
),
|
|
3222
|
-
/* @__PURE__ */ (0,
|
|
3223
|
-
|
|
3749
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3750
|
+
import_react26.ThreadPrimitive.Messages,
|
|
3224
3751
|
{
|
|
3225
3752
|
components: {
|
|
3226
3753
|
UserMessage: UserMessageSlot,
|
|
@@ -3229,9 +3756,9 @@ var Thread = ({
|
|
|
3229
3756
|
}
|
|
3230
3757
|
}
|
|
3231
3758
|
),
|
|
3232
|
-
/* @__PURE__ */ (0,
|
|
3233
|
-
/* @__PURE__ */ (0,
|
|
3234
|
-
/* @__PURE__ */ (0,
|
|
3759
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react26.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: [
|
|
3760
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ScrollToBottomSlot, {}),
|
|
3761
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ComposerSlot, { placeholder: composerPlaceholder })
|
|
3235
3762
|
] })
|
|
3236
3763
|
]
|
|
3237
3764
|
}
|
|
@@ -3242,105 +3769,164 @@ var Thread = ({
|
|
|
3242
3769
|
);
|
|
3243
3770
|
};
|
|
3244
3771
|
var ThreadScrollToBottom = () => {
|
|
3245
|
-
return /* @__PURE__ */ (0,
|
|
3772
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3246
3773
|
TooltipIconButton,
|
|
3247
3774
|
{
|
|
3248
3775
|
tooltip: "Scroll to bottom",
|
|
3249
|
-
variant: "
|
|
3250
|
-
className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center
|
|
3251
|
-
children: /* @__PURE__ */ (0,
|
|
3776
|
+
variant: "secondary",
|
|
3777
|
+
className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center disabled:invisible",
|
|
3778
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.ArrowDownIcon, { className: "size-4" })
|
|
3252
3779
|
}
|
|
3253
3780
|
) });
|
|
3254
3781
|
};
|
|
3782
|
+
var welcomeStagger = {
|
|
3783
|
+
initial: {},
|
|
3784
|
+
animate: {
|
|
3785
|
+
transition: { staggerChildren: 0.16, delayChildren: 0.12 }
|
|
3786
|
+
}
|
|
3787
|
+
};
|
|
3788
|
+
var welcomeItem = {
|
|
3789
|
+
initial: { opacity: 0, y: 14 },
|
|
3790
|
+
animate: {
|
|
3791
|
+
opacity: 1,
|
|
3792
|
+
y: 0,
|
|
3793
|
+
transition: { duration: 0.9, ease: luxuryEase }
|
|
3794
|
+
}
|
|
3795
|
+
};
|
|
3796
|
+
var welcomeIcon = {
|
|
3797
|
+
initial: { opacity: 0, y: 10, scale: 0.96 },
|
|
3798
|
+
animate: {
|
|
3799
|
+
opacity: 1,
|
|
3800
|
+
y: 0,
|
|
3801
|
+
scale: 1,
|
|
3802
|
+
transition: { duration: 1.1, ease: luxuryEase }
|
|
3803
|
+
}
|
|
3804
|
+
};
|
|
3255
3805
|
var ThreadWelcome = ({
|
|
3256
3806
|
config,
|
|
3257
3807
|
suggestions,
|
|
3258
3808
|
Suggestions: SuggestionsSlot = Suggestions
|
|
3259
3809
|
}) => {
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3810
|
+
const isEmpty = (0, import_react26.useThread)((s) => s.messages.length === 0);
|
|
3811
|
+
if (!isEmpty) return null;
|
|
3812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
|
|
3813
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3814
|
+
import_react27.motion.div,
|
|
3815
|
+
{
|
|
3816
|
+
className: "aui-thread-welcome-message flex flex-col items-center justify-center px-4 text-center",
|
|
3817
|
+
variants: welcomeStagger,
|
|
3818
|
+
initial: "initial",
|
|
3819
|
+
animate: "animate",
|
|
3820
|
+
children: [
|
|
3821
|
+
config?.icon && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react27.motion.div, { variants: welcomeIcon, className: "mb-5", children: config.icon }),
|
|
3822
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3823
|
+
import_react27.motion.h1,
|
|
3824
|
+
{
|
|
3825
|
+
variants: welcomeItem,
|
|
3826
|
+
className: "aui-thread-welcome-message-inner font-semibold text-2xl",
|
|
3827
|
+
children: config?.heading ?? "How can I help you today?"
|
|
3828
|
+
}
|
|
3829
|
+
),
|
|
3830
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3831
|
+
import_react27.motion.p,
|
|
3832
|
+
{
|
|
3833
|
+
variants: welcomeItem,
|
|
3834
|
+
className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
|
|
3835
|
+
children: config?.subheading ?? "Send a message to start a conversation."
|
|
3836
|
+
}
|
|
3837
|
+
)
|
|
3838
|
+
]
|
|
3839
|
+
}
|
|
3840
|
+
) }),
|
|
3841
|
+
suggestions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SuggestionsSlot, { suggestions }) })
|
|
3842
|
+
] });
|
|
3285
3843
|
};
|
|
3286
3844
|
var MessageError = () => {
|
|
3287
|
-
return /* @__PURE__ */ (0,
|
|
3845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.MessagePrimitive.Error, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.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__ */ (0, import_jsx_runtime27.jsx)(import_react26.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
|
|
3288
3846
|
};
|
|
3289
3847
|
var AssistantMessage = () => {
|
|
3290
|
-
return /* @__PURE__ */ (0,
|
|
3291
|
-
|
|
3848
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3849
|
+
import_react26.MessagePrimitive.Root,
|
|
3292
3850
|
{
|
|
3293
3851
|
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",
|
|
3294
3852
|
"data-role": "assistant",
|
|
3295
3853
|
children: [
|
|
3296
|
-
/* @__PURE__ */ (0,
|
|
3297
|
-
/* @__PURE__ */ (0,
|
|
3298
|
-
|
|
3854
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
|
|
3855
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3856
|
+
import_react26.MessagePrimitive.Parts,
|
|
3299
3857
|
{
|
|
3300
3858
|
components: {
|
|
3301
3859
|
Text: MarkdownText,
|
|
3302
|
-
|
|
3860
|
+
// `Override` (not `Fallback`) replaces the default tool renderer
|
|
3861
|
+
// entirely so we never fall back to the assistant-ui boilerplate.
|
|
3862
|
+
tools: { Override: ToolArtifactFallback }
|
|
3303
3863
|
}
|
|
3304
3864
|
}
|
|
3305
3865
|
),
|
|
3306
|
-
/* @__PURE__ */ (0,
|
|
3866
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MessageError, {})
|
|
3307
3867
|
] }),
|
|
3308
|
-
/* @__PURE__ */ (0,
|
|
3868
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-assistant-message-footer mt-0 ml-1 flex", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AssistantActionBar, {}) })
|
|
3309
3869
|
]
|
|
3310
3870
|
}
|
|
3311
3871
|
);
|
|
3312
3872
|
};
|
|
3873
|
+
var ASSISTANT_ACTION_ICON_CLASS = cn(
|
|
3874
|
+
"size-6 min-h-6 min-w-6 text-muted-foreground/45 hover:text-muted-foreground/80",
|
|
3875
|
+
// The v2 fill span sits inside `group/tbv2 > span:first-child`. We mute it
|
|
3876
|
+
// here so action-bar buttons read as subtle icons rather than full pills.
|
|
3877
|
+
"[&>span:first-child]:bg-transparent",
|
|
3878
|
+
"[&>span:first-child]:group-hover/tbv2:bg-muted/70"
|
|
3879
|
+
);
|
|
3313
3880
|
var AssistantActionBar = () => {
|
|
3314
|
-
return /* @__PURE__ */ (0,
|
|
3315
|
-
|
|
3881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3882
|
+
import_react26.ActionBarPrimitive.Root,
|
|
3316
3883
|
{
|
|
3317
3884
|
hideWhenRunning: true,
|
|
3318
3885
|
autohide: "not-last",
|
|
3319
|
-
|
|
3320
|
-
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",
|
|
3886
|
+
className: "aui-assistant-action-bar-root flex items-center gap-0 bg-transparent px-0 py-0.5 text-muted-foreground/60",
|
|
3321
3887
|
children: [
|
|
3322
|
-
/* @__PURE__ */ (0,
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3888
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3889
|
+
TooltipIconButton,
|
|
3890
|
+
{
|
|
3891
|
+
tooltip: "Copy",
|
|
3892
|
+
variant: "ghost",
|
|
3893
|
+
className: ASSISTANT_ACTION_ICON_CLASS,
|
|
3894
|
+
children: [
|
|
3895
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.AuiIf, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.CheckIcon, { className: "size-3" }) }),
|
|
3896
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.AuiIf, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.CopyIcon, { className: "size-3" }) })
|
|
3897
|
+
]
|
|
3898
|
+
}
|
|
3899
|
+
) }),
|
|
3900
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3901
|
+
TooltipIconButton,
|
|
3902
|
+
{
|
|
3903
|
+
tooltip: "Regenerate",
|
|
3904
|
+
variant: "ghost",
|
|
3905
|
+
className: ASSISTANT_ACTION_ICON_CLASS,
|
|
3906
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.RefreshCwIcon, { className: "size-3" })
|
|
3907
|
+
}
|
|
3908
|
+
) }),
|
|
3909
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react26.ActionBarMorePrimitive.Root, { children: [
|
|
3910
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3329
3911
|
TooltipIconButton,
|
|
3330
3912
|
{
|
|
3331
3913
|
tooltip: "More",
|
|
3332
|
-
|
|
3333
|
-
|
|
3914
|
+
variant: "ghost",
|
|
3915
|
+
className: cn(
|
|
3916
|
+
ASSISTANT_ACTION_ICON_CLASS,
|
|
3917
|
+
"data-[state=open]:text-muted-foreground/80"
|
|
3918
|
+
),
|
|
3919
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.MoreHorizontalIcon, { className: "size-3" })
|
|
3334
3920
|
}
|
|
3335
3921
|
) }),
|
|
3336
|
-
/* @__PURE__ */ (0,
|
|
3337
|
-
|
|
3922
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3923
|
+
import_react26.ActionBarMorePrimitive.Content,
|
|
3338
3924
|
{
|
|
3339
3925
|
side: "bottom",
|
|
3340
3926
|
align: "start",
|
|
3341
|
-
className: "aui-action-bar-more-content z-50 min-w-
|
|
3342
|
-
children: /* @__PURE__ */ (0,
|
|
3343
|
-
/* @__PURE__ */ (0,
|
|
3927
|
+
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",
|
|
3928
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react26.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: [
|
|
3929
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.DownloadIcon, { className: "size-4 shrink-0" }),
|
|
3344
3930
|
"Export as Markdown"
|
|
3345
3931
|
] }) })
|
|
3346
3932
|
}
|
|
@@ -3350,51 +3936,71 @@ var AssistantActionBar = () => {
|
|
|
3350
3936
|
}
|
|
3351
3937
|
);
|
|
3352
3938
|
};
|
|
3939
|
+
var UserMessageText = () => {
|
|
3940
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.MessagePartPrimitive.Text, { smooth: false }) });
|
|
3941
|
+
};
|
|
3353
3942
|
var UserMessage = () => {
|
|
3354
|
-
return /* @__PURE__ */ (0,
|
|
3355
|
-
|
|
3943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3944
|
+
import_react26.MessagePrimitive.Root,
|
|
3356
3945
|
{
|
|
3357
|
-
className: "aui-user-message-root
|
|
3946
|
+
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",
|
|
3358
3947
|
"data-role": "user",
|
|
3359
3948
|
children: [
|
|
3360
|
-
/* @__PURE__ */ (0,
|
|
3361
|
-
/* @__PURE__ */ (0,
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UserMessageAttachments, {}),
|
|
3950
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3951
|
+
import_react27.motion.div,
|
|
3952
|
+
{
|
|
3953
|
+
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",
|
|
3954
|
+
initial: { opacity: 0, y: 8, scale: 0.99 },
|
|
3955
|
+
animate: { opacity: 1, y: 0, scale: 1 },
|
|
3956
|
+
transition: { duration: 0.65, ease: luxuryEase },
|
|
3957
|
+
children: [
|
|
3958
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.MessagePrimitive.Parts, { components: { Text: UserMessageText } }),
|
|
3959
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UserActionBar, {}) })
|
|
3960
|
+
]
|
|
3961
|
+
}
|
|
3962
|
+
)
|
|
3365
3963
|
]
|
|
3366
3964
|
}
|
|
3367
3965
|
);
|
|
3368
3966
|
};
|
|
3369
3967
|
var UserActionBar = () => {
|
|
3370
|
-
return /* @__PURE__ */ (0,
|
|
3371
|
-
|
|
3968
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3969
|
+
import_react26.ActionBarPrimitive.Root,
|
|
3372
3970
|
{
|
|
3373
3971
|
hideWhenRunning: true,
|
|
3374
3972
|
autohide: "not-last",
|
|
3375
3973
|
className: "aui-user-action-bar-root flex flex-col items-end",
|
|
3376
|
-
children: /* @__PURE__ */ (0,
|
|
3974
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3975
|
+
TooltipIconButton,
|
|
3976
|
+
{
|
|
3977
|
+
tooltip: "Edit",
|
|
3978
|
+
variant: "ghost",
|
|
3979
|
+
className: ASSISTANT_ACTION_ICON_CLASS,
|
|
3980
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.PencilIcon, { className: "size-3" })
|
|
3981
|
+
}
|
|
3982
|
+
) })
|
|
3377
3983
|
}
|
|
3378
3984
|
);
|
|
3379
3985
|
};
|
|
3380
3986
|
var EditComposer = () => {
|
|
3381
|
-
return /* @__PURE__ */ (0,
|
|
3382
|
-
/* @__PURE__ */ (0,
|
|
3383
|
-
|
|
3987
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.MessagePrimitive.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react26.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
|
|
3988
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3989
|
+
import_react26.ComposerPrimitive.Input,
|
|
3384
3990
|
{
|
|
3385
3991
|
className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
|
|
3386
3992
|
autoFocus: true
|
|
3387
3993
|
}
|
|
3388
3994
|
),
|
|
3389
|
-
/* @__PURE__ */ (0,
|
|
3390
|
-
/* @__PURE__ */ (0,
|
|
3391
|
-
/* @__PURE__ */ (0,
|
|
3995
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
|
|
3996
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
|
|
3997
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
|
|
3392
3998
|
] })
|
|
3393
3999
|
] }) });
|
|
3394
4000
|
};
|
|
3395
4001
|
|
|
3396
4002
|
// src/components/chat.tsx
|
|
3397
|
-
var
|
|
4003
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3398
4004
|
function TimbalChat({
|
|
3399
4005
|
workforceId,
|
|
3400
4006
|
baseUrl,
|
|
@@ -3405,7 +4011,7 @@ function TimbalChat({
|
|
|
3405
4011
|
debug,
|
|
3406
4012
|
...threadProps
|
|
3407
4013
|
}) {
|
|
3408
|
-
return /* @__PURE__ */ (0,
|
|
4014
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3409
4015
|
TimbalRuntimeProvider,
|
|
3410
4016
|
{
|
|
3411
4017
|
workforceId,
|
|
@@ -3415,23 +4021,1598 @@ function TimbalChat({
|
|
|
3415
4021
|
attachmentsUploadUrl,
|
|
3416
4022
|
attachmentsAccept,
|
|
3417
4023
|
debug,
|
|
3418
|
-
children: /* @__PURE__ */ (0,
|
|
4024
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Thread, { ...threadProps })
|
|
3419
4025
|
}
|
|
3420
4026
|
);
|
|
3421
4027
|
}
|
|
3422
4028
|
|
|
3423
|
-
// src/
|
|
3424
|
-
var
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
4029
|
+
// src/components/workforce-selector.tsx
|
|
4030
|
+
var import_lucide_react9 = require("lucide-react");
|
|
4031
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
4032
|
+
var WorkforceSelector = ({
|
|
4033
|
+
workforces,
|
|
4034
|
+
value,
|
|
4035
|
+
onChange,
|
|
4036
|
+
hideWhenSingle = true,
|
|
4037
|
+
className,
|
|
4038
|
+
placeholder = "Select agent"
|
|
4039
|
+
}) => {
|
|
4040
|
+
if (workforces.length === 0) return null;
|
|
4041
|
+
if (hideWhenSingle && workforces.length === 1) return null;
|
|
4042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
4043
|
+
"div",
|
|
4044
|
+
{
|
|
4045
|
+
className: cn(
|
|
4046
|
+
"aui-workforce-selector relative inline-flex items-center",
|
|
4047
|
+
studioTopbarPillHeightClass,
|
|
4048
|
+
studioSecondaryChromeClass,
|
|
4049
|
+
"rounded-full",
|
|
4050
|
+
className
|
|
4051
|
+
),
|
|
4052
|
+
children: [
|
|
4053
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
4054
|
+
"select",
|
|
4055
|
+
{
|
|
4056
|
+
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",
|
|
4057
|
+
value,
|
|
4058
|
+
onChange: (e) => onChange(e.target.value),
|
|
4059
|
+
"aria-label": placeholder,
|
|
4060
|
+
children: [
|
|
4061
|
+
!value && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "", children: placeholder }),
|
|
4062
|
+
workforces.map((w) => {
|
|
4063
|
+
const id = idOf(w);
|
|
4064
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: id, children: w.name ?? id }, id);
|
|
4065
|
+
})
|
|
4066
|
+
]
|
|
4067
|
+
}
|
|
4068
|
+
),
|
|
4069
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4070
|
+
import_lucide_react9.ChevronDownIcon,
|
|
4071
|
+
{
|
|
4072
|
+
className: "aui-workforce-selector-icon pointer-events-none absolute right-3 size-3.5 text-muted-foreground/70",
|
|
4073
|
+
"aria-hidden": true
|
|
4074
|
+
}
|
|
4075
|
+
)
|
|
4076
|
+
]
|
|
4077
|
+
}
|
|
4078
|
+
);
|
|
4079
|
+
};
|
|
4080
|
+
function idOf(item) {
|
|
4081
|
+
return item.id ?? item.uid ?? item.name ?? "";
|
|
4082
|
+
}
|
|
3428
4083
|
|
|
3429
|
-
|
|
4084
|
+
// src/hooks/use-workforces.ts
|
|
4085
|
+
var import_react28 = require("react");
|
|
4086
|
+
function useWorkforces(options = {}) {
|
|
4087
|
+
const { baseUrl = "/api", fetch: fetchFn, pickInitial, enabled = true } = options;
|
|
4088
|
+
const [workforces, setWorkforces] = (0, import_react28.useState)([]);
|
|
4089
|
+
const [selectedId, setSelectedId] = (0, import_react28.useState)("");
|
|
4090
|
+
const [isLoading, setIsLoading] = (0, import_react28.useState)(enabled);
|
|
4091
|
+
const [error, setError] = (0, import_react28.useState)(null);
|
|
4092
|
+
const fetchFnRef = (0, import_react28.useRef)(fetchFn ?? authFetch);
|
|
4093
|
+
(0, import_react28.useEffect)(() => {
|
|
4094
|
+
fetchFnRef.current = fetchFn ?? authFetch;
|
|
4095
|
+
}, [fetchFn]);
|
|
4096
|
+
const pickInitialRef = (0, import_react28.useRef)(pickInitial);
|
|
4097
|
+
(0, import_react28.useEffect)(() => {
|
|
4098
|
+
pickInitialRef.current = pickInitial;
|
|
4099
|
+
}, [pickInitial]);
|
|
4100
|
+
const load = (0, import_react28.useMemo)(() => {
|
|
4101
|
+
return async () => {
|
|
4102
|
+
if (!enabled) {
|
|
4103
|
+
setIsLoading(false);
|
|
4104
|
+
return;
|
|
4105
|
+
}
|
|
4106
|
+
setIsLoading(true);
|
|
4107
|
+
setError(null);
|
|
4108
|
+
try {
|
|
4109
|
+
const res = await fetchFnRef.current(`${baseUrl}/workforce`);
|
|
4110
|
+
if (!res.ok) throw new Error(`Failed to load workforces (${res.status})`);
|
|
4111
|
+
const data = await res.json();
|
|
4112
|
+
setWorkforces(data);
|
|
4113
|
+
setSelectedId((current) => {
|
|
4114
|
+
if (current && data.some((w) => idOf2(w) === current)) return current;
|
|
4115
|
+
const initial = pickInitialRef.current?.(data) ?? data.find((w) => w.type === "agent") ?? data[0];
|
|
4116
|
+
return initial ? idOf2(initial) : "";
|
|
4117
|
+
});
|
|
4118
|
+
} catch (err) {
|
|
4119
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
4120
|
+
} finally {
|
|
4121
|
+
setIsLoading(false);
|
|
4122
|
+
}
|
|
4123
|
+
};
|
|
4124
|
+
}, [baseUrl, enabled]);
|
|
4125
|
+
(0, import_react28.useEffect)(() => {
|
|
4126
|
+
load();
|
|
4127
|
+
}, [load]);
|
|
4128
|
+
const selected = (0, import_react28.useMemo)(
|
|
4129
|
+
() => workforces.find((w) => idOf2(w) === selectedId),
|
|
4130
|
+
[workforces, selectedId]
|
|
4131
|
+
);
|
|
4132
|
+
return {
|
|
4133
|
+
workforces,
|
|
4134
|
+
selectedId,
|
|
4135
|
+
setSelectedId,
|
|
4136
|
+
selected,
|
|
4137
|
+
isLoading,
|
|
4138
|
+
error,
|
|
4139
|
+
refresh: load
|
|
4140
|
+
};
|
|
4141
|
+
}
|
|
4142
|
+
function idOf2(item) {
|
|
4143
|
+
return item.id ?? item.uid ?? item.name ?? "";
|
|
4144
|
+
}
|
|
3430
4145
|
|
|
3431
|
-
|
|
3432
|
-
|
|
4146
|
+
// src/design/tokens.ts
|
|
4147
|
+
var SIDEBAR_WIDTH_PX = 224;
|
|
4148
|
+
var SIDEBAR_WIDTH_COLLAPSED_PX = 52;
|
|
4149
|
+
var SIDEBAR_MOBILE_PX = 272;
|
|
4150
|
+
var SIDEBAR_GAP_PX = 12;
|
|
4151
|
+
var SIDEBAR_CONTENT_GAP_PX = 8;
|
|
4152
|
+
var TOPBAR_GAP_PX = 8;
|
|
4153
|
+
var TOPBAR_HEIGHT_PX = 48;
|
|
4154
|
+
var PILL_HEIGHT_PX = 40;
|
|
4155
|
+
var SIDEBAR_INSET_PX_EXPANDED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
4156
|
+
var SIDEBAR_INSET_PX_COLLAPSED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_COLLAPSED_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
4157
|
+
var px = (n) => `${n / 16}rem`;
|
|
4158
|
+
var SIDEBAR_WIDTH = px(SIDEBAR_WIDTH_PX);
|
|
4159
|
+
var SIDEBAR_WIDTH_COLLAPSED = px(SIDEBAR_WIDTH_COLLAPSED_PX);
|
|
4160
|
+
var SIDEBAR_GAP = px(SIDEBAR_GAP_PX);
|
|
4161
|
+
var SIDEBAR_CONTENT_GAP = px(SIDEBAR_CONTENT_GAP_PX);
|
|
4162
|
+
var TOPBAR_GAP = px(TOPBAR_GAP_PX);
|
|
4163
|
+
var TOPBAR_HEIGHT = px(TOPBAR_HEIGHT_PX);
|
|
4164
|
+
var PILL_HEIGHT = px(PILL_HEIGHT_PX);
|
|
4165
|
+
var SIDEBAR_INSET_EXPANDED = px(SIDEBAR_INSET_PX_EXPANDED);
|
|
4166
|
+
var SIDEBAR_INSET_COLLAPSED = px(SIDEBAR_INSET_PX_COLLAPSED);
|
|
4167
|
+
var studioChromeShellStyle = {
|
|
4168
|
+
"--studio-topbar-gap": TOPBAR_GAP,
|
|
4169
|
+
"--studio-topbar-height": TOPBAR_HEIGHT,
|
|
4170
|
+
"--studio-chrome-pill-height": PILL_HEIGHT,
|
|
4171
|
+
"--studio-inset-top": `calc(${TOPBAR_GAP} + ${TOPBAR_HEIGHT})`,
|
|
4172
|
+
"--studio-sidebar-gap": SIDEBAR_GAP,
|
|
4173
|
+
"--studio-sidebar-width": SIDEBAR_WIDTH,
|
|
4174
|
+
"--studio-sidebar-width-collapsed": SIDEBAR_WIDTH_COLLAPSED,
|
|
4175
|
+
"--studio-sidebar-content-gap": SIDEBAR_CONTENT_GAP,
|
|
4176
|
+
"--studio-inset-left": SIDEBAR_INSET_EXPANDED,
|
|
4177
|
+
"--studio-inset-left-collapsed": SIDEBAR_INSET_COLLAPSED
|
|
4178
|
+
};
|
|
4179
|
+
var STORAGE_KEYS = {
|
|
4180
|
+
sidebarCollapsed: "timbal-studio-sidebar-collapsed"
|
|
4181
|
+
};
|
|
4182
|
+
var DOM_IDS = {
|
|
4183
|
+
sidebarRuntimeAnchor: "timbal-studio-sidebar-runtime-anchor",
|
|
4184
|
+
topbarBrandAnchor: "timbal-studio-topbar-brand-anchor"
|
|
4185
|
+
};
|
|
3433
4186
|
|
|
3434
|
-
|
|
4187
|
+
// src/components/chat-shell.tsx
|
|
4188
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
4189
|
+
var TimbalChatShell = ({
|
|
4190
|
+
workforceId,
|
|
4191
|
+
brand,
|
|
4192
|
+
headerActions,
|
|
4193
|
+
hideWorkforceSelector,
|
|
4194
|
+
className,
|
|
4195
|
+
headerClassName,
|
|
4196
|
+
baseUrl,
|
|
4197
|
+
fetch: fetch2,
|
|
4198
|
+
...chatProps
|
|
4199
|
+
}) => {
|
|
4200
|
+
const { workforces, selectedId, setSelectedId } = useWorkforces({
|
|
4201
|
+
baseUrl,
|
|
4202
|
+
fetch: fetch2
|
|
4203
|
+
});
|
|
4204
|
+
const effectiveId = workforceId ?? selectedId;
|
|
4205
|
+
const showSelector = !hideWorkforceSelector && !workforceId && workforces.length > 0;
|
|
4206
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4207
|
+
"div",
|
|
4208
|
+
{
|
|
4209
|
+
className: cn(
|
|
4210
|
+
"aui-chat-shell relative flex h-dvh flex-col overflow-hidden bg-background",
|
|
4211
|
+
className
|
|
4212
|
+
),
|
|
4213
|
+
style: studioChromeShellStyle,
|
|
4214
|
+
children: [
|
|
4215
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4216
|
+
"div",
|
|
4217
|
+
{
|
|
4218
|
+
className: cn(
|
|
4219
|
+
"pointer-events-none absolute inset-0 z-0",
|
|
4220
|
+
studioPlaygroundGradientClass
|
|
4221
|
+
),
|
|
4222
|
+
"aria-hidden": true
|
|
4223
|
+
}
|
|
4224
|
+
),
|
|
4225
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4226
|
+
"header",
|
|
4227
|
+
{
|
|
4228
|
+
className: cn(
|
|
4229
|
+
"aui-chat-shell-header relative z-10 flex shrink-0 items-center justify-between px-4 pt-[var(--studio-topbar-gap)] pb-2",
|
|
4230
|
+
headerClassName
|
|
4231
|
+
),
|
|
4232
|
+
style: { minHeight: "var(--studio-topbar-height)" },
|
|
4233
|
+
children: [
|
|
4234
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
4235
|
+
brand,
|
|
4236
|
+
showSelector && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4237
|
+
WorkforceSelector,
|
|
4238
|
+
{
|
|
4239
|
+
workforces,
|
|
4240
|
+
value: selectedId,
|
|
4241
|
+
onChange: setSelectedId
|
|
4242
|
+
}
|
|
4243
|
+
)
|
|
4244
|
+
] }),
|
|
4245
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex shrink-0 items-center gap-1", children: headerActions })
|
|
4246
|
+
]
|
|
4247
|
+
}
|
|
4248
|
+
),
|
|
4249
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4250
|
+
TimbalChat,
|
|
4251
|
+
{
|
|
4252
|
+
workforceId: effectiveId,
|
|
4253
|
+
baseUrl,
|
|
4254
|
+
fetch: fetch2,
|
|
4255
|
+
className: "relative z-10 min-h-0 flex-1 bg-transparent",
|
|
4256
|
+
...chatProps
|
|
4257
|
+
},
|
|
4258
|
+
effectiveId
|
|
4259
|
+
)
|
|
4260
|
+
]
|
|
4261
|
+
}
|
|
4262
|
+
);
|
|
4263
|
+
};
|
|
4264
|
+
|
|
4265
|
+
// src/components/studio/studio-shell.tsx
|
|
4266
|
+
var import_react41 = require("react");
|
|
4267
|
+
var import_lucide_react13 = require("lucide-react");
|
|
4268
|
+
var import_react42 = require("motion/react");
|
|
4269
|
+
|
|
4270
|
+
// src/design/sidebar-motion.ts
|
|
4271
|
+
var STUDIO_SIDEBAR_EASE_ENTER = [0, 0, 0.2, 1];
|
|
4272
|
+
var STUDIO_SIDEBAR_EASE_EXIT = [0.4, 0, 1, 1];
|
|
4273
|
+
var STUDIO_SIDEBAR_EASE = [0.16, 1, 0.3, 1];
|
|
4274
|
+
var STUDIO_SIDEBAR_ENTRIES_OUT_S = 0.1;
|
|
4275
|
+
var STUDIO_SIDEBAR_WIDTH_S = 0.17;
|
|
4276
|
+
var STUDIO_SIDEBAR_ENTRY_ITEM_IN_S = 0.18;
|
|
4277
|
+
var STUDIO_SIDEBAR_STAGGER_S = 0.03;
|
|
4278
|
+
var STUDIO_SIDEBAR_EXPAND_REVEAL_FRAC = 0.5;
|
|
4279
|
+
var STUDIO_SIDEBAR_CONTENT_NUDGE_PX = 6;
|
|
4280
|
+
var studioSidebarEntriesContainerVariants = {
|
|
4281
|
+
hidden: {
|
|
4282
|
+
opacity: 0,
|
|
4283
|
+
transition: {
|
|
4284
|
+
duration: STUDIO_SIDEBAR_ENTRIES_OUT_S,
|
|
4285
|
+
ease: STUDIO_SIDEBAR_EASE_EXIT,
|
|
4286
|
+
staggerChildren: 0
|
|
4287
|
+
}
|
|
4288
|
+
},
|
|
4289
|
+
visible: {
|
|
4290
|
+
opacity: 1,
|
|
4291
|
+
transition: {
|
|
4292
|
+
duration: 0.06,
|
|
4293
|
+
ease: STUDIO_SIDEBAR_EASE_ENTER,
|
|
4294
|
+
staggerChildren: STUDIO_SIDEBAR_STAGGER_S,
|
|
4295
|
+
delayChildren: 0.02
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
};
|
|
4299
|
+
var studioSidebarEntryItemVariants = {
|
|
4300
|
+
hidden: {
|
|
4301
|
+
opacity: 0,
|
|
4302
|
+
x: -STUDIO_SIDEBAR_CONTENT_NUDGE_PX,
|
|
4303
|
+
scale: 0.99
|
|
4304
|
+
},
|
|
4305
|
+
visible: {
|
|
4306
|
+
opacity: 1,
|
|
4307
|
+
x: 0,
|
|
4308
|
+
scale: 1,
|
|
4309
|
+
transition: {
|
|
4310
|
+
duration: STUDIO_SIDEBAR_ENTRY_ITEM_IN_S,
|
|
4311
|
+
ease: STUDIO_SIDEBAR_EASE_ENTER
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
};
|
|
4315
|
+
function studioSidebarEntriesTransition(visible, reduced) {
|
|
4316
|
+
if (reduced) return { duration: 0.01 };
|
|
4317
|
+
return visible ? { duration: 0.06, ease: STUDIO_SIDEBAR_EASE_ENTER } : { duration: STUDIO_SIDEBAR_ENTRIES_OUT_S, ease: STUDIO_SIDEBAR_EASE_EXIT };
|
|
4318
|
+
}
|
|
4319
|
+
function studioSidebarWidthTransition(reduced, direction = "collapse") {
|
|
4320
|
+
if (reduced) return { duration: 0.01 };
|
|
4321
|
+
return {
|
|
4322
|
+
duration: direction === "expand" ? STUDIO_SIDEBAR_WIDTH_S : STUDIO_SIDEBAR_WIDTH_S * 0.94,
|
|
4323
|
+
ease: direction === "expand" ? STUDIO_SIDEBAR_EASE_ENTER : STUDIO_SIDEBAR_EASE_EXIT
|
|
4324
|
+
};
|
|
4325
|
+
}
|
|
4326
|
+
function studioSidebarDrawerTransition(reduced) {
|
|
4327
|
+
if (reduced) return { duration: 0.01 };
|
|
4328
|
+
return {
|
|
4329
|
+
duration: 0.22,
|
|
4330
|
+
ease: STUDIO_SIDEBAR_EASE
|
|
4331
|
+
};
|
|
4332
|
+
}
|
|
4333
|
+
function studioSidebarBackdropTransition(reduced) {
|
|
4334
|
+
if (reduced) return { duration: 0.01 };
|
|
4335
|
+
return { duration: 0.16, ease: STUDIO_SIDEBAR_EASE_EXIT };
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4338
|
+
// src/hooks/use-sidebar-collapse-phase.ts
|
|
4339
|
+
var import_react29 = require("react");
|
|
4340
|
+
var WIDTH_OVERLAP_FRAC = 0.7;
|
|
4341
|
+
function useSidebarCollapsePhase(collapsed, reducedMotion) {
|
|
4342
|
+
const [widthCollapsed, setWidthCollapsed] = (0, import_react29.useState)(collapsed);
|
|
4343
|
+
const [entriesVisible, setEntriesVisible] = (0, import_react29.useState)(true);
|
|
4344
|
+
const collapsedTarget = (0, import_react29.useRef)(collapsed);
|
|
4345
|
+
const isFirstRender = (0, import_react29.useRef)(true);
|
|
4346
|
+
const widthTimerRef = (0, import_react29.useRef)(null);
|
|
4347
|
+
const revealTimerRef = (0, import_react29.useRef)(null);
|
|
4348
|
+
(0, import_react29.useEffect)(() => {
|
|
4349
|
+
collapsedTarget.current = collapsed;
|
|
4350
|
+
}, [collapsed]);
|
|
4351
|
+
const clearWidthTimer = () => {
|
|
4352
|
+
if (widthTimerRef.current !== null) {
|
|
4353
|
+
clearTimeout(widthTimerRef.current);
|
|
4354
|
+
widthTimerRef.current = null;
|
|
4355
|
+
}
|
|
4356
|
+
};
|
|
4357
|
+
const clearRevealTimer = () => {
|
|
4358
|
+
if (revealTimerRef.current !== null) {
|
|
4359
|
+
clearTimeout(revealTimerRef.current);
|
|
4360
|
+
revealTimerRef.current = null;
|
|
4361
|
+
}
|
|
4362
|
+
};
|
|
4363
|
+
const applyWidthTarget = (0, import_react29.useCallback)(() => {
|
|
4364
|
+
const willExpand = !collapsedTarget.current;
|
|
4365
|
+
setWidthCollapsed(collapsedTarget.current);
|
|
4366
|
+
clearRevealTimer();
|
|
4367
|
+
if (willExpand && !reducedMotion) {
|
|
4368
|
+
revealTimerRef.current = setTimeout(
|
|
4369
|
+
() => setEntriesVisible(true),
|
|
4370
|
+
STUDIO_SIDEBAR_WIDTH_S * 1e3 * STUDIO_SIDEBAR_EXPAND_REVEAL_FRAC
|
|
4371
|
+
);
|
|
4372
|
+
}
|
|
4373
|
+
}, [reducedMotion]);
|
|
4374
|
+
(0, import_react29.useEffect)(() => {
|
|
4375
|
+
clearWidthTimer();
|
|
4376
|
+
clearRevealTimer();
|
|
4377
|
+
if (reducedMotion) {
|
|
4378
|
+
setWidthCollapsed(collapsed);
|
|
4379
|
+
setEntriesVisible(true);
|
|
4380
|
+
return;
|
|
4381
|
+
}
|
|
4382
|
+
if (isFirstRender.current) {
|
|
4383
|
+
isFirstRender.current = false;
|
|
4384
|
+
setWidthCollapsed(collapsed);
|
|
4385
|
+
setEntriesVisible(true);
|
|
4386
|
+
return;
|
|
4387
|
+
}
|
|
4388
|
+
setEntriesVisible(false);
|
|
4389
|
+
widthTimerRef.current = setTimeout(
|
|
4390
|
+
applyWidthTarget,
|
|
4391
|
+
STUDIO_SIDEBAR_ENTRIES_OUT_S * 1e3 * WIDTH_OVERLAP_FRAC
|
|
4392
|
+
);
|
|
4393
|
+
return () => {
|
|
4394
|
+
clearWidthTimer();
|
|
4395
|
+
clearRevealTimer();
|
|
4396
|
+
};
|
|
4397
|
+
}, [collapsed, reducedMotion, applyWidthTarget]);
|
|
4398
|
+
const onEntriesBlurOutComplete = (0, import_react29.useCallback)(() => {
|
|
4399
|
+
applyWidthTarget();
|
|
4400
|
+
}, [applyWidthTarget]);
|
|
4401
|
+
const onPanelWidthComplete = (0, import_react29.useCallback)(() => {
|
|
4402
|
+
clearRevealTimer();
|
|
4403
|
+
setEntriesVisible(true);
|
|
4404
|
+
}, []);
|
|
4405
|
+
const isCollapsedRail = widthCollapsed;
|
|
4406
|
+
return {
|
|
4407
|
+
widthCollapsed,
|
|
4408
|
+
isCollapsedRail,
|
|
4409
|
+
entriesVisible,
|
|
4410
|
+
onEntriesBlurOutComplete,
|
|
4411
|
+
onPanelWidthComplete
|
|
4412
|
+
};
|
|
4413
|
+
}
|
|
4414
|
+
|
|
4415
|
+
// src/components/studio/sidebar-backdrop.tsx
|
|
4416
|
+
var import_react30 = require("motion/react");
|
|
4417
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
4418
|
+
var StudioSidebarBackdrop = ({
|
|
4419
|
+
open,
|
|
4420
|
+
onClose
|
|
4421
|
+
}) => {
|
|
4422
|
+
const reducedMotion = (0, import_react30.useReducedMotion)();
|
|
4423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react30.AnimatePresence, { children: open ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
4424
|
+
import_react30.motion.button,
|
|
4425
|
+
{
|
|
4426
|
+
type: "button",
|
|
4427
|
+
className: "fixed inset-0 z-40 bg-foreground/30 backdrop-blur-[2px] md:hidden",
|
|
4428
|
+
"aria-label": "Close menu",
|
|
4429
|
+
initial: { opacity: 0 },
|
|
4430
|
+
animate: { opacity: 1 },
|
|
4431
|
+
exit: { opacity: 0 },
|
|
4432
|
+
transition: studioSidebarBackdropTransition(!!reducedMotion),
|
|
4433
|
+
onClick: onClose
|
|
4434
|
+
}
|
|
4435
|
+
) : null });
|
|
4436
|
+
};
|
|
4437
|
+
|
|
4438
|
+
// src/components/studio/sidebar-context.tsx
|
|
4439
|
+
var import_react31 = require("react");
|
|
4440
|
+
var StudioSidebarContext = (0, import_react31.createContext)({
|
|
4441
|
+
collapsed: false,
|
|
4442
|
+
isMobile: false,
|
|
4443
|
+
isCollapsedRail: false,
|
|
4444
|
+
iconOnlyLayout: false
|
|
4445
|
+
});
|
|
4446
|
+
function useStudioSidebarLayout() {
|
|
4447
|
+
return (0, import_react31.useContext)(StudioSidebarContext);
|
|
4448
|
+
}
|
|
4449
|
+
|
|
4450
|
+
// src/components/studio/sidebar.tsx
|
|
4451
|
+
var import_react35 = require("react");
|
|
4452
|
+
var import_react36 = require("motion/react");
|
|
4453
|
+
|
|
4454
|
+
// src/components/studio/sidebar-entries.tsx
|
|
4455
|
+
var import_react32 = require("motion/react");
|
|
4456
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
4457
|
+
var StudioSidebarEntries = ({
|
|
4458
|
+
visible,
|
|
4459
|
+
onBlurOutComplete,
|
|
4460
|
+
children,
|
|
4461
|
+
className
|
|
4462
|
+
}) => {
|
|
4463
|
+
const reducedMotion = (0, import_react32.useReducedMotion)();
|
|
4464
|
+
if (reducedMotion) {
|
|
4465
|
+
return visible ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn("flex min-h-0 flex-1 flex-col", className), children }) : null;
|
|
4466
|
+
}
|
|
4467
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
4468
|
+
import_react32.motion.div,
|
|
4469
|
+
{
|
|
4470
|
+
className: cn("flex min-h-0 flex-1 flex-col", className),
|
|
4471
|
+
initial: false,
|
|
4472
|
+
variants: studioSidebarEntriesContainerVariants,
|
|
4473
|
+
animate: visible ? "visible" : "hidden",
|
|
4474
|
+
transition: studioSidebarEntriesTransition(visible, false),
|
|
4475
|
+
onAnimationComplete: (definition) => {
|
|
4476
|
+
if (definition === "hidden") {
|
|
4477
|
+
onBlurOutComplete();
|
|
4478
|
+
}
|
|
4479
|
+
},
|
|
4480
|
+
style: { pointerEvents: visible ? "auto" : "none" },
|
|
4481
|
+
"aria-hidden": !visible,
|
|
4482
|
+
children
|
|
4483
|
+
}
|
|
4484
|
+
);
|
|
4485
|
+
};
|
|
4486
|
+
|
|
4487
|
+
// src/components/studio/sidebar-footer.tsx
|
|
4488
|
+
var import_lucide_react10 = require("lucide-react");
|
|
4489
|
+
|
|
4490
|
+
// src/auth/provider.tsx
|
|
4491
|
+
var import_react33 = require("react");
|
|
4492
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
4493
|
+
function isInsideIframe() {
|
|
4494
|
+
try {
|
|
4495
|
+
return typeof window !== "undefined" && window.self !== window.top;
|
|
4496
|
+
} catch {
|
|
4497
|
+
return true;
|
|
4498
|
+
}
|
|
4499
|
+
}
|
|
4500
|
+
var SessionContext = (0, import_react33.createContext)(void 0);
|
|
4501
|
+
var useSession = () => {
|
|
4502
|
+
const context = (0, import_react33.useContext)(SessionContext);
|
|
4503
|
+
if (context === void 0) {
|
|
4504
|
+
throw new Error("useSession must be used within a SessionProvider");
|
|
4505
|
+
}
|
|
4506
|
+
return context;
|
|
4507
|
+
};
|
|
4508
|
+
var useOptionalSession = () => {
|
|
4509
|
+
const context = (0, import_react33.useContext)(SessionContext);
|
|
4510
|
+
return context ?? null;
|
|
4511
|
+
};
|
|
4512
|
+
var SessionProvider = ({
|
|
4513
|
+
children,
|
|
4514
|
+
enabled = true
|
|
4515
|
+
}) => {
|
|
4516
|
+
const [user, setUser] = (0, import_react33.useState)(null);
|
|
4517
|
+
const [loading, setLoading] = (0, import_react33.useState)(enabled);
|
|
4518
|
+
const [embedded] = (0, import_react33.useState)(isInsideIframe);
|
|
4519
|
+
(0, import_react33.useEffect)(() => {
|
|
4520
|
+
if (!enabled) {
|
|
4521
|
+
setLoading(false);
|
|
4522
|
+
return;
|
|
4523
|
+
}
|
|
4524
|
+
let ignore = false;
|
|
4525
|
+
const restoreSession = async () => {
|
|
4526
|
+
try {
|
|
4527
|
+
const u = await fetchCurrentUser();
|
|
4528
|
+
if (ignore) return;
|
|
4529
|
+
if (u) {
|
|
4530
|
+
setUser(u);
|
|
4531
|
+
setLoading(false);
|
|
4532
|
+
return;
|
|
4533
|
+
}
|
|
4534
|
+
if (getRefreshToken()) {
|
|
4535
|
+
const ok = await refreshAccessToken();
|
|
4536
|
+
if (ignore) return;
|
|
4537
|
+
if (ok) {
|
|
4538
|
+
const refreshedUser = await fetchCurrentUser();
|
|
4539
|
+
if (ignore) return;
|
|
4540
|
+
if (refreshedUser) {
|
|
4541
|
+
setUser(refreshedUser);
|
|
4542
|
+
setLoading(false);
|
|
4543
|
+
return;
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
4547
|
+
} catch {
|
|
4548
|
+
if (ignore) return;
|
|
4549
|
+
clearTokens();
|
|
4550
|
+
}
|
|
4551
|
+
if (!ignore && !embedded) {
|
|
4552
|
+
setLoading(false);
|
|
4553
|
+
}
|
|
4554
|
+
};
|
|
4555
|
+
restoreSession();
|
|
4556
|
+
let messageCleanup;
|
|
4557
|
+
if (embedded) {
|
|
4558
|
+
const handleMessage = async (event) => {
|
|
4559
|
+
if (ignore) return;
|
|
4560
|
+
if (event.data?.type !== "timbal:auth" || !event.data.token) return;
|
|
4561
|
+
setAccessToken(event.data.token);
|
|
4562
|
+
if (event.data.refreshToken) {
|
|
4563
|
+
setRefreshToken(event.data.refreshToken);
|
|
4564
|
+
}
|
|
4565
|
+
const u = await fetchCurrentUser();
|
|
4566
|
+
if (!ignore) {
|
|
4567
|
+
setUser(u);
|
|
4568
|
+
setLoading(false);
|
|
4569
|
+
}
|
|
4570
|
+
};
|
|
4571
|
+
window.addEventListener("message", handleMessage);
|
|
4572
|
+
window.parent.postMessage({ type: "timbal:request-session" }, "*");
|
|
4573
|
+
messageCleanup = () => window.removeEventListener("message", handleMessage);
|
|
4574
|
+
}
|
|
4575
|
+
return () => {
|
|
4576
|
+
ignore = true;
|
|
4577
|
+
messageCleanup?.();
|
|
4578
|
+
};
|
|
4579
|
+
}, [enabled, embedded]);
|
|
4580
|
+
const logout = (0, import_react33.useCallback)(() => {
|
|
4581
|
+
clearTokens();
|
|
4582
|
+
setUser(null);
|
|
4583
|
+
const returnTo = encodeURIComponent(
|
|
4584
|
+
window.location.pathname + window.location.search
|
|
4585
|
+
);
|
|
4586
|
+
fetch("/api/auth/logout", { method: "POST" }).finally(
|
|
4587
|
+
() => window.location.href = `/api/auth/login?return_to=${returnTo}`
|
|
4588
|
+
);
|
|
4589
|
+
}, []);
|
|
4590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
4591
|
+
SessionContext.Provider,
|
|
4592
|
+
{
|
|
4593
|
+
value: {
|
|
4594
|
+
user,
|
|
4595
|
+
loading,
|
|
4596
|
+
isAuthenticated: !!user,
|
|
4597
|
+
isEmbedded: embedded,
|
|
4598
|
+
logout
|
|
4599
|
+
},
|
|
4600
|
+
children
|
|
4601
|
+
}
|
|
4602
|
+
);
|
|
4603
|
+
};
|
|
4604
|
+
|
|
4605
|
+
// src/components/studio/sidebar-layout.ts
|
|
4606
|
+
function studioSidebarIconOnlyLayout(isMobile, isCollapsedRail) {
|
|
4607
|
+
if (isMobile) return false;
|
|
4608
|
+
return isCollapsedRail;
|
|
4609
|
+
}
|
|
4610
|
+
var studioSidebarCollapsedRailInsetClass = "box-border w-full px-1.5";
|
|
4611
|
+
var studioSidebarCollapsedRailChipRowClass = "flex w-full justify-center";
|
|
4612
|
+
function studioSidebarNavItemClasses(iconOnly, isActive) {
|
|
4613
|
+
if (iconOnly) {
|
|
4614
|
+
return cn(
|
|
4615
|
+
studioSidebarNavItemClass,
|
|
4616
|
+
studioSidebarNavItemLayout(true),
|
|
4617
|
+
isActive ? studioSidebarCollapsedRailItemActiveClass : studioSidebarCollapsedRailItemIdleClass
|
|
4618
|
+
);
|
|
4619
|
+
}
|
|
4620
|
+
return cn(
|
|
4621
|
+
studioSidebarNavItemClass,
|
|
4622
|
+
studioSidebarNavItemLayout(false),
|
|
4623
|
+
isActive ? studioSidebarNavItemActiveClass : studioSidebarNavItemIdleClass
|
|
4624
|
+
);
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4627
|
+
// src/components/studio/sidebar-entry-motion.tsx
|
|
4628
|
+
var import_react34 = require("motion/react");
|
|
4629
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
4630
|
+
var StudioSidebarEntryMotion = ({
|
|
4631
|
+
children,
|
|
4632
|
+
className
|
|
4633
|
+
}) => {
|
|
4634
|
+
const reducedMotion = (0, import_react34.useReducedMotion)();
|
|
4635
|
+
if (reducedMotion) {
|
|
4636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className, children });
|
|
4637
|
+
}
|
|
4638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react34.motion.div, { variants: studioSidebarEntryItemVariants, className: cn(className), children });
|
|
4639
|
+
};
|
|
4640
|
+
|
|
4641
|
+
// src/components/studio/sidebar-tooltip.tsx
|
|
4642
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
4643
|
+
var StudioSidebarTooltip = ({
|
|
4644
|
+
label,
|
|
4645
|
+
enabled,
|
|
4646
|
+
children
|
|
4647
|
+
}) => {
|
|
4648
|
+
if (!enabled) return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children });
|
|
4649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(Tooltip, { children: [
|
|
4650
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TooltipTrigger, { asChild: true, children }),
|
|
4651
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TooltipContent, { side: "right", className: "text-xs", children: label })
|
|
4652
|
+
] });
|
|
4653
|
+
};
|
|
4654
|
+
|
|
4655
|
+
// src/components/studio/sidebar-footer.tsx
|
|
4656
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
4657
|
+
function userInitials(name, email) {
|
|
4658
|
+
const fromName = name.trim().split(/\s+/).map((part) => part.charAt(0)).join("").slice(0, 2).toUpperCase();
|
|
4659
|
+
if (fromName) return fromName;
|
|
4660
|
+
return email.charAt(0).toUpperCase() || "?";
|
|
4661
|
+
}
|
|
4662
|
+
var StudioSidebarFooter = ({
|
|
4663
|
+
iconOnlyLayout,
|
|
4664
|
+
showTooltips,
|
|
4665
|
+
onSignOut,
|
|
4666
|
+
emptyCaption = null
|
|
4667
|
+
}) => {
|
|
4668
|
+
const session = useOptionalSession();
|
|
4669
|
+
const user = session?.user ?? null;
|
|
4670
|
+
const handleSignOut = () => {
|
|
4671
|
+
session?.logout();
|
|
4672
|
+
onSignOut?.();
|
|
4673
|
+
};
|
|
4674
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(StudioSidebarEntryMotion, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
4675
|
+
"footer",
|
|
4676
|
+
{
|
|
4677
|
+
className: cn(
|
|
4678
|
+
"mt-auto w-full shrink-0 py-2.5",
|
|
4679
|
+
iconOnlyLayout ? studioSidebarCollapsedRailInsetClass : "px-2.5"
|
|
4680
|
+
),
|
|
4681
|
+
children: user ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
4682
|
+
iconOnlyLayout ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: studioSidebarCollapsedRailChipRowClass, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Avatar, { size: "sm", className: "size-8", children: [
|
|
4683
|
+
user.user_photo_url ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AvatarImage, { src: user.user_photo_url, alt: user.user_name }) : null,
|
|
4684
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AvatarFallback, { className: "text-[10px]", children: userInitials(user.user_name, user.user_email) })
|
|
4685
|
+
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
4686
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Avatar, { size: "sm", children: [
|
|
4687
|
+
user.user_photo_url ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AvatarImage, { src: user.user_photo_url, alt: user.user_name }) : null,
|
|
4688
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AvatarFallback, { children: userInitials(user.user_name, user.user_email) })
|
|
4689
|
+
] }),
|
|
4690
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
4691
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "truncate text-sm font-medium text-foreground", children: user.user_name }),
|
|
4692
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "truncate text-xs text-muted-foreground", children: user.user_email })
|
|
4693
|
+
] })
|
|
4694
|
+
] }),
|
|
4695
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
4696
|
+
"div",
|
|
4697
|
+
{
|
|
4698
|
+
className: iconOnlyLayout ? studioSidebarCollapsedRailChipRowClass : void 0,
|
|
4699
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(StudioSidebarTooltip, { label: "Sign out", enabled: showTooltips, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
4700
|
+
"button",
|
|
4701
|
+
{
|
|
4702
|
+
type: "button",
|
|
4703
|
+
onClick: handleSignOut,
|
|
4704
|
+
className: cn(
|
|
4705
|
+
studioSidebarNavItemClasses(iconOnlyLayout, false),
|
|
4706
|
+
iconOnlyLayout && "inline-flex"
|
|
4707
|
+
),
|
|
4708
|
+
"aria-label": "Sign out",
|
|
4709
|
+
children: [
|
|
4710
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react10.LogOut, { className: "size-3.5 shrink-0" }),
|
|
4711
|
+
!iconOnlyLayout ? "Sign out" : null
|
|
4712
|
+
]
|
|
4713
|
+
}
|
|
4714
|
+
) })
|
|
4715
|
+
}
|
|
4716
|
+
)
|
|
4717
|
+
] }) : !iconOnlyLayout && emptyCaption ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: emptyCaption }) : null
|
|
4718
|
+
}
|
|
4719
|
+
) });
|
|
4720
|
+
};
|
|
4721
|
+
|
|
4722
|
+
// src/components/studio/sidebar-header.tsx
|
|
4723
|
+
var import_lucide_react11 = require("lucide-react");
|
|
4724
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
4725
|
+
var sidebarHeaderClass = "flex h-12 shrink-0 items-center px-2";
|
|
4726
|
+
var toggleButtonClass = cn(
|
|
4727
|
+
"flex shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors",
|
|
4728
|
+
"hover:bg-muted hover:text-foreground",
|
|
4729
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15"
|
|
4730
|
+
);
|
|
4731
|
+
var SidebarToggleButton = ({ ariaLabel, expanded, onClick, children }) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4732
|
+
"button",
|
|
4733
|
+
{
|
|
4734
|
+
type: "button",
|
|
4735
|
+
onClick,
|
|
4736
|
+
className: cn(toggleButtonClass, "size-7"),
|
|
4737
|
+
"aria-label": ariaLabel,
|
|
4738
|
+
"aria-expanded": expanded,
|
|
4739
|
+
children
|
|
4740
|
+
}
|
|
4741
|
+
);
|
|
4742
|
+
var CollapsedBrandToggle = ({
|
|
4743
|
+
onExpand,
|
|
4744
|
+
brand
|
|
4745
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: studioSidebarCollapsedRailChipRowClass, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(StudioSidebarTooltip, { label: "Expand sidebar", enabled: true, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
4746
|
+
"button",
|
|
4747
|
+
{
|
|
4748
|
+
type: "button",
|
|
4749
|
+
onClick: onExpand,
|
|
4750
|
+
"aria-label": "Expand sidebar",
|
|
4751
|
+
"aria-expanded": false,
|
|
4752
|
+
className: cn(
|
|
4753
|
+
toggleButtonClass,
|
|
4754
|
+
"group relative inline-flex size-8 items-center justify-center overflow-hidden rounded-lg"
|
|
4755
|
+
),
|
|
4756
|
+
children: [
|
|
4757
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4758
|
+
"span",
|
|
4759
|
+
{
|
|
4760
|
+
"aria-hidden": true,
|
|
4761
|
+
className: cn(
|
|
4762
|
+
"pointer-events-none flex items-center justify-center",
|
|
4763
|
+
"transition-[opacity,transform] duration-200 ease-out",
|
|
4764
|
+
"group-hover:scale-90 group-hover:opacity-0"
|
|
4765
|
+
),
|
|
4766
|
+
children: brand
|
|
4767
|
+
}
|
|
4768
|
+
),
|
|
4769
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4770
|
+
import_lucide_react11.ChevronRight,
|
|
4771
|
+
{
|
|
4772
|
+
"aria-hidden": true,
|
|
4773
|
+
className: cn(
|
|
4774
|
+
"pointer-events-none absolute inset-0 m-auto size-4",
|
|
4775
|
+
"opacity-0 transition-[opacity,transform] duration-200 ease-out",
|
|
4776
|
+
"group-hover:opacity-100"
|
|
4777
|
+
)
|
|
4778
|
+
}
|
|
4779
|
+
)
|
|
4780
|
+
]
|
|
4781
|
+
}
|
|
4782
|
+
) }) });
|
|
4783
|
+
var StudioSidebarHeader = ({
|
|
4784
|
+
isCollapsedRail,
|
|
4785
|
+
isMobile,
|
|
4786
|
+
mobileOpen,
|
|
4787
|
+
onToggle,
|
|
4788
|
+
brand
|
|
4789
|
+
}) => {
|
|
4790
|
+
if (isMobile) {
|
|
4791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("header", { className: cn(sidebarHeaderClass, "justify-between gap-2 pr-2"), children: [
|
|
4792
|
+
brand,
|
|
4793
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4794
|
+
SidebarToggleButton,
|
|
4795
|
+
{
|
|
4796
|
+
ariaLabel: "Close menu",
|
|
4797
|
+
expanded: mobileOpen,
|
|
4798
|
+
onClick: onToggle,
|
|
4799
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react11.X, { className: "size-3.5" })
|
|
4800
|
+
}
|
|
4801
|
+
)
|
|
4802
|
+
] });
|
|
4803
|
+
}
|
|
4804
|
+
if (isCollapsedRail) {
|
|
4805
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4806
|
+
"header",
|
|
4807
|
+
{
|
|
4808
|
+
className: cn(
|
|
4809
|
+
"flex h-12 shrink-0 items-center",
|
|
4810
|
+
studioSidebarCollapsedRailInsetClass
|
|
4811
|
+
),
|
|
4812
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CollapsedBrandToggle, { onExpand: onToggle, brand })
|
|
4813
|
+
}
|
|
4814
|
+
);
|
|
4815
|
+
}
|
|
4816
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("header", { className: cn(sidebarHeaderClass, "justify-between gap-1 pr-2"), children: [
|
|
4817
|
+
brand,
|
|
4818
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4819
|
+
SidebarToggleButton,
|
|
4820
|
+
{
|
|
4821
|
+
ariaLabel: "Collapse sidebar",
|
|
4822
|
+
expanded: true,
|
|
4823
|
+
onClick: onToggle,
|
|
4824
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react11.ChevronLeft, { className: "size-4" })
|
|
4825
|
+
}
|
|
4826
|
+
)
|
|
4827
|
+
] });
|
|
4828
|
+
};
|
|
4829
|
+
|
|
4830
|
+
// src/components/studio/sidebar-workforce.ts
|
|
4831
|
+
function workforceItemId(w) {
|
|
4832
|
+
return w.id ?? w.uid ?? w.name ?? "";
|
|
4833
|
+
}
|
|
4834
|
+
function workforceItemLabel(w) {
|
|
4835
|
+
return w.name ?? workforceItemId(w);
|
|
4836
|
+
}
|
|
4837
|
+
function workforceItemInitial(w) {
|
|
4838
|
+
const label = workforceItemLabel(w);
|
|
4839
|
+
return label.charAt(0).toUpperCase() || "?";
|
|
4840
|
+
}
|
|
4841
|
+
|
|
4842
|
+
// src/components/studio/sidebar-nav.tsx
|
|
4843
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
4844
|
+
var StudioSidebarNav = ({
|
|
4845
|
+
workforces,
|
|
4846
|
+
selectedId,
|
|
4847
|
+
onSelect,
|
|
4848
|
+
iconOnlyLayout,
|
|
4849
|
+
showTooltips
|
|
4850
|
+
}) => {
|
|
4851
|
+
if (workforces.length === 0) return null;
|
|
4852
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4853
|
+
"nav",
|
|
4854
|
+
{
|
|
4855
|
+
className: cn(
|
|
4856
|
+
"flex min-h-0 flex-1 flex-col overflow-y-auto py-1",
|
|
4857
|
+
iconOnlyLayout ? cn(studioSidebarCollapsedRailInsetClass, "gap-1") : "gap-0.5 px-2"
|
|
4858
|
+
),
|
|
4859
|
+
"aria-label": "Agents",
|
|
4860
|
+
children: workforces.map((w) => {
|
|
4861
|
+
const id = workforceItemId(w);
|
|
4862
|
+
const isActive = id === selectedId;
|
|
4863
|
+
const label = workforceItemLabel(w);
|
|
4864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4865
|
+
StudioSidebarEntryMotion,
|
|
4866
|
+
{
|
|
4867
|
+
className: iconOnlyLayout ? studioSidebarCollapsedRailChipRowClass : void 0,
|
|
4868
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(StudioSidebarTooltip, { label, enabled: showTooltips, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4869
|
+
"button",
|
|
4870
|
+
{
|
|
4871
|
+
type: "button",
|
|
4872
|
+
onClick: () => onSelect(id),
|
|
4873
|
+
"aria-pressed": isActive,
|
|
4874
|
+
"aria-label": label,
|
|
4875
|
+
className: cn(
|
|
4876
|
+
studioSidebarNavItemClasses(iconOnlyLayout, isActive),
|
|
4877
|
+
iconOnlyLayout && "inline-flex"
|
|
4878
|
+
),
|
|
4879
|
+
children: iconOnlyLayout ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs font-semibold leading-none", children: workforceItemInitial(w) }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "min-w-0 truncate", children: label })
|
|
4880
|
+
}
|
|
4881
|
+
) })
|
|
4882
|
+
},
|
|
4883
|
+
id
|
|
4884
|
+
);
|
|
4885
|
+
})
|
|
4886
|
+
}
|
|
4887
|
+
);
|
|
4888
|
+
};
|
|
4889
|
+
|
|
4890
|
+
// src/components/studio/timbal-mark.tsx
|
|
4891
|
+
var import_shaders_react = require("@paper-design/shaders-react");
|
|
4892
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
4893
|
+
var DEFAULT_SIZE = 64;
|
|
4894
|
+
var TRANSPARENT_BACK = "#00000000";
|
|
4895
|
+
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=";
|
|
4896
|
+
function TimbalMark({
|
|
4897
|
+
className,
|
|
4898
|
+
size = DEFAULT_SIZE,
|
|
4899
|
+
src = TIMBAL_SYMBOL_DATA_URI
|
|
4900
|
+
}) {
|
|
4901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
4902
|
+
"div",
|
|
4903
|
+
{
|
|
4904
|
+
className: cn("relative shrink-0 bg-transparent", className),
|
|
4905
|
+
style: { width: size, height: size },
|
|
4906
|
+
role: "img",
|
|
4907
|
+
"aria-label": "Timbal",
|
|
4908
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
4909
|
+
import_shaders_react.LiquidMetal,
|
|
4910
|
+
{
|
|
4911
|
+
width: size,
|
|
4912
|
+
height: size,
|
|
4913
|
+
image: src,
|
|
4914
|
+
colorBack: TRANSPARENT_BACK,
|
|
4915
|
+
colorTint: "#ffffff",
|
|
4916
|
+
shape: "none",
|
|
4917
|
+
repetition: 2,
|
|
4918
|
+
softness: 0.1,
|
|
4919
|
+
shiftRed: 0.3,
|
|
4920
|
+
shiftBlue: 0.3,
|
|
4921
|
+
distortion: 0.07,
|
|
4922
|
+
contour: 0.4,
|
|
4923
|
+
angle: 70,
|
|
4924
|
+
speed: 1,
|
|
4925
|
+
scale: 0.6,
|
|
4926
|
+
fit: "contain",
|
|
4927
|
+
className: "size-full bg-transparent",
|
|
4928
|
+
style: { background: "transparent" },
|
|
4929
|
+
webGlContextAttributes: {
|
|
4930
|
+
alpha: true,
|
|
4931
|
+
premultipliedAlpha: false
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
)
|
|
4935
|
+
}
|
|
4936
|
+
);
|
|
4937
|
+
}
|
|
4938
|
+
|
|
4939
|
+
// src/components/studio/sidebar.tsx
|
|
4940
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
4941
|
+
var DEFAULT_BREAKPOINT_PX = 768;
|
|
4942
|
+
function readPersistedCollapsed(key) {
|
|
4943
|
+
if (!key || typeof window === "undefined") return false;
|
|
4944
|
+
try {
|
|
4945
|
+
return window.localStorage.getItem(key) === "1";
|
|
4946
|
+
} catch {
|
|
4947
|
+
return false;
|
|
4948
|
+
}
|
|
4949
|
+
}
|
|
4950
|
+
function writePersistedCollapsed(key, collapsed) {
|
|
4951
|
+
if (!key || typeof window === "undefined") return;
|
|
4952
|
+
try {
|
|
4953
|
+
window.localStorage.setItem(key, collapsed ? "1" : "0");
|
|
4954
|
+
} catch {
|
|
4955
|
+
}
|
|
4956
|
+
}
|
|
4957
|
+
var StudioSidebarPanel = ({
|
|
4958
|
+
workforces,
|
|
4959
|
+
selectedId,
|
|
4960
|
+
onSelect,
|
|
4961
|
+
collapsed,
|
|
4962
|
+
onCollapsedChange,
|
|
4963
|
+
isMobile,
|
|
4964
|
+
mobileOpen,
|
|
4965
|
+
onMobileOpenChange,
|
|
4966
|
+
widthCollapsed,
|
|
4967
|
+
entriesVisible,
|
|
4968
|
+
onEntriesBlurOutComplete,
|
|
4969
|
+
onPanelWidthComplete,
|
|
4970
|
+
brand,
|
|
4971
|
+
emptyCaption = null
|
|
4972
|
+
}) => {
|
|
4973
|
+
const reducedMotion = (0, import_react36.useReducedMotion)();
|
|
4974
|
+
const isCollapsedRail = widthCollapsed && !isMobile;
|
|
4975
|
+
const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
|
|
4976
|
+
const isDrawerOpen = isMobile && mobileOpen;
|
|
4977
|
+
const widthDirection = widthCollapsed ? "collapse" : "expand";
|
|
4978
|
+
const widthTransition = studioSidebarWidthTransition(
|
|
4979
|
+
!!reducedMotion,
|
|
4980
|
+
widthDirection
|
|
4981
|
+
);
|
|
4982
|
+
const handleToggle = () => {
|
|
4983
|
+
if (isMobile) {
|
|
4984
|
+
onMobileOpenChange(false);
|
|
4985
|
+
return;
|
|
4986
|
+
}
|
|
4987
|
+
onCollapsedChange(!collapsed);
|
|
4988
|
+
};
|
|
4989
|
+
const panelWidthPx = isMobile ? SIDEBAR_MOBILE_PX : widthCollapsed ? SIDEBAR_WIDTH_COLLAPSED_PX : SIDEBAR_WIDTH_PX;
|
|
4990
|
+
const brandNode = brand ?? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(TimbalMark, { size: 32 });
|
|
4991
|
+
const panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4992
|
+
import_react36.motion.div,
|
|
4993
|
+
{
|
|
4994
|
+
"data-sidebar-collapsed": isCollapsedRail ? "" : void 0,
|
|
4995
|
+
className: cn(
|
|
4996
|
+
"flex h-full flex-col overflow-hidden",
|
|
4997
|
+
studioSidebarPanelClass,
|
|
4998
|
+
isMobile ? "rounded-none rounded-r-2xl" : "rounded-2xl"
|
|
4999
|
+
),
|
|
5000
|
+
initial: false,
|
|
5001
|
+
animate: { width: panelWidthPx },
|
|
5002
|
+
transition: widthTransition,
|
|
5003
|
+
style: { willChange: entriesVisible ? void 0 : "width" },
|
|
5004
|
+
onAnimationComplete: isMobile || entriesVisible ? void 0 : () => onPanelWidthComplete(),
|
|
5005
|
+
children: [
|
|
5006
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5007
|
+
StudioSidebarHeader,
|
|
5008
|
+
{
|
|
5009
|
+
isCollapsedRail,
|
|
5010
|
+
isMobile,
|
|
5011
|
+
mobileOpen,
|
|
5012
|
+
onToggle: handleToggle,
|
|
5013
|
+
brand: brandNode
|
|
5014
|
+
}
|
|
5015
|
+
),
|
|
5016
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
5017
|
+
StudioSidebarEntries,
|
|
5018
|
+
{
|
|
5019
|
+
visible: entriesVisible,
|
|
5020
|
+
onBlurOutComplete: onEntriesBlurOutComplete,
|
|
5021
|
+
children: [
|
|
5022
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5023
|
+
"div",
|
|
5024
|
+
{
|
|
5025
|
+
id: DOM_IDS.sidebarRuntimeAnchor,
|
|
5026
|
+
className: cn(
|
|
5027
|
+
"min-h-0 shrink-0 empty:hidden",
|
|
5028
|
+
iconOnlyLayout ? "px-1.5 pt-1.5" : "px-2 pt-1.5"
|
|
5029
|
+
)
|
|
5030
|
+
}
|
|
5031
|
+
),
|
|
5032
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5033
|
+
StudioSidebarNav,
|
|
5034
|
+
{
|
|
5035
|
+
workforces,
|
|
5036
|
+
selectedId,
|
|
5037
|
+
onSelect,
|
|
5038
|
+
iconOnlyLayout,
|
|
5039
|
+
showTooltips: isCollapsedRail
|
|
5040
|
+
}
|
|
5041
|
+
),
|
|
5042
|
+
workforces.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "min-h-0 flex-1" }) : null,
|
|
5043
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5044
|
+
StudioSidebarFooter,
|
|
5045
|
+
{
|
|
5046
|
+
iconOnlyLayout,
|
|
5047
|
+
showTooltips: isCollapsedRail,
|
|
5048
|
+
onSignOut: isMobile ? () => onMobileOpenChange(false) : void 0,
|
|
5049
|
+
emptyCaption
|
|
5050
|
+
}
|
|
5051
|
+
)
|
|
5052
|
+
]
|
|
5053
|
+
}
|
|
5054
|
+
)
|
|
5055
|
+
]
|
|
5056
|
+
}
|
|
5057
|
+
);
|
|
5058
|
+
if (isMobile) {
|
|
5059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5060
|
+
import_react36.motion.aside,
|
|
5061
|
+
{
|
|
5062
|
+
className: "fixed inset-y-0 left-0 z-[60] flex",
|
|
5063
|
+
"aria-label": "Studio navigation",
|
|
5064
|
+
"aria-hidden": !mobileOpen,
|
|
5065
|
+
initial: false,
|
|
5066
|
+
animate: {
|
|
5067
|
+
x: isDrawerOpen ? 0 : -(SIDEBAR_MOBILE_PX + 32)
|
|
5068
|
+
},
|
|
5069
|
+
transition: studioSidebarDrawerTransition(!!reducedMotion),
|
|
5070
|
+
style: { pointerEvents: isDrawerOpen ? "auto" : "none" },
|
|
5071
|
+
children: panel
|
|
5072
|
+
}
|
|
5073
|
+
);
|
|
5074
|
+
}
|
|
5075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5076
|
+
"aside",
|
|
5077
|
+
{
|
|
5078
|
+
className: "absolute inset-y-0 left-0 z-[60] flex py-[var(--studio-sidebar-gap)] pl-[var(--studio-sidebar-gap)]",
|
|
5079
|
+
"aria-label": "Studio navigation",
|
|
5080
|
+
children: panel
|
|
5081
|
+
}
|
|
5082
|
+
);
|
|
5083
|
+
};
|
|
5084
|
+
var StudioSidebar = ({
|
|
5085
|
+
workforces: workforcesProp,
|
|
5086
|
+
selectedId: selectedIdProp,
|
|
5087
|
+
onSelect,
|
|
5088
|
+
defaultCollapsed = false,
|
|
5089
|
+
persistKey = STORAGE_KEYS.sidebarCollapsed,
|
|
5090
|
+
mobileBreakpointPx = DEFAULT_BREAKPOINT_PX,
|
|
5091
|
+
brand,
|
|
5092
|
+
emptyCaption,
|
|
5093
|
+
mobileOpen: mobileOpenProp,
|
|
5094
|
+
onMobileOpenChange: onMobileOpenChangeProp
|
|
5095
|
+
}) => {
|
|
5096
|
+
const reducedMotion = (0, import_react36.useReducedMotion)();
|
|
5097
|
+
const fetched = useWorkforces({ enabled: workforcesProp === void 0 });
|
|
5098
|
+
const workforces = workforcesProp ?? fetched.workforces;
|
|
5099
|
+
const [internalSelected, setInternalSelected] = (0, import_react35.useState)(
|
|
5100
|
+
selectedIdProp ?? ""
|
|
5101
|
+
);
|
|
5102
|
+
(0, import_react35.useEffect)(() => {
|
|
5103
|
+
if (selectedIdProp !== void 0) return;
|
|
5104
|
+
if (internalSelected) return;
|
|
5105
|
+
const first = workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name;
|
|
5106
|
+
if (first) setInternalSelected(first);
|
|
5107
|
+
}, [workforces, selectedIdProp, internalSelected]);
|
|
5108
|
+
const selectedId = selectedIdProp ?? internalSelected ?? workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name ?? "";
|
|
5109
|
+
const handleSelect = (0, import_react35.useCallback)(
|
|
5110
|
+
(id) => {
|
|
5111
|
+
if (selectedIdProp === void 0) setInternalSelected(id);
|
|
5112
|
+
onSelect?.(id);
|
|
5113
|
+
},
|
|
5114
|
+
[selectedIdProp, onSelect]
|
|
5115
|
+
);
|
|
5116
|
+
const [collapsed, setCollapsed] = (0, import_react35.useState)(() => {
|
|
5117
|
+
const persisted = readPersistedCollapsed(persistKey);
|
|
5118
|
+
return persisted || defaultCollapsed;
|
|
5119
|
+
});
|
|
5120
|
+
const handleCollapsedChange = (0, import_react35.useCallback)(
|
|
5121
|
+
(next) => {
|
|
5122
|
+
setCollapsed(next);
|
|
5123
|
+
writePersistedCollapsed(persistKey, next);
|
|
5124
|
+
},
|
|
5125
|
+
[persistKey]
|
|
5126
|
+
);
|
|
5127
|
+
const [isMobile, setIsMobile] = (0, import_react35.useState)(() => {
|
|
5128
|
+
if (typeof window === "undefined") return false;
|
|
5129
|
+
return window.innerWidth < mobileBreakpointPx;
|
|
5130
|
+
});
|
|
5131
|
+
(0, import_react35.useEffect)(() => {
|
|
5132
|
+
if (typeof window === "undefined") return;
|
|
5133
|
+
const onResize = () => setIsMobile(window.innerWidth < mobileBreakpointPx);
|
|
5134
|
+
onResize();
|
|
5135
|
+
window.addEventListener("resize", onResize);
|
|
5136
|
+
return () => window.removeEventListener("resize", onResize);
|
|
5137
|
+
}, [mobileBreakpointPx]);
|
|
5138
|
+
const [internalMobileOpen, setInternalMobileOpen] = (0, import_react35.useState)(false);
|
|
5139
|
+
const mobileOpen = mobileOpenProp ?? internalMobileOpen;
|
|
5140
|
+
const setMobileOpen = (0, import_react35.useCallback)(
|
|
5141
|
+
(next) => {
|
|
5142
|
+
if (mobileOpenProp === void 0) setInternalMobileOpen(next);
|
|
5143
|
+
onMobileOpenChangeProp?.(next);
|
|
5144
|
+
},
|
|
5145
|
+
[mobileOpenProp, onMobileOpenChangeProp]
|
|
5146
|
+
);
|
|
5147
|
+
const effectiveCollapsed = isMobile ? false : collapsed;
|
|
5148
|
+
const {
|
|
5149
|
+
widthCollapsed,
|
|
5150
|
+
entriesVisible: phaseEntriesVisible,
|
|
5151
|
+
onEntriesBlurOutComplete,
|
|
5152
|
+
onPanelWidthComplete
|
|
5153
|
+
} = useSidebarCollapsePhase(effectiveCollapsed, !!reducedMotion);
|
|
5154
|
+
const entriesVisible = isMobile || phaseEntriesVisible;
|
|
5155
|
+
const isCollapsedRail = widthCollapsed && !isMobile;
|
|
5156
|
+
const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
|
|
5157
|
+
const contextValue = (0, import_react35.useMemo)(
|
|
5158
|
+
() => ({
|
|
5159
|
+
collapsed: effectiveCollapsed,
|
|
5160
|
+
isMobile,
|
|
5161
|
+
isCollapsedRail,
|
|
5162
|
+
iconOnlyLayout
|
|
5163
|
+
}),
|
|
5164
|
+
[effectiveCollapsed, isMobile, isCollapsedRail, iconOnlyLayout]
|
|
5165
|
+
);
|
|
5166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(StudioSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5167
|
+
StudioSidebarPanel,
|
|
5168
|
+
{
|
|
5169
|
+
workforces,
|
|
5170
|
+
selectedId,
|
|
5171
|
+
onSelect: handleSelect,
|
|
5172
|
+
collapsed: effectiveCollapsed,
|
|
5173
|
+
onCollapsedChange: handleCollapsedChange,
|
|
5174
|
+
isMobile,
|
|
5175
|
+
mobileOpen,
|
|
5176
|
+
onMobileOpenChange: setMobileOpen,
|
|
5177
|
+
widthCollapsed,
|
|
5178
|
+
entriesVisible,
|
|
5179
|
+
onEntriesBlurOutComplete,
|
|
5180
|
+
onPanelWidthComplete,
|
|
5181
|
+
brand,
|
|
5182
|
+
emptyCaption
|
|
5183
|
+
}
|
|
5184
|
+
) });
|
|
5185
|
+
};
|
|
5186
|
+
|
|
5187
|
+
// src/components/studio/sidebar-runtime-portal.tsx
|
|
5188
|
+
var import_react37 = require("react");
|
|
5189
|
+
var import_react_dom = require("react-dom");
|
|
5190
|
+
var import_lucide_react12 = require("lucide-react");
|
|
5191
|
+
var import_react38 = require("@assistant-ui/react");
|
|
5192
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
5193
|
+
var StudioSidebarRuntimePortal = ({
|
|
5194
|
+
label = "New chat"
|
|
5195
|
+
}) => {
|
|
5196
|
+
const { iconOnlyLayout } = useStudioSidebarLayout();
|
|
5197
|
+
const hasMessages = (0, import_react38.useThread)((s) => s.messages.length > 0);
|
|
5198
|
+
const { clear } = useTimbalRuntime();
|
|
5199
|
+
const [anchor, setAnchor] = (0, import_react37.useState)(null);
|
|
5200
|
+
const startNewChat = (0, import_react37.useCallback)(() => {
|
|
5201
|
+
clear();
|
|
5202
|
+
}, [clear]);
|
|
5203
|
+
(0, import_react37.useLayoutEffect)(() => {
|
|
5204
|
+
setAnchor(document.getElementById(DOM_IDS.sidebarRuntimeAnchor));
|
|
5205
|
+
}, []);
|
|
5206
|
+
if (!anchor || !hasMessages) return null;
|
|
5207
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
5208
|
+
"button",
|
|
5209
|
+
{
|
|
5210
|
+
type: "button",
|
|
5211
|
+
onClick: startNewChat,
|
|
5212
|
+
"aria-label": label,
|
|
5213
|
+
className: studioSidebarNavItemClasses(iconOnlyLayout, false),
|
|
5214
|
+
children: [
|
|
5215
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react12.MessageSquarePlus, { className: "size-3.5 shrink-0" }),
|
|
5216
|
+
!iconOnlyLayout ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "min-w-0 truncate", children: label }) : null
|
|
5217
|
+
]
|
|
5218
|
+
}
|
|
5219
|
+
);
|
|
5220
|
+
return (0, import_react_dom.createPortal)(
|
|
5221
|
+
iconOnlyLayout ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(Tooltip, { children: [
|
|
5222
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TooltipTrigger, { asChild: true, children: button }),
|
|
5223
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TooltipContent, { side: "right", className: "text-xs", children: label })
|
|
5224
|
+
] }) : button,
|
|
5225
|
+
anchor
|
|
5226
|
+
);
|
|
5227
|
+
};
|
|
5228
|
+
|
|
5229
|
+
// src/components/studio/welcome.tsx
|
|
5230
|
+
var import_react39 = require("motion/react");
|
|
5231
|
+
var import_react40 = require("@assistant-ui/react");
|
|
5232
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
5233
|
+
var luxuryEase2 = [0.16, 1, 0.3, 1];
|
|
5234
|
+
var welcomeStagger2 = {
|
|
5235
|
+
initial: {},
|
|
5236
|
+
animate: {
|
|
5237
|
+
transition: { staggerChildren: 0.16, delayChildren: 0.18 }
|
|
5238
|
+
}
|
|
5239
|
+
};
|
|
5240
|
+
var welcomeItem2 = {
|
|
5241
|
+
initial: { opacity: 0, y: 14 },
|
|
5242
|
+
animate: {
|
|
5243
|
+
opacity: 1,
|
|
5244
|
+
y: 0,
|
|
5245
|
+
transition: { duration: 0.9, ease: luxuryEase2 }
|
|
5246
|
+
}
|
|
5247
|
+
};
|
|
5248
|
+
var welcomeIcon2 = {
|
|
5249
|
+
initial: { opacity: 0, y: 10, scale: 0.96 },
|
|
5250
|
+
animate: {
|
|
5251
|
+
opacity: 1,
|
|
5252
|
+
y: 0,
|
|
5253
|
+
scale: 1,
|
|
5254
|
+
transition: { duration: 1.1, ease: luxuryEase2 }
|
|
5255
|
+
}
|
|
5256
|
+
};
|
|
5257
|
+
var StudioWelcome = ({ config, icon }) => {
|
|
5258
|
+
const isEmpty = (0, import_react40.useThread)((s) => s.messages.length === 0);
|
|
5259
|
+
if (!isEmpty) return null;
|
|
5260
|
+
const iconNode = icon ?? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5261
|
+
TimbalMark,
|
|
5262
|
+
{
|
|
5263
|
+
size: 112,
|
|
5264
|
+
className: "max-md:scale-[0.58] max-md:origin-center"
|
|
5265
|
+
}
|
|
5266
|
+
);
|
|
5267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5268
|
+
import_react39.motion.div,
|
|
5269
|
+
{
|
|
5270
|
+
className: "aui-thread-welcome-message flex flex-col items-center justify-center px-2 text-center sm:px-4",
|
|
5271
|
+
variants: welcomeStagger2,
|
|
5272
|
+
initial: "initial",
|
|
5273
|
+
animate: "animate",
|
|
5274
|
+
children: [
|
|
5275
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react39.motion.div, { variants: welcomeIcon2, className: "mb-4 md:mb-5", children: iconNode }),
|
|
5276
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5277
|
+
import_react39.motion.h1,
|
|
5278
|
+
{
|
|
5279
|
+
variants: welcomeItem2,
|
|
5280
|
+
className: "aui-thread-welcome-message-inner text-xl font-semibold sm:text-2xl",
|
|
5281
|
+
children: config?.heading ?? "How can I help you today?"
|
|
5282
|
+
}
|
|
5283
|
+
),
|
|
5284
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5285
|
+
import_react39.motion.p,
|
|
5286
|
+
{
|
|
5287
|
+
variants: welcomeItem2,
|
|
5288
|
+
className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
|
|
5289
|
+
children: config?.subheading ?? "Send a message to start a conversation."
|
|
5290
|
+
}
|
|
5291
|
+
)
|
|
5292
|
+
]
|
|
5293
|
+
}
|
|
5294
|
+
) }) });
|
|
5295
|
+
};
|
|
5296
|
+
|
|
5297
|
+
// src/components/studio/studio-shell.tsx
|
|
5298
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
5299
|
+
var import_react43 = require("react");
|
|
5300
|
+
var DEFAULT_BREAKPOINT_PX2 = 768;
|
|
5301
|
+
function readPersistedCollapsed2(key) {
|
|
5302
|
+
if (!key || typeof window === "undefined") return false;
|
|
5303
|
+
try {
|
|
5304
|
+
return window.localStorage.getItem(key) === "1";
|
|
5305
|
+
} catch {
|
|
5306
|
+
return false;
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
function writePersistedCollapsed2(key, collapsed) {
|
|
5310
|
+
if (!key || typeof window === "undefined") return;
|
|
5311
|
+
try {
|
|
5312
|
+
window.localStorage.setItem(key, collapsed ? "1" : "0");
|
|
5313
|
+
} catch {
|
|
5314
|
+
}
|
|
5315
|
+
}
|
|
5316
|
+
function makeComposerWithPortal(BaseComposer) {
|
|
5317
|
+
const Resolved = BaseComposer ?? Composer;
|
|
5318
|
+
return function StudioComposerWithSidebar(props) {
|
|
5319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
5320
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(StudioSidebarRuntimePortal, {}),
|
|
5321
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Resolved, { ...props })
|
|
5322
|
+
] });
|
|
5323
|
+
};
|
|
5324
|
+
}
|
|
5325
|
+
var TimbalStudioShell = ({
|
|
5326
|
+
workforceId,
|
|
5327
|
+
workforces: workforcesProp,
|
|
5328
|
+
workforcesFetch,
|
|
5329
|
+
workforcesBaseUrl,
|
|
5330
|
+
brand,
|
|
5331
|
+
headerActions,
|
|
5332
|
+
headerStart,
|
|
5333
|
+
defaultCollapsed = false,
|
|
5334
|
+
persistKey = STORAGE_KEYS.sidebarCollapsed,
|
|
5335
|
+
mobileBreakpointPx = DEFAULT_BREAKPOINT_PX2,
|
|
5336
|
+
sidebarEmptyCaption = null,
|
|
5337
|
+
welcome,
|
|
5338
|
+
components,
|
|
5339
|
+
...chatProps
|
|
5340
|
+
}) => {
|
|
5341
|
+
const reducedMotion = (0, import_react42.useReducedMotion)();
|
|
5342
|
+
const shouldFetchWorkforces = !workforceId && workforcesProp === void 0;
|
|
5343
|
+
const fetched = useWorkforces({
|
|
5344
|
+
enabled: shouldFetchWorkforces,
|
|
5345
|
+
fetch: workforcesFetch,
|
|
5346
|
+
baseUrl: workforcesBaseUrl
|
|
5347
|
+
});
|
|
5348
|
+
const workforces = workforcesProp ?? fetched.workforces;
|
|
5349
|
+
const [internalSelected, setInternalSelected] = (0, import_react41.useState)(
|
|
5350
|
+
workforceId ?? ""
|
|
5351
|
+
);
|
|
5352
|
+
(0, import_react41.useEffect)(() => {
|
|
5353
|
+
if (workforceId) return;
|
|
5354
|
+
if (internalSelected) return;
|
|
5355
|
+
const first = workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name;
|
|
5356
|
+
if (first) setInternalSelected(first);
|
|
5357
|
+
}, [workforces, workforceId, internalSelected]);
|
|
5358
|
+
const activeWorkforceId = workforceId ?? internalSelected ?? fetched.selectedId ?? "";
|
|
5359
|
+
const [collapsed, setCollapsed] = (0, import_react41.useState)(() => {
|
|
5360
|
+
const persisted = readPersistedCollapsed2(persistKey);
|
|
5361
|
+
return persisted || defaultCollapsed;
|
|
5362
|
+
});
|
|
5363
|
+
const [isMobile, setIsMobile] = (0, import_react41.useState)(() => {
|
|
5364
|
+
if (typeof window === "undefined") return false;
|
|
5365
|
+
return window.innerWidth < mobileBreakpointPx;
|
|
5366
|
+
});
|
|
5367
|
+
const [mobileSidebarOpen, setMobileSidebarOpen] = (0, import_react41.useState)(false);
|
|
5368
|
+
(0, import_react41.useEffect)(() => {
|
|
5369
|
+
if (typeof window === "undefined") return;
|
|
5370
|
+
const onResize = () => setIsMobile(window.innerWidth < mobileBreakpointPx);
|
|
5371
|
+
onResize();
|
|
5372
|
+
window.addEventListener("resize", onResize);
|
|
5373
|
+
return () => window.removeEventListener("resize", onResize);
|
|
5374
|
+
}, [mobileBreakpointPx]);
|
|
5375
|
+
(0, import_react41.useEffect)(() => {
|
|
5376
|
+
if (!isMobile) setMobileSidebarOpen(false);
|
|
5377
|
+
}, [isMobile]);
|
|
5378
|
+
(0, import_react41.useEffect)(() => {
|
|
5379
|
+
if (!mobileSidebarOpen) return;
|
|
5380
|
+
const onKeyDown = (e) => {
|
|
5381
|
+
if (e.key === "Escape") setMobileSidebarOpen(false);
|
|
5382
|
+
};
|
|
5383
|
+
window.addEventListener("keydown", onKeyDown);
|
|
5384
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
5385
|
+
}, [mobileSidebarOpen]);
|
|
5386
|
+
const effectiveCollapsed = isMobile ? false : collapsed;
|
|
5387
|
+
const {
|
|
5388
|
+
widthCollapsed,
|
|
5389
|
+
entriesVisible: phaseEntriesVisible,
|
|
5390
|
+
onEntriesBlurOutComplete,
|
|
5391
|
+
onPanelWidthComplete
|
|
5392
|
+
} = useSidebarCollapsePhase(effectiveCollapsed, !!reducedMotion);
|
|
5393
|
+
const entriesVisible = isMobile || phaseEntriesVisible;
|
|
5394
|
+
const isCollapsedRail = widthCollapsed && !isMobile;
|
|
5395
|
+
const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
|
|
5396
|
+
const layoutDirection = widthCollapsed ? "collapse" : "expand";
|
|
5397
|
+
const layoutTransition = studioSidebarWidthTransition(
|
|
5398
|
+
!!reducedMotion,
|
|
5399
|
+
layoutDirection
|
|
5400
|
+
);
|
|
5401
|
+
const desktopInsetPx = widthCollapsed ? SIDEBAR_INSET_PX_COLLAPSED : SIDEBAR_INSET_PX_EXPANDED;
|
|
5402
|
+
const onCollapsedChange = (0, import_react41.useCallback)(
|
|
5403
|
+
(next) => {
|
|
5404
|
+
setCollapsed(next);
|
|
5405
|
+
writePersistedCollapsed2(persistKey, next);
|
|
5406
|
+
},
|
|
5407
|
+
[persistKey]
|
|
5408
|
+
);
|
|
5409
|
+
const handleSelectWorkforce = (0, import_react41.useCallback)(
|
|
5410
|
+
(id) => {
|
|
5411
|
+
if (!workforceId) setInternalSelected(id);
|
|
5412
|
+
if (isMobile) setMobileSidebarOpen(false);
|
|
5413
|
+
},
|
|
5414
|
+
[workforceId, isMobile]
|
|
5415
|
+
);
|
|
5416
|
+
const sidebarContext = (0, import_react41.useMemo)(
|
|
5417
|
+
() => ({
|
|
5418
|
+
collapsed: effectiveCollapsed,
|
|
5419
|
+
isMobile,
|
|
5420
|
+
isCollapsedRail,
|
|
5421
|
+
iconOnlyLayout
|
|
5422
|
+
}),
|
|
5423
|
+
[effectiveCollapsed, isMobile, isCollapsedRail, iconOnlyLayout]
|
|
5424
|
+
);
|
|
5425
|
+
const resolvedComponents = (0, import_react41.useMemo)(() => {
|
|
5426
|
+
const next = { Welcome: StudioWelcome, ...components };
|
|
5427
|
+
next.Composer = makeComposerWithPortal(components?.Composer);
|
|
5428
|
+
return next;
|
|
5429
|
+
}, [components]);
|
|
5430
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(StudioSidebarContext.Provider, { value: sidebarContext, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
5431
|
+
"div",
|
|
5432
|
+
{
|
|
5433
|
+
className: cn(
|
|
5434
|
+
"relative h-dvh overflow-hidden bg-background",
|
|
5435
|
+
isMobile && mobileSidebarOpen && "max-md:overflow-hidden"
|
|
5436
|
+
),
|
|
5437
|
+
style: studioChromeShellStyle,
|
|
5438
|
+
children: [
|
|
5439
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5440
|
+
"div",
|
|
5441
|
+
{
|
|
5442
|
+
className: "pointer-events-none absolute inset-0 z-0 bg-background",
|
|
5443
|
+
"aria-hidden": true
|
|
5444
|
+
}
|
|
5445
|
+
),
|
|
5446
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5447
|
+
"div",
|
|
5448
|
+
{
|
|
5449
|
+
className: cn(
|
|
5450
|
+
"pointer-events-none absolute inset-0 z-0",
|
|
5451
|
+
studioPlaygroundGradientClass
|
|
5452
|
+
),
|
|
5453
|
+
"aria-hidden": true
|
|
5454
|
+
}
|
|
5455
|
+
),
|
|
5456
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5457
|
+
StudioSidebarBackdrop,
|
|
5458
|
+
{
|
|
5459
|
+
open: isMobile && mobileSidebarOpen,
|
|
5460
|
+
onClose: () => setMobileSidebarOpen(false)
|
|
5461
|
+
}
|
|
5462
|
+
),
|
|
5463
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5464
|
+
StudioSidebarPanel,
|
|
5465
|
+
{
|
|
5466
|
+
workforces,
|
|
5467
|
+
selectedId: activeWorkforceId,
|
|
5468
|
+
onSelect: handleSelectWorkforce,
|
|
5469
|
+
collapsed: effectiveCollapsed,
|
|
5470
|
+
onCollapsedChange,
|
|
5471
|
+
isMobile,
|
|
5472
|
+
mobileOpen: mobileSidebarOpen,
|
|
5473
|
+
onMobileOpenChange: setMobileSidebarOpen,
|
|
5474
|
+
widthCollapsed,
|
|
5475
|
+
entriesVisible,
|
|
5476
|
+
onEntriesBlurOutComplete,
|
|
5477
|
+
onPanelWidthComplete,
|
|
5478
|
+
brand,
|
|
5479
|
+
emptyCaption: sidebarEmptyCaption
|
|
5480
|
+
}
|
|
5481
|
+
),
|
|
5482
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
5483
|
+
import_react42.motion.header,
|
|
5484
|
+
{
|
|
5485
|
+
className: cn(
|
|
5486
|
+
"absolute top-0 right-0 z-40 flex items-start justify-between gap-2",
|
|
5487
|
+
"px-3 pt-[var(--studio-topbar-gap)] md:px-4",
|
|
5488
|
+
"left-0"
|
|
5489
|
+
),
|
|
5490
|
+
initial: false,
|
|
5491
|
+
animate: { left: isMobile ? 0 : desktopInsetPx },
|
|
5492
|
+
transition: layoutTransition,
|
|
5493
|
+
children: [
|
|
5494
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
5495
|
+
"div",
|
|
5496
|
+
{
|
|
5497
|
+
className: cn(
|
|
5498
|
+
"flex min-w-0 flex-1 items-center gap-2",
|
|
5499
|
+
studioTopbarPillHeightClass
|
|
5500
|
+
),
|
|
5501
|
+
children: [
|
|
5502
|
+
isMobile && !mobileSidebarOpen ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5503
|
+
TimbalV2Button,
|
|
5504
|
+
{
|
|
5505
|
+
variant: "secondary",
|
|
5506
|
+
size: "sm",
|
|
5507
|
+
isIconOnly: true,
|
|
5508
|
+
className: studioTopbarIconPillClass,
|
|
5509
|
+
onClick: () => setMobileSidebarOpen(true),
|
|
5510
|
+
"aria-label": "Open menu",
|
|
5511
|
+
"aria-expanded": false,
|
|
5512
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react13.Menu, { className: "size-4" })
|
|
5513
|
+
}
|
|
5514
|
+
) : null,
|
|
5515
|
+
headerStart
|
|
5516
|
+
]
|
|
5517
|
+
}
|
|
5518
|
+
),
|
|
5519
|
+
headerActions ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex shrink-0 items-center gap-1", children: headerActions }) : null
|
|
5520
|
+
]
|
|
5521
|
+
}
|
|
5522
|
+
),
|
|
5523
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5524
|
+
import_react42.motion.main,
|
|
5525
|
+
{
|
|
5526
|
+
className: cn(
|
|
5527
|
+
"relative z-10 flex h-full min-w-0 flex-col",
|
|
5528
|
+
"pt-[var(--studio-inset-top)]",
|
|
5529
|
+
"px-3 md:px-0"
|
|
5530
|
+
),
|
|
5531
|
+
initial: false,
|
|
5532
|
+
animate: { paddingLeft: isMobile ? 12 : desktopInsetPx },
|
|
5533
|
+
transition: layoutTransition,
|
|
5534
|
+
children: activeWorkforceId ? /* @__PURE__ */ (0, import_react43.createElement)(
|
|
5535
|
+
TimbalChat,
|
|
5536
|
+
{
|
|
5537
|
+
...chatProps,
|
|
5538
|
+
workforceId: activeWorkforceId,
|
|
5539
|
+
key: activeWorkforceId,
|
|
5540
|
+
welcome,
|
|
5541
|
+
components: resolvedComponents,
|
|
5542
|
+
className: cn("min-h-0 flex-1 bg-transparent", chatProps.className)
|
|
5543
|
+
}
|
|
5544
|
+
) : null
|
|
5545
|
+
}
|
|
5546
|
+
)
|
|
5547
|
+
]
|
|
5548
|
+
}
|
|
5549
|
+
) });
|
|
5550
|
+
};
|
|
5551
|
+
|
|
5552
|
+
// src/components/studio/mode-toggle.tsx
|
|
5553
|
+
var import_react44 = require("react");
|
|
5554
|
+
var import_lucide_react14 = require("lucide-react");
|
|
5555
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
5556
|
+
var ModeToggle = ({
|
|
5557
|
+
theme,
|
|
5558
|
+
setTheme,
|
|
5559
|
+
className,
|
|
5560
|
+
label = "Toggle theme"
|
|
5561
|
+
}) => {
|
|
5562
|
+
const isControlled = theme !== void 0;
|
|
5563
|
+
const [internalIsDark, setInternalIsDark] = (0, import_react44.useState)(false);
|
|
5564
|
+
(0, import_react44.useEffect)(() => {
|
|
5565
|
+
if (isControlled) return;
|
|
5566
|
+
if (typeof document === "undefined") return;
|
|
5567
|
+
setInternalIsDark(document.documentElement.classList.contains("dark"));
|
|
5568
|
+
}, [isControlled]);
|
|
5569
|
+
const isDark = isControlled ? theme === "dark" : internalIsDark;
|
|
5570
|
+
const onClick = (0, import_react44.useCallback)(() => {
|
|
5571
|
+
const next = isDark ? "light" : "dark";
|
|
5572
|
+
if (setTheme) {
|
|
5573
|
+
setTheme(next);
|
|
5574
|
+
return;
|
|
5575
|
+
}
|
|
5576
|
+
if (typeof document === "undefined") return;
|
|
5577
|
+
document.documentElement.classList.toggle("dark", next === "dark");
|
|
5578
|
+
setInternalIsDark(next === "dark");
|
|
5579
|
+
}, [isDark, setTheme]);
|
|
5580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
5581
|
+
TimbalV2Button,
|
|
5582
|
+
{
|
|
5583
|
+
variant: "secondary",
|
|
5584
|
+
size: "sm",
|
|
5585
|
+
isIconOnly: true,
|
|
5586
|
+
onClick,
|
|
5587
|
+
className: cn(
|
|
5588
|
+
studioTopbarPillHeightClass,
|
|
5589
|
+
studioTopbarIconPillClass,
|
|
5590
|
+
"relative",
|
|
5591
|
+
className
|
|
5592
|
+
),
|
|
5593
|
+
"aria-label": label,
|
|
5594
|
+
title: label,
|
|
5595
|
+
children: [
|
|
5596
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react14.Sun, { className: "size-3.5 scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" }),
|
|
5597
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react14.Moon, { className: "absolute size-3.5 scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" }),
|
|
5598
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "sr-only", children: label })
|
|
5599
|
+
]
|
|
5600
|
+
}
|
|
5601
|
+
);
|
|
5602
|
+
};
|
|
5603
|
+
|
|
5604
|
+
// src/artifacts/agent-instructions.ts
|
|
5605
|
+
var ARTIFACT_AGENT_INSTRUCTIONS = `
|
|
5606
|
+
## Rich artifacts (Timbal chat UI)
|
|
5607
|
+
|
|
5608
|
+
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.
|
|
5609
|
+
|
|
5610
|
+
### Delivery channels (either works)
|
|
5611
|
+
|
|
5612
|
+
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.
|
|
5613
|
+
2. **Inline markdown fence** \u2014 embed the same JSON inside a fenced block:
|
|
5614
|
+
|
|
5615
|
+
\`\`\`timbal-artifact
|
|
3435
5616
|
{"type":"chart","data":[{"month":"Jan","sales":120}]}
|
|
3436
5617
|
\`\`\`
|
|
3437
5618
|
|
|
@@ -3546,288 +5727,9 @@ When you call a tool that returns an artifact (\`make_chart\`, \`ask_question\`,
|
|
|
3546
5727
|
4. Treat the widget as visible to the user; refer to it as "above" / "the chart" / "the choices" \u2014 never reproduce its contents.
|
|
3547
5728
|
`.trim();
|
|
3548
5729
|
|
|
3549
|
-
// src/index.ts
|
|
3550
|
-
var import_react26 = require("@assistant-ui/react");
|
|
3551
|
-
|
|
3552
|
-
// src/hooks/use-workforces.ts
|
|
3553
|
-
var import_react24 = require("react");
|
|
3554
|
-
function useWorkforces(options = {}) {
|
|
3555
|
-
const { baseUrl = "/api", fetch: fetchFn, pickInitial } = options;
|
|
3556
|
-
const [workforces, setWorkforces] = (0, import_react24.useState)([]);
|
|
3557
|
-
const [selectedId, setSelectedId] = (0, import_react24.useState)("");
|
|
3558
|
-
const [isLoading, setIsLoading] = (0, import_react24.useState)(true);
|
|
3559
|
-
const [error, setError] = (0, import_react24.useState)(null);
|
|
3560
|
-
const fetchFnRef = (0, import_react24.useRef)(fetchFn ?? authFetch);
|
|
3561
|
-
(0, import_react24.useEffect)(() => {
|
|
3562
|
-
fetchFnRef.current = fetchFn ?? authFetch;
|
|
3563
|
-
}, [fetchFn]);
|
|
3564
|
-
const pickInitialRef = (0, import_react24.useRef)(pickInitial);
|
|
3565
|
-
(0, import_react24.useEffect)(() => {
|
|
3566
|
-
pickInitialRef.current = pickInitial;
|
|
3567
|
-
}, [pickInitial]);
|
|
3568
|
-
const load = (0, import_react24.useMemo)(() => {
|
|
3569
|
-
return async () => {
|
|
3570
|
-
setIsLoading(true);
|
|
3571
|
-
setError(null);
|
|
3572
|
-
try {
|
|
3573
|
-
const res = await fetchFnRef.current(`${baseUrl}/workforce`);
|
|
3574
|
-
if (!res.ok) throw new Error(`Failed to load workforces (${res.status})`);
|
|
3575
|
-
const data = await res.json();
|
|
3576
|
-
setWorkforces(data);
|
|
3577
|
-
setSelectedId((current) => {
|
|
3578
|
-
if (current && data.some((w) => idOf(w) === current)) return current;
|
|
3579
|
-
const initial = pickInitialRef.current?.(data) ?? data.find((w) => w.type === "agent") ?? data[0];
|
|
3580
|
-
return initial ? idOf(initial) : "";
|
|
3581
|
-
});
|
|
3582
|
-
} catch (err) {
|
|
3583
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
3584
|
-
} finally {
|
|
3585
|
-
setIsLoading(false);
|
|
3586
|
-
}
|
|
3587
|
-
};
|
|
3588
|
-
}, [baseUrl]);
|
|
3589
|
-
(0, import_react24.useEffect)(() => {
|
|
3590
|
-
load();
|
|
3591
|
-
}, [load]);
|
|
3592
|
-
const selected = (0, import_react24.useMemo)(
|
|
3593
|
-
() => workforces.find((w) => idOf(w) === selectedId),
|
|
3594
|
-
[workforces, selectedId]
|
|
3595
|
-
);
|
|
3596
|
-
return {
|
|
3597
|
-
workforces,
|
|
3598
|
-
selectedId,
|
|
3599
|
-
setSelectedId,
|
|
3600
|
-
selected,
|
|
3601
|
-
isLoading,
|
|
3602
|
-
error,
|
|
3603
|
-
refresh: load
|
|
3604
|
-
};
|
|
3605
|
-
}
|
|
3606
|
-
function idOf(item) {
|
|
3607
|
-
return item.id ?? item.uid ?? item.name ?? "";
|
|
3608
|
-
}
|
|
3609
|
-
|
|
3610
|
-
// src/components/workforce-selector.tsx
|
|
3611
|
-
var import_lucide_react8 = require("lucide-react");
|
|
3612
|
-
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3613
|
-
var WorkforceSelector = ({
|
|
3614
|
-
workforces,
|
|
3615
|
-
value,
|
|
3616
|
-
onChange,
|
|
3617
|
-
hideWhenSingle = true,
|
|
3618
|
-
className,
|
|
3619
|
-
placeholder = "Select agent"
|
|
3620
|
-
}) => {
|
|
3621
|
-
if (workforces.length === 0) return null;
|
|
3622
|
-
if (hideWhenSingle && workforces.length === 1) return null;
|
|
3623
|
-
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("aui-workforce-selector relative inline-flex items-center", className), children: [
|
|
3624
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3625
|
-
"select",
|
|
3626
|
-
{
|
|
3627
|
-
className: "aui-workforce-selector-input h-7 cursor-pointer appearance-none rounded-md border-none bg-transparent pr-5 pl-1.5 text-xs font-medium text-muted-foreground shadow-none outline-none ring-0 transition-colors hover:text-foreground focus:ring-0",
|
|
3628
|
-
value,
|
|
3629
|
-
onChange: (e) => onChange(e.target.value),
|
|
3630
|
-
"aria-label": placeholder,
|
|
3631
|
-
children: [
|
|
3632
|
-
!value && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "", children: placeholder }),
|
|
3633
|
-
workforces.map((w) => {
|
|
3634
|
-
const id = idOf2(w);
|
|
3635
|
-
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: id, children: w.name ?? id }, id);
|
|
3636
|
-
})
|
|
3637
|
-
]
|
|
3638
|
-
}
|
|
3639
|
-
),
|
|
3640
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.ChevronDownIcon, { className: "aui-workforce-selector-icon pointer-events-none absolute right-1 size-3 text-muted-foreground" })
|
|
3641
|
-
] });
|
|
3642
|
-
};
|
|
3643
|
-
function idOf2(item) {
|
|
3644
|
-
return item.id ?? item.uid ?? item.name ?? "";
|
|
3645
|
-
}
|
|
3646
|
-
|
|
3647
|
-
// src/components/chat-shell.tsx
|
|
3648
|
-
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3649
|
-
var TimbalChatShell = ({
|
|
3650
|
-
workforceId,
|
|
3651
|
-
brand,
|
|
3652
|
-
headerActions,
|
|
3653
|
-
hideWorkforceSelector,
|
|
3654
|
-
className,
|
|
3655
|
-
headerClassName,
|
|
3656
|
-
baseUrl,
|
|
3657
|
-
fetch: fetch2,
|
|
3658
|
-
...chatProps
|
|
3659
|
-
}) => {
|
|
3660
|
-
const {
|
|
3661
|
-
workforces,
|
|
3662
|
-
selectedId,
|
|
3663
|
-
setSelectedId
|
|
3664
|
-
} = useWorkforces({ baseUrl, fetch: fetch2 });
|
|
3665
|
-
const effectiveId = workforceId ?? selectedId;
|
|
3666
|
-
const showSelector = !hideWorkforceSelector && !workforceId && workforces.length > 0;
|
|
3667
|
-
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
3668
|
-
"div",
|
|
3669
|
-
{
|
|
3670
|
-
className: cn(
|
|
3671
|
-
"aui-chat-shell flex h-screen flex-col overflow-hidden",
|
|
3672
|
-
className
|
|
3673
|
-
),
|
|
3674
|
-
children: [
|
|
3675
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
3676
|
-
"header",
|
|
3677
|
-
{
|
|
3678
|
-
className: cn(
|
|
3679
|
-
"aui-chat-shell-header flex shrink-0 items-center justify-between border-b border-border/50 bg-background/90 px-5 py-2 backdrop-blur-md",
|
|
3680
|
-
headerClassName
|
|
3681
|
-
),
|
|
3682
|
-
children: [
|
|
3683
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center", children: [
|
|
3684
|
-
brand,
|
|
3685
|
-
showSelector && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
3686
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mx-3.5 h-3.5 w-px bg-border" }),
|
|
3687
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3688
|
-
WorkforceSelector,
|
|
3689
|
-
{
|
|
3690
|
-
workforces,
|
|
3691
|
-
value: selectedId,
|
|
3692
|
-
onChange: setSelectedId
|
|
3693
|
-
}
|
|
3694
|
-
)
|
|
3695
|
-
] })
|
|
3696
|
-
] }),
|
|
3697
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex items-center gap-0.5", children: headerActions })
|
|
3698
|
-
]
|
|
3699
|
-
}
|
|
3700
|
-
),
|
|
3701
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3702
|
-
TimbalChat,
|
|
3703
|
-
{
|
|
3704
|
-
workforceId: effectiveId,
|
|
3705
|
-
baseUrl,
|
|
3706
|
-
fetch: fetch2,
|
|
3707
|
-
className: "min-h-0 flex-1",
|
|
3708
|
-
...chatProps
|
|
3709
|
-
},
|
|
3710
|
-
effectiveId
|
|
3711
|
-
)
|
|
3712
|
-
]
|
|
3713
|
-
}
|
|
3714
|
-
);
|
|
3715
|
-
};
|
|
3716
|
-
|
|
3717
|
-
// src/auth/provider.tsx
|
|
3718
|
-
var import_react25 = require("react");
|
|
3719
|
-
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
3720
|
-
function isInsideIframe() {
|
|
3721
|
-
try {
|
|
3722
|
-
return typeof window !== "undefined" && window.self !== window.top;
|
|
3723
|
-
} catch {
|
|
3724
|
-
return true;
|
|
3725
|
-
}
|
|
3726
|
-
}
|
|
3727
|
-
var SessionContext = (0, import_react25.createContext)(void 0);
|
|
3728
|
-
var useSession = () => {
|
|
3729
|
-
const context = (0, import_react25.useContext)(SessionContext);
|
|
3730
|
-
if (context === void 0) {
|
|
3731
|
-
throw new Error("useSession must be used within a SessionProvider");
|
|
3732
|
-
}
|
|
3733
|
-
return context;
|
|
3734
|
-
};
|
|
3735
|
-
var SessionProvider = ({
|
|
3736
|
-
children,
|
|
3737
|
-
enabled = true
|
|
3738
|
-
}) => {
|
|
3739
|
-
const [user, setUser] = (0, import_react25.useState)(null);
|
|
3740
|
-
const [loading, setLoading] = (0, import_react25.useState)(enabled);
|
|
3741
|
-
const [embedded] = (0, import_react25.useState)(isInsideIframe);
|
|
3742
|
-
(0, import_react25.useEffect)(() => {
|
|
3743
|
-
if (!enabled) {
|
|
3744
|
-
setLoading(false);
|
|
3745
|
-
return;
|
|
3746
|
-
}
|
|
3747
|
-
let ignore = false;
|
|
3748
|
-
const restoreSession = async () => {
|
|
3749
|
-
try {
|
|
3750
|
-
const u = await fetchCurrentUser();
|
|
3751
|
-
if (ignore) return;
|
|
3752
|
-
if (u) {
|
|
3753
|
-
setUser(u);
|
|
3754
|
-
setLoading(false);
|
|
3755
|
-
return;
|
|
3756
|
-
}
|
|
3757
|
-
if (getRefreshToken()) {
|
|
3758
|
-
const ok = await refreshAccessToken();
|
|
3759
|
-
if (ignore) return;
|
|
3760
|
-
if (ok) {
|
|
3761
|
-
const refreshedUser = await fetchCurrentUser();
|
|
3762
|
-
if (ignore) return;
|
|
3763
|
-
if (refreshedUser) {
|
|
3764
|
-
setUser(refreshedUser);
|
|
3765
|
-
setLoading(false);
|
|
3766
|
-
return;
|
|
3767
|
-
}
|
|
3768
|
-
}
|
|
3769
|
-
}
|
|
3770
|
-
} catch {
|
|
3771
|
-
if (ignore) return;
|
|
3772
|
-
clearTokens();
|
|
3773
|
-
}
|
|
3774
|
-
if (!ignore && !embedded) {
|
|
3775
|
-
setLoading(false);
|
|
3776
|
-
}
|
|
3777
|
-
};
|
|
3778
|
-
restoreSession();
|
|
3779
|
-
let messageCleanup;
|
|
3780
|
-
if (embedded) {
|
|
3781
|
-
const handleMessage = async (event) => {
|
|
3782
|
-
if (ignore) return;
|
|
3783
|
-
if (event.data?.type !== "timbal:auth" || !event.data.token) return;
|
|
3784
|
-
setAccessToken(event.data.token);
|
|
3785
|
-
if (event.data.refreshToken) {
|
|
3786
|
-
setRefreshToken(event.data.refreshToken);
|
|
3787
|
-
}
|
|
3788
|
-
const u = await fetchCurrentUser();
|
|
3789
|
-
if (!ignore) {
|
|
3790
|
-
setUser(u);
|
|
3791
|
-
setLoading(false);
|
|
3792
|
-
}
|
|
3793
|
-
};
|
|
3794
|
-
window.addEventListener("message", handleMessage);
|
|
3795
|
-
window.parent.postMessage({ type: "timbal:request-session" }, "*");
|
|
3796
|
-
messageCleanup = () => window.removeEventListener("message", handleMessage);
|
|
3797
|
-
}
|
|
3798
|
-
return () => {
|
|
3799
|
-
ignore = true;
|
|
3800
|
-
messageCleanup?.();
|
|
3801
|
-
};
|
|
3802
|
-
}, [enabled, embedded]);
|
|
3803
|
-
const logout = (0, import_react25.useCallback)(() => {
|
|
3804
|
-
clearTokens();
|
|
3805
|
-
setUser(null);
|
|
3806
|
-
const returnTo = encodeURIComponent(
|
|
3807
|
-
window.location.pathname + window.location.search
|
|
3808
|
-
);
|
|
3809
|
-
fetch("/api/auth/logout", { method: "POST" }).finally(
|
|
3810
|
-
() => window.location.href = `/api/auth/login?return_to=${returnTo}`
|
|
3811
|
-
);
|
|
3812
|
-
}, []);
|
|
3813
|
-
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
3814
|
-
SessionContext.Provider,
|
|
3815
|
-
{
|
|
3816
|
-
value: {
|
|
3817
|
-
user,
|
|
3818
|
-
loading,
|
|
3819
|
-
isAuthenticated: !!user,
|
|
3820
|
-
isEmbedded: embedded,
|
|
3821
|
-
logout
|
|
3822
|
-
},
|
|
3823
|
-
children
|
|
3824
|
-
}
|
|
3825
|
-
);
|
|
3826
|
-
};
|
|
3827
|
-
|
|
3828
5730
|
// src/auth/guard.tsx
|
|
3829
|
-
var
|
|
3830
|
-
var
|
|
5731
|
+
var import_lucide_react15 = require("lucide-react");
|
|
5732
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3831
5733
|
var AuthGuard = ({
|
|
3832
5734
|
children,
|
|
3833
5735
|
requireAuth = false,
|
|
@@ -3838,7 +5740,7 @@ var AuthGuard = ({
|
|
|
3838
5740
|
return children;
|
|
3839
5741
|
}
|
|
3840
5742
|
if (loading) {
|
|
3841
|
-
return /* @__PURE__ */ (0,
|
|
5743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react15.Loader2, { className: "w-8 h-8 animate-spin" }) });
|
|
3842
5744
|
}
|
|
3843
5745
|
if (requireAuth && !isAuthenticated && !isEmbedded) {
|
|
3844
5746
|
const returnTo = encodeURIComponent(
|
|
@@ -3849,6 +5751,9 @@ var AuthGuard = ({
|
|
|
3849
5751
|
}
|
|
3850
5752
|
return children;
|
|
3851
5753
|
};
|
|
5754
|
+
|
|
5755
|
+
// src/index.ts
|
|
5756
|
+
var import_react45 = require("@assistant-ui/react");
|
|
3852
5757
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3853
5758
|
0 && (module.exports = {
|
|
3854
5759
|
ARTIFACT_AGENT_INSTRUCTIONS,
|
|
@@ -3858,6 +5763,7 @@ var AuthGuard = ({
|
|
|
3858
5763
|
ArtifactRegistryProvider,
|
|
3859
5764
|
ArtifactView,
|
|
3860
5765
|
AssistantRuntimeProvider,
|
|
5766
|
+
AuiIf,
|
|
3861
5767
|
AuthGuard,
|
|
3862
5768
|
Avatar,
|
|
3863
5769
|
AvatarFallback,
|
|
@@ -3865,8 +5771,6 @@ var AuthGuard = ({
|
|
|
3865
5771
|
Button,
|
|
3866
5772
|
ChartArtifactView,
|
|
3867
5773
|
Composer,
|
|
3868
|
-
ComposerAddAttachment,
|
|
3869
|
-
ComposerAttachments,
|
|
3870
5774
|
ComposerPrimitive,
|
|
3871
5775
|
DEFAULT_UPLOAD_ACCEPT,
|
|
3872
5776
|
Dialog,
|
|
@@ -3880,17 +5784,21 @@ var AuthGuard = ({
|
|
|
3880
5784
|
JsonArtifactView,
|
|
3881
5785
|
MarkdownText,
|
|
3882
5786
|
MessagePrimitive,
|
|
5787
|
+
ModeToggle,
|
|
3883
5788
|
QuestionArtifactView,
|
|
3884
5789
|
SessionProvider,
|
|
3885
5790
|
Shimmer,
|
|
5791
|
+
StudioSidebar,
|
|
5792
|
+
StudioWelcome,
|
|
3886
5793
|
Suggestions,
|
|
3887
|
-
SyntaxHighlighter,
|
|
3888
5794
|
TableArtifactView,
|
|
3889
5795
|
Thread,
|
|
3890
5796
|
ThreadPrimitive,
|
|
3891
5797
|
TimbalChat,
|
|
3892
5798
|
TimbalChatShell,
|
|
5799
|
+
TimbalMark,
|
|
3893
5800
|
TimbalRuntimeProvider,
|
|
5801
|
+
TimbalStudioShell,
|
|
3894
5802
|
ToolArtifactFallback,
|
|
3895
5803
|
ToolFallback,
|
|
3896
5804
|
Tooltip,
|
|
@@ -3902,10 +5810,8 @@ var AuthGuard = ({
|
|
|
3902
5810
|
UiCustomNodeRegistryProvider,
|
|
3903
5811
|
UiEventProvider,
|
|
3904
5812
|
UiNodeView,
|
|
3905
|
-
UserMessageAttachments,
|
|
3906
5813
|
WorkforceSelector,
|
|
3907
5814
|
authFetch,
|
|
3908
|
-
buttonVariants,
|
|
3909
5815
|
clearTokens,
|
|
3910
5816
|
cn,
|
|
3911
5817
|
createDefaultAttachmentAdapter,
|
|
@@ -3931,12 +5837,14 @@ var AuthGuard = ({
|
|
|
3931
5837
|
useArtifactRegistry,
|
|
3932
5838
|
useComposerRuntime,
|
|
3933
5839
|
useMessageRuntime,
|
|
5840
|
+
useOptionalSession,
|
|
3934
5841
|
useResolvedSuggestions,
|
|
3935
5842
|
useSession,
|
|
3936
5843
|
useThread,
|
|
3937
5844
|
useThreadRuntime,
|
|
3938
5845
|
useTimbalRuntime,
|
|
3939
5846
|
useTimbalStream,
|
|
5847
|
+
useToolRunning,
|
|
3940
5848
|
useUiCustomNodeRegistry,
|
|
3941
5849
|
useUiDispatch,
|
|
3942
5850
|
useUiEventEmitter,
|