@timbal-ai/timbal-react 0.5.4 → 0.6.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.
Files changed (44) hide show
  1. package/README.md +128 -4
  2. package/dist/app.cjs +5311 -0
  3. package/dist/app.d.cts +29 -0
  4. package/dist/app.d.ts +29 -0
  5. package/dist/app.esm.js +81 -0
  6. package/dist/chart-artifact-C71dk4xI.d.ts +329 -0
  7. package/dist/chart-artifact-CPEpOmtV.d.cts +329 -0
  8. package/dist/chat-CWtQWDtJ.d.cts +650 -0
  9. package/dist/chat-CWtQWDtJ.d.ts +650 -0
  10. package/dist/chat.cjs +4162 -0
  11. package/dist/chat.d.cts +13 -0
  12. package/dist/chat.d.ts +13 -0
  13. package/dist/chat.esm.js +51 -0
  14. package/dist/chunk-4TCJQSIX.esm.js +565 -0
  15. package/dist/chunk-IYENDIRY.esm.js +119 -0
  16. package/dist/chunk-KC5QLVUG.esm.js +22 -0
  17. package/dist/chunk-M4V6Q6XO.esm.js +1082 -0
  18. package/dist/chunk-OFHLFNJH.esm.js +138 -0
  19. package/dist/chunk-OVHR7J3J.esm.js +1574 -0
  20. package/dist/chunk-WLTW56MC.esm.js +66 -0
  21. package/dist/chunk-YJQLLFKP.esm.js +3672 -0
  22. package/dist/index.cjs +1823 -359
  23. package/dist/index.d.cts +15 -931
  24. package/dist/index.d.ts +15 -931
  25. package/dist/index.esm.js +187 -5578
  26. package/dist/layout-B9VayJhZ.d.cts +75 -0
  27. package/dist/layout-CQWngNQ7.d.ts +75 -0
  28. package/dist/studio.cjs +5734 -0
  29. package/dist/studio.d.cts +15 -0
  30. package/dist/studio.d.ts +15 -0
  31. package/dist/studio.esm.js +27 -0
  32. package/dist/styles.css +52 -2
  33. package/dist/timbal-v2-button-F4-z7m33.d.cts +40 -0
  34. package/dist/timbal-v2-button-F4-z7m33.d.ts +40 -0
  35. package/dist/ui.cjs +720 -0
  36. package/dist/ui.d.cts +74 -0
  37. package/dist/ui.d.ts +74 -0
  38. package/dist/ui.esm.js +44 -0
  39. package/dist/welcome--80i_O0p.d.cts +190 -0
  40. package/dist/welcome-BOizSp5h.d.ts +190 -0
  41. package/package.json +35 -3
  42. package/scripts/dev-linked.mjs +66 -0
  43. package/vite/local-dev.d.ts +4 -0
  44. package/vite/local-dev.mjs +71 -0
package/dist/index.cjs CHANGED
@@ -32,21 +32,30 @@ 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: () => import_react46.ActionBarPrimitive,
35
+ ActionBarPrimitive: () => import_react57.ActionBarPrimitive,
36
+ AppChatPanel: () => AppChatPanel,
37
+ AppConfirmDialog: () => AppConfirmDialog,
38
+ AppCopilotProvider: () => AppCopilotProvider,
39
+ AppShell: () => AppShell,
40
+ AppShellChatTrigger: () => AppShellChatTrigger,
41
+ AppShellTopbar: () => AppShellTopbar,
36
42
  ArtifactCard: () => ArtifactCard,
37
43
  ArtifactRegistryProvider: () => ArtifactRegistryProvider,
38
44
  ArtifactView: () => ArtifactView,
39
- AssistantRuntimeProvider: () => import_react46.AssistantRuntimeProvider,
40
- AuiIf: () => import_react46.AuiIf,
45
+ AssistantRuntimeProvider: () => import_react57.AssistantRuntimeProvider,
46
+ AuiIf: () => import_react57.AuiIf,
41
47
  AuthGuard: () => AuthGuard,
42
48
  Avatar: () => Avatar,
43
49
  AvatarFallback: () => AvatarFallback,
44
50
  AvatarImage: () => AvatarImage,
51
+ Breadcrumbs: () => Breadcrumbs,
45
52
  Button: () => Button,
46
53
  ChartArtifactView: () => ChartArtifactView,
54
+ ChartPanel: () => ChartPanel,
47
55
  Composer: () => Composer,
48
- ComposerPrimitive: () => import_react46.ComposerPrimitive,
56
+ ComposerPrimitive: () => import_react57.ComposerPrimitive,
49
57
  DEFAULT_UPLOAD_ACCEPT: () => DEFAULT_UPLOAD_ACCEPT,
58
+ DataTable: () => DataTable,
50
59
  Dialog: () => Dialog,
51
60
  DialogClose: () => DialogClose,
52
61
  DialogContent: () => DialogContent,
