@lukeashford/aurelius 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +888 -192
- package/dist/index.d.ts +888 -192
- package/dist/index.js +2236 -355
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2147 -284
- package/dist/index.mjs.map +1 -1
- package/dist/styles/theme.css +20 -2
- package/llms.md +29 -6
- package/package.json +5 -3
- package/scripts/eslint.mjs +10 -1
package/dist/index.js
CHANGED
|
@@ -36,22 +36,31 @@ __export(index_exports, {
|
|
|
36
36
|
AccordionTrigger: () => AccordionTrigger,
|
|
37
37
|
Alert: () => Alert,
|
|
38
38
|
AlertDialog: () => AlertDialog,
|
|
39
|
+
ArtifactsPanel: () => ArtifactsPanel,
|
|
40
|
+
ArtifactsPanelToggle: () => ArtifactsPanelToggle,
|
|
41
|
+
AttachmentPreview: () => AttachmentPreview,
|
|
39
42
|
Avatar: () => Avatar,
|
|
40
43
|
Badge: () => Badge,
|
|
44
|
+
BranchNavigator: () => BranchNavigator,
|
|
41
45
|
BrandIcon: () => BrandIcon,
|
|
42
46
|
Breadcrumb: () => Breadcrumb,
|
|
43
47
|
BreadcrumbItem: () => BreadcrumbItem,
|
|
44
48
|
BreadcrumbLink: () => BreadcrumbLink,
|
|
45
49
|
Button: () => Button,
|
|
46
50
|
Card: () => Card,
|
|
47
|
-
|
|
51
|
+
ChatInput: () => ChatInput,
|
|
52
|
+
ChatInterface: () => ChatInterface,
|
|
53
|
+
ChatView: () => ChatView,
|
|
48
54
|
Checkbox: () => Checkbox,
|
|
49
55
|
Col: () => Col,
|
|
56
|
+
CollapsedSidebarToggle: () => CollapsedSidebarToggle,
|
|
50
57
|
ColorSwatch: () => ColorSwatch,
|
|
51
58
|
ConfirmDialog: () => ConfirmDialog,
|
|
52
59
|
Container: () => Container,
|
|
60
|
+
ConversationSidebar: () => ConversationSidebar,
|
|
53
61
|
Divider: () => Divider,
|
|
54
62
|
Drawer: () => Drawer,
|
|
63
|
+
FileChip: () => FileChip,
|
|
55
64
|
HelperText: () => HelperText,
|
|
56
65
|
ImageCard: () => ImageCard,
|
|
57
66
|
Input: () => Input,
|
|
@@ -74,6 +83,7 @@ __export(index_exports, {
|
|
|
74
83
|
MenuSeparator: () => MenuSeparator,
|
|
75
84
|
MenuTrigger: () => MenuTrigger,
|
|
76
85
|
Message: () => Message,
|
|
86
|
+
MessageActions: () => MessageActions,
|
|
77
87
|
Modal: () => Modal,
|
|
78
88
|
Navbar: () => Navbar,
|
|
79
89
|
NavbarBrand: () => NavbarBrand,
|
|
@@ -109,9 +119,24 @@ __export(index_exports, {
|
|
|
109
119
|
TableRow: () => TableRow,
|
|
110
120
|
Tabs: () => Tabs,
|
|
111
121
|
Textarea: () => Textarea,
|
|
122
|
+
ThinkingIndicator: () => ThinkingIndicator,
|
|
112
123
|
ToastProvider: () => ToastProvider,
|
|
113
124
|
Tooltip: () => Tooltip,
|
|
114
125
|
VideoCard: () => VideoCard,
|
|
126
|
+
addMessageToTree: () => addMessageToTree,
|
|
127
|
+
createEmptyTree: () => createEmptyTree,
|
|
128
|
+
createPreviewUrl: () => createPreviewUrl,
|
|
129
|
+
generateId: () => generateId,
|
|
130
|
+
getActivePathMessages: () => getActivePathMessages,
|
|
131
|
+
getSiblingInfo: () => getSiblingInfo,
|
|
132
|
+
isBranchPoint: () => isBranchPoint,
|
|
133
|
+
isImageFile: () => isImageFile,
|
|
134
|
+
messagesToTree: () => messagesToTree,
|
|
135
|
+
revokePreviewUrl: () => revokePreviewUrl,
|
|
136
|
+
switchBranch: () => switchBranch,
|
|
137
|
+
updateNodeContent: () => updateNodeContent,
|
|
138
|
+
useArtifactParser: () => useArtifactParser,
|
|
139
|
+
useScrollAnchor: () => useScrollAnchor,
|
|
115
140
|
useToast: () => useToast,
|
|
116
141
|
version: () => version
|
|
117
142
|
});
|
|
@@ -979,7 +1004,7 @@ var Tooltip = ({ content, children, open = false, side = "top" }) => {
|
|
|
979
1004
|
{
|
|
980
1005
|
role: "tooltip",
|
|
981
1006
|
className: cx(
|
|
982
|
-
"pointer-events-none absolute z-50 whitespace-nowrap
|
|
1007
|
+
"pointer-events-none absolute z-50 whitespace-nowrap border border-ash bg-graphite px-3 py-1.5 text-sm text-white shadow-lg transition-opacity duration-200 ease-out",
|
|
983
1008
|
open ? "opacity-100" : "opacity-0",
|
|
984
1009
|
side === "top" && "left-1/2 -translate-x-1/2 -top-2 -translate-y-full",
|
|
985
1010
|
side === "bottom" && "left-1/2 -translate-x-1/2 -bottom-2 translate-y-full",
|
|
@@ -1189,11 +1214,152 @@ var ListSubheader = import_react13.default.forwardRef(
|
|
|
1189
1214
|
);
|
|
1190
1215
|
ListSubheader.displayName = "ListSubheader";
|
|
1191
1216
|
|
|
1192
|
-
// src/components/
|
|
1217
|
+
// src/components/FileChip.tsx
|
|
1193
1218
|
var import_react14 = __toESM(require("react"));
|
|
1194
|
-
var
|
|
1195
|
-
|
|
1219
|
+
var import_lucide_react2 = require("lucide-react");
|
|
1220
|
+
function formatBytes(bytes) {
|
|
1221
|
+
if (bytes === 0) return "0 B";
|
|
1222
|
+
const k = 1024;
|
|
1223
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
1224
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
1225
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
1226
|
+
}
|
|
1227
|
+
function getFileIcon(type) {
|
|
1228
|
+
if (!type) return import_lucide_react2.File;
|
|
1229
|
+
if (type.startsWith("image/")) return import_lucide_react2.FileImage;
|
|
1230
|
+
if (type.startsWith("video/")) return import_lucide_react2.FileVideo;
|
|
1231
|
+
if (type.startsWith("audio/")) return import_lucide_react2.FileAudio;
|
|
1232
|
+
if (type.startsWith("text/")) return import_lucide_react2.FileText;
|
|
1233
|
+
if (type.includes("javascript") || type.includes("typescript") || type.includes("json") || type.includes("xml")) {
|
|
1234
|
+
return import_lucide_react2.FileCode;
|
|
1235
|
+
}
|
|
1236
|
+
if (type.includes("zip") || type.includes("rar") || type.includes("tar") || type.includes("gz")) {
|
|
1237
|
+
return import_lucide_react2.FileArchive;
|
|
1238
|
+
}
|
|
1239
|
+
return import_lucide_react2.File;
|
|
1240
|
+
}
|
|
1241
|
+
var statusStyles = {
|
|
1242
|
+
pending: "border-silver/30",
|
|
1243
|
+
uploading: "border-gold/50",
|
|
1244
|
+
complete: "border-success/50",
|
|
1245
|
+
error: "border-error/50"
|
|
1246
|
+
};
|
|
1247
|
+
var FileChip = import_react14.default.forwardRef(
|
|
1248
|
+
({
|
|
1249
|
+
name,
|
|
1250
|
+
size,
|
|
1251
|
+
type,
|
|
1252
|
+
status = "complete",
|
|
1253
|
+
previewUrl,
|
|
1254
|
+
onRemove,
|
|
1255
|
+
removable = true,
|
|
1256
|
+
error,
|
|
1257
|
+
className,
|
|
1258
|
+
...rest
|
|
1259
|
+
}, ref) => {
|
|
1260
|
+
const Icon = getFileIcon(type);
|
|
1261
|
+
const isImage = type?.startsWith("image/");
|
|
1262
|
+
const showPreview = isImage && previewUrl;
|
|
1196
1263
|
return /* @__PURE__ */ import_react14.default.createElement(
|
|
1264
|
+
"div",
|
|
1265
|
+
{
|
|
1266
|
+
ref,
|
|
1267
|
+
className: cx(
|
|
1268
|
+
"group relative inline-flex items-center gap-2 px-2 py-1.5",
|
|
1269
|
+
"bg-charcoal border text-sm text-white",
|
|
1270
|
+
"transition-colors duration-150",
|
|
1271
|
+
statusStyles[status],
|
|
1272
|
+
status === "error" && "bg-error/10",
|
|
1273
|
+
className
|
|
1274
|
+
),
|
|
1275
|
+
role: "listitem",
|
|
1276
|
+
...rest
|
|
1277
|
+
},
|
|
1278
|
+
showPreview ? /* @__PURE__ */ import_react14.default.createElement("div", { className: "w-8 h-8 flex-shrink-0 overflow-hidden bg-slate" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1279
|
+
"img",
|
|
1280
|
+
{
|
|
1281
|
+
src: previewUrl,
|
|
1282
|
+
alt: "",
|
|
1283
|
+
className: "w-full h-full object-cover"
|
|
1284
|
+
}
|
|
1285
|
+
)) : /* @__PURE__ */ import_react14.default.createElement(Icon, { className: cx(
|
|
1286
|
+
"w-4 h-4 flex-shrink-0",
|
|
1287
|
+
status === "error" ? "text-error" : "text-silver"
|
|
1288
|
+
) }),
|
|
1289
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-col min-w-0 flex-1" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "truncate max-w-40", title: name }, name), size !== void 0 && status !== "error" && /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs text-silver/60" }, formatBytes(size)), status === "error" && error && /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs text-error truncate", title: error }, error)),
|
|
1290
|
+
status === "uploading" && /* @__PURE__ */ import_react14.default.createElement(import_lucide_react2.Loader2, { className: "w-3.5 h-3.5 text-gold animate-spin flex-shrink-0" }),
|
|
1291
|
+
status === "pending" && /* @__PURE__ */ import_react14.default.createElement("div", { className: "w-2 h-2 rounded-full bg-silver/50 flex-shrink-0" }),
|
|
1292
|
+
removable && onRemove && /* @__PURE__ */ import_react14.default.createElement(
|
|
1293
|
+
"button",
|
|
1294
|
+
{
|
|
1295
|
+
type: "button",
|
|
1296
|
+
onClick: (e) => {
|
|
1297
|
+
e.stopPropagation();
|
|
1298
|
+
onRemove();
|
|
1299
|
+
},
|
|
1300
|
+
className: cx(
|
|
1301
|
+
"p-0.5 text-silver/40 hover:text-white transition-colors",
|
|
1302
|
+
"hover:bg-white/10",
|
|
1303
|
+
"opacity-0 group-hover:opacity-100",
|
|
1304
|
+
"focus:opacity-100"
|
|
1305
|
+
),
|
|
1306
|
+
"aria-label": `Remove ${name}`
|
|
1307
|
+
},
|
|
1308
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react2.X, { className: "w-3.5 h-3.5" })
|
|
1309
|
+
)
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
);
|
|
1313
|
+
FileChip.displayName = "FileChip";
|
|
1314
|
+
|
|
1315
|
+
// src/components/AttachmentPreview.tsx
|
|
1316
|
+
var import_react15 = __toESM(require("react"));
|
|
1317
|
+
var AttachmentPreview = import_react15.default.forwardRef(
|
|
1318
|
+
({
|
|
1319
|
+
attachments,
|
|
1320
|
+
onRemove,
|
|
1321
|
+
removable = true,
|
|
1322
|
+
maxVisible,
|
|
1323
|
+
className,
|
|
1324
|
+
...rest
|
|
1325
|
+
}, ref) => {
|
|
1326
|
+
if (attachments.length === 0) return null;
|
|
1327
|
+
const visibleAttachments = maxVisible && maxVisible > 0 ? attachments.slice(0, maxVisible) : attachments;
|
|
1328
|
+
const hiddenCount = maxVisible && maxVisible > 0 ? Math.max(0, attachments.length - maxVisible) : 0;
|
|
1329
|
+
return /* @__PURE__ */ import_react15.default.createElement(
|
|
1330
|
+
"div",
|
|
1331
|
+
{
|
|
1332
|
+
ref,
|
|
1333
|
+
className: cx("flex flex-wrap gap-2", className),
|
|
1334
|
+
role: "list",
|
|
1335
|
+
"aria-label": "Attached files",
|
|
1336
|
+
...rest
|
|
1337
|
+
},
|
|
1338
|
+
visibleAttachments.map((attachment) => /* @__PURE__ */ import_react15.default.createElement(
|
|
1339
|
+
FileChip,
|
|
1340
|
+
{
|
|
1341
|
+
key: attachment.id,
|
|
1342
|
+
name: attachment.file.name,
|
|
1343
|
+
size: attachment.file.size,
|
|
1344
|
+
type: attachment.file.type,
|
|
1345
|
+
status: attachment.status,
|
|
1346
|
+
previewUrl: attachment.previewUrl,
|
|
1347
|
+
error: attachment.error,
|
|
1348
|
+
removable,
|
|
1349
|
+
onRemove: onRemove ? () => onRemove(attachment.id) : void 0
|
|
1350
|
+
}
|
|
1351
|
+
)),
|
|
1352
|
+
hiddenCount > 0 && /* @__PURE__ */ import_react15.default.createElement("div", { className: "inline-flex items-center px-2 py-1.5 bg-charcoal border border-silver/30 text-sm text-silver" }, "+", hiddenCount, " more")
|
|
1353
|
+
);
|
|
1354
|
+
}
|
|
1355
|
+
);
|
|
1356
|
+
AttachmentPreview.displayName = "AttachmentPreview";
|
|
1357
|
+
|
|
1358
|
+
// src/components/Label.tsx
|
|
1359
|
+
var import_react16 = __toESM(require("react"));
|
|
1360
|
+
var Label = import_react16.default.forwardRef(
|
|
1361
|
+
({ className, required, children, ...rest }, ref) => {
|
|
1362
|
+
return /* @__PURE__ */ import_react16.default.createElement(
|
|
1197
1363
|
"label",
|
|
1198
1364
|
{
|
|
1199
1365
|
ref,
|
|
@@ -1201,17 +1367,17 @@ var Label = import_react14.default.forwardRef(
|
|
|
1201
1367
|
...rest
|
|
1202
1368
|
},
|
|
1203
1369
|
children,
|
|
1204
|
-
required && /* @__PURE__ */
|
|
1370
|
+
required && /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-error ml-1" }, "*")
|
|
1205
1371
|
);
|
|
1206
1372
|
}
|
|
1207
1373
|
);
|
|
1208
1374
|
Label.displayName = "Label";
|
|
1209
1375
|
|
|
1210
1376
|
// src/components/HelperText.tsx
|
|
1211
|
-
var
|
|
1212
|
-
var HelperText =
|
|
1377
|
+
var import_react17 = __toESM(require("react"));
|
|
1378
|
+
var HelperText = import_react17.default.forwardRef(
|
|
1213
1379
|
({ className, error, children, ...rest }, ref) => {
|
|
1214
|
-
return /* @__PURE__ */
|
|
1380
|
+
return /* @__PURE__ */ import_react17.default.createElement(
|
|
1215
1381
|
"p",
|
|
1216
1382
|
{
|
|
1217
1383
|
ref,
|
|
@@ -1225,12 +1391,12 @@ var HelperText = import_react15.default.forwardRef(
|
|
|
1225
1391
|
HelperText.displayName = "HelperText";
|
|
1226
1392
|
|
|
1227
1393
|
// src/components/Textarea.tsx
|
|
1228
|
-
var
|
|
1229
|
-
var Textarea =
|
|
1394
|
+
var import_react18 = __toESM(require("react"));
|
|
1395
|
+
var Textarea = import_react18.default.forwardRef(
|
|
1230
1396
|
({ error = false, className, disabled, ...rest }, ref) => {
|
|
1231
1397
|
const base = "w-full px-3 py-2 bg-graphite border border-ash rounded-none text-white placeholder:text-zinc min-h-[80px] transition-all duration-fast focus:border-gold focus:ring-1 focus:ring-gold focus:outline-none disabled:bg-slate disabled:text-dim disabled:cursor-not-allowed";
|
|
1232
1398
|
const errorCls = error ? "border-error focus:border-error focus:ring-error" : "";
|
|
1233
|
-
return /* @__PURE__ */
|
|
1399
|
+
return /* @__PURE__ */ import_react18.default.createElement(
|
|
1234
1400
|
"textarea",
|
|
1235
1401
|
{
|
|
1236
1402
|
ref,
|
|
@@ -1244,11 +1410,11 @@ var Textarea = import_react16.default.forwardRef(
|
|
|
1244
1410
|
Textarea.displayName = "Textarea";
|
|
1245
1411
|
|
|
1246
1412
|
// src/components/Select.tsx
|
|
1247
|
-
var
|
|
1413
|
+
var import_react19 = __toESM(require("react"));
|
|
1248
1414
|
var selectBgImage = `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23C9A227' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`;
|
|
1249
|
-
var Select =
|
|
1415
|
+
var Select = import_react19.default.forwardRef(
|
|
1250
1416
|
({ error = false, className, disabled, options, children, ...rest }, ref) => {
|
|
1251
|
-
return /* @__PURE__ */
|
|
1417
|
+
return /* @__PURE__ */ import_react19.default.createElement(
|
|
1252
1418
|
"select",
|
|
1253
1419
|
{
|
|
1254
1420
|
ref,
|
|
@@ -1268,19 +1434,19 @@ var Select = import_react17.default.forwardRef(
|
|
|
1268
1434
|
disabled,
|
|
1269
1435
|
...rest
|
|
1270
1436
|
},
|
|
1271
|
-
options ? options.map((opt) => /* @__PURE__ */
|
|
1437
|
+
options ? options.map((opt) => /* @__PURE__ */ import_react19.default.createElement("option", { key: opt.value, value: opt.value }, opt.label)) : children
|
|
1272
1438
|
);
|
|
1273
1439
|
}
|
|
1274
1440
|
);
|
|
1275
1441
|
Select.displayName = "Select";
|
|
1276
1442
|
|
|
1277
1443
|
// src/components/Checkbox.tsx
|
|
1278
|
-
var
|
|
1444
|
+
var import_react20 = __toESM(require("react"));
|
|
1279
1445
|
var checkmarkSvg = `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='%231A1A1A' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")`;
|
|
1280
|
-
var Checkbox =
|
|
1446
|
+
var Checkbox = import_react20.default.forwardRef(
|
|
1281
1447
|
({ className, label, id, ...rest }, ref) => {
|
|
1282
1448
|
const inputId = id || rest.name || Math.random().toString(36).substr(2, 9);
|
|
1283
|
-
const setRef = (0,
|
|
1449
|
+
const setRef = (0, import_react20.useCallback)((node) => {
|
|
1284
1450
|
if (node) {
|
|
1285
1451
|
if (node.checked) {
|
|
1286
1452
|
node.style.backgroundImage = checkmarkSvg;
|
|
@@ -1292,14 +1458,14 @@ var Checkbox = import_react18.default.forwardRef(
|
|
|
1292
1458
|
ref.current = node;
|
|
1293
1459
|
}
|
|
1294
1460
|
}, [ref]);
|
|
1295
|
-
return /* @__PURE__ */
|
|
1461
|
+
return /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
1296
1462
|
"input",
|
|
1297
1463
|
{
|
|
1298
1464
|
type: "checkbox",
|
|
1299
1465
|
id: inputId,
|
|
1300
1466
|
ref: setRef,
|
|
1301
1467
|
className: cx(
|
|
1302
|
-
"appearance-none h-4 w-4 border border-ash
|
|
1468
|
+
"appearance-none h-4 w-4 border border-ash bg-graphite",
|
|
1303
1469
|
"checked:bg-gold checked:border-gold",
|
|
1304
1470
|
"focus:ring-1 focus:ring-gold focus:ring-offset-1 focus:ring-offset-obsidian",
|
|
1305
1471
|
"transition duration-200 ease-in-out cursor-pointer",
|
|
@@ -1322,18 +1488,18 @@ var Checkbox = import_react18.default.forwardRef(
|
|
|
1322
1488
|
},
|
|
1323
1489
|
...rest
|
|
1324
1490
|
}
|
|
1325
|
-
), label && /* @__PURE__ */
|
|
1491
|
+
), label && /* @__PURE__ */ import_react20.default.createElement("label", { htmlFor: inputId, className: "ml-2 text-sm text-silver cursor-pointer select-none" }, label));
|
|
1326
1492
|
}
|
|
1327
1493
|
);
|
|
1328
1494
|
Checkbox.displayName = "Checkbox";
|
|
1329
1495
|
|
|
1330
1496
|
// src/components/Radio.tsx
|
|
1331
|
-
var
|
|
1497
|
+
var import_react21 = __toESM(require("react"));
|
|
1332
1498
|
var radioDotSvg = `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='%231A1A1A' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")`;
|
|
1333
|
-
var Radio =
|
|
1499
|
+
var Radio = import_react21.default.forwardRef(
|
|
1334
1500
|
({ className, label, id, ...rest }, ref) => {
|
|
1335
1501
|
const inputId = id || rest.name || Math.random().toString(36).substr(2, 9);
|
|
1336
|
-
const setRef = (0,
|
|
1502
|
+
const setRef = (0, import_react21.useCallback)((node) => {
|
|
1337
1503
|
if (node) {
|
|
1338
1504
|
if (node.checked) {
|
|
1339
1505
|
node.style.backgroundImage = radioDotSvg;
|
|
@@ -1345,7 +1511,7 @@ var Radio = import_react19.default.forwardRef(
|
|
|
1345
1511
|
ref.current = node;
|
|
1346
1512
|
}
|
|
1347
1513
|
}, [ref]);
|
|
1348
|
-
return /* @__PURE__ */
|
|
1514
|
+
return /* @__PURE__ */ import_react21.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ import_react21.default.createElement(
|
|
1349
1515
|
"input",
|
|
1350
1516
|
{
|
|
1351
1517
|
type: "radio",
|
|
@@ -1383,20 +1549,20 @@ var Radio = import_react19.default.forwardRef(
|
|
|
1383
1549
|
},
|
|
1384
1550
|
...rest
|
|
1385
1551
|
}
|
|
1386
|
-
), label && /* @__PURE__ */
|
|
1552
|
+
), label && /* @__PURE__ */ import_react21.default.createElement("label", { htmlFor: inputId, className: "ml-2 text-sm text-silver cursor-pointer select-none" }, label));
|
|
1387
1553
|
}
|
|
1388
1554
|
);
|
|
1389
1555
|
Radio.displayName = "Radio";
|
|
1390
1556
|
|
|
1391
1557
|
// src/components/Switch.tsx
|
|
1392
|
-
var
|
|
1393
|
-
var Switch =
|
|
1558
|
+
var import_react22 = __toESM(require("react"));
|
|
1559
|
+
var Switch = import_react22.default.forwardRef(
|
|
1394
1560
|
({ checked: controlledChecked, defaultChecked = false, onCheckedChange, disabled, className, label, ...rest }, ref) => {
|
|
1395
|
-
const [internalChecked, setInternalChecked] = (0,
|
|
1561
|
+
const [internalChecked, setInternalChecked] = (0, import_react22.useState)(defaultChecked);
|
|
1396
1562
|
const isControlled = controlledChecked !== void 0;
|
|
1397
1563
|
const checked = isControlled ? controlledChecked : internalChecked;
|
|
1398
|
-
const buttonRef = (0,
|
|
1399
|
-
const setRefs = (0,
|
|
1564
|
+
const buttonRef = (0, import_react22.useRef)(null);
|
|
1565
|
+
const setRefs = (0, import_react22.useCallback)(
|
|
1400
1566
|
(node) => {
|
|
1401
1567
|
buttonRef.current = node;
|
|
1402
1568
|
if (typeof ref === "function") {
|
|
@@ -1416,7 +1582,7 @@ var Switch = import_react20.default.forwardRef(
|
|
|
1416
1582
|
onCheckedChange?.(newChecked);
|
|
1417
1583
|
rest.onClick?.(e);
|
|
1418
1584
|
};
|
|
1419
|
-
return /* @__PURE__ */
|
|
1585
|
+
return /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement(
|
|
1420
1586
|
"button",
|
|
1421
1587
|
{
|
|
1422
1588
|
type: "button",
|
|
@@ -1436,7 +1602,7 @@ var Switch = import_react20.default.forwardRef(
|
|
|
1436
1602
|
),
|
|
1437
1603
|
...rest
|
|
1438
1604
|
},
|
|
1439
|
-
/* @__PURE__ */
|
|
1605
|
+
/* @__PURE__ */ import_react22.default.createElement(
|
|
1440
1606
|
"span",
|
|
1441
1607
|
{
|
|
1442
1608
|
className: cx(
|
|
@@ -1446,7 +1612,7 @@ var Switch = import_react20.default.forwardRef(
|
|
|
1446
1612
|
)
|
|
1447
1613
|
}
|
|
1448
1614
|
)
|
|
1449
|
-
), label && /* @__PURE__ */
|
|
1615
|
+
), label && /* @__PURE__ */ import_react22.default.createElement(
|
|
1450
1616
|
"span",
|
|
1451
1617
|
{
|
|
1452
1618
|
className: "text-sm text-silver cursor-pointer",
|
|
@@ -1462,7 +1628,7 @@ var Switch = import_react20.default.forwardRef(
|
|
|
1462
1628
|
Switch.displayName = "Switch";
|
|
1463
1629
|
|
|
1464
1630
|
// src/components/Slider.tsx
|
|
1465
|
-
var
|
|
1631
|
+
var import_react23 = __toESM(require("react"));
|
|
1466
1632
|
var SIZE_TRACK = {
|
|
1467
1633
|
sm: "h-1",
|
|
1468
1634
|
md: "h-2",
|
|
@@ -1473,7 +1639,7 @@ var SIZE_THUMB = {
|
|
|
1473
1639
|
md: "h-4 w-4",
|
|
1474
1640
|
lg: "h-5 w-5"
|
|
1475
1641
|
};
|
|
1476
|
-
var Slider =
|
|
1642
|
+
var Slider = import_react23.default.forwardRef(
|
|
1477
1643
|
({
|
|
1478
1644
|
value: controlledValue,
|
|
1479
1645
|
defaultValue = 0,
|
|
@@ -1489,13 +1655,13 @@ var Slider = import_react21.default.forwardRef(
|
|
|
1489
1655
|
className,
|
|
1490
1656
|
...props
|
|
1491
1657
|
}, ref) => {
|
|
1492
|
-
const [internalValue, setInternalValue] = (0,
|
|
1493
|
-
const [isDragging, setIsDragging] = (0,
|
|
1494
|
-
const trackRef = (0,
|
|
1658
|
+
const [internalValue, setInternalValue] = (0, import_react23.useState)(defaultValue);
|
|
1659
|
+
const [isDragging, setIsDragging] = (0, import_react23.useState)(false);
|
|
1660
|
+
const trackRef = (0, import_react23.useRef)(null);
|
|
1495
1661
|
const isControlled = controlledValue !== void 0;
|
|
1496
1662
|
const value = isControlled ? controlledValue : internalValue;
|
|
1497
1663
|
const percentage = (value - min) / (max - min) * 100;
|
|
1498
|
-
const updateValue = (0,
|
|
1664
|
+
const updateValue = (0, import_react23.useCallback)(
|
|
1499
1665
|
(clientX) => {
|
|
1500
1666
|
if (!trackRef.current || disabled) return;
|
|
1501
1667
|
const rect = trackRef.current.getBoundingClientRect();
|
|
@@ -1561,14 +1727,14 @@ var Slider = import_react21.default.forwardRef(
|
|
|
1561
1727
|
onChange?.(newValue);
|
|
1562
1728
|
onChangeEnd?.(newValue);
|
|
1563
1729
|
};
|
|
1564
|
-
return /* @__PURE__ */
|
|
1730
|
+
return /* @__PURE__ */ import_react23.default.createElement(
|
|
1565
1731
|
"div",
|
|
1566
1732
|
{
|
|
1567
1733
|
ref,
|
|
1568
1734
|
className: cx("relative w-full py-2", disabled && "opacity-50", className),
|
|
1569
1735
|
...props
|
|
1570
1736
|
},
|
|
1571
|
-
/* @__PURE__ */
|
|
1737
|
+
/* @__PURE__ */ import_react23.default.createElement(
|
|
1572
1738
|
"div",
|
|
1573
1739
|
{
|
|
1574
1740
|
ref: trackRef,
|
|
@@ -1578,14 +1744,14 @@ var Slider = import_react21.default.forwardRef(
|
|
|
1578
1744
|
),
|
|
1579
1745
|
onMouseDown: handleMouseDown
|
|
1580
1746
|
},
|
|
1581
|
-
/* @__PURE__ */
|
|
1747
|
+
/* @__PURE__ */ import_react23.default.createElement(
|
|
1582
1748
|
"div",
|
|
1583
1749
|
{
|
|
1584
1750
|
className: cx("absolute inset-y-0 left-0 bg-gold", SIZE_TRACK[size]),
|
|
1585
1751
|
style: { width: `${percentage}%` }
|
|
1586
1752
|
}
|
|
1587
1753
|
),
|
|
1588
|
-
/* @__PURE__ */
|
|
1754
|
+
/* @__PURE__ */ import_react23.default.createElement(
|
|
1589
1755
|
"div",
|
|
1590
1756
|
{
|
|
1591
1757
|
role: "slider",
|
|
@@ -1606,7 +1772,7 @@ var Slider = import_react21.default.forwardRef(
|
|
|
1606
1772
|
),
|
|
1607
1773
|
style: { left: `${percentage}%` }
|
|
1608
1774
|
},
|
|
1609
|
-
showTooltip && isDragging && /* @__PURE__ */
|
|
1775
|
+
showTooltip && isDragging && /* @__PURE__ */ import_react23.default.createElement("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-graphite border border-ash text-xs text-white whitespace-nowrap" }, formatValue(value))
|
|
1610
1776
|
)
|
|
1611
1777
|
)
|
|
1612
1778
|
);
|
|
@@ -1615,10 +1781,10 @@ var Slider = import_react21.default.forwardRef(
|
|
|
1615
1781
|
Slider.displayName = "Slider";
|
|
1616
1782
|
|
|
1617
1783
|
// src/components/InputGroup.tsx
|
|
1618
|
-
var
|
|
1619
|
-
var InputGroup =
|
|
1784
|
+
var import_react24 = __toESM(require("react"));
|
|
1785
|
+
var InputGroup = import_react24.default.forwardRef(
|
|
1620
1786
|
({ className, children, ...props }, ref) => {
|
|
1621
|
-
return /* @__PURE__ */
|
|
1787
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
1622
1788
|
"div",
|
|
1623
1789
|
{
|
|
1624
1790
|
ref,
|
|
@@ -1630,9 +1796,9 @@ var InputGroup = import_react22.default.forwardRef(
|
|
|
1630
1796
|
}
|
|
1631
1797
|
);
|
|
1632
1798
|
InputGroup.displayName = "InputGroup";
|
|
1633
|
-
var InputLeftAddon =
|
|
1799
|
+
var InputLeftAddon = import_react24.default.forwardRef(
|
|
1634
1800
|
({ className, children, ...props }, ref) => {
|
|
1635
|
-
return /* @__PURE__ */
|
|
1801
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
1636
1802
|
"div",
|
|
1637
1803
|
{
|
|
1638
1804
|
ref,
|
|
@@ -1648,9 +1814,9 @@ var InputLeftAddon = import_react22.default.forwardRef(
|
|
|
1648
1814
|
}
|
|
1649
1815
|
);
|
|
1650
1816
|
InputLeftAddon.displayName = "InputLeftAddon";
|
|
1651
|
-
var InputRightAddon =
|
|
1817
|
+
var InputRightAddon = import_react24.default.forwardRef(
|
|
1652
1818
|
({ className, children, ...props }, ref) => {
|
|
1653
|
-
return /* @__PURE__ */
|
|
1819
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
1654
1820
|
"div",
|
|
1655
1821
|
{
|
|
1656
1822
|
ref,
|
|
@@ -1666,9 +1832,9 @@ var InputRightAddon = import_react22.default.forwardRef(
|
|
|
1666
1832
|
}
|
|
1667
1833
|
);
|
|
1668
1834
|
InputRightAddon.displayName = "InputRightAddon";
|
|
1669
|
-
var InputLeftElement =
|
|
1835
|
+
var InputLeftElement = import_react24.default.forwardRef(
|
|
1670
1836
|
({ className, children, ...props }, ref) => {
|
|
1671
|
-
return /* @__PURE__ */
|
|
1837
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
1672
1838
|
"div",
|
|
1673
1839
|
{
|
|
1674
1840
|
ref,
|
|
@@ -1684,9 +1850,9 @@ var InputLeftElement = import_react22.default.forwardRef(
|
|
|
1684
1850
|
}
|
|
1685
1851
|
);
|
|
1686
1852
|
InputLeftElement.displayName = "InputLeftElement";
|
|
1687
|
-
var InputRightElement =
|
|
1853
|
+
var InputRightElement = import_react24.default.forwardRef(
|
|
1688
1854
|
({ className, children, ...props }, ref) => {
|
|
1689
|
-
return /* @__PURE__ */
|
|
1855
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
1690
1856
|
"div",
|
|
1691
1857
|
{
|
|
1692
1858
|
ref,
|
|
@@ -1701,9 +1867,9 @@ var InputRightElement = import_react22.default.forwardRef(
|
|
|
1701
1867
|
}
|
|
1702
1868
|
);
|
|
1703
1869
|
InputRightElement.displayName = "InputRightElement";
|
|
1704
|
-
var InputWrapper =
|
|
1870
|
+
var InputWrapper = import_react24.default.forwardRef(
|
|
1705
1871
|
({ className, children, ...props }, ref) => {
|
|
1706
|
-
return /* @__PURE__ */
|
|
1872
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
1707
1873
|
"div",
|
|
1708
1874
|
{
|
|
1709
1875
|
ref,
|
|
@@ -1717,13 +1883,13 @@ var InputWrapper = import_react22.default.forwardRef(
|
|
|
1717
1883
|
InputWrapper.displayName = "InputWrapper";
|
|
1718
1884
|
|
|
1719
1885
|
// src/components/Alert.tsx
|
|
1720
|
-
var
|
|
1721
|
-
var
|
|
1886
|
+
var import_react25 = __toESM(require("react"));
|
|
1887
|
+
var import_lucide_react3 = require("lucide-react");
|
|
1722
1888
|
var icons = {
|
|
1723
|
-
info:
|
|
1724
|
-
success:
|
|
1725
|
-
warning:
|
|
1726
|
-
error:
|
|
1889
|
+
info: import_lucide_react3.Info,
|
|
1890
|
+
success: import_lucide_react3.CheckCircle,
|
|
1891
|
+
warning: import_lucide_react3.AlertTriangle,
|
|
1892
|
+
error: import_lucide_react3.XCircle
|
|
1727
1893
|
};
|
|
1728
1894
|
var variantStyles = {
|
|
1729
1895
|
info: "bg-info/10 border-info text-info",
|
|
@@ -1731,10 +1897,10 @@ var variantStyles = {
|
|
|
1731
1897
|
warning: "bg-warning/10 border-warning text-warning",
|
|
1732
1898
|
error: "bg-error/10 border-error text-error"
|
|
1733
1899
|
};
|
|
1734
|
-
var Alert =
|
|
1900
|
+
var Alert = import_react25.default.forwardRef(
|
|
1735
1901
|
({ variant = "info", title, children, className, ...rest }, ref) => {
|
|
1736
1902
|
const Icon = icons[variant];
|
|
1737
|
-
return /* @__PURE__ */
|
|
1903
|
+
return /* @__PURE__ */ import_react25.default.createElement(
|
|
1738
1904
|
"div",
|
|
1739
1905
|
{
|
|
1740
1906
|
ref,
|
|
@@ -1746,18 +1912,18 @@ var Alert = import_react23.default.forwardRef(
|
|
|
1746
1912
|
),
|
|
1747
1913
|
...rest
|
|
1748
1914
|
},
|
|
1749
|
-
/* @__PURE__ */
|
|
1750
|
-
/* @__PURE__ */
|
|
1915
|
+
/* @__PURE__ */ import_react25.default.createElement(Icon, { className: "h-5 w-5 shrink-0" }),
|
|
1916
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1" }, title && /* @__PURE__ */ import_react25.default.createElement("h5", { className: "mb-1 font-medium leading-none tracking-tight text-current" }, title), /* @__PURE__ */ import_react25.default.createElement("div", { className: "text-sm opacity-90" }, children))
|
|
1751
1917
|
);
|
|
1752
1918
|
}
|
|
1753
1919
|
);
|
|
1754
1920
|
Alert.displayName = "Alert";
|
|
1755
1921
|
|
|
1756
1922
|
// src/components/Spinner.tsx
|
|
1757
|
-
var
|
|
1923
|
+
var import_react26 = __toESM(require("react"));
|
|
1758
1924
|
var Spinner = ({ className, size = "md", ...rest }) => {
|
|
1759
1925
|
const sizeClass = size === "sm" ? "h-4 w-4" : size === "lg" ? "h-8 w-8" : "h-6 w-6";
|
|
1760
|
-
return /* @__PURE__ */
|
|
1926
|
+
return /* @__PURE__ */ import_react26.default.createElement(
|
|
1761
1927
|
"svg",
|
|
1762
1928
|
{
|
|
1763
1929
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1770,20 +1936,20 @@ var Spinner = ({ className, size = "md", ...rest }) => {
|
|
|
1770
1936
|
className: cx("animate-spin text-gold", sizeClass, className),
|
|
1771
1937
|
...rest
|
|
1772
1938
|
},
|
|
1773
|
-
/* @__PURE__ */
|
|
1939
|
+
/* @__PURE__ */ import_react26.default.createElement("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
|
|
1774
1940
|
);
|
|
1775
1941
|
};
|
|
1776
1942
|
Spinner.displayName = "Spinner";
|
|
1777
1943
|
|
|
1778
1944
|
// src/components/Skeleton.tsx
|
|
1779
|
-
var
|
|
1780
|
-
var Skeleton =
|
|
1945
|
+
var import_react27 = __toESM(require("react"));
|
|
1946
|
+
var Skeleton = import_react27.default.forwardRef(
|
|
1781
1947
|
({ className, ...rest }, ref) => {
|
|
1782
|
-
return /* @__PURE__ */
|
|
1948
|
+
return /* @__PURE__ */ import_react27.default.createElement(
|
|
1783
1949
|
"div",
|
|
1784
1950
|
{
|
|
1785
1951
|
ref,
|
|
1786
|
-
className: cx("animate-pulse bg-ash
|
|
1952
|
+
className: cx("animate-pulse bg-ash", className),
|
|
1787
1953
|
...rest
|
|
1788
1954
|
}
|
|
1789
1955
|
);
|
|
@@ -1792,7 +1958,7 @@ var Skeleton = import_react25.default.forwardRef(
|
|
|
1792
1958
|
Skeleton.displayName = "Skeleton";
|
|
1793
1959
|
|
|
1794
1960
|
// src/components/Progress.tsx
|
|
1795
|
-
var
|
|
1961
|
+
var import_react28 = __toESM(require("react"));
|
|
1796
1962
|
var SIZE_MAP = {
|
|
1797
1963
|
sm: "h-1",
|
|
1798
1964
|
md: "h-2",
|
|
@@ -1804,7 +1970,7 @@ var VARIANT_MAP2 = {
|
|
|
1804
1970
|
warning: "bg-warning",
|
|
1805
1971
|
error: "bg-error"
|
|
1806
1972
|
};
|
|
1807
|
-
var Progress =
|
|
1973
|
+
var Progress = import_react28.default.forwardRef(
|
|
1808
1974
|
({
|
|
1809
1975
|
value = 0,
|
|
1810
1976
|
max = 100,
|
|
@@ -1818,7 +1984,7 @@ var Progress = import_react26.default.forwardRef(
|
|
|
1818
1984
|
}, ref) => {
|
|
1819
1985
|
const percentage = Math.min(100, Math.max(0, value / max * 100));
|
|
1820
1986
|
const displayValue = formatValue ? formatValue(value, max) : `${Math.round(percentage)}%`;
|
|
1821
|
-
return /* @__PURE__ */
|
|
1987
|
+
return /* @__PURE__ */ import_react28.default.createElement("div", { ref, className: cx("w-full", className), ...props }, showValue && /* @__PURE__ */ import_react28.default.createElement("div", { className: "flex justify-between mb-1" }, /* @__PURE__ */ import_react28.default.createElement("span", { className: "text-sm text-silver" }, "Progress"), /* @__PURE__ */ import_react28.default.createElement("span", { className: "text-sm text-white font-medium" }, displayValue)), /* @__PURE__ */ import_react28.default.createElement(
|
|
1822
1988
|
"div",
|
|
1823
1989
|
{
|
|
1824
1990
|
className: cx(
|
|
@@ -1830,7 +1996,7 @@ var Progress = import_react26.default.forwardRef(
|
|
|
1830
1996
|
"aria-valuemin": 0,
|
|
1831
1997
|
"aria-valuemax": max
|
|
1832
1998
|
},
|
|
1833
|
-
/* @__PURE__ */
|
|
1999
|
+
/* @__PURE__ */ import_react28.default.createElement(
|
|
1834
2000
|
"div",
|
|
1835
2001
|
{
|
|
1836
2002
|
className: cx(
|
|
@@ -1849,16 +2015,16 @@ var Progress = import_react26.default.forwardRef(
|
|
|
1849
2015
|
Progress.displayName = "Progress";
|
|
1850
2016
|
|
|
1851
2017
|
// src/components/Toast.tsx
|
|
1852
|
-
var
|
|
2018
|
+
var import_react29 = __toESM(require("react"));
|
|
1853
2019
|
var import_react_dom = require("react-dom");
|
|
1854
|
-
var
|
|
1855
|
-
var ToastContext = (0,
|
|
2020
|
+
var import_lucide_react4 = require("lucide-react");
|
|
2021
|
+
var ToastContext = (0, import_react29.createContext)(null);
|
|
1856
2022
|
function useToast() {
|
|
1857
|
-
const context = (0,
|
|
2023
|
+
const context = (0, import_react29.useContext)(ToastContext);
|
|
1858
2024
|
if (!context) {
|
|
1859
2025
|
throw new Error("useToast must be used within a ToastProvider");
|
|
1860
2026
|
}
|
|
1861
|
-
const toast = (0,
|
|
2027
|
+
const toast = (0, import_react29.useCallback)(
|
|
1862
2028
|
(options) => {
|
|
1863
2029
|
return context.addToast(options);
|
|
1864
2030
|
},
|
|
@@ -1874,12 +2040,12 @@ var ToastProvider = ({
|
|
|
1874
2040
|
position = "bottom-right",
|
|
1875
2041
|
defaultDuration = 5e3
|
|
1876
2042
|
}) => {
|
|
1877
|
-
const [toasts, setToasts] = (0,
|
|
1878
|
-
const [mounted, setMounted] = (0,
|
|
1879
|
-
(0,
|
|
2043
|
+
const [toasts, setToasts] = (0, import_react29.useState)([]);
|
|
2044
|
+
const [mounted, setMounted] = (0, import_react29.useState)(false);
|
|
2045
|
+
(0, import_react29.useEffect)(() => {
|
|
1880
2046
|
setMounted(true);
|
|
1881
2047
|
}, []);
|
|
1882
|
-
const addToast = (0,
|
|
2048
|
+
const addToast = (0, import_react29.useCallback)(
|
|
1883
2049
|
(toast) => {
|
|
1884
2050
|
const id = Math.random().toString(36).substr(2, 9);
|
|
1885
2051
|
const newToast = {
|
|
@@ -1892,14 +2058,14 @@ var ToastProvider = ({
|
|
|
1892
2058
|
},
|
|
1893
2059
|
[defaultDuration]
|
|
1894
2060
|
);
|
|
1895
|
-
const removeToast = (0,
|
|
2061
|
+
const removeToast = (0, import_react29.useCallback)((id) => {
|
|
1896
2062
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
1897
2063
|
}, []);
|
|
1898
|
-
return /* @__PURE__ */
|
|
2064
|
+
return /* @__PURE__ */ import_react29.default.createElement(ToastContext.Provider, { value: { toasts, addToast, removeToast, position } }, children, mounted && /* @__PURE__ */ import_react29.default.createElement(ToastViewport, null));
|
|
1899
2065
|
};
|
|
1900
2066
|
ToastProvider.displayName = "ToastProvider";
|
|
1901
2067
|
var ToastViewport = () => {
|
|
1902
|
-
const context = (0,
|
|
2068
|
+
const context = (0, import_react29.useContext)(ToastContext);
|
|
1903
2069
|
if (!context) return null;
|
|
1904
2070
|
const { toasts, position } = context;
|
|
1905
2071
|
const positionClasses = {
|
|
@@ -1911,7 +2077,7 @@ var ToastViewport = () => {
|
|
|
1911
2077
|
"bottom-center": "bottom-4 left-1/2 -translate-x-1/2"
|
|
1912
2078
|
};
|
|
1913
2079
|
return (0, import_react_dom.createPortal)(
|
|
1914
|
-
/* @__PURE__ */
|
|
2080
|
+
/* @__PURE__ */ import_react29.default.createElement(
|
|
1915
2081
|
"div",
|
|
1916
2082
|
{
|
|
1917
2083
|
className: cx(
|
|
@@ -1919,7 +2085,7 @@ var ToastViewport = () => {
|
|
|
1919
2085
|
positionClasses[position]
|
|
1920
2086
|
)
|
|
1921
2087
|
},
|
|
1922
|
-
toasts.map((toast) => /* @__PURE__ */
|
|
2088
|
+
toasts.map((toast) => /* @__PURE__ */ import_react29.default.createElement(Toast, { key: toast.id, ...toast }))
|
|
1923
2089
|
),
|
|
1924
2090
|
document.body
|
|
1925
2091
|
);
|
|
@@ -1933,10 +2099,10 @@ var VARIANT_STYLES2 = {
|
|
|
1933
2099
|
};
|
|
1934
2100
|
var VARIANT_ICONS = {
|
|
1935
2101
|
default: null,
|
|
1936
|
-
success: /* @__PURE__ */
|
|
1937
|
-
error: /* @__PURE__ */
|
|
1938
|
-
warning: /* @__PURE__ */
|
|
1939
|
-
info: /* @__PURE__ */
|
|
2102
|
+
success: /* @__PURE__ */ import_react29.default.createElement(import_lucide_react4.CheckCircle, { className: "h-5 w-5 text-success" }),
|
|
2103
|
+
error: /* @__PURE__ */ import_react29.default.createElement(import_lucide_react4.AlertCircle, { className: "h-5 w-5 text-error" }),
|
|
2104
|
+
warning: /* @__PURE__ */ import_react29.default.createElement(import_lucide_react4.AlertTriangle, { className: "h-5 w-5 text-warning" }),
|
|
2105
|
+
info: /* @__PURE__ */ import_react29.default.createElement(import_lucide_react4.Info, { className: "h-5 w-5 text-info" })
|
|
1940
2106
|
};
|
|
1941
2107
|
var Toast = ({
|
|
1942
2108
|
id,
|
|
@@ -1946,8 +2112,8 @@ var Toast = ({
|
|
|
1946
2112
|
duration,
|
|
1947
2113
|
action
|
|
1948
2114
|
}) => {
|
|
1949
|
-
const context = (0,
|
|
1950
|
-
(0,
|
|
2115
|
+
const context = (0, import_react29.useContext)(ToastContext);
|
|
2116
|
+
(0, import_react29.useEffect)(() => {
|
|
1951
2117
|
if (duration && duration > 0) {
|
|
1952
2118
|
const timer = setTimeout(() => {
|
|
1953
2119
|
context?.removeToast(id);
|
|
@@ -1956,7 +2122,7 @@ var Toast = ({
|
|
|
1956
2122
|
}
|
|
1957
2123
|
}, [id, duration, context]);
|
|
1958
2124
|
const icon = VARIANT_ICONS[variant];
|
|
1959
|
-
return /* @__PURE__ */
|
|
2125
|
+
return /* @__PURE__ */ import_react29.default.createElement(
|
|
1960
2126
|
"div",
|
|
1961
2127
|
{
|
|
1962
2128
|
role: "alert",
|
|
@@ -1965,29 +2131,29 @@ var Toast = ({
|
|
|
1965
2131
|
VARIANT_STYLES2[variant]
|
|
1966
2132
|
)
|
|
1967
2133
|
},
|
|
1968
|
-
/* @__PURE__ */
|
|
2134
|
+
/* @__PURE__ */ import_react29.default.createElement("div", { className: "flex gap-3" }, icon && /* @__PURE__ */ import_react29.default.createElement("div", { className: "shrink-0 mt-0.5" }, icon), /* @__PURE__ */ import_react29.default.createElement("div", { className: "flex-1 min-w-0" }, title && /* @__PURE__ */ import_react29.default.createElement("p", { className: "text-sm font-medium text-white" }, title), description && /* @__PURE__ */ import_react29.default.createElement("p", { className: "text-sm text-silver mt-1" }, description), action && /* @__PURE__ */ import_react29.default.createElement("div", { className: "mt-3" }, action)), /* @__PURE__ */ import_react29.default.createElement(
|
|
1969
2135
|
"button",
|
|
1970
2136
|
{
|
|
1971
2137
|
onClick: () => context?.removeToast(id),
|
|
1972
2138
|
className: "shrink-0 text-silver hover:text-white transition-colors"
|
|
1973
2139
|
},
|
|
1974
|
-
/* @__PURE__ */
|
|
1975
|
-
/* @__PURE__ */
|
|
2140
|
+
/* @__PURE__ */ import_react29.default.createElement(import_lucide_react4.X, { className: "h-4 w-4" }),
|
|
2141
|
+
/* @__PURE__ */ import_react29.default.createElement("span", { className: "sr-only" }, "Dismiss")
|
|
1976
2142
|
))
|
|
1977
2143
|
);
|
|
1978
2144
|
};
|
|
1979
2145
|
Toast.displayName = "Toast";
|
|
1980
2146
|
|
|
1981
2147
|
// src/components/Modal.tsx
|
|
1982
|
-
var
|
|
2148
|
+
var import_react30 = __toESM(require("react"));
|
|
1983
2149
|
var import_react_dom2 = require("react-dom");
|
|
1984
|
-
var
|
|
2150
|
+
var import_lucide_react5 = require("lucide-react");
|
|
1985
2151
|
var Modal = ({ isOpen, onClose, title, children, className }) => {
|
|
1986
|
-
const [mounted, setMounted] = (0,
|
|
1987
|
-
(0,
|
|
2152
|
+
const [mounted, setMounted] = (0, import_react30.useState)(false);
|
|
2153
|
+
(0, import_react30.useEffect)(() => {
|
|
1988
2154
|
setMounted(true);
|
|
1989
2155
|
}, []);
|
|
1990
|
-
(0,
|
|
2156
|
+
(0, import_react30.useEffect)(() => {
|
|
1991
2157
|
if (isOpen) {
|
|
1992
2158
|
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
1993
2159
|
document.body.style.overflow = "hidden";
|
|
@@ -2001,7 +2167,7 @@ var Modal = ({ isOpen, onClose, title, children, className }) => {
|
|
|
2001
2167
|
document.body.style.paddingRight = "0px";
|
|
2002
2168
|
};
|
|
2003
2169
|
}, [isOpen]);
|
|
2004
|
-
(0,
|
|
2170
|
+
(0, import_react30.useEffect)(() => {
|
|
2005
2171
|
const handleEsc = (e) => {
|
|
2006
2172
|
if (e.key === "Escape") onClose();
|
|
2007
2173
|
};
|
|
@@ -2010,7 +2176,7 @@ var Modal = ({ isOpen, onClose, title, children, className }) => {
|
|
|
2010
2176
|
}, [onClose]);
|
|
2011
2177
|
if (!mounted) return null;
|
|
2012
2178
|
if (!isOpen) return null;
|
|
2013
|
-
const content = /* @__PURE__ */
|
|
2179
|
+
const content = /* @__PURE__ */ import_react30.default.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6", onClick: onClose }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "fixed inset-0 z-40 bg-obsidian/80 backdrop-blur-sm", "aria-hidden": "true" }), /* @__PURE__ */ import_react30.default.createElement(
|
|
2014
2180
|
"div",
|
|
2015
2181
|
{
|
|
2016
2182
|
role: "dialog",
|
|
@@ -2022,17 +2188,17 @@ var Modal = ({ isOpen, onClose, title, children, className }) => {
|
|
|
2022
2188
|
"data-state": "open",
|
|
2023
2189
|
onClick: (e) => e.stopPropagation()
|
|
2024
2190
|
},
|
|
2025
|
-
/* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
2191
|
+
/* @__PURE__ */ import_react30.default.createElement("div", { className: "flex items-center justify-between mb-2" }, title ? /* @__PURE__ */ import_react30.default.createElement("h3", { className: "text-xl font-semibold text-white m-0" }, title) : /* @__PURE__ */ import_react30.default.createElement("div", null), /* @__PURE__ */ import_react30.default.createElement("button", { onClick: onClose, className: "text-silver hover:text-white transition-colors ml-auto" }, /* @__PURE__ */ import_react30.default.createElement(import_lucide_react5.X, { className: "h-5 w-5" }), /* @__PURE__ */ import_react30.default.createElement("span", { className: "sr-only" }, "Close"))),
|
|
2192
|
+
/* @__PURE__ */ import_react30.default.createElement("div", null, children)
|
|
2027
2193
|
));
|
|
2028
2194
|
return (0, import_react_dom2.createPortal)(content, document.body);
|
|
2029
2195
|
};
|
|
2030
2196
|
Modal.displayName = "Modal";
|
|
2031
2197
|
|
|
2032
2198
|
// src/components/Drawer.tsx
|
|
2033
|
-
var
|
|
2199
|
+
var import_react31 = __toESM(require("react"));
|
|
2034
2200
|
var import_react_dom3 = require("react-dom");
|
|
2035
|
-
var
|
|
2201
|
+
var import_lucide_react6 = require("lucide-react");
|
|
2036
2202
|
var SIZE_MAP2 = {
|
|
2037
2203
|
sm: {
|
|
2038
2204
|
left: "w-64",
|
|
@@ -2086,11 +2252,11 @@ var Drawer = ({
|
|
|
2086
2252
|
children,
|
|
2087
2253
|
className
|
|
2088
2254
|
}) => {
|
|
2089
|
-
const [mounted, setMounted] = (0,
|
|
2090
|
-
(0,
|
|
2255
|
+
const [mounted, setMounted] = (0, import_react31.useState)(false);
|
|
2256
|
+
(0, import_react31.useEffect)(() => {
|
|
2091
2257
|
setMounted(true);
|
|
2092
2258
|
}, []);
|
|
2093
|
-
(0,
|
|
2259
|
+
(0, import_react31.useEffect)(() => {
|
|
2094
2260
|
if (isOpen) {
|
|
2095
2261
|
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
2096
2262
|
document.body.style.overflow = "hidden";
|
|
@@ -2104,7 +2270,7 @@ var Drawer = ({
|
|
|
2104
2270
|
document.body.style.paddingRight = "0px";
|
|
2105
2271
|
};
|
|
2106
2272
|
}, [isOpen]);
|
|
2107
|
-
(0,
|
|
2273
|
+
(0, import_react31.useEffect)(() => {
|
|
2108
2274
|
const handleEsc = (e) => {
|
|
2109
2275
|
if (e.key === "Escape") onClose();
|
|
2110
2276
|
};
|
|
@@ -2112,7 +2278,7 @@ var Drawer = ({
|
|
|
2112
2278
|
return () => window.removeEventListener("keydown", handleEsc);
|
|
2113
2279
|
}, [onClose]);
|
|
2114
2280
|
if (!mounted) return null;
|
|
2115
|
-
const content = /* @__PURE__ */
|
|
2281
|
+
const content = /* @__PURE__ */ import_react31.default.createElement(
|
|
2116
2282
|
"div",
|
|
2117
2283
|
{
|
|
2118
2284
|
className: cx(
|
|
@@ -2120,7 +2286,7 @@ var Drawer = ({
|
|
|
2120
2286
|
isOpen ? "pointer-events-auto" : "pointer-events-none"
|
|
2121
2287
|
)
|
|
2122
2288
|
},
|
|
2123
|
-
/* @__PURE__ */
|
|
2289
|
+
/* @__PURE__ */ import_react31.default.createElement(
|
|
2124
2290
|
"div",
|
|
2125
2291
|
{
|
|
2126
2292
|
className: cx(
|
|
@@ -2131,7 +2297,7 @@ var Drawer = ({
|
|
|
2131
2297
|
"aria-hidden": "true"
|
|
2132
2298
|
}
|
|
2133
2299
|
),
|
|
2134
|
-
/* @__PURE__ */
|
|
2300
|
+
/* @__PURE__ */ import_react31.default.createElement(
|
|
2135
2301
|
"div",
|
|
2136
2302
|
{
|
|
2137
2303
|
role: "dialog",
|
|
@@ -2149,16 +2315,16 @@ var Drawer = ({
|
|
|
2149
2315
|
className
|
|
2150
2316
|
)
|
|
2151
2317
|
},
|
|
2152
|
-
/* @__PURE__ */
|
|
2318
|
+
/* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center justify-between px-4 py-3 border-b border-ash" }, title ? /* @__PURE__ */ import_react31.default.createElement("h2", { className: "text-lg font-semibold text-white m-0" }, title) : /* @__PURE__ */ import_react31.default.createElement("div", null), /* @__PURE__ */ import_react31.default.createElement(
|
|
2153
2319
|
"button",
|
|
2154
2320
|
{
|
|
2155
2321
|
onClick: onClose,
|
|
2156
2322
|
className: "text-silver hover:text-white transition-colors"
|
|
2157
2323
|
},
|
|
2158
|
-
/* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2324
|
+
/* @__PURE__ */ import_react31.default.createElement(import_lucide_react6.X, { className: "h-5 w-5" }),
|
|
2325
|
+
/* @__PURE__ */ import_react31.default.createElement("span", { className: "sr-only" }, "Close")
|
|
2160
2326
|
)),
|
|
2161
|
-
/* @__PURE__ */
|
|
2327
|
+
/* @__PURE__ */ import_react31.default.createElement("div", { className: "flex-1 overflow-auto p-4" }, children)
|
|
2162
2328
|
)
|
|
2163
2329
|
);
|
|
2164
2330
|
return (0, import_react_dom3.createPortal)(content, document.body);
|
|
@@ -2166,7 +2332,7 @@ var Drawer = ({
|
|
|
2166
2332
|
Drawer.displayName = "Drawer";
|
|
2167
2333
|
|
|
2168
2334
|
// src/components/Popover.tsx
|
|
2169
|
-
var
|
|
2335
|
+
var import_react32 = __toESM(require("react"));
|
|
2170
2336
|
var POSITION_CLASSES2 = {
|
|
2171
2337
|
top: {
|
|
2172
2338
|
start: "bottom-full left-0 mb-2",
|
|
@@ -2198,12 +2364,12 @@ var Popover = ({
|
|
|
2198
2364
|
onOpenChange,
|
|
2199
2365
|
closeOnClickOutside = true
|
|
2200
2366
|
}) => {
|
|
2201
|
-
const [internalOpen, setInternalOpen] = (0,
|
|
2367
|
+
const [internalOpen, setInternalOpen] = (0, import_react32.useState)(false);
|
|
2202
2368
|
const isControlled = controlledOpen !== void 0;
|
|
2203
2369
|
const isOpen = isControlled ? controlledOpen : internalOpen;
|
|
2204
|
-
const containerRef = (0,
|
|
2205
|
-
const baseId = (0,
|
|
2206
|
-
const setIsOpen = (0,
|
|
2370
|
+
const containerRef = (0, import_react32.useRef)(null);
|
|
2371
|
+
const baseId = (0, import_react32.useId)();
|
|
2372
|
+
const setIsOpen = (0, import_react32.useCallback)(
|
|
2207
2373
|
(newOpen) => {
|
|
2208
2374
|
if (!isControlled) {
|
|
2209
2375
|
setInternalOpen(newOpen);
|
|
@@ -2212,7 +2378,7 @@ var Popover = ({
|
|
|
2212
2378
|
},
|
|
2213
2379
|
[isControlled, onOpenChange]
|
|
2214
2380
|
);
|
|
2215
|
-
(0,
|
|
2381
|
+
(0, import_react32.useEffect)(() => {
|
|
2216
2382
|
if (!isOpen || !closeOnClickOutside) return;
|
|
2217
2383
|
const handleClickOutside = (e) => {
|
|
2218
2384
|
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
@@ -2222,7 +2388,7 @@ var Popover = ({
|
|
|
2222
2388
|
document.addEventListener("mousedown", handleClickOutside);
|
|
2223
2389
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
2224
2390
|
}, [isOpen, closeOnClickOutside, setIsOpen]);
|
|
2225
|
-
(0,
|
|
2391
|
+
(0, import_react32.useEffect)(() => {
|
|
2226
2392
|
if (!isOpen) return;
|
|
2227
2393
|
const handleEscape = (e) => {
|
|
2228
2394
|
if (e.key === "Escape") {
|
|
@@ -2235,14 +2401,14 @@ var Popover = ({
|
|
|
2235
2401
|
const handleTriggerClick = () => {
|
|
2236
2402
|
setIsOpen(!isOpen);
|
|
2237
2403
|
};
|
|
2238
|
-
const triggerElement =
|
|
2404
|
+
const triggerElement = import_react32.default.cloneElement(trigger, {
|
|
2239
2405
|
onClick: handleTriggerClick,
|
|
2240
2406
|
"aria-haspopup": "dialog",
|
|
2241
2407
|
"aria-expanded": isOpen,
|
|
2242
2408
|
"aria-controls": `${baseId}-popover`,
|
|
2243
2409
|
id: `${baseId}-trigger`
|
|
2244
2410
|
});
|
|
2245
|
-
return /* @__PURE__ */
|
|
2411
|
+
return /* @__PURE__ */ import_react32.default.createElement("div", { ref: containerRef, className: "relative inline-block" }, triggerElement, isOpen && /* @__PURE__ */ import_react32.default.createElement(
|
|
2246
2412
|
"div",
|
|
2247
2413
|
{
|
|
2248
2414
|
id: `${baseId}-popover`,
|
|
@@ -2261,7 +2427,7 @@ var Popover = ({
|
|
|
2261
2427
|
Popover.displayName = "Popover";
|
|
2262
2428
|
|
|
2263
2429
|
// src/components/Dialog.tsx
|
|
2264
|
-
var
|
|
2430
|
+
var import_react33 = __toESM(require("react"));
|
|
2265
2431
|
var ConfirmDialog = ({
|
|
2266
2432
|
title = "Confirm",
|
|
2267
2433
|
description,
|
|
@@ -2274,15 +2440,15 @@ var ConfirmDialog = ({
|
|
|
2274
2440
|
isLoading = false,
|
|
2275
2441
|
...props
|
|
2276
2442
|
}) => {
|
|
2277
|
-
const handleCancel = (0,
|
|
2443
|
+
const handleCancel = (0, import_react33.useCallback)(() => {
|
|
2278
2444
|
onCancel?.();
|
|
2279
2445
|
onClose();
|
|
2280
2446
|
}, [onCancel, onClose]);
|
|
2281
|
-
const handleConfirm = (0,
|
|
2447
|
+
const handleConfirm = (0, import_react33.useCallback)(async () => {
|
|
2282
2448
|
await onConfirm();
|
|
2283
2449
|
onClose();
|
|
2284
2450
|
}, [onConfirm, onClose]);
|
|
2285
|
-
return /* @__PURE__ */
|
|
2451
|
+
return /* @__PURE__ */ import_react33.default.createElement(Modal, { title, onClose, ...props }, description && /* @__PURE__ */ import_react33.default.createElement("p", { className: "text-sm text-silver mb-6" }, description), /* @__PURE__ */ import_react33.default.createElement("div", { className: "flex justify-end gap-3" }, /* @__PURE__ */ import_react33.default.createElement(Button, { variant: "outlined", onClick: handleCancel, disabled: isLoading }, cancelText), /* @__PURE__ */ import_react33.default.createElement(
|
|
2286
2452
|
Button,
|
|
2287
2453
|
{
|
|
2288
2454
|
variant: confirmVariant,
|
|
@@ -2305,7 +2471,7 @@ var AlertDialog = ({
|
|
|
2305
2471
|
variant === "warning" && "text-warning",
|
|
2306
2472
|
variant === "error" && "text-error"
|
|
2307
2473
|
);
|
|
2308
|
-
return /* @__PURE__ */
|
|
2474
|
+
return /* @__PURE__ */ import_react33.default.createElement(Modal, { onClose, ...props }, /* @__PURE__ */ import_react33.default.createElement("h3", { className: cx("text-xl font-semibold mb-2", titleClass) }, title), description && /* @__PURE__ */ import_react33.default.createElement("p", { className: "text-sm text-silver mb-6" }, description), /* @__PURE__ */ import_react33.default.createElement("div", { className: "flex justify-end" }, /* @__PURE__ */ import_react33.default.createElement(Button, { variant: "primary", onClick: onClose }, acknowledgeText)));
|
|
2309
2475
|
};
|
|
2310
2476
|
AlertDialog.displayName = "AlertDialog";
|
|
2311
2477
|
var PromptDialog = ({
|
|
@@ -2321,12 +2487,12 @@ var PromptDialog = ({
|
|
|
2321
2487
|
isLoading = false,
|
|
2322
2488
|
...props
|
|
2323
2489
|
}) => {
|
|
2324
|
-
const [value, setValue] =
|
|
2325
|
-
const handleCancel = (0,
|
|
2490
|
+
const [value, setValue] = import_react33.default.useState(defaultValue);
|
|
2491
|
+
const handleCancel = (0, import_react33.useCallback)(() => {
|
|
2326
2492
|
onCancel?.();
|
|
2327
2493
|
onClose();
|
|
2328
2494
|
}, [onCancel, onClose]);
|
|
2329
|
-
const handleSubmit = (0,
|
|
2495
|
+
const handleSubmit = (0, import_react33.useCallback)(
|
|
2330
2496
|
async (e) => {
|
|
2331
2497
|
e.preventDefault();
|
|
2332
2498
|
await onSubmit(value);
|
|
@@ -2334,7 +2500,7 @@ var PromptDialog = ({
|
|
|
2334
2500
|
},
|
|
2335
2501
|
[onSubmit, value, onClose]
|
|
2336
2502
|
);
|
|
2337
|
-
return /* @__PURE__ */
|
|
2503
|
+
return /* @__PURE__ */ import_react33.default.createElement(Modal, { title, onClose, ...props }, /* @__PURE__ */ import_react33.default.createElement("form", { onSubmit: handleSubmit }, description && /* @__PURE__ */ import_react33.default.createElement("p", { className: "text-sm text-silver mb-4" }, description), /* @__PURE__ */ import_react33.default.createElement(
|
|
2338
2504
|
"input",
|
|
2339
2505
|
{
|
|
2340
2506
|
type: "text",
|
|
@@ -2349,7 +2515,7 @@ var PromptDialog = ({
|
|
|
2349
2515
|
),
|
|
2350
2516
|
autoFocus: true
|
|
2351
2517
|
}
|
|
2352
|
-
), /* @__PURE__ */
|
|
2518
|
+
), /* @__PURE__ */ import_react33.default.createElement("div", { className: "flex justify-end gap-3" }, /* @__PURE__ */ import_react33.default.createElement(
|
|
2353
2519
|
Button,
|
|
2354
2520
|
{
|
|
2355
2521
|
type: "button",
|
|
@@ -2358,27 +2524,27 @@ var PromptDialog = ({
|
|
|
2358
2524
|
disabled: isLoading
|
|
2359
2525
|
},
|
|
2360
2526
|
cancelText
|
|
2361
|
-
), /* @__PURE__ */
|
|
2527
|
+
), /* @__PURE__ */ import_react33.default.createElement(Button, { type: "submit", variant: "important", loading: isLoading }, submitText))));
|
|
2362
2528
|
};
|
|
2363
2529
|
PromptDialog.displayName = "PromptDialog";
|
|
2364
2530
|
|
|
2365
2531
|
// src/components/Tabs.tsx
|
|
2366
|
-
var
|
|
2367
|
-
var TabsContext = (0,
|
|
2532
|
+
var import_react34 = __toESM(require("react"));
|
|
2533
|
+
var TabsContext = (0, import_react34.createContext)(null);
|
|
2368
2534
|
function useTabsContext() {
|
|
2369
|
-
const context = (0,
|
|
2535
|
+
const context = (0, import_react34.useContext)(TabsContext);
|
|
2370
2536
|
if (!context) {
|
|
2371
2537
|
throw new Error("Tabs components must be used within a Tabs provider");
|
|
2372
2538
|
}
|
|
2373
2539
|
return context;
|
|
2374
2540
|
}
|
|
2375
|
-
var Tabs =
|
|
2541
|
+
var Tabs = import_react34.default.forwardRef(
|
|
2376
2542
|
({ defaultValue, value, onValueChange, children, className, ...props }, ref) => {
|
|
2377
|
-
const [internalValue, setInternalValue] = (0,
|
|
2543
|
+
const [internalValue, setInternalValue] = (0, import_react34.useState)(defaultValue ?? "");
|
|
2378
2544
|
const isControlled = value !== void 0;
|
|
2379
2545
|
const activeTab = isControlled ? value : internalValue;
|
|
2380
|
-
const baseId = (0,
|
|
2381
|
-
const setActiveTab = (0,
|
|
2546
|
+
const baseId = (0, import_react34.useId)();
|
|
2547
|
+
const setActiveTab = (0, import_react34.useCallback)(
|
|
2382
2548
|
(id) => {
|
|
2383
2549
|
if (!isControlled) {
|
|
2384
2550
|
setInternalValue(id);
|
|
@@ -2387,13 +2553,13 @@ var Tabs = import_react32.default.forwardRef(
|
|
|
2387
2553
|
},
|
|
2388
2554
|
[isControlled, onValueChange]
|
|
2389
2555
|
);
|
|
2390
|
-
return /* @__PURE__ */
|
|
2556
|
+
return /* @__PURE__ */ import_react34.default.createElement(TabsContext.Provider, { value: { activeTab, setActiveTab, baseId } }, /* @__PURE__ */ import_react34.default.createElement("div", { ref, className: cx("w-full", className), ...props }, children));
|
|
2391
2557
|
}
|
|
2392
2558
|
);
|
|
2393
2559
|
Tabs.displayName = "Tabs";
|
|
2394
|
-
var TabList =
|
|
2560
|
+
var TabList = import_react34.default.forwardRef(
|
|
2395
2561
|
({ children, className, ...props }, ref) => {
|
|
2396
|
-
return /* @__PURE__ */
|
|
2562
|
+
return /* @__PURE__ */ import_react34.default.createElement(
|
|
2397
2563
|
"div",
|
|
2398
2564
|
{
|
|
2399
2565
|
ref,
|
|
@@ -2409,13 +2575,13 @@ var TabList = import_react32.default.forwardRef(
|
|
|
2409
2575
|
}
|
|
2410
2576
|
);
|
|
2411
2577
|
TabList.displayName = "TabList";
|
|
2412
|
-
var Tab =
|
|
2578
|
+
var Tab = import_react34.default.forwardRef(
|
|
2413
2579
|
({ value, children, className, disabled, ...props }, ref) => {
|
|
2414
2580
|
const { activeTab, setActiveTab, baseId } = useTabsContext();
|
|
2415
2581
|
const isActive = activeTab === value;
|
|
2416
2582
|
const panelId = `${baseId}-panel-${value}`;
|
|
2417
2583
|
const tabId = `${baseId}-tab-${value}`;
|
|
2418
|
-
return /* @__PURE__ */
|
|
2584
|
+
return /* @__PURE__ */ import_react34.default.createElement(
|
|
2419
2585
|
"button",
|
|
2420
2586
|
{
|
|
2421
2587
|
ref,
|
|
@@ -2442,7 +2608,7 @@ var Tab = import_react32.default.forwardRef(
|
|
|
2442
2608
|
}
|
|
2443
2609
|
);
|
|
2444
2610
|
Tab.displayName = "Tab";
|
|
2445
|
-
var TabPanel =
|
|
2611
|
+
var TabPanel = import_react34.default.forwardRef(
|
|
2446
2612
|
({ value, forceMount = false, children, className, ...props }, ref) => {
|
|
2447
2613
|
const { activeTab, baseId } = useTabsContext();
|
|
2448
2614
|
const isActive = activeTab === value;
|
|
@@ -2451,7 +2617,7 @@ var TabPanel = import_react32.default.forwardRef(
|
|
|
2451
2617
|
if (!isActive && !forceMount) {
|
|
2452
2618
|
return null;
|
|
2453
2619
|
}
|
|
2454
|
-
return /* @__PURE__ */
|
|
2620
|
+
return /* @__PURE__ */ import_react34.default.createElement(
|
|
2455
2621
|
"div",
|
|
2456
2622
|
{
|
|
2457
2623
|
ref,
|
|
@@ -2474,19 +2640,19 @@ var TabPanel = import_react32.default.forwardRef(
|
|
|
2474
2640
|
TabPanel.displayName = "TabPanel";
|
|
2475
2641
|
|
|
2476
2642
|
// src/components/Accordion.tsx
|
|
2477
|
-
var
|
|
2478
|
-
var
|
|
2479
|
-
var AccordionContext = (0,
|
|
2643
|
+
var import_react35 = __toESM(require("react"));
|
|
2644
|
+
var import_lucide_react7 = require("lucide-react");
|
|
2645
|
+
var AccordionContext = (0, import_react35.createContext)(null);
|
|
2480
2646
|
function useAccordionContext() {
|
|
2481
|
-
const context = (0,
|
|
2647
|
+
const context = (0, import_react35.useContext)(AccordionContext);
|
|
2482
2648
|
if (!context) {
|
|
2483
2649
|
throw new Error("Accordion components must be used within an Accordion provider");
|
|
2484
2650
|
}
|
|
2485
2651
|
return context;
|
|
2486
2652
|
}
|
|
2487
|
-
var Accordion =
|
|
2653
|
+
var Accordion = import_react35.default.forwardRef(
|
|
2488
2654
|
({ type = "single", defaultValue, value, onValueChange, children, className, ...props }, ref) => {
|
|
2489
|
-
const [internalValue, setInternalValue] = (0,
|
|
2655
|
+
const [internalValue, setInternalValue] = (0, import_react35.useState)(() => {
|
|
2490
2656
|
if (defaultValue) {
|
|
2491
2657
|
return new Set(Array.isArray(defaultValue) ? defaultValue : [defaultValue]);
|
|
2492
2658
|
}
|
|
@@ -2494,7 +2660,7 @@ var Accordion = import_react33.default.forwardRef(
|
|
|
2494
2660
|
});
|
|
2495
2661
|
const isControlled = value !== void 0;
|
|
2496
2662
|
const expandedItems = isControlled ? new Set(Array.isArray(value) ? value : [value]) : internalValue;
|
|
2497
|
-
const toggleItem = (0,
|
|
2663
|
+
const toggleItem = (0, import_react35.useCallback)(
|
|
2498
2664
|
(id) => {
|
|
2499
2665
|
const newSet = new Set(expandedItems);
|
|
2500
2666
|
if (newSet.has(id)) {
|
|
@@ -2513,7 +2679,7 @@ var Accordion = import_react33.default.forwardRef(
|
|
|
2513
2679
|
},
|
|
2514
2680
|
[expandedItems, type, isControlled, onValueChange]
|
|
2515
2681
|
);
|
|
2516
|
-
return /* @__PURE__ */
|
|
2682
|
+
return /* @__PURE__ */ import_react35.default.createElement(AccordionContext.Provider, { value: { expandedItems, toggleItem, type } }, /* @__PURE__ */ import_react35.default.createElement(
|
|
2517
2683
|
"div",
|
|
2518
2684
|
{
|
|
2519
2685
|
ref,
|
|
@@ -2525,10 +2691,10 @@ var Accordion = import_react33.default.forwardRef(
|
|
|
2525
2691
|
}
|
|
2526
2692
|
);
|
|
2527
2693
|
Accordion.displayName = "Accordion";
|
|
2528
|
-
var AccordionItemContext = (0,
|
|
2529
|
-
var AccordionItem =
|
|
2694
|
+
var AccordionItemContext = (0, import_react35.createContext)(null);
|
|
2695
|
+
var AccordionItem = import_react35.default.forwardRef(
|
|
2530
2696
|
({ value, disabled = false, children, className, ...props }, ref) => {
|
|
2531
|
-
return /* @__PURE__ */
|
|
2697
|
+
return /* @__PURE__ */ import_react35.default.createElement(AccordionItemContext.Provider, { value: { value, disabled } }, /* @__PURE__ */ import_react35.default.createElement(
|
|
2532
2698
|
"div",
|
|
2533
2699
|
{
|
|
2534
2700
|
ref,
|
|
@@ -2541,17 +2707,17 @@ var AccordionItem = import_react33.default.forwardRef(
|
|
|
2541
2707
|
}
|
|
2542
2708
|
);
|
|
2543
2709
|
AccordionItem.displayName = "AccordionItem";
|
|
2544
|
-
var AccordionTrigger =
|
|
2710
|
+
var AccordionTrigger = import_react35.default.forwardRef(
|
|
2545
2711
|
({ children, className, ...props }, ref) => {
|
|
2546
2712
|
const { expandedItems, toggleItem } = useAccordionContext();
|
|
2547
|
-
const itemContext = (0,
|
|
2548
|
-
const baseId = (0,
|
|
2713
|
+
const itemContext = (0, import_react35.useContext)(AccordionItemContext);
|
|
2714
|
+
const baseId = (0, import_react35.useId)();
|
|
2549
2715
|
if (!itemContext) {
|
|
2550
2716
|
throw new Error("AccordionTrigger must be used within an AccordionItem");
|
|
2551
2717
|
}
|
|
2552
2718
|
const { value, disabled } = itemContext;
|
|
2553
2719
|
const isExpanded = expandedItems.has(value);
|
|
2554
|
-
return /* @__PURE__ */
|
|
2720
|
+
return /* @__PURE__ */ import_react35.default.createElement("h3", { className: "m-0" }, /* @__PURE__ */ import_react35.default.createElement(
|
|
2555
2721
|
"button",
|
|
2556
2722
|
{
|
|
2557
2723
|
ref,
|
|
@@ -2572,9 +2738,9 @@ var AccordionTrigger = import_react33.default.forwardRef(
|
|
|
2572
2738
|
),
|
|
2573
2739
|
...props
|
|
2574
2740
|
},
|
|
2575
|
-
/* @__PURE__ */
|
|
2576
|
-
/* @__PURE__ */
|
|
2577
|
-
|
|
2741
|
+
/* @__PURE__ */ import_react35.default.createElement("span", null, children),
|
|
2742
|
+
/* @__PURE__ */ import_react35.default.createElement(
|
|
2743
|
+
import_lucide_react7.ChevronDown,
|
|
2578
2744
|
{
|
|
2579
2745
|
className: cx(
|
|
2580
2746
|
"h-4 w-4 text-silver transition-transform duration-200",
|
|
@@ -2586,17 +2752,17 @@ var AccordionTrigger = import_react33.default.forwardRef(
|
|
|
2586
2752
|
}
|
|
2587
2753
|
);
|
|
2588
2754
|
AccordionTrigger.displayName = "AccordionTrigger";
|
|
2589
|
-
var AccordionContent =
|
|
2755
|
+
var AccordionContent = import_react35.default.forwardRef(
|
|
2590
2756
|
({ children, className, ...props }, ref) => {
|
|
2591
2757
|
const { expandedItems } = useAccordionContext();
|
|
2592
|
-
const itemContext = (0,
|
|
2593
|
-
const baseId = (0,
|
|
2758
|
+
const itemContext = (0, import_react35.useContext)(AccordionItemContext);
|
|
2759
|
+
const baseId = (0, import_react35.useId)();
|
|
2594
2760
|
if (!itemContext) {
|
|
2595
2761
|
throw new Error("AccordionContent must be used within an AccordionItem");
|
|
2596
2762
|
}
|
|
2597
2763
|
const { value } = itemContext;
|
|
2598
2764
|
const isExpanded = expandedItems.has(value);
|
|
2599
|
-
return /* @__PURE__ */
|
|
2765
|
+
return /* @__PURE__ */ import_react35.default.createElement(
|
|
2600
2766
|
"div",
|
|
2601
2767
|
{
|
|
2602
2768
|
ref,
|
|
@@ -2611,28 +2777,28 @@ var AccordionContent = import_react33.default.forwardRef(
|
|
|
2611
2777
|
),
|
|
2612
2778
|
...props
|
|
2613
2779
|
},
|
|
2614
|
-
/* @__PURE__ */
|
|
2780
|
+
/* @__PURE__ */ import_react35.default.createElement("div", { className: "px-4 pb-4 text-sm text-silver" }, children)
|
|
2615
2781
|
);
|
|
2616
2782
|
}
|
|
2617
2783
|
);
|
|
2618
2784
|
AccordionContent.displayName = "AccordionContent";
|
|
2619
2785
|
|
|
2620
2786
|
// src/components/Menu.tsx
|
|
2621
|
-
var
|
|
2622
|
-
var MenuContext = (0,
|
|
2787
|
+
var import_react36 = __toESM(require("react"));
|
|
2788
|
+
var MenuContext = (0, import_react36.createContext)(null);
|
|
2623
2789
|
function useMenuContext() {
|
|
2624
|
-
const context = (0,
|
|
2790
|
+
const context = (0, import_react36.useContext)(MenuContext);
|
|
2625
2791
|
if (!context) {
|
|
2626
2792
|
throw new Error("Menu components must be used within a Menu provider");
|
|
2627
2793
|
}
|
|
2628
2794
|
return context;
|
|
2629
2795
|
}
|
|
2630
2796
|
var Menu = ({ children, open, onOpenChange }) => {
|
|
2631
|
-
const [internalOpen, setInternalOpen] = (0,
|
|
2797
|
+
const [internalOpen, setInternalOpen] = (0, import_react36.useState)(false);
|
|
2632
2798
|
const isControlled = open !== void 0;
|
|
2633
2799
|
const isOpen = isControlled ? open : internalOpen;
|
|
2634
|
-
const baseId = (0,
|
|
2635
|
-
const setIsOpen = (0,
|
|
2800
|
+
const baseId = (0, import_react36.useId)();
|
|
2801
|
+
const setIsOpen = (0, import_react36.useCallback)(
|
|
2636
2802
|
(newOpen) => {
|
|
2637
2803
|
if (!isControlled) {
|
|
2638
2804
|
setInternalOpen(newOpen);
|
|
@@ -2641,7 +2807,7 @@ var Menu = ({ children, open, onOpenChange }) => {
|
|
|
2641
2807
|
},
|
|
2642
2808
|
[isControlled, onOpenChange]
|
|
2643
2809
|
);
|
|
2644
|
-
return /* @__PURE__ */
|
|
2810
|
+
return /* @__PURE__ */ import_react36.default.createElement(
|
|
2645
2811
|
MenuContext.Provider,
|
|
2646
2812
|
{
|
|
2647
2813
|
value: {
|
|
@@ -2651,11 +2817,11 @@ var Menu = ({ children, open, onOpenChange }) => {
|
|
|
2651
2817
|
menuId: `${baseId}-menu`
|
|
2652
2818
|
}
|
|
2653
2819
|
},
|
|
2654
|
-
/* @__PURE__ */
|
|
2820
|
+
/* @__PURE__ */ import_react36.default.createElement("div", { className: "relative inline-block" }, children)
|
|
2655
2821
|
);
|
|
2656
2822
|
};
|
|
2657
2823
|
Menu.displayName = "Menu";
|
|
2658
|
-
var MenuTrigger =
|
|
2824
|
+
var MenuTrigger = import_react36.default.forwardRef(
|
|
2659
2825
|
({ children, className, asChild, ...props }, ref) => {
|
|
2660
2826
|
const { isOpen, setIsOpen, triggerId, menuId } = useMenuContext();
|
|
2661
2827
|
const handleClick = (e) => {
|
|
@@ -2663,7 +2829,7 @@ var MenuTrigger = import_react34.default.forwardRef(
|
|
|
2663
2829
|
setIsOpen(!isOpen);
|
|
2664
2830
|
props.onClick?.(e);
|
|
2665
2831
|
};
|
|
2666
|
-
return /* @__PURE__ */
|
|
2832
|
+
return /* @__PURE__ */ import_react36.default.createElement(
|
|
2667
2833
|
"button",
|
|
2668
2834
|
{
|
|
2669
2835
|
ref,
|
|
@@ -2684,11 +2850,11 @@ var MenuTrigger = import_react34.default.forwardRef(
|
|
|
2684
2850
|
}
|
|
2685
2851
|
);
|
|
2686
2852
|
MenuTrigger.displayName = "MenuTrigger";
|
|
2687
|
-
var MenuContent =
|
|
2853
|
+
var MenuContent = import_react36.default.forwardRef(
|
|
2688
2854
|
({ children, className, align = "start", side = "bottom", ...props }, ref) => {
|
|
2689
2855
|
const { isOpen, setIsOpen, triggerId, menuId } = useMenuContext();
|
|
2690
|
-
const menuRef = (0,
|
|
2691
|
-
(0,
|
|
2856
|
+
const menuRef = (0, import_react36.useRef)(null);
|
|
2857
|
+
(0, import_react36.useEffect)(() => {
|
|
2692
2858
|
if (!isOpen) return;
|
|
2693
2859
|
const handleClickOutside = (e) => {
|
|
2694
2860
|
const trigger = document.getElementById(triggerId);
|
|
@@ -2718,7 +2884,7 @@ var MenuContent = import_react34.default.forwardRef(
|
|
|
2718
2884
|
top: "bottom-full mb-1",
|
|
2719
2885
|
bottom: "top-full mt-1"
|
|
2720
2886
|
};
|
|
2721
|
-
return /* @__PURE__ */
|
|
2887
|
+
return /* @__PURE__ */ import_react36.default.createElement(
|
|
2722
2888
|
"div",
|
|
2723
2889
|
{
|
|
2724
2890
|
ref: (node) => {
|
|
@@ -2744,7 +2910,7 @@ var MenuContent = import_react34.default.forwardRef(
|
|
|
2744
2910
|
}
|
|
2745
2911
|
);
|
|
2746
2912
|
MenuContent.displayName = "MenuContent";
|
|
2747
|
-
var MenuItem =
|
|
2913
|
+
var MenuItem = import_react36.default.forwardRef(
|
|
2748
2914
|
({ children, className, icon, destructive, disabled, onClick, ...props }, ref) => {
|
|
2749
2915
|
const { setIsOpen } = useMenuContext();
|
|
2750
2916
|
const handleClick = (e) => {
|
|
@@ -2752,7 +2918,7 @@ var MenuItem = import_react34.default.forwardRef(
|
|
|
2752
2918
|
onClick?.(e);
|
|
2753
2919
|
setIsOpen(false);
|
|
2754
2920
|
};
|
|
2755
|
-
return /* @__PURE__ */
|
|
2921
|
+
return /* @__PURE__ */ import_react36.default.createElement(
|
|
2756
2922
|
"button",
|
|
2757
2923
|
{
|
|
2758
2924
|
ref,
|
|
@@ -2770,13 +2936,13 @@ var MenuItem = import_react34.default.forwardRef(
|
|
|
2770
2936
|
),
|
|
2771
2937
|
...props
|
|
2772
2938
|
},
|
|
2773
|
-
icon && /* @__PURE__ */
|
|
2939
|
+
icon && /* @__PURE__ */ import_react36.default.createElement("span", { className: "w-4 h-4 shrink-0" }, icon),
|
|
2774
2940
|
children
|
|
2775
2941
|
);
|
|
2776
2942
|
}
|
|
2777
2943
|
);
|
|
2778
2944
|
MenuItem.displayName = "MenuItem";
|
|
2779
|
-
var MenuSeparator =
|
|
2945
|
+
var MenuSeparator = import_react36.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ import_react36.default.createElement(
|
|
2780
2946
|
"div",
|
|
2781
2947
|
{
|
|
2782
2948
|
ref,
|
|
@@ -2786,7 +2952,7 @@ var MenuSeparator = import_react34.default.forwardRef(({ className, ...props },
|
|
|
2786
2952
|
}
|
|
2787
2953
|
));
|
|
2788
2954
|
MenuSeparator.displayName = "MenuSeparator";
|
|
2789
|
-
var MenuLabel =
|
|
2955
|
+
var MenuLabel = import_react36.default.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ import_react36.default.createElement(
|
|
2790
2956
|
"div",
|
|
2791
2957
|
{
|
|
2792
2958
|
ref,
|
|
@@ -2798,10 +2964,10 @@ var MenuLabel = import_react34.default.forwardRef(({ className, children, ...pro
|
|
|
2798
2964
|
MenuLabel.displayName = "MenuLabel";
|
|
2799
2965
|
|
|
2800
2966
|
// src/components/Navbar.tsx
|
|
2801
|
-
var
|
|
2802
|
-
var Navbar =
|
|
2967
|
+
var import_react37 = __toESM(require("react"));
|
|
2968
|
+
var Navbar = import_react37.default.forwardRef(
|
|
2803
2969
|
({ fixed = false, bordered = true, className, children, ...props }, ref) => {
|
|
2804
|
-
return /* @__PURE__ */
|
|
2970
|
+
return /* @__PURE__ */ import_react37.default.createElement(
|
|
2805
2971
|
"nav",
|
|
2806
2972
|
{
|
|
2807
2973
|
ref,
|
|
@@ -2813,14 +2979,14 @@ var Navbar = import_react35.default.forwardRef(
|
|
|
2813
2979
|
),
|
|
2814
2980
|
...props
|
|
2815
2981
|
},
|
|
2816
|
-
/* @__PURE__ */
|
|
2982
|
+
/* @__PURE__ */ import_react37.default.createElement("div", { className: "flex items-center justify-between" }, children)
|
|
2817
2983
|
);
|
|
2818
2984
|
}
|
|
2819
2985
|
);
|
|
2820
2986
|
Navbar.displayName = "Navbar";
|
|
2821
|
-
var NavbarBrand =
|
|
2987
|
+
var NavbarBrand = import_react37.default.forwardRef(
|
|
2822
2988
|
({ className, children, ...props }, ref) => {
|
|
2823
|
-
return /* @__PURE__ */
|
|
2989
|
+
return /* @__PURE__ */ import_react37.default.createElement(
|
|
2824
2990
|
"div",
|
|
2825
2991
|
{
|
|
2826
2992
|
ref,
|
|
@@ -2832,14 +2998,14 @@ var NavbarBrand = import_react35.default.forwardRef(
|
|
|
2832
2998
|
}
|
|
2833
2999
|
);
|
|
2834
3000
|
NavbarBrand.displayName = "NavbarBrand";
|
|
2835
|
-
var NavbarContent =
|
|
3001
|
+
var NavbarContent = import_react37.default.forwardRef(
|
|
2836
3002
|
({ position = "center", className, children, ...props }, ref) => {
|
|
2837
3003
|
const positionClasses = {
|
|
2838
3004
|
start: "mr-auto",
|
|
2839
3005
|
center: "mx-auto",
|
|
2840
3006
|
end: "ml-auto"
|
|
2841
3007
|
};
|
|
2842
|
-
return /* @__PURE__ */
|
|
3008
|
+
return /* @__PURE__ */ import_react37.default.createElement(
|
|
2843
3009
|
"div",
|
|
2844
3010
|
{
|
|
2845
3011
|
ref,
|
|
@@ -2855,9 +3021,9 @@ var NavbarContent = import_react35.default.forwardRef(
|
|
|
2855
3021
|
}
|
|
2856
3022
|
);
|
|
2857
3023
|
NavbarContent.displayName = "NavbarContent";
|
|
2858
|
-
var NavbarItem =
|
|
3024
|
+
var NavbarItem = import_react37.default.forwardRef(
|
|
2859
3025
|
({ active = false, className, children, ...props }, ref) => {
|
|
2860
|
-
return /* @__PURE__ */
|
|
3026
|
+
return /* @__PURE__ */ import_react37.default.createElement(
|
|
2861
3027
|
"div",
|
|
2862
3028
|
{
|
|
2863
3029
|
ref,
|
|
@@ -2872,9 +3038,9 @@ var NavbarItem = import_react35.default.forwardRef(
|
|
|
2872
3038
|
}
|
|
2873
3039
|
);
|
|
2874
3040
|
NavbarItem.displayName = "NavbarItem";
|
|
2875
|
-
var NavbarLink =
|
|
3041
|
+
var NavbarLink = import_react37.default.forwardRef(
|
|
2876
3042
|
({ active = false, className, children, ...props }, ref) => {
|
|
2877
|
-
return /* @__PURE__ */
|
|
3043
|
+
return /* @__PURE__ */ import_react37.default.createElement(
|
|
2878
3044
|
"a",
|
|
2879
3045
|
{
|
|
2880
3046
|
ref,
|
|
@@ -2890,7 +3056,7 @@ var NavbarLink = import_react35.default.forwardRef(
|
|
|
2890
3056
|
}
|
|
2891
3057
|
);
|
|
2892
3058
|
NavbarLink.displayName = "NavbarLink";
|
|
2893
|
-
var NavbarDivider =
|
|
3059
|
+
var NavbarDivider = import_react37.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ import_react37.default.createElement(
|
|
2894
3060
|
"div",
|
|
2895
3061
|
{
|
|
2896
3062
|
ref,
|
|
@@ -2901,19 +3067,19 @@ var NavbarDivider = import_react35.default.forwardRef(({ className, ...props },
|
|
|
2901
3067
|
NavbarDivider.displayName = "NavbarDivider";
|
|
2902
3068
|
|
|
2903
3069
|
// src/components/Breadcrumb.tsx
|
|
2904
|
-
var
|
|
2905
|
-
var
|
|
2906
|
-
var Breadcrumb =
|
|
3070
|
+
var import_react38 = __toESM(require("react"));
|
|
3071
|
+
var import_lucide_react8 = require("lucide-react");
|
|
3072
|
+
var Breadcrumb = import_react38.default.forwardRef(
|
|
2907
3073
|
({ separator, className, children, ...props }, ref) => {
|
|
2908
|
-
const items =
|
|
2909
|
-
const defaultSeparator = /* @__PURE__ */
|
|
2910
|
-
return /* @__PURE__ */
|
|
3074
|
+
const items = import_react38.default.Children.toArray(children);
|
|
3075
|
+
const defaultSeparator = /* @__PURE__ */ import_react38.default.createElement(import_lucide_react8.ChevronRight, { className: "h-4 w-4 text-ash" });
|
|
3076
|
+
return /* @__PURE__ */ import_react38.default.createElement("nav", { ref, "aria-label": "Breadcrumb", className, ...props }, /* @__PURE__ */ import_react38.default.createElement("ol", { className: "flex items-center gap-2" }, items.map((child, index) => /* @__PURE__ */ import_react38.default.createElement("li", { key: index, className: "flex items-center gap-2" }, child, index < items.length - 1 && /* @__PURE__ */ import_react38.default.createElement("span", { "aria-hidden": "true" }, separator ?? defaultSeparator)))));
|
|
2911
3077
|
}
|
|
2912
3078
|
);
|
|
2913
3079
|
Breadcrumb.displayName = "Breadcrumb";
|
|
2914
|
-
var BreadcrumbItem =
|
|
3080
|
+
var BreadcrumbItem = import_react38.default.forwardRef(
|
|
2915
3081
|
({ current = false, className, children, ...props }, ref) => {
|
|
2916
|
-
return /* @__PURE__ */
|
|
3082
|
+
return /* @__PURE__ */ import_react38.default.createElement(
|
|
2917
3083
|
"span",
|
|
2918
3084
|
{
|
|
2919
3085
|
ref,
|
|
@@ -2930,9 +3096,9 @@ var BreadcrumbItem = import_react36.default.forwardRef(
|
|
|
2930
3096
|
}
|
|
2931
3097
|
);
|
|
2932
3098
|
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
2933
|
-
var BreadcrumbLink =
|
|
3099
|
+
var BreadcrumbLink = import_react38.default.forwardRef(
|
|
2934
3100
|
({ className, children, ...props }, ref) => {
|
|
2935
|
-
return /* @__PURE__ */
|
|
3101
|
+
return /* @__PURE__ */ import_react38.default.createElement(
|
|
2936
3102
|
"a",
|
|
2937
3103
|
{
|
|
2938
3104
|
ref,
|
|
@@ -2949,8 +3115,8 @@ var BreadcrumbLink = import_react36.default.forwardRef(
|
|
|
2949
3115
|
BreadcrumbLink.displayName = "BreadcrumbLink";
|
|
2950
3116
|
|
|
2951
3117
|
// src/components/Pagination.tsx
|
|
2952
|
-
var
|
|
2953
|
-
var
|
|
3118
|
+
var import_react39 = __toESM(require("react"));
|
|
3119
|
+
var import_lucide_react9 = require("lucide-react");
|
|
2954
3120
|
function generatePagination(currentPage, totalPages, siblingCount) {
|
|
2955
3121
|
const totalSlots = siblingCount * 2 + 5;
|
|
2956
3122
|
if (totalPages <= totalSlots) {
|
|
@@ -2979,7 +3145,7 @@ function generatePagination(currentPage, totalPages, siblingCount) {
|
|
|
2979
3145
|
);
|
|
2980
3146
|
return [1, "ellipsis", ...middleRange, "ellipsis", totalPages];
|
|
2981
3147
|
}
|
|
2982
|
-
var Pagination =
|
|
3148
|
+
var Pagination = import_react39.default.forwardRef(
|
|
2983
3149
|
({
|
|
2984
3150
|
page,
|
|
2985
3151
|
totalPages,
|
|
@@ -2991,7 +3157,7 @@ var Pagination = import_react37.default.forwardRef(
|
|
|
2991
3157
|
}, ref) => {
|
|
2992
3158
|
const pages = generatePagination(page, totalPages, siblingCount);
|
|
2993
3159
|
const buttonBaseClass = "flex items-center justify-center h-8 min-w-8 px-2 text-sm border border-ash transition-colors duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gold";
|
|
2994
|
-
return /* @__PURE__ */
|
|
3160
|
+
return /* @__PURE__ */ import_react39.default.createElement(
|
|
2995
3161
|
"nav",
|
|
2996
3162
|
{
|
|
2997
3163
|
ref,
|
|
@@ -3000,7 +3166,7 @@ var Pagination = import_react37.default.forwardRef(
|
|
|
3000
3166
|
className: cx("flex items-center gap-1", className),
|
|
3001
3167
|
...props
|
|
3002
3168
|
},
|
|
3003
|
-
/* @__PURE__ */
|
|
3169
|
+
/* @__PURE__ */ import_react39.default.createElement(
|
|
3004
3170
|
"button",
|
|
3005
3171
|
{
|
|
3006
3172
|
type: "button",
|
|
@@ -3013,17 +3179,17 @@ var Pagination = import_react37.default.forwardRef(
|
|
|
3013
3179
|
page <= 1 && "opacity-50 cursor-not-allowed hover:border-ash"
|
|
3014
3180
|
)
|
|
3015
3181
|
},
|
|
3016
|
-
/* @__PURE__ */
|
|
3182
|
+
/* @__PURE__ */ import_react39.default.createElement(import_lucide_react9.ChevronLeft, { className: "h-4 w-4" })
|
|
3017
3183
|
),
|
|
3018
3184
|
pages.map(
|
|
3019
|
-
(pageNum, index) => pageNum === "ellipsis" ? /* @__PURE__ */
|
|
3185
|
+
(pageNum, index) => pageNum === "ellipsis" ? /* @__PURE__ */ import_react39.default.createElement(
|
|
3020
3186
|
"span",
|
|
3021
3187
|
{
|
|
3022
3188
|
key: `ellipsis-${index}`,
|
|
3023
3189
|
className: "flex items-center justify-center h-8 w-8 text-silver"
|
|
3024
3190
|
},
|
|
3025
|
-
/* @__PURE__ */
|
|
3026
|
-
) : /* @__PURE__ */
|
|
3191
|
+
/* @__PURE__ */ import_react39.default.createElement(import_lucide_react9.MoreHorizontal, { className: "h-4 w-4" })
|
|
3192
|
+
) : /* @__PURE__ */ import_react39.default.createElement(
|
|
3027
3193
|
"button",
|
|
3028
3194
|
{
|
|
3029
3195
|
key: pageNum,
|
|
@@ -3039,7 +3205,7 @@ var Pagination = import_react37.default.forwardRef(
|
|
|
3039
3205
|
pageNum
|
|
3040
3206
|
)
|
|
3041
3207
|
),
|
|
3042
|
-
/* @__PURE__ */
|
|
3208
|
+
/* @__PURE__ */ import_react39.default.createElement(
|
|
3043
3209
|
"button",
|
|
3044
3210
|
{
|
|
3045
3211
|
type: "button",
|
|
@@ -3052,7 +3218,7 @@ var Pagination = import_react37.default.forwardRef(
|
|
|
3052
3218
|
page >= totalPages && "opacity-50 cursor-not-allowed hover:border-ash"
|
|
3053
3219
|
)
|
|
3054
3220
|
},
|
|
3055
|
-
/* @__PURE__ */
|
|
3221
|
+
/* @__PURE__ */ import_react39.default.createElement(import_lucide_react9.ChevronRight, { className: "h-4 w-4" })
|
|
3056
3222
|
)
|
|
3057
3223
|
);
|
|
3058
3224
|
}
|
|
@@ -3060,9 +3226,9 @@ var Pagination = import_react37.default.forwardRef(
|
|
|
3060
3226
|
Pagination.displayName = "Pagination";
|
|
3061
3227
|
|
|
3062
3228
|
// src/components/Stepper.tsx
|
|
3063
|
-
var
|
|
3064
|
-
var
|
|
3065
|
-
var Stepper =
|
|
3229
|
+
var import_react40 = __toESM(require("react"));
|
|
3230
|
+
var import_lucide_react10 = require("lucide-react");
|
|
3231
|
+
var Stepper = import_react40.default.forwardRef(
|
|
3066
3232
|
({ steps, currentStep, status, className, ...rest }, ref) => {
|
|
3067
3233
|
const currentIndex = steps.findIndex((step) => step.id === currentStep);
|
|
3068
3234
|
const getStepState = (index) => {
|
|
@@ -3074,7 +3240,7 @@ var Stepper = import_react38.default.forwardRef(
|
|
|
3074
3240
|
}
|
|
3075
3241
|
return "future";
|
|
3076
3242
|
};
|
|
3077
|
-
return /* @__PURE__ */
|
|
3243
|
+
return /* @__PURE__ */ import_react40.default.createElement(
|
|
3078
3244
|
"div",
|
|
3079
3245
|
{
|
|
3080
3246
|
ref,
|
|
@@ -3084,7 +3250,7 @@ var Stepper = import_react38.default.forwardRef(
|
|
|
3084
3250
|
steps.map((step, index) => {
|
|
3085
3251
|
const state = getStepState(index);
|
|
3086
3252
|
const isLast = index === steps.length - 1;
|
|
3087
|
-
return /* @__PURE__ */
|
|
3253
|
+
return /* @__PURE__ */ import_react40.default.createElement(import_react40.default.Fragment, { key: step.id }, /* @__PURE__ */ import_react40.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react40.default.createElement(
|
|
3088
3254
|
"div",
|
|
3089
3255
|
{
|
|
3090
3256
|
className: cx(
|
|
@@ -3095,8 +3261,8 @@ var Stepper = import_react38.default.forwardRef(
|
|
|
3095
3261
|
state === "future" && "bg-charcoal border-ash text-silver"
|
|
3096
3262
|
)
|
|
3097
3263
|
},
|
|
3098
|
-
state === "complete" ? /* @__PURE__ */
|
|
3099
|
-
), /* @__PURE__ */
|
|
3264
|
+
state === "complete" ? /* @__PURE__ */ import_react40.default.createElement(import_lucide_react10.Check, { className: "h-5 w-5" }) : /* @__PURE__ */ import_react40.default.createElement("span", null, index + 1)
|
|
3265
|
+
), /* @__PURE__ */ import_react40.default.createElement(
|
|
3100
3266
|
"span",
|
|
3101
3267
|
{
|
|
3102
3268
|
className: cx(
|
|
@@ -3108,7 +3274,7 @@ var Stepper = import_react38.default.forwardRef(
|
|
|
3108
3274
|
)
|
|
3109
3275
|
},
|
|
3110
3276
|
step.label
|
|
3111
|
-
)), !isLast && /* @__PURE__ */
|
|
3277
|
+
)), !isLast && /* @__PURE__ */ import_react40.default.createElement(
|
|
3112
3278
|
"div",
|
|
3113
3279
|
{
|
|
3114
3280
|
className: cx(
|
|
@@ -3124,10 +3290,10 @@ var Stepper = import_react38.default.forwardRef(
|
|
|
3124
3290
|
Stepper.displayName = "Stepper";
|
|
3125
3291
|
|
|
3126
3292
|
// src/components/Message.tsx
|
|
3127
|
-
var
|
|
3293
|
+
var import_react42 = __toESM(require("react"));
|
|
3128
3294
|
|
|
3129
3295
|
// src/components/MarkdownContent.tsx
|
|
3130
|
-
var
|
|
3296
|
+
var import_react41 = __toESM(require("react"));
|
|
3131
3297
|
var import_dompurify = __toESM(require("dompurify"));
|
|
3132
3298
|
var DEFAULT_SANITIZE_CONFIG = {
|
|
3133
3299
|
ALLOWED_TAGS: [
|
|
@@ -3197,7 +3363,7 @@ var DEFAULT_SANITIZE_CONFIG = {
|
|
|
3197
3363
|
ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i
|
|
3198
3364
|
};
|
|
3199
3365
|
function useDOMPurifySetup() {
|
|
3200
|
-
(0,
|
|
3366
|
+
(0, import_react41.useMemo)(() => {
|
|
3201
3367
|
import_dompurify.default.addHook("afterSanitizeAttributes", (node) => {
|
|
3202
3368
|
if (node.tagName === "A") {
|
|
3203
3369
|
node.setAttribute("target", "_blank");
|
|
@@ -3206,17 +3372,45 @@ function useDOMPurifySetup() {
|
|
|
3206
3372
|
});
|
|
3207
3373
|
}, []);
|
|
3208
3374
|
}
|
|
3209
|
-
var
|
|
3210
|
-
|
|
3375
|
+
var CURSOR_BASE_CLASSES = "inline-block bg-current animate-cursor-blink w-0.5 h-cursor translate-y-cursor-offset";
|
|
3376
|
+
function injectStreamingCursor(html, cursorClassName) {
|
|
3377
|
+
if (!html.trim()) {
|
|
3378
|
+
return `<span class="${cx(CURSOR_BASE_CLASSES, cursorClassName)}" aria-hidden="true"></span>`;
|
|
3379
|
+
}
|
|
3380
|
+
const cursorHtml = `<span class="${cx(CURSOR_BASE_CLASSES, cursorClassName)}" aria-hidden="true"></span>`;
|
|
3381
|
+
const parser = new DOMParser();
|
|
3382
|
+
const doc = parser.parseFromString(`<div>${html}</div>`, "text/html");
|
|
3383
|
+
const container = doc.body.firstChild;
|
|
3384
|
+
if (!container) {
|
|
3385
|
+
return html + cursorHtml;
|
|
3386
|
+
}
|
|
3387
|
+
let target = container;
|
|
3388
|
+
while (target.lastElementChild) {
|
|
3389
|
+
const lastChild = target.lastElementChild;
|
|
3390
|
+
const tagName = lastChild.tagName.toLowerCase();
|
|
3391
|
+
if (["code", "a", "strong", "em", "b", "i", "span", "mark", "del", "s"].includes(tagName)) {
|
|
3392
|
+
break;
|
|
3393
|
+
}
|
|
3394
|
+
target = lastChild;
|
|
3395
|
+
}
|
|
3396
|
+
target.insertAdjacentHTML("beforeend", cursorHtml);
|
|
3397
|
+
return container.innerHTML;
|
|
3398
|
+
}
|
|
3399
|
+
var MarkdownContent = import_react41.default.forwardRef(
|
|
3400
|
+
({ className, content, sanitizeConfig, isStreaming, cursorClassName, ...rest }, ref) => {
|
|
3211
3401
|
useDOMPurifySetup();
|
|
3212
|
-
const sanitizedHtml = (0,
|
|
3213
|
-
if (!content) {
|
|
3402
|
+
const sanitizedHtml = (0, import_react41.useMemo)(() => {
|
|
3403
|
+
if (!content && !isStreaming) {
|
|
3214
3404
|
return "";
|
|
3215
3405
|
}
|
|
3216
3406
|
const config = sanitizeConfig ?? DEFAULT_SANITIZE_CONFIG;
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3407
|
+
const sanitized = content ? import_dompurify.default.sanitize(content, config) : "";
|
|
3408
|
+
if (isStreaming) {
|
|
3409
|
+
return injectStreamingCursor(sanitized, cursorClassName);
|
|
3410
|
+
}
|
|
3411
|
+
return sanitized;
|
|
3412
|
+
}, [content, sanitizeConfig, isStreaming, cursorClassName]);
|
|
3413
|
+
return /* @__PURE__ */ import_react41.default.createElement(
|
|
3220
3414
|
"div",
|
|
3221
3415
|
{
|
|
3222
3416
|
ref,
|
|
@@ -3229,16 +3423,202 @@ var MarkdownContent = import_react39.default.forwardRef(
|
|
|
3229
3423
|
);
|
|
3230
3424
|
MarkdownContent.displayName = "MarkdownContent";
|
|
3231
3425
|
|
|
3426
|
+
// src/components/Message.tsx
|
|
3427
|
+
var variantStyles2 = {
|
|
3428
|
+
user: "bg-gold text-obsidian ml-auto",
|
|
3429
|
+
assistant: "bg-charcoal border border-ash text-white mr-auto"
|
|
3430
|
+
};
|
|
3431
|
+
var ActionButton = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ import_react42.default.createElement(
|
|
3432
|
+
"button",
|
|
3433
|
+
{
|
|
3434
|
+
type: "button",
|
|
3435
|
+
onClick,
|
|
3436
|
+
disabled,
|
|
3437
|
+
className: cx(
|
|
3438
|
+
"p-1.5 text-silver/60 hover:text-silver transition-colors duration-150",
|
|
3439
|
+
"hover:bg-white/5",
|
|
3440
|
+
"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent",
|
|
3441
|
+
className
|
|
3442
|
+
),
|
|
3443
|
+
"aria-label": label
|
|
3444
|
+
},
|
|
3445
|
+
children
|
|
3446
|
+
);
|
|
3447
|
+
var CopyIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-3.5 h-3.5" }, /* @__PURE__ */ import_react42.default.createElement("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" }));
|
|
3448
|
+
var CheckIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-3.5 h-3.5 text-success" }, /* @__PURE__ */ import_react42.default.createElement("polyline", { points: "20 6 9 17 4 12" }));
|
|
3449
|
+
var PencilIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-3.5 h-3.5" }, /* @__PURE__ */ import_react42.default.createElement("path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "m15 5 4 4" }));
|
|
3450
|
+
var RetryIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-3.5 h-3.5" }, /* @__PURE__ */ import_react42.default.createElement("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "M21 3v5h-5" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "M8 16H3v5" }));
|
|
3451
|
+
var ChevronLeftIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-3 h-3" }, /* @__PURE__ */ import_react42.default.createElement("path", { d: "m15 18-6-6 6-6" }));
|
|
3452
|
+
var ChevronRightIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-3 h-3" }, /* @__PURE__ */ import_react42.default.createElement("path", { d: "m9 18 6-6-6-6" }));
|
|
3453
|
+
var GitBranchIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-3 h-3 mr-0.5 text-silver/50" }, /* @__PURE__ */ import_react42.default.createElement("line", { x1: "6", x2: "6", y1: "3", y2: "15" }), /* @__PURE__ */ import_react42.default.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ import_react42.default.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" }));
|
|
3454
|
+
var XIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-4 h-4" }, /* @__PURE__ */ import_react42.default.createElement("path", { d: "M18 6 6 18" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "m6 6 12 12" }));
|
|
3455
|
+
var SendIcon = () => /* @__PURE__ */ import_react42.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-4 h-4" }, /* @__PURE__ */ import_react42.default.createElement("path", { d: "m22 2-7 20-4-9-9-4Z" }), /* @__PURE__ */ import_react42.default.createElement("path", { d: "M22 2 11 13" }));
|
|
3456
|
+
var Message = import_react42.default.forwardRef(
|
|
3457
|
+
({ variant = "assistant", className, content, isStreaming, branchInfo, actions, hideActions, ...rest }, ref) => {
|
|
3458
|
+
const isUser = variant === "user";
|
|
3459
|
+
const [copied, setCopied] = (0, import_react42.useState)(false);
|
|
3460
|
+
const [isEditing, setIsEditing] = (0, import_react42.useState)(false);
|
|
3461
|
+
const [editValue, setEditValue] = (0, import_react42.useState)(content);
|
|
3462
|
+
const textareaRef = (0, import_react42.useRef)(null);
|
|
3463
|
+
const showBranchNav = branchInfo && branchInfo.total > 1;
|
|
3464
|
+
const showActions = actions && !hideActions && !isStreaming;
|
|
3465
|
+
(0, import_react42.useEffect)(() => {
|
|
3466
|
+
if (isEditing && textareaRef.current) {
|
|
3467
|
+
const textarea = textareaRef.current;
|
|
3468
|
+
textarea.style.height = "auto";
|
|
3469
|
+
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
3470
|
+
textarea.focus();
|
|
3471
|
+
textarea.setSelectionRange(textarea.value.length, textarea.value.length);
|
|
3472
|
+
}
|
|
3473
|
+
}, [isEditing]);
|
|
3474
|
+
const handleCopy = async () => {
|
|
3475
|
+
try {
|
|
3476
|
+
await navigator.clipboard.writeText(content);
|
|
3477
|
+
setCopied(true);
|
|
3478
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
3479
|
+
} catch {
|
|
3480
|
+
const textArea = document.createElement("textarea");
|
|
3481
|
+
textArea.value = content;
|
|
3482
|
+
document.body.appendChild(textArea);
|
|
3483
|
+
textArea.select();
|
|
3484
|
+
document.execCommand("copy");
|
|
3485
|
+
document.body.removeChild(textArea);
|
|
3486
|
+
setCopied(true);
|
|
3487
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
3488
|
+
}
|
|
3489
|
+
};
|
|
3490
|
+
const handleStartEdit = () => {
|
|
3491
|
+
setEditValue(content);
|
|
3492
|
+
setIsEditing(true);
|
|
3493
|
+
};
|
|
3494
|
+
const handleCancelEdit = () => {
|
|
3495
|
+
setIsEditing(false);
|
|
3496
|
+
setEditValue(content);
|
|
3497
|
+
};
|
|
3498
|
+
const handleSubmitEdit = () => {
|
|
3499
|
+
const trimmed = editValue.trim();
|
|
3500
|
+
if (trimmed && trimmed !== content) {
|
|
3501
|
+
actions?.onEdit?.(trimmed);
|
|
3502
|
+
}
|
|
3503
|
+
setIsEditing(false);
|
|
3504
|
+
};
|
|
3505
|
+
const handleEditKeyDown = (e) => {
|
|
3506
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
3507
|
+
e.preventDefault();
|
|
3508
|
+
handleSubmitEdit();
|
|
3509
|
+
} else if (e.key === "Escape") {
|
|
3510
|
+
handleCancelEdit();
|
|
3511
|
+
}
|
|
3512
|
+
};
|
|
3513
|
+
const handleEditChange = (e) => {
|
|
3514
|
+
setEditValue(e.target.value);
|
|
3515
|
+
const textarea = e.target;
|
|
3516
|
+
textarea.style.height = "auto";
|
|
3517
|
+
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
3518
|
+
};
|
|
3519
|
+
return /* @__PURE__ */ import_react42.default.createElement(
|
|
3520
|
+
"div",
|
|
3521
|
+
{
|
|
3522
|
+
ref,
|
|
3523
|
+
className: cx(
|
|
3524
|
+
"flex flex-col",
|
|
3525
|
+
isUser ? "items-end" : "items-start",
|
|
3526
|
+
className
|
|
3527
|
+
),
|
|
3528
|
+
...rest
|
|
3529
|
+
},
|
|
3530
|
+
isUser && isEditing ? /* @__PURE__ */ import_react42.default.createElement("div", { className: "w-full max-w-11/12" }, /* @__PURE__ */ import_react42.default.createElement("div", { className: "relative bg-gold" }, /* @__PURE__ */ import_react42.default.createElement(
|
|
3531
|
+
"textarea",
|
|
3532
|
+
{
|
|
3533
|
+
ref: textareaRef,
|
|
3534
|
+
value: editValue,
|
|
3535
|
+
onChange: handleEditChange,
|
|
3536
|
+
onKeyDown: handleEditKeyDown,
|
|
3537
|
+
className: "w-full bg-transparent text-obsidian px-3 py-2 pr-20 resize-none outline-none min-h-10 text-sm",
|
|
3538
|
+
rows: 1
|
|
3539
|
+
}
|
|
3540
|
+
), /* @__PURE__ */ import_react42.default.createElement("div", { className: "absolute right-1 top-1/2 -translate-y-1/2 flex gap-0.5" }, /* @__PURE__ */ import_react42.default.createElement(
|
|
3541
|
+
"button",
|
|
3542
|
+
{
|
|
3543
|
+
type: "button",
|
|
3544
|
+
onClick: handleCancelEdit,
|
|
3545
|
+
className: "p-1.5 text-obsidian/60 hover:text-obsidian transition-colors",
|
|
3546
|
+
"aria-label": "Cancel edit"
|
|
3547
|
+
},
|
|
3548
|
+
/* @__PURE__ */ import_react42.default.createElement(XIcon, null)
|
|
3549
|
+
), /* @__PURE__ */ import_react42.default.createElement(
|
|
3550
|
+
"button",
|
|
3551
|
+
{
|
|
3552
|
+
type: "button",
|
|
3553
|
+
onClick: handleSubmitEdit,
|
|
3554
|
+
disabled: !editValue.trim() || editValue.trim() === content,
|
|
3555
|
+
className: "p-1.5 text-obsidian/60 hover:text-obsidian transition-colors disabled:opacity-30",
|
|
3556
|
+
"aria-label": "Submit edit"
|
|
3557
|
+
},
|
|
3558
|
+
/* @__PURE__ */ import_react42.default.createElement(SendIcon, null)
|
|
3559
|
+
)))) : /* @__PURE__ */ import_react42.default.createElement(
|
|
3560
|
+
"div",
|
|
3561
|
+
{
|
|
3562
|
+
className: cx(
|
|
3563
|
+
"px-3 py-2 w-fit max-w-11/12",
|
|
3564
|
+
variantStyles2[variant]
|
|
3565
|
+
)
|
|
3566
|
+
},
|
|
3567
|
+
/* @__PURE__ */ import_react42.default.createElement(
|
|
3568
|
+
MarkdownContent,
|
|
3569
|
+
{
|
|
3570
|
+
content,
|
|
3571
|
+
className: cx("prose-sm", isUser ? "prose-inherit" : "prose-invert"),
|
|
3572
|
+
isStreaming,
|
|
3573
|
+
cursorClassName: "ml-0.5"
|
|
3574
|
+
}
|
|
3575
|
+
)
|
|
3576
|
+
),
|
|
3577
|
+
showActions && !isEditing && /* @__PURE__ */ import_react42.default.createElement("div", { className: cx(
|
|
3578
|
+
"flex items-center gap-0.5 mt-1",
|
|
3579
|
+
isUser ? "mr-1" : "ml-1"
|
|
3580
|
+
) }, actions.showCopy !== false && /* @__PURE__ */ import_react42.default.createElement(ActionButton, { onClick: handleCopy, label: copied ? "Copied!" : "Copy message" }, copied ? /* @__PURE__ */ import_react42.default.createElement(CheckIcon, null) : /* @__PURE__ */ import_react42.default.createElement(CopyIcon, null)), isUser && actions.onEdit && /* @__PURE__ */ import_react42.default.createElement(ActionButton, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react42.default.createElement(PencilIcon, null)), !isUser && actions.onRetry && /* @__PURE__ */ import_react42.default.createElement(ActionButton, { onClick: actions.onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react42.default.createElement(RetryIcon, null)), showBranchNav && /* @__PURE__ */ import_react42.default.createElement(import_react42.default.Fragment, null, /* @__PURE__ */ import_react42.default.createElement("div", { className: "w-px h-4 bg-ash/40 mx-1" }), /* @__PURE__ */ import_react42.default.createElement("div", { className: "flex items-center gap-0.5 text-silver/70" }, /* @__PURE__ */ import_react42.default.createElement(GitBranchIcon, null), /* @__PURE__ */ import_react42.default.createElement(
|
|
3581
|
+
"button",
|
|
3582
|
+
{
|
|
3583
|
+
type: "button",
|
|
3584
|
+
onClick: branchInfo.onPrevious,
|
|
3585
|
+
disabled: branchInfo.current <= 1,
|
|
3586
|
+
className: cx(
|
|
3587
|
+
"p-0.5 hover:text-white hover:bg-white/10 transition-colors",
|
|
3588
|
+
"disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-silver/70"
|
|
3589
|
+
),
|
|
3590
|
+
"aria-label": "Previous branch"
|
|
3591
|
+
},
|
|
3592
|
+
/* @__PURE__ */ import_react42.default.createElement(ChevronLeftIcon, null)
|
|
3593
|
+
), /* @__PURE__ */ import_react42.default.createElement("span", { className: "text-xs tabular-nums min-w-6 text-center" }, branchInfo.current, "/", branchInfo.total), /* @__PURE__ */ import_react42.default.createElement(
|
|
3594
|
+
"button",
|
|
3595
|
+
{
|
|
3596
|
+
type: "button",
|
|
3597
|
+
onClick: branchInfo.onNext,
|
|
3598
|
+
disabled: branchInfo.current >= branchInfo.total,
|
|
3599
|
+
className: cx(
|
|
3600
|
+
"p-0.5 hover:text-white hover:bg-white/10 transition-colors",
|
|
3601
|
+
"disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-silver/70"
|
|
3602
|
+
),
|
|
3603
|
+
"aria-label": "Next branch"
|
|
3604
|
+
},
|
|
3605
|
+
/* @__PURE__ */ import_react42.default.createElement(ChevronRightIcon, null)
|
|
3606
|
+
))))
|
|
3607
|
+
);
|
|
3608
|
+
}
|
|
3609
|
+
);
|
|
3610
|
+
Message.displayName = "Message";
|
|
3611
|
+
|
|
3232
3612
|
// src/components/StreamingCursor.tsx
|
|
3233
|
-
var
|
|
3234
|
-
var StreamingCursor =
|
|
3613
|
+
var import_react43 = __toESM(require("react"));
|
|
3614
|
+
var StreamingCursor = import_react43.default.forwardRef(
|
|
3235
3615
|
({ className, variant = "line", ...rest }, ref) => {
|
|
3236
3616
|
const variantStyles3 = {
|
|
3237
3617
|
block: "w-2.5 h-cursor translate-y-cursor-offset",
|
|
3238
3618
|
line: "w-0.5 h-cursor translate-y-cursor-offset",
|
|
3239
3619
|
underscore: "w-2.5 h-0.5 self-end mb-0.5"
|
|
3240
3620
|
};
|
|
3241
|
-
return /* @__PURE__ */
|
|
3621
|
+
return /* @__PURE__ */ import_react43.default.createElement(
|
|
3242
3622
|
"span",
|
|
3243
3623
|
{
|
|
3244
3624
|
ref,
|
|
@@ -3255,131 +3635,852 @@ var StreamingCursor = import_react40.default.forwardRef(
|
|
|
3255
3635
|
);
|
|
3256
3636
|
StreamingCursor.displayName = "StreamingCursor";
|
|
3257
3637
|
|
|
3258
|
-
// src/components/
|
|
3259
|
-
var
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3638
|
+
// src/components/chat/ChatInterface.tsx
|
|
3639
|
+
var import_react54 = __toESM(require("react"));
|
|
3640
|
+
|
|
3641
|
+
// src/components/chat/ChatView.tsx
|
|
3642
|
+
var import_react47 = __toESM(require("react"));
|
|
3643
|
+
|
|
3644
|
+
// src/components/chat/hooks/useScrollAnchor.ts
|
|
3645
|
+
var import_react44 = require("react");
|
|
3646
|
+
function useScrollAnchor(options = {}) {
|
|
3647
|
+
const { behavior = "smooth", block = "start" } = options;
|
|
3648
|
+
const containerRef = (0, import_react44.useRef)(null);
|
|
3649
|
+
const anchorRef = (0, import_react44.useRef)(null);
|
|
3650
|
+
const scrollToAnchor = (0, import_react44.useCallback)(() => {
|
|
3651
|
+
const el = anchorRef.current;
|
|
3652
|
+
if (!el) return;
|
|
3653
|
+
requestAnimationFrame(() => {
|
|
3654
|
+
requestAnimationFrame(() => {
|
|
3655
|
+
el.scrollIntoView({ behavior, block });
|
|
3656
|
+
});
|
|
3657
|
+
});
|
|
3658
|
+
}, [behavior, block]);
|
|
3659
|
+
const scrollToBottom = (0, import_react44.useCallback)(() => {
|
|
3660
|
+
const container = containerRef.current;
|
|
3661
|
+
if (!container) return;
|
|
3662
|
+
if (typeof container.scrollTo === "function") {
|
|
3663
|
+
container.scrollTo({ top: container.scrollHeight, behavior });
|
|
3664
|
+
} else {
|
|
3665
|
+
container.scrollTop = container.scrollHeight;
|
|
3666
|
+
}
|
|
3667
|
+
}, [behavior]);
|
|
3668
|
+
const isScrolledToBottom = (0, import_react44.useCallback)(() => {
|
|
3669
|
+
const container = containerRef.current;
|
|
3670
|
+
if (!container) return true;
|
|
3671
|
+
const threshold = 50;
|
|
3672
|
+
const { scrollTop, scrollHeight, clientHeight } = container;
|
|
3673
|
+
return scrollHeight - scrollTop - clientHeight < threshold;
|
|
3674
|
+
}, []);
|
|
3675
|
+
return {
|
|
3676
|
+
containerRef,
|
|
3677
|
+
anchorRef,
|
|
3678
|
+
scrollToAnchor,
|
|
3679
|
+
scrollToBottom,
|
|
3680
|
+
isScrolledToBottom
|
|
3681
|
+
};
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3684
|
+
// src/components/chat/hooks/useAdaptiveSpacer.ts
|
|
3685
|
+
var import_react45 = require("react");
|
|
3686
|
+
function useAdaptiveSpacer(options = {}) {
|
|
3687
|
+
const { minHeight = 0, containerRef: externalContainerRef, anchorRef } = options;
|
|
3688
|
+
const internalContainerRef = (0, import_react45.useRef)(null);
|
|
3689
|
+
const containerRef = externalContainerRef ?? internalContainerRef;
|
|
3690
|
+
const contentRef = (0, import_react45.useRef)(null);
|
|
3691
|
+
const spacerRef = (0, import_react45.useRef)(null);
|
|
3692
|
+
const [spacerHeight, setSpacerHeight] = (0, import_react45.useState)(0);
|
|
3693
|
+
const recalculate = (0, import_react45.useCallback)(() => {
|
|
3694
|
+
const container = containerRef.current;
|
|
3695
|
+
const content = contentRef.current;
|
|
3696
|
+
if (!container || !content) return;
|
|
3697
|
+
const style = getComputedStyle(container);
|
|
3698
|
+
const paddingTop = parseFloat(style.paddingTop) || 0;
|
|
3699
|
+
const paddingBottom = parseFloat(style.paddingBottom) || 0;
|
|
3700
|
+
const availableHeight = container.clientHeight - paddingTop - paddingBottom;
|
|
3701
|
+
let heightFromAnchorToBottom;
|
|
3702
|
+
const anchor = anchorRef?.current;
|
|
3703
|
+
if (anchor && content.contains(anchor)) {
|
|
3704
|
+
const anchorTop = anchor.offsetTop;
|
|
3705
|
+
heightFromAnchorToBottom = content.scrollHeight - anchorTop;
|
|
3706
|
+
} else {
|
|
3707
|
+
heightFromAnchorToBottom = content.scrollHeight;
|
|
3708
|
+
}
|
|
3709
|
+
const newSpacerHeight = Math.max(minHeight, availableHeight - heightFromAnchorToBottom);
|
|
3710
|
+
if (spacerRef.current) {
|
|
3711
|
+
spacerRef.current.style.height = `${newSpacerHeight}px`;
|
|
3712
|
+
}
|
|
3713
|
+
setSpacerHeight(newSpacerHeight);
|
|
3714
|
+
}, [minHeight, anchorRef]);
|
|
3715
|
+
(0, import_react45.useEffect)(() => {
|
|
3716
|
+
const container = containerRef.current;
|
|
3717
|
+
const content = contentRef.current;
|
|
3718
|
+
if (!container || !content) return;
|
|
3719
|
+
recalculate();
|
|
3720
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
3721
|
+
recalculate();
|
|
3722
|
+
});
|
|
3723
|
+
resizeObserver.observe(container);
|
|
3724
|
+
resizeObserver.observe(content);
|
|
3725
|
+
const mutationObserver = new MutationObserver(() => {
|
|
3726
|
+
requestAnimationFrame(recalculate);
|
|
3727
|
+
});
|
|
3728
|
+
mutationObserver.observe(content, {
|
|
3729
|
+
childList: true,
|
|
3730
|
+
subtree: true,
|
|
3731
|
+
characterData: true
|
|
3732
|
+
});
|
|
3733
|
+
return () => {
|
|
3734
|
+
resizeObserver.disconnect();
|
|
3735
|
+
mutationObserver.disconnect();
|
|
3736
|
+
};
|
|
3737
|
+
}, [recalculate]);
|
|
3738
|
+
return {
|
|
3739
|
+
containerRef,
|
|
3740
|
+
contentRef,
|
|
3741
|
+
spacerRef,
|
|
3742
|
+
spacerHeight,
|
|
3743
|
+
recalculate
|
|
3744
|
+
};
|
|
3745
|
+
}
|
|
3746
|
+
|
|
3747
|
+
// src/components/chat/ThinkingIndicator.tsx
|
|
3748
|
+
var import_react46 = __toESM(require("react"));
|
|
3749
|
+
var THINKING_PHRASES = [
|
|
3750
|
+
"Consulting the ancient tomes...",
|
|
3751
|
+
"Parsing the ineffable...",
|
|
3752
|
+
"Traversing the manifold of possibilities...",
|
|
3753
|
+
"Genuflecting before the oracle...",
|
|
3754
|
+
"Distilling quintessence...",
|
|
3755
|
+
"Communing with the machine spirits...",
|
|
3756
|
+
"Unfolding higher dimensions...",
|
|
3757
|
+
"Perturbing the probability matrix...",
|
|
3758
|
+
"Invoking the categorical imperative...",
|
|
3759
|
+
"Reticulating splines...",
|
|
3760
|
+
"Brewing a fresh batch of tokens...",
|
|
3761
|
+
"Consulting my inner monologue...",
|
|
3762
|
+
"Summoning the muse..."
|
|
3763
|
+
];
|
|
3764
|
+
var ThinkingIndicator = import_react46.default.forwardRef(
|
|
3765
|
+
({
|
|
3766
|
+
isVisible = true,
|
|
3767
|
+
phraseInterval = 2500,
|
|
3768
|
+
phrases = THINKING_PHRASES,
|
|
3769
|
+
className,
|
|
3770
|
+
...rest
|
|
3771
|
+
}, ref) => {
|
|
3772
|
+
const [currentIndex, setCurrentIndex] = (0, import_react46.useState)(() => Math.floor(Math.random() * phrases.length));
|
|
3773
|
+
const [isTransitioning, setIsTransitioning] = (0, import_react46.useState)(false);
|
|
3774
|
+
(0, import_react46.useEffect)(() => {
|
|
3775
|
+
if (!isVisible || phrases.length <= 1) return;
|
|
3776
|
+
const interval = setInterval(() => {
|
|
3777
|
+
setIsTransitioning(true);
|
|
3778
|
+
setTimeout(() => {
|
|
3779
|
+
setCurrentIndex((prev) => (prev + 1) % phrases.length);
|
|
3780
|
+
setIsTransitioning(false);
|
|
3781
|
+
}, 200);
|
|
3782
|
+
}, phraseInterval);
|
|
3783
|
+
return () => clearInterval(interval);
|
|
3784
|
+
}, [isVisible, phrases.length, phraseInterval]);
|
|
3785
|
+
if (!isVisible) return null;
|
|
3786
|
+
return /* @__PURE__ */ import_react46.default.createElement(
|
|
3267
3787
|
"div",
|
|
3268
3788
|
{
|
|
3269
3789
|
ref,
|
|
3270
3790
|
className: cx(
|
|
3271
|
-
"px-3 py-2 w-fit",
|
|
3272
|
-
|
|
3791
|
+
"flex items-center gap-2 px-3 py-2 w-fit",
|
|
3792
|
+
"bg-charcoal border border-ash text-silver",
|
|
3793
|
+
"mr-auto",
|
|
3273
3794
|
className
|
|
3274
3795
|
),
|
|
3796
|
+
role: "status",
|
|
3797
|
+
"aria-live": "polite",
|
|
3275
3798
|
...rest
|
|
3276
3799
|
},
|
|
3277
|
-
/* @__PURE__ */
|
|
3278
|
-
|
|
3800
|
+
/* @__PURE__ */ import_react46.default.createElement("div", { className: "flex gap-1", "aria-hidden": "true" }, /* @__PURE__ */ import_react46.default.createElement("span", { className: "w-1.5 h-1.5 bg-gold/60 rounded-full animate-pulse", style: { animationDelay: "0ms" } }), /* @__PURE__ */ import_react46.default.createElement("span", { className: "w-1.5 h-1.5 bg-gold/60 rounded-full animate-pulse", style: { animationDelay: "150ms" } }), /* @__PURE__ */ import_react46.default.createElement("span", { className: "w-1.5 h-1.5 bg-gold/60 rounded-full animate-pulse", style: { animationDelay: "300ms" } })),
|
|
3801
|
+
/* @__PURE__ */ import_react46.default.createElement(
|
|
3802
|
+
"span",
|
|
3279
3803
|
{
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3804
|
+
className: cx(
|
|
3805
|
+
"text-sm italic transition-opacity duration-200",
|
|
3806
|
+
isTransitioning ? "opacity-0" : "opacity-100"
|
|
3807
|
+
)
|
|
3808
|
+
},
|
|
3809
|
+
phrases[currentIndex]
|
|
3810
|
+
)
|
|
3285
3811
|
);
|
|
3286
3812
|
}
|
|
3287
3813
|
);
|
|
3288
|
-
|
|
3814
|
+
ThinkingIndicator.displayName = "ThinkingIndicator";
|
|
3289
3815
|
|
|
3290
|
-
// src/components/
|
|
3291
|
-
var
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
messages.map(({ id, variant, className: messageClassName, ...messageProps }, index) => /* @__PURE__ */ import_react42.default.createElement(
|
|
3316
|
-
Message,
|
|
3816
|
+
// src/components/chat/ChatView.tsx
|
|
3817
|
+
var ChatView = import_react47.default.forwardRef(
|
|
3818
|
+
({ messages, latestUserMessageIndex, isStreaming, isThinking, onScroll, className, ...rest }, ref) => {
|
|
3819
|
+
const { containerRef, anchorRef, scrollToAnchor } = useScrollAnchor({
|
|
3820
|
+
behavior: "smooth",
|
|
3821
|
+
block: "start"
|
|
3822
|
+
});
|
|
3823
|
+
const { contentRef, spacerRef, spacerHeight } = useAdaptiveSpacer({
|
|
3824
|
+
containerRef,
|
|
3825
|
+
anchorRef
|
|
3826
|
+
});
|
|
3827
|
+
(0, import_react47.useEffect)(() => {
|
|
3828
|
+
if (latestUserMessageIndex !== void 0 && latestUserMessageIndex >= 0) {
|
|
3829
|
+
scrollToAnchor();
|
|
3830
|
+
}
|
|
3831
|
+
}, [latestUserMessageIndex, scrollToAnchor]);
|
|
3832
|
+
const latestUserIdx = latestUserMessageIndex ?? messages.reduceRight((found, msg, idx) => {
|
|
3833
|
+
if (found === -1 && msg.variant === "user") {
|
|
3834
|
+
return idx;
|
|
3835
|
+
}
|
|
3836
|
+
return found;
|
|
3837
|
+
}, -1);
|
|
3838
|
+
const showThinking = isThinking && messages.length > 0 && messages[messages.length - 1]?.variant === "user";
|
|
3839
|
+
return /* @__PURE__ */ import_react47.default.createElement(
|
|
3840
|
+
"div",
|
|
3317
3841
|
{
|
|
3318
|
-
|
|
3842
|
+
ref: (node) => {
|
|
3843
|
+
;
|
|
3844
|
+
containerRef.current = node;
|
|
3845
|
+
if (typeof ref === "function") {
|
|
3846
|
+
ref(node);
|
|
3847
|
+
} else if (ref) {
|
|
3848
|
+
ref.current = node;
|
|
3849
|
+
}
|
|
3850
|
+
},
|
|
3851
|
+
onScroll,
|
|
3852
|
+
className: cx(
|
|
3853
|
+
"flex flex-col w-full h-full overflow-y-auto scroll-smooth",
|
|
3854
|
+
"px-4 py-6 overscroll-contain",
|
|
3855
|
+
className
|
|
3856
|
+
),
|
|
3857
|
+
...rest
|
|
3858
|
+
},
|
|
3859
|
+
/* @__PURE__ */ import_react47.default.createElement("div", { ref: contentRef, className: "relative flex flex-col gap-3" }, messages.map(({
|
|
3860
|
+
id,
|
|
3319
3861
|
variant,
|
|
3320
3862
|
className: messageClassName,
|
|
3863
|
+
branchInfo,
|
|
3864
|
+
actions,
|
|
3865
|
+
isStreaming: nodeIsStreaming,
|
|
3321
3866
|
...messageProps
|
|
3867
|
+
}, index) => {
|
|
3868
|
+
const isAnchor = index === latestUserIdx;
|
|
3869
|
+
const isLastMessage = index === messages.length - 1;
|
|
3870
|
+
const showStreaming = isLastMessage && isStreaming && variant === "assistant";
|
|
3871
|
+
const isMessageStreaming = showStreaming || !!nodeIsStreaming;
|
|
3872
|
+
return /* @__PURE__ */ import_react47.default.createElement(
|
|
3873
|
+
"div",
|
|
3874
|
+
{
|
|
3875
|
+
key: id ?? `msg-${index}`,
|
|
3876
|
+
ref: isAnchor ? anchorRef : void 0,
|
|
3877
|
+
className: isAnchor ? "scroll-mt-4" : void 0
|
|
3878
|
+
},
|
|
3879
|
+
/* @__PURE__ */ import_react47.default.createElement(
|
|
3880
|
+
Message,
|
|
3881
|
+
{
|
|
3882
|
+
variant,
|
|
3883
|
+
isStreaming: isMessageStreaming,
|
|
3884
|
+
className: messageClassName,
|
|
3885
|
+
branchInfo,
|
|
3886
|
+
actions,
|
|
3887
|
+
hideActions: isMessageStreaming,
|
|
3888
|
+
...messageProps
|
|
3889
|
+
}
|
|
3890
|
+
)
|
|
3891
|
+
);
|
|
3892
|
+
}), showThinking && /* @__PURE__ */ import_react47.default.createElement(ThinkingIndicator, { isVisible: true })),
|
|
3893
|
+
/* @__PURE__ */ import_react47.default.createElement(
|
|
3894
|
+
"div",
|
|
3895
|
+
{
|
|
3896
|
+
ref: spacerRef,
|
|
3897
|
+
className: "shrink-0 pointer-events-none",
|
|
3898
|
+
style: { height: spacerHeight },
|
|
3899
|
+
"aria-hidden": "true"
|
|
3900
|
+
}
|
|
3901
|
+
)
|
|
3902
|
+
);
|
|
3903
|
+
}
|
|
3904
|
+
);
|
|
3905
|
+
ChatView.displayName = "ChatView";
|
|
3906
|
+
|
|
3907
|
+
// src/components/chat/ChatInput.tsx
|
|
3908
|
+
var import_react48 = __toESM(require("react"));
|
|
3909
|
+
var import_lucide_react11 = require("lucide-react");
|
|
3910
|
+
|
|
3911
|
+
// src/components/chat/types.ts
|
|
3912
|
+
function isImageFile(file) {
|
|
3913
|
+
return file.type.startsWith("image/");
|
|
3914
|
+
}
|
|
3915
|
+
function createPreviewUrl(file) {
|
|
3916
|
+
if (isImageFile(file)) {
|
|
3917
|
+
return URL.createObjectURL(file);
|
|
3918
|
+
}
|
|
3919
|
+
return void 0;
|
|
3920
|
+
}
|
|
3921
|
+
function revokePreviewUrl(url) {
|
|
3922
|
+
if (url) {
|
|
3923
|
+
URL.revokeObjectURL(url);
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
function generateId() {
|
|
3927
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
3928
|
+
}
|
|
3929
|
+
function createEmptyTree() {
|
|
3930
|
+
return {
|
|
3931
|
+
nodes: {},
|
|
3932
|
+
rootIds: [],
|
|
3933
|
+
activeLeafId: null
|
|
3934
|
+
};
|
|
3935
|
+
}
|
|
3936
|
+
function addMessageToTree(tree, message, parentId = null) {
|
|
3937
|
+
const newNodes = { ...tree.nodes };
|
|
3938
|
+
const newRootIds = [...tree.rootIds];
|
|
3939
|
+
let branchIndex = 0;
|
|
3940
|
+
if (parentId && newNodes[parentId]) {
|
|
3941
|
+
branchIndex = newNodes[parentId].children.length;
|
|
3942
|
+
} else if (!parentId) {
|
|
3943
|
+
branchIndex = newRootIds.length;
|
|
3944
|
+
}
|
|
3945
|
+
const newNode = {
|
|
3946
|
+
...message,
|
|
3947
|
+
parentId,
|
|
3948
|
+
children: [],
|
|
3949
|
+
branchIndex,
|
|
3950
|
+
createdAt: message.createdAt ?? Date.now()
|
|
3951
|
+
};
|
|
3952
|
+
newNodes[message.id] = newNode;
|
|
3953
|
+
if (parentId && newNodes[parentId]) {
|
|
3954
|
+
newNodes[parentId] = {
|
|
3955
|
+
...newNodes[parentId],
|
|
3956
|
+
children: [...newNodes[parentId].children, message.id]
|
|
3957
|
+
};
|
|
3958
|
+
} else {
|
|
3959
|
+
newRootIds.push(message.id);
|
|
3960
|
+
}
|
|
3961
|
+
return {
|
|
3962
|
+
nodes: newNodes,
|
|
3963
|
+
rootIds: newRootIds,
|
|
3964
|
+
activeLeafId: message.id
|
|
3965
|
+
};
|
|
3966
|
+
}
|
|
3967
|
+
function getActivePathMessages(tree) {
|
|
3968
|
+
if (!tree.activeLeafId) return [];
|
|
3969
|
+
const path = [];
|
|
3970
|
+
let currentId = tree.activeLeafId;
|
|
3971
|
+
while (currentId) {
|
|
3972
|
+
const node = tree.nodes[currentId];
|
|
3973
|
+
if (!node) break;
|
|
3974
|
+
path.unshift(node);
|
|
3975
|
+
currentId = node.parentId;
|
|
3976
|
+
}
|
|
3977
|
+
return path;
|
|
3978
|
+
}
|
|
3979
|
+
function getSiblingInfo(tree, nodeId) {
|
|
3980
|
+
const node = tree.nodes[nodeId];
|
|
3981
|
+
if (!node) return { total: 1, current: 1 };
|
|
3982
|
+
if (node.parentId) {
|
|
3983
|
+
const parent = tree.nodes[node.parentId];
|
|
3984
|
+
if (parent) {
|
|
3985
|
+
const index = parent.children.indexOf(nodeId);
|
|
3986
|
+
return {
|
|
3987
|
+
total: parent.children.length,
|
|
3988
|
+
current: index + 1
|
|
3989
|
+
};
|
|
3990
|
+
}
|
|
3991
|
+
} else {
|
|
3992
|
+
const index = tree.rootIds.indexOf(nodeId);
|
|
3993
|
+
return {
|
|
3994
|
+
total: tree.rootIds.length,
|
|
3995
|
+
current: index + 1
|
|
3996
|
+
};
|
|
3997
|
+
}
|
|
3998
|
+
return { total: 1, current: 1 };
|
|
3999
|
+
}
|
|
4000
|
+
function switchBranch(tree, nodeId, direction) {
|
|
4001
|
+
const node = tree.nodes[nodeId];
|
|
4002
|
+
if (!node) return tree;
|
|
4003
|
+
let siblings;
|
|
4004
|
+
let currentIndex;
|
|
4005
|
+
if (node.parentId) {
|
|
4006
|
+
const parent = tree.nodes[node.parentId];
|
|
4007
|
+
if (!parent) return tree;
|
|
4008
|
+
siblings = parent.children;
|
|
4009
|
+
currentIndex = siblings.indexOf(nodeId);
|
|
4010
|
+
} else {
|
|
4011
|
+
siblings = tree.rootIds;
|
|
4012
|
+
currentIndex = siblings.indexOf(nodeId);
|
|
4013
|
+
}
|
|
4014
|
+
if (siblings.length <= 1) return tree;
|
|
4015
|
+
const newIndex = direction === "next" ? (currentIndex + 1) % siblings.length : (currentIndex - 1 + siblings.length) % siblings.length;
|
|
4016
|
+
const newNodeId = siblings[newIndex];
|
|
4017
|
+
let leafId = newNodeId;
|
|
4018
|
+
let currentNode = tree.nodes[leafId];
|
|
4019
|
+
while (currentNode && currentNode.children.length > 0) {
|
|
4020
|
+
leafId = currentNode.children[0];
|
|
4021
|
+
currentNode = tree.nodes[leafId];
|
|
4022
|
+
}
|
|
4023
|
+
return {
|
|
4024
|
+
...tree,
|
|
4025
|
+
activeLeafId: leafId
|
|
4026
|
+
};
|
|
4027
|
+
}
|
|
4028
|
+
function updateNodeContent(tree, nodeId, content, isStreaming) {
|
|
4029
|
+
const node = tree.nodes[nodeId];
|
|
4030
|
+
if (!node) return tree;
|
|
4031
|
+
return {
|
|
4032
|
+
...tree,
|
|
4033
|
+
nodes: {
|
|
4034
|
+
...tree.nodes,
|
|
4035
|
+
[nodeId]: {
|
|
4036
|
+
...node,
|
|
4037
|
+
content,
|
|
4038
|
+
isStreaming: isStreaming ?? node.isStreaming
|
|
3322
4039
|
}
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
}
|
|
3326
|
-
|
|
4040
|
+
}
|
|
4041
|
+
};
|
|
4042
|
+
}
|
|
4043
|
+
function messagesToTree(messages) {
|
|
4044
|
+
let tree = createEmptyTree();
|
|
4045
|
+
for (const msg of messages) {
|
|
4046
|
+
const parentId = tree.activeLeafId;
|
|
4047
|
+
tree = addMessageToTree(tree, {
|
|
4048
|
+
id: msg.id,
|
|
4049
|
+
role: msg.role,
|
|
4050
|
+
content: msg.content,
|
|
4051
|
+
parentId,
|
|
4052
|
+
isStreaming: msg.isStreaming
|
|
4053
|
+
}, parentId);
|
|
4054
|
+
}
|
|
4055
|
+
return tree;
|
|
4056
|
+
}
|
|
4057
|
+
function isBranchPoint(tree, nodeId) {
|
|
4058
|
+
const node = tree.nodes[nodeId];
|
|
4059
|
+
return node ? node.children.length > 1 : false;
|
|
4060
|
+
}
|
|
3327
4061
|
|
|
3328
|
-
// src/components/
|
|
3329
|
-
var
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
4062
|
+
// src/components/chat/ChatInput.tsx
|
|
4063
|
+
var ChatInput = import_react48.default.forwardRef(
|
|
4064
|
+
({
|
|
4065
|
+
position = "bottom",
|
|
4066
|
+
placeholder = "Send a message...",
|
|
4067
|
+
helperText,
|
|
4068
|
+
onSubmit,
|
|
4069
|
+
disabled = false,
|
|
4070
|
+
animate = true,
|
|
4071
|
+
isStreaming = false,
|
|
4072
|
+
onStop,
|
|
4073
|
+
attachments: controlledAttachments,
|
|
4074
|
+
onAttachmentsChange,
|
|
4075
|
+
showAttachmentButton = true,
|
|
4076
|
+
acceptedFileTypes,
|
|
4077
|
+
className,
|
|
4078
|
+
...rest
|
|
4079
|
+
}, ref) => {
|
|
4080
|
+
const [value, setValue] = (0, import_react48.useState)("");
|
|
4081
|
+
const [localAttachments, setLocalAttachments] = (0, import_react48.useState)([]);
|
|
4082
|
+
const [isDragOver, setIsDragOver] = (0, import_react48.useState)(false);
|
|
4083
|
+
const textareaRef = (0, import_react48.useRef)(null);
|
|
4084
|
+
const fileInputRef = (0, import_react48.useRef)(null);
|
|
4085
|
+
const attachments = controlledAttachments ?? localAttachments;
|
|
4086
|
+
const setAttachments = (0, import_react48.useCallback)(
|
|
4087
|
+
(newAttachments) => {
|
|
4088
|
+
if (onAttachmentsChange) {
|
|
4089
|
+
if (typeof newAttachments === "function") {
|
|
4090
|
+
onAttachmentsChange(newAttachments(attachments));
|
|
4091
|
+
} else {
|
|
4092
|
+
onAttachmentsChange(newAttachments);
|
|
4093
|
+
}
|
|
4094
|
+
} else {
|
|
4095
|
+
setLocalAttachments(newAttachments);
|
|
4096
|
+
}
|
|
4097
|
+
},
|
|
4098
|
+
[attachments, onAttachmentsChange]
|
|
4099
|
+
);
|
|
4100
|
+
const handleSubmit = (0, import_react48.useCallback)(() => {
|
|
4101
|
+
const trimmed = value.trim();
|
|
4102
|
+
if (!trimmed || disabled || isStreaming) {
|
|
4103
|
+
return;
|
|
4104
|
+
}
|
|
4105
|
+
onSubmit?.(trimmed, attachments.length > 0 ? attachments : void 0);
|
|
4106
|
+
setValue("");
|
|
4107
|
+
setAttachments([]);
|
|
4108
|
+
if (textareaRef.current) {
|
|
4109
|
+
textareaRef.current.style.height = "auto";
|
|
4110
|
+
}
|
|
4111
|
+
}, [value, disabled, isStreaming, onSubmit, attachments, setAttachments]);
|
|
4112
|
+
const handleKeyDown = (0, import_react48.useCallback)(
|
|
4113
|
+
(e) => {
|
|
4114
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
4115
|
+
e.preventDefault();
|
|
4116
|
+
handleSubmit();
|
|
4117
|
+
}
|
|
4118
|
+
},
|
|
4119
|
+
[handleSubmit]
|
|
4120
|
+
);
|
|
4121
|
+
const handleChange = (0, import_react48.useCallback)((e) => {
|
|
4122
|
+
setValue(e.target.value);
|
|
4123
|
+
const textarea = e.target;
|
|
4124
|
+
textarea.style.height = "auto";
|
|
4125
|
+
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
|
4126
|
+
}, []);
|
|
4127
|
+
(0, import_react48.useEffect)(() => {
|
|
4128
|
+
if (!disabled && !isStreaming && textareaRef.current) {
|
|
4129
|
+
textareaRef.current.focus();
|
|
4130
|
+
}
|
|
4131
|
+
}, [disabled, isStreaming]);
|
|
4132
|
+
const addFiles = (0, import_react48.useCallback)(
|
|
4133
|
+
(files) => {
|
|
4134
|
+
const newAttachments = Array.from(files).map((file) => ({
|
|
4135
|
+
id: generateId(),
|
|
4136
|
+
file,
|
|
4137
|
+
previewUrl: isImageFile(file) ? createPreviewUrl(file) : void 0,
|
|
4138
|
+
status: "pending"
|
|
4139
|
+
}));
|
|
4140
|
+
setAttachments((prev) => [...prev, ...newAttachments]);
|
|
4141
|
+
},
|
|
4142
|
+
[setAttachments]
|
|
4143
|
+
);
|
|
4144
|
+
const handleFileSelect = (0, import_react48.useCallback)(
|
|
4145
|
+
(e) => {
|
|
4146
|
+
const files = e.target.files;
|
|
4147
|
+
if (files && files.length > 0) {
|
|
4148
|
+
addFiles(files);
|
|
4149
|
+
}
|
|
4150
|
+
e.target.value = "";
|
|
4151
|
+
},
|
|
4152
|
+
[addFiles]
|
|
4153
|
+
);
|
|
4154
|
+
const handleRemoveAttachment = (0, import_react48.useCallback)(
|
|
4155
|
+
(id) => {
|
|
4156
|
+
setAttachments((prev) => {
|
|
4157
|
+
const attachment = prev.find((a) => a.id === id);
|
|
4158
|
+
if (attachment?.previewUrl) {
|
|
4159
|
+
URL.revokeObjectURL(attachment.previewUrl);
|
|
4160
|
+
}
|
|
4161
|
+
return prev.filter((a) => a.id !== id);
|
|
4162
|
+
});
|
|
4163
|
+
},
|
|
4164
|
+
[setAttachments]
|
|
4165
|
+
);
|
|
4166
|
+
const handleDragEnter = (0, import_react48.useCallback)((e) => {
|
|
4167
|
+
e.preventDefault();
|
|
4168
|
+
e.stopPropagation();
|
|
4169
|
+
setIsDragOver(true);
|
|
4170
|
+
}, []);
|
|
4171
|
+
const handleDragLeave = (0, import_react48.useCallback)((e) => {
|
|
4172
|
+
e.preventDefault();
|
|
4173
|
+
e.stopPropagation();
|
|
4174
|
+
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
4175
|
+
setIsDragOver(false);
|
|
4176
|
+
}
|
|
4177
|
+
}, []);
|
|
4178
|
+
const handleDragOver = (0, import_react48.useCallback)((e) => {
|
|
4179
|
+
e.preventDefault();
|
|
4180
|
+
e.stopPropagation();
|
|
4181
|
+
}, []);
|
|
4182
|
+
const handleDrop = (0, import_react48.useCallback)(
|
|
4183
|
+
(e) => {
|
|
4184
|
+
e.preventDefault();
|
|
4185
|
+
e.stopPropagation();
|
|
4186
|
+
setIsDragOver(false);
|
|
4187
|
+
const files = e.dataTransfer.files;
|
|
4188
|
+
if (files && files.length > 0) {
|
|
4189
|
+
addFiles(files);
|
|
4190
|
+
}
|
|
4191
|
+
},
|
|
4192
|
+
[addFiles]
|
|
4193
|
+
);
|
|
4194
|
+
const isCentered = position === "centered";
|
|
4195
|
+
const hasAttachments = attachments.length > 0;
|
|
4196
|
+
const canSubmit = value.trim() && !disabled && !isStreaming;
|
|
4197
|
+
return /* @__PURE__ */ import_react48.default.createElement(
|
|
3339
4198
|
"div",
|
|
3340
4199
|
{
|
|
3341
4200
|
ref,
|
|
3342
4201
|
className: cx(
|
|
3343
|
-
"
|
|
3344
|
-
|
|
3345
|
-
|
|
4202
|
+
"w-full",
|
|
4203
|
+
isCentered && "flex flex-col items-center justify-center",
|
|
4204
|
+
animate && "transition-all duration-300 ease-out",
|
|
3346
4205
|
className
|
|
3347
4206
|
),
|
|
3348
4207
|
...rest
|
|
3349
4208
|
},
|
|
3350
|
-
|
|
4209
|
+
isCentered && helperText && /* @__PURE__ */ import_react48.default.createElement("p", { className: "text-silver text-sm mb-4 text-center" }, helperText),
|
|
4210
|
+
/* @__PURE__ */ import_react48.default.createElement(
|
|
4211
|
+
"div",
|
|
4212
|
+
{
|
|
4213
|
+
className: cx(
|
|
4214
|
+
"relative w-full bg-charcoal border",
|
|
4215
|
+
isDragOver ? "border-gold ring-1 ring-gold/30" : "border-ash/60",
|
|
4216
|
+
"focus-within:border-gold/60 focus-within:ring-1 focus-within:ring-gold/20",
|
|
4217
|
+
"transition-colors duration-200",
|
|
4218
|
+
isCentered && "max-w-lg"
|
|
4219
|
+
),
|
|
4220
|
+
onDragEnter: showAttachmentButton ? handleDragEnter : void 0,
|
|
4221
|
+
onDragLeave: showAttachmentButton ? handleDragLeave : void 0,
|
|
4222
|
+
onDragOver: showAttachmentButton ? handleDragOver : void 0,
|
|
4223
|
+
onDrop: showAttachmentButton ? handleDrop : void 0
|
|
4224
|
+
},
|
|
4225
|
+
hasAttachments && /* @__PURE__ */ import_react48.default.createElement("div", { className: "px-3 pt-3 pb-1" }, /* @__PURE__ */ import_react48.default.createElement(
|
|
4226
|
+
AttachmentPreview,
|
|
4227
|
+
{
|
|
4228
|
+
attachments,
|
|
4229
|
+
onRemove: handleRemoveAttachment,
|
|
4230
|
+
removable: !isStreaming
|
|
4231
|
+
}
|
|
4232
|
+
)),
|
|
4233
|
+
isDragOver && /* @__PURE__ */ import_react48.default.createElement(
|
|
4234
|
+
"div",
|
|
4235
|
+
{
|
|
4236
|
+
className: "absolute inset-0 bg-gold/10 flex items-center justify-center z-10 pointer-events-none"
|
|
4237
|
+
},
|
|
4238
|
+
/* @__PURE__ */ import_react48.default.createElement("span", { className: "text-gold text-sm font-medium" }, "Drop files here")
|
|
4239
|
+
),
|
|
4240
|
+
/* @__PURE__ */ import_react48.default.createElement("div", { className: "flex items-end" }, showAttachmentButton && /* @__PURE__ */ import_react48.default.createElement(import_react48.default.Fragment, null, /* @__PURE__ */ import_react48.default.createElement(
|
|
4241
|
+
"button",
|
|
4242
|
+
{
|
|
4243
|
+
type: "button",
|
|
4244
|
+
onClick: () => fileInputRef.current?.click(),
|
|
4245
|
+
disabled: disabled || isStreaming,
|
|
4246
|
+
className: cx(
|
|
4247
|
+
"p-3 text-silver/60 hover:text-silver transition-colors",
|
|
4248
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
4249
|
+
),
|
|
4250
|
+
"aria-label": "Attach file"
|
|
4251
|
+
},
|
|
4252
|
+
/* @__PURE__ */ import_react48.default.createElement(import_lucide_react11.Paperclip, { className: "w-5 h-5" })
|
|
4253
|
+
), /* @__PURE__ */ import_react48.default.createElement(
|
|
4254
|
+
"input",
|
|
4255
|
+
{
|
|
4256
|
+
ref: fileInputRef,
|
|
4257
|
+
type: "file",
|
|
4258
|
+
multiple: true,
|
|
4259
|
+
accept: acceptedFileTypes,
|
|
4260
|
+
onChange: handleFileSelect,
|
|
4261
|
+
className: "hidden",
|
|
4262
|
+
"aria-hidden": "true"
|
|
4263
|
+
}
|
|
4264
|
+
)), /* @__PURE__ */ import_react48.default.createElement(
|
|
4265
|
+
"textarea",
|
|
4266
|
+
{
|
|
4267
|
+
ref: textareaRef,
|
|
4268
|
+
value,
|
|
4269
|
+
onChange: handleChange,
|
|
4270
|
+
onKeyDown: handleKeyDown,
|
|
4271
|
+
placeholder,
|
|
4272
|
+
disabled: disabled || isStreaming,
|
|
4273
|
+
rows: 1,
|
|
4274
|
+
className: cx(
|
|
4275
|
+
"flex-1 bg-transparent text-white placeholder:text-silver/60",
|
|
4276
|
+
"py-3 pr-12 resize-none outline-none min-h-12",
|
|
4277
|
+
!showAttachmentButton && "pl-4",
|
|
4278
|
+
(disabled || isStreaming) && "opacity-50 cursor-not-allowed"
|
|
4279
|
+
),
|
|
4280
|
+
style: { maxHeight: 200 }
|
|
4281
|
+
}
|
|
4282
|
+
), isStreaming ? /* @__PURE__ */ import_react48.default.createElement(
|
|
4283
|
+
"button",
|
|
4284
|
+
{
|
|
4285
|
+
type: "button",
|
|
4286
|
+
onClick: onStop,
|
|
4287
|
+
className: cx(
|
|
4288
|
+
"absolute right-2 bottom-2 p-2",
|
|
4289
|
+
"text-error hover:bg-error/10 transition-colors duration-200"
|
|
4290
|
+
),
|
|
4291
|
+
"aria-label": "Stop generation"
|
|
4292
|
+
},
|
|
4293
|
+
/* @__PURE__ */ import_react48.default.createElement(import_lucide_react11.Square, { className: "w-5 h-5 fill-current" })
|
|
4294
|
+
) : /* @__PURE__ */ import_react48.default.createElement(
|
|
4295
|
+
"button",
|
|
4296
|
+
{
|
|
4297
|
+
type: "button",
|
|
4298
|
+
onClick: handleSubmit,
|
|
4299
|
+
disabled: !canSubmit,
|
|
4300
|
+
className: cx(
|
|
4301
|
+
"absolute right-2 bottom-2 p-2",
|
|
4302
|
+
"transition-colors duration-200",
|
|
4303
|
+
canSubmit ? "text-gold hover:bg-gold/10" : "text-silver/40 cursor-not-allowed"
|
|
4304
|
+
),
|
|
4305
|
+
"aria-label": "Send message"
|
|
4306
|
+
},
|
|
4307
|
+
/* @__PURE__ */ import_react48.default.createElement(import_lucide_react11.Send, { className: "w-5 h-5" })
|
|
4308
|
+
))
|
|
4309
|
+
)
|
|
3351
4310
|
);
|
|
3352
4311
|
}
|
|
3353
4312
|
);
|
|
3354
|
-
|
|
4313
|
+
ChatInput.displayName = "ChatInput";
|
|
3355
4314
|
|
|
3356
|
-
// src/components/
|
|
3357
|
-
var
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
4315
|
+
// src/components/chat/ConversationSidebar.tsx
|
|
4316
|
+
var import_react49 = __toESM(require("react"));
|
|
4317
|
+
function HistoryIcon({ className }) {
|
|
4318
|
+
return /* @__PURE__ */ import_react49.default.createElement(
|
|
4319
|
+
"svg",
|
|
4320
|
+
{
|
|
4321
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4322
|
+
viewBox: "0 0 20 20",
|
|
4323
|
+
fill: "currentColor",
|
|
4324
|
+
className
|
|
4325
|
+
},
|
|
4326
|
+
/* @__PURE__ */ import_react49.default.createElement(
|
|
4327
|
+
"path",
|
|
4328
|
+
{
|
|
4329
|
+
fillRule: "evenodd",
|
|
4330
|
+
d: "M10 18a8 8 0 100-16 8 8 0 000 16zm.75-13a.75.75 0 00-1.5 0v5c0 .414.336.75.75.75h4a.75.75 0 000-1.5h-3.25V5z",
|
|
4331
|
+
clipRule: "evenodd"
|
|
4332
|
+
}
|
|
4333
|
+
)
|
|
4334
|
+
);
|
|
4335
|
+
}
|
|
4336
|
+
function ChevronLeftIcon2({ className }) {
|
|
4337
|
+
return /* @__PURE__ */ import_react49.default.createElement(
|
|
4338
|
+
"svg",
|
|
4339
|
+
{
|
|
4340
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4341
|
+
viewBox: "0 0 20 20",
|
|
4342
|
+
fill: "currentColor",
|
|
4343
|
+
className
|
|
4344
|
+
},
|
|
4345
|
+
/* @__PURE__ */ import_react49.default.createElement(
|
|
4346
|
+
"path",
|
|
4347
|
+
{
|
|
4348
|
+
fillRule: "evenodd",
|
|
4349
|
+
d: "M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z",
|
|
4350
|
+
clipRule: "evenodd"
|
|
4351
|
+
}
|
|
4352
|
+
)
|
|
4353
|
+
);
|
|
4354
|
+
}
|
|
4355
|
+
var ConversationSidebar = import_react49.default.forwardRef(
|
|
4356
|
+
({
|
|
4357
|
+
conversations,
|
|
4358
|
+
isCollapsed = false,
|
|
4359
|
+
onSelectConversation,
|
|
4360
|
+
onNewChat,
|
|
4361
|
+
onToggleCollapse,
|
|
4362
|
+
className,
|
|
4363
|
+
...rest
|
|
4364
|
+
}, ref) => {
|
|
4365
|
+
if (isCollapsed) {
|
|
4366
|
+
return /* @__PURE__ */ import_react49.default.createElement(
|
|
4367
|
+
"div",
|
|
4368
|
+
{
|
|
4369
|
+
ref,
|
|
4370
|
+
className: cx(
|
|
4371
|
+
"h-full bg-charcoal/80 border-r border-ash/40 flex flex-col items-center py-3",
|
|
4372
|
+
"w-12 flex-shrink-0",
|
|
4373
|
+
className
|
|
4374
|
+
),
|
|
4375
|
+
...rest
|
|
4376
|
+
},
|
|
4377
|
+
/* @__PURE__ */ import_react49.default.createElement(
|
|
4378
|
+
"button",
|
|
4379
|
+
{
|
|
4380
|
+
onClick: onToggleCollapse,
|
|
4381
|
+
className: cx(
|
|
4382
|
+
"p-2",
|
|
4383
|
+
"text-silver hover:text-white hover:bg-ash/20",
|
|
4384
|
+
"transition-colors duration-150"
|
|
4385
|
+
),
|
|
4386
|
+
"aria-label": "Expand sidebar"
|
|
4387
|
+
},
|
|
4388
|
+
/* @__PURE__ */ import_react49.default.createElement(HistoryIcon, { className: "w-5 h-5" })
|
|
4389
|
+
)
|
|
4390
|
+
);
|
|
4391
|
+
}
|
|
4392
|
+
return /* @__PURE__ */ import_react49.default.createElement(
|
|
3361
4393
|
"div",
|
|
3362
4394
|
{
|
|
3363
4395
|
ref,
|
|
3364
|
-
className: cx(
|
|
4396
|
+
className: cx(
|
|
4397
|
+
"h-full bg-charcoal/80 border-r border-ash/40 flex flex-col",
|
|
4398
|
+
"w-64 flex-shrink-0",
|
|
4399
|
+
className
|
|
4400
|
+
),
|
|
3365
4401
|
...rest
|
|
3366
4402
|
},
|
|
3367
|
-
/* @__PURE__ */
|
|
3368
|
-
"
|
|
4403
|
+
/* @__PURE__ */ import_react49.default.createElement("div", { className: "p-3 border-b border-ash/40 flex-shrink-0 flex items-center gap-2" }, /* @__PURE__ */ import_react49.default.createElement(
|
|
4404
|
+
"button",
|
|
3369
4405
|
{
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
4406
|
+
onClick: onToggleCollapse,
|
|
4407
|
+
className: cx(
|
|
4408
|
+
"p-1.5",
|
|
4409
|
+
"text-silver hover:text-white hover:bg-ash/20",
|
|
4410
|
+
"transition-colors duration-150"
|
|
4411
|
+
),
|
|
4412
|
+
"aria-label": "Collapse sidebar"
|
|
4413
|
+
},
|
|
4414
|
+
/* @__PURE__ */ import_react49.default.createElement(ChevronLeftIcon2, { className: "w-5 h-5" })
|
|
4415
|
+
), /* @__PURE__ */ import_react49.default.createElement(
|
|
4416
|
+
"button",
|
|
4417
|
+
{
|
|
4418
|
+
onClick: onNewChat,
|
|
4419
|
+
className: cx(
|
|
4420
|
+
"flex-1 px-3 py-2",
|
|
4421
|
+
"bg-gold/10 hover:bg-gold/20 text-gold",
|
|
4422
|
+
"border border-gold/30",
|
|
4423
|
+
"flex items-center justify-center gap-2",
|
|
4424
|
+
"transition-colors duration-200"
|
|
4425
|
+
)
|
|
4426
|
+
},
|
|
4427
|
+
/* @__PURE__ */ import_react49.default.createElement(
|
|
4428
|
+
"svg",
|
|
4429
|
+
{
|
|
4430
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4431
|
+
viewBox: "0 0 20 20",
|
|
4432
|
+
fill: "currentColor",
|
|
4433
|
+
className: "w-4 h-4"
|
|
4434
|
+
},
|
|
4435
|
+
/* @__PURE__ */ import_react49.default.createElement("path", { d: "M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z" })
|
|
4436
|
+
),
|
|
4437
|
+
/* @__PURE__ */ import_react49.default.createElement("span", { className: "text-sm font-medium" }, "New Chat")
|
|
4438
|
+
)),
|
|
4439
|
+
/* @__PURE__ */ import_react49.default.createElement("div", { className: "flex-1 overflow-y-auto py-2" }, conversations.length === 0 ? /* @__PURE__ */ import_react49.default.createElement("p", { className: "px-4 py-2 text-sm text-silver/60" }, "No conversations yet") : /* @__PURE__ */ import_react49.default.createElement("div", { className: "space-y-1 px-2" }, conversations.map((conversation) => /* @__PURE__ */ import_react49.default.createElement(
|
|
4440
|
+
"button",
|
|
4441
|
+
{
|
|
4442
|
+
key: conversation.id,
|
|
4443
|
+
onClick: () => onSelectConversation?.(conversation.id),
|
|
4444
|
+
className: cx(
|
|
4445
|
+
"w-full px-3 py-2 text-left",
|
|
4446
|
+
"transition-colors duration-150",
|
|
4447
|
+
conversation.isActive ? "bg-ash/40 text-white" : "text-silver hover:bg-ash/20 hover:text-white"
|
|
4448
|
+
)
|
|
4449
|
+
},
|
|
4450
|
+
/* @__PURE__ */ import_react49.default.createElement("p", { className: "text-sm font-medium truncate" }, conversation.title),
|
|
4451
|
+
conversation.preview && /* @__PURE__ */ import_react49.default.createElement("p", { className: "text-xs text-silver/60 truncate mt-0.5" }, conversation.preview),
|
|
4452
|
+
conversation.timestamp && /* @__PURE__ */ import_react49.default.createElement("p", { className: "text-xs text-silver/40 mt-1" }, conversation.timestamp)
|
|
4453
|
+
))))
|
|
3376
4454
|
);
|
|
3377
4455
|
}
|
|
3378
4456
|
);
|
|
3379
|
-
|
|
4457
|
+
ConversationSidebar.displayName = "ConversationSidebar";
|
|
4458
|
+
var CollapsedSidebarToggle = import_react49.default.forwardRef(({ onExpand, className, ...rest }, ref) => {
|
|
4459
|
+
return /* @__PURE__ */ import_react49.default.createElement(
|
|
4460
|
+
"button",
|
|
4461
|
+
{
|
|
4462
|
+
ref,
|
|
4463
|
+
onClick: onExpand,
|
|
4464
|
+
className: cx(
|
|
4465
|
+
"p-2",
|
|
4466
|
+
"bg-charcoal/80 border border-ash/40",
|
|
4467
|
+
"text-silver hover:text-white hover:bg-ash/20",
|
|
4468
|
+
"transition-colors duration-150",
|
|
4469
|
+
className
|
|
4470
|
+
),
|
|
4471
|
+
"aria-label": "Expand sidebar",
|
|
4472
|
+
...rest
|
|
4473
|
+
},
|
|
4474
|
+
/* @__PURE__ */ import_react49.default.createElement(HistoryIcon, { className: "w-5 h-5" })
|
|
4475
|
+
);
|
|
4476
|
+
});
|
|
4477
|
+
CollapsedSidebarToggle.displayName = "CollapsedSidebarToggle";
|
|
4478
|
+
|
|
4479
|
+
// src/components/chat/ArtifactsPanel.tsx
|
|
4480
|
+
var import_react52 = __toESM(require("react"));
|
|
3380
4481
|
|
|
3381
4482
|
// src/components/ImageCard.tsx
|
|
3382
|
-
var
|
|
4483
|
+
var import_react50 = __toESM(require("react"));
|
|
3383
4484
|
var ASPECT_RATIO_PRESETS = {
|
|
3384
4485
|
landscape: "3 / 2",
|
|
3385
4486
|
portrait: "2 / 3",
|
|
@@ -3391,7 +4492,7 @@ function resolveAspectRatio(ratio) {
|
|
|
3391
4492
|
}
|
|
3392
4493
|
return ratio.replace("/", " / ");
|
|
3393
4494
|
}
|
|
3394
|
-
var ImageCard =
|
|
4495
|
+
var ImageCard = import_react50.default.forwardRef(
|
|
3395
4496
|
({
|
|
3396
4497
|
src,
|
|
3397
4498
|
alt,
|
|
@@ -3408,7 +4509,7 @@ var ImageCard = import_react45.default.forwardRef(
|
|
|
3408
4509
|
}, ref) => {
|
|
3409
4510
|
const hasAspectRatio = aspectRatio !== void 0;
|
|
3410
4511
|
const isContain = objectFit === "contain";
|
|
3411
|
-
return /* @__PURE__ */
|
|
4512
|
+
return /* @__PURE__ */ import_react50.default.createElement(Card, { ref, className: cx("p-0 overflow-hidden group w-fit", className), ...props }, /* @__PURE__ */ import_react50.default.createElement(
|
|
3412
4513
|
"div",
|
|
3413
4514
|
{
|
|
3414
4515
|
className: cx(
|
|
@@ -3418,7 +4519,7 @@ var ImageCard = import_react45.default.forwardRef(
|
|
|
3418
4519
|
),
|
|
3419
4520
|
style: hasAspectRatio ? { aspectRatio: resolveAspectRatio(aspectRatio) } : void 0
|
|
3420
4521
|
},
|
|
3421
|
-
/* @__PURE__ */
|
|
4522
|
+
/* @__PURE__ */ import_react50.default.createElement(
|
|
3422
4523
|
"img",
|
|
3423
4524
|
{
|
|
3424
4525
|
src,
|
|
@@ -3431,20 +4532,20 @@ var ImageCard = import_react45.default.forwardRef(
|
|
|
3431
4532
|
)
|
|
3432
4533
|
}
|
|
3433
4534
|
),
|
|
3434
|
-
overlay && /* @__PURE__ */
|
|
4535
|
+
overlay && /* @__PURE__ */ import_react50.default.createElement(
|
|
3435
4536
|
"div",
|
|
3436
4537
|
{
|
|
3437
4538
|
className: "absolute inset-0 bg-obsidian/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex items-center justify-center"
|
|
3438
4539
|
},
|
|
3439
4540
|
overlay
|
|
3440
4541
|
)
|
|
3441
|
-
), (title || subtitle || children) && /* @__PURE__ */
|
|
4542
|
+
), (title || subtitle || children) && /* @__PURE__ */ import_react50.default.createElement("div", { className: cx("px-4 py-4", contentClassName) }, title && /* @__PURE__ */ import_react50.default.createElement("h4", { className: "text-lg font-semibold leading-tight" }, title), subtitle && /* @__PURE__ */ import_react50.default.createElement("p", { className: "text-sm text-silver leading-normal" }, subtitle), children));
|
|
3442
4543
|
}
|
|
3443
4544
|
);
|
|
3444
4545
|
ImageCard.displayName = "ImageCard";
|
|
3445
4546
|
|
|
3446
4547
|
// src/components/VideoCard.tsx
|
|
3447
|
-
var
|
|
4548
|
+
var import_react51 = __toESM(require("react"));
|
|
3448
4549
|
var import_react_player2 = __toESM(require("react-player"));
|
|
3449
4550
|
var ASPECT_RATIO_PRESETS2 = {
|
|
3450
4551
|
video: "16 / 9",
|
|
@@ -3457,7 +4558,7 @@ function resolveAspectRatio2(ratio) {
|
|
|
3457
4558
|
}
|
|
3458
4559
|
return ratio.replace("/", " / ");
|
|
3459
4560
|
}
|
|
3460
|
-
var VideoCard =
|
|
4561
|
+
var VideoCard = import_react51.default.forwardRef(
|
|
3461
4562
|
({
|
|
3462
4563
|
src,
|
|
3463
4564
|
title,
|
|
@@ -3477,16 +4578,16 @@ var VideoCard = import_react46.default.forwardRef(
|
|
|
3477
4578
|
...props
|
|
3478
4579
|
}, ref) => {
|
|
3479
4580
|
const hasAspectRatio = aspectRatio !== void 0;
|
|
3480
|
-
return /* @__PURE__ */
|
|
4581
|
+
return /* @__PURE__ */ import_react51.default.createElement(Card, { ref, className: cx("p-0 overflow-hidden group w-full", className), ...props }, /* @__PURE__ */ import_react51.default.createElement(
|
|
3481
4582
|
"div",
|
|
3482
4583
|
{
|
|
3483
4584
|
className: cx(
|
|
3484
|
-
"relative bg-
|
|
4585
|
+
"relative bg-obsidian overflow-hidden",
|
|
3485
4586
|
mediaClassName
|
|
3486
4587
|
),
|
|
3487
4588
|
style: { aspectRatio: resolveAspectRatio2(aspectRatio) }
|
|
3488
4589
|
},
|
|
3489
|
-
/* @__PURE__ */
|
|
4590
|
+
/* @__PURE__ */ import_react51.default.createElement(
|
|
3490
4591
|
import_react_player2.default,
|
|
3491
4592
|
{
|
|
3492
4593
|
src,
|
|
@@ -3502,7 +4603,7 @@ var VideoCard = import_react46.default.forwardRef(
|
|
|
3502
4603
|
...playerProps
|
|
3503
4604
|
}
|
|
3504
4605
|
)
|
|
3505
|
-
), (title || subtitle || children) && /* @__PURE__ */
|
|
4606
|
+
), (title || subtitle || children) && /* @__PURE__ */ import_react51.default.createElement("div", { className: cx("px-4 py-4", contentClassName) }, title && /* @__PURE__ */ import_react51.default.createElement("h4", { className: "text-lg font-semibold leading-tight" }, title), subtitle && /* @__PURE__ */ import_react51.default.createElement(
|
|
3506
4607
|
"p",
|
|
3507
4608
|
{
|
|
3508
4609
|
className: "text-sm text-silver leading-normal mt-1"
|
|
@@ -3513,16 +4614,771 @@ var VideoCard = import_react46.default.forwardRef(
|
|
|
3513
4614
|
);
|
|
3514
4615
|
VideoCard.displayName = "VideoCard";
|
|
3515
4616
|
|
|
4617
|
+
// src/components/chat/ArtifactsPanel.tsx
|
|
4618
|
+
function LayersIcon({ className }) {
|
|
4619
|
+
return /* @__PURE__ */ import_react52.default.createElement(
|
|
4620
|
+
"svg",
|
|
4621
|
+
{
|
|
4622
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4623
|
+
viewBox: "0 0 20 20",
|
|
4624
|
+
fill: "currentColor",
|
|
4625
|
+
className
|
|
4626
|
+
},
|
|
4627
|
+
/* @__PURE__ */ import_react52.default.createElement("path", { d: "M3.196 12.87l-.825.483a.75.75 0 000 1.294l7.25 4.25a.75.75 0 00.758 0l7.25-4.25a.75.75 0 000-1.294l-.825-.484-5.666 3.322a2.25 2.25 0 01-2.276 0L3.196 12.87z" }),
|
|
4628
|
+
/* @__PURE__ */ import_react52.default.createElement("path", { d: "M3.196 8.87l-.825.483a.75.75 0 000 1.294l7.25 4.25a.75.75 0 00.758 0l7.25-4.25a.75.75 0 000-1.294l-.825-.484-5.666 3.322a2.25 2.25 0 01-2.276 0L3.196 8.87z" }),
|
|
4629
|
+
/* @__PURE__ */ import_react52.default.createElement("path", { d: "M10.38 1.103a.75.75 0 00-.76 0l-7.25 4.25a.75.75 0 000 1.294l7.25 4.25a.75.75 0 00.76 0l7.25-4.25a.75.75 0 000-1.294l-7.25-4.25z" })
|
|
4630
|
+
);
|
|
4631
|
+
}
|
|
4632
|
+
function ChevronRightIcon2({ className }) {
|
|
4633
|
+
return /* @__PURE__ */ import_react52.default.createElement(
|
|
4634
|
+
"svg",
|
|
4635
|
+
{
|
|
4636
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4637
|
+
viewBox: "0 0 20 20",
|
|
4638
|
+
fill: "currentColor",
|
|
4639
|
+
className
|
|
4640
|
+
},
|
|
4641
|
+
/* @__PURE__ */ import_react52.default.createElement(
|
|
4642
|
+
"path",
|
|
4643
|
+
{
|
|
4644
|
+
fillRule: "evenodd",
|
|
4645
|
+
d: "M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z",
|
|
4646
|
+
clipRule: "evenodd"
|
|
4647
|
+
}
|
|
4648
|
+
)
|
|
4649
|
+
);
|
|
4650
|
+
}
|
|
4651
|
+
function ArtifactSkeleton({ type }) {
|
|
4652
|
+
if (type === "image") {
|
|
4653
|
+
return /* @__PURE__ */ import_react52.default.createElement("div", { className: "overflow-hidden" }, /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "w-full h-48" }), /* @__PURE__ */ import_react52.default.createElement("div", { className: "p-4 bg-charcoal border border-ash/40 border-t-0" }, /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-5 w-3/4 mb-2" }), /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-4 w-1/2" })));
|
|
4654
|
+
}
|
|
4655
|
+
if (type === "video") {
|
|
4656
|
+
return /* @__PURE__ */ import_react52.default.createElement("div", { className: "overflow-hidden" }, /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "w-full aspect-video" }), /* @__PURE__ */ import_react52.default.createElement("div", { className: "p-4 bg-charcoal border border-ash/40 border-t-0" }, /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-5 w-3/4 mb-2" }), /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-4 w-1/2" })));
|
|
4657
|
+
}
|
|
4658
|
+
return /* @__PURE__ */ import_react52.default.createElement("div", { className: "p-4 bg-charcoal border border-ash/40 space-y-2" }, /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-5 w-1/2" }), /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-4 w-full" }), /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-4 w-full" }), /* @__PURE__ */ import_react52.default.createElement(Skeleton, { className: "h-4 w-3/4" }));
|
|
4659
|
+
}
|
|
4660
|
+
function ArtifactRenderer({ artifact, isLoading }) {
|
|
4661
|
+
const [imageLoaded, setImageLoaded] = (0, import_react52.useState)(false);
|
|
4662
|
+
const [minDelayPassed, setMinDelayPassed] = (0, import_react52.useState)(false);
|
|
4663
|
+
(0, import_react52.useEffect)(() => {
|
|
4664
|
+
setImageLoaded(false);
|
|
4665
|
+
setMinDelayPassed(false);
|
|
4666
|
+
const timer = setTimeout(() => {
|
|
4667
|
+
setMinDelayPassed(true);
|
|
4668
|
+
}, 800);
|
|
4669
|
+
return () => clearTimeout(timer);
|
|
4670
|
+
}, [artifact.src, artifact.id]);
|
|
4671
|
+
if (isLoading || artifact.isPending) {
|
|
4672
|
+
return /* @__PURE__ */ import_react52.default.createElement(ArtifactSkeleton, { type: artifact.type });
|
|
4673
|
+
}
|
|
4674
|
+
const showContent = imageLoaded && minDelayPassed;
|
|
4675
|
+
switch (artifact.type) {
|
|
4676
|
+
case "image":
|
|
4677
|
+
return /* @__PURE__ */ import_react52.default.createElement("div", { className: "relative" }, !showContent && /* @__PURE__ */ import_react52.default.createElement(ArtifactSkeleton, { type: "image" }), /* @__PURE__ */ import_react52.default.createElement(
|
|
4678
|
+
ImageCard,
|
|
4679
|
+
{
|
|
4680
|
+
src: artifact.src || "",
|
|
4681
|
+
alt: artifact.alt || "Artifact image",
|
|
4682
|
+
title: artifact.title,
|
|
4683
|
+
subtitle: artifact.subtitle,
|
|
4684
|
+
aspectRatio: "landscape",
|
|
4685
|
+
className: cx(
|
|
4686
|
+
"w-full transition-opacity duration-300",
|
|
4687
|
+
showContent ? "opacity-100" : "opacity-0 absolute inset-0"
|
|
4688
|
+
),
|
|
4689
|
+
onLoad: () => setImageLoaded(true)
|
|
4690
|
+
}
|
|
4691
|
+
));
|
|
4692
|
+
case "video":
|
|
4693
|
+
return /* @__PURE__ */ import_react52.default.createElement(
|
|
4694
|
+
VideoCard,
|
|
4695
|
+
{
|
|
4696
|
+
src: artifact.src || "",
|
|
4697
|
+
title: artifact.title,
|
|
4698
|
+
subtitle: artifact.subtitle,
|
|
4699
|
+
aspectRatio: "video",
|
|
4700
|
+
controls: true,
|
|
4701
|
+
className: "w-full"
|
|
4702
|
+
}
|
|
4703
|
+
);
|
|
4704
|
+
case "text":
|
|
4705
|
+
return /* @__PURE__ */ import_react52.default.createElement("div", { className: "p-4 bg-charcoal border border-ash/40" }, artifact.title && /* @__PURE__ */ import_react52.default.createElement("h4", { className: "text-lg font-semibold text-white mb-2" }, artifact.title), /* @__PURE__ */ import_react52.default.createElement(
|
|
4706
|
+
MarkdownContent,
|
|
4707
|
+
{
|
|
4708
|
+
content: artifact.content || "",
|
|
4709
|
+
className: "prose-sm prose-invert"
|
|
4710
|
+
}
|
|
4711
|
+
));
|
|
4712
|
+
default:
|
|
4713
|
+
return null;
|
|
4714
|
+
}
|
|
4715
|
+
}
|
|
4716
|
+
var ArtifactsPanel = import_react52.default.forwardRef(
|
|
4717
|
+
({ artifacts, isOpen = false, onClose, isLoading = false, className, ...rest }, ref) => {
|
|
4718
|
+
if (!isOpen) {
|
|
4719
|
+
return /* @__PURE__ */ import_react52.default.createElement(
|
|
4720
|
+
"div",
|
|
4721
|
+
{
|
|
4722
|
+
ref,
|
|
4723
|
+
className: cx(
|
|
4724
|
+
"h-full bg-charcoal/80 border-l border-ash/40 flex flex-col items-center py-3",
|
|
4725
|
+
"w-12 flex-shrink-0",
|
|
4726
|
+
className
|
|
4727
|
+
),
|
|
4728
|
+
...rest
|
|
4729
|
+
},
|
|
4730
|
+
/* @__PURE__ */ import_react52.default.createElement(
|
|
4731
|
+
"button",
|
|
4732
|
+
{
|
|
4733
|
+
onClick: onClose,
|
|
4734
|
+
className: cx(
|
|
4735
|
+
"p-2",
|
|
4736
|
+
"text-silver hover:text-white hover:bg-ash/20",
|
|
4737
|
+
"transition-colors duration-150",
|
|
4738
|
+
"relative"
|
|
4739
|
+
),
|
|
4740
|
+
"aria-label": "Expand artifacts panel"
|
|
4741
|
+
},
|
|
4742
|
+
/* @__PURE__ */ import_react52.default.createElement(LayersIcon, { className: "w-5 h-5" }),
|
|
4743
|
+
artifacts.length > 0 && /* @__PURE__ */ import_react52.default.createElement("span", { className: "absolute -top-1 -right-1 w-4 h-4 bg-gold text-obsidian text-xs font-medium flex items-center justify-center rounded-full" }, artifacts.length)
|
|
4744
|
+
)
|
|
4745
|
+
);
|
|
4746
|
+
}
|
|
4747
|
+
return /* @__PURE__ */ import_react52.default.createElement(
|
|
4748
|
+
"div",
|
|
4749
|
+
{
|
|
4750
|
+
ref,
|
|
4751
|
+
className: cx(
|
|
4752
|
+
"h-full bg-charcoal/50 border-l border-ash/40 flex flex-col",
|
|
4753
|
+
"w-96 flex-shrink-0",
|
|
4754
|
+
className
|
|
4755
|
+
),
|
|
4756
|
+
...rest
|
|
4757
|
+
},
|
|
4758
|
+
/* @__PURE__ */ import_react52.default.createElement("div", { className: "flex items-center justify-between p-4 border-b border-ash/40 flex-shrink-0" }, /* @__PURE__ */ import_react52.default.createElement("h3", { className: "text-lg font-semibold text-white" }, "Artifacts"), /* @__PURE__ */ import_react52.default.createElement(
|
|
4759
|
+
"button",
|
|
4760
|
+
{
|
|
4761
|
+
onClick: onClose,
|
|
4762
|
+
className: cx(
|
|
4763
|
+
"p-1.5",
|
|
4764
|
+
"text-silver hover:text-white hover:bg-ash/20",
|
|
4765
|
+
"transition-colors duration-150"
|
|
4766
|
+
),
|
|
4767
|
+
"aria-label": "Collapse artifacts panel"
|
|
4768
|
+
},
|
|
4769
|
+
/* @__PURE__ */ import_react52.default.createElement(ChevronRightIcon2, { className: "w-5 h-5" })
|
|
4770
|
+
)),
|
|
4771
|
+
/* @__PURE__ */ import_react52.default.createElement("div", { className: "flex-1 overflow-y-auto p-4 space-y-4" }, artifacts.length === 0 && !isLoading ? /* @__PURE__ */ import_react52.default.createElement("p", { className: "text-sm text-silver/60 text-center py-8" }, "No artifacts to display") : artifacts.map((artifact) => /* @__PURE__ */ import_react52.default.createElement(
|
|
4772
|
+
ArtifactRenderer,
|
|
4773
|
+
{
|
|
4774
|
+
key: artifact.id,
|
|
4775
|
+
artifact,
|
|
4776
|
+
isLoading
|
|
4777
|
+
}
|
|
4778
|
+
)))
|
|
4779
|
+
);
|
|
4780
|
+
}
|
|
4781
|
+
);
|
|
4782
|
+
ArtifactsPanel.displayName = "ArtifactsPanel";
|
|
4783
|
+
var ArtifactsPanelToggle = import_react52.default.forwardRef(({ artifactCount = 0, onExpand, className, ...rest }, ref) => {
|
|
4784
|
+
return /* @__PURE__ */ import_react52.default.createElement(
|
|
4785
|
+
"button",
|
|
4786
|
+
{
|
|
4787
|
+
ref,
|
|
4788
|
+
onClick: onExpand,
|
|
4789
|
+
className: cx(
|
|
4790
|
+
"p-2",
|
|
4791
|
+
"bg-charcoal/80 border border-ash/40",
|
|
4792
|
+
"text-silver hover:text-white hover:bg-ash/20",
|
|
4793
|
+
"transition-colors duration-150",
|
|
4794
|
+
"flex items-center gap-2",
|
|
4795
|
+
"relative",
|
|
4796
|
+
className
|
|
4797
|
+
),
|
|
4798
|
+
"aria-label": "Expand artifacts panel",
|
|
4799
|
+
...rest
|
|
4800
|
+
},
|
|
4801
|
+
/* @__PURE__ */ import_react52.default.createElement(LayersIcon, { className: "w-5 h-5" }),
|
|
4802
|
+
artifactCount > 0 && /* @__PURE__ */ import_react52.default.createElement("span", { className: "absolute -top-1 -right-1 w-4 h-4 bg-gold text-obsidian text-xs font-medium flex items-center justify-center rounded-full" }, artifactCount)
|
|
4803
|
+
);
|
|
4804
|
+
});
|
|
4805
|
+
ArtifactsPanelToggle.displayName = "ArtifactsPanelToggle";
|
|
4806
|
+
|
|
4807
|
+
// src/components/chat/hooks/useArtifactParser.ts
|
|
4808
|
+
var import_react53 = require("react");
|
|
4809
|
+
var COMPLETE_ARTIFACT_REGEX = /:::artifact\{([^}]+)\}(?:([^:]*?))?:::/gs;
|
|
4810
|
+
var ARTIFACT_START_REGEX = /:::artifact\{/;
|
|
4811
|
+
function parseAttributes(attrString) {
|
|
4812
|
+
const attrs = {};
|
|
4813
|
+
const regex = /(\w+)="([^"]*)"/g;
|
|
4814
|
+
let match;
|
|
4815
|
+
while ((match = regex.exec(attrString)) !== null) {
|
|
4816
|
+
attrs[match[1]] = match[2];
|
|
4817
|
+
}
|
|
4818
|
+
return attrs;
|
|
4819
|
+
}
|
|
4820
|
+
function generateStableArtifactId(type, identifier) {
|
|
4821
|
+
const str = `${type}:${identifier}`;
|
|
4822
|
+
let hash = 0;
|
|
4823
|
+
for (let i = 0; i < str.length; i++) {
|
|
4824
|
+
const char = str.charCodeAt(i);
|
|
4825
|
+
hash = (hash << 5) - hash + char;
|
|
4826
|
+
hash = hash & hash;
|
|
4827
|
+
}
|
|
4828
|
+
return `artifact-${Math.abs(hash).toString(36)}`;
|
|
4829
|
+
}
|
|
4830
|
+
function useArtifactParser(content) {
|
|
4831
|
+
return (0, import_react53.useMemo)(() => {
|
|
4832
|
+
if (!content) {
|
|
4833
|
+
return { cleanContent: "", artifacts: [], hasPendingArtifact: false };
|
|
4834
|
+
}
|
|
4835
|
+
const artifacts = [];
|
|
4836
|
+
let workingContent = content;
|
|
4837
|
+
let artifactIndex = 0;
|
|
4838
|
+
workingContent = workingContent.replace(COMPLETE_ARTIFACT_REGEX, (_, attrString, innerContent) => {
|
|
4839
|
+
const attrs = parseAttributes(attrString);
|
|
4840
|
+
const type = attrs.type || "text";
|
|
4841
|
+
const identifier = attrs.src || attrs.content || innerContent || `idx-${artifactIndex++}`;
|
|
4842
|
+
const id = generateStableArtifactId(type, identifier);
|
|
4843
|
+
const artifact = {
|
|
4844
|
+
id,
|
|
4845
|
+
type,
|
|
4846
|
+
title: attrs.title,
|
|
4847
|
+
subtitle: attrs.subtitle
|
|
4848
|
+
};
|
|
4849
|
+
if (type === "text") {
|
|
4850
|
+
artifact.content = innerContent?.trim() || attrs.content;
|
|
4851
|
+
} else if (type === "image") {
|
|
4852
|
+
artifact.src = attrs.src;
|
|
4853
|
+
artifact.alt = attrs.alt || "Image";
|
|
4854
|
+
} else if (type === "video") {
|
|
4855
|
+
artifact.src = attrs.src;
|
|
4856
|
+
}
|
|
4857
|
+
artifacts.push(artifact);
|
|
4858
|
+
return "";
|
|
4859
|
+
});
|
|
4860
|
+
const startMatch = workingContent.match(ARTIFACT_START_REGEX);
|
|
4861
|
+
let hasPendingArtifact = false;
|
|
4862
|
+
if (startMatch && startMatch.index !== void 0) {
|
|
4863
|
+
workingContent = workingContent.substring(0, startMatch.index);
|
|
4864
|
+
hasPendingArtifact = true;
|
|
4865
|
+
artifacts.push({
|
|
4866
|
+
id: "artifact-pending",
|
|
4867
|
+
type: "image",
|
|
4868
|
+
// Default to image for skeleton
|
|
4869
|
+
isPending: true
|
|
4870
|
+
});
|
|
4871
|
+
}
|
|
4872
|
+
return {
|
|
4873
|
+
cleanContent: workingContent.trim(),
|
|
4874
|
+
artifacts,
|
|
4875
|
+
hasPendingArtifact
|
|
4876
|
+
};
|
|
4877
|
+
}, [content]);
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4880
|
+
// src/components/chat/ChatInterface.tsx
|
|
4881
|
+
var ChatInterface = import_react54.default.forwardRef(
|
|
4882
|
+
({
|
|
4883
|
+
messages = [],
|
|
4884
|
+
conversationTree,
|
|
4885
|
+
onTreeChange,
|
|
4886
|
+
conversations = [],
|
|
4887
|
+
onMessageSubmit,
|
|
4888
|
+
onEditMessage,
|
|
4889
|
+
onRetryMessage,
|
|
4890
|
+
onStop,
|
|
4891
|
+
onSelectConversation,
|
|
4892
|
+
onNewChat,
|
|
4893
|
+
isStreaming = false,
|
|
4894
|
+
isThinking = false,
|
|
4895
|
+
placeholder = "Send a message...",
|
|
4896
|
+
emptyStateHelper = "Type anything to start a conversation",
|
|
4897
|
+
initialSidebarCollapsed = false,
|
|
4898
|
+
emptyState,
|
|
4899
|
+
showAttachmentButton = true,
|
|
4900
|
+
enableMessageActions = true,
|
|
4901
|
+
attachments: propsAttachments,
|
|
4902
|
+
onAttachmentsChange,
|
|
4903
|
+
className,
|
|
4904
|
+
...rest
|
|
4905
|
+
}, ref) => {
|
|
4906
|
+
const [sidebarCollapsed, setSidebarCollapsed] = (0, import_react54.useState)(initialSidebarCollapsed);
|
|
4907
|
+
const [artifactsPanelOpen, setArtifactsPanelOpen] = (0, import_react54.useState)(false);
|
|
4908
|
+
const isTreeMode = !!conversationTree;
|
|
4909
|
+
const effectiveMessages = (0, import_react54.useMemo)(() => {
|
|
4910
|
+
if (isTreeMode && conversationTree) {
|
|
4911
|
+
const pathNodes = getActivePathMessages(conversationTree);
|
|
4912
|
+
return pathNodes.map((node) => ({
|
|
4913
|
+
id: node.id,
|
|
4914
|
+
variant: node.role,
|
|
4915
|
+
content: node.content,
|
|
4916
|
+
isStreaming: node.isStreaming
|
|
4917
|
+
}));
|
|
4918
|
+
}
|
|
4919
|
+
return messages;
|
|
4920
|
+
}, [isTreeMode, conversationTree, messages]);
|
|
4921
|
+
const latestUserMessageIndex = (0, import_react54.useMemo)(() => {
|
|
4922
|
+
for (let i = effectiveMessages.length - 1; i >= 0; i--) {
|
|
4923
|
+
if (effectiveMessages[i].variant === "user") {
|
|
4924
|
+
return i;
|
|
4925
|
+
}
|
|
4926
|
+
}
|
|
4927
|
+
return -1;
|
|
4928
|
+
}, [effectiveMessages]);
|
|
4929
|
+
const allAssistantContent = (0, import_react54.useMemo)(() => {
|
|
4930
|
+
return effectiveMessages.filter((msg) => msg.variant === "assistant").map((msg) => msg.content).join("\n\n");
|
|
4931
|
+
}, [effectiveMessages]);
|
|
4932
|
+
const { artifacts, hasPendingArtifact } = useArtifactParser(allAssistantContent);
|
|
4933
|
+
const currentStreamingCleanContent = (0, import_react54.useMemo)(() => {
|
|
4934
|
+
if (!isStreaming || effectiveMessages.length === 0) {
|
|
4935
|
+
return null;
|
|
4936
|
+
}
|
|
4937
|
+
const lastMessage = effectiveMessages[effectiveMessages.length - 1];
|
|
4938
|
+
if (lastMessage.variant === "assistant") {
|
|
4939
|
+
const content = lastMessage.content;
|
|
4940
|
+
let clean = content.replace(/:::artifact\{[^}]+}(?:[^:]*?)?:::/gs, "");
|
|
4941
|
+
const startMatch = clean.match(/:::artifact\{/);
|
|
4942
|
+
if (startMatch && startMatch.index !== void 0) {
|
|
4943
|
+
clean = clean.substring(0, startMatch.index);
|
|
4944
|
+
}
|
|
4945
|
+
return clean.trim();
|
|
4946
|
+
}
|
|
4947
|
+
return null;
|
|
4948
|
+
}, [effectiveMessages, isStreaming]);
|
|
4949
|
+
import_react54.default.useEffect(() => {
|
|
4950
|
+
if ((artifacts.length > 0 || hasPendingArtifact) && !artifactsPanelOpen) {
|
|
4951
|
+
setArtifactsPanelOpen(true);
|
|
4952
|
+
}
|
|
4953
|
+
}, [artifacts.length, hasPendingArtifact, artifactsPanelOpen]);
|
|
4954
|
+
const handleBranchSwitch = (0, import_react54.useCallback)(
|
|
4955
|
+
(nodeId, direction) => {
|
|
4956
|
+
if (!isTreeMode || !conversationTree || !onTreeChange) {
|
|
4957
|
+
return;
|
|
4958
|
+
}
|
|
4959
|
+
const newTree = switchBranch(conversationTree, nodeId, direction);
|
|
4960
|
+
onTreeChange(newTree);
|
|
4961
|
+
},
|
|
4962
|
+
[isTreeMode, conversationTree, onTreeChange]
|
|
4963
|
+
);
|
|
4964
|
+
const displayMessages = (0, import_react54.useMemo)(() => {
|
|
4965
|
+
return effectiveMessages.map((msg, idx) => {
|
|
4966
|
+
let cleanContent = msg.content;
|
|
4967
|
+
if (msg.variant === "assistant") {
|
|
4968
|
+
if (isStreaming && idx === effectiveMessages.length - 1 && currentStreamingCleanContent !== null) {
|
|
4969
|
+
cleanContent = currentStreamingCleanContent;
|
|
4970
|
+
} else {
|
|
4971
|
+
let clean = msg.content.replace(/:::artifact\{[^}]+}(?:[^:]*?)?:::/gs, "");
|
|
4972
|
+
const startMatch = clean.match(/:::artifact\{/);
|
|
4973
|
+
if (startMatch && startMatch.index !== void 0) {
|
|
4974
|
+
clean = clean.substring(0, startMatch.index);
|
|
4975
|
+
}
|
|
4976
|
+
cleanContent = clean.trim();
|
|
4977
|
+
}
|
|
4978
|
+
}
|
|
4979
|
+
let branchInfo = void 0;
|
|
4980
|
+
if (isTreeMode && conversationTree) {
|
|
4981
|
+
const siblingInfo = getSiblingInfo(conversationTree, msg.id);
|
|
4982
|
+
if (siblingInfo.total > 1) {
|
|
4983
|
+
branchInfo = {
|
|
4984
|
+
current: siblingInfo.current,
|
|
4985
|
+
total: siblingInfo.total,
|
|
4986
|
+
onPrevious: () => handleBranchSwitch(msg.id, "prev"),
|
|
4987
|
+
onNext: () => handleBranchSwitch(msg.id, "next")
|
|
4988
|
+
};
|
|
4989
|
+
}
|
|
4990
|
+
}
|
|
4991
|
+
const actions = enableMessageActions ? {
|
|
4992
|
+
showCopy: true,
|
|
4993
|
+
onEdit: msg.variant === "user" && onEditMessage ? (newContent) => onEditMessage(msg.id, newContent) : void 0,
|
|
4994
|
+
onRetry: msg.variant === "assistant" && onRetryMessage ? () => onRetryMessage(msg.id) : void 0
|
|
4995
|
+
} : void 0;
|
|
4996
|
+
return {
|
|
4997
|
+
...msg,
|
|
4998
|
+
content: cleanContent,
|
|
4999
|
+
branchInfo,
|
|
5000
|
+
actions
|
|
5001
|
+
};
|
|
5002
|
+
});
|
|
5003
|
+
}, [
|
|
5004
|
+
effectiveMessages,
|
|
5005
|
+
isStreaming,
|
|
5006
|
+
currentStreamingCleanContent,
|
|
5007
|
+
isTreeMode,
|
|
5008
|
+
conversationTree,
|
|
5009
|
+
enableMessageActions,
|
|
5010
|
+
onEditMessage,
|
|
5011
|
+
onRetryMessage,
|
|
5012
|
+
handleBranchSwitch
|
|
5013
|
+
]);
|
|
5014
|
+
const allArtifacts = (0, import_react54.useMemo)(() => {
|
|
5015
|
+
return artifacts;
|
|
5016
|
+
}, [artifacts]);
|
|
5017
|
+
const handleSubmit = (0, import_react54.useCallback)(
|
|
5018
|
+
(message, attachments) => {
|
|
5019
|
+
onMessageSubmit?.(message, attachments);
|
|
5020
|
+
},
|
|
5021
|
+
[onMessageSubmit]
|
|
5022
|
+
);
|
|
5023
|
+
const toggleSidebar = (0, import_react54.useCallback)(() => {
|
|
5024
|
+
setSidebarCollapsed((prev) => !prev);
|
|
5025
|
+
}, []);
|
|
5026
|
+
const toggleArtifactsPanel = (0, import_react54.useCallback)(() => {
|
|
5027
|
+
setArtifactsPanelOpen((prev) => !prev);
|
|
5028
|
+
}, []);
|
|
5029
|
+
const isEmpty = effectiveMessages.length === 0;
|
|
5030
|
+
return /* @__PURE__ */ import_react54.default.createElement(
|
|
5031
|
+
"div",
|
|
5032
|
+
{
|
|
5033
|
+
ref,
|
|
5034
|
+
className: cx("flex h-full w-full bg-obsidian overflow-hidden", className),
|
|
5035
|
+
...rest
|
|
5036
|
+
},
|
|
5037
|
+
/* @__PURE__ */ import_react54.default.createElement(
|
|
5038
|
+
ConversationSidebar,
|
|
5039
|
+
{
|
|
5040
|
+
conversations,
|
|
5041
|
+
isCollapsed: sidebarCollapsed,
|
|
5042
|
+
onSelectConversation,
|
|
5043
|
+
onNewChat,
|
|
5044
|
+
onToggleCollapse: toggleSidebar
|
|
5045
|
+
}
|
|
5046
|
+
),
|
|
5047
|
+
/* @__PURE__ */ import_react54.default.createElement("div", { className: "flex-1 flex flex-col min-w-0 relative" }, /* @__PURE__ */ import_react54.default.createElement("div", { className: cx(
|
|
5048
|
+
"flex-1 flex flex-col min-h-0 relative transition-all duration-500",
|
|
5049
|
+
isEmpty ? "justify-center" : "justify-start"
|
|
5050
|
+
) }, /* @__PURE__ */ import_react54.default.createElement("div", { className: cx(
|
|
5051
|
+
"transition-all duration-500 ease-in-out",
|
|
5052
|
+
isEmpty ? "flex-1" : "flex-zero"
|
|
5053
|
+
) }), /* @__PURE__ */ import_react54.default.createElement("div", { className: cx(
|
|
5054
|
+
"transition-all duration-500 ease-in-out overflow-hidden flex flex-col",
|
|
5055
|
+
isEmpty ? "flex-zero opacity-0" : "flex-1 opacity-100"
|
|
5056
|
+
) }, /* @__PURE__ */ import_react54.default.createElement(
|
|
5057
|
+
ChatView,
|
|
5058
|
+
{
|
|
5059
|
+
messages: displayMessages,
|
|
5060
|
+
latestUserMessageIndex,
|
|
5061
|
+
isStreaming,
|
|
5062
|
+
isThinking,
|
|
5063
|
+
className: "flex-1"
|
|
5064
|
+
}
|
|
5065
|
+
)), /* @__PURE__ */ import_react54.default.createElement("div", { className: cx(
|
|
5066
|
+
"transition-all duration-500 ease-in-out z-10 w-full",
|
|
5067
|
+
isEmpty ? "p-4" : "shrink-0 p-4 border-t border-ash/40 bg-obsidian"
|
|
5068
|
+
) }, isEmpty && emptyState ? /* @__PURE__ */ import_react54.default.createElement("div", { className: "flex justify-center" }, emptyState) : /* @__PURE__ */ import_react54.default.createElement(
|
|
5069
|
+
ChatInput,
|
|
5070
|
+
{
|
|
5071
|
+
position: isEmpty ? "centered" : "bottom",
|
|
5072
|
+
placeholder,
|
|
5073
|
+
helperText: isEmpty ? emptyStateHelper : void 0,
|
|
5074
|
+
onSubmit: handleSubmit,
|
|
5075
|
+
disabled: isEmpty ? isStreaming : isStreaming && !onStop,
|
|
5076
|
+
isStreaming,
|
|
5077
|
+
onStop,
|
|
5078
|
+
showAttachmentButton,
|
|
5079
|
+
attachments: propsAttachments,
|
|
5080
|
+
onAttachmentsChange
|
|
5081
|
+
}
|
|
5082
|
+
)), /* @__PURE__ */ import_react54.default.createElement("div", { className: cx(
|
|
5083
|
+
"transition-all duration-500 ease-in-out",
|
|
5084
|
+
isEmpty ? "flex-1" : "flex-zero"
|
|
5085
|
+
) }))),
|
|
5086
|
+
/* @__PURE__ */ import_react54.default.createElement(
|
|
5087
|
+
ArtifactsPanel,
|
|
5088
|
+
{
|
|
5089
|
+
artifacts: allArtifacts,
|
|
5090
|
+
isOpen: artifactsPanelOpen,
|
|
5091
|
+
onClose: toggleArtifactsPanel,
|
|
5092
|
+
isLoading: isStreaming && hasPendingArtifact
|
|
5093
|
+
}
|
|
5094
|
+
)
|
|
5095
|
+
);
|
|
5096
|
+
}
|
|
5097
|
+
);
|
|
5098
|
+
ChatInterface.displayName = "ChatInterface";
|
|
5099
|
+
|
|
5100
|
+
// src/components/chat/MessageActions.tsx
|
|
5101
|
+
var import_react55 = __toESM(require("react"));
|
|
5102
|
+
var import_lucide_react12 = require("lucide-react");
|
|
5103
|
+
var ActionButton2 = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ import_react55.default.createElement(
|
|
5104
|
+
"button",
|
|
5105
|
+
{
|
|
5106
|
+
type: "button",
|
|
5107
|
+
onClick,
|
|
5108
|
+
disabled,
|
|
5109
|
+
className: cx(
|
|
5110
|
+
"p-1.5 text-silver/60 hover:text-silver transition-colors duration-150",
|
|
5111
|
+
"hover:bg-white/5 ",
|
|
5112
|
+
"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent",
|
|
5113
|
+
className
|
|
5114
|
+
),
|
|
5115
|
+
"aria-label": label
|
|
5116
|
+
},
|
|
5117
|
+
children
|
|
5118
|
+
);
|
|
5119
|
+
var MessageActions = import_react55.default.forwardRef(
|
|
5120
|
+
({
|
|
5121
|
+
variant,
|
|
5122
|
+
content,
|
|
5123
|
+
onEdit,
|
|
5124
|
+
onRetry,
|
|
5125
|
+
isEditing: controlledIsEditing,
|
|
5126
|
+
onEditingChange,
|
|
5127
|
+
editValue: controlledEditValue,
|
|
5128
|
+
className,
|
|
5129
|
+
...rest
|
|
5130
|
+
}, ref) => {
|
|
5131
|
+
const [localIsEditing, setLocalIsEditing] = (0, import_react55.useState)(false);
|
|
5132
|
+
const [localEditValue, setLocalEditValue] = (0, import_react55.useState)(content);
|
|
5133
|
+
const [copied, setCopied] = (0, import_react55.useState)(false);
|
|
5134
|
+
const isEditing = controlledIsEditing ?? localIsEditing;
|
|
5135
|
+
const editValue = controlledEditValue ?? localEditValue;
|
|
5136
|
+
const setIsEditing = (0, import_react55.useCallback)(
|
|
5137
|
+
(value) => {
|
|
5138
|
+
if (onEditingChange) {
|
|
5139
|
+
onEditingChange(value);
|
|
5140
|
+
} else {
|
|
5141
|
+
setLocalIsEditing(value);
|
|
5142
|
+
}
|
|
5143
|
+
},
|
|
5144
|
+
[onEditingChange]
|
|
5145
|
+
);
|
|
5146
|
+
const setEditValue = (0, import_react55.useCallback)((value) => {
|
|
5147
|
+
setLocalEditValue(value);
|
|
5148
|
+
}, []);
|
|
5149
|
+
const handleCopy = (0, import_react55.useCallback)(async () => {
|
|
5150
|
+
try {
|
|
5151
|
+
await navigator.clipboard.writeText(content);
|
|
5152
|
+
setCopied(true);
|
|
5153
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
5154
|
+
} catch {
|
|
5155
|
+
const textArea = document.createElement("textarea");
|
|
5156
|
+
textArea.value = content;
|
|
5157
|
+
document.body.appendChild(textArea);
|
|
5158
|
+
textArea.select();
|
|
5159
|
+
document.execCommand("copy");
|
|
5160
|
+
document.body.removeChild(textArea);
|
|
5161
|
+
setCopied(true);
|
|
5162
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
5163
|
+
}
|
|
5164
|
+
}, [content]);
|
|
5165
|
+
const handleStartEdit = (0, import_react55.useCallback)(() => {
|
|
5166
|
+
setLocalEditValue(content);
|
|
5167
|
+
setIsEditing(true);
|
|
5168
|
+
}, [content, setIsEditing]);
|
|
5169
|
+
const handleCancelEdit = (0, import_react55.useCallback)(() => {
|
|
5170
|
+
setIsEditing(false);
|
|
5171
|
+
setLocalEditValue(content);
|
|
5172
|
+
}, [content, setIsEditing]);
|
|
5173
|
+
const handleSubmitEdit = (0, import_react55.useCallback)(() => {
|
|
5174
|
+
const trimmed = editValue.trim();
|
|
5175
|
+
if (trimmed && trimmed !== content) {
|
|
5176
|
+
onEdit?.(trimmed);
|
|
5177
|
+
}
|
|
5178
|
+
setIsEditing(false);
|
|
5179
|
+
}, [editValue, content, onEdit, setIsEditing]);
|
|
5180
|
+
const handleEditKeyDown = (0, import_react55.useCallback)(
|
|
5181
|
+
(e) => {
|
|
5182
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
5183
|
+
e.preventDefault();
|
|
5184
|
+
handleSubmitEdit();
|
|
5185
|
+
} else if (e.key === "Escape") {
|
|
5186
|
+
handleCancelEdit();
|
|
5187
|
+
}
|
|
5188
|
+
},
|
|
5189
|
+
[handleSubmitEdit, handleCancelEdit]
|
|
5190
|
+
);
|
|
5191
|
+
const isUser = variant === "user";
|
|
5192
|
+
if (isUser && isEditing) {
|
|
5193
|
+
return /* @__PURE__ */ import_react55.default.createElement(
|
|
5194
|
+
"div",
|
|
5195
|
+
{
|
|
5196
|
+
ref,
|
|
5197
|
+
className: cx("mt-2", className),
|
|
5198
|
+
...rest
|
|
5199
|
+
},
|
|
5200
|
+
/* @__PURE__ */ import_react55.default.createElement("div", { className: "relative bg-charcoal border border-ash/60 focus-within:border-gold/60 focus-within:ring-1 focus-within:ring-gold/20" }, /* @__PURE__ */ import_react55.default.createElement(
|
|
5201
|
+
"textarea",
|
|
5202
|
+
{
|
|
5203
|
+
value: editValue,
|
|
5204
|
+
onChange: (e) => setEditValue(e.target.value),
|
|
5205
|
+
onKeyDown: handleEditKeyDown,
|
|
5206
|
+
className: "w-full bg-transparent text-white px-3 py-2 pr-20 resize-none outline-none min-h-16 text-sm",
|
|
5207
|
+
autoFocus: true,
|
|
5208
|
+
rows: 2
|
|
5209
|
+
}
|
|
5210
|
+
), /* @__PURE__ */ import_react55.default.createElement("div", { className: "absolute right-2 bottom-2 flex gap-1" }, /* @__PURE__ */ import_react55.default.createElement(
|
|
5211
|
+
ActionButton2,
|
|
5212
|
+
{
|
|
5213
|
+
onClick: handleCancelEdit,
|
|
5214
|
+
label: "Cancel edit",
|
|
5215
|
+
className: "text-silver/60 hover:text-error"
|
|
5216
|
+
},
|
|
5217
|
+
/* @__PURE__ */ import_react55.default.createElement(import_lucide_react12.X, { className: "w-4 h-4" })
|
|
5218
|
+
), /* @__PURE__ */ import_react55.default.createElement(
|
|
5219
|
+
ActionButton2,
|
|
5220
|
+
{
|
|
5221
|
+
onClick: handleSubmitEdit,
|
|
5222
|
+
label: "Submit edit",
|
|
5223
|
+
className: "text-silver/60 hover:text-gold",
|
|
5224
|
+
disabled: !editValue.trim() || editValue.trim() === content
|
|
5225
|
+
},
|
|
5226
|
+
/* @__PURE__ */ import_react55.default.createElement(import_lucide_react12.Send, { className: "w-4 h-4" })
|
|
5227
|
+
))),
|
|
5228
|
+
/* @__PURE__ */ import_react55.default.createElement("p", { className: "text-xs text-silver/50 mt-1" }, "Press Enter to submit, Esc to cancel. This will create a new branch.")
|
|
5229
|
+
);
|
|
5230
|
+
}
|
|
5231
|
+
return /* @__PURE__ */ import_react55.default.createElement(
|
|
5232
|
+
"div",
|
|
5233
|
+
{
|
|
5234
|
+
ref,
|
|
5235
|
+
className: cx(
|
|
5236
|
+
"flex items-center gap-0.5 mt-1",
|
|
5237
|
+
isUser ? "justify-end" : "justify-start",
|
|
5238
|
+
className
|
|
5239
|
+
),
|
|
5240
|
+
...rest
|
|
5241
|
+
},
|
|
5242
|
+
/* @__PURE__ */ import_react55.default.createElement(ActionButton2, { onClick: handleCopy, label: copied ? "Copied!" : "Copy message" }, copied ? /* @__PURE__ */ import_react55.default.createElement(import_lucide_react12.Check, { className: "w-3.5 h-3.5 text-success" }) : /* @__PURE__ */ import_react55.default.createElement(import_lucide_react12.Copy, { className: "w-3.5 h-3.5" })),
|
|
5243
|
+
isUser && onEdit && /* @__PURE__ */ import_react55.default.createElement(ActionButton2, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react55.default.createElement(import_lucide_react12.Pencil, { className: "w-3.5 h-3.5" })),
|
|
5244
|
+
!isUser && onRetry && /* @__PURE__ */ import_react55.default.createElement(ActionButton2, { onClick: onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react55.default.createElement(import_lucide_react12.RotateCcw, { className: "w-3.5 h-3.5" }))
|
|
5245
|
+
);
|
|
5246
|
+
}
|
|
5247
|
+
);
|
|
5248
|
+
MessageActions.displayName = "MessageActions";
|
|
5249
|
+
|
|
5250
|
+
// src/components/chat/BranchNavigator.tsx
|
|
5251
|
+
var import_react56 = __toESM(require("react"));
|
|
5252
|
+
var import_lucide_react13 = require("lucide-react");
|
|
5253
|
+
var BranchNavigator = import_react56.default.forwardRef(
|
|
5254
|
+
({
|
|
5255
|
+
current,
|
|
5256
|
+
total,
|
|
5257
|
+
onPrevious,
|
|
5258
|
+
onNext,
|
|
5259
|
+
size = "sm",
|
|
5260
|
+
showIcon = true,
|
|
5261
|
+
className,
|
|
5262
|
+
...rest
|
|
5263
|
+
}, ref) => {
|
|
5264
|
+
if (total <= 1) return null;
|
|
5265
|
+
const isFirst = current <= 1;
|
|
5266
|
+
const isLast = current >= total;
|
|
5267
|
+
const buttonSize = size === "sm" ? "p-0.5" : "p-1";
|
|
5268
|
+
const iconSize = size === "sm" ? "w-3 h-3" : "w-4 h-4";
|
|
5269
|
+
const textSize = size === "sm" ? "text-xs" : "text-sm";
|
|
5270
|
+
return /* @__PURE__ */ import_react56.default.createElement(
|
|
5271
|
+
"div",
|
|
5272
|
+
{
|
|
5273
|
+
ref,
|
|
5274
|
+
className: cx(
|
|
5275
|
+
"inline-flex items-center gap-0.5 text-silver/70",
|
|
5276
|
+
className
|
|
5277
|
+
),
|
|
5278
|
+
role: "navigation",
|
|
5279
|
+
"aria-label": "Branch navigation",
|
|
5280
|
+
...rest
|
|
5281
|
+
},
|
|
5282
|
+
showIcon && /* @__PURE__ */ import_react56.default.createElement(import_lucide_react13.GitBranch, { className: cx(iconSize, "mr-0.5 text-silver/50"), "aria-hidden": "true" }),
|
|
5283
|
+
/* @__PURE__ */ import_react56.default.createElement(
|
|
5284
|
+
"button",
|
|
5285
|
+
{
|
|
5286
|
+
type: "button",
|
|
5287
|
+
onClick: onPrevious,
|
|
5288
|
+
disabled: isFirst,
|
|
5289
|
+
className: cx(
|
|
5290
|
+
buttonSize,
|
|
5291
|
+
"hover:text-white hover:bg-white/10 transition-colors",
|
|
5292
|
+
"disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-silver/70"
|
|
5293
|
+
),
|
|
5294
|
+
"aria-label": "Previous branch"
|
|
5295
|
+
},
|
|
5296
|
+
/* @__PURE__ */ import_react56.default.createElement(import_lucide_react13.ChevronLeft, { className: iconSize })
|
|
5297
|
+
),
|
|
5298
|
+
/* @__PURE__ */ import_react56.default.createElement("span", { className: cx(textSize, "tabular-nums min-w-6 text-center") }, current, "/", total),
|
|
5299
|
+
/* @__PURE__ */ import_react56.default.createElement(
|
|
5300
|
+
"button",
|
|
5301
|
+
{
|
|
5302
|
+
type: "button",
|
|
5303
|
+
onClick: onNext,
|
|
5304
|
+
disabled: isLast,
|
|
5305
|
+
className: cx(
|
|
5306
|
+
buttonSize,
|
|
5307
|
+
"hover:text-white hover:bg-white/10 transition-colors",
|
|
5308
|
+
"disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-silver/70"
|
|
5309
|
+
),
|
|
5310
|
+
"aria-label": "Next branch"
|
|
5311
|
+
},
|
|
5312
|
+
/* @__PURE__ */ import_react56.default.createElement(import_lucide_react13.ChevronRight, { className: iconSize })
|
|
5313
|
+
)
|
|
5314
|
+
);
|
|
5315
|
+
}
|
|
5316
|
+
);
|
|
5317
|
+
BranchNavigator.displayName = "BranchNavigator";
|
|
5318
|
+
|
|
5319
|
+
// src/components/BrandIcon.tsx
|
|
5320
|
+
var import_react57 = __toESM(require("react"));
|
|
5321
|
+
var sizeMap2 = {
|
|
5322
|
+
sm: "h-8 w-8 text-sm",
|
|
5323
|
+
md: "h-12 w-12 text-base",
|
|
5324
|
+
lg: "h-16 w-16 text-lg"
|
|
5325
|
+
};
|
|
5326
|
+
var BrandIcon = import_react57.default.forwardRef(
|
|
5327
|
+
({ size = "md", variant = "solid", children, className, ...rest }, ref) => {
|
|
5328
|
+
const variantClasses = variant === "solid" ? "bg-gold text-obsidian border-2 border-gold" : "bg-transparent text-gold border-2 border-gold";
|
|
5329
|
+
return /* @__PURE__ */ import_react57.default.createElement(
|
|
5330
|
+
"div",
|
|
5331
|
+
{
|
|
5332
|
+
ref,
|
|
5333
|
+
className: cx(
|
|
5334
|
+
"inline-flex items-center justify-center rounded-none font-bold select-none overflow-hidden",
|
|
5335
|
+
sizeMap2[size],
|
|
5336
|
+
variantClasses,
|
|
5337
|
+
className
|
|
5338
|
+
),
|
|
5339
|
+
...rest
|
|
5340
|
+
},
|
|
5341
|
+
children
|
|
5342
|
+
);
|
|
5343
|
+
}
|
|
5344
|
+
);
|
|
5345
|
+
BrandIcon.displayName = "BrandIcon";
|
|
5346
|
+
|
|
5347
|
+
// src/components/ColorSwatch.tsx
|
|
5348
|
+
var import_react58 = __toESM(require("react"));
|
|
5349
|
+
var ColorSwatch = import_react58.default.forwardRef(
|
|
5350
|
+
({ color, label, className, ...rest }, ref) => {
|
|
5351
|
+
return /* @__PURE__ */ import_react58.default.createElement(
|
|
5352
|
+
"div",
|
|
5353
|
+
{
|
|
5354
|
+
ref,
|
|
5355
|
+
className: cx("flex flex-col items-center gap-2", className),
|
|
5356
|
+
...rest
|
|
5357
|
+
},
|
|
5358
|
+
/* @__PURE__ */ import_react58.default.createElement(
|
|
5359
|
+
"div",
|
|
5360
|
+
{
|
|
5361
|
+
className: "h-16 w-16 border-2 border-ash rounded-none shadow-sm",
|
|
5362
|
+
style: { backgroundColor: color },
|
|
5363
|
+
"aria-label": label || color
|
|
5364
|
+
}
|
|
5365
|
+
),
|
|
5366
|
+
label && /* @__PURE__ */ import_react58.default.createElement("span", { className: "text-xs text-silver font-medium" }, label)
|
|
5367
|
+
);
|
|
5368
|
+
}
|
|
5369
|
+
);
|
|
5370
|
+
ColorSwatch.displayName = "ColorSwatch";
|
|
5371
|
+
|
|
3516
5372
|
// src/components/SectionHeading.tsx
|
|
3517
|
-
var
|
|
5373
|
+
var import_react59 = __toESM(require("react"));
|
|
3518
5374
|
var levelStyles = {
|
|
3519
5375
|
h2: "text-2xl mb-4",
|
|
3520
5376
|
h3: "text-xl mb-3"
|
|
3521
5377
|
};
|
|
3522
|
-
var SectionHeading =
|
|
5378
|
+
var SectionHeading = import_react59.default.forwardRef(
|
|
3523
5379
|
({ level = "h2", children, className, ...rest }, ref) => {
|
|
3524
5380
|
const Component = level;
|
|
3525
|
-
return /* @__PURE__ */
|
|
5381
|
+
return /* @__PURE__ */ import_react59.default.createElement(
|
|
3526
5382
|
Component,
|
|
3527
5383
|
{
|
|
3528
5384
|
ref,
|
|
@@ -3549,22 +5405,31 @@ var version = "2.0.0";
|
|
|
3549
5405
|
AccordionTrigger,
|
|
3550
5406
|
Alert,
|
|
3551
5407
|
AlertDialog,
|
|
5408
|
+
ArtifactsPanel,
|
|
5409
|
+
ArtifactsPanelToggle,
|
|
5410
|
+
AttachmentPreview,
|
|
3552
5411
|
Avatar,
|
|
3553
5412
|
Badge,
|
|
5413
|
+
BranchNavigator,
|
|
3554
5414
|
BrandIcon,
|
|
3555
5415
|
Breadcrumb,
|
|
3556
5416
|
BreadcrumbItem,
|
|
3557
5417
|
BreadcrumbLink,
|
|
3558
5418
|
Button,
|
|
3559
5419
|
Card,
|
|
3560
|
-
|
|
5420
|
+
ChatInput,
|
|
5421
|
+
ChatInterface,
|
|
5422
|
+
ChatView,
|
|
3561
5423
|
Checkbox,
|
|
3562
5424
|
Col,
|
|
5425
|
+
CollapsedSidebarToggle,
|
|
3563
5426
|
ColorSwatch,
|
|
3564
5427
|
ConfirmDialog,
|
|
3565
5428
|
Container,
|
|
5429
|
+
ConversationSidebar,
|
|
3566
5430
|
Divider,
|
|
3567
5431
|
Drawer,
|
|
5432
|
+
FileChip,
|
|
3568
5433
|
HelperText,
|
|
3569
5434
|
ImageCard,
|
|
3570
5435
|
Input,
|
|
@@ -3587,6 +5452,7 @@ var version = "2.0.0";
|
|
|
3587
5452
|
MenuSeparator,
|
|
3588
5453
|
MenuTrigger,
|
|
3589
5454
|
Message,
|
|
5455
|
+
MessageActions,
|
|
3590
5456
|
Modal,
|
|
3591
5457
|
Navbar,
|
|
3592
5458
|
NavbarBrand,
|
|
@@ -3622,9 +5488,24 @@ var version = "2.0.0";
|
|
|
3622
5488
|
TableRow,
|
|
3623
5489
|
Tabs,
|
|
3624
5490
|
Textarea,
|
|
5491
|
+
ThinkingIndicator,
|
|
3625
5492
|
ToastProvider,
|
|
3626
5493
|
Tooltip,
|
|
3627
5494
|
VideoCard,
|
|
5495
|
+
addMessageToTree,
|
|
5496
|
+
createEmptyTree,
|
|
5497
|
+
createPreviewUrl,
|
|
5498
|
+
generateId,
|
|
5499
|
+
getActivePathMessages,
|
|
5500
|
+
getSiblingInfo,
|
|
5501
|
+
isBranchPoint,
|
|
5502
|
+
isImageFile,
|
|
5503
|
+
messagesToTree,
|
|
5504
|
+
revokePreviewUrl,
|
|
5505
|
+
switchBranch,
|
|
5506
|
+
updateNodeContent,
|
|
5507
|
+
useArtifactParser,
|
|
5508
|
+
useScrollAnchor,
|
|
3628
5509
|
useToast,
|
|
3629
5510
|
version
|
|
3630
5511
|
});
|