llmasaservice-ui 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.css CHANGED
@@ -306,3 +306,26 @@
306
306
  .side-panel-dark .scroll-button:hover {
307
307
  background-color: #0056b3;
308
308
  }
309
+ .chat-status {
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ padding: 10px;
314
+ border-radius: 20px;
315
+ background-color: #f0f0f0;
316
+ }
317
+ .loading-dots {
318
+ font-size: 20px;
319
+ animation: blink 1s linear infinite;
320
+ }
321
+ @keyframes blink {
322
+ 0% {
323
+ opacity: 1;
324
+ }
325
+ 50% {
326
+ opacity: 0;
327
+ }
328
+ 100% {
329
+ opacity: 1;
330
+ }
331
+ }
package/dist/index.js CHANGED
@@ -148,6 +148,11 @@ var ChatPanel = ({
148
148
  messagesAndHistory.push({ role: "user", content: prompt });
149
149
  messagesAndHistory.push({ role: "assistant", content: response2 });
150
150
  });
151
+ setHistory((prevHistory) => {
152
+ return __spreadProps(__spreadValues({}, prevHistory), {
153
+ [nextPrompt != null ? nextPrompt : ""]: ""
154
+ });
155
+ });
151
156
  const controller = new AbortController();
152
157
  send(nextPrompt, messagesAndHistory, true, true, null, controller);
153
158
  setLastPrompt(nextPrompt);
