llmasaservice-ui 0.2.5 → 0.2.6

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.js CHANGED
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
22
22
  return a;
23
23
  };
24
24
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __objRest = (source, exclude) => {
26
+ var target = {};
27
+ for (var prop in source)
28
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
+ target[prop] = source[prop];
30
+ if (source != null && __getOwnPropSymbols)
31
+ for (var prop of __getOwnPropSymbols(source)) {
32
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
+ target[prop] = source[prop];
34
+ }
35
+ return target;
36
+ };
25
37
  var __export = (target, all) => {
26
38
  for (var name in all)
27
39
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -56,6 +68,8 @@ var import_llmasaservice_client = require("llmasaservice-client");
56
68
  var import_react = __toESM(require("react"));
57
69
  var import_react_markdown = __toESM(require("react-markdown"));
58
70
  var import_remark_gfm = __toESM(require("remark-gfm"));
71
+ var import_react_syntax_highlighter = require("react-syntax-highlighter");
72
+ var import_prism = require("react-syntax-highlighter/dist/cjs/styles/prism");
59
73
  var ChatPanel = ({
60
74
  project_id,
61
75
  initialPrompt = "",
@@ -168,6 +182,63 @@ var ChatPanel = ({
168
182
  var _a;
169
183
  (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
170
184
  };
185
+ const CodeBlock = (_a) => {
186
+ var _b = _a, { node, className, children, style } = _b, props = __objRest(_b, ["node", "className", "children", "style"]);
187
+ console.log("CodeBlock", className, children, style, props);
188
+ const match = /language-(\w+)/.exec(className || "");
189
+ return match ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(
190
+ "div",
191
+ {
192
+ style: {
193
+ border: 0,
194
+ padding: 0,
195
+ height: "16px",
196
+ display: "flex",
197
+ justifyContent: "space-between",
198
+ alignItems: "center"
199
+ }
200
+ },
201
+ /* @__PURE__ */ import_react.default.createElement("span", null, match ? match[1] : "Unknown"),
202
+ /* @__PURE__ */ import_react.default.createElement(
203
+ "button",
204
+ {
205
+ onClick: () => copyToClipboard(children),
206
+ className: "copy-button"
207
+ },
208
+ /* @__PURE__ */ import_react.default.createElement(
209
+ "svg",
210
+ {
211
+ xmlns: "http://www.w3.org/2000/svg",
212
+ viewBox: "0 0 320 320",
213
+ fill: "currentColor",
214
+ className: "icon-svg"
215
+ },
216
+ /* @__PURE__ */ import_react.default.createElement(
217
+ "path",
218
+ {
219
+ d: "M35,270h45v45c0,8.284,6.716,15,15,15h200c8.284,0,15-6.716,15-15V75c0-8.284-6.716-15-15-15h-45V15\r\n c0-8.284-6.716-15-15-15H35c-8.284,0-15,6.716-15,15v240C20,263.284,26.716,270,35,270z M280,300H110V90h170V300z M50,30h170v30H95\r\n c-8.284,0-15,6.716-15,15v165H50V30z"
220
+ }
221
+ ),
222
+ /* @__PURE__ */ import_react.default.createElement("path", { d: "M155,120c-8.284,0-15,6.716-15,15s6.716,15,15,15h80c8.284,0,15-6.716,15-15s-6.716-15-15-15H155z" }),
223
+ /* @__PURE__ */ import_react.default.createElement("path", { d: "M235,180h-80c-8.284,0-15,6.716-15,15s6.716,15,15,15h80c8.284,0,15-6.716,15-15S243.284,180,235,180z" }),
224
+ /* @__PURE__ */ import_react.default.createElement(
225
+ "path",
226
+ {
227
+ d: "M235,240h-80c-8.284,0-15,6.716-15,15c0,8.284,6.716,15,15,15h80c8.284,0,15-6.716,15-15C250,246.716,243.284,240,235,240z\r\n "
228
+ }
229
+ )
230
+ )
231
+ )
232
+ ), /* @__PURE__ */ import_react.default.createElement(
233
+ import_react_syntax_highlighter.Prism,
234
+ __spreadValues({
235
+ style: theme === "light" ? import_prism.materialLight : import_prism.materialDark,
236
+ PreTag: "div",
237
+ language: match[1]
238
+ }, props),
239
+ String(children).replace(/\n$/, "")
240
+ )) : /* @__PURE__ */ import_react.default.createElement("code", __spreadValues({ className: className ? className : "" }, props), children);
241
+ };
171
242
  return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(
172
243
  "div",
173
244
  {
@@ -175,7 +246,22 @@ var ChatPanel = ({
175
246
  className: "side-panel" + (theme === "light" ? "" : "-dark")
176
247
  },
177
248
  /* @__PURE__ */ import_react.default.createElement("div", { className: "title" }, title),
178
- /* @__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, remarkPlugins: [import_remark_gfm.default] }, 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, remarkPlugins: [import_remark_gfm.default] }, response2), /* @__PURE__ */ import_react.default.createElement("div", { className: "button-container" }, /* @__PURE__ */ import_react.default.createElement(
249
+ /* @__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(
250
+ import_react_markdown.default,
251
+ {
252
+ className: markdownClass,
253
+ remarkPlugins: [import_remark_gfm.default]
254
+ },
255
+ initialMessage
256
+ ))) : 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(
257
+ import_react_markdown.default,
258
+ {
259
+ className: markdownClass,
260
+ remarkPlugins: [import_remark_gfm.default],
261
+ components: { code: CodeBlock }
262
+ },
263
+ response2
264
+ ), /* @__PURE__ */ import_react.default.createElement("div", { className: "button-container" }, /* @__PURE__ */ import_react.default.createElement(
179
265
  "button",
180
266
  {
181
267
  className: "copy-button",
package/dist/index.mjs CHANGED
@@ -17,12 +17,29 @@ var __spreadValues = (a, b) => {
17
17
  return a;
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
20
32
 
21
33
  // src/ChatPanel.tsx
22
34
  import { useLLM } from "llmasaservice-client";
23
35
  import React, { useEffect, useRef, useState } from "react";
24
36
  import ReactMarkdown from "react-markdown";
25
37
  import remarkGfm from "remark-gfm";
38
+ import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
39
+ import {
40
+ materialLight,
41
+ materialDark
42
+ } from "react-syntax-highlighter/dist/cjs/styles/prism";
26
43
  var ChatPanel = ({
27
44
  project_id,
28
45
  initialPrompt = "",
@@ -135,6 +152,63 @@ var ChatPanel = ({
135
152
  var _a;
136
153
  (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
137
154
  };
155
+ const CodeBlock = (_a) => {
156
+ var _b = _a, { node, className, children, style } = _b, props = __objRest(_b, ["node", "className", "children", "style"]);
157
+ console.log("CodeBlock", className, children, style, props);
158
+ const match = /language-(\w+)/.exec(className || "");
159
+ return match ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
160
+ "div",
161
+ {
162
+ style: {
163
+ border: 0,
164
+ padding: 0,
165
+ height: "16px",
166
+ display: "flex",
167
+ justifyContent: "space-between",
168
+ alignItems: "center"
169
+ }
170
+ },
171
+ /* @__PURE__ */ React.createElement("span", null, match ? match[1] : "Unknown"),
172
+ /* @__PURE__ */ React.createElement(
173
+ "button",
174
+ {
175
+ onClick: () => copyToClipboard(children),
176
+ className: "copy-button"
177
+ },
178
+ /* @__PURE__ */ React.createElement(
179
+ "svg",
180
+ {
181
+ xmlns: "http://www.w3.org/2000/svg",
182
+ viewBox: "0 0 320 320",
183
+ fill: "currentColor",
184
+ className: "icon-svg"
185
+ },
186
+ /* @__PURE__ */ React.createElement(
187
+ "path",
188
+ {
189
+ d: "M35,270h45v45c0,8.284,6.716,15,15,15h200c8.284,0,15-6.716,15-15V75c0-8.284-6.716-15-15-15h-45V15\r\n c0-8.284-6.716-15-15-15H35c-8.284,0-15,6.716-15,15v240C20,263.284,26.716,270,35,270z M280,300H110V90h170V300z M50,30h170v30H95\r\n c-8.284,0-15,6.716-15,15v165H50V30z"
190
+ }
191
+ ),
192
+ /* @__PURE__ */ React.createElement("path", { d: "M155,120c-8.284,0-15,6.716-15,15s6.716,15,15,15h80c8.284,0,15-6.716,15-15s-6.716-15-15-15H155z" }),
193
+ /* @__PURE__ */ React.createElement("path", { d: "M235,180h-80c-8.284,0-15,6.716-15,15s6.716,15,15,15h80c8.284,0,15-6.716,15-15S243.284,180,235,180z" }),
194
+ /* @__PURE__ */ React.createElement(
195
+ "path",
196
+ {
197
+ d: "M235,240h-80c-8.284,0-15,6.716-15,15c0,8.284,6.716,15,15,15h80c8.284,0,15-6.716,15-15C250,246.716,243.284,240,235,240z\r\n "
198
+ }
199
+ )
200
+ )
201
+ )
202
+ ), /* @__PURE__ */ React.createElement(
203
+ SyntaxHighlighter,
204
+ __spreadValues({
205
+ style: theme === "light" ? materialLight : materialDark,
206
+ PreTag: "div",
207
+ language: match[1]
208
+ }, props),
209
+ String(children).replace(/\n$/, "")
210
+ )) : /* @__PURE__ */ React.createElement("code", __spreadValues({ className: className ? className : "" }, props), children);
211
+ };
138
212
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
139
213
  "div",
140
214
  {
@@ -142,7 +216,22 @@ var ChatPanel = ({
142
216
  className: "side-panel" + (theme === "light" ? "" : "-dark")
143
217
  },
144
218
  /* @__PURE__ */ React.createElement("div", { className: "title" }, title),
145
- /* @__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, remarkPlugins: [remarkGfm] }, 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, remarkPlugins: [remarkGfm] }, response2), /* @__PURE__ */ React.createElement("div", { className: "button-container" }, /* @__PURE__ */ React.createElement(
219
+ /* @__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(
220
+ ReactMarkdown,
221
+ {
222
+ className: markdownClass,
223
+ remarkPlugins: [remarkGfm]
224
+ },
225
+ initialMessage
226
+ ))) : 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(
227
+ ReactMarkdown,
228
+ {
229
+ className: markdownClass,
230
+ remarkPlugins: [remarkGfm],
231
+ components: { code: CodeBlock }
232
+ },
233
+ response2
234
+ ), /* @__PURE__ */ React.createElement("div", { className: "button-container" }, /* @__PURE__ */ React.createElement(
146
235
  "button",
147
236
  {
148
237
  className: "copy-button",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llmasaservice-ui",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Prebuilt UI components for LLMAsAService.io",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -46,6 +46,7 @@
46
46
  "dependencies": {
47
47
  "llmasaservice-client": "^0.4.0",
48
48
  "react-markdown": "^9.0.1",
49
+ "react-syntax-highlighter": "^15.5.0",
49
50
  "remark-gfm": "^4.0.0"
50
51
  },
51
52
  "peerDependencies": {
package/src/ChatPanel.tsx CHANGED
@@ -3,6 +3,11 @@ import React, { useEffect, useRef, useState } from "react";
3
3
  import ReactMarkdown from "react-markdown";
4
4
  import "./ChatPanel.css";
5
5
  import remarkGfm from "remark-gfm";
6
+ import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
7
+ import {
8
+ materialLight,
9
+ materialDark,
10
+ } from "react-syntax-highlighter/dist/cjs/styles/prism";
6
11
 
7
12
  export interface ChatPanelProps {
8
13
  project_id: string;
@@ -27,7 +32,7 @@ interface ExtraProps extends React.HTMLAttributes<HTMLElement> {
27
32
  inline?: boolean;
28
33
  }
29
34
 
30
- const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
35
+ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
31
36
  project_id,
32
37
  initialPrompt = "",
33
38
  title = "Chat",
@@ -166,6 +171,63 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
166
171
  bottomRef.current?.scrollIntoView({ behavior: "smooth" });
167
172
  };
168
173
 
174
+ const CodeBlock = ({ node, className, children, style, ...props }: any) => {
175
+ console.log("CodeBlock", className, children, style, props);
176
+ const match = /language-(\w+)/.exec(className || "");
177
+
178
+ return match ? (
179
+ <>
180
+ <div
181
+ style={{
182
+ border: 0,
183
+ padding: 0,
184
+ height: "16px",
185
+ display: "flex",
186
+ justifyContent: "space-between",
187
+ alignItems: "center",
188
+ }}
189
+ >
190
+ <span>{match ? match[1] : "Unknown"}</span>
191
+ <button
192
+ onClick={() => copyToClipboard(children)}
193
+ className="copy-button"
194
+ >
195
+ <svg
196
+ xmlns="http://www.w3.org/2000/svg"
197
+ viewBox="0 0 320 320"
198
+ fill="currentColor"
199
+ className="icon-svg"
200
+ >
201
+ <path
202
+ d="M35,270h45v45c0,8.284,6.716,15,15,15h200c8.284,0,15-6.716,15-15V75c0-8.284-6.716-15-15-15h-45V15
203
+ c0-8.284-6.716-15-15-15H35c-8.284,0-15,6.716-15,15v240C20,263.284,26.716,270,35,270z M280,300H110V90h170V300z M50,30h170v30H95
204
+ c-8.284,0-15,6.716-15,15v165H50V30z"
205
+ />
206
+ <path d="M155,120c-8.284,0-15,6.716-15,15s6.716,15,15,15h80c8.284,0,15-6.716,15-15s-6.716-15-15-15H155z" />
207
+ <path d="M235,180h-80c-8.284,0-15,6.716-15,15s6.716,15,15,15h80c8.284,0,15-6.716,15-15S243.284,180,235,180z" />
208
+ <path
209
+ d="M235,240h-80c-8.284,0-15,6.716-15,15c0,8.284,6.716,15,15,15h80c8.284,0,15-6.716,15-15C250,246.716,243.284,240,235,240z
210
+ "
211
+ />
212
+ </svg>
213
+ </button>
214
+ </div>
215
+ <SyntaxHighlighter
216
+ style={theme === "light" ? materialLight : materialDark}
217
+ PreTag="div"
218
+ language={match[1]}
219
+ {...props}
220
+ >
221
+ {String(children).replace(/\n$/, "")}
222
+ </SyntaxHighlighter>
223
+ </>
224
+ ) : (
225
+ <code className={className ? className : ""} {...props}>
226
+ {children}
227
+ </code>
228
+ );
229
+ };
230
+
169
231
  return (
170
232
  <>
171
233
  <div
@@ -177,7 +239,10 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
177
239
  {initialMessage && initialMessage !== "" ? (
178
240
  <div className="history-entry">
179
241
  <div className="response">
180
- <ReactMarkdown className={markdownClass} remarkPlugins={[remarkGfm]}>
242
+ <ReactMarkdown
243
+ className={markdownClass}
244
+ remarkPlugins={[remarkGfm]}
245
+ >
181
246
  {initialMessage}
182
247
  </ReactMarkdown>
183
248
  </div>
@@ -193,7 +258,11 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
193
258
  {index === Object.keys(history).length - 1 && isLoading ? (
194
259
  <div className="loading-text">loading...</div>
195
260
  ) : null}
196
- <ReactMarkdown className={markdownClass} remarkPlugins={[remarkGfm]} >
261
+ <ReactMarkdown
262
+ className={markdownClass}
263
+ remarkPlugins={[remarkGfm]}
264
+ components={{ code: CodeBlock }}
265
+ >
197
266
  {response}
198
267
  </ReactMarkdown>
199
268
  <div className="button-container">