@neuronection/assistant-ui 0.22.0 → 0.24.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/CHANGELOG.md +92 -0
- package/README.md +9 -0
- package/dist/about.js +1 -1
- package/dist/ai-magic-fill.js +1 -1
- package/dist/chat-branch-tree.d.ts +45 -0
- package/dist/chat-branch-tree.js +3 -0
- package/dist/chat-branch-tree.js.map +1 -0
- package/dist/chat-composer.d.ts +50 -0
- package/dist/chat-composer.js +3 -0
- package/dist/chat-composer.js.map +1 -0
- package/dist/chat-core.d.ts +154 -0
- package/dist/chat-core.js +4 -0
- package/dist/chat-core.js.map +1 -0
- package/dist/chat-drawer.d.ts +32 -0
- package/dist/chat-drawer.js +3 -0
- package/dist/chat-drawer.js.map +1 -0
- package/dist/chat-launcher.d.ts +28 -0
- package/dist/chat-launcher.js +3 -0
- package/dist/chat-launcher.js.map +1 -0
- package/dist/chat-markdown.d.ts +64 -0
- package/dist/chat-markdown.js +3 -0
- package/dist/chat-markdown.js.map +1 -0
- package/dist/chat-message.d.ts +108 -0
- package/dist/chat-message.js +3 -0
- package/dist/chat-message.js.map +1 -0
- package/dist/chat-panel.d.ts +28 -0
- package/dist/chat-panel.js +3 -0
- package/dist/chat-panel.js.map +1 -0
- package/dist/chat-reasoning.d.ts +27 -0
- package/dist/chat-reasoning.js +3 -0
- package/dist/chat-reasoning.js.map +1 -0
- package/dist/chat-session-list.d.ts +51 -0
- package/dist/chat-session-list.js +3 -0
- package/dist/chat-session-list.js.map +1 -0
- package/dist/chat-tool-card.d.ts +37 -0
- package/dist/chat-tool-card.js +3 -0
- package/dist/chat-tool-card.js.map +1 -0
- package/dist/chat-transcript.d.ts +33 -0
- package/dist/chat-transcript.js +3 -0
- package/dist/chat-transcript.js.map +1 -0
- package/dist/{chunk-CZ2BL2ZL.js → chunk-3JJ2WCPN.js} +2 -2
- package/dist/{chunk-CZ2BL2ZL.js.map → chunk-3JJ2WCPN.js.map} +1 -1
- package/dist/chunk-5IOLDMDY.js +3 -0
- package/dist/chunk-5IOLDMDY.js.map +1 -0
- package/dist/{chunk-EODV6JK7.js → chunk-5QTHDB3D.js} +3 -3
- package/dist/{chunk-EODV6JK7.js.map → chunk-5QTHDB3D.js.map} +1 -1
- package/dist/chunk-6E6RRLKU.js +3 -0
- package/dist/chunk-6E6RRLKU.js.map +1 -0
- package/dist/chunk-6GNLY2EB.js +272 -0
- package/dist/chunk-6GNLY2EB.js.map +1 -0
- package/dist/chunk-743FJDRA.js +184 -0
- package/dist/chunk-743FJDRA.js.map +1 -0
- package/dist/{chunk-4UJKXTWY.js → chunk-AY77TWLT.js} +8 -3
- package/dist/chunk-AY77TWLT.js.map +1 -0
- package/dist/chunk-BSIWLVDX.js +217 -0
- package/dist/chunk-BSIWLVDX.js.map +1 -0
- package/dist/chunk-BVJT67B5.js +134 -0
- package/dist/chunk-BVJT67B5.js.map +1 -0
- package/dist/chunk-DZBTJZZV.js +201 -0
- package/dist/chunk-DZBTJZZV.js.map +1 -0
- package/dist/chunk-HQIYSW2D.js +131 -0
- package/dist/chunk-HQIYSW2D.js.map +1 -0
- package/dist/chunk-JPDD5AFN.js +119 -0
- package/dist/chunk-JPDD5AFN.js.map +1 -0
- package/dist/chunk-LSCWBNG3.js +3 -0
- package/dist/chunk-LSCWBNG3.js.map +1 -0
- package/dist/chunk-NKYPNEOX.js +198 -0
- package/dist/chunk-NKYPNEOX.js.map +1 -0
- package/dist/{chunk-INMAUGBK.js → chunk-OH7AJ3WY.js} +3 -3
- package/dist/{chunk-INMAUGBK.js.map → chunk-OH7AJ3WY.js.map} +1 -1
- package/dist/chunk-PAQ6YQ7Y.js +3 -0
- package/dist/chunk-PAQ6YQ7Y.js.map +1 -0
- package/dist/chunk-QVDCFZSE.js +72 -0
- package/dist/chunk-QVDCFZSE.js.map +1 -0
- package/dist/chunk-RPLEI6LQ.js +102 -0
- package/dist/chunk-RPLEI6LQ.js.map +1 -0
- package/dist/chunk-S62VJVWB.js +36 -0
- package/dist/chunk-S62VJVWB.js.map +1 -0
- package/dist/chunk-X3C2FBMR.js +141 -0
- package/dist/chunk-X3C2FBMR.js.map +1 -0
- package/dist/{chunk-7YLR4AGA.js → chunk-XZWLTTHA.js} +2 -2
- package/dist/{chunk-7YLR4AGA.js.map → chunk-XZWLTTHA.js.map} +1 -1
- package/dist/chunk-Z4IBQ53C.js +75 -0
- package/dist/chunk-Z4IBQ53C.js.map +1 -0
- package/dist/{chunk-7KD4MG75.js → chunk-ZK2V2LPA.js} +3 -3
- package/dist/chunk-ZK2V2LPA.js.map +1 -0
- package/dist/copy-button.js +1 -1
- package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +39 -26
- package/dist/index.js.map +1 -1
- package/dist/portal.js +1 -1
- package/dist/rich-text-editor.js +1 -1
- package/dist/settings-shell.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/tree-YaIz73vo.d.ts +54 -0
- package/dist/types-DZwzmyKE.d.ts +44 -0
- package/package.json +56 -2
- package/dist/chunk-4UJKXTWY.js.map +0 -1
- package/dist/chunk-7KD4MG75.js.map +0 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { Button } from './chunk-GTXGTQ6F.js';
|
|
2
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
import { ChevronLeft, ChevronRight, Copy, Pencil, RotateCcw, TriangleAlert } from 'lucide-react';
|
|
6
|
+
|
|
7
|
+
var ChatMessageEditor = React.forwardRef(
|
|
8
|
+
function ChatMessageEditor2({ value, onValueChange, onSubmit, onCancel, submitDisabled = false, rows = 3, labels, className }, ref) {
|
|
9
|
+
const onKeyDown = (event) => {
|
|
10
|
+
if (event.key === "Escape") {
|
|
11
|
+
event.preventDefault();
|
|
12
|
+
onCancel();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
if (!submitDisabled) {
|
|
18
|
+
onSubmit();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return /* @__PURE__ */ jsxs("div", { ref, "data-as": "chat-message-editor", className: cn("flex w-full flex-col gap-2", className), children: [
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
"textarea",
|
|
25
|
+
{
|
|
26
|
+
value,
|
|
27
|
+
rows,
|
|
28
|
+
"aria-label": labels?.ariaLabel ?? "Edit message",
|
|
29
|
+
onChange: (event) => onValueChange(event.target.value),
|
|
30
|
+
onKeyDown,
|
|
31
|
+
className: "w-full resize-y rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2 text-sm text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]"
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2", children: [
|
|
35
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onCancel, children: labels?.cancel ?? "Cancel" }),
|
|
36
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", disabled: submitDisabled, onClick: onSubmit, children: labels?.save ?? "Save & resend" })
|
|
37
|
+
] })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
var MessageVariantSwitcher = React.forwardRef(
|
|
42
|
+
function MessageVariantSwitcher2({ variants, onSelect, labels, className }, ref) {
|
|
43
|
+
const { index, count, siblingIds } = variants;
|
|
44
|
+
const previousId = index > 1 ? siblingIds[index - 2] : void 0;
|
|
45
|
+
const nextId = index < count ? siblingIds[index] : void 0;
|
|
46
|
+
const select = (event, messageId) => {
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
if (messageId !== void 0) {
|
|
49
|
+
onSelect(messageId);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
return /* @__PURE__ */ jsxs(
|
|
53
|
+
"div",
|
|
54
|
+
{
|
|
55
|
+
ref,
|
|
56
|
+
role: "group",
|
|
57
|
+
"aria-label": labels?.group ?? "Message variants",
|
|
58
|
+
"data-as": "message-variant-switcher",
|
|
59
|
+
className: cn("flex items-center gap-0.5 text-xs text-[var(--as-muted-fg)]", className),
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
"button",
|
|
63
|
+
{
|
|
64
|
+
type: "button",
|
|
65
|
+
disabled: previousId === void 0,
|
|
66
|
+
"aria-label": labels?.previous ?? "Previous variant",
|
|
67
|
+
title: labels?.previous ?? "Previous variant",
|
|
68
|
+
onClick: (event) => select(event, previousId),
|
|
69
|
+
className: "rounded-[var(--as-radius-sm)] p-0.5 transition-colors hover:bg-[var(--as-surface-raised)] hover:text-[var(--as-fg)] disabled:pointer-events-none disabled:opacity-30 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
|
|
70
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-3.5", "aria-hidden": true })
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ jsxs("span", { className: "tabular-nums", title: labels?.variantOf?.(index, count) ?? `Variant ${index} of ${count}`, children: [
|
|
74
|
+
index,
|
|
75
|
+
"/",
|
|
76
|
+
count
|
|
77
|
+
] }),
|
|
78
|
+
/* @__PURE__ */ jsx(
|
|
79
|
+
"button",
|
|
80
|
+
{
|
|
81
|
+
type: "button",
|
|
82
|
+
disabled: nextId === void 0,
|
|
83
|
+
"aria-label": labels?.next ?? "Next variant",
|
|
84
|
+
title: labels?.next ?? "Next variant",
|
|
85
|
+
onClick: (event) => select(event, nextId),
|
|
86
|
+
className: "rounded-[var(--as-radius-sm)] p-0.5 transition-colors hover:bg-[var(--as-surface-raised)] hover:text-[var(--as-fg)] disabled:pointer-events-none disabled:opacity-30 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
|
|
87
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5", "aria-hidden": true })
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
var actionButtonClass = "rounded-[var(--as-radius-sm)] p-1 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-surface-raised)] hover:text-[var(--as-fg)] focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]";
|
|
96
|
+
var ChatMessage = React.forwardRef(
|
|
97
|
+
function ChatMessage2({
|
|
98
|
+
role,
|
|
99
|
+
content,
|
|
100
|
+
reasoning,
|
|
101
|
+
children,
|
|
102
|
+
status = "done",
|
|
103
|
+
error,
|
|
104
|
+
actions,
|
|
105
|
+
editing = false,
|
|
106
|
+
variants,
|
|
107
|
+
onSelectVariant,
|
|
108
|
+
meta,
|
|
109
|
+
chips,
|
|
110
|
+
attachments,
|
|
111
|
+
labels,
|
|
112
|
+
compact = false,
|
|
113
|
+
className
|
|
114
|
+
}, ref) {
|
|
115
|
+
const isUser = role === "user";
|
|
116
|
+
const isSystem = role === "system";
|
|
117
|
+
const showActions = actions !== void 0 && (actions.onCopy !== void 0 || actions.onEdit !== void 0 || actions.onRegenerate !== void 0 || (actions.extras?.length ?? 0) > 0);
|
|
118
|
+
const editorLabels = { save: labels?.save, cancel: labels?.cancel, ariaLabel: labels?.ariaLabel };
|
|
119
|
+
const switcherLabels = { group: labels?.group, variantOf: labels?.variantOf, previous: labels?.previous, next: labels?.next };
|
|
120
|
+
if (isSystem) {
|
|
121
|
+
return /* @__PURE__ */ jsx(
|
|
122
|
+
"div",
|
|
123
|
+
{
|
|
124
|
+
ref,
|
|
125
|
+
"data-as": "chat-message",
|
|
126
|
+
"data-role": role,
|
|
127
|
+
className: cn("flex justify-center", className),
|
|
128
|
+
children: /* @__PURE__ */ jsx("div", { className: "rounded-full border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-1 text-xs text-[var(--as-muted-fg)]", children: content })
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return /* @__PURE__ */ jsxs(
|
|
133
|
+
"div",
|
|
134
|
+
{
|
|
135
|
+
ref,
|
|
136
|
+
"data-as": "chat-message",
|
|
137
|
+
"data-role": role,
|
|
138
|
+
"data-status": status,
|
|
139
|
+
className: cn("group/message flex w-full flex-col", isUser ? "items-end" : "items-start", className),
|
|
140
|
+
children: [
|
|
141
|
+
attachments ? /* @__PURE__ */ jsx("div", { className: "mb-1.5 flex w-full flex-wrap justify-end gap-1.5", children: attachments }) : null,
|
|
142
|
+
/* @__PURE__ */ jsxs(
|
|
143
|
+
"div",
|
|
144
|
+
{
|
|
145
|
+
className: cn(
|
|
146
|
+
"relative flex max-w-[92%] flex-col gap-1.5 rounded-[var(--as-radius-lg)] px-3 py-2 text-sm",
|
|
147
|
+
compact && "px-2.5 py-1.5",
|
|
148
|
+
isUser ? "rounded-br-[var(--as-radius-sm)] bg-[var(--as-primary)] text-[var(--as-primary-fg)]" : "rounded-bl-[var(--as-radius-sm)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-fg)]"
|
|
149
|
+
),
|
|
150
|
+
children: [
|
|
151
|
+
reasoning ? /* @__PURE__ */ jsx("div", { className: "not-prose", children: reasoning }) : null,
|
|
152
|
+
editing ? /* @__PURE__ */ jsx(
|
|
153
|
+
ChatMessageEditor,
|
|
154
|
+
{
|
|
155
|
+
value: editing.value,
|
|
156
|
+
onValueChange: editing.onValueChange,
|
|
157
|
+
onSubmit: editing.onSubmit,
|
|
158
|
+
onCancel: editing.onCancel,
|
|
159
|
+
submitDisabled: editing.submitDisabled,
|
|
160
|
+
labels: editorLabels
|
|
161
|
+
}
|
|
162
|
+
) : /* @__PURE__ */ jsx("div", { className: "min-w-0", children: content }),
|
|
163
|
+
status === "interrupted" ? /* @__PURE__ */ jsx("span", { className: "self-start rounded-full bg-[var(--as-warning)]/15 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-[var(--as-warning)]", children: labels?.interrupted ?? "Stopped" }) : null,
|
|
164
|
+
status === "error" && error ? /* @__PURE__ */ jsxs(
|
|
165
|
+
"div",
|
|
166
|
+
{
|
|
167
|
+
role: "alert",
|
|
168
|
+
className: "flex flex-col gap-1 rounded-[var(--as-radius)] border border-[var(--as-danger)]/40 bg-[var(--as-danger)]/10 px-2.5 py-1.5 text-xs text-[var(--as-danger)]",
|
|
169
|
+
children: [
|
|
170
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono font-semibold uppercase tracking-wide", children: error.code }),
|
|
171
|
+
/* @__PURE__ */ jsx("span", { className: "whitespace-pre-wrap break-words", children: error.message }),
|
|
172
|
+
error.retryable && actions?.onRetry ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "self-start", onClick: actions.onRetry, children: labels?.retry ?? "Retry" }) : null
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
) : null,
|
|
176
|
+
chips ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: chips }) : null,
|
|
177
|
+
children ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5", children }) : null,
|
|
178
|
+
showActions && !editing ? /* @__PURE__ */ jsxs(
|
|
179
|
+
"div",
|
|
180
|
+
{
|
|
181
|
+
className: cn(
|
|
182
|
+
"absolute top-1 flex items-center gap-0.5 rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-0.5 opacity-0 shadow-[var(--as-shadow-1)] transition-opacity focus-within:opacity-100 group-hover/message:opacity-100",
|
|
183
|
+
isUser ? "-left-9" : "-right-9"
|
|
184
|
+
),
|
|
185
|
+
children: [
|
|
186
|
+
actions?.onCopy ? /* @__PURE__ */ jsx("button", { type: "button", className: actionButtonClass, "aria-label": labels?.copy ?? "Copy", title: labels?.copy ?? "Copy", onClick: actions.onCopy, children: /* @__PURE__ */ jsx(Copy, { className: "size-3.5", "aria-hidden": true }) }) : null,
|
|
187
|
+
actions?.onEdit ? /* @__PURE__ */ jsx("button", { type: "button", className: actionButtonClass, "aria-label": labels?.edit ?? "Edit", title: labels?.edit ?? "Edit", onClick: actions.onEdit, children: /* @__PURE__ */ jsx(Pencil, { className: "size-3.5", "aria-hidden": true }) }) : null,
|
|
188
|
+
actions?.onRegenerate ? /* @__PURE__ */ jsx("button", { type: "button", className: actionButtonClass, "aria-label": labels?.regenerate ?? "Regenerate", title: labels?.regenerate ?? "Regenerate", onClick: actions.onRegenerate, children: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5", "aria-hidden": true }) }) : null,
|
|
189
|
+
actions?.extras?.map((extra) => /* @__PURE__ */ jsx(
|
|
190
|
+
"button",
|
|
191
|
+
{
|
|
192
|
+
type: "button",
|
|
193
|
+
className: cn(actionButtonClass, extra.danger && "hover:text-[var(--as-danger)]"),
|
|
194
|
+
"aria-label": extra.label,
|
|
195
|
+
title: extra.label,
|
|
196
|
+
onClick: extra.onClick,
|
|
197
|
+
children: extra.icon ? /* @__PURE__ */ jsx(extra.icon, { className: "size-3.5", "aria-hidden": true }) : /* @__PURE__ */ jsx(TriangleAlert, { className: "size-3.5", "aria-hidden": true })
|
|
198
|
+
},
|
|
199
|
+
extra.key
|
|
200
|
+
))
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
) : null
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
),
|
|
207
|
+
meta ? /* @__PURE__ */ jsx("div", { className: "mt-0.5 flex flex-wrap items-center gap-1.5 px-1 text-[10px] text-[var(--as-muted-fg)]", children: meta }) : null,
|
|
208
|
+
variants && variants.count > 1 && onSelectVariant ? /* @__PURE__ */ jsx(MessageVariantSwitcher, { variants, onSelect: onSelectVariant, labels: switcherLabels, className: "mt-0.5 px-1" }) : null
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
export { ChatMessage, ChatMessageEditor, MessageVariantSwitcher };
|
|
216
|
+
//# sourceMappingURL=chunk-BSIWLVDX.js.map
|
|
217
|
+
//# sourceMappingURL=chunk-BSIWLVDX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/chat-message/ChatMessageEditor.tsx","../src/components/chat-message/MessageVariantSwitcher.tsx","../src/components/chat-message/ChatMessage.tsx"],"names":["ChatMessageEditor","React2","MessageVariantSwitcher","jsxs","jsx","React3","ChatMessage"],"mappings":"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","file":"chunk-BSIWLVDX.js","sourcesContent":["import * as React from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\n\nexport interface ChatMessageEditorLabels {\n save: string\n cancel: string\n ariaLabel: string\n}\n\nexport interface ChatMessageEditorProps {\n value: string\n onValueChange: (value: string) => void\n /** Save & resend — branches the tree (family `edit` endpoint) and reruns the turn. */\n onSubmit: () => void\n onCancel: () => void\n submitDisabled?: boolean\n rows?: number\n labels?: Partial<ChatMessageEditorLabels>\n className?: string\n}\n\n/**\n * Inline user-prompt editor for the edit-and-resend flow (study pattern):\n * controlled textarea, Cmd/Ctrl+Enter saves, Escape cancels.\n */\nexport const ChatMessageEditor = React.forwardRef<HTMLDivElement, ChatMessageEditorProps>(\n function ChatMessageEditor(\n { value, onValueChange, onSubmit, onCancel, submitDisabled = false, rows = 3, labels, className },\n ref,\n ) {\n const onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement> = (event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n onCancel()\n return\n }\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n if (!submitDisabled) {\n onSubmit()\n }\n }\n }\n\n return (\n <div ref={ref} data-as=\"chat-message-editor\" className={cn('flex w-full flex-col gap-2', className)}>\n <textarea\n value={value}\n rows={rows}\n aria-label={labels?.ariaLabel ?? 'Edit message'}\n onChange={(event) => onValueChange(event.target.value)}\n onKeyDown={onKeyDown}\n className=\"w-full resize-y rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2 text-sm text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n />\n <div className=\"flex items-center justify-end gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n {labels?.cancel ?? 'Cancel'}\n </Button>\n <Button size=\"sm\" disabled={submitDisabled} onClick={onSubmit}>\n {labels?.save ?? 'Save & resend'}\n </Button>\n </div>\n </div>\n )\n },\n)\n","import * as React from 'react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\n\nimport type { ChatMessageVariants } from '../chat-core/types'\nimport { cn } from '../../lib/utils'\n\nexport interface MessageVariantSwitcherLabels {\n group: string\n variantOf: (index: number, count: number) => string\n previous: string\n next: string\n}\n\nexport interface MessageVariantSwitcherProps {\n variants: ChatMessageVariants\n /** Flip the parent's active-child pointer to the sibling id (family `select` endpoint). */\n onSelect: (messageId: string) => void\n labels?: Partial<MessageVariantSwitcherLabels>\n className?: string\n}\n\n/**\n * The `‹ n/N ›` sibling-variant switcher under a branched message\n * (study's inline switcher, family branching contract).\n */\nexport const MessageVariantSwitcher = React.forwardRef<HTMLDivElement, MessageVariantSwitcherProps>(\n function MessageVariantSwitcher({ variants, onSelect, labels, className }, ref) {\n const { index, count, siblingIds } = variants\n const previousId = index > 1 ? siblingIds[index - 2] : undefined\n const nextId = index < count ? siblingIds[index] : undefined\n\n const select = (event: React.MouseEvent<HTMLButtonElement>, messageId: string | undefined) => {\n event.stopPropagation()\n if (messageId !== undefined) {\n onSelect(messageId)\n }\n }\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={labels?.group ?? 'Message variants'}\n data-as=\"message-variant-switcher\"\n className={cn('flex items-center gap-0.5 text-xs text-[var(--as-muted-fg)]', className)}\n >\n <button\n type=\"button\"\n disabled={previousId === undefined}\n aria-label={labels?.previous ?? 'Previous variant'}\n title={labels?.previous ?? 'Previous variant'}\n onClick={(event) => select(event, previousId)}\n className=\"rounded-[var(--as-radius-sm)] p-0.5 transition-colors hover:bg-[var(--as-surface-raised)] hover:text-[var(--as-fg)] disabled:pointer-events-none disabled:opacity-30 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <ChevronLeft className=\"size-3.5\" aria-hidden />\n </button>\n <span className=\"tabular-nums\" title={labels?.variantOf?.(index, count) ?? `Variant ${index} of ${count}`}>\n {index}/{count}\n </span>\n <button\n type=\"button\"\n disabled={nextId === undefined}\n aria-label={labels?.next ?? 'Next variant'}\n title={labels?.next ?? 'Next variant'}\n onClick={(event) => select(event, nextId)}\n className=\"rounded-[var(--as-radius-sm)] p-0.5 transition-colors hover:bg-[var(--as-surface-raised)] hover:text-[var(--as-fg)] disabled:pointer-events-none disabled:opacity-30 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <ChevronRight className=\"size-3.5\" aria-hidden />\n </button>\n </div>\n )\n },\n)\n","import * as React from 'react'\nimport { Copy, Pencil, RotateCcw, TriangleAlert } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport type { ChatError, ChatMessageVariants, ChatRole } from '../chat-core/types'\nimport { ChatMessageEditor, type ChatMessageEditorLabels } from './ChatMessageEditor'\nimport { MessageVariantSwitcher, type MessageVariantSwitcherLabels } from './MessageVariantSwitcher'\n\nexport interface ChatMessageAction {\n key: string\n label: string\n icon?: LucideIcon\n onClick: () => void\n danger?: boolean\n}\n\nexport interface ChatMessageActions {\n onCopy?: () => void\n onEdit?: () => void\n onRegenerate?: () => void\n onRetry?: () => void\n /** Extra icon actions (app-specific). */\n extras?: ChatMessageAction[]\n}\n\nexport interface ChatMessageLabels {\n copy: string\n edit: string\n regenerate: string\n retry: string\n interrupted: string\n error: string\n}\n\nexport interface ChatMessageProps {\n role: ChatRole\n /** Usually a `MarkdownSurface`; any node graph renders here. */\n content: React.ReactNode\n /** Thinking block slot (usually `ChatReasoning`). */\n reasoning?: React.ReactNode\n /** Tool cards / HITL cards below the content. */\n children?: React.ReactNode\n status?: 'streaming' | 'done' | 'error' | 'interrupted'\n error?: ChatError\n actions?: ChatMessageActions\n /** Edit-and-resend mode for user messages (renders `ChatMessageEditor`). */\n editing?: false | { value: string; onValueChange: (value: string) => void; onSubmit: () => void; onCancel: () => void; submitDisabled?: boolean }\n variants?: ChatMessageVariants\n onSelectVariant?: (messageId: string) => void\n /** Badge row (model, latency, tokens — app-defined). */\n meta?: React.ReactNode\n /** Deep-link chip row (career references, health citations). */\n chips?: React.ReactNode\n /** Attachment rail above the content. */\n attachments?: React.ReactNode\n labels?: Partial<ChatMessageLabels & ChatMessageEditorLabels & MessageVariantSwitcherLabels>\n compact?: boolean\n className?: string\n}\n\nconst actionButtonClass =\n 'rounded-[var(--as-radius-sm)] p-1 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-surface-raised)] hover:text-[var(--as-fg)] focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]'\n\n/**\n * The family chat bubble: role-aligned, hover action row (copy / edit /\n * regenerate + app extras), variant switcher under branched messages,\n * reasoning and below-content slots, inline edit-and-resend, error +\n * interrupted states. Presentational — state lives app-side.\n */\nexport const ChatMessage = React.forwardRef<HTMLDivElement, ChatMessageProps>(\n function ChatMessage(\n {\n role,\n content,\n reasoning,\n children,\n status = 'done',\n error,\n actions,\n editing = false,\n variants,\n onSelectVariant,\n meta,\n chips,\n attachments,\n labels,\n compact = false,\n className,\n },\n ref,\n ) {\n const isUser = role === 'user'\n const isSystem = role === 'system'\n const showActions =\n actions !== undefined && (actions.onCopy !== undefined || actions.onEdit !== undefined || actions.onRegenerate !== undefined || (actions.extras?.length ?? 0) > 0)\n const editorLabels = { save: labels?.save, cancel: labels?.cancel, ariaLabel: labels?.ariaLabel }\n const switcherLabels = { group: labels?.group, variantOf: labels?.variantOf, previous: labels?.previous, next: labels?.next }\n\n if (isSystem) {\n return (\n <div\n ref={ref}\n data-as=\"chat-message\"\n data-role={role}\n className={cn('flex justify-center', className)}\n >\n <div className=\"rounded-full border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-1 text-xs text-[var(--as-muted-fg)]\">\n {content}\n </div>\n </div>\n )\n }\n\n return (\n <div\n ref={ref}\n data-as=\"chat-message\"\n data-role={role}\n data-status={status}\n className={cn('group/message flex w-full flex-col', isUser ? 'items-end' : 'items-start', className)}\n >\n {attachments ? <div className=\"mb-1.5 flex w-full flex-wrap justify-end gap-1.5\">{attachments}</div> : null}\n <div\n className={cn(\n 'relative flex max-w-[92%] flex-col gap-1.5 rounded-[var(--as-radius-lg)] px-3 py-2 text-sm',\n compact && 'px-2.5 py-1.5',\n isUser\n ? 'rounded-br-[var(--as-radius-sm)] bg-[var(--as-primary)] text-[var(--as-primary-fg)]'\n : 'rounded-bl-[var(--as-radius-sm)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-fg)]',\n )}\n >\n {reasoning ? <div className=\"not-prose\">{reasoning}</div> : null}\n {editing ? (\n <ChatMessageEditor\n value={editing.value}\n onValueChange={editing.onValueChange}\n onSubmit={editing.onSubmit}\n onCancel={editing.onCancel}\n submitDisabled={editing.submitDisabled}\n labels={editorLabels}\n />\n ) : (\n <div className=\"min-w-0\">{content}</div>\n )}\n {status === 'interrupted' ? (\n <span className=\"self-start rounded-full bg-[var(--as-warning)]/15 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-[var(--as-warning)]\">\n {labels?.interrupted ?? 'Stopped'}\n </span>\n ) : null}\n {status === 'error' && error ? (\n <div\n role=\"alert\"\n className=\"flex flex-col gap-1 rounded-[var(--as-radius)] border border-[var(--as-danger)]/40 bg-[var(--as-danger)]/10 px-2.5 py-1.5 text-xs text-[var(--as-danger)]\"\n >\n <span className=\"font-mono font-semibold uppercase tracking-wide\">{error.code}</span>\n <span className=\"whitespace-pre-wrap break-words\">{error.message}</span>\n {error.retryable && actions?.onRetry ? (\n <Button variant=\"outline\" size=\"sm\" className=\"self-start\" onClick={actions.onRetry}>\n {labels?.retry ?? 'Retry'}\n </Button>\n ) : null}\n </div>\n ) : null}\n {chips ? <div className=\"flex flex-wrap gap-1.5\">{chips}</div> : null}\n {children ? <div className=\"flex flex-col gap-1.5\">{children}</div> : null}\n {showActions && !editing ? (\n <div\n className={cn(\n 'absolute top-1 flex items-center gap-0.5 rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-0.5 opacity-0 shadow-[var(--as-shadow-1)] transition-opacity focus-within:opacity-100 group-hover/message:opacity-100',\n isUser ? '-left-9' : '-right-9',\n )}\n >\n {actions?.onCopy ? (\n <button type=\"button\" className={actionButtonClass} aria-label={labels?.copy ?? 'Copy'} title={labels?.copy ?? 'Copy'} onClick={actions.onCopy}>\n <Copy className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n {actions?.onEdit ? (\n <button type=\"button\" className={actionButtonClass} aria-label={labels?.edit ?? 'Edit'} title={labels?.edit ?? 'Edit'} onClick={actions.onEdit}>\n <Pencil className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n {actions?.onRegenerate ? (\n <button type=\"button\" className={actionButtonClass} aria-label={labels?.regenerate ?? 'Regenerate'} title={labels?.regenerate ?? 'Regenerate'} onClick={actions.onRegenerate}>\n <RotateCcw className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n {actions?.extras?.map((extra) => (\n <button\n key={extra.key}\n type=\"button\"\n className={cn(actionButtonClass, extra.danger && 'hover:text-[var(--as-danger)]')}\n aria-label={extra.label}\n title={extra.label}\n onClick={extra.onClick}\n >\n {extra.icon ? <extra.icon className=\"size-3.5\" aria-hidden /> : <TriangleAlert className=\"size-3.5\" aria-hidden />}\n </button>\n ))}\n </div>\n ) : null}\n </div>\n {meta ? <div className=\"mt-0.5 flex flex-wrap items-center gap-1.5 px-1 text-[10px] text-[var(--as-muted-fg)]\">{meta}</div> : null}\n {variants && variants.count > 1 && onSelectVariant ? (\n <MessageVariantSwitcher variants={variants} onSelect={onSelectVariant} labels={switcherLabels} className=\"mt-0.5 px-1\" />\n ) : null}\n </div>\n )\n },\n)\n"]}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { ChatMessage } from './chunk-BSIWLVDX.js';
|
|
2
|
+
import { MarkdownSurface } from './chunk-DZBTJZZV.js';
|
|
3
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { ArrowDown } from 'lucide-react';
|
|
6
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
7
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function defaultRenderItem(message) {
|
|
10
|
+
return /* @__PURE__ */ jsx(
|
|
11
|
+
ChatMessage,
|
|
12
|
+
{
|
|
13
|
+
role: message.role,
|
|
14
|
+
status: message.status,
|
|
15
|
+
content: /* @__PURE__ */ jsx(MarkdownSurface, { value: message.content, streaming: message.status === "streaming" }),
|
|
16
|
+
variants: message.variants
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
var ChatTranscript = React.forwardRef(
|
|
21
|
+
function ChatTranscript2({
|
|
22
|
+
items,
|
|
23
|
+
renderItem = defaultRenderItem,
|
|
24
|
+
live,
|
|
25
|
+
emptyState,
|
|
26
|
+
autoScroll = true,
|
|
27
|
+
scrollThresholdPx = 120,
|
|
28
|
+
virtualized = false,
|
|
29
|
+
labels,
|
|
30
|
+
className
|
|
31
|
+
}, ref) {
|
|
32
|
+
const scrollRef = React.useRef(null);
|
|
33
|
+
const atBottomRef = React.useRef(true);
|
|
34
|
+
const [showJump, setShowJump] = React.useState(false);
|
|
35
|
+
const [announcement, setAnnouncement] = React.useState("");
|
|
36
|
+
const previousCountRef = React.useRef(-1);
|
|
37
|
+
const onScroll = () => {
|
|
38
|
+
const element = scrollRef.current;
|
|
39
|
+
if (element === null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const distance = element.scrollHeight - element.scrollTop - element.clientHeight;
|
|
43
|
+
const atBottom = distance <= scrollThresholdPx;
|
|
44
|
+
atBottomRef.current = atBottom;
|
|
45
|
+
setShowJump(element.scrollHeight > element.clientHeight && !atBottom);
|
|
46
|
+
};
|
|
47
|
+
React.useEffect(() => {
|
|
48
|
+
const element = scrollRef.current;
|
|
49
|
+
if (element === null || !autoScroll || !atBottomRef.current) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const frame = requestAnimationFrame(() => {
|
|
53
|
+
element.scrollTop = element.scrollHeight;
|
|
54
|
+
});
|
|
55
|
+
return () => cancelAnimationFrame(frame);
|
|
56
|
+
});
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
if (previousCountRef.current === -1) {
|
|
59
|
+
previousCountRef.current = items.length;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (items.length > previousCountRef.current) {
|
|
63
|
+
const added = items[items.length - 1];
|
|
64
|
+
previousCountRef.current = items.length;
|
|
65
|
+
if (added && added.role !== "user") {
|
|
66
|
+
setAnnouncement(labels?.replied ?? "Assistant replied");
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
previousCountRef.current = items.length;
|
|
71
|
+
}, [items, labels]);
|
|
72
|
+
const scrollToBottom = () => {
|
|
73
|
+
const element = scrollRef.current;
|
|
74
|
+
if (element !== null) {
|
|
75
|
+
element.scrollTo({ top: element.scrollHeight, behavior: "smooth" });
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const rowCount = items.length + (live !== void 0 ? 1 : 0);
|
|
79
|
+
const virtualizer = useVirtualizer({
|
|
80
|
+
count: virtualized ? rowCount : 0,
|
|
81
|
+
getScrollElement: () => scrollRef.current,
|
|
82
|
+
estimateSize: () => 120,
|
|
83
|
+
overscan: 8,
|
|
84
|
+
initialRect: { width: 480, height: 600 }
|
|
85
|
+
});
|
|
86
|
+
return /* @__PURE__ */ jsxs("div", { ref, "data-as": "chat-transcript", className: cn("relative min-h-0 flex-1", className), children: [
|
|
87
|
+
/* @__PURE__ */ jsx(
|
|
88
|
+
"div",
|
|
89
|
+
{
|
|
90
|
+
ref: scrollRef,
|
|
91
|
+
onScroll,
|
|
92
|
+
role: "log",
|
|
93
|
+
"aria-label": labels?.log ?? "Conversation",
|
|
94
|
+
"aria-busy": live !== void 0,
|
|
95
|
+
className: "h-full overflow-y-auto overscroll-contain px-1 py-2",
|
|
96
|
+
children: items.length === 0 && live === void 0 ? /* @__PURE__ */ jsx("div", { className: "flex h-full min-h-40 items-center justify-center p-4 text-sm text-[var(--as-muted-fg)]", children: emptyState ?? (labels?.empty ?? "Start the conversation") }) : virtualized ? /* @__PURE__ */ jsx("div", { style: { height: virtualizer.getTotalSize(), position: "relative" }, children: virtualizer.getVirtualItems().map((row) => {
|
|
97
|
+
const isLive = row.index >= items.length;
|
|
98
|
+
const node = isLive ? live : renderItem(items[row.index], row.index);
|
|
99
|
+
return /* @__PURE__ */ jsx(
|
|
100
|
+
"div",
|
|
101
|
+
{
|
|
102
|
+
"data-index": row.index,
|
|
103
|
+
ref: virtualizer.measureElement,
|
|
104
|
+
style: { position: "absolute", top: 0, left: 0, width: "100%", transform: `translateY(${row.start}px)` },
|
|
105
|
+
className: "px-2 py-1.5",
|
|
106
|
+
children: node
|
|
107
|
+
},
|
|
108
|
+
row.key
|
|
109
|
+
);
|
|
110
|
+
}) }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 px-2", children: [
|
|
111
|
+
items.map((message, index) => /* @__PURE__ */ jsx("div", { children: renderItem(message, index) }, message.id)),
|
|
112
|
+
live !== void 0 ? /* @__PURE__ */ jsx("div", { "data-as": "chat-transcript-live", children: live }) : null
|
|
113
|
+
] })
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
/* @__PURE__ */ jsx("div", { "aria-live": "polite", className: "sr-only", children: announcement }),
|
|
117
|
+
showJump ? /* @__PURE__ */ jsx(
|
|
118
|
+
"button",
|
|
119
|
+
{
|
|
120
|
+
type: "button",
|
|
121
|
+
onClick: scrollToBottom,
|
|
122
|
+
"aria-label": labels?.scrollToBottom ?? "Scroll to latest",
|
|
123
|
+
title: labels?.scrollToBottom ?? "Scroll to latest",
|
|
124
|
+
className: "absolute bottom-3 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-fg)] shadow-[var(--as-shadow-2)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]",
|
|
125
|
+
children: /* @__PURE__ */ jsx(ArrowDown, { className: "size-4", "aria-hidden": true })
|
|
126
|
+
}
|
|
127
|
+
) : null
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
export { ChatTranscript };
|
|
133
|
+
//# sourceMappingURL=chunk-BVJT67B5.js.map
|
|
134
|
+
//# sourceMappingURL=chunk-BVJT67B5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/chat-transcript/ChatTranscript.tsx"],"names":["ChatTranscript"],"mappings":"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","file":"chunk-BVJT67B5.js","sourcesContent":["import * as React from 'react'\nimport { ArrowDown } from 'lucide-react'\nimport { useVirtualizer } from '@tanstack/react-virtual'\n\nimport { cn } from '../../lib/utils'\nimport { ChatMessage } from '../chat-message/ChatMessage'\nimport { MarkdownSurface } from '../chat-markdown/MarkdownSurface'\nimport type { ChatMessageView } from '../chat-core/types'\n\nexport interface ChatTranscriptLabels {\n log: string\n scrollToBottom: string\n empty: string\n replied: string\n}\n\nexport interface ChatTranscriptProps {\n items: ChatMessageView[]\n /** Override the default `ChatMessage` + `MarkdownSurface` rendering. */\n renderItem?: (message: ChatMessageView, index: number) => React.ReactNode\n /** Streaming tail — the live turn bubble (or any node). */\n live?: React.ReactNode\n emptyState?: React.ReactNode\n /** Stick to bottom while the user hasn't scrolled away. Default true. */\n autoScroll?: boolean\n /** Distance from the bottom that still counts as \"at the bottom\". Default 120 px. */\n scrollThresholdPx?: number\n /** Virtualize long transcripts (dynamic row measurement). Default false. */\n virtualized?: boolean\n labels?: Partial<ChatTranscriptLabels>\n className?: string\n}\n\nfunction defaultRenderItem(message: ChatMessageView) {\n return (\n <ChatMessage\n role={message.role}\n status={message.status}\n content={<MarkdownSurface value={message.content} streaming={message.status === 'streaming'} />}\n variants={message.variants}\n />\n )\n}\n\n/**\n * The conversation list: `role=\"log\"` with polite turn-completion\n * announcements, stick-to-bottom auto-scroll with a jump-to-latest pill,\n * optional virtualization for thousand-message threads.\n */\nexport const ChatTranscript = React.forwardRef<HTMLDivElement, ChatTranscriptProps>(\n function ChatTranscript(\n {\n items,\n renderItem = defaultRenderItem,\n live,\n emptyState,\n autoScroll = true,\n scrollThresholdPx = 120,\n virtualized = false,\n labels,\n className,\n },\n ref,\n ) {\n const scrollRef = React.useRef<HTMLDivElement | null>(null)\n const atBottomRef = React.useRef(true)\n const [showJump, setShowJump] = React.useState(false)\n const [announcement, setAnnouncement] = React.useState('')\n const previousCountRef = React.useRef(-1)\n\n const onScroll = () => {\n const element = scrollRef.current\n if (element === null) {\n return\n }\n const distance = element.scrollHeight - element.scrollTop - element.clientHeight\n const atBottom = distance <= scrollThresholdPx\n atBottomRef.current = atBottom\n setShowJump(element.scrollHeight > element.clientHeight && !atBottom)\n }\n\n React.useEffect(() => {\n const element = scrollRef.current\n if (element === null || !autoScroll || !atBottomRef.current) {\n return\n }\n const frame = requestAnimationFrame(() => {\n element.scrollTop = element.scrollHeight\n })\n return () => cancelAnimationFrame(frame)\n })\n\n React.useEffect(() => {\n if (previousCountRef.current === -1) {\n previousCountRef.current = items.length\n return\n }\n if (items.length > previousCountRef.current) {\n const added = items[items.length - 1]\n previousCountRef.current = items.length\n if (added && added.role !== 'user') {\n setAnnouncement(labels?.replied ?? 'Assistant replied')\n }\n return\n }\n previousCountRef.current = items.length\n }, [items, labels])\n\n const scrollToBottom = () => {\n const element = scrollRef.current\n if (element !== null) {\n element.scrollTo({ top: element.scrollHeight, behavior: 'smooth' })\n }\n }\n\n const rowCount = items.length + (live !== undefined ? 1 : 0)\n const virtualizer = useVirtualizer({\n count: virtualized ? rowCount : 0,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => 120,\n overscan: 8,\n initialRect: { width: 480, height: 600 },\n })\n\n return (\n <div ref={ref} data-as=\"chat-transcript\" className={cn('relative min-h-0 flex-1', className)}>\n <div\n ref={scrollRef}\n onScroll={onScroll}\n role=\"log\"\n aria-label={labels?.log ?? 'Conversation'}\n aria-busy={live !== undefined}\n className=\"h-full overflow-y-auto overscroll-contain px-1 py-2\"\n >\n {items.length === 0 && live === undefined ? (\n <div className=\"flex h-full min-h-40 items-center justify-center p-4 text-sm text-[var(--as-muted-fg)]\">\n {emptyState ?? (labels?.empty ?? 'Start the conversation')}\n </div>\n ) : virtualized ? (\n <div style={{ height: virtualizer.getTotalSize(), position: 'relative' }}>\n {virtualizer.getVirtualItems().map((row) => {\n const isLive = row.index >= items.length\n const node = isLive ? live : renderItem(items[row.index]!, row.index)\n return (\n <div\n key={row.key}\n data-index={row.index}\n ref={virtualizer.measureElement}\n style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${row.start}px)` }}\n className=\"px-2 py-1.5\"\n >\n {node}\n </div>\n )\n })}\n </div>\n ) : (\n <div className=\"flex flex-col gap-3 px-2\">\n {items.map((message, index) => (\n <div key={message.id}>{renderItem(message, index)}</div>\n ))}\n {live !== undefined ? <div data-as=\"chat-transcript-live\">{live}</div> : null}\n </div>\n )}\n </div>\n <div aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </div>\n {showJump ? (\n <button\n type=\"button\"\n onClick={scrollToBottom}\n aria-label={labels?.scrollToBottom ?? 'Scroll to latest'}\n title={labels?.scrollToBottom ?? 'Scroll to latest'}\n className=\"absolute bottom-3 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-fg)] shadow-[var(--as-shadow-2)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <ArrowDown className=\"size-4\" aria-hidden />\n </button>\n ) : null}\n </div>\n )\n },\n)\n"]}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { CopyButton } from './chunk-3JJ2WCPN.js';
|
|
2
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
3
|
+
import * as React3 from 'react';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
import ReactMarkdown, { defaultUrlTransform } from 'react-markdown';
|
|
6
|
+
import rehypeKatex from 'rehype-katex';
|
|
7
|
+
import remarkGfm from 'remark-gfm';
|
|
8
|
+
import remarkMath from 'remark-math';
|
|
9
|
+
|
|
10
|
+
var MarkdownCodeBlock = React3.forwardRef(
|
|
11
|
+
function MarkdownCodeBlock2({ code, language, showLanguage = true, labels, className }, ref) {
|
|
12
|
+
const copyLabel = labels?.copy ?? "Copy code";
|
|
13
|
+
const codeLabel = labels?.code ?? "Code";
|
|
14
|
+
return /* @__PURE__ */ jsxs(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
ref,
|
|
18
|
+
"data-as": "markdown-code-block",
|
|
19
|
+
className: cn(
|
|
20
|
+
"group/code relative my-3 overflow-hidden rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)]",
|
|
21
|
+
className
|
|
22
|
+
),
|
|
23
|
+
children: [
|
|
24
|
+
showLanguage && language ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-[var(--as-border)] px-3 py-1 font-sans text-[10px] font-medium uppercase tracking-wide text-[var(--as-muted-fg)]", children: [
|
|
25
|
+
/* @__PURE__ */ jsx("span", { children: language }),
|
|
26
|
+
/* @__PURE__ */ jsx(CopyButton, { value: code, label: copyLabel, className: "opacity-60 transition-opacity group-hover/code:opacity-100" })
|
|
27
|
+
] }) : /* @__PURE__ */ jsx(
|
|
28
|
+
CopyButton,
|
|
29
|
+
{
|
|
30
|
+
value: code,
|
|
31
|
+
label: copyLabel,
|
|
32
|
+
className: "absolute right-2 top-2 opacity-0 transition-opacity focus-visible:opacity-100 group-hover/code:opacity-100"
|
|
33
|
+
}
|
|
34
|
+
),
|
|
35
|
+
/* @__PURE__ */ jsx("pre", { className: cn("overflow-x-auto p-3 font-mono text-xs leading-relaxed", !showLanguage && "pt-3"), children: /* @__PURE__ */ jsx("code", { "aria-label": language ? `${language} ${codeLabel}` : codeLabel, children: code }) })
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
var mermaidInitialized = false;
|
|
42
|
+
async function renderMermaid(id, code, theme) {
|
|
43
|
+
const mermaid = (await import('mermaid')).default;
|
|
44
|
+
if (!mermaidInitialized) {
|
|
45
|
+
mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme });
|
|
46
|
+
mermaidInitialized = true;
|
|
47
|
+
}
|
|
48
|
+
const { svg } = await mermaid.render(id, code);
|
|
49
|
+
return svg;
|
|
50
|
+
}
|
|
51
|
+
function extractText(node) {
|
|
52
|
+
if (node === null || node === void 0 || typeof node === "boolean") {
|
|
53
|
+
return "";
|
|
54
|
+
}
|
|
55
|
+
if (typeof node === "string" || typeof node === "number") {
|
|
56
|
+
return String(node);
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(node)) {
|
|
59
|
+
return node.map(extractText).join("");
|
|
60
|
+
}
|
|
61
|
+
if (React3.isValidElement(node)) {
|
|
62
|
+
return extractText(node.props.children);
|
|
63
|
+
}
|
|
64
|
+
return "";
|
|
65
|
+
}
|
|
66
|
+
var MermaidDiagram = React3.forwardRef(
|
|
67
|
+
function MermaidDiagram2({ code, theme = "neutral", labels, className }, ref) {
|
|
68
|
+
const reactId = React3.useId().replace(/[^a-zA-Z0-9]/g, "");
|
|
69
|
+
const [svg, setSvg] = React3.useState(null);
|
|
70
|
+
const [failed, setFailed] = React3.useState(false);
|
|
71
|
+
React3.useEffect(() => {
|
|
72
|
+
let cancelled = false;
|
|
73
|
+
setFailed(false);
|
|
74
|
+
setSvg(null);
|
|
75
|
+
renderMermaid(`as-mermaid-${reactId}`, code, theme).then((result) => {
|
|
76
|
+
if (!cancelled) {
|
|
77
|
+
setSvg(result);
|
|
78
|
+
}
|
|
79
|
+
}).catch(() => {
|
|
80
|
+
if (!cancelled) {
|
|
81
|
+
setFailed(true);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return () => {
|
|
85
|
+
cancelled = true;
|
|
86
|
+
};
|
|
87
|
+
}, [code, theme, reactId]);
|
|
88
|
+
if (failed || svg === null) {
|
|
89
|
+
return /* @__PURE__ */ jsx(
|
|
90
|
+
MarkdownCodeBlock,
|
|
91
|
+
{
|
|
92
|
+
ref: failed ? ref : void 0,
|
|
93
|
+
code,
|
|
94
|
+
language: "mermaid",
|
|
95
|
+
labels: { code: labels?.diagram ?? "Diagram" },
|
|
96
|
+
className: cn("my-3", svg === null && !failed ? "opacity-60" : void 0, className)
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return /* @__PURE__ */ jsx(
|
|
101
|
+
"div",
|
|
102
|
+
{
|
|
103
|
+
ref,
|
|
104
|
+
"data-as": "mermaid-diagram",
|
|
105
|
+
className: cn(
|
|
106
|
+
"my-3 flex justify-center overflow-x-auto rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-3 [&_svg]:max-w-full",
|
|
107
|
+
className
|
|
108
|
+
),
|
|
109
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
var fenceLanguage = (className) => /language-([\w+-]+)/.exec(className ?? "")?.[1];
|
|
115
|
+
var MarkdownSurface = React3.memo(
|
|
116
|
+
React3.forwardRef(function MarkdownSurface2({
|
|
117
|
+
value,
|
|
118
|
+
streaming = false,
|
|
119
|
+
gfm = true,
|
|
120
|
+
math = true,
|
|
121
|
+
mermaid = true,
|
|
122
|
+
mermaidTheme = "neutral",
|
|
123
|
+
components,
|
|
124
|
+
urlTransform = defaultUrlTransform,
|
|
125
|
+
showCodeLanguage = true,
|
|
126
|
+
labels,
|
|
127
|
+
className
|
|
128
|
+
}, ref) {
|
|
129
|
+
const mermaidEnabled = mermaid && !streaming;
|
|
130
|
+
const defaultComponents = React3.useMemo(
|
|
131
|
+
() => ({
|
|
132
|
+
pre: ({ children }) => {
|
|
133
|
+
const child = Array.isArray(children) ? children[0] : children;
|
|
134
|
+
if (React3.isValidElement(child)) {
|
|
135
|
+
const childProps = child.props;
|
|
136
|
+
const text = extractText(childProps.children).replace(/\n$/, "");
|
|
137
|
+
const language = fenceLanguage(childProps.className);
|
|
138
|
+
if (language === "mermaid" && mermaidEnabled) {
|
|
139
|
+
return /* @__PURE__ */ jsx(MermaidDiagram, { code: text, theme: mermaidTheme, labels: { diagram: labels?.code } });
|
|
140
|
+
}
|
|
141
|
+
return /* @__PURE__ */ jsx(MarkdownCodeBlock, { code: text, language, showLanguage: showCodeLanguage, labels });
|
|
142
|
+
}
|
|
143
|
+
return /* @__PURE__ */ jsx("pre", { children });
|
|
144
|
+
},
|
|
145
|
+
code: ({ className: codeClassName, children, ...rest }) => /* @__PURE__ */ jsx(
|
|
146
|
+
"code",
|
|
147
|
+
{
|
|
148
|
+
className: cn(
|
|
149
|
+
"rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] px-1 py-0.5 font-mono text-[0.85em]",
|
|
150
|
+
codeClassName
|
|
151
|
+
),
|
|
152
|
+
...rest,
|
|
153
|
+
children
|
|
154
|
+
}
|
|
155
|
+
),
|
|
156
|
+
a: ({ href, children, ...rest }) => {
|
|
157
|
+
const external = typeof href === "string" && (href.startsWith("http://") || href.startsWith("https://"));
|
|
158
|
+
return /* @__PURE__ */ jsx(
|
|
159
|
+
"a",
|
|
160
|
+
{
|
|
161
|
+
href,
|
|
162
|
+
className: "text-[var(--as-primary)] underline underline-offset-2",
|
|
163
|
+
...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
164
|
+
...rest,
|
|
165
|
+
children
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
},
|
|
169
|
+
table: ({ children, ...rest }) => /* @__PURE__ */ jsx("div", { className: "my-3 overflow-x-auto rounded-[var(--as-radius)] border border-[var(--as-border)]", children: /* @__PURE__ */ jsx("table", { className: "w-full border-collapse text-[0.875em]", ...rest, children }) }),
|
|
170
|
+
img: ({ alt, ...rest }) => /* @__PURE__ */ jsx("img", { alt: alt ?? "", className: "my-2 max-w-full rounded-[var(--as-radius)]", loading: "lazy", ...rest })
|
|
171
|
+
}),
|
|
172
|
+
[labels, mermaidEnabled, mermaidTheme, showCodeLanguage]
|
|
173
|
+
);
|
|
174
|
+
const mergedComponents = React3.useMemo(
|
|
175
|
+
() => ({ ...defaultComponents, ...components }),
|
|
176
|
+
[defaultComponents, components]
|
|
177
|
+
);
|
|
178
|
+
const remarkPlugins = React3.useMemo(
|
|
179
|
+
() => [gfm ? remarkGfm : null, math ? remarkMath : null].filter((plugin) => plugin !== null),
|
|
180
|
+
[gfm, math]
|
|
181
|
+
);
|
|
182
|
+
const rehypePlugins = React3.useMemo(
|
|
183
|
+
() => math ? [[rehypeKatex, { strict: false, throwOnError: false, output: "html" }]] : [],
|
|
184
|
+
[math]
|
|
185
|
+
);
|
|
186
|
+
return /* @__PURE__ */ jsx("div", { ref, "data-as": "chat-markdown", className: cn("min-w-0 text-[var(--as-fg)]", className), children: /* @__PURE__ */ jsx(
|
|
187
|
+
ReactMarkdown,
|
|
188
|
+
{
|
|
189
|
+
remarkPlugins,
|
|
190
|
+
rehypePlugins,
|
|
191
|
+
components: mergedComponents,
|
|
192
|
+
urlTransform,
|
|
193
|
+
children: value
|
|
194
|
+
}
|
|
195
|
+
) });
|
|
196
|
+
})
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
export { MarkdownCodeBlock, MarkdownSurface, MermaidDiagram };
|
|
200
|
+
//# sourceMappingURL=chunk-DZBTJZZV.js.map
|
|
201
|
+
//# sourceMappingURL=chunk-DZBTJZZV.js.map
|