@@ -169,7 +174,7 @@ var ChatPanel = ({
169
174
  className: "side-panel" + (theme === "light" ? "" : "-dark")
170
175
  },
171
176
  /* @__PURE__ */ import_react.default.createElement("div", { className: "title" }, title),
172
- /* @__PURE__ */ import_react.default.createElement("div", { className: "responseArea", ref: responseAreaRef }, isLoading ? /* @__PURE__ */ import_react.default.createElement("div", { className: "loading-text" }, "loading...") : null, initialMessage && initialMessage !== "" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "history-entry" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "response" }, /* @__PURE__ */ import_react.default.createElement(import_react_markdown.default, { className: markdownClass }, initialMessage))) : null, Object.entries(history).map(([prompt, response2], index) => /* @__PURE__ */ import_react.default.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ import_react.default.createElement("div", { className: "prompt" }, prompt), /* @__PURE__ */ import_react.default.createElement("div", { className: "response" }, /* @__PURE__ */ import_react.default.createElement(import_react_markdown.default, { className: markdownClass }, response2), /* @__PURE__ */ import_react.default.createElement("div", { className: "button-container" }, /* @__PURE__ */ import_react.default.createElement(
177
+ /* @__PURE__ */ import_react.default.createElement("div", { className: "responseArea", ref: responseAreaRef }, initialMessage && initialMessage !== "" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "history-entry" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "response" }, /* @__PURE__ */ import_react.default.createElement(import_react_markdown.default, { className: markdownClass }, initialMessage))) : null, Object.entries(history).map(([prompt, response2], index) => /* @__PURE__ */ import_react.default.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ import_react.default.createElement("div", { className: "prompt" }, prompt), /* @__PURE__ */ import_react.default.createElement("div", { className: "response" }, index === Object.keys(history).length - 1 && isLoading ? /* @__PURE__ */ import_react.default.createElement("div", { className: "loading-text" }, "loading...") : null, /* @__PURE__ */ import_react.default.createElement(import_react_markdown.default, { className: markdownClass }, response2), /* @__PURE__ */ import_react.default.createElement("div", { className: "button-container" }, /* @__PURE__ */ import_react.default.createElement(
173
178
  "button",
174
179
  {
175
180
  className: "copy-button",
package/dist/index.mjs CHANGED
@@ -115,6 +115,11 @@ var ChatPanel = ({
115
115
  messagesAndHistory.push({ role: "user", content: prompt });
116
116
  messagesAndHistory.push({ role: "assistant", content: response2 });
117
117
  });
118
+ setHistory((prevHistory) => {
119
+ return __spreadProps(__spreadValues({}, prevHistory), {
120
+ [nextPrompt != null ? nextPrompt : ""]: ""
121
+ });
122
+ });
118
123
  const controller = new AbortController();
119
124
  send(nextPrompt, messagesAndHistory, true, true, null, controller);
120
125
  setLastPrompt(nextPrompt);
@@ -136,7 +141,7 @@ var ChatPanel = ({
136
141
  className: "side-panel" + (theme === "light" ? "" : "-dark")
137
142
  },
138
143
  /* @__PURE__ */ React.createElement("div", { className: "title" }, title),
139
- /* @__PURE__ */ React.createElement("div", { className: "responseArea", ref: responseAreaRef }, isLoading ? /* @__PURE__ */ React.createElement("div", { className: "loading-text" }, "loading...") : null, initialMessage && initialMessage !== "" ? /* @__PURE__ */ React.createElement("div", { className: "history-entry" }, /* @__PURE__ */ React.createElement("div", { className: "response" }, /* @__PURE__ */ React.createElement(ReactMarkdown, { className: markdownClass }, initialMessage))) : null, Object.entries(history).map(([prompt, response2], index) => /* @__PURE__ */ React.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ React.createElement("div", { className: "prompt" }, prompt), /* @__PURE__ */ React.createElement("div", { className: "response" }, /* @__PURE__ */ React.createElement(ReactMarkdown, { className: markdownClass }, response2), /* @__PURE__ */ React.createElement("div", { className: "button-container" }, /* @__PURE__ */ React.createElement(
144
+ /* @__PURE__ */ React.createElement("div", { className: "responseArea", ref: responseAreaRef }, initialMessage && initialMessage !== "" ? /* @__PURE__ */ React.createElement("div", { className: "history-entry" }, /* @__PURE__ */ React.createElement("div", { className: "response" }, /* @__PURE__ */ React.createElement(ReactMarkdown, { className: markdownClass }, initialMessage))) : null, Object.entries(history).map(([prompt, response2], index) => /* @__PURE__ */ React.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ React.createElement("div", { className: "prompt" }, prompt), /* @__PURE__ */ React.createElement("div", { className: "response" }, index === Object.keys(history).length - 1 && isLoading ? /* @__PURE__ */ React.createElement("div", { className: "loading-text" }, "loading...") : null, /* @__PURE__ */ React.createElement(ReactMarkdown, { className: markdownClass }, response2), /* @__PURE__ */ React.createElement("div", { className: "button-container" }, /* @__PURE__ */ React.createElement(
140
145
  "button",
141
146
  {
142
147
  className: "copy-button",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llmasaservice-ui",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Prebuilt UI components for LLMAsAService.io",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/ChatPanel.css CHANGED
@@ -321,3 +321,29 @@
321
321
  .side-panel-dark .scroll-button:hover {
322
322
  background-color: #0056b3;
323
323
  }
324
+
325
+ .chat-status {
326
+ display: flex;
327
+ align-items: center;
328
+ justify-content: center;
329
+ padding: 10px;
330
+ border-radius: 20px;
331
+ background-color: #f0f0f0;
332
+ }
333
+
334
+ .loading-dots {
335
+ font-size: 20px;
336
+ animation: blink 1s linear infinite;
337
+ }
338
+
339
+ @keyframes blink {
340
+ 0% {
341
+ opacity: 1;
342
+ }
343
+ 50% {
344
+ opacity: 0;
345
+ }
346
+ 100% {
347
+ opacity: 1;
348
+ }
349
+ }
package/src/ChatPanel.tsx CHANGED
@@ -2,6 +2,7 @@ import { LLMAsAServiceCustomer, useLLM } from "llmasaservice-client";
2
2
  import React, { useEffect, useRef, useState } from "react";
3
3
  import ReactMarkdown from "react-markdown";
4
4
  import "./ChatPanel.css";
5
+ import ChatStatus from "./ChatStatus";
5
6
 
6
7
  export interface ChatPanelProps {
7
8
  project_id: string;
@@ -136,6 +137,14 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
136
137
  messagesAndHistory.push({ role: "assistant", content: response });
137
138
  });
138
139
 
140
+ // set the history prompt with the about to be sent prompt
141
+ setHistory((prevHistory) => {
142
+ return {
143
+ ...prevHistory,
144
+ [nextPrompt ?? ""]: "",
145
+ };
146
+ });
147
+
139
148
  const controller = new AbortController();
140
149
  send(nextPrompt, messagesAndHistory, true, true, null, controller);
141
150
 
@@ -161,7 +170,6 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
161
170
  >
162
171
  <div className="title">{title}</div>
163
172
  <div className="responseArea" ref={responseAreaRef}>
164
- {isLoading ? <div className="loading-text">loading...</div> : null}
165
173
  {initialMessage && initialMessage !== "" ? (
166
174
  <div className="history-entry">
167
175
  <div className="response">
@@ -176,7 +184,11 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
176
184
  {hideInitialPrompt && index === 0 ? null : (
177
185
  <div className="prompt">{prompt}</div>
178
186
  )}
187
+
179
188
  <div className="response">
189
+ {index === Object.keys(history).length - 1 && isLoading ? (
190
+ <div className="loading-text">loading...</div>
191
+ ) : null}
180
192
  <ReactMarkdown className={markdownClass}>
181
193
  {response}
182
194
  </ReactMarkdown>
@@ -0,0 +1,40 @@
1
+ import React, { useState, useEffect } from 'react';
2
+
3
+ interface ChatStatusProps {
4
+ isLoading: boolean;
5
+ }
6
+
7
+ const ChatStatus: React.FC<ChatStatusProps> = ({ isLoading }) => {
8
+ const [dots, setDots] = useState<string[]>(['', '', '']);
9
+ const [dotIndex, setDotIndex] = useState<number>(0);
10
+
11
+ useEffect(() => {
12
+ if (isLoading) {
13
+ const interval = setInterval(() => {
14
+ setDots((prevDots) => {
15
+ const newDots = [...prevDots];
16
+ newDots[dotIndex] = '.';
17
+ setDotIndex((prevIndex) => (prevIndex + 1) % 3);
18
+ return newDots;
19
+ });
20
+ }, 500);
21
+
22
+ return () => clearInterval(interval);
23
+ } else {
24
+ setDots(['', '', '']);
25
+ setDotIndex(0);
26
+ }
27
+ }, [isLoading, dotIndex]);
28
+
29
+ return (
30
+ <div className="chat-status">
31
+ {isLoading ? (
32
+ <span className="loading-dots">
33
+ {dots.join('')}
34
+ </span>
35
+ ) : null}
36
+ </div>
37
+ );
38
+ };
39
+
40
+ export default ChatStatus;