@nextclaw/agent-chat-ui 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +238 -66
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -341,6 +341,12 @@ const ChatButton = React.forwardRef(({ className, variant, size, ...props }, ref
|
|
|
341
341
|
ChatButton.displayName = "ChatButton";
|
|
342
342
|
//#endregion
|
|
343
343
|
//#region src/components/chat/ui/chat-input-bar/chat-input-bar-actions.tsx
|
|
344
|
+
const SEND_ERROR_PREVIEW_MAX_CHARS = 120;
|
|
345
|
+
function buildSendErrorPreview(value) {
|
|
346
|
+
const compact = value.replace(/\s+/g, " ").trim();
|
|
347
|
+
if (compact.length <= SEND_ERROR_PREVIEW_MAX_CHARS) return compact;
|
|
348
|
+
return `${compact.slice(0, SEND_ERROR_PREVIEW_MAX_CHARS - 1)}…`;
|
|
349
|
+
}
|
|
344
350
|
function StopIcon() {
|
|
345
351
|
return /* @__PURE__ */ jsx("span", {
|
|
346
352
|
"aria-hidden": "true",
|
|
@@ -348,22 +354,49 @@ function StopIcon() {
|
|
|
348
354
|
className: "block h-3 w-3 rounded-[2px] bg-gray-700 shadow-[inset_0_0_0_1px_rgba(17,24,39,0.06)]"
|
|
349
355
|
});
|
|
350
356
|
}
|
|
351
|
-
function ChatInputBarActions(
|
|
352
|
-
const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;
|
|
357
|
+
function ChatInputBarActions({ sendError, sendErrorDetailsLabel, isSending, canStopGeneration, sendDisabled, stopDisabled, stopHint, sendButtonLabel, stopButtonLabel, onSend, onStop }) {
|
|
358
|
+
const { Popover, PopoverContent, PopoverTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;
|
|
359
|
+
const normalizedSendError = sendError?.trim() ?? "";
|
|
360
|
+
const sendErrorPreview = normalizedSendError ? buildSendErrorPreview(normalizedSendError) : "";
|
|
361
|
+
const resolvedSendErrorDetailsLabel = sendErrorDetailsLabel?.trim() || "Details";
|
|
353
362
|
return /* @__PURE__ */ jsxs("div", {
|
|
354
363
|
className: "flex flex-col items-end gap-1",
|
|
355
|
-
children: [
|
|
356
|
-
className: "max-w-[420px]
|
|
357
|
-
children:
|
|
364
|
+
children: [normalizedSendError ? /* @__PURE__ */ jsxs("div", {
|
|
365
|
+
className: "flex max-w-[420px] items-start justify-end gap-2 text-right",
|
|
366
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
367
|
+
className: "min-w-0 flex-1 text-[11px] text-red-600",
|
|
368
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
369
|
+
className: "block truncate",
|
|
370
|
+
title: normalizedSendError,
|
|
371
|
+
children: sendErrorPreview
|
|
372
|
+
})
|
|
373
|
+
}), /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
374
|
+
asChild: true,
|
|
375
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
376
|
+
type: "button",
|
|
377
|
+
className: "shrink-0 rounded-full border border-red-200/80 bg-red-50 px-2 py-0.5 text-[10px] font-semibold text-red-700 transition-colors hover:bg-red-100",
|
|
378
|
+
children: resolvedSendErrorDetailsLabel
|
|
379
|
+
})
|
|
380
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
381
|
+
align: "end",
|
|
382
|
+
className: "w-[min(32rem,calc(100vw-1.5rem))] border-red-100/80 p-0",
|
|
383
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
384
|
+
className: "border-b border-red-100 bg-red-50/80 px-4 py-2 text-xs font-semibold text-red-700",
|
|
385
|
+
children: resolvedSendErrorDetailsLabel
|
|
386
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
387
|
+
className: "max-h-80 overflow-auto whitespace-pre-wrap break-words px-4 py-3 text-xs leading-relaxed text-red-700",
|
|
388
|
+
children: normalizedSendError
|
|
389
|
+
})]
|
|
390
|
+
})] })]
|
|
358
391
|
}) : null, /* @__PURE__ */ jsx("div", {
|
|
359
392
|
className: "flex items-center gap-2",
|
|
360
|
-
children:
|
|
393
|
+
children: isSending ? canStopGeneration ? /* @__PURE__ */ jsx(ChatButton, {
|
|
361
394
|
size: "icon",
|
|
362
395
|
variant: "outline",
|
|
363
396
|
className: "h-8 w-8 rounded-full",
|
|
364
|
-
"aria-label":
|
|
365
|
-
onClick: () => void
|
|
366
|
-
disabled:
|
|
397
|
+
"aria-label": stopButtonLabel,
|
|
398
|
+
onClick: () => void onStop(),
|
|
399
|
+
disabled: stopDisabled,
|
|
367
400
|
children: /* @__PURE__ */ jsx(StopIcon, {})
|
|
368
401
|
}) : /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
369
402
|
asChild: true,
|
|
@@ -371,7 +404,7 @@ function ChatInputBarActions(props) {
|
|
|
371
404
|
size: "icon",
|
|
372
405
|
variant: "outline",
|
|
373
406
|
className: "h-8 w-8 rounded-full",
|
|
374
|
-
"aria-label":
|
|
407
|
+
"aria-label": stopButtonLabel,
|
|
375
408
|
disabled: true,
|
|
376
409
|
children: /* @__PURE__ */ jsx(StopIcon, {})
|
|
377
410
|
}) })
|
|
@@ -379,14 +412,14 @@ function ChatInputBarActions(props) {
|
|
|
379
412
|
side: "top",
|
|
380
413
|
children: /* @__PURE__ */ jsx("p", {
|
|
381
414
|
className: "text-xs",
|
|
382
|
-
children:
|
|
415
|
+
children: stopHint
|
|
383
416
|
})
|
|
384
417
|
})] }) }) : /* @__PURE__ */ jsx(ChatButton, {
|
|
385
418
|
size: "icon",
|
|
386
419
|
className: "h-8 w-8 rounded-full",
|
|
387
|
-
"aria-label":
|
|
388
|
-
onClick: () => void
|
|
389
|
-
disabled:
|
|
420
|
+
"aria-label": sendButtonLabel,
|
|
421
|
+
onClick: () => void onSend(),
|
|
422
|
+
disabled: sendDisabled,
|
|
390
423
|
children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-5 w-5" })
|
|
391
424
|
})
|
|
392
425
|
})]
|
|
@@ -2270,6 +2303,25 @@ const IMAGE_EXTENSIONS = new Set([
|
|
|
2270
2303
|
"tiff",
|
|
2271
2304
|
"webp"
|
|
2272
2305
|
]);
|
|
2306
|
+
const AUDIO_EXTENSIONS = new Set([
|
|
2307
|
+
"aac",
|
|
2308
|
+
"flac",
|
|
2309
|
+
"m4a",
|
|
2310
|
+
"mp3",
|
|
2311
|
+
"ogg",
|
|
2312
|
+
"opus",
|
|
2313
|
+
"wav",
|
|
2314
|
+
"weba"
|
|
2315
|
+
]);
|
|
2316
|
+
const VIDEO_EXTENSIONS = new Set([
|
|
2317
|
+
"avi",
|
|
2318
|
+
"m4v",
|
|
2319
|
+
"mov",
|
|
2320
|
+
"mp4",
|
|
2321
|
+
"mkv",
|
|
2322
|
+
"webm",
|
|
2323
|
+
"wmv"
|
|
2324
|
+
]);
|
|
2273
2325
|
const DOCUMENT_EXTENSIONS = new Set([
|
|
2274
2326
|
"doc",
|
|
2275
2327
|
"docx",
|
|
@@ -2327,6 +2379,36 @@ function readFileExtension(label) {
|
|
|
2327
2379
|
function isImageDataUrl(dataUrl) {
|
|
2328
2380
|
return typeof dataUrl === "string" && /^data:image\//i.test(dataUrl.trim());
|
|
2329
2381
|
}
|
|
2382
|
+
function inferMimeTypeFromExtension(extension) {
|
|
2383
|
+
if (IMAGE_EXTENSIONS.has(extension)) {
|
|
2384
|
+
if (extension === "jpg" || extension === "jpeg") return "image/jpeg";
|
|
2385
|
+
if (extension === "svg") return "image/svg+xml";
|
|
2386
|
+
return `image/${extension}`;
|
|
2387
|
+
}
|
|
2388
|
+
if (AUDIO_EXTENSIONS.has(extension)) {
|
|
2389
|
+
if (extension === "mp3") return "audio/mpeg";
|
|
2390
|
+
if (extension === "m4a") return "audio/mp4";
|
|
2391
|
+
if (extension === "weba") return "audio/webm";
|
|
2392
|
+
return `audio/${extension}`;
|
|
2393
|
+
}
|
|
2394
|
+
if (VIDEO_EXTENSIONS.has(extension)) {
|
|
2395
|
+
if (extension === "mov") return "video/quicktime";
|
|
2396
|
+
if (extension === "m4v") return "video/mp4";
|
|
2397
|
+
return `video/${extension}`;
|
|
2398
|
+
}
|
|
2399
|
+
if (extension === "pdf") return "application/pdf";
|
|
2400
|
+
return null;
|
|
2401
|
+
}
|
|
2402
|
+
function inferMimeTypeFromFileName(fileName) {
|
|
2403
|
+
const extension = readFileExtension(fileName);
|
|
2404
|
+
if (!extension) return null;
|
|
2405
|
+
return inferMimeTypeFromExtension(extension);
|
|
2406
|
+
}
|
|
2407
|
+
function resolveRenderableMimeType(file) {
|
|
2408
|
+
const normalizedMimeType = file.mimeType.trim().toLowerCase();
|
|
2409
|
+
if (normalizedMimeType.length > 0 && normalizedMimeType !== "application/octet-stream") return normalizedMimeType;
|
|
2410
|
+
return inferMimeTypeFromFileName(file.label);
|
|
2411
|
+
}
|
|
2330
2412
|
function isImageFileLike(file) {
|
|
2331
2413
|
const normalizedMimeType = file.mimeType.trim().toLowerCase();
|
|
2332
2414
|
const extension = readFileExtension(file.label);
|
|
@@ -2336,8 +2418,8 @@ function resolveFileCategory(label, mimeType) {
|
|
|
2336
2418
|
const extension = readFileExtension(label);
|
|
2337
2419
|
const normalizedMimeType = mimeType.toLowerCase();
|
|
2338
2420
|
if (normalizedMimeType.startsWith("image/") || IMAGE_EXTENSIONS.has(extension)) return "image";
|
|
2339
|
-
if (normalizedMimeType.startsWith("audio/")) return "audio";
|
|
2340
|
-
if (normalizedMimeType.startsWith("video/")) return "video";
|
|
2421
|
+
if (normalizedMimeType.startsWith("audio/") || AUDIO_EXTENSIONS.has(extension)) return "audio";
|
|
2422
|
+
if (normalizedMimeType.startsWith("video/") || VIDEO_EXTENSIONS.has(extension)) return "video";
|
|
2341
2423
|
if (normalizedMimeType.includes("pdf") || extension === "pdf") return "pdf";
|
|
2342
2424
|
if (ARCHIVE_EXTENSIONS.has(extension) || /(zip|tar|gzip|rar|compressed|archive)/.test(normalizedMimeType)) return "archive";
|
|
2343
2425
|
if (SHEET_EXTENSIONS.has(extension) || /(spreadsheet|sheet|excel|csv)/.test(normalizedMimeType)) return "sheet";
|
|
@@ -2369,6 +2451,18 @@ const DEFAULT_FILE_CATEGORY_LABELS = {
|
|
|
2369
2451
|
sheet: "Spreadsheet",
|
|
2370
2452
|
video: "Video"
|
|
2371
2453
|
};
|
|
2454
|
+
const FILE_CATEGORY_ICONS = {
|
|
2455
|
+
archive: FileArchive,
|
|
2456
|
+
audio: FileAudio2,
|
|
2457
|
+
code: FileCode2,
|
|
2458
|
+
data: FileJson2,
|
|
2459
|
+
document: FileText,
|
|
2460
|
+
generic: File,
|
|
2461
|
+
image: FileImage,
|
|
2462
|
+
pdf: FileText,
|
|
2463
|
+
sheet: FileSpreadsheet,
|
|
2464
|
+
video: FileVideo2
|
|
2465
|
+
};
|
|
2372
2466
|
function readFileCategoryLabel(category, texts) {
|
|
2373
2467
|
return texts?.attachmentCategoryLabels?.[category] ?? DEFAULT_FILE_CATEGORY_LABELS[category];
|
|
2374
2468
|
}
|
|
@@ -2384,20 +2478,17 @@ function renderActionPill(label, isUser, isInteractive) {
|
|
|
2384
2478
|
children: label
|
|
2385
2479
|
});
|
|
2386
2480
|
}
|
|
2387
|
-
function
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
if (category === "video") return FileVideo2;
|
|
2396
|
-
if (category === "document") return FileText;
|
|
2397
|
-
return File;
|
|
2481
|
+
function renderActionLink(label, href, isUser) {
|
|
2482
|
+
return /* @__PURE__ */ jsx("a", {
|
|
2483
|
+
href,
|
|
2484
|
+
target: "_blank",
|
|
2485
|
+
rel: "noreferrer",
|
|
2486
|
+
className: cn("inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium transition duration-200", isUser ? "border-white/14 bg-white/12 text-white hover:border-white/20 hover:bg-white/16" : "border-slate-200/80 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50"),
|
|
2487
|
+
children: label
|
|
2488
|
+
});
|
|
2398
2489
|
}
|
|
2399
2490
|
function FileCategoryGlyph({ category, isUser }) {
|
|
2400
|
-
const Icon =
|
|
2491
|
+
const Icon = FILE_CATEGORY_ICONS[category];
|
|
2401
2492
|
return /* @__PURE__ */ jsx("div", {
|
|
2402
2493
|
className: cn("flex h-14 w-14 shrink-0 items-center justify-center rounded-[1rem] border", isUser ? "border-white/12 bg-white/10 text-white" : FILE_CATEGORY_TILE_CLASSES[category]),
|
|
2403
2494
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
@@ -2406,14 +2497,10 @@ function FileCategoryGlyph({ category, isUser }) {
|
|
|
2406
2497
|
})
|
|
2407
2498
|
});
|
|
2408
2499
|
}
|
|
2409
|
-
function
|
|
2410
|
-
const {
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
const actionLabel = isInteractive ? texts?.attachmentOpenLabel ?? "Open" : texts?.attachmentAttachedLabel ?? "Attached";
|
|
2414
|
-
const categoryLabel = readFileCategoryLabel(category, texts);
|
|
2415
|
-
const shellClasses = cn("block overflow-hidden rounded-[1.25rem] border transition duration-200", isUser ? "border-white/12 bg-white/10 text-white" : "border-slate-200/80 bg-white/95 text-slate-900", isInteractive && (isUser ? "hover:border-white/18 hover:bg-white/13" : "hover:border-slate-300 hover:bg-white"));
|
|
2416
|
-
if (renderAsImage && file.dataUrl) return /* @__PURE__ */ jsx("a", {
|
|
2500
|
+
function renderImagePreview(params) {
|
|
2501
|
+
const { file, categoryLabel, sizeLabel, isUser } = params;
|
|
2502
|
+
if (!file.dataUrl) return null;
|
|
2503
|
+
return /* @__PURE__ */ jsx("a", {
|
|
2417
2504
|
href: file.dataUrl,
|
|
2418
2505
|
target: "_blank",
|
|
2419
2506
|
rel: "noreferrer",
|
|
@@ -2436,7 +2523,10 @@ function ChatMessageFile({ file, isUser = false, texts }) {
|
|
|
2436
2523
|
})]
|
|
2437
2524
|
})
|
|
2438
2525
|
});
|
|
2439
|
-
|
|
2526
|
+
}
|
|
2527
|
+
function renderFileCardHeader(params) {
|
|
2528
|
+
const { category, file, categoryLabel, sizeLabel, isUser, action } = params;
|
|
2529
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2440
2530
|
className: "flex items-center gap-3 p-3.5",
|
|
2441
2531
|
children: [/* @__PURE__ */ jsx(FileCategoryGlyph, {
|
|
2442
2532
|
category,
|
|
@@ -2451,11 +2541,85 @@ function ChatMessageFile({ file, isUser = false, texts }) {
|
|
|
2451
2541
|
className: "truncate text-[15px] font-semibold leading-5",
|
|
2452
2542
|
children: file.label
|
|
2453
2543
|
}), renderMetaLine(categoryLabel, sizeLabel, isUser)]
|
|
2454
|
-
}),
|
|
2544
|
+
}), action]
|
|
2455
2545
|
})
|
|
2456
2546
|
})]
|
|
2457
2547
|
});
|
|
2458
|
-
|
|
2548
|
+
}
|
|
2549
|
+
function renderInlineMediaCard(params) {
|
|
2550
|
+
const { category, file, categoryLabel, sizeLabel, isUser, shellClasses, actionLabel } = params;
|
|
2551
|
+
if (!file.dataUrl || category !== "audio" && category !== "video") return null;
|
|
2552
|
+
const mediaMimeType = resolveRenderableMimeType(file);
|
|
2553
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2554
|
+
className: shellClasses,
|
|
2555
|
+
children: [renderFileCardHeader({
|
|
2556
|
+
category,
|
|
2557
|
+
file,
|
|
2558
|
+
categoryLabel,
|
|
2559
|
+
sizeLabel,
|
|
2560
|
+
isUser,
|
|
2561
|
+
action: renderActionLink(actionLabel, file.dataUrl, isUser)
|
|
2562
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2563
|
+
className: "px-3.5 pb-3.5",
|
|
2564
|
+
children: category === "audio" ? /* @__PURE__ */ jsx("audio", {
|
|
2565
|
+
controls: true,
|
|
2566
|
+
preload: "metadata",
|
|
2567
|
+
"aria-label": file.label,
|
|
2568
|
+
className: "block w-full",
|
|
2569
|
+
children: /* @__PURE__ */ jsx("source", {
|
|
2570
|
+
src: file.dataUrl,
|
|
2571
|
+
...mediaMimeType ? { type: mediaMimeType } : {}
|
|
2572
|
+
})
|
|
2573
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
2574
|
+
className: cn("overflow-hidden rounded-[1rem] border", isUser ? "border-white/10 bg-slate-950/26" : "border-slate-200/80 bg-slate-100/80"),
|
|
2575
|
+
children: /* @__PURE__ */ jsx("video", {
|
|
2576
|
+
controls: true,
|
|
2577
|
+
preload: "metadata",
|
|
2578
|
+
playsInline: true,
|
|
2579
|
+
"aria-label": file.label,
|
|
2580
|
+
className: "block max-h-[28rem] w-full bg-black",
|
|
2581
|
+
children: /* @__PURE__ */ jsx("source", {
|
|
2582
|
+
src: file.dataUrl,
|
|
2583
|
+
...mediaMimeType ? { type: mediaMimeType } : {}
|
|
2584
|
+
})
|
|
2585
|
+
})
|
|
2586
|
+
})
|
|
2587
|
+
})]
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2590
|
+
function ChatMessageFile({ file, isUser = false, texts }) {
|
|
2591
|
+
const { category, sizeLabel } = buildChatMessageFileMeta(file);
|
|
2592
|
+
const renderAsImage = isImageFileLike(file) && Boolean(file.dataUrl);
|
|
2593
|
+
const renderAsAudio = category === "audio" && Boolean(file.dataUrl);
|
|
2594
|
+
const renderAsVideo = category === "video" && Boolean(file.dataUrl);
|
|
2595
|
+
const isInteractive = Boolean(file.dataUrl);
|
|
2596
|
+
const actionLabel = isInteractive ? texts?.attachmentOpenLabel ?? "Open" : texts?.attachmentAttachedLabel ?? "Attached";
|
|
2597
|
+
const categoryLabel = readFileCategoryLabel(category, texts);
|
|
2598
|
+
const shellClasses = cn("block overflow-hidden rounded-[1.25rem] border transition duration-200", isUser ? "border-white/12 bg-white/10 text-white" : "border-slate-200/80 bg-white/95 text-slate-900", isInteractive && (isUser ? "hover:border-white/18 hover:bg-white/13" : "hover:border-slate-300 hover:bg-white"));
|
|
2599
|
+
if (renderAsImage) return renderImagePreview({
|
|
2600
|
+
file,
|
|
2601
|
+
categoryLabel,
|
|
2602
|
+
sizeLabel,
|
|
2603
|
+
isUser
|
|
2604
|
+
});
|
|
2605
|
+
if (renderAsAudio || renderAsVideo) return renderInlineMediaCard({
|
|
2606
|
+
category,
|
|
2607
|
+
file,
|
|
2608
|
+
categoryLabel,
|
|
2609
|
+
sizeLabel,
|
|
2610
|
+
isUser,
|
|
2611
|
+
shellClasses,
|
|
2612
|
+
actionLabel
|
|
2613
|
+
});
|
|
2614
|
+
const content = renderFileCardHeader({
|
|
2615
|
+
category,
|
|
2616
|
+
file,
|
|
2617
|
+
categoryLabel,
|
|
2618
|
+
sizeLabel,
|
|
2619
|
+
isUser,
|
|
2620
|
+
action: renderActionPill(actionLabel, isUser, isInteractive)
|
|
2621
|
+
});
|
|
2622
|
+
if (!isInteractive || !file.dataUrl) return /* @__PURE__ */ jsx("div", {
|
|
2459
2623
|
className: shellClasses,
|
|
2460
2624
|
children: content
|
|
2461
2625
|
});
|
|
@@ -2726,13 +2890,11 @@ function ToolCardHeaderSessionAction({ action, onAction }) {
|
|
|
2726
2890
|
//#endregion
|
|
2727
2891
|
//#region src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation-lines.tsx
|
|
2728
2892
|
const FILE_TEXT_CLASS_NAME = "font-mono text-[11px] leading-5";
|
|
2729
|
-
const FILE_ROW_CLASS_NAME = `h-5 ${FILE_TEXT_CLASS_NAME}`;
|
|
2893
|
+
const FILE_ROW_CLASS_NAME = `flex h-5 w-full ${FILE_TEXT_CLASS_NAME}`;
|
|
2730
2894
|
const FILE_LINE_NUMBER_CELL_CLASS_NAME = "flex h-5 items-center justify-center px-2.5 tabular-nums select-none";
|
|
2731
|
-
function formatLineNumber(value) {
|
|
2732
|
-
return typeof value === "number" ? String(value) : "";
|
|
2733
|
-
}
|
|
2734
2895
|
function readVisibleLineNumber(line) {
|
|
2735
|
-
|
|
2896
|
+
const value = line.newLineNumber ?? line.oldLineNumber;
|
|
2897
|
+
return typeof value === "number" ? String(value) : "";
|
|
2736
2898
|
}
|
|
2737
2899
|
function readLineKey(prefix, line, index) {
|
|
2738
2900
|
return `${prefix}-${index}-${line.oldLineNumber ?? "x"}-${line.newLineNumber ?? "x"}`;
|
|
@@ -2750,9 +2912,8 @@ function readLineNumberColumnWidth(block) {
|
|
|
2750
2912
|
}, 0);
|
|
2751
2913
|
return `${Math.max(6.5, Math.min(8, maxDigits + 3.5))}ch`;
|
|
2752
2914
|
}
|
|
2753
|
-
function
|
|
2754
|
-
|
|
2755
|
-
return { gridTemplateColumns: `${params.lineNumberColumnWidth} minmax(0, 1fr)` };
|
|
2915
|
+
function readCodeColumnWidth(block) {
|
|
2916
|
+
return `calc(${block.lines.reduce((currentMax, line) => Math.max(currentMax, Math.max(1, line.text.length)), 1)}ch + 1.25rem)`;
|
|
2756
2917
|
}
|
|
2757
2918
|
function getLineNumberTone(line) {
|
|
2758
2919
|
if (line.kind === "remove") return "border-r border-rose-200 bg-rose-50 text-rose-700";
|
|
@@ -2765,29 +2926,27 @@ function getCodeRowTone(line) {
|
|
|
2765
2926
|
return "bg-white text-amber-950/80";
|
|
2766
2927
|
}
|
|
2767
2928
|
function FileOperationLineNumberCell({ layout, line, lineNumberColumnWidth }) {
|
|
2768
|
-
const lineNumberCellClassName = layout === "compact" ? "sticky left-0 z-[1]" : "w-full shrink-0";
|
|
2769
2929
|
return /* @__PURE__ */ jsx("span", {
|
|
2770
2930
|
"data-file-line-number-cell": "true",
|
|
2771
|
-
style: layout === "compact" ? {
|
|
2772
|
-
|
|
2931
|
+
style: layout === "compact" ? {
|
|
2932
|
+
width: lineNumberColumnWidth,
|
|
2933
|
+
minWidth: lineNumberColumnWidth
|
|
2934
|
+
} : void 0,
|
|
2935
|
+
className: cn(FILE_LINE_NUMBER_CELL_CLASS_NAME, layout === "compact" ? "sticky left-0 z-[1]" : "w-full shrink-0", getLineNumberTone(line)),
|
|
2773
2936
|
children: readVisibleLineNumber(line)
|
|
2774
2937
|
});
|
|
2775
2938
|
}
|
|
2776
2939
|
function FileOperationCodeCell({ line }) {
|
|
2777
2940
|
return /* @__PURE__ */ jsx("span", {
|
|
2778
2941
|
"data-file-code-row": "true",
|
|
2779
|
-
className: cn("block min-w-
|
|
2942
|
+
className: cn("block min-w-0 flex-1 whitespace-pre px-2.5", getCodeRowTone(line)),
|
|
2780
2943
|
children: line.text || " "
|
|
2781
2944
|
});
|
|
2782
2945
|
}
|
|
2783
2946
|
function FileOperationLineRow({ line, showLineNumbers, lineNumberColumnWidth }) {
|
|
2784
2947
|
return /* @__PURE__ */ jsxs("div", {
|
|
2785
2948
|
"data-file-line-row": "true",
|
|
2786
|
-
className:
|
|
2787
|
-
style: buildRowTemplateColumns({
|
|
2788
|
-
showLineNumbers,
|
|
2789
|
-
lineNumberColumnWidth
|
|
2790
|
-
}),
|
|
2949
|
+
className: FILE_ROW_CLASS_NAME,
|
|
2791
2950
|
children: [showLineNumbers ? /* @__PURE__ */ jsx(FileOperationLineNumberCell, {
|
|
2792
2951
|
layout: "compact",
|
|
2793
2952
|
line,
|
|
@@ -2798,6 +2957,7 @@ function FileOperationLineRow({ line, showLineNumbers, lineNumberColumnWidth })
|
|
|
2798
2957
|
function FileOperationWorkspaceSurface({ block }) {
|
|
2799
2958
|
const showLineNumbers = readHasBlockLineNumbers(block);
|
|
2800
2959
|
const lineNumberColumnWidth = readLineNumberColumnWidth(block);
|
|
2960
|
+
const codeColumnWidth = readCodeColumnWidth(block);
|
|
2801
2961
|
return /* @__PURE__ */ jsxs("div", {
|
|
2802
2962
|
"data-file-code-surface": "true",
|
|
2803
2963
|
"data-file-code-surface-layout": "workspace",
|
|
@@ -2817,11 +2977,16 @@ function FileOperationWorkspaceSurface({ block }) {
|
|
|
2817
2977
|
}) : null, /* @__PURE__ */ jsxs("div", {
|
|
2818
2978
|
"data-file-code-canvas": "true",
|
|
2819
2979
|
className: "flex h-full min-h-full min-w-0 flex-1 flex-col bg-white",
|
|
2820
|
-
children: [
|
|
2821
|
-
"data-file-code-
|
|
2822
|
-
className:
|
|
2823
|
-
|
|
2824
|
-
|
|
2980
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2981
|
+
"data-file-code-stack": "true",
|
|
2982
|
+
className: "min-w-full",
|
|
2983
|
+
style: { minWidth: codeColumnWidth },
|
|
2984
|
+
children: block.lines.map((line, index) => /* @__PURE__ */ jsx("div", {
|
|
2985
|
+
"data-file-code-canvas-row": "true",
|
|
2986
|
+
className: FILE_ROW_CLASS_NAME,
|
|
2987
|
+
children: /* @__PURE__ */ jsx(FileOperationCodeCell, { line })
|
|
2988
|
+
}, readLineKey("code", line, index)))
|
|
2989
|
+
}), /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 bg-white" })]
|
|
2825
2990
|
})]
|
|
2826
2991
|
});
|
|
2827
2992
|
}
|
|
@@ -2829,15 +2994,22 @@ function FileOperationCodeSurface({ block, layout = "compact" }) {
|
|
|
2829
2994
|
if (layout === "workspace") return /* @__PURE__ */ jsx(FileOperationWorkspaceSurface, { block });
|
|
2830
2995
|
const showLineNumbers = readHasBlockLineNumbers(block);
|
|
2831
2996
|
const lineNumberColumnWidth = readLineNumberColumnWidth(block);
|
|
2997
|
+
const codeColumnWidth = readCodeColumnWidth(block);
|
|
2998
|
+
const surfaceMinWidth = showLineNumbers ? `calc(${lineNumberColumnWidth} + ${codeColumnWidth})` : codeColumnWidth;
|
|
2832
2999
|
return /* @__PURE__ */ jsx("div", {
|
|
2833
3000
|
"data-file-code-surface": "true",
|
|
2834
3001
|
"data-file-code-surface-layout": "compact",
|
|
2835
3002
|
className: "overflow-x-auto custom-scrollbar-amber bg-white",
|
|
2836
|
-
children:
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
3003
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
3004
|
+
"data-file-code-stack": "true",
|
|
3005
|
+
className: "min-w-full",
|
|
3006
|
+
style: { minWidth: surfaceMinWidth },
|
|
3007
|
+
children: block.lines.map((line, index) => /* @__PURE__ */ jsx(FileOperationLineRow, {
|
|
3008
|
+
line,
|
|
3009
|
+
showLineNumbers,
|
|
3010
|
+
lineNumberColumnWidth
|
|
3011
|
+
}, readLineKey("row", line, index)))
|
|
3012
|
+
})
|
|
2841
3013
|
});
|
|
2842
3014
|
}
|
|
2843
3015
|
function FileOperationLinesGrid({ block }) {
|