cevvo-widget 1.0.7 → 1.1.0
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/widget.js +88 -45
- 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?"},
|
|
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">
|
|
@@ -308,18 +308,41 @@
|
|
|
308
308
|
border-bottom-right-radius: 4px;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
.cevvo-bubble code {
|
|
311
|
+
.cevvo-bubble .cevvo-inline-code {
|
|
312
312
|
background: rgba(0,0,0,0.08);
|
|
313
313
|
padding: 2px 6px;
|
|
314
314
|
border-radius: 4px;
|
|
315
|
-
font-family: 'SF Mono', Monaco, monospace;
|
|
316
|
-
font-size:
|
|
315
|
+
font-family: 'SF Mono', 'Fira Code', Monaco, Consolas, monospace;
|
|
316
|
+
font-size: 12px;
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
.cevvo-bubble.user code {
|
|
319
|
+
.cevvo-bubble.user .cevvo-inline-code {
|
|
320
320
|
background: rgba(255,255,255,0.15);
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
.cevvo-bubble .cevvo-code-block {
|
|
324
|
+
background: #1a1b26;
|
|
325
|
+
color: #c0caf5;
|
|
326
|
+
border-radius: 8px;
|
|
327
|
+
padding: 14px 16px;
|
|
328
|
+
margin: 8px 0;
|
|
329
|
+
overflow-x: auto;
|
|
330
|
+
font-family: 'SF Mono', 'Fira Code', Monaco, Consolas, monospace;
|
|
331
|
+
font-size: 12px;
|
|
332
|
+
line-height: 1.6;
|
|
333
|
+
white-space: pre;
|
|
334
|
+
word-break: normal;
|
|
335
|
+
-webkit-overflow-scrolling: touch;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.cevvo-bubble .cevvo-code-block code {
|
|
339
|
+
background: none;
|
|
340
|
+
padding: 0;
|
|
341
|
+
border-radius: 0;
|
|
342
|
+
font-size: inherit;
|
|
343
|
+
color: inherit;
|
|
344
|
+
}
|
|
345
|
+
|
|
323
346
|
/* Typing indicator */
|
|
324
347
|
.cevvo-typing {
|
|
325
348
|
display: flex;
|
|
@@ -465,8 +488,12 @@
|
|
|
465
488
|
border: 1px solid #e4e4e7;
|
|
466
489
|
border-radius: 10px;
|
|
467
490
|
font-size: 14px;
|
|
491
|
+
line-height: 1.5;
|
|
468
492
|
outline: none;
|
|
469
493
|
background: #fff;
|
|
494
|
+
box-sizing: border-box;
|
|
495
|
+
width: 100%;
|
|
496
|
+
min-width: 0;
|
|
470
497
|
transition: border-color 0.15s ease;
|
|
471
498
|
}
|
|
472
499
|
|
|
@@ -501,6 +528,15 @@
|
|
|
501
528
|
opacity: 0.85;
|
|
502
529
|
}
|
|
503
530
|
|
|
531
|
+
.cevvo-disclaimer {
|
|
532
|
+
text-align: center;
|
|
533
|
+
font-size: 9px;
|
|
534
|
+
line-height: 1.4;
|
|
535
|
+
color: #a1a1aa;
|
|
536
|
+
margin: 0 0 8px;
|
|
537
|
+
padding: 0 12px;
|
|
538
|
+
}
|
|
539
|
+
|
|
504
540
|
.cevvo-powered {
|
|
505
541
|
text-align: center;
|
|
506
542
|
font-size: 11px;
|
|
@@ -579,18 +615,22 @@
|
|
|
579
615
|
.cevvo-modal-overlay.mode-modal .cevvo-input-wrapper {
|
|
580
616
|
display: flex;
|
|
581
617
|
flex-direction: column;
|
|
582
|
-
gap:
|
|
583
|
-
padding: 16px;
|
|
618
|
+
gap: 10px;
|
|
619
|
+
padding: 14px 16px;
|
|
584
620
|
border: 1px solid #e4e4e7;
|
|
585
621
|
border-radius: 14px;
|
|
586
622
|
background: #fff;
|
|
623
|
+
box-sizing: border-box;
|
|
587
624
|
}
|
|
588
625
|
|
|
589
626
|
.cevvo-modal-overlay.mode-modal .cevvo-input {
|
|
590
627
|
border: none;
|
|
591
|
-
padding: 0;
|
|
628
|
+
padding: 4px 0;
|
|
592
629
|
font-size: 15px;
|
|
630
|
+
line-height: 1.5;
|
|
593
631
|
background: transparent;
|
|
632
|
+
width: 100%;
|
|
633
|
+
box-sizing: border-box;
|
|
594
634
|
}
|
|
595
635
|
|
|
596
636
|
.cevvo-modal-overlay.mode-modal .cevvo-input:focus {
|
|
@@ -819,56 +859,58 @@
|
|
|
819
859
|
border-color: #38383a;
|
|
820
860
|
color: #e5e5ea;
|
|
821
861
|
}
|
|
822
|
-
`;class h{constructor(
|
|
862
|
+
`;class h{constructor(o={}){this.config={...b,...o},this.isOpen=!1,this.messages=[],this.threadId=null,this.isLoading=!1;const e=()=>{this.injectStyles(),this.createElements(),this.bindEvents()};document.body?e():document.addEventListener("DOMContentLoaded",e)}injectStyles(){if(document.getElementById("cevvo-widget-styles"))return;const o=document.createElement("style");o.id="cevvo-widget-styles",o.textContent=f,document.head.appendChild(o)}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 o=this.resolveTheme()==="dark"?"cevvo-dark":"";this.container.className=`cevvo-widget ${o}`.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 o=this.config.modalExampleQuestions.map(e=>`<button class="cevvo-example-btn">${this.escapeHtml(e)}</button>`).join("");return`
|
|
823
863
|
<div class="cevvo-modal">
|
|
824
864
|
<div class="cevvo-modal-header">
|
|
825
865
|
<div class="cevvo-header-info">
|
|
826
|
-
<div class="cevvo-header-logo">${
|
|
866
|
+
<div class="cevvo-header-logo">${n.cevvoLogo}</div>
|
|
827
867
|
<div class="cevvo-header-text">
|
|
828
868
|
<h2>${this.escapeHtml(this.config.modalTitle)}</h2>
|
|
829
869
|
<p>${this.escapeHtml(this.config.modalSubtitle)}</p>
|
|
830
870
|
</div>
|
|
831
871
|
</div>
|
|
832
872
|
<div class="cevvo-header-actions">
|
|
833
|
-
<button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${
|
|
834
|
-
<button class="cevvo-close-btn" title="Close">${
|
|
873
|
+
<button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${n.trash}</button>
|
|
874
|
+
<button class="cevvo-close-btn" title="Close">${n.close}</button>
|
|
835
875
|
</div>
|
|
836
876
|
</div>
|
|
837
877
|
<div class="cevvo-modal-body">
|
|
838
878
|
<div class="cevvo-empty-state">
|
|
839
|
-
<div class="cevvo-empty-icon">${
|
|
879
|
+
<div class="cevvo-empty-icon">${n.sparkle}</div>
|
|
840
880
|
<h3>${this.escapeHtml(this.config.welcomeMessage)}</h3>
|
|
841
|
-
${
|
|
881
|
+
${o?`<div class="cevvo-example-questions">${o}</div>`:""}
|
|
842
882
|
</div>
|
|
843
883
|
</div>
|
|
844
884
|
<div class="cevvo-modal-footer">
|
|
885
|
+
${this.config.disclaimer?`<p class="cevvo-disclaimer">${this.escapeHtml(this.config.disclaimer)}</p>`:""}
|
|
845
886
|
<form class="cevvo-input-form">
|
|
846
887
|
<input type="text" class="cevvo-input" placeholder="${this.escapeHtml(this.config.modalPlaceholder)}" />
|
|
847
|
-
<button type="submit" class="cevvo-send-btn" disabled>${
|
|
888
|
+
<button type="submit" class="cevvo-send-btn" disabled>${n.send}</button>
|
|
848
889
|
</form>
|
|
849
890
|
<p class="cevvo-powered">Powered by <a href="https://cevvo.ai" target="_blank" rel="noopener">Cevvo</a></p>
|
|
850
891
|
</div>
|
|
851
892
|
</div>
|
|
852
|
-
`}renderModalMode(){const
|
|
893
|
+
`}renderModalMode(){const o=this.config.modalDescription||this.config.modalSubtitle||"Ask me anything about the documentation.";return`
|
|
853
894
|
<div class="cevvo-modal">
|
|
854
895
|
<div class="cevvo-modal-header">
|
|
855
896
|
<div class="cevvo-header-info">
|
|
856
|
-
<div class="cevvo-header-logo">${
|
|
897
|
+
<div class="cevvo-header-logo">${n.cevvoLogo}</div>
|
|
857
898
|
<div class="cevvo-header-text">
|
|
858
899
|
<h2>${this.escapeHtml(this.config.modalTitle)}</h2>
|
|
859
900
|
</div>
|
|
860
901
|
</div>
|
|
861
902
|
<div class="cevvo-header-actions">
|
|
862
|
-
<button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${
|
|
863
|
-
<button class="cevvo-close-btn" title="Close">${
|
|
903
|
+
<button class="cevvo-clear-btn" title="Clear chat" style="display:none;">${n.trash}</button>
|
|
904
|
+
<button class="cevvo-close-btn" title="Close">${n.close}</button>
|
|
864
905
|
</div>
|
|
865
906
|
</div>
|
|
866
907
|
<div class="cevvo-modal-description" style="padding: 0 24px;">
|
|
867
|
-
${
|
|
908
|
+
${o}
|
|
868
909
|
</div>
|
|
869
910
|
<div class="cevvo-modal-body">
|
|
870
911
|
</div>
|
|
871
912
|
<div class="cevvo-modal-footer">
|
|
913
|
+
${this.config.disclaimer?`<p class="cevvo-disclaimer">${this.escapeHtml(this.config.disclaimer)}</p>`:""}
|
|
872
914
|
<div class="cevvo-input-wrapper">
|
|
873
915
|
<form class="cevvo-input-form" style="gap: 0;">
|
|
874
916
|
<input type="text" class="cevvo-input" placeholder="${this.escapeHtml(this.config.modalPlaceholder)}" />
|
|
@@ -879,61 +921,62 @@
|
|
|
879
921
|
For harder questions. Searches longer across all sources. Takes up to ~1 minute.
|
|
880
922
|
</div>
|
|
881
923
|
<button type="button" class="cevvo-deep-thinking-btn">
|
|
882
|
-
${
|
|
924
|
+
${n.brain}
|
|
883
925
|
<span>Deep thinking</span>
|
|
884
926
|
</button>
|
|
885
927
|
</div>
|
|
886
|
-
<button type="submit" class="cevvo-send-btn" disabled>${
|
|
928
|
+
<button type="submit" class="cevvo-send-btn" disabled>${n.arrowUp}</button>
|
|
887
929
|
</div>
|
|
888
930
|
</div>
|
|
889
931
|
<div class="cevvo-powered">
|
|
890
932
|
<div class="cevvo-powered-left">
|
|
891
933
|
<span>Powered by</span>
|
|
892
|
-
${
|
|
934
|
+
${n.cevvoLogo}
|
|
893
935
|
<a href="https://cevvo.ai" target="_blank" rel="noopener">cevvo.ai</a>
|
|
894
936
|
</div>
|
|
895
937
|
</div>
|
|
896
938
|
</div>
|
|
897
939
|
</div>
|
|
898
|
-
`}bindEvents(){this.button.addEventListener("click",()=>this.toggle()),this.overlay.addEventListener("click",
|
|
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&&(
|
|
940
|
+
`}bindEvents(){this.button.addEventListener("click",()=>this.toggle()),this.overlay.addEventListener("click",e=>{e.target===this.overlay&&this.close()}),this.closeBtn.addEventListener("click",()=>this.close()),this.clearBtn.addEventListener("click",()=>this.clearMessages()),this.form.addEventListener("submit",e=>{e.preventDefault(),this.sendMessage()}),this.overlay.querySelector(".cevvo-send-btn").addEventListener("click",e=>{e.preventDefault(),this.sendMessage()}),this.input.addEventListener("input",()=>{const e=this.overlay.querySelector(".cevvo-send-btn");e.disabled=!this.input.value.trim()||this.isLoading}),this.input.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),this.sendMessage())}),this.overlay.addEventListener("click",e=>{e.target.classList.contains("cevvo-example-btn")&&(this.input.value=e.target.textContent,this.sendMessage())}),this.messagesContainer.addEventListener("click",e=>{const t=e.target.closest("button");if(!t)return;const s=t.closest(".cevvo-actions");if(!s)return;const i=s.dataset.messageId,r=t.closest(".cevvo-message"),d=r==null?void 0:r.dataset.msgId,c=this.messages.find(l=>l.id===d);if(t.classList.contains("cevvo-copy-btn")&&(c!=null&&c.content)&&(navigator.clipboard.writeText(c.content),t.innerHTML=n.check,setTimeout(()=>{t.innerHTML=n.copy},2e3)),t.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(t.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",e=>{(e.metaKey||e.ctrlKey)&&e.key==="k"&&(e.preventDefault(),this.toggle()),e.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 o=this.input.value.trim();if(!o||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:o});const e=this.addMessage({role:"assistant",content:"",isLoading:!0});this.isLoading=!0;try{const t={"Content-Type":"application/json","X-API-Key":this.config.apiKey},s=await fetch(`${this.config.apiUrl}/widget/chat/stream`,{method:"POST",headers:t,body:JSON.stringify({message:o,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(`
|
|
941
|
+
`);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(e,{content:d,isLoading:!1})),v.sources&&(c=v.sources),v.question_answer_id&&(l=v.question_answer_id)}catch{}}}this.updateMessage(e,{content:d||"I'm sorry, I couldn't generate a response.",sources:c,messageId:l,isLoading:!1})}catch(t){console.error("Chat error:",t),this.updateMessage(e,{content:"Sorry, something went wrong. Please try again.",isLoading:!1})}finally{this.isLoading=!1}}addMessage(o){const e=Date.now().toString();return this.messages.push({id:e,...o}),this.renderMessages(),this.clearBtn.style.display="flex",this.updateModalState(),e}updateMessage(o,e){const t=this.messages.find(s=>s.id===o);t&&(Object.assign(t,e),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
942
|
<div class="cevvo-empty-state">
|
|
901
|
-
<div class="cevvo-empty-icon">${
|
|
943
|
+
<div class="cevvo-empty-icon">${n.sparkle}</div>
|
|
902
944
|
<h3>${this.escapeHtml(this.config.welcomeMessage)}</h3>
|
|
903
945
|
${this.config.modalExampleQuestions.length?`
|
|
904
946
|
<div class="cevvo-example-questions">
|
|
905
|
-
${this.config.modalExampleQuestions.map(
|
|
947
|
+
${this.config.modalExampleQuestions.map(o=>`<button class="cevvo-example-btn">${this.escapeHtml(o)}</button>`).join("")}
|
|
906
948
|
</div>
|
|
907
949
|
`:""}
|
|
908
950
|
</div>
|
|
909
951
|
`;return}this.messagesContainer.innerHTML=`
|
|
910
952
|
<div class="cevvo-messages">
|
|
911
|
-
${this.messages.map(
|
|
953
|
+
${this.messages.map(o=>this.renderMessage(o)).join("")}
|
|
912
954
|
</div>
|
|
913
|
-
`,this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight}renderMessage(
|
|
955
|
+
`,this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight}renderMessage(o){var d;const e=o.role==="assistant"?n.cevvoLogo:n.user,t=o.isLoading?'<div class="cevvo-typing"><span></span><span></span><span></span></div>':this.formatContent(o.content),s=(d=o.sources)!=null&&d.length?`
|
|
914
956
|
<div class="cevvo-sources">
|
|
915
|
-
<div class="cevvo-sources-header">${
|
|
916
|
-
${
|
|
917
|
-
<a href="${this.escapeHtml(
|
|
918
|
-
<span class="cevvo-source-num">${
|
|
919
|
-
<span class="cevvo-source-title">${this.escapeHtml(
|
|
920
|
-
${
|
|
957
|
+
<div class="cevvo-sources-header">${n.link} Sources</div>
|
|
958
|
+
${o.sources.map((c,l)=>`
|
|
959
|
+
<a href="${this.escapeHtml(c.source_url||c.url||"#")}" target="_blank" rel="noopener" class="cevvo-source-link">
|
|
960
|
+
<span class="cevvo-source-num">${l+1}</span>
|
|
961
|
+
<span class="cevvo-source-title">${this.escapeHtml(c.title||"Source")}</span>
|
|
962
|
+
${n.link}
|
|
921
963
|
</a>
|
|
922
964
|
`).join("")}
|
|
923
965
|
</div>
|
|
924
|
-
`:"",
|
|
925
|
-
<div class="cevvo-actions ${
|
|
926
|
-
<button class="cevvo-copy-btn" title="Copy">${
|
|
927
|
-
<button class="cevvo-thumbs-up ${
|
|
928
|
-
<button class="cevvo-thumbs-down ${
|
|
966
|
+
`:"",i=o.feedback==="positive"?"feedback-positive":o.feedback==="negative"?"feedback-negative":"",r=o.role==="assistant"&&o.content&&!o.isLoading?`
|
|
967
|
+
<div class="cevvo-actions ${i}" data-message-id="${o.messageId||""}">
|
|
968
|
+
<button class="cevvo-copy-btn" title="Copy">${n.copy}</button>
|
|
969
|
+
<button class="cevvo-thumbs-up ${o.feedback==="positive"?"active":""}" title="Helpful">${n.thumbsUp}</button>
|
|
970
|
+
<button class="cevvo-thumbs-down ${o.feedback==="negative"?"active":""}" title="Not helpful">${n.thumbsDown}</button>
|
|
929
971
|
</div>
|
|
930
972
|
`:"";return`
|
|
931
|
-
<div class="cevvo-message ${
|
|
932
|
-
<div class="cevvo-avatar ${
|
|
973
|
+
<div class="cevvo-message ${o.role}" data-msg-id="${o.id}">
|
|
974
|
+
<div class="cevvo-avatar ${o.role}">${e}</div>
|
|
933
975
|
<div class="cevvo-message-content">
|
|
934
|
-
<div class="cevvo-bubble ${
|
|
976
|
+
<div class="cevvo-bubble ${o.role}">${t}</div>
|
|
935
977
|
${s}
|
|
936
|
-
${
|
|
978
|
+
${r}
|
|
937
979
|
</div>
|
|
938
980
|
</div>
|
|
939
|
-
`}async submitFeedback(e
|
|
981
|
+
`}async submitFeedback(o,e){if(o)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:o,rating:e,project_id:this.config.projectId})})}catch(t){console.error("Feedback error:",t)}}formatContent(o){let e=this.escapeHtml(o);return e=e.replace(/```(\w*)\n([\s\S]*?)```/g,(t,s,i)=>`<pre class="cevvo-code-block"><code>${i.trim()}</code></pre>`),e=e.replace(/`([^`]+)`/g,'<code class="cevvo-inline-code">$1</code>'),e=e.replace(/\*\*(.*?)\*\*/g,"<strong>$1</strong>"),e=e.replace(/\*(.*?)\*/g,"<em>$1</em>"),e=e.replace(/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener" style="color:var(--cevvo-accent,#2563eb);text-decoration:underline;">$1</a>'),e=e.replace(/^(\d+)\.\s+(.+)$/gm,'<li style="margin-left:1.2em;list-style:decimal;">$2</li>'),e=e.replace(/^[-•]\s+(.+)$/gm,'<li style="margin-left:1.2em;list-style:disc;">$1</li>'),e=e.replace(/\n/g,"<br>"),e=e.replace(/<pre class="cevvo-code-block"><code>([\s\S]*?)<\/code><\/pre>/g,(t,s)=>`<pre class="cevvo-code-block"><code>${s.replace(/<br>/g,`
|
|
982
|
+
`)}</code></pre>`),e}escapeHtml(o){const e=document.createElement("div");return e.textContent=o,e.innerHTML}}async function g(a,o,e){const t=e||p;try{const s=await fetch(`${t}/widget/config?project_id=${encodeURIComponent(a)}`,{method:"GET",headers:{"X-API-Key":o}});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(a={})=>{if(a.projectId&&a.apiKey){const o=await g(a.projectId,a.apiKey,a.apiUrl);if(o)for(const[e,t]of Object.entries(o))t!=null&&t!==""&&(a[e]=t)}return new h(a)},initWithRemoteConfig:async(a,o,e)=>{const t=e||p,s=await g(a,o,t),i={};if(s)for(const[d,c]of Object.entries(s))c!=null&&c!==""&&(i[d]=c);const r={projectId:a,apiKey:o,apiUrl:t,...i};return new h(r)},testCredentials:async(a,o,e)=>{const t=e||p;try{const s=await fetch(`${t}/widget/config?project_id=${encodeURIComponent(a)}`,{method:"GET",headers:{"X-API-Key":o}});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 o=a.getAttribute("data-cevvo-project-id")||"",e=a.getAttribute("data-cevvo-api-key")||"",t=a.getAttribute("data-cevvo-api-url")||void 0;let s=null;o&&e&&(s=await g(o,e,t));const i={projectId:o,apiKey:e,apiUrl:t,...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")}},r=a.getAttribute("data-cevvo-example-questions");if(r)try{i.modalExampleQuestions=JSON.parse(r)}catch{}new h(i)}})})()})();
|