@shapesos/clay 0.4.0 → 0.4.1
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/chat.cjs +84 -354
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.d.cts +13 -24
- package/dist/chat.d.ts +13 -24
- package/dist/chat.js +10 -4
- package/dist/chunk-72TJUKMV.js +1 -0
- package/dist/{chunk-P7NISN4V.js → chunk-AEXYOY5H.js} +11 -11
- package/dist/chunk-AEXYOY5H.js.map +1 -0
- package/dist/{chunk-UKM5VQKW.js → chunk-BIATJTD4.js} +5 -5
- package/dist/chunk-BIATJTD4.js.map +1 -0
- package/dist/chunk-EPS4LOOW.js +339 -0
- package/dist/chunk-EPS4LOOW.js.map +1 -0
- package/dist/icon.cjs +12 -12
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.js +2 -2
- package/dist/index.cjs +162 -386
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -5
- package/dist/index.d.ts +14 -5
- package/dist/index.js +69 -19
- package/dist/index.js.map +1 -1
- package/dist/lottie.cjs +5 -5
- package/dist/lottie.cjs.map +1 -1
- package/dist/lottie.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2GFOESHR.js +0 -613
- package/dist/chunk-2GFOESHR.js.map +0 -1
- package/dist/chunk-7AJSQJQ5.js +0 -1
- package/dist/chunk-P7NISN4V.js.map +0 -1
- package/dist/chunk-UKM5VQKW.js.map +0 -1
- /package/dist/{chunk-7AJSQJQ5.js.map → chunk-72TJUKMV.js.map} +0 -0
package/dist/lottie.js
CHANGED
package/package.json
CHANGED
package/dist/chunk-2GFOESHR.js
DELETED
|
@@ -1,613 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
typographyMixin,
|
|
3
|
-
typographyTypes
|
|
4
|
-
} from "./chunk-A6DKIFWS.js";
|
|
5
|
-
import {
|
|
6
|
-
Icon,
|
|
7
|
-
IconButton
|
|
8
|
-
} from "./chunk-P7NISN4V.js";
|
|
9
|
-
import {
|
|
10
|
-
colors
|
|
11
|
-
} from "./chunk-6HNZQ2BF.js";
|
|
12
|
-
|
|
13
|
-
// src/chat/chat-root/chat-root.tsx
|
|
14
|
-
import { useMemo } from "react";
|
|
15
|
-
|
|
16
|
-
// src/chat/chat-context/chat-context.ts
|
|
17
|
-
import { createContext, useContext } from "react";
|
|
18
|
-
var ChatContext = createContext(null);
|
|
19
|
-
function useChatContext() {
|
|
20
|
-
const context = useContext(ChatContext);
|
|
21
|
-
if (!context) {
|
|
22
|
-
throw new Error("useChatContext must be used within a Chat.Root component");
|
|
23
|
-
}
|
|
24
|
-
return context;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// src/chat/chat-root/chat-root-styles.ts
|
|
28
|
-
import styled from "styled-components";
|
|
29
|
-
var RootContainer = styled.div`
|
|
30
|
-
display: flex;
|
|
31
|
-
flex-direction: column;
|
|
32
|
-
height: 100%;
|
|
33
|
-
overflow: hidden;
|
|
34
|
-
`;
|
|
35
|
-
|
|
36
|
-
// src/chat/chat-root/chat-root.tsx
|
|
37
|
-
import { jsx } from "react/jsx-runtime";
|
|
38
|
-
function ChatRoot({
|
|
39
|
-
messages,
|
|
40
|
-
onSendMessage,
|
|
41
|
-
isLoading = false,
|
|
42
|
-
onStop,
|
|
43
|
-
onCopyMessage,
|
|
44
|
-
onThumbUpClick,
|
|
45
|
-
onThumbDownClick,
|
|
46
|
-
children
|
|
47
|
-
}) {
|
|
48
|
-
const contextValue = useMemo(
|
|
49
|
-
() => ({ messages, onSendMessage, isLoading, onStop, onCopyMessage, onThumbUpClick, onThumbDownClick }),
|
|
50
|
-
[messages, onSendMessage, isLoading, onStop, onCopyMessage, onThumbUpClick, onThumbDownClick]
|
|
51
|
-
);
|
|
52
|
-
return /* @__PURE__ */ jsx(ChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(RootContainer, { children }) });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// src/chat/chat-message-content/chat-message-content.tsx
|
|
56
|
-
import ReactMarkdown from "react-markdown";
|
|
57
|
-
import remarkGfm from "remark-gfm";
|
|
58
|
-
|
|
59
|
-
// src/chat/chat-message-content/chat-message-content-styles.ts
|
|
60
|
-
import styled2 from "styled-components";
|
|
61
|
-
var ContentWrapper = styled2.div`
|
|
62
|
-
${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
|
|
63
|
-
color: ${colors["brown-100"]};
|
|
64
|
-
word-break: break-word;
|
|
65
|
-
|
|
66
|
-
& p {
|
|
67
|
-
margin: 0;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
& p + p {
|
|
71
|
-
margin-top: 8px;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
& ul,
|
|
75
|
-
& ol {
|
|
76
|
-
margin: 4px 0;
|
|
77
|
-
padding-left: 20px;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
& a {
|
|
81
|
-
color: ${colors["brown-100"]};
|
|
82
|
-
text-decoration: underline;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
& pre {
|
|
86
|
-
overflow-x: auto;
|
|
87
|
-
padding: 8px;
|
|
88
|
-
margin: 4px 0;
|
|
89
|
-
background: ${colors["brown-10"]};
|
|
90
|
-
border: 1px solid ${colors["brown-alpha-12"]};
|
|
91
|
-
border-radius: 8px;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
& pre code {
|
|
95
|
-
padding: 0;
|
|
96
|
-
background: none;
|
|
97
|
-
border-radius: 0;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
& code {
|
|
101
|
-
padding: 2px 4px;
|
|
102
|
-
background: ${colors["brown-10"]};
|
|
103
|
-
border-radius: 4px;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
& table {
|
|
107
|
-
border-collapse: collapse;
|
|
108
|
-
margin: 8px 0;
|
|
109
|
-
width: 100%;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
& th,
|
|
113
|
-
& td {
|
|
114
|
-
border: 1px solid ${colors["brown-alpha-12"]};
|
|
115
|
-
padding: 6px 12px;
|
|
116
|
-
text-align: left;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
& th {
|
|
120
|
-
background: ${colors["brown-10"]};
|
|
121
|
-
font-weight: 600;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
& blockquote {
|
|
125
|
-
margin: 4px 0;
|
|
126
|
-
padding-left: 12px;
|
|
127
|
-
border-left: 3px solid ${colors["brown-30"]};
|
|
128
|
-
color: ${colors["brown-70"]};
|
|
129
|
-
}
|
|
130
|
-
`;
|
|
131
|
-
|
|
132
|
-
// src/chat/chat-message-content/chat-message-content.tsx
|
|
133
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
134
|
-
function ChatMessageContent({ content }) {
|
|
135
|
-
return /* @__PURE__ */ jsx2(ContentWrapper, { children: /* @__PURE__ */ jsx2(ReactMarkdown, { remarkPlugins: [remarkGfm], children: content }) });
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// src/chat/chat-message-actions/chat-message-actions.tsx
|
|
139
|
-
import { useCallback as useCallback2 } from "react";
|
|
140
|
-
|
|
141
|
-
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
142
|
-
import { forwardRef, createElement } from "react";
|
|
143
|
-
|
|
144
|
-
// node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs
|
|
145
|
-
var defaultAttributes = {
|
|
146
|
-
outline: {
|
|
147
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
148
|
-
width: 24,
|
|
149
|
-
height: 24,
|
|
150
|
-
viewBox: "0 0 24 24",
|
|
151
|
-
fill: "none",
|
|
152
|
-
stroke: "currentColor",
|
|
153
|
-
strokeWidth: 2,
|
|
154
|
-
strokeLinecap: "round",
|
|
155
|
-
strokeLinejoin: "round"
|
|
156
|
-
},
|
|
157
|
-
filled: {
|
|
158
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
159
|
-
width: 24,
|
|
160
|
-
height: 24,
|
|
161
|
-
viewBox: "0 0 24 24",
|
|
162
|
-
fill: "currentColor",
|
|
163
|
-
stroke: "none"
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
168
|
-
var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
169
|
-
const Component = forwardRef(
|
|
170
|
-
({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => createElement(
|
|
171
|
-
"svg",
|
|
172
|
-
{
|
|
173
|
-
ref,
|
|
174
|
-
...defaultAttributes[type],
|
|
175
|
-
width: size,
|
|
176
|
-
height: size,
|
|
177
|
-
className: [`tabler-icon`, `tabler-icon-${iconName}`, className].join(" "),
|
|
178
|
-
...type === "filled" ? {
|
|
179
|
-
fill: color
|
|
180
|
-
} : {
|
|
181
|
-
strokeWidth: stroke,
|
|
182
|
-
stroke: color
|
|
183
|
-
},
|
|
184
|
-
...rest
|
|
185
|
-
},
|
|
186
|
-
[
|
|
187
|
-
title && createElement("title", { key: "svg-title" }, title),
|
|
188
|
-
...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
|
|
189
|
-
...Array.isArray(children) ? children : [children]
|
|
190
|
-
]
|
|
191
|
-
)
|
|
192
|
-
);
|
|
193
|
-
Component.displayName = `${iconNamePascal}`;
|
|
194
|
-
return Component;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconArrowUp.mjs
|
|
198
|
-
var __iconNode = [["path", { "d": "M12 5l0 14", "key": "svg-0" }], ["path", { "d": "M18 11l-6 -6", "key": "svg-1" }], ["path", { "d": "M6 11l6 -6", "key": "svg-2" }]];
|
|
199
|
-
var IconArrowUp = createReactComponent("outline", "arrow-up", "ArrowUp", __iconNode);
|
|
200
|
-
|
|
201
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
|
|
202
|
-
var __iconNode2 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
|
|
203
|
-
var IconCheck = createReactComponent("outline", "check", "Check", __iconNode2);
|
|
204
|
-
|
|
205
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
|
|
206
|
-
var __iconNode3 = [["path", { "d": "M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666", "key": "svg-0" }], ["path", { "d": "M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1", "key": "svg-1" }]];
|
|
207
|
-
var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode3);
|
|
208
|
-
|
|
209
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
|
|
210
|
-
var __iconNode4 = [["path", { "d": "M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3", "key": "svg-0" }]];
|
|
211
|
-
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode4);
|
|
212
|
-
|
|
213
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
|
|
214
|
-
var __iconNode5 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3", "key": "svg-0" }]];
|
|
215
|
-
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode5);
|
|
216
|
-
|
|
217
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconPlayerStopFilled.mjs
|
|
218
|
-
var __iconNode6 = [["path", { "d": "M17 4h-10a3 3 0 0 0 -3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3 -3v-10a3 3 0 0 0 -3 -3z", "key": "svg-0" }]];
|
|
219
|
-
var IconPlayerStopFilled = createReactComponent("filled", "player-stop-filled", "PlayerStopFilled", __iconNode6);
|
|
220
|
-
|
|
221
|
-
// src/chat/hooks/use-copy-to-clipboard.ts
|
|
222
|
-
import { useState, useCallback, useRef, useEffect } from "react";
|
|
223
|
-
|
|
224
|
-
// src/utils/clipboard.ts
|
|
225
|
-
function copyToClipboard(text, options) {
|
|
226
|
-
navigator.clipboard.writeText(text).then(
|
|
227
|
-
() => options?.onSuccess?.(),
|
|
228
|
-
(error) => options?.onFailure?.(error)
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// src/chat/hooks/use-copy-to-clipboard.ts
|
|
233
|
-
var RESET_DELAY_MS = 2e3;
|
|
234
|
-
function useCopyToClipboard() {
|
|
235
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
236
|
-
const timeoutRef = useRef(null);
|
|
237
|
-
useEffect(() => {
|
|
238
|
-
return () => {
|
|
239
|
-
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
240
|
-
};
|
|
241
|
-
}, []);
|
|
242
|
-
const copy = useCallback((text) => {
|
|
243
|
-
copyToClipboard(text, {
|
|
244
|
-
onSuccess: () => {
|
|
245
|
-
setIsCopied(true);
|
|
246
|
-
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
247
|
-
timeoutRef.current = setTimeout(() => {
|
|
248
|
-
setIsCopied(false);
|
|
249
|
-
timeoutRef.current = null;
|
|
250
|
-
}, RESET_DELAY_MS);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
}, []);
|
|
254
|
-
return { isCopied, copy };
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// src/chat/chat-message-actions/chat-message-actions-styles.ts
|
|
258
|
-
import styled3 from "styled-components";
|
|
259
|
-
var ActionsContainer = styled3.div`
|
|
260
|
-
display: flex;
|
|
261
|
-
gap: 2px;
|
|
262
|
-
margin-top: 4px;
|
|
263
|
-
opacity: 0;
|
|
264
|
-
pointer-events: none;
|
|
265
|
-
transition: opacity 150ms ease;
|
|
266
|
-
`;
|
|
267
|
-
|
|
268
|
-
// src/chat/chat-message-actions/chat-message-actions.tsx
|
|
269
|
-
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
270
|
-
function ChatMessageActions({ messageId, content, role, isHelpful }) {
|
|
271
|
-
const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
|
|
272
|
-
const { isCopied, copy } = useCopyToClipboard();
|
|
273
|
-
const handleCopy = useCallback2(() => {
|
|
274
|
-
copy(content);
|
|
275
|
-
onCopyMessage?.(messageId);
|
|
276
|
-
}, [content, messageId, copy, onCopyMessage]);
|
|
277
|
-
const handleThumbUp = useCallback2(() => {
|
|
278
|
-
onThumbUpClick?.(messageId, isHelpful === true ? null : true);
|
|
279
|
-
}, [messageId, isHelpful, onThumbUpClick]);
|
|
280
|
-
const handleThumbDown = useCallback2(() => {
|
|
281
|
-
onThumbDownClick?.(messageId, isHelpful === false ? null : false);
|
|
282
|
-
}, [messageId, isHelpful, onThumbDownClick]);
|
|
283
|
-
const isAssistant = role === "assistant";
|
|
284
|
-
const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
|
|
285
|
-
return /* @__PURE__ */ jsxs(ActionsContainer, { children: [
|
|
286
|
-
/* @__PURE__ */ jsx3(
|
|
287
|
-
IconButton,
|
|
288
|
-
{
|
|
289
|
-
icon: isCopied ? IconCheck : IconCopy,
|
|
290
|
-
onClick: handleCopy,
|
|
291
|
-
"aria-label": isCopied ? "Copied" : "Copy message"
|
|
292
|
-
}
|
|
293
|
-
),
|
|
294
|
-
hasFeedback && /* @__PURE__ */ jsx3(
|
|
295
|
-
IconButton,
|
|
296
|
-
{
|
|
297
|
-
icon: IconThumbUp,
|
|
298
|
-
onClick: handleThumbUp,
|
|
299
|
-
isSelected: isHelpful === true,
|
|
300
|
-
"aria-label": "Good response"
|
|
301
|
-
}
|
|
302
|
-
),
|
|
303
|
-
hasFeedback && /* @__PURE__ */ jsx3(
|
|
304
|
-
IconButton,
|
|
305
|
-
{
|
|
306
|
-
icon: IconThumbDown,
|
|
307
|
-
onClick: handleThumbDown,
|
|
308
|
-
isSelected: isHelpful === false,
|
|
309
|
-
"aria-label": "Bad response"
|
|
310
|
-
}
|
|
311
|
-
)
|
|
312
|
-
] });
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// src/chat/chat-message/chat-message-styles.ts
|
|
316
|
-
import styled4 from "styled-components";
|
|
317
|
-
var MessageRow = styled4.div`
|
|
318
|
-
display: flex;
|
|
319
|
-
justify-content: ${({ $role }) => $role === "user" ? "flex-end" : "flex-start"};
|
|
320
|
-
`;
|
|
321
|
-
var MessageContainer = styled4.div`
|
|
322
|
-
display: flex;
|
|
323
|
-
flex-direction: column;
|
|
324
|
-
align-items: ${({ $role }) => $role === "user" ? "flex-end" : "flex-start"};
|
|
325
|
-
max-width: 90%;
|
|
326
|
-
|
|
327
|
-
&:hover ${ActionsContainer} {
|
|
328
|
-
opacity: 1;
|
|
329
|
-
pointer-events: auto;
|
|
330
|
-
}
|
|
331
|
-
`;
|
|
332
|
-
var MessageBubble = styled4.div`
|
|
333
|
-
${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
|
|
334
|
-
color: ${colors["brown-100"]};
|
|
335
|
-
background: ${({ $role }) => $role === "user" ? colors.white : "transparent"};
|
|
336
|
-
padding: ${({ $role }) => $role === "user" ? "12px 16px" : "0"};
|
|
337
|
-
border-radius: ${({ $role }) => $role === "user" ? "16px" : "0"};
|
|
338
|
-
`;
|
|
339
|
-
|
|
340
|
-
// src/chat/chat-message/chat-message.tsx
|
|
341
|
-
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
342
|
-
function ChatMessage({ message }) {
|
|
343
|
-
return /* @__PURE__ */ jsx4(MessageRow, { $role: message.role, children: /* @__PURE__ */ jsxs2(MessageContainer, { $role: message.role, children: [
|
|
344
|
-
/* @__PURE__ */ jsx4(MessageBubble, { $role: message.role, children: /* @__PURE__ */ jsx4(ChatMessageContent, { content: message.content }) }),
|
|
345
|
-
/* @__PURE__ */ jsx4(
|
|
346
|
-
ChatMessageActions,
|
|
347
|
-
{
|
|
348
|
-
messageId: message.id,
|
|
349
|
-
content: message.content,
|
|
350
|
-
role: message.role,
|
|
351
|
-
isHelpful: message.isHelpful
|
|
352
|
-
}
|
|
353
|
-
)
|
|
354
|
-
] }) });
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// src/chat/hooks/use-auto-scroll.ts
|
|
358
|
-
import { useRef as useRef2, useState as useState2, useEffect as useEffect2, useLayoutEffect, useCallback as useCallback3 } from "react";
|
|
359
|
-
function useAutoScroll(messageCount) {
|
|
360
|
-
const scrollContainerRef = useRef2(null);
|
|
361
|
-
const sentinelRef = useRef2(null);
|
|
362
|
-
const [isAtBottom, setIsAtBottom] = useState2(true);
|
|
363
|
-
const prevMessageCountRef = useRef2(messageCount);
|
|
364
|
-
const hasInitializedRef = useRef2(false);
|
|
365
|
-
useLayoutEffect(() => {
|
|
366
|
-
const el = scrollContainerRef.current;
|
|
367
|
-
if (el) {
|
|
368
|
-
el.scrollTop = el.scrollHeight;
|
|
369
|
-
}
|
|
370
|
-
}, []);
|
|
371
|
-
useEffect2(() => {
|
|
372
|
-
if (!hasInitializedRef.current) {
|
|
373
|
-
hasInitializedRef.current = true;
|
|
374
|
-
requestAnimationFrame(() => {
|
|
375
|
-
const el = scrollContainerRef.current;
|
|
376
|
-
if (el) {
|
|
377
|
-
el.scrollTop = el.scrollHeight;
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
}, []);
|
|
382
|
-
useEffect2(() => {
|
|
383
|
-
const sentinel = sentinelRef.current;
|
|
384
|
-
const scrollContainer = scrollContainerRef.current;
|
|
385
|
-
if (!sentinel || !scrollContainer) return;
|
|
386
|
-
const observer = new IntersectionObserver(
|
|
387
|
-
([entry]) => {
|
|
388
|
-
setIsAtBottom(entry.isIntersecting);
|
|
389
|
-
},
|
|
390
|
-
{ root: scrollContainer, threshold: 0 }
|
|
391
|
-
);
|
|
392
|
-
observer.observe(sentinel);
|
|
393
|
-
return () => observer.disconnect();
|
|
394
|
-
}, []);
|
|
395
|
-
useEffect2(() => {
|
|
396
|
-
if (!hasInitializedRef.current) return;
|
|
397
|
-
if (messageCount > prevMessageCountRef.current) {
|
|
398
|
-
requestAnimationFrame(() => {
|
|
399
|
-
const el = scrollContainerRef.current;
|
|
400
|
-
if (el) {
|
|
401
|
-
el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
prevMessageCountRef.current = messageCount;
|
|
406
|
-
}, [messageCount]);
|
|
407
|
-
const scrollToBottom = useCallback3(() => {
|
|
408
|
-
const el = scrollContainerRef.current;
|
|
409
|
-
if (el) {
|
|
410
|
-
el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
|
|
411
|
-
}
|
|
412
|
-
}, []);
|
|
413
|
-
return { scrollContainerRef, sentinelRef, isAtBottom, scrollToBottom };
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// src/chat/chat-message-list/chat-message-list-styles.ts
|
|
417
|
-
import styled5 from "styled-components";
|
|
418
|
-
var ListContainer = styled5.div`
|
|
419
|
-
display: flex;
|
|
420
|
-
flex-direction: column;
|
|
421
|
-
flex: 1;
|
|
422
|
-
overflow-y: auto;
|
|
423
|
-
|
|
424
|
-
&::-webkit-scrollbar {
|
|
425
|
-
width: 6px;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
&::-webkit-scrollbar-track {
|
|
429
|
-
background: transparent;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
&::-webkit-scrollbar-thumb {
|
|
433
|
-
background: ${colors["brown-30"]};
|
|
434
|
-
border-radius: 3px;
|
|
435
|
-
}
|
|
436
|
-
`;
|
|
437
|
-
var MessagesList = styled5.div`
|
|
438
|
-
display: flex;
|
|
439
|
-
flex-direction: column;
|
|
440
|
-
gap: 40px;
|
|
441
|
-
padding: 0 16px 32px 16px;
|
|
442
|
-
`;
|
|
443
|
-
var ScrollSentinel = styled5.div`
|
|
444
|
-
flex-shrink: 0;
|
|
445
|
-
height: 16px;
|
|
446
|
-
`;
|
|
447
|
-
|
|
448
|
-
// src/chat/chat-message-list/chat-message-list.tsx
|
|
449
|
-
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
450
|
-
function ChatMessageList() {
|
|
451
|
-
const { messages } = useChatContext();
|
|
452
|
-
const { scrollContainerRef, sentinelRef } = useAutoScroll(messages.length);
|
|
453
|
-
return /* @__PURE__ */ jsxs3(ListContainer, { ref: scrollContainerRef, "data-testid": "chat-list-container", children: [
|
|
454
|
-
/* @__PURE__ */ jsx5(MessagesList, { children: messages.map((message) => /* @__PURE__ */ jsx5(ChatMessage, { message }, message.id)) }),
|
|
455
|
-
/* @__PURE__ */ jsx5(ScrollSentinel, { ref: sentinelRef, "data-testid": "chat-scroll-sentinel" })
|
|
456
|
-
] });
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// src/chat/chat-composer/chat-composer.tsx
|
|
460
|
-
import { useState as useState3, useCallback as useCallback4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
461
|
-
|
|
462
|
-
// src/chat/chat-composer/chat-composer-styles.ts
|
|
463
|
-
import styled6 from "styled-components";
|
|
464
|
-
var ComposerContainer = styled6.div`
|
|
465
|
-
position: relative;
|
|
466
|
-
background: ${colors.white};
|
|
467
|
-
border-radius: 12px;
|
|
468
|
-
box-shadow: 0 0 4px 0 ${colors["brown-alpha-12"]};
|
|
469
|
-
padding: 8px 0;
|
|
470
|
-
`;
|
|
471
|
-
var TextArea = styled6.textarea`
|
|
472
|
-
display: block;
|
|
473
|
-
width: 100%;
|
|
474
|
-
resize: none;
|
|
475
|
-
border: none;
|
|
476
|
-
background: transparent;
|
|
477
|
-
${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
|
|
478
|
-
color: ${colors["brown-90"]};
|
|
479
|
-
padding: 4px 46px 4px 16px;
|
|
480
|
-
min-height: 20px;
|
|
481
|
-
max-height: 200px;
|
|
482
|
-
overflow-y: auto;
|
|
483
|
-
box-sizing: border-box;
|
|
484
|
-
|
|
485
|
-
&::placeholder {
|
|
486
|
-
color: ${colors["brown-60"]};
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
&:focus {
|
|
490
|
-
outline: none;
|
|
491
|
-
}
|
|
492
|
-
`;
|
|
493
|
-
var SendButton = styled6.button`
|
|
494
|
-
position: absolute;
|
|
495
|
-
bottom: 8px;
|
|
496
|
-
right: 8px;
|
|
497
|
-
width: 30px;
|
|
498
|
-
height: 30px;
|
|
499
|
-
border: none;
|
|
500
|
-
border-radius: 12px;
|
|
501
|
-
cursor: pointer;
|
|
502
|
-
display: flex;
|
|
503
|
-
align-items: center;
|
|
504
|
-
justify-content: center;
|
|
505
|
-
background: ${colors["brown-100"]};
|
|
506
|
-
color: ${colors.white};
|
|
507
|
-
transition: background-color 75ms;
|
|
508
|
-
padding: 0;
|
|
509
|
-
|
|
510
|
-
&:disabled {
|
|
511
|
-
background: ${colors["brown-50"]};
|
|
512
|
-
cursor: default;
|
|
513
|
-
}
|
|
514
|
-
`;
|
|
515
|
-
|
|
516
|
-
// src/chat/chat-composer/chat-composer.tsx
|
|
517
|
-
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
518
|
-
function ChatComposer({ placeholder = "Type a message..." }) {
|
|
519
|
-
const { onSendMessage, isLoading, onStop } = useChatContext();
|
|
520
|
-
const [value, setValue] = useState3("");
|
|
521
|
-
const textAreaRef = useRef3(null);
|
|
522
|
-
const isEmpty = value.trim().length === 0;
|
|
523
|
-
const resizeTextArea = useCallback4(() => {
|
|
524
|
-
const el = textAreaRef.current;
|
|
525
|
-
if (!el) return;
|
|
526
|
-
el.style.height = "auto";
|
|
527
|
-
el.style.height = `${el.scrollHeight}px`;
|
|
528
|
-
}, []);
|
|
529
|
-
useEffect3(() => {
|
|
530
|
-
resizeTextArea();
|
|
531
|
-
}, [value, resizeTextArea]);
|
|
532
|
-
useEffect3(() => {
|
|
533
|
-
textAreaRef.current?.focus();
|
|
534
|
-
}, []);
|
|
535
|
-
const handleSend = useCallback4(() => {
|
|
536
|
-
const trimmed = value.trim();
|
|
537
|
-
if (!trimmed) return;
|
|
538
|
-
onSendMessage(trimmed);
|
|
539
|
-
setValue("");
|
|
540
|
-
requestAnimationFrame(() => textAreaRef.current?.focus());
|
|
541
|
-
}, [value, onSendMessage]);
|
|
542
|
-
const handleKeyDown = useCallback4(
|
|
543
|
-
(e) => {
|
|
544
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
545
|
-
e.preventDefault();
|
|
546
|
-
handleSend();
|
|
547
|
-
}
|
|
548
|
-
},
|
|
549
|
-
[handleSend]
|
|
550
|
-
);
|
|
551
|
-
const handleChange = useCallback4((e) => {
|
|
552
|
-
setValue(e.target.value);
|
|
553
|
-
}, []);
|
|
554
|
-
const handleButtonClick = useCallback4(() => {
|
|
555
|
-
if (isLoading && onStop) {
|
|
556
|
-
onStop();
|
|
557
|
-
} else {
|
|
558
|
-
handleSend();
|
|
559
|
-
}
|
|
560
|
-
}, [isLoading, onStop, handleSend]);
|
|
561
|
-
return /* @__PURE__ */ jsxs4(ComposerContainer, { children: [
|
|
562
|
-
/* @__PURE__ */ jsx6(
|
|
563
|
-
TextArea,
|
|
564
|
-
{
|
|
565
|
-
ref: textAreaRef,
|
|
566
|
-
value,
|
|
567
|
-
onChange: handleChange,
|
|
568
|
-
onKeyDown: handleKeyDown,
|
|
569
|
-
placeholder,
|
|
570
|
-
rows: 1
|
|
571
|
-
}
|
|
572
|
-
),
|
|
573
|
-
/* @__PURE__ */ jsx6(
|
|
574
|
-
SendButton,
|
|
575
|
-
{
|
|
576
|
-
onClick: handleButtonClick,
|
|
577
|
-
disabled: !isLoading && isEmpty,
|
|
578
|
-
"aria-label": isLoading ? "Stop generating" : "Send message",
|
|
579
|
-
children: isLoading ? /* @__PURE__ */ jsx6(Icon, { icon: IconPlayerStopFilled, size: 16 }) : /* @__PURE__ */ jsx6(Icon, { icon: IconArrowUp, size: 16 })
|
|
580
|
-
}
|
|
581
|
-
)
|
|
582
|
-
] });
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
// src/chat/chat-namespace.ts
|
|
586
|
-
var Chat = {
|
|
587
|
-
Root: ChatRoot,
|
|
588
|
-
MessageList: ChatMessageList,
|
|
589
|
-
Composer: ChatComposer
|
|
590
|
-
};
|
|
591
|
-
|
|
592
|
-
export {
|
|
593
|
-
Chat
|
|
594
|
-
};
|
|
595
|
-
/*! Bundled license information:
|
|
596
|
-
|
|
597
|
-
@tabler/icons-react/dist/esm/defaultAttributes.mjs:
|
|
598
|
-
@tabler/icons-react/dist/esm/createReactComponent.mjs:
|
|
599
|
-
@tabler/icons-react/dist/esm/icons/IconArrowUp.mjs:
|
|
600
|
-
@tabler/icons-react/dist/esm/icons/IconCheck.mjs:
|
|
601
|
-
@tabler/icons-react/dist/esm/icons/IconCopy.mjs:
|
|
602
|
-
@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
|
|
603
|
-
@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
|
|
604
|
-
@tabler/icons-react/dist/esm/icons/IconPlayerStopFilled.mjs:
|
|
605
|
-
@tabler/icons-react/dist/esm/tabler-icons-react.mjs:
|
|
606
|
-
(**
|
|
607
|
-
* @license @tabler/icons-react v3.37.1 - MIT
|
|
608
|
-
*
|
|
609
|
-
* This source code is licensed under the MIT license.
|
|
610
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
611
|
-
*)
|
|
612
|
-
*/
|
|
613
|
-
//# sourceMappingURL=chunk-2GFOESHR.js.map
|