reachat 0.0.1 → 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.
Files changed (46) hide show
  1. package/README.md +84 -39
  2. package/dist/{Sessions.d.ts → Chat.d.ts} +23 -17
  3. package/dist/ChatContext.d.ts +16 -0
  4. package/dist/ChatInput.d.ts +42 -0
  5. package/dist/Markdown/CodeHighlighter.d.ts +9 -0
  6. package/dist/Markdown/Markdown.d.ts +11 -0
  7. package/dist/Markdown/Table.d.ts +5 -0
  8. package/dist/Markdown/index.d.ts +4 -0
  9. package/dist/Markdown/plugins/index.d.ts +1 -0
  10. package/dist/Markdown/plugins/remarkCve.d.ts +1 -0
  11. package/dist/SessionMessages/MessageActions.d.ts +45 -0
  12. package/dist/SessionMessages/MessageFile.d.ts +14 -0
  13. package/dist/SessionMessages/MessageFiles.d.ts +11 -0
  14. package/dist/SessionMessages/MessageQuestion.d.ts +9 -0
  15. package/dist/SessionMessages/MessageResponse.d.ts +13 -0
  16. package/dist/SessionMessages/MessageSource.d.ts +10 -0
  17. package/dist/SessionMessages/MessageSources.d.ts +11 -0
  18. package/dist/SessionMessages/SessionEmpty.d.ts +6 -0
  19. package/dist/SessionMessages/SessionMessage.d.ts +15 -0
  20. package/dist/SessionMessages/SessionMessagePanel.d.ts +3 -0
  21. package/dist/SessionMessages/SessionMessages.d.ts +23 -0
  22. package/dist/SessionMessages/SessionMessagesHeader.d.ts +3 -0
  23. package/dist/SessionMessages/index.d.ts +12 -0
  24. package/dist/SessionsList/NewSessionButton.d.ts +10 -0
  25. package/dist/SessionsList/SessionGroups.d.ts +10 -0
  26. package/dist/SessionsList/SessionListItem.d.ts +22 -0
  27. package/dist/SessionsList/SessionsGroup.d.ts +10 -0
  28. package/dist/SessionsList/SessionsList.d.ts +3 -0
  29. package/dist/SessionsList/index.d.ts +5 -0
  30. package/dist/docs.json +1379 -0
  31. package/dist/index.d.ts +4 -5
  32. package/dist/index.js +758 -131
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.umd.cjs +737 -120
  35. package/dist/index.umd.cjs.map +1 -1
  36. package/dist/theme.d.ts +70 -1
  37. package/dist/types.d.ts +71 -17
  38. package/dist/utils.d.ts +7 -0
  39. package/dist/utils.spec.d.ts +1 -0
  40. package/package.json +31 -19
  41. package/dist/SessionInput.d.ts +0 -22
  42. package/dist/SessionListItem.d.ts +0 -11
  43. package/dist/SessionMessage.d.ts +0 -10
  44. package/dist/SessionMessages.d.ts +0 -9
  45. package/dist/SessionsList.d.ts +0 -11
  46. package/dist/useLlm.d.ts +0 -3
package/dist/index.js CHANGED
@@ -1,6 +1,14 @@
1
- import TextareaAutosize from "react-textarea-autosize";
2
- const useLlm = (options) => {
3
- };
1
+ import { cn, Textarea, Button, Ellipsis, DateFormat, IconButton, Card, useInfinityList, useComponentTheme, List, ListItem } from "reablocks";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { motion, AnimatePresence } from "framer-motion";
4
+ import ReactMarkdown from "react-markdown";
5
+ import remarkGfm from "remark-gfm";
6
+ import hljs from "highlight.js";
7
+ import "highlight.js/styles/atom-one-dark.css";
8
+ import { findAndReplace } from "mdast-util-find-and-replace";
9
+ import remarkYoutube from "remark-youtube";
10
+ import { useHotkeys } from "reakeys";
11
+ import { isToday, isYesterday, isThisWeek, isThisMonth, isThisYear, format } from "date-fns";
4
12
  var jsxRuntime = { exports: {} };
5
13
  var reactJsxRuntime_production_min = {};
6
14
  var react = { exports: {} };
@@ -378,38 +386,38 @@ function requireReact_development() {
378
386
  ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame;
379
387
  ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue;
380
388
  }
381
- function warn(format) {
389
+ function warn(format2) {
382
390
  {
383
391
  {
384
392
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
385
393
  args[_key - 1] = arguments[_key];
386
394
  }
387
- printWarning("warn", format, args);
395
+ printWarning("warn", format2, args);
388
396
  }
389
397
  }
390
398
  }
391
- function error(format) {
399
+ function error(format2) {
392
400
  {
393
401
  {
394
402
  for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
395
403
  args[_key2 - 1] = arguments[_key2];
396
404
  }
397
- printWarning("error", format, args);
405
+ printWarning("error", format2, args);
398
406
  }
399
407
  }
400
408
  }