@@ -54,20 +63,41 @@ __export(index_exports, {
54
63
  DialogPortal: () => DialogPortal,
55
64
  DialogTitle: () => DialogTitle,
56
65
  DialogTrigger: () => DialogTrigger,
66
+ EmptyState: () => EmptyState2,
67
+ Field: () => Field,
68
+ FieldInput: () => FieldInput,
69
+ FieldSelect: () => FieldSelect,
70
+ FieldSwitch: () => FieldSwitch,
71
+ FieldTextarea: () => FieldTextarea,
72
+ FilterBar: () => FilterBar,
73
+ FormSection: () => FormSection,
57
74
  HtmlArtifactView: () => HtmlArtifactView,
58
75
  JsonArtifactView: () => JsonArtifactView,
59
76
  MarkdownText: () => MarkdownText,
60
- MessagePrimitive: () => import_react46.MessagePrimitive,
77
+ MemoPillSegmentedTabs: () => MemoPillSegmentedTabs,
78
+ MessagePrimitive: () => import_react57.MessagePrimitive,
61
79
  ModeToggle: () => ModeToggle,
80
+ Page: () => Page,
81
+ PageHeader: () => PageHeader,
82
+ PillSegmentedTabs: () => PillSegmentedTabs,
62
83
  QuestionArtifactView: () => QuestionArtifactView,
84
+ STUDIO_NAV_MODE: () => STUDIO_NAV_MODE,
85
+ SearchInput: () => SearchInput,
86
+ Section: () => Section,
63
87
  SessionProvider: () => SessionProvider,
64
88
  Shimmer: () => Shimmer,
89
+ StatTile: () => StatTile,
90
+ StatusBadge: () => StatusBadge,
91
+ StudioModeSwitch: () => StudioModeSwitch,
65
92
  StudioSidebar: () => StudioSidebar,
66
93
  StudioWelcome: () => StudioWelcome,
94
+ SubNav: () => SubNav,
67
95
  Suggestions: () => Suggestions,
96
+ SurfaceCard: () => SurfaceCard,
97
+ THREAD_DEFAULT_MAX_WIDTH: () => THREAD_DEFAULT_MAX_WIDTH,
68
98
  TableArtifactView: () => TableArtifactView,
69
99
  Thread: () => Thread,
70
- ThreadPrimitive: () => import_react46.ThreadPrimitive,
100
+ ThreadPrimitive: () => import_react57.ThreadPrimitive,
71
101
  TimbalChat: () => TimbalChat,
72
102
  TimbalChatShell: () => TimbalChatShell,
73
103
  TimbalMark: () => TimbalMark,
@@ -85,6 +115,8 @@ __export(index_exports, {
85
115
  UiEventProvider: () => UiEventProvider,
86
116
  UiNodeView: () => UiNodeView,
87
117
  WorkforceSelector: () => WorkforceSelector,
118
+ assistantMessageContentClass: () => assistantMessageContentClass,
119
+ assistantMessageRootClass: () => assistantMessageRootClass,
88
120
  authFetch: () => authFetch,
89
121
  clearTokens: () => clearTokens,
90
122
  cn: () => cn,
@@ -108,14 +140,17 @@ __export(index_exports, {
108
140
  setPath: () => setPath,
109
141
  setRefreshToken: () => setRefreshToken,
110
142
  splitMarkdownByArtifacts: () => splitMarkdownByArtifacts,
143
+ threadMessageColumnClass: () => threadMessageColumnClass,
144
+ useAppCopilotContext: () => useAppCopilotContext,
145
+ useAppShellChat: () => useAppShellChat,
111
146
  useArtifactRegistry: () => useArtifactRegistry,
112
- useComposerRuntime: () => import_react46.useComposerRuntime,
113
- useMessageRuntime: () => import_react46.useMessageRuntime,
147
+ useComposerRuntime: () => import_react57.useComposerRuntime,
148
+ useMessageRuntime: () => import_react57.useMessageRuntime,
114
149
  useOptionalSession: () => useOptionalSession,
115
150
  useResolvedSuggestions: () => useResolvedSuggestions,
116
151
  useSession: () => useSession,
117
- useThread: () => import_react46.useThread,
118
- useThreadRuntime: () => import_react46.useThreadRuntime,
152
+ useThread: () => import_react57.useThread,
153
+ useThreadRuntime: () => import_react57.useThreadRuntime,
119
154
  useTimbalRuntime: () => useTimbalRuntime,
120
155
  useTimbalStream: () => useTimbalStream,
121
156
  useToolRunning: () => useToolRunning,
@@ -123,7 +158,8 @@ __export(index_exports, {
123
158
  useUiDispatch: () => useUiDispatch,
124
159
  useUiEventEmitter: () => useUiEventEmitter,
125
160
  useUiState: () => useUiState,
126
- useWorkforces: () => useWorkforces
161
+ useWorkforces: () => useWorkforces,
162
+ userMessageRootClass: () => userMessageRootClass
127
163
  });
128
164
  module.exports = __toCommonJS(index_exports);
129
165
 
@@ -1000,13 +1036,13 @@ function findParentIdFromAuiParent(messages, auiParentId) {
1000
1036
  // src/index.ts
1001
1037
  var import_timbal_sdk2 = require("@timbal-ai/timbal-sdk");
1002
1038
 
1003
- // src/components/thread.tsx
1004
- var import_react26 = require("react");
1005
- var import_react27 = require("@assistant-ui/react");
1039
+ // src/chat/thread.tsx
1040
+ var import_react27 = require("react");
1041
+ var import_react28 = require("@assistant-ui/react");
1006
1042
  var import_lucide_react8 = require("lucide-react");
1007
- var import_react28 = require("motion/react");
1043
+ var import_react29 = require("motion/react");
1008
1044
 
1009
- // src/components/attachment.tsx
1045
+ // src/chat/attachment.tsx
1010
1046
  var import_react5 = require("react");
1011
1047
  var import_lucide_react2 = require("lucide-react");
1012
1048
  var import_react6 = require("@assistant-ui/react");
@@ -1074,6 +1110,110 @@ function TooltipContent({
1074
1110
  // src/ui/dialog.tsx
1075
1111
  var import_lucide_react = require("lucide-react");
1076
1112
  var import_radix_ui2 = require("radix-ui");
1113
+
1114
+ // src/design/button-tokens.ts
1115
+ var TIMBAL_V2_ELEVATED_GRADIENT = "bg-gradient-to-b from-elevated-from to-elevated-to";
1116
+ var TIMBAL_V2_MODAL_SURFACE = cn(
1117
+ "bg-gradient-to-b from-modal-from to-modal-to",
1118
+ "border border-border shadow-card-elevated"
1119
+ );
1120
+ var TIMBAL_V2_PRIMARY_GRADIENT = "bg-gradient-to-b from-primary-fill-from to-primary-fill-to";
1121
+ var TIMBAL_V2_FROM_LEGACY_BUTTON = {
1122
+ default: "primary",
1123
+ destructive: "destructive",
1124
+ outline: "secondary",
1125
+ secondary: "secondary",
1126
+ ghost: "ghost",
1127
+ link: "link"
1128
+ };
1129
+ var TIMBAL_V2_SIZE_HEIGHT = {
1130
+ xs: "min-h-8 h-8",
1131
+ sm: "min-h-9 h-9",
1132
+ md: "min-h-10 h-10",
1133
+ lg: "min-h-11 h-11"
1134
+ };
1135
+ var TIMBAL_V2_SIZE_ICON = {
1136
+ xs: "min-h-8 min-w-8 size-8",
1137
+ sm: "min-h-8 min-w-8 size-8",
1138
+ md: "min-h-10 min-w-10 size-10",
1139
+ lg: "min-h-11 min-w-11 size-11"
1140
+ };
1141
+ var TIMBAL_V2_SIZE_LABEL_PX = {
1142
+ xs: "px-3",
1143
+ sm: "px-4",
1144
+ md: "px-5",
1145
+ lg: "px-6"
1146
+ };
1147
+ var TIMBAL_V2_FILL = {
1148
+ primary: [
1149
+ "bg-gradient-to-b from-primary-fill-from to-primary-fill-to",
1150
+ "group-hover/tbv2:from-primary-fill-hover-from group-hover/tbv2:to-primary-fill-hover-to",
1151
+ "group-active/tbv2:from-primary-fill-active-from group-active/tbv2:to-primary-fill-active-to"
1152
+ ].join(" "),
1153
+ informative: [
1154
+ TIMBAL_V2_PRIMARY_GRADIENT,
1155
+ "group-hover/tbv2:from-primary-fill-hover-from group-hover/tbv2:to-primary-fill-hover-to",
1156
+ "group-active/tbv2:from-primary-fill-active-from group-active/tbv2:to-primary-fill-active-to",
1157
+ "group-active/tbv2:[background-image:linear-gradient(to_top,rgba(0,0,0,0.08),transparent_55%)]"
1158
+ ].join(" "),
1159
+ destructive: [
1160
+ TIMBAL_V2_ELEVATED_GRADIENT,
1161
+ "group-hover/tbv2:from-destructive-fill-hover-from group-hover/tbv2:to-destructive-fill-hover-to",
1162
+ "group-active/tbv2:from-destructive-fill-active-from group-active/tbv2:to-destructive-fill-active-to"
1163
+ ].join(" "),
1164
+ secondary: [
1165
+ TIMBAL_V2_ELEVATED_GRADIENT,
1166
+ "group-hover/tbv2:from-secondary-fill-hover-from group-hover/tbv2:to-secondary-fill-hover-to",
1167
+ "group-active/tbv2:from-secondary-fill-active-from group-active/tbv2:to-secondary-fill-active-to"
1168
+ ].join(" "),
1169
+ ghost: [
1170
+ "bg-transparent",
1171
+ "group-hover/tbv2:bg-ghost-fill-hover",
1172
+ "group-active/tbv2:bg-ghost-fill-active"
1173
+ ].join(" "),
1174
+ link: "bg-transparent"
1175
+ };
1176
+ var TIMBAL_V2_LABEL = {
1177
+ primary: "text-primary-foreground",
1178
+ informative: "text-primary-foreground",
1179
+ destructive: "text-destructive",
1180
+ secondary: "text-foreground",
1181
+ ghost: "text-foreground",
1182
+ link: "text-foreground underline decoration-foreground/25 underline-offset-2 group-hover/tbv2:decoration-foreground/45"
1183
+ };
1184
+ var TIMBAL_V2_BORDER = {
1185
+ primary: "",
1186
+ informative: "border border-foreground/15",
1187
+ destructive: "border border-destructive/45",
1188
+ secondary: "border border-border",
1189
+ ghost: "",
1190
+ link: ""
1191
+ };
1192
+ var TIMBAL_V2_SHADOW = {
1193
+ primary: "shadow-card",
1194
+ informative: "shadow-card",
1195
+ destructive: "shadow-card",
1196
+ secondary: "shadow-card",
1197
+ ghost: "",
1198
+ link: ""
1199
+ };
1200
+ var TIMBAL_V2_SWITCH_TRACK_OFF = cn(
1201
+ TIMBAL_V2_ELEVATED_GRADIENT,
1202
+ "border border-border shadow-card"
1203
+ );
1204
+ var TIMBAL_V2_SWITCH_THUMB = cn(
1205
+ TIMBAL_V2_ELEVATED_GRADIENT,
1206
+ "border border-border/80 shadow-sm"
1207
+ );
1208
+ var TIMBAL_V2_SECONDARY_CHROME = [
1209
+ TIMBAL_V2_ELEVATED_GRADIENT,
1210
+ "border border-border shadow-card",
1211
+ "transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
1212
+ "hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to",
1213
+ "active:from-secondary-fill-active-from active:to-secondary-fill-active-to"
1214
+ ].join(" ");
1215
+
1216
+ // src/ui/dialog.tsx
1077
1217
  var import_jsx_runtime4 = require("react/jsx-runtime");
1078
1218
  function Dialog({
1079
1219
  ...props
@@ -1104,7 +1244,7 @@ function DialogOverlay({
1104
1244
  {
1105
1245
  "data-slot": "dialog-overlay",
1106
1246
  className: cn(
1107
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
1247
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-[70] bg-black/50",
1108
1248
  className
1109
1249
  ),
1110
1250
  ...props
@@ -1124,7 +1264,8 @@ function DialogContent({
1124
1264
  {
1125
1265
  "data-slot": "dialog-content",
1126
1266
  className: cn(
1127
- "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
1267
+ TIMBAL_V2_MODAL_SURFACE,
1268
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-[70] grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl p-6 duration-200 outline-none sm:max-w-lg",
1128
1269
  className
1129
1270
  ),
1130
1271
  ...props,
@@ -1134,7 +1275,7 @@ function DialogContent({
1134
1275
  import_radix_ui2.Dialog.Close,
1135
1276
  {
1136
1277
  "data-slot": "dialog-close",
1137
- className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1278
+ className: "ring-offset-background focus:ring-ring data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-[opacity,background-color] hover:bg-ghost-fill-hover hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1138
1279
  children: [
1139
1280
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.XIcon, {}),
1140
1281
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sr-only", children: "Close" })
@@ -1211,98 +1352,53 @@ function AvatarFallback({
1211
1352
  );
1212
1353
  }
1213
1354
 
1214
- // src/components/tooltip-icon-button.tsx
1355
+ // src/chat/tooltip-icon-button.tsx
1215
1356
  var import_react4 = require("react");
1216
1357
 
1217
1358
  // src/ui/timbal-v2-button.tsx
1218
1359
  var React = __toESM(require("react"), 1);
1219
1360
  var import_radix_ui4 = require("radix-ui");
1220
-
1221
- // src/design/button-tokens.ts
1222
- var TIMBAL_V2_SIZE_HEIGHT = {
1223
- xs: "min-h-8 h-8",
1224
- sm: "min-h-9 h-9",
1225
- md: "min-h-10 h-10",
1226
- lg: "min-h-11 h-11"
1227
- };
1228
- var TIMBAL_V2_SIZE_ICON = {
1229
- xs: "min-h-8 min-w-8 size-8",
1230
- sm: "min-h-8 min-w-8 size-8",
1231
- md: "min-h-10 min-w-10 size-10",
1232
- lg: "min-h-11 min-w-11 size-11"
1233
- };
1234
- var TIMBAL_V2_SIZE_LABEL_PX = {
1235
- xs: "px-3",
1236
- sm: "px-4",
1237
- md: "px-5",
1238
- lg: "px-6"
1239
- };
1240
- var TIMBAL_V2_FILL = {
1361
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1362
+ var TIMBAL_V2_FILL_AS_CHILD = {
1241
1363
  primary: [
1242
1364
  "bg-gradient-to-b from-primary-fill-from to-primary-fill-to",
1243
- "group-hover/tbv2:from-primary-fill-hover-from group-hover/tbv2:to-primary-fill-hover-to",
1244
- "group-active/tbv2:from-primary-fill-active-from group-active/tbv2:to-primary-fill-active-to"
1365
+ "hover:from-primary-fill-hover-from hover:to-primary-fill-hover-to",
1366
+ "active:from-primary-fill-active-from active:to-primary-fill-active-to"
1245
1367
  ].join(" "),
1246
1368
  informative: [
1247
- "bg-primary",
1248
- "group-active/tbv2:[background-image:linear-gradient(to_top,rgba(0,0,0,0.08),transparent_55%)]"
1369
+ TIMBAL_V2_PRIMARY_GRADIENT,
1370
+ "hover:from-primary-fill-hover-from hover:to-primary-fill-hover-to",
1371
+ "active:from-primary-fill-active-from active:to-primary-fill-active-to",
1372
+ "active:[background-image:linear-gradient(to_top,rgba(0,0,0,0.08),transparent_55%)]"
1249
1373
  ].join(" "),
1250
1374
  destructive: [
1251
- "bg-gradient-to-b from-elevated-from to-elevated-to",
1252
- "group-hover/tbv2:from-destructive-fill-hover-from group-hover/tbv2:to-destructive-fill-hover-to",
1253
- "group-active/tbv2:from-destructive-fill-active-from group-active/tbv2:to-destructive-fill-active-to"
1375
+ TIMBAL_V2_ELEVATED_GRADIENT,
1376
+ "hover:from-destructive-fill-hover-from hover:to-destructive-fill-hover-to",
1377
+ "active:from-destructive-fill-active-from active:to-destructive-fill-active-to"
1254
1378
  ].join(" "),
1255
1379
  secondary: [
1256
- "bg-gradient-to-b from-elevated-from to-elevated-to",
1257
- "group-hover/tbv2:from-secondary-fill-hover-from group-hover/tbv2:to-secondary-fill-hover-to",
1258
- "group-active/tbv2:from-secondary-fill-active-from group-active/tbv2:to-secondary-fill-active-to"
1380
+ TIMBAL_V2_ELEVATED_GRADIENT,
1381
+ "hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to",
1382
+ "active:from-secondary-fill-active-from active:to-secondary-fill-active-to"
1259
1383
  ].join(" "),
1260
1384
  ghost: [
1261
1385
  "bg-transparent",
1262
- "group-hover/tbv2:bg-ghost-fill-hover",
1263
- "group-active/tbv2:bg-ghost-fill-active"
1386
+ "hover:bg-ghost-fill-hover",
1387
+ "active:bg-ghost-fill-active"
1264
1388
  ].join(" "),
1265
1389
  link: "bg-transparent"
1266
1390
  };
1267
- var TIMBAL_V2_LABEL = {
1268
- primary: "text-primary-foreground",
1269
- informative: "text-primary-foreground",
1270
- destructive: "text-destructive",
1271
- secondary: "text-foreground",
1272
- ghost: "text-foreground",
1273
- link: "text-foreground underline decoration-foreground/25 underline-offset-2 group-hover/tbv2:decoration-foreground/45"
1274
- };
1275
- var TIMBAL_V2_BORDER = {
1276
- primary: "",
1277
- informative: "border border-foreground/15",
1278
- destructive: "border border-destructive/45",
1279
- secondary: "border border-border",
1280
- ghost: "",
1281
- link: ""
1282
- };
1283
- var TIMBAL_V2_SHADOW = {
1284
- primary: "shadow-card",
1285
- informative: "shadow-card",
1286
- destructive: "shadow-card",
1287
- secondary: "shadow-card",
1288
- ghost: "",
1289
- link: ""
1391
+ var TIMBAL_V2_LABEL_AS_CHILD = {
1392
+ ...TIMBAL_V2_LABEL,
1393
+ link: "text-foreground underline decoration-foreground/25 underline-offset-2 hover:decoration-foreground/45"
1290
1394
  };
1291
- var TIMBAL_V2_SECONDARY_CHROME = [
1292
- "bg-gradient-to-b from-elevated-from to-elevated-to border border-border shadow-card",
1293
- "transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
1294
- "hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to",
1295
- "active:from-secondary-fill-active-from active:to-secondary-fill-active-to"
1296
- ].join(" ");
1297
-
1298
- // src/ui/timbal-v2-button.tsx
1299
- var import_jsx_runtime6 = require("react/jsx-runtime");
1300
1395
  var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
1301
1396
  variant = "secondary",
1302
1397
  size = "sm",
1303
1398
  isIconOnly = false,
1304
1399
  isLoading = false,
1305
1400
  fullWidth = false,
1401
+ shape = "pill",
1306
1402
  asChild = false,
1307
1403
  className,
1308
1404
  disabled,
@@ -1311,28 +1407,49 @@ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
1311
1407
  ...props
1312
1408
  }, ref) {
1313
1409
  const isDisabled = disabled || isLoading;
1314
- const Comp = asChild ? import_radix_ui4.Slot.Root : "button";
1315
1410
  const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
1316
- const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : "rounded-full";
1411
+ const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : shape === "rect" ? "rounded-md" : "rounded-full";
1412
+ const sharedRootClass = cn(
1413
+ "relative box-border inline-flex items-center justify-center gap-2 whitespace-nowrap border-0 text-sm font-normal shadow-none transition duration-200 ease-in-out",
1414
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
1415
+ sizeClass,
1416
+ radiusClass,
1417
+ TIMBAL_V2_BORDER[variant],
1418
+ TIMBAL_V2_SHADOW[variant],
1419
+ fullWidth && "w-full",
1420
+ isDisabled && "pointer-events-none opacity-50",
1421
+ className
1422
+ );
1423
+ if (asChild) {
1424
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1425
+ import_radix_ui4.Slot.Root,
1426
+ {
1427
+ ref,
1428
+ "aria-disabled": isDisabled ? true : void 0,
1429
+ "data-slot": "timbal-v2-button",
1430
+ "data-variant": variant,
1431
+ className: cn(
1432
+ sharedRootClass,
1433
+ TIMBAL_V2_FILL_AS_CHILD[variant],
1434
+ !isIconOnly && TIMBAL_V2_SIZE_LABEL_PX[size],
1435
+ TIMBAL_V2_LABEL_AS_CHILD[variant]
1436
+ ),
1437
+ ...props,
1438
+ children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : children
1439
+ }
1440
+ );
1441
+ }
1317
1442
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1318
- Comp,
1443
+ "button",
1319
1444
  {
1320
1445
  ref,
1321
- type: asChild ? void 0 : type,
1322
- disabled: asChild ? void 0 : isDisabled,
1323
- "aria-disabled": asChild && isDisabled ? true : void 0,
1446
+ type,
1447
+ disabled: isDisabled,
1324
1448
  "data-slot": "timbal-v2-button",
1325
1449
  "data-variant": variant,
1326
1450
  className: cn(
1327
- "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",
1328
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
1329
- sizeClass,
1330
- radiusClass,
1331
- TIMBAL_V2_BORDER[variant],
1332
- TIMBAL_V2_SHADOW[variant],
1333
- fullWidth && "w-full",
1334
- isDisabled && "pointer-events-none opacity-50",
1335
- className
1451
+ "group/tbv2 flex-col items-stretch overflow-hidden bg-transparent p-0",
1452
+ sharedRootClass
1336
1453
  ),
1337
1454
  ...props,
1338
1455
  children: [
@@ -1362,7 +1479,7 @@ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
1362
1479
  );
1363
1480
  });
1364
1481
 
1365
- // src/components/tooltip-icon-button.tsx
1482
+ // src/chat/tooltip-icon-button.tsx
1366
1483
  var import_jsx_runtime7 = require("react/jsx-runtime");
1367
1484
  var TooltipIconButton = (0, import_react4.forwardRef)(function TooltipIconButton2({ tooltip, side = "bottom", variant = "secondary", children, ...props }, ref) {
1368
1485
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Tooltip, { children: [
@@ -1374,7 +1491,7 @@ var TooltipIconButton = (0, import_react4.forwardRef)(function TooltipIconButton
1374
1491
  ] });
1375
1492
  });
1376
1493
 
1377
- // src/components/attachment.tsx
1494
+ // src/chat/attachment.tsx
1378
1495
  var import_jsx_runtime8 = require("react/jsx-runtime");
1379
1496
  var useFileSrc = (file) => {
1380
1497
  const [src, setSrc] = (0, import_react5.useState)(void 0);
@@ -1533,7 +1650,7 @@ var ComposerAddAttachment = () => {
1533
1650
  ) });
1534
1651
  };
1535
1652
 
1536
- // src/components/markdown-text.tsx
1653
+ // src/chat/markdown-text.tsx
1537
1654
  var import_dot = require("@assistant-ui/react-markdown/styles/dot.css");
1538
1655
  var import_katex_min = require("katex/dist/katex.min.css");
1539
1656
  var import_react_markdown = require("@assistant-ui/react-markdown");
@@ -1543,7 +1660,7 @@ var import_rehype_katex = __toESM(require("rehype-katex"), 1);
1543
1660
  var import_react17 = require("react");
1544
1661
  var import_lucide_react4 = require("lucide-react");
1545
1662
 
1546
- // src/components/syntax-highlighter.tsx
1663
+ // src/chat/syntax-highlighter.tsx
1547
1664
  var import_react16 = require("react");
1548
1665
  var import_core = require("shiki/core");
1549
1666
  var import_javascript = require("shiki/engine/javascript");
@@ -1881,24 +1998,27 @@ var studioTopbarPillHeightClass = "h-[var(--studio-chrome-pill-height)] min-h-[v
1881
1998
  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)]";
1882
1999
  var studioPlaygroundGradientClass = "bg-gradient-to-b from-playground-from via-playground-via to-playground-to";
1883
2000
  var studioComposeInputShellClass = cn(
1884
- "aui-composer-shell flex w-full flex-col rounded-2xl bg-composer-bg shadow-card-elevated outline-none",
2001
+ "aui-composer-shell flex w-full flex-col overflow-hidden rounded-2xl bg-composer-bg shadow-card-elevated outline-none",
1885
2002
  "border border-composer-border",
1886
2003
  "transition-[box-shadow,border-color]",
1887
2004
  "focus-within:border-composer-border-focus focus-within:ring-2 focus-within:ring-foreground/5"
1888
2005
  );
1889
2006
  var studioSecondaryChromeClass = TIMBAL_V2_SECONDARY_CHROME;
1890
- var studioIntegrationSurfaceSolid = "bg-gradient-to-b from-elevated-from to-elevated-to shadow-card";
2007
+ var studioSearchChromeClass = cn(
2008
+ studioSecondaryChromeClass,
2009
+ studioTopbarPillHeightClass,
2010
+ "inline-flex items-center gap-2 rounded-full px-2.5"
2011
+ );
2012
+ var studioIntegrationSurfaceSolid = cn(
2013
+ TIMBAL_V2_ELEVATED_GRADIENT,
2014
+ "shadow-card"
2015
+ );
1891
2016
  var studioIntegrationBorder = "border border-border";
1892
2017
  var studioIntegrationCardClass = cn(
1893
2018
  "rounded-xl",
1894
2019
  studioIntegrationSurfaceSolid,
1895
2020
  studioIntegrationBorder
1896
2021
  );
1897
- var studioIntegrationIconTileClass = cn(
1898
- "flex size-9 shrink-0 items-center justify-center rounded-lg",
1899
- studioIntegrationSurfaceSolid,
1900
- studioIntegrationBorder
1901
- );
1902
2022
  var studioListRowButtonClass = cn(
1903
2023
  "flex w-full cursor-pointer items-center gap-3 rounded-xl px-3 py-2.5 text-left",
1904
2024
  studioIntegrationCardClass,
@@ -1911,10 +2031,6 @@ var studioComposerIoWellClass = cn(
1911
2031
  studioIntegrationSurfaceSolid,
1912
2032
  studioIntegrationBorder
1913
2033
  );
1914
- var studioToolCardShellClass = cn(
1915
- studioIntegrationCardClass,
1916
- "my-2 min-h-0 overflow-hidden"
1917
- );
1918
2034
  var studioSidebarPanelClass = cn(
1919
2035
  "bg-sidebar text-sidebar-foreground",
1920
2036
  "border border-sidebar-border",
@@ -1977,10 +2093,15 @@ var studioArtifactShellClass = cn(
1977
2093
  studioIntegrationCardClass,
1978
2094
  "my-2 w-full min-w-0 overflow-hidden"
1979
2095
  );
1980
- 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";
2096
+ var studioQuestionOptionClass = cn(
2097
+ "flex w-full items-center gap-2 rounded-lg border border-transparent px-2 py-1.5 text-left text-sm",
2098
+ "transition-[background-color,border-color,box-shadow] duration-200",
2099
+ "hover:border-border hover:bg-gradient-to-b hover:from-elevated-from hover:to-elevated-to hover:shadow-card",
2100
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2"
2101
+ );
1981
2102
  var studioQuestionOptionSelectedClass = cn(
1982
2103
  studioQuestionOptionClass,
1983
- "border-border bg-accent ring-1 ring-foreground/10"
2104
+ "border-border bg-gradient-to-b from-elevated-from to-elevated-to shadow-card ring-1 ring-foreground/10"
1984
2105
  );
1985
2106
 
1986
2107
  // src/artifacts/question-artifact.tsx
@@ -2247,29 +2368,38 @@ var import_react13 = require("@assistant-ui/react");
2247
2368
 
2248
2369
  // src/ui/button.tsx
2249
2370
  var import_class_variance_authority = require("class-variance-authority");
2250
- var import_radix_ui5 = require("radix-ui");
2251
2371
  var import_jsx_runtime16 = require("react/jsx-runtime");
2372
+ var LEGACY_SIZE_TO_V2 = {
2373
+ default: "md",
2374
+ xs: "xs",
2375
+ sm: "sm",
2376
+ lg: "lg",
2377
+ icon: "sm",
2378
+ "icon-xs": "xs",
2379
+ "icon-sm": "sm",
2380
+ "icon-lg": "lg"
2381
+ };
2252
2382
  var buttonVariants = (0, import_class_variance_authority.cva)(
2253
- "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",
2383
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0",
2254
2384
  {
2255
2385
  variants: {
2256
2386
  variant: {
2257
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
2258
- destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/30",
2259
- outline: "border border-border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
2260
- secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
2261
- ghost: "hover:bg-accent hover:text-accent-foreground",
2262
- link: "text-primary underline-offset-4 hover:underline"
2387
+ default: "",
2388
+ destructive: "",
2389
+ outline: "",
2390
+ secondary: "",
2391
+ ghost: "",
2392
+ link: ""
2263
2393
  },
2264
2394
  size: {
2265
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
2266
- xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
2267
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
2268
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
2269
- icon: "size-9",
2270
- "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
2271
- "icon-sm": "size-8",
2272
- "icon-lg": "size-10"
2395
+ default: "",
2396
+ xs: "",
2397
+ sm: "",
2398
+ lg: "",
2399
+ icon: "",
2400
+ "icon-xs": "",
2401
+ "icon-sm": "",
2402
+ "icon-lg": ""
2273
2403
  }
2274
2404
  },
2275
2405
  defaultVariants: {
@@ -2285,13 +2415,20 @@ function Button({
2285
2415
  asChild = false,
2286
2416
  ...props
2287
2417
  }) {
2288
- const Comp = asChild ? import_radix_ui5.Slot.Root : "button";
2418
+ const v2Variant = TIMBAL_V2_FROM_LEGACY_BUTTON[variant ?? "default"];
2419
+ const v2Size = LEGACY_SIZE_TO_V2[size ?? "default"];
2420
+ const isIconOnly = typeof size === "string" && size.startsWith("icon");
2289
2421
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2290
- Comp,
2422
+ TimbalV2Button,
2291
2423
  {
2292
2424
  "data-slot": "button",
2293
2425
  "data-variant": variant,
2294
2426
  "data-size": size,
2427
+ variant: v2Variant,
2428
+ size: v2Size,
2429
+ shape: "rect",
2430
+ isIconOnly,
2431
+ asChild,
2295
2432
  className: cn(buttonVariants({ variant, size, className })),
2296
2433
  ...props
2297
2434
  }
@@ -2520,14 +2657,15 @@ var ToggleNode = ({ node }) => {
2520
2657
  "aria-checked": value,
2521
2658
  onClick: onToggle,
2522
2659
  className: cn(
2523
- "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border transition-colors",
2524
- value ? "border-primary bg-primary" : "border-border bg-muted hover:bg-muted/80"
2660
+ "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
2661
+ value ? "border-foreground/15 bg-gradient-to-b from-primary-fill-from to-primary-fill-to shadow-card" : cn(TIMBAL_V2_SWITCH_TRACK_OFF, "hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to")
2525
2662
  ),
2526
2663
  children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2527
2664
  "span",
2528
2665
  {
2529
2666
  className: cn(
2530
- "inline-block size-4 transform rounded-full bg-background shadow transition-transform",
2667
+ "inline-block size-4 transform rounded-full transition-transform",
2668
+ TIMBAL_V2_SWITCH_THUMB,
2531
2669
  value ? "translate-x-4" : "translate-x-0.5"
2532
2670
  ),
2533
2671
  "aria-hidden": true
@@ -2759,7 +2897,7 @@ function splitMarkdownByArtifacts(markdown) {
2759
2897
  return segments;
2760
2898
  }
2761
2899
 
2762
- // src/components/syntax-highlighter.tsx
2900
+ // src/chat/syntax-highlighter.tsx
2763
2901
  var import_javascript2 = __toESM(require("shiki/langs/javascript.mjs"), 1);
2764
2902
  var import_typescript = __toESM(require("shiki/langs/typescript.mjs"), 1);
2765
2903
  var import_python = __toESM(require("shiki/langs/python.mjs"), 1);
@@ -2866,7 +3004,7 @@ var ShikiSyntaxHighlighter = ({
2866
3004
  };
2867
3005
  var syntax_highlighter_default = ShikiSyntaxHighlighter;
2868
3006
 
2869
- // src/components/markdown-text.tsx
3007
+ // src/chat/markdown-text.tsx
2870
3008
  var import_jsx_runtime21 = require("react/jsx-runtime");
2871
3009
  var MarkdownTextImpl = () => {
2872
3010
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
@@ -3121,7 +3259,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
3121
3259
  CodeHeader
3122
3260
  });
3123
3261
 
3124
- // src/components/tool-fallback.tsx
3262
+ // src/chat/tool-fallback.tsx
3125
3263
  var import_react21 = require("react");
3126
3264
  var import_lucide_react5 = require("lucide-react");
3127
3265
  var import_react22 = require("@assistant-ui/react");
@@ -3169,7 +3307,7 @@ var ShimmerComponent = ({
3169
3307
  };
3170
3308
  var Shimmer = (0, import_react19.memo)(ShimmerComponent);
3171
3309
 
3172
- // src/components/motion.tsx
3310
+ // src/chat/motion.tsx
3173
3311
  var import_react20 = require("motion/react");
3174
3312
  var import_jsx_runtime23 = require("react/jsx-runtime");
3175
3313
  var luxuryEase = [0.16, 1, 0.3, 1];
@@ -3267,7 +3405,7 @@ function ToolBodyPresence({
3267
3405
  );
3268
3406
  }
3269
3407
 
3270
- // src/components/tool-fallback.tsx
3408
+ // src/chat/tool-fallback.tsx
3271
3409
  var import_jsx_runtime24 = require("react/jsx-runtime");
3272
3410
  function detectRunning({
3273
3411
  status,
@@ -3462,7 +3600,7 @@ var ToolArtifactFallback = (props) => {
3462
3600
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ToolFallback, { ...props });
3463
3601
  };
3464
3602
 
3465
- // src/components/composer.tsx
3603
+ // src/chat/composer.tsx
3466
3604
  var import_react23 = require("@assistant-ui/react");
3467
3605
  var import_lucide_react6 = require("lucide-react");
3468
3606
  var import_jsx_runtime26 = require("react/jsx-runtime");
@@ -3572,7 +3710,7 @@ var ComposerSendOrCancel = ({ sendTooltip }) => {
3572
3710
  ] });
3573
3711
  };
3574
3712
 
3575
- // src/components/suggestions.tsx
3713
+ // src/chat/suggestions.tsx
3576
3714
  var import_react24 = require("react");
3577
3715
  var import_react25 = require("@assistant-ui/react");
3578
3716
  var import_lucide_react7 = require("lucide-react");
@@ -3714,18 +3852,30 @@ function scheduleThemeSanityCheck() {
3714
3852
  }
3715
3853
  }
3716
3854
 
3717
- // src/components/thread.tsx
3855
+ // src/chat/thread-variant.tsx
3856
+ var import_react26 = require("react");
3857
+ var ThreadVariantContext = (0, import_react26.createContext)("default");
3858
+ var ThreadVariantProvider = ThreadVariantContext.Provider;
3859
+ function useThreadVariant() {
3860
+ return (0, import_react26.useContext)(ThreadVariantContext);
3861
+ }
3862
+
3863
+ // src/chat/thread.tsx
3718
3864
  var import_jsx_runtime28 = require("react/jsx-runtime");
3719
3865
  var Thread = ({
3720
3866
  className,
3721
- maxWidth = "44rem",
3867
+ variant = "default",
3868
+ maxWidth: maxWidthProp,
3722
3869
  welcome,
3723
3870
  suggestions,
3724
- composerPlaceholder = "Send a message...",
3871
+ composerPlaceholder,
3725
3872
  components,
3726
3873
  artifacts,
3727
3874
  onArtifactEvent
3728
3875
  }) => {
3876
+ const isPanel = variant === "panel";
3877
+ const maxWidth = maxWidthProp ?? (isPanel ? "100%" : "44rem");
3878
+ const placeholder = composerPlaceholder ?? (isPanel ? "Ask about this page\u2026" : "Send a message...");
3729
3879
  const WelcomeSlot = components?.Welcome ?? ThreadWelcome;
3730
3880
  const ComposerSlot = components?.Composer ?? Composer;
3731
3881
  const UserMessageSlot = components?.UserMessage ?? UserMessage;
@@ -3733,28 +3883,33 @@ var Thread = ({
3733
3883
  const EditComposerSlot = components?.EditComposer ?? EditComposer;
3734
3884
  const ScrollToBottomSlot = components?.ScrollToBottom ?? ThreadScrollToBottom;
3735
3885
  const SuggestionsSlot = components?.Suggestions ?? Suggestions;
3736
- (0, import_react26.useEffect)(() => {
3886
+ (0, import_react27.useEffect)(() => {
3737
3887
  scheduleThemeSanityCheck();
3738
3888
  }, []);
3739
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3889
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ThreadVariantProvider, { value: variant, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3740
3890
  ArtifactRegistryProvider,
3741
3891
  {
3742
3892
  renderers: artifacts?.renderers,
3743
3893
  override: artifacts?.override,
3744
3894
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
3745
3895
  }), children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3746
- import_react27.ThreadPrimitive.Root,
3896
+ import_react28.ThreadPrimitive.Root,
3747
3897
  {
3748
3898
  className: cn(
3749
3899
  "aui-root aui-thread-root @container flex h-full flex-col bg-transparent",
3900
+ isPanel && "aui-thread-root--panel",
3750
3901
  className
3751
3902
  ),
3752
3903
  style: { ["--thread-max-width"]: maxWidth },
3904
+ "data-thread-variant": variant,
3753
3905
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3754
- import_react27.ThreadPrimitive.Viewport,
3906
+ import_react28.ThreadPrimitive.Viewport,
3755
3907
  {
3756
3908
  turnAnchor: "bottom",
3757
- className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-pb-4 px-4 pt-4",
3909
+ className: cn(
3910
+ "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-pb-28",
3911
+ isPanel ? "px-2 pt-2" : "px-4 pt-4"
3912
+ ),
3758
3913
  children: [
3759
3914
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3760
3915
  WelcomeSlot,
@@ -3765,7 +3920,7 @@ var Thread = ({
3765
3920
  }
3766
3921
  ),
3767
3922
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3768
- import_react27.ThreadPrimitive.Messages,
3923
+ import_react28.ThreadPrimitive.Messages,
3769
3924
  {
3770
3925
  components: {
3771
3926
  UserMessage: UserMessageSlot,
@@ -3774,20 +3929,38 @@ var Thread = ({
3774
3929
  }
3775
3930
  }
3776
3931
  ),
3777
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react27.ThreadPrimitive.ViewportFooter, { className: "aui-thread-viewport-footer sticky bottom-0 z-10 mx-auto mt-auto flex w-full max-w-(--thread-max-width) isolate flex-col gap-4 bg-transparent pt-2 pb-4 md:pb-6", children: [
3778
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ScrollToBottomSlot, {}),
3779
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ComposerSlot, { placeholder: composerPlaceholder })
3780
- ] })
3932
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3933
+ import_react28.ThreadPrimitive.ViewportFooter,
3934
+ {
3935
+ className: cn(
3936
+ "aui-thread-viewport-footer sticky bottom-0 z-10 mt-auto w-full isolate pt-2",
3937
+ isPanel ? "bg-card pb-2" : "bg-background pb-4 md:pb-6"
3938
+ ),
3939
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3940
+ "div",
3941
+ {
3942
+ className: cn(
3943
+ "mx-auto flex w-full max-w-(--thread-max-width) flex-col",
3944
+ isPanel ? "gap-2" : "gap-4"
3945
+ ),
3946
+ children: [
3947
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ScrollToBottomSlot, {}),
3948
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ComposerSlot, { placeholder })
3949
+ ]
3950
+ }
3951
+ )
3952
+ }
3953
+ )
3781
3954
  ]
3782
3955
  }
3783
3956
  )
3784
3957
  }
3785
3958
  ) })
3786
3959
  }
3787
- );
3960
+ ) });
3788
3961
  };
3789
3962
  var ThreadScrollToBottom = () => {
3790
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3963
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3791
3964
  TooltipIconButton,
3792
3965
  {
3793
3966
  tooltip: "Scroll to bottom",
@@ -3825,64 +3998,86 @@ var ThreadWelcome = ({
3825
3998
  suggestions,
3826
3999
  Suggestions: SuggestionsSlot = Suggestions
3827
4000
  }) => {
3828
- const isEmpty = (0, import_react27.useThread)((s) => s.messages.length === 0);
4001
+ const isEmpty = (0, import_react28.useThread)((s) => s.messages.length === 0);
4002
+ const isPanel = useThreadVariant() === "panel";
3829
4003
  if (!isEmpty) return null;
4004
+ const defaultHeading = isPanel ? "Ask about this page" : "How can I help you today?";
4005
+ const defaultSubheading = isPanel ? "The assistant can use dashboard context from your app." : "Send a message to start a conversation.";
3830
4006
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
3831
4007
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3832
- import_react28.motion.div,
4008
+ import_react29.motion.div,
3833
4009
  {
3834
- className: "aui-thread-welcome-message flex flex-col items-center justify-center px-4 text-center",
4010
+ className: cn(
4011
+ "aui-thread-welcome-message flex flex-col items-center justify-center text-center",
4012
+ isPanel ? "px-2" : "px-4"
4013
+ ),
3835
4014
  variants: welcomeStagger,
3836
4015
  initial: "initial",
3837
4016
  animate: "animate",
3838
4017
  children: [
3839
- config?.icon && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.motion.div, { variants: welcomeIcon, className: "mb-5", children: config.icon }),
4018
+ config?.icon && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react29.motion.div, { variants: welcomeIcon, className: isPanel ? "mb-3" : "mb-5", children: config.icon }),
3840
4019
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3841
- import_react28.motion.h1,
4020
+ import_react29.motion.h1,
3842
4021
  {
3843
4022
  variants: welcomeItem,
3844
- className: "aui-thread-welcome-message-inner font-semibold text-2xl",
3845
- children: config?.heading ?? "How can I help you today?"
4023
+ className: cn(
4024
+ "aui-thread-welcome-message-inner font-semibold",
4025
+ isPanel ? "text-base" : "text-2xl"
4026
+ ),
4027
+ children: config?.heading ?? defaultHeading
3846
4028
  }
3847
4029
  ),
3848
4030
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3849
- import_react28.motion.p,
4031
+ import_react29.motion.p,
3850
4032
  {
3851
4033
  variants: welcomeItem,
3852
- className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
3853
- children: config?.subheading ?? "Send a message to start a conversation."
4034
+ className: "aui-thread-welcome-message-inner mt-1.5 text-muted-foreground text-sm",
4035
+ children: config?.subheading ?? defaultSubheading
3854
4036
  }
3855
4037
  )
3856
4038
  ]
3857
4039
  }
3858
4040
  ) }),
3859
- suggestions && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SuggestionsSlot, { suggestions }) })
4041
+ suggestions && !isPanel ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SuggestionsSlot, { suggestions }) }) : null
3860
4042
  ] });
