cevvo-widget 1.0.7 → 1.0.9

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.
Files changed (2) hide show
  1. package/dist/widget.js +53 -34
  2. package/package.json +1 -1
package/dist/widget.js CHANGED
@@ -1,4 +1,4 @@
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">
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?",disclaimer:"AI responses may be inaccurate or incomplete. Please verify important information from original sources."},n={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">
@@ -465,8 +465,12 @@
465
465
  border: 1px solid #e4e4e7;
466
466
  border-radius: 10px;
467
467
  font-size: 14px;
468
+ line-height: 1.5;
468
469
  outline: none;
469
470
  background: #fff;
471
+ box-sizing: border-box;
472
+ width: 100%;
473
+ min-width: 0;
470
474
  transition: border-color 0.15s ease;
471
475
  }
472
476
 
@@ -501,6 +505,15 @@
501
505
  opacity: 0.85;
502
506
  }
503
507
 
508
+ .cevvo-disclaimer {
509
+ text-align: center;
510
+ font-size: 9px;
511
+ line-height: 1.4;
512
+ color: #a1a1aa;
513
+ margin: 0 0 8px;
514
+ padding: 0 12px;
515
+ }
516
+
504
517
  .cevvo-powered {
505
518
  text-align: center;
506
519
  font-size: 11px;
@@ -579,18 +592,22 @@
579
592
  .cevvo-modal-overlay.mode-modal .cevvo-input-wrapper {
580
593
  display: flex;
581
594
  flex-direction: column;
582
- gap: 12px;
583
- padding: 16px;
595
+ gap: 10px;
596
+ padding: 14px 16px;
584
597
  border: 1px solid #e4e4e7;
585
598
  border-radius: 14px;
586
599
  background: #fff;
600
+ box-sizing: border-box;
587
601
  }
588
602
 
589
603
  .cevvo-modal-overlay.mode-modal .cevvo-input {
590
604
  border: none;
591
- padding: 0;
605
+ padding: 4px 0;
592
606
  font-size: 15px;
607
+ line-height: 1.5;
593
608
  background: transparent;
609
+ width: 100%;
610
+ box-sizing: border-box;
594
611
  }
595
612
 
596
613
  .cevvo-modal-overlay.mode-modal .cevvo-input:focus {
@@ -819,48 +836,49 @@
819
836
  border-color: #38383a;
820
837
  color: #e5e5ea;
821
838
  }
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`
839
+ `;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=`${n.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`
823
840
  <div class="cevvo-modal">
824
841
  <div class="cevvo-modal-header">
825
842
  <div class="cevvo-header-info">
826
- <div class="cevvo-header-logo">${i.cevvoLogo}</div>
843
+ <div class="cevvo-header-logo">${n.cevvoLogo}</div>
827
844
  <div class="cevvo-header-text">
828
845
  <h2>${this.escapeHtml(this.config.modalTitle)}</h2>
829
846
  <p>${this.escapeHtml(this.config.modalSubtitle)}</p>
830
847
  </div>
831
848
  </div>
832
849
  <div class="cevvo-header-actions">
833
- <button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${i.trash}</button>
834
- <button class="cevvo-close-btn" title="Close">${i.close}</button>
850
+ <button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${n.trash}</button>
851
+ <button class="cevvo-close-btn" title="Close">${n.close}</button>
835
852
  </div>
836
853
  </div>
837
854
  <div class="cevvo-modal-body">
838
855
  <div class="cevvo-empty-state">
839
- <div class="cevvo-empty-icon">${i.sparkle}</div>
856
+ <div class="cevvo-empty-icon">${n.sparkle}</div>
840
857
  <h3>${this.escapeHtml(this.config.welcomeMessage)}</h3>
841
858
  ${e?`<div class="cevvo-example-questions">${e}</div>`:""}
842
859
  </div>
843
860
  </div>
844
861
  <div class="cevvo-modal-footer">
862
+ ${this.config.disclaimer?`<p class="cevvo-disclaimer">${this.escapeHtml(this.config.disclaimer)}</p>`:""}
845
863
  <form class="cevvo-input-form">
846
864
  <input type="text" class="cevvo-input" placeholder="${this.escapeHtml(this.config.modalPlaceholder)}" />
847
- <button type="submit" class="cevvo-send-btn" disabled>${i.send}</button>
865
+ <button type="submit" class="cevvo-send-btn" disabled>${n.send}</button>
848
866
  </form>
849
867
  <p class="cevvo-powered">Powered by <a href="https://cevvo.ai" target="_blank" rel="noopener">Cevvo</a></p>
850
868
  </div>
851
869
  </div>
852
- `}renderModalMode(){const e=this.config.modalDescription||'This is a <a href="#">Cevvo-powered</a> AI assistant with access to all documentation, FAQs, API specs and tutorials. This is an example of the <a href="#">website widget</a> integration.';return`
870
+ `}renderModalMode(){const e=this.config.modalDescription||this.config.modalSubtitle||"Ask me anything about the documentation.";return`
853
871
  <div class="cevvo-modal">
854
872
  <div class="cevvo-modal-header">
855
873
  <div class="cevvo-header-info">
856
- <div class="cevvo-header-logo">${i.cevvoLogo}</div>
874
+ <div class="cevvo-header-logo">${n.cevvoLogo}</div>
857
875
  <div class="cevvo-header-text">
858
876
  <h2>${this.escapeHtml(this.config.modalTitle)}</h2>
859
877
  </div>
860
878
  </div>
861
879
  <div class="cevvo-header-actions">
862
- <button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${i.trash}</button>
863
- <button class="cevvo-close-btn" title="Close">${i.close}</button>
880
+ <button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${n.trash}</button>
881
+ <button class="cevvo-close-btn" title="Close">${n.close}</button>
864
882
  </div>
865
883
  </div>
866
884
  <div class="cevvo-modal-description" style="padding: 0 24px;">
@@ -869,6 +887,7 @@
869
887
  <div class="cevvo-modal-body">
870
888
  </div>
871
889
  <div class="cevvo-modal-footer">
890
+ ${this.config.disclaimer?`<p class="cevvo-disclaimer">${this.escapeHtml(this.config.disclaimer)}</p>`:""}
872
891
  <div class="cevvo-input-wrapper">
873
892
  <form class="cevvo-input-form" style="gap: 0;">
874
893
  <input type="text" class="cevvo-input" placeholder="${this.escapeHtml(this.config.modalPlaceholder)}" />
@@ -879,26 +898,26 @@
879
898
  For harder questions. Searches longer across all sources. Takes up to ~1 minute.
880
899
  </div>
881
900
  <button type="button" class="cevvo-deep-thinking-btn">
882
- ${i.brain}
901
+ ${n.brain}
883
902
  <span>Deep thinking</span>
884
903
  </button>
885
904
  </div>
886
- <button type="submit" class="cevvo-send-btn" disabled>${i.arrowUp}</button>
905
+ <button type="submit" class="cevvo-send-btn" disabled>${n.arrowUp}</button>
887
906
  </div>
888
907
  </div>
889
908
  <div class="cevvo-powered">
890
909
  <div class="cevvo-powered-left">
891
910
  <span>Powered by</span>
892
- ${i.cevvoLogo}
911
+ ${n.cevvoLogo}
893
912
  <a href="https://cevvo.ai" target="_blank" rel="noopener">cevvo.ai</a>
894
913
  </div>
895
914
  </div>
896
915
  </div>
897
916
  </div>
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=`
917
+ `}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 i=s.dataset.messageId,r=a.closest(".cevvo-message"),d=r==null?void 0:r.dataset.msgId,c=this.messages.find(l=>l.id===d);if(a.classList.contains("cevvo-copy-btn")&&(c!=null&&c.content)&&(navigator.clipboard.writeText(c.content),a.innerHTML=n.check,setTimeout(()=>{a.innerHTML=n.copy},2e3)),a.classList.contains("cevvo-thumbs-up")&&i){const l=(c==null?void 0:c.feedback)==="positive"?null:"positive";c&&(c.feedback=l),this.submitFeedback(parseInt(i),5),this.renderMessages()}if(a.classList.contains("cevvo-thumbs-down")&&i){const l=(c==null?void 0:c.feedback)==="negative"?null:"negative";c&&(c.feedback=l),this.submitFeedback(parseInt(i),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 i=s.body.getReader(),r=new TextDecoder;let d="",c=[],l=null;for(;;){const{done:x,value:y}=await i.read();if(x)break;const w=r.decode(y,{stream:!0}).split(`
918
+ `);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&&(d+=v.token,this.updateMessage(o,{content:d,isLoading:!1})),v.sources&&(c=v.sources),v.question_answer_id&&(l=v.question_answer_id)}catch{}}}this.updateMessage(o,{content:d||"I'm sorry, I couldn't generate a response.",sources:c,messageId:l,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=`
900
919
  <div class="cevvo-empty-state">
901
- <div class="cevvo-empty-icon">${i.sparkle}</div>
920
+ <div class="cevvo-empty-icon">${n.sparkle}</div>
902
921
  <h3>${this.escapeHtml(this.config.welcomeMessage)}</h3>
903
922
  ${this.config.modalExampleQuestions.length?`
904
923
  <div class="cevvo-example-questions">
@@ -910,22 +929,22 @@
910
929
  <div class="cevvo-messages">
911
930
  ${this.messages.map(e=>this.renderMessage(e)).join("")}
912
931
  </div>
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?`
932
+ `,this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight}renderMessage(e){var d;const o=e.role==="assistant"?n.cevvoLogo:n.user,a=e.isLoading?'<div class="cevvo-typing"><span></span><span></span><span></span></div>':this.formatContent(e.content),s=(d=e.sources)!=null&&d.length?`
914
933
  <div class="cevvo-sources">
915
- <div class="cevvo-sources-header">${i.link} Sources</div>
916
- ${e.sources.map((r,d)=>`
917
- <a href="${this.escapeHtml(r.source_url||r.url||"#")}" target="_blank" rel="noopener" class="cevvo-source-link">
918
- <span class="cevvo-source-num">${d+1}</span>
919
- <span class="cevvo-source-title">${this.escapeHtml(r.title||"Source")}</span>
920
- ${i.link}
934
+ <div class="cevvo-sources-header">${n.link} Sources</div>
935
+ ${e.sources.map((c,l)=>`
936
+ <a href="${this.escapeHtml(c.source_url||c.url||"#")}" target="_blank" rel="noopener" class="cevvo-source-link">
937
+ <span class="cevvo-source-num">${l+1}</span>
938
+ <span class="cevvo-source-title">${this.escapeHtml(c.title||"Source")}</span>
939
+ ${n.link}
921
940
  </a>
922
941
  `).join("")}
923
942
  </div>
924
- `:"",n=e.feedback==="positive"?"feedback-positive":e.feedback==="negative"?"feedback-negative":"",c=e.role==="assistant"&&e.content&&!e.isLoading?`
925
- <div class="cevvo-actions ${n}" data-message-id="${e.messageId||""}">
926
- <button class="cevvo-copy-btn" title="Copy">${i.copy}</button>
927
- <button class="cevvo-thumbs-up ${e.feedback==="positive"?"active":""}" title="Helpful">${i.thumbsUp}</button>
928
- <button class="cevvo-thumbs-down ${e.feedback==="negative"?"active":""}" title="Not helpful">${i.thumbsDown}</button>
943
+ `:"",i=e.feedback==="positive"?"feedback-positive":e.feedback==="negative"?"feedback-negative":"",r=e.role==="assistant"&&e.content&&!e.isLoading?`
944
+ <div class="cevvo-actions ${i}" data-message-id="${e.messageId||""}">
945
+ <button class="cevvo-copy-btn" title="Copy">${n.copy}</button>
946
+ <button class="cevvo-thumbs-up ${e.feedback==="positive"?"active":""}" title="Helpful">${n.thumbsUp}</button>
947
+ <button class="cevvo-thumbs-down ${e.feedback==="negative"?"active":""}" title="Not helpful">${n.thumbsDown}</button>
929
948
  </div>
930
949
  `:"";return`
931
950
  <div class="cevvo-message ${e.role}" data-msg-id="${e.id}">
@@ -933,7 +952,7 @@
933
952
  <div class="cevvo-message-content">
934
953
  <div class="cevvo-bubble ${e.role}">${a}</div>
935
954
  ${s}
936
- ${c}
955
+ ${r}
937
956
  </div>
938
957
  </div>
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)}})})()})();
958
+ `}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 i=await s.json();return{mode:i.mode,buttonText:i.buttonText,buttonPosition:i.position,projectColor:i.primaryColor,buttonBgColor:i.primaryColor,theme:i.theme||"light",modalTitle:i.modalTitle,modalSubtitle:i.modalSubtitle,modalExampleQuestions:i.exampleQuestions||[],welcomeMessage:i.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);if(e)for(const[o,a]of Object.entries(e))a!=null&&a!==""&&(t[o]=a)}return new h(t)},initWithRemoteConfig:async(t,e,o)=>{const a=await g(t,e,o),s={};if(a)for(const[r,d]of Object.entries(a))d!=null&&d!==""&&(s[r]=d);const i={projectId:t,apiKey:e,apiUrl:o,...s};return new h(i)},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 i={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")}},r=t.getAttribute("data-cevvo-example-questions");if(r)try{i.modalExampleQuestions=JSON.parse(r)}catch{}new h(i)}})})()})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cevvo-widget",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Cevvo Widget - AI-powered chat for your docs",
5
5
  "type": "module",
6
6
  "main": "dist/widget.js",