401
- function printWarning(level, format, args) {
409
+ function printWarning(level, format2, args) {
402
410
  {
403
411
  var ReactDebugCurrentFrame2 = ReactSharedInternals.ReactDebugCurrentFrame;
404
412
  var stack = ReactDebugCurrentFrame2.getStackAddendum();
405
413
  if (stack !== "") {
406
- format += "%s";
414
+ format2 += "%s";
407
415
  args = args.concat([stack]);
408
416
  }
409
417
  var argsWithFormat = args.map(function(item) {
410
418
  return String(item);
411
419
  });
412
- argsWithFormat.unshift("Warning: " + format);
420
+ argsWithFormat.unshift("Warning: " + format2);
413
421
  Function.prototype.apply.call(console[level], console, argsWithFormat);
414
422
  }
415
423
  }
@@ -2230,28 +2238,28 @@ function requireReactJsxRuntime_development() {
2230
2238
  return null;
2231
2239
  }
2232
2240
  var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
2233
- function error(format) {
2241
+ function error(format2) {
2234
2242
  {
2235
2243
  {
2236
2244
  for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
2237
2245
  args[_key2 - 1] = arguments[_key2];
2238
2246
  }
2239
- printWarning("error", format, args);
2247
+ printWarning("error", format2, args);
2240
2248
  }
2241
2249
  }
2242
2250
  }
2243
- function printWarning(level, format, args) {
2251
+ function printWarning(level, format2, args) {
2244
2252
  {
2245
2253
  var ReactDebugCurrentFrame2 = ReactSharedInternals.ReactDebugCurrentFrame;
2246
2254
  var stack = ReactDebugCurrentFrame2.getStackAddendum();
2247
2255
  if (stack !== "") {
2248
- format += "%s";
2256
+ format2 += "%s";
2249
2257
  args = args.concat([stack]);
2250
2258
  }
2251
2259
  var argsWithFormat = args.map(function(item) {
2252
2260
  return String(item);
2253
2261
  });
2254
- argsWithFormat.unshift("Warning: " + format);
2262
+ argsWithFormat.unshift("Warning: " + format2);
2255
2263
  Function.prototype.apply.call(console[level], console, argsWithFormat);
2256
2264
  }
2257
2265
  }
@@ -3089,11 +3097,30 @@ if (process.env.NODE_ENV === "production") {
3089
3097
  jsxRuntime.exports = requireReactJsxRuntime_development();
3090
3098
  }
3091
3099
  var jsxRuntimeExports = jsxRuntime.exports;
3092
- const SessionInput = ({ onSendMessage, isLoading, inputPlaceholder, onStopMessage }) => {
3100
+ const SvgSend = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-send-horizontal", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "m3 3 3 9-3 9 19-9Z" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M6 12h16" }));
3101
+ const SvgStop = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-octagon-x", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "m15 9-6 6" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z" }), /* @__PURE__ */ reactExports.createElement("path", { d: "m9 9 6 6" }));
3102
+ const SvgPaperclip = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-paperclip", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" }));
3103
+ const ChatContext = reactExports.createContext({
3104
+ sessions: [],
3105
+ activeSessionId: null
3106
+ });
3107
+ const ChatInput = ({
3108
+ allowedFiles,
3109
+ onSendMessage,
3110
+ placeholder,
3111
+ onStopMessage,
3112
+ onFileUpload,
3113
+ defaultValue,
3114
+ sendIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgSend, {}),
3115
+ stopIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgStop, {}),
3116
+ attachIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgPaperclip, {})
3117
+ }) => {
3118
+ const { theme, isLoading } = reactExports.useContext(ChatContext);
3093
3119
  const [message, setMessage] = reactExports.useState("");
3120
+ const fileInputRef = reactExports.useRef(null);
3094
3121
  const handleSendMessage = () => {
3095
3122
  if (message.trim()) {
3096
- onSendMessage(message);
3123
+ onSendMessage == null ? void 0 : onSendMessage(message);
3097
3124
  setMessage("");
3098
3125
  }
3099
3126
  };
@@ -3103,168 +3130,768 @@ const SessionInput = ({ onSendMessage, isLoading, inputPlaceholder, onStopMessag
3103
3130
  handleSendMessage();
3104
3131
  }
3105
3132
  };
3106
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-input mt-4", children: [
3133
+ const handleFileUpload = (event) => {
3134
+ var _a;
3135
+ const file = (_a = event.target.files) == null ? void 0 : _a[0];
3136
+ if (file && onFileUpload) {
3137
+ onFileUpload(file);
3138
+ }
3139
+ };
3140
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn(theme.input.base), children: [
3107
3141
  /* @__PURE__ */ jsxRuntimeExports.jsx(
3108
- TextareaAutosize,
3142
+ Textarea,
3109
3143
  {
3110
- className: "w-full p-2 border rounded",
3111
- minRows: 3,
3144
+ containerClassName: cn(theme.input.input),
3145
+ minRows: 1,
3112
3146
  autoFocus: true,
3113
3147
  value: message,
3114
3148
  onChange: (e) => setMessage(e.target.value),
3149
+ defaultValue,
3115
3150
  onKeyPress: handleKeyPress,
3116
- placeholder: inputPlaceholder,
3151
+ placeholder,
3117
3152
  disabled: isLoading
3118
3153
  }
3119
3154
  ),
3120
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 flex space-x-2", children: [
3155
+ (allowedFiles == null ? void 0 : allowedFiles.length) > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3121
3156
  /* @__PURE__ */ jsxRuntimeExports.jsx(
3122
- "button",
3157
+ "input",
3123
3158
  {
3124
- className: "px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-700",
3125
- onClick: handleSendMessage,
3126
- disabled: isLoading,
3127
- children: "Send"
3159
+ type: "file",
3160
+ ref: fileInputRef,
3161
+ className: "hidden",
3162
+ accept: allowedFiles.join(","),
3163
+ onChange: handleFileUpload
3128
3164
  }
3129
3165
  ),
3130
- isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(
3131
- "button",
3166
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3167
+ Button,
3132
3168
  {
3133
- className: "px-4 py-2 bg-red-500 text-white rounded hover:bg-red-700",
3134
- onClick: onStopMessage,
3135
- children: "Stop"
3169
+ title: "Upload",
3170
+ className: cn(theme.input.upload),
3171
+ onClick: () => {
3172
+ var _a;
3173
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
3174
+ },
3175
+ children: attachIcon
3136
3176
  }
3137
3177
  )
3138
- ] })
3178
+ ] }),
3179
+ isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(
3180
+ Button,
3181
+ {
3182
+ title: "Stop",
3183
+ className: cn(theme.input.stop),
3184
+ onClick: onStopMessage,
3185
+ children: stopIcon
3186
+ }
3187
+ ),
3188
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3189
+ Button,
3190
+ {
3191
+ title: "Send",
3192
+ className: cn(theme.input.send),
3193
+ onClick: handleSendMessage,
3194
+ disabled: isLoading,
3195
+ children: sendIcon
3196
+ }
3197
+ )
3139
3198
  ] });
