@a.izzuddin/ai-chat 0.2.4 → 0.2.7

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.mjs CHANGED
@@ -2,6 +2,7 @@ import { css, LitElement, html } from 'lit';
2
2
  import { state, customElement } from 'lit/decorators.js';
3
3
  import { repeat } from 'lit/directives/repeat.js';
4
4
  import { classMap } from 'lit/directives/class-map.js';
5
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
5
6
 
6
7
  var __defProp = Object.defineProperty;
7
8
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -13,7 +14,7 @@ var __decorateClass = (decorators, target, key, kind) => {
13
14
  if (kind && result) __defProp(target, key, result);
14
15
  return result;
15
16
  };
16
- var VERSION = "0.2.4";
17
+ var VERSION = "0.2.7";
17
18
  var AIChat = class extends LitElement {
18
19
  constructor() {
19
20
  super();
@@ -25,6 +26,14 @@ var AIChat = class extends LitElement {
25
26
  this.initialMessages = [];
26
27
  this.botAvatarUrl = "";
27
28
  this.backgroundImageUrl = "";
29
+ this.widgetWidth = "380px";
30
+ this.widgetHeight = "600px";
31
+ this.primaryColor = "#3681D3";
32
+ this.primaryColorHover = "#3457C7";
33
+ this.userMessageBg = "#D6E4FF";
34
+ this.botMessageBg = "#F5F5F5";
35
+ this.welcomeMessage = "How can I help you today?";
36
+ this.welcomeSubtitle = "";
28
37
  this.messages = [];
29
38
  this.input = "";
30
39
  this.isLoading = false;
@@ -33,6 +42,67 @@ var AIChat = class extends LitElement {
33
42
  toggleWidget() {
34
43
  this.isOpen = !this.isOpen;
35
44
  }
45
+ lightenColor(hex, percent = 15) {
46
+ hex = hex.replace("#", "");
47
+ const r = parseInt(hex.substring(0, 2), 16);
48
+ const g = parseInt(hex.substring(2, 4), 16);
49
+ const b = parseInt(hex.substring(4, 6), 16);
50
+ const newR = Math.min(255, Math.round(r + (255 - r) * (percent / 100)));
51
+ const newG = Math.min(255, Math.round(g + (255 - g) * (percent / 100)));
52
+ const newB = Math.min(255, Math.round(b + (255 - b) * (percent / 100)));
53
+ return `#${newR.toString(16).padStart(2, "0")}${newG.toString(16).padStart(2, "0")}${newB.toString(16).padStart(2, "0")}`;
54
+ }
55
+ formatMessageContent(content) {
56
+ const escapeHtml = (text) => {
57
+ const div = document.createElement("div");
58
+ div.textContent = text;
59
+ return div.innerHTML;
60
+ };
61
+ let processedContent = content.replace(/(\d+\.\s+[^0-9]+?)(?=\s+\d+\.\s+|\s*$)/g, "$1\n");
62
+ processedContent = processedContent.replace(/(-\s+[^-]+?)(?=\s+-\s+|\s*$)/g, "$1\n");
63
+ const lines = processedContent.split("\n");
64
+ let formattedContent = "";
65
+ let inList = false;
66
+ let listType = null;
67
+ for (let i = 0; i < lines.length; i++) {
68
+ const line = lines[i];
69
+ const trimmedLine = line.trim();
70
+ const unorderedMatch = trimmedLine.match(/^[-*•]\s+(.+)$/);
71
+ const orderedMatch = trimmedLine.match(/^\d+\.\s+(.+)$/);
72
+ if (unorderedMatch) {
73
+ if (!inList || listType !== "ul") {
74
+ if (inList) formattedContent += listType === "ol" ? "</ol>" : "</ul>";
75
+ formattedContent += "<ul>";
76
+ inList = true;
77
+ listType = "ul";
78
+ }
79
+ formattedContent += `<li>${escapeHtml(unorderedMatch[1])}</li>`;
80
+ } else if (orderedMatch) {
81
+ if (!inList || listType !== "ol") {
82
+ if (inList) formattedContent += listType === "ol" ? "</ol>" : "</ul>";
83
+ formattedContent += "<ol>";
84
+ inList = true;
85
+ listType = "ol";
86
+ }
87
+ formattedContent += `<li>${escapeHtml(orderedMatch[1])}</li>`;
88
+ } else {
89
+ if (inList) {
90
+ formattedContent += listType === "ol" ? "</ol>" : "</ul>";
91
+ inList = false;
92
+ listType = null;
93
+ }
94
+ if (trimmedLine === "") {
95
+ formattedContent += "<br>";
96
+ } else {
97
+ formattedContent += escapeHtml(line) + "\n";
98
+ }
99
+ }
100
+ }
101
+ if (inList) {
102
+ formattedContent += listType === "ol" ? "</ol>" : "</ul>";
103
+ }
104
+ return formattedContent;
105
+ }
36
106
  connectedCallback() {
37
107
  super.connectedCallback();
38
108
  if (this.initialMessages && this.initialMessages.length > 0) {
@@ -93,6 +163,7 @@ var AIChat = class extends LitElement {
93
163
  console.log("\u{1F50D} Raw API response:", data);
94
164
  let responseText = "No response from agent";
95
165
  let faqs = void 0;
166
+ let suggestedQuestions = void 0;
96
167
  if (data && typeof data === "object" && data.response && typeof data.response === "string") {
97
168
  console.log("\u{1F4DD} data.response type:", typeof data.response);
98
169
  console.log("\u{1F4DD} data.response preview:", data.response.substring(0, 100));
@@ -104,12 +175,15 @@ var AIChat = class extends LitElement {
104
175
  console.log("\u2705 Parsed inner data with JSON.parse");
105
176
  if (innerData && innerData.response && typeof innerData.response === "string") {
106
177
  responseText = innerData.response;
107
- faqs = innerData.faqs_used || void 0;
178
+ faqs = innerData.faq_used || innerData.faqs_used || void 0;
179
+ suggestedQuestions = innerData.suggested_follow_ups || innerData.suggested_questions || void 0;
108
180
  console.log("\u2705 Extracted text length:", responseText.length);
109
181
  console.log("\u2705 Extracted FAQs count:", faqs?.length || 0);
182
+ console.log("\u2705 Extracted suggested questions count:", suggestedQuestions?.length || 0);
110
183
  } else {
111
184
  responseText = data.response;
112
- faqs = data.faqs_used || void 0;
185
+ faqs = data.faq_used || data.faqs_used || void 0;
186
+ suggestedQuestions = data.suggested_follow_ups || data.suggested_questions || void 0;
113
187
  }
114
188
  } catch (parseError) {
115
189
  console.warn("\u26A0\uFE0F JSON.parse failed, using regex extraction...", parseError);
@@ -122,7 +196,7 @@ var AIChat = class extends LitElement {
122
196
  console.error("\u274C Could not extract response");
123
197
  responseText = "Error: Could not parse response";
124
198
  }
125
- const faqsPattern = /"faqs_used"\s*:\s*(\[[^\]]*\])/s;
199
+ const faqsPattern = /"(?:faq_used|faqs_used)"\s*:\s*(\[[^\]]*\])/s;
126
200
  const faqsMatch = data.response.match(faqsPattern);
127
201
  if (faqsMatch) {
128
202
  try {
@@ -130,7 +204,7 @@ var AIChat = class extends LitElement {
130
204
  console.log("\u2705 Extracted FAQs, count:", faqs?.length || 0);
131
205
  } catch {
132
206
  console.log("\u26A0\uFE0F Could not parse FAQs, trying multiline...");
133
- const faqsMultiPattern = /"faqs_used"\s*:\s*(\[[\s\S]*?\n\s*\])/;
207
+ const faqsMultiPattern = /"(?:faq_used|faqs_used)"\s*:\s*(\[[\s\S]*?\n\s*\])/;
134
208
  const faqsMultiMatch = data.response.match(faqsMultiPattern);
135
209
  if (faqsMultiMatch) {
136
210
  try {
@@ -142,11 +216,32 @@ var AIChat = class extends LitElement {
142
216
  }
143
217
  }
144
218
  }
219
+ const suggestedPattern = /"(?:suggested_follow_ups|suggested_questions)"\s*:\s*(\[[^\]]*\])/s;
220
+ const suggestedMatch = data.response.match(suggestedPattern);
221
+ if (suggestedMatch) {
222
+ try {
223
+ suggestedQuestions = JSON.parse(suggestedMatch[1]);
224
+ console.log("\u2705 Extracted suggested questions, count:", suggestedQuestions?.length || 0);
225
+ } catch {
226
+ console.log("\u26A0\uFE0F Could not parse suggested questions, trying multiline...");
227
+ const suggestedMultiPattern = /"(?:suggested_follow_ups|suggested_questions)"\s*:\s*(\[[\s\S]*?\n\s*\])/;
228
+ const suggestedMultiMatch = data.response.match(suggestedMultiPattern);
229
+ if (suggestedMultiMatch) {
230
+ try {
231
+ suggestedQuestions = JSON.parse(suggestedMultiMatch[1]);
232
+ console.log("\u2705 Extracted multi-line suggested questions, count:", suggestedQuestions?.length || 0);
233
+ } catch {
234
+ suggestedQuestions = void 0;
235
+ }
236
+ }
237
+ }
238
+ }
145
239
  }
146
240
  } else {
147
241
  console.log("\u{1F4C4} Direct text response (not JSON)");
148
242
  responseText = data.response;
149
- faqs = data.faqs_used || void 0;
243
+ faqs = data.faq_used || data.faqs_used || void 0;
244
+ suggestedQuestions = data.suggested_follow_ups || data.suggested_questions || void 0;
150
245
  }
151
246
  } else if (typeof data === "string") {
152
247
  console.log("\u{1F4C4} Response is a plain string");
@@ -154,15 +249,19 @@ var AIChat = class extends LitElement {
154
249
  } else if (data && typeof data === "object") {
155
250
  console.warn("\u26A0\uFE0F Unexpected format, using fallback");
156
251
  responseText = data.message || data.answer || "Error: Unexpected response format";
252
+ faqs = data.faq_used || data.faqs_used || void 0;
253
+ suggestedQuestions = data.suggested_follow_ups || data.suggested_questions || void 0;
157
254
  }
158
255
  console.log("\u{1F3AF} Final responseText length:", responseText.length);
159
256
  console.log("\u{1F3AF} Final responseText preview:", responseText.substring(0, 100));
160
257
  console.log("\u{1F3AF} Final FAQs:", faqs);
258
+ console.log("\u{1F3AF} Final suggested questions:", suggestedQuestions);
161
259
  const assistantMessage = {
162
260
  id: (Date.now() + 1).toString(),
163
261
  role: "assistant",
164
262
  content: responseText,
165
- faqs
263
+ faqs,
264
+ suggestedQuestions
166
265
  };
167
266
  this.messages = [...this.messages, assistantMessage];
168
267
  this.dispatchEvent(new CustomEvent("response-received", {
@@ -190,20 +289,34 @@ Please check your API endpoint configuration.`
190
289
  }
191
290
  }
192
291
  renderChatUI() {
292
+ const primaryColorLight = this.lightenColor(this.primaryColor, 15);
193
293
  return html`
194
294
  <!-- Header -->
195
- <div class="header">
295
+ <div class="header" style="--primary-color: ${this.primaryColor}; --primary-color-light: ${primaryColorLight}; --primary-color-hover: ${this.primaryColorHover};">
196
296
  <div class="header-content">
297
+ <div class="header-avatar">
298
+ ${this.botAvatarUrl ? html`<img src="${this.botAvatarUrl}" alt="Bot" class="header-avatar-image" />` : html`<svg viewBox="0 0 24 24" fill="none" stroke="${this.primaryColor}" stroke-width="2" style="width: 1.5rem; height: 1.5rem;">
299
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
300
+ </svg>`}
301
+ </div>
197
302
  <h1 class="title">${this.chatTitle}</h1>
198
303
  </div>
199
304
  </div>
200
305
 
201
306
  <!-- Messages Area -->
202
- <div class="messages-area" style="${this.backgroundImageUrl ? `--background-image-url: url('${this.backgroundImageUrl}')` : ""}">
307
+ <div class="messages-area" style="--user-message-bg: ${this.userMessageBg}; --bot-message-bg: ${this.botMessageBg}; --primary-color: ${this.primaryColor}; --primary-color-light: ${primaryColorLight}; --primary-color-hover: ${this.primaryColorHover}; ${this.backgroundImageUrl ? `--background-image-url: url('${this.backgroundImageUrl}');` : ""}">
203
308
  <div class="messages-container">
204
309
  ${this.messages.length === 0 ? html`
205
310
  <div class="empty-state">
206
- <p>How can I help you today?</p>
311
+ <div class="empty-state-avatar">
312
+ ${this.botAvatarUrl ? html`<img src="${this.botAvatarUrl}" alt="Bot" class="empty-state-avatar-image" />` : html`<svg viewBox="0 0 24 24" fill="none" stroke="#9ca3af" stroke-width="2">
313
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
314
+ </svg>`}
315
+ </div>
316
+ <div class="empty-state-content">
317
+ <p class="empty-state-message">${this.welcomeMessage}</p>
318
+ ${this.welcomeSubtitle ? html`<p class="empty-state-subtitle">${this.welcomeSubtitle}</p>` : ""}
319
+ </div>
207
320
  </div>
208
321
  ` : ""}
209
322
 
@@ -217,19 +330,31 @@ Please check your API endpoint configuration.`
217
330
  ${msg.role === "user" ? "U" : this.botAvatarUrl ? html`<img src="${this.botAvatarUrl}" alt="AI" class="avatar-image" />` : "AI"}
218
331
  </div>
219
332
  <div class="message-content">
220
- <p class="message-text">${msg.content}</p>
333
+ <div class="message-text">${unsafeHTML(this.formatMessageContent(msg.content))}</div>
221
334
  ${msg.role === "assistant" && msg.faqs && msg.faqs.length > 0 ? html`
222
335
  <div class="faq-section">
223
336
  <p class="faq-title">Related FAQs:</p>
224
337
  <ul class="faq-list">
225
338
  ${msg.faqs.map((faq) => html`
226
- <li class="faq-item" @click=${() => this.handleFAQClick(faq.question)}>
339
+ <li class="faq-item-static">
227
340
  ${faq.question}
228
341
  </li>
229
342
  `)}
230
343
  </ul>
231
344
  </div>
232
345
  ` : ""}
346
+ ${msg.role === "assistant" && msg.suggestedQuestions && msg.suggestedQuestions.length > 0 ? html`
347
+ <div class="faq-section">
348
+ <p class="faq-title">Suggested Questions:</p>
349
+ <ul class="faq-list">
350
+ ${msg.suggestedQuestions.map((question) => html`
351
+ <li class="faq-item" @click=${() => this.handleFAQClick(question)}>
352
+ ${question}
353
+ </li>
354
+ `)}
355
+ </ul>
356
+ </div>
357
+ ` : ""}
233
358
  </div>
234
359
  </div>
235
360
  `)}
@@ -250,7 +375,7 @@ Please check your API endpoint configuration.`
250
375
  </div>
251
376
 
252
377
  <!-- Input Area -->
253
- <div class="input-area">
378
+ <div class="input-area" style="--primary-color: ${this.primaryColor}; --primary-color-hover: ${this.primaryColorHover};">
254
379
  <form class="input-form" @submit=${this.handleSubmit}>
255
380
  <input
256
381
  type="text"
@@ -283,17 +408,22 @@ Please check your API endpoint configuration.`
283
408
  `;
284
409
  }
285
410
  render() {
411
+ const primaryColorLight = this.lightenColor(this.primaryColor, 15);
286
412
  if (this.mode === "widget") {
287
413
  return html`
288
414
  <div class="widget-container">
289
415
  <!-- Chat Window -->
290
- <div class=${classMap({ "widget-window": true, "open": this.isOpen })}>
416
+ <div
417
+ class=${classMap({ "widget-window": true, "open": this.isOpen })}
418
+ style="--widget-width: ${this.widgetWidth}; --widget-height: ${this.widgetHeight};"
419
+ >
291
420
  ${this.renderChatUI()}
292
421
  </div>
293
422
 
294
423
  <!-- Toggle Button -->
295
424
  <button
296
425
  class="widget-button"
426
+ style="--primary-color: ${this.primaryColor}; --primary-color-light: ${primaryColorLight};"
297
427
  @click=${this.toggleWidget}
298
428
  aria-label=${this.isOpen ? "Close chat" : "Open chat"}
299
429
  >
@@ -325,7 +455,7 @@ AIChat.styles = css`
325
455
  display: flex;
326
456
  flex-direction: column;
327
457
  height: 100vh;
328
- background: #fafafa;
458
+ background: #ffffff;
329
459
  }
330
460
 
331
461
  :host([mode="fullscreen"][theme="dark"]) {
@@ -349,19 +479,19 @@ AIChat.styles = css`
349
479
  width: 60px;
350
480
  height: 60px;
351
481
  border-radius: 50%;
352
- background: #2563eb;
482
+ background: #3681D3;
353
483
  border: none;
354
484
  cursor: pointer;
355
485
  display: flex;
356
486
  align-items: center;
357
487
  justify-content: center;
358
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
488
+ box-shadow: 0 4px 16px rgba(65, 105, 225, 0.3);
359
489
  transition: transform 0.2s, box-shadow 0.2s;
360
490
  }
361
491
 
362
492
  .widget-button:hover {
363
493
  transform: scale(1.05);
364
- box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
494
+ box-shadow: 0 6px 20px rgba(65, 105, 225, 0.4);
365
495
  }
366
496
 
367
497
  .widget-button svg {
@@ -374,11 +504,11 @@ AIChat.styles = css`
374
504
  position: absolute;
375
505
  bottom: 80px;
376
506
  right: 0;
377
- width: 380px;
378
- height: 600px;
507
+ width: var(--widget-width, 380px);
508
+ height: var(--widget-height, 600px);
379
509
  background: #fff;
380
- border-radius: 12px;
381
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
510
+ border-radius: 16px;
511
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.05);
382
512
  display: flex;
383
513
  flex-direction: column;
384
514
  overflow: hidden;
@@ -399,35 +529,251 @@ AIChat.styles = css`
399
529
  color: #fafafa;
400
530
  }
401
531
 
402
- @media (max-width: 480px) {
532
+ /* Tablet breakpoint */
533
+ @media (max-width: 1024px) and (min-width: 769px) {
534
+ .widget-window {
535
+ width: var(--widget-width, 400px);
536
+ height: var(--widget-height, 650px);
537
+ }
538
+ }
539
+
540
+ /* Small tablet breakpoint */
541
+ @media (max-width: 768px) and (min-width: 481px) {
542
+ .widget-window {
543
+ width: var(--widget-width, 360px);
544
+ height: var(--widget-height, 550px);
545
+ }
546
+ }
547
+
548
+ /* Mobile portrait */
549
+ @media (max-width: 480px) and (orientation: portrait) {
403
550
  .widget-window {
404
551
  width: calc(100vw - 40px);
552
+ height: 70vh;
553
+ bottom: 80px;
554
+ right: 0;
555
+ }
556
+
557
+ .widget-button {
558
+ width: 56px;
559
+ height: 56px;
560
+ }
561
+
562
+ .widget-button svg {
563
+ width: 24px;
564
+ height: 24px;
565
+ }
566
+ }
567
+
568
+ /* Mobile landscape */
569
+ @media (max-width: 900px) and (orientation: landscape) {
570
+ .widget-window {
571
+ width: var(--widget-width, 500px);
405
572
  height: calc(100vh - 100px);
406
573
  bottom: 80px;
407
574
  right: 0;
408
575
  }
576
+
577
+ .widget-button {
578
+ width: 56px;
579
+ height: 56px;
580
+ }
581
+
582
+ .widget-button svg {
583
+ width: 24px;
584
+ height: 24px;
585
+ }
586
+ }
587
+
588
+ /* Mobile responsive styles for all modes */
589
+ @media (max-width: 768px) {
590
+ .header {
591
+ padding: 0.875rem 1rem;
592
+ }
593
+
594
+ .header-avatar {
595
+ width: 2.25rem;
596
+ height: 2.25rem;
597
+ }
598
+
599
+ .title {
600
+ font-size: 1.125rem;
601
+ }
602
+
603
+ .messages-area {
604
+ padding: 1rem 0.75rem;
605
+ }
606
+
607
+ .message {
608
+ gap: 0.75rem;
609
+ }
610
+
611
+ .avatar {
612
+ width: 2rem;
613
+ height: 2rem;
614
+ font-size: 0.75rem;
615
+ }
616
+
617
+ .message-content {
618
+ max-width: 100%;
619
+ padding: 0.625rem 0.875rem;
620
+ font-size: 0.9375rem;
621
+ }
622
+
623
+ .empty-state {
624
+ margin-top: 3rem;
625
+ }
626
+
627
+ .empty-state p {
628
+ font-size: 1.25rem;
629
+ padding: 0 1rem;
630
+ }
631
+
632
+ .faq-section {
633
+ margin-top: 0.75rem;
634
+ padding-top: 0.75rem;
635
+ }
636
+
637
+ .faq-item {
638
+ font-size: 0.8125rem;
639
+ padding: 0;
640
+ }
641
+
642
+ .input-area {
643
+ padding: 0.75rem;
644
+ }
645
+
646
+ .input-form {
647
+ gap: 0.5rem;
648
+ }
649
+
650
+ .input-field {
651
+ height: 2.75rem;
652
+ padding: 0 0.875rem;
653
+ font-size: 0.9375rem;
654
+ }
655
+
656
+ .send-button {
657
+ width: 2.75rem;
658
+ height: 2.75rem;
659
+ flex-shrink: 0;
660
+ }
661
+
662
+ .send-icon {
663
+ width: 1.125rem;
664
+ height: 1.125rem;
665
+ }
666
+ }
667
+
668
+ /* Extra small screens */
669
+ @media (max-width: 480px) {
670
+ .header {
671
+ padding: 0.75rem 0.875rem;
672
+ }
673
+
674
+ .header-avatar {
675
+ width: 2rem;
676
+ height: 2rem;
677
+ }
678
+
679
+ .title {
680
+ font-size: 1rem;
681
+ }
682
+
683
+ .messages-area {
684
+ padding: 0.75rem 0.5rem;
685
+ }
686
+
687
+ .message {
688
+ gap: 0.5rem;
689
+ }
690
+
691
+ .avatar {
692
+ width: 1.75rem;
693
+ height: 1.75rem;
694
+ font-size: 0.7rem;
695
+ }
696
+
697
+ .message-content {
698
+ padding: 0.5rem 0.75rem;
699
+ font-size: 0.875rem;
700
+ border-radius: 0.75rem;
701
+ }
702
+
703
+ .empty-state {
704
+ margin-top: 2rem;
705
+ }
706
+
707
+ .empty-state p {
708
+ font-size: 1.125rem;
709
+ }
710
+
711
+ .input-area {
712
+ padding: 0.625rem;
713
+ }
714
+
715
+ .input-field {
716
+ height: 2.5rem;
717
+ padding: 0 0.75rem;
718
+ font-size: 0.875rem;
719
+ }
720
+
721
+ .send-button {
722
+ width: 2.5rem;
723
+ height: 2.5rem;
724
+ }
725
+
726
+ .version-tag {
727
+ font-size: 0.7rem;
728
+ padding: 0.375rem;
729
+ }
409
730
  }
410
731
 
411
732
  .header {
412
- border-bottom: 1px solid #e4e4e7;
413
- background: #fff;
414
- padding: 1rem;
733
+ background:#3681D3;
734
+ padding: 1rem 1.25rem;
735
+ display: flex;
736
+ align-items: center;
737
+ gap: 0.75rem;
738
+ box-shadow: 0 2px 8px rgba(65, 105, 225, 0.2);
415
739
  }
416
740
 
417
741
  :host([theme="dark"]) .header {
418
- border-bottom-color: #27272a;
419
- background: #18181b;
742
+ background: #3681D3
420
743
  }
421
744
 
422
745
  .header-content {
423
746
  max-width: 56rem;
424
747
  margin: 0 auto;
748
+ display: flex;
749
+ align-items: center;
750
+ gap: 0.75rem;
751
+ width: 100%;
752
+ }
753
+
754
+ .header-avatar {
755
+ width: 2.5rem;
756
+ height: 2.5rem;
757
+ border-radius: 50%;
758
+ background: #fff;
759
+ display: flex;
760
+ align-items: center;
761
+ justify-content: center;
762
+ overflow: hidden;
763
+ flex-shrink: 0;
764
+ }
765
+
766
+ .header-avatar-image {
767
+ width: 100%;
768
+ height: 100%;
769
+ object-fit: cover;
425
770
  }
426
771
 
427
772
  .title {
428
773
  font-size: 1.25rem;
429
774
  font-weight: 600;
430
775
  margin: 0;
776
+ color: #fff;
431
777
  }
432
778
 
433
779
  .messages-area {
@@ -435,6 +781,11 @@ AIChat.styles = css`
435
781
  overflow-y: auto;
436
782
  padding: 1.5rem 1rem;
437
783
  position: relative;
784
+ background: #ffffff;
785
+ }
786
+
787
+ :host([theme="dark"]) .messages-area {
788
+ background: #000;
438
789
  }
439
790
 
440
791
  .messages-area::before {
@@ -448,7 +799,7 @@ AIChat.styles = css`
448
799
  background-size: 200px auto 60%;
449
800
  background-position: center center;
450
801
  background-repeat: no-repeat;
451
- opacity: 0.5;
802
+ opacity: 0.03;
452
803
  pointer-events: none;
453
804
  z-index: 0;
454
805
  }
@@ -465,18 +816,74 @@ AIChat.styles = css`
465
816
 
466
817
  .empty-state {
467
818
  text-align: center;
468
- color: #71717a;
469
819
  margin-top: 5rem;
820
+ display: flex;
821
+ flex-direction: column;
822
+ align-items: center;
823
+ gap: 1.5rem;
470
824
  }
471
825
 
472
826
  :host([theme="dark"]) .empty-state {
473
827
  color: #a1a1aa;
474
828
  }
475
829
 
476
- .empty-state p {
477
- font-size: 1.5rem;
478
- font-weight: 500;
830
+ .empty-state-avatar {
831
+ width: 5rem;
832
+ height: 5rem;
833
+ border-radius: 50%;
834
+ background: #E5E7EB;
835
+ display: flex;
836
+ align-items: center;
837
+ justify-content: center;
838
+ overflow: hidden;
839
+ }
840
+
841
+ :host([theme="dark"]) .empty-state-avatar {
842
+ background: #3f3f46;
843
+ }
844
+
845
+ .empty-state-avatar-image {
846
+ width: 100%;
847
+ height: 100%;
848
+ object-fit: cover;
849
+ }
850
+
851
+ .empty-state-avatar svg {
852
+ width: 3rem;
853
+ height: 3rem;
854
+ color: #9ca3af;
855
+ }
856
+
857
+ :host([theme="dark"]) .empty-state-avatar svg {
858
+ color: #6b7280;
859
+ }
860
+
861
+ .empty-state-content {
862
+ display: flex;
863
+ flex-direction: column;
864
+ gap: 0.5rem;
865
+ }
866
+
867
+ .empty-state-message {
868
+ font-size: 1.25rem;
869
+ font-weight: 600;
870
+ margin: 0;
871
+ color: #374151;
872
+ }
873
+
874
+ :host([theme="dark"]) .empty-state-message {
875
+ color: #f3f4f6;
876
+ }
877
+
878
+ .empty-state-subtitle {
879
+ font-size: 0.9375rem;
479
880
  margin: 0;
881
+ color: #6b7280;
882
+ max-width: 24rem;
883
+ }
884
+
885
+ :host([theme="dark"]) .empty-state-subtitle {
886
+ color: #9ca3af;
480
887
  }
481
888
 
482
889
  .message {
@@ -492,18 +899,20 @@ AIChat.styles = css`
492
899
  width: 2.5rem;
493
900
  height: 2.5rem;
494
901
  border-radius: 9999px;
495
- background: #e4e4e7;
902
+ background: #E5E7EB;
496
903
  display: flex;
497
904
  align-items: center;
498
905
  justify-content: center;
499
906
  flex-shrink: 0;
500
- font-weight: 500;
907
+ font-weight: 600;
501
908
  font-size: 0.875rem;
502
909
  overflow: hidden;
910
+ color: #6B7280;
503
911
  }
504
912
 
505
913
  :host([theme="dark"]) .avatar {
506
914
  background: #3f3f46;
915
+ color: #9ca3af;
507
916
  }
508
917
 
509
918
  .avatar-image {
@@ -514,36 +923,63 @@ AIChat.styles = css`
514
923
 
515
924
  .message-content {
516
925
  max-width: 36rem;
517
- padding: 0.75rem 1rem;
518
- border-radius: 1rem;
926
+ padding: 0.875rem 1.125rem;
927
+ border-radius: 1.25rem;
928
+ line-height: 1.6;
519
929
  }
520
930
 
521
931
  .message.user .message-content {
522
- background: #2563eb;
523
- color: #fff;
932
+ background: var(--user-message-bg, #D6E4FF);
933
+ color: #1a1a1a;
934
+ border-radius: 1.25rem 1.25rem 0.25rem 1.25rem;
524
935
  }
525
936
 
526
937
  .message.assistant .message-content {
527
- background: #fff;
528
- border: 1px solid #e4e4e7;
529
- color: #09090b;
938
+ background: var(--bot-message-bg, #F5F5F5);
939
+ color: #1a1a1a;
940
+ border-radius: 1.25rem 1.25rem 1.25rem 0.25rem;
941
+ }
942
+
943
+ :host([theme="dark"]) .message.user .message-content {
944
+ background: #3D5A99;
945
+ color: #fff;
530
946
  }
531
947
 
532
948
  :host([theme="dark"]) .message.assistant .message-content {
533
949
  background: #27272a;
534
- border-color: #3f3f46;
535
950
  color: #fafafa;
536
951
  }
537
952
 
538
953
  .message-text {
539
954
  white-space: pre-wrap;
540
955
  margin: 0;
956
+ word-wrap: break-word;
957
+ }
958
+
959
+ .message-text ul,
960
+ .message-text ol {
961
+ margin: 0.5rem 0;
962
+ padding-left: 1.5rem;
963
+ white-space: normal;
964
+ }
965
+
966
+ .message-text li {
967
+ margin: 0.25rem 0;
968
+ white-space: normal;
969
+ }
970
+
971
+ .message-text ul {
972
+ list-style-type: disc;
973
+ }
974
+
975
+ .message-text ol {
976
+ list-style-type: decimal;
541
977
  }
542
978
 
543
979
  .faq-section {
544
- margin-top: 1rem;
545
- padding-top: 1rem;
546
- border-top: 1px solid #e4e4e7;
980
+ margin-top: 0.75rem;
981
+ padding-top: 0.75rem;
982
+ border-top: 1px solid #d1d5db;
547
983
  }
548
984
 
549
985
  :host([theme="dark"]) .faq-section {
@@ -552,13 +988,13 @@ AIChat.styles = css`
552
988
 
553
989
  .faq-title {
554
990
  font-size: 0.875rem;
555
- font-weight: 500;
556
- color: #3f3f46;
557
- margin: 0 0 0.5rem 0;
991
+ font-weight: 600;
992
+ color: var(--primary-color, #3681D3);
993
+ margin: 0 0 0.375rem 0;
558
994
  }
559
995
 
560
996
  :host([theme="dark"]) .faq-title {
561
- color: #d4d4d8;
997
+ color: var(--primary-color-light, #5B7FE8);
562
998
  }
563
999
 
564
1000
  .faq-list {
@@ -567,30 +1003,46 @@ AIChat.styles = css`
567
1003
  margin: 0;
568
1004
  display: flex;
569
1005
  flex-direction: column;
570
- gap: 0.5rem;
1006
+ gap: 0.375rem;
571
1007
  }
572
1008
 
573
1009
  .faq-item {
574
1010
  font-size: 0.875rem;
575
- color: #52525b;
576
- padding: 0.5rem;
577
- border-radius: 0.375rem;
1011
+ color: var(--primary-color, #3681D3);
1012
+ padding: 0;
1013
+ border-radius: 0.5rem;
578
1014
  cursor: pointer;
579
1015
  transition: background-color 0.2s, color 0.2s;
1016
+ border: 1px solid transparent;
580
1017
  }
581
1018
 
582
1019
  .faq-item:hover {
583
- background-color: #f4f4f5;
584
- color: #18181b;
1020
+ background-color: #EEF2FF;
1021
+ color: var(--primary-color-hover, #3457C7);
1022
+ border-color: #C7D2FE;
585
1023
  }
586
1024
 
587
1025
  :host([theme="dark"]) .faq-item {
588
- color: #a1a1aa;
1026
+ color: var(--primary-color-light, #5B7FE8);
589
1027
  }
590
1028
 
591
1029
  :host([theme="dark"]) .faq-item:hover {
592
- background-color: #27272a;
593
- color: #fafafa;
1030
+ background-color: #1e293b;
1031
+ color: #93C5FD;
1032
+ border-color: #3f3f46;
1033
+ }
1034
+
1035
+ .faq-item-static {
1036
+ font-size: 0.875rem;
1037
+ color: #6B7280;
1038
+ padding: 0;
1039
+ border-radius: 0.5rem;
1040
+ cursor: default;
1041
+ border: 1px solid transparent;
1042
+ }
1043
+
1044
+ :host([theme="dark"]) .faq-item-static {
1045
+ color: #9CA3AF;
594
1046
  }
595
1047
 
596
1048
  .loading {
@@ -613,14 +1065,14 @@ AIChat.styles = css`
613
1065
  }
614
1066
 
615
1067
  .input-area {
616
- border-top: 1px solid #e4e4e7;
1068
+ border-top: 1px solid #e5e7eb;
617
1069
  background: #fff;
618
- padding: 1rem;
1070
+ padding: 1rem 1.25rem;
619
1071
  }
620
1072
 
621
1073
  :host([theme="dark"]) .input-area {
622
1074
  border-top-color: #27272a;
623
- background: #000;
1075
+ background: #18181b;
624
1076
  }
625
1077
 
626
1078
  .input-form {
@@ -628,18 +1080,24 @@ AIChat.styles = css`
628
1080
  margin: 0 auto;
629
1081
  display: flex;
630
1082
  gap: 0.75rem;
1083
+ align-items: center;
631
1084
  }
632
1085
 
633
1086
  .input-field {
634
1087
  flex: 1;
635
1088
  height: 3rem;
636
1089
  padding: 0 1rem;
637
- border: 1px solid #e4e4e7;
638
- border-radius: 0.5rem;
639
- font-size: 1rem;
1090
+ border: 1px solid #d1d5db;
1091
+ border-radius: 1.5rem;
1092
+ font-size: 0.9375rem;
640
1093
  font-family: inherit;
641
1094
  background: #fff;
642
- color: #09090b;
1095
+ color: #374151;
1096
+ transition: border-color 0.2s, box-shadow 0.2s;
1097
+ }
1098
+
1099
+ .input-field::placeholder {
1100
+ color: #9ca3af;
643
1101
  }
644
1102
 
645
1103
  :host([theme="dark"]) .input-field {
@@ -649,8 +1107,9 @@ AIChat.styles = css`
649
1107
  }
650
1108
 
651
1109
  .input-field:focus {
652
- outline: 2px solid #2563eb;
653
- outline-offset: 2px;
1110
+ outline: none;
1111
+ border-color: var(--primary-color, #3681D3);
1112
+ box-shadow: 0 0 0 3px rgba(65, 105, 225, 0.1);
654
1113
  }
655
1114
 
656
1115
  .input-field:disabled {
@@ -663,17 +1122,23 @@ AIChat.styles = css`
663
1122
  height: 3rem;
664
1123
  border-radius: 9999px;
665
1124
  border: none;
666
- background: #2563eb;
1125
+ background: var(--primary-color, #3681D3);
667
1126
  color: #fff;
668
1127
  cursor: pointer;
669
1128
  display: flex;
670
1129
  align-items: center;
671
1130
  justify-content: center;
672
- transition: background 0.2s;
1131
+ transition: background 0.2s, transform 0.1s;
1132
+ flex-shrink: 0;
673
1133
  }
674
1134
 
675
1135
  .send-button:hover:not(:disabled) {
676
- background: #1d4ed8;
1136
+ background: var(--primary-color-hover, #3457C7);
1137
+ transform: scale(1.05);
1138
+ }
1139
+
1140
+ .send-button:active:not(:disabled) {
1141
+ transform: scale(0.95);
677
1142
  }
678
1143
 
679
1144
  .send-button:disabled {
@@ -690,12 +1155,12 @@ AIChat.styles = css`
690
1155
  text-align: center;
691
1156
  padding: 0.5rem;
692
1157
  font-size: 0.75rem;
693
- color: #71717a;
694
- border-top: 1px solid #e4e4e7;
1158
+ color: #9ca3af;
1159
+ border-top: 1px solid #e5e7eb;
695
1160
  }
696
1161
 
697
1162
  :host([theme="dark"]) .version-tag {
698
- color: #a1a1aa;
1163
+ color: #6b7280;
699
1164
  border-top-color: #27272a;
700
1165
  }
701
1166
  `;
@@ -707,7 +1172,15 @@ AIChat.properties = {
707
1172
  mode: { type: String, reflect: true },
708
1173
  initialMessages: { type: Array },
709
1174
  botAvatarUrl: { type: String, attribute: "bot-avatar-url" },
710
- backgroundImageUrl: { type: String, attribute: "background-image-url" }
1175
+ backgroundImageUrl: { type: String, attribute: "background-image-url" },
1176
+ widgetWidth: { type: String, attribute: "widget-width" },
1177
+ widgetHeight: { type: String, attribute: "widget-height" },
1178
+ primaryColor: { type: String, attribute: "primary-color" },
1179
+ primaryColorHover: { type: String, attribute: "primary-color-hover" },
1180
+ userMessageBg: { type: String, attribute: "user-message-bg" },
1181
+ botMessageBg: { type: String, attribute: "bot-message-bg" },
1182
+ welcomeMessage: { type: String, attribute: "welcome-message" },
1183
+ welcomeSubtitle: { type: String, attribute: "welcome-subtitle" }
711
1184
  };
712
1185
  __decorateClass([
713
1186
  state()