@vocantly/widget 0.1.17 → 0.1.18

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.cjs CHANGED
@@ -132,7 +132,9 @@ var ut=Object.create;var oe=Object.defineProperty;var gt=Object.getOwnPropertyDe
132
132
  .caf-root .caf-send:disabled{opacity:.38;cursor:not-allowed;transform:none;box-shadow:none;}
133
133
  .caf-foot{text-align:center;font-size:10.5px;line-height:1.3;color:#98a2b3;padding:7px 10px 9px;background:#fff;letter-spacing:.01em;}
134
134
 
135
- .caf-panel.caf-prechat .caf-msgs{justify-content:center;padding:22px;background:linear-gradient(160deg,#f7f9ff 0%,#f5f7fb 58%,#fff 100%);}
135
+ .caf-panel.caf-prechat .caf-msgs{justify-content:flex-start;padding:22px;background:linear-gradient(160deg,#f7f9ff 0%,#f5f7fb 58%,#fff 100%);}
136
+ .caf-panel.caf-prechat .caf-msgs>:not(.caf-form){display:none;}
137
+ .caf-panel.caf-prechat .caf-form{flex:none;}
136
138
  .caf-panel.caf-prechat .caf-composer{display:none;}
137
139
  .caf-form{width:100%;background:#fff;border:1px solid #e1e6ee;border-radius:20px;padding:22px;margin:0;display:flex;flex-direction:column;
138
140
  box-shadow:0 14px 36px rgba(24,34,55,.08);}
@@ -228,7 +230,7 @@ var ut=Object.create;var oe=Object.defineProperty;var gt=Object.getOwnPropertyDe
228
230
  <button class="caf-launcher" data-caf="launcher" aria-label="Open support chat" aria-controls="caf-support-panel" aria-expanded="false">
229
231
  <span data-caf="launcher-icon">${e.launcher==="\u{1F4AC}"?'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>':y(e.launcher)}</span>
230
232
  <span class="caf-badge" data-caf="badge" style="display:none">0</span>
231
- </button>`,document.body.appendChild(t),{root:t,$:n=>t.querySelector(`[data-caf="${n}"]`)}}function Xt(e){if(I)return I.open(),I.api;let t={...Jt,...e||{}};if(!t.wsUrl)throw new Error("VocantlyWidget.init requires wsUrl");if(!t.publicKey&&!(t.token&&t.conversationId))throw new Error("VocantlyWidget.init requires either { publicKey } (anonymous) or { token, conversationId }");if(t.publicKey&&!t.apiUrl)throw new Error("VocantlyWidget.init with publicKey also requires apiUrl");Yt(t.primaryColor,t.position);let{root:i,$:n}=Gt(t),a={panel:i.querySelector(".caf-panel"),msgs:n("msgs"),input:n("input"),send:n("send"),dot:n("dot"),badge:n("badge"),launcher:n("launcher"),call:n("call"),file:n("file"),attach:n("attach"),ticket:n("ticket"),upload:n("upload"),uploadBar:n("upload-bar"),uploadLabel:n("upload-label"),pending:n("pending"),pendingThumb:n("pending-thumb"),pendingName:n("pending-name"),pendingRemove:n("pending-remove"),human:n("human"),feedback:n("feedback")},o=null;function r(s,c="error",h=5e3){a.feedback&&(o&&clearTimeout(o),a.feedback.textContent=s,a.feedback.className=`caf-feedback show${c==="success"?" success":""}`,a.feedback.setAttribute("role",c==="error"?"alert":"status"),h>0&&(o=setTimeout(()=>{a.feedback.className="caf-feedback",a.feedback.textContent=""},h)))}function l(){o&&clearTimeout(o),o=null,a.feedback.className="caf-feedback",a.feedback.textContent=""}let d=null,f=!1,v=()=>t.calls===!0||f;function b(){d&&q&&a.call&&(a.call.style.display="flex")}function R(){return new Promise((s,c)=>{if(window.VocantlyWidgetCall)return s();let h=document.createElement("script");h.src=t.callBundleUrl,h.async=!0,h.onload=()=>s(),h.onerror=()=>c(new Error("call bundle load failed")),document.head.appendChild(h)})}async function k(){if(!(d||!O))try{if(await R(),!window.VocantlyWidgetCall)return;let s=document.createElement("div");document.body.appendChild(s),d=window.VocantlyWidgetCall.mount(s,O,{logoText:"CA",sessionTitle:t.title||"Call",sessionSubtitle:t.subtitle||"Secured via Vocantly",primaryColor:t.primaryColor,self:{name:"You",role:"Visitor"},peer:{name:t.title||"Support",role:"Agent"},voiceOnly:!0,simple:!0}),a.call&&(a.call.onclick=()=>d.startCall("voice")),b()}catch(s){r("Calling is unavailable right now. You can keep chatting with support."),t.debug&&console.error("[caf] call setup failed",s)}}let u=t.token||"",C=t.conversationId||"",F=u?Ye(u):null,_=null,ke=new Set,Se=!1,ee=!1,Ce=0,_e=!1,q=!t.collectContact,Te=!1,z=s=>{a.dot.className="caf-dot"+(s?" "+s:"")},V=()=>{a.msgs.scrollTop=a.msgs.scrollHeight},Me=s=>{Ce=s,a.badge.textContent=String(s),a.badge.style.display=s>0?"flex":"none"};function te(s,c){let h=document.createElement("div");h.className="caf-m "+s,h.innerHTML=c,a.msgs.appendChild(h),V()}function Ee(s){var S,L,T,P,U,$;if(s.optimistic)return;let c=(S=s.id)!=null?S:s.message_id,h=(T=(L=s.senderId)!=null?L:s.sender_id)!=null?T:"",g=(U=(P=s.content)!=null?P:s.text)!=null?U:"",p=($=s.messageType)!=null?$:s.message_type,w=s.attachments,x=c||`${h}:${g}`;if(ke.has(x))return;if(ke.add(x),p==="system"){te("caf-note",xe(g)),t.csat&&tt();return}let m=F&&h===F;(p==="image"||p==="video"||p==="file")&&w&&w.length?et(m,g,p,w[0]):te(m?"caf-self":"caf-other",xe(g)),!m&&Se&&Qt(),!m&&!ee&&Me(Ce+1)}function Ze(s,c){return`<div class="caf-media-skeleton" style="${s!=="file"&&c.width&&c.height?`aspect-ratio:${c.width}/${c.height};`:"aspect-ratio:4/3;"}"></div>`}function Re(s,c){let h=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
233
+ </button>`,document.body.appendChild(t),{root:t,$:n=>t.querySelector(`[data-caf="${n}"]`)}}function Xt(e){if(I)return I.open(),I.api;let t={...Jt,...e||{}};if(!t.wsUrl)throw new Error("VocantlyWidget.init requires wsUrl");if(!t.publicKey&&!(t.token&&t.conversationId))throw new Error("VocantlyWidget.init requires either { publicKey } (anonymous) or { token, conversationId }");if(t.publicKey&&!t.apiUrl)throw new Error("VocantlyWidget.init with publicKey also requires apiUrl");Yt(t.primaryColor,t.position);let{root:i,$:n}=Gt(t),a={panel:i.querySelector(".caf-panel"),msgs:n("msgs"),input:n("input"),send:n("send"),dot:n("dot"),badge:n("badge"),launcher:n("launcher"),call:n("call"),file:n("file"),attach:n("attach"),ticket:n("ticket"),upload:n("upload"),uploadBar:n("upload-bar"),uploadLabel:n("upload-label"),pending:n("pending"),pendingThumb:n("pending-thumb"),pendingName:n("pending-name"),pendingRemove:n("pending-remove"),human:n("human"),feedback:n("feedback")},o=null;function r(s,c="error",h=5e3){a.feedback&&(o&&clearTimeout(o),a.feedback.textContent=s,a.feedback.className=`caf-feedback show${c==="success"?" success":""}`,a.feedback.setAttribute("role",c==="error"?"alert":"status"),h>0&&(o=setTimeout(()=>{a.feedback.className="caf-feedback",a.feedback.textContent=""},h)))}function l(){o&&clearTimeout(o),o=null,a.feedback.className="caf-feedback",a.feedback.textContent=""}let d=null,f=!1,v=()=>t.calls===!0||f;function b(){d&&q&&a.call&&(a.call.style.display="flex")}function R(){return new Promise((s,c)=>{if(window.VocantlyWidgetCall)return s();let h=document.createElement("script");h.src=t.callBundleUrl,h.async=!0,h.onload=()=>s(),h.onerror=()=>c(new Error("call bundle load failed")),document.head.appendChild(h)})}async function k(){if(!(d||!O))try{if(await R(),!window.VocantlyWidgetCall)return;let s=document.createElement("div");document.body.appendChild(s),d=window.VocantlyWidgetCall.mount(s,O,{logoText:"CA",sessionTitle:t.title||"Call",sessionSubtitle:t.subtitle||"Secured via Vocantly",primaryColor:t.primaryColor,self:{name:"You",role:"Visitor"},peer:{name:t.title||"Support",role:"Agent"},voiceOnly:!0,simple:!0}),a.call&&(a.call.onclick=()=>d.startCall("voice")),b()}catch(s){r("Calling is unavailable right now. You can keep chatting with support."),t.debug&&console.error("[caf] call setup failed",s)}}let u=t.token||"",C=t.conversationId||"",F=u?Ye(u):null,_=null,ke=new Set,Se=!1,ee=!1,Ce=0,_e=!1,q=!t.collectContact,Te=!1,z=s=>{a.dot.className="caf-dot"+(s?" "+s:"")},V=()=>{if(a.panel.classList.contains("caf-prechat")){a.msgs.scrollTop=0;return}a.msgs.scrollTop=a.msgs.scrollHeight},Me=s=>{Ce=s,a.badge.textContent=String(s),a.badge.style.display=s>0?"flex":"none"};function te(s,c){let h=document.createElement("div");h.className="caf-m "+s,h.innerHTML=c,a.msgs.appendChild(h),V()}function Ee(s){var S,L,T,P,U,$;if(s.optimistic)return;let c=(S=s.id)!=null?S:s.message_id,h=(T=(L=s.senderId)!=null?L:s.sender_id)!=null?T:"",g=(U=(P=s.content)!=null?P:s.text)!=null?U:"",p=($=s.messageType)!=null?$:s.message_type,w=s.attachments,x=c||`${h}:${g}`;if(ke.has(x))return;if(ke.add(x),p==="system"){te("caf-note",xe(g)),t.csat&&tt();return}let m=F&&h===F;(p==="image"||p==="video"||p==="file")&&w&&w.length?et(m,g,p,w[0]):te(m?"caf-self":"caf-other",xe(g)),!m&&Se&&Qt(),!m&&!ee&&Me(Ce+1)}function Ze(s,c){return`<div class="caf-media-skeleton" style="${s!=="file"&&c.width&&c.height?`aspect-ratio:${c.width}/${c.height};`:"aspect-ratio:4/3;"}"></div>`}function Re(s,c){let h=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
232
234
  <span class="caf-file-meta"><span class="caf-file-name">${y(s.file_name)}</span><span class="caf-file-size">${y(Kt(s.size_bytes))}</span></span>`;return c?`<a class="caf-file-chip" href="${c}" target="_blank" rel="noopener noreferrer" download="${y(s.file_name)}">${h}</a>`:`<div class="caf-file-chip">${h}</div>`}function he(s,c){s&&(s.innerHTML=`<div class="caf-media-error">Couldn't load ${y(c)}</div>`)}function et(s,c,h,g){let p=document.createElement("div");if(p.className="caf-m caf-media "+(s?"caf-self":"caf-other"),p.innerHTML=`<div class="caf-media-body" data-media>${h==="file"?Re(g):Ze(h,g)}</div>`,c){let w=document.createElement("div");w.className="caf-media-caption",w.innerHTML=xe(c),p.appendChild(w)}a.msgs.appendChild(p),V(),_&&_.conversations.getAttachmentDownloadUrl(g.bucket,g.key).then(w=>{let x=p.querySelector("[data-media]");if(x){if(h==="image"){let m=document.createElement("a");m.href=w.url,m.target="_blank",m.rel="noopener noreferrer";let S=document.createElement("img");S.alt=g.file_name,S.loading="lazy",S.onerror=()=>he(x,g.file_name),S.src=w.url,m.appendChild(S),x.innerHTML="",x.appendChild(m)}else if(h==="video"){let m=document.createElement("video");m.controls=!0,m.preload="metadata",m.onerror=()=>he(x,g.file_name),m.src=w.url,x.innerHTML="",x.appendChild(m)}else x.innerHTML=Re(g,w.url);V()}}).catch(w=>{t.debug&&console.error("[caf] attachment load failed",w),he(p.querySelector("[data-media]"),g.file_name)})}let Ae=!1;function tt(){if(Ae||!t.apiUrl||!C)return;Ae=!0;let s=document.createElement("div");s.className="caf-csat",s.innerHTML=`<div>${y(t.csatPrompt)}</div><div class="caf-csat-row"></div>`;let c=s.querySelector(".caf-csat-row");[["1","\u{1F61E}"],["2","\u{1F641}"],["3","\u{1F610}"],["4","\u{1F642}"],["5","\u{1F600}"]].forEach(([h,g])=>{let p=document.createElement("button");p.className="caf-csat-b",p.type="button",p.textContent=g,p.setAttribute("aria-label",h+" out of 5"),p.onclick=()=>it(Number(h),s),c.appendChild(p)}),a.msgs.appendChild(s),V()}async function it(s,c){c.innerHTML=`<div>${y(t.csatThanks)}</div>`,V();try{await fetch(t.apiUrl.replace(/\/$/,"")+"/sdk/conversations/"+C+"/rating",{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer "+u},body:JSON.stringify({rating:s})})}catch(h){t.debug&&console.error("[caf] csat failed",h)}}function ie(s){a.input.disabled=!s,a.send.disabled=!s,a.attach.disabled=!s,a.human.disabled=!s,a.input.placeholder=s?t.placeholder:"\u2026"}function $e(){!_e&&t.greeting&&(te("caf-sys",y(t.greeting)),_e=!0)}function pe(s,c){return!s||typeof s!="object"?"":s[c]||s.en||Object.values(s)[0]||""}function nt(){let s=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";if(!s)return;let c=null;try{c=localStorage.getItem(s)}catch{}if(!c){c="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(s,c)}catch{}}return c}function at(s,c){if(s.visibility==="agent_only"||s.type==="hidden")return"";let h=y(pe(s.label,c)||s.key),g=y(pe(s.placeholder,c)),p=s.required?' required aria-required="true"':"",w=(s.options||[]).filter(m=>m.is_active).map(m=>`<option value="${y(m.value)}">${y(pe(m.label,c)||m.value)}</option>`).join(""),x;if(s.type==="long_text")x=`<textarea class="caf-fi" name="${y(s.key)}" placeholder="${g}"${p}></textarea>`;else if(s.type==="select")x=`<select class="caf-fi" name="${y(s.key)}"${p}><option value="">Select\u2026</option>${w}</select>`;else{if(s.type==="checkbox"||s.type==="consent")return`<label class="caf-check-field"><input name="${y(s.key)}" type="checkbox"${p} /><span>${h}${s.required?' <span class="caf-required">*</span>':""}</span></label><span class="caf-field-error">Please confirm this field.</span>`;{let m=s.type==="email"?"email":s.type==="phone"?"tel":s.type==="number"||s.type==="currency"?"number":s.type==="date"?"date":s.type==="url"?"url":"text";x=`<input class="caf-fi" name="${y(s.key)}" type="${m}" placeholder="${g}"${p} />`}}return`<label class="caf-fl">${h}${s.required?' <span class="caf-required">*</span>':' <span class="caf-optional">Optional</span>'}${x}<span class="caf-field-error">Please complete this field.</span></label>`}function je(){return`<div class="caf-ticket-intro">
233
235
  <div class="caf-form-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v7a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-7a2 2 0 0 0 0-4V5Z"/><path d="M13 5v2M13 11v2M13 17v2"/></svg></div>
234
236
  <div class="caf-ticket-intro-copy"><div class="caf-form-t">${y(t.ticketLabel)}</div><p class="caf-form-d">Tell us what happened. We\u2019ll create a reference so you can track every update.</p></div>
@@ -253,4 +255,4 @@ var ut=Object.create;var oe=Object.defineProperty;var gt=Object.getOwnPropertyDe
253
255
  <div class="caf-ferr" id="caf-contact-error" data-caf="f-err" role="alert" aria-live="polite"></div>
254
256
  <button class="caf-fbtn" data-caf="f-go" type="submit"><span>Start conversation</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg></button>
255
257
  ${t.requireEmail?"":'<button class="caf-fskip" data-caf="f-skip" type="button">Continue without details</button>'}
256
- <p class="caf-form-privacy">Your details are only used to support this conversation.</p>`,a.msgs.appendChild(s);let c=w=>s.querySelector(`[data-caf="${w}"]`),h=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,g=async w=>{let x=c("f-name").value.trim(),m=c("f-email").value.trim(),S=c("f-email");if(c("f-err").textContent="",S.setAttribute("aria-invalid","false"),w){if(t.requireEmail&&!m){c("f-err").textContent="Email is required.",S.setAttribute("aria-invalid","true"),S.focus();return}if(m&&!h.test(m)){c("f-err").textContent="Enter a valid email.",S.setAttribute("aria-invalid","true"),S.focus();return}let L=c("f-go");L.disabled=!0,L.querySelector("span").textContent="Starting\u2026";try{await ot(x,m)}catch(T){c("f-err").textContent="We couldn\u2019t start the conversation. Check your connection and try again.",L.disabled=!1,L.querySelector("span").textContent="Start conversation",t.debug&&console.error("[caf] saveContact failed",T);return}}s.remove(),a.panel.classList.remove("caf-prechat"),q=!0,b(),ie(!0),$e(),setTimeout(()=>a.input.focus(),30)};s.onsubmit=w=>{w.preventDefault(),g(!0)};let p=c("f-skip");p&&(p.onclick=()=>g(!1)),setTimeout(()=>c("f-name").focus(),40)}function ne(){if(ee=!0,a.panel.classList.add("open"),a.panel.setAttribute("aria-hidden","false"),a.launcher.setAttribute("aria-expanded","true"),a.launcher.setAttribute("aria-label","Close support chat"),Me(0),se().catch(()=>{}),!q&&!Te){ct();return}q&&($e(),setTimeout(()=>a.input.focus(),50))}function ae(){ee=!1,a.panel.classList.remove("open"),a.panel.setAttribute("aria-hidden","true"),a.launcher.setAttribute("aria-expanded","false"),a.launcher.setAttribute("aria-label","Open support chat"),a.launcher.focus()}a.launcher.onclick=()=>ee?ae():ne(),n("close").onclick=ae;let O=null,re=null,B=null;function Ie(){B&&(URL.revokeObjectURL(B),B=null),re=null,a.pending.classList.remove("show"),a.pendingThumb.innerHTML="",a.pendingName.textContent=""}function lt(s){re=s,a.pendingName.textContent=s.name,s.type&&s.type.startsWith("image/")?(B=URL.createObjectURL(s),a.pendingThumb.innerHTML=`<img src="${B}" alt="" />`):a.pendingThumb.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>',a.pending.classList.add("show"),setTimeout(()=>a.input.focus(),30)}async function fe(){if(!q)return;let s=a.input.value.trim();if(re){let c=re;Ie(),a.input.value="",a.input.style.height="auto",ht(c,s);return}if(!(!s||!O))try{a.send.disabled=!0,await Promise.resolve(O.sendMessage(s)),a.input.value="",a.input.style.height="auto"}catch(c){r("Your message wasn\u2019t sent. Please try again."),t.debug&&console.error("[caf] send failed",c)}finally{a.send.disabled=!1}}function Le(s,c){a.upload.classList.add("show"),a.uploadBar.style.width=c+"%",a.uploadLabel.textContent=`Sending ${s}\u2026 ${c}%`}function dt(){a.upload.classList.remove("show")}async function ht(s,c){if(!(!q||!O)){ie(!1),Le(s.name,0);try{await O.sendMedia(s,{caption:c||void 0,onProgress:h=>Le(s.name,h)})}catch(h){t.debug&&console.error("[caf] sendMedia failed",h),te("caf-note","Couldn\u2019t send that file. Please try again.")}finally{dt(),ie(q)}}}a.attach.onclick=()=>a.file.click(),!t.tickets||!t.publicKey?a.ticket.style.display="none":a.ticket.onclick=st,a.human.onclick=async()=>{if(!(!q||!O||a.human.disabled))try{a.human.disabled=!0,await Promise.resolve(O.sendMessage("I'd like to talk to a human agent.")),a.human.disabled=!0,a.human.textContent="Human requested",r("A human support agent has been requested.","success")}catch(s){a.human.disabled=!1,r("We couldn\u2019t request a human agent. Please try again."),t.debug&&console.error("[caf] human handoff request failed",s)}},a.file.addEventListener("change",()=>{let s=a.file.files&&a.file.files[0];a.file.value="",s&&lt(s)}),a.pendingRemove.onclick=()=>Ie(),a.send.onclick=fe,ie(q),a.input.addEventListener("input",()=>{a.input.style.height="auto",a.input.style.height=Math.min(a.input.scrollHeight,96)+"px"}),a.input.addEventListener("keydown",s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),fe())});let ue=t.publicKey?"caf_session_"+t.publicKey.slice(-10):"",pt=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";function Ue(){if(!ue)return null;try{let s=JSON.parse(localStorage.getItem(ue)||"null");if(s&&s.token&&s.conversationId&&s.exp>Date.now())return s}catch{}return null}async function ft(){let s=t.apiUrl.replace(/\/$/,""),c=ue,h=pt,g=Ue();if(g)return f=!!g.calls_enabled,{token:g.token,conversationId:g.conversationId};let p=null;try{p=localStorage.getItem(h)}catch{}if(!p){p="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(h,p)}catch{}}let w=await fetch(s+"/sdk/anonymous-session",{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":t.publicKey},body:JSON.stringify({visitor_id:p})});if(!w.ok)throw new Error("anonymous-session HTTP "+w.status);let x=await w.json(),m=x.data||x;f=!!m.calls_enabled;let S=Date.now()+Math.max(0,(m.expires_in||3600)*1e3-6e4);try{localStorage.setItem(c,JSON.stringify({token:m.token,conversationId:m.conversation_id,exp:S,calls_enabled:f}))}catch{}return{token:m.token,conversationId:m.conversation_id}}let J=null;function se(){return J||(J=(async()=>{var s,c,h,g;try{if(z(""),t.publicKey){let p=await ft();u=p.token,C=p.conversationId,F=Ye(u)}if(_=new Qe({wsUrl:t.wsUrl,token:u,apiUrl:t.apiUrl,appId:u?(s=Xe(u))==null?void 0:s.app_id:void 0,autoReconnect:!0,debug:t.debug}),_.on("connected",()=>{z("on"),l()}),_.on("disconnected",()=>z("")),_.on("reconnecting",()=>z("")),_.on("error",()=>{z("err"),r("Connection interrupted. We\u2019re trying to reconnect.","error",0)}),await _.connect(),await _.conversations.join(C),O=_.conversations.get(C),O.on("message",Ee),t.apiUrl&&typeof O.fetchMessages=="function")try{let p=await O.fetchMessages({limit:30});((g=(h=p==null?void 0:p.messages)!=null?h:(c=p==null?void 0:p.data)==null?void 0:c.messages)!=null?g:[]).forEach(Ee)}catch{}Se=!0,v()&&k()}catch(p){throw z("err"),J=null,r("We couldn\u2019t connect to support. Please check your connection and try again.","error",0),t.debug&&console.error("[caf] connect/provision failed",p),p}})(),J)}(!t.publicKey||Ue())&&se().catch(()=>{}),t.autoOpen&&ne();let Oe={open:ne,close:ae,send:async s=>{await se(),a.input.value=s,await fe()},destroy:()=>{try{_==null||_.disconnect()}catch{}i.remove(),I=null}};return I={open:ne,close:ae,api:Oe},Oe}function Zt(){I==null||I.open()}function ei(){I==null||I.close()}function ti(){I==null||I.api.destroy()}
258
+ <p class="caf-form-privacy">Your details are only used to support this conversation.</p>`,a.msgs.appendChild(s),a.msgs.scrollTop=0;let c=w=>s.querySelector(`[data-caf="${w}"]`),h=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,g=async w=>{let x=c("f-name").value.trim(),m=c("f-email").value.trim(),S=c("f-email");if(c("f-err").textContent="",S.setAttribute("aria-invalid","false"),w){if(t.requireEmail&&!m){c("f-err").textContent="Email is required.",S.setAttribute("aria-invalid","true"),S.focus();return}if(m&&!h.test(m)){c("f-err").textContent="Enter a valid email.",S.setAttribute("aria-invalid","true"),S.focus();return}let L=c("f-go");L.disabled=!0,L.querySelector("span").textContent="Starting\u2026";try{await ot(x,m)}catch(T){c("f-err").textContent="We couldn\u2019t start the conversation. Check your connection and try again.",L.disabled=!1,L.querySelector("span").textContent="Start conversation",t.debug&&console.error("[caf] saveContact failed",T);return}}s.remove(),a.panel.classList.remove("caf-prechat"),q=!0,b(),ie(!0),$e(),setTimeout(()=>a.input.focus(),30)};s.onsubmit=w=>{w.preventDefault(),g(!0)};let p=c("f-skip");p&&(p.onclick=()=>g(!1)),setTimeout(()=>c("f-name").focus(),40)}function ne(){if(ee=!0,a.panel.classList.add("open"),a.panel.setAttribute("aria-hidden","false"),a.launcher.setAttribute("aria-expanded","true"),a.launcher.setAttribute("aria-label","Close support chat"),Me(0),se().catch(()=>{}),!q&&!Te){ct();return}q&&($e(),setTimeout(()=>a.input.focus(),50))}function ae(){ee=!1,a.panel.classList.remove("open"),a.panel.setAttribute("aria-hidden","true"),a.launcher.setAttribute("aria-expanded","false"),a.launcher.setAttribute("aria-label","Open support chat"),a.launcher.focus()}a.launcher.onclick=()=>ee?ae():ne(),n("close").onclick=ae;let O=null,re=null,B=null;function Ie(){B&&(URL.revokeObjectURL(B),B=null),re=null,a.pending.classList.remove("show"),a.pendingThumb.innerHTML="",a.pendingName.textContent=""}function lt(s){re=s,a.pendingName.textContent=s.name,s.type&&s.type.startsWith("image/")?(B=URL.createObjectURL(s),a.pendingThumb.innerHTML=`<img src="${B}" alt="" />`):a.pendingThumb.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>',a.pending.classList.add("show"),setTimeout(()=>a.input.focus(),30)}async function fe(){if(!q)return;let s=a.input.value.trim();if(re){let c=re;Ie(),a.input.value="",a.input.style.height="auto",ht(c,s);return}if(!(!s||!O))try{a.send.disabled=!0,await Promise.resolve(O.sendMessage(s)),a.input.value="",a.input.style.height="auto"}catch(c){r("Your message wasn\u2019t sent. Please try again."),t.debug&&console.error("[caf] send failed",c)}finally{a.send.disabled=!1}}function Le(s,c){a.upload.classList.add("show"),a.uploadBar.style.width=c+"%",a.uploadLabel.textContent=`Sending ${s}\u2026 ${c}%`}function dt(){a.upload.classList.remove("show")}async function ht(s,c){if(!(!q||!O)){ie(!1),Le(s.name,0);try{await O.sendMedia(s,{caption:c||void 0,onProgress:h=>Le(s.name,h)})}catch(h){t.debug&&console.error("[caf] sendMedia failed",h),te("caf-note","Couldn\u2019t send that file. Please try again.")}finally{dt(),ie(q)}}}a.attach.onclick=()=>a.file.click(),!t.tickets||!t.publicKey?a.ticket.style.display="none":a.ticket.onclick=st,a.human.onclick=async()=>{if(!(!q||!O||a.human.disabled))try{a.human.disabled=!0,await Promise.resolve(O.sendMessage("I'd like to talk to a human agent.")),a.human.disabled=!0,a.human.textContent="Human requested",r("A human support agent has been requested.","success")}catch(s){a.human.disabled=!1,r("We couldn\u2019t request a human agent. Please try again."),t.debug&&console.error("[caf] human handoff request failed",s)}},a.file.addEventListener("change",()=>{let s=a.file.files&&a.file.files[0];a.file.value="",s&&lt(s)}),a.pendingRemove.onclick=()=>Ie(),a.send.onclick=fe,ie(q),a.input.addEventListener("input",()=>{a.input.style.height="auto",a.input.style.height=Math.min(a.input.scrollHeight,96)+"px"}),a.input.addEventListener("keydown",s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),fe())});let ue=t.publicKey?"caf_session_"+t.publicKey.slice(-10):"",pt=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";function Ue(){if(!ue)return null;try{let s=JSON.parse(localStorage.getItem(ue)||"null");if(s&&s.token&&s.conversationId&&s.exp>Date.now())return s}catch{}return null}async function ft(){let s=t.apiUrl.replace(/\/$/,""),c=ue,h=pt,g=Ue();if(g)return f=!!g.calls_enabled,{token:g.token,conversationId:g.conversationId};let p=null;try{p=localStorage.getItem(h)}catch{}if(!p){p="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(h,p)}catch{}}let w=await fetch(s+"/sdk/anonymous-session",{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":t.publicKey},body:JSON.stringify({visitor_id:p})});if(!w.ok)throw new Error("anonymous-session HTTP "+w.status);let x=await w.json(),m=x.data||x;f=!!m.calls_enabled;let S=Date.now()+Math.max(0,(m.expires_in||3600)*1e3-6e4);try{localStorage.setItem(c,JSON.stringify({token:m.token,conversationId:m.conversation_id,exp:S,calls_enabled:f}))}catch{}return{token:m.token,conversationId:m.conversation_id}}let J=null;function se(){return J||(J=(async()=>{var s,c,h,g;try{if(z(""),t.publicKey){let p=await ft();u=p.token,C=p.conversationId,F=Ye(u)}if(_=new Qe({wsUrl:t.wsUrl,token:u,apiUrl:t.apiUrl,appId:u?(s=Xe(u))==null?void 0:s.app_id:void 0,autoReconnect:!0,debug:t.debug}),_.on("connected",()=>{z("on"),l()}),_.on("disconnected",()=>z("")),_.on("reconnecting",()=>z("")),_.on("error",()=>{z("err"),r("Connection interrupted. We\u2019re trying to reconnect.","error",0)}),await _.connect(),await _.conversations.join(C),O=_.conversations.get(C),O.on("message",Ee),t.apiUrl&&typeof O.fetchMessages=="function")try{let p=await O.fetchMessages({limit:30});((g=(h=p==null?void 0:p.messages)!=null?h:(c=p==null?void 0:p.data)==null?void 0:c.messages)!=null?g:[]).forEach(Ee)}catch{}Se=!0,v()&&k()}catch(p){throw z("err"),J=null,r("We couldn\u2019t connect to support. Please check your connection and try again.","error",0),t.debug&&console.error("[caf] connect/provision failed",p),p}})(),J)}(!t.publicKey||Ue())&&se().catch(()=>{}),t.autoOpen&&ne();let Oe={open:ne,close:ae,send:async s=>{await se(),a.input.value=s,await fe()},destroy:()=>{try{_==null||_.disconnect()}catch{}i.remove(),I=null}};return I={open:ne,close:ae,api:Oe},Oe}function Zt(){I==null||I.open()}function ei(){I==null||I.close()}function ti(){I==null||I.api.destroy()}
package/dist/index.mjs CHANGED
@@ -132,7 +132,9 @@ var ut=Object.create;var De=Object.defineProperty;var gt=Object.getOwnPropertyDe
132
132
  .caf-root .caf-send:disabled{opacity:.38;cursor:not-allowed;transform:none;box-shadow:none;}
133
133
  .caf-foot{text-align:center;font-size:10.5px;line-height:1.3;color:#98a2b3;padding:7px 10px 9px;background:#fff;letter-spacing:.01em;}
134
134
 
135
- .caf-panel.caf-prechat .caf-msgs{justify-content:center;padding:22px;background:linear-gradient(160deg,#f7f9ff 0%,#f5f7fb 58%,#fff 100%);}
135
+ .caf-panel.caf-prechat .caf-msgs{justify-content:flex-start;padding:22px;background:linear-gradient(160deg,#f7f9ff 0%,#f5f7fb 58%,#fff 100%);}
136
+ .caf-panel.caf-prechat .caf-msgs>:not(.caf-form){display:none;}
137
+ .caf-panel.caf-prechat .caf-form{flex:none;}
136
138
  .caf-panel.caf-prechat .caf-composer{display:none;}
137
139
  .caf-form{width:100%;background:#fff;border:1px solid #e1e6ee;border-radius:20px;padding:22px;margin:0;display:flex;flex-direction:column;
138
140
  box-shadow:0 14px 36px rgba(24,34,55,.08);}
@@ -228,7 +230,7 @@ var ut=Object.create;var De=Object.defineProperty;var gt=Object.getOwnPropertyDe
228
230
  <button class="caf-launcher" data-caf="launcher" aria-label="Open support chat" aria-controls="caf-support-panel" aria-expanded="false">
229
231
  <span data-caf="launcher-icon">${e.launcher==="\u{1F4AC}"?'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>':y(e.launcher)}</span>
230
232
  <span class="caf-badge" data-caf="badge" style="display:none">0</span>
231
- </button>`,document.body.appendChild(t),{root:t,$:n=>t.querySelector(`[data-caf="${n}"]`)}}function $i(e){if(I)return I.open(),I.api;let t={...Bt,...e||{}};if(!t.wsUrl)throw new Error("VocantlyWidget.init requires wsUrl");if(!t.publicKey&&!(t.token&&t.conversationId))throw new Error("VocantlyWidget.init requires either { publicKey } (anonymous) or { token, conversationId }");if(t.publicKey&&!t.apiUrl)throw new Error("VocantlyWidget.init with publicKey also requires apiUrl");Qt(t.primaryColor,t.position);let{root:i,$:n}=Yt(t),a={panel:i.querySelector(".caf-panel"),msgs:n("msgs"),input:n("input"),send:n("send"),dot:n("dot"),badge:n("badge"),launcher:n("launcher"),call:n("call"),file:n("file"),attach:n("attach"),ticket:n("ticket"),upload:n("upload"),uploadBar:n("upload-bar"),uploadLabel:n("upload-label"),pending:n("pending"),pendingThumb:n("pending-thumb"),pendingName:n("pending-name"),pendingRemove:n("pending-remove"),human:n("human"),feedback:n("feedback")},o=null;function r(s,c="error",h=5e3){a.feedback&&(o&&clearTimeout(o),a.feedback.textContent=s,a.feedback.className=`caf-feedback show${c==="success"?" success":""}`,a.feedback.setAttribute("role",c==="error"?"alert":"status"),h>0&&(o=setTimeout(()=>{a.feedback.className="caf-feedback",a.feedback.textContent=""},h)))}function l(){o&&clearTimeout(o),o=null,a.feedback.className="caf-feedback",a.feedback.textContent=""}let d=null,f=!1,v=()=>t.calls===!0||f;function b(){d&&q&&a.call&&(a.call.style.display="flex")}function R(){return new Promise((s,c)=>{if(window.VocantlyWidgetCall)return s();let h=document.createElement("script");h.src=t.callBundleUrl,h.async=!0,h.onload=()=>s(),h.onerror=()=>c(new Error("call bundle load failed")),document.head.appendChild(h)})}async function k(){if(!(d||!O))try{if(await R(),!window.VocantlyWidgetCall)return;let s=document.createElement("div");document.body.appendChild(s),d=window.VocantlyWidgetCall.mount(s,O,{logoText:"CA",sessionTitle:t.title||"Call",sessionSubtitle:t.subtitle||"Secured via Vocantly",primaryColor:t.primaryColor,self:{name:"You",role:"Visitor"},peer:{name:t.title||"Support",role:"Agent"},voiceOnly:!0,simple:!0}),a.call&&(a.call.onclick=()=>d.startCall("voice")),b()}catch(s){r("Calling is unavailable right now. You can keep chatting with support."),t.debug&&console.error("[caf] call setup failed",s)}}let u=t.token||"",C=t.conversationId||"",F=u?Ye(u):null,_=null,xe=new Set,ke=!1,te=!1,Se=0,Ce=!1,q=!t.collectContact,_e=!1,V=s=>{a.dot.className="caf-dot"+(s?" "+s:"")},W=()=>{a.msgs.scrollTop=a.msgs.scrollHeight},Te=s=>{Se=s,a.badge.textContent=String(s),a.badge.style.display=s>0?"flex":"none"};function ie(s,c){let h=document.createElement("div");h.className="caf-m "+s,h.innerHTML=c,a.msgs.appendChild(h),W()}function Me(s){var S,L,T,P,U,$;if(s.optimistic)return;let c=(S=s.id)!=null?S:s.message_id,h=(T=(L=s.senderId)!=null?L:s.sender_id)!=null?T:"",g=(U=(P=s.content)!=null?P:s.text)!=null?U:"",p=($=s.messageType)!=null?$:s.message_type,w=s.attachments,x=c||`${h}:${g}`;if(xe.has(x))return;if(xe.add(x),p==="system"){ie("caf-note",ye(g)),t.csat&&tt();return}let m=F&&h===F;(p==="image"||p==="video"||p==="file")&&w&&w.length?et(m,g,p,w[0]):ie(m?"caf-self":"caf-other",ye(g)),!m&&ke&&Kt(),!m&&!te&&Te(Se+1)}function Ze(s,c){return`<div class="caf-media-skeleton" style="${s!=="file"&&c.width&&c.height?`aspect-ratio:${c.width}/${c.height};`:"aspect-ratio:4/3;"}"></div>`}function Ee(s,c){let h=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
233
+ </button>`,document.body.appendChild(t),{root:t,$:n=>t.querySelector(`[data-caf="${n}"]`)}}function $i(e){if(I)return I.open(),I.api;let t={...Bt,...e||{}};if(!t.wsUrl)throw new Error("VocantlyWidget.init requires wsUrl");if(!t.publicKey&&!(t.token&&t.conversationId))throw new Error("VocantlyWidget.init requires either { publicKey } (anonymous) or { token, conversationId }");if(t.publicKey&&!t.apiUrl)throw new Error("VocantlyWidget.init with publicKey also requires apiUrl");Qt(t.primaryColor,t.position);let{root:i,$:n}=Yt(t),a={panel:i.querySelector(".caf-panel"),msgs:n("msgs"),input:n("input"),send:n("send"),dot:n("dot"),badge:n("badge"),launcher:n("launcher"),call:n("call"),file:n("file"),attach:n("attach"),ticket:n("ticket"),upload:n("upload"),uploadBar:n("upload-bar"),uploadLabel:n("upload-label"),pending:n("pending"),pendingThumb:n("pending-thumb"),pendingName:n("pending-name"),pendingRemove:n("pending-remove"),human:n("human"),feedback:n("feedback")},o=null;function r(s,c="error",h=5e3){a.feedback&&(o&&clearTimeout(o),a.feedback.textContent=s,a.feedback.className=`caf-feedback show${c==="success"?" success":""}`,a.feedback.setAttribute("role",c==="error"?"alert":"status"),h>0&&(o=setTimeout(()=>{a.feedback.className="caf-feedback",a.feedback.textContent=""},h)))}function l(){o&&clearTimeout(o),o=null,a.feedback.className="caf-feedback",a.feedback.textContent=""}let d=null,f=!1,v=()=>t.calls===!0||f;function b(){d&&q&&a.call&&(a.call.style.display="flex")}function R(){return new Promise((s,c)=>{if(window.VocantlyWidgetCall)return s();let h=document.createElement("script");h.src=t.callBundleUrl,h.async=!0,h.onload=()=>s(),h.onerror=()=>c(new Error("call bundle load failed")),document.head.appendChild(h)})}async function k(){if(!(d||!O))try{if(await R(),!window.VocantlyWidgetCall)return;let s=document.createElement("div");document.body.appendChild(s),d=window.VocantlyWidgetCall.mount(s,O,{logoText:"CA",sessionTitle:t.title||"Call",sessionSubtitle:t.subtitle||"Secured via Vocantly",primaryColor:t.primaryColor,self:{name:"You",role:"Visitor"},peer:{name:t.title||"Support",role:"Agent"},voiceOnly:!0,simple:!0}),a.call&&(a.call.onclick=()=>d.startCall("voice")),b()}catch(s){r("Calling is unavailable right now. You can keep chatting with support."),t.debug&&console.error("[caf] call setup failed",s)}}let u=t.token||"",C=t.conversationId||"",F=u?Ye(u):null,_=null,xe=new Set,ke=!1,te=!1,Se=0,Ce=!1,q=!t.collectContact,_e=!1,V=s=>{a.dot.className="caf-dot"+(s?" "+s:"")},W=()=>{if(a.panel.classList.contains("caf-prechat")){a.msgs.scrollTop=0;return}a.msgs.scrollTop=a.msgs.scrollHeight},Te=s=>{Se=s,a.badge.textContent=String(s),a.badge.style.display=s>0?"flex":"none"};function ie(s,c){let h=document.createElement("div");h.className="caf-m "+s,h.innerHTML=c,a.msgs.appendChild(h),W()}function Me(s){var S,L,T,P,U,$;if(s.optimistic)return;let c=(S=s.id)!=null?S:s.message_id,h=(T=(L=s.senderId)!=null?L:s.sender_id)!=null?T:"",g=(U=(P=s.content)!=null?P:s.text)!=null?U:"",p=($=s.messageType)!=null?$:s.message_type,w=s.attachments,x=c||`${h}:${g}`;if(xe.has(x))return;if(xe.add(x),p==="system"){ie("caf-note",ye(g)),t.csat&&tt();return}let m=F&&h===F;(p==="image"||p==="video"||p==="file")&&w&&w.length?et(m,g,p,w[0]):ie(m?"caf-self":"caf-other",ye(g)),!m&&ke&&Kt(),!m&&!te&&Te(Se+1)}function Ze(s,c){return`<div class="caf-media-skeleton" style="${s!=="file"&&c.width&&c.height?`aspect-ratio:${c.width}/${c.height};`:"aspect-ratio:4/3;"}"></div>`}function Ee(s,c){let h=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
232
234
  <span class="caf-file-meta"><span class="caf-file-name">${y(s.file_name)}</span><span class="caf-file-size">${y(Jt(s.size_bytes))}</span></span>`;return c?`<a class="caf-file-chip" href="${c}" target="_blank" rel="noopener noreferrer" download="${y(s.file_name)}">${h}</a>`:`<div class="caf-file-chip">${h}</div>`}function he(s,c){s&&(s.innerHTML=`<div class="caf-media-error">Couldn't load ${y(c)}</div>`)}function et(s,c,h,g){let p=document.createElement("div");if(p.className="caf-m caf-media "+(s?"caf-self":"caf-other"),p.innerHTML=`<div class="caf-media-body" data-media>${h==="file"?Ee(g):Ze(h,g)}</div>`,c){let w=document.createElement("div");w.className="caf-media-caption",w.innerHTML=ye(c),p.appendChild(w)}a.msgs.appendChild(p),W(),_&&_.conversations.getAttachmentDownloadUrl(g.bucket,g.key).then(w=>{let x=p.querySelector("[data-media]");if(x){if(h==="image"){let m=document.createElement("a");m.href=w.url,m.target="_blank",m.rel="noopener noreferrer";let S=document.createElement("img");S.alt=g.file_name,S.loading="lazy",S.onerror=()=>he(x,g.file_name),S.src=w.url,m.appendChild(S),x.innerHTML="",x.appendChild(m)}else if(h==="video"){let m=document.createElement("video");m.controls=!0,m.preload="metadata",m.onerror=()=>he(x,g.file_name),m.src=w.url,x.innerHTML="",x.appendChild(m)}else x.innerHTML=Ee(g,w.url);W()}}).catch(w=>{t.debug&&console.error("[caf] attachment load failed",w),he(p.querySelector("[data-media]"),g.file_name)})}let Re=!1;function tt(){if(Re||!t.apiUrl||!C)return;Re=!0;let s=document.createElement("div");s.className="caf-csat",s.innerHTML=`<div>${y(t.csatPrompt)}</div><div class="caf-csat-row"></div>`;let c=s.querySelector(".caf-csat-row");[["1","\u{1F61E}"],["2","\u{1F641}"],["3","\u{1F610}"],["4","\u{1F642}"],["5","\u{1F600}"]].forEach(([h,g])=>{let p=document.createElement("button");p.className="caf-csat-b",p.type="button",p.textContent=g,p.setAttribute("aria-label",h+" out of 5"),p.onclick=()=>it(Number(h),s),c.appendChild(p)}),a.msgs.appendChild(s),W()}async function it(s,c){c.innerHTML=`<div>${y(t.csatThanks)}</div>`,W();try{await fetch(t.apiUrl.replace(/\/$/,"")+"/sdk/conversations/"+C+"/rating",{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer "+u},body:JSON.stringify({rating:s})})}catch(h){t.debug&&console.error("[caf] csat failed",h)}}function ne(s){a.input.disabled=!s,a.send.disabled=!s,a.attach.disabled=!s,a.human.disabled=!s,a.input.placeholder=s?t.placeholder:"\u2026"}function Ae(){!Ce&&t.greeting&&(ie("caf-sys",y(t.greeting)),Ce=!0)}function pe(s,c){return!s||typeof s!="object"?"":s[c]||s.en||Object.values(s)[0]||""}function nt(){let s=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";if(!s)return;let c=null;try{c=localStorage.getItem(s)}catch{}if(!c){c="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(s,c)}catch{}}return c}function at(s,c){if(s.visibility==="agent_only"||s.type==="hidden")return"";let h=y(pe(s.label,c)||s.key),g=y(pe(s.placeholder,c)),p=s.required?' required aria-required="true"':"",w=(s.options||[]).filter(m=>m.is_active).map(m=>`<option value="${y(m.value)}">${y(pe(m.label,c)||m.value)}</option>`).join(""),x;if(s.type==="long_text")x=`<textarea class="caf-fi" name="${y(s.key)}" placeholder="${g}"${p}></textarea>`;else if(s.type==="select")x=`<select class="caf-fi" name="${y(s.key)}"${p}><option value="">Select\u2026</option>${w}</select>`;else{if(s.type==="checkbox"||s.type==="consent")return`<label class="caf-check-field"><input name="${y(s.key)}" type="checkbox"${p} /><span>${h}${s.required?' <span class="caf-required">*</span>':""}</span></label><span class="caf-field-error">Please confirm this field.</span>`;{let m=s.type==="email"?"email":s.type==="phone"?"tel":s.type==="number"||s.type==="currency"?"number":s.type==="date"?"date":s.type==="url"?"url":"text";x=`<input class="caf-fi" name="${y(s.key)}" type="${m}" placeholder="${g}"${p} />`}}return`<label class="caf-fl">${h}${s.required?' <span class="caf-required">*</span>':' <span class="caf-optional">Optional</span>'}${x}<span class="caf-field-error">Please complete this field.</span></label>`}function $e(){return`<div class="caf-ticket-intro">
233
235
  <div class="caf-form-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v7a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-7a2 2 0 0 0 0-4V5Z"/><path d="M13 5v2M13 11v2M13 17v2"/></svg></div>
234
236
  <div class="caf-ticket-intro-copy"><div class="caf-form-t">${y(t.ticketLabel)}</div><p class="caf-form-d">Tell us what happened. We\u2019ll create a reference so you can track every update.</p></div>
@@ -253,4 +255,4 @@ var ut=Object.create;var De=Object.defineProperty;var gt=Object.getOwnPropertyDe
253
255
  <div class="caf-ferr" id="caf-contact-error" data-caf="f-err" role="alert" aria-live="polite"></div>
254
256
  <button class="caf-fbtn" data-caf="f-go" type="submit"><span>Start conversation</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg></button>
255
257
  ${t.requireEmail?"":'<button class="caf-fskip" data-caf="f-skip" type="button">Continue without details</button>'}
256
- <p class="caf-form-privacy">Your details are only used to support this conversation.</p>`,a.msgs.appendChild(s);let c=w=>s.querySelector(`[data-caf="${w}"]`),h=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,g=async w=>{let x=c("f-name").value.trim(),m=c("f-email").value.trim(),S=c("f-email");if(c("f-err").textContent="",S.setAttribute("aria-invalid","false"),w){if(t.requireEmail&&!m){c("f-err").textContent="Email is required.",S.setAttribute("aria-invalid","true"),S.focus();return}if(m&&!h.test(m)){c("f-err").textContent="Enter a valid email.",S.setAttribute("aria-invalid","true"),S.focus();return}let L=c("f-go");L.disabled=!0,L.querySelector("span").textContent="Starting\u2026";try{await ot(x,m)}catch(T){c("f-err").textContent="We couldn\u2019t start the conversation. Check your connection and try again.",L.disabled=!1,L.querySelector("span").textContent="Start conversation",t.debug&&console.error("[caf] saveContact failed",T);return}}s.remove(),a.panel.classList.remove("caf-prechat"),q=!0,b(),ne(!0),Ae(),setTimeout(()=>a.input.focus(),30)};s.onsubmit=w=>{w.preventDefault(),g(!0)};let p=c("f-skip");p&&(p.onclick=()=>g(!1)),setTimeout(()=>c("f-name").focus(),40)}function ae(){if(te=!0,a.panel.classList.add("open"),a.panel.setAttribute("aria-hidden","false"),a.launcher.setAttribute("aria-expanded","true"),a.launcher.setAttribute("aria-label","Close support chat"),Te(0),oe().catch(()=>{}),!q&&!_e){ct();return}q&&(Ae(),setTimeout(()=>a.input.focus(),50))}function re(){te=!1,a.panel.classList.remove("open"),a.panel.setAttribute("aria-hidden","true"),a.launcher.setAttribute("aria-expanded","false"),a.launcher.setAttribute("aria-label","Open support chat"),a.launcher.focus()}a.launcher.onclick=()=>te?re():ae(),n("close").onclick=re;let O=null,se=null,J=null;function je(){J&&(URL.revokeObjectURL(J),J=null),se=null,a.pending.classList.remove("show"),a.pendingThumb.innerHTML="",a.pendingName.textContent=""}function lt(s){se=s,a.pendingName.textContent=s.name,s.type&&s.type.startsWith("image/")?(J=URL.createObjectURL(s),a.pendingThumb.innerHTML=`<img src="${J}" alt="" />`):a.pendingThumb.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>',a.pending.classList.add("show"),setTimeout(()=>a.input.focus(),30)}async function fe(){if(!q)return;let s=a.input.value.trim();if(se){let c=se;je(),a.input.value="",a.input.style.height="auto",ht(c,s);return}if(!(!s||!O))try{a.send.disabled=!0,await Promise.resolve(O.sendMessage(s)),a.input.value="",a.input.style.height="auto"}catch(c){r("Your message wasn\u2019t sent. Please try again."),t.debug&&console.error("[caf] send failed",c)}finally{a.send.disabled=!1}}function Ie(s,c){a.upload.classList.add("show"),a.uploadBar.style.width=c+"%",a.uploadLabel.textContent=`Sending ${s}\u2026 ${c}%`}function dt(){a.upload.classList.remove("show")}async function ht(s,c){if(!(!q||!O)){ne(!1),Ie(s.name,0);try{await O.sendMedia(s,{caption:c||void 0,onProgress:h=>Ie(s.name,h)})}catch(h){t.debug&&console.error("[caf] sendMedia failed",h),ie("caf-note","Couldn\u2019t send that file. Please try again.")}finally{dt(),ne(q)}}}a.attach.onclick=()=>a.file.click(),!t.tickets||!t.publicKey?a.ticket.style.display="none":a.ticket.onclick=st,a.human.onclick=async()=>{if(!(!q||!O||a.human.disabled))try{a.human.disabled=!0,await Promise.resolve(O.sendMessage("I'd like to talk to a human agent.")),a.human.disabled=!0,a.human.textContent="Human requested",r("A human support agent has been requested.","success")}catch(s){a.human.disabled=!1,r("We couldn\u2019t request a human agent. Please try again."),t.debug&&console.error("[caf] human handoff request failed",s)}},a.file.addEventListener("change",()=>{let s=a.file.files&&a.file.files[0];a.file.value="",s&&lt(s)}),a.pendingRemove.onclick=()=>je(),a.send.onclick=fe,ne(q),a.input.addEventListener("input",()=>{a.input.style.height="auto",a.input.style.height=Math.min(a.input.scrollHeight,96)+"px"}),a.input.addEventListener("keydown",s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),fe())});let ue=t.publicKey?"caf_session_"+t.publicKey.slice(-10):"",pt=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";function Le(){if(!ue)return null;try{let s=JSON.parse(localStorage.getItem(ue)||"null");if(s&&s.token&&s.conversationId&&s.exp>Date.now())return s}catch{}return null}async function ft(){let s=t.apiUrl.replace(/\/$/,""),c=ue,h=pt,g=Le();if(g)return f=!!g.calls_enabled,{token:g.token,conversationId:g.conversationId};let p=null;try{p=localStorage.getItem(h)}catch{}if(!p){p="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(h,p)}catch{}}let w=await fetch(s+"/sdk/anonymous-session",{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":t.publicKey},body:JSON.stringify({visitor_id:p})});if(!w.ok)throw new Error("anonymous-session HTTP "+w.status);let x=await w.json(),m=x.data||x;f=!!m.calls_enabled;let S=Date.now()+Math.max(0,(m.expires_in||3600)*1e3-6e4);try{localStorage.setItem(c,JSON.stringify({token:m.token,conversationId:m.conversation_id,exp:S,calls_enabled:f}))}catch{}return{token:m.token,conversationId:m.conversation_id}}let K=null;function oe(){return K||(K=(async()=>{var s,c,h,g;try{if(V(""),t.publicKey){let p=await ft();u=p.token,C=p.conversationId,F=Ye(u)}if(_=new Qe({wsUrl:t.wsUrl,token:u,apiUrl:t.apiUrl,appId:u?(s=Xe(u))==null?void 0:s.app_id:void 0,autoReconnect:!0,debug:t.debug}),_.on("connected",()=>{V("on"),l()}),_.on("disconnected",()=>V("")),_.on("reconnecting",()=>V("")),_.on("error",()=>{V("err"),r("Connection interrupted. We\u2019re trying to reconnect.","error",0)}),await _.connect(),await _.conversations.join(C),O=_.conversations.get(C),O.on("message",Me),t.apiUrl&&typeof O.fetchMessages=="function")try{let p=await O.fetchMessages({limit:30});((g=(h=p==null?void 0:p.messages)!=null?h:(c=p==null?void 0:p.data)==null?void 0:c.messages)!=null?g:[]).forEach(Me)}catch{}ke=!0,v()&&k()}catch(p){throw V("err"),K=null,r("We couldn\u2019t connect to support. Please check your connection and try again.","error",0),t.debug&&console.error("[caf] connect/provision failed",p),p}})(),K)}(!t.publicKey||Le())&&oe().catch(()=>{}),t.autoOpen&&ae();let Ue={open:ae,close:re,send:async s=>{await oe(),a.input.value=s,await fe()},destroy:()=>{try{_==null||_.disconnect()}catch{}i.remove(),I=null}};return I={open:ae,close:re,api:Ue},Ue}function ji(){I==null||I.open()}function Ii(){I==null||I.close()}function Li(){I==null||I.api.destroy()}export{Ii as close,Li as destroy,$i as init,ji as open};
258
+ <p class="caf-form-privacy">Your details are only used to support this conversation.</p>`,a.msgs.appendChild(s),a.msgs.scrollTop=0;let c=w=>s.querySelector(`[data-caf="${w}"]`),h=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,g=async w=>{let x=c("f-name").value.trim(),m=c("f-email").value.trim(),S=c("f-email");if(c("f-err").textContent="",S.setAttribute("aria-invalid","false"),w){if(t.requireEmail&&!m){c("f-err").textContent="Email is required.",S.setAttribute("aria-invalid","true"),S.focus();return}if(m&&!h.test(m)){c("f-err").textContent="Enter a valid email.",S.setAttribute("aria-invalid","true"),S.focus();return}let L=c("f-go");L.disabled=!0,L.querySelector("span").textContent="Starting\u2026";try{await ot(x,m)}catch(T){c("f-err").textContent="We couldn\u2019t start the conversation. Check your connection and try again.",L.disabled=!1,L.querySelector("span").textContent="Start conversation",t.debug&&console.error("[caf] saveContact failed",T);return}}s.remove(),a.panel.classList.remove("caf-prechat"),q=!0,b(),ne(!0),Ae(),setTimeout(()=>a.input.focus(),30)};s.onsubmit=w=>{w.preventDefault(),g(!0)};let p=c("f-skip");p&&(p.onclick=()=>g(!1)),setTimeout(()=>c("f-name").focus(),40)}function ae(){if(te=!0,a.panel.classList.add("open"),a.panel.setAttribute("aria-hidden","false"),a.launcher.setAttribute("aria-expanded","true"),a.launcher.setAttribute("aria-label","Close support chat"),Te(0),oe().catch(()=>{}),!q&&!_e){ct();return}q&&(Ae(),setTimeout(()=>a.input.focus(),50))}function re(){te=!1,a.panel.classList.remove("open"),a.panel.setAttribute("aria-hidden","true"),a.launcher.setAttribute("aria-expanded","false"),a.launcher.setAttribute("aria-label","Open support chat"),a.launcher.focus()}a.launcher.onclick=()=>te?re():ae(),n("close").onclick=re;let O=null,se=null,J=null;function je(){J&&(URL.revokeObjectURL(J),J=null),se=null,a.pending.classList.remove("show"),a.pendingThumb.innerHTML="",a.pendingName.textContent=""}function lt(s){se=s,a.pendingName.textContent=s.name,s.type&&s.type.startsWith("image/")?(J=URL.createObjectURL(s),a.pendingThumb.innerHTML=`<img src="${J}" alt="" />`):a.pendingThumb.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>',a.pending.classList.add("show"),setTimeout(()=>a.input.focus(),30)}async function fe(){if(!q)return;let s=a.input.value.trim();if(se){let c=se;je(),a.input.value="",a.input.style.height="auto",ht(c,s);return}if(!(!s||!O))try{a.send.disabled=!0,await Promise.resolve(O.sendMessage(s)),a.input.value="",a.input.style.height="auto"}catch(c){r("Your message wasn\u2019t sent. Please try again."),t.debug&&console.error("[caf] send failed",c)}finally{a.send.disabled=!1}}function Ie(s,c){a.upload.classList.add("show"),a.uploadBar.style.width=c+"%",a.uploadLabel.textContent=`Sending ${s}\u2026 ${c}%`}function dt(){a.upload.classList.remove("show")}async function ht(s,c){if(!(!q||!O)){ne(!1),Ie(s.name,0);try{await O.sendMedia(s,{caption:c||void 0,onProgress:h=>Ie(s.name,h)})}catch(h){t.debug&&console.error("[caf] sendMedia failed",h),ie("caf-note","Couldn\u2019t send that file. Please try again.")}finally{dt(),ne(q)}}}a.attach.onclick=()=>a.file.click(),!t.tickets||!t.publicKey?a.ticket.style.display="none":a.ticket.onclick=st,a.human.onclick=async()=>{if(!(!q||!O||a.human.disabled))try{a.human.disabled=!0,await Promise.resolve(O.sendMessage("I'd like to talk to a human agent.")),a.human.disabled=!0,a.human.textContent="Human requested",r("A human support agent has been requested.","success")}catch(s){a.human.disabled=!1,r("We couldn\u2019t request a human agent. Please try again."),t.debug&&console.error("[caf] human handoff request failed",s)}},a.file.addEventListener("change",()=>{let s=a.file.files&&a.file.files[0];a.file.value="",s&&lt(s)}),a.pendingRemove.onclick=()=>je(),a.send.onclick=fe,ne(q),a.input.addEventListener("input",()=>{a.input.style.height="auto",a.input.style.height=Math.min(a.input.scrollHeight,96)+"px"}),a.input.addEventListener("keydown",s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),fe())});let ue=t.publicKey?"caf_session_"+t.publicKey.slice(-10):"",pt=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";function Le(){if(!ue)return null;try{let s=JSON.parse(localStorage.getItem(ue)||"null");if(s&&s.token&&s.conversationId&&s.exp>Date.now())return s}catch{}return null}async function ft(){let s=t.apiUrl.replace(/\/$/,""),c=ue,h=pt,g=Le();if(g)return f=!!g.calls_enabled,{token:g.token,conversationId:g.conversationId};let p=null;try{p=localStorage.getItem(h)}catch{}if(!p){p="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(h,p)}catch{}}let w=await fetch(s+"/sdk/anonymous-session",{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":t.publicKey},body:JSON.stringify({visitor_id:p})});if(!w.ok)throw new Error("anonymous-session HTTP "+w.status);let x=await w.json(),m=x.data||x;f=!!m.calls_enabled;let S=Date.now()+Math.max(0,(m.expires_in||3600)*1e3-6e4);try{localStorage.setItem(c,JSON.stringify({token:m.token,conversationId:m.conversation_id,exp:S,calls_enabled:f}))}catch{}return{token:m.token,conversationId:m.conversation_id}}let K=null;function oe(){return K||(K=(async()=>{var s,c,h,g;try{if(V(""),t.publicKey){let p=await ft();u=p.token,C=p.conversationId,F=Ye(u)}if(_=new Qe({wsUrl:t.wsUrl,token:u,apiUrl:t.apiUrl,appId:u?(s=Xe(u))==null?void 0:s.app_id:void 0,autoReconnect:!0,debug:t.debug}),_.on("connected",()=>{V("on"),l()}),_.on("disconnected",()=>V("")),_.on("reconnecting",()=>V("")),_.on("error",()=>{V("err"),r("Connection interrupted. We\u2019re trying to reconnect.","error",0)}),await _.connect(),await _.conversations.join(C),O=_.conversations.get(C),O.on("message",Me),t.apiUrl&&typeof O.fetchMessages=="function")try{let p=await O.fetchMessages({limit:30});((g=(h=p==null?void 0:p.messages)!=null?h:(c=p==null?void 0:p.data)==null?void 0:c.messages)!=null?g:[]).forEach(Me)}catch{}ke=!0,v()&&k()}catch(p){throw V("err"),K=null,r("We couldn\u2019t connect to support. Please check your connection and try again.","error",0),t.debug&&console.error("[caf] connect/provision failed",p),p}})(),K)}(!t.publicKey||Le())&&oe().catch(()=>{}),t.autoOpen&&ae();let Ue={open:ae,close:re,send:async s=>{await oe(),a.input.value=s,await fe()},destroy:()=>{try{_==null||_.disconnect()}catch{}i.remove(),I=null}};return I={open:ae,close:re,api:Ue},Ue}function ji(){I==null||I.open()}function Ii(){I==null||I.close()}function Li(){I==null||I.api.destroy()}export{Ii as close,Li as destroy,$i as init,ji as open};
@@ -132,7 +132,9 @@ var VocantlyWidget=(()=>{var gt=Object.create;var ce=Object.defineProperty;var m
132
132
  .caf-root .caf-send:disabled{opacity:.38;cursor:not-allowed;transform:none;box-shadow:none;}
133
133
  .caf-foot{text-align:center;font-size:10.5px;line-height:1.3;color:#98a2b3;padding:7px 10px 9px;background:#fff;letter-spacing:.01em;}
134
134
 
135
- .caf-panel.caf-prechat .caf-msgs{justify-content:center;padding:22px;background:linear-gradient(160deg,#f7f9ff 0%,#f5f7fb 58%,#fff 100%);}
135
+ .caf-panel.caf-prechat .caf-msgs{justify-content:flex-start;padding:22px;background:linear-gradient(160deg,#f7f9ff 0%,#f5f7fb 58%,#fff 100%);}
136
+ .caf-panel.caf-prechat .caf-msgs>:not(.caf-form){display:none;}
137
+ .caf-panel.caf-prechat .caf-form{flex:none;}
136
138
  .caf-panel.caf-prechat .caf-composer{display:none;}
137
139
  .caf-form{width:100%;background:#fff;border:1px solid #e1e6ee;border-radius:20px;padding:22px;margin:0;display:flex;flex-direction:column;
138
140
  box-shadow:0 14px 36px rgba(24,34,55,.08);}
@@ -228,7 +230,7 @@ var VocantlyWidget=(()=>{var gt=Object.create;var ce=Object.defineProperty;var m
228
230
  <button class="caf-launcher" data-caf="launcher" aria-label="Open support chat" aria-controls="caf-support-panel" aria-expanded="false">
229
231
  <span data-caf="launcher-icon">${e.launcher==="\u{1F4AC}"?'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>':y(e.launcher)}</span>
230
232
  <span class="caf-badge" data-caf="badge" style="display:none">0</span>
231
- </button>`,document.body.appendChild(t),{root:t,$:n=>t.querySelector(`[data-caf="${n}"]`)}}function Zt(e){if(I)return I.open(),I.api;let t={...Kt,...e||{}};if(!t.wsUrl)throw new Error("VocantlyWidget.init requires wsUrl");if(!t.publicKey&&!(t.token&&t.conversationId))throw new Error("VocantlyWidget.init requires either { publicKey } (anonymous) or { token, conversationId }");if(t.publicKey&&!t.apiUrl)throw new Error("VocantlyWidget.init with publicKey also requires apiUrl");Gt(t.primaryColor,t.position);let{root:i,$:n}=Xt(t),a={panel:i.querySelector(".caf-panel"),msgs:n("msgs"),input:n("input"),send:n("send"),dot:n("dot"),badge:n("badge"),launcher:n("launcher"),call:n("call"),file:n("file"),attach:n("attach"),ticket:n("ticket"),upload:n("upload"),uploadBar:n("upload-bar"),uploadLabel:n("upload-label"),pending:n("pending"),pendingThumb:n("pending-thumb"),pendingName:n("pending-name"),pendingRemove:n("pending-remove"),human:n("human"),feedback:n("feedback")},o=null;function r(s,c="error",h=5e3){a.feedback&&(o&&clearTimeout(o),a.feedback.textContent=s,a.feedback.className=`caf-feedback show${c==="success"?" success":""}`,a.feedback.setAttribute("role",c==="error"?"alert":"status"),h>0&&(o=setTimeout(()=>{a.feedback.className="caf-feedback",a.feedback.textContent=""},h)))}function l(){o&&clearTimeout(o),o=null,a.feedback.className="caf-feedback",a.feedback.textContent=""}let d=null,f=!1,v=()=>t.calls===!0||f;function b(){d&&q&&a.call&&(a.call.style.display="flex")}function R(){return new Promise((s,c)=>{if(window.VocantlyWidgetCall)return s();let h=document.createElement("script");h.src=t.callBundleUrl,h.async=!0,h.onload=()=>s(),h.onerror=()=>c(new Error("call bundle load failed")),document.head.appendChild(h)})}async function k(){if(!(d||!O))try{if(await R(),!window.VocantlyWidgetCall)return;let s=document.createElement("div");document.body.appendChild(s),d=window.VocantlyWidgetCall.mount(s,O,{logoText:"CA",sessionTitle:t.title||"Call",sessionSubtitle:t.subtitle||"Secured via Vocantly",primaryColor:t.primaryColor,self:{name:"You",role:"Visitor"},peer:{name:t.title||"Support",role:"Agent"},voiceOnly:!0,simple:!0}),a.call&&(a.call.onclick=()=>d.startCall("voice")),b()}catch(s){r("Calling is unavailable right now. You can keep chatting with support."),t.debug&&console.error("[caf] call setup failed",s)}}let u=t.token||"",C=t.conversationId||"",N=u?Ge(u):null,_=null,Se=new Set,Ce=!1,te=!1,_e=0,Te=!1,q=!t.collectContact,Me=!1,V=s=>{a.dot.className="caf-dot"+(s?" "+s:"")},W=()=>{a.msgs.scrollTop=a.msgs.scrollHeight},Ee=s=>{_e=s,a.badge.textContent=String(s),a.badge.style.display=s>0?"flex":"none"};function ie(s,c){let h=document.createElement("div");h.className="caf-m "+s,h.innerHTML=c,a.msgs.appendChild(h),W()}function Re(s){var S,L,T,P,U,$;if(s.optimistic)return;let c=(S=s.id)!=null?S:s.message_id,h=(T=(L=s.senderId)!=null?L:s.sender_id)!=null?T:"",g=(U=(P=s.content)!=null?P:s.text)!=null?U:"",p=($=s.messageType)!=null?$:s.message_type,w=s.attachments,x=c||`${h}:${g}`;if(Se.has(x))return;if(Se.add(x),p==="system"){ie("caf-note",ke(g)),t.csat&&it();return}let m=N&&h===N;(p==="image"||p==="video"||p==="file")&&w&&w.length?tt(m,g,p,w[0]):ie(m?"caf-self":"caf-other",ke(g)),!m&&Ce&&Yt(),!m&&!te&&Ee(_e+1)}function et(s,c){return`<div class="caf-media-skeleton" style="${s!=="file"&&c.width&&c.height?`aspect-ratio:${c.width}/${c.height};`:"aspect-ratio:4/3;"}"></div>`}function Ae(s,c){let h=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
233
+ </button>`,document.body.appendChild(t),{root:t,$:n=>t.querySelector(`[data-caf="${n}"]`)}}function Zt(e){if(I)return I.open(),I.api;let t={...Kt,...e||{}};if(!t.wsUrl)throw new Error("VocantlyWidget.init requires wsUrl");if(!t.publicKey&&!(t.token&&t.conversationId))throw new Error("VocantlyWidget.init requires either { publicKey } (anonymous) or { token, conversationId }");if(t.publicKey&&!t.apiUrl)throw new Error("VocantlyWidget.init with publicKey also requires apiUrl");Gt(t.primaryColor,t.position);let{root:i,$:n}=Xt(t),a={panel:i.querySelector(".caf-panel"),msgs:n("msgs"),input:n("input"),send:n("send"),dot:n("dot"),badge:n("badge"),launcher:n("launcher"),call:n("call"),file:n("file"),attach:n("attach"),ticket:n("ticket"),upload:n("upload"),uploadBar:n("upload-bar"),uploadLabel:n("upload-label"),pending:n("pending"),pendingThumb:n("pending-thumb"),pendingName:n("pending-name"),pendingRemove:n("pending-remove"),human:n("human"),feedback:n("feedback")},o=null;function r(s,c="error",h=5e3){a.feedback&&(o&&clearTimeout(o),a.feedback.textContent=s,a.feedback.className=`caf-feedback show${c==="success"?" success":""}`,a.feedback.setAttribute("role",c==="error"?"alert":"status"),h>0&&(o=setTimeout(()=>{a.feedback.className="caf-feedback",a.feedback.textContent=""},h)))}function l(){o&&clearTimeout(o),o=null,a.feedback.className="caf-feedback",a.feedback.textContent=""}let d=null,f=!1,v=()=>t.calls===!0||f;function b(){d&&q&&a.call&&(a.call.style.display="flex")}function R(){return new Promise((s,c)=>{if(window.VocantlyWidgetCall)return s();let h=document.createElement("script");h.src=t.callBundleUrl,h.async=!0,h.onload=()=>s(),h.onerror=()=>c(new Error("call bundle load failed")),document.head.appendChild(h)})}async function k(){if(!(d||!O))try{if(await R(),!window.VocantlyWidgetCall)return;let s=document.createElement("div");document.body.appendChild(s),d=window.VocantlyWidgetCall.mount(s,O,{logoText:"CA",sessionTitle:t.title||"Call",sessionSubtitle:t.subtitle||"Secured via Vocantly",primaryColor:t.primaryColor,self:{name:"You",role:"Visitor"},peer:{name:t.title||"Support",role:"Agent"},voiceOnly:!0,simple:!0}),a.call&&(a.call.onclick=()=>d.startCall("voice")),b()}catch(s){r("Calling is unavailable right now. You can keep chatting with support."),t.debug&&console.error("[caf] call setup failed",s)}}let u=t.token||"",C=t.conversationId||"",N=u?Ge(u):null,_=null,Se=new Set,Ce=!1,te=!1,_e=0,Te=!1,q=!t.collectContact,Me=!1,V=s=>{a.dot.className="caf-dot"+(s?" "+s:"")},W=()=>{if(a.panel.classList.contains("caf-prechat")){a.msgs.scrollTop=0;return}a.msgs.scrollTop=a.msgs.scrollHeight},Ee=s=>{_e=s,a.badge.textContent=String(s),a.badge.style.display=s>0?"flex":"none"};function ie(s,c){let h=document.createElement("div");h.className="caf-m "+s,h.innerHTML=c,a.msgs.appendChild(h),W()}function Re(s){var S,L,T,P,U,$;if(s.optimistic)return;let c=(S=s.id)!=null?S:s.message_id,h=(T=(L=s.senderId)!=null?L:s.sender_id)!=null?T:"",g=(U=(P=s.content)!=null?P:s.text)!=null?U:"",p=($=s.messageType)!=null?$:s.message_type,w=s.attachments,x=c||`${h}:${g}`;if(Se.has(x))return;if(Se.add(x),p==="system"){ie("caf-note",ke(g)),t.csat&&it();return}let m=N&&h===N;(p==="image"||p==="video"||p==="file")&&w&&w.length?tt(m,g,p,w[0]):ie(m?"caf-self":"caf-other",ke(g)),!m&&Ce&&Yt(),!m&&!te&&Ee(_e+1)}function et(s,c){return`<div class="caf-media-skeleton" style="${s!=="file"&&c.width&&c.height?`aspect-ratio:${c.width}/${c.height};`:"aspect-ratio:4/3;"}"></div>`}function Ae(s,c){let h=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
232
234
  <span class="caf-file-meta"><span class="caf-file-name">${y(s.file_name)}</span><span class="caf-file-size">${y(Qt(s.size_bytes))}</span></span>`;return c?`<a class="caf-file-chip" href="${c}" target="_blank" rel="noopener noreferrer" download="${y(s.file_name)}">${h}</a>`:`<div class="caf-file-chip">${h}</div>`}function pe(s,c){s&&(s.innerHTML=`<div class="caf-media-error">Couldn't load ${y(c)}</div>`)}function tt(s,c,h,g){let p=document.createElement("div");if(p.className="caf-m caf-media "+(s?"caf-self":"caf-other"),p.innerHTML=`<div class="caf-media-body" data-media>${h==="file"?Ae(g):et(h,g)}</div>`,c){let w=document.createElement("div");w.className="caf-media-caption",w.innerHTML=ke(c),p.appendChild(w)}a.msgs.appendChild(p),W(),_&&_.conversations.getAttachmentDownloadUrl(g.bucket,g.key).then(w=>{let x=p.querySelector("[data-media]");if(x){if(h==="image"){let m=document.createElement("a");m.href=w.url,m.target="_blank",m.rel="noopener noreferrer";let S=document.createElement("img");S.alt=g.file_name,S.loading="lazy",S.onerror=()=>pe(x,g.file_name),S.src=w.url,m.appendChild(S),x.innerHTML="",x.appendChild(m)}else if(h==="video"){let m=document.createElement("video");m.controls=!0,m.preload="metadata",m.onerror=()=>pe(x,g.file_name),m.src=w.url,x.innerHTML="",x.appendChild(m)}else x.innerHTML=Ae(g,w.url);W()}}).catch(w=>{t.debug&&console.error("[caf] attachment load failed",w),pe(p.querySelector("[data-media]"),g.file_name)})}let $e=!1;function it(){if($e||!t.apiUrl||!C)return;$e=!0;let s=document.createElement("div");s.className="caf-csat",s.innerHTML=`<div>${y(t.csatPrompt)}</div><div class="caf-csat-row"></div>`;let c=s.querySelector(".caf-csat-row");[["1","\u{1F61E}"],["2","\u{1F641}"],["3","\u{1F610}"],["4","\u{1F642}"],["5","\u{1F600}"]].forEach(([h,g])=>{let p=document.createElement("button");p.className="caf-csat-b",p.type="button",p.textContent=g,p.setAttribute("aria-label",h+" out of 5"),p.onclick=()=>nt(Number(h),s),c.appendChild(p)}),a.msgs.appendChild(s),W()}async function nt(s,c){c.innerHTML=`<div>${y(t.csatThanks)}</div>`,W();try{await fetch(t.apiUrl.replace(/\/$/,"")+"/sdk/conversations/"+C+"/rating",{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer "+u},body:JSON.stringify({rating:s})})}catch(h){t.debug&&console.error("[caf] csat failed",h)}}function ne(s){a.input.disabled=!s,a.send.disabled=!s,a.attach.disabled=!s,a.human.disabled=!s,a.input.placeholder=s?t.placeholder:"\u2026"}function je(){!Te&&t.greeting&&(ie("caf-sys",y(t.greeting)),Te=!0)}function fe(s,c){return!s||typeof s!="object"?"":s[c]||s.en||Object.values(s)[0]||""}function at(){let s=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";if(!s)return;let c=null;try{c=localStorage.getItem(s)}catch{}if(!c){c="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(s,c)}catch{}}return c}function rt(s,c){if(s.visibility==="agent_only"||s.type==="hidden")return"";let h=y(fe(s.label,c)||s.key),g=y(fe(s.placeholder,c)),p=s.required?' required aria-required="true"':"",w=(s.options||[]).filter(m=>m.is_active).map(m=>`<option value="${y(m.value)}">${y(fe(m.label,c)||m.value)}</option>`).join(""),x;if(s.type==="long_text")x=`<textarea class="caf-fi" name="${y(s.key)}" placeholder="${g}"${p}></textarea>`;else if(s.type==="select")x=`<select class="caf-fi" name="${y(s.key)}"${p}><option value="">Select\u2026</option>${w}</select>`;else{if(s.type==="checkbox"||s.type==="consent")return`<label class="caf-check-field"><input name="${y(s.key)}" type="checkbox"${p} /><span>${h}${s.required?' <span class="caf-required">*</span>':""}</span></label><span class="caf-field-error">Please confirm this field.</span>`;{let m=s.type==="email"?"email":s.type==="phone"?"tel":s.type==="number"||s.type==="currency"?"number":s.type==="date"?"date":s.type==="url"?"url":"text";x=`<input class="caf-fi" name="${y(s.key)}" type="${m}" placeholder="${g}"${p} />`}}return`<label class="caf-fl">${h}${s.required?' <span class="caf-required">*</span>':' <span class="caf-optional">Optional</span>'}${x}<span class="caf-field-error">Please complete this field.</span></label>`}function Ie(){return`<div class="caf-ticket-intro">
233
235
  <div class="caf-form-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v7a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-7a2 2 0 0 0 0-4V5Z"/><path d="M13 5v2M13 11v2M13 17v2"/></svg></div>
234
236
  <div class="caf-ticket-intro-copy"><div class="caf-form-t">${y(t.ticketLabel)}</div><p class="caf-form-d">Tell us what happened. We\u2019ll create a reference so you can track every update.</p></div>
@@ -253,4 +255,4 @@ var VocantlyWidget=(()=>{var gt=Object.create;var ce=Object.defineProperty;var m
253
255
  <div class="caf-ferr" id="caf-contact-error" data-caf="f-err" role="alert" aria-live="polite"></div>
254
256
  <button class="caf-fbtn" data-caf="f-go" type="submit"><span>Start conversation</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg></button>
255
257
  ${t.requireEmail?"":'<button class="caf-fskip" data-caf="f-skip" type="button">Continue without details</button>'}
256
- <p class="caf-form-privacy">Your details are only used to support this conversation.</p>`,a.msgs.appendChild(s);let c=w=>s.querySelector(`[data-caf="${w}"]`),h=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,g=async w=>{let x=c("f-name").value.trim(),m=c("f-email").value.trim(),S=c("f-email");if(c("f-err").textContent="",S.setAttribute("aria-invalid","false"),w){if(t.requireEmail&&!m){c("f-err").textContent="Email is required.",S.setAttribute("aria-invalid","true"),S.focus();return}if(m&&!h.test(m)){c("f-err").textContent="Enter a valid email.",S.setAttribute("aria-invalid","true"),S.focus();return}let L=c("f-go");L.disabled=!0,L.querySelector("span").textContent="Starting\u2026";try{await ct(x,m)}catch(T){c("f-err").textContent="We couldn\u2019t start the conversation. Check your connection and try again.",L.disabled=!1,L.querySelector("span").textContent="Start conversation",t.debug&&console.error("[caf] saveContact failed",T);return}}s.remove(),a.panel.classList.remove("caf-prechat"),q=!0,b(),ne(!0),je(),setTimeout(()=>a.input.focus(),30)};s.onsubmit=w=>{w.preventDefault(),g(!0)};let p=c("f-skip");p&&(p.onclick=()=>g(!1)),setTimeout(()=>c("f-name").focus(),40)}function ae(){if(te=!0,a.panel.classList.add("open"),a.panel.setAttribute("aria-hidden","false"),a.launcher.setAttribute("aria-expanded","true"),a.launcher.setAttribute("aria-label","Close support chat"),Ee(0),oe().catch(()=>{}),!q&&!Me){lt();return}q&&(je(),setTimeout(()=>a.input.focus(),50))}function re(){te=!1,a.panel.classList.remove("open"),a.panel.setAttribute("aria-hidden","true"),a.launcher.setAttribute("aria-expanded","false"),a.launcher.setAttribute("aria-label","Open support chat"),a.launcher.focus()}a.launcher.onclick=()=>te?re():ae(),n("close").onclick=re;let O=null,se=null,J=null;function Le(){J&&(URL.revokeObjectURL(J),J=null),se=null,a.pending.classList.remove("show"),a.pendingThumb.innerHTML="",a.pendingName.textContent=""}function dt(s){se=s,a.pendingName.textContent=s.name,s.type&&s.type.startsWith("image/")?(J=URL.createObjectURL(s),a.pendingThumb.innerHTML=`<img src="${J}" alt="" />`):a.pendingThumb.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>',a.pending.classList.add("show"),setTimeout(()=>a.input.focus(),30)}async function ue(){if(!q)return;let s=a.input.value.trim();if(se){let c=se;Le(),a.input.value="",a.input.style.height="auto",pt(c,s);return}if(!(!s||!O))try{a.send.disabled=!0,await Promise.resolve(O.sendMessage(s)),a.input.value="",a.input.style.height="auto"}catch(c){r("Your message wasn\u2019t sent. Please try again."),t.debug&&console.error("[caf] send failed",c)}finally{a.send.disabled=!1}}function Ue(s,c){a.upload.classList.add("show"),a.uploadBar.style.width=c+"%",a.uploadLabel.textContent=`Sending ${s}\u2026 ${c}%`}function ht(){a.upload.classList.remove("show")}async function pt(s,c){if(!(!q||!O)){ne(!1),Ue(s.name,0);try{await O.sendMedia(s,{caption:c||void 0,onProgress:h=>Ue(s.name,h)})}catch(h){t.debug&&console.error("[caf] sendMedia failed",h),ie("caf-note","Couldn\u2019t send that file. Please try again.")}finally{ht(),ne(q)}}}a.attach.onclick=()=>a.file.click(),!t.tickets||!t.publicKey?a.ticket.style.display="none":a.ticket.onclick=ot,a.human.onclick=async()=>{if(!(!q||!O||a.human.disabled))try{a.human.disabled=!0,await Promise.resolve(O.sendMessage("I'd like to talk to a human agent.")),a.human.disabled=!0,a.human.textContent="Human requested",r("A human support agent has been requested.","success")}catch(s){a.human.disabled=!1,r("We couldn\u2019t request a human agent. Please try again."),t.debug&&console.error("[caf] human handoff request failed",s)}},a.file.addEventListener("change",()=>{let s=a.file.files&&a.file.files[0];a.file.value="",s&&dt(s)}),a.pendingRemove.onclick=()=>Le(),a.send.onclick=ue,ne(q),a.input.addEventListener("input",()=>{a.input.style.height="auto",a.input.style.height=Math.min(a.input.scrollHeight,96)+"px"}),a.input.addEventListener("keydown",s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),ue())});let ge=t.publicKey?"caf_session_"+t.publicKey.slice(-10):"",ft=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";function Oe(){if(!ge)return null;try{let s=JSON.parse(localStorage.getItem(ge)||"null");if(s&&s.token&&s.conversationId&&s.exp>Date.now())return s}catch{}return null}async function ut(){let s=t.apiUrl.replace(/\/$/,""),c=ge,h=ft,g=Oe();if(g)return f=!!g.calls_enabled,{token:g.token,conversationId:g.conversationId};let p=null;try{p=localStorage.getItem(h)}catch{}if(!p){p="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(h,p)}catch{}}let w=await fetch(s+"/sdk/anonymous-session",{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":t.publicKey},body:JSON.stringify({visitor_id:p})});if(!w.ok)throw new Error("anonymous-session HTTP "+w.status);let x=await w.json(),m=x.data||x;f=!!m.calls_enabled;let S=Date.now()+Math.max(0,(m.expires_in||3600)*1e3-6e4);try{localStorage.setItem(c,JSON.stringify({token:m.token,conversationId:m.conversation_id,exp:S,calls_enabled:f}))}catch{}return{token:m.token,conversationId:m.conversation_id}}let K=null;function oe(){return K||(K=(async()=>{var s,c,h,g;try{if(V(""),t.publicKey){let p=await ut();u=p.token,C=p.conversationId,N=Ge(u)}if(_=new Ye({wsUrl:t.wsUrl,token:u,apiUrl:t.apiUrl,appId:u?(s=Ze(u))==null?void 0:s.app_id:void 0,autoReconnect:!0,debug:t.debug}),_.on("connected",()=>{V("on"),l()}),_.on("disconnected",()=>V("")),_.on("reconnecting",()=>V("")),_.on("error",()=>{V("err"),r("Connection interrupted. We\u2019re trying to reconnect.","error",0)}),await _.connect(),await _.conversations.join(C),O=_.conversations.get(C),O.on("message",Re),t.apiUrl&&typeof O.fetchMessages=="function")try{let p=await O.fetchMessages({limit:30});((g=(h=p==null?void 0:p.messages)!=null?h:(c=p==null?void 0:p.data)==null?void 0:c.messages)!=null?g:[]).forEach(Re)}catch{}Ce=!0,v()&&k()}catch(p){throw V("err"),K=null,r("We couldn\u2019t connect to support. Please check your connection and try again.","error",0),t.debug&&console.error("[caf] connect/provision failed",p),p}})(),K)}(!t.publicKey||Oe())&&oe().catch(()=>{}),t.autoOpen&&ae();let He={open:ae,close:re,send:async s=>{await oe(),a.input.value=s,await ue()},destroy:()=>{try{_==null||_.disconnect()}catch{}i.remove(),I=null}};return I={open:ae,close:re,api:He},He}function ei(){I==null||I.open()}function ti(){I==null||I.close()}function ii(){I==null||I.api.destroy()}return xt(ni);})();
258
+ <p class="caf-form-privacy">Your details are only used to support this conversation.</p>`,a.msgs.appendChild(s),a.msgs.scrollTop=0;let c=w=>s.querySelector(`[data-caf="${w}"]`),h=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,g=async w=>{let x=c("f-name").value.trim(),m=c("f-email").value.trim(),S=c("f-email");if(c("f-err").textContent="",S.setAttribute("aria-invalid","false"),w){if(t.requireEmail&&!m){c("f-err").textContent="Email is required.",S.setAttribute("aria-invalid","true"),S.focus();return}if(m&&!h.test(m)){c("f-err").textContent="Enter a valid email.",S.setAttribute("aria-invalid","true"),S.focus();return}let L=c("f-go");L.disabled=!0,L.querySelector("span").textContent="Starting\u2026";try{await ct(x,m)}catch(T){c("f-err").textContent="We couldn\u2019t start the conversation. Check your connection and try again.",L.disabled=!1,L.querySelector("span").textContent="Start conversation",t.debug&&console.error("[caf] saveContact failed",T);return}}s.remove(),a.panel.classList.remove("caf-prechat"),q=!0,b(),ne(!0),je(),setTimeout(()=>a.input.focus(),30)};s.onsubmit=w=>{w.preventDefault(),g(!0)};let p=c("f-skip");p&&(p.onclick=()=>g(!1)),setTimeout(()=>c("f-name").focus(),40)}function ae(){if(te=!0,a.panel.classList.add("open"),a.panel.setAttribute("aria-hidden","false"),a.launcher.setAttribute("aria-expanded","true"),a.launcher.setAttribute("aria-label","Close support chat"),Ee(0),oe().catch(()=>{}),!q&&!Me){lt();return}q&&(je(),setTimeout(()=>a.input.focus(),50))}function re(){te=!1,a.panel.classList.remove("open"),a.panel.setAttribute("aria-hidden","true"),a.launcher.setAttribute("aria-expanded","false"),a.launcher.setAttribute("aria-label","Open support chat"),a.launcher.focus()}a.launcher.onclick=()=>te?re():ae(),n("close").onclick=re;let O=null,se=null,J=null;function Le(){J&&(URL.revokeObjectURL(J),J=null),se=null,a.pending.classList.remove("show"),a.pendingThumb.innerHTML="",a.pendingName.textContent=""}function dt(s){se=s,a.pendingName.textContent=s.name,s.type&&s.type.startsWith("image/")?(J=URL.createObjectURL(s),a.pendingThumb.innerHTML=`<img src="${J}" alt="" />`):a.pendingThumb.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>',a.pending.classList.add("show"),setTimeout(()=>a.input.focus(),30)}async function ue(){if(!q)return;let s=a.input.value.trim();if(se){let c=se;Le(),a.input.value="",a.input.style.height="auto",pt(c,s);return}if(!(!s||!O))try{a.send.disabled=!0,await Promise.resolve(O.sendMessage(s)),a.input.value="",a.input.style.height="auto"}catch(c){r("Your message wasn\u2019t sent. Please try again."),t.debug&&console.error("[caf] send failed",c)}finally{a.send.disabled=!1}}function Ue(s,c){a.upload.classList.add("show"),a.uploadBar.style.width=c+"%",a.uploadLabel.textContent=`Sending ${s}\u2026 ${c}%`}function ht(){a.upload.classList.remove("show")}async function pt(s,c){if(!(!q||!O)){ne(!1),Ue(s.name,0);try{await O.sendMedia(s,{caption:c||void 0,onProgress:h=>Ue(s.name,h)})}catch(h){t.debug&&console.error("[caf] sendMedia failed",h),ie("caf-note","Couldn\u2019t send that file. Please try again.")}finally{ht(),ne(q)}}}a.attach.onclick=()=>a.file.click(),!t.tickets||!t.publicKey?a.ticket.style.display="none":a.ticket.onclick=ot,a.human.onclick=async()=>{if(!(!q||!O||a.human.disabled))try{a.human.disabled=!0,await Promise.resolve(O.sendMessage("I'd like to talk to a human agent.")),a.human.disabled=!0,a.human.textContent="Human requested",r("A human support agent has been requested.","success")}catch(s){a.human.disabled=!1,r("We couldn\u2019t request a human agent. Please try again."),t.debug&&console.error("[caf] human handoff request failed",s)}},a.file.addEventListener("change",()=>{let s=a.file.files&&a.file.files[0];a.file.value="",s&&dt(s)}),a.pendingRemove.onclick=()=>Le(),a.send.onclick=ue,ne(q),a.input.addEventListener("input",()=>{a.input.style.height="auto",a.input.style.height=Math.min(a.input.scrollHeight,96)+"px"}),a.input.addEventListener("keydown",s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),ue())});let ge=t.publicKey?"caf_session_"+t.publicKey.slice(-10):"",ft=t.publicKey?"caf_vid_"+t.publicKey.slice(-10):"";function Oe(){if(!ge)return null;try{let s=JSON.parse(localStorage.getItem(ge)||"null");if(s&&s.token&&s.conversationId&&s.exp>Date.now())return s}catch{}return null}async function ut(){let s=t.apiUrl.replace(/\/$/,""),c=ge,h=ft,g=Oe();if(g)return f=!!g.calls_enabled,{token:g.token,conversationId:g.conversationId};let p=null;try{p=localStorage.getItem(h)}catch{}if(!p){p="v_"+Math.random().toString(36).slice(2)+Date.now().toString(36);try{localStorage.setItem(h,p)}catch{}}let w=await fetch(s+"/sdk/anonymous-session",{method:"POST",headers:{"Content-Type":"application/json","X-Api-Key":t.publicKey},body:JSON.stringify({visitor_id:p})});if(!w.ok)throw new Error("anonymous-session HTTP "+w.status);let x=await w.json(),m=x.data||x;f=!!m.calls_enabled;let S=Date.now()+Math.max(0,(m.expires_in||3600)*1e3-6e4);try{localStorage.setItem(c,JSON.stringify({token:m.token,conversationId:m.conversation_id,exp:S,calls_enabled:f}))}catch{}return{token:m.token,conversationId:m.conversation_id}}let K=null;function oe(){return K||(K=(async()=>{var s,c,h,g;try{if(V(""),t.publicKey){let p=await ut();u=p.token,C=p.conversationId,N=Ge(u)}if(_=new Ye({wsUrl:t.wsUrl,token:u,apiUrl:t.apiUrl,appId:u?(s=Ze(u))==null?void 0:s.app_id:void 0,autoReconnect:!0,debug:t.debug}),_.on("connected",()=>{V("on"),l()}),_.on("disconnected",()=>V("")),_.on("reconnecting",()=>V("")),_.on("error",()=>{V("err"),r("Connection interrupted. We\u2019re trying to reconnect.","error",0)}),await _.connect(),await _.conversations.join(C),O=_.conversations.get(C),O.on("message",Re),t.apiUrl&&typeof O.fetchMessages=="function")try{let p=await O.fetchMessages({limit:30});((g=(h=p==null?void 0:p.messages)!=null?h:(c=p==null?void 0:p.data)==null?void 0:c.messages)!=null?g:[]).forEach(Re)}catch{}Ce=!0,v()&&k()}catch(p){throw V("err"),K=null,r("We couldn\u2019t connect to support. Please check your connection and try again.","error",0),t.debug&&console.error("[caf] connect/provision failed",p),p}})(),K)}(!t.publicKey||Oe())&&oe().catch(()=>{}),t.autoOpen&&ae();let He={open:ae,close:re,send:async s=>{await oe(),a.input.value=s,await ue()},destroy:()=>{try{_==null||_.disconnect()}catch{}i.remove(),I=null}};return I={open:ae,close:re,api:He},He}function ei(){I==null||I.open()}function ti(){I==null||I.close()}function ii(){I==null||I.api.destroy()}return xt(ni);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vocantly/widget",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Drop-in embeddable support chat widget for Vocantly, built on @vocantly/sdk.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",