3140
3199
  };
3141
- const SessionMessage = ({
3200
+ const SessionEmpty = ({
3201
+ children
3202
+ }) => {
3203
+ const { theme } = reactExports.useContext(ChatContext);
3204
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn(theme.empty), children });
3205
+ };
3206
+ const SessionMessagesHeader = ({ children }) => {
3207
+ const { activeSession, theme } = reactExports.useContext(ChatContext);
3208
+ const Comp = children ? Slot : "header";
3209
+ if (!activeSession) {
3210
+ return null;
3211
+ }
3212
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, { className: cn(theme.messages.header), children: children || /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3213
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: cn(theme.messages.title), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Ellipsis, { limit: 125, value: activeSession.title }) }),
3214
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3215
+ DateFormat,
3216
+ {
3217
+ className: cn(theme.messages.date),
3218
+ date: activeSession.createdAt
3219
+ }
3220
+ )
3221
+ ] }) });
3222
+ };
3223
+ const SessionMessagePanel = ({ children }) => {
3224
+ const { theme } = reactExports.useContext(ChatContext);
3225
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn(theme.messages.base), children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-full flex flex-col", children }) });
3226
+ };
3227
+ const SvgCopy = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-copy", ...props }, /* @__PURE__ */ reactExports.createElement("rect", { width: 14, height: 14, x: 8, y: 8, rx: 2, ry: 2 }), /* @__PURE__ */ reactExports.createElement("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" }));
3228
+ const SvgThumbsDown = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-thumbs-down", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "M17 14V2" }), /* @__PURE__ */ reactExports.createElement("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" }));
3229
+ const SvgThumbsUp = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-thumbs-up", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "M7 10v12" }), /* @__PURE__ */ reactExports.createElement("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" }));
3230
+ const SvgRefresh = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-refresh-ccw", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M3 3v5h5" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M16 16h5v5" }));
3231
+ const CodeHighlighter = ({ className, children }) => {
3232
+ const codeBlockRef = reactExports.useRef(null);
3233
+ reactExports.useLayoutEffect(() => {
3234
+ hljs.highlightElement(codeBlockRef.current);
3235
+ }, []);
3236
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("code", { ref: codeBlockRef, className: cn(className), children });
3237
+ };
3238
+ const TableComponent = ({ children, ...props }) => /* @__PURE__ */ jsxRuntimeExports.jsx("table", { ...props, children });
3239
+ const TableHeaderCell = ({ children, ...props }) => /* @__PURE__ */ jsxRuntimeExports.jsx("th", { ...props, children });
3240
+ const TableDataCell = ({ children, ...props }) => /* @__PURE__ */ jsxRuntimeExports.jsx("td", { ...props, children });
3241
+ const Markdown = ({
3242
+ children,
3243
+ remarkPlugins = [remarkGfm]
3244
+ }) => {
3245
+ const { theme } = reactExports.useContext(ChatContext);
3246
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
3247
+ ReactMarkdown,
3248
+ {
3249
+ remarkPlugins,
3250
+ components: {
3251
+ code: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx(
3252
+ CodeHighlighter,
3253
+ {
3254
+ ...props,
3255
+ className: cn(theme.messages.message.markdown.code)
3256
+ }
3257
+ ),
3258
+ table: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx(TableComponent, { ...props, className: cn(theme.messages.message.markdown.table) }),
3259
+ th: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx(TableHeaderCell, { ...props, className: cn(theme.messages.message.markdown.th) }),
3260
+ td: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx(TableDataCell, { ...props, className: cn(theme.messages.message.markdown.td) }),
3261
+ a: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx("a", { ...props, className: cn(theme.messages.message.markdown.a) }),
3262
+ p: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx("p", { ...props, className: cn(theme.messages.message.markdown.p) }),
3263
+ li: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { ...props, className: cn(theme.messages.message.markdown.li) }),
3264
+ ul: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { ...props, className: cn(theme.messages.message.markdown.ul) }),
3265
+ ol: (props) => /* @__PURE__ */ jsxRuntimeExports.jsx("ol", { ...props, className: cn(theme.messages.message.markdown.ol) })
3266
+ },
3267
+ children
3268
+ }
3269
+ );
3270
+ };
3271
+ const CVE_REGEX = /(CVE-(19|20)\d{2}-\d{4,7})/gi;
3272
+ function remarkCve() {
3273
+ return (tree, _file) => {
3274
+ findAndReplace(tree, [[
3275
+ CVE_REGEX,
3276
+ replaceCve
3277
+ ]]);
3278
+ };
3279
+ function replaceCve(value, id) {
3280
+ return [
3281
+ {
3282
+ type: "link",
3283
+ url: `https://cve.mitre.org/cgi-bin/cvename.cgi?name=${id}`,
3284
+ children: [
3285
+ { children: [{ type: "text", value: value.trim() }] }
3286
+ ]
3287
+ }
3288
+ ];
3289
+ }
3290
+ }
3291
+ const MessageQuestion = ({
3142
3292
  question,
3293
+ children
3294
+ }) => {
3295
+ const { theme, remarkPlugins = [remarkGfm, remarkYoutube] } = reactExports.useContext(ChatContext);
3296
+ const Comp = children ? Slot : "div";
3297
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, { className: cn(theme.messages.message.question), children: children || /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { remarkPlugins, children: question }) });
3298
+ };
3299
+ const MessageResponse = ({
3143
3300
  response,
3144
- responseTransformers = []
3301
+ isLoading,
3302
+ children
3145
3303
  }) => {
3146
- const transformResponse = (response2) => {
3147
- const applyTransformers = (index, response3) => {
3148
- if (index >= responseTransformers.length) return response3;
3149
- const transformer = responseTransformers[index];
3150
- return transformer(response3, (transformedResponse) => applyTransformers(index + 1, transformedResponse));
3151
- };
3152
- return applyTransformers(0, response2);
3153
- };
3154
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "conversation mb-2", children: [
3155
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "question font-semibold", children: question }),
3156
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "response text-gray-700", children: transformResponse(response) })
3157
- ] });
3304
+ const { theme, remarkPlugins = [remarkGfm, remarkYoutube] } = reactExports.useContext(ChatContext);
3305
+ const Comp = children ? Slot : "div";
3306
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, { className: cn(theme.messages.message.response), children: children || /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3307
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { remarkPlugins, children: response }),
3308
+ isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(
3309
+ motion.div,
3310
+ {
3311
+ className: cn(theme.messages.message.cursor),
3312
+ animate: { opacity: [1, 0] },
3313
+ transition: {
3314
+ duration: 0.7,
3315
+ repeat: Infinity,
3316
+ repeatType: "reverse"
3317
+ }
3318
+ }
3319
+ )
3320
+ ] }) });
3158
3321
  };
