aptolix_chatbot 1.0.5 → 1.0.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.
@@ -370,6 +370,9 @@
370
370
  min-height: 180px;
371
371
  width: 100vw;
372
372
  max-width: 100vw;
373
+ left: 0;
374
+ right: 0;
375
+ margin: 0;
373
376
  }
374
377
  #aptolix-chat-header {
375
378
  font-size: 1rem;
@@ -381,6 +384,12 @@
381
384
  #aptolix-chat-input {
382
385
  padding: 6px 2px;
383
386
  }
387
+ #aptolix-chat-expand {
388
+ display: none !important;
389
+ }
390
+ #aptolix-chat-window.section-mode #aptolix-chat-close {
391
+ display: none !important;
392
+ }
384
393
  }
385
394
 
386
395
  .aptolix-retry-btn {
@@ -397,5 +406,33 @@
397
406
  background: #d8b4fe;
398
407
  }
399
408
 
409
+ .aptolix-hint-bubble {
410
+ position: fixed;
411
+ right: 40px;
412
+ bottom: 110px;
413
+ z-index: 9999;
414
+ background: #fff;
415
+ border-radius: 8px;
416
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
417
+ padding: 16px 40px 16px 16px;
418
+ min-width: 180px;
419
+ max-width: 320px;
420
+ font-size: 1em;
421
+ color: #333;
422
+ pointer-events: auto; /* Ensure it's clickable */
423
+ }
424
+
425
+ .aptolix-hint-bubble::after {
426
+ content: "";
427
+ position: absolute;
428
+ bottom: -12px; /* Position arrow below the bubble */
429
+ right: 28px; /* Align arrow with bubble */
430
+ width: 0;
431
+ height: 0;
432
+ border-left: 10px solid transparent;
433
+ border-right: 10px solid transparent;
434
+ border-top: 12px solid #fff; /* Same as bubble background */
435
+ }
436
+
400
437
 
401
438
 
package/src/index.js CHANGED
@@ -2,19 +2,92 @@
2
2
  import './chatbotstyle.css';
3
3
 
