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