3159
- const SessionMessages = ({
3160
- conversations,
3161
- responseTransformers
3322
+ const SvgFile = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-file", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }));
3323
+ const MessageFile = ({
3324
+ name,
3325
+ type,
3326
+ url,
3327
+ limit = 100,
3328
+ fileIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgFile, {})
3162
3329
  }) => {
3163
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "conversations mt-2", children: conversations.map((conversation) => /* @__PURE__ */ jsxRuntimeExports.jsx(
3164
- SessionMessage,
3330
+ const { theme } = reactExports.useContext(ChatContext);
3331
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
3332
+ "figure",
3165
3333
  {
3166
- question: conversation.question,
3167
- response: conversation.response || "",
3168
- responseTransformers
3169
- },
3170
- conversation.id
3171
- )) });
3334
+ className: cn(theme.messages.message.files.file.base),
3335
+ onClick: () => {
3336
+ window.open(url, "_blank");
3337
+ },
3338
+ children: [
3339
+ fileIcon,
3340
+ (name || type) && /* @__PURE__ */ jsxRuntimeExports.jsx("figcaption", { children: name && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn(theme.messages.message.files.file.name), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Ellipsis, { value: name, limit }) }) })
3341
+ ]
3342
+ }
3343
+ );
3172
3344
  };
3173
- const SessionListItem = ({
3174
- session,
3175
- isActive,
3176
- onSelectSession,
3177
- onDeleteSession
3178
- }) => {
3345
+ const MessageFiles = ({ files, children }) => {
3346
+ const { theme } = reactExports.useContext(ChatContext);
3347
+ const Comp = children ? Slot : MessageFile;
3348
+ if (!files || files.length === 0) {
3349
+ return null;
3350
+ }
3351
+ return files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn(theme.messages.message.files.base), children: files.map((file, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, { ...file, children }, index)) });
3352
+ };
3353
+ const MessageSource = ({ title, url, image, limit = 50 }) => {
3354
+ const { theme } = reactExports.useContext(ChatContext);
3179
3355
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
3180
- "div",
3356
+ "figure",
3181
3357
  {
3182
- className: `session border p-4 mb-4 rounded ${isActive ? "bg-blue-100" : "bg-white"} cursor-pointer`,
3183
- onClick: () => onSelectSession && onSelectSession(session.id),
3358
+ className: cn(theme.messages.message.sources.source.base),
3359
+ onClick: () => {
3360
+ if (url) {
3361
+ window.open(url, "_blank");
3362
+ }
3363
+ },
3184
3364
  children: [
3185
- /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold", children: session.title }),
3186
- onDeleteSession && /* @__PURE__ */ jsxRuntimeExports.jsx(
3187
- "button",
3188
- {
3189
- className: "mt-2 text-red-500 hover:text-red-700",
3190
- onClick: (e) => {
3191
- e.stopPropagation();
3192
- onDeleteSession(session.id);
3193
- },
3194
- children: "Delete"
3195
- }
3196
- )
3365
+ image && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: image, alt: title, className: cn(theme.messages.message.sources.source.image) }),
3366
+ (title || url) && /* @__PURE__ */ jsxRuntimeExports.jsxs("figcaption", { children: [
3367
+ title && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn(theme.messages.message.sources.source.title), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Ellipsis, { value: title, limit }) }),
3368
+ url && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: cn(theme.messages.message.sources.source.url), children: url })
3369
+ ] })
3197
3370
  ]
3198
3371
  }
3199
3372
  );
3200
3373
  };
