cevvo-widget 1.0.4 → 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.
package/README.md CHANGED
@@ -10,7 +10,7 @@ Add the following script to your HTML:
10
10
 
11
11
  ```html
12
12
  <script
13
- src="https://cdn.cevvo.ai/widget/cevvo-widget.js"
13
+ src="https://cdn.cevvo.ai/widget/widget.js"
14
14
  data-cevvo-project-id="your-project-id"
15
15
  data-cevvo-api-key="your-api-key">
16
16
  </script>
@@ -19,7 +19,7 @@ Add the following script to your HTML:
19
19
  ### Via JavaScript
20
20
 
21
21
  ```html
22
- <script src="https://cdn.cevvo.ai/widget/cevvo-widget.js"></script>
22
+ <script src="https://cdn.cevvo.ai/widget/widget.js"></script>
23
23
  <script>
24
24
  CevvoWidget.init({
25
25
  projectId: 'your-project-id',
@@ -106,7 +106,7 @@ When using script tag initialization, use these data attributes:
106
106
 
107
107
  ```html
108
108
  <script
109
- src="https://cdn.cevvo.ai/cevvo-widget.js"
109
+ src="https://cdn.cevvo.ai/widget/widget.js"
110
110
  data-cevvo-project-id="proj_abc123"
111
111
  data-cevvo-api-key="sk_live_xyz789"
112
112
  data-cevvo-project-color="#8b5cf6"
@@ -1,4 +1,4 @@
1
- (function(){"use strict";(function(){const p="https://prod-backend-api.cevvo.ai/api/v1",f={projectId:"",apiKey:"",apiUrl:p,projectName:"AI Assistant",projectColor:"#2563eb",buttonText:"Ask AI",buttonBgColor:"#2563eb",buttonTextColor:"#ffffff",buttonPosition:"bottom-right",buttonOffsetX:"20px",buttonOffsetY:"20px",modalTitle:"AI Assistant",modalSubtitle:"Ask me anything",modalPlaceholder:"Ask a question...",modalExampleQuestions:[],modalWidth:"420px",modalHeight:"600px",mode:"chat"},i={cevvoLogo:`<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 32 32">
1
+ (function(){"use strict";(function(){const p="https://prod-backend-api.cevvo.ai/api/v1",b={projectId:"",apiKey:"",apiUrl:p,projectName:"AI Assistant",projectColor:"#2563eb",buttonText:"Ask AI",buttonBgColor:"#2563eb",buttonTextColor:"#ffffff",buttonPosition:"bottom-right",buttonOffsetX:"20px",buttonOffsetY:"20px",modalTitle:"AI Assistant",modalSubtitle:"Ask me anything",modalPlaceholder:"Ask a question...",modalExampleQuestions:[],modalWidth:"420px",modalHeight:"600px",mode:"chat",theme:"light",welcomeMessage:"Hi! How can I help you?"},i={cevvoLogo:`<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 32 32">
2
2
  <ellipse cx="13" cy="16" rx="8" ry="10" fill="#21244A" transform="rotate(-15 13 16)"/>
3
3
  <ellipse cx="19" cy="16" rx="8" ry="10" fill="#F69F06" transform="rotate(15 19 16)" opacity="0.85"/>
4
4
  </svg>`,close:`<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 256" fill="currentColor">
@@ -25,7 +25,7 @@
25
25
  <path d="M248,132a56,56,0,0,0-32-50.61V72a48,48,0,0,0-88-26.49A48,48,0,0,0,40,72v9.39a56,56,0,0,0,0,101.2V192a48,48,0,0,0,88,26.49A48,48,0,0,0,216,192v-9.41A56.09,56.09,0,0,0,248,132ZM88,216a32,32,0,0,1-32-32v-8.81a55.45,55.45,0,0,0,8,.58,56.22,56.22,0,0,0,24-5.39v13.85a8,8,0,0,0,16,0v-24a8,8,0,0,0-8-8,40,40,0,1,1,0-80,8,8,0,0,0,8-8V40a32,32,0,0,1,64,0v24.23a8,8,0,0,0,8,8,40,40,0,1,1,0,80,8,8,0,0,0-8,8v24a8,8,0,0,0,16,0V170.39a56.22,56.22,0,0,0,24,5.39,55.45,55.45,0,0,0,8-.58V184a32,32,0,0,1-64,0V170.54a8,8,0,0,0-8-8,8,8,0,0,0-8,8V184A32,32,0,0,1,88,216Z"/>
26
26
  </svg>`,arrowUp:`<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 256 256" fill="currentColor">
27
27
  <path d="M205.66,117.66a8,8,0,0,1-11.32,0L136,59.31V216a8,8,0,0,1-16,0V59.31L61.66,117.66a8,8,0,0,1-11.32-11.32l72-72a8,8,0,0,1,11.32,0l72,72A8,8,0,0,1,205.66,117.66Z"/>
28
- </svg>`},b=`
28
+ </svg>`},f=`
29
29
  .cevvo-widget * {
30
30
  box-sizing: border-box;
31
31
  margin: 0;
@@ -683,7 +683,143 @@
683
683
  width: 16px;
684
684
  height: 16px;
685
685
  }
686
- `;class h{constructor(e={}){this.config={...f,...e},this.isOpen=!1,this.messages=[],this.threadId=null,this.isLoading=!1;const t=()=>{this.injectStyles(),this.createElements(),this.bindEvents()};document.body?t():document.addEventListener("DOMContentLoaded",t)}injectStyles(){if(document.getElementById("cevvo-widget-styles"))return;const e=document.createElement("style");e.id="cevvo-widget-styles",e.textContent=b,document.head.appendChild(e)}createElements(){this.container=document.createElement("div"),this.container.className="cevvo-widget",this.container.style.setProperty("--cevvo-accent",this.config.projectColor),this.button=document.createElement("button"),this.button.className=`cevvo-widget-btn ${this.config.buttonPosition}`,this.button.style.background=this.config.buttonBgColor,this.button.style.color=this.config.buttonTextColor,this.button.innerHTML=`${i.cevvoLogo}<span>${this.config.buttonText}</span>`,this.overlay=document.createElement("div"),this.overlay.className=`cevvo-modal-overlay ${this.config.mode==="modal"?"mode-modal":""}`,this.overlay.innerHTML=this.config.mode==="modal"?this.renderModalMode():this.renderModal(),this.container.appendChild(this.button),this.container.appendChild(this.overlay),document.body.appendChild(this.container),this.modal=this.overlay.querySelector(".cevvo-modal"),this.messagesContainer=this.overlay.querySelector(".cevvo-modal-body"),this.input=this.overlay.querySelector(".cevvo-input"),this.form=this.overlay.querySelector(".cevvo-input-form"),this.clearBtn=this.overlay.querySelector(".cevvo-clear-btn"),this.closeBtn=this.overlay.querySelector(".cevvo-close-btn")}renderModal(){const e=this.config.modalExampleQuestions.map(t=>`<button class="cevvo-example-btn">${this.escapeHtml(t)}</button>`).join("");return`
686
+
687
+ /* Dark Theme */
688
+ .cevvo-dark .cevvo-widget-btn {
689
+ background: #1c1c1e;
690
+ color: #f5f5f7;
691
+ border-color: #38383a;
692
+ }
693
+
694
+ .cevvo-dark .cevvo-widget-btn:hover {
695
+ border-color: #48484a;
696
+ box-shadow: 0 8px 20px rgba(0,0,0,0.3), 0 4px 8px rgba(0,0,0,0.2);
697
+ }
698
+
699
+ .cevvo-dark .cevvo-modal {
700
+ background: #1c1c1e;
701
+ border-color: #38383a;
702
+ box-shadow: 0 8px 30px rgba(0,0,0,0.4), 0 4px 12px rgba(0,0,0,0.3);
703
+ }
704
+
705
+ .cevvo-dark .cevvo-modal-header {
706
+ background: #1c1c1e;
707
+ border-bottom-color: #38383a;
708
+ }
709
+
710
+ .cevvo-dark .cevvo-header-text h2 { color: #f5f5f7; }
711
+ .cevvo-dark .cevvo-header-text p { color: #8e8e93; }
712
+
713
+ .cevvo-dark .cevvo-header-actions button { color: #8e8e93; }
714
+ .cevvo-dark .cevvo-header-actions button:hover {
715
+ background: #2c2c2e;
716
+ color: #f5f5f7;
717
+ }
718
+
719
+ .cevvo-dark .cevvo-modal-body { background: #1c1c1e; }
720
+
721
+ .cevvo-dark .cevvo-empty-icon {
722
+ background: #2c2c2e;
723
+ color: #f5f5f7;
724
+ }
725
+
726
+ .cevvo-dark .cevvo-empty-state h3 { color: #f5f5f7; }
727
+ .cevvo-dark .cevvo-empty-state p { color: #8e8e93; }
728
+
729
+ .cevvo-dark .cevvo-example-btn {
730
+ background: #2c2c2e;
731
+ border-color: #38383a;
732
+ color: #e5e5ea;
733
+ }
734
+
735
+ .cevvo-dark .cevvo-example-btn:hover {
736
+ background: #3a3a3c;
737
+ border-color: var(--cevvo-accent, #2563eb);
738
+ }
739
+
740
+ .cevvo-dark .cevvo-bubble.assistant {
741
+ background: #2c2c2e;
742
+ color: #f5f5f7;
743
+ }
744
+
745
+ .cevvo-dark .cevvo-bubble code {
746
+ background: rgba(255,255,255,0.1);
747
+ }
748
+
749
+ .cevvo-dark .cevvo-sources {
750
+ background: #2c2c2e;
751
+ border-color: #38383a;
752
+ }
753
+
754
+ .cevvo-dark .cevvo-sources-header { color: #8e8e93; }
755
+
756
+ .cevvo-dark .cevvo-source-link {
757
+ background: #1c1c1e;
758
+ border-color: #38383a;
759
+ color: #e5e5ea;
760
+ }
761
+
762
+ .cevvo-dark .cevvo-source-link:hover {
763
+ background: #2c2c2e;
764
+ }
765
+
766
+ .cevvo-dark .cevvo-source-num {
767
+ background: #38383a;
768
+ color: #8e8e93;
769
+ }
770
+
771
+ .cevvo-dark .cevvo-actions button { color: #636366; }
772
+ .cevvo-dark .cevvo-actions button:hover {
773
+ background: #2c2c2e;
774
+ color: #f5f5f7;
775
+ }
776
+
777
+ .cevvo-dark .cevvo-modal-footer {
778
+ background: #161618;
779
+ border-top-color: #38383a;
780
+ }
781
+
782
+ .cevvo-dark .cevvo-input {
783
+ background: #2c2c2e;
784
+ border-color: #38383a;
785
+ color: #f5f5f7;
786
+ }
787
+
788
+ .cevvo-dark .cevvo-input::placeholder { color: #636366; }
789
+
790
+ .cevvo-dark .cevvo-powered { color: #636366; }
791
+ .cevvo-dark .cevvo-powered a { color: #8e8e93; }
792
+
793
+ /* Dark mode - modal mode specifics */
794
+ .cevvo-dark .cevvo-modal-overlay.mode-modal .cevvo-modal-header {
795
+ background: linear-gradient(to bottom, #2c2c2e, #1c1c1e);
796
+ }
797
+
798
+ .cevvo-dark .cevvo-modal-overlay.mode-modal .cevvo-modal-description {
799
+ color: #a1a1a6;
800
+ }
801
+
802
+ .cevvo-dark .cevvo-modal-overlay.mode-modal .cevvo-modal-footer {
803
+ background: #1c1c1e;
804
+ }
805
+
806
+ .cevvo-dark .cevvo-modal-overlay.mode-modal .cevvo-input-wrapper {
807
+ background: #2c2c2e;
808
+ border-color: #38383a;
809
+ }
810
+
811
+ .cevvo-dark .cevvo-modal-overlay.mode-modal .cevvo-deep-thinking-btn {
812
+ background: #2c2c2e;
813
+ border-color: #38383a;
814
+ color: #e5e5ea;
815
+ }
816
+
817
+ .cevvo-dark .cevvo-modal-overlay.mode-modal .cevvo-deep-thinking-tooltip {
818
+ background: #2c2c2e;
819
+ border-color: #38383a;
820
+ color: #e5e5ea;
821
+ }
822
+ `;class h{constructor(e={}){this.config={...b,...e},this.isOpen=!1,this.messages=[],this.threadId=null,this.isLoading=!1;const o=()=>{this.injectStyles(),this.createElements(),this.bindEvents()};document.body?o():document.addEventListener("DOMContentLoaded",o)}injectStyles(){if(document.getElementById("cevvo-widget-styles"))return;const e=document.createElement("style");e.id="cevvo-widget-styles",e.textContent=f,document.head.appendChild(e)}resolveTheme(){return this.config.theme==="auto"?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":this.config.theme||"light"}createElements(){this.container=document.createElement("div");const e=this.resolveTheme()==="dark"?"cevvo-dark":"";this.container.className=`cevvo-widget ${e}`.trim(),this.container.style.setProperty("--cevvo-accent",this.config.projectColor),this.button=document.createElement("button"),this.button.className=`cevvo-widget-btn ${this.config.buttonPosition}`,this.button.style.background=this.config.buttonBgColor,this.button.style.color=this.config.buttonTextColor,this.button.innerHTML=`${i.cevvoLogo}<span>${this.config.buttonText}</span>`,this.overlay=document.createElement("div"),this.overlay.className=`cevvo-modal-overlay ${this.config.mode==="modal"?"mode-modal":""}`,this.overlay.innerHTML=this.config.mode==="modal"?this.renderModalMode():this.renderModal(),this.container.appendChild(this.button),this.container.appendChild(this.overlay),document.body.appendChild(this.container),this.modal=this.overlay.querySelector(".cevvo-modal"),this.messagesContainer=this.overlay.querySelector(".cevvo-modal-body"),this.input=this.overlay.querySelector(".cevvo-input"),this.form=this.overlay.querySelector(".cevvo-input-form"),this.clearBtn=this.overlay.querySelector(".cevvo-clear-btn"),this.closeBtn=this.overlay.querySelector(".cevvo-close-btn")}renderModal(){const e=this.config.modalExampleQuestions.map(o=>`<button class="cevvo-example-btn">${this.escapeHtml(o)}</button>`).join("");return`
687
823
  <div class="cevvo-modal">
688
824
  <div class="cevvo-modal-header">
689
825
  <div class="cevvo-header-info">
@@ -701,8 +837,7 @@
701
837
  <div class="cevvo-modal-body">
702
838
  <div class="cevvo-empty-state">
703
839
  <div class="cevvo-empty-icon">${i.sparkle}</div>
704
- <h3>How can I help you?</h3>
705
- <p>Ask me anything about our documentation and I'll help you find the answer.</p>
840
+ <h3>${this.escapeHtml(this.config.welcomeMessage)}</h3>
706
841
  ${e?`<div class="cevvo-example-questions">${e}</div>`:""}
707
842
  </div>
708
843
  </div>
@@ -760,12 +895,11 @@
760
895
  </div>
761
896
  </div>
762
897
  </div>
763
- `}bindEvents(){this.button.addEventListener("click",()=>this.toggle()),this.overlay.addEventListener("click",t=>{t.target===this.overlay&&this.close()}),this.closeBtn.addEventListener("click",()=>this.close()),this.clearBtn.addEventListener("click",()=>this.clearMessages()),this.form.addEventListener("submit",t=>{t.preventDefault(),this.sendMessage()}),this.overlay.querySelector(".cevvo-send-btn").addEventListener("click",t=>{t.preventDefault(),this.sendMessage()}),this.input.addEventListener("input",()=>{const t=this.overlay.querySelector(".cevvo-send-btn");t.disabled=!this.input.value.trim()||this.isLoading}),this.input.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),this.sendMessage())}),this.overlay.addEventListener("click",t=>{t.target.classList.contains("cevvo-example-btn")&&(this.input.value=t.target.textContent,this.sendMessage())}),this.messagesContainer.addEventListener("click",t=>{const o=t.target.closest("button");if(!o)return;const s=o.closest(".cevvo-actions");if(!s)return;const n=s.dataset.messageId,c=o.closest(".cevvo-message"),l=c==null?void 0:c.dataset.msgId,r=this.messages.find(d=>d.id===l);if(o.classList.contains("cevvo-copy-btn")&&(r!=null&&r.content)&&(navigator.clipboard.writeText(r.content),o.innerHTML=i.check,setTimeout(()=>{o.innerHTML=i.copy},2e3)),o.classList.contains("cevvo-thumbs-up")&&n){const d=(r==null?void 0:r.feedback)==="positive"?null:"positive";r&&(r.feedback=d),this.submitFeedback(parseInt(n),5),this.renderMessages()}if(o.classList.contains("cevvo-thumbs-down")&&n){const d=(r==null?void 0:r.feedback)==="negative"?null:"negative";r&&(r.feedback=d),this.submitFeedback(parseInt(n),1),this.renderMessages()}}),document.addEventListener("keydown",t=>{(t.metaKey||t.ctrlKey)&&t.key==="k"&&(t.preventDefault(),this.toggle()),t.key==="Escape"&&this.isOpen&&this.close()})}toggle(){this.isOpen?this.close():this.open()}open(){this.isOpen=!0,this.overlay.classList.add("is-open"),this.button.style.display="none",setTimeout(()=>this.input.focus(),100)}close(){this.isOpen=!1,this.overlay.classList.remove("is-open"),this.button.style.display="flex"}updateModalState(){this.config.mode==="modal"&&(this.messages.length>0?this.overlay.classList.add("has-messages"):this.overlay.classList.remove("has-messages"))}async sendMessage(){const e=this.input.value.trim();if(!e||this.isLoading)return;if(!this.config.projectId||!this.config.apiKey){this.addMessage({role:"assistant",content:'Widget not configured. Please set Project ID and API Key, then click "Apply Changes".'});return}this.input.value="",this.overlay.querySelector(".cevvo-send-btn").disabled=!0,this.addMessage({role:"user",content:e});const t=this.addMessage({role:"assistant",content:"",isLoading:!0});this.isLoading=!0;try{const o={"Content-Type":"application/json","X-API-Key":this.config.apiKey},s=await fetch(`${this.config.apiUrl}/widget/chat/stream`,{method:"POST",headers:o,body:JSON.stringify({message:e,thread_id:this.threadId,project_id:this.config.projectId})});if(!s.ok)throw new Error("Failed to send message");const n=s.body.getReader(),c=new TextDecoder;let l="",r=[],d=null;for(;;){const{done:x,value:y}=await n.read();if(x)break;const w=c.decode(y,{stream:!0}).split(`
764
- `);for(const u of w)if(u.startsWith("data: ")){const m=u.slice(6);if(m==="[DONE]")continue;try{const v=JSON.parse(m);v.thread_id&&(this.threadId=v.thread_id),v.token&&(l+=v.token,this.updateMessage(t,{content:l,isLoading:!1})),v.sources&&(r=v.sources),v.question_answer_id&&(d=v.question_answer_id)}catch{}}}this.updateMessage(t,{content:l||"I'm sorry, I couldn't generate a response.",sources:r,messageId:d,isLoading:!1})}catch(o){console.error("Chat error:",o),this.updateMessage(t,{content:"Sorry, something went wrong. Please try again.",isLoading:!1})}finally{this.isLoading=!1}}addMessage(e){const t=Date.now().toString();return this.messages.push({id:t,...e}),this.renderMessages(),this.clearBtn.style.display="flex",this.updateModalState(),t}updateMessage(e,t){const o=this.messages.find(s=>s.id===e);o&&(Object.assign(o,t),this.renderMessages())}clearMessages(){this.messages=[],this.threadId=null,this.clearBtn.style.display="none",this.renderMessages(),this.updateModalState()}renderMessages(){if(this.messages.length===0){this.messagesContainer.innerHTML=`
898
+ `}bindEvents(){this.button.addEventListener("click",()=>this.toggle()),this.overlay.addEventListener("click",o=>{o.target===this.overlay&&this.close()}),this.closeBtn.addEventListener("click",()=>this.close()),this.clearBtn.addEventListener("click",()=>this.clearMessages()),this.form.addEventListener("submit",o=>{o.preventDefault(),this.sendMessage()}),this.overlay.querySelector(".cevvo-send-btn").addEventListener("click",o=>{o.preventDefault(),this.sendMessage()}),this.input.addEventListener("input",()=>{const o=this.overlay.querySelector(".cevvo-send-btn");o.disabled=!this.input.value.trim()||this.isLoading}),this.input.addEventListener("keydown",o=>{o.key==="Enter"&&!o.shiftKey&&(o.preventDefault(),this.sendMessage())}),this.overlay.addEventListener("click",o=>{o.target.classList.contains("cevvo-example-btn")&&(this.input.value=o.target.textContent,this.sendMessage())}),this.messagesContainer.addEventListener("click",o=>{const a=o.target.closest("button");if(!a)return;const s=a.closest(".cevvo-actions");if(!s)return;const n=s.dataset.messageId,c=a.closest(".cevvo-message"),l=c==null?void 0:c.dataset.msgId,r=this.messages.find(d=>d.id===l);if(a.classList.contains("cevvo-copy-btn")&&(r!=null&&r.content)&&(navigator.clipboard.writeText(r.content),a.innerHTML=i.check,setTimeout(()=>{a.innerHTML=i.copy},2e3)),a.classList.contains("cevvo-thumbs-up")&&n){const d=(r==null?void 0:r.feedback)==="positive"?null:"positive";r&&(r.feedback=d),this.submitFeedback(parseInt(n),5),this.renderMessages()}if(a.classList.contains("cevvo-thumbs-down")&&n){const d=(r==null?void 0:r.feedback)==="negative"?null:"negative";r&&(r.feedback=d),this.submitFeedback(parseInt(n),1),this.renderMessages()}}),document.addEventListener("keydown",o=>{(o.metaKey||o.ctrlKey)&&o.key==="k"&&(o.preventDefault(),this.toggle()),o.key==="Escape"&&this.isOpen&&this.close()})}toggle(){this.isOpen?this.close():this.open()}open(){this.isOpen=!0,this.overlay.classList.add("is-open"),this.button.style.display="none",setTimeout(()=>this.input.focus(),100)}close(){this.isOpen=!1,this.overlay.classList.remove("is-open"),this.button.style.display="flex"}updateModalState(){this.config.mode==="modal"&&(this.messages.length>0?this.overlay.classList.add("has-messages"):this.overlay.classList.remove("has-messages"))}async sendMessage(){const e=this.input.value.trim();if(!e||this.isLoading)return;if(!this.config.projectId||!this.config.apiKey){this.addMessage({role:"assistant",content:'Widget not configured. Please set Project ID and API Key, then click "Apply Changes".'});return}this.input.value="",this.overlay.querySelector(".cevvo-send-btn").disabled=!0,this.addMessage({role:"user",content:e});const o=this.addMessage({role:"assistant",content:"",isLoading:!0});this.isLoading=!0;try{const a={"Content-Type":"application/json","X-API-Key":this.config.apiKey},s=await fetch(`${this.config.apiUrl}/widget/chat/stream`,{method:"POST",headers:a,body:JSON.stringify({message:e,thread_id:this.threadId,project_id:this.config.projectId})});if(!s.ok)throw new Error("Failed to send message");const n=s.body.getReader(),c=new TextDecoder;let l="",r=[],d=null;for(;;){const{done:x,value:y}=await n.read();if(x)break;const w=c.decode(y,{stream:!0}).split(`
899
+ `);for(const m of w)if(m.startsWith("data: ")){const u=m.slice(6);if(u==="[DONE]")continue;try{const v=JSON.parse(u);v.thread_id&&(this.threadId=v.thread_id),v.token&&(l+=v.token,this.updateMessage(o,{content:l,isLoading:!1})),v.sources&&(r=v.sources),v.question_answer_id&&(d=v.question_answer_id)}catch{}}}this.updateMessage(o,{content:l||"I'm sorry, I couldn't generate a response.",sources:r,messageId:d,isLoading:!1})}catch(a){console.error("Chat error:",a),this.updateMessage(o,{content:"Sorry, something went wrong. Please try again.",isLoading:!1})}finally{this.isLoading=!1}}addMessage(e){const o=Date.now().toString();return this.messages.push({id:o,...e}),this.renderMessages(),this.clearBtn.style.display="flex",this.updateModalState(),o}updateMessage(e,o){const a=this.messages.find(s=>s.id===e);a&&(Object.assign(a,o),this.renderMessages())}clearMessages(){this.messages=[],this.threadId=null,this.clearBtn.style.display="none",this.renderMessages(),this.updateModalState()}renderMessages(){if(this.messages.length===0){this.messagesContainer.innerHTML=`
765
900
  <div class="cevvo-empty-state">
766
901
  <div class="cevvo-empty-icon">${i.sparkle}</div>
767
- <h3>How can I help you?</h3>
768
- <p>Ask me anything about our documentation and I'll help you find the answer.</p>
902
+ <h3>${this.escapeHtml(this.config.welcomeMessage)}</h3>
769
903
  ${this.config.modalExampleQuestions.length?`
770
904
  <div class="cevvo-example-questions">
771
905
  ${this.config.modalExampleQuestions.map(e=>`<button class="cevvo-example-btn">${this.escapeHtml(e)}</button>`).join("")}
@@ -776,7 +910,7 @@
776
910
  <div class="cevvo-messages">
777
911
  ${this.messages.map(e=>this.renderMessage(e)).join("")}
778
912
  </div>
779
- `,this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight}renderMessage(e){var l;const t=e.role==="assistant"?i.cevvoLogo:i.user,o=e.isLoading?'<div class="cevvo-typing"><span></span><span></span><span></span></div>':this.formatContent(e.content),s=(l=e.sources)!=null&&l.length?`
913
+ `,this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight}renderMessage(e){var l;const o=e.role==="assistant"?i.cevvoLogo:i.user,a=e.isLoading?'<div class="cevvo-typing"><span></span><span></span><span></span></div>':this.formatContent(e.content),s=(l=e.sources)!=null&&l.length?`
780
914
  <div class="cevvo-sources">
781
915
  <div class="cevvo-sources-header">${i.link} Sources</div>
782
916
  ${e.sources.map((r,d)=>`
@@ -795,11 +929,11 @@
795
929
  </div>
796
930
  `:"";return`
797
931
  <div class="cevvo-message ${e.role}" data-msg-id="${e.id}">
798
- <div class="cevvo-avatar ${e.role}">${t}</div>
932
+ <div class="cevvo-avatar ${e.role}">${o}</div>
799
933
  <div class="cevvo-message-content">
800
- <div class="cevvo-bubble ${e.role}">${o}</div>
934
+ <div class="cevvo-bubble ${e.role}">${a}</div>
801
935
  ${s}
802
936
  ${c}
803
937
  </div>
804
938
  </div>
805
- `}async submitFeedback(e,t){if(e)try{await fetch(`${this.config.apiUrl}/widget/feedback`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({message_id:e,rating:t,project_id:this.config.projectId})})}catch(o){console.error("Feedback error:",o)}}formatContent(e){return this.escapeHtml(e).replace(/\n/g,"<br>").replace(/\*\*(.*?)\*\*/g,"<strong>$1</strong>").replace(/\*(.*?)\*/g,"<em>$1</em>").replace(/`(.*?)`/g,"<code>$1</code>")}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}}async function g(a,e,t){const o=t||p;try{const s=await fetch(`${o}/widget/config?project_id=${encodeURIComponent(a)}`,{method:"GET",headers:{"X-API-Key":e}});if(!s.ok)return console.warn("[CevvoWidget] Failed to fetch config:",s.status),null;const n=await s.json();return{mode:n.mode,buttonText:n.buttonText,buttonPosition:n.position,projectColor:n.primaryColor,buttonBgColor:n.primaryColor,modalTitle:n.modalTitle,modalSubtitle:n.modalSubtitle,modalExampleQuestions:n.exampleQuestions||[],welcomeMessage:n.welcomeMessage}}catch(s){return console.warn("[CevvoWidget] Error fetching config:",s.message),null}}window.CevvoWidget={init:a=>new h(a),initWithRemoteConfig:async(a,e,t)=>{const o=await g(a,e,t),s={projectId:a,apiKey:e,apiUrl:t,...o};return new h(s)},testCredentials:async(a,e,t)=>{const o=t||p;try{const s=await fetch(`${o}/widget/config?project_id=${encodeURIComponent(a)}`,{method:"GET",headers:{"X-API-Key":e}});return{success:s.ok,status:s.status,data:s.ok?await s.json():null}}catch(s){return{success:!1,status:0,error:s.message}}}},document.addEventListener("DOMContentLoaded",async()=>{const a=document.querySelector("script[data-cevvo-project-id]");if(a){const e=a.getAttribute("data-cevvo-project-id")||"",t=a.getAttribute("data-cevvo-api-key")||"",o=a.getAttribute("data-cevvo-api-url")||void 0;let s=null;e&&t&&(s=await g(e,t,o));const n={projectId:e,apiKey:t,apiUrl:o,...s,...a.getAttribute("data-cevvo-project-name")&&{projectName:a.getAttribute("data-cevvo-project-name")},...a.getAttribute("data-cevvo-project-color")&&{projectColor:a.getAttribute("data-cevvo-project-color")},...a.getAttribute("data-cevvo-button-text")&&{buttonText:a.getAttribute("data-cevvo-button-text")},...a.getAttribute("data-cevvo-button-bg-color")&&{buttonBgColor:a.getAttribute("data-cevvo-button-bg-color")},...a.getAttribute("data-cevvo-modal-title")&&{modalTitle:a.getAttribute("data-cevvo-modal-title")},...a.getAttribute("data-cevvo-modal-placeholder")&&{modalPlaceholder:a.getAttribute("data-cevvo-modal-placeholder")}},c=a.getAttribute("data-cevvo-example-questions");if(c)try{n.modalExampleQuestions=JSON.parse(c)}catch{}new h(n)}})})()})();
939
+ `}async submitFeedback(e,o){if(e)try{await fetch(`${this.config.apiUrl}/widget/feedback`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({message_id:e,rating:o,project_id:this.config.projectId})})}catch(a){console.error("Feedback error:",a)}}formatContent(e){return this.escapeHtml(e).replace(/\n/g,"<br>").replace(/\*\*(.*?)\*\*/g,"<strong>$1</strong>").replace(/\*(.*?)\*/g,"<em>$1</em>").replace(/`(.*?)`/g,"<code>$1</code>")}escapeHtml(e){const o=document.createElement("div");return o.textContent=e,o.innerHTML}}async function g(t,e,o){const a=o||p;try{const s=await fetch(`${a}/widget/config?project_id=${encodeURIComponent(t)}`,{method:"GET",headers:{"X-API-Key":e}});if(!s.ok)return console.warn("[CevvoWidget] Failed to fetch config:",s.status),null;const n=await s.json();return{mode:n.mode,buttonText:n.buttonText,buttonPosition:n.position,projectColor:n.primaryColor,buttonBgColor:n.primaryColor,theme:n.theme||"light",modalTitle:n.modalTitle,modalSubtitle:n.modalSubtitle,modalExampleQuestions:n.exampleQuestions||[],welcomeMessage:n.welcomeMessage}}catch(s){return console.warn("[CevvoWidget] Error fetching config:",s.message),null}}window.CevvoWidget={init:async(t={})=>{if(t.projectId&&t.apiKey){const e=await g(t.projectId,t.apiKey,t.apiUrl);e&&(t={...t,...e})}return new h(t)},initWithRemoteConfig:async(t,e,o)=>{const a=await g(t,e,o),s={projectId:t,apiKey:e,apiUrl:o,...a};return new h(s)},testCredentials:async(t,e,o)=>{const a=o||p;try{const s=await fetch(`${a}/widget/config?project_id=${encodeURIComponent(t)}`,{method:"GET",headers:{"X-API-Key":e}});return{success:s.ok,status:s.status,data:s.ok?await s.json():null}}catch(s){return{success:!1,status:0,error:s.message}}}},document.addEventListener("DOMContentLoaded",async()=>{const t=document.querySelector("script[data-cevvo-project-id]");if(t){const e=t.getAttribute("data-cevvo-project-id")||"",o=t.getAttribute("data-cevvo-api-key")||"",a=t.getAttribute("data-cevvo-api-url")||void 0;let s=null;e&&o&&(s=await g(e,o,a));const n={projectId:e,apiKey:o,apiUrl:a,...s,...t.getAttribute("data-cevvo-project-name")&&{projectName:t.getAttribute("data-cevvo-project-name")},...t.getAttribute("data-cevvo-project-color")&&{projectColor:t.getAttribute("data-cevvo-project-color")},...t.getAttribute("data-cevvo-button-text")&&{buttonText:t.getAttribute("data-cevvo-button-text")},...t.getAttribute("data-cevvo-button-bg-color")&&{buttonBgColor:t.getAttribute("data-cevvo-button-bg-color")},...t.getAttribute("data-cevvo-modal-title")&&{modalTitle:t.getAttribute("data-cevvo-modal-title")},...t.getAttribute("data-cevvo-modal-placeholder")&&{modalPlaceholder:t.getAttribute("data-cevvo-modal-placeholder")}},c=t.getAttribute("data-cevvo-example-questions");if(c)try{n.modalExampleQuestions=JSON.parse(c)}catch{}new h(n)}})})()})();
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "cevvo-widget",
3
- "version": "1.0.4",
3
+ "version": "1.0.7",
4
4
  "description": "Cevvo Widget - AI-powered chat for your docs",
5
5
  "type": "module",
6
- "main": "dist/cevvo-widget.js",
7
- "module": "dist/cevvo-widget.js",
8
- "unpkg": "dist/cevvo-widget.js",
9
- "jsdelivr": "dist/cevvo-widget.js",
6
+ "main": "dist/widget.js",
7
+ "module": "dist/widget.js",
8
+ "unpkg": "dist/widget.js",
9
+ "jsdelivr": "dist/widget.js",
10
10
  "files": [
11
11
  "dist"
12
12
  ],