llmasaservice-ui 0.2.3 → 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
@@ -174,7 +174,7 @@ var ChatPanel = ({
174
174
  className: "side-panel" + (theme === "light" ? "" : "-dark")
175
175
  },
176
176
  /* @__PURE__ */ import_react.default.createElement("div", { className: "title" }, title),
177
- /* @__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(
178
178
  "button",
179
179
  {
180
180
  className: "copy-button",
package/dist/index.mjs CHANGED
@@ -141,7 +141,7 @@ var ChatPanel = ({
141
141
  className: "side-panel" + (theme === "light" ? "" : "-dark")
142
142
  },
143
143
  /* @__PURE__ */ React.createElement("div", { className: "title" }, title),
144
- /* @__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(
145
145
  "button",
146
146
  {
147
147
  className: "copy-button",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llmasaservice-ui",
3
- "version": "0.2.3",
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;
@@ -169,7 +170,6 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
169
170
  >
170
171
  <div className="title">{title}</div>
171
172
  <div className="responseArea" ref={responseAreaRef}>
172
- {isLoading ? <div className="loading-text">loading...</div> : null}
173
173
  {initialMessage && initialMessage !== "" ? (
174
174
  <div className="history-entry">
175
175
  <div className="response">
@@ -184,7 +184,11 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
184
184
  {hideInitialPrompt && index === 0 ? null : (
185
185
  <div className="prompt">{prompt}</div>
186
186
  )}
187
+
187
188
  <div className="response">
189
+ {index === Object.keys(history).length - 1 && isLoading ? (
190
+ <div className="loading-text">loading...</div>
191
+ ) : null}
188
192
  <ReactMarkdown className={markdownClass}>
189
193
  {response}
190
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;