@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.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
- ChatHistory: () => ChatHistory,
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 rounded-md border border-ash bg-graphite px-3 py-1.5 text-sm text-white shadow-lg transition-opacity duration-200 ease-out",
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/Label.tsx
1217
+ // src/components/FileChip.tsx
1193
1218
  var import_react14 = __toESM(require("react"));
1194
- var Label = import_react14.default.forwardRef(
1195
- ({ className, required, children, ...rest }, ref) => {
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__ */ import_react14.default.createElement("span", { className: "text-error ml-1" }, "*")
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 import_react15 = __toESM(require("react"));
1212
- var HelperText = import_react15.default.forwardRef(
1377
+ var import_react17 = __toESM(require("react"));
1378
+ var HelperText = import_react17.default.forwardRef(
1213
1379
  ({ className, error, children, ...rest }, ref) => {
1214
- return /* @__PURE__ */ import_react15.default.createElement(
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 import_react16 = __toESM(require("react"));
1229
- var Textarea = import_react16.default.forwardRef(
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__ */ import_react16.default.createElement(
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 import_react17 = __toESM(require("react"));
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 = import_react17.default.forwardRef(
1415
+ var Select = import_react19.default.forwardRef(
1250
1416
  ({ error = false, className, disabled, options, children, ...rest }, ref) => {
1251
- return /* @__PURE__ */ import_react17.default.createElement(
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__ */ import_react17.default.createElement("option", { key: opt.value, value: opt.value }, opt.label)) : children
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 import_react18 = __toESM(require("react"));
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 = import_react18.default.forwardRef(
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, import_react18.useCallback)((node) => {
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__ */ import_react18.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ import_react18.default.createElement(
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 rounded-sm bg-graphite",
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__ */ import_react18.default.createElement("label", { htmlFor: inputId, className: "ml-2 text-sm text-silver cursor-pointer select-none" }, label));
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 import_react19 = __toESM(require("react"));
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 = import_react19.default.forwardRef(
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, import_react19.useCallback)((node) => {
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__ */ import_react19.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ import_react19.default.createElement(
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__ */ import_react19.default.createElement("label", { htmlFor: inputId, className: "ml-2 text-sm text-silver cursor-pointer select-none" }, label));
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 import_react20 = __toESM(require("react"));
1393
- var Switch = import_react20.default.forwardRef(
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, import_react20.useState)(defaultChecked);
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, import_react20.useRef)(null);
1399
- const setRefs = (0, import_react20.useCallback)(
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__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement(
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__ */ import_react20.default.createElement(
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__ */ import_react20.default.createElement(
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 import_react21 = __toESM(require("react"));
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 = import_react21.default.forwardRef(
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, import_react21.useState)(defaultValue);
1493
- const [isDragging, setIsDragging] = (0, import_react21.useState)(false);
1494
- const trackRef = (0, import_react21.useRef)(null);
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, import_react21.useCallback)(
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__ */ import_react21.default.createElement(
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__ */ import_react21.default.createElement(
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__ */ import_react21.default.createElement(
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__ */ import_react21.default.createElement(
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__ */ import_react21.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))
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 import_react22 = __toESM(require("react"));
1619
- var InputGroup = import_react22.default.forwardRef(
1784
+ var import_react24 = __toESM(require("react"));
1785
+ var InputGroup = import_react24.default.forwardRef(
1620
1786
  ({ className, children, ...props }, ref) => {
1621
- return /* @__PURE__ */ import_react22.default.createElement(
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 = import_react22.default.forwardRef(
1799
+ var InputLeftAddon = import_react24.default.forwardRef(
1634
1800
  ({ className, children, ...props }, ref) => {
1635
- return /* @__PURE__ */ import_react22.default.createElement(
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 = import_react22.default.forwardRef(
1817
+ var InputRightAddon = import_react24.default.forwardRef(
1652
1818
  ({ className, children, ...props }, ref) => {
1653
- return /* @__PURE__ */ import_react22.default.createElement(
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 = import_react22.default.forwardRef(
1835
+ var InputLeftElement = import_react24.default.forwardRef(
1670
1836
  ({ className, children, ...props }, ref) => {
1671
- return /* @__PURE__ */ import_react22.default.createElement(
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 = import_react22.default.forwardRef(
1853
+ var InputRightElement = import_react24.default.forwardRef(
1688
1854
  ({ className, children, ...props }, ref) => {
1689
- return /* @__PURE__ */ import_react22.default.createElement(
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 = import_react22.default.forwardRef(
1870
+ var InputWrapper = import_react24.default.forwardRef(
1705
1871
  ({ className, children, ...props }, ref) => {
1706
- return /* @__PURE__ */ import_react22.default.createElement(
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 import_react23 = __toESM(require("react"));
1721
- var import_lucide_react2 = require("lucide-react");
1886
+ var import_react25 = __toESM(require("react"));
1887
+ var import_lucide_react3 = require("lucide-react");
1722
1888
  var icons = {
1723
- info: import_lucide_react2.Info,
1724
- success: import_lucide_react2.CheckCircle,
1725
- warning: import_lucide_react2.AlertTriangle,
1726
- error: import_lucide_react2.XCircle
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 = import_react23.default.forwardRef(
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__ */ import_react23.default.createElement(
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__ */ import_react23.default.createElement(Icon, { className: "h-5 w-5 shrink-0" }),
1750
- /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex-1" }, title && /* @__PURE__ */ import_react23.default.createElement("h5", { className: "mb-1 font-medium leading-none tracking-tight text-current" }, title), /* @__PURE__ */ import_react23.default.createElement("div", { className: "text-sm opacity-90" }, children))
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 import_react24 = __toESM(require("react"));
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__ */ import_react24.default.createElement(
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__ */ import_react24.default.createElement("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
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 import_react25 = __toESM(require("react"));
1780
- var Skeleton = import_react25.default.forwardRef(
1945
+ var import_react27 = __toESM(require("react"));
1946
+ var Skeleton = import_react27.default.forwardRef(
1781
1947
  ({ className, ...rest }, ref) => {
1782
- return /* @__PURE__ */ import_react25.default.createElement(
1948
+ return /* @__PURE__ */ import_react27.default.createElement(
1783
1949
  "div",
1784
1950
  {
1785
1951
  ref,
1786
- className: cx("animate-pulse bg-ash rounded-sm", className),
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 import_react26 = __toESM(require("react"));
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 = import_react26.default.forwardRef(
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__ */ import_react26.default.createElement("div", { ref, className: cx("w-full", className), ...props }, showValue && /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex justify-between mb-1" }, /* @__PURE__ */ import_react26.default.createElement("span", { className: "text-sm text-silver" }, "Progress"), /* @__PURE__ */ import_react26.default.createElement("span", { className: "text-sm text-white font-medium" }, displayValue)), /* @__PURE__ */ import_react26.default.createElement(
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__ */ import_react26.default.createElement(
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 import_react27 = __toESM(require("react"));
2018
+ var import_react29 = __toESM(require("react"));
1853
2019
  var import_react_dom = require("react-dom");
1854
- var import_lucide_react3 = require("lucide-react");
1855
- var ToastContext = (0, import_react27.createContext)(null);
2020
+ var import_lucide_react4 = require("lucide-react");
2021
+ var ToastContext = (0, import_react29.createContext)(null);
1856
2022
  function useToast() {
1857
- const context = (0, import_react27.useContext)(ToastContext);
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, import_react27.useCallback)(
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, import_react27.useState)([]);
1878
- const [mounted, setMounted] = (0, import_react27.useState)(false);
1879
- (0, import_react27.useEffect)(() => {
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, import_react27.useCallback)(
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, import_react27.useCallback)((id) => {
2061
+ const removeToast = (0, import_react29.useCallback)((id) => {
1896
2062
  setToasts((prev) => prev.filter((t) => t.id !== id));
1897
2063
  }, []);
1898
- return /* @__PURE__ */ import_react27.default.createElement(ToastContext.Provider, { value: { toasts, addToast, removeToast, position } }, children, mounted && /* @__PURE__ */ import_react27.default.createElement(ToastViewport, null));
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, import_react27.useContext)(ToastContext);
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__ */ import_react27.default.createElement(
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__ */ import_react27.default.createElement(Toast, { key: toast.id, ...toast }))
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__ */ import_react27.default.createElement(import_lucide_react3.CheckCircle, { className: "h-5 w-5 text-success" }),
1937
- error: /* @__PURE__ */ import_react27.default.createElement(import_lucide_react3.AlertCircle, { className: "h-5 w-5 text-error" }),
1938
- warning: /* @__PURE__ */ import_react27.default.createElement(import_lucide_react3.AlertTriangle, { className: "h-5 w-5 text-warning" }),
1939
- info: /* @__PURE__ */ import_react27.default.createElement(import_lucide_react3.Info, { className: "h-5 w-5 text-info" })
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, import_react27.useContext)(ToastContext);
1950
- (0, import_react27.useEffect)(() => {
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__ */ import_react27.default.createElement(
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__ */ import_react27.default.createElement("div", { className: "flex gap-3" }, icon && /* @__PURE__ */ import_react27.default.createElement("div", { className: "shrink-0 mt-0.5" }, icon), /* @__PURE__ */ import_react27.default.createElement("div", { className: "flex-1 min-w-0" }, title && /* @__PURE__ */ import_react27.default.createElement("p", { className: "text-sm font-medium text-white" }, title), description && /* @__PURE__ */ import_react27.default.createElement("p", { className: "text-sm text-silver mt-1" }, description), action && /* @__PURE__ */ import_react27.default.createElement("div", { className: "mt-3" }, action)), /* @__PURE__ */ import_react27.default.createElement(
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__ */ import_react27.default.createElement(import_lucide_react3.X, { className: "h-4 w-4" }),
1975
- /* @__PURE__ */ import_react27.default.createElement("span", { className: "sr-only" }, "Dismiss")
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 import_react28 = __toESM(require("react"));
2148
+ var import_react30 = __toESM(require("react"));
1983
2149
  var import_react_dom2 = require("react-dom");
1984
- var import_lucide_react4 = require("lucide-react");
2150
+ var import_lucide_react5 = require("lucide-react");
1985
2151
  var Modal = ({ isOpen, onClose, title, children, className }) => {
1986
- const [mounted, setMounted] = (0, import_react28.useState)(false);
1987
- (0, import_react28.useEffect)(() => {
2152
+ const [mounted, setMounted] = (0, import_react30.useState)(false);
2153
+ (0, import_react30.useEffect)(() => {
1988
2154
  setMounted(true);
1989
2155
  }, []);
1990
- (0, import_react28.useEffect)(() => {
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, import_react28.useEffect)(() => {
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__ */ import_react28.default.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6", onClick: onClose }, /* @__PURE__ */ import_react28.default.createElement("div", { className: "fixed inset-0 z-40 bg-obsidian/80 backdrop-blur-sm", "aria-hidden": "true" }), /* @__PURE__ */ import_react28.default.createElement(
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__ */ import_react28.default.createElement("div", { className: "flex items-center justify-between mb-2" }, title ? /* @__PURE__ */ import_react28.default.createElement("h3", { className: "text-xl font-semibold text-white m-0" }, title) : /* @__PURE__ */ import_react28.default.createElement("div", null), /* @__PURE__ */ import_react28.default.createElement("button", { onClick: onClose, className: "text-silver hover:text-white transition-colors ml-auto" }, /* @__PURE__ */ import_react28.default.createElement(import_lucide_react4.X, { className: "h-5 w-5" }), /* @__PURE__ */ import_react28.default.createElement("span", { className: "sr-only" }, "Close"))),
2026
- /* @__PURE__ */ import_react28.default.createElement("div", null, children)
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 import_react29 = __toESM(require("react"));
2199
+ var import_react31 = __toESM(require("react"));
2034
2200
  var import_react_dom3 = require("react-dom");
2035
- var import_lucide_react5 = require("lucide-react");
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, import_react29.useState)(false);
2090
- (0, import_react29.useEffect)(() => {
2255
+ const [mounted, setMounted] = (0, import_react31.useState)(false);
2256
+ (0, import_react31.useEffect)(() => {
2091
2257
  setMounted(true);
2092
2258
  }, []);
2093
- (0, import_react29.useEffect)(() => {
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, import_react29.useEffect)(() => {
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__ */ import_react29.default.createElement(
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__ */ import_react29.default.createElement(
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__ */ import_react29.default.createElement(
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__ */ import_react29.default.createElement("div", { className: "flex items-center justify-between px-4 py-3 border-b border-ash" }, title ? /* @__PURE__ */ import_react29.default.createElement("h2", { className: "text-lg font-semibold text-white m-0" }, title) : /* @__PURE__ */ import_react29.default.createElement("div", null), /* @__PURE__ */ import_react29.default.createElement(
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__ */ import_react29.default.createElement(import_lucide_react5.X, { className: "h-5 w-5" }),
2159
- /* @__PURE__ */ import_react29.default.createElement("span", { className: "sr-only" }, "Close")
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__ */ import_react29.default.createElement("div", { className: "flex-1 overflow-auto p-4" }, children)
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 import_react30 = __toESM(require("react"));
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, import_react30.useState)(false);
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, import_react30.useRef)(null);
2205
- const baseId = (0, import_react30.useId)();
2206
- const setIsOpen = (0, import_react30.useCallback)(
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, import_react30.useEffect)(() => {
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, import_react30.useEffect)(() => {
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 = import_react30.default.cloneElement(trigger, {
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__ */ import_react30.default.createElement("div", { ref: containerRef, className: "relative inline-block" }, triggerElement, isOpen && /* @__PURE__ */ import_react30.default.createElement(
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 import_react31 = __toESM(require("react"));
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, import_react31.useCallback)(() => {
2443
+ const handleCancel = (0, import_react33.useCallback)(() => {
2278
2444
  onCancel?.();
2279
2445
  onClose();
2280
2446
  }, [onCancel, onClose]);
2281
- const handleConfirm = (0, import_react31.useCallback)(async () => {
2447
+ const handleConfirm = (0, import_react33.useCallback)(async () => {
2282
2448
  await onConfirm();
2283
2449
  onClose();
2284
2450
  }, [onConfirm, onClose]);
2285
- return /* @__PURE__ */ import_react31.default.createElement(Modal, { title, onClose, ...props }, description && /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-sm text-silver mb-6" }, description), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex justify-end gap-3" }, /* @__PURE__ */ import_react31.default.createElement(Button, { variant: "outlined", onClick: handleCancel, disabled: isLoading }, cancelText), /* @__PURE__ */ import_react31.default.createElement(
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__ */ import_react31.default.createElement(Modal, { onClose, ...props }, /* @__PURE__ */ import_react31.default.createElement("h3", { className: cx("text-xl font-semibold mb-2", titleClass) }, title), description && /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-sm text-silver mb-6" }, description), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex justify-end" }, /* @__PURE__ */ import_react31.default.createElement(Button, { variant: "primary", onClick: onClose }, acknowledgeText)));
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] = import_react31.default.useState(defaultValue);
2325
- const handleCancel = (0, import_react31.useCallback)(() => {
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, import_react31.useCallback)(
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__ */ import_react31.default.createElement(Modal, { title, onClose, ...props }, /* @__PURE__ */ import_react31.default.createElement("form", { onSubmit: handleSubmit }, description && /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-sm text-silver mb-4" }, description), /* @__PURE__ */ import_react31.default.createElement(
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__ */ import_react31.default.createElement("div", { className: "flex justify-end gap-3" }, /* @__PURE__ */ import_react31.default.createElement(
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__ */ import_react31.default.createElement(Button, { type: "submit", variant: "important", loading: isLoading }, submitText))));
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 import_react32 = __toESM(require("react"));
2367
- var TabsContext = (0, import_react32.createContext)(null);
2532
+ var import_react34 = __toESM(require("react"));
2533
+ var TabsContext = (0, import_react34.createContext)(null);
2368
2534
  function useTabsContext() {
2369
- const context = (0, import_react32.useContext)(TabsContext);
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 = import_react32.default.forwardRef(
2541
+ var Tabs = import_react34.default.forwardRef(
2376
2542
  ({ defaultValue, value, onValueChange, children, className, ...props }, ref) => {
2377
- const [internalValue, setInternalValue] = (0, import_react32.useState)(defaultValue ?? "");
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, import_react32.useId)();
2381
- const setActiveTab = (0, import_react32.useCallback)(
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__ */ import_react32.default.createElement(TabsContext.Provider, { value: { activeTab, setActiveTab, baseId } }, /* @__PURE__ */ import_react32.default.createElement("div", { ref, className: cx("w-full", className), ...props }, children));
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 = import_react32.default.forwardRef(
2560
+ var TabList = import_react34.default.forwardRef(
2395
2561
  ({ children, className, ...props }, ref) => {
2396
- return /* @__PURE__ */ import_react32.default.createElement(
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 = import_react32.default.forwardRef(
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__ */ import_react32.default.createElement(
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 = import_react32.default.forwardRef(
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__ */ import_react32.default.createElement(
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 import_react33 = __toESM(require("react"));
2478
- var import_lucide_react6 = require("lucide-react");
2479
- var AccordionContext = (0, import_react33.createContext)(null);
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, import_react33.useContext)(AccordionContext);
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 = import_react33.default.forwardRef(
2653
+ var Accordion = import_react35.default.forwardRef(
2488
2654
  ({ type = "single", defaultValue, value, onValueChange, children, className, ...props }, ref) => {
2489
- const [internalValue, setInternalValue] = (0, import_react33.useState)(() => {
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, import_react33.useCallback)(
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__ */ import_react33.default.createElement(AccordionContext.Provider, { value: { expandedItems, toggleItem, type } }, /* @__PURE__ */ import_react33.default.createElement(
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, import_react33.createContext)(null);
2529
- var AccordionItem = import_react33.default.forwardRef(
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__ */ import_react33.default.createElement(AccordionItemContext.Provider, { value: { value, disabled } }, /* @__PURE__ */ import_react33.default.createElement(
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 = import_react33.default.forwardRef(
2710
+ var AccordionTrigger = import_react35.default.forwardRef(
2545
2711
  ({ children, className, ...props }, ref) => {
2546
2712
  const { expandedItems, toggleItem } = useAccordionContext();
2547
- const itemContext = (0, import_react33.useContext)(AccordionItemContext);
2548
- const baseId = (0, import_react33.useId)();
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__ */ import_react33.default.createElement("h3", { className: "m-0" }, /* @__PURE__ */ import_react33.default.createElement(
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__ */ import_react33.default.createElement("span", null, children),
2576
- /* @__PURE__ */ import_react33.default.createElement(
2577
- import_lucide_react6.ChevronDown,
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 = import_react33.default.forwardRef(
2755
+ var AccordionContent = import_react35.default.forwardRef(
2590
2756
  ({ children, className, ...props }, ref) => {
2591
2757
  const { expandedItems } = useAccordionContext();
2592
- const itemContext = (0, import_react33.useContext)(AccordionItemContext);
2593
- const baseId = (0, import_react33.useId)();
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__ */ import_react33.default.createElement(
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__ */ import_react33.default.createElement("div", { className: "px-4 pb-4 text-sm text-silver" }, children)
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 import_react34 = __toESM(require("react"));
2622
- var MenuContext = (0, import_react34.createContext)(null);
2787
+ var import_react36 = __toESM(require("react"));
2788
+ var MenuContext = (0, import_react36.createContext)(null);
2623
2789
  function useMenuContext() {
2624
- const context = (0, import_react34.useContext)(MenuContext);
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, import_react34.useState)(false);
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, import_react34.useId)();
2635
- const setIsOpen = (0, import_react34.useCallback)(
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__ */ import_react34.default.createElement(
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__ */ import_react34.default.createElement("div", { className: "relative inline-block" }, children)
2820
+ /* @__PURE__ */ import_react36.default.createElement("div", { className: "relative inline-block" }, children)
2655
2821
  );
2656
2822
  };
2657
2823
  Menu.displayName = "Menu";
2658
- var MenuTrigger = import_react34.default.forwardRef(
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__ */ import_react34.default.createElement(
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 = import_react34.default.forwardRef(
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, import_react34.useRef)(null);
2691
- (0, import_react34.useEffect)(() => {
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__ */ import_react34.default.createElement(
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 = import_react34.default.forwardRef(
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__ */ import_react34.default.createElement(
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__ */ import_react34.default.createElement("span", { className: "w-4 h-4 shrink-0" }, icon),
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 = import_react34.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ import_react34.default.createElement(
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 = import_react34.default.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ import_react34.default.createElement(
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 import_react35 = __toESM(require("react"));
2802
- var Navbar = import_react35.default.forwardRef(
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__ */ import_react35.default.createElement(
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__ */ import_react35.default.createElement("div", { className: "flex items-center justify-between" }, children)
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 = import_react35.default.forwardRef(
2987
+ var NavbarBrand = import_react37.default.forwardRef(
2822
2988
  ({ className, children, ...props }, ref) => {
2823
- return /* @__PURE__ */ import_react35.default.createElement(
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 = import_react35.default.forwardRef(
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__ */ import_react35.default.createElement(
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 = import_react35.default.forwardRef(
3024
+ var NavbarItem = import_react37.default.forwardRef(
2859
3025
  ({ active = false, className, children, ...props }, ref) => {
2860
- return /* @__PURE__ */ import_react35.default.createElement(
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 = import_react35.default.forwardRef(
3041
+ var NavbarLink = import_react37.default.forwardRef(
2876
3042
  ({ active = false, className, children, ...props }, ref) => {
2877
- return /* @__PURE__ */ import_react35.default.createElement(
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 = import_react35.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ import_react35.default.createElement(
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 import_react36 = __toESM(require("react"));
2905
- var import_lucide_react7 = require("lucide-react");
2906
- var Breadcrumb = import_react36.default.forwardRef(
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 = import_react36.default.Children.toArray(children);
2909
- const defaultSeparator = /* @__PURE__ */ import_react36.default.createElement(import_lucide_react7.ChevronRight, { className: "h-4 w-4 text-ash" });
2910
- return /* @__PURE__ */ import_react36.default.createElement("nav", { ref, "aria-label": "Breadcrumb", className, ...props }, /* @__PURE__ */ import_react36.default.createElement("ol", { className: "flex items-center gap-2" }, items.map((child, index) => /* @__PURE__ */ import_react36.default.createElement("li", { key: index, className: "flex items-center gap-2" }, child, index < items.length - 1 && /* @__PURE__ */ import_react36.default.createElement("span", { "aria-hidden": "true" }, separator ?? defaultSeparator)))));
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 = import_react36.default.forwardRef(
3080
+ var BreadcrumbItem = import_react38.default.forwardRef(
2915
3081
  ({ current = false, className, children, ...props }, ref) => {
2916
- return /* @__PURE__ */ import_react36.default.createElement(
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 = import_react36.default.forwardRef(
3099
+ var BreadcrumbLink = import_react38.default.forwardRef(
2934
3100
  ({ className, children, ...props }, ref) => {
2935
- return /* @__PURE__ */ import_react36.default.createElement(
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 import_react37 = __toESM(require("react"));
2953
- var import_lucide_react8 = require("lucide-react");
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 = import_react37.default.forwardRef(
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__ */ import_react37.default.createElement(
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__ */ import_react37.default.createElement(
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__ */ import_react37.default.createElement(import_lucide_react8.ChevronLeft, { className: "h-4 w-4" })
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__ */ import_react37.default.createElement(
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__ */ import_react37.default.createElement(import_lucide_react8.MoreHorizontal, { className: "h-4 w-4" })
3026
- ) : /* @__PURE__ */ import_react37.default.createElement(
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__ */ import_react37.default.createElement(
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__ */ import_react37.default.createElement(import_lucide_react8.ChevronRight, { className: "h-4 w-4" })
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 import_react38 = __toESM(require("react"));
3064
- var import_lucide_react9 = require("lucide-react");
3065
- var Stepper = import_react38.default.forwardRef(
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__ */ import_react38.default.createElement(
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__ */ import_react38.default.createElement(import_react38.default.Fragment, { key: step.id }, /* @__PURE__ */ import_react38.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react38.default.createElement(
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__ */ import_react38.default.createElement(import_lucide_react9.Check, { className: "h-5 w-5" }) : /* @__PURE__ */ import_react38.default.createElement("span", null, index + 1)
3099
- ), /* @__PURE__ */ import_react38.default.createElement(
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__ */ import_react38.default.createElement(
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 import_react41 = __toESM(require("react"));
3293
+ var import_react42 = __toESM(require("react"));
3128
3294
 
3129
3295
  // src/components/MarkdownContent.tsx
3130
- var import_react39 = __toESM(require("react"));
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, import_react39.useMemo)(() => {
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 MarkdownContent = import_react39.default.forwardRef(
3210
- ({ className, content, sanitizeConfig, ...rest }, ref) => {
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, import_react39.useMemo)(() => {
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
- return import_dompurify.default.sanitize(content, config);
3218
- }, [content, sanitizeConfig]);
3219
- return /* @__PURE__ */ import_react39.default.createElement(
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 import_react40 = __toESM(require("react"));
3234
- var StreamingCursor = import_react40.default.forwardRef(
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__ */ import_react40.default.createElement(
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/Message.tsx
3259
- var variantStyles2 = {
3260
- user: "bg-gold text-obsidian ml-auto",
3261
- assistant: "bg-charcoal border border-ash text-white mr-auto"
3262
- };
3263
- var Message = import_react41.default.forwardRef(
3264
- ({ variant = "assistant", className, content, isStreaming, ...rest }, ref) => {
3265
- const isUser = variant === "user";
3266
- return /* @__PURE__ */ import_react41.default.createElement(
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
- variantStyles2[variant],
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__ */ import_react41.default.createElement(
3278
- MarkdownContent,
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
- content,
3281
- className: cx("prose-sm", isUser ? "prose-inherit" : "prose-invert")
3282
- }
3283
- ),
3284
- isStreaming && /* @__PURE__ */ import_react41.default.createElement(StreamingCursor, { className: "ml-0.5" })
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
- Message.displayName = "Message";
3814
+ ThinkingIndicator.displayName = "ThinkingIndicator";
3289
3815
 
3290
- // src/components/ChatHistory.tsx
3291
- var import_react42 = __toESM(require("react"));
3292
- var ChatHistory = ({ messages, className, ...rest }) => {
3293
- const innerRef = (0, import_react42.useRef)(null);
3294
- (0, import_react42.useEffect)(() => {
3295
- const el = innerRef.current;
3296
- if (!el) {
3297
- return;
3298
- }
3299
- if (typeof el.scrollTo === "function") {
3300
- el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
3301
- } else {
3302
- el.scrollTop = el.scrollHeight;
3303
- }
3304
- }, [messages]);
3305
- return /* @__PURE__ */ import_react42.default.createElement(
3306
- "div",
3307
- {
3308
- ref: innerRef,
3309
- className: cx(
3310
- "flex flex-col gap-3 justify-end w-full h-96 bg-charcoal/50 border border-ash/40 p-4 overflow-y-auto",
3311
- className
3312
- ),
3313
- ...rest
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
- key: id ?? index,
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
- ChatHistory.displayName = "ChatHistory";
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/BrandIcon.tsx
3329
- var import_react43 = __toESM(require("react"));
3330
- var sizeMap2 = {
3331
- sm: "h-8 w-8 text-sm",
3332
- md: "h-12 w-12 text-base",
3333
- lg: "h-16 w-16 text-lg"
3334
- };
3335
- var BrandIcon = import_react43.default.forwardRef(
3336
- ({ size = "md", variant = "solid", children, className, ...rest }, ref) => {
3337
- const variantClasses = variant === "solid" ? "bg-gold text-obsidian border-2 border-gold" : "bg-transparent text-gold border-2 border-gold";
3338
- return /* @__PURE__ */ import_react43.default.createElement(
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
- "inline-flex items-center justify-center rounded-none font-bold select-none overflow-hidden",
3344
- sizeMap2[size],
3345
- variantClasses,
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
- children
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
- BrandIcon.displayName = "BrandIcon";
4313
+ ChatInput.displayName = "ChatInput";
3355
4314
 
3356
- // src/components/ColorSwatch.tsx
3357
- var import_react44 = __toESM(require("react"));
3358
- var ColorSwatch = import_react44.default.forwardRef(
3359
- ({ color, label, className, ...rest }, ref) => {
3360
- return /* @__PURE__ */ import_react44.default.createElement(
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("flex flex-col items-center gap-2", className),
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__ */ import_react44.default.createElement(
3368
- "div",
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
- className: "h-16 w-16 border-2 border-ash rounded-none shadow-sm",
3371
- style: { backgroundColor: color },
3372
- "aria-label": label || color
3373
- }
3374
- ),
3375
- label && /* @__PURE__ */ import_react44.default.createElement("span", { className: "text-xs text-silver font-medium" }, label)
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
- ColorSwatch.displayName = "ColorSwatch";
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 import_react45 = __toESM(require("react"));
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 = import_react45.default.forwardRef(
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__ */ import_react45.default.createElement(Card, { ref, className: cx("p-0 overflow-hidden group w-fit", className), ...props }, /* @__PURE__ */ import_react45.default.createElement(
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__ */ import_react45.default.createElement(
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__ */ import_react45.default.createElement(
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__ */ import_react45.default.createElement("div", { className: cx("px-4 py-4", contentClassName) }, title && /* @__PURE__ */ import_react45.default.createElement("h4", { className: "text-lg font-semibold leading-tight" }, title), subtitle && /* @__PURE__ */ import_react45.default.createElement("p", { className: "text-sm text-silver leading-normal" }, subtitle), children));
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 import_react46 = __toESM(require("react"));
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 = import_react46.default.forwardRef(
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__ */ import_react46.default.createElement(Card, { ref, className: cx("p-0 overflow-hidden group w-full", className), ...props }, /* @__PURE__ */ import_react46.default.createElement(
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-black overflow-hidden",
4585
+ "relative bg-obsidian overflow-hidden",
3485
4586
  mediaClassName
3486
4587
  ),
3487
4588
  style: { aspectRatio: resolveAspectRatio2(aspectRatio) }
3488
4589
  },
3489
- /* @__PURE__ */ import_react46.default.createElement(
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__ */ import_react46.default.createElement("div", { className: cx("px-4 py-4", contentClassName) }, title && /* @__PURE__ */ import_react46.default.createElement("h4", { className: "text-lg font-semibold leading-tight" }, title), subtitle && /* @__PURE__ */ import_react46.default.createElement(
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 import_react47 = __toESM(require("react"));
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 = import_react47.default.forwardRef(
5378
+ var SectionHeading = import_react59.default.forwardRef(
3523
5379
  ({ level = "h2", children, className, ...rest }, ref) => {
3524
5380
  const Component = level;
3525
- return /* @__PURE__ */ import_react47.default.createElement(
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
- ChatHistory,
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
  });