3861
4043
  };
3862
4044
  var MessageError = () => {
3863
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.MessagePrimitive.Error, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.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_runtime28.jsx)(import_react27.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
4045
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.MessagePrimitive.Error, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.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_runtime28.jsx)(import_react28.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
3864
4046
  };
3865
4047
  var AssistantMessage = () => {
4048
+ const isPanel = useThreadVariant() === "panel";
3866
4049
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3867
- import_react27.MessagePrimitive.Root,
4050
+ import_react28.MessagePrimitive.Root,
3868
4051
  {
3869
- 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",
4052
+ className: cn(
4053
+ "aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in duration-150",
4054
+ isPanel ? "py-2" : "py-3"
4055
+ ),
3870
4056
  "data-role": "assistant",
3871
4057
  children: [
3872
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
3873
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3874
- import_react27.MessagePrimitive.Parts,
3875
- {
3876
- components: {
3877
- Text: MarkdownText,
3878
- // `Override` (not `Fallback`) replaces the default tool renderer
3879
- // entirely so we never fall back to the assistant-ui boilerplate.
3880
- tools: { Override: ToolArtifactFallback }
3881
- }
3882
- }
3883
- ),
3884
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MessageError, {})
3885
- ] }),
4058
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4059
+ "div",
4060
+ {
4061
+ className: cn(
4062
+ "aui-assistant-message-content wrap-break-word text-foreground leading-relaxed",
4063
+ isPanel ? "px-1 text-sm" : "px-2"
4064
+ ),
4065
+ children: [
4066
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4067
+ import_react28.MessagePrimitive.Parts,
4068
+ {
4069
+ components: {
4070
+ Text: MarkdownText,
4071
+ // `Override` (not `Fallback`) replaces the default tool renderer
4072
+ // entirely so we never fall back to the assistant-ui boilerplate.
4073
+ tools: { Override: ToolArtifactFallback }
4074
+ }
4075
+ }
4076
+ ),
4077
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MessageError, {})
4078
+ ]
4079
+ }
4080
+ ),
3886
4081
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "aui-assistant-message-footer mt-1 mb-3 ml-1 flex", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(AssistantActionBar, {}) })
3887
4082
  ]
3888
4083
  }
@@ -3893,29 +4088,29 @@ var ASSISTANT_ACTION_ICON_CLASS = cn(
3893
4088
  // The v2 fill span sits inside `group/tbv2 > span:first-child`. We mute it
3894
4089
  // here so action-bar buttons read as subtle icons rather than full pills.
3895
4090
  "[&>span:first-child]:bg-transparent",
3896
- "[&>span:first-child]:group-hover/tbv2:bg-muted/70"
4091
+ "[&>span:first-child]:group-hover/tbv2:bg-ghost-fill-hover"
3897
4092
  );
3898
4093
  var AssistantActionBar = () => {
3899
4094
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3900
- import_react27.ActionBarPrimitive.Root,
4095
+ import_react28.ActionBarPrimitive.Root,
3901
4096
  {
3902
4097
  hideWhenRunning: true,
3903
4098
  autohide: "never",
3904
4099
  className: "aui-assistant-action-bar-root flex items-center gap-0 bg-transparent px-0 py-0.5 text-muted-foreground/60",
3905
4100
  children: [
3906
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4101
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3907
4102
  TooltipIconButton,
3908
4103
  {
3909
4104
  tooltip: "Copy",
3910
4105
  variant: "ghost",
3911
4106
  className: ASSISTANT_ACTION_ICON_CLASS,
3912
4107
  children: [
3913
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.AuiIf, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react8.CheckIcon, { className: "size-3" }) }),
3914
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.AuiIf, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react8.CopyIcon, { className: "size-3" }) })
4108
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.AuiIf, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react8.CheckIcon, { className: "size-3" }) }),
4109
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.AuiIf, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react8.CopyIcon, { className: "size-3" }) })
3915
4110
  ]
3916
4111
  }
3917
4112
  ) }),
3918
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4113
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3919
4114
  TooltipIconButton,
3920
4115
  {
3921
4116
  tooltip: "Regenerate",
@@ -3924,8 +4119,8 @@ var AssistantActionBar = () => {
3924
4119
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react8.RefreshCwIcon, { className: "size-3" })
3925
4120
  }
3926
4121
  ) }),
3927
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react27.ActionBarMorePrimitive.Root, { children: [
3928
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4122
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react28.ActionBarMorePrimitive.Root, { children: [
4123
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3929
4124
  TooltipIconButton,
3930
4125
  {
3931
4126
  tooltip: "More",
@@ -3938,12 +4133,12 @@ var AssistantActionBar = () => {
3938
4133
  }
3939
4134
  ) }),
3940
4135
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3941
- import_react27.ActionBarMorePrimitive.Content,
4136
+ import_react28.ActionBarMorePrimitive.Content,
3942
4137
  {
3943
4138
  side: "bottom",
3944
4139
  align: "start",
3945
4140
  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",
3946
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react27.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: [
4141
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react28.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: [
3947
4142
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react8.DownloadIcon, { className: "size-4 shrink-0" }),
3948
4143
  "Export as Markdown"
3949
4144
  ] }) })
@@ -3955,25 +4150,32 @@ var AssistantActionBar = () => {
3955
4150
  );
3956
4151
  };
3957
4152
  var UserMessageText = () => {
3958
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.MessagePartPrimitive.Text, { smooth: false }) });
4153
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.MessagePartPrimitive.Text, { smooth: false }) });
3959
4154
  };
3960
4155
  var UserMessage = () => {
4156
+ const isPanel = useThreadVariant() === "panel";
3961
4157
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3962
- import_react27.MessagePrimitive.Root,
4158
+ import_react28.MessagePrimitive.Root,
3963
4159
  {
3964
- 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",
4160
+ className: cn(
4161
+ "aui-user-message-root mx-auto flex w-full max-w-(--thread-max-width) flex-col items-end gap-2",
4162
+ isPanel ? "px-1 py-2" : "px-2 py-3"
4163
+ ),
3965
4164
  "data-role": "user",
3966
4165
  children: [
3967
4166
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UserMessageAttachments, {}),
3968
4167
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3969
- import_react28.motion.div,
4168
+ import_react29.motion.div,
3970
4169
  {
3971
- 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",
4170
+ className: cn(
4171
+ "aui-user-message-content relative inline-block max-w-[85%] rounded-2xl bg-bubble-user text-bubble-user-foreground",
4172
+ isPanel ? "px-3 py-2 text-sm" : "max-w-[80%] px-4 py-2.5"
4173
+ ),
3972
4174
  initial: { opacity: 0, y: 8, scale: 0.99 },
3973
4175
  animate: { opacity: 1, y: 0, scale: 1 },
3974
4176
  transition: { duration: 0.65, ease: luxuryEase },
3975
4177
  children: [
3976
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.MessagePrimitive.Parts, { components: { Text: UserMessageText } }),
4178
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.MessagePrimitive.Parts, { components: { Text: UserMessageText } }),
3977
4179
  /* @__PURE__ */ (0, import_jsx_runtime28.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_runtime28.jsx)(UserActionBar, {}) })
3978
4180
  ]
3979
4181
  }
@@ -3984,12 +4186,12 @@ var UserMessage = () => {
3984
4186
  };
3985
4187
  var UserActionBar = () => {
3986
4188
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3987
- import_react27.ActionBarPrimitive.Root,
4189
+ import_react28.ActionBarPrimitive.Root,
3988
4190
  {
3989
4191
  hideWhenRunning: true,
3990
4192
  autohide: "always",
3991
4193
  className: "aui-user-action-bar-root flex flex-col items-end",
3992
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4194
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3993
4195
  TooltipIconButton,
3994
4196
  {
3995
4197
  tooltip: "Edit",
@@ -4002,22 +4204,22 @@ var UserActionBar = () => {
4002
4204
  );
4003
4205
  };
4004
4206
  var EditComposer = () => {
4005
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.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_runtime28.jsxs)(import_react27.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
4207
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.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_runtime28.jsxs)(import_react28.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
4006
4208
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4007
- import_react27.ComposerPrimitive.Input,
4209
+ import_react28.ComposerPrimitive.Input,
4008
4210
  {
4009
4211
  className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
4010
4212
  autoFocus: true
4011
4213
  }
4012
4214
  ),
4013
4215
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
4014
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
4015
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react27.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
4216
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
4217
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react28.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
4016
4218
  ] })
4017
4219
  ] }) });
4018
4220
  };
4019
4221
 
4020
- // src/components/chat.tsx
4222
+ // src/chat/chat.tsx
4021
4223
  var import_jsx_runtime29 = require("react/jsx-runtime");