4
4
  const AptolixChatbot = {
5
- init: ({ apiHost, chatflowid, title, subtitle, greeting, mode = "bubble", target }) => {
5
+ init: ({ apiHost, chatflowid, title, subtitle, greeting, mode = "bubble", target, hintText = "I am here to help", hintDelay = 5000 // default 5 seconds
6
+ }) => {
6
7
 
7
8
  const modeClass = mode === "section" ? "section-mode" : "bubble-mode";
8
-
9
- let bubble;
9
+ const chatWindow = document.createElement('div');
10
+
11
+ let bubble, hintBubbleTimeout, hintBubble;
10
12
  if (mode === "bubble") {
11
13
  bubble = document.createElement('div');
12
14
  bubble.id = "aptolix-chat-bubble";
13
15
  bubble.innerText = "💬";
14
16
  document.body.appendChild(bubble);
17
+
18
+ // Remove any existing hint bubble before creating a new one
19
+ const existingHintBubble = document.getElementById("aptolix-chat-hint-bubble");
20
+ if (existingHintBubble) {
21
+ existingHintBubble.remove();
22
+ }
23
+
24
+ // Create hint bubble but keep it hidden initially
25
+ hintBubble = document.createElement('div');
26
+ hintBubble.id = "aptolix-chat-hint-bubble";
27
+ hintBubble.className = "aptolix-hint-bubble";
28
+ hintBubble.style.display = "none";
29
+ hintBubble.style.position = "fixed";
30
+ hintBubble.style.right = "40px";
31
+ hintBubble.style.bottom = "110px";
32
+ hintBubble.style.zIndex = "9999"; // <-- Ensure it's on top
33
+
34
+ // Create the hint text span
35
+ const hintTextSpan = document.createElement('span');
36
+ hintTextSpan.textContent = hintText;
37
+
38
+ // Create the close button
39
+ const hintCloseBtn = document.createElement('button');
40
+ hintCloseBtn.id = "aptolix-hint-close";
41
+ hintCloseBtn.title = "Close";
42
+ hintCloseBtn.setAttribute("aria-label", "Close");
43
+ hintCloseBtn.innerHTML = "&#10005;";
44
+ hintCloseBtn.style.background = "none";
45
+ hintCloseBtn.style.border = "none";
46
+ hintCloseBtn.style.color = "#9333ea";
47
+ hintCloseBtn.style.fontSize = "1.3em";
48
+ hintCloseBtn.style.position = "absolute";
49
+ hintCloseBtn.style.top = "8px";
50
+ hintCloseBtn.style.right = "12px";
51
+ hintCloseBtn.style.cursor = "pointer";
52
+ hintCloseBtn.style.padding = "0";
53
+
54
+ // Add event listener directly
55
+ hintCloseBtn.addEventListener("click", () => {
56
+ hintBubble.style.display = "none";
57
+ sessionStorage.setItem("aptolixHintClosed", "true");
58
+ clearTimeout(hintBubbleTimeout);
59
+ });
60
+
61
+ // Append children
62
+ hintBubble.appendChild(hintTextSpan);
63
+ hintBubble.appendChild(hintCloseBtn);
64
+
65
+ document.body.appendChild(hintBubble);
66
+
67
+ // Show hint bubble after delay, unless closed in session
68
+ hintBubbleTimeout = setTimeout(() => {
69
+ if (
70
+ chatWindow.style.display === "none" &&
71
+ !sessionStorage.getItem("aptolixHintClosed")
72
+ ) {
73
+ hintBubble.style.display = "block";
74
+ }
75
+ }, hintDelay);
76
+
77
+ // Hide hint bubble when main bubble is clicked
78
+ bubble.addEventListener("click", () => {
79
+ hintBubble.style.display = "none";
80
+ clearTimeout(hintBubbleTimeout);
81
+ });
82
+
83
+ // Hide hint bubble if chat is opened by other means
84
+ chatWindow.addEventListener("transitionstart", () => {
85
+ hintBubble.style.display = "none";
86
+ clearTimeout(hintBubbleTimeout);
87
+ });
15
88
  }
16
89
 
17
- const chatWindow = document.createElement('div');
90
+
18
91
  chatWindow.id = "aptolix-chat-window";
19
92
  chatWindow.classList.add(modeClass);
20
93
  chatWindow.style.display = mode === "section" ? "flex" : "none";
@@ -31,7 +104,7 @@ const AptolixChatbot = {
31
104
  <div id="aptolix-chat-header">
32
105
  <div class="aptolix-header-flex">
33
106
  <div class="aptolix-header-title">
34
- <strong>${title || "Assistant"}</strong>
107
+ <strong>${title || "AI Chatbot"}</strong>
35
108
  ${subtitle ? `<div class="aptolix-header-subtitle">${subtitle}</div>` : ""}
36
109
  </div>
37
110
  <div class="aptolix-header-actions">
@@ -39,6 +112,7 @@ const AptolixChatbot = {
39
112
  <button id="aptolix-chat-expand" title="Expand/Collapse" aria-label="Expand/Collapse">
40
113
  <span id="aptolix-chat-expand-icon">⤢</span>
41
114
  </button>
115
+ <button id="aptolix-chat-download" title="Download chat" aria-label="Download chat">⤓</button>
42
116
  <button id="aptolix-chat-close" title="Close chat" aria-label="Close chat">×</button>
43
117
  </div>
44
118
  </div>
@@ -60,6 +134,7 @@ const AptolixChatbot = {
60
134
  const input = chatWindow.querySelector("#aptolix-chat-inputbox");
61
135
  const sendButton = chatWindow.querySelector("button");
62
136
  const messagesDiv = chatWindow.querySelector("#aptolix-chat-messages");
137
+ const downloadBtn = chatWindow.querySelector("#aptolix-chat-download");
63
138
 
64
139
  if (mode === "bubble") {
65
140
  closeBtn.addEventListener("click", () => {
@@ -233,6 +308,31 @@ const AptolixChatbot = {
233
308
  this.style.overflowY = 'hidden';
234
309
  }
235
310
  });
311
+
312
+ downloadBtn.addEventListener("click", () => {
313
+ // Collect all messages
314
+ const messages = Array.from(messagesDiv.querySelectorAll('.message')).map(msg => {
315
+ const sender = msg.classList.contains('user') ? "You" : "Bot";
316
+ // Remove HTML tags for plain text
317
+ const text = msg.innerText || msg.textContent;
318
+ return `${sender}: ${text}`;
319
+ }).join('\n\n');
320
+
321
+ // Create a blob and trigger download
322
+ const blob = new Blob([messages], { type: "text/plain" });
323
+ const url = URL.createObjectURL(blob);
324
+ const a = document.createElement("a");
325
+ a.href = url;
326
+ a.download = "chat_history.txt";
327
+ document.body.appendChild(a);
328
+ a.click();
329
+ setTimeout(() => {
330
+ document.body.removeChild(a);
331
+ URL.revokeObjectURL(url);
332
+ }, 100);
333
+ });
334
+
335
+
236
336
  },
237
337
  initFull: function(options) {
238
338
  let el = document.querySelector('aptolix-chatbot');
@@ -270,7 +370,7 @@ class AptolixChatbotElement extends HTMLElement {
270
370
  const chatflowid = this.getAttribute('chatflowid');
271
371
  if (!apiHost || !chatflowid) return;
272
372
 
273
- const title = this.getAttribute('title') || "Aptolix Assistant";
373
+ const title = this.getAttribute('title') || "Aptolix AI Chatbot";
274
374
  const greeting = this.getAttribute('greeting');
275
375
  const subtitle = this.getAttribute('subtitle');
276
376
  const targetAttr = this.getAttribute('target');