3201
- const SessionsList = ({
3202
- sessions,
3203
- activeSessionId,
3204
- onSelectSession,
3205
- onDeleteSession
3374
+ const MessageSources = ({
3375
+ sources,
3376
+ children
3206
3377
  }) => {
3207
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: sessions.map((session) => /* @__PURE__ */ jsxRuntimeExports.jsx(
3208
- SessionListItem,
3209
- {
3210
- session,
3211
- isActive: session.id === activeSessionId,
3212
- onSelectSession,
3213
- onDeleteSession
3214
- },
3215
- session.id
3216
- )) });
3378
+ const { theme } = reactExports.useContext(ChatContext);
3379
+ const Comp = children ? Slot : MessageSource;
3380
+ if (!sources || sources.length === 0) {
3381
+ return null;
3382
+ }
3383
+ return sources && sources.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn(theme.messages.message.sources.base), children: sources.map((source, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, { ...source, children }, index)) });
3384
+ };
3385
+ const MessageActions = ({
3386
+ children,
3387
+ ...props
3388
+ }) => {
3389
+ const { theme } = reactExports.useContext(ChatContext);
3390
+ const {
3391
+ question,
3392
+ response,
3393
+ copyIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgCopy, {}),
3394
+ thumbsUpIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgThumbsUp, {}),
3395
+ thumbsDownIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgThumbsDown, {}),
3396
+ refreshIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgRefresh, {}),
3397
+ onCopy,
3398
+ onUpvote,
3399
+ onDownvote,
3400
+ onRefresh
3401
+ } = props;
3402
+ const Comp = children ? Slot : "div";
3403
+ const handleCopy = (text) => {
3404
+ navigator.clipboard.writeText(text).then(() => {
3405
+ console.log("Text copied to clipboard");
3406
+ }).catch((err) => {
3407
+ console.error("Could not copy text: ", err);
3408
+ });
3409
+ };
3410
+ return (copyIcon || thumbsDownIcon || thumbsUpIcon || refreshIcon) && /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, { className: cn(theme.messages.message.footer.base), children: children || /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3411
+ copyIcon && /* @__PURE__ */ jsxRuntimeExports.jsx(
3412
+ IconButton,
3413
+ {
3414
+ variant: "text",
3415
+ disablePadding: true,
3416
+ title: "Copy question and response",
3417
+ className: cn(theme.messages.message.footer.copy),
3418
+ onClick: onCopy ? onCopy : () => handleCopy(`${question}
3419
+ ${response}`),
3420
+ children: copyIcon
3421
+ }
3422
+ ),
3423
+ thumbsUpIcon && /* @__PURE__ */ jsxRuntimeExports.jsx(
3424
+ IconButton,
3425
+ {
3426
+ variant: "text",
3427
+ disablePadding: true,
3428
+ title: "Upvote",
3429
+ className: cn(theme.messages.message.footer.upvote),
3430
+ onClick: onUpvote,
3431
+ children: thumbsUpIcon
3432
+ }
3433
+ ),
3434
+ thumbsDownIcon && /* @__PURE__ */ jsxRuntimeExports.jsx(
3435
+ IconButton,
3436
+ {
3437
+ variant: "text",
3438
+ disablePadding: true,
3439
+ title: "Downvote",
3440
+ className: cn(theme.messages.message.footer.downvote),
3441
+ onClick: onDownvote,
3442
+ children: thumbsDownIcon
3443
+ }
3444
+ ),
3445
+ refreshIcon && /* @__PURE__ */ jsxRuntimeExports.jsx(
3446
+ IconButton,
3447
+ {
3448
+ variant: "text",
3449
+ disablePadding: true,
3450
+ title: "Refresh",
3451
+ className: cn(theme.messages.message.footer.refresh),
3452
+ onClick: onRefresh,
3453
+ children: refreshIcon
3454
+ }
3455
+ )
3456
+ ] }) });
3457
+ };
3458
+ const messageVariants = {
3459
+ hidden: {
3460
+ opacity: 0,
3461
+ y: 20
3462
+ },
3463
+ visible: {
3464
+ opacity: 1,
3465
+ y: 0,
3466
+ transition: {
3467
+ duration: 0.4
3468
+ }
3469
+ }
3217
3470
  };
