├── .gitignore
├── README.md
├── dist
└── build
│ └── static
│ └── js
│ └── bundle.min.js
├── package-lock.json
├── package.json
├── public
└── index.html
├── src
├── chatPlaceholder
│ └── index.tsx
├── chatWidget
│ ├── chatTrigger
│ │ └── index.tsx
│ ├── chatWindow
│ │ ├── chatMessage
│ │ │ └── index.tsx
│ │ └── index.tsx
│ ├── index.tsx
│ └── utils.ts
├── controllers
│ └── index.ts
├── index.tsx
├── react-app-env.d.ts
├── reportWebVitals.ts
├── setupTests.ts
└── types
│ └── chatWidget
│ └── index.ts
├── tsconfig.json
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Langflow Embedded Chat ⛓️
2 |
3 | Welcome to the Langflow Embedded Chat repository! 🎉
4 |
5 | The Langflow Embedded Chat is a powerful web component that enables seamless communication with the [Langflow ⛓️](https://github.com/logspace-ai/langflow). This widget provides a chat interface, allowing you to integrate Langflow ⛓️ into your web applications effortlessly.
6 |
7 | [](https://opensource.org/licenses/MIT)
8 |
9 | ## What is Langflow?
10 |
11 | Langflow is a no-code open-source project that empowers developers to build cutting-edge applications using Language Model technologies. With Langflow, you can leverage the power of LLMs (Large Language Models) to enhance user interactions, generate human-like text, and gain valuable insights from natural language data.
12 |
13 | ## Features
14 |
15 | 🌟 Seamless Integration: Easily integrate the Langflow Widget into your website or web application with just a few lines of JavaScript.
16 |
17 | 🚀 Interactive Chat Interface: Engage your users with a user-friendly chat interface, powered by Langflow's advanced language understanding capabilities.
18 |
19 | 🎛️ Customizable Styling: Customize the appearance of the chat widget to match your application's design and branding.
20 |
21 | 🌐 Multilingual Support: Communicate with users in multiple languages, opening up your application to a global audience.
22 |
23 | ## Installation
24 |
25 | ### Option 1: CDN Link
26 |
27 | Use the Langflow Widget directly from the CDN by including the following script tag in your HTML:
28 |
29 | ```html
30 |
31 | ```
32 |
33 | ### Option 2: Local Build
34 |
35 | 1. Clone this repository to your local machine:
36 |
37 | ```bash
38 | git clone https://github.com/logspace-ai/langflow-embedded-chat.git
39 | ```
40 |
41 | 2. Navigate to the project directory:
42 |
43 | ```bash
44 | cd langflow-embedded-chat
45 | ```
46 |
47 | 3. Build the project to generate the bundle:
48 |
49 | ```bash
50 | npm run build
51 | ```
52 |
53 | 5. After the build process completes, you'll find the bundle in the `dist/build/static/js` folder. You can include this JavaScript file in your HTML:
54 |
55 | ```html
56 |
57 | ```
58 |
59 | ## Usage
60 |
61 | ### on simple HTML
62 | ```html
63 |
64 |
65 |
66 |
67 |
68 |
72 |
73 |
74 | ```
75 |
76 | ### on React
77 | Import the js bundle in the index.html of your react project
78 | ```html
79 |
80 | ```
81 | Encapsulate your custom element in a react component
82 | ```html
83 | export default function ChatWidget() {
84 | return (
85 |
86 |
89 |
90 | );
91 | }
92 | ```
93 |
94 | ## Configuration
95 |
96 | Use the widget API to customize your widget:
97 |
98 | | Prop | Type | Required |
99 | |-----------------------|-----------|----------|
100 | | api_key | string | No |
101 | | bot_message_style | json | No |
102 | | chat_position | string | No |
103 | | chat_trigger_style | json | No |
104 | | chat_window_style | json | No |
105 | | output_type | string | No |
106 | | input_type | string | No |
107 | | output_component | string | No |
108 | | error_message_style | json | No |
109 | | flow_id | string | Yes |
110 | | height | number | No |
111 | | host_url | string | Yes |
112 | | input_container_style | json | No |
113 | | input_style | json | No |
114 | | online | boolean | No |
115 | | start_open | boolean | No |
116 | | online_message | string | No |
117 | | placeholder | string | No |
118 | | placeholder_sending | string | No |
119 | | send_button_style | json | No |
120 | | send_icon_style | json | No |
121 | | tweaks | json | No |
122 | | user_message_style | json | No |
123 | | width | number | No |
124 | | window_title | string | No |
125 | | session_id | string | No |
126 | | additional_headers | json | No |
127 |
128 | - **api_key:**
129 | - Type: String
130 | - Required: No
131 | - Description: X-API-Key header to send to Langflow
132 |
133 |
134 | - **bot_message_style:**
135 | - Type: JSON
136 | - Required: No
137 | - Description: Styling options for formatting bot messages in the chat window.
138 |
139 | - **input_type:**
140 | - Type: String
141 | - Required: No
142 | - Description: Specifies the input type for chat messages.
143 |
144 | - **output_type:**
145 | - Type: String
146 | - Required: No
147 | - Description: Specifies the output type for chat messages.
148 |
149 | - **output_component:**
150 | - Type: String
151 | - Required: No
152 | - Description: Specify the output ID for chat messages; this is necessary when multiple outputs are present.
153 |
154 | - **chat_position:**
155 | - Type: String
156 | - Required: No
157 | - Description: Determines the position of the chat window (top-left, top-center, top-right, center-left, center-right, bottom-right, bottom-center, bottom-left).
158 |
159 | - **chat_trigger_style:**
160 | - Type: JSON
161 | - Required: No
162 | - Description: Styling options for the chat trigger.
163 |
164 | - **chat_window_style:**
165 | - Type: JSON
166 | - Required: No
167 | - Description: Styling options for the overall chat window.
168 |
169 | - **error_message_style:**
170 | - Type: JSON
171 | - Required: No
172 | - Description: Styling options for error messages in the chat window.
173 |
174 | - **flow_id:**
175 | - Type: String
176 | - Required: Yes
177 | - Description: Identifier for the flow associated with the component.
178 |
179 | - **height:**
180 | - Type: Number
181 | - Required: No
182 | - Description: Specifies the height of the chat window in pixels.
183 |
184 | - **host_url:**
185 | - Type: String
186 | - Required: Yes
187 | - Description: The URL of the host for communication with the chat component.
188 |
189 | - **input_container_style:**
190 | - Type: JSON
191 | - Required: No
192 | - Description: Styling options for the input container where chat messages are typed.
193 |
194 | - **input_style:**
195 | - Type: JSON
196 | - Required: No
197 | - Description: Styling options for the chat input field.
198 |
199 | - **Online:**
200 | - Type: Boolean
201 | - Required: No
202 | - Description: Indicates if the chat component is online or offline.
203 |
204 | - **start_open:**
205 | - Type: Boolean
206 | - Required: No
207 | - Description: Indicates if the chat window should be open by default.
208 |
209 | - **online_message:**
210 | - Type: String
211 | - Required: No
212 | - Description: Custom message to display when the chat component is online.
213 |
214 | - **placeholder:**
215 | - Type: String
216 | - Required: No
217 | - Description: Placeholder text for the chat input field.
218 |
219 | - **placeholder_sending:**
220 | - Type: String
221 | - Required: No
222 | - Description: Placeholder text to display while a message is being sent.
223 |
224 | - **send_button_style:**
225 | - Type: JSON
226 | - Required: No
227 | - Description: Styling options for the send button in the chat window.
228 |
229 | - **send_icon_style:**
230 | - Type: JSON
231 | - Required: No
232 | - Description: Styling options for the send icon in the chat window.
233 |
234 | - **tweaks:**
235 | - Type: JSON
236 | - Required: No
237 | - Description: Additional custom tweaks for the associated flow.
238 |
239 | - **user_message_style:**
240 | - Type: JSON
241 | - Required: No
242 | - Description: Styling options for formatting user messages in the chat window.
243 |
244 | - **width:**
245 | - Type: Number
246 | - Required: No
247 | - Description: Specifies the width of the chat window in pixels.
248 |
249 | - **window_title:**
250 | - Type: String
251 | - Required: No
252 | - Description: Title for the chat window, displayed in the header or title bar.
253 |
254 | - **session_id:**
255 | - Type: String
256 | - Required: No
257 | - Description: Custom session id to override the random session id used as default.
258 |
259 | - **additional_headers:**
260 | - Type: JSON
261 | - Required: No
262 | - Description: Additional headers to be sent to Langflow server
263 |
264 |
265 | ## Live example:
266 | Try out or [live example](https://codesandbox.io/s/langflow-embedded-chat-example-dv9zpx) to see how the Langflow Embedded Chat ⛓️ works.
267 |
268 | 1. first create a Flow and save it using [Langflow ⛓️](https://github.com/logspace-ai/langflow).
269 | 2. Get the hosted URL to use in the live example.
270 | 3. If you are using a public host (like [Hugging Face Spaces](https://huggingface.co/spaces/Logspace/Langflow)) use tweaks to keep your API keys safe.
271 |
272 | ## License
273 |
274 | This project is licensed under the [MIT License](https://opensource.org/licenses/MIT) - see the [LICENSE](https://github.com/logspace-ai/langflow-embedded-chat/tree/main/LICENSE) file for details.
275 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "langflow-embedded-chat",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@r2wc/react-to-web-component": "^2.0.2",
7 | "@testing-library/jest-dom": "^5.16.5",
8 | "@testing-library/react": "^13.4.0",
9 | "@testing-library/user-event": "^13.5.0",
10 | "@types/jest": "^27.5.2",
11 | "@types/node": "^16.18.37",
12 | "@types/react": "^18.2.14",
13 | "@types/react-dom": "^18.2.6",
14 | "axios": "^1.4.0",
15 | "lucide-react": "^0.256.0",
16 | "react": "^18.2.0",
17 | "react-dom": "^18.2.0",
18 | "react-markdown": "^8.0.7",
19 | "react-scripts": "5.0.1",
20 | "react-shadow": "^20.3.0",
21 | "rehype-mathjax": "^4.0.3",
22 | "remark-gfm": "3.0.1",
23 | "typescript": "^4.9.5",
24 | "uglifyjs-webpack-plugin": "^2.2.0",
25 | "uuid": "^10.0.0",
26 | "web-vitals": "^2.1.4"
27 | },
28 | "scripts": {
29 | "start": "react-scripts start",
30 | "build": "npm install --legacy-peer-deps && npm run build:react && npm run build:bundle",
31 | "build:react": "react-scripts build",
32 | "build:bundle": "webpack --config webpack.config.js",
33 | "test": "react-scripts test",
34 | "eject": "react-scripts eject"
35 | },
36 | "eslintConfig": {
37 | "extends": [
38 | "react-app",
39 | "react-app/jest"
40 | ]
41 | },
42 | "browserslist": {
43 | "production": [
44 | ">0.2%",
45 | "not dead",
46 | "not op_mini all"
47 | ],
48 | "development": [
49 | "last 1 chrome version",
50 | "last 1 firefox version",
51 | "last 1 safari version"
52 | ]
53 | },
54 | "devDependencies": {
55 | "webpack-cli": "^5.1.4"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/src/chatPlaceholder/index.tsx:
--------------------------------------------------------------------------------
1 | import { MoreHorizontal } from "lucide-react";
2 | import { ChatMessagePlaceholderType } from "../types/chatWidget";
3 |
4 | export default function ChatMessagePlaceholder({
5 | bot_message_style,
6 | }: ChatMessagePlaceholderType) {
7 | return (
8 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/src/chatWidget/chatTrigger/index.tsx:
--------------------------------------------------------------------------------
1 | import { MessageSquare, X } from "lucide-react"
2 | export default function ChatTrigger({ style, open, setOpen, triggerRef }: { style?: React.CSSProperties, open: boolean, setOpen: Function, triggerRef: React.RefObject | null }) {
3 |
4 | return (
5 |
14 | )
15 | }
--------------------------------------------------------------------------------
/src/chatWidget/chatWindow/chatMessage/index.tsx:
--------------------------------------------------------------------------------
1 | import Markdown from "react-markdown";
2 | import { ChatMessageType } from "../../../types/chatWidget";
3 | import remarkGfm from "remark-gfm";
4 | import rehypeMathjax from "rehype-mathjax";
5 |
6 | export default function ChatMessage({
7 | message,
8 | isSend,
9 | error,
10 | user_message_style,
11 | bot_message_style,
12 | error_message_style,
13 | }: ChatMessageType) {
14 |
15 | return (
16 |
21 | {isSend ? (
22 |
23 | {message}
24 |
25 | ) : error ? (
26 |
27 | {message}
28 |
29 | ) : (
30 |
31 |
36 | {message}
37 |
38 |
39 | )}
40 |
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/src/chatWidget/chatWindow/index.tsx:
--------------------------------------------------------------------------------
1 | import { Send } from "lucide-react";
2 | import { extractMessageFromOutput, getAnimationOrigin, getChatPosition } from "../utils";
3 | import React, { useEffect, useRef, useState } from "react";
4 | import { ChatMessageType } from "../../types/chatWidget";
5 | import ChatMessage from "./chatMessage";
6 | import { sendMessage } from "../../controllers";
7 | import ChatMessagePlaceholder from "../../chatPlaceholder";
8 |
9 | export default function ChatWindow({
10 | api_key,
11 | flowId,
12 | hostUrl,
13 | updateLastMessage,
14 | messages,
15 | output_type,
16 | input_type,
17 | output_component,
18 | bot_message_style,
19 | send_icon_style,
20 | user_message_style,
21 | chat_window_style,
22 | error_message_style,
23 | placeholder_sending,
24 | send_button_style,
25 | online = true,
26 | open,
27 | online_message = "We'll reply as soon as we can",
28 | offline_message = "We're offline now",
29 | window_title = "Chat",
30 | placeholder,
31 | input_style,
32 | input_container_style,
33 | addMessage,
34 | position,
35 | triggerRef,
36 | width = 450,
37 | height = 650,
38 | tweaks,
39 | sessionId,
40 | additional_headers
41 | }: {
42 | api_key?: string;
43 | output_type: string,
44 | input_type: string,
45 | output_component?: string,
46 | bot_message_style?: React.CSSProperties;
47 | send_icon_style?: React.CSSProperties;
48 | user_message_style?: React.CSSProperties;
49 | chat_window_style?: React.CSSProperties;
50 | error_message_style?: React.CSSProperties;
51 | send_button_style?: React.CSSProperties;
52 | online?: boolean;
53 | open: boolean;
54 | online_message?: string;
55 | placeholder_sending?: string;
56 | offline_message?: string;
57 | window_title?: string;
58 | placeholder?: string;
59 | input_style?: React.CSSProperties;
60 | input_container_style?: React.CSSProperties;
61 | tweaks?: { [key: string]: any };
62 | flowId: string;
63 | hostUrl: string;
64 | updateLastMessage: Function;
65 | messages: ChatMessageType[];
66 | addMessage: Function;
67 | position?: string;
68 | triggerRef: React.RefObject;
69 | width?: number;
70 | height?: number;
71 | sessionId: React.MutableRefObject;
72 | additional_headers?: { [key: string]: string };
73 |
74 | }) {
75 | const [value, setValue] = useState("");
76 | const ref = useRef(null);
77 | const lastMessage = useRef(null);
78 | const [windowPosition, setWindowPosition] = useState({ left: "0", top: "0" });
79 | const inputRef = useRef(null); /* User input Ref */
80 | useEffect(() => {
81 | if (triggerRef)
82 | setWindowPosition(
83 | getChatPosition(
84 | triggerRef.current!.getBoundingClientRect(),
85 | width,
86 | height,
87 | position
88 | )
89 | );
90 | }, [triggerRef, width, height, position]);
91 |
92 | /* Initial listener for loss of focus that refocuses User input after a small delay */
93 |
94 | const [sendingMessage, setSendingMessage] = useState(false);
95 |
96 | function handleClick() {
97 | if (value && value.trim() !== "") {
98 | addMessage({ message: value, isSend: true });
99 | setSendingMessage(true);
100 | setValue("");
101 | sendMessage(hostUrl, flowId, value, input_type, output_type, sessionId, output_component, tweaks, api_key, additional_headers)
102 | .then((res) => {
103 | if (
104 | res.data &&
105 | res.data.outputs &&
106 | Object.keys(res.data.outputs).length > 0 &&
107 | res.data.outputs[0].outputs && res.data.outputs[0].outputs.length > 0
108 | ) {
109 | const flowOutputs: Array = res.data.outputs[0].outputs;
110 | if (output_component &&
111 | flowOutputs.map(e => e.component_id).includes(output_component)) {
112 | Object.values(flowOutputs.find(e => e.component_id === output_component).outputs).forEach((output: any) => {
113 | addMessage({
114 | message: extractMessageFromOutput(output),
115 | isSend: false,
116 | });
117 | })
118 | } else if (
119 | flowOutputs.length === 1
120 | ) {
121 | Object.values(flowOutputs[0].outputs).forEach((output: any) => {
122 | addMessage({
123 | message: extractMessageFromOutput(output),
124 | isSend: false,
125 | });
126 | })
127 | } else {
128 | flowOutputs
129 | .sort((a, b) => {
130 | // Get the earliest timestamp from each flowOutput's outputs
131 | const aTimestamp = Math.min(...Object.values(a.outputs).map((output: any) => Date.parse(output.message?.timestamp)));
132 | const bTimestamp = Math.min(...Object.values(b.outputs).map((output: any) => Date.parse(output.message?.timestamp)));
133 | return aTimestamp - bTimestamp; // Sort descending (newest first)
134 | })
135 | .forEach((flowOutput) => {
136 | Object.values(flowOutput.outputs).forEach((output: any) => {
137 | addMessage({
138 | message: extractMessageFromOutput(output),
139 | isSend: false,
140 | });
141 | });
142 | });
143 | }
144 | }
145 | if (res.data && res.data.session_id) {
146 | sessionId.current = res.data.session_id;
147 | }
148 | setSendingMessage(false);
149 | })
150 | .catch((err) => {
151 | const response = err.response;
152 | if (err.code === "ERR_NETWORK") {
153 | updateLastMessage({
154 | message: "Network error",
155 | isSend: false,
156 | error: true,
157 | });
158 | } else if (
159 | response &&
160 | response.status === 500 &&
161 | response.data &&
162 | response.data.detail
163 | ) {
164 | updateLastMessage({
165 | message: response.data.detail,
166 | isSend: false,
167 | error: true,
168 | });
169 | }
170 | console.error(err);
171 | setSendingMessage(false);
172 | });
173 | }
174 | }
175 |
176 | useEffect(() => {
177 | if (lastMessage.current)
178 | lastMessage.current.scrollIntoView({ behavior: "smooth" });
179 | }, [messages]);
180 |
181 | /* Refocus the User input whenever a new response is returned from the LLM */
182 |
183 | useEffect(() => {
184 | // after a slight delay
185 | setTimeout(() => {
186 | inputRef.current?.focus();
187 | }, 100);
188 | }, [messages, open]);
189 |
190 | return (
191 |
199 |
204 |
205 | {window_title}
206 |
207 | {online ? (
208 | <>
209 |
210 | {online_message}
211 | >
212 | ) : (
213 | <>
214 |
215 | {offline_message}
216 | >
217 | )}
218 |
219 |
220 |
221 | {messages.map((message, index) => (
222 |
231 | ))}
232 | {sendingMessage && (
233 |
234 | )}
235 |
236 |
237 |
238 | setValue(e.target.value)}
241 | onKeyDown={(e) => {
242 | if (e.key === "Enter") handleClick();
243 | }}
244 | type="text"
245 | disabled={sendingMessage}
246 | placeholder={sendingMessage ? (placeholder_sending || "Thinking...") : (placeholder || "Type your message...")}
247 | style={input_style}
248 | ref={inputRef}
249 | className="cl-input-element"
250 | />
251 |
266 |
267 |
268 |
269 | );
270 | }
271 |
--------------------------------------------------------------------------------
/src/chatWidget/index.tsx:
--------------------------------------------------------------------------------
1 | import { useRef, useState } from "react";
2 | import ChatTrigger from "./chatTrigger";
3 | import ChatWindow from "./chatWindow";
4 | import { ChatMessageType } from "../types/chatWidget";
5 | const { v4: uuidv4 } = require('uuid');
6 |
7 | export default function ChatWidget({
8 | api_key,
9 | output_type = "chat",
10 | input_type = "chat",
11 | output_component,
12 | chat_trigger_style,
13 | host_url,
14 | flow_id,
15 | tweaks,
16 | send_icon_style,
17 | bot_message_style,
18 | user_message_style,
19 | chat_window_style,
20 | height,
21 | width,
22 | error_message_style,
23 | send_button_style,
24 | online,
25 | online_message,
26 | offline_message,
27 | window_title,
28 | chat_position,
29 | placeholder,
30 | input_style,
31 | placeholder_sending,
32 | input_container_style,
33 | additional_headers,
34 | session_id,
35 | start_open=false,
36 | }: {
37 | api_key?: string;
38 | input_value: string,
39 | output_type: string,
40 | input_type: string,
41 | output_component?: string;
42 | send_icon_style?: React.CSSProperties;
43 | chat_position?: string;
44 | chat_trigger_style?: React.CSSProperties;
45 | bot_message_style?: React.CSSProperties;
46 | user_message_style?: React.CSSProperties;
47 | chat_window_style?: React.CSSProperties;
48 | online?: boolean;
49 | online_message?: string;
50 | offline_message?: string;
51 | height?: number;
52 | width?: number;
53 | window_title?: string;
54 | error_message_style?: React.CSSProperties;
55 | send_button_style?: React.CSSProperties;
56 | placeholder_sending?: string;
57 | placeholder?: string;
58 | input_style?: React.CSSProperties;
59 | input_container_style?: React.CSSProperties;
60 | host_url: string;
61 | flow_id: string;
62 | tweaks?: { [key: string]: any };
63 | additional_headers?: { [key: string]: string };
64 | session_id?: string;
65 | start_open?: boolean;
66 | }) {
67 | const [open, setOpen] = useState(start_open);
68 | const [messages, setMessages] = useState([]);
69 | const sessionId = useRef(session_id ?? uuidv4());
70 | function updateLastMessage(message: ChatMessageType) {
71 | setMessages((prev) => {
72 | prev[prev.length - 1] = message;
73 | return [...prev];
74 | });
75 | }
76 | function addMessage(message: ChatMessageType) {
77 | setMessages((prev) => [...prev, message]);
78 | }
79 | const triggerRef = useRef(null);
80 |
81 | const styles = `
82 | /*
83 | ! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com
84 | */
85 |
86 | /*
87 | 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
88 | 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
89 | */
90 |
91 | *,
92 | ::before,
93 | ::after {
94 | box-sizing: border-box;
95 | /* 1 */
96 | border-width: 0;
97 | /* 2 */
98 | border-style: solid;
99 | /* 2 */
100 | border-color: #e5e7eb;
101 | /* 2 */
102 | }
103 |
104 | ::before,
105 | ::after {
106 | --tw-content: '';
107 | }
108 |
109 | /*
110 | 1. Use a consistent sensible line-height in all browsers.
111 | 2. Prevent adjustments of font size after orientation changes in iOS.
112 | 3. Use a more readable tab size.
113 | 4. Use the user's configured 'sans' font-family by default.
114 | 5. Use the user's configured 'sans' font-feature-settings by default.
115 | 6. Use the user's configured 'sans' font-variation-settings by default.
116 | */
117 |
118 | html {
119 | line-height: 1.5;
120 | /* 1 */
121 | -webkit-text-size-adjust: 100%;
122 | /* 2 */
123 | /* 3 */
124 | tab-size: 4;
125 | /* 3 */
126 | font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
127 | /* 4 */
128 | -webkit-font-feature-settings: normal;
129 | font-feature-settings: normal;
130 | /* 5 */
131 | font-variation-settings: normal;
132 | /* 6 */
133 | }
134 |
135 | /*
136 | 1. Remove the margin in all browsers.
137 | 2. Inherit line-height from 'html' so users can set them as a class directly on the 'html' element.
138 | */
139 |
140 | body {
141 | margin: 0;
142 | /* 1 */
143 | line-height: inherit;
144 | /* 2 */
145 | }
146 |
147 | /*
148 | 1. Add the correct height in Firefox.
149 | 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
150 | 3. Ensure horizontal rules are visible by default.
151 | */
152 |
153 | /*
154 | Add the correct text decoration in Chrome, Edge, and Safari.
155 | */
156 |
157 | abbr:where([title]) {
158 | -webkit-text-decoration: underline dotted;
159 | text-decoration: underline dotted;
160 | }
161 |
162 | /*
163 | Remove the default font size and weight for headings.
164 | */
165 |
166 | /*
167 | Add the correct font weight in Edge and Safari.
168 | */
169 |
170 | b,
171 | strong {
172 | font-weight: bolder;
173 | }
174 |
175 | /*
176 | 1. Use the user's configured 'mono' font family by default.
177 | 2. Correct the odd 'em' font sizing in all browsers.
178 | */
179 |
180 | code,
181 | kbd,
182 | samp,
183 | pre {
184 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
185 | /* 1 */
186 | font-size: 1em;
187 | /* 2 */
188 | }
189 |
190 | /*
191 | Add the correct font size in all browsers.
192 | */
193 |
194 | small {
195 | font-size: 80%;
196 | }
197 |
198 | /*
199 | Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
200 | */
201 |
202 | sub,
203 | sup {
204 | font-size: 75%;
205 | line-height: 0;
206 | position: relative;
207 | vertical-align: baseline;
208 | }
209 |
210 | sub {
211 | bottom: -0.25em;
212 | }
213 |
214 | sup {
215 | top: -0.5em;
216 | }
217 |
218 | /*
219 | 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
220 | 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
221 | 3. Remove gaps between table borders by default.
222 | */
223 |
224 |
225 |
226 | /*
227 | 1. Change the font styles in all browsers.
228 | 2. Remove the margin in Firefox and Safari.
229 | 3. Remove default padding in all browsers.
230 | */
231 |
232 | button,
233 | input,
234 | optgroup,
235 | select,
236 | textarea {
237 | font-family: inherit;
238 | /* 1 */
239 | font-size: 100%;
240 | /* 1 */
241 | font-weight: inherit;
242 | /* 1 */
243 | line-height: inherit;
244 | /* 1 */
245 | color: inherit;
246 | /* 1 */
247 | margin: 0;
248 | /* 2 */
249 | padding: 0;
250 | /* 3 */
251 | }
252 |
253 | /*
254 | Remove the inheritance of text transform in Edge and Firefox.
255 | */
256 |
257 | button,
258 | select {
259 | text-transform: none;
260 | }
261 |
262 | /*
263 | 1. Correct the inability to style clickable types in iOS and Safari.
264 | 2. Remove default button styles.
265 | */
266 |
267 | button,
268 | [type='button'],
269 | [type='reset'],
270 | [type='submit'] {
271 | -webkit-appearance: button;
272 | /* 1 */
273 | background-color: transparent;
274 | /* 2 */
275 | background-image: none;
276 | /* 2 */
277 | }
278 |
279 | /*
280 | Use the modern Firefox focus style for all focusable elements.
281 | */
282 |
283 | :-moz-focusring {
284 | outline: auto;
285 | }
286 |
287 | /*
288 | Remove the additional ':invalid' styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
289 | */
290 |
291 | :-moz-ui-invalid {
292 | box-shadow: none;
293 | }
294 |
295 | /*
296 | Add the correct vertical alignment in Chrome and Firefox.
297 | */
298 |
299 | progress {
300 | vertical-align: baseline;
301 | }
302 |
303 | /*
304 | Correct the cursor style of increment and decrement buttons in Safari.
305 | */
306 |
307 | ::-webkit-inner-spin-button,
308 | ::-webkit-outer-spin-button {
309 | height: auto;
310 | }
311 |
312 | /*
313 | 1. Correct the odd appearance in Chrome and Safari.
314 | 2. Correct the outline style in Safari.
315 | */
316 |
317 | [type='search'] {
318 | -webkit-appearance: textfield;
319 | /* 1 */
320 | outline-offset: -2px;
321 | /* 2 */
322 | }
323 |
324 | /*
325 | Remove the inner padding in Chrome and Safari on macOS.
326 | */
327 |
328 | ::-webkit-search-decoration {
329 | -webkit-appearance: none;
330 | }
331 |
332 | /*
333 | 1. Correct the inability to style clickable types in iOS and Safari.
334 | 2. Change font properties to 'inherit' in Safari.
335 | */
336 |
337 | ::-webkit-file-upload-button {
338 | -webkit-appearance: button;
339 | /* 1 */
340 | font: inherit;
341 | /* 2 */
342 | }
343 |
344 | /*
345 | Add the correct display in Chrome and Safari.
346 | */
347 |
348 | summary {
349 | display: list-item;
350 | }
351 |
352 | /*
353 | Removes the default spacing and border for appropriate elements.
354 | */
355 |
356 | fieldset {
357 | margin: 0;
358 | padding: 0;
359 | }
360 |
361 | legend {
362 | padding: 0;
363 | }
364 |
365 |
366 | /*
367 | Prevent resizing textareas horizontally by default.
368 | */
369 |
370 | textarea {
371 | resize: vertical;
372 | }
373 |
374 | /*
375 | 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
376 | 2. Set the default placeholder color to the user's configured gray 400 color.
377 | */
378 |
379 | input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
380 | opacity: 1;
381 | /* 1 */
382 | color: #9ca3af;
383 | /* 2 */
384 | }
385 |
386 | input::placeholder,
387 | textarea::placeholder {
388 | opacity: 1;
389 | /* 1 */
390 | color: #9ca3af;
391 | /* 2 */
392 | }
393 |
394 | /*
395 | Set the default cursor for buttons.
396 | */
397 |
398 | button,
399 | [role="button"] {
400 | cursor: pointer;
401 | }
402 |
403 | /*
404 | Make sure disabled buttons don't get the pointer cursor.
405 | */
406 |
407 | :disabled {
408 | cursor: default;
409 | }
410 |
411 | /*
412 | 1. Make replaced elements 'display: block' by default. (https://github.com/mozdevs/cssremedy/issues/14)
413 | 2. Add 'vertical-align: middle' to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
414 | This can trigger a poorly considered lint error in some tools but is included by design.
415 | */
416 |
417 | img,
418 | svg,
419 | video,
420 | canvas,
421 | audio,
422 | iframe,
423 | embed,
424 | object {
425 | display: block;
426 | /* 1 */
427 | vertical-align: middle;
428 | /* 2 */
429 | }
430 |
431 | /*
432 | Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
433 | */
434 |
435 | img,
436 | video {
437 | max-width: 100%;
438 | height: auto;
439 | }
440 |
441 | /* Make elements with the HTML hidden attribute stay hidden by default */
442 |
443 | [hidden] {
444 | display: none;
445 | }
446 |
447 | *, ::before, ::after {
448 | --tw-border-spacing-x: 0;
449 | --tw-border-spacing-y: 0;
450 | --tw-translate-x: 0;
451 | --tw-translate-y: 0;
452 | --tw-rotate: 0;
453 | --tw-skew-x: 0;
454 | --tw-skew-y: 0;
455 | --tw-scale-x: 1;
456 | --tw-scale-y: 1;
457 | --tw-pan-x: ;
458 | --tw-pan-y: ;
459 | --tw-pinch-zoom: ;
460 | --tw-scroll-snap-strictness: proximity;
461 | --tw-gradient-from-position: ;
462 | --tw-gradient-via-position: ;
463 | --tw-gradient-to-position: ;
464 | --tw-ordinal: ;
465 | --tw-slashed-zero: ;
466 | --tw-numeric-figure: ;
467 | --tw-numeric-spacing: ;
468 | --tw-numeric-fraction: ;
469 | --tw-ring-inset: ;
470 | --tw-ring-offset-width: 0px;
471 | --tw-ring-offset-color: #fff;
472 | --tw-ring-color: rgb(59 130 246 / 0.5);
473 | --tw-ring-offset-shadow: 0 0 #0000;
474 | --tw-ring-shadow: 0 0 #0000;
475 | --tw-shadow: 0 0 #0000;
476 | --tw-shadow-colored: 0 0 #0000;
477 | --tw-blur: ;
478 | --tw-brightness: ;
479 | --tw-contrast: ;
480 | --tw-grayscale: ;
481 | --tw-hue-rotate: ;
482 | --tw-invert: ;
483 | --tw-saturate: ;
484 | --tw-sepia: ;
485 | --tw-drop-shadow: ;
486 | --tw-backdrop-blur: ;
487 | --tw-backdrop-brightness: ;
488 | --tw-backdrop-contrast: ;
489 | --tw-backdrop-grayscale: ;
490 | --tw-backdrop-hue-rotate: ;
491 | --tw-backdrop-invert: ;
492 | --tw-backdrop-opacity: ;
493 | --tw-backdrop-saturate: ;
494 | --tw-backdrop-sepia: ;
495 | }
496 |
497 | ::-webkit-backdrop {
498 | --tw-border-spacing-x: 0;
499 | --tw-border-spacing-y: 0;
500 | --tw-translate-x: 0;
501 | --tw-translate-y: 0;
502 | --tw-rotate: 0;
503 | --tw-skew-x: 0;
504 | --tw-skew-y: 0;
505 | --tw-scale-x: 1;
506 | --tw-scale-y: 1;
507 | --tw-pan-x: ;
508 | --tw-pan-y: ;
509 | --tw-pinch-zoom: ;
510 | --tw-scroll-snap-strictness: proximity;
511 | --tw-gradient-from-position: ;
512 | --tw-gradient-via-position: ;
513 | --tw-gradient-to-position: ;
514 | --tw-ordinal: ;
515 | --tw-slashed-zero: ;
516 | --tw-numeric-figure: ;
517 | --tw-numeric-spacing: ;
518 | --tw-numeric-fraction: ;
519 | --tw-ring-inset: ;
520 | --tw-ring-offset-width: 0px;
521 | --tw-ring-offset-color: #fff;
522 | --tw-ring-color: rgb(59 130 246 / 0.5);
523 | --tw-ring-offset-shadow: 0 0 #0000;
524 | --tw-ring-shadow: 0 0 #0000;
525 | --tw-shadow: 0 0 #0000;
526 | --tw-shadow-colored: 0 0 #0000;
527 | --tw-blur: ;
528 | --tw-brightness: ;
529 | --tw-contrast: ;
530 | --tw-grayscale: ;
531 | --tw-hue-rotate: ;
532 | --tw-invert: ;
533 | --tw-saturate: ;
534 | --tw-sepia: ;
535 | --tw-drop-shadow: ;
536 | --tw-backdrop-blur: ;
537 | --tw-backdrop-brightness: ;
538 | --tw-backdrop-contrast: ;
539 | --tw-backdrop-grayscale: ;
540 | --tw-backdrop-hue-rotate: ;
541 | --tw-backdrop-invert: ;
542 | --tw-backdrop-opacity: ;
543 | --tw-backdrop-saturate: ;
544 | --tw-backdrop-sepia: ;
545 | }
546 |
547 | ::backdrop {
548 | --tw-border-spacing-x: 0;
549 | --tw-border-spacing-y: 0;
550 | --tw-translate-x: 0;
551 | --tw-translate-y: 0;
552 | --tw-rotate: 0;
553 | --tw-skew-x: 0;
554 | --tw-skew-y: 0;
555 | --tw-scale-x: 1;
556 | --tw-scale-y: 1;
557 | --tw-pan-x: ;
558 | --tw-pan-y: ;
559 | --tw-pinch-zoom: ;
560 | --tw-scroll-snap-strictness: proximity;
561 | --tw-gradient-from-position: ;
562 | --tw-gradient-via-position: ;
563 | --tw-gradient-to-position: ;
564 | --tw-ordinal: ;
565 | --tw-slashed-zero: ;
566 | --tw-numeric-figure: ;
567 | --tw-numeric-spacing: ;
568 | --tw-numeric-fraction: ;
569 | --tw-ring-inset: ;
570 | --tw-ring-offset-width: 0px;
571 | --tw-ring-offset-color: #fff;
572 | --tw-ring-color: rgb(59 130 246 / 0.5);
573 | --tw-ring-offset-shadow: 0 0 #0000;
574 | --tw-ring-shadow: 0 0 #0000;
575 | --tw-shadow: 0 0 #0000;
576 | --tw-shadow-colored: 0 0 #0000;
577 | --tw-blur: ;
578 | --tw-brightness: ;
579 | --tw-contrast: ;
580 | --tw-grayscale: ;
581 | --tw-hue-rotate: ;
582 | --tw-invert: ;
583 | --tw-saturate: ;
584 | --tw-sepia: ;
585 | --tw-drop-shadow: ;
586 | --tw-backdrop-blur: ;
587 | --tw-backdrop-brightness: ;
588 | --tw-backdrop-contrast: ;
589 | --tw-backdrop-grayscale: ;
590 | --tw-backdrop-hue-rotate: ;
591 | --tw-backdrop-invert: ;
592 | --tw-backdrop-opacity: ;
593 | --tw-backdrop-saturate: ;
594 | --tw-backdrop-sepia: ;
595 | }
596 |
597 | .cl-trigger {
598 | display: flex;
599 | height: 3rem;
600 | width: 3rem;
601 | align-items: center;
602 | justify-content: center;
603 | border-radius: 9999px;
604 | --tw-bg-opacity: 1;
605 | background-color: rgb(59 130 246 / var(--tw-bg-opacity));
606 | font-weight: 700;
607 | --tw-text-opacity: 1;
608 | color: rgb(255 255 255 / var(--tw-text-opacity));
609 | transition-property: all;
610 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
611 | transition-duration: 150ms;
612 | }
613 |
614 | .cl-trigger:hover {
615 | --tw-bg-opacity: 1;
616 | background-color: rgb(29 78 216 / var(--tw-bg-opacity));
617 | }
618 |
619 | .cl-window {
620 | display: flex;
621 | flex-direction: column;
622 | overflow: hidden;
623 | border-radius: 1rem;
624 | --tw-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
625 | --tw-shadow-colored: 0 0 10px var(--tw-shadow-color);
626 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
627 | }
628 |
629 | .cl-scale-100 {
630 | --tw-scale-x: 1;
631 | --tw-scale-y: 1;
632 | -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
633 | transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
634 | }
635 |
636 | .cl-scale-0 {
637 | --tw-scale-x: 0;
638 | --tw-scale-y: 0;
639 | -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
640 | transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
641 | }
642 |
643 | .cl-trigger-icon {
644 | position: absolute;
645 | height: 50%;
646 | width: 50%;
647 | transition-property: all;
648 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
649 | transition-duration: 500ms;
650 | }
651 |
652 | .cl-chat-window {
653 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
654 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
655 | sans-serif;
656 | position: absolute;
657 | transition-property: all;
658 | transition-duration: 300ms;
659 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
660 | }
661 |
662 | .cl-online-message {
663 | height: 0.5rem;
664 | width: 0.5rem;
665 | border-radius: 9999px;
666 | --tw-bg-opacity: 1;
667 | background-color: rgb(34 197 94 / var(--tw-bg-opacity));
668 | }
669 |
670 | .cl-offline-message {
671 | height: 0.5rem;
672 | width: 0.5rem;
673 | border-radius: 9999px;
674 | --tw-bg-opacity: 1;
675 | background-color: rgb(239 68 68 / var(--tw-bg-opacity));
676 | }
677 |
678 | .cl-send-icon {
679 | margin-right: 1.25rem;
680 | height: 1.5rem;
681 | width: 1.5rem;
682 | }
683 |
684 | .cl-notsending-message {
685 | stroke: #3b82f6;
686 | }
687 |
688 | .cl-notsending-message:hover {
689 | stroke: #60a5fa;
690 | }
691 |
692 | .cl-sending-message {
693 | stroke: #9ca3af;
694 | }
695 |
696 | .cl-header-subtitle {
697 | display: flex;
698 | align-items: center;
699 | gap: 0.5rem;
700 | font-size: 0.875rem;
701 | line-height: 1.25rem;
702 | font-weight: 300;
703 | color: rgb(107 114 128);
704 | }
705 |
706 | .cl-header {
707 | z-index: 10;
708 | display: flex;
709 | flex-direction: column;
710 | --tw-bg-opacity: 1;
711 | background-color: rgb(255 255 255 / var(--tw-bg-opacity));
712 | padding-top: 1rem;
713 | padding-bottom: 1rem;
714 | padding-left: 1.5rem;
715 | padding-right: 1.5rem;
716 | font-size: 1.125rem;
717 | line-height: 1.75rem;
718 | font-weight: 400;
719 | color: rgb(17 24 39);
720 | --tw-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
721 | --tw-shadow-colored: 0 0 10px var(--tw-shadow-color);
722 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
723 | }
724 |
725 | .cl-messages_container {
726 | z-index: 0;
727 | display: flex;
728 | height: 100%;
729 | width: 100%;
730 | flex-direction: column;
731 | overflow: scroll;
732 | overflow-x: clip;
733 | --tw-bg-opacity: 1;
734 | background-color: rgb(249 250 251 / var(--tw-bg-opacity));
735 | padding-left: 1rem;
736 | padding-right: 1rem;
737 | padding-top: 0.5rem;
738 | padding-bottom: 0.5rem;
739 | -ms-overflow-style: none;
740 | scrollbar-width: none;
741 | }
742 |
743 | .cl-messages_container::-webkit-scrollbar {
744 | display: none;
745 | }
746 |
747 | .cl-input_container {
748 | display: flex;
749 | width: 100%;
750 | align-items: center;
751 | border-top-width: 1px;
752 | --tw-border-opacity: 1;
753 | border-color: rgb(229 231 235 / var(--tw-border-opacity));
754 | --tw-bg-opacity: 1;
755 | background-color: rgb(255 255 255 / var(--tw-bg-opacity));
756 | }
757 |
758 | .cl-chat-message {
759 | display: flex;
760 | width: 100%;
761 | padding-top: 0.5rem;
762 | padding-bottom: 0.5rem;
763 | padding-left: 0.5rem;
764 | padding-right: 0.5rem;
765 | }
766 |
767 | @-webkit-keyframes pulse {
768 | 50% {
769 | opacity: .5;
770 | }
771 | }
772 |
773 | @keyframes pulse {
774 | 50% {
775 | opacity: .5;
776 | }
777 | }
778 |
779 | .cl-animate-pulse {
780 | -webkit-animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
781 | animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
782 | }
783 |
784 | .cl-justify-start {
785 | justify-content: flex-start;
786 | }
787 |
788 | .cl-justify-end {
789 | justify-content: flex-end;
790 | }
791 |
792 | .cl-input-element {
793 | height: 100%;
794 | width: 100%;
795 | padding-left: 1.25rem;
796 | padding-right: 1.25rem;
797 | padding-top: 1.25rem;
798 | padding-bottom: 1.25rem;
799 | font-weight: 300;
800 | background-color: rgb(255 255 255);
801 | color: rgb(17 24 39);
802 | }
803 |
804 | .cl-input-element:focus {
805 | outline: 2px solid transparent;
806 | outline-offset: 2px;
807 | }
808 |
809 | .cl-user_message {
810 | width: -webkit-fit-content;
811 | width: -moz-fit-content;
812 | width: fit-content;
813 | max-width: 90%;
814 | -webkit-column-break-before: all;
815 | break-before: all;
816 | border-radius: 0.75rem;
817 | border-top-right-radius: 0.125rem;
818 | --tw-bg-opacity: 1;
819 | background-color: rgb(59 130 246 / var(--tw-bg-opacity));
820 | padding-left: 1rem;
821 | padding-right: 1rem;
822 | padding-top: 0.5rem;
823 | padding-bottom: 0.5rem;
824 | text-align: right;
825 | --tw-text-opacity: 1;
826 | color: rgb(255 255 255 / var(--tw-text-opacity));
827 | }
828 |
829 | .cl-error_message {
830 | width: -webkit-fit-content;
831 | width: -moz-fit-content;
832 | width: fit-content;
833 | max-width: 90%;
834 | -webkit-column-break-before: all;
835 | break-before: all;
836 | border-radius: 0.75rem;
837 | border-top-left-radius: 0.125rem;
838 | --tw-bg-opacity: 1;
839 | background-color: rgb(248 113 113 / var(--tw-bg-opacity));
840 | padding-left: 1rem;
841 | padding-right: 1rem;
842 | padding-top: 0.5rem;
843 | padding-bottom: 0.5rem;
844 | text-align: left;
845 | --tw-text-opacity: 1;
846 | color: rgb(255 255 255 / var(--tw-text-opacity));
847 | }
848 |
849 | .cl-bot_message {
850 | width: -webkit-fit-content;
851 | width: -moz-fit-content;
852 | width: fit-content;
853 | max-width: 90%;
854 | -webkit-column-break-before: all;
855 | break-before: all;
856 | border-radius: 0.75rem;
857 | border-top-left-radius: 0.125rem;
858 | --tw-bg-opacity: 1;
859 | background-color: rgb(229 231 235 / var(--tw-bg-opacity));
860 | padding-left: 1rem;
861 | padding-right: 1rem;
862 | padding-top: 0.5rem;
863 | padding-bottom: 0.5rem;
864 | text-align: left;
865 | --tw-text-opacity: 1;
866 | color: rgb(31 41 55 / var(--tw-text-opacity));
867 | }
868 |
869 | .origin-bottom {
870 | -webkit-transform-origin: bottom;
871 | transform-origin: bottom;
872 | }
873 |
874 | .origin-bottom-left {
875 | -webkit-transform-origin: bottom left;
876 | transform-origin: bottom left;
877 | }
878 |
879 | .origin-bottom-right {
880 | -webkit-transform-origin: bottom right;
881 | transform-origin: bottom right;
882 | }
883 |
884 | .origin-center {
885 | -webkit-transform-origin: center;
886 | transform-origin: center;
887 | }
888 |
889 | .origin-top {
890 | -webkit-transform-origin: top;
891 | transform-origin: top;
892 | }
893 |
894 | .origin-top-left {
895 | -webkit-transform-origin: top left;
896 | transform-origin: top left;
897 | }
898 |
899 | .origin-top-right {
900 | -webkit-transform-origin: top right;
901 | transform-origin: top right;
902 | }
903 |
904 | .shadow {
905 | --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
906 | --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
907 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
908 | }
909 | input::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
910 | color: rgb(156 163 175);
911 | opacity: 1; /* Firefox */
912 | }
913 |
914 | input:-ms-input-placeholder { /* Internet Explorer 10-11 */
915 | color: rgb(156 163 175);
916 | }
917 |
918 | input::-ms-input-placeholder { /* Microsoft Edge */
919 | color: rgb(156 163 175);
920 | }
921 | `;
922 |
923 | const markdownBody = `
924 |
925 | .markdown-body {
926 | --base-size-4: 0.25rem;
927 | --base-size-8: 0.5rem;
928 | --base-size-16: 1rem;
929 | --base-text-weight-normal: 400;
930 | --base-text-weight-medium: 500;
931 | --base-text-weight-semibold: 600;
932 | --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
933 | }
934 |
935 | @media (prefers-color-scheme: dark) {
936 | .markdown-body,
937 | [data-theme="dark"] {
938 | /*dark*/
939 | color-scheme: dark;
940 | --focus-outlineColor: #1f6feb;
941 | --fgColor-default: #e6edf3;
942 | --fgColor-muted: #8d96a0;
943 | --fgColor-accent: #4493f8;
944 | --fgColor-success: #3fb950;
945 | --fgColor-attention: #d29922;
946 | --fgColor-danger: #f85149;
947 | --fgColor-done: #ab7df8;
948 | --bgColor-default: #0d1117;
949 | --bgColor-muted: #161b22;
950 | --bgColor-neutral-muted: #6e768166;
951 | --bgColor-attention-muted: #bb800926;
952 | --borderColor-default: #30363d;
953 | --borderColor-muted: #30363db3;
954 | --borderColor-neutral-muted: #6e768166;
955 | --borderColor-accent-emphasis: #1f6feb;
956 | --borderColor-success-emphasis: #238636;
957 | --borderColor-attention-emphasis: #9e6a03;
958 | --borderColor-danger-emphasis: #da3633;
959 | --borderColor-done-emphasis: #8957e5;
960 | --color-prettylights-syntax-comment: #8b949e;
961 | --color-prettylights-syntax-constant: #79c0ff;
962 | --color-prettylights-syntax-constant-other-reference-link: #a5d6ff;
963 | --color-prettylights-syntax-entity: #d2a8ff;
964 | --color-prettylights-syntax-storage-modifier-import: #c9d1d9;
965 | --color-prettylights-syntax-entity-tag: #7ee787;
966 | --color-prettylights-syntax-keyword: #ff7b72;
967 | --color-prettylights-syntax-string: #a5d6ff;
968 | --color-prettylights-syntax-variable: #ffa657;
969 | --color-prettylights-syntax-brackethighlighter-unmatched: #f85149;
970 | --color-prettylights-syntax-brackethighlighter-angle: #8b949e;
971 | --color-prettylights-syntax-invalid-illegal-text: #f0f6fc;
972 | --color-prettylights-syntax-invalid-illegal-bg: #8e1519;
973 | --color-prettylights-syntax-carriage-return-text: #f0f6fc;
974 | --color-prettylights-syntax-carriage-return-bg: #b62324;
975 | --color-prettylights-syntax-string-regexp: #7ee787;
976 | --color-prettylights-syntax-markup-list: #f2cc60;
977 | --color-prettylights-syntax-markup-heading: #1f6feb;
978 | --color-prettylights-syntax-markup-italic: #c9d1d9;
979 | --color-prettylights-syntax-markup-bold: #c9d1d9;
980 | --color-prettylights-syntax-markup-deleted-text: #ffdcd7;
981 | --color-prettylights-syntax-markup-deleted-bg: #67060c;
982 | --color-prettylights-syntax-markup-inserted-text: #aff5b4;
983 | --color-prettylights-syntax-markup-inserted-bg: #033a16;
984 | --color-prettylights-syntax-markup-changed-text: #ffdfb6;
985 | --color-prettylights-syntax-markup-changed-bg: #5a1e02;
986 | --color-prettylights-syntax-markup-ignored-text: #c9d1d9;
987 | --color-prettylights-syntax-markup-ignored-bg: #1158c7;
988 | --color-prettylights-syntax-meta-diff-range: #d2a8ff;
989 | --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58;
990 | }
991 | }
992 |
993 | @media (prefers-color-scheme: light) {
994 | .markdown-body,
995 | [data-theme="light"] {
996 | /*light*/
997 | color-scheme: light;
998 | --focus-outlineColor: #0969da;
999 | --fgColor-default: #1f2328;
1000 | --fgColor-muted: #636c76;
1001 | --fgColor-accent: #0969da;
1002 | --fgColor-success: #1a7f37;
1003 | --fgColor-attention: #9a6700;
1004 | --fgColor-danger: #d1242f;
1005 | --fgColor-done: #8250df;
1006 | --bgColor-default: #ffffff;
1007 | --bgColor-muted: #f6f8fa;
1008 | --bgColor-neutral-muted: #afb8c133;
1009 | --bgColor-attention-muted: #fff8c5;
1010 | --borderColor-default: #d0d7de;
1011 | --borderColor-muted: #d0d7deb3;
1012 | --borderColor-neutral-muted: #afb8c133;
1013 | --borderColor-accent-emphasis: #0969da;
1014 | --borderColor-success-emphasis: #1a7f37;
1015 | --borderColor-attention-emphasis: #bf8700;
1016 | --borderColor-danger-emphasis: #cf222e;
1017 | --borderColor-done-emphasis: #8250df;
1018 | --color-prettylights-syntax-comment: #57606a;
1019 | --color-prettylights-syntax-constant: #0550ae;
1020 | --color-prettylights-syntax-constant-other-reference-link: #0a3069;
1021 | --color-prettylights-syntax-entity: #6639ba;
1022 | --color-prettylights-syntax-storage-modifier-import: #24292f;
1023 | --color-prettylights-syntax-entity-tag: #0550ae;
1024 | --color-prettylights-syntax-keyword: #cf222e;
1025 | --color-prettylights-syntax-string: #0a3069;
1026 | --color-prettylights-syntax-variable: #953800;
1027 | --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;
1028 | --color-prettylights-syntax-brackethighlighter-angle: #57606a;
1029 | --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;
1030 | --color-prettylights-syntax-invalid-illegal-bg: #82071e;
1031 | --color-prettylights-syntax-carriage-return-text: #f6f8fa;
1032 | --color-prettylights-syntax-carriage-return-bg: #cf222e;
1033 | --color-prettylights-syntax-string-regexp: #116329;
1034 | --color-prettylights-syntax-markup-list: #3b2300;
1035 | --color-prettylights-syntax-markup-heading: #0550ae;
1036 | --color-prettylights-syntax-markup-italic: #24292f;
1037 | --color-prettylights-syntax-markup-bold: #24292f;
1038 | --color-prettylights-syntax-markup-deleted-text: #82071e;
1039 | --color-prettylights-syntax-markup-deleted-bg: #ffebe9;
1040 | --color-prettylights-syntax-markup-inserted-text: #116329;
1041 | --color-prettylights-syntax-markup-inserted-bg: #dafbe1;
1042 | --color-prettylights-syntax-markup-changed-text: #953800;
1043 | --color-prettylights-syntax-markup-changed-bg: #ffd8b5;
1044 | --color-prettylights-syntax-markup-ignored-text: #eaeef2;
1045 | --color-prettylights-syntax-markup-ignored-bg: #0550ae;
1046 | --color-prettylights-syntax-meta-diff-range: #8250df;
1047 | --color-prettylights-syntax-sublimelinter-gutter-mark: #8c959f;
1048 | }
1049 | }
1050 |
1051 | .markdown-body {
1052 | -ms-text-size-adjust: 100%;
1053 | -webkit-text-size-adjust: 100%;
1054 | margin: 0;
1055 | font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
1056 | font-size: 16px;
1057 | line-height: 1.5;
1058 | word-wrap: break-word;
1059 | scroll-behavior: auto;
1060 | }
1061 |
1062 | .markdown-body .octicon {
1063 | display: inline-block;
1064 | fill: currentColor;
1065 | vertical-align: text-bottom;
1066 | }
1067 |
1068 | .markdown-body h1:hover .anchor .octicon-link:before,
1069 | .markdown-body h2:hover .anchor .octicon-link:before,
1070 | .markdown-body h3:hover .anchor .octicon-link:before,
1071 | .markdown-body h4:hover .anchor .octicon-link:before,
1072 | .markdown-body h5:hover .anchor .octicon-link:before,
1073 | .markdown-body h6:hover .anchor .octicon-link:before {
1074 | width: 16px;
1075 | height: 16px;
1076 | content: ' ';
1077 | display: inline-block;
1078 | background-color: currentColor;
1079 | -webkit-mask-image: url("data:image/svg+xml,");
1080 | mask-image: url("data:image/svg+xml,");
1081 | }
1082 |
1083 | .markdown-body details,
1084 | .markdown-body figcaption,
1085 | .markdown-body figure {
1086 | display: block;
1087 | }
1088 |
1089 | .markdown-body summary {
1090 | display: list-item;
1091 | }
1092 |
1093 | .markdown-body [hidden] {
1094 | display: none !important;
1095 | }
1096 |
1097 | .markdown-body a {
1098 | background-color: transparent;
1099 | color: var(--fgColor-accent);
1100 | text-decoration: none;
1101 | }
1102 |
1103 | .markdown-body abbr[title] {
1104 | border-bottom: none;
1105 | -webkit-text-decoration: underline dotted;
1106 | text-decoration: underline dotted;
1107 | }
1108 |
1109 | .markdown-body b,
1110 | .markdown-body strong {
1111 | font-weight: var(--base-text-weight-semibold, 600);
1112 | }
1113 |
1114 | .markdown-body dfn {
1115 | font-style: italic;
1116 | }
1117 |
1118 | .markdown-body h1 {
1119 | margin: .67em 0;
1120 | font-weight: var(--base-text-weight-semibold, 600);
1121 | padding-bottom: .3em;
1122 | font-size: 2em;
1123 | border-bottom: 1px solid var(--borderColor-muted);
1124 | }
1125 |
1126 | .markdown-body mark {
1127 | background-color: var(--bgColor-attention-muted);
1128 | color: var(--fgColor-default);
1129 | }
1130 |
1131 | .markdown-body small {
1132 | font-size: 90%;
1133 | }
1134 |
1135 | .markdown-body sub,
1136 | .markdown-body sup {
1137 | font-size: 75%;
1138 | line-height: 0;
1139 | position: relative;
1140 | vertical-align: baseline;
1141 | }
1142 |
1143 | .markdown-body sub {
1144 | bottom: -0.25em;
1145 | }
1146 |
1147 | .markdown-body sup {
1148 | top: -0.5em;
1149 | }
1150 |
1151 | .markdown-body img {
1152 | border-style: none;
1153 | max-width: 100%;
1154 | box-sizing: content-box;
1155 | }
1156 |
1157 | .markdown-body code,
1158 | .markdown-body kbd,
1159 | .markdown-body pre,
1160 | .markdown-body samp {
1161 | font-family: monospace;
1162 | font-size: 1em;
1163 | }
1164 |
1165 | .markdown-body figure {
1166 | margin: 1em 40px;
1167 | }
1168 |
1169 | .markdown-body hr {
1170 | box-sizing: content-box;
1171 | overflow: hidden;
1172 | background: transparent;
1173 | border-bottom: 1px solid var(--borderColor-muted);
1174 | height: .25em;
1175 | padding: 0;
1176 | margin: 24px 0;
1177 | background-color: var(--borderColor-default);
1178 | border: 0;
1179 | }
1180 |
1181 | .markdown-body input {
1182 | font: inherit;
1183 | margin: 0;
1184 | overflow: visible;
1185 | font-family: inherit;
1186 | font-size: inherit;
1187 | line-height: inherit;
1188 | }
1189 |
1190 | .markdown-body [type=button],
1191 | .markdown-body [type=reset],
1192 | .markdown-body [type=submit] {
1193 | -webkit-appearance: button;
1194 | appearance: button;
1195 | }
1196 |
1197 | .markdown-body [type=checkbox],
1198 | .markdown-body [type=radio] {
1199 | box-sizing: border-box;
1200 | padding: 0;
1201 | }
1202 |
1203 | .markdown-body [type=number]::-webkit-inner-spin-button,
1204 | .markdown-body [type=number]::-webkit-outer-spin-button {
1205 | height: auto;
1206 | }
1207 |
1208 | .markdown-body [type=search]::-webkit-search-cancel-button,
1209 | .markdown-body [type=search]::-webkit-search-decoration {
1210 | -webkit-appearance: none;
1211 | appearance: none;
1212 | }
1213 |
1214 | .markdown-body ::-webkit-input-placeholder {
1215 | color: inherit;
1216 | opacity: .54;
1217 | }
1218 |
1219 | .markdown-body ::-webkit-file-upload-button {
1220 | -webkit-appearance: button;
1221 | appearance: button;
1222 | font: inherit;
1223 | }
1224 |
1225 | .markdown-body a:hover {
1226 | text-decoration: underline;
1227 | }
1228 |
1229 | .markdown-body ::placeholder {
1230 | color: var(--fgColor-muted);
1231 | opacity: 1;
1232 | }
1233 |
1234 | .markdown-body hr::before {
1235 | display: table;
1236 | content: "";
1237 | }
1238 |
1239 | .markdown-body hr::after {
1240 | display: table;
1241 | clear: both;
1242 | content: "";
1243 | }
1244 |
1245 | .markdown-body table {
1246 | border-spacing: 0;
1247 | border-collapse: collapse;
1248 | display: block;
1249 | width: max-content;
1250 | max-width: 100%;
1251 | overflow: auto;
1252 | }
1253 |
1254 | .markdown-body td,
1255 | .markdown-body th {
1256 | padding: 0;
1257 | }
1258 |
1259 | .markdown-body details summary {
1260 | cursor: pointer;
1261 | }
1262 |
1263 | .markdown-body details:not([open])>*:not(summary) {
1264 | display: none;
1265 | }
1266 |
1267 | .markdown-body a:focus,
1268 | .markdown-body [role=button]:focus,
1269 | .markdown-body input[type=radio]:focus,
1270 | .markdown-body input[type=checkbox]:focus {
1271 | outline: 2px solid var(--focus-outlineColor);
1272 | outline-offset: -2px;
1273 | box-shadow: none;
1274 | }
1275 |
1276 | .markdown-body a:focus:not(:focus-visible),
1277 | .markdown-body [role=button]:focus:not(:focus-visible),
1278 | .markdown-body input[type=radio]:focus:not(:focus-visible),
1279 | .markdown-body input[type=checkbox]:focus:not(:focus-visible) {
1280 | outline: solid 1px transparent;
1281 | }
1282 |
1283 | .markdown-body a:focus-visible,
1284 | .markdown-body [role=button]:focus-visible,
1285 | .markdown-body input[type=radio]:focus-visible,
1286 | .markdown-body input[type=checkbox]:focus-visible {
1287 | outline: 2px solid var(--focus-outlineColor);
1288 | outline-offset: -2px;
1289 | box-shadow: none;
1290 | }
1291 |
1292 | .markdown-body a:not([class]):focus,
1293 | .markdown-body a:not([class]):focus-visible,
1294 | .markdown-body input[type=radio]:focus,
1295 | .markdown-body input[type=radio]:focus-visible,
1296 | .markdown-body input[type=checkbox]:focus,
1297 | .markdown-body input[type=checkbox]:focus-visible {
1298 | outline-offset: 0;
1299 | }
1300 |
1301 | .markdown-body kbd {
1302 | display: inline-block;
1303 | padding: 3px 5px;
1304 | font: 11px var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
1305 | line-height: 10px;
1306 | color: var(--fgColor-default);
1307 | vertical-align: middle;
1308 | background-color: var(--bgColor-muted);
1309 | border: solid 1px var(--borderColor-neutral-muted);
1310 | border-bottom-color: var(--borderColor-neutral-muted);
1311 | border-radius: 6px;
1312 | box-shadow: inset 0 -1px 0 var(--borderColor-neutral-muted);
1313 | }
1314 |
1315 | .markdown-body h1,
1316 | .markdown-body h2,
1317 | .markdown-body h3,
1318 | .markdown-body h4,
1319 | .markdown-body h5,
1320 | .markdown-body h6 {
1321 | margin-top: 24px;
1322 | margin-bottom: 16px;
1323 | font-weight: var(--base-text-weight-semibold, 600);
1324 | line-height: 1.25;
1325 | }
1326 |
1327 | .markdown-body h2 {
1328 | font-weight: var(--base-text-weight-semibold, 600);
1329 | padding-bottom: .3em;
1330 | font-size: 1.5em;
1331 | border-bottom: 1px solid var(--borderColor-muted);
1332 | }
1333 |
1334 | .markdown-body h3 {
1335 | font-weight: var(--base-text-weight-semibold, 600);
1336 | font-size: 1.25em;
1337 | }
1338 |
1339 | .markdown-body h4 {
1340 | font-weight: var(--base-text-weight-semibold, 600);
1341 | font-size: 1em;
1342 | }
1343 |
1344 | .markdown-body h5 {
1345 | font-weight: var(--base-text-weight-semibold, 600);
1346 | font-size: .875em;
1347 | }
1348 |
1349 | .markdown-body h6 {
1350 | font-weight: var(--base-text-weight-semibold, 600);
1351 | font-size: .85em;
1352 | color: var(--fgColor-muted);
1353 | }
1354 |
1355 | .markdown-body p {
1356 | margin-top: 0;
1357 | margin-bottom: 10px;
1358 | }
1359 |
1360 | .markdown-body blockquote {
1361 | margin: 0;
1362 | padding: 0 1em;
1363 | color: var(--fgColor-muted);
1364 | }
1365 |
1366 | .markdown-body ul,
1367 | .markdown-body ol {
1368 | margin-top: 0;
1369 | margin-bottom: 0;
1370 | padding-left: 2em;
1371 | }
1372 |
1373 | .markdown-body ol ol,
1374 | .markdown-body ul ol {
1375 | list-style-type: lower-roman;
1376 | }
1377 |
1378 | .markdown-body ul ul ol,
1379 | .markdown-body ul ol ol,
1380 | .markdown-body ol ul ol,
1381 | .markdown-body ol ol ol {
1382 | list-style-type: lower-alpha;
1383 | }
1384 |
1385 | .markdown-body dd {
1386 | margin-left: 0;
1387 | }
1388 |
1389 | .markdown-body tt,
1390 | .markdown-body code,
1391 | .markdown-body samp {
1392 | font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
1393 | font-size: 12px;
1394 | }
1395 |
1396 | .markdown-body pre {
1397 | margin-top: 0;
1398 | margin-bottom: 0;
1399 | font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
1400 | font-size: 12px;
1401 | word-wrap: normal;
1402 | }
1403 |
1404 | .markdown-body .octicon {
1405 | display: inline-block;
1406 | overflow: visible !important;
1407 | vertical-align: text-bottom;
1408 | fill: currentColor;
1409 | }
1410 |
1411 | .markdown-body input::-webkit-outer-spin-button,
1412 | .markdown-body input::-webkit-inner-spin-button {
1413 | margin: 0;
1414 | -webkit-appearance: none;
1415 | appearance: none;
1416 | }
1417 |
1418 | .markdown-body .mr-2 {
1419 | margin-right: var(--base-size-8, 8px) !important;
1420 | }
1421 |
1422 | .markdown-body::before {
1423 | display: table;
1424 | content: "";
1425 | }
1426 |
1427 | .markdown-body::after {
1428 | display: table;
1429 | clear: both;
1430 | content: "";
1431 | }
1432 |
1433 | .markdown-body>*:first-child {
1434 | margin-top: 0 !important;
1435 | }
1436 |
1437 | .markdown-body>*:last-child {
1438 | margin-bottom: 0 !important;
1439 | }
1440 |
1441 | .markdown-body a:not([href]) {
1442 | color: inherit;
1443 | text-decoration: none;
1444 | }
1445 |
1446 | .markdown-body .absent {
1447 | color: var(--fgColor-danger);
1448 | }
1449 |
1450 | .markdown-body .anchor {
1451 | float: left;
1452 | padding-right: 4px;
1453 | margin-left: -20px;
1454 | line-height: 1;
1455 | }
1456 |
1457 | .markdown-body .anchor:focus {
1458 | outline: none;
1459 | }
1460 |
1461 | .markdown-body p,
1462 | .markdown-body blockquote,
1463 | .markdown-body ul,
1464 | .markdown-body ol,
1465 | .markdown-body dl,
1466 | .markdown-body table,
1467 | .markdown-body pre,
1468 | .markdown-body details {
1469 | margin-top: 0;
1470 | margin-bottom: 16px;
1471 | }
1472 |
1473 | .markdown-body blockquote>:first-child {
1474 | margin-top: 0;
1475 | }
1476 |
1477 | .markdown-body blockquote>:last-child {
1478 | margin-bottom: 0;
1479 | }
1480 |
1481 | .markdown-body h1 .octicon-link,
1482 | .markdown-body h2 .octicon-link,
1483 | .markdown-body h3 .octicon-link,
1484 | .markdown-body h4 .octicon-link,
1485 | .markdown-body h5 .octicon-link,
1486 | .markdown-body h6 .octicon-link {
1487 | color: var(--fgColor-default);
1488 | vertical-align: middle;
1489 | visibility: hidden;
1490 | }
1491 |
1492 | .markdown-body h1:hover .anchor,
1493 | .markdown-body h2:hover .anchor,
1494 | .markdown-body h3:hover .anchor,
1495 | .markdown-body h4:hover .anchor,
1496 | .markdown-body h5:hover .anchor,
1497 | .markdown-body h6:hover .anchor {
1498 | text-decoration: none;
1499 | }
1500 |
1501 | .markdown-body h1:hover .anchor .octicon-link,
1502 | .markdown-body h2:hover .anchor .octicon-link,
1503 | .markdown-body h3:hover .anchor .octicon-link,
1504 | .markdown-body h4:hover .anchor .octicon-link,
1505 | .markdown-body h5:hover .anchor .octicon-link,
1506 | .markdown-body h6:hover .anchor .octicon-link {
1507 | visibility: visible;
1508 | }
1509 |
1510 | .markdown-body h1 tt,
1511 | .markdown-body h1 code,
1512 | .markdown-body h2 tt,
1513 | .markdown-body h2 code,
1514 | .markdown-body h3 tt,
1515 | .markdown-body h3 code,
1516 | .markdown-body h4 tt,
1517 | .markdown-body h4 code,
1518 | .markdown-body h5 tt,
1519 | .markdown-body h5 code,
1520 | .markdown-body h6 tt,
1521 | .markdown-body h6 code {
1522 | padding: 0 .2em;
1523 | font-size: inherit;
1524 | }
1525 |
1526 | .markdown-body summary h1,
1527 | .markdown-body summary h2,
1528 | .markdown-body summary h3,
1529 | .markdown-body summary h4,
1530 | .markdown-body summary h5,
1531 | .markdown-body summary h6 {
1532 | display: inline-block;
1533 | }
1534 |
1535 | .markdown-body summary h1 .anchor,
1536 | .markdown-body summary h2 .anchor,
1537 | .markdown-body summary h3 .anchor,
1538 | .markdown-body summary h4 .anchor,
1539 | .markdown-body summary h5 .anchor,
1540 | .markdown-body summary h6 .anchor {
1541 | margin-left: -40px;
1542 | }
1543 |
1544 | .markdown-body summary h1,
1545 | .markdown-body summary h2 {
1546 | padding-bottom: 0;
1547 | border-bottom: 0;
1548 | }
1549 |
1550 | .markdown-body ul.no-list,
1551 | .markdown-body ol.no-list {
1552 | padding: 0;
1553 | list-style-type: none;
1554 | }
1555 |
1556 | .markdown-body ol[type="a s"] {
1557 | list-style-type: lower-alpha;
1558 | }
1559 |
1560 | .markdown-body ol[type="A s"] {
1561 | list-style-type: upper-alpha;
1562 | }
1563 |
1564 | .markdown-body ol[type="i s"] {
1565 | list-style-type: lower-roman;
1566 | }
1567 |
1568 | .markdown-body ol[type="I s"] {
1569 | list-style-type: upper-roman;
1570 | }
1571 |
1572 | .markdown-body ol[type="1"] {
1573 | list-style-type: decimal;
1574 | }
1575 |
1576 | .markdown-body div>ol:not([type]) {
1577 | list-style-type: decimal;
1578 | }
1579 |
1580 | .markdown-body ul ul,
1581 | .markdown-body ul ol,
1582 | .markdown-body ol ol,
1583 | .markdown-body ol ul {
1584 | margin-top: 0;
1585 | margin-bottom: 0;
1586 | }
1587 |
1588 | .markdown-body li>p {
1589 | margin-top: 16px;
1590 | }
1591 |
1592 | .markdown-body li+li {
1593 | margin-top: .25em;
1594 | }
1595 |
1596 | .markdown-body dl {
1597 | padding: 0;
1598 | }
1599 |
1600 | .markdown-body dl dt {
1601 | padding: 0;
1602 | margin-top: 16px;
1603 | font-size: 1em;
1604 | font-style: italic;
1605 | font-weight: var(--base-text-weight-semibold, 600);
1606 | }
1607 |
1608 | .markdown-body dl dd {
1609 | padding: 0 16px;
1610 | margin-bottom: 16px;
1611 | }
1612 |
1613 | .markdown-body table th {
1614 | font-weight: var(--base-text-weight-semibold, 600);
1615 | }
1616 |
1617 | .markdown-body table th,
1618 | .markdown-body table td {
1619 | padding: 6px 13px;
1620 | border: 1px solid var(--borderColor-default);
1621 | }
1622 |
1623 | .markdown-body table td>:last-child {
1624 | margin-bottom: 0;
1625 | }
1626 |
1627 | .markdown-body table tr {
1628 | border-top: 1px solid var(--borderColor-muted);
1629 | }
1630 |
1631 | .markdown-body table img {
1632 | background-color: transparent;
1633 | }
1634 |
1635 | .markdown-body img[align=right] {
1636 | padding-left: 20px;
1637 | }
1638 |
1639 | .markdown-body img[align=left] {
1640 | padding-right: 20px;
1641 | }
1642 |
1643 | .markdown-body .emoji {
1644 | max-width: none;
1645 | vertical-align: text-top;
1646 | background-color: transparent;
1647 | }
1648 |
1649 | .markdown-body span.frame {
1650 | display: block;
1651 | overflow: hidden;
1652 | }
1653 |
1654 | .markdown-body span.frame>span {
1655 | display: block;
1656 | float: left;
1657 | width: auto;
1658 | padding: 7px;
1659 | margin: 13px 0 0;
1660 | overflow: hidden;
1661 | border: 1px solid var(--borderColor-default);
1662 | }
1663 |
1664 | .markdown-body span.frame span img {
1665 | display: block;
1666 | float: left;
1667 | }
1668 |
1669 | .markdown-body span.frame span span {
1670 | display: block;
1671 | padding: 5px 0 0;
1672 | clear: both;
1673 | color: var(--fgColor-default);
1674 | }
1675 |
1676 | .markdown-body span.align-center {
1677 | display: block;
1678 | overflow: hidden;
1679 | clear: both;
1680 | }
1681 |
1682 | .markdown-body span.align-center>span {
1683 | display: block;
1684 | margin: 13px auto 0;
1685 | overflow: hidden;
1686 | text-align: center;
1687 | }
1688 |
1689 | .markdown-body span.align-center span img {
1690 | margin: 0 auto;
1691 | text-align: center;
1692 | }
1693 |
1694 | .markdown-body span.align-right {
1695 | display: block;
1696 | overflow: hidden;
1697 | clear: both;
1698 | }
1699 |
1700 | .markdown-body span.align-right>span {
1701 | display: block;
1702 | margin: 13px 0 0;
1703 | overflow: hidden;
1704 | text-align: right;
1705 | }
1706 |
1707 | .markdown-body span.align-right span img {
1708 | margin: 0;
1709 | text-align: right;
1710 | }
1711 |
1712 | .markdown-body span.float-left {
1713 | display: block;
1714 | float: left;
1715 | margin-right: 13px;
1716 | overflow: hidden;
1717 | }
1718 |
1719 | .markdown-body span.float-left span {
1720 | margin: 13px 0 0;
1721 | }
1722 |
1723 | .markdown-body span.float-right {
1724 | display: block;
1725 | float: right;
1726 | margin-left: 13px;
1727 | overflow: hidden;
1728 | }
1729 |
1730 | .markdown-body span.float-right>span {
1731 | display: block;
1732 | margin: 13px auto 0;
1733 | overflow: hidden;
1734 | text-align: right;
1735 | }
1736 |
1737 | .markdown-body code,
1738 | .markdown-body tt {
1739 | padding: .2em .4em;
1740 | margin: 0;
1741 | font-size: 85%;
1742 | white-space: break-spaces;
1743 | background-color: var(--bgColor-neutral-muted);
1744 | border-radius: 6px;
1745 | }
1746 |
1747 | .markdown-body code br,
1748 | .markdown-body tt br {
1749 | display: none;
1750 | }
1751 |
1752 | .markdown-body del code {
1753 | text-decoration: inherit;
1754 | }
1755 |
1756 | .markdown-body samp {
1757 | font-size: 85%;
1758 | }
1759 |
1760 | .markdown-body pre code {
1761 | font-size: 100%;
1762 | }
1763 |
1764 | .markdown-body pre>code {
1765 | padding: 0;
1766 | margin: 0;
1767 | word-break: normal;
1768 | white-space: pre;
1769 | background: transparent;
1770 | border: 0;
1771 | }
1772 |
1773 | .markdown-body .highlight {
1774 | margin-bottom: 16px;
1775 | }
1776 |
1777 | .markdown-body .highlight pre {
1778 | margin-bottom: 0;
1779 | word-break: normal;
1780 | }
1781 |
1782 | .markdown-body .highlight pre,
1783 | .markdown-body pre {
1784 | padding: 16px;
1785 | overflow: auto;
1786 | font-size: 85%;
1787 | line-height: 1.45;
1788 | color: var(--fgColor-default);
1789 | background-color: var(--bgColor-muted);
1790 | border-radius: 6px;
1791 | }
1792 |
1793 | .markdown-body pre code,
1794 | .markdown-body pre tt {
1795 | display: inline;
1796 | max-width: auto;
1797 | padding: 0;
1798 | margin: 0;
1799 | overflow: visible;
1800 | line-height: inherit;
1801 | word-wrap: normal;
1802 | background-color: transparent;
1803 | border: 0;
1804 | }
1805 |
1806 | .markdown-body .csv-data td,
1807 | .markdown-body .csv-data th {
1808 | padding: 5px;
1809 | overflow: hidden;
1810 | font-size: 12px;
1811 | line-height: 1;
1812 | text-align: left;
1813 | white-space: nowrap;
1814 | }
1815 |
1816 | .markdown-body .csv-data .blob-num {
1817 | padding: 10px 8px 9px;
1818 | text-align: right;
1819 | border: 0;
1820 | }
1821 |
1822 | .markdown-body .csv-data tr {
1823 | border-top: 0;
1824 | }
1825 |
1826 | .markdown-body .csv-data th {
1827 | font-weight: var(--base-text-weight-semibold, 600);
1828 | background: var(--bgColor-muted);
1829 | border-top: 0;
1830 | }
1831 |
1832 | .markdown-body [data-footnote-ref]::before {
1833 | content: "[";
1834 | }
1835 |
1836 | .markdown-body [data-footnote-ref]::after {
1837 | content: "]";
1838 | }
1839 |
1840 | .markdown-body .footnotes {
1841 | font-size: 12px;
1842 | color: var(--fgColor-muted);
1843 | border-top: 1px solid var(--borderColor-default);
1844 | }
1845 |
1846 | .markdown-body .footnotes ol {
1847 | padding-left: 16px;
1848 | }
1849 |
1850 | .markdown-body .footnotes ol ul {
1851 | display: inline-block;
1852 | padding-left: 16px;
1853 | margin-top: 16px;
1854 | }
1855 |
1856 | .markdown-body .footnotes li {
1857 | position: relative;
1858 | }
1859 |
1860 | .markdown-body .footnotes li:target::before {
1861 | position: absolute;
1862 | top: -8px;
1863 | right: -8px;
1864 | bottom: -8px;
1865 | left: -24px;
1866 | pointer-events: none;
1867 | content: "";
1868 | border: 2px solid var(--borderColor-accent-emphasis);
1869 | border-radius: 6px;
1870 | }
1871 |
1872 | .markdown-body .footnotes li:target {
1873 | color: var(--fgColor-default);
1874 | }
1875 |
1876 | .markdown-body .footnotes .data-footnote-backref g-emoji {
1877 | font-family: monospace;
1878 | }
1879 |
1880 | .markdown-body .pl-c {
1881 | color: var(--color-prettylights-syntax-comment);
1882 | }
1883 |
1884 | .markdown-body .pl-c1,
1885 | .markdown-body .pl-s .pl-v {
1886 | color: var(--color-prettylights-syntax-constant);
1887 | }
1888 |
1889 | .markdown-body .pl-e,
1890 | .markdown-body .pl-en {
1891 | color: var(--color-prettylights-syntax-entity);
1892 | }
1893 |
1894 | .markdown-body .pl-smi,
1895 | .markdown-body .pl-s .pl-s1 {
1896 | color: var(--color-prettylights-syntax-storage-modifier-import);
1897 | }
1898 |
1899 | .markdown-body .pl-ent {
1900 | color: var(--color-prettylights-syntax-entity-tag);
1901 | }
1902 |
1903 | .markdown-body .pl-k {
1904 | color: var(--color-prettylights-syntax-keyword);
1905 | }
1906 |
1907 | .markdown-body .pl-s,
1908 | .markdown-body .pl-pds,
1909 | .markdown-body .pl-s .pl-pse .pl-s1,
1910 | .markdown-body .pl-sr,
1911 | .markdown-body .pl-sr .pl-cce,
1912 | .markdown-body .pl-sr .pl-sre,
1913 | .markdown-body .pl-sr .pl-sra {
1914 | color: var(--color-prettylights-syntax-string);
1915 | }
1916 |
1917 | .markdown-body .pl-v,
1918 | .markdown-body .pl-smw {
1919 | color: var(--color-prettylights-syntax-variable);
1920 | }
1921 |
1922 | .markdown-body .pl-bu {
1923 | color: var(--color-prettylights-syntax-brackethighlighter-unmatched);
1924 | }
1925 |
1926 | .markdown-body .pl-ii {
1927 | color: var(--color-prettylights-syntax-invalid-illegal-text);
1928 | background-color: var(--color-prettylights-syntax-invalid-illegal-bg);
1929 | }
1930 |
1931 | .markdown-body .pl-c2 {
1932 | color: var(--color-prettylights-syntax-carriage-return-text);
1933 | background-color: var(--color-prettylights-syntax-carriage-return-bg);
1934 | }
1935 |
1936 | .markdown-body .pl-sr .pl-cce {
1937 | font-weight: bold;
1938 | color: var(--color-prettylights-syntax-string-regexp);
1939 | }
1940 |
1941 | .markdown-body .pl-ml {
1942 | color: var(--color-prettylights-syntax-markup-list);
1943 | }
1944 |
1945 | .markdown-body .pl-mh,
1946 | .markdown-body .pl-mh .pl-en,
1947 | .markdown-body .pl-ms {
1948 | font-weight: bold;
1949 | color: var(--color-prettylights-syntax-markup-heading);
1950 | }
1951 |
1952 | .markdown-body .pl-mi {
1953 | font-style: italic;
1954 | color: var(--color-prettylights-syntax-markup-italic);
1955 | }
1956 |
1957 | .markdown-body .pl-mb {
1958 | font-weight: bold;
1959 | color: var(--color-prettylights-syntax-markup-bold);
1960 | }
1961 |
1962 | .markdown-body .pl-md {
1963 | color: var(--color-prettylights-syntax-markup-deleted-text);
1964 | background-color: var(--color-prettylights-syntax-markup-deleted-bg);
1965 | }
1966 |
1967 | .markdown-body .pl-mi1 {
1968 | color: var(--color-prettylights-syntax-markup-inserted-text);
1969 | background-color: var(--color-prettylights-syntax-markup-inserted-bg);
1970 | }
1971 |
1972 | .markdown-body .pl-mc {
1973 | color: var(--color-prettylights-syntax-markup-changed-text);
1974 | background-color: var(--color-prettylights-syntax-markup-changed-bg);
1975 | }
1976 |
1977 | .markdown-body .pl-mi2 {
1978 | color: var(--color-prettylights-syntax-markup-ignored-text);
1979 | background-color: var(--color-prettylights-syntax-markup-ignored-bg);
1980 | }
1981 |
1982 | .markdown-body .pl-mdr {
1983 | font-weight: bold;
1984 | color: var(--color-prettylights-syntax-meta-diff-range);
1985 | }
1986 |
1987 | .markdown-body .pl-ba {
1988 | color: var(--color-prettylights-syntax-brackethighlighter-angle);
1989 | }
1990 |
1991 | .markdown-body .pl-sg {
1992 | color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);
1993 | }
1994 |
1995 | .markdown-body .pl-corl {
1996 | text-decoration: underline;
1997 | color: var(--color-prettylights-syntax-constant-other-reference-link);
1998 | }
1999 |
2000 | .markdown-body [role=button]:focus:not(:focus-visible),
2001 | .markdown-body [role=tabpanel][tabindex="0"]:focus:not(:focus-visible),
2002 | .markdown-body button:focus:not(:focus-visible),
2003 | .markdown-body summary:focus:not(:focus-visible),
2004 | .markdown-body a:focus:not(:focus-visible) {
2005 | outline: none;
2006 | box-shadow: none;
2007 | }
2008 |
2009 | .markdown-body [tabindex="0"]:focus:not(:focus-visible),
2010 | .markdown-body details-dialog:focus:not(:focus-visible) {
2011 | outline: none;
2012 | }
2013 |
2014 | .markdown-body g-emoji {
2015 | display: inline-block;
2016 | min-width: 1ch;
2017 | font-family: "Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
2018 | font-size: 1em;
2019 | font-style: normal !important;
2020 | font-weight: var(--base-text-weight-normal, 400);
2021 | line-height: 1;
2022 | vertical-align: -0.075em;
2023 | }
2024 |
2025 | .markdown-body g-emoji img {
2026 | width: 1em;
2027 | height: 1em;
2028 | }
2029 |
2030 | .markdown-body .task-list-item {
2031 | list-style-type: none;
2032 | }
2033 |
2034 | .markdown-body .task-list-item label {
2035 | font-weight: var(--base-text-weight-normal, 400);
2036 | }
2037 |
2038 | .markdown-body .task-list-item.enabled label {
2039 | cursor: pointer;
2040 | }
2041 |
2042 | .markdown-body .task-list-item+.task-list-item {
2043 | margin-top: var(--base-size-4);
2044 | }
2045 |
2046 | .markdown-body .task-list-item .handle {
2047 | display: none;
2048 | }
2049 |
2050 | .markdown-body .task-list-item-checkbox {
2051 | margin: 0 .2em .25em -1.4em;
2052 | vertical-align: middle;
2053 | }
2054 |
2055 | .markdown-body .contains-task-list:dir(rtl) .task-list-item-checkbox {
2056 | margin: 0 -1.6em .25em .2em;
2057 | }
2058 |
2059 | .markdown-body .contains-task-list {
2060 | position: relative;
2061 | }
2062 |
2063 | .markdown-body .contains-task-list:hover .task-list-item-convert-container,
2064 | .markdown-body .contains-task-list:focus-within .task-list-item-convert-container {
2065 | display: block;
2066 | width: auto;
2067 | height: 24px;
2068 | overflow: visible;
2069 | clip: auto;
2070 | }
2071 |
2072 | .markdown-body ::-webkit-calendar-picker-indicator {
2073 | filter: invert(50%);
2074 | }
2075 |
2076 | .markdown-body .markdown-alert {
2077 | padding: var(--base-size-8) var(--base-size-16);
2078 | margin-bottom: var(--base-size-16);
2079 | color: inherit;
2080 | border-left: .25em solid var(--borderColor-default);
2081 | }
2082 |
2083 | .markdown-body .markdown-alert>:first-child {
2084 | margin-top: 0;
2085 | }
2086 |
2087 | .markdown-body .markdown-alert>:last-child {
2088 | margin-bottom: 0;
2089 | }
2090 |
2091 | .markdown-body .markdown-alert .markdown-alert-title {
2092 | display: flex;
2093 | font-weight: var(--base-text-weight-medium, 500);
2094 | align-items: center;
2095 | line-height: 1;
2096 | }
2097 |
2098 | .markdown-body .markdown-alert.markdown-alert-note {
2099 | border-left-color: var(--borderColor-accent-emphasis);
2100 | }
2101 |
2102 | .markdown-body .markdown-alert.markdown-alert-note .markdown-alert-title {
2103 | color: var(--fgColor-accent);
2104 | }
2105 |
2106 | .markdown-body .markdown-alert.markdown-alert-important {
2107 | border-left-color: var(--borderColor-done-emphasis);
2108 | }
2109 |
2110 | .markdown-body .markdown-alert.markdown-alert-important .markdown-alert-title {
2111 | color: var(--fgColor-done);
2112 | }
2113 |
2114 | .markdown-body .markdown-alert.markdown-alert-warning {
2115 | border-left-color: var(--borderColor-attention-emphasis);
2116 | }
2117 |
2118 | .markdown-body .markdown-alert.markdown-alert-warning .markdown-alert-title {
2119 | color: var(--fgColor-attention);
2120 | }
2121 |
2122 | .markdown-body .markdown-alert.markdown-alert-tip {
2123 | border-left-color: var(--borderColor-success-emphasis);
2124 | }
2125 |
2126 | .markdown-body .markdown-alert.markdown-alert-tip .markdown-alert-title {
2127 | color: var(--fgColor-success);
2128 | }
2129 |
2130 | .markdown-body .markdown-alert.markdown-alert-caution {
2131 | border-left-color: var(--borderColor-danger-emphasis);
2132 | }
2133 |
2134 | .markdown-body .markdown-alert.markdown-alert-caution .markdown-alert-title {
2135 | color: var(--fgColor-danger);
2136 | }
2137 |
2138 | .markdown-body>*:first-child>.heading-element:first-child {
2139 | margin-top: 0 !important;
2140 | }`
2141 | return (
2142 |
2143 |
2144 |
2150 |
2183 |
2184 | );
2185 | }
2186 |
--------------------------------------------------------------------------------
/src/chatWidget/utils.ts:
--------------------------------------------------------------------------------
1 | export function getChatPosition(
2 | triggerPosition: DOMRect,
3 | Cwidth:number,
4 | Cheight:number,
5 | position?: string,
6 | ): { top: string; left: string;
7 | position?: string, } {
8 | if (!triggerPosition) {
9 | return { top: "0px", left: "0px" }; // Return empty string if trigger position is not available
10 | }
11 |
12 | const { top, left, width, height } = triggerPosition;
13 |
14 | const distance = 5; // Adjust this value to set the desired distance from the trigger
15 | if(!position) return { top: distance + height+ "px", left: width + "px" };
16 |
17 | switch (position) {
18 | case "top-left":
19 | return { top: - distance - Cheight + "px", left: -Cwidth + "px" };
20 | case "top-center":
21 | return { top: - distance - Cheight + "px", left: width/2-Cwidth / 2 + "px" };
22 | case "top-right":
23 | return { top: - distance - Cheight + "px", left: width+ "px" };
24 | case "center-left":
25 | return { top: width/2-Cheight/2 + "px", left: -Cwidth - distance + "px" };
26 | case "center-right":
27 | return {
28 | top: width/2-Cheight/2 + "px",
29 | left: width + distance + "px",
30 | };
31 | case "bottom-right":
32 | return { top: distance + height+ "px", left: width + "px" };
33 | case "bottom-center":
34 | return {
35 | top: distance + height+ "px",
36 | left: width/2-Cwidth / 2 + "px",
37 | };
38 | case "bottom-left":
39 | return { top: distance + height+ "px", left: -Cwidth + "px"};
40 | default:
41 | return { top: distance + height+ "px", left: width + "px" };
42 | }
43 | }
44 |
45 | export function getAnimationOrigin(position?:string) {
46 | if(!position) return "origin-top-left";
47 | switch (position) {
48 | case "top-left":
49 | return 'origin-bottom-right'
50 | case "top-center":
51 | return "origin-bottom";
52 | case "top-right":
53 | return "origin-bottom-left";
54 | case "center-left":
55 | return "origin-center";
56 | case "center-right":
57 | return "origin-center";
58 | case "bottom-right":
59 | return "origin-top-left";
60 | case "bottom-center":
61 | return "origin-top";
62 | case "bottom-left":
63 | return "origin-top-right"
64 | default:
65 | return "origin-top-left"
66 | }
67 | }
68 |
69 | export function extractMessageFromOutput(output:{type:string, message:any}){
70 | console.log(output)
71 | const {type, message} = output;
72 | if(type === "text") return message;
73 | if (type ==="message") return message.text;
74 | if(type==="object") return message.text;
75 | return "Unknown message structure"
76 | }
--------------------------------------------------------------------------------
/src/controllers/index.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | export async function sendMessage(baseUrl: string, flowId: string, message: string,input_type:string,output_type:string,sessionId:React.MutableRefObject,output_component?:string, tweaks?: Object,api_key?:string,additional_headers?:{[key:string]:string}) {
4 | let data:any;
5 | data = {input_type,input_value:message,output_type}
6 | if (tweaks) {
7 | data["tweaks"]= tweaks
8 | }
9 | if(output_component){
10 | data["output_component"]=output_component;
11 | }
12 | let headers:{[key:string]:string}= {"Content-Type": "application/json"}
13 | if( api_key){
14 | headers["x-api-key"]=api_key;
15 | }
16 | if (additional_headers){
17 | headers = Object.assign(headers, additional_headers);
18 | // headers = {...headers, ...additional_headers};
19 | }
20 | if(sessionId.current && sessionId.current!=""){
21 | data.session_id=sessionId.current;
22 | }
23 | let response = axios.post(`${baseUrl}/api/v1/run/${flowId}`, data,{headers});
24 | return response;
25 | }
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import r2wc from '@r2wc/react-to-web-component';
2 | import ChatWidget from './chatWidget';
3 |
4 | customElements.define('langflow-chat', r2wc(ChatWidget, {
5 | shadow: "closed",
6 | props: {
7 | start_open: "boolean",
8 | api_key: "string",
9 | output_type: "string",
10 | input_type: "string",
11 | output_component: "string",
12 | chat_trigger_style: "json",
13 | host_url: "string",
14 | flow_id: "string",
15 | online: "boolean",
16 | online_message: "string",
17 | window_title: "string",
18 | tweaks:"json",
19 | bot_message_style:"json",
20 | user_message_style:"json",
21 | chat_window_style:"json",
22 | height:"number",
23 | width:"number",
24 | session_id:"string",
25 | chat_output_key:"string",
26 | error_message_style:"json",
27 | send_button_style:"json",
28 | send_icon_style:"json",
29 | placeholder:"string",
30 | placeholder_sending:"string",
31 | input_style:"json",
32 | input_container_style:"json",
33 | chat_position:"string",
34 | additional_headers:"json",
35 | },
36 | }));
--------------------------------------------------------------------------------
/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/src/types/chatWidget/index.ts:
--------------------------------------------------------------------------------
1 | export type ChatMessageType = {
2 | message: string;
3 | isSend: boolean;
4 | error?: boolean;
5 | bot_message_style?: React.CSSProperties;
6 | user_message_style?: React.CSSProperties;
7 | error_message_style?: React.CSSProperties;
8 | };
9 |
10 |
11 | export type ChatMessagePlaceholderType = {
12 | bot_message_style?: React.CSSProperties;
13 | };
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
3 | const glob = require("glob");
4 |
5 | module.exports = {
6 | entry: {
7 | "bundle.js": glob
8 | .sync("build/static/?(js|css)/main.*.?(js|css)")
9 | .map((f) => path.resolve(__dirname, f)),
10 | },
11 | output: {
12 | filename: "build/static/js/bundle.min.js",
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.css$/,
18 | use: ["style-loader", "css-loader"],
19 | },
20 | ],
21 | },
22 | plugins: [
23 | new UglifyJsPlugin(),
24 | ],
25 | };
26 |
--------------------------------------------------------------------------------