@px-ui/ai 1.0.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/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/assets/icons/chat-icon.tsx +18 -0
- package/dist/assets/icons/check-icon.tsx +18 -0
- package/dist/assets/icons/close-icon.tsx +19 -0
- package/dist/assets/icons/copy-icon.tsx +19 -0
- package/dist/assets/icons/debug-icon.tsx +19 -0
- package/dist/assets/icons/index.ts +11 -0
- package/dist/assets/icons/menu-icon.tsx +20 -0
- package/dist/assets/icons/new-chat-icon.tsx +19 -0
- package/dist/assets/icons/sparkles-icon.tsx +23 -0
- package/dist/assets/icons/thumbs-down-icon.tsx +19 -0
- package/dist/assets/icons/thumbs-up-icon.tsx +19 -0
- package/dist/assets/images/xandi-avatar.png +0 -0
- package/dist/chunk-BAz01cYq.js +18 -0
- package/dist/index.css +37 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +773 -0
- package/dist/index.js.map +1 -0
- package/package.json +71 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
import { t as __export } from "./chunk-BAz01cYq.js";
|
|
2
|
+
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Avatar, Button, Dialog, FileIcon, SendIcon, StopIcon, Tooltip, toast } from "@px-ui/core";
|
|
5
|
+
import ReactMarkdown from "react-markdown";
|
|
6
|
+
|
|
7
|
+
//#region src/context/xandi-context.tsx
|
|
8
|
+
const XandiContext = createContext(null);
|
|
9
|
+
function XandiProvider({ api, userId, orgId, sessionId: initialSessionId, onFeedback, children }) {
|
|
10
|
+
const [sessionId, setSessionId] = useState(initialSessionId ?? null);
|
|
11
|
+
const [messages, setMessages] = useState([]);
|
|
12
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!initialSessionId) setSessionId(crypto.randomUUID());
|
|
15
|
+
}, [initialSessionId]);
|
|
16
|
+
const sendMessage = async (text) => {
|
|
17
|
+
if (!text.trim() || isLoading) return;
|
|
18
|
+
const userMessage = {
|
|
19
|
+
id: crypto.randomUUID(),
|
|
20
|
+
role: "user",
|
|
21
|
+
content: text
|
|
22
|
+
};
|
|
23
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
24
|
+
setIsLoading(true);
|
|
25
|
+
try {
|
|
26
|
+
const data = await (await fetch(api, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: {
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
"x-org-id": orgId,
|
|
31
|
+
"x-user-id": userId
|
|
32
|
+
},
|
|
33
|
+
body: JSON.stringify({ message: text })
|
|
34
|
+
})).json();
|
|
35
|
+
if (data.success && data.response) {
|
|
36
|
+
const assistantMessage = {
|
|
37
|
+
id: crypto.randomUUID(),
|
|
38
|
+
role: "assistant",
|
|
39
|
+
content: data.response
|
|
40
|
+
};
|
|
41
|
+
setMessages((prev) => [...prev, assistantMessage]);
|
|
42
|
+
}
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error("Failed to send message:", error);
|
|
45
|
+
} finally {
|
|
46
|
+
setIsLoading(false);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const value = {
|
|
50
|
+
messages,
|
|
51
|
+
isLoading,
|
|
52
|
+
sessionId,
|
|
53
|
+
sendMessage,
|
|
54
|
+
onFeedback
|
|
55
|
+
};
|
|
56
|
+
return /* @__PURE__ */ jsx(XandiContext.Provider, {
|
|
57
|
+
value,
|
|
58
|
+
children
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function useXandi() {
|
|
62
|
+
const context = useContext(XandiContext);
|
|
63
|
+
if (!context) throw new Error("useXandi must be used within XandiProvider");
|
|
64
|
+
return context;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/components/x-main-intake.tsx
|
|
69
|
+
function XMainIntake({ placeholder = "Ask about jobs, candidates, timesheets, or anything workforce...", suggestions = [] }) {
|
|
70
|
+
const { isLoading, sendMessage } = useXandi();
|
|
71
|
+
const [input, setInput] = useState("");
|
|
72
|
+
const handleSubmit = (e) => {
|
|
73
|
+
e?.preventDefault();
|
|
74
|
+
if (input.trim() && !isLoading) {
|
|
75
|
+
sendMessage(input);
|
|
76
|
+
setInput("");
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const handleSuggestionClick = (prompt) => {
|
|
80
|
+
setInput(prompt);
|
|
81
|
+
};
|
|
82
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
83
|
+
className: "flex flex-col gap-3",
|
|
84
|
+
children: [/* @__PURE__ */ jsxs("form", {
|
|
85
|
+
onSubmit: handleSubmit,
|
|
86
|
+
className: "flex flex-col gap-2 rounded-2xl border border-ppx-neutral-5 bg-ppx-neutral-1 p-3",
|
|
87
|
+
children: [
|
|
88
|
+
/* @__PURE__ */ jsx("div", { className: "uploads-section" }),
|
|
89
|
+
/* @__PURE__ */ jsx(XIntakeTextarea, {
|
|
90
|
+
value: input,
|
|
91
|
+
onChange: setInput,
|
|
92
|
+
onSubmit: handleSubmit,
|
|
93
|
+
placeholder,
|
|
94
|
+
disabled: isLoading
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ jsxs("div", {
|
|
97
|
+
className: "actions-section flex flex-row items-center gap-2",
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsx(Button, {
|
|
100
|
+
type: "button",
|
|
101
|
+
variant: "ghost",
|
|
102
|
+
size: "icon-sm",
|
|
103
|
+
disabled: isLoading,
|
|
104
|
+
children: /* @__PURE__ */ jsx(FileIcon, { width: 20 })
|
|
105
|
+
}),
|
|
106
|
+
/* @__PURE__ */ jsx("span", {
|
|
107
|
+
className: "ml-auto text-ppx-xs text-ppx-neutral-10",
|
|
108
|
+
children: "Enter to send · Shift+Enter for new line"
|
|
109
|
+
}),
|
|
110
|
+
/* @__PURE__ */ jsx(Button, {
|
|
111
|
+
type: "submit",
|
|
112
|
+
size: "icon-sm",
|
|
113
|
+
disabled: isLoading || !input.trim(),
|
|
114
|
+
className: "flex h-8 w-8 items-center justify-center rounded-full bg-ppx-green-5 text-white transition-all hover:bg-ppx-green-4 hover:shadow-[0_0_12px_rgba(40,182,116,0.6)] disabled:bg-ppx-neutral-5 disabled:text-ppx-neutral-10 disabled:shadow-none",
|
|
115
|
+
children: isLoading ? /* @__PURE__ */ jsx(StopIcon, { width: 14 }) : /* @__PURE__ */ jsx(SendIcon, { width: 16 })
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
})
|
|
119
|
+
]
|
|
120
|
+
}), suggestions.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
121
|
+
className: "flex flex-wrap justify-center gap-2",
|
|
122
|
+
children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsx(Button, {
|
|
123
|
+
type: "button",
|
|
124
|
+
variant: "outline",
|
|
125
|
+
size: "sm",
|
|
126
|
+
onClick: () => handleSuggestionClick(suggestion.prompt),
|
|
127
|
+
className: "animate-[popUp_0.3s_ease-out_forwards] rounded-full opacity-0",
|
|
128
|
+
style: { animationDelay: `${index * .1}s` },
|
|
129
|
+
children: suggestion.label
|
|
130
|
+
}, suggestion.id))
|
|
131
|
+
})]
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function XIntakeTextarea({ value, onChange, onSubmit, placeholder, disabled }) {
|
|
135
|
+
const handleKeyDown = (e) => {
|
|
136
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
137
|
+
e.preventDefault();
|
|
138
|
+
onSubmit();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
return /* @__PURE__ */ jsx("textarea", {
|
|
142
|
+
className: "w-full resize-none border-none bg-transparent outline-none",
|
|
143
|
+
placeholder,
|
|
144
|
+
disabled,
|
|
145
|
+
value,
|
|
146
|
+
onChange: (e) => onChange(e.target.value),
|
|
147
|
+
onKeyDown: handleKeyDown
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/assets/icons/chat-icon.tsx
|
|
153
|
+
function ChatIcon(props) {
|
|
154
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
155
|
+
width: "18",
|
|
156
|
+
height: "18",
|
|
157
|
+
viewBox: "0 0 24 24",
|
|
158
|
+
fill: "none",
|
|
159
|
+
stroke: "currentColor",
|
|
160
|
+
strokeWidth: "2",
|
|
161
|
+
strokeLinecap: "round",
|
|
162
|
+
strokeLinejoin: "round",
|
|
163
|
+
...props,
|
|
164
|
+
children: /* @__PURE__ */ jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/assets/icons/check-icon.tsx
|
|
170
|
+
function CheckIcon(props) {
|
|
171
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
172
|
+
width: "16",
|
|
173
|
+
height: "16",
|
|
174
|
+
viewBox: "0 0 24 24",
|
|
175
|
+
fill: "none",
|
|
176
|
+
stroke: "currentColor",
|
|
177
|
+
strokeWidth: "2",
|
|
178
|
+
strokeLinecap: "round",
|
|
179
|
+
strokeLinejoin: "round",
|
|
180
|
+
...props,
|
|
181
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/assets/icons/close-icon.tsx
|
|
187
|
+
function CloseIcon(props) {
|
|
188
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
189
|
+
width: "20",
|
|
190
|
+
height: "20",
|
|
191
|
+
viewBox: "0 0 24 24",
|
|
192
|
+
fill: "none",
|
|
193
|
+
stroke: "currentColor",
|
|
194
|
+
strokeWidth: "2",
|
|
195
|
+
strokeLinecap: "round",
|
|
196
|
+
strokeLinejoin: "round",
|
|
197
|
+
...props,
|
|
198
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }), /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })]
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region src/assets/icons/copy-icon.tsx
|
|
204
|
+
function CopyIcon(props) {
|
|
205
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
206
|
+
width: "16",
|
|
207
|
+
height: "16",
|
|
208
|
+
viewBox: "0 0 24 24",
|
|
209
|
+
fill: "none",
|
|
210
|
+
stroke: "currentColor",
|
|
211
|
+
strokeWidth: "2",
|
|
212
|
+
strokeLinecap: "round",
|
|
213
|
+
strokeLinejoin: "round",
|
|
214
|
+
...props,
|
|
215
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
216
|
+
width: "14",
|
|
217
|
+
height: "14",
|
|
218
|
+
x: "8",
|
|
219
|
+
y: "8",
|
|
220
|
+
rx: "2",
|
|
221
|
+
ry: "2"
|
|
222
|
+
}), /* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })]
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/assets/icons/debug-icon.tsx
|
|
228
|
+
function DebugIcon(props) {
|
|
229
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
230
|
+
width: "16",
|
|
231
|
+
height: "16",
|
|
232
|
+
viewBox: "0 0 24 24",
|
|
233
|
+
fill: "none",
|
|
234
|
+
stroke: "currentColor",
|
|
235
|
+
strokeWidth: "2",
|
|
236
|
+
strokeLinecap: "round",
|
|
237
|
+
strokeLinejoin: "round",
|
|
238
|
+
...props,
|
|
239
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1" }), /* @__PURE__ */ jsx("path", { d: "M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1" })]
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
//#endregion
|
|
244
|
+
//#region src/assets/icons/menu-icon.tsx
|
|
245
|
+
function MenuIcon(props) {
|
|
246
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
247
|
+
width: "20",
|
|
248
|
+
height: "20",
|
|
249
|
+
viewBox: "0 0 24 24",
|
|
250
|
+
fill: "none",
|
|
251
|
+
stroke: "currentColor",
|
|
252
|
+
strokeWidth: "2",
|
|
253
|
+
strokeLinecap: "round",
|
|
254
|
+
strokeLinejoin: "round",
|
|
255
|
+
...props,
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ jsx("line", {
|
|
258
|
+
x1: "4",
|
|
259
|
+
x2: "20",
|
|
260
|
+
y1: "12",
|
|
261
|
+
y2: "12"
|
|
262
|
+
}),
|
|
263
|
+
/* @__PURE__ */ jsx("line", {
|
|
264
|
+
x1: "4",
|
|
265
|
+
x2: "20",
|
|
266
|
+
y1: "6",
|
|
267
|
+
y2: "6"
|
|
268
|
+
}),
|
|
269
|
+
/* @__PURE__ */ jsx("line", {
|
|
270
|
+
x1: "4",
|
|
271
|
+
x2: "20",
|
|
272
|
+
y1: "18",
|
|
273
|
+
y2: "18"
|
|
274
|
+
})
|
|
275
|
+
]
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
//#endregion
|
|
280
|
+
//#region src/assets/icons/new-chat-icon.tsx
|
|
281
|
+
function NewChatIcon(props) {
|
|
282
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
283
|
+
width: "20",
|
|
284
|
+
height: "20",
|
|
285
|
+
viewBox: "0 0 24 24",
|
|
286
|
+
fill: "none",
|
|
287
|
+
stroke: "currentColor",
|
|
288
|
+
strokeWidth: "2",
|
|
289
|
+
strokeLinecap: "round",
|
|
290
|
+
strokeLinejoin: "round",
|
|
291
|
+
...props,
|
|
292
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }), /* @__PURE__ */ jsx("path", { d: "M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z" })]
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region src/assets/icons/sparkles-icon.tsx
|
|
298
|
+
function SparklesIcon(props) {
|
|
299
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
300
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
301
|
+
width: "20",
|
|
302
|
+
height: "20",
|
|
303
|
+
viewBox: "0 0 24 24",
|
|
304
|
+
fill: "none",
|
|
305
|
+
stroke: "currentColor",
|
|
306
|
+
strokeWidth: "2",
|
|
307
|
+
strokeLinecap: "round",
|
|
308
|
+
strokeLinejoin: "round",
|
|
309
|
+
...props,
|
|
310
|
+
children: [
|
|
311
|
+
/* @__PURE__ */ jsx("path", { d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" }),
|
|
312
|
+
/* @__PURE__ */ jsx("path", { d: "M20 3v4" }),
|
|
313
|
+
/* @__PURE__ */ jsx("path", { d: "M22 5h-4" }),
|
|
314
|
+
/* @__PURE__ */ jsx("path", { d: "M4 17v2" }),
|
|
315
|
+
/* @__PURE__ */ jsx("path", { d: "M5 18H3" })
|
|
316
|
+
]
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
//#endregion
|
|
321
|
+
//#region src/assets/icons/thumbs-down-icon.tsx
|
|
322
|
+
function ThumbsDownIcon(props) {
|
|
323
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
324
|
+
width: "16",
|
|
325
|
+
height: "16",
|
|
326
|
+
viewBox: "0 0 24 24",
|
|
327
|
+
fill: "none",
|
|
328
|
+
stroke: "currentColor",
|
|
329
|
+
strokeWidth: "2",
|
|
330
|
+
strokeLinecap: "round",
|
|
331
|
+
strokeLinejoin: "round",
|
|
332
|
+
...props,
|
|
333
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M17 14V2" }), /* @__PURE__ */ jsx("path", { d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z" })]
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/assets/icons/thumbs-up-icon.tsx
|
|
339
|
+
function ThumbsUpIcon(props) {
|
|
340
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
341
|
+
width: "16",
|
|
342
|
+
height: "16",
|
|
343
|
+
viewBox: "0 0 24 24",
|
|
344
|
+
fill: "none",
|
|
345
|
+
stroke: "currentColor",
|
|
346
|
+
strokeWidth: "2",
|
|
347
|
+
strokeLinecap: "round",
|
|
348
|
+
strokeLinejoin: "round",
|
|
349
|
+
...props,
|
|
350
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M7 10v12" }), /* @__PURE__ */ jsx("path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z" })]
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/components/x-message-actions.tsx
|
|
356
|
+
var x_message_actions_exports = /* @__PURE__ */ __export({
|
|
357
|
+
Copy: () => Copy,
|
|
358
|
+
Debug: () => Debug,
|
|
359
|
+
Feedback: () => Feedback,
|
|
360
|
+
Root: () => Root
|
|
361
|
+
});
|
|
362
|
+
/**
|
|
363
|
+
* Container for message actions. Use with composable children:
|
|
364
|
+
* - XMessageActions.Feedback
|
|
365
|
+
* - XMessageActions.Copy
|
|
366
|
+
* - XMessageActions.Debug
|
|
367
|
+
*/
|
|
368
|
+
function Root({ children }) {
|
|
369
|
+
return /* @__PURE__ */ jsx("div", {
|
|
370
|
+
className: "flex items-center gap-1",
|
|
371
|
+
children
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
function Feedback({ messageId }) {
|
|
375
|
+
const { onFeedback } = useXandi();
|
|
376
|
+
const [feedback, setFeedback] = useState(null);
|
|
377
|
+
const handleFeedback = (type) => {
|
|
378
|
+
const newFeedback = feedback === type ? null : type;
|
|
379
|
+
setFeedback(newFeedback);
|
|
380
|
+
onFeedback?.(messageId, newFeedback);
|
|
381
|
+
};
|
|
382
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, { render: /* @__PURE__ */ jsx(Button, {
|
|
383
|
+
variant: "ghost",
|
|
384
|
+
size: "icon-sm",
|
|
385
|
+
onClick: () => handleFeedback("up"),
|
|
386
|
+
className: `h-7 w-7 ${feedback === "up" ? "bg-ppx-green-2 text-ppx-green-5" : "text-ppx-neutral-10 hover:text-ppx-neutral-12"}`,
|
|
387
|
+
children: /* @__PURE__ */ jsx(ThumbsUpIcon, { className: feedback === "up" ? "fill-current" : "" })
|
|
388
|
+
}) }), /* @__PURE__ */ jsx(Tooltip.Content, { children: feedback === "up" ? "You found this helpful" : "Good response" })] }), /* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, { render: /* @__PURE__ */ jsx(Button, {
|
|
389
|
+
variant: "ghost",
|
|
390
|
+
size: "icon-sm",
|
|
391
|
+
onClick: () => handleFeedback("down"),
|
|
392
|
+
className: `h-7 w-7 ${feedback === "down" ? "bg-ppx-red-2 text-ppx-red-5" : "text-ppx-neutral-10 hover:text-ppx-neutral-12"}`,
|
|
393
|
+
children: /* @__PURE__ */ jsx(ThumbsDownIcon, { className: feedback === "down" ? "fill-current" : "" })
|
|
394
|
+
}) }), /* @__PURE__ */ jsx(Tooltip.Content, { children: feedback === "down" ? "You found this unhelpful" : "Bad response" })] })] });
|
|
395
|
+
}
|
|
396
|
+
function Copy({ content }) {
|
|
397
|
+
const [copied, setCopied] = useState(false);
|
|
398
|
+
const handleCopy = async () => {
|
|
399
|
+
try {
|
|
400
|
+
await navigator.clipboard.writeText(content);
|
|
401
|
+
setCopied(true);
|
|
402
|
+
toast.add({
|
|
403
|
+
title: "Copied!",
|
|
404
|
+
description: "Message copied to clipboard",
|
|
405
|
+
type: "success"
|
|
406
|
+
});
|
|
407
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
408
|
+
} catch {
|
|
409
|
+
toast.add({
|
|
410
|
+
title: "Failed to copy",
|
|
411
|
+
description: "Could not copy message to clipboard",
|
|
412
|
+
type: "error"
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
return /* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, { render: /* @__PURE__ */ jsx(Button, {
|
|
417
|
+
variant: "ghost",
|
|
418
|
+
size: "icon-sm",
|
|
419
|
+
onClick: handleCopy,
|
|
420
|
+
className: "h-7 w-7 text-ppx-neutral-10 hover:text-ppx-neutral-12",
|
|
421
|
+
children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-ppx-green-5" }) : /* @__PURE__ */ jsx(CopyIcon, {})
|
|
422
|
+
}) }), /* @__PURE__ */ jsx(Tooltip.Content, { children: copied ? "Copied!" : "Copy message" })] });
|
|
423
|
+
}
|
|
424
|
+
function Debug({ messageId, debugTrace }) {
|
|
425
|
+
const [debugOpen, setDebugOpen] = useState(false);
|
|
426
|
+
return /* @__PURE__ */ jsxs(Dialog.Root, {
|
|
427
|
+
open: debugOpen,
|
|
428
|
+
onOpenChange: setDebugOpen,
|
|
429
|
+
children: [/* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, { render: /* @__PURE__ */ jsx(Dialog.Trigger, { render: /* @__PURE__ */ jsx(Button, {
|
|
430
|
+
variant: "ghost",
|
|
431
|
+
size: "icon-sm",
|
|
432
|
+
className: "h-7 w-7 text-ppx-neutral-10 hover:text-ppx-neutral-12",
|
|
433
|
+
children: /* @__PURE__ */ jsx(DebugIcon, {})
|
|
434
|
+
}) }) }), /* @__PURE__ */ jsx(Tooltip.Content, { children: "View debug trace" })] }), /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, {}), /* @__PURE__ */ jsxs(Dialog.Content, {
|
|
435
|
+
className: "max-w-2xl",
|
|
436
|
+
children: [
|
|
437
|
+
/* @__PURE__ */ jsxs(Dialog.Header, { children: [/* @__PURE__ */ jsx(Dialog.Title, { children: "Debug Trace" }), /* @__PURE__ */ jsxs(Dialog.Description, { children: ["Response debug information for message ", messageId] })] }),
|
|
438
|
+
/* @__PURE__ */ jsx("div", {
|
|
439
|
+
className: "max-h-96 overflow-auto rounded bg-ppx-neutral-2 p-4",
|
|
440
|
+
children: /* @__PURE__ */ jsx("pre", {
|
|
441
|
+
className: "whitespace-pre-wrap font-mono text-ppx-xs text-ppx-neutral-12",
|
|
442
|
+
children: JSON.stringify(debugTrace, null, 2)
|
|
443
|
+
})
|
|
444
|
+
}),
|
|
445
|
+
/* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsx(Dialog.Close, { render: /* @__PURE__ */ jsx(Button, {
|
|
446
|
+
variant: "outline",
|
|
447
|
+
children: "Close"
|
|
448
|
+
}) }) })
|
|
449
|
+
]
|
|
450
|
+
})] })]
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
//#endregion
|
|
455
|
+
//#region src/components/renderers/markdown-renderer.tsx
|
|
456
|
+
function MarkdownRenderer({ message }) {
|
|
457
|
+
const isUser = message.role === "user";
|
|
458
|
+
const baseClass = `text-ppx-sm leading-relaxed ${isUser ? "text-white" : "text-ppx-neutral-13"}`;
|
|
459
|
+
const showActions = !isUser;
|
|
460
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
461
|
+
className: baseClass,
|
|
462
|
+
children: /* @__PURE__ */ jsx(ReactMarkdown, {
|
|
463
|
+
components: {
|
|
464
|
+
p: ({ children }) => /* @__PURE__ */ jsx("p", {
|
|
465
|
+
className: "mb-2 last:mb-0",
|
|
466
|
+
children
|
|
467
|
+
}),
|
|
468
|
+
ul: ({ children }) => /* @__PURE__ */ jsx("ul", {
|
|
469
|
+
className: "mb-2 list-disc pl-4",
|
|
470
|
+
children
|
|
471
|
+
}),
|
|
472
|
+
ol: ({ children }) => /* @__PURE__ */ jsx("ol", {
|
|
473
|
+
className: "mb-2 list-decimal pl-4",
|
|
474
|
+
children
|
|
475
|
+
}),
|
|
476
|
+
li: ({ children }) => /* @__PURE__ */ jsx("li", {
|
|
477
|
+
className: "mb-1",
|
|
478
|
+
children
|
|
479
|
+
}),
|
|
480
|
+
a: ({ href, children }) => /* @__PURE__ */ jsx("a", {
|
|
481
|
+
href,
|
|
482
|
+
className: "underline",
|
|
483
|
+
target: "_blank",
|
|
484
|
+
rel: "noopener noreferrer",
|
|
485
|
+
children
|
|
486
|
+
}),
|
|
487
|
+
strong: ({ children }) => /* @__PURE__ */ jsx("strong", {
|
|
488
|
+
className: "font-semibold",
|
|
489
|
+
children
|
|
490
|
+
})
|
|
491
|
+
},
|
|
492
|
+
children: message.content
|
|
493
|
+
})
|
|
494
|
+
}), showActions && /* @__PURE__ */ jsx("div", {
|
|
495
|
+
className: "mt-2",
|
|
496
|
+
children: /* @__PURE__ */ jsxs(Root, { children: [
|
|
497
|
+
/* @__PURE__ */ jsx(Feedback, { messageId: message.id }),
|
|
498
|
+
/* @__PURE__ */ jsx(Copy, { content: message.content }),
|
|
499
|
+
message.debugTrace != null && /* @__PURE__ */ jsx(Debug, {
|
|
500
|
+
messageId: message.id,
|
|
501
|
+
debugTrace: message.debugTrace
|
|
502
|
+
})
|
|
503
|
+
] })
|
|
504
|
+
})] });
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
//#endregion
|
|
508
|
+
//#region src/components/renderers/text-renderer.tsx
|
|
509
|
+
function TextRenderer({ message }) {
|
|
510
|
+
const isUser = message.role === "user";
|
|
511
|
+
const showActions = !isUser;
|
|
512
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
|
|
513
|
+
className: `text-ppx-sm leading-relaxed ${isUser ? "text-white" : "text-ppx-neutral-13"}`,
|
|
514
|
+
children: message.content
|
|
515
|
+
}), showActions && /* @__PURE__ */ jsx("div", {
|
|
516
|
+
className: "mt-2",
|
|
517
|
+
children: /* @__PURE__ */ jsxs(Root, { children: [
|
|
518
|
+
/* @__PURE__ */ jsx(Feedback, { messageId: message.id }),
|
|
519
|
+
/* @__PURE__ */ jsx(Copy, { content: message.content }),
|
|
520
|
+
message.debugTrace != null && /* @__PURE__ */ jsx(Debug, {
|
|
521
|
+
messageId: message.id,
|
|
522
|
+
debugTrace: message.debugTrace
|
|
523
|
+
})
|
|
524
|
+
] })
|
|
525
|
+
})] });
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
//#endregion
|
|
529
|
+
//#region src/components/x-message-item.tsx
|
|
530
|
+
/**
|
|
531
|
+
* Router component that renders messages based on their type.
|
|
532
|
+
* Defaults to markdown rendering if no type is specified.
|
|
533
|
+
*/
|
|
534
|
+
function XMessageItem({ message }) {
|
|
535
|
+
const isUser = message.role === "user";
|
|
536
|
+
const messageType = message.type ?? "markdown";
|
|
537
|
+
return /* @__PURE__ */ jsx("div", {
|
|
538
|
+
className: `flex ${isUser ? "justify-end" : "justify-start"}`,
|
|
539
|
+
children: isUser ? /* @__PURE__ */ jsx("div", {
|
|
540
|
+
className: "max-w-[90%] rounded-2xl rounded-br-sm bg-ppx-green-5 px-4 py-2.5",
|
|
541
|
+
children: /* @__PURE__ */ jsx(MessageRenderer, {
|
|
542
|
+
type: messageType,
|
|
543
|
+
message
|
|
544
|
+
})
|
|
545
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
546
|
+
className: "max-w-[90%]",
|
|
547
|
+
children: /* @__PURE__ */ jsx(MessageRenderer, {
|
|
548
|
+
type: messageType,
|
|
549
|
+
message
|
|
550
|
+
})
|
|
551
|
+
})
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Switch component that selects the appropriate renderer based on message type.
|
|
556
|
+
*/
|
|
557
|
+
function MessageRenderer({ type, message }) {
|
|
558
|
+
switch (type) {
|
|
559
|
+
case "text": return /* @__PURE__ */ jsx(TextRenderer, { message });
|
|
560
|
+
case "markdown":
|
|
561
|
+
default: return /* @__PURE__ */ jsx(MarkdownRenderer, { message });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
//#endregion
|
|
566
|
+
//#region src/constants.ts
|
|
567
|
+
const XANDI_AVATAR_URL = new URL("./assets/images/xandi-avatar.png", import.meta.url).href;
|
|
568
|
+
|
|
569
|
+
//#endregion
|
|
570
|
+
//#region src/components/x-typing-indicator.tsx
|
|
571
|
+
function XTypingIndicator() {
|
|
572
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
573
|
+
className: "flex items-center gap-4",
|
|
574
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
575
|
+
className: "animate-[popUp_0.3s_ease-out_forwards]",
|
|
576
|
+
children: /* @__PURE__ */ jsx(Avatar, {
|
|
577
|
+
imgSrc: XANDI_AVATAR_URL,
|
|
578
|
+
name: "Xandi",
|
|
579
|
+
variant: "rounded",
|
|
580
|
+
size: "48px",
|
|
581
|
+
hideTooltip: true,
|
|
582
|
+
className: "border-2 border-ppx-neutral-4"
|
|
583
|
+
})
|
|
584
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
585
|
+
className: "flex animate-[slideIn_0.3s_ease-out_0.2s_forwards] items-center gap-2 rounded-xl bg-ppx-neutral-2 px-[10px] pb-[5px] pt-[10px] opacity-0 shadow-sm",
|
|
586
|
+
children: [
|
|
587
|
+
/* @__PURE__ */ jsx("span", { className: "h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-9 [animation-delay:-0.3s]" }),
|
|
588
|
+
/* @__PURE__ */ jsx("span", { className: "h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-6 [animation-delay:-0.15s]" }),
|
|
589
|
+
/* @__PURE__ */ jsx("span", { className: "h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-9" })
|
|
590
|
+
]
|
|
591
|
+
})]
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
//#endregion
|
|
596
|
+
//#region src/components/x-message-container.tsx
|
|
597
|
+
function XMessageContainer({ height = 400 }) {
|
|
598
|
+
const { messages, isLoading } = useXandi();
|
|
599
|
+
const containerRef = useRef(null);
|
|
600
|
+
useEffect(() => {
|
|
601
|
+
if (containerRef.current) containerRef.current.scrollTop = containerRef.current.scrollHeight;
|
|
602
|
+
}, [messages, isLoading]);
|
|
603
|
+
return /* @__PURE__ */ jsx("div", {
|
|
604
|
+
ref: containerRef,
|
|
605
|
+
className: "overflow-y-auto py-[10px]",
|
|
606
|
+
style: { height: typeof height === "number" ? `${height}px` : height },
|
|
607
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
608
|
+
className: "flex flex-col gap-5 p-4",
|
|
609
|
+
children: [messages.map((message) => /* @__PURE__ */ jsx(XMessageItem, { message }, message.id)), isLoading && /* @__PURE__ */ jsx(XTypingIndicator, {})]
|
|
610
|
+
})
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
//#endregion
|
|
615
|
+
//#region src/components/x-welcome.tsx
|
|
616
|
+
function XWelcome({ message }) {
|
|
617
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
618
|
+
className: "flex flex-col items-center justify-center gap-4 py-12",
|
|
619
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
620
|
+
className: "relative",
|
|
621
|
+
children: [
|
|
622
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -inset-1 rounded-full bg-gradient-to-b from-ppx-green-4 via-ppx-green-5/50 to-transparent" }),
|
|
623
|
+
/* @__PURE__ */ jsx("div", {
|
|
624
|
+
className: "relative rounded-full bg-ppx-neutral-18 p-1",
|
|
625
|
+
children: /* @__PURE__ */ jsx(Avatar, {
|
|
626
|
+
imgSrc: XANDI_AVATAR_URL,
|
|
627
|
+
name: "Xandi",
|
|
628
|
+
variant: "rounded",
|
|
629
|
+
size: "120px",
|
|
630
|
+
hideTooltip: true
|
|
631
|
+
})
|
|
632
|
+
}),
|
|
633
|
+
/* @__PURE__ */ jsx("div", {
|
|
634
|
+
className: "absolute -bottom-2 left-1/2",
|
|
635
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
636
|
+
className: "flex h-6 w-6 animate-[pulse-zoom_2s_ease-in-out_infinite] items-center justify-center rounded-full bg-ppx-green-5",
|
|
637
|
+
children: /* @__PURE__ */ jsx(SparklesIcon, { className: "text-white" })
|
|
638
|
+
})
|
|
639
|
+
})
|
|
640
|
+
]
|
|
641
|
+
}), /* @__PURE__ */ jsx("h2", {
|
|
642
|
+
className: "text-ppx-xl font-semibold text-ppx-foreground",
|
|
643
|
+
children: message
|
|
644
|
+
})]
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
//#endregion
|
|
649
|
+
//#region src/components/xandi.tsx
|
|
650
|
+
function Xandi({ welcomeMessage = "How can I help you today?", suggestions = [] }) {
|
|
651
|
+
const { messages, isLoading } = useXandi();
|
|
652
|
+
const isEmpty = messages.length === 0;
|
|
653
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
654
|
+
className: "flex flex-col",
|
|
655
|
+
children: [isEmpty ? /* @__PURE__ */ jsx(XWelcome, { message: welcomeMessage }) : /* @__PURE__ */ jsx(XMessageContainer, {}), /* @__PURE__ */ jsx(XMainIntake, { suggestions: isEmpty ? suggestions : [] })]
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
//#endregion
|
|
660
|
+
//#region src/components/x-header.tsx
|
|
661
|
+
function XHeader({ title = "Xandi", onClose, onNewChat, onToggleHistory }) {
|
|
662
|
+
return /* @__PURE__ */ jsxs("header", {
|
|
663
|
+
className: "flex items-center justify-between border-b border-ppx-neutral-5 bg-ppx-neutral-2 px-3 py-2",
|
|
664
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
665
|
+
className: "flex items-center gap-2",
|
|
666
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
667
|
+
variant: "ghost",
|
|
668
|
+
size: "icon-sm",
|
|
669
|
+
onClick: onToggleHistory,
|
|
670
|
+
"aria-label": "Toggle chat history",
|
|
671
|
+
children: /* @__PURE__ */ jsx(MenuIcon, {})
|
|
672
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
673
|
+
className: "flex items-center gap-2",
|
|
674
|
+
children: [/* @__PURE__ */ jsx(Avatar, {
|
|
675
|
+
imgSrc: XANDI_AVATAR_URL,
|
|
676
|
+
name: "Xandi",
|
|
677
|
+
variant: "rounded",
|
|
678
|
+
size: "24px",
|
|
679
|
+
hideTooltip: true
|
|
680
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
681
|
+
className: "font-medium text-ppx-foreground",
|
|
682
|
+
children: title
|
|
683
|
+
})]
|
|
684
|
+
})]
|
|
685
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
686
|
+
className: "flex items-center gap-1",
|
|
687
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
688
|
+
variant: "ghost",
|
|
689
|
+
size: "icon-sm",
|
|
690
|
+
onClick: onNewChat,
|
|
691
|
+
"aria-label": "New chat",
|
|
692
|
+
children: /* @__PURE__ */ jsx(NewChatIcon, {})
|
|
693
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
694
|
+
variant: "ghost",
|
|
695
|
+
size: "icon-sm",
|
|
696
|
+
onClick: onClose,
|
|
697
|
+
"aria-label": "Close",
|
|
698
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
699
|
+
})]
|
|
700
|
+
})]
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
//#endregion
|
|
705
|
+
//#region src/components/x-chat-history.tsx
|
|
706
|
+
function XChatHistory({ groups = [], activeChatId, onSelectChat }) {
|
|
707
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
708
|
+
className: "flex-1 overflow-y-auto",
|
|
709
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
710
|
+
className: "px-3 py-2",
|
|
711
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
712
|
+
className: "flex items-center gap-2 text-ppx-sm font-medium text-ppx-foreground",
|
|
713
|
+
children: [/* @__PURE__ */ jsx(ChatIcon, {}), "Chats"]
|
|
714
|
+
})
|
|
715
|
+
}), groups.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
716
|
+
className: "px-6 py-4 text-ppx-sm text-ppx-neutral-10",
|
|
717
|
+
children: "No chat history yet"
|
|
718
|
+
}) : groups.map((group) => /* @__PURE__ */ jsxs("div", {
|
|
719
|
+
className: "mb-2",
|
|
720
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
721
|
+
className: "px-6 py-2 text-ppx-xs font-medium text-ppx-neutral-10",
|
|
722
|
+
children: group.label
|
|
723
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
724
|
+
className: "space-y-0.5",
|
|
725
|
+
children: group.items.map((item) => /* @__PURE__ */ jsx(Button, {
|
|
726
|
+
variant: "ghost",
|
|
727
|
+
onClick: () => onSelectChat?.(item.id),
|
|
728
|
+
className: `w-full justify-start truncate rounded-none px-6 ${activeChatId === item.id ? "bg-ppx-neutral-4 text-ppx-foreground" : "text-ppx-neutral-12"}`,
|
|
729
|
+
children: item.title
|
|
730
|
+
}, item.id))
|
|
731
|
+
})]
|
|
732
|
+
}, group.label))]
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
//#endregion
|
|
737
|
+
//#region src/components/x-sidebar.tsx
|
|
738
|
+
function XSidebar({ isOpen = true, chatHistory = [], activeChatId, onClose, onNewChat, onSelectChat }) {
|
|
739
|
+
if (!isOpen) return null;
|
|
740
|
+
return /* @__PURE__ */ jsxs("aside", {
|
|
741
|
+
className: "flex h-full w-64 flex-col border-r border-ppx-neutral-5 bg-ppx-neutral-2",
|
|
742
|
+
children: [
|
|
743
|
+
/* @__PURE__ */ jsx("div", {
|
|
744
|
+
className: "flex items-center justify-between border-b border-ppx-neutral-5 p-3",
|
|
745
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
746
|
+
variant: "ghost",
|
|
747
|
+
size: "icon-sm",
|
|
748
|
+
onClick: onClose,
|
|
749
|
+
"aria-label": "Close sidebar",
|
|
750
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
751
|
+
})
|
|
752
|
+
}),
|
|
753
|
+
/* @__PURE__ */ jsx("div", {
|
|
754
|
+
className: "p-3",
|
|
755
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
756
|
+
variant: "ghost",
|
|
757
|
+
onClick: onNewChat,
|
|
758
|
+
className: "w-full justify-start gap-3",
|
|
759
|
+
children: [/* @__PURE__ */ jsx(NewChatIcon, { className: "h-5 w-5" }), "New chat"]
|
|
760
|
+
})
|
|
761
|
+
}),
|
|
762
|
+
/* @__PURE__ */ jsx(XChatHistory, {
|
|
763
|
+
groups: chatHistory,
|
|
764
|
+
activeChatId,
|
|
765
|
+
onSelectChat
|
|
766
|
+
})
|
|
767
|
+
]
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
//#endregion
|
|
772
|
+
export { XChatHistory, XHeader, x_message_actions_exports as XMessageActions, XSidebar, Xandi, XandiProvider, useXandi };
|
|
773
|
+
//# sourceMappingURL=index.js.map
|