3218
- const Sessions = ({
3219
- viewType,
3471
+ const SessionMessage = ({
3472
+ conversation,
3473
+ isLast,
3474
+ children
3475
+ }) => {
3476
+ const { theme, isLoading } = reactExports.useContext(ChatContext);
3477
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(motion.div, { variants: messageVariants, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { className: cn(theme.messages.message.base), children: children || /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3478
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MessageFiles, { files: conversation.files }),
3479
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MessageQuestion, { question: conversation.question }),
3480
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3481
+ MessageResponse,
3482
+ {
3483
+ response: conversation.response,
3484
+ isLoading: isLast && isLoading
3485
+ }
3486
+ ),
3487
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSources, { sources: conversation.sources }),
3488
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3489
+ MessageActions,
3490
+ {
3491
+ question: conversation.question,
3492
+ response: conversation.response,
3493
+ copyIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(SvgCopy, {}),
3494
+ thumbsUpIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(SvgThumbsUp, {}),
3495
+ thumbsDownIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(SvgThumbsDown, {}),
3496
+ refreshIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(SvgRefresh, {})
3497
+ }
3498
+ )
3499
+ ] }) }) }, conversation.id);
3500
+ };
3501
+ const containerVariants = {
3502
+ hidden: {},
3503
+ visible: {
3504
+ transition: {
3505
+ staggerChildren: 0.07
3506
+ }
3507
+ }
3508
+ };
3509
+ const SessionMessages = ({
3510
+ children,
3511
+ newSessionContent,
3512
+ limit = 10,
3513
+ showMoreText = "Show more"
3514
+ }) => {
3515
+ const { activeSession, theme, isLoading } = reactExports.useContext(ChatContext);
3516
+ const contentRef = reactExports.useRef(null);
3517
+ const [isAnimating, setIsAnimating] = reactExports.useState(true);
3518
+ reactExports.useEffect(() => {
3519
+ if (contentRef.current) {
3520
+ requestAnimationFrame(
3521
+ () => contentRef.current.scrollTop = contentRef.current.scrollHeight
3522
+ );
3523
+ }
3524
+ }, [activeSession, isAnimating]);
3525
+ function handleShowMore() {
3526
+ showNext(10);
3527
+ requestAnimationFrame(() => contentRef.current.scrollTop = 0);
3528
+ }
3529
+ const reversedConvos = reactExports.useMemo(
3530
+ () => [...(activeSession == null ? void 0 : activeSession.conversations) ?? []].reverse(),
3531
+ [activeSession]
3532
+ );
3533
+ const { data, hasMore, showNext } = useInfinityList({
3534
+ items: reversedConvos,
3535
+ limit
3536
+ });
3537
+ const reReversedConvo = reactExports.useMemo(() => [...data].reverse(), [data]);
3538
+ const convosToRender = limit ? reReversedConvo : activeSession == null ? void 0 : activeSession.conversations;
3539
+ if (!activeSession) {
3540
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(SessionEmpty, { children: newSessionContent });
3541
+ }
3542
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn(theme.messages.content), ref: contentRef, children: [
3543
+ hasMore && /* @__PURE__ */ jsxRuntimeExports.jsx(
3544
+ Button,
3545
+ {
3546
+ variant: "outline",
3547
+ className: cn(theme.messages.showMore),
3548
+ fullWidth: true,
3549
+ onClick: handleShowMore,
3550
+ children: showMoreText
3551
+ }
3552
+ ),
3553
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AnimatePresence, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3554
+ motion.div,
3555
+ {
3556
+ variants: containerVariants,
3557
+ initial: "hidden",
3558
+ animate: "visible",
3559
+ onAnimationComplete: () => {
3560
+ setIsAnimating(false);
3561
+ },
3562
+ children: children(convosToRender)
3563
+ },
3564
+ activeSession == null ? void 0 : activeSession.id
3565
+ ) })
3566
+ ] });
3567
+ };
3568
+ const chatTheme = {
3569
+ base: "text-white",
3570
+ console: "flex w-full gap-5 h-full",
3571
+ companion: "p-4",
3572
+ empty: "text-center flex-1",
3573
+ sessions: {
3574
+ base: "overflow-auto min-w-[150px] w-[30%] max-w-[300px] bg-[#11111F] p-5 rounded",
3575
+ group: "text-xs text-gray-400 mt-4",
3576
+ create: "mb-4",
3577
+ session: {
3578
+ base: "",
3579
+ active: " text-primary",
3580
+ delete: "[&>svg]:w-4 [&>svg]:h-4 opacity-50"
3581
+ }
3582
+ },
3583
+ messages: {
3584
+ base: "flex flex-col flex-1 overflow-hidden",
3585
+ title: "text-2xl font-bold",
3586
+ date: "text-sm whitespace-nowrap pt-2",
3587
+ content: "mt-2 flex-1 overflow-auto",
3588
+ header: "flex justify-between items-start gap-2",
3589
+ showMore: "mb-4",
3590
+ message: {
3591
+ base: "mb-6 flex flex-col p-5 rounded",
3592
+ question: "font-semibold text-gray-400 mb-1",
3593
+ response: "",
3594
+ cursor: "inline-block w-1 h-4 bg-current",
3595
+ files: {
3596
+ base: "mb-2 flex gap-3",
3597
+ file: {
3598
+ base: "flex gap-2 border border-gray-700 p-2 rounded cursor-pointer",
3599
+ name: "text-sm"
3600
+ }
3601
+ },
3602
+ sources: {
3603
+ base: "my-4 flex gap-3",
3604
+ source: {
3605
+ base: "flex gap-2 border border-gray-700 p-2 rounded cursor-pointer",
3606
+ image: "w-6 h-6 rounded-md",
3607
+ title: "text-md block",
3608
+ url: "text-sm text-blue-700 underline"
3609
+ }
3610
+ },
3611
+ markdown: {
3612
+ p: "mb-2",
3613
+ a: "text-blue-700 underline",
3614
+ table: "table-auto w-full m-2",
3615
+ th: "px-4 py-2 text-left font-bold border-b border-gray-500",
3616
+ td: "px-4 py-2",
3617
+ code: "m-2 rounded",
3618
+ li: "mb-2 ml-6",
3619
+ ul: "mb-4 list-disc",
3620
+ ol: "mb-4 list-decimal"
3621
+ },
3622
+ footer: {
3623
+ base: "mt-3 flex gap-3",
3624
+ copy: "[&>svg]:w-4 [&>svg]:h-4 opacity-50",
3625
+ upvote: "[&>svg]:w-4 [&>svg]:h-4 opacity-50",
3626
+ downvote: "[&>svg]:w-4 [&>svg]:h-4 opacity-50",
3627
+ refresh: "[&>svg]:w-4 [&>svg]:h-4 opacity-50"
3628
+ }
3629
+ }
3630
+ },
3631
+ input: {
3632
+ base: "flex mt-4",
3633
+ upload: "px-4 py-2 text-white",
3634
+ input: "w-full",
3635
+ send: "px-4 py-2 text-white",
3636
+ stop: "px-4 py-2 bg-red-500 text-white rounded hover:bg-red-700"
3637
+ }
3638
+ };
3639
+ const Chat = ({
3640
+ children,
3641
+ viewType = "console",
3220
3642
  sessions,
3221
3643
  onSelectSession,
3222
3644
  onDeleteSession,
3223
3645
  isLoading,
3224
3646
  activeSessionId,
3225
- responseTransformers = [],
3226
- inputPlaceholder = "Type your message here...",
3227
- onSendMessage,
3228
- onStopMessage
3647
+ theme: customTheme = chatTheme,
3648
+ onNewSession,
3649
+ remarkPlugins,
3650
+ style,
3651
+ className
3229
3652
  }) => {
3230
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `sessions-container ${viewType === "companion" ? "p-4" : "p-8"}`, children: isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3231
- /* @__PURE__ */ jsxRuntimeExports.jsx(
3232
- SessionsList,
3233
- {
3234
- sessions,
3235
- activeSessionId,
3236
- onSelectSession,
3237
- onDeleteSession
3653
+ const theme = useComponentTheme("chat", customTheme);
3654
+ const [internalActiveSessionID, setInternalActiveSessionID] = reactExports.useState(activeSessionId);
3655
+ reactExports.useEffect(() => {
3656
+ setInternalActiveSessionID(activeSessionId);
3657
+ }, [activeSessionId]);
3658
+ const handleSelectSession = reactExports.useCallback(
3659
+ (sessionId) => {
3660
+ setInternalActiveSessionID(sessionId);
3661
+ onSelectSession == null ? void 0 : onSelectSession(sessionId);
3662
+ },
3663
+ [onSelectSession]
3664
+ );
3665
+ const handleDeleteSession = reactExports.useCallback(
3666
+ (sessionId) => {
3667
+ setInternalActiveSessionID(void 0);
3668
+ onDeleteSession == null ? void 0 : onDeleteSession(sessionId);
3669
+ },
3670
+ [onDeleteSession]
3671
+ );
3672
+ const handleCreateNewSession = reactExports.useCallback(() => {
3673
+ setInternalActiveSessionID(void 0);
3674
+ onNewSession == null ? void 0 : onNewSession();
3675
+ }, [onNewSession]);
3676
+ useHotkeys([
3677
+ {
3678
+ name: "Create new session",
3679
+ category: "Chat",
3680
+ keys: "meta+shift+s",
3681
+ callback: (event) => {
3682
+ event.preventDefault();
3683
+ handleCreateNewSession();
3238
3684
  }
3239
- ),
3240
- activeSessionId && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "active-session mt-4", children: sessions.filter((session) => session.id === activeSessionId).map((session) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3241
- /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold", children: session.title }),
3242
- /* @__PURE__ */ jsxRuntimeExports.jsx(
3243
- SessionMessages,
3244
- {
3245
- conversations: session.conversations,
3246
- responseTransformers
3247
- }
3248
- ),
3249
- /* @__PURE__ */ jsxRuntimeExports.jsx(
3250
- SessionInput,
3685
+ }
3686
+ ]);
3687
+ const activeSession = reactExports.useMemo(
3688
+ () => sessions.find((session) => session.id === internalActiveSessionID),
3689
+ [sessions, internalActiveSessionID]
3690
+ );
3691
+ const contextValue = reactExports.useMemo(
3692
+ () => ({
3693
+ sessions,
3694
+ activeSession,
3695
+ remarkPlugins,
3696
+ theme,
3697
+ isLoading,
3698
+ activeSessionId: internalActiveSessionID,
3699
+ selectSession: handleSelectSession,
3700
+ deleteSession: handleDeleteSession,
3701
+ createSession: handleCreateNewSession
3702
+ }),
3703
+ [
3704
+ isLoading,
3705
+ theme,
3706
+ remarkPlugins,
3707
+ sessions,
3708
+ activeSession,
3709
+ internalActiveSessionID,
3710
+ handleSelectSession,
3711
+ handleDeleteSession,
3712
+ handleCreateNewSession
3713
+ ]
3714
+ );
3715
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(ChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3716
+ "div",
3717
+ {
3718
+ className: cn(className, theme.base, {
3719
+ [theme.companion]: viewType === "companion",
3720
+ [theme.console]: viewType === "console"
3721
+ }),
3722
+ style,
3723
+ children
3724
+ }
3725
+ ) });
3726
+ };
3727
+ const SessionsList = ({ children }) => {
3728
+ const { theme } = reactExports.useContext(ChatContext);
3729
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(List, { className: cn(theme.sessions.base), children });
3730
+ };
3731
+ const SvgTrash = (props) => /* @__PURE__ */ reactExports.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1, strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-trash-2", ...props }, /* @__PURE__ */ reactExports.createElement("path", { d: "M3 6h18" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), /* @__PURE__ */ reactExports.createElement("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }), /* @__PURE__ */ reactExports.createElement("line", { x1: 10, x2: 10, y1: 11, y2: 17 }), /* @__PURE__ */ reactExports.createElement("line", { x1: 14, x2: 14, y1: 11, y2: 17 }));
3732
+ const SessionListItem = ({
3733
+ children,
3734
+ session,
3735
+ deletable = true,
3736
+ limit = 100,
3737
+ deleteIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(SvgTrash, {})
3738
+ }) => {
3739
+ const { activeSessionId, selectSession, deleteSession, theme } = reactExports.useContext(ChatContext);
3740
+ const Comp = children ? Slot : ListItem;
3741
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
3742
+ Comp,
3743
+ {
3744
+ dense: true,
3745
+ disableGutters: true,
3746
+ active: session.id === activeSessionId,
3747
+ className: cn(theme.sessions.session.base, {
3748
+ [theme.sessions.session.active]: session.id === activeSessionId
3749
+ }),
3750
+ onClick: () => selectSession == null ? void 0 : selectSession(session.id),
3751
+ end: /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: deletable && /* @__PURE__ */ jsxRuntimeExports.jsx(
3752
+ IconButton,
3251
3753
  {
3252
- inputPlaceholder,
3253
- isLoading,
3254
- onSendMessage,
3255
- onStopMessage
3754
+ size: "small",
3755
+ variant: "text",
3756
+ onClick: (e) => {
3757
+ e.stopPropagation();
3758
+ deleteSession(session.id);
3759
+ },
3760
+ className: cn(theme.sessions.session.delete),
3761
+ children: deleteIcon
3256
3762
  }
3257
- )
3258
- ] }, session.id)) })
3259
- ] }) });
3763
+ ) }),
3764
+ children: children || /* @__PURE__ */ jsxRuntimeExports.jsx(Ellipsis, { value: session.title, limit })
3765
+ }
3766
+ );
3767
+ };
3768
+ const NewSessionButton = ({
3769
+ children,
3770
+ newSessionText = "New Session"
3771
+ }) => {
3772
+ const { theme, createSession } = reactExports.useContext(ChatContext);
3773
+ const Comp = children ? Slot : Button;
3774
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
3775
+ Comp,
3776
+ {
3777
+ fullWidth: true,
3778
+ disableMargins: true,
3779
+ color: "primary",
3780
+ className: cn(theme.sessions.create),
3781
+ onClick: createSession,
3782
+ children: children || newSessionText
3783
+ }
3784
+ );
3785
+ };
3786
+ const sortOrder = [
3787
+ "Today",
3788
+ "Yesterday",
3789
+ "Last Week",
3790
+ "Last Month",
3791
+ "January",
3792
+ "February",
3793
+ "March",
3794
+ "April",
3795
+ "May",
3796
+ "June",
3797
+ "July",
3798
+ "August",
3799
+ "September",
3800
+ "October",
3801
+ "November",
3802
+ "December",
3803
+ "Last Year"
3804
+ ];
3805
+ function groupSessionsByDate(sessions) {
3806
+ const grouped = {};
3807
+ sessions.forEach((session) => {
3808
+ const createdAt = new Date(session.createdAt);
3809
+ if (isToday(createdAt)) {
3810
+ if (!grouped["Today"]) grouped["Today"] = [];
3811
+ grouped["Today"].push(session);
3812
+ } else if (isYesterday(createdAt)) {
3813
+ if (!grouped["Yesterday"]) grouped["Yesterday"] = [];
3814
+ grouped["Yesterday"].push(session);
3815
+ } else if (isThisWeek(createdAt)) {
3816
+ if (!grouped["Last Week"]) grouped["Last Week"] = [];
3817
+ grouped["Last Week"].push(session);
3818
+ } else if (isThisMonth(createdAt)) {
3819
+ if (!grouped["Last Month"]) grouped["Last Month"] = [];
3820
+ grouped["Last Month"].push(session);
3821
+ } else if (isThisYear(createdAt)) {
3822
+ const monthName = format(createdAt, "MMMM");
3823
+ if (!grouped[monthName]) grouped[monthName] = [];
3824
+ grouped[monthName].push(session);
3825
+ } else {
3826
+ if (!grouped["Last Year"]) grouped["Last Year"] = [];
3827
+ grouped["Last Year"].push(session);
3828
+ }
3829
+ });
3830
+ Object.keys(grouped).forEach((key) => {
3831
+ if (grouped[key].length === 0) {
3832
+ delete grouped[key];
3833
+ }
3834
+ });
3835
+ const sortedGroups = Object.keys(grouped).sort(
3836
+ (a, b) => sortOrder.indexOf(a) - sortOrder.indexOf(b)
3837
+ );
3838
+ return sortedGroups.map((heading) => ({
3839
+ heading,
3840
+ sessions: grouped[heading].sort(
3841
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
3842
+ )
3843
+ }));
3844
+ }
3845
+ const SessionGroups = ({ children }) => {
3846
+ const { sessions } = reactExports.useContext(ChatContext);
3847
+ const groups = reactExports.useMemo(() => groupSessionsByDate(sessions), [sessions]);
3848
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children(groups) });
3849
+ };
3850
+ const SessionsGroup = ({
3851
+ heading,
3852
+ children
3853
+ }) => {
3854
+ const { theme } = reactExports.useContext(ChatContext);
3855
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3856
+ heading && /* @__PURE__ */ jsxRuntimeExports.jsx(
3857
+ ListItem,
3858
+ {
3859
+ disableGutters: true,
3860
+ disablePadding: true,
3861
+ className: cn(theme.sessions.group),
3862
+ children: heading
3863
+ }
3864
+ ),
3865
+ children
3866
+ ] });
3260
3867
  };
3261
3868
  export {
3262
- SessionInput,
3869
+ Chat,
3870
+ ChatContext,
3871
+ ChatInput,
3872
+ CodeHighlighter,
3873
+ Markdown,
3874
+ MessageActions,
3875
+ MessageFile,
3876
+ MessageFiles,
3877
+ MessageQuestion,
3878
+ MessageResponse,
3879
+ MessageSource,
3880
+ MessageSources,
3881
+ NewSessionButton,
3882
+ SessionEmpty,
3883
+ SessionGroups,
3263
3884
  SessionListItem,
3264
3885
  SessionMessage,
3886
+ SessionMessagePanel,
3265
3887
  SessionMessages,
3266
- Sessions,
3888
+ SessionMessagesHeader,
3889
+ SessionsGroup,
3267
3890
  SessionsList,
3268
- useLlm
3891
+ TableComponent,
3892
+ TableDataCell,
3893
+ TableHeaderCell,
3894
+ chatTheme,
3895
+ remarkCve
3269
3896
  };
3270
3897
  //# sourceMappingURL=index.js.map