4022
4224
  function TimbalChat({
4023
4225
  workforceId,
@@ -4044,7 +4246,7 @@ function TimbalChat({
4044
4246
  );
4045
4247
  }
4046
4248
 
4047
- // src/components/workforce-selector.tsx
4249
+ // src/chat/workforce-selector.tsx
4048
4250
  var import_lucide_react9 = require("lucide-react");
4049
4251
  var import_jsx_runtime30 = require("react/jsx-runtime");
4050
4252
  var WorkforceSelector = ({
@@ -4100,22 +4302,22 @@ function idOf(item) {
4100
4302
  }
4101
4303
 
4102
4304
  // src/hooks/use-workforces.ts
4103
- var import_react29 = require("react");
4305
+ var import_react30 = require("react");
4104
4306
  function useWorkforces(options = {}) {
4105
4307
  const { baseUrl = "/api", fetch: fetchFn, pickInitial, enabled = true } = options;
4106
- const [workforces, setWorkforces] = (0, import_react29.useState)([]);
4107
- const [selectedId, setSelectedId] = (0, import_react29.useState)("");
4108
- const [isLoading, setIsLoading] = (0, import_react29.useState)(enabled);
4109
- const [error, setError] = (0, import_react29.useState)(null);
4110
- const fetchFnRef = (0, import_react29.useRef)(fetchFn ?? authFetch);
4111
- (0, import_react29.useEffect)(() => {
4308
+ const [workforces, setWorkforces] = (0, import_react30.useState)([]);
4309
+ const [selectedId, setSelectedId] = (0, import_react30.useState)("");
4310
+ const [isLoading, setIsLoading] = (0, import_react30.useState)(enabled);
4311
+ const [error, setError] = (0, import_react30.useState)(null);
4312
+ const fetchFnRef = (0, import_react30.useRef)(fetchFn ?? authFetch);
4313
+ (0, import_react30.useEffect)(() => {
4112
4314
  fetchFnRef.current = fetchFn ?? authFetch;
4113
4315
  }, [fetchFn]);
4114
- const pickInitialRef = (0, import_react29.useRef)(pickInitial);
4115
- (0, import_react29.useEffect)(() => {
4316
+ const pickInitialRef = (0, import_react30.useRef)(pickInitial);
4317
+ (0, import_react30.useEffect)(() => {
4116
4318
  pickInitialRef.current = pickInitial;
4117
4319
  }, [pickInitial]);
4118
- const load = (0, import_react29.useMemo)(() => {
4320
+ const load = (0, import_react30.useMemo)(() => {
4119
4321
  return async () => {
4120
4322
  if (!enabled) {
4121
4323
  setIsLoading(false);
@@ -4140,10 +4342,10 @@ function useWorkforces(options = {}) {
4140
4342
  }
4141
4343
  };
4142
4344
  }, [baseUrl, enabled]);
4143
- (0, import_react29.useEffect)(() => {
4345
+ (0, import_react30.useEffect)(() => {
4144
4346
  load();
4145
4347
  }, [load]);
4146
- const selected = (0, import_react29.useMemo)(
4348
+ const selected = (0, import_react30.useMemo)(
4147
4349
  () => workforces.find((w) => idOf2(w) === selectedId),
4148
4350
  [workforces, selectedId]
4149
4351
  );
@@ -4202,7 +4404,7 @@ var DOM_IDS = {
4202
4404
  topbarBrandAnchor: "timbal-studio-topbar-brand-anchor"
4203
4405
  };
4204
4406
 
4205
- // src/components/chat-shell.tsx
4407
+ // src/studio/shell/chat-shell.tsx
4206
4408
  var import_jsx_runtime31 = require("react/jsx-runtime");
4207
4409
  var TimbalChatShell = ({
4208
4410
  workforceId,
@@ -4280,10 +4482,10 @@ var TimbalChatShell = ({
4280
4482
  );
4281
4483
  };
4282
4484
 
4283
- // src/components/studio/studio-shell.tsx
4284
- var import_react42 = require("react");
4485
+ // src/studio/shell/studio-shell.tsx
4486
+ var import_react45 = require("react");
4285
4487
  var import_lucide_react13 = require("lucide-react");
4286
- var import_react43 = require("motion/react");
4488
+ var import_react46 = require("motion/react");
4287
4489
 
4288
4490
  // src/design/sidebar-motion.ts
4289
4491
  var STUDIO_SIDEBAR_EASE_ENTER = [0, 0, 0.2, 1];
@@ -4354,16 +4556,16 @@ function studioSidebarBackdropTransition(reduced) {
4354
4556
  }
4355
4557
 
4356
4558
  // src/hooks/use-sidebar-collapse-phase.ts
4357
- var import_react30 = require("react");
4559
+ var import_react31 = require("react");
4358
4560
  var WIDTH_OVERLAP_FRAC = 0.7;
4359
4561
  function useSidebarCollapsePhase(collapsed, reducedMotion) {
4360
- const [widthCollapsed, setWidthCollapsed] = (0, import_react30.useState)(collapsed);
4361
- const [entriesVisible, setEntriesVisible] = (0, import_react30.useState)(true);
4362
- const collapsedTarget = (0, import_react30.useRef)(collapsed);
4363
- const isFirstRender = (0, import_react30.useRef)(true);
4364
- const widthTimerRef = (0, import_react30.useRef)(null);
4365
- const revealTimerRef = (0, import_react30.useRef)(null);
4366
- (0, import_react30.useEffect)(() => {
4562
+ const [widthCollapsed, setWidthCollapsed] = (0, import_react31.useState)(collapsed);
4563
+ const [entriesVisible, setEntriesVisible] = (0, import_react31.useState)(true);
4564
+ const collapsedTarget = (0, import_react31.useRef)(collapsed);
4565
+ const isFirstRender = (0, import_react31.useRef)(true);
4566
+ const widthTimerRef = (0, import_react31.useRef)(null);
4567
+ const revealTimerRef = (0, import_react31.useRef)(null);
4568
+ (0, import_react31.useEffect)(() => {
4367
4569
  collapsedTarget.current = collapsed;
4368
4570
  }, [collapsed]);
4369
4571
  const clearWidthTimer = () => {
@@ -4378,7 +4580,7 @@ function useSidebarCollapsePhase(collapsed, reducedMotion) {
4378
4580
  revealTimerRef.current = null;
4379
4581
  }
4380
4582
  };
4381
- const applyWidthTarget = (0, import_react30.useCallback)(() => {
4583
+ const applyWidthTarget = (0, import_react31.useCallback)(() => {
4382
4584
  const willExpand = !collapsedTarget.current;
4383
4585
  setWidthCollapsed(collapsedTarget.current);
4384
4586
  clearRevealTimer();
@@ -4389,7 +4591,7 @@ function useSidebarCollapsePhase(collapsed, reducedMotion) {
4389
4591
  );
4390
4592
  }
4391
4593
  }, [reducedMotion]);
4392
- (0, import_react30.useEffect)(() => {
4594
+ (0, import_react31.useEffect)(() => {
4393
4595
  clearWidthTimer();
4394
4596
  clearRevealTimer();
4395
4597
  if (reducedMotion) {
@@ -4413,10 +4615,10 @@ function useSidebarCollapsePhase(collapsed, reducedMotion) {
4413
4615
  clearRevealTimer();
4414
4616
  };
4415
4617
  }, [collapsed, reducedMotion, applyWidthTarget]);
4416
- const onEntriesBlurOutComplete = (0, import_react30.useCallback)(() => {
4618
+ const onEntriesBlurOutComplete = (0, import_react31.useCallback)(() => {
4417
4619
  applyWidthTarget();
4418
4620
  }, [applyWidthTarget]);
4419
- const onPanelWidthComplete = (0, import_react30.useCallback)(() => {
4621
+ const onPanelWidthComplete = (0, import_react31.useCallback)(() => {
4420
4622
  clearRevealTimer();
4421
4623
  setEntriesVisible(true);
4422
4624
  }, []);
@@ -4430,16 +4632,16 @@ function useSidebarCollapsePhase(collapsed, reducedMotion) {
4430
4632
  };
4431
4633
  }
4432
4634
 
4433
- // src/components/studio/sidebar-backdrop.tsx
4434
- var import_react31 = require("motion/react");
4635
+ // src/studio/sidebar/sidebar-backdrop.tsx
4636
+ var import_react32 = require("motion/react");
4435
4637
  var import_jsx_runtime32 = require("react/jsx-runtime");
4436
4638
  var StudioSidebarBackdrop = ({
4437
4639
  open,
4438
4640
  onClose
4439
4641
  }) => {
4440
- const reducedMotion = (0, import_react31.useReducedMotion)();
4441
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react31.AnimatePresence, { children: open ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
4442
- import_react31.motion.button,
4642
+ const reducedMotion = (0, import_react32.useReducedMotion)();
4643
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react32.AnimatePresence, { children: open ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
4644
+ import_react32.motion.button,
4443
4645
  {
4444
4646
  type: "button",
4445
4647
  className: "fixed inset-0 z-40 bg-foreground/30 backdrop-blur-[2px] md:hidden",
@@ -4453,24 +4655,24 @@ var StudioSidebarBackdrop = ({
4453
4655
  ) : null });
4454
4656
  };
4455
4657
 
4456
- // src/components/studio/sidebar-context.tsx
4457
- var import_react32 = require("react");
4458
- var StudioSidebarContext = (0, import_react32.createContext)({
4658
+ // src/studio/sidebar/sidebar-context.tsx
4659
+ var import_react33 = require("react");
4660
+ var StudioSidebarContext = (0, import_react33.createContext)({
4459
4661
  collapsed: false,
4460
4662
  isMobile: false,
4461
4663
  isCollapsedRail: false,
4462
4664
  iconOnlyLayout: false
4463
4665
  });
4464
4666
  function useStudioSidebarLayout() {
4465
- return (0, import_react32.useContext)(StudioSidebarContext);
4667
+ return (0, import_react33.useContext)(StudioSidebarContext);
4466
4668
  }
4467
4669
 
4468
- // src/components/studio/sidebar.tsx
4469
- var import_react36 = require("react");
4470
- var import_react37 = require("motion/react");
4670
+ // src/studio/sidebar/sidebar.tsx
4671
+ var import_react39 = require("react");
4672
+ var import_react40 = require("motion/react");
4471
4673
 
4472
- // src/components/studio/sidebar-entries.tsx
4473
- var import_react33 = require("motion/react");
4674
+ // src/studio/sidebar/sidebar-entries.tsx
4675
+ var import_react34 = require("motion/react");
4474
4676
  var import_jsx_runtime33 = require("react/jsx-runtime");
4475
4677
  var StudioSidebarEntries = ({
4476
4678
  visible,
@@ -4478,12 +4680,12 @@ var StudioSidebarEntries = ({
4478
4680
  children,
4479
4681
  className
4480
4682
  }) => {
4481
- const reducedMotion = (0, import_react33.useReducedMotion)();
4683
+ const reducedMotion = (0, import_react34.useReducedMotion)();
4482
4684
  if (reducedMotion) {
4483
4685
  return visible ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn("flex min-h-0 flex-1 flex-col", className), children }) : null;
4484
4686
  }
4485
4687
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
4486
- import_react33.motion.div,
4688
+ import_react34.motion.div,
4487
4689
  {
4488
4690
  className: cn("flex min-h-0 flex-1 flex-col", className),
4489
4691
  initial: false,
@@ -4502,11 +4704,11 @@ var StudioSidebarEntries = ({
4502
4704
  );
4503
4705
  };
4504
4706
 
4505
- // src/components/studio/sidebar-footer.tsx
4707
+ // src/studio/sidebar/sidebar-footer.tsx
4506
4708
  var import_lucide_react10 = require("lucide-react");
4507
4709
 
4508
4710
  // src/auth/provider.tsx
4509
- var import_react34 = require("react");
4711
+ var import_react35 = require("react");
4510
4712
  var import_jsx_runtime34 = require("react/jsx-runtime");
4511
4713
  function isInsideIframe() {
4512
4714
  try {
@@ -4515,26 +4717,26 @@ function isInsideIframe() {
4515
4717
  return true;
4516
4718
  }
4517
4719
  }
4518
- var SessionContext = (0, import_react34.createContext)(void 0);
4720
+ var SessionContext = (0, import_react35.createContext)(void 0);
4519
4721
  var useSession = () => {
4520
- const context = (0, import_react34.useContext)(SessionContext);
4722
+ const context = (0, import_react35.useContext)(SessionContext);
4521
4723
  if (context === void 0) {
4522
4724
  throw new Error("useSession must be used within a SessionProvider");
4523
4725
  }
4524
4726
  return context;
4525
4727
  };
4526
4728
  var useOptionalSession = () => {
4527
- const context = (0, import_react34.useContext)(SessionContext);
4729
+ const context = (0, import_react35.useContext)(SessionContext);
4528
4730
  return context ?? null;
4529
4731
  };
4530
4732
  var SessionProvider = ({
4531
4733
  children,
4532
4734
  enabled = true
4533
4735
  }) => {
4534
- const [user, setUser] = (0, import_react34.useState)(null);
4535
- const [loading, setLoading] = (0, import_react34.useState)(enabled);
4536
- const [embedded] = (0, import_react34.useState)(isInsideIframe);
4537
- (0, import_react34.useEffect)(() => {
4736
+ const [user, setUser] = (0, import_react35.useState)(null);
4737
+ const [loading, setLoading] = (0, import_react35.useState)(enabled);
4738
+ const [embedded] = (0, import_react35.useState)(isInsideIframe);
4739
+ (0, import_react35.useEffect)(() => {
4538
4740
  if (!enabled) {
4539
4741
  setLoading(false);
4540
4742
  return;
@@ -4595,7 +4797,7 @@ var SessionProvider = ({
4595
4797
  messageCleanup?.();
4596
4798
  };
4597
4799
  }, [enabled, embedded]);
4598
- const logout = (0, import_react34.useCallback)(() => {
4800
+ const logout = (0, import_react35.useCallback)(() => {
4599
4801
  clearTokens();
4600
4802
  setUser(null);
4601
4803
  const returnTo = encodeURIComponent(
@@ -4620,7 +4822,7 @@ var SessionProvider = ({
4620
4822
  );
4621
4823
  };
4622
4824
 
4623
- // src/components/studio/sidebar-layout.ts
4825
+ // src/studio/sidebar/sidebar-layout.ts
4624
4826
  function studioSidebarIconOnlyLayout(isMobile, isCollapsedRail) {
4625
4827
  if (isMobile) return false;
4626
4828
  return isCollapsedRail;
@@ -4642,21 +4844,21 @@ function studioSidebarNavItemClasses(iconOnly, isActive) {
4642
4844
  );
4643
4845
  }
4644
4846
 
4645
- // src/components/studio/sidebar-entry-motion.tsx
4646
- var import_react35 = require("motion/react");
4847
+ // src/studio/sidebar/sidebar-entry-motion.tsx
4848
+ var import_react36 = require("motion/react");
4647
4849
  var import_jsx_runtime35 = require("react/jsx-runtime");
4648
4850
  var StudioSidebarEntryMotion = ({
4649
4851
  children,
4650
4852
  className
4651
4853
  }) => {
4652
- const reducedMotion = (0, import_react35.useReducedMotion)();
4854
+ const reducedMotion = (0, import_react36.useReducedMotion)();
4653
4855
  if (reducedMotion) {
4654
4856
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className, children });
4655
4857
  }
4656
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react35.motion.div, { variants: studioSidebarEntryItemVariants, className: cn(className), children });
4858
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react36.motion.div, { variants: studioSidebarEntryItemVariants, className: cn(className), children });
4657
4859
  };
4658
4860
 
4659
- // src/components/studio/sidebar-tooltip.tsx
4861
+ // src/studio/sidebar/sidebar-tooltip.tsx
4660
4862
  var import_jsx_runtime36 = require("react/jsx-runtime");
4661
4863
  var StudioSidebarTooltip = ({
4662
4864
  label,
@@ -4670,7 +4872,7 @@ var StudioSidebarTooltip = ({
4670
4872
  ] });
4671
4873
  };
4672
4874
 
4673
- // src/components/studio/sidebar-footer.tsx
4875
+ // src/studio/sidebar/sidebar-footer.tsx
4674
4876
  var import_jsx_runtime37 = require("react/jsx-runtime");
4675
4877
  function userInitials(name, email) {
4676
4878
  const fromName = name.trim().split(/\s+/).map((part) => part.charAt(0)).join("").slice(0, 2).toUpperCase();
@@ -4737,7 +4939,7 @@ var StudioSidebarFooter = ({
4737
4939
  ) });
4738
4940
  };
4739
4941
 
4740
- // src/components/studio/sidebar-header.tsx
4942
+ // src/studio/sidebar/sidebar-header.tsx
4741
4943
  var import_lucide_react11 = require("lucide-react");
4742
4944
  var import_jsx_runtime38 = require("react/jsx-runtime");
4743
4945
  var sidebarHeaderClass = "flex h-12 shrink-0 items-center px-2";
@@ -4845,7 +5047,7 @@ var StudioSidebarHeader = ({
4845
5047
  ] });
4846
5048
  };
4847
5049
 
4848
- // src/components/studio/sidebar-workforce.ts
5050
+ // src/studio/sidebar/sidebar-workforce.ts
4849
5051
  function workforceItemId(w) {
4850
5052
  return w.id ?? w.uid ?? w.name ?? "";
4851
5053
  }
@@ -4857,7 +5059,7 @@ function workforceItemInitial(w) {
4857
5059
  return label.charAt(0).toUpperCase() || "?";
4858
5060
  }
4859
5061
 
4860
- // src/components/studio/sidebar-nav.tsx
5062
+ // src/studio/sidebar/sidebar-nav.tsx
4861
5063
  var import_jsx_runtime39 = require("react/jsx-runtime");
4862
5064
  var StudioSidebarNav = ({
4863
5065
  workforces,
@@ -4905,7 +5107,7 @@ var StudioSidebarNav = ({
4905
5107
  );
4906
5108
  };
4907
5109
 
4908
- // src/components/studio/timbal-mark.tsx
5110
+ // src/studio/sidebar/timbal-mark.tsx
4909
5111
  var import_shaders_react = require("@paper-design/shaders-react");
4910
5112
  var import_jsx_runtime40 = require("react/jsx-runtime");
4911
5113
  var DEFAULT_SIZE = 64;
@@ -4954,7 +5156,32 @@ function TimbalMark({
4954
5156
  );
4955
5157
  }
4956
5158
 
4957
- // src/components/studio/sidebar.tsx
5159
+ // src/studio/sidebar/shell-inset-bridge-context.tsx
5160
+ var import_react38 = require("react");
5161
+
5162
+ // src/layout/shell-inset-context.tsx
5163
+ var import_react37 = require("react");
5164
+ var ShellInsetContext = (0, import_react37.createContext)(null);
5165
+ var ShellInsetProvider = ShellInsetContext.Provider;
5166
+ function useShellInsetReporter() {
5167
+ return (0, import_react37.useContext)(ShellInsetContext);
5168
+ }
5169
+
5170
+ // src/studio/sidebar/shell-inset-bridge-context.tsx
5171
+ var StudioSidebarShellInsetBridge = ({
5172
+ onInsetChange
5173
+ }) => {
5174
+ const reportInset = useShellInsetReporter();
5175
+ const { isMobile, isCollapsedRail } = useStudioSidebarLayout();
5176
+ (0, import_react38.useLayoutEffect)(() => {
5177
+ const insetPx = isMobile ? 0 : isCollapsedRail ? SIDEBAR_INSET_PX_COLLAPSED : SIDEBAR_INSET_PX_EXPANDED;
5178
+ reportInset?.(insetPx);
5179
+ onInsetChange?.(insetPx);
5180
+ }, [reportInset, onInsetChange, isMobile, isCollapsedRail]);
5181
+ return null;
5182
+ };
5183
+
5184
+ // src/studio/sidebar/sidebar.tsx
4958
5185
  var import_jsx_runtime41 = require("react/jsx-runtime");
4959
5186
  var DEFAULT_BREAKPOINT_PX = 768;
4960
5187
  function readPersistedCollapsed(key) {
@@ -4988,7 +5215,7 @@ var StudioSidebarPanel = ({
4988
5215
  brand,
4989
5216
  emptyCaption = null
4990
5217
  }) => {
4991
- const reducedMotion = (0, import_react37.useReducedMotion)();
5218
+ const reducedMotion = (0, import_react40.useReducedMotion)();
4992
5219
  const isCollapsedRail = widthCollapsed && !isMobile;
4993
5220
  const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
4994
5221
  const isDrawerOpen = isMobile && mobileOpen;
@@ -5007,7 +5234,7 @@ var StudioSidebarPanel = ({
5007
5234
  const panelWidthPx = isMobile ? SIDEBAR_MOBILE_PX : widthCollapsed ? SIDEBAR_WIDTH_COLLAPSED_PX : SIDEBAR_WIDTH_PX;
5008
5235
  const brandNode = brand ?? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TimbalMark, { size: 32 });
5009
5236
  const panel = /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
5010
- import_react37.motion.div,
5237
+ import_react40.motion.div,
5011
5238
  {
5012
5239
  "data-sidebar-collapsed": isCollapsedRail ? "" : void 0,
5013
5240
  className: cn(
@@ -5075,7 +5302,7 @@ var StudioSidebarPanel = ({
5075
5302
  );
5076
5303
  if (isMobile) {
5077
5304
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5078
- import_react37.motion.aside,
5305
+ import_react40.motion.aside,
5079
5306
  {
5080
5307
  className: "fixed inset-y-0 left-0 z-[60] flex",
5081
5308
  "aria-label": "Studio navigation",
@@ -5109,53 +5336,54 @@ var StudioSidebar = ({
5109
5336
  brand,
5110
5337
  emptyCaption,
5111
5338
  mobileOpen: mobileOpenProp,
5112
- onMobileOpenChange: onMobileOpenChangeProp
5339
+ onMobileOpenChange: onMobileOpenChangeProp,
5340
+ onInsetChange
5113
5341
  }) => {
5114
- const reducedMotion = (0, import_react37.useReducedMotion)();
5342
+ const reducedMotion = (0, import_react40.useReducedMotion)();
5115
5343
  const fetched = useWorkforces({ enabled: workforcesProp === void 0 });
5116
5344
  const workforces = workforcesProp ?? fetched.workforces;
5117
- const [internalSelected, setInternalSelected] = (0, import_react36.useState)(
5345
+ const [internalSelected, setInternalSelected] = (0, import_react39.useState)(
5118
5346
  selectedIdProp ?? ""
5119
5347
  );
5120
- (0, import_react36.useEffect)(() => {
5348
+ (0, import_react39.useEffect)(() => {
5121
5349
  if (selectedIdProp !== void 0) return;
5122
5350
  if (internalSelected) return;
5123
5351
  const first = workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name;
5124
5352
  if (first) setInternalSelected(first);
5125
5353
  }, [workforces, selectedIdProp, internalSelected]);
5126
5354
  const selectedId = selectedIdProp ?? internalSelected ?? workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name ?? "";
5127
- const handleSelect = (0, import_react36.useCallback)(
5355
+ const handleSelect = (0, import_react39.useCallback)(
5128
5356
  (id) => {
5129
5357
  if (selectedIdProp === void 0) setInternalSelected(id);
5130
5358
  onSelect?.(id);
5131
5359
  },
5132
5360
  [selectedIdProp, onSelect]
5133
5361
  );
5134
- const [collapsed, setCollapsed] = (0, import_react36.useState)(() => {
5362
+ const [collapsed, setCollapsed] = (0, import_react39.useState)(() => {
5135
5363
  const persisted = readPersistedCollapsed(persistKey);
5136
5364
  return persisted || defaultCollapsed;
5137
5365
  });
5138
- const handleCollapsedChange = (0, import_react36.useCallback)(
5366
+ const handleCollapsedChange = (0, import_react39.useCallback)(
5139
5367
  (next) => {
5140
5368
  setCollapsed(next);
5141
5369
  writePersistedCollapsed(persistKey, next);
5142
5370
  },
5143
5371
  [persistKey]
5144
5372
  );
5145
- const [isMobile, setIsMobile] = (0, import_react36.useState)(() => {
5373
+ const [isMobile, setIsMobile] = (0, import_react39.useState)(() => {
5146
5374
  if (typeof window === "undefined") return false;
5147
5375
  return window.innerWidth < mobileBreakpointPx;
5148
5376
  });
5149
- (0, import_react36.useEffect)(() => {
5377
+ (0, import_react39.useEffect)(() => {
5150
5378
  if (typeof window === "undefined") return;
5151
5379
  const onResize = () => setIsMobile(window.innerWidth < mobileBreakpointPx);
5152
5380
  onResize();
5153
5381
  window.addEventListener("resize", onResize);
5154
5382
  return () => window.removeEventListener("resize", onResize);
5155
5383
  }, [mobileBreakpointPx]);
5156
- const [internalMobileOpen, setInternalMobileOpen] = (0, import_react36.useState)(false);
5384
+ const [internalMobileOpen, setInternalMobileOpen] = (0, import_react39.useState)(false);
5157
5385
  const mobileOpen = mobileOpenProp ?? internalMobileOpen;
5158
- const setMobileOpen = (0, import_react36.useCallback)(
5386
+ const setMobileOpen = (0, import_react39.useCallback)(
5159
5387
  (next) => {
5160
5388
  if (mobileOpenProp === void 0) setInternalMobileOpen(next);
5161
5389
  onMobileOpenChangeProp?.(next);
@@ -5172,7 +5400,7 @@ var StudioSidebar = ({
5172
5400
  const entriesVisible = isMobile || phaseEntriesVisible;
5173
5401
  const isCollapsedRail = widthCollapsed && !isMobile;
5174
5402
  const iconOnlyLayout = studioSidebarIconOnlyLayout(isMobile, isCollapsedRail);
5175
- const contextValue = (0, import_react36.useMemo)(
5403
+ const contextValue = (0, import_react39.useMemo)(
5176
5404
  () => ({
5177
5405
  collapsed: effectiveCollapsed,
5178
5406
  isMobile,
@@ -5181,44 +5409,47 @@ var StudioSidebar = ({
5181
5409
  }),
5182
5410
  [effectiveCollapsed, isMobile, isCollapsedRail, iconOnlyLayout]
5183
5411
  );
5184
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5185
- StudioSidebarPanel,
5186
- {
5187
- workforces,
5188
- selectedId,
5189
- onSelect: handleSelect,
5190
- collapsed: effectiveCollapsed,
5191
- onCollapsedChange: handleCollapsedChange,
5192
- isMobile,
5193
- mobileOpen,
5194
- onMobileOpenChange: setMobileOpen,
5195
- widthCollapsed,
5196
- entriesVisible,
5197
- onEntriesBlurOutComplete,
5198
- onPanelWidthComplete,
5199
- brand,
5200
- emptyCaption
5201
- }
5202
- ) });
5412
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(StudioSidebarContext.Provider, { value: contextValue, children: [
5413
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSidebarShellInsetBridge, { onInsetChange }),
5414
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5415
+ StudioSidebarPanel,
5416
+ {
5417
+ workforces,
5418
+ selectedId,
5419
+ onSelect: handleSelect,
5420
+ collapsed: effectiveCollapsed,
5421
+ onCollapsedChange: handleCollapsedChange,
5422
+ isMobile,
5423
+ mobileOpen,
5424
+ onMobileOpenChange: setMobileOpen,
5425
+ widthCollapsed,
5426
+ entriesVisible,
5427
+ onEntriesBlurOutComplete,
5428
+ onPanelWidthComplete,
5429
+ brand,
5430
+ emptyCaption
5431
+ }
5432
+ )
5433
+ ] });
5203
5434
  };
5204
5435
 
5205
- // src/components/studio/sidebar-runtime-portal.tsx
5206
- var import_react38 = require("react");
5436
+ // src/studio/sidebar/sidebar-runtime-portal.tsx
5437
+ var import_react41 = require("react");
5207
5438
  var import_react_dom = require("react-dom");
5208
5439
  var import_lucide_react12 = require("lucide-react");
5209
- var import_react39 = require("@assistant-ui/react");
5440
+ var import_react42 = require("@assistant-ui/react");
5210
5441
  var import_jsx_runtime42 = require("react/jsx-runtime");
5211
5442
  var StudioSidebarRuntimePortal = ({
5212
5443
  label = "New chat"
5213
5444
  }) => {
5214
5445
  const { iconOnlyLayout } = useStudioSidebarLayout();
5215
- const hasMessages = (0, import_react39.useThread)((s) => s.messages.length > 0);
5446
+ const hasMessages = (0, import_react42.useThread)((s) => s.messages.length > 0);
5216
5447
  const { clear } = useTimbalRuntime();
5217
- const [anchor, setAnchor] = (0, import_react38.useState)(null);
5218
- const startNewChat = (0, import_react38.useCallback)(() => {
5448
+ const [anchor, setAnchor] = (0, import_react41.useState)(null);
5449
+ const startNewChat = (0, import_react41.useCallback)(() => {
5219
5450
  clear();
5220
5451
  }, [clear]);
5221
- (0, import_react38.useLayoutEffect)(() => {
5452
+ (0, import_react41.useLayoutEffect)(() => {
5222
5453
  setAnchor(document.getElementById(DOM_IDS.sidebarRuntimeAnchor));
5223
5454
  }, []);
5224
5455
  if (!anchor || !hasMessages) return null;
@@ -5244,11 +5475,10 @@ var StudioSidebarRuntimePortal = ({
5244
5475
  );
5245
5476
  };
5246
5477
 
5247
- // src/components/studio/welcome.tsx
5248
- var import_react40 = require("motion/react");
5249
- var import_react41 = require("@assistant-ui/react");
5478
+ // src/studio/sidebar/welcome.tsx
5479
+ var import_react43 = require("motion/react");
5480
+ var import_react44 = require("@assistant-ui/react");
5250
5481
  var import_jsx_runtime43 = require("react/jsx-runtime");
5251
- var luxuryEase2 = [0.16, 1, 0.3, 1];
5252
5482
  var welcomeStagger2 = {
5253
5483
  initial: {},
5254
5484
  animate: {
@@ -5260,7 +5490,7 @@ var welcomeItem2 = {
5260
5490
  animate: {
5261
5491
  opacity: 1,
5262
5492
  y: 0,
5263
- transition: { duration: 0.9, ease: luxuryEase2 }
5493
+ transition: { duration: 0.9, ease: luxuryEase }
5264
5494
  }
5265
5495
  };
5266
5496
  var welcomeIcon2 = {
@@ -5269,11 +5499,11 @@ var welcomeIcon2 = {
5269
5499
  opacity: 1,
5270
5500
  y: 0,
5271
5501
  scale: 1,
5272
- transition: { duration: 1.1, ease: luxuryEase2 }
5502
+ transition: { duration: 1.1, ease: luxuryEase }
5273
5503
  }
5274
5504
  };
5275
5505
  var StudioWelcome = ({ config, icon }) => {
5276
- const isEmpty = (0, import_react41.useThread)((s) => s.messages.length === 0);
5506
+ const isEmpty = (0, import_react44.useThread)((s) => s.messages.length === 0);
5277
5507
  if (!isEmpty) return null;
5278
5508
  const iconNode = icon ?? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
5279
5509
  TimbalMark,
@@ -5283,16 +5513,16 @@ var StudioWelcome = ({ config, icon }) => {
5283
5513
  }
5284
5514
  );
5285
5515
  return /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
5286
- import_react40.motion.div,
5516
+ import_react43.motion.div,
5287
5517
  {
5288
5518
  className: "aui-thread-welcome-message flex flex-col items-center justify-center px-2 text-center sm:px-4",
5289
5519
  variants: welcomeStagger2,
5290
5520
  initial: "initial",
5291
5521
  animate: "animate",
5292
5522
  children: [
5293
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react40.motion.div, { variants: welcomeIcon2, className: "mb-4 md:mb-5", children: iconNode }),
5523
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react43.motion.div, { variants: welcomeIcon2, className: "mb-4 md:mb-5", children: iconNode }),
5294
5524
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
5295
- import_react40.motion.h1,
5525
+ import_react43.motion.h1,
5296
5526
  {
5297
5527
  variants: welcomeItem2,
5298
5528
  className: "aui-thread-welcome-message-inner text-xl font-semibold sm:text-2xl",
@@ -5300,7 +5530,7 @@ var StudioWelcome = ({ config, icon }) => {
5300
5530
  }
5301
5531
  ),
5302
5532
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
5303
- import_react40.motion.p,
5533
+ import_react43.motion.p,
5304
5534
  {
5305
5535
  variants: welcomeItem2,
5306
5536
  className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
@@ -5312,9 +5542,9 @@ var StudioWelcome = ({ config, icon }) => {
5312
5542
  ) }) });
5313
5543
  };
5314
5544
 
5315
- // src/components/studio/studio-shell.tsx
5545
+ // src/studio/shell/studio-shell.tsx
5316
5546
  var import_jsx_runtime44 = require("react/jsx-runtime");
5317
- var import_react44 = require("react");
5547
+ var import_react47 = require("react");
5318
5548
  var DEFAULT_BREAKPOINT_PX2 = 768;
5319
5549
  function readPersistedCollapsed2(key) {
5320
5550
  if (!key || typeof window === "undefined") return false;
@@ -5356,7 +5586,7 @@ var TimbalStudioShell = ({
5356
5586
  components,
5357
5587
  ...chatProps
5358
5588
  }) => {
5359
- const reducedMotion = (0, import_react43.useReducedMotion)();
5589
+ const reducedMotion = (0, import_react46.useReducedMotion)();
5360
5590
  const shouldFetchWorkforces = !workforceId && workforcesProp === void 0;
5361
5591
  const fetched = useWorkforces({
5362
5592
  enabled: shouldFetchWorkforces,
@@ -5364,36 +5594,36 @@ var TimbalStudioShell = ({
5364
5594
  baseUrl: workforcesBaseUrl
5365
5595
  });
5366
5596
  const workforces = workforcesProp ?? fetched.workforces;
5367
- const [internalSelected, setInternalSelected] = (0, import_react42.useState)(
5597
+ const [internalSelected, setInternalSelected] = (0, import_react45.useState)(
5368
5598
  workforceId ?? ""
5369
5599
  );
5370
- (0, import_react42.useEffect)(() => {
5600
+ (0, import_react45.useEffect)(() => {
5371
5601
  if (workforceId) return;
5372
5602
  if (internalSelected) return;
5373
5603
  const first = workforces[0]?.id ?? workforces[0]?.uid ?? workforces[0]?.name;
5374
5604
  if (first) setInternalSelected(first);
5375
5605
  }, [workforces, workforceId, internalSelected]);
5376
5606
  const activeWorkforceId = workforceId ?? internalSelected ?? fetched.selectedId ?? "";
5377
- const [collapsed, setCollapsed] = (0, import_react42.useState)(() => {
5607
+ const [collapsed, setCollapsed] = (0, import_react45.useState)(() => {
5378
5608
  const persisted = readPersistedCollapsed2(persistKey);
5379
5609
  return persisted || defaultCollapsed;
5380
5610
  });
5381
- const [isMobile, setIsMobile] = (0, import_react42.useState)(() => {
5611
+ const [isMobile, setIsMobile] = (0, import_react45.useState)(() => {
5382
5612
  if (typeof window === "undefined") return false;
5383
5613
  return window.innerWidth < mobileBreakpointPx;
5384
5614
  });
5385
- const [mobileSidebarOpen, setMobileSidebarOpen] = (0, import_react42.useState)(false);
5386
- (0, import_react42.useEffect)(() => {
5615
+ const [mobileSidebarOpen, setMobileSidebarOpen] = (0, import_react45.useState)(false);
5616
+ (0, import_react45.useEffect)(() => {
5387
5617
  if (typeof window === "undefined") return;
5388
5618
  const onResize = () => setIsMobile(window.innerWidth < mobileBreakpointPx);
5389
5619
  onResize();
5390
5620
  window.addEventListener("resize", onResize);
5391
5621
  return () => window.removeEventListener("resize", onResize);
5392
5622
  }, [mobileBreakpointPx]);
5393
- (0, import_react42.useEffect)(() => {
5623
+ (0, import_react45.useEffect)(() => {
5394
5624
  if (!isMobile) setMobileSidebarOpen(false);
5395
5625
  }, [isMobile]);
5396
- (0, import_react42.useEffect)(() => {
5626
+ (0, import_react45.useEffect)(() => {
5397
5627
  if (!mobileSidebarOpen) return;
5398
5628
  const onKeyDown = (e) => {
5399
5629
  if (e.key === "Escape") setMobileSidebarOpen(false);
@@ -5417,21 +5647,21 @@ var TimbalStudioShell = ({
5417
5647
  layoutDirection
5418
5648
  );
5419
5649
  const desktopInsetPx = widthCollapsed ? SIDEBAR_INSET_PX_COLLAPSED : SIDEBAR_INSET_PX_EXPANDED;
5420
- const onCollapsedChange = (0, import_react42.useCallback)(
5650
+ const onCollapsedChange = (0, import_react45.useCallback)(
5421
5651
  (next) => {
5422
5652
  setCollapsed(next);
5423
5653
  writePersistedCollapsed2(persistKey, next);
5424
5654
  },
5425
5655
  [persistKey]
5426
5656
  );
5427
- const handleSelectWorkforce = (0, import_react42.useCallback)(
5657
+ const handleSelectWorkforce = (0, import_react45.useCallback)(
5428
5658
  (id) => {
5429
5659
  if (!workforceId) setInternalSelected(id);
5430
5660
  if (isMobile) setMobileSidebarOpen(false);
5431
5661
  },
5432
5662
  [workforceId, isMobile]
5433
5663
  );
5434
- const sidebarContext = (0, import_react42.useMemo)(
5664
+ const sidebarContext = (0, import_react45.useMemo)(
5435
5665
  () => ({
5436
5666
  collapsed: effectiveCollapsed,
5437
5667
  isMobile,
@@ -5440,7 +5670,7 @@ var TimbalStudioShell = ({
5440
5670
  }),
5441
5671
  [effectiveCollapsed, isMobile, isCollapsedRail, iconOnlyLayout]
5442
5672
  );
5443
- const resolvedComponents = (0, import_react42.useMemo)(() => {
5673
+ const resolvedComponents = (0, import_react45.useMemo)(() => {
5444
5674
  const next = { Welcome: StudioWelcome, ...components };
5445
5675
  next.Composer = makeComposerWithPortal(components?.Composer);
5446
5676
  return next;
@@ -5498,7 +5728,7 @@ var TimbalStudioShell = ({
5498
5728
  }
5499
5729
  ),
5500
5730
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
5501
- import_react43.motion.header,
5731
+ import_react46.motion.header,
5502
5732
  {
5503
5733
  className: cn(
5504
5734
  "absolute top-0 right-0 z-40 flex items-start justify-between gap-2",
@@ -5539,7 +5769,7 @@ var TimbalStudioShell = ({
5539
5769
  }
5540
5770
  ),
5541
5771
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5542
- import_react43.motion.main,
5772
+ import_react46.motion.main,
5543
5773
  {
5544
5774
  className: cn(
5545
5775
  "relative z-10 flex h-full min-w-0 flex-col",
@@ -5549,7 +5779,7 @@ var TimbalStudioShell = ({
5549
5779
  initial: false,
5550
5780
  animate: { paddingLeft: isMobile ? 12 : desktopInsetPx },
5551
5781
  transition: layoutTransition,
5552
- children: activeWorkforceId ? /* @__PURE__ */ (0, import_react44.createElement)(
5782
+ children: activeWorkforceId ? /* @__PURE__ */ (0, import_react47.createElement)(
5553
5783
  TimbalChat,
5554
5784
  {
5555
5785
  ...chatProps,
@@ -5567,8 +5797,23 @@ var TimbalStudioShell = ({
5567
5797
  ) });
5568
5798
  };
5569
5799
 
5570
- // src/components/studio/mode-toggle.tsx
5571
- var import_react45 = require("react");
5800
+ // src/chat/layout.ts
5801
+ var THREAD_DEFAULT_MAX_WIDTH = "44rem";
5802
+ var threadMessageColumnClass = "mx-auto w-full max-w-(--thread-max-width)";
5803
+ var assistantMessageRootClass = [
5804
+ "aui-assistant-message-root relative",
5805
+ threadMessageColumnClass,
5806
+ "py-3 duration-150"
5807
+ ].join(" ");
5808
+ var assistantMessageContentClass = "wrap-break-word px-2 text-foreground leading-relaxed";
5809
+ var userMessageRootClass = [
5810
+ "aui-user-message-root flex flex-col items-end gap-2",
5811
+ threadMessageColumnClass,
5812
+ "px-2 py-3"
5813
+ ].join(" ");
5814
+
5815
+ // src/studio/sidebar/mode-toggle.tsx
5816
+ var import_react48 = require("react");
5572
5817
  var import_lucide_react14 = require("lucide-react");
5573
5818
  var import_jsx_runtime45 = require("react/jsx-runtime");
5574
5819
  var ModeToggle = ({
@@ -5578,14 +5823,14 @@ var ModeToggle = ({
5578
5823
  label = "Toggle theme"
5579
5824
  }) => {
5580
5825
  const isControlled = theme !== void 0;
5581
- const [internalIsDark, setInternalIsDark] = (0, import_react45.useState)(false);
5582
- (0, import_react45.useEffect)(() => {
5826
+ const [internalIsDark, setInternalIsDark] = (0, import_react48.useState)(false);
5827
+ (0, import_react48.useEffect)(() => {
5583
5828
  if (isControlled) return;
5584
5829
  if (typeof document === "undefined") return;
5585
5830
  setInternalIsDark(document.documentElement.classList.contains("dark"));
5586
5831
  }, [isControlled]);
5587
5832
  const isDark = isControlled ? theme === "dark" : internalIsDark;
5588
- const onClick = (0, import_react45.useCallback)(() => {
5833
+ const onClick = (0, import_react48.useCallback)(() => {
5589
5834
  const next = isDark ? "light" : "dark";
5590
5835
  if (setTheme) {
5591
5836
  setTheme(next);
@@ -5619,7 +5864,1190 @@ var ModeToggle = ({
5619
5864
  );
5620
5865
  };
5621
5866
 
5622
- // src/artifacts/agent-instructions.ts
5867
+ // src/studio/mode-switch.tsx
5868
+ var import_react51 = require("react");
5869
+
5870
+ // src/ui/pill-segmented-tabs.tsx
5871
+ var import_react49 = require("react");
5872
+ var import_react50 = require("motion/react");
5873
+
5874
+ // src/design/pill-segmented-classes.ts
5875
+ var pillSegmentedTrackBase = "inline-flex w-fit max-w-max shrink-0 self-start items-center rounded-full";
5876
+ var pillSegmentedTrackSurface = cn(
5877
+ "bg-pill-segmented-track border border-[var(--pill-segmented-track-border)]",
5878
+ "shadow-[var(--pill-segmented-track-shadow)]"
5879
+ );
5880
+ var pillSegmentedTrackClass = cn(
5881
+ pillSegmentedTrackBase,
5882
+ pillSegmentedTrackSurface,
5883
+ "gap-1 p-1"
5884
+ );
5885
+ var pillSegmentedTrackFlushClass = cn(
5886
+ pillSegmentedTrackBase,
5887
+ pillSegmentedTrackSurface,
5888
+ "h-[var(--studio-chrome-pill-height)] items-center gap-0.5 overflow-visible p-0.5"
5889
+ );
5890
+ var pillSegmentedSegmentClass = cn(
5891
+ "relative flex items-center gap-1.5 rounded-full px-4 py-1.5 text-xs font-normal transition-colors"
5892
+ );
5893
+ var pillSegmentedFlushSegmentClass = cn(
5894
+ "relative box-border inline-flex h-9 min-h-9 items-center justify-center gap-1.5 rounded-full px-3.5 py-0",
5895
+ "text-sm font-normal leading-tight transition-colors"
5896
+ );
5897
+ var pillSegmentedActiveIndicatorClass = cn(
5898
+ "absolute inset-0 rounded-full",
5899
+ "border border-[var(--pill-segmented-indicator-border)]",
5900
+ "bg-gradient-to-b from-[var(--pill-segmented-indicator-from)] to-[var(--pill-segmented-indicator-to)]",
5901
+ "shadow-[var(--pill-segmented-indicator-shadow)]"
5902
+ );
5903
+
5904
+ // src/ui/pill-segmented-tabs.tsx
5905
+ var import_jsx_runtime46 = require("react/jsx-runtime");
5906
+ var PillTab = ({
5907
+ tabKey,
5908
+ label,
5909
+ isActive,
5910
+ disabled,
5911
+ onSelect,
5912
+ layoutId,
5913
+ segmentClassName,
5914
+ animateIndicator
5915
+ }) => {
5916
+ const handlePress = (0, import_react49.useCallback)(() => {
5917
+ if (!disabled) onSelect(tabKey);
5918
+ }, [disabled, onSelect, tabKey]);
5919
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
5920
+ "button",
5921
+ {
5922
+ type: "button",
5923
+ onClick: handlePress,
5924
+ disabled,
5925
+ "aria-pressed": isActive,
5926
+ className: cn(
5927
+ segmentClassName,
5928
+ disabled && "cursor-not-allowed opacity-50",
5929
+ !disabled && (isActive ? "text-foreground" : "text-muted-foreground hover:text-foreground")
5930
+ ),
5931
+ children: [
5932
+ isActive && animateIndicator ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5933
+ import_react50.motion.div,
5934
+ {
5935
+ layoutId,
5936
+ className: pillSegmentedActiveIndicatorClass,
5937
+ transition: { type: "spring", duration: 0.3, bounce: 0.15 }
5938
+ }
5939
+ ) : isActive ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: pillSegmentedActiveIndicatorClass, "aria-hidden": true }) : null,
5940
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "relative z-10 whitespace-nowrap", children: label })
5941
+ ]
5942
+ }
5943
+ );
5944
+ };
5945
+ var PillSegmentedTabs = ({
5946
+ value,
5947
+ onChange,
5948
+ tabs,
5949
+ className,
5950
+ trackVariant = "default",
5951
+ layoutId: layoutIdProp,
5952
+ "aria-label": ariaLabel
5953
+ }) => {
5954
+ const reactId = (0, import_react49.useId)();
5955
+ const layoutId = layoutIdProp ?? `pill-segmented-${reactId.replace(/:/g, "")}`;
5956
+ const reducedMotion = (0, import_react50.useReducedMotion)();
5957
+ const isFlush = trackVariant === "flush";
5958
+ const trackClass2 = isFlush ? pillSegmentedTrackFlushClass : pillSegmentedTrackClass;
5959
+ const segmentClassName = isFlush ? pillSegmentedFlushSegmentClass : pillSegmentedSegmentClass;
5960
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { role: "group", "aria-label": ariaLabel, className: cn(trackClass2, className), children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5961
+ PillTab,
5962
+ {
5963
+ tabKey: tab.key,
5964
+ label: tab.label,
5965
+ disabled: tab.disabled,
5966
+ isActive: value === tab.key,
5967
+ onSelect: onChange,
5968
+ layoutId,
5969
+ segmentClassName,
5970
+ animateIndicator: !reducedMotion
5971
+ },
5972
+ tab.key
5973
+ )) });
5974
+ };
5975
+ var MemoPillSegmentedTabs = (0, import_react49.memo)(PillSegmentedTabs);
5976
+
5977
+ // src/studio/mode-switch.tsx
5978
+ var import_jsx_runtime47 = require("react/jsx-runtime");
5979
+ var STUDIO_NAV_MODE = {
5980
+ BUILD: "build",
5981
+ OPERATE: "operate"
5982
+ };
5983
+ var StudioModeSwitch = (0, import_react51.memo)(
5984
+ function StudioModeSwitch2({
5985
+ value,
5986
+ onChange,
5987
+ className,
5988
+ buildLabel = "Build",
5989
+ manageLabel = "Manage",
5990
+ "aria-label": ariaLabel = "Studio mode"
5991
+ }) {
5992
+ const tabs = (0, import_react51.useMemo)(
5993
+ () => [
5994
+ { key: STUDIO_NAV_MODE.BUILD, label: buildLabel },
5995
+ { key: STUDIO_NAV_MODE.OPERATE, label: manageLabel }
5996
+ ],
5997
+ [buildLabel, manageLabel]
5998
+ );
5999
+ const handleChange = (0, import_react51.useCallback)(
6000
+ (key) => {
6001
+ if (key === STUDIO_NAV_MODE.BUILD || key === STUDIO_NAV_MODE.OPERATE) {
6002
+ onChange(key);
6003
+ }
6004
+ },
6005
+ [onChange]
6006
+ );
6007
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6008
+ "div",
6009
+ {
6010
+ "data-tour": "studio-mode-switch",
6011
+ "data-studio-chrome-align": "mode-switch",
6012
+ id: "studio-chrome-mode-switch",
6013
+ className,
6014
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6015
+ PillSegmentedTabs,
6016
+ {
6017
+ value,
6018
+ onChange: handleChange,
6019
+ tabs,
6020
+ trackVariant: "flush",
6021
+ layoutId: "studio-nav-mode-segmented",
6022
+ "aria-label": ariaLabel
6023
+ }
6024
+ )
6025
+ }
6026
+ );
6027
+ }
6028
+ );
6029
+
6030
+ // src/app/layout/AppShell.tsx
6031
+ var import_react53 = require("motion/react");
6032
+ var import_react54 = require("react");
6033
+
6034
+ // src/design/app-classes.ts
6035
+ var appPageColumnClass = "mx-auto w-full max-w-6xl px-4 md:px-6";
6036
+ var appShellTopbarInsetClass = "w-full px-4 md:px-6";
6037
+ var appShellInsetTopClass = "pt-4 md:pt-6";
6038
+ var appShellTopbarRowClass = cn(
6039
+ studioTopbarPillHeightClass,
6040
+ "flex w-full items-center justify-between gap-2"
6041
+ );
6042
+ var appShellTopbarStickyClass = cn(
6043
+ "sticky top-0 z-20 shrink-0 bg-background pb-2",
6044
+ appShellInsetTopClass
6045
+ );
6046
+ var appPageHeaderClass = cn(
6047
+ "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
6048
+ "pb-4 pt-2"
6049
+ );
6050
+ var appSectionClass = "flex flex-col gap-4 py-4";
6051
+ var appSectionTitleClass = "text-lg font-semibold text-foreground";
6052
+ var appSectionDescriptionClass = "text-sm text-muted-foreground";
6053
+ var appSurfaceCardClass = cn(
6054
+ studioIntegrationCardClass,
6055
+ "p-4 md:p-5"
6056
+ );
6057
+ var appStatTileClass = cn(
6058
+ appSurfaceCardClass,
6059
+ "flex flex-col gap-1"
6060
+ );
6061
+ var appStatValueClass = "text-2xl font-semibold tracking-tight text-foreground";
6062
+ var appStatLabelClass = "text-sm text-muted-foreground";
6063
+ var appFilterBarClass = cn(
6064
+ "flex flex-wrap items-center gap-2",
6065
+ studioTopbarPillHeightClass
6066
+ );
6067
+ var appSearchInputClass = cn(studioSearchChromeClass, "text-sm");
6068
+ var appBreadcrumbsClass = "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground";
6069
+ var appBreadcrumbLinkClass = "transition-colors hover:text-foreground";
6070
+ var appFieldClass = "flex flex-col gap-1.5";
6071
+ var appFieldLabelClass = "text-sm font-medium text-foreground";
6072
+ var appFieldHintClass = "text-xs text-muted-foreground";
6073
+ var appInputClass = cn(
6074
+ studioSecondaryChromeClass,
6075
+ "h-10 w-full rounded-lg px-3 text-sm text-foreground outline-none",
6076
+ "placeholder:text-muted-foreground/70",
6077
+ "focus-visible:ring-2 focus-visible:ring-foreground/10"
6078
+ );
6079
+ var appEmptyStateClass = cn(
6080
+ appSurfaceCardClass,
6081
+ "flex flex-col items-center justify-center gap-2 py-12 text-center"
6082
+ );
6083
+ var appEmptyStateTitleClass = "text-base font-medium text-foreground";
6084
+ var appEmptyStateDescriptionClass = "max-w-sm text-sm text-muted-foreground";
6085
+ var appChartPanelClass = cn(appSurfaceCardClass, "flex flex-col gap-3");
6086
+ var appChartPanelTitleClass = "text-sm font-medium text-foreground";
6087
+
6088
+ // src/app/layout/app-shell-chat-context.tsx
6089
+ var import_react52 = require("react");
6090
+ var AppShellChatContext = (0, import_react52.createContext)(null);
6091
+ var AppShellChatProvider = AppShellChatContext.Provider;
6092
+ function useAppShellChat() {
6093
+ return (0, import_react52.useContext)(AppShellChatContext);
6094
+ }
6095
+
6096
+ // src/app/layout/AppShell.tsx
6097
+ var import_jsx_runtime48 = require("react/jsx-runtime");
6098
+ var floatingTriggerClass = cn(
6099
+ "aui-app-shell-chat-trigger-fixed fixed z-50 rounded-full px-5 py-2.5 text-sm font-medium shadow-card-elevated",
6100
+ "bg-primary text-primary-foreground transition-colors hover:bg-primary/90",
6101
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
6102
+ "bottom-6 right-6 max-sm:bottom-4 max-sm:right-4"
6103
+ );
6104
+ var floatingPanelClass = cn(
6105
+ "aui-app-shell-chat-float fixed z-50 flex flex-col overflow-hidden rounded-2xl border border-border/60 shadow-card-elevated",
6106
+ "bg-card/85 backdrop-blur-xl supports-backdrop-filter:bg-card/75",
6107
+ // Mobile: stretch between insets (no fixed width — avoids a wide empty strip on the right)
6108
+ "max-sm:inset-x-3 max-sm:top-3 max-sm:bottom-3 max-sm:w-auto",
6109
+ "sm:top-6 sm:right-6 sm:bottom-6 sm:w-[var(--app-shell-chat-width)] sm:max-w-[calc(100vw-3rem)]"
6110
+ );
6111
+ var AppShellBody = ({
6112
+ sidebar,
6113
+ topbarContent,
6114
+ mainClassName,
6115
+ insetPaddingPx,
6116
+ insetExpanded,
6117
+ children
6118
+ }) => {
6119
+ const reducedMotion = (0, import_react53.useReducedMotion)();
6120
+ const layoutDirection = insetExpanded ? "expand" : "collapse";
6121
+ const layoutTransition = studioSidebarWidthTransition(
6122
+ !!reducedMotion,
6123
+ layoutDirection
6124
+ );
6125
+ const insetPadding = sidebar ? insetPaddingPx : 0;
6126
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6127
+ import_react53.motion.div,
6128
+ {
6129
+ className: "aui-app-shell-body relative z-10 flex min-h-0 min-w-0 flex-1 flex-col",
6130
+ initial: false,
6131
+ animate: { paddingLeft: insetPadding },
6132
+ transition: layoutTransition,
6133
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
6134
+ "div",
6135
+ {
6136
+ className: cn(
6137
+ "aui-app-shell-scroll flex min-h-0 flex-1 flex-col overflow-y-auto",
6138
+ !topbarContent && appShellInsetTopClass
6139
+ ),
6140
+ children: [
6141
+ topbarContent ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("header", { className: cn("aui-app-shell-topbar-region", appShellTopbarStickyClass), children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: appShellTopbarInsetClass, children: topbarContent }) }) : null,
6142
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("main", { className: cn("aui-app-shell-main min-w-0 flex-1", mainClassName), children })
6143
+ ]
6144
+ }
6145
+ )
6146
+ }
6147
+ );
6148
+ };
6149
+ var AppShell = ({
6150
+ sidebar,
6151
+ topbar,
6152
+ header,
6153
+ children,
6154
+ chat,
6155
+ chatWidth = "24rem",
6156
+ chatHeight,
6157
+ chatOpen: chatOpenProp,
6158
+ defaultChatOpen = false,
6159
+ onChatOpenChange,
6160
+ chatCollapsible = true,
6161
+ chatTriggerLabel = "Assistant",
6162
+ hideChatTrigger = false,
6163
+ className,
6164
+ mainClassName
6165
+ }) => {
6166
+ const topbarContent = topbar ?? header;
6167
+ const hasChat = Boolean(chat);
6168
+ const [uncontrolledOpen, setUncontrolledOpen] = (0, import_react54.useState)(defaultChatOpen);
6169
+ const isChatControlled = chatOpenProp !== void 0;
6170
+ const chatOpen = isChatControlled ? chatOpenProp : uncontrolledOpen;
6171
+ const setChatOpen = (0, import_react54.useCallback)(
6172
+ (open) => {
6173
+ if (!isChatControlled) {
6174
+ setUncontrolledOpen(open);
6175
+ }
6176
+ onChatOpenChange?.(open);
6177
+ },
6178
+ [isChatControlled, onChatOpenChange]
6179
+ );
6180
+ const toggleChat = (0, import_react54.useCallback)(() => {
6181
+ setChatOpen(!chatOpen);
6182
+ }, [chatOpen, setChatOpen]);
6183
+ const [insetPaddingPx, setInsetPaddingPx] = (0, import_react54.useState)(
6184
+ sidebar ? SIDEBAR_INSET_PX_EXPANDED : 0
6185
+ );
6186
+ const reportShellInset = (0, import_react54.useCallback)((insetPx) => {
6187
+ setInsetPaddingPx(insetPx);
6188
+ }, []);
6189
+ const insetExpanded = insetPaddingPx >= SIDEBAR_INSET_PX_EXPANDED;
6190
+ const shellBody = /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6191
+ AppShellBody,
6192
+ {
6193
+ sidebar,
6194
+ topbarContent,
6195
+ mainClassName,
6196
+ insetPaddingPx,
6197
+ insetExpanded,
6198
+ children
6199
+ }
6200
+ );
6201
+ const tree = /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ShellInsetProvider, { value: sidebar ? reportShellInset : null, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
6202
+ "div",
6203
+ {
6204
+ className: cn(
6205
+ "aui-app-shell relative flex h-dvh overflow-hidden bg-background",
6206
+ className
6207
+ ),
6208
+ style: studioChromeShellStyle,
6209
+ children: [
6210
+ sidebar,
6211
+ shellBody,
6212
+ hasChat && chatOpen ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6213
+ "div",
6214
+ {
6215
+ className: floatingPanelClass,
6216
+ style: {
6217
+ ["--app-shell-chat-width"]: chatWidth,
6218
+ ...chatHeight ? { height: chatHeight } : void 0
6219
+ },
6220
+ role: "dialog",
6221
+ "aria-label": typeof chatTriggerLabel === "string" ? chatTriggerLabel : "Assistant",
6222
+ children: chat
6223
+ }
6224
+ ) : null,
6225
+ hasChat && chatCollapsible && !chatOpen && !hideChatTrigger ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6226
+ "button",
6227
+ {
6228
+ type: "button",
6229
+ className: floatingTriggerClass,
6230
+ onClick: () => setChatOpen(true),
6231
+ "aria-expanded": false,
6232
+ children: chatTriggerLabel
6233
+ }
6234
+ ) : null
6235
+ ]
6236
+ }
6237
+ ) });
6238
+ if (!hasChat) {
6239
+ return tree;
6240
+ }
6241
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6242
+ AppShellChatProvider,
6243
+ {
6244
+ value: {
6245
+ open: chatOpen,
6246
+ setOpen: setChatOpen,
6247
+ toggle: toggleChat,
6248
+ collapsible: chatCollapsible
6249
+ },
6250
+ children: tree
6251
+ }
6252
+ );
6253
+ };
6254
+
6255
+ // src/app/layout/AppShellTopbar.tsx
6256
+ var import_jsx_runtime49 = require("react/jsx-runtime");
6257
+ var AppShellTopbar = ({
6258
+ start,
6259
+ actions,
6260
+ children,
6261
+ className
6262
+ }) => {
6263
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cn("aui-app-shell-topbar", appShellTopbarRowClass, className), children: [
6264
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
6265
+ start,
6266
+ children
6267
+ ] }),
6268
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "aui-app-shell-topbar-actions flex shrink-0 items-center gap-2", children: actions }) : null
6269
+ ] });
6270
+ };
6271
+
6272
+ // src/app/layout/AppShellChatTrigger.tsx
6273
+ var import_jsx_runtime50 = require("react/jsx-runtime");
6274
+ var floatingPositionClass = "fixed bottom-6 right-6 z-50 max-sm:bottom-4 max-sm:right-4";
6275
+ var AppShellChatTrigger = ({
6276
+ className,
6277
+ label = "Assistant",
6278
+ placement = "inline"
6279
+ }) => {
6280
+ const shellChat = useAppShellChat();
6281
+ if (!shellChat || shellChat.open) return null;
6282
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
6283
+ TimbalV2Button,
6284
+ {
6285
+ type: "button",
6286
+ variant: placement === "floating" ? "primary" : "secondary",
6287
+ size: "sm",
6288
+ className: cn(
6289
+ "aui-app-shell-chat-trigger",
6290
+ placement === "floating" && floatingPositionClass,
6291
+ placement === "floating" && "shadow-card-elevated",
6292
+ className
6293
+ ),
6294
+ onClick: () => shellChat.setOpen(true),
6295
+ "aria-expanded": false,
6296
+ children: label
6297
+ }
6298
+ );
6299
+ };
6300
+
6301
+ // src/app/layout/PageHeader.tsx
6302
+ var import_jsx_runtime51 = require("react/jsx-runtime");
6303
+ var PageHeader = ({
6304
+ title,
6305
+ description,
6306
+ actions,
6307
+ className
6308
+ }) => {
6309
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("header", { className: cn("aui-app-page-header", appPageHeaderClass, className), children: [
6310
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "min-w-0", children: [
6311
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }),
6312
+ description ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
6313
+ ] }),
6314
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "aui-app-page-header-actions flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
6315
+ ] });
6316
+ };
6317
+
6318
+ // src/app/layout/Page.tsx
6319
+ var import_jsx_runtime52 = require("react/jsx-runtime");
6320
+ var Page = ({
6321
+ children,
6322
+ breadcrumbs,
6323
+ className,
6324
+ ...headerProps
6325
+ }) => {
6326
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: cn("aui-app-page", appPageColumnClass, className), children: [
6327
+ breadcrumbs,
6328
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(PageHeader, { ...headerProps }),
6329
+ children
6330
+ ] });
6331
+ };
6332
+
6333
+ // src/app/layout/Section.tsx
6334
+ var import_jsx_runtime53 = require("react/jsx-runtime");
6335
+ var Section = ({
6336
+ title,
6337
+ description,
6338
+ children,
6339
+ className
6340
+ }) => {
6341
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("section", { className: cn("aui-app-section", appSectionClass, className), children: [
6342
+ title ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h2", { className: appSectionTitleClass, children: title }) : null,
6343
+ description ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: appSectionDescriptionClass, children: description }) : null,
6344
+ children
6345
+ ] });
6346
+ };
6347
+
6348
+ // src/app/copilot/app-copilot-context.tsx
6349
+ var import_react55 = require("react");
6350
+ var import_jsx_runtime54 = require("react/jsx-runtime");
6351
+ var AppCopilotContext = (0, import_react55.createContext)(null);
6352
+ var AppCopilotProvider = ({
6353
+ value,
6354
+ children
6355
+ }) => {
6356
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(AppCopilotContext.Provider, { value, children });
6357
+ };
6358
+ function useAppCopilotContext() {
6359
+ return (0, import_react55.useContext)(AppCopilotContext) ?? {};
6360
+ }
6361
+
6362
+ // src/app/chat/AppChatPanel.tsx
6363
+ var import_lucide_react15 = require("lucide-react");
6364
+ var import_jsx_runtime55 = require("react/jsx-runtime");
6365
+ var shellClass = "aui-app-chat-panel flex h-full min-h-0 flex-col overflow-hidden";
6366
+ var chromeClass = cn(
6367
+ "aui-app-chat-panel-chrome relative z-20 flex min-h-12 shrink-0 items-center justify-end",
6368
+ "bg-card/90 px-2 pt-3 pb-3 backdrop-blur-sm"
6369
+ );
6370
+ var closeButtonClass = cn(
6371
+ "aui-app-chat-panel-close flex size-8 shrink-0 items-center justify-center rounded-md",
6372
+ "text-muted-foreground transition-colors hover:bg-foreground/5 hover:text-foreground",
6373
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
6374
+ );
6375
+ var bodyClass = cn(
6376
+ "aui-app-chat-panel-body relative min-h-0 flex-1 overflow-hidden",
6377
+ "[&_.aui-thread-root]:h-full",
6378
+ "[&_.aui-thread-viewport]:scrollbar-thin",
6379
+ "[&_.aui-thread-viewport]:[scrollbar-color:var(--border)_transparent]",
6380
+ // Reserve the scrollbar gutter on BOTH edges so the composer + messages
6381
+ // stay symmetric (otherwise the right-side scrollbar adds a phantom inset).
6382
+ "[&_.aui-thread-viewport]:[scrollbar-gutter:stable_both-edges]",
6383
+ // Tighter symmetric horizontal inset for panel + composer
6384
+ "[&_.aui-thread-viewport]:!px-2",
6385
+ "[&_.aui-thread-viewport]:!pt-2",
6386
+ "[&_.aui-user-message-root]:!px-0",
6387
+ "[&_.aui-composer-input]:!px-2",
6388
+ "[&_.aui-composer-action-wrapper]:!px-2"
6389
+ );
6390
+ var AppChatPanel = ({
6391
+ className,
6392
+ workforceId,
6393
+ baseUrl,
6394
+ fetch: fetch2,
6395
+ attachments,
6396
+ attachmentsUploadUrl,
6397
+ attachmentsAccept,
6398
+ debug,
6399
+ welcome,
6400
+ suggestions,
6401
+ composerPlaceholder,
6402
+ components,
6403
+ artifacts,
6404
+ onArtifactEvent,
6405
+ ...rest
6406
+ }) => {
6407
+ const shellChat = useAppShellChat();
6408
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cn(shellClass, className), children: [
6409
+ shellChat?.collapsible ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: chromeClass, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6410
+ "button",
6411
+ {
6412
+ type: "button",
6413
+ className: closeButtonClass,
6414
+ onClick: () => shellChat.setOpen(false),
6415
+ "aria-label": "Close assistant",
6416
+ children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_lucide_react15.XIcon, { className: "size-4", "aria-hidden": true })
6417
+ }
6418
+ ) }) : null,
6419
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: bodyClass, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6420
+ TimbalRuntimeProvider,
6421
+ {
6422
+ workforceId,
6423
+ baseUrl,
6424
+ fetch: fetch2,
6425
+ attachments,
6426
+ attachmentsUploadUrl,
6427
+ attachmentsAccept,
6428
+ debug,
6429
+ children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6430
+ Thread,
6431
+ {
6432
+ variant: "panel",
6433
+ className: "aui-app-chat-panel-thread",
6434
+ welcome,
6435
+ suggestions,
6436
+ composerPlaceholder,
6437
+ components,
6438
+ artifacts,
6439
+ onArtifactEvent,
6440
+ ...rest
6441
+ }
6442
+ )
6443
+ }
6444
+ ) })
6445
+ ] });
6446
+ };
6447
+
6448
+ // src/app/surfaces/SurfaceCard.tsx
6449
+ var import_jsx_runtime56 = require("react/jsx-runtime");
6450
+ var SurfaceCard = ({ children, className }) => {
6451
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
6452
+ };
6453
+
6454
+ // src/app/surfaces/StatTile.tsx
6455
+ var import_jsx_runtime57 = require("react/jsx-runtime");
6456
+ var StatTile = ({ label, value, hint, className }) => {
6457
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: cn("aui-app-stat-tile", appStatTileClass, className), children: [
6458
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: appStatLabelClass, children: label }),
6459
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: appStatValueClass, children: value }),
6460
+ hint ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "text-xs text-muted-foreground", children: hint }) : null
6461
+ ] });
6462
+ };
6463
+
6464
+ // src/app/surfaces/EmptyState.tsx
6465
+ var import_jsx_runtime58 = require("react/jsx-runtime");
6466
+ var EmptyState2 = ({
6467
+ title,
6468
+ description,
6469
+ action,
6470
+ className
6471
+ }) => {
6472
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: cn("aui-app-empty-state", appEmptyStateClass, className), children: [
6473
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: appEmptyStateTitleClass, children: title }),
6474
+ description ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
6475
+ action
6476
+ ] });
6477
+ };
6478
+
6479
+ // src/app/surfaces/StatusBadge.tsx
6480
+ var import_jsx_runtime59 = require("react/jsx-runtime");
6481
+ var statusBadgeToneClass = {
6482
+ default: "bg-muted text-foreground",
6483
+ primary: "bg-primary/10 text-primary",
6484
+ success: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
6485
+ warn: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
6486
+ muted: "bg-muted/80 text-muted-foreground"
6487
+ };
6488
+ var StatusBadge = ({
6489
+ children,
6490
+ tone = "default",
6491
+ className
6492
+ }) => {
6493
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
6494
+ "span",
6495
+ {
6496
+ className: cn(
6497
+ "aui-app-status-badge inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
6498
+ statusBadgeToneClass[tone],
6499
+ className
6500
+ ),
6501
+ children
6502
+ }
6503
+ );
6504
+ };
6505
+
6506
+ // src/app/surfaces/AppConfirmDialog.tsx
6507
+ var import_jsx_runtime60 = require("react/jsx-runtime");
6508
+ var bodyClass2 = "flex flex-col gap-4 p-6";
6509
+ var titleClass = "pr-8";
6510
+ var actionsClass = "flex flex-wrap justify-end gap-2";
6511
+ var AppConfirmDialog = ({
6512
+ open,
6513
+ onOpenChange,
6514
+ title,
6515
+ description,
6516
+ confirmLabel = "Confirm",
6517
+ cancelLabel = "Cancel",
6518
+ onConfirm,
6519
+ destructive = false,
6520
+ className
6521
+ }) => {
6522
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Dialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
6523
+ DialogContent,
6524
+ {
6525
+ className: cn("gap-0 p-0 sm:max-w-md", className),
6526
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: bodyClass2, children: [
6527
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(DialogTitle, { className: titleClass, children: title }),
6528
+ description ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-sm text-muted-foreground", children: description }) : null,
6529
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: actionsClass, children: [
6530
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
6531
+ TimbalV2Button,
6532
+ {
6533
+ type: "button",
6534
+ variant: "secondary",
6535
+ size: "sm",
6536
+ onClick: () => onOpenChange(false),
6537
+ children: cancelLabel
6538
+ }
6539
+ ),
6540
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
6541
+ TimbalV2Button,
6542
+ {
6543
+ type: "button",
6544
+ variant: destructive ? "destructive" : "primary",
6545
+ size: "sm",
6546
+ onClick: () => {
6547
+ onConfirm();
6548
+ onOpenChange(false);
6549
+ },
6550
+ children: confirmLabel
6551
+ }
6552
+ )
6553
+ ] })
6554
+ ] })
6555
+ }
6556
+ ) });
6557
+ };
6558
+
6559
+ // src/app/navigation/SubNav.tsx
6560
+ var import_jsx_runtime61 = require("react/jsx-runtime");
6561
+ var SubNav = ({
6562
+ items,
6563
+ activeId,
6564
+ onChange,
6565
+ className,
6566
+ "aria-label": ariaLabel = "Section navigation",
6567
+ layoutId
6568
+ }) => {
6569
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
6570
+ PillSegmentedTabs,
6571
+ {
6572
+ value: activeId,
6573
+ onChange,
6574
+ tabs: items.map((item) => ({ key: item.id, label: item.label })),
6575
+ trackVariant: "flush",
6576
+ layoutId: layoutId ?? "app-sub-nav-segmented",
6577
+ "aria-label": ariaLabel
6578
+ }
6579
+ ) });
6580
+ };
6581
+
6582
+ // src/app/navigation/Breadcrumbs.tsx
6583
+ var import_jsx_runtime62 = require("react/jsx-runtime");
6584
+ var Breadcrumbs = ({ items, className }) => {
6585
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
6586
+ const isLast = index === items.length - 1;
6587
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("li", { className: "inline-flex items-center gap-1.5", children: [
6588
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
6589
+ isLast ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
6590
+ "button",
6591
+ {
6592
+ type: "button",
6593
+ className: appBreadcrumbLinkClass,
6594
+ onClick: item.onClick,
6595
+ children: item.label
6596
+ }
6597
+ )
6598
+ ] }, index);
6599
+ }) }) });
6600
+ };
6601
+
6602
+ // src/app/forms/Field.tsx
6603
+ var import_jsx_runtime63 = require("react/jsx-runtime");
6604
+ var Field = ({
6605
+ label,
6606
+ hint,
6607
+ error,
6608
+ children,
6609
+ className,
6610
+ htmlFor
6611
+ }) => {
6612
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: cn("aui-app-field", appFieldClass, className), children: [
6613
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("label", { className: appFieldLabelClass, htmlFor, children: label }),
6614
+ children,
6615
+ hint && !error ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: appFieldHintClass, children: hint }) : null,
6616
+ error ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
6617
+ ] });
6618
+ };
6619
+ var FieldInput = ({
6620
+ label,
6621
+ hint,
6622
+ error,
6623
+ fieldClassName,
6624
+ className,
6625
+ id,
6626
+ ...inputProps
6627
+ }) => {
6628
+ const inputId = id ?? inputProps.name;
6629
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
6630
+ Field,
6631
+ {
6632
+ label,
6633
+ hint,
6634
+ error,
6635
+ htmlFor: inputId,
6636
+ className: fieldClassName,
6637
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
6638
+ "input",
6639
+ {
6640
+ id: inputId,
6641
+ className: cn(appInputClass, className),
6642
+ "aria-invalid": error ? true : void 0,
6643
+ ...inputProps
6644
+ }
6645
+ )
6646
+ }
6647
+ );
6648
+ };
6649
+
6650
+ // src/app/forms/FieldTextarea.tsx
6651
+ var import_jsx_runtime64 = require("react/jsx-runtime");
6652
+ var textareaClass = cn(
6653
+ appInputClass,
6654
+ "min-h-[5.5rem] resize-y py-2.5 leading-relaxed"
6655
+ );
6656
+ var FieldTextarea = ({
6657
+ label,
6658
+ hint,
6659
+ error,
6660
+ fieldClassName,
6661
+ className,
6662
+ id,
6663
+ ...props
6664
+ }) => {
6665
+ const textareaId = id ?? props.name;
6666
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
6667
+ Field,
6668
+ {
6669
+ label,
6670
+ hint,
6671
+ error,
6672
+ htmlFor: textareaId,
6673
+ className: fieldClassName,
6674
+ children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
6675
+ "textarea",
6676
+ {
6677
+ id: textareaId,
6678
+ className: cn(textareaClass, className),
6679
+ "aria-invalid": error ? true : void 0,
6680
+ ...props
6681
+ }
6682
+ )
6683
+ }
6684
+ );
6685
+ };
6686
+
6687
+ // src/app/forms/FieldSelect.tsx
6688
+ var import_lucide_react16 = require("lucide-react");
6689
+ var import_jsx_runtime65 = require("react/jsx-runtime");
6690
+ var selectWrapClass = "relative";
6691
+ var selectClass = cn(
6692
+ appInputClass,
6693
+ "appearance-none pr-9"
6694
+ );
6695
+ var FieldSelect = ({
6696
+ label,
6697
+ hint,
6698
+ error,
6699
+ fieldClassName,
6700
+ className,
6701
+ children,
6702
+ id,
6703
+ ...props
6704
+ }) => {
6705
+ const selectId = id ?? props.name;
6706
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
6707
+ Field,
6708
+ {
6709
+ label,
6710
+ hint,
6711
+ error,
6712
+ htmlFor: selectId,
6713
+ className: fieldClassName,
6714
+ children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: selectWrapClass, children: [
6715
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
6716
+ "select",
6717
+ {
6718
+ id: selectId,
6719
+ className: cn(selectClass, className),
6720
+ "aria-invalid": error ? true : void 0,
6721
+ ...props,
6722
+ children
6723
+ }
6724
+ ),
6725
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
6726
+ import_lucide_react16.ChevronDownIcon,
6727
+ {
6728
+ className: "pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-muted-foreground",
6729
+ "aria-hidden": true
6730
+ }
6731
+ )
6732
+ ] })
6733
+ }
6734
+ );
6735
+ };
6736
+
6737
+ // src/app/forms/FieldSwitch.tsx
6738
+ var import_jsx_runtime66 = require("react/jsx-runtime");
6739
+ var trackClass = cn(
6740
+ "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
6741
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-foreground/10",
6742
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
6743
+ TIMBAL_V2_SWITCH_TRACK_OFF,
6744
+ "peer-checked:border-foreground/15 peer-checked:from-primary-fill-from peer-checked:to-primary-fill-to peer-checked:shadow-card",
6745
+ "peer-checked:[&>span]:translate-x-4"
6746
+ );
6747
+ var thumbClass = cn(
6748
+ "pointer-events-none inline-block size-4 shrink-0 translate-x-0.5 rounded-full transition-transform",
6749
+ TIMBAL_V2_SWITCH_THUMB
6750
+ );
6751
+ var FieldSwitch = ({
6752
+ label,
6753
+ description,
6754
+ className,
6755
+ id,
6756
+ ...props
6757
+ }) => {
6758
+ const inputId = id ?? props.name ?? "switch";
6759
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
6760
+ "label",
6761
+ {
6762
+ className: cn(
6763
+ "aui-app-field-switch flex cursor-pointer items-start gap-3",
6764
+ className
6765
+ ),
6766
+ htmlFor: inputId,
6767
+ children: [
6768
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "relative mt-0.5", children: [
6769
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
6770
+ "input",
6771
+ {
6772
+ id: inputId,
6773
+ type: "checkbox",
6774
+ role: "switch",
6775
+ className: "peer sr-only",
6776
+ ...props
6777
+ }
6778
+ ),
6779
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: thumbClass }) })
6780
+ ] }),
6781
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
6782
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "text-sm font-medium text-foreground", children: label }),
6783
+ description ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "text-xs text-muted-foreground", children: description }) : null
6784
+ ] })
6785
+ ]
6786
+ }
6787
+ );
6788
+ };
6789
+
6790
+ // src/app/forms/SearchInput.tsx
6791
+ var import_lucide_react17 = require("lucide-react");
6792
+ var import_jsx_runtime67 = require("react/jsx-runtime");
6793
+ var SearchInput = ({
6794
+ className,
6795
+ placeholder = "Search\u2026",
6796
+ ...props
6797
+ }) => {
6798
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
6799
+ "label",
6800
+ {
6801
+ className: cn(
6802
+ "aui-app-search-input inline-flex min-w-[12rem] items-center gap-2",
6803
+ appSearchInputClass,
6804
+ className
6805
+ ),
6806
+ children: [
6807
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react17.SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
6808
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
6809
+ "input",
6810
+ {
6811
+ type: "search",
6812
+ placeholder,
6813
+ className: "min-w-0 flex-1 border-0 bg-transparent text-sm outline-none placeholder:text-muted-foreground/70",
6814
+ ...props
6815
+ }
6816
+ )
6817
+ ]
6818
+ }
6819
+ );
6820
+ };
6821
+
6822
+ // src/app/forms/FormSection.tsx
6823
+ var import_jsx_runtime68 = require("react/jsx-runtime");
6824
+ var FormSection = ({ title, children, className }) => {
6825
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("fieldset", { className: cn("aui-app-form-section", appSectionClass, "border-0 p-0", className), children: [
6826
+ title ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
6827
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "flex flex-col gap-4", children })
6828
+ ] });
6829
+ };
6830
+
6831
+ // src/app/data/FilterBar.tsx
6832
+ var import_jsx_runtime69 = require("react/jsx-runtime");
6833
+ var FilterBar = ({ children, className }) => {
6834
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6835
+ "div",
6836
+ {
6837
+ className: cn("aui-app-filter-bar", appFilterBarClass, className),
6838
+ role: "toolbar",
6839
+ "aria-label": "Filters",
6840
+ children
6841
+ }
6842
+ );
6843
+ };
6844
+
6845
+ // src/app/data/DataTable.tsx
6846
+ var import_react56 = require("react");
6847
+ var import_lucide_react18 = require("lucide-react");
6848
+ var import_jsx_runtime70 = require("react/jsx-runtime");
6849
+ var shellClass2 = "overflow-hidden rounded-xl border border-border bg-card shadow-card";
6850
+ var tableClass = "w-full border-collapse bg-transparent text-sm";
6851
+ var headCellClass = "border-b border-border/60 bg-transparent px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-muted-foreground";
6852
+ var bodyCellClass = "border-b border-border/40 bg-transparent px-4 py-2.5 text-foreground";
6853
+ var rowClass = "bg-transparent transition-colors hover:bg-foreground/[0.03] data-[clickable=true]:cursor-pointer";
6854
+ var footCellClass = "border-t border-border/60 bg-transparent px-4 py-2.5 text-xs text-muted-foreground";
6855
+ var footInnerClass = "flex flex-wrap items-center gap-2";
6856
+ var emptyCellClass = "bg-transparent px-4 py-10 text-center text-sm text-muted-foreground";
6857
+ var sortButtonClass = "group inline-flex min-w-0 items-center gap-1.5 rounded-md -mx-1 px-1 py-0.5 text-left font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10";
6858
+ var stickyHeadClass = "sticky top-0 z-[1] bg-card/95 shadow-[0_1px_0_0_hsl(var(--border)/0.5)] backdrop-blur-sm [&_th]:bg-card/95";
6859
+ var alignClass = {
6860
+ left: "text-left",
6861
+ center: "text-center",
6862
+ right: "text-right"
6863
+ };
6864
+ function compareSortValues(a, b) {
6865
+ if (a == null && b == null) return 0;
6866
+ if (a == null) return 1;
6867
+ if (b == null) return -1;
6868
+ if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
6869
+ if (typeof a === "number" && typeof b === "number") return a - b;
6870
+ if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
6871
+ return String(a).localeCompare(String(b), void 0, { sensitivity: "base" });
6872
+ }
6873
+ function nextSort(current, columnId) {
6874
+ if (current?.columnId !== columnId) {
6875
+ return { columnId, direction: "asc" };
6876
+ }
6877
+ if (current.direction === "asc") {
6878
+ return { columnId, direction: "desc" };
6879
+ }
6880
+ return null;
6881
+ }
6882
+ function SortIndicator({
6883
+ active,
6884
+ direction
6885
+ }) {
6886
+ const iconClass = "size-3.5 shrink-0 opacity-60 group-hover:opacity-100";
6887
+ if (!active) {
6888
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(import_lucide_react18.ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
6889
+ }
6890
+ if (direction === "desc") {
6891
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(import_lucide_react18.ArrowDownIcon, { className: iconClass, "aria-hidden": true });
6892
+ }
6893
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(import_lucide_react18.ArrowUpIcon, { className: iconClass, "aria-hidden": true });
6894
+ }
6895
+ function DataTable({
6896
+ columns,
6897
+ rows,
6898
+ getRowKey,
6899
+ emptyTitle = "No data",
6900
+ emptyDescription,
6901
+ emptyMode = "replace",
6902
+ className,
6903
+ sort: sortProp,
6904
+ defaultSort = null,
6905
+ onSortChange,
6906
+ showRowCount = false,
6907
+ rowCountLabel,
6908
+ footer,
6909
+ onRowClick,
6910
+ stickyHeader = false,
6911
+ dense = false,
6912
+ caption
6913
+ }) {
6914
+ const [uncontrolledSort, setUncontrolledSort] = (0, import_react56.useState)(
6915
+ defaultSort
6916
+ );
6917
+ const isSortControlled = sortProp !== void 0;
6918
+ const sort = isSortControlled ? sortProp : uncontrolledSort;
6919
+ const setSort = (next) => {
6920
+ if (!isSortControlled) {
6921
+ setUncontrolledSort(next);
6922
+ }
6923
+ onSortChange?.(next);
6924
+ };
6925
+ const sortedRows = (0, import_react56.useMemo)(() => {
6926
+ if (!sort) return rows;
6927
+ const column = columns.find((col) => col.id === sort.columnId);
6928
+ if (!column?.sortable) return rows;
6929
+ const getValue = column.sortValue ?? ((row) => {
6930
+ const rendered = column.cell(row);
6931
+ if (rendered === null || rendered === void 0 || typeof rendered === "string" || typeof rendered === "number" || typeof rendered === "boolean") {
6932
+ return rendered;
6933
+ }
6934
+ return String(rendered);
6935
+ });
6936
+ return [...rows].sort((a, b) => {
6937
+ const cmp = compareSortValues(getValue(a), getValue(b));
6938
+ return sort.direction === "asc" ? cmp : -cmp;
6939
+ });
6940
+ }, [columns, rows, sort]);
6941
+ const cellPad = dense ? "px-3 py-2" : void 0;
6942
+ const headPad = dense ? "px-3 py-2" : void 0;
6943
+ if (rows.length === 0 && emptyMode === "replace") {
6944
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(EmptyState2, { title: emptyTitle, description: emptyDescription, className });
6945
+ }
6946
+ const rowCountText = rowCountLabel?.(sortedRows.length) ?? `${sortedRows.length} row${sortedRows.length === 1 ? "" : "s"}`;
6947
+ const hasFoot = Boolean((showRowCount || footer) && sortedRows.length > 0);
6948
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("table", { className: tableClass, children: [
6949
+ caption ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("caption", { className: "sr-only", children: caption }) : null,
6950
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("tr", { children: columns.map((col) => {
6951
+ const isSorted = sort?.columnId === col.id;
6952
+ const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
6953
+ const headerContent = col.sortable ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
6954
+ "button",
6955
+ {
6956
+ type: "button",
6957
+ className: sortButtonClass,
6958
+ onClick: () => setSort(nextSort(sort, col.id)),
6959
+ children: [
6960
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "truncate", children: col.header }),
6961
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
6962
+ ]
6963
+ }
6964
+ ) : col.header;
6965
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6966
+ "th",
6967
+ {
6968
+ scope: "col",
6969
+ "aria-sort": ariaSort,
6970
+ className: cn(
6971
+ headCellClass,
6972
+ headPad,
6973
+ col.align && alignClass[col.align],
6974
+ col.headerClassName
6975
+ ),
6976
+ children: headerContent
6977
+ },
6978
+ col.id
6979
+ );
6980
+ }) }) }),
6981
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: sortedRows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("td", { colSpan: columns.length, className: emptyCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
6982
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { className: "font-medium text-foreground", children: emptyTitle }),
6983
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
6984
+ ] }) }) }) : sortedRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6985
+ "tr",
6986
+ {
6987
+ className: rowClass,
6988
+ "data-clickable": onRowClick ? "true" : void 0,
6989
+ onClick: onRowClick ? () => onRowClick(row) : void 0,
6990
+ onKeyDown: onRowClick ? (event) => {
6991
+ if (event.key === "Enter" || event.key === " ") {
6992
+ event.preventDefault();
6993
+ onRowClick(row);
6994
+ }
6995
+ } : void 0,
6996
+ tabIndex: onRowClick ? 0 : void 0,
6997
+ role: onRowClick ? "button" : void 0,
6998
+ children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6999
+ "td",
7000
+ {
7001
+ className: cn(
7002
+ bodyCellClass,
7003
+ cellPad,
7004
+ col.align && alignClass[col.align],
7005
+ col.className
7006
+ ),
7007
+ children: col.cell(row)
7008
+ },
7009
+ col.id
7010
+ ))
7011
+ },
7012
+ getRowKey(row)
7013
+ )) }),
7014
+ hasFoot ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("tfoot", { children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("td", { colSpan: columns.length, className: footCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
7015
+ "div",
7016
+ {
7017
+ className: cn(
7018
+ footInnerClass,
7019
+ showRowCount && footer ? "justify-between" : "justify-start"
7020
+ ),
7021
+ children: [
7022
+ showRowCount ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { children: rowCountText }) : null,
7023
+ footer
7024
+ ]
7025
+ }
7026
+ ) }) }) }) : null
7027
+ ] }) }) });
7028
+ }
7029
+
7030
+ // src/app/data/ChartPanel.tsx
7031
+ var import_jsx_runtime71 = require("react/jsx-runtime");
7032
+ var chartEmbedClass = "[&_.aui-artifact-root]:my-0 [&_.aui-artifact-root]:rounded-none [&_.aui-artifact-root]:border-0 [&_.aui-artifact-root]:bg-transparent [&_.aui-artifact-root]:shadow-none";
7033
+ var ChartPanel = ({
7034
+ title,
7035
+ artifact,
7036
+ children,
7037
+ actions,
7038
+ className
7039
+ }) => {
7040
+ const body = children ?? (artifact ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: chartEmbedClass, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ChartArtifactView, { artifact }) }) : null);
7041
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: cn("aui-app-chart-panel", appChartPanelClass, className), children: [
7042
+ title || actions ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
7043
+ title ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("h3", { className: appChartPanelTitleClass, children: title }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", {}),
7044
+ actions
7045
+ ] }) : null,
7046
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "min-h-[12rem] w-full", children: body })
7047
+ ] });
7048
+ };
7049
+
7050
+ // src/artifacts/agent-instructions.ts
5623
7051
  var ARTIFACT_AGENT_INSTRUCTIONS = `
5624
7052
  ## Rich artifacts (Timbal chat UI)
5625
7053
 
@@ -5746,8 +7174,8 @@ When you call a tool that returns an artifact (\`make_chart\`, \`ask_question\`,
5746
7174
  `.trim();
