@heedb/web-sdk 0.1.6 → 1.0.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.
Files changed (3) hide show
  1. package/dist/widget.js +10 -10
  2. package/package.json +1 -1
  3. package/widget.js +111 -96
package/dist/widget.js CHANGED
@@ -1,8 +1,8 @@
1
- /* Heedb Widget v0.1.6 — https://heedb.com */
2
- "use strict";(()=>{(function(){var W,U,K,J,V;let w=document.currentScript||document.querySelector("script[data-api-key]"),E=(W=w==null?void 0:w.getAttribute("data-api-key"))!=null?W:"",N=(U=w==null?void 0:w.src)!=null?U:"",I=(w==null?void 0:w.getAttribute("data-host"))||(N?new URL(N).origin:"");if(!E){console.warn("[Heedb] Missing data-api-key on <script> tag.");return}let p={},u=!1,X={primary:"#18181b",text:"#18181b",bg:"#ffffff"},G={primary:"#e4e4e7",text:"#e4e4e7",bg:"#1a1a1a"};function R(){return p.mode==="dark"?!0:p.mode==="light"?!1:p.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)").matches:!1}function Y(){return u?G:X}function S(e,t){let n=p[e];return n!=null?String(n):t}let L=!1,h="contact",A="",C=(K=localStorage.getItem("heedb_name"))!=null?K:"",b=(J=localStorage.getItem("heedb_email"))!=null?J:"",y=(V=localStorage.getItem("heedb_token"))!=null?V:"",v=null,H=null;async function Q(e,t){try{let n=await D("/api/threads/token",{api_key:E,email:e,userHash:t});if(n.ok){let l=await n.json();if(l.widgetToken){y=l.widgetToken,localStorage.setItem("heedb_token",l.widgetToken);return}}y="",localStorage.removeItem("heedb_token")}catch(n){y="",localStorage.removeItem("heedb_token")}}window.Heedb={version:"0.1.6",init(e={}){e.name&&(C=e.name,localStorage.setItem("heedb_name",e.name)),e.email&&(b=e.email,localStorage.setItem("heedb_email",e.email),e.userHash?Q(e.email,e.userHash).then(()=>{z(),L&&v&&k()}):(z(),L&&v&&k()))},reset(){C="",b="",y="",localStorage.removeItem("heedb_name"),localStorage.removeItem("heedb_email"),localStorage.removeItem("heedb_token"),h="contact",L=!1,v&&(v.style.display="none"),z()}};function D(e,t){return fetch(`${I}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}function Z(e){let t=new URL(`${I}/api/threads`);return t.searchParams.set("api_key",E),t.searchParams.set("email",e),y&&t.searchParams.set("token",y),fetch(t.toString()).then(n=>n.json())}function ee(e){let t=new URL(`${I}/api/threads/${e}`);return t.searchParams.set("api_key",E),t.searchParams.set("email",b),t.searchParams.set("token",y),fetch(t.toString()).then(n=>n.json())}function te(e,t){return D(`/api/threads/${e}/reply`,{api_key:E,email:b,token:y,message:t})}async function ne(){var e;try{let t=new URL(`${I}/api/widget-config`);t.searchParams.set("api_key",E);let n=await fetch(t.toString());if(n.ok)return(e=(await n.json()).config)!=null?e:{}}catch(t){}return{}}function O(){var f,x;let e=Y(),t=S(u?"darkPrimaryColor":"primaryColor",e.primary),n=S(u?"darkTextColor":"textColor",e.text),l=S(u?"darkBgColor":"bgColor",e.bg),o=(f=p.borderRadius)!=null?f:16,r=(x=p.buttonRadius)!=null?x:50,c=p.fontFamily||"system-ui, -apple-system, sans-serif",m=p.position==="bottom-left",d=r>=50?"50%":`${r}px`,s=Math.round(o*.5),i=p.triggerMode==="tag",g=p.triggerMode==="embedded"||i;return`
1
+ /* Heedb Widget v0.1.7 — https://heedb.com */
2
+ "use strict";(()=>{(function(){var W,U,K,J,V;let w=document.currentScript||document.querySelector("script[data-api-key]"),E=(W=w==null?void 0:w.getAttribute("data-api-key"))!=null?W:"",N=(U=w==null?void 0:w.src)!=null?U:"",I=(w==null?void 0:w.getAttribute("data-host"))||(N?new URL(N).origin:"");if(!E){console.warn("[Heedb] Missing data-api-key on <script> tag.");return}let c={},u=!1,X={primary:"#18181b",text:"#18181b",bg:"#ffffff"},G={primary:"#e4e4e7",text:"#e4e4e7",bg:"#1a1a1a"};function R(){return c.mode==="dark"?!0:c.mode==="light"?!1:c.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)").matches:!1}function Y(){return u?G:X}function $(e,t){let n=c[e];return n!=null?String(n):t}let C=!1,h="contact",A="",L=(K=localStorage.getItem("heedb_name"))!=null?K:"",b=(J=localStorage.getItem("heedb_email"))!=null?J:"",y=(V=localStorage.getItem("heedb_token"))!=null?V:"",v=null,H=null;async function Q(e,t){try{let n=await D("/api/threads/token",{api_key:E,email:e,userHash:t});if(n.ok){let l=await n.json();if(l.widgetToken){y=l.widgetToken,localStorage.setItem("heedb_token",l.widgetToken);return}}y="",localStorage.removeItem("heedb_token")}catch(n){y="",localStorage.removeItem("heedb_token")}}window.Heedb={version:"0.1.7",init(e={}){e.name&&(L=e.name,localStorage.setItem("heedb_name",e.name)),e.email&&(b=e.email,localStorage.setItem("heedb_email",e.email),e.userHash?Q(e.email,e.userHash).then(()=>{z(),C&&v&&k()}):(z(),C&&v&&k()))},reset(){L="",b="",y="",localStorage.removeItem("heedb_name"),localStorage.removeItem("heedb_email"),localStorage.removeItem("heedb_token"),h="contact",C=!1,v&&(v.style.display="none"),z()}};function D(e,t){return fetch(`${I}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}function Z(e){let t=new URL(`${I}/api/threads`);return t.searchParams.set("api_key",E),t.searchParams.set("email",e),y&&t.searchParams.set("token",y),fetch(t.toString()).then(n=>n.json())}function ee(e){let t=new URL(`${I}/api/threads/${e}`);return t.searchParams.set("api_key",E),t.searchParams.set("email",b),t.searchParams.set("token",y),fetch(t.toString()).then(n=>n.json())}function te(e,t){return D(`/api/threads/${e}/reply`,{api_key:E,email:b,token:y,message:t})}async function ne(){var e;try{let t=new URL(`${I}/api/widget-config`);t.searchParams.set("api_key",E);let n=await fetch(t.toString());if(n.ok)return(e=(await n.json()).config)!=null?e:{}}catch(t){}return{}}function O(){var f,x;let e=Y(),t=$(u?"darkPrimaryColor":"primaryColor",e.primary),n=$(u?"darkTextColor":"textColor",e.text),l=$(u?"darkBgColor":"bgColor",e.bg),o=(f=c.borderRadius)!=null?f:16,r=(x=c.buttonRadius)!=null?x:50,d=c.fontFamily||"system-ui, -apple-system, sans-serif",m=c.position==="bottom-left",p=r>=50?"50%":`${r}px`,s=Math.round(o*.5),i=c.triggerMode==="tag",g=c.triggerMode==="embedded"||i;return`
3
3
  .llp-btn {
4
4
  position: fixed; bottom: 24px; ${m?"left: 24px":"right: 24px"}; z-index: 999998;
5
- width: 52px; height: 52px; border-radius: ${d}; border: none;
5
+ width: 52px; height: 52px; border-radius: ${p}; border: none;
6
6
  background: ${t}; color: #fff; font-size: 22px; cursor: pointer;
7
7
  box-shadow: 0 4px 16px rgba(0,0,0,.25);
8
8
  display: ${g?"none":"flex"}; align-items: center; justify-content: center;
@@ -14,12 +14,12 @@
14
14
  .llp-btn-icon svg { width: 22px; height: 22px; fill: currentColor; }
15
15
  .llp-btn:has(.llp-btn-label) { width: auto; padding: 0 18px; gap: 4px; }
16
16
  .llp-tag {
17
- position: fixed; ${m?"left: 0":"right: 0"}; top: 50%; z-index: 999998;
18
- transform: ${m?"rotate(90deg) translateX(-50%)":"rotate(-90deg) translateX(50%)"};
19
- transform-origin: ${m?"left top":"right top"};
17
+ position: fixed !important; ${m?"left: 0 !important":"right: 0 !important"}; top: 50% !important; z-index: 999998 !important;
18
+ transform: ${m?"rotate(90deg) translateX(-50%)":"rotate(-90deg) translateX(50%)"} !important;
19
+ transform-origin: ${m?"left bottom":"right bottom"} !important;
20
20
  background: ${t}; color: #fff; border: none; cursor: pointer;
21
21
  padding: 8px 18px; font-size: 13px; font-weight: 600;
22
- font-family: ${c};
22
+ font-family: ${d};
23
23
  border-radius: ${Math.min(r,12)}px ${Math.min(r,12)}px 0 0;
24
24
  box-shadow: 0 2px 12px rgba(0,0,0,.2);
25
25
  display: flex; align-items: center; gap: 6px;
@@ -32,7 +32,7 @@
32
32
  width: 370px; max-height: 560px; border-radius: ${o}px;
33
33
  background: ${l}; box-shadow: 0 8px 32px rgba(0,0,0,.18);
34
34
  display: flex; flex-direction: column; overflow: hidden;
35
- font-family: ${c}; font-size: 14px; color: ${n};
35
+ font-family: ${d}; font-size: 14px; color: ${n};
36
36
  transition: opacity .15s, transform .15s;
37
37
  }
38
38
  .llp-header {
@@ -147,10 +147,10 @@
147
147
  }
148
148
  .llp-chat-send:hover { opacity: .85; }
149
149
  .llp-chat-send:disabled { opacity: .5; cursor: not-allowed; }
150
- `}function a(e,t={},n=[]){let l=document.createElement(e);for(let[o,r]of Object.entries(t))o==="class"?l.className=r:o==="style"?l.setAttribute("style",r):o.startsWith("on")&&typeof r=="function"?l.addEventListener(o.slice(2),r):l.setAttribute(o,String(r));for(let o of n)l.appendChild(typeof o=="string"?document.createTextNode(o):o);return l}function P(e,t,n=""){let l=document.createElement("input");return l.type=e,l.id=t,l.placeholder=n,l.className="llp-input",l}function ae(e,t=""){let n=document.createElement("textarea");return n.id=e,n.placeholder=t,n.className="llp-textarea",n}function oe(e,t){let n=document.createElement("select");n.id=e,n.className="llp-select";for(let l of t){let o=document.createElement("option");o.value=l.value,o.textContent=l.label,n.appendChild(o)}return n}function k(){if(!v)return;let e=v.querySelector(".llp-body");e.innerHTML="",h==="contact"?le(e):h==="privacy"?ie(e):h==="threads"?re(e):h==="thread-detail"&&ce(e),M&&(M.style.display=h==="thread-detail"?"none":"flex")}function le(e,t=""){let n=!!(C&&b),l=a("label",{class:"llp-label"},["Name"]),o=P("text","llp-name","Jane Smith");C&&(o.value=C);let r=a("label",{class:"llp-label"},["Email"]),c=P("email","llp-email","jane@example.com");(t||b)&&(c.value=t||b);let m=a("label",{class:"llp-label"},["Message"]),d=ae("llp-message","How can we help?"),s=a("div",{class:"llp-error",style:"display:none"}),i=a("button",{class:"llp-btn-submit"},["Send message"]);i.onclick=async()=>{let g=o.value.trim(),f=c.value.trim(),x=d.value.trim();if(s.style.display="none",!g||!f||!x){s.textContent="Please fill in all fields.",s.style.display="block";return}i.disabled=!0,i.textContent="Sending\u2026";try{let T=await D("/api/contact",{api_key:E,name:g,email:f,message:x});if(T.ok)b=f,localStorage.setItem("heedb_email",f),z(),q(e,"Message sent!","We'll get back to you soon. Check your inbox for a confirmation email.");else{let me=await T.json();s.textContent=me.error||"Something went wrong.",s.style.display="block",i.disabled=!1,i.textContent="Send message"}}catch(T){s.textContent="Network error. Please try again.",s.style.display="block",i.disabled=!1,i.textContent="Send message"}},n?e.append(m,d,s,i):e.append(l,o,r,c,m,d,s,i)}function ie(e){let t=!!(C&&b),n=a("label",{class:"llp-label"},["Name"]),l=P("text","llp-priv-name","Jane Smith");C&&(l.value=C);let o=a("label",{class:"llp-label"},["Email"]),r=P("email","llp-priv-email","jane@example.com");b&&(r.value=b);let c=a("label",{class:"llp-label"},["Request type"]),m=oe("llp-priv-type",[{value:"deletion",label:"Delete my data"},{value:"access",label:"Access my data"},{value:"portability",label:"Export my data"},{value:"correction",label:"Correct my data"},{value:"restriction",label:"Restrict processing"},{value:"objection",label:"Object to processing"},{value:"other",label:"Other"}]),d=a("div",{class:"llp-error",style:"display:none"}),s=a("button",{class:"llp-btn-submit"},["Submit request"]);s.onclick=async()=>{let i=l.value.trim(),g=r.value.trim(),f=m.value;if(d.style.display="none",!i||!g){d.textContent="Please fill in all fields.",d.style.display="block";return}s.disabled=!0,s.textContent="Submitting\u2026";try{let x=await D("/api/privacy-request",{api_key:E,name:i,email:g,request_type:f});if(x.ok)b=g,localStorage.setItem("heedb_email",g),z(),q(e,"Request submitted!","Your privacy request has been received. We'll respond within 30 days.");else{let T=await x.json();d.textContent=T.error||"Something went wrong.",d.style.display="block",s.disabled=!1,s.textContent="Submit request"}}catch(x){d.textContent="Network error. Please try again.",d.style.display="block",s.disabled=!1,s.textContent="Submit request"}},t?e.append(c,m,d,s):e.append(n,l,o,r,c,m,d,s)}async function re(e){var t;if(!y){e.innerHTML="";let n=a("p",{style:"color:#71717a;text-align:center;margin:8px 0;font-size:13px;line-height:1.5"},["Send a message below to view your message history."]),l=a("div",{class:"llp-new-msg"}),o=a("button",{},["+ Send a message"]);o.onclick=()=>{h="contact",$("contact"),k()},l.appendChild(o),e.append(n,l);return}e.innerHTML='<p style="color:#71717a;text-align:center">Loading\u2026</p>';try{let{threads:n}=await Z(b);if(e.innerHTML="",n.length===0){let r=a("p",{style:"color:#71717a;text-align:center;margin:8px 0"},["No open messages yet."]);e.appendChild(r)}else for(let r of n){let c=a("span",{class:`llp-badge llp-badge-${r.status}`},[r.status]),m=a("div",{class:"llp-thread-label"},[r.type==="privacy"?"Privacy request":"Message"," \u2022 "]);m.appendChild(c);let d=a("div",{class:"llp-thread-text"},[(t=r.preview)!=null?t:""]),s=new Date(r.createdAt).toLocaleDateString(),i=a("div",{class:"llp-thread-meta"},[s]),g=a("div",{class:"llp-thread-item"});g.append(m,d,i),g.onclick=()=>se(r.id),e.appendChild(g)}let l=a("div",{class:"llp-new-msg"}),o=a("button",{},["+ Send a new message"]);o.onclick=()=>{h="contact",$("contact"),k()},l.appendChild(o),e.appendChild(l)}catch(n){e.innerHTML='<p style="color:#ef4444;text-align:center">Failed to load messages.</p>'}}function se(e){A=e,h="thread-detail",k()}async function ce(e){e.innerHTML='<p style="color:#71717a;text-align:center">Loading\u2026</p>';let t=a("button",{class:"llp-chat-back"},["\u2190 Back to messages"]);t.onclick=()=>{h="threads",$("threads"),k()};try{let l=(await ee(A)).messages||[];e.innerHTML="",e.style.padding="12px",e.appendChild(t);let o=a("div",{class:"llp-chat-messages"});for(let i of l){let g=i.direction==="inbound",f=a("div",{style:`display:flex;flex-direction:column;${g?"align-items:flex-start":"align-items:flex-end"}`}),x=a("div",{class:`llp-chat-bubble ${g?"llp-chat-inbound":"llp-chat-outbound"}`},[de(i.body)]),T=a("div",{class:`llp-chat-time ${g?"":"llp-chat-time-right"}`},[pe(i.createdAt)]);f.append(x,T),o.appendChild(f)}e.appendChild(o),requestAnimationFrame(()=>{o.scrollTop=o.scrollHeight});let r=a("div",{class:"llp-chat-reply"}),c=document.createElement("textarea");c.className="llp-chat-reply-input",c.placeholder="Type a reply\u2026",c.rows=1,c.addEventListener("input",()=>{c.style.height="auto",c.style.height=Math.min(c.scrollHeight,80)+"px"});let m=a("button",{class:"llp-chat-send"},["Send"]),d=a("div",{class:"llp-error",style:"display:none;margin-top:4px"});async function s(){let i=c.value.trim();if(i){m.disabled=!0,m.textContent="\u2026",d.style.display="none";try{let g=await te(A,i);if(g.ok){let f=a("div",{style:"display:flex;flex-direction:column;align-items:flex-start"}),x=a("div",{class:"llp-chat-bubble llp-chat-inbound"},[i]),T=a("div",{class:"llp-chat-time"},["Just now"]);f.append(x,T),o.appendChild(f),o.scrollTop=o.scrollHeight,c.value="",c.style.height="auto"}else{let f=await g.json();d.textContent=f.error||"Failed to send.",d.style.display="block"}}catch(g){d.textContent="Network error. Please try again.",d.style.display="block"}m.disabled=!1,m.textContent="Send"}}m.onclick=s,c.addEventListener("keydown",i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),s())}),r.append(c,m),e.append(r,d),requestAnimationFrame(()=>c.focus())}catch(n){e.innerHTML="",e.appendChild(t),e.appendChild(a("p",{style:"color:#ef4444;text-align:center"},["Failed to load conversation."]))}}function de(e){let t=e.split(`
150
+ `}function a(e,t={},n=[]){let l=document.createElement(e);for(let[o,r]of Object.entries(t))o==="class"?l.className=r:o==="style"?l.setAttribute("style",r):o.startsWith("on")&&typeof r=="function"?l.addEventListener(o.slice(2),r):l.setAttribute(o,String(r));for(let o of n)l.appendChild(typeof o=="string"?document.createTextNode(o):o);return l}function P(e,t,n=""){let l=document.createElement("input");return l.type=e,l.id=t,l.placeholder=n,l.className="llp-input",l}function ae(e,t=""){let n=document.createElement("textarea");return n.id=e,n.placeholder=t,n.className="llp-textarea",n}function oe(e,t){let n=document.createElement("select");n.id=e,n.className="llp-select";for(let l of t){let o=document.createElement("option");o.value=l.value,o.textContent=l.label,n.appendChild(o)}return n}function k(){if(!v)return;let e=v.querySelector(".llp-body");e.innerHTML="",h==="contact"?le(e):h==="privacy"?ie(e):h==="threads"?re(e):h==="thread-detail"&&ce(e),M&&(M.style.display=h==="thread-detail"?"none":"flex")}function le(e,t=""){let n=!!(L&&b),l=a("label",{class:"llp-label"},["Name"]),o=P("text","llp-name","Jane Smith");L&&(o.value=L);let r=a("label",{class:"llp-label"},["Email"]),d=P("email","llp-email","jane@example.com");(t||b)&&(d.value=t||b);let m=a("label",{class:"llp-label"},["Message"]),p=ae("llp-message","How can we help?"),s=a("div",{class:"llp-error",style:"display:none"}),i=a("button",{class:"llp-btn-submit"},["Send message"]);i.onclick=async()=>{let g=o.value.trim(),f=d.value.trim(),x=p.value.trim();if(s.style.display="none",!g||!f||!x){s.textContent="Please fill in all fields.",s.style.display="block";return}i.disabled=!0,i.textContent="Sending\u2026";try{let T=await D("/api/contact",{api_key:E,name:g,email:f,message:x});if(T.ok)b=f,localStorage.setItem("heedb_email",f),z(),q(e,"Message sent!","We'll get back to you soon. Check your inbox for a confirmation email.");else{let me=await T.json();s.textContent=me.error||"Something went wrong.",s.style.display="block",i.disabled=!1,i.textContent="Send message"}}catch(T){s.textContent="Network error. Please try again.",s.style.display="block",i.disabled=!1,i.textContent="Send message"}},n?e.append(m,p,s,i):e.append(l,o,r,d,m,p,s,i)}function ie(e){let t=!!(L&&b),n=a("label",{class:"llp-label"},["Name"]),l=P("text","llp-priv-name","Jane Smith");L&&(l.value=L);let o=a("label",{class:"llp-label"},["Email"]),r=P("email","llp-priv-email","jane@example.com");b&&(r.value=b);let d=a("label",{class:"llp-label"},["Request type"]),m=oe("llp-priv-type",[{value:"deletion",label:"Delete my data"},{value:"access",label:"Access my data"},{value:"portability",label:"Export my data"},{value:"correction",label:"Correct my data"},{value:"restriction",label:"Restrict processing"},{value:"objection",label:"Object to processing"},{value:"other",label:"Other"}]),p=a("div",{class:"llp-error",style:"display:none"}),s=a("button",{class:"llp-btn-submit"},["Submit request"]);s.onclick=async()=>{let i=l.value.trim(),g=r.value.trim(),f=m.value;if(p.style.display="none",!i||!g){p.textContent="Please fill in all fields.",p.style.display="block";return}s.disabled=!0,s.textContent="Submitting\u2026";try{let x=await D("/api/privacy-request",{api_key:E,name:i,email:g,request_type:f});if(x.ok)b=g,localStorage.setItem("heedb_email",g),z(),q(e,"Request submitted!","Your privacy request has been received. We'll respond within 30 days.");else{let T=await x.json();p.textContent=T.error||"Something went wrong.",p.style.display="block",s.disabled=!1,s.textContent="Submit request"}}catch(x){p.textContent="Network error. Please try again.",p.style.display="block",s.disabled=!1,s.textContent="Submit request"}},t?e.append(d,m,p,s):e.append(n,l,o,r,d,m,p,s)}async function re(e){var t;if(!y){e.innerHTML="";let n=a("p",{style:"color:#71717a;text-align:center;margin:8px 0;font-size:13px;line-height:1.5"},["Send a message below to view your message history."]),l=a("div",{class:"llp-new-msg"}),o=a("button",{},["+ Send a message"]);o.onclick=()=>{h="contact",S("contact"),k()},l.appendChild(o),e.append(n,l);return}e.innerHTML='<p style="color:#71717a;text-align:center">Loading\u2026</p>';try{let{threads:n}=await Z(b);if(e.innerHTML="",n.length===0){let r=a("p",{style:"color:#71717a;text-align:center;margin:8px 0"},["No open messages yet."]);e.appendChild(r)}else for(let r of n){let d=a("span",{class:`llp-badge llp-badge-${r.status}`},[r.status]),m=a("div",{class:"llp-thread-label"},[r.type==="privacy"?"Privacy request":"Message"," \u2022 "]);m.appendChild(d);let p=a("div",{class:"llp-thread-text"},[(t=r.preview)!=null?t:""]),s=new Date(r.createdAt).toLocaleDateString(),i=a("div",{class:"llp-thread-meta"},[s]),g=a("div",{class:"llp-thread-item"});g.append(m,p,i),g.onclick=()=>se(r.id),e.appendChild(g)}let l=a("div",{class:"llp-new-msg"}),o=a("button",{},["+ Send a new message"]);o.onclick=()=>{h="contact",S("contact"),k()},l.appendChild(o),e.appendChild(l)}catch(n){e.innerHTML='<p style="color:#ef4444;text-align:center">Failed to load messages.</p>'}}function se(e){A=e,h="thread-detail",k()}async function ce(e){e.innerHTML='<p style="color:#71717a;text-align:center">Loading\u2026</p>';let t=a("button",{class:"llp-chat-back"},["\u2190 Back to messages"]);t.onclick=()=>{h="threads",S("threads"),k()};try{let l=(await ee(A)).messages||[];e.innerHTML="",e.style.padding="12px",e.appendChild(t);let o=a("div",{class:"llp-chat-messages"});for(let i of l){let g=i.direction==="inbound",f=a("div",{style:`display:flex;flex-direction:column;${g?"align-items:flex-start":"align-items:flex-end"}`}),x=a("div",{class:`llp-chat-bubble ${g?"llp-chat-inbound":"llp-chat-outbound"}`},[de(i.body)]),T=a("div",{class:`llp-chat-time ${g?"":"llp-chat-time-right"}`},[pe(i.createdAt)]);f.append(x,T),o.appendChild(f)}e.appendChild(o),requestAnimationFrame(()=>{o.scrollTop=o.scrollHeight});let r=a("div",{class:"llp-chat-reply"}),d=document.createElement("textarea");d.className="llp-chat-reply-input",d.placeholder="Type a reply\u2026",d.rows=1,d.addEventListener("input",()=>{d.style.height="auto",d.style.height=Math.min(d.scrollHeight,80)+"px"});let m=a("button",{class:"llp-chat-send"},["Send"]),p=a("div",{class:"llp-error",style:"display:none;margin-top:4px"});async function s(){let i=d.value.trim();if(i){m.disabled=!0,m.textContent="\u2026",p.style.display="none";try{let g=await te(A,i);if(g.ok){let f=a("div",{style:"display:flex;flex-direction:column;align-items:flex-start"}),x=a("div",{class:"llp-chat-bubble llp-chat-inbound"},[i]),T=a("div",{class:"llp-chat-time"},["Just now"]);f.append(x,T),o.appendChild(f),o.scrollTop=o.scrollHeight,d.value="",d.style.height="auto"}else{let f=await g.json();p.textContent=f.error||"Failed to send.",p.style.display="block"}}catch(g){p.textContent="Network error. Please try again.",p.style.display="block"}m.disabled=!1,m.textContent="Send"}}m.onclick=s,d.addEventListener("keydown",i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),s())}),r.append(d,m),e.append(r,p),requestAnimationFrame(()=>d.focus())}catch(n){e.innerHTML="",e.appendChild(t),e.appendChild(a("p",{style:"color:#ef4444;text-align:center"},["Failed to load conversation."]))}}function de(e){let t=e.split(`
151
151
  `),n=[];for(let l of t){let o=l.trim();if(/^(On|Em|El|Le|Am|Il giorno) .+(<[^>]+@[^>]+>).*(wrote|escreveu|escribi|crit|schrieb|scritto)\s?:$/i.test(o)||/<[^>]+@[^>]+>/.test(o)&&o.endsWith(":")||/^-{3,}$/.test(o))break;/^>{1,}\s/.test(o)||n.push(l)}return n.join(`
152
152
  `).trim()}function pe(e){let t=new Date(e),l=new Date().getTime()-t.getTime(),o=Math.floor(l/6e4);if(o<1)return"Just now";if(o<60)return`${o}m ago`;let r=Math.floor(o/60);return r<24?`${r}h ago`:t.toLocaleDateString()}function q(e,t,n){e.innerHTML="";let l=a("div",{class:"llp-success"});l.innerHTML=`
153
153
  <div class="llp-success-icon">\u2705</div>
154
154
  <h3>${t}</h3>
155
155
  <p>${n}</p>
156
- `,e.appendChild(l)}let M=null,_=null;function $(e){h=e,M&&M.querySelectorAll(".llp-tab").forEach(t=>{t.classList.toggle("active",t.dataset.mode===e)})}function z(){_&&(_.style.display=b&&y?"":"none")}let B=null;function ge(){u=R(),B&&(B.textContent=O())}async function F(){p=await ne(),u=R(),B=document.createElement("style"),B.textContent=O(),document.head.appendChild(B),p.mode==="system"&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{ge(),L&&v&&k()});let e=p.triggerIcon?p.triggerIcon:p.triggerEmoji||"\u{1F4AC}",t=p.triggerText||"";if(H=a("button",{class:"llp-btn",title:"Contact us","aria-label":"Open contact widget"}),p.triggerIcon){let i=a("span",{class:"llp-btn-icon"});i.innerHTML=p.triggerIcon,H.appendChild(i)}else H.appendChild(document.createTextNode(p.triggerEmoji||"\u{1F4AC}"));if(t&&H.appendChild(a("span",{class:"llp-btn-label"},[t])),H.onclick=j,document.body.appendChild(H),p.triggerMode==="embedded"&&p.triggerSelector){let i=document.querySelector(p.triggerSelector);i&&i.addEventListener("click",g=>{g.preventDefault(),j()})}if(p.triggerMode==="tag"){let i=a("button",{class:"llp-tag","aria-label":"Open contact widget"}),g=a("span",{class:"llp-tag-icon"},[p.triggerEmoji||"\u{1F4AC}"]);i.appendChild(g),i.appendChild(document.createTextNode(p.triggerText||"Feedback")),i.onclick=j,document.body.appendChild(i)}v=a("div",{class:"llp-panel",style:"display:none"});let n=a("div",{class:"llp-header"}),l=a("h2",{},[p.headerTitle||"Contact us"]),o=a("button",{class:"llp-close","aria-label":"Close"},["\u2715"]);o.onclick=j,n.append(l,o),M=a("div",{class:"llp-tabs"});let r=a("button",{class:"llp-tab active","data-mode":"contact"},["Message"]),c=a("button",{class:"llp-tab","data-mode":"privacy"},["Privacy"]);_=a("button",{class:"llp-tab","data-mode":"threads"},["Messages"]),_.style.display=b&&y?"":"none",r.onclick=()=>{$("contact"),k()},c.onclick=()=>{$("privacy"),k()},_.onclick=()=>{$("threads"),k()},M.append(r,c,_);let m=a("div",{class:"llp-body"}),d=a("div",{class:"llp-footer"}),s=a("a",{href:"https://heedb.com",target:"_blank",rel:"noopener noreferrer"},["Powered by Heedb"]);d.appendChild(s),v.append(n,M,m,d),document.body.appendChild(v)}function j(){L=!L,v&&(v.style.display=L?"flex":"none",L&&(b&&y&&h!=="privacy"&&h!=="thread-detail"&&(h="threads",$("threads")),k()))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",F):F()})();})();
156
+ `,e.appendChild(l)}let M=null,_=null;function S(e){h=e,M&&M.querySelectorAll(".llp-tab").forEach(t=>{t.classList.toggle("active",t.dataset.mode===e)})}function z(){_&&(_.style.display=b&&y?"":"none")}let B=null;function ge(){u=R(),B&&(B.textContent=O())}async function F(){if(c=await ne(),u=R(),B=document.createElement("style"),B.textContent=O(),document.head.appendChild(B),c.customCSS){let i=document.createElement("style");i.textContent=c.customCSS,document.head.appendChild(i)}c.mode==="system"&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{ge(),C&&v&&k()});let e=c.triggerIcon?c.triggerIcon:c.triggerEmoji||"\u{1F4AC}",t=c.triggerText||"";if(H=a("button",{class:"llp-btn",title:"Contact us","aria-label":"Open contact widget"}),c.triggerIcon){let i=a("span",{class:"llp-btn-icon"});i.innerHTML=c.triggerIcon,H.appendChild(i)}else H.appendChild(document.createTextNode(c.triggerEmoji||"\u{1F4AC}"));if(t&&H.appendChild(a("span",{class:"llp-btn-label"},[t])),H.onclick=j,document.body.appendChild(H),c.triggerMode==="embedded"&&c.triggerSelector){let i=document.querySelector(c.triggerSelector);i&&i.addEventListener("click",g=>{g.preventDefault(),j()})}if(c.triggerMode==="tag"){let i=a("button",{class:"llp-tag","aria-label":"Open contact widget"}),g=a("span",{class:"llp-tag-icon"},[c.triggerEmoji||"\u{1F4AC}"]);i.appendChild(g),i.appendChild(document.createTextNode(c.triggerText||"Feedback")),i.onclick=j,document.body.appendChild(i)}v=a("div",{class:"llp-panel",style:"display:none"});let n=a("div",{class:"llp-header"}),l=a("h2",{},[c.headerTitle||"Contact us"]),o=a("button",{class:"llp-close","aria-label":"Close"},["\u2715"]);o.onclick=j,n.append(l,o),M=a("div",{class:"llp-tabs"});let r=a("button",{class:"llp-tab active","data-mode":"contact"},["Message"]),d=a("button",{class:"llp-tab","data-mode":"privacy"},["Privacy"]);_=a("button",{class:"llp-tab","data-mode":"threads"},["Messages"]),_.style.display=b&&y?"":"none",r.onclick=()=>{S("contact"),k()},d.onclick=()=>{S("privacy"),k()},_.onclick=()=>{S("threads"),k()},M.append(r,d,_);let m=a("div",{class:"llp-body"}),p=a("div",{class:"llp-footer"}),s=a("a",{href:"https://heedb.com",target:"_blank",rel:"noopener noreferrer"},["Powered by Heedb"]);p.appendChild(s),v.append(n,M,m,p),document.body.appendChild(v)}function j(){C=!C,v&&(v.style.display=C?"flex":"none",C&&(b&&y&&h!=="privacy"&&h!=="thread-detail"&&(h="threads",S("threads")),k()))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",F):F()})();})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heedb/web-sdk",
3
- "version": "0.1.6",
3
+ "version": "1.0.0",
4
4
  "description": "Drop-in feedback widget with email conversations for any website",
5
5
  "license": "MIT",
6
6
  "repository": {
package/widget.js CHANGED
@@ -1,156 +1,171 @@
1
- /* Heedb Widget v0.1.6 — https://heedb.com */
2
- "use strict";(()=>{(function(){var W,U,K,J,V;let w=document.currentScript||document.querySelector("script[data-api-key]"),E=(W=w==null?void 0:w.getAttribute("data-api-key"))!=null?W:"",N=(U=w==null?void 0:w.src)!=null?U:"",I=(w==null?void 0:w.getAttribute("data-host"))||(N?new URL(N).origin:"");if(!E){console.warn("[Heedb] Missing data-api-key on <script> tag.");return}let p={},u=!1,X={primary:"#18181b",text:"#18181b",bg:"#ffffff"},G={primary:"#e4e4e7",text:"#e4e4e7",bg:"#1a1a1a"};function R(){return p.mode==="dark"?!0:p.mode==="light"?!1:p.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)").matches:!1}function Y(){return u?G:X}function S(e,t){let n=p[e];return n!=null?String(n):t}let L=!1,h="contact",A="",C=(K=localStorage.getItem("heedb_name"))!=null?K:"",b=(J=localStorage.getItem("heedb_email"))!=null?J:"",y=(V=localStorage.getItem("heedb_token"))!=null?V:"",v=null,H=null;async function Q(e,t){try{let n=await D("/api/threads/token",{api_key:E,email:e,userHash:t});if(n.ok){let l=await n.json();if(l.widgetToken){y=l.widgetToken,localStorage.setItem("heedb_token",l.widgetToken);return}}y="",localStorage.removeItem("heedb_token")}catch(n){y="",localStorage.removeItem("heedb_token")}}window.Heedb={version:"0.1.6",init(e={}){e.name&&(C=e.name,localStorage.setItem("heedb_name",e.name)),e.email&&(b=e.email,localStorage.setItem("heedb_email",e.email),e.userHash?Q(e.email,e.userHash).then(()=>{z(),L&&v&&k()}):(z(),L&&v&&k()))},reset(){C="",b="",y="",localStorage.removeItem("heedb_name"),localStorage.removeItem("heedb_email"),localStorage.removeItem("heedb_token"),h="contact",L=!1,v&&(v.style.display="none"),z()}};function D(e,t){return fetch(`${I}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}function Z(e){let t=new URL(`${I}/api/threads`);return t.searchParams.set("api_key",E),t.searchParams.set("email",e),y&&t.searchParams.set("token",y),fetch(t.toString()).then(n=>n.json())}function ee(e){let t=new URL(`${I}/api/threads/${e}`);return t.searchParams.set("api_key",E),t.searchParams.set("email",b),t.searchParams.set("token",y),fetch(t.toString()).then(n=>n.json())}function te(e,t){return D(`/api/threads/${e}/reply`,{api_key:E,email:b,token:y,message:t})}async function ne(){var e;try{let t=new URL(`${I}/api/widget-config`);t.searchParams.set("api_key",E);let n=await fetch(t.toString());if(n.ok)return(e=(await n.json()).config)!=null?e:{}}catch(t){}return{}}function O(){var f,x;let e=Y(),t=S(u?"darkPrimaryColor":"primaryColor",e.primary),n=S(u?"darkTextColor":"textColor",e.text),l=S(u?"darkBgColor":"bgColor",e.bg),o=(f=p.borderRadius)!=null?f:16,r=(x=p.buttonRadius)!=null?x:50,c=p.fontFamily||"system-ui, -apple-system, sans-serif",m=p.position==="bottom-left",d=r>=50?"50%":`${r}px`,s=Math.round(o*.5),i=p.triggerMode==="tag",g=p.triggerMode==="embedded"||i;return`
3
- .llp-btn {
4
- position: fixed; bottom: 24px; ${m?"left: 24px":"right: 24px"}; z-index: 999998;
5
- width: 52px; height: 52px; border-radius: ${d}; border: none;
1
+ /* Heedb Widget */
2
+ "use strict";(()=>{(function(){var te,ae,ne,se,oe;let E=document.currentScript||document.querySelector("script[data-api-key]"),H=(te=E==null?void 0:E.getAttribute("data-api-key"))!=null?te:"",Y=(ae=E==null?void 0:E.src)!=null?ae:"",I=(E==null?void 0:E.getAttribute("data-host"))||(Y?new URL(Y).origin:"");if(!H){console.warn("[Heedb] Missing data-api-key on <script> tag.");return}let ie=1,r={},b=!1,re={primary:"#18181b",text:"#18181b",bg:"#ffffff"},de={primary:"#e4e4e7",text:"#e4e4e7",bg:"#1a1a1a"},B={en:{contactTab:"Message",privacyTab:"Privacy",messagesTab:"Messages",nameLabel:"Name",emailLabel:"Email",messageLabel:"Message",namePlaceholder:"Jane Smith",emailPlaceholder:"jane@example.com",messagePlaceholder:"How can we help?",sendMessage:"Send message",sending:"Sending\u2026",fillAllFields:"Please fill in all fields.",messageSentTitle:"Message sent!",messageSentBody:"We'll get back to you soon. Check your inbox for a confirmation email.",networkError:"Network error. Please try again.",somethingWrong:"Something went wrong.",rateLimited:"Too many messages. Please wait a moment.",requestType:"Request type",deleteData:"Delete my data",accessData:"Access my data",exportData:"Export my data",correctData:"Correct my data",restrictProcessing:"Restrict processing",objectProcessing:"Object to processing",other:"Other",submitRequest:"Submit request",submitting:"Submitting\u2026",requestSubmittedTitle:"Request submitted!",requestSubmittedBody:"Your privacy request has been received. We'll respond within 30 days.",contactUs:"Contact us",feedback:"Feedback",poweredBy:"Powered by Heedb",justNow:"Just now",minutesAgo:"{mins}m ago",hoursAgo:"{hours}h ago",send:"Send",backToMessages:"\u2190 Back to messages",noThreadsAuth:"Send a message below to view your message history.",sendAMessage:"+ Send a message",sendNewMessage:"+ Send a new message",noOpenMessages:"No open messages yet.",loading:"Loading\u2026",failedToLoad:"Failed to load messages.",failedToLoadConvo:"Failed to load conversation.",failedToSend:"Failed to send.",typeReply:"Type a reply\u2026",privacyRequest:"Privacy request",message:"Message"},es:{contactTab:"Mensaje",privacyTab:"Privacidad",messagesTab:"Mensajes",nameLabel:"Nombre",emailLabel:"Correo",messageLabel:"Mensaje",namePlaceholder:"Mar\xEDa Garc\xEDa",emailPlaceholder:"maria@empresa.com",messagePlaceholder:"\xBFC\xF3mo podemos ayudarte?",sendMessage:"Enviar mensaje",sending:"Enviando\u2026",fillAllFields:"Por favor, completa todos los campos.",messageSentTitle:"\xA1Mensaje enviado!",messageSentBody:"Te responderemos pronto. Revisa tu bandeja de entrada para un correo de confirmaci\xF3n.",networkError:"Error de red. Int\xE9ntalo de nuevo.",somethingWrong:"Algo sali\xF3 mal.",rateLimited:"Demasiados mensajes. Espera un momento.",requestType:"Tipo de solicitud",deleteData:"Eliminar mis datos",accessData:"Acceder a mis datos",exportData:"Exportar mis datos",correctData:"Corregir mis datos",restrictProcessing:"Restringir procesamiento",objectProcessing:"Oponerse al procesamiento",other:"Otro",submitRequest:"Enviar solicitud",submitting:"Enviando\u2026",requestSubmittedTitle:"\xA1Solicitud enviada!",requestSubmittedBody:"Tu solicitud de privacidad ha sido recibida. Responderemos en un plazo de 30 d\xEDas.",contactUs:"Cont\xE1ctanos",feedback:"Comentarios",poweredBy:"Impulsado por Heedb",justNow:"Ahora",minutesAgo:"hace {mins}m",hoursAgo:"hace {hours}h",send:"Enviar",backToMessages:"\u2190 Volver a mensajes",noThreadsAuth:"Env\xEDa un mensaje para ver tu historial.",sendAMessage:"+ Enviar un mensaje",sendNewMessage:"+ Enviar un nuevo mensaje",noOpenMessages:"No hay mensajes a\xFAn.",loading:"Cargando\u2026",failedToLoad:"No se pudieron cargar los mensajes.",failedToLoadConvo:"No se pudo cargar la conversaci\xF3n.",failedToSend:"No se pudo enviar.",typeReply:"Escribe una respuesta\u2026",privacyRequest:"Solicitud de privacidad",message:"Mensaje"},pt:{contactTab:"Mensagem",privacyTab:"Privacidade",messagesTab:"Mensagens",nameLabel:"Nome",emailLabel:"Email",messageLabel:"Mensagem",namePlaceholder:"Maria Silva",emailPlaceholder:"maria@empresa.com",messagePlaceholder:"Como podemos ajudar?",sendMessage:"Enviar mensagem",sending:"Enviando\u2026",fillAllFields:"Por favor, preencha todos os campos.",messageSentTitle:"Mensagem enviada!",messageSentBody:"Responderemos em breve. Verifique sua caixa de entrada para um email de confirma\xE7\xE3o.",networkError:"Erro de rede. Tente novamente.",somethingWrong:"Algo deu errado.",rateLimited:"Muitas mensagens. Aguarde um momento.",requestType:"Tipo de solicita\xE7\xE3o",deleteData:"Excluir meus dados",accessData:"Acessar meus dados",exportData:"Exportar meus dados",correctData:"Corrigir meus dados",restrictProcessing:"Restringir processamento",objectProcessing:"Opor-se ao processamento",other:"Outro",submitRequest:"Enviar solicita\xE7\xE3o",submitting:"Enviando\u2026",requestSubmittedTitle:"Solicita\xE7\xE3o enviada!",requestSubmittedBody:"Sua solicita\xE7\xE3o de privacidade foi recebida. Responderemos em at\xE9 30 dias.",contactUs:"Fale conosco",feedback:"Feedback",poweredBy:"Powered by Heedb",justNow:"Agora",minutesAgo:"h\xE1 {mins}m",hoursAgo:"h\xE1 {hours}h",send:"Enviar",backToMessages:"\u2190 Voltar \xE0s mensagens",noThreadsAuth:"Envie uma mensagem para ver seu hist\xF3rico.",sendAMessage:"+ Enviar uma mensagem",sendNewMessage:"+ Enviar uma nova mensagem",noOpenMessages:"Nenhuma mensagem ainda.",loading:"Carregando\u2026",failedToLoad:"N\xE3o foi poss\xEDvel carregar as mensagens.",failedToLoadConvo:"N\xE3o foi poss\xEDvel carregar a conversa.",failedToSend:"N\xE3o foi poss\xEDvel enviar.",typeReply:"Digite uma resposta\u2026",privacyRequest:"Solicita\xE7\xE3o de privacidade",message:"Mensagem"}},R="en";function n(e){var t,a,o;return(o=(a=(t=B[R])==null?void 0:t[e])!=null?a:B.en[e])!=null?o:e}function z(e){if(e)return e[R]||e.en}function G(){var a;let e=E==null?void 0:E.getAttribute("data-lang");if(e&&e in B)return e;if(O&&O in B)return O;if(r.language&&r.language in B)return r.language;let t=(a=document.documentElement.lang)==null?void 0:a.slice(0,2);return t&&t in B?t:"en"}let O;function J(){return r.mode==="dark"?!0:r.mode==="light"?!1:r.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)").matches:!1}function le(){return b?de:re}function j(e,t){let a=r[e];return a!=null?String(a):t}let S=!1,k="contact",V="",A=(ne=localStorage.getItem("heedb_name"))!=null?ne:"",T=(se=localStorage.getItem("heedb_email"))!=null?se:"",M=(oe=localStorage.getItem("heedb_token"))!=null?oe:"",f=null,_=null;async function ce(e,t){try{let a=await F("/api/threads/token",{api_key:H,email:e,userHash:t});if(a.ok){let o=await a.json();if(o.widgetToken){M=o.widgetToken,localStorage.setItem("heedb_token",o.widgetToken);return}}M="",localStorage.removeItem("heedb_token")}catch(a){M="",localStorage.removeItem("heedb_token")}}window.Heedb={version:typeof __HEEDB_VERSION__!="undefined"?__HEEDB_VERSION__:"dev",init(e={}){e.lang&&(O=e.lang,R=G(),Z(),S&&f&&C()),e.name&&(A=e.name,localStorage.setItem("heedb_name",e.name)),e.email&&(T=e.email,localStorage.setItem("heedb_email",e.email),e.userHash?ce(e.email,e.userHash).then(()=>{N(),S&&f&&C()}):(N(),S&&f&&C()))},reset(){A="",T="",M="",localStorage.removeItem("heedb_name"),localStorage.removeItem("heedb_email"),localStorage.removeItem("heedb_token"),k="contact",S=!1,f&&(f.style.display="none"),N()}};function F(e,t){return fetch(`${I}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}function pe(e){let t=new URL(`${I}/api/threads`);return t.searchParams.set("api_key",H),t.searchParams.set("email",e),M&&t.searchParams.set("token",M),fetch(t.toString()).then(a=>a.json())}function me(e){let t=new URL(`${I}/api/threads/${e}`);return t.searchParams.set("api_key",H),t.searchParams.set("email",T),t.searchParams.set("token",M),fetch(t.toString()).then(a=>a.json())}function ge(e,t){return F(`/api/threads/${e}/reply`,{api_key:H,email:T,token:M,message:t})}async function ue(){var e;try{let t=new URL(`${I}/api/widget-config`);t.searchParams.set("api_key",H),t.searchParams.set("v",String(ie));let a=await fetch(t.toString());if(a.ok)return(e=(await a.json()).config)!=null?e:{}}catch(t){}return{}}function X(){var g,y;let e=le(),t=j(b?"darkPrimaryColor":"primaryColor",e.primary),a=j(b?"darkTextColor":"textColor",e.text),o=j(b?"darkBgColor":"bgColor",e.bg),i=(g=r.borderRadius)!=null?g:16,d=(y=r.buttonRadius)!=null?y:50,x=r.fontFamily||"system-ui, -apple-system, sans-serif",u=r.position==="bottom-left",c=d>=50?"50%":`${d}px`,p=Math.round(i*.5),l=r.triggerMode==="tag",m=r.triggerMode==="embedded"||l;return`
3
+ .heedb-btn {
4
+ position: fixed; bottom: 24px; ${u?"left: 24px":"right: 24px"}; z-index: 999998;
5
+ width: 52px; height: 52px; border-radius: ${c}; border: none;
6
6
  background: ${t}; color: #fff; font-size: 22px; cursor: pointer;
7
7
  box-shadow: 0 4px 16px rgba(0,0,0,.25);
8
- display: ${g?"none":"flex"}; align-items: center; justify-content: center;
9
- transition: transform .15s;
10
- }
11
- .llp-btn:hover { transform: scale(1.08); }
12
- .llp-btn-label { font-size: 14px; font-weight: 600; margin-left: 6px; }
13
- .llp-btn-icon { display: flex; align-items: center; justify-content: center; }
14
- .llp-btn-icon svg { width: 22px; height: 22px; fill: currentColor; }
15
- .llp-btn:has(.llp-btn-label) { width: auto; padding: 0 18px; gap: 4px; }
16
- .llp-tag {
17
- position: fixed; ${m?"left: 0":"right: 0"}; top: 50%; z-index: 999998;
18
- transform: ${m?"rotate(90deg) translateX(-50%)":"rotate(-90deg) translateX(50%)"};
19
- transform-origin: ${m?"left top":"right top"};
8
+ display: ${m?"none":"flex"}; align-items: center; justify-content: center;
9
+ font-family: ${x}; transition: transform .15s;
10
+ }
11
+ .heedb-btn:hover { transform: scale(1.08); }
12
+ .heedb-btn-label { font-size: 14px; font-weight: 600; margin-left: 6px; }
13
+ .heedb-btn-icon { display: flex; align-items: center; justify-content: center; }
14
+ .heedb-btn-icon svg { width: 22px; height: 22px; fill: currentColor; }
15
+ .heedb-btn:has(.heedb-btn-label) { width: auto; padding: 0 18px; gap: 4px; }
16
+ .heedb-tag {
17
+ position: fixed !important; ${u?"left: 0 !important":"right: 0 !important"}; top: 50% !important; z-index: 999998 !important;
18
+ transform: ${u?"rotate(90deg) translateX(-50%)":"rotate(-90deg) translateX(50%)"} !important;
19
+ transform-origin: ${u?"left bottom":"right bottom"} !important;
20
20
  background: ${t}; color: #fff; border: none; cursor: pointer;
21
21
  padding: 8px 18px; font-size: 13px; font-weight: 600;
22
- font-family: ${c};
23
- border-radius: ${Math.min(r,12)}px ${Math.min(r,12)}px 0 0;
22
+ font-family: ${x};
23
+ border-radius: ${Math.min(d,12)}px ${Math.min(d,12)}px 0 0;
24
24
  box-shadow: 0 2px 12px rgba(0,0,0,.2);
25
25
  display: flex; align-items: center; gap: 6px;
26
26
  transition: opacity .15s;
27
27
  }
28
- .llp-tag:hover { opacity: .9; }
29
- .llp-tag-icon { font-size: 16px; }
30
- .llp-panel {
31
- position: fixed; bottom: 88px; ${m?"left: 24px":"right: 24px"}; z-index: 999999;
32
- width: 370px; max-height: 560px; border-radius: ${o}px;
33
- background: ${l}; box-shadow: 0 8px 32px rgba(0,0,0,.18);
28
+ .heedb-tag:hover { opacity: .9; }
29
+ .heedb-tag-icon { font-size: 16px; }
30
+ .heedb-panel {
31
+ position: fixed; bottom: 88px; ${u?"left: 24px":"right: 24px"}; z-index: 999999;
32
+ width: 280px; max-height: 560px; border-radius: ${i}px;
33
+ background: ${o}; box-shadow: 0 8px 32px rgba(0,0,0,.18);
34
34
  display: flex; flex-direction: column; overflow: hidden;
35
- font-family: ${c}; font-size: 14px; color: ${n};
35
+ font-family: ${x}; font-size: 14px; color: ${a};
36
36
  transition: opacity .15s, transform .15s;
37
37
  }
38
- .llp-header {
38
+ .heedb-header {
39
39
  background: ${t}; color: #fff; padding: 14px 16px;
40
40
  display: flex; align-items: center; justify-content: space-between;
41
41
  }
42
- .llp-header h2 { margin: 0; font-size: 15px; font-weight: 600; }
43
- .llp-close {
42
+ .heedb-header h2 { margin: 0; font-size: 15px; font-weight: 600; }
43
+ .heedb-close {
44
44
  background: none; border: none; color: #fff; cursor: pointer;
45
45
  font-size: 18px; line-height: 1; padding: 0;
46
46
  }
47
- .llp-tabs {
48
- display: flex; border-bottom: 1px solid ${u?"#333":"#e4e4e7"};
47
+ .heedb-tabs {
48
+ display: flex; border-bottom: 1px solid ${b?"#333":"#e4e4e7"};
49
49
  }
50
- .llp-tab {
50
+ .heedb-tab {
51
51
  flex: 1; padding: 10px 0; border: none; background: none;
52
52
  cursor: pointer; font-size: 13px; font-weight: 500; color: #71717a;
53
53
  border-bottom: 2px solid transparent; margin-bottom: -1px;
54
54
  }
55
- .llp-tab.active { color: ${n}; border-bottom-color: ${t}; }
56
- .llp-body { padding: 16px; overflow-y: auto; flex: 1; }
57
- .llp-label { display: block; font-size: 12px; font-weight: 600; color: #52525b; margin-bottom: 4px; }
58
- .llp-input, .llp-textarea, .llp-select {
55
+ .heedb-tab.active { color: ${a}; border-bottom-color: ${t}; }
56
+ .heedb-body { padding: 16px; overflow-y: auto; flex: 1; }
57
+ .heedb-label { display: block; font-size: 12px; font-weight: 600; color: #52525b; margin-bottom: 4px; }
58
+ .heedb-input, .heedb-textarea, .heedb-select {
59
59
  width: 100%; box-sizing: border-box; padding: 8px 10px;
60
- border: 1px solid ${u?"#444":"#d4d4d8"}; border-radius: ${s}px;
61
- font-size: 13px; color: ${n}; margin-bottom: 10px;
62
- font-family: inherit; background: ${u?"#222":l};
60
+ border: 1px solid ${b?"#444":"#d4d4d8"}; border-radius: ${p}px;
61
+ font-size: 13px; color: ${a}; margin-bottom: 10px;
62
+ font-family: inherit; background: ${b?"#222":o};
63
63
  }
64
- .llp-textarea { min-height: 80px; resize: vertical; }
65
- .llp-input:focus, .llp-textarea:focus, .llp-select:focus {
64
+ .heedb-textarea { min-height: 80px; resize: vertical; }
65
+ .heedb-input:focus, .heedb-textarea:focus, .heedb-select:focus {
66
66
  outline: none; border-color: ${t};
67
67
  }
68
- .llp-btn-submit {
68
+ .heedb-btn-submit {
69
69
  width: 100%; padding: 10px; background: ${t}; color: #fff;
70
- border: none; border-radius: ${s}px; font-size: 14px; font-weight: 600;
70
+ border: none; border-radius: ${p}px; font-size: 14px; font-weight: 600;
71
71
  cursor: pointer; transition: opacity .15s;
72
72
  }
73
- .llp-btn-submit:hover { opacity: .85; }
74
- .llp-btn-submit:disabled { opacity: .5; cursor: not-allowed; }
75
- .llp-error { color: #ef4444; font-size: 12px; margin-bottom: 8px; }
76
- .llp-success { text-align: center; padding: 24px 8px; }
77
- .llp-success-icon { font-size: 36px; }
78
- .llp-success h3 { margin: 12px 0 6px; font-size: 15px; color: ${n}; }
79
- .llp-success p { margin: 0; color: #71717a; font-size: 13px; line-height: 1.5; }
80
- .llp-thread-item {
81
- padding: 10px 12px; border: 1px solid ${u?"#333":"#e4e4e7"}; border-radius: ${s}px;
73
+ .heedb-btn-submit:hover { opacity: .85; }
74
+ .heedb-btn-submit:disabled { opacity: .5; cursor: not-allowed; }
75
+ .heedb-error { color: #ef4444; font-size: 12px; margin-bottom: 8px; }
76
+ .heedb-success { text-align: center; padding: 24px 8px; }
77
+ .heedb-success-icon { font-size: 36px; }
78
+ .heedb-success h3 { margin: 12px 0 6px; font-size: 15px; color: ${a}; }
79
+ .heedb-success p { margin: 0; color: #71717a; font-size: 13px; line-height: 1.5; }
80
+ .heedb-thread-item {
81
+ padding: 10px 12px; border: 1px solid ${b?"#333":"#e4e4e7"}; border-radius: ${p}px;
82
82
  margin-bottom: 8px; cursor: pointer; display: block; color: inherit;
83
83
  transition: background .1s; background: none;
84
84
  }
85
- .llp-thread-item:hover { background: ${u?"#252525":"#f4f4f5"}; }
86
- .llp-thread-label { font-size: 12px; color: #71717a; margin-bottom: 2px; }
87
- .llp-thread-text { font-size: 13px; color: ${n}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
88
- .llp-thread-meta { font-size: 11px; color: #a1a1aa; margin-top: 3px; }
89
- .llp-badge { display: inline-block; padding: 1px 6px; border-radius: 9999px; font-size: 10px; font-weight: 600; }
90
- .llp-badge-open { background: #d1fae5; color: #065f46; }
91
- .llp-badge-replied { background: #dbeafe; color: #1e40af; }
92
- .llp-new-msg { margin-top: 12px; padding-top: 12px; border-top: 1px solid ${u?"#333":"#e4e4e7"}; }
93
- .llp-new-msg button {
94
- width: 100%; padding: 8px; background: none; border: 1px solid ${u?"#444":"#d4d4d8"};
95
- border-radius: ${s}px; font-size: 13px; cursor: pointer; color: ${u?"#999":"#52525b"};
96
- }
97
- .llp-new-msg button:hover { background: ${u?"#252525":"#f4f4f5"}; }
98
- .llp-footer {
99
- padding: 6px 16px; text-align: center; border-top: 1px solid ${u?"#333":"#f0f0f0"};
100
- }
101
- .llp-footer a {
85
+ .heedb-thread-item:hover { background: ${b?"#252525":"#f4f4f5"}; }
86
+ .heedb-thread-label { font-size: 12px; color: #71717a; margin-bottom: 2px; }
87
+ .heedb-thread-text { font-size: 13px; color: ${a}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
88
+ .heedb-thread-meta { font-size: 11px; color: #a1a1aa; margin-top: 3px; }
89
+ .heedb-badge { display: inline-block; padding: 1px 6px; border-radius: 9999px; font-size: 10px; font-weight: 600; }
90
+ .heedb-badge-open { background: #d1fae5; color: #065f46; }
91
+ .heedb-badge-replied { background: #dbeafe; color: #1e40af; }
92
+ .heedb-new-msg { margin-top: 12px; padding-top: 12px; border-top: 1px solid ${b?"#333":"#e4e4e7"}; }
93
+ .heedb-new-msg button {
94
+ width: 100%; padding: 8px; background: none; border: 1px solid ${b?"#444":"#d4d4d8"};
95
+ border-radius: ${p}px; font-size: 13px; cursor: pointer; color: ${b?"#999":"#52525b"};
96
+ }
97
+ .heedb-new-msg button:hover { background: ${b?"#252525":"#f4f4f5"}; }
98
+ .heedb-footer {
99
+ padding: 6px 16px; text-align: center; border-top: 1px solid ${b?"#333":"#f0f0f0"};
100
+ }
101
+ .heedb-footer a {
102
102
  font-size: 10px; color: #a1a1aa; text-decoration: none; font-weight: 500;
103
103
  }
104
- .llp-footer a:hover { color: #71717a; text-decoration: underline; }
104
+ .heedb-footer a:hover { color: #71717a; text-decoration: underline; }
105
105
 
106
106
  /* Chat view */
107
- .llp-chat-back {
107
+ .heedb-chat-back {
108
108
  background: none; border: none; cursor: pointer; font-size: 13px;
109
109
  color: ${t}; padding: 0; margin-bottom: 12px; font-weight: 500;
110
110
  display: flex; align-items: center; gap: 4px;
111
111
  }
112
- .llp-chat-back:hover { text-decoration: underline; }
113
- .llp-chat-messages {
112
+ .heedb-chat-back:hover { text-decoration: underline; }
113
+ .heedb-chat-messages {
114
114
  display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px;
115
115
  max-height: 320px; overflow-y: auto;
116
116
  }
117
- .llp-chat-bubble {
118
- padding: 8px 12px; border-radius: ${Math.max(s,8)}px; font-size: 13px;
117
+ .heedb-chat-bubble {
118
+ padding: 8px 12px; border-radius: ${Math.max(p,8)}px; font-size: 13px;
119
119
  line-height: 1.45; max-width: 85%; word-wrap: break-word;
120
120
  white-space: pre-wrap;
121
121
  }
122
- .llp-chat-inbound {
123
- background: ${u?"#252525":"#f4f4f5"}; color: ${n}; align-self: flex-start;
122
+ .heedb-chat-inbound {
123
+ background: ${b?"#252525":"#f4f4f5"}; color: ${a}; align-self: flex-start;
124
124
  border-bottom-left-radius: 4px;
125
125
  }
126
- .llp-chat-outbound {
126
+ .heedb-chat-outbound {
127
127
  background: ${t}; color: #fff; align-self: flex-end;
128
128
  border-bottom-right-radius: 4px;
129
129
  }
130
- .llp-chat-time {
130
+ .heedb-chat-time {
131
131
  font-size: 10px; color: #a1a1aa; margin-top: 2px;
132
132
  }
133
- .llp-chat-time-right { text-align: right; }
134
- .llp-chat-reply {
135
- display: flex; gap: 8px; border-top: 1px solid ${u?"#333":"#e4e4e7"}; padding-top: 12px;
133
+ .heedb-chat-time-right { text-align: right; }
134
+ .heedb-chat-reply {
135
+ display: flex; gap: 8px; border-top: 1px solid ${b?"#333":"#e4e4e7"}; padding-top: 12px;
136
136
  }
137
- .llp-chat-reply-input {
138
- flex: 1; padding: 8px 10px; border: 1px solid ${u?"#444":"#d4d4d8"}; border-radius: ${s}px;
139
- font-size: 13px; font-family: inherit; color: ${n}; background: ${u?"#222":l};
137
+ .heedb-chat-reply-input {
138
+ flex: 1; padding: 8px 10px; border: 1px solid ${b?"#444":"#d4d4d8"}; border-radius: ${p}px;
139
+ font-size: 13px; font-family: inherit; color: ${a}; background: ${b?"#222":o};
140
140
  resize: none; min-height: 36px; max-height: 80px; box-sizing: border-box;
141
141
  }
142
- .llp-chat-reply-input:focus { outline: none; border-color: ${t}; }
143
- .llp-chat-send {
142
+ .heedb-chat-reply-input:focus { outline: none; border-color: ${t}; }
143
+ .heedb-chat-send {
144
144
  padding: 8px 14px; background: ${t}; color: #fff; border: none;
145
- border-radius: ${s}px; font-size: 13px; font-weight: 600; cursor: pointer;
145
+ border-radius: ${p}px; font-size: 13px; font-weight: 600; cursor: pointer;
146
146
  transition: opacity .15s; white-space: nowrap; align-self: flex-end;
147
147
  }
148
- .llp-chat-send:hover { opacity: .85; }
149
- .llp-chat-send:disabled { opacity: .5; cursor: not-allowed; }
150
- `}function a(e,t={},n=[]){let l=document.createElement(e);for(let[o,r]of Object.entries(t))o==="class"?l.className=r:o==="style"?l.setAttribute("style",r):o.startsWith("on")&&typeof r=="function"?l.addEventListener(o.slice(2),r):l.setAttribute(o,String(r));for(let o of n)l.appendChild(typeof o=="string"?document.createTextNode(o):o);return l}function P(e,t,n=""){let l=document.createElement("input");return l.type=e,l.id=t,l.placeholder=n,l.className="llp-input",l}function ae(e,t=""){let n=document.createElement("textarea");return n.id=e,n.placeholder=t,n.className="llp-textarea",n}function oe(e,t){let n=document.createElement("select");n.id=e,n.className="llp-select";for(let l of t){let o=document.createElement("option");o.value=l.value,o.textContent=l.label,n.appendChild(o)}return n}function k(){if(!v)return;let e=v.querySelector(".llp-body");e.innerHTML="",h==="contact"?le(e):h==="privacy"?ie(e):h==="threads"?re(e):h==="thread-detail"&&ce(e),M&&(M.style.display=h==="thread-detail"?"none":"flex")}function le(e,t=""){let n=!!(C&&b),l=a("label",{class:"llp-label"},["Name"]),o=P("text","llp-name","Jane Smith");C&&(o.value=C);let r=a("label",{class:"llp-label"},["Email"]),c=P("email","llp-email","jane@example.com");(t||b)&&(c.value=t||b);let m=a("label",{class:"llp-label"},["Message"]),d=ae("llp-message","How can we help?"),s=a("div",{class:"llp-error",style:"display:none"}),i=a("button",{class:"llp-btn-submit"},["Send message"]);i.onclick=async()=>{let g=o.value.trim(),f=c.value.trim(),x=d.value.trim();if(s.style.display="none",!g||!f||!x){s.textContent="Please fill in all fields.",s.style.display="block";return}i.disabled=!0,i.textContent="Sending\u2026";try{let T=await D("/api/contact",{api_key:E,name:g,email:f,message:x});if(T.ok)b=f,localStorage.setItem("heedb_email",f),z(),q(e,"Message sent!","We'll get back to you soon. Check your inbox for a confirmation email.");else{let me=await T.json();s.textContent=me.error||"Something went wrong.",s.style.display="block",i.disabled=!1,i.textContent="Send message"}}catch(T){s.textContent="Network error. Please try again.",s.style.display="block",i.disabled=!1,i.textContent="Send message"}},n?e.append(m,d,s,i):e.append(l,o,r,c,m,d,s,i)}function ie(e){let t=!!(C&&b),n=a("label",{class:"llp-label"},["Name"]),l=P("text","llp-priv-name","Jane Smith");C&&(l.value=C);let o=a("label",{class:"llp-label"},["Email"]),r=P("email","llp-priv-email","jane@example.com");b&&(r.value=b);let c=a("label",{class:"llp-label"},["Request type"]),m=oe("llp-priv-type",[{value:"deletion",label:"Delete my data"},{value:"access",label:"Access my data"},{value:"portability",label:"Export my data"},{value:"correction",label:"Correct my data"},{value:"restriction",label:"Restrict processing"},{value:"objection",label:"Object to processing"},{value:"other",label:"Other"}]),d=a("div",{class:"llp-error",style:"display:none"}),s=a("button",{class:"llp-btn-submit"},["Submit request"]);s.onclick=async()=>{let i=l.value.trim(),g=r.value.trim(),f=m.value;if(d.style.display="none",!i||!g){d.textContent="Please fill in all fields.",d.style.display="block";return}s.disabled=!0,s.textContent="Submitting\u2026";try{let x=await D("/api/privacy-request",{api_key:E,name:i,email:g,request_type:f});if(x.ok)b=g,localStorage.setItem("heedb_email",g),z(),q(e,"Request submitted!","Your privacy request has been received. We'll respond within 30 days.");else{let T=await x.json();d.textContent=T.error||"Something went wrong.",d.style.display="block",s.disabled=!1,s.textContent="Submit request"}}catch(x){d.textContent="Network error. Please try again.",d.style.display="block",s.disabled=!1,s.textContent="Submit request"}},t?e.append(c,m,d,s):e.append(n,l,o,r,c,m,d,s)}async function re(e){var t;if(!y){e.innerHTML="";let n=a("p",{style:"color:#71717a;text-align:center;margin:8px 0;font-size:13px;line-height:1.5"},["Send a message below to view your message history."]),l=a("div",{class:"llp-new-msg"}),o=a("button",{},["+ Send a message"]);o.onclick=()=>{h="contact",$("contact"),k()},l.appendChild(o),e.append(n,l);return}e.innerHTML='<p style="color:#71717a;text-align:center">Loading\u2026</p>';try{let{threads:n}=await Z(b);if(e.innerHTML="",n.length===0){let r=a("p",{style:"color:#71717a;text-align:center;margin:8px 0"},["No open messages yet."]);e.appendChild(r)}else for(let r of n){let c=a("span",{class:`llp-badge llp-badge-${r.status}`},[r.status]),m=a("div",{class:"llp-thread-label"},[r.type==="privacy"?"Privacy request":"Message"," \u2022 "]);m.appendChild(c);let d=a("div",{class:"llp-thread-text"},[(t=r.preview)!=null?t:""]),s=new Date(r.createdAt).toLocaleDateString(),i=a("div",{class:"llp-thread-meta"},[s]),g=a("div",{class:"llp-thread-item"});g.append(m,d,i),g.onclick=()=>se(r.id),e.appendChild(g)}let l=a("div",{class:"llp-new-msg"}),o=a("button",{},["+ Send a new message"]);o.onclick=()=>{h="contact",$("contact"),k()},l.appendChild(o),e.appendChild(l)}catch(n){e.innerHTML='<p style="color:#ef4444;text-align:center">Failed to load messages.</p>'}}function se(e){A=e,h="thread-detail",k()}async function ce(e){e.innerHTML='<p style="color:#71717a;text-align:center">Loading\u2026</p>';let t=a("button",{class:"llp-chat-back"},["\u2190 Back to messages"]);t.onclick=()=>{h="threads",$("threads"),k()};try{let l=(await ee(A)).messages||[];e.innerHTML="",e.style.padding="12px",e.appendChild(t);let o=a("div",{class:"llp-chat-messages"});for(let i of l){let g=i.direction==="inbound",f=a("div",{style:`display:flex;flex-direction:column;${g?"align-items:flex-start":"align-items:flex-end"}`}),x=a("div",{class:`llp-chat-bubble ${g?"llp-chat-inbound":"llp-chat-outbound"}`},[de(i.body)]),T=a("div",{class:`llp-chat-time ${g?"":"llp-chat-time-right"}`},[pe(i.createdAt)]);f.append(x,T),o.appendChild(f)}e.appendChild(o),requestAnimationFrame(()=>{o.scrollTop=o.scrollHeight});let r=a("div",{class:"llp-chat-reply"}),c=document.createElement("textarea");c.className="llp-chat-reply-input",c.placeholder="Type a reply\u2026",c.rows=1,c.addEventListener("input",()=>{c.style.height="auto",c.style.height=Math.min(c.scrollHeight,80)+"px"});let m=a("button",{class:"llp-chat-send"},["Send"]),d=a("div",{class:"llp-error",style:"display:none;margin-top:4px"});async function s(){let i=c.value.trim();if(i){m.disabled=!0,m.textContent="\u2026",d.style.display="none";try{let g=await te(A,i);if(g.ok){let f=a("div",{style:"display:flex;flex-direction:column;align-items:flex-start"}),x=a("div",{class:"llp-chat-bubble llp-chat-inbound"},[i]),T=a("div",{class:"llp-chat-time"},["Just now"]);f.append(x,T),o.appendChild(f),o.scrollTop=o.scrollHeight,c.value="",c.style.height="auto"}else{let f=await g.json();d.textContent=f.error||"Failed to send.",d.style.display="block"}}catch(g){d.textContent="Network error. Please try again.",d.style.display="block"}m.disabled=!1,m.textContent="Send"}}m.onclick=s,c.addEventListener("keydown",i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),s())}),r.append(c,m),e.append(r,d),requestAnimationFrame(()=>c.focus())}catch(n){e.innerHTML="",e.appendChild(t),e.appendChild(a("p",{style:"color:#ef4444;text-align:center"},["Failed to load conversation."]))}}function de(e){let t=e.split(`
151
- `),n=[];for(let l of t){let o=l.trim();if(/^(On|Em|El|Le|Am|Il giorno) .+(<[^>]+@[^>]+>).*(wrote|escreveu|escribi|crit|schrieb|scritto)\s?:$/i.test(o)||/<[^>]+@[^>]+>/.test(o)&&o.endsWith(":")||/^-{3,}$/.test(o))break;/^>{1,}\s/.test(o)||n.push(l)}return n.join(`
152
- `).trim()}function pe(e){let t=new Date(e),l=new Date().getTime()-t.getTime(),o=Math.floor(l/6e4);if(o<1)return"Just now";if(o<60)return`${o}m ago`;let r=Math.floor(o/60);return r<24?`${r}h ago`:t.toLocaleDateString()}function q(e,t,n){e.innerHTML="";let l=a("div",{class:"llp-success"});l.innerHTML=`
153
- <div class="llp-success-icon">\u2705</div>
148
+ .heedb-chat-send:hover { opacity: .85; }
149
+ .heedb-chat-send:disabled { opacity: .5; cursor: not-allowed; }
150
+
151
+ /* Skeleton loading */
152
+ .heedb-skeleton { pointer-events: none; }
153
+ .heedb-skel-line {
154
+ background: ${b?"#333":"#e4e4e7"};
155
+ border-radius: 4px;
156
+ animation: heedb-pulse 1.5s ease-in-out infinite;
157
+ }
158
+ @keyframes heedb-pulse {
159
+ 0%, 100% { opacity: 0.4; }
160
+ 50% { opacity: 1; }
161
+ }
162
+
163
+ /* Body fade transition */
164
+ .heedb-body { transition: opacity .15s ease; }
165
+ `}function s(e,t={},a=[]){let o=document.createElement(e);for(let[i,d]of Object.entries(t))i==="class"?o.className=d:i==="style"?o.setAttribute("style",d):i.startsWith("on")&&typeof d=="function"?o.addEventListener(i.slice(2),d):o.setAttribute(i,String(d));for(let i of a)o.appendChild(typeof i=="string"?document.createTextNode(i):i);return o}function W(e,t,a=""){let o=document.createElement("input");return o.type=e,o.id=t,o.placeholder=a,o.className="heedb-input",o}function he(e,t=""){let a=document.createElement("textarea");return a.id=e,a.placeholder=t,a.className="heedb-textarea",a}function be(e,t){let a=document.createElement("select");a.id=e,a.className="heedb-select";for(let o of t){let i=document.createElement("option");i.value=o.value,i.textContent=o.label,a.appendChild(i)}return a}function C(){if(!f)return;let e=f.querySelector(".heedb-body");e.innerHTML="",k==="contact"?fe(e):k==="privacy"?xe(e):k==="threads"?ye(e):k==="thread-detail"&&Te(e),$&&($.style.display=k==="thread-detail"?"none":"flex")}function fe(e,t=""){let a=!!(A&&T),o=s("label",{class:"heedb-label"},[n("nameLabel")]),i=W("text","heedb-name",n("namePlaceholder"));A&&(i.value=A);let d=s("label",{class:"heedb-label"},[n("emailLabel")]),x=W("email","heedb-email",n("emailPlaceholder"));(t||T)&&(x.value=t||T);let u=z(r.messageLabel),c=u?s("label",{class:"heedb-label"},[u]):null,p=he("heedb-message",z(r.messagePlaceholder)||n("messagePlaceholder")),l=s("div",{class:"heedb-error",style:"display:none"}),m=s("button",{class:"heedb-btn-submit"},[n("sendMessage")]);m.onclick=async()=>{var w;let g=i.value.trim(),y=x.value.trim(),h=p.value.trim();if(l.style.display="none",!g||!y||!h){l.textContent=n("fillAllFields"),l.style.display="block";return}m.disabled=!0,m.textContent=n("sending");try{let v=await F("/api/contact",{api_key:H,name:g,email:y,message:h,lang:R});if(v.ok)T=y,localStorage.setItem("heedb_email",y),N(),Q(e,n("messageSentTitle"),n("messageSentBody"));else if(v.status===429){let L=parseInt((w=v.headers.get("Retry-After"))!=null?w:"60",10);l.textContent=n("rateLimited"),l.style.display="block",m.textContent=n("sendMessage"),setTimeout(()=>{m.disabled=!1,l.style.display="none"},L*1e3)}else{let L=await v.json();l.textContent=L.error||n("somethingWrong"),l.style.display="block",m.disabled=!1,m.textContent=n("sendMessage")}}catch(v){l.textContent=n("networkError"),l.style.display="block",m.disabled=!1,m.textContent=n("sendMessage")}},a?(c&&e.append(c),e.append(p,l,m)):(e.append(o,i,d,x),c&&e.append(c),e.append(p,l,m))}function xe(e){let t=!!(A&&T),a=s("label",{class:"heedb-label"},[n("nameLabel")]),o=W("text","heedb-priv-name",n("namePlaceholder"));A&&(o.value=A);let i=s("label",{class:"heedb-label"},[n("emailLabel")]),d=W("email","heedb-priv-email",n("emailPlaceholder"));T&&(d.value=T);let x=s("label",{class:"heedb-label"},[n("requestType")]),u=be("heedb-priv-type",[{value:"deletion",label:n("deleteData")},{value:"access",label:n("accessData")},{value:"portability",label:n("exportData")}]),c=s("div",{class:"heedb-error",style:"display:none"}),p=s("button",{class:"heedb-btn-submit"},[n("submitRequest")]);p.onclick=async()=>{var y;let l=o.value.trim(),m=d.value.trim(),g=u.value;if(c.style.display="none",!l||!m){c.textContent=n("fillAllFields"),c.style.display="block";return}p.disabled=!0,p.textContent=n("submitting");try{let h=await F("/api/privacy-request",{api_key:H,name:l,email:m,request_type:g,lang:R});if(h.ok)T=m,localStorage.setItem("heedb_email",m),N(),Q(e,n("requestSubmittedTitle"),n("requestSubmittedBody"));else if(h.status===429){let w=parseInt((y=h.headers.get("Retry-After"))!=null?y:"60",10);c.textContent=n("rateLimited"),c.style.display="block",p.textContent=n("submitRequest"),setTimeout(()=>{p.disabled=!1,c.style.display="none"},w*1e3)}else{let w=await h.json();c.textContent=w.error||n("somethingWrong"),c.style.display="block",p.disabled=!1,p.textContent=n("submitRequest")}}catch(h){c.textContent=n("networkError"),c.style.display="block",p.disabled=!1,p.textContent=n("submitRequest")}},t?e.append(x,u,c,p):e.append(a,o,i,d,x,u,c,p)}async function ye(e){var t;if(!M){e.innerHTML="";let a=s("p",{style:"color:#71717a;text-align:center;margin:8px 0;font-size:13px;line-height:1.5"},[n("noThreadsAuth")]),o=s("div",{class:"heedb-new-msg"}),i=s("button",{},[n("sendAMessage")]);i.onclick=()=>{k="contact",P("contact"),C()},o.appendChild(i),e.append(a,o);return}e.innerHTML="";for(let a=0;a<3;a++){let o=s("div",{class:"heedb-thread-item heedb-skeleton"});o.append(s("div",{class:"heedb-skel-line",style:"width:40%;height:12px"}),s("div",{class:"heedb-skel-line",style:"width:80%;height:13px;margin-top:6px"}),s("div",{class:"heedb-skel-line",style:"width:30%;height:11px;margin-top:4px"})),e.appendChild(o)}try{let{threads:a}=await pe(T);if(e.innerHTML="",e.style.opacity="0",requestAnimationFrame(()=>{e.style.opacity="1"}),a.length===0){let d=s("p",{style:"color:#71717a;text-align:center;margin:8px 0"},[z(r.emptyStateText)||n("noOpenMessages")]);e.appendChild(d)}else for(let d of a){let x=s("span",{class:`heedb-badge heedb-badge-${d.status}`},[d.status]),u=s("div",{class:"heedb-thread-label"},[d.type==="privacy"?n("privacyRequest"):n("message")," \u2022 "]);u.appendChild(x);let c=s("div",{class:"heedb-thread-text"},[(t=d.preview)!=null?t:""]),p=new Date(d.createdAt).toLocaleDateString(),l=s("div",{class:"heedb-thread-meta"},[p]),m=s("div",{class:"heedb-thread-item"});m.append(u,c,l),m.onclick=()=>ve(d.id),e.appendChild(m)}let o=s("div",{class:"heedb-new-msg"}),i=s("button",{},[n("sendNewMessage")]);i.onclick=()=>{k="contact",P("contact"),C()},o.appendChild(i),e.appendChild(o)}catch(a){e.innerHTML=`<p style="color:#ef4444;text-align:center">${n("failedToLoad")}</p>`}}function ve(e){V=e,k="thread-detail",C()}async function Te(e){e.innerHTML="",e.style.padding="12px";let t=s("div",{class:"heedb-skel-line",style:"width:50%;height:13px;margin-bottom:12px"});e.appendChild(t);let a=s("div",{style:"display:flex;flex-direction:column;gap:8px"}),o=["65%","50%","70%","45%"],i=["flex-start","flex-end","flex-start","flex-end"];for(let x=0;x<4;x++){let u=s("div",{style:`display:flex;flex-direction:column;align-items:${i[x]}`});u.appendChild(s("div",{class:"heedb-skel-line",style:`width:${o[x]};height:32px;border-radius:8px`})),a.appendChild(u)}e.appendChild(a);let d=s("button",{class:"heedb-chat-back"},[n("backToMessages")]);d.onclick=()=>{k="threads",P("threads"),C()};try{let u=(await me(V)).messages||[];e.innerHTML="",e.style.padding="12px",e.appendChild(d);let c=s("div",{class:"heedb-chat-messages"});for(let h of u){let w=h.direction==="inbound",v=s("div",{style:`display:flex;flex-direction:column;${w?"align-items:flex-start":"align-items:flex-end"}`}),L=s("div",{class:`heedb-chat-bubble ${w?"heedb-chat-inbound":"heedb-chat-outbound"}`},[we(h.body)]),K=s("div",{class:`heedb-chat-time ${w?"":"heedb-chat-time-right"}`},[ke(h.createdAt)]);v.append(L,K),c.appendChild(v)}e.appendChild(c),requestAnimationFrame(()=>{c.scrollTop=c.scrollHeight});let p=s("div",{class:"heedb-chat-reply"}),l=document.createElement("textarea");l.className="heedb-chat-reply-input",l.placeholder=n("typeReply"),l.rows=1,l.addEventListener("input",()=>{l.style.height="auto",l.style.height=Math.min(l.scrollHeight,80)+"px"});let m=s("button",{class:"heedb-chat-send"},[n("send")]),g=s("div",{class:"heedb-error",style:"display:none;margin-top:4px"});async function y(){let h=l.value.trim();if(h){m.disabled=!0,m.textContent="\u2026",g.style.display="none";try{let w=await ge(V,h);if(w.ok){let v=s("div",{style:"display:flex;flex-direction:column;align-items:flex-start"}),L=s("div",{class:"heedb-chat-bubble heedb-chat-inbound"},[h]),K=s("div",{class:"heedb-chat-time"},[n("justNow")]);v.append(L,K),c.appendChild(v),c.scrollTop=c.scrollHeight,l.value="",l.style.height="auto"}else{let v=await w.json();g.textContent=v.error||n("failedToSend"),g.style.display="block"}}catch(w){g.textContent=n("networkError"),g.style.display="block"}m.disabled=!1,m.textContent=n("send")}}m.onclick=y,l.addEventListener("keydown",h=>{h.key==="Enter"&&!h.shiftKey&&(h.preventDefault(),y())}),p.append(l,m),e.append(p,g),requestAnimationFrame(()=>l.focus())}catch(x){e.innerHTML="",e.appendChild(d),e.appendChild(s("p",{style:"color:#ef4444;text-align:center"},[n("failedToLoadConvo")]))}}function we(e){let t=e.split(`
166
+ `),a=[];for(let o of t){let i=o.trim();if(/^(On|Em|El|Le|Am|Il giorno) .+(<[^>]+@[^>]+>).*(wrote|escreveu|escribi|crit|schrieb|scritto)\s?:$/i.test(i)||/<[^>]+@[^>]+>/.test(i)&&i.endsWith(":")||/^-{3,}$/.test(i))break;/^>{1,}\s/.test(i)||a.push(o)}return a.join(`
167
+ `).trim()}function ke(e){let t=new Date(e),o=new Date().getTime()-t.getTime(),i=Math.floor(o/6e4);if(i<1)return n("justNow");if(i<60)return n("minutesAgo").replace("{mins}",String(i));let d=Math.floor(i/60);return d<24?n("hoursAgo").replace("{hours}",String(d)):t.toLocaleDateString()}function Q(e,t,a){e.innerHTML="";let o=s("div",{class:"heedb-success"});o.innerHTML=`
168
+ <div class="heedb-success-icon">\u2705</div>
154
169
  <h3>${t}</h3>
155
- <p>${n}</p>
156
- `,e.appendChild(l)}let M=null,_=null;function $(e){h=e,M&&M.querySelectorAll(".llp-tab").forEach(t=>{t.classList.toggle("active",t.dataset.mode===e)})}function z(){_&&(_.style.display=b&&y?"":"none")}let B=null;function ge(){u=R(),B&&(B.textContent=O())}async function F(){p=await ne(),u=R(),B=document.createElement("style"),B.textContent=O(),document.head.appendChild(B),p.mode==="system"&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{ge(),L&&v&&k()});let e=p.triggerIcon?p.triggerIcon:p.triggerEmoji||"\u{1F4AC}",t=p.triggerText||"";if(H=a("button",{class:"llp-btn",title:"Contact us","aria-label":"Open contact widget"}),p.triggerIcon){let i=a("span",{class:"llp-btn-icon"});i.innerHTML=p.triggerIcon,H.appendChild(i)}else H.appendChild(document.createTextNode(p.triggerEmoji||"\u{1F4AC}"));if(t&&H.appendChild(a("span",{class:"llp-btn-label"},[t])),H.onclick=j,document.body.appendChild(H),p.triggerMode==="embedded"&&p.triggerSelector){let i=document.querySelector(p.triggerSelector);i&&i.addEventListener("click",g=>{g.preventDefault(),j()})}if(p.triggerMode==="tag"){let i=a("button",{class:"llp-tag","aria-label":"Open contact widget"}),g=a("span",{class:"llp-tag-icon"},[p.triggerEmoji||"\u{1F4AC}"]);i.appendChild(g),i.appendChild(document.createTextNode(p.triggerText||"Feedback")),i.onclick=j,document.body.appendChild(i)}v=a("div",{class:"llp-panel",style:"display:none"});let n=a("div",{class:"llp-header"}),l=a("h2",{},[p.headerTitle||"Contact us"]),o=a("button",{class:"llp-close","aria-label":"Close"},["\u2715"]);o.onclick=j,n.append(l,o),M=a("div",{class:"llp-tabs"});let r=a("button",{class:"llp-tab active","data-mode":"contact"},["Message"]),c=a("button",{class:"llp-tab","data-mode":"privacy"},["Privacy"]);_=a("button",{class:"llp-tab","data-mode":"threads"},["Messages"]),_.style.display=b&&y?"":"none",r.onclick=()=>{$("contact"),k()},c.onclick=()=>{$("privacy"),k()},_.onclick=()=>{$("threads"),k()},M.append(r,c,_);let m=a("div",{class:"llp-body"}),d=a("div",{class:"llp-footer"}),s=a("a",{href:"https://heedb.com",target:"_blank",rel:"noopener noreferrer"},["Powered by Heedb"]);d.appendChild(s),v.append(n,M,m,d),document.body.appendChild(v)}function j(){L=!L,v&&(v.style.display=L?"flex":"none",L&&(b&&y&&h!=="privacy"&&h!=="thread-detail"&&(h="threads",$("threads")),k()))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",F):F()})();})();
170
+ <p>${a}</p>
171
+ `,e.appendChild(o)}let $=null,D=null;function P(e){k=e,$&&$.querySelectorAll(".heedb-tab").forEach(t=>{t.classList.toggle("active",t.dataset.mode===e)})}function N(){D&&(D.style.display=T&&M?"":"none")}let q=null;function Z(){b=J(),q&&(q.textContent=X())}async function ee(){if(r=await ue(),R=G(),b=J(),q=document.createElement("style"),q.textContent=X(),document.head.appendChild(q),r.customCSS){let g=document.createElement("style");g.textContent=r.customCSS,document.head.appendChild(g)}r.mode==="system"&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{Z(),S&&f&&C()});let e=r.triggerIcon?r.triggerIcon:r.triggerEmoji||"\u{1F4AC}",t=r.triggerText||"";if(_=s("button",{class:"heedb-btn",title:n("contactUs"),"aria-label":"Open contact widget"}),r.triggerIcon){let g=s("span",{class:"heedb-btn-icon"}),h=new DOMParser().parseFromString(r.triggerIcon,"image/svg+xml").querySelector("svg");if(h){h.querySelectorAll("script,foreignObject,iframe,object,embed").forEach(L=>L.remove());let w=document.createTreeWalker(h,NodeFilter.SHOW_ELEMENT),v;for(;v=w.nextNode();)for(let L of Array.from(v.attributes))(L.name.startsWith("on")||/^\s*javascript:/i.test(L.value))&&v.removeAttribute(L.name);g.appendChild(h)}_.appendChild(g)}else _.appendChild(document.createTextNode(r.triggerEmoji||"\u{1F4AC}"));if(t&&_.appendChild(s("span",{class:"heedb-btn-label"},[t])),_.onclick=U,document.body.appendChild(_),r.triggerMode==="embedded"&&r.triggerSelector){let g=document.querySelector(r.triggerSelector);g&&g.addEventListener("click",y=>{y.preventDefault(),U()})}if(r.triggerMode==="tag"){let g=s("button",{class:"heedb-tag","aria-label":"Open contact widget"}),y=s("span",{class:"heedb-tag-icon"},[r.triggerEmoji||"\u{1F4AC}"]);g.appendChild(y),g.appendChild(document.createTextNode(r.triggerText||n("feedback"))),g.onclick=U,document.body.appendChild(g)}f=s("div",{class:"heedb-panel",style:"display:none"});let a=s("div",{class:"heedb-header"}),o=s("h2",{},[r.headerTitle||n("contactUs")]),i=s("button",{class:"heedb-close","aria-label":"Close"},["\u2715"]);i.onclick=U,a.append(o,i),$=s("div",{class:"heedb-tabs"});let d=s("button",{class:"heedb-tab active","data-mode":"contact"},[z(r.contactTabLabel)||n("contactTab")]),u=r.showPrivacyTab!==!1?s("button",{class:"heedb-tab","data-mode":"privacy"},[n("privacyTab")]):null;D=s("button",{class:"heedb-tab","data-mode":"threads"},[n("messagesTab")]),D.style.display=T&&M?"":"none",d.onclick=()=>{P("contact"),C()},u&&(u.onclick=()=>{P("privacy"),C()}),D.onclick=()=>{P("threads"),C()},$.append(d),u&&$.append(u),$.append(D);let c=s("div",{class:"heedb-body"}),p=s("div",{class:"heedb-footer"}),l=new URLSearchParams({utm_source:"widget",utm_medium:"heedb-widget",utm_campaign:window.location.hostname}),m=s("a",{href:`https://heedb.com?${l.toString()}`,target:"_blank",rel:"noopener noreferrer"},[n("poweredBy")]);p.appendChild(m),f.append(a,$,c,p),document.body.appendChild(f)}function U(){S=!S,f&&(S?(f.style.display="flex",f.style.opacity="0",f.style.transform="translateY(8px)",requestAnimationFrame(()=>{f.style.opacity="1",f.style.transform="translateY(0)"}),T&&M&&k!=="privacy"&&k!=="thread-detail"&&(k="threads",P("threads")),C()):(f.style.opacity="0",f.style.transform="translateY(8px)",setTimeout(()=>{!S&&f&&(f.style.display="none")},150)))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",ee):ee()})();})();