5747
7175
 
5748
7176
  // src/auth/guard.tsx
5749
- var import_lucide_react15 = require("lucide-react");
5750
- var import_jsx_runtime46 = require("react/jsx-runtime");
7177
+ var import_lucide_react19 = require("lucide-react");
7178
+ var import_jsx_runtime72 = require("react/jsx-runtime");
5751
7179
  var AuthGuard = ({
5752
7180
  children,
5753
7181
  requireAuth = false,
@@ -5758,7 +7186,7 @@ var AuthGuard = ({
5758
7186
  return children;
5759
7187
  }
5760
7188
  if (loading) {
5761
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react15.Loader2, { className: "w-8 h-8 animate-spin" }) });
7189
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react19.Loader2, { className: "w-8 h-8 animate-spin" }) });
5762
7190
  }
5763
7191
  if (requireAuth && !isAuthenticated && !isEmbedded) {
5764
7192
  const returnTo = encodeURIComponent(
@@ -5771,12 +7199,18 @@ var AuthGuard = ({
5771
7199
  };
5772
7200
 
5773
7201
  // src/index.ts
5774
- var import_react46 = require("@assistant-ui/react");
7202
+ var import_react57 = require("@assistant-ui/react");
5775
7203
  // Annotate the CommonJS export names for ESM import in node:
5776
7204
  0 && (module.exports = {
5777
7205
  ARTIFACT_AGENT_INSTRUCTIONS,
5778
7206
  ARTIFACT_FENCE_LANGUAGES,
5779
7207
  ActionBarPrimitive,
7208
+ AppChatPanel,
7209
+ AppConfirmDialog,
7210
+ AppCopilotProvider,
7211
+ AppShell,
7212
+ AppShellChatTrigger,
7213
+ AppShellTopbar,
5780
7214
  ArtifactCard,
5781
7215
  ArtifactRegistryProvider,
5782
7216
  ArtifactView,
@@ -5786,11 +7220,14 @@ var import_react46 = require("@assistant-ui/react");
5786
7220
  Avatar,
5787
7221
  AvatarFallback,
5788
7222
  AvatarImage,
7223
+ Breadcrumbs,
5789
7224
  Button,
5790
7225
  ChartArtifactView,
7226
+ ChartPanel,
5791
7227
  Composer,
5792
7228
  ComposerPrimitive,
5793
7229
  DEFAULT_UPLOAD_ACCEPT,
7230
+ DataTable,
5794
7231
  Dialog,
5795
7232
  DialogClose,
5796
7233
  DialogContent,
@@ -5798,17 +7235,38 @@ var import_react46 = require("@assistant-ui/react");
5798
7235
  DialogPortal,
5799
7236
  DialogTitle,
5800
7237
  DialogTrigger,
7238
+ EmptyState,
7239
+ Field,
7240
+ FieldInput,
7241
+ FieldSelect,
7242
+ FieldSwitch,
7243
+ FieldTextarea,
7244
+ FilterBar,
7245
+ FormSection,
5801
7246
  HtmlArtifactView,
5802
7247
  JsonArtifactView,
5803
7248
  MarkdownText,
7249
+ MemoPillSegmentedTabs,
5804
7250
  MessagePrimitive,
5805
7251
  ModeToggle,
7252
+ Page,
7253
+ PageHeader,
7254
+ PillSegmentedTabs,
5806
7255
  QuestionArtifactView,
7256
+ STUDIO_NAV_MODE,
7257
+ SearchInput,
7258
+ Section,
5807
7259
  SessionProvider,
5808
7260
  Shimmer,
7261
+ StatTile,
7262
+ StatusBadge,
7263
+ StudioModeSwitch,
5809
7264
  StudioSidebar,
5810
7265
  StudioWelcome,
7266
+ SubNav,
5811
7267
  Suggestions,
7268
+ SurfaceCard,
7269
+ THREAD_DEFAULT_MAX_WIDTH,
5812
7270
  TableArtifactView,
5813
7271
  Thread,
5814
7272
  ThreadPrimitive,
@@ -5829,6 +7287,8 @@ var import_react46 = require("@assistant-ui/react");
5829
7287
  UiEventProvider,
5830
7288
  UiNodeView,
5831
7289
  WorkforceSelector,
7290
+ assistantMessageContentClass,
7291
+ assistantMessageRootClass,
5832
7292
  authFetch,
5833
7293
  clearTokens,
5834
7294
  cn,
@@ -5852,6 +7312,9 @@ var import_react46 = require("@assistant-ui/react");
5852
7312
  setPath,
5853
7313
  setRefreshToken,
5854
7314
  splitMarkdownByArtifacts,
7315
+ threadMessageColumnClass,
7316
+ useAppCopilotContext,
7317
+ useAppShellChat,
5855
7318
  useArtifactRegistry,
5856
7319
  useComposerRuntime,
5857
7320
  useMessageRuntime,
@@ -5867,5 +7330,6 @@ var import_react46 = require("@assistant-ui/react");
5867
7330
  useUiDispatch,
5868
7331
  useUiEventEmitter,
5869
7332
  useUiState,
5870
- useWorkforces
7333
+ useWorkforces,
7334
+ userMessageRootClass
5871
7335
  });