@bitpalm/ai-agents 0.1.18 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +23 -0
- package/dist/react.d.ts +23 -0
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/dist/widget.global.js +1 -1
- package/dist/widget.global.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,6 +35,11 @@ const widget = createWidget({ slug: 'your-agent-slug', token: 'your-embed-token'
|
|
|
35
35
|
// Programmatic control
|
|
36
36
|
widget.open();
|
|
37
37
|
widget.close();
|
|
38
|
+
widget.identify({
|
|
39
|
+
externalUserId: 'cust_123',
|
|
40
|
+
name: 'Max Mustermann',
|
|
41
|
+
email: 'max@example.com',
|
|
42
|
+
});
|
|
38
43
|
widget.destroy();
|
|
39
44
|
```
|
|
40
45
|
|
|
@@ -84,6 +89,41 @@ Disable auto-identity for one specific form:
|
|
|
84
89
|
<form data-bp-identify="off">...</form>
|
|
85
90
|
```
|
|
86
91
|
|
|
92
|
+
## Manual Identify (Logged-in Users)
|
|
93
|
+
|
|
94
|
+
If your website has authenticated users, call `identify()` after login to attach trusted profile data to the current visitor:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
widget.identify({
|
|
98
|
+
externalUserId: "user_42",
|
|
99
|
+
name: "Alex Example",
|
|
100
|
+
email: "alex@example.com",
|
|
101
|
+
phone: "+491701234567",
|
|
102
|
+
company: "Example GmbH",
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Optional signed identify fields (forwarded to your BitPalm backend):
|
|
107
|
+
|
|
108
|
+
- `signature`: backend-generated HMAC signature
|
|
109
|
+
- `signedAt`: unix timestamp (seconds)
|
|
110
|
+
- `signatureVersion`: currently `"v1"`
|
|
111
|
+
|
|
112
|
+
For script-tag integrations, trigger identify via a browser event:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
window.dispatchEvent(
|
|
116
|
+
new CustomEvent("bitpalm-identify", {
|
|
117
|
+
detail: {
|
|
118
|
+
slug: "your-agent-slug",
|
|
119
|
+
externalUserId: "user_42",
|
|
120
|
+
name: "Alex Example",
|
|
121
|
+
email: "alex@example.com",
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
);
|
|
125
|
+
```
|
|
126
|
+
|
|
87
127
|
## License
|
|
88
128
|
|
|
89
129
|
MIT — [AI Agent Platform by BitPalm](https://agents.bitpalm.ae)
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var ne=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Le=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var Ae=(n,t)=>{for(var d in t)ne(n,d,{get:t[d],enumerable:!0})},Me=(n,t,d,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let m of Le(t))!Te.call(n,m)&&m!==d&&ne(n,m,{get:()=>t[m],enumerable:!(i=Ie(t,m))||i.enumerable});return n};var ke=n=>Me(ne({},"__esModule",{value:!0}),n);var We={};Ae(We,{createWidget:()=>G});module.exports=ke(We);var Ce="https://agents.bitpalm.ae",y="_bp_",_e=new Set(["password","file","checkbox","radio","submit","button","reset","image"]),$e=8e3,xe=`${y}identify_signature`,Se=`${y}identify_fingerprint`,Ee=`${y}identify_sent_at`;function u(n,t=180){return n?n.replace(/\s+/g," ").trim().slice(0,t):""}function Be(n){return n?` ${n.toLowerCase().replace(/[_-]+/g," ").replace(/[^a-z0-9\s@.]/g," ").replace(/\s+/g," ").trim()} `:""}function F(n,t){for(let d of t)if(n.includes(d))return!0;return!1}function C(n){return/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i.test(n)}function _(n){let t=u(n,50);if(!t)return"";let d=t.startsWith("+"),i=t.replace(/\D/g,"");return i.length<6?"":`${d?"+":""}${i.slice(0,20)}`}function N(n,t){for(let d of t){let i=n.querySelector(d),m=u(i?.value);if(m)return m}return""}function Pe(n){return u(n.getAttribute("data-bp-field")||n.getAttribute("data-bitpalm-field"),64).toLowerCase().replace(/[_\s]+/g,"-")}function He(n){return n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Oe(n,t){let d=[],i=(o,v=140)=>{let l=u(o,v);l&&d.push(l)};i(t.name),i(t.id),i(t.getAttribute("autocomplete")),i(t.getAttribute("placeholder")),i(t.getAttribute("aria-label")),i(t.getAttribute("data-field")),i(t.getAttribute("data-name")),i(t.getAttribute("data-label")),i(t.getAttribute("data-bp-field")),i(t.getAttribute("data-bitpalm-field"));let m=new Set,h=o=>{let v=u(o,200);!v||m.has(v)||(m.add(v),d.push(v))};for(let o of Array.from(t.labels||[]))h(o.textContent);if(t.id){let o=n.querySelector(`label[for="${He(t.id)}"]`);h(o?.textContent)}let g=t.closest("label");h(g?.textContent);let r=t.getAttribute("aria-labelledby");if(r)for(let o of r.split(/\s+/)){if(!o)continue;let v=n.ownerDocument.getElementById(o);h(v?.textContent)}return d}function De(n){let t=u(N(n,["[data-bp-email]","[data-bitpalm-email]"]),140).toLowerCase(),d=_(N(n,["[data-bp-phone]","[data-bitpalm-phone]"])),i=u(N(n,["[data-bp-name]","[data-bitpalm-name]","[data-bp-full-name]","[data-bitpalm-full-name]"])),m=u(N(n,["[data-bp-first-name]","[data-bitpalm-first-name]"])),h=u(N(n,["[data-bp-last-name]","[data-bitpalm-last-name]"])),g=u(N(n,["[data-bp-company]","[data-bitpalm-company]"]));for(let l of Array.from(n.elements)){if(!(l instanceof HTMLInputElement||l instanceof HTMLTextAreaElement||l instanceof HTMLSelectElement)||l.disabled||l instanceof HTMLInputElement&&_e.has(l.type.toLowerCase()))continue;let f=Pe(l),p=l.hasAttribute("data-bp-email")||l.hasAttribute("data-bitpalm-email")||l.hasAttribute("data-bp-phone")||l.hasAttribute("data-bitpalm-phone")||l.hasAttribute("data-bp-name")||l.hasAttribute("data-bitpalm-name")||l.hasAttribute("data-bp-full-name")||l.hasAttribute("data-bitpalm-full-name")||l.hasAttribute("data-bp-first-name")||l.hasAttribute("data-bitpalm-first-name")||l.hasAttribute("data-bp-last-name")||l.hasAttribute("data-bitpalm-last-name")||l.hasAttribute("data-bp-company")||l.hasAttribute("data-bitpalm-company")||!!f;if(l instanceof HTMLInputElement&&l.type.toLowerCase()==="hidden"&&!p)continue;let c=u(l.value);if(!c)continue;let $=l instanceof HTMLInputElement?l.type.toLowerCase():"",E=Be(Oe(n,l).join(" "));if(!t&&f==="email"&&C(c)){t=c.toLowerCase();continue}if(!d&&(f==="phone"||f==="tel"||f==="mobile"||f==="whatsapp")){let I=_(c);if(I){d=I;continue}}if(!g&&f==="company"){g=u(c,160);continue}if(!m&&(f==="first-name"||f==="firstname")){m=u(c,100);continue}if(!h&&(f==="last-name"||f==="lastname"||f==="surname")){h=u(c,100);continue}if(!i&&(f==="name"||f==="full-name"||f==="fullname")){!C(c)&&!_(c)&&(i=u(c,140));continue}let W=$==="email"||F(E,[" email "," e mail "," mail "," email adresse "," mailadresse "," correo "]),B=$==="tel"||F(E,[" phone "," phone number "," mobile "," tel "," telefon "," telefonnummer "," whatsapp "," handy "," kontakt "," nummer "]),P=F(E,[" company "," company name "," firma "," firmenname "," organization "," organisation "," business "," unternehmen "," agency "," brokerage "]),H=F(E,[" first name "," firstname "," given name "," givenname "," vorname "," fname "]),O=F(E,[" last name "," lastname "," family name "," familyname "," surname "," nachname "," lname "]),U=F(E,[" full name "," fullname "," contact name "," name "])&&!W&&!B;if(!t&&W&&C(c)){t=c.toLowerCase();continue}if(!d&&B){let I=_(c);if(I){d=I;continue}}if(!g&&P){g=u(c,160);continue}if(!m&&H){m=u(c,100);continue}if(!h&&O){h=u(c,100);continue}if(!i&&U&&!C(c)&&!_(c)){i=u(c,140);continue}!t&&C(c)&&(t=c.toLowerCase())}if(i&&(C(i)||_(i))&&(i=""),g&&(C(g)||_(g))&&(g=""),i||(i=u([m,h].filter(Boolean).join(" "),140)),i&&t&&i.toLowerCase()===t.toLowerCase()&&(i=""),!!!(t||d)&&!!!(i&&g))return null;let v={...i?{name:i}:{},...t?{email:t}:{},...d?{phone:d}:{},...g?{company:g}:{}};return Object.keys(v).length>0?v:null}function Fe(){if(typeof document<"u"){let n=document.documentElement.lang;if(n)return n.slice(0,2).toLowerCase()}return"en"}function oe(n,t=1200){if(typeof window<"u"&&"requestIdleCallback"in window){window.requestIdleCallback(n,{timeout:t});return}setTimeout(n,Math.min(t,300))}function ie(){if(typeof window>"u")return!1;let n=typeof navigator<"u"?navigator.userAgent:"";if(/Android|iPhone|iPad|iPod|IEMobile|Windows Phone|Mobile/i.test(n))return!0;let d=window.matchMedia("(pointer: coarse)").matches,i=window.matchMedia("(hover: none)").matches,m=Math.min(window.screen?.width||window.innerWidth,window.screen?.height||window.innerHeight);return d&&i&&m<=900}function G(n){let{slug:t,locale:d=Fe(),baseUrl:i=Ce,token:m,zIndex:h=9999,autoIdentify:g=!0}=n,r=document,o=r.createElement("iframe"),v=`${i}/t/${t}/widget`,l=new URLSearchParams({locale:d});m&&l.set("token",m),o.src=`${v}?${l.toString()}`,o.allow="clipboard-write",o.setAttribute("allowtransparency","true"),o.loading="lazy",o.style.cssText=`position:fixed;bottom:0;right:0;width:1px;height:1px;border:none;z-index:${h};background:transparent;color-scheme:normal;opacity:0;pointer-events:none;`;let f=new URL(o.src).origin,p=r.createElement("div");if(p.setAttribute("role","button"),p.setAttribute("aria-label","Chat"),p.style.cssText=`position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;display:none;align-items:center;justify-content:center;cursor:pointer;z-index:${h-1};background:#00ff41;box-shadow:0 0 15px rgba(0,255,65,0.31);transition:transform .2s,opacity .3s;opacity:0;`,p.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',p.onmouseenter=()=>{p.style.transform="scale(1.1)"},p.onmouseleave=()=>{p.style.transform="scale(1)"},p.onclick=()=>be(),r.body.appendChild(p),!r.getElementById("_bp_fade")){let e=r.createElement("style");e.id="_bp_fade",e.textContent="@keyframes _bp_fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}",r.head.appendChild(e)}let c=null,$=!1,E=!1,W=!1,B=!1,P=!1,H=()=>{W||(W=!0,r.body.appendChild(o))},O=!1,U=0,I={overflow:"",overscrollBehavior:""},b={overflow:"",overscrollBehavior:"",position:"",top:"",left:"",right:"",width:""},ae=()=>{if(O||!ie())return;let a=r.documentElement,s=r.body;U=window.scrollY||window.pageYOffset||0,I.overflow=a.style.overflow,I.overscrollBehavior=a.style.overscrollBehavior,b.overflow=s.style.overflow,b.overscrollBehavior=s.style.overscrollBehavior,b.position=s.style.position,b.top=s.style.top,b.left=s.style.left,b.right=s.style.right,b.width=s.style.width,a.style.overflow="hidden",a.style.overscrollBehavior="none",s.style.overflow="hidden",s.style.overscrollBehavior="none",s.style.position="fixed",s.style.top=`-${U}px`,s.style.left="0",s.style.right="0",s.style.width="100%",O=!0},D=()=>{if(!O)return;let e=r.documentElement,a=r.body;e.style.overflow=I.overflow,e.style.overscrollBehavior=I.overscrollBehavior,a.style.overflow=b.overflow,a.style.overscrollBehavior=b.overscrollBehavior,a.style.position=b.position,a.style.top=b.top,a.style.left=b.left,a.style.right=b.right,a.style.width=b.width,window.scrollTo(0,U),O=!1},se=()=>{let e=ie();o.style.display==="none"&&(o.style.display=""),e?(o.style.width="100vw",o.style.height="100dvh",o.style.left="0",o.style.top="0",ae()):(o.style.width="420px",o.style.height="620px",o.style.left="",o.style.top="",D()),o.style.opacity="1",o.style.pointerEvents="auto"},M=()=>{c&&(c.remove(),c=null)},z=()=>{},K=()=>{},re=e=>{if(e.origin===f){if(e.data?.type==="bitpalm-widget-config"){E=!1,$=!0,o.style.display==="none"&&(o.style.display=""),e.data.primaryColor&&(p.style.background=e.data.primaryColor,p.style.boxShadow=e.data.chatShadow==="none"?"none":`0 0 15px ${e.data.primaryColor}50`);let a=e.data.chatButtonIconColor||"black";if(e.data.chatButtonIconSvg){p.innerHTML="";let s=r.createElement("span");s.style.cssText=`display:flex;align-items:center;justify-content:center;width:24px;height:24px;color:${a}`;let w=new DOMParser().parseFromString(e.data.chatButtonIconSvg,"image/svg+xml").querySelector("svg");w?(w.querySelectorAll("script,foreignObject").forEach(A=>A.remove()),w.querySelectorAll("*").forEach(A=>{for(let j of[...A.attributes])(j.name.startsWith("on")||j.value&&j.value.includes("javascript:"))&&A.removeAttribute(j.name)}),w.setAttribute("width","24"),w.setAttribute("height","24"),w.style.display="block",s.appendChild(w)):s.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',p.appendChild(s)}else{let s=p.querySelector("svg");s&&(s.style.stroke=a)}p.style.display="flex",requestAnimationFrame(()=>{p.style.opacity="1"})}if(e.data?.type==="bitpalm-widget-resize"){let a=e.data.width>0,s=ie();a?(o.style.width=s?"100vw":`${e.data.width}px`,o.style.height=s?"100dvh":`${e.data.height}px`,s?(o.style.left="0",o.style.top="0",ae()):D(),o.style.opacity="1",o.style.pointerEvents="auto"):(D(),o.style.width="1px",o.style.height="1px",o.style.left="",o.style.top="",o.style.opacity="0",o.style.pointerEvents="none"),p.style.display=a?"none":"flex"}if(e.data?.type==="bitpalm-trigger-show"){if(E||!$)return;M(),c=r.createElement("div"),c.style.cssText=`position:fixed;bottom:90px;right:24px;max-width:240px;background:#fff;border-radius:16px;padding:12px 32px 12px 12px;box-shadow:0 2px 20px rgba(0,0,0,0.08);cursor:pointer;z-index:${h-1};font-family:system-ui,sans-serif;animation:_bp_fade .3s;`;let a=(e.data.message||"").replace(/</g,"<");c.innerHTML=`<p style="font-size:14px;color:#1f2937;margin:0;">${a}</p><div style="position:absolute;bottom:-8px;right:20px;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #fff;"></div>`;let s=r.createElement("button");s.style.cssText="position:absolute;top:-8px;right:-8px;width:28px;height:28px;border-radius:50%;background:#fff;border:none;box-shadow:0 1px 4px rgba(0,0,0,0.1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;color:#9ca3af;",s.innerHTML="✕",s.onclick=S=>{S.stopPropagation(),M(),o.contentWindow?.postMessage({type:"bitpalm-trigger-dismiss"},"*")},c.onclick=()=>{if(M(),p.style.display="none",se(),H(),!B){P=!0;return}o.contentWindow?.postMessage({type:"bitpalm-trigger-engaged"},"*")},c.appendChild(s),r.body.appendChild(c)}e.data?.type==="bitpalm-trigger-hide"&&M(),e.data?.type==="bitpalm-request-context"&&z(),e.data?.type==="bitpalm-widget-blocked"&&(E=!0,$=!1,p.style.display="none",M(),D(),o.style.display="none")}};window.addEventListener("message",re);let L=!1;try{L=localStorage.getItem(`${y}optout`)==="1"}catch{}let Y=`${y}vid`,x="";if(!L){try{x=localStorage.getItem(Y)||""}catch{}if(!x){let e=r.cookie.match(new RegExp(`(?:^|; )${Y}=([^;]+)`));x=e?decodeURIComponent(e[1]):""}x||(x=crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,11)}`);try{localStorage.setItem(Y,x)}catch{}try{r.cookie=`${Y}=${encodeURIComponent(x)};path=/;max-age=31536000;SameSite=Lax`}catch{}}L||oe(()=>{try{let e=new URLSearchParams(location.search),a={};for(let T of["utm_source","utm_medium","utm_campaign","utm_term","utm_content"]){let w=e.get(T);w&&(a[T]=w)}let s=JSON.stringify({tenant_slug:t,visitor_id:x,url:location.href,referrer:r.referrer||void 0,...Object.keys(a).length>0?{utm:a}:{}}),S=`${i}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(S,new Blob([s],{type:"application/json"})):fetch(S,{method:"POST",body:s,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}},2e3);let V="",Z="",X=0;try{V=sessionStorage.getItem(xe)||"",Z=sessionStorage.getItem(Se)||"";let e=parseInt(sessionStorage.getItem(Ee)||"0",10);Number.isFinite(e)&&e>0&&(X=e)}catch{}let le=e=>{if(L||!g||!x)return;let a=e.target instanceof HTMLFormElement?e.target:e.target instanceof Element?e.target.closest("form"):null;if(!(a instanceof HTMLFormElement))return;let s=(a.getAttribute("data-bp-identify")||a.getAttribute("data-bitpalm-identify")||"").toLowerCase();if(s==="off"||s==="false"||s==="0")return;let S=De(a);if(!S)return;let T=[S.email||"",S.phone||"",S.name||"",S.company||""].join("|").toLowerCase(),w=[a.getAttribute("id")||"",a.getAttribute("name")||"",a.getAttribute("action")||"",T].join("|").toLowerCase(),A=Date.now();if(!(A-X<$e&&(w===V||T===Z))){V=w,Z=T,X=A;try{sessionStorage.setItem(xe,w),sessionStorage.setItem(Se,T),sessionStorage.setItem(Ee,String(A))}catch{}try{let we=JSON.stringify({tenant_slug:t,visitor_id:x,url:location.href,referrer:r.referrer||void 0,...S}),ve=`${i}/api/widget/identify`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(ve,new Blob([we],{type:"application/json"})):fetch(ve,{method:"POST",body:we,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}}};!L&&g&&r.addEventListener("submit",le,!0);let R=parseInt(sessionStorage.getItem(`${y}pages`)||"0")+1;sessionStorage.setItem(`${y}pages`,String(R));let k=JSON.parse(sessionStorage.getItem(`${y}hist`)||"[]");k.push(location.href),k.length>20&&(k=k.slice(-20)),sessionStorage.setItem(`${y}hist`,JSON.stringify(k));let ce=Date.now(),q=parseInt(sessionStorage.getItem(`${y}site_start`)||"0");q||(q=ce,sessionStorage.setItem(`${y}site_start`,String(q)));let de=[];z=()=>{let e=!1;try{e=!!localStorage.getItem(`${y}visited`)}catch{e=!1}if(o.contentWindow?.postMessage({type:"bitpalm-parent-context",url:location.href,title:r.title,returning:e,pageCount:R,pageHistory:k,loadedAt:ce,siteStart:q,locale:d,visitorId:L?"":x},"*"),!e&&!L)try{localStorage.setItem(`${y}visited`,"1")}catch{}},o.addEventListener("load",()=>{B=!0,z(),[120,450,1100].forEach(e=>{let a=setTimeout(()=>z(),e);de.push(a)}),P&&(P=!1,K())}),r.readyState==="loading"?r.addEventListener("DOMContentLoaded",()=>oe(H,1600),{once:!0}):oe(H,1600);let pe=history.pushState.bind(history),me=history.replaceState.bind(history),J=()=>{R++,sessionStorage.setItem(`${y}pages`,String(R));let e=JSON.parse(sessionStorage.getItem(`${y}hist`)||"[]");if(e.push(location.href),e.length>20&&e.splice(0,e.length-20),k=e,sessionStorage.setItem(`${y}hist`,JSON.stringify(e)),o.contentWindow?.postMessage({type:"bitpalm-page-change",url:location.href,title:r.title,pageCount:R,pageHistory:e,loadedAt:Date.now()},"*"),!L)try{let a=JSON.stringify({tenant_slug:t,visitor_id:x,url:location.href}),s=`${i}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(s,new Blob([a],{type:"application/json"})):fetch(s,{method:"POST",body:a,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}};history.pushState=function(...e){pe(...e),J()},history.replaceState=function(...e){me(...e),J()},window.addEventListener("popstate",J);let ue=-1,Q,fe=()=>{clearTimeout(Q),Q=setTimeout(()=>{let e=Math.max(r.documentElement.scrollHeight,r.body.scrollHeight)-window.innerHeight,a=e>0?Math.round(window.scrollY/e*100):100;a!==ue&&(ue=a,o.contentWindow?.postMessage({type:"bitpalm-scroll-depth",percent:a},"*"))},500)};window.addEventListener("scroll",fe,{passive:!0});let ge=e=>{e.clientY<=0&&o.contentWindow?.postMessage({type:"bitpalm-exit-intent"},"*")};r.addEventListener("mouseout",ge);let ee,ye=!1,te=()=>{clearTimeout(ee),!ye&&(ee=setTimeout(()=>{ye=!0,o.contentWindow?.postMessage({type:"bitpalm-inactivity"},"*")},15e3))},he=["mousemove","keydown","scroll","touchstart"];he.forEach(e=>r.addEventListener(e,te,{passive:!0})),te(),K=()=>{o.contentWindow?.postMessage({type:"bitpalm-open"},"*");let e=o.src.split("#")[0];o.src=`${e}#bp-open-${Date.now()}`};let be=()=>{if(p.style.display="none",M(),se(),H(),!B){P=!0;return}K()};return{open:be,close:()=>{D(),o.contentWindow?.postMessage({type:"bitpalm-close"},"*")},destroy:()=>{window.removeEventListener("message",re),window.removeEventListener("scroll",fe),window.removeEventListener("popstate",J),r.removeEventListener("mouseout",ge),r.removeEventListener("submit",le,!0),he.forEach(e=>r.removeEventListener(e,te)),clearTimeout(Q),clearTimeout(ee),de.forEach(e=>clearTimeout(e)),history.pushState=pe,history.replaceState=me,D(),M(),p.remove(),o.remove()}}}function Ne(n){if(n==null)return;let t=n.trim().toLowerCase();if(["1","true","yes","on"].includes(t))return!0;if(["0","false","no","off"].includes(t))return!1}if(typeof document<"u"){let n=document.currentScript;if(n?.dataset.slug){let t=()=>{G({slug:n.dataset.slug,locale:n.dataset.locale,baseUrl:n.dataset.baseUrl,token:n.dataset.token,zIndex:n.dataset.zIndex?Number(n.dataset.zIndex):void 0,autoIdentify:Ne(n.dataset.autoIdentify)})};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t):t()}}0&&(module.exports={createWidget});
|
|
1
|
+
"use strict";var se=Object.defineProperty;var $e=Object.getOwnPropertyDescriptor;var He=Object.getOwnPropertyNames;var Ne=Object.prototype.hasOwnProperty;var Fe=(t,n)=>{for(var m in n)se(t,m,{get:n[m],enumerable:!0})},Oe=(t,n,m,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let f of He(n))!Ne.call(t,f)&&f!==m&&se(t,f,{get:()=>n[f],enumerable:!(s=$e(n,f))||s.enumerable});return t};var De=t=>Oe(se({},"__esModule",{value:!0}),t);var Ze={};Fe(Ze,{createWidget:()=>V});module.exports=De(Ze);var Re="https://agents.bitpalm.ae",y="_bp_",Ue=new Set(["password","file","checkbox","radio","submit","button","reset","image"]),We=8e3,Me=`${y}identify_signature`,ke=`${y}identify_fingerprint`,Pe=`${y}identify_sent_at`;function je(t){return[t.external_user_id||"",t.email||"",t.phone||"",t.name||"",t.company||"",t.signature||"",t.signed_at!=null?String(t.signed_at):"",t.signature_version||""].join("|").toLowerCase()}function d(t,n=180){return t?t.replace(/\s+/g," ").trim().slice(0,n):""}function ze(t){return t?` ${t.toLowerCase().replace(/[_-]+/g," ").replace(/[^a-z0-9\s@.]/g," ").replace(/\s+/g," ").trim()} `:""}function D(t,n){for(let m of n)if(t.includes(m))return!0;return!1}function _(t){return/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i.test(t)}function T(t){let n=d(t,50);if(!n)return"";let m=n.startsWith("+"),s=n.replace(/\D/g,"");return s.length<6?"":`${m?"+":""}${s.slice(0,20)}`}function Ce(t){let n=d(t,140).toLowerCase();return!n||!_(n)?"":n}function R(t,n){for(let m of n){let s=t.querySelector(m),f=d(s?.value);if(f)return f}return""}function qe(t){return d(t.getAttribute("data-bp-field")||t.getAttribute("data-bitpalm-field"),64).toLowerCase().replace(/[_\s]+/g,"-")}function Ye(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Je(t,n){let m=[],s=(o,v=140)=>{let l=d(o,v);l&&m.push(l)};s(n.name),s(n.id),s(n.getAttribute("autocomplete")),s(n.getAttribute("placeholder")),s(n.getAttribute("aria-label")),s(n.getAttribute("data-field")),s(n.getAttribute("data-name")),s(n.getAttribute("data-label")),s(n.getAttribute("data-bp-field")),s(n.getAttribute("data-bitpalm-field"));let f=new Set,h=o=>{let v=d(o,200);!v||f.has(v)||(f.add(v),m.push(v))};for(let o of Array.from(n.labels||[]))h(o.textContent);if(n.id){let o=t.querySelector(`label[for="${Ye(n.id)}"]`);h(o?.textContent)}let g=n.closest("label");h(g?.textContent);let r=n.getAttribute("aria-labelledby");if(r)for(let o of r.split(/\s+/)){if(!o)continue;let v=t.ownerDocument.getElementById(o);h(v?.textContent)}return m}function Ge(t){let n=d(R(t,["[data-bp-email]","[data-bitpalm-email]"]),140).toLowerCase(),m=T(R(t,["[data-bp-phone]","[data-bitpalm-phone]"])),s=d(R(t,["[data-bp-name]","[data-bitpalm-name]","[data-bp-full-name]","[data-bitpalm-full-name]"])),f=d(R(t,["[data-bp-first-name]","[data-bitpalm-first-name]"])),h=d(R(t,["[data-bp-last-name]","[data-bitpalm-last-name]"])),g=d(R(t,["[data-bp-company]","[data-bitpalm-company]"]));for(let l of Array.from(t.elements)){if(!(l instanceof HTMLInputElement||l instanceof HTMLTextAreaElement||l instanceof HTMLSelectElement)||l.disabled||l instanceof HTMLInputElement&&Ue.has(l.type.toLowerCase()))continue;let p=qe(l),u=l.hasAttribute("data-bp-email")||l.hasAttribute("data-bitpalm-email")||l.hasAttribute("data-bp-phone")||l.hasAttribute("data-bitpalm-phone")||l.hasAttribute("data-bp-name")||l.hasAttribute("data-bitpalm-name")||l.hasAttribute("data-bp-full-name")||l.hasAttribute("data-bitpalm-full-name")||l.hasAttribute("data-bp-first-name")||l.hasAttribute("data-bitpalm-first-name")||l.hasAttribute("data-bp-last-name")||l.hasAttribute("data-bitpalm-last-name")||l.hasAttribute("data-bp-company")||l.hasAttribute("data-bitpalm-company")||!!p;if(l instanceof HTMLInputElement&&l.type.toLowerCase()==="hidden"&&!u)continue;let c=d(l.value);if(!c)continue;let B=l instanceof HTMLInputElement?l.type.toLowerCase():"",E=ze(Je(t,l).join(" "));if(!n&&p==="email"&&_(c)){n=c.toLowerCase();continue}if(!m&&(p==="phone"||p==="tel"||p==="mobile"||p==="whatsapp")){let I=T(c);if(I){m=I;continue}}if(!g&&p==="company"){g=d(c,160);continue}if(!f&&(p==="first-name"||p==="firstname")){f=d(c,100);continue}if(!h&&(p==="last-name"||p==="lastname"||p==="surname")){h=d(c,100);continue}if(!s&&(p==="name"||p==="full-name"||p==="fullname")){!_(c)&&!T(c)&&(s=d(c,140));continue}let U=B==="email"||D(E,[" email "," e mail "," mail "," email adresse "," mailadresse "," correo "]),$=B==="tel"||D(E,[" phone "," phone number "," mobile "," tel "," telefon "," telefonnummer "," whatsapp "," handy "," kontakt "," nummer "]),H=D(E,[" company "," company name "," firma "," firmenname "," organization "," organisation "," business "," unternehmen "," agency "," brokerage "]),N=D(E,[" first name "," firstname "," given name "," givenname "," vorname "," fname "]),F=D(E,[" last name "," lastname "," family name "," familyname "," surname "," nachname "," lname "]),W=D(E,[" full name "," fullname "," contact name "," name "])&&!U&&!$;if(!n&&U&&_(c)){n=c.toLowerCase();continue}if(!m&&$){let I=T(c);if(I){m=I;continue}}if(!g&&H){g=d(c,160);continue}if(!f&&N){f=d(c,100);continue}if(!h&&F){h=d(c,100);continue}if(!s&&W&&!_(c)&&!T(c)){s=d(c,140);continue}!n&&_(c)&&(n=c.toLowerCase())}if(s&&(_(s)||T(s))&&(s=""),g&&(_(g)||T(g))&&(g=""),s||(s=d([f,h].filter(Boolean).join(" "),140)),s&&n&&s.toLowerCase()===n.toLowerCase()&&(s=""),!!!(n||m)&&!!!(s&&g))return null;let v={...s?{name:s}:{},...n?{email:n}:{},...m?{phone:m}:{},...g?{company:g}:{}};return Object.keys(v).length>0?v:null}function Ve(){if(typeof document<"u"){let t=document.documentElement.lang;if(t)return t.slice(0,2).toLowerCase()}return"en"}function re(t,n=1200){if(typeof window<"u"&&"requestIdleCallback"in window){window.requestIdleCallback(t,{timeout:n});return}setTimeout(t,Math.min(n,300))}function le(){if(typeof window>"u")return!1;let t=typeof navigator<"u"?navigator.userAgent:"";if(/Android|iPhone|iPad|iPod|IEMobile|Windows Phone|Mobile/i.test(t))return!0;let m=window.matchMedia("(pointer: coarse)").matches,s=window.matchMedia("(hover: none)").matches,f=Math.min(window.screen?.width||window.innerWidth,window.screen?.height||window.innerHeight);return m&&s&&f<=900}function V(t){let{slug:n,locale:m=Ve(),baseUrl:s=Re,token:f,zIndex:h=9999,autoIdentify:g=!0}=t,r=document,o=r.createElement("iframe"),v=`${s}/t/${n}/widget`,l=new URLSearchParams({locale:m});f&&l.set("token",f),o.src=`${v}?${l.toString()}`,o.allow="clipboard-write",o.setAttribute("allowtransparency","true"),o.loading="lazy",o.style.cssText=`position:fixed;bottom:0;right:0;width:1px;height:1px;border:none;z-index:${h};background:transparent;color-scheme:normal;opacity:0;pointer-events:none;`;let p=new URL(o.src).origin,u=r.createElement("div");if(u.setAttribute("role","button"),u.setAttribute("aria-label","Chat"),u.style.cssText=`position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;display:none;align-items:center;justify-content:center;cursor:pointer;z-index:${h-1};background:#00ff41;box-shadow:0 0 15px rgba(0,255,65,0.31);transition:transform .2s,opacity .3s;opacity:0;`,u.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',u.onmouseenter=()=>{u.style.transform="scale(1.1)"},u.onmouseleave=()=>{u.style.transform="scale(1)"},u.onclick=()=>Ee(),r.body.appendChild(u),!r.getElementById("_bp_fade")){let e=r.createElement("style");e.id="_bp_fade",e.textContent="@keyframes _bp_fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}",r.head.appendChild(e)}let c=null,B=!1,E=!1,U=!1,$=!1,H=!1,N=()=>{U||(U=!0,r.body.appendChild(o))},F=!1,W=0,I={overflow:"",overscrollBehavior:""},b={overflow:"",overscrollBehavior:"",position:"",top:"",left:"",right:"",width:""},ce=()=>{if(F||!le())return;let a=r.documentElement,i=r.body;W=window.scrollY||window.pageYOffset||0,I.overflow=a.style.overflow,I.overscrollBehavior=a.style.overscrollBehavior,b.overflow=i.style.overflow,b.overscrollBehavior=i.style.overscrollBehavior,b.position=i.style.position,b.top=i.style.top,b.left=i.style.left,b.right=i.style.right,b.width=i.style.width,a.style.overflow="hidden",a.style.overscrollBehavior="none",i.style.overflow="hidden",i.style.overscrollBehavior="none",i.style.position="fixed",i.style.top=`-${W}px`,i.style.left="0",i.style.right="0",i.style.width="100%",F=!0},O=()=>{if(!F)return;let e=r.documentElement,a=r.body;e.style.overflow=I.overflow,e.style.overscrollBehavior=I.overscrollBehavior,a.style.overflow=b.overflow,a.style.overscrollBehavior=b.overscrollBehavior,a.style.position=b.position,a.style.top=b.top,a.style.left=b.left,a.style.right=b.right,a.style.width=b.width,window.scrollTo(0,W),F=!1},de=()=>{let e=le();o.style.display==="none"&&(o.style.display=""),e?(o.style.width="100vw",o.style.height="100dvh",o.style.left="0",o.style.top="0",ce()):(o.style.width="420px",o.style.height="620px",o.style.left="",o.style.top="",O()),o.style.opacity="1",o.style.pointerEvents="auto"},M=()=>{c&&(c.remove(),c=null)},z=()=>{},K=()=>{},me=e=>{if(e.origin===p){if(e.data?.type==="bitpalm-widget-config"){E=!1,B=!0,o.style.display==="none"&&(o.style.display=""),e.data.primaryColor&&(u.style.background=e.data.primaryColor,u.style.boxShadow=e.data.chatShadow==="none"?"none":`0 0 15px ${e.data.primaryColor}50`);let a=e.data.chatButtonIconColor||"black";if(e.data.chatButtonIconSvg){u.innerHTML="";let i=r.createElement("span");i.style.cssText=`display:flex;align-items:center;justify-content:center;width:24px;height:24px;color:${a}`;let S=new DOMParser().parseFromString(e.data.chatButtonIconSvg,"image/svg+xml").querySelector("svg");S?(S.querySelectorAll("script,foreignObject").forEach(P=>P.remove()),S.querySelectorAll("*").forEach(P=>{for(let C of[...P.attributes])(C.name.startsWith("on")||C.value&&C.value.includes("javascript:"))&&P.removeAttribute(C.name)}),S.setAttribute("width","24"),S.setAttribute("height","24"),S.style.display="block",i.appendChild(S)):i.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',u.appendChild(i)}else{let i=u.querySelector("svg");i&&(i.style.stroke=a)}u.style.display="flex",requestAnimationFrame(()=>{u.style.opacity="1"})}if(e.data?.type==="bitpalm-widget-resize"){let a=e.data.width>0,i=le();a?(o.style.width=i?"100vw":`${e.data.width}px`,o.style.height=i?"100dvh":`${e.data.height}px`,i?(o.style.left="0",o.style.top="0",ce()):O(),o.style.opacity="1",o.style.pointerEvents="auto"):(O(),o.style.width="1px",o.style.height="1px",o.style.left="",o.style.top="",o.style.opacity="0",o.style.pointerEvents="none"),u.style.display=a?"none":"flex"}if(e.data?.type==="bitpalm-trigger-show"){if(E||!B)return;M(),c=r.createElement("div"),c.style.cssText=`position:fixed;bottom:90px;right:24px;max-width:240px;background:#fff;border-radius:16px;padding:12px 32px 12px 12px;box-shadow:0 2px 20px rgba(0,0,0,0.08);cursor:pointer;z-index:${h-1};font-family:system-ui,sans-serif;animation:_bp_fade .3s;`;let a=(e.data.message||"").replace(/</g,"<");c.innerHTML=`<p style="font-size:14px;color:#1f2937;margin:0;">${a}</p><div style="position:absolute;bottom:-8px;right:20px;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #fff;"></div>`;let i=r.createElement("button");i.style.cssText="position:absolute;top:-8px;right:-8px;width:28px;height:28px;border-radius:50%;background:#fff;border:none;box-shadow:0 1px 4px rgba(0,0,0,0.1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;color:#9ca3af;",i.innerHTML="✕",i.onclick=w=>{w.stopPropagation(),M(),o.contentWindow?.postMessage({type:"bitpalm-trigger-dismiss"},"*")},c.onclick=()=>{if(M(),u.style.display="none",de(),N(),!$){H=!0;return}o.contentWindow?.postMessage({type:"bitpalm-trigger-engaged"},"*")},c.appendChild(i),r.body.appendChild(c)}e.data?.type==="bitpalm-trigger-hide"&&M(),e.data?.type==="bitpalm-request-context"&&z(),e.data?.type==="bitpalm-widget-blocked"&&(E=!0,B=!1,u.style.display="none",M(),O(),o.style.display="none")}};window.addEventListener("message",me);let L=!1;try{L=localStorage.getItem(`${y}optout`)==="1"}catch{}let q=`${y}vid`,x="";if(!L){try{x=localStorage.getItem(q)||""}catch{}if(!x){let e=r.cookie.match(new RegExp(`(?:^|; )${q}=([^;]+)`));x=e?decodeURIComponent(e[1]):""}x||(x=crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,11)}`);try{localStorage.setItem(q,x)}catch{}try{r.cookie=`${q}=${encodeURIComponent(x)};path=/;max-age=31536000;SameSite=Lax`}catch{}}L||re(()=>{try{let e=new URLSearchParams(location.search),a={};for(let A of["utm_source","utm_medium","utm_campaign","utm_term","utm_content"]){let S=e.get(A);S&&(a[A]=S)}let i=JSON.stringify({tenant_slug:n,visitor_id:x,url:location.href,referrer:r.referrer||void 0,...Object.keys(a).length>0?{utm:a}:{}}),w=`${s}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(w,new Blob([i],{type:"application/json"})):fetch(w,{method:"POST",body:i,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}},2e3);let Z="",X="",Q=0;try{Z=sessionStorage.getItem(Me)||"",X=sessionStorage.getItem(ke)||"";let e=parseInt(sessionStorage.getItem(Pe)||"0",10);Number.isFinite(e)&&e>0&&(Q=e)}catch{}let ue=(e,a="")=>{if(L||!x)return;let i={},w=d(e.name,140),A=Ce(e.email),S=T(e.phone),P=d(e.company,160),C=d(e.external_user_id,140),Te=d(e.signature,260),ie=Number(e.signed_at);if(w&&(i.name=w),A&&(i.email=A),S&&(i.phone=S),P&&(i.company=P),C&&(i.external_user_id=C),Te&&(i.signature=Te),Number.isFinite(ie)&&ie>0&&(i.signed_at=Math.floor(ie)),(e.signature_version==="v1"||i.signature)&&(i.signature_version="v1"),!i.name&&!i.email&&!i.phone&&!i.company&&!i.external_user_id)return;let G=je(i),oe=[a.toLowerCase(),G].filter(Boolean).join("|"),ae=Date.now();if(!(ae-Q<We&&(oe===Z||G===X))){Z=oe,X=G,Q=ae;try{sessionStorage.setItem(Me,oe),sessionStorage.setItem(ke,G),sessionStorage.setItem(Pe,String(ae))}catch{}try{let Ae=JSON.stringify({tenant_slug:n,visitor_id:x,url:location.href,referrer:r.referrer||void 0,...i}),_e=`${s}/api/widget/identify`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(_e,new Blob([Ae],{type:"application/json"})):fetch(_e,{method:"POST",body:Ae,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}}},fe=e=>{if(L||!g||!x)return;let a=e.target instanceof HTMLFormElement?e.target:e.target instanceof Element?e.target.closest("form"):null;if(!(a instanceof HTMLFormElement))return;let i=(a.getAttribute("data-bp-identify")||a.getAttribute("data-bitpalm-identify")||"").toLowerCase();if(i==="off"||i==="false"||i==="0")return;let w=Ge(a);if(!w)return;let A=[a.getAttribute("id")||"",a.getAttribute("name")||"",a.getAttribute("action")||""].join("|");ue(w,A)};!L&&g&&r.addEventListener("submit",fe,!0);let j=parseInt(sessionStorage.getItem(`${y}pages`)||"0")+1;sessionStorage.setItem(`${y}pages`,String(j));let k=JSON.parse(sessionStorage.getItem(`${y}hist`)||"[]");k.push(location.href),k.length>20&&(k=k.slice(-20)),sessionStorage.setItem(`${y}hist`,JSON.stringify(k));let pe=Date.now(),Y=parseInt(sessionStorage.getItem(`${y}site_start`)||"0");Y||(Y=pe,sessionStorage.setItem(`${y}site_start`,String(Y)));let ge=[];z=()=>{let e=!1;try{e=!!localStorage.getItem(`${y}visited`)}catch{e=!1}if(o.contentWindow?.postMessage({type:"bitpalm-parent-context",url:location.href,title:r.title,returning:e,pageCount:j,pageHistory:k,loadedAt:pe,siteStart:Y,locale:m,visitorId:L?"":x},"*"),!e&&!L)try{localStorage.setItem(`${y}visited`,"1")}catch{}},o.addEventListener("load",()=>{$=!0,z(),[120,450,1100].forEach(e=>{let a=setTimeout(()=>z(),e);ge.push(a)}),H&&(H=!1,K())}),r.readyState==="loading"?r.addEventListener("DOMContentLoaded",()=>re(N,1600),{once:!0}):re(N,1600);let ye=history.pushState.bind(history),he=history.replaceState.bind(history),J=()=>{j++,sessionStorage.setItem(`${y}pages`,String(j));let e=JSON.parse(sessionStorage.getItem(`${y}hist`)||"[]");if(e.push(location.href),e.length>20&&e.splice(0,e.length-20),k=e,sessionStorage.setItem(`${y}hist`,JSON.stringify(e)),o.contentWindow?.postMessage({type:"bitpalm-page-change",url:location.href,title:r.title,pageCount:j,pageHistory:e,loadedAt:Date.now()},"*"),!L)try{let a=JSON.stringify({tenant_slug:n,visitor_id:x,url:location.href}),i=`${s}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(i,new Blob([a],{type:"application/json"})):fetch(i,{method:"POST",body:a,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}};history.pushState=function(...e){ye(...e),J()},history.replaceState=function(...e){he(...e),J()},window.addEventListener("popstate",J);let be=-1,ee,we=()=>{clearTimeout(ee),ee=setTimeout(()=>{let e=Math.max(r.documentElement.scrollHeight,r.body.scrollHeight)-window.innerHeight,a=e>0?Math.round(window.scrollY/e*100):100;a!==be&&(be=a,o.contentWindow?.postMessage({type:"bitpalm-scroll-depth",percent:a},"*"))},500)};window.addEventListener("scroll",we,{passive:!0});let ve=e=>{e.clientY<=0&&o.contentWindow?.postMessage({type:"bitpalm-exit-intent"},"*")};r.addEventListener("mouseout",ve);let te,xe=!1,ne=()=>{clearTimeout(te),!xe&&(te=setTimeout(()=>{xe=!0,o.contentWindow?.postMessage({type:"bitpalm-inactivity"},"*")},15e3))},Se=["mousemove","keydown","scroll","touchstart"];Se.forEach(e=>r.addEventListener(e,ne,{passive:!0})),ne(),K=()=>{o.contentWindow?.postMessage({type:"bitpalm-open"},"*");let e=o.src.split("#")[0];o.src=`${e}#bp-open-${Date.now()}`};let Ee=()=>{if(u.style.display="none",M(),de(),N(),!$){H=!0;return}K()},Be=()=>{O(),o.contentWindow?.postMessage({type:"bitpalm-close"},"*")},Ie=e=>{!e||typeof e!="object"||ue({external_user_id:d(e.externalUserId,140)||void 0,name:d(e.name,140)||void 0,email:Ce(e.email)||void 0,phone:T(e.phone)||void 0,company:d(e.company,160)||void 0,signature:d(e.signature,260)||void 0,signed_at:Number.isFinite(Number(e.signedAt))?Math.floor(Number(e.signedAt)):void 0,signature_version:e.signatureVersion==="v1"?"v1":void 0},"manual")},Le=e=>{let i=e.detail;if(!i||typeof i!="object")return;let w=d(i.slug,120);w&&w!==n||Ie(i)};return window.addEventListener("bitpalm-identify",Le),{open:Ee,close:Be,identify:Ie,destroy:()=>{window.removeEventListener("message",me),window.removeEventListener("scroll",we),window.removeEventListener("popstate",J),r.removeEventListener("mouseout",ve),r.removeEventListener("submit",fe,!0),Se.forEach(e=>r.removeEventListener(e,ne)),clearTimeout(ee),clearTimeout(te),ge.forEach(e=>clearTimeout(e)),history.pushState=ye,history.replaceState=he,window.removeEventListener("bitpalm-identify",Le),O(),M(),u.remove(),o.remove()}}}function Ke(t){if(t==null)return;let n=t.trim().toLowerCase();if(["1","true","yes","on"].includes(n))return!0;if(["0","false","no","off"].includes(n))return!1}if(typeof document<"u"){let t=document.currentScript;if(t?.dataset.slug){let n=()=>{V({slug:t.dataset.slug,locale:t.dataset.locale,baseUrl:t.dataset.baseUrl,token:t.dataset.token,zIndex:t.dataset.zIndex?Number(t.dataset.zIndex):void 0,autoIdentify:Ke(t.dataset.autoIdentify)})};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n):n()}}0&&(module.exports={createWidget});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/widget.ts"],"sourcesContent":["export { createWidget } from \"./widget\";\nexport type { BitPalmAgentOptions, BitPalmAgentInstance } from \"./types\";\n\nimport { createWidget } from \"./widget\";\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value == null) return undefined;\n const normalized = value.trim().toLowerCase();\n if ([\"1\", \"true\", \"yes\", \"on\"].includes(normalized)) return true;\n if ([\"0\", \"false\", \"no\", \"off\"].includes(normalized)) return false;\n return undefined;\n}\n\n/**\n * Auto-init from script tag:\n * <script src=\"https://cdn.bitpalm.ae/widget.js\" data-slug=\"my-agent\"></script>\n */\nif (typeof document !== \"undefined\") {\n const script = document.currentScript as HTMLScriptElement | null;\n if (script?.dataset.slug) {\n const init = () => {\n createWidget({\n slug: script!.dataset.slug!,\n locale: script!.dataset.locale,\n baseUrl: script!.dataset.baseUrl,\n token: script!.dataset.token,\n zIndex: script!.dataset.zIndex ? Number(script!.dataset.zIndex) : undefined,\n autoIdentify: parseBoolean(script!.dataset.autoIdentify),\n });\n };\n\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", init);\n } else {\n init();\n }\n }\n}\n","import type { BitPalmAgentOptions, BitPalmAgentInstance } from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://agents.bitpalm.ae\";\nconst STORAGE_PREFIX = \"_bp_\";\nconst IGNORED_INPUT_TYPES = new Set([\"password\", \"file\", \"checkbox\", \"radio\", \"submit\", \"button\", \"reset\", \"image\"]);\nconst IDENTITY_DEDUPE_WINDOW_MS = 8_000;\nconst IDENTITY_SIGNATURE_KEY = `${STORAGE_PREFIX}identify_signature`;\nconst IDENTITY_FINGERPRINT_KEY = `${STORAGE_PREFIX}identify_fingerprint`;\nconst IDENTITY_SENT_AT_KEY = `${STORAGE_PREFIX}identify_sent_at`;\n\ntype FormFieldElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n\ntype IdentityPayload = {\n name?: string;\n email?: string;\n phone?: string;\n company?: string;\n};\n\nfunction normalizeText(value: string | null | undefined, maxLen = 180): string {\n if (!value) return \"\";\n return value.replace(/\\s+/g, \" \").trim().slice(0, maxLen);\n}\n\nfunction normalizeTokens(value: string | null | undefined): string {\n if (!value) return \"\";\n return ` ${value.toLowerCase().replace(/[_-]+/g, \" \").replace(/[^a-z0-9\\s@.]/g, \" \").replace(/\\s+/g, \" \").trim()} `;\n}\n\nfunction includesAny(haystack: string, needles: string[]): boolean {\n for (const needle of needles) {\n if (haystack.includes(needle)) return true;\n }\n return false;\n}\n\nfunction isEmail(value: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/i.test(value);\n}\n\nfunction normalizePhone(value: string): string {\n const trimmed = normalizeText(value, 50);\n if (!trimmed) return \"\";\n const hasPlus = trimmed.startsWith(\"+\");\n const digits = trimmed.replace(/\\D/g, \"\");\n if (digits.length < 6) return \"\";\n return `${hasPlus ? \"+\" : \"\"}${digits.slice(0, 20)}`;\n}\n\nfunction getExplicitValue(form: HTMLFormElement, selectors: string[]): string {\n for (const selector of selectors) {\n const el = form.querySelector<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>(selector);\n const value = normalizeText(el?.value);\n if (value) return value;\n }\n return \"\";\n}\n\nfunction getFieldHint(el: FormFieldElement): string {\n return normalizeText(el.getAttribute(\"data-bp-field\") || el.getAttribute(\"data-bitpalm-field\"), 64)\n .toLowerCase()\n .replace(/[_\\s]+/g, \"-\");\n}\n\nfunction escapeAttrSelectorValue(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction collectElementTokenParts(form: HTMLFormElement, el: FormFieldElement): string[] {\n const parts: string[] = [];\n const pushText = (value: string | null | undefined, maxLen = 140) => {\n const clean = normalizeText(value, maxLen);\n if (clean) parts.push(clean);\n };\n\n pushText(el.name);\n pushText(el.id);\n pushText(el.getAttribute(\"autocomplete\"));\n pushText(el.getAttribute(\"placeholder\"));\n pushText(el.getAttribute(\"aria-label\"));\n pushText(el.getAttribute(\"data-field\"));\n pushText(el.getAttribute(\"data-name\"));\n pushText(el.getAttribute(\"data-label\"));\n pushText(el.getAttribute(\"data-bp-field\"));\n pushText(el.getAttribute(\"data-bitpalm-field\"));\n\n const seenLabels = new Set<string>();\n const pushLabel = (value: string | null | undefined) => {\n const label = normalizeText(value, 200);\n if (!label || seenLabels.has(label)) return;\n seenLabels.add(label);\n parts.push(label);\n };\n\n for (const label of Array.from(el.labels || [])) {\n pushLabel(label.textContent);\n }\n\n if (el.id) {\n const forLabel = form.querySelector(`label[for=\"${escapeAttrSelectorValue(el.id)}\"]`);\n pushLabel(forLabel?.textContent);\n }\n\n const nearestLabel = el.closest(\"label\");\n pushLabel(nearestLabel?.textContent);\n\n const ariaLabelledBy = el.getAttribute(\"aria-labelledby\");\n if (ariaLabelledBy) {\n for (const id of ariaLabelledBy.split(/\\s+/)) {\n if (!id) continue;\n const ref = form.ownerDocument.getElementById(id);\n pushLabel(ref?.textContent);\n }\n }\n\n return parts;\n}\n\nfunction extractIdentityFromForm(form: HTMLFormElement): IdentityPayload | null {\n let email = normalizeText(getExplicitValue(form, [\n \"[data-bp-email]\",\n \"[data-bitpalm-email]\",\n ]), 140).toLowerCase();\n\n let phone = normalizePhone(getExplicitValue(form, [\n \"[data-bp-phone]\",\n \"[data-bitpalm-phone]\",\n ]));\n\n let name = normalizeText(getExplicitValue(form, [\n \"[data-bp-name]\",\n \"[data-bitpalm-name]\",\n \"[data-bp-full-name]\",\n \"[data-bitpalm-full-name]\",\n ]));\n\n let firstName = normalizeText(getExplicitValue(form, [\n \"[data-bp-first-name]\",\n \"[data-bitpalm-first-name]\",\n ]));\n\n let lastName = normalizeText(getExplicitValue(form, [\n \"[data-bp-last-name]\",\n \"[data-bitpalm-last-name]\",\n ]));\n\n let company = normalizeText(getExplicitValue(form, [\n \"[data-bp-company]\",\n \"[data-bitpalm-company]\",\n ]));\n\n for (const rawEl of Array.from(form.elements)) {\n if (!(rawEl instanceof HTMLInputElement || rawEl instanceof HTMLTextAreaElement || rawEl instanceof HTMLSelectElement)) continue;\n if (rawEl.disabled) continue;\n if (rawEl instanceof HTMLInputElement && IGNORED_INPUT_TYPES.has(rawEl.type.toLowerCase())) continue;\n const fieldHint = getFieldHint(rawEl);\n\n const explicitField =\n rawEl.hasAttribute(\"data-bp-email\") ||\n rawEl.hasAttribute(\"data-bitpalm-email\") ||\n rawEl.hasAttribute(\"data-bp-phone\") ||\n rawEl.hasAttribute(\"data-bitpalm-phone\") ||\n rawEl.hasAttribute(\"data-bp-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-name\") ||\n rawEl.hasAttribute(\"data-bp-full-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-full-name\") ||\n rawEl.hasAttribute(\"data-bp-first-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-first-name\") ||\n rawEl.hasAttribute(\"data-bp-last-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-last-name\") ||\n rawEl.hasAttribute(\"data-bp-company\") ||\n rawEl.hasAttribute(\"data-bitpalm-company\") ||\n !!fieldHint;\n\n if (rawEl instanceof HTMLInputElement && rawEl.type.toLowerCase() === \"hidden\" && !explicitField) continue;\n\n const value = normalizeText(rawEl.value);\n if (!value) continue;\n\n const type = rawEl instanceof HTMLInputElement ? rawEl.type.toLowerCase() : \"\";\n const tokens = normalizeTokens(collectElementTokenParts(form, rawEl).join(\" \"));\n\n if (!email && fieldHint === \"email\" && isEmail(value)) {\n email = value.toLowerCase();\n continue;\n }\n if (!phone && (fieldHint === \"phone\" || fieldHint === \"tel\" || fieldHint === \"mobile\" || fieldHint === \"whatsapp\")) {\n const normalized = normalizePhone(value);\n if (normalized) {\n phone = normalized;\n continue;\n }\n }\n if (!company && fieldHint === \"company\") {\n company = normalizeText(value, 160);\n continue;\n }\n if (!firstName && (fieldHint === \"first-name\" || fieldHint === \"firstname\")) {\n firstName = normalizeText(value, 100);\n continue;\n }\n if (!lastName && (fieldHint === \"last-name\" || fieldHint === \"lastname\" || fieldHint === \"surname\")) {\n lastName = normalizeText(value, 100);\n continue;\n }\n if (!name && (fieldHint === \"name\" || fieldHint === \"full-name\" || fieldHint === \"fullname\")) {\n if (!isEmail(value) && !normalizePhone(value)) name = normalizeText(value, 140);\n continue;\n }\n\n const emailLike = type === \"email\" || includesAny(tokens, [\" email \", \" e mail \", \" mail \", \" email adresse \", \" mailadresse \", \" correo \"]);\n const phoneLike = type === \"tel\" || includesAny(tokens, [\" phone \", \" phone number \", \" mobile \", \" tel \", \" telefon \", \" telefonnummer \", \" whatsapp \", \" handy \", \" kontakt \", \" nummer \"]);\n const companyLike = includesAny(tokens, [\" company \", \" company name \", \" firma \", \" firmenname \", \" organization \", \" organisation \", \" business \", \" unternehmen \", \" agency \", \" brokerage \"]);\n const firstNameLike = includesAny(tokens, [\" first name \", \" firstname \", \" given name \", \" givenname \", \" vorname \", \" fname \"]);\n const lastNameLike = includesAny(tokens, [\" last name \", \" lastname \", \" family name \", \" familyname \", \" surname \", \" nachname \", \" lname \"]);\n const fullNameLike = includesAny(tokens, [\" full name \", \" fullname \", \" contact name \", \" name \"]) && !emailLike && !phoneLike;\n\n if (!email && emailLike && isEmail(value)) {\n email = value.toLowerCase();\n continue;\n }\n if (!phone && phoneLike) {\n const normalized = normalizePhone(value);\n if (normalized) {\n phone = normalized;\n continue;\n }\n }\n if (!company && companyLike) {\n company = normalizeText(value, 160);\n continue;\n }\n if (!firstName && firstNameLike) {\n firstName = normalizeText(value, 100);\n continue;\n }\n if (!lastName && lastNameLike) {\n lastName = normalizeText(value, 100);\n continue;\n }\n if (!name && fullNameLike && !isEmail(value) && !normalizePhone(value)) {\n name = normalizeText(value, 140);\n continue;\n }\n\n if (!email && isEmail(value)) {\n email = value.toLowerCase();\n }\n }\n\n if (name && (isEmail(name) || normalizePhone(name))) {\n name = \"\";\n }\n if (company && (isEmail(company) || normalizePhone(company))) {\n company = \"\";\n }\n\n if (!name) {\n name = normalizeText([firstName, lastName].filter(Boolean).join(\" \"), 140);\n }\n\n if (name && email && name.toLowerCase() === email.toLowerCase()) {\n name = \"\";\n }\n\n const hasContactSignal = !!(email || phone);\n const hasStrongProfileSignal = !!(name && company);\n if (!hasContactSignal && !hasStrongProfileSignal) {\n return null;\n }\n\n const identity: IdentityPayload = {\n ...(name ? { name } : {}),\n ...(email ? { email } : {}),\n ...(phone ? { phone } : {}),\n ...(company ? { company } : {}),\n };\n\n return Object.keys(identity).length > 0 ? identity : null;\n}\n\nfunction detectLocale(): string {\n if (typeof document !== \"undefined\") {\n const lang = document.documentElement.lang;\n if (lang) return lang.slice(0, 2).toLowerCase();\n }\n return \"en\";\n}\n\nfunction runWhenIdle(task: () => void, timeout = 1200) {\n if (typeof window !== \"undefined\" && \"requestIdleCallback\" in window) {\n (\n window as unknown as {\n requestIdleCallback: (cb: () => void, opts?: { timeout?: number }) => number;\n }\n ).requestIdleCallback(task, { timeout });\n return;\n }\n setTimeout(task, Math.min(timeout, 300));\n}\n\nfunction isMobileWidgetDevice(): boolean {\n if (typeof window === \"undefined\") return false;\n const userAgent = typeof navigator !== \"undefined\" ? navigator.userAgent : \"\";\n const isMobileUa = /Android|iPhone|iPad|iPod|IEMobile|Windows Phone|Mobile/i.test(userAgent);\n if (isMobileUa) return true;\n\n const coarsePointer = window.matchMedia(\"(pointer: coarse)\").matches;\n const noHover = window.matchMedia(\"(hover: none)\").matches;\n const minScreenSide = Math.min(\n window.screen?.width || window.innerWidth,\n window.screen?.height || window.innerHeight,\n );\n return coarsePointer && noHover && minScreenSide <= 900;\n}\n\nexport function createWidget(options: BitPalmAgentOptions): BitPalmAgentInstance {\n const {\n slug,\n locale = detectLocale(),\n baseUrl = DEFAULT_BASE_URL,\n token,\n zIndex = 9999,\n autoIdentify = true,\n } = options;\n\n const d = document;\n\n // --- Iframe ---\n const iframe = d.createElement(\"iframe\");\n const widgetUrl = `${baseUrl}/t/${slug}/widget`;\n const qs = new URLSearchParams({ locale });\n if (token) qs.set(\"token\", token);\n iframe.src = `${widgetUrl}?${qs.toString()}`;\n iframe.allow = \"clipboard-write\";\n iframe.setAttribute(\"allowtransparency\", \"true\");\n iframe.loading = \"lazy\";\n iframe.style.cssText = `position:fixed;bottom:0;right:0;width:1px;height:1px;border:none;z-index:${zIndex};background:transparent;color-scheme:normal;opacity:0;pointer-events:none;`;\n\n const origin = new URL(iframe.src).origin;\n\n // --- Native launcher button ---\n const btn = d.createElement(\"div\");\n btn.setAttribute(\"role\", \"button\");\n btn.setAttribute(\"aria-label\", \"Chat\");\n btn.style.cssText = `position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;display:none;align-items:center;justify-content:center;cursor:pointer;z-index:${zIndex - 1};background:#00ff41;box-shadow:0 0 15px rgba(0,255,65,0.31);transition:transform .2s,opacity .3s;opacity:0;`;\n btn.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"black\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\"/></svg>';\n btn.onmouseenter = () => { btn.style.transform = \"scale(1.1)\"; };\n btn.onmouseleave = () => { btn.style.transform = \"scale(1)\"; };\n btn.onclick = () => openWidget();\n d.body.appendChild(btn);\n\n // --- Fade animation for trigger bubbles ---\n if (!d.getElementById(\"_bp_fade\")) {\n const s = d.createElement(\"style\");\n s.id = \"_bp_fade\";\n s.textContent = \"@keyframes _bp_fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\";\n d.head.appendChild(s);\n }\n\n // --- Trigger bubble ---\n let bubble: HTMLDivElement | null = null;\n let launcherReady = false;\n let widgetBlocked = false;\n let iframeMounted = false;\n let iframeReady = false;\n let pendingOpen = false;\n const mountIframe = () => {\n if (iframeMounted) return;\n iframeMounted = true;\n d.body.appendChild(iframe);\n };\n let mobileScrollLocked = false;\n let scrollLockY = 0;\n const prevHtmlStyle = {\n overflow: \"\",\n overscrollBehavior: \"\",\n };\n const prevBodyStyle = {\n overflow: \"\",\n overscrollBehavior: \"\",\n position: \"\",\n top: \"\",\n left: \"\",\n right: \"\",\n width: \"\",\n };\n const lockMobilePageScroll = () => {\n if (mobileScrollLocked) return;\n const mobile = isMobileWidgetDevice();\n if (!mobile) return;\n const html = d.documentElement;\n const body = d.body;\n scrollLockY = window.scrollY || window.pageYOffset || 0;\n prevHtmlStyle.overflow = html.style.overflow;\n prevHtmlStyle.overscrollBehavior = html.style.overscrollBehavior;\n prevBodyStyle.overflow = body.style.overflow;\n prevBodyStyle.overscrollBehavior = body.style.overscrollBehavior;\n prevBodyStyle.position = body.style.position;\n prevBodyStyle.top = body.style.top;\n prevBodyStyle.left = body.style.left;\n prevBodyStyle.right = body.style.right;\n prevBodyStyle.width = body.style.width;\n html.style.overflow = \"hidden\";\n html.style.overscrollBehavior = \"none\";\n body.style.overflow = \"hidden\";\n body.style.overscrollBehavior = \"none\";\n body.style.position = \"fixed\";\n body.style.top = `-${scrollLockY}px`;\n body.style.left = \"0\";\n body.style.right = \"0\";\n body.style.width = \"100%\";\n mobileScrollLocked = true;\n };\n const unlockMobilePageScroll = () => {\n if (!mobileScrollLocked) return;\n const html = d.documentElement;\n const body = d.body;\n html.style.overflow = prevHtmlStyle.overflow;\n html.style.overscrollBehavior = prevHtmlStyle.overscrollBehavior;\n body.style.overflow = prevBodyStyle.overflow;\n body.style.overscrollBehavior = prevBodyStyle.overscrollBehavior;\n body.style.position = prevBodyStyle.position;\n body.style.top = prevBodyStyle.top;\n body.style.left = prevBodyStyle.left;\n body.style.right = prevBodyStyle.right;\n body.style.width = prevBodyStyle.width;\n window.scrollTo(0, scrollLockY);\n mobileScrollLocked = false;\n };\n const prepareIframeForOpen = () => {\n const mobile = isMobileWidgetDevice();\n if (iframe.style.display === \"none\") iframe.style.display = \"\";\n if (mobile) {\n iframe.style.width = \"100vw\";\n iframe.style.height = \"100dvh\";\n iframe.style.left = \"0\";\n iframe.style.top = \"0\";\n lockMobilePageScroll();\n } else {\n // Match desktop widget target size so the opening animation is visible from frame 1.\n iframe.style.width = \"420px\";\n iframe.style.height = \"620px\";\n iframe.style.left = \"\";\n iframe.style.top = \"\";\n unlockMobilePageScroll();\n }\n iframe.style.opacity = \"1\";\n iframe.style.pointerEvents = \"auto\";\n };\n const removeBubble = () => {\n if (bubble) { bubble.remove(); bubble = null; }\n };\n let sendParentContext = () => {};\n let sendOpenSignal = () => {};\n\n // --- postMessage handler ---\n const handleMessage = (e: MessageEvent) => {\n if (e.origin !== origin) return;\n\n // Widget config (colors, icon)\n if (e.data?.type === \"bitpalm-widget-config\") {\n widgetBlocked = false;\n launcherReady = true;\n if (iframe.style.display === \"none\") iframe.style.display = \"\";\n if (e.data.primaryColor) {\n btn.style.background = e.data.primaryColor;\n btn.style.boxShadow = e.data.chatShadow === \"none\" ? \"none\" : `0 0 15px ${e.data.primaryColor}50`;\n }\n const ic = e.data.chatButtonIconColor || \"black\";\n if (e.data.chatButtonIconSvg) {\n btn.innerHTML = \"\";\n const sp = d.createElement(\"span\");\n sp.style.cssText = `display:flex;align-items:center;justify-content:center;width:24px;height:24px;color:${ic}`;\n const parser = new DOMParser();\n const doc = parser.parseFromString(e.data.chatButtonIconSvg, \"image/svg+xml\");\n const svg = doc.querySelector(\"svg\");\n if (svg) {\n // Remove dangerous elements and attributes\n svg.querySelectorAll(\"script,foreignObject\").forEach(el => el.remove());\n svg.querySelectorAll(\"*\").forEach(el => {\n for (const attr of [...el.attributes]) {\n if (attr.name.startsWith(\"on\") || (attr.value && attr.value.includes(\"javascript:\"))) {\n el.removeAttribute(attr.name);\n }\n }\n });\n svg.setAttribute(\"width\", \"24\");\n svg.setAttribute(\"height\", \"24\");\n svg.style.display = \"block\";\n sp.appendChild(svg);\n } else {\n // Fallback: use default icon\n sp.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\"/></svg>';\n }\n btn.appendChild(sp);\n } else {\n const sv = btn.querySelector(\"svg\");\n if (sv) (sv as SVGElement).style.stroke = ic;\n }\n btn.style.display = \"flex\";\n // Fade in after styles are applied\n requestAnimationFrame(() => { btn.style.opacity = \"1\"; });\n }\n\n // Resize — use full viewport on mobile\n if (e.data?.type === \"bitpalm-widget-resize\") {\n const isOpen = e.data.width > 0;\n const mobile = isMobileWidgetDevice();\n if (isOpen) {\n iframe.style.width = mobile ? \"100vw\" : `${e.data.width}px`;\n iframe.style.height = mobile ? \"100dvh\" : `${e.data.height}px`;\n if (mobile) {\n iframe.style.left = \"0\";\n iframe.style.top = \"0\";\n lockMobilePageScroll();\n } else {\n unlockMobilePageScroll();\n }\n iframe.style.opacity = \"1\";\n iframe.style.pointerEvents = \"auto\";\n } else {\n unlockMobilePageScroll();\n iframe.style.width = \"1px\";\n iframe.style.height = \"1px\";\n iframe.style.left = \"\";\n iframe.style.top = \"\";\n iframe.style.opacity = \"0\";\n iframe.style.pointerEvents = \"none\";\n }\n btn.style.display = isOpen ? \"none\" : \"flex\";\n }\n\n // Trigger bubble show\n if (e.data?.type === \"bitpalm-trigger-show\") {\n if (widgetBlocked || !launcherReady) return;\n removeBubble();\n bubble = d.createElement(\"div\");\n bubble.style.cssText = `position:fixed;bottom:90px;right:24px;max-width:240px;background:#fff;border-radius:16px;padding:12px 32px 12px 12px;box-shadow:0 2px 20px rgba(0,0,0,0.08);cursor:pointer;z-index:${zIndex - 1};font-family:system-ui,sans-serif;animation:_bp_fade .3s;`;\n const msg = (e.data.message || \"\").replace(/</g, \"<\");\n bubble.innerHTML = `<p style=\"font-size:14px;color:#1f2937;margin:0;\">${msg}</p><div style=\"position:absolute;bottom:-8px;right:20px;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #fff;\"></div>`;\n const close = d.createElement(\"button\");\n close.style.cssText = \"position:absolute;top:-8px;right:-8px;width:28px;height:28px;border-radius:50%;background:#fff;border:none;box-shadow:0 1px 4px rgba(0,0,0,0.1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;color:#9ca3af;\";\n close.innerHTML = \"✕\";\n close.onclick = (ev) => { ev.stopPropagation(); removeBubble(); iframe.contentWindow?.postMessage({ type: \"bitpalm-trigger-dismiss\" }, \"*\"); };\n bubble.onclick = () => {\n removeBubble();\n btn.style.display = \"none\";\n prepareIframeForOpen();\n mountIframe();\n if (!iframeReady) {\n pendingOpen = true;\n return;\n }\n iframe.contentWindow?.postMessage({ type: \"bitpalm-trigger-engaged\" }, \"*\");\n };\n bubble.appendChild(close);\n d.body.appendChild(bubble);\n }\n\n // Trigger bubble hide\n if (e.data?.type === \"bitpalm-trigger-hide\") { removeBubble(); }\n\n // Iframe requests latest parent context (avoids first-load race conditions)\n if (e.data?.type === \"bitpalm-request-context\") {\n sendParentContext();\n }\n\n // Widget blocked (excluded path or access denied) — hide button & iframe\n if (e.data?.type === \"bitpalm-widget-blocked\") {\n widgetBlocked = true;\n launcherReady = false;\n btn.style.display = \"none\";\n removeBubble();\n unlockMobilePageScroll();\n iframe.style.display = \"none\";\n }\n };\n window.addEventListener(\"message\", handleMessage);\n\n // --- Privacy opt-out check ---\n let optedOut = false;\n try { optedOut = localStorage.getItem(`${STORAGE_PREFIX}optout`) === \"1\"; } catch { /* ignore */ }\n\n // --- Persistent Visitor ID (skip if opted out) ---\n const VID_KEY = `${STORAGE_PREFIX}vid`;\n let visitorId = \"\";\n if (!optedOut) {\n try { visitorId = localStorage.getItem(VID_KEY) || \"\"; } catch { /* ignore */ }\n if (!visitorId) {\n // Fallback: try reading from cookie\n const match = d.cookie.match(new RegExp(`(?:^|; )${VID_KEY}=([^;]+)`));\n visitorId = match ? decodeURIComponent(match[1]) : \"\";\n }\n if (!visitorId) {\n visitorId = crypto.randomUUID ? crypto.randomUUID() : (`${Date.now()}-${Math.random().toString(36).slice(2, 11)}`);\n }\n // Persist in both localStorage and cookie (cookie survives Safari ITP clearing localStorage)\n try { localStorage.setItem(VID_KEY, visitorId); } catch { /* ignore */ }\n try {\n const maxAge = 365 * 24 * 60 * 60; // 1 year\n d.cookie = `${VID_KEY}=${encodeURIComponent(visitorId)};path=/;max-age=${maxAge};SameSite=Lax`;\n } catch { /* ignore */ }\n }\n\n // --- Visitor beacon: track page view even without chat (skip if opted out) ---\n if (!optedOut) {\n runWhenIdle(() => {\n try {\n const utmParams = new URLSearchParams(location.search);\n const utm: Record<string, string> = {};\n for (const key of [\"utm_source\", \"utm_medium\", \"utm_campaign\", \"utm_term\", \"utm_content\"]) {\n const val = utmParams.get(key);\n if (val) utm[key] = val;\n }\n const beaconPayload = JSON.stringify({\n tenant_slug: slug,\n visitor_id: visitorId,\n url: location.href,\n referrer: d.referrer || undefined,\n ...(Object.keys(utm).length > 0 ? { utm } : {}),\n });\n const beaconUrl = `${baseUrl}/api/widget/impression`;\n if (typeof navigator.sendBeacon === \"function\") {\n navigator.sendBeacon(beaconUrl, new Blob([beaconPayload], { type: \"application/json\" }));\n } else {\n fetch(beaconUrl, { method: \"POST\", body: beaconPayload, headers: { \"Content-Type\": \"application/json\" }, keepalive: true }).catch(() => {});\n }\n } catch { /* ignore */ }\n }, 2000);\n }\n\n // --- Auto-identify visitor from form submissions on host page ---\n let lastIdentitySignature = \"\";\n let lastIdentityFingerprint = \"\";\n let lastIdentitySentAt = 0;\n try {\n lastIdentitySignature = sessionStorage.getItem(IDENTITY_SIGNATURE_KEY) || \"\";\n lastIdentityFingerprint = sessionStorage.getItem(IDENTITY_FINGERPRINT_KEY) || \"\";\n const storedAt = parseInt(sessionStorage.getItem(IDENTITY_SENT_AT_KEY) || \"0\", 10);\n if (Number.isFinite(storedAt) && storedAt > 0) {\n lastIdentitySentAt = storedAt;\n }\n } catch {\n // ignore\n }\n\n const handleFormSubmit = (event: Event) => {\n if (optedOut || !autoIdentify || !visitorId) return;\n\n const form = event.target instanceof HTMLFormElement\n ? event.target\n : event.target instanceof Element\n ? event.target.closest(\"form\")\n : null;\n if (!(form instanceof HTMLFormElement)) return;\n\n const formIdentifySetting = (form.getAttribute(\"data-bp-identify\") || form.getAttribute(\"data-bitpalm-identify\") || \"\").toLowerCase();\n if (formIdentifySetting === \"off\" || formIdentifySetting === \"false\" || formIdentifySetting === \"0\") return;\n\n const identity = extractIdentityFromForm(form);\n if (!identity) return;\n\n const identityFingerprint = [\n identity.email || \"\",\n identity.phone || \"\",\n identity.name || \"\",\n identity.company || \"\",\n ].join(\"|\").toLowerCase();\n\n const signature = [\n form.getAttribute(\"id\") || \"\",\n form.getAttribute(\"name\") || \"\",\n form.getAttribute(\"action\") || \"\",\n identityFingerprint,\n ].join(\"|\").toLowerCase();\n\n const now = Date.now();\n const insideDedupWindow = now - lastIdentitySentAt < IDENTITY_DEDUPE_WINDOW_MS;\n if (insideDedupWindow && (signature === lastIdentitySignature || identityFingerprint === lastIdentityFingerprint)) {\n return;\n }\n\n lastIdentitySignature = signature;\n lastIdentityFingerprint = identityFingerprint;\n lastIdentitySentAt = now;\n try {\n sessionStorage.setItem(IDENTITY_SIGNATURE_KEY, signature);\n sessionStorage.setItem(IDENTITY_FINGERPRINT_KEY, identityFingerprint);\n sessionStorage.setItem(IDENTITY_SENT_AT_KEY, String(now));\n } catch {\n // ignore\n }\n\n try {\n const payload = JSON.stringify({\n tenant_slug: slug,\n visitor_id: visitorId,\n url: location.href,\n referrer: d.referrer || undefined,\n ...identity,\n });\n const identifyUrl = `${baseUrl}/api/widget/identify`;\n if (typeof navigator.sendBeacon === \"function\") {\n navigator.sendBeacon(identifyUrl, new Blob([payload], { type: \"application/json\" }));\n } else {\n fetch(identifyUrl, { method: \"POST\", body: payload, headers: { \"Content-Type\": \"application/json\" }, keepalive: true }).catch(() => {});\n }\n } catch {\n // ignore\n }\n };\n\n if (!optedOut && autoIdentify) {\n d.addEventListener(\"submit\", handleFormSubmit, true);\n }\n\n // --- Visitor Intelligence: page counter + history ---\n let pageCount = parseInt(sessionStorage.getItem(`${STORAGE_PREFIX}pages`) || \"0\") + 1;\n sessionStorage.setItem(`${STORAGE_PREFIX}pages`, String(pageCount));\n\n let hist: string[] = JSON.parse(sessionStorage.getItem(`${STORAGE_PREFIX}hist`) || \"[]\");\n hist.push(location.href);\n if (hist.length > 20) hist = hist.slice(-20);\n sessionStorage.setItem(`${STORAGE_PREFIX}hist`, JSON.stringify(hist));\n\n const loadedAt = Date.now();\n let siteStart = parseInt(sessionStorage.getItem(`${STORAGE_PREFIX}site_start`) || \"0\");\n if (!siteStart) {\n siteStart = loadedAt;\n sessionStorage.setItem(`${STORAGE_PREFIX}site_start`, String(siteStart));\n }\n\n const contextRetryTimers: ReturnType<typeof setTimeout>[] = [];\n sendParentContext = () => {\n let returning = false;\n try {\n returning = !!localStorage.getItem(`${STORAGE_PREFIX}visited`);\n } catch {\n returning = false;\n }\n iframe.contentWindow?.postMessage({\n type: \"bitpalm-parent-context\",\n url: location.href,\n title: d.title,\n returning,\n pageCount,\n pageHistory: hist,\n loadedAt,\n siteStart,\n locale,\n visitorId: optedOut ? \"\" : visitorId,\n }, \"*\");\n if (!returning && !optedOut) {\n try { localStorage.setItem(`${STORAGE_PREFIX}visited`, \"1\"); } catch { /* ignore */ }\n }\n };\n\n // --- Send parent context on iframe load ---\n iframe.addEventListener(\"load\", () => {\n iframeReady = true;\n sendParentContext();\n [120, 450, 1100].forEach((delay) => {\n const timer = setTimeout(() => sendParentContext(), delay);\n contextRetryTimers.push(timer);\n });\n if (pendingOpen) {\n pendingOpen = false;\n sendOpenSignal();\n }\n });\n\n // Lazy-mount iframe after initial paint/idle to reduce impact on host load.\n if (d.readyState === \"loading\") {\n d.addEventListener(\"DOMContentLoaded\", () => runWhenIdle(mountIframe, 1600), { once: true });\n } else {\n runWhenIdle(mountIframe, 1600);\n }\n\n // --- SPA navigation detection ---\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n const onNav = () => {\n pageCount++;\n sessionStorage.setItem(`${STORAGE_PREFIX}pages`, String(pageCount));\n const h: string[] = JSON.parse(sessionStorage.getItem(`${STORAGE_PREFIX}hist`) || \"[]\");\n h.push(location.href);\n if (h.length > 20) h.splice(0, h.length - 20);\n hist = h;\n sessionStorage.setItem(`${STORAGE_PREFIX}hist`, JSON.stringify(h));\n iframe.contentWindow?.postMessage({\n type: \"bitpalm-page-change\",\n url: location.href,\n title: d.title,\n pageCount,\n pageHistory: h,\n loadedAt: Date.now(),\n }, \"*\");\n // Track page view for visitor (skip if opted out)\n if (!optedOut) {\n try {\n const navPayload = JSON.stringify({ tenant_slug: slug, visitor_id: visitorId, url: location.href });\n const navUrl = `${baseUrl}/api/widget/impression`;\n if (typeof navigator.sendBeacon === \"function\") {\n navigator.sendBeacon(navUrl, new Blob([navPayload], { type: \"application/json\" }));\n } else {\n fetch(navUrl, { method: \"POST\", body: navPayload, headers: { \"Content-Type\": \"application/json\" }, keepalive: true }).catch(() => {});\n }\n } catch { /* ignore */ }\n }\n };\n\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\n origPush(...args);\n onNav();\n };\n history.replaceState = function (...args: Parameters<typeof history.replaceState>) {\n origReplace(...args);\n onNav();\n };\n window.addEventListener(\"popstate\", onNav);\n\n // --- Scroll depth tracking ---\n let lastScrollDepth = -1;\n let scrollTimeout: ReturnType<typeof setTimeout>;\n const handleScroll = () => {\n clearTimeout(scrollTimeout);\n scrollTimeout = setTimeout(() => {\n const total = Math.max(d.documentElement.scrollHeight, d.body.scrollHeight) - window.innerHeight;\n const pct = total > 0 ? Math.round(window.scrollY / total * 100) : 100;\n if (pct !== lastScrollDepth) {\n lastScrollDepth = pct;\n iframe.contentWindow?.postMessage({ type: \"bitpalm-scroll-depth\", percent: pct }, \"*\");\n }\n }, 500);\n };\n window.addEventListener(\"scroll\", handleScroll, { passive: true });\n\n // --- Exit intent ---\n const handleMouseOut = (e: MouseEvent) => {\n if (e.clientY <= 0) {\n iframe.contentWindow?.postMessage({ type: \"bitpalm-exit-intent\" }, \"*\");\n }\n };\n d.addEventListener(\"mouseout\", handleMouseOut);\n\n // --- Inactivity detection (15s) ---\n let idleTimer: ReturnType<typeof setTimeout>;\n let idleFired = false;\n const resetIdle = () => {\n clearTimeout(idleTimer);\n if (idleFired) return;\n idleTimer = setTimeout(() => {\n idleFired = true;\n iframe.contentWindow?.postMessage({ type: \"bitpalm-inactivity\" }, \"*\");\n }, 15_000);\n };\n const idleEvents = [\"mousemove\", \"keydown\", \"scroll\", \"touchstart\"] as const;\n idleEvents.forEach((ev) => d.addEventListener(ev, resetIdle, { passive: true }));\n resetIdle();\n\n sendOpenSignal = () => {\n // Primary: postMessage\n iframe.contentWindow?.postMessage({ type: \"bitpalm-open\" }, \"*\");\n // Fallback for mobile: trigger hashchange inside iframe (no reload)\n const base = iframe.src.split(\"#\")[0];\n iframe.src = `${base}#bp-open-${Date.now()}`;\n };\n\n // --- Public API ---\n const openWidget = () => {\n btn.style.display = \"none\";\n removeBubble();\n prepareIframeForOpen();\n mountIframe();\n if (!iframeReady) {\n pendingOpen = true;\n return;\n }\n sendOpenSignal();\n };\n\n const closeWidget = () => {\n unlockMobilePageScroll();\n iframe.contentWindow?.postMessage({ type: \"bitpalm-close\" }, \"*\");\n };\n\n const destroy = () => {\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"scroll\", handleScroll);\n window.removeEventListener(\"popstate\", onNav);\n d.removeEventListener(\"mouseout\", handleMouseOut);\n d.removeEventListener(\"submit\", handleFormSubmit, true);\n idleEvents.forEach((ev) => d.removeEventListener(ev, resetIdle));\n clearTimeout(scrollTimeout);\n clearTimeout(idleTimer);\n contextRetryTimers.forEach((t) => clearTimeout(t));\n history.pushState = origPush;\n history.replaceState = origReplace;\n unlockMobilePageScroll();\n removeBubble();\n btn.remove();\n iframe.remove();\n };\n\n return { open: openWidget, close: closeWidget, destroy };\n}\n"],"mappings":"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","names":["src_exports","__export","createWidget","__toCommonJS","DEFAULT_BASE_URL","STORAGE_PREFIX","IGNORED_INPUT_TYPES","IDENTITY_DEDUPE_WINDOW_MS","IDENTITY_SIGNATURE_KEY","IDENTITY_FINGERPRINT_KEY","IDENTITY_SENT_AT_KEY","normalizeText","value","maxLen","normalizeTokens","includesAny","haystack","needles","needle","isEmail","normalizePhone","trimmed","hasPlus","digits","getExplicitValue","form","selectors","selector","el","getFieldHint","escapeAttrSelectorValue","collectElementTokenParts","parts","pushText","clean","seenLabels","pushLabel","label","forLabel","nearestLabel","ariaLabelledBy","id","ref","extractIdentityFromForm","email","phone","name","firstName","lastName","company","rawEl","fieldHint","explicitField","type","tokens","normalized","emailLike","phoneLike","companyLike","firstNameLike","lastNameLike","fullNameLike","identity","detectLocale","lang","runWhenIdle","task","timeout","isMobileWidgetDevice","userAgent","coarsePointer","noHover","minScreenSide","createWidget","options","slug","locale","baseUrl","token","zIndex","autoIdentify","d","iframe","widgetUrl","qs","origin","btn","openWidget","s","bubble","launcherReady","widgetBlocked","iframeMounted","iframeReady","pendingOpen","mountIframe","mobileScrollLocked","scrollLockY","prevHtmlStyle","prevBodyStyle","lockMobilePageScroll","html","body","unlockMobilePageScroll","prepareIframeForOpen","mobile","removeBubble","sendParentContext","sendOpenSignal","handleMessage","ic","sp","svg","attr","sv","isOpen","msg","close","ev","optedOut","VID_KEY","visitorId","match","utmParams","utm","key","val","beaconPayload","beaconUrl","lastIdentitySignature","lastIdentityFingerprint","lastIdentitySentAt","storedAt","handleFormSubmit","event","formIdentifySetting","identityFingerprint","signature","now","payload","identifyUrl","pageCount","hist","loadedAt","siteStart","contextRetryTimers","returning","delay","timer","origPush","origReplace","onNav","h","navPayload","navUrl","args","lastScrollDepth","scrollTimeout","handleScroll","total","pct","handleMouseOut","idleTimer","idleFired","resetIdle","idleEvents","base","t","parseBoolean","value","normalized","script","init","createWidget"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/widget.ts"],"sourcesContent":["export { createWidget } from \"./widget\";\nexport type { BitPalmAgentOptions, BitPalmAgentInstance, BitPalmIdentifyPayload } from \"./types\";\n\nimport { createWidget } from \"./widget\";\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value == null) return undefined;\n const normalized = value.trim().toLowerCase();\n if ([\"1\", \"true\", \"yes\", \"on\"].includes(normalized)) return true;\n if ([\"0\", \"false\", \"no\", \"off\"].includes(normalized)) return false;\n return undefined;\n}\n\n/**\n * Auto-init from script tag:\n * <script src=\"https://cdn.bitpalm.ae/widget.js\" data-slug=\"my-agent\"></script>\n */\nif (typeof document !== \"undefined\") {\n const script = document.currentScript as HTMLScriptElement | null;\n if (script?.dataset.slug) {\n const init = () => {\n createWidget({\n slug: script!.dataset.slug!,\n locale: script!.dataset.locale,\n baseUrl: script!.dataset.baseUrl,\n token: script!.dataset.token,\n zIndex: script!.dataset.zIndex ? Number(script!.dataset.zIndex) : undefined,\n autoIdentify: parseBoolean(script!.dataset.autoIdentify),\n });\n };\n\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", init);\n } else {\n init();\n }\n }\n}\n","import type { BitPalmAgentOptions, BitPalmAgentInstance, BitPalmIdentifyPayload } from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://agents.bitpalm.ae\";\nconst STORAGE_PREFIX = \"_bp_\";\nconst IGNORED_INPUT_TYPES = new Set([\"password\", \"file\", \"checkbox\", \"radio\", \"submit\", \"button\", \"reset\", \"image\"]);\nconst IDENTITY_DEDUPE_WINDOW_MS = 8_000;\nconst IDENTITY_SIGNATURE_KEY = `${STORAGE_PREFIX}identify_signature`;\nconst IDENTITY_FINGERPRINT_KEY = `${STORAGE_PREFIX}identify_fingerprint`;\nconst IDENTITY_SENT_AT_KEY = `${STORAGE_PREFIX}identify_sent_at`;\n\ntype FormFieldElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n\ntype IdentityPayload = {\n name?: string;\n email?: string;\n phone?: string;\n company?: string;\n};\n\ntype IdentifyRequestPayload = IdentityPayload & {\n external_user_id?: string;\n signature?: string;\n signed_at?: number;\n signature_version?: \"v1\";\n};\n\nfunction buildIdentityFingerprint(payload: IdentifyRequestPayload): string {\n return [\n payload.external_user_id || \"\",\n payload.email || \"\",\n payload.phone || \"\",\n payload.name || \"\",\n payload.company || \"\",\n payload.signature || \"\",\n payload.signed_at != null ? String(payload.signed_at) : \"\",\n payload.signature_version || \"\",\n ]\n .join(\"|\")\n .toLowerCase();\n}\n\nfunction normalizeText(value: string | null | undefined, maxLen = 180): string {\n if (!value) return \"\";\n return value.replace(/\\s+/g, \" \").trim().slice(0, maxLen);\n}\n\nfunction normalizeTokens(value: string | null | undefined): string {\n if (!value) return \"\";\n return ` ${value.toLowerCase().replace(/[_-]+/g, \" \").replace(/[^a-z0-9\\s@.]/g, \" \").replace(/\\s+/g, \" \").trim()} `;\n}\n\nfunction includesAny(haystack: string, needles: string[]): boolean {\n for (const needle of needles) {\n if (haystack.includes(needle)) return true;\n }\n return false;\n}\n\nfunction isEmail(value: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/i.test(value);\n}\n\nfunction normalizePhone(value: string | null | undefined): string {\n const trimmed = normalizeText(value, 50);\n if (!trimmed) return \"\";\n const hasPlus = trimmed.startsWith(\"+\");\n const digits = trimmed.replace(/\\D/g, \"\");\n if (digits.length < 6) return \"\";\n return `${hasPlus ? \"+\" : \"\"}${digits.slice(0, 20)}`;\n}\n\nfunction normalizeEmail(value: string | null | undefined): string {\n const normalized = normalizeText(value, 140).toLowerCase();\n if (!normalized) return \"\";\n if (!isEmail(normalized)) return \"\";\n return normalized;\n}\n\nfunction getExplicitValue(form: HTMLFormElement, selectors: string[]): string {\n for (const selector of selectors) {\n const el = form.querySelector<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>(selector);\n const value = normalizeText(el?.value);\n if (value) return value;\n }\n return \"\";\n}\n\nfunction getFieldHint(el: FormFieldElement): string {\n return normalizeText(el.getAttribute(\"data-bp-field\") || el.getAttribute(\"data-bitpalm-field\"), 64)\n .toLowerCase()\n .replace(/[_\\s]+/g, \"-\");\n}\n\nfunction escapeAttrSelectorValue(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction collectElementTokenParts(form: HTMLFormElement, el: FormFieldElement): string[] {\n const parts: string[] = [];\n const pushText = (value: string | null | undefined, maxLen = 140) => {\n const clean = normalizeText(value, maxLen);\n if (clean) parts.push(clean);\n };\n\n pushText(el.name);\n pushText(el.id);\n pushText(el.getAttribute(\"autocomplete\"));\n pushText(el.getAttribute(\"placeholder\"));\n pushText(el.getAttribute(\"aria-label\"));\n pushText(el.getAttribute(\"data-field\"));\n pushText(el.getAttribute(\"data-name\"));\n pushText(el.getAttribute(\"data-label\"));\n pushText(el.getAttribute(\"data-bp-field\"));\n pushText(el.getAttribute(\"data-bitpalm-field\"));\n\n const seenLabels = new Set<string>();\n const pushLabel = (value: string | null | undefined) => {\n const label = normalizeText(value, 200);\n if (!label || seenLabels.has(label)) return;\n seenLabels.add(label);\n parts.push(label);\n };\n\n for (const label of Array.from(el.labels || [])) {\n pushLabel(label.textContent);\n }\n\n if (el.id) {\n const forLabel = form.querySelector(`label[for=\"${escapeAttrSelectorValue(el.id)}\"]`);\n pushLabel(forLabel?.textContent);\n }\n\n const nearestLabel = el.closest(\"label\");\n pushLabel(nearestLabel?.textContent);\n\n const ariaLabelledBy = el.getAttribute(\"aria-labelledby\");\n if (ariaLabelledBy) {\n for (const id of ariaLabelledBy.split(/\\s+/)) {\n if (!id) continue;\n const ref = form.ownerDocument.getElementById(id);\n pushLabel(ref?.textContent);\n }\n }\n\n return parts;\n}\n\nfunction extractIdentityFromForm(form: HTMLFormElement): IdentityPayload | null {\n let email = normalizeText(getExplicitValue(form, [\n \"[data-bp-email]\",\n \"[data-bitpalm-email]\",\n ]), 140).toLowerCase();\n\n let phone = normalizePhone(getExplicitValue(form, [\n \"[data-bp-phone]\",\n \"[data-bitpalm-phone]\",\n ]));\n\n let name = normalizeText(getExplicitValue(form, [\n \"[data-bp-name]\",\n \"[data-bitpalm-name]\",\n \"[data-bp-full-name]\",\n \"[data-bitpalm-full-name]\",\n ]));\n\n let firstName = normalizeText(getExplicitValue(form, [\n \"[data-bp-first-name]\",\n \"[data-bitpalm-first-name]\",\n ]));\n\n let lastName = normalizeText(getExplicitValue(form, [\n \"[data-bp-last-name]\",\n \"[data-bitpalm-last-name]\",\n ]));\n\n let company = normalizeText(getExplicitValue(form, [\n \"[data-bp-company]\",\n \"[data-bitpalm-company]\",\n ]));\n\n for (const rawEl of Array.from(form.elements)) {\n if (!(rawEl instanceof HTMLInputElement || rawEl instanceof HTMLTextAreaElement || rawEl instanceof HTMLSelectElement)) continue;\n if (rawEl.disabled) continue;\n if (rawEl instanceof HTMLInputElement && IGNORED_INPUT_TYPES.has(rawEl.type.toLowerCase())) continue;\n const fieldHint = getFieldHint(rawEl);\n\n const explicitField =\n rawEl.hasAttribute(\"data-bp-email\") ||\n rawEl.hasAttribute(\"data-bitpalm-email\") ||\n rawEl.hasAttribute(\"data-bp-phone\") ||\n rawEl.hasAttribute(\"data-bitpalm-phone\") ||\n rawEl.hasAttribute(\"data-bp-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-name\") ||\n rawEl.hasAttribute(\"data-bp-full-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-full-name\") ||\n rawEl.hasAttribute(\"data-bp-first-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-first-name\") ||\n rawEl.hasAttribute(\"data-bp-last-name\") ||\n rawEl.hasAttribute(\"data-bitpalm-last-name\") ||\n rawEl.hasAttribute(\"data-bp-company\") ||\n rawEl.hasAttribute(\"data-bitpalm-company\") ||\n !!fieldHint;\n\n if (rawEl instanceof HTMLInputElement && rawEl.type.toLowerCase() === \"hidden\" && !explicitField) continue;\n\n const value = normalizeText(rawEl.value);\n if (!value) continue;\n\n const type = rawEl instanceof HTMLInputElement ? rawEl.type.toLowerCase() : \"\";\n const tokens = normalizeTokens(collectElementTokenParts(form, rawEl).join(\" \"));\n\n if (!email && fieldHint === \"email\" && isEmail(value)) {\n email = value.toLowerCase();\n continue;\n }\n if (!phone && (fieldHint === \"phone\" || fieldHint === \"tel\" || fieldHint === \"mobile\" || fieldHint === \"whatsapp\")) {\n const normalized = normalizePhone(value);\n if (normalized) {\n phone = normalized;\n continue;\n }\n }\n if (!company && fieldHint === \"company\") {\n company = normalizeText(value, 160);\n continue;\n }\n if (!firstName && (fieldHint === \"first-name\" || fieldHint === \"firstname\")) {\n firstName = normalizeText(value, 100);\n continue;\n }\n if (!lastName && (fieldHint === \"last-name\" || fieldHint === \"lastname\" || fieldHint === \"surname\")) {\n lastName = normalizeText(value, 100);\n continue;\n }\n if (!name && (fieldHint === \"name\" || fieldHint === \"full-name\" || fieldHint === \"fullname\")) {\n if (!isEmail(value) && !normalizePhone(value)) name = normalizeText(value, 140);\n continue;\n }\n\n const emailLike = type === \"email\" || includesAny(tokens, [\" email \", \" e mail \", \" mail \", \" email adresse \", \" mailadresse \", \" correo \"]);\n const phoneLike = type === \"tel\" || includesAny(tokens, [\" phone \", \" phone number \", \" mobile \", \" tel \", \" telefon \", \" telefonnummer \", \" whatsapp \", \" handy \", \" kontakt \", \" nummer \"]);\n const companyLike = includesAny(tokens, [\" company \", \" company name \", \" firma \", \" firmenname \", \" organization \", \" organisation \", \" business \", \" unternehmen \", \" agency \", \" brokerage \"]);\n const firstNameLike = includesAny(tokens, [\" first name \", \" firstname \", \" given name \", \" givenname \", \" vorname \", \" fname \"]);\n const lastNameLike = includesAny(tokens, [\" last name \", \" lastname \", \" family name \", \" familyname \", \" surname \", \" nachname \", \" lname \"]);\n const fullNameLike = includesAny(tokens, [\" full name \", \" fullname \", \" contact name \", \" name \"]) && !emailLike && !phoneLike;\n\n if (!email && emailLike && isEmail(value)) {\n email = value.toLowerCase();\n continue;\n }\n if (!phone && phoneLike) {\n const normalized = normalizePhone(value);\n if (normalized) {\n phone = normalized;\n continue;\n }\n }\n if (!company && companyLike) {\n company = normalizeText(value, 160);\n continue;\n }\n if (!firstName && firstNameLike) {\n firstName = normalizeText(value, 100);\n continue;\n }\n if (!lastName && lastNameLike) {\n lastName = normalizeText(value, 100);\n continue;\n }\n if (!name && fullNameLike && !isEmail(value) && !normalizePhone(value)) {\n name = normalizeText(value, 140);\n continue;\n }\n\n if (!email && isEmail(value)) {\n email = value.toLowerCase();\n }\n }\n\n if (name && (isEmail(name) || normalizePhone(name))) {\n name = \"\";\n }\n if (company && (isEmail(company) || normalizePhone(company))) {\n company = \"\";\n }\n\n if (!name) {\n name = normalizeText([firstName, lastName].filter(Boolean).join(\" \"), 140);\n }\n\n if (name && email && name.toLowerCase() === email.toLowerCase()) {\n name = \"\";\n }\n\n const hasContactSignal = !!(email || phone);\n const hasStrongProfileSignal = !!(name && company);\n if (!hasContactSignal && !hasStrongProfileSignal) {\n return null;\n }\n\n const identity: IdentityPayload = {\n ...(name ? { name } : {}),\n ...(email ? { email } : {}),\n ...(phone ? { phone } : {}),\n ...(company ? { company } : {}),\n };\n\n return Object.keys(identity).length > 0 ? identity : null;\n}\n\nfunction detectLocale(): string {\n if (typeof document !== \"undefined\") {\n const lang = document.documentElement.lang;\n if (lang) return lang.slice(0, 2).toLowerCase();\n }\n return \"en\";\n}\n\nfunction runWhenIdle(task: () => void, timeout = 1200) {\n if (typeof window !== \"undefined\" && \"requestIdleCallback\" in window) {\n (\n window as unknown as {\n requestIdleCallback: (cb: () => void, opts?: { timeout?: number }) => number;\n }\n ).requestIdleCallback(task, { timeout });\n return;\n }\n setTimeout(task, Math.min(timeout, 300));\n}\n\nfunction isMobileWidgetDevice(): boolean {\n if (typeof window === \"undefined\") return false;\n const userAgent = typeof navigator !== \"undefined\" ? navigator.userAgent : \"\";\n const isMobileUa = /Android|iPhone|iPad|iPod|IEMobile|Windows Phone|Mobile/i.test(userAgent);\n if (isMobileUa) return true;\n\n const coarsePointer = window.matchMedia(\"(pointer: coarse)\").matches;\n const noHover = window.matchMedia(\"(hover: none)\").matches;\n const minScreenSide = Math.min(\n window.screen?.width || window.innerWidth,\n window.screen?.height || window.innerHeight,\n );\n return coarsePointer && noHover && minScreenSide <= 900;\n}\n\nexport function createWidget(options: BitPalmAgentOptions): BitPalmAgentInstance {\n const {\n slug,\n locale = detectLocale(),\n baseUrl = DEFAULT_BASE_URL,\n token,\n zIndex = 9999,\n autoIdentify = true,\n } = options;\n\n const d = document;\n\n // --- Iframe ---\n const iframe = d.createElement(\"iframe\");\n const widgetUrl = `${baseUrl}/t/${slug}/widget`;\n const qs = new URLSearchParams({ locale });\n if (token) qs.set(\"token\", token);\n iframe.src = `${widgetUrl}?${qs.toString()}`;\n iframe.allow = \"clipboard-write\";\n iframe.setAttribute(\"allowtransparency\", \"true\");\n iframe.loading = \"lazy\";\n iframe.style.cssText = `position:fixed;bottom:0;right:0;width:1px;height:1px;border:none;z-index:${zIndex};background:transparent;color-scheme:normal;opacity:0;pointer-events:none;`;\n\n const origin = new URL(iframe.src).origin;\n\n // --- Native launcher button ---\n const btn = d.createElement(\"div\");\n btn.setAttribute(\"role\", \"button\");\n btn.setAttribute(\"aria-label\", \"Chat\");\n btn.style.cssText = `position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;display:none;align-items:center;justify-content:center;cursor:pointer;z-index:${zIndex - 1};background:#00ff41;box-shadow:0 0 15px rgba(0,255,65,0.31);transition:transform .2s,opacity .3s;opacity:0;`;\n btn.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"black\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\"/></svg>';\n btn.onmouseenter = () => { btn.style.transform = \"scale(1.1)\"; };\n btn.onmouseleave = () => { btn.style.transform = \"scale(1)\"; };\n btn.onclick = () => openWidget();\n d.body.appendChild(btn);\n\n // --- Fade animation for trigger bubbles ---\n if (!d.getElementById(\"_bp_fade\")) {\n const s = d.createElement(\"style\");\n s.id = \"_bp_fade\";\n s.textContent = \"@keyframes _bp_fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\";\n d.head.appendChild(s);\n }\n\n // --- Trigger bubble ---\n let bubble: HTMLDivElement | null = null;\n let launcherReady = false;\n let widgetBlocked = false;\n let iframeMounted = false;\n let iframeReady = false;\n let pendingOpen = false;\n const mountIframe = () => {\n if (iframeMounted) return;\n iframeMounted = true;\n d.body.appendChild(iframe);\n };\n let mobileScrollLocked = false;\n let scrollLockY = 0;\n const prevHtmlStyle = {\n overflow: \"\",\n overscrollBehavior: \"\",\n };\n const prevBodyStyle = {\n overflow: \"\",\n overscrollBehavior: \"\",\n position: \"\",\n top: \"\",\n left: \"\",\n right: \"\",\n width: \"\",\n };\n const lockMobilePageScroll = () => {\n if (mobileScrollLocked) return;\n const mobile = isMobileWidgetDevice();\n if (!mobile) return;\n const html = d.documentElement;\n const body = d.body;\n scrollLockY = window.scrollY || window.pageYOffset || 0;\n prevHtmlStyle.overflow = html.style.overflow;\n prevHtmlStyle.overscrollBehavior = html.style.overscrollBehavior;\n prevBodyStyle.overflow = body.style.overflow;\n prevBodyStyle.overscrollBehavior = body.style.overscrollBehavior;\n prevBodyStyle.position = body.style.position;\n prevBodyStyle.top = body.style.top;\n prevBodyStyle.left = body.style.left;\n prevBodyStyle.right = body.style.right;\n prevBodyStyle.width = body.style.width;\n html.style.overflow = \"hidden\";\n html.style.overscrollBehavior = \"none\";\n body.style.overflow = \"hidden\";\n body.style.overscrollBehavior = \"none\";\n body.style.position = \"fixed\";\n body.style.top = `-${scrollLockY}px`;\n body.style.left = \"0\";\n body.style.right = \"0\";\n body.style.width = \"100%\";\n mobileScrollLocked = true;\n };\n const unlockMobilePageScroll = () => {\n if (!mobileScrollLocked) return;\n const html = d.documentElement;\n const body = d.body;\n html.style.overflow = prevHtmlStyle.overflow;\n html.style.overscrollBehavior = prevHtmlStyle.overscrollBehavior;\n body.style.overflow = prevBodyStyle.overflow;\n body.style.overscrollBehavior = prevBodyStyle.overscrollBehavior;\n body.style.position = prevBodyStyle.position;\n body.style.top = prevBodyStyle.top;\n body.style.left = prevBodyStyle.left;\n body.style.right = prevBodyStyle.right;\n body.style.width = prevBodyStyle.width;\n window.scrollTo(0, scrollLockY);\n mobileScrollLocked = false;\n };\n const prepareIframeForOpen = () => {\n const mobile = isMobileWidgetDevice();\n if (iframe.style.display === \"none\") iframe.style.display = \"\";\n if (mobile) {\n iframe.style.width = \"100vw\";\n iframe.style.height = \"100dvh\";\n iframe.style.left = \"0\";\n iframe.style.top = \"0\";\n lockMobilePageScroll();\n } else {\n // Match desktop widget target size so the opening animation is visible from frame 1.\n iframe.style.width = \"420px\";\n iframe.style.height = \"620px\";\n iframe.style.left = \"\";\n iframe.style.top = \"\";\n unlockMobilePageScroll();\n }\n iframe.style.opacity = \"1\";\n iframe.style.pointerEvents = \"auto\";\n };\n const removeBubble = () => {\n if (bubble) { bubble.remove(); bubble = null; }\n };\n let sendParentContext = () => {};\n let sendOpenSignal = () => {};\n\n // --- postMessage handler ---\n const handleMessage = (e: MessageEvent) => {\n if (e.origin !== origin) return;\n\n // Widget config (colors, icon)\n if (e.data?.type === \"bitpalm-widget-config\") {\n widgetBlocked = false;\n launcherReady = true;\n if (iframe.style.display === \"none\") iframe.style.display = \"\";\n if (e.data.primaryColor) {\n btn.style.background = e.data.primaryColor;\n btn.style.boxShadow = e.data.chatShadow === \"none\" ? \"none\" : `0 0 15px ${e.data.primaryColor}50`;\n }\n const ic = e.data.chatButtonIconColor || \"black\";\n if (e.data.chatButtonIconSvg) {\n btn.innerHTML = \"\";\n const sp = d.createElement(\"span\");\n sp.style.cssText = `display:flex;align-items:center;justify-content:center;width:24px;height:24px;color:${ic}`;\n const parser = new DOMParser();\n const doc = parser.parseFromString(e.data.chatButtonIconSvg, \"image/svg+xml\");\n const svg = doc.querySelector(\"svg\");\n if (svg) {\n // Remove dangerous elements and attributes\n svg.querySelectorAll(\"script,foreignObject\").forEach(el => el.remove());\n svg.querySelectorAll(\"*\").forEach(el => {\n for (const attr of [...el.attributes]) {\n if (attr.name.startsWith(\"on\") || (attr.value && attr.value.includes(\"javascript:\"))) {\n el.removeAttribute(attr.name);\n }\n }\n });\n svg.setAttribute(\"width\", \"24\");\n svg.setAttribute(\"height\", \"24\");\n svg.style.display = \"block\";\n sp.appendChild(svg);\n } else {\n // Fallback: use default icon\n sp.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\"/></svg>';\n }\n btn.appendChild(sp);\n } else {\n const sv = btn.querySelector(\"svg\");\n if (sv) (sv as SVGElement).style.stroke = ic;\n }\n btn.style.display = \"flex\";\n // Fade in after styles are applied\n requestAnimationFrame(() => { btn.style.opacity = \"1\"; });\n }\n\n // Resize — use full viewport on mobile\n if (e.data?.type === \"bitpalm-widget-resize\") {\n const isOpen = e.data.width > 0;\n const mobile = isMobileWidgetDevice();\n if (isOpen) {\n iframe.style.width = mobile ? \"100vw\" : `${e.data.width}px`;\n iframe.style.height = mobile ? \"100dvh\" : `${e.data.height}px`;\n if (mobile) {\n iframe.style.left = \"0\";\n iframe.style.top = \"0\";\n lockMobilePageScroll();\n } else {\n unlockMobilePageScroll();\n }\n iframe.style.opacity = \"1\";\n iframe.style.pointerEvents = \"auto\";\n } else {\n unlockMobilePageScroll();\n iframe.style.width = \"1px\";\n iframe.style.height = \"1px\";\n iframe.style.left = \"\";\n iframe.style.top = \"\";\n iframe.style.opacity = \"0\";\n iframe.style.pointerEvents = \"none\";\n }\n btn.style.display = isOpen ? \"none\" : \"flex\";\n }\n\n // Trigger bubble show\n if (e.data?.type === \"bitpalm-trigger-show\") {\n if (widgetBlocked || !launcherReady) return;\n removeBubble();\n bubble = d.createElement(\"div\");\n bubble.style.cssText = `position:fixed;bottom:90px;right:24px;max-width:240px;background:#fff;border-radius:16px;padding:12px 32px 12px 12px;box-shadow:0 2px 20px rgba(0,0,0,0.08);cursor:pointer;z-index:${zIndex - 1};font-family:system-ui,sans-serif;animation:_bp_fade .3s;`;\n const msg = (e.data.message || \"\").replace(/</g, \"<\");\n bubble.innerHTML = `<p style=\"font-size:14px;color:#1f2937;margin:0;\">${msg}</p><div style=\"position:absolute;bottom:-8px;right:20px;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #fff;\"></div>`;\n const close = d.createElement(\"button\");\n close.style.cssText = \"position:absolute;top:-8px;right:-8px;width:28px;height:28px;border-radius:50%;background:#fff;border:none;box-shadow:0 1px 4px rgba(0,0,0,0.1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;color:#9ca3af;\";\n close.innerHTML = \"✕\";\n close.onclick = (ev) => { ev.stopPropagation(); removeBubble(); iframe.contentWindow?.postMessage({ type: \"bitpalm-trigger-dismiss\" }, \"*\"); };\n bubble.onclick = () => {\n removeBubble();\n btn.style.display = \"none\";\n prepareIframeForOpen();\n mountIframe();\n if (!iframeReady) {\n pendingOpen = true;\n return;\n }\n iframe.contentWindow?.postMessage({ type: \"bitpalm-trigger-engaged\" }, \"*\");\n };\n bubble.appendChild(close);\n d.body.appendChild(bubble);\n }\n\n // Trigger bubble hide\n if (e.data?.type === \"bitpalm-trigger-hide\") { removeBubble(); }\n\n // Iframe requests latest parent context (avoids first-load race conditions)\n if (e.data?.type === \"bitpalm-request-context\") {\n sendParentContext();\n }\n\n // Widget blocked (excluded path or access denied) — hide button & iframe\n if (e.data?.type === \"bitpalm-widget-blocked\") {\n widgetBlocked = true;\n launcherReady = false;\n btn.style.display = \"none\";\n removeBubble();\n unlockMobilePageScroll();\n iframe.style.display = \"none\";\n }\n };\n window.addEventListener(\"message\", handleMessage);\n\n // --- Privacy opt-out check ---\n let optedOut = false;\n try { optedOut = localStorage.getItem(`${STORAGE_PREFIX}optout`) === \"1\"; } catch { /* ignore */ }\n\n // --- Persistent Visitor ID (skip if opted out) ---\n const VID_KEY = `${STORAGE_PREFIX}vid`;\n let visitorId = \"\";\n if (!optedOut) {\n try { visitorId = localStorage.getItem(VID_KEY) || \"\"; } catch { /* ignore */ }\n if (!visitorId) {\n // Fallback: try reading from cookie\n const match = d.cookie.match(new RegExp(`(?:^|; )${VID_KEY}=([^;]+)`));\n visitorId = match ? decodeURIComponent(match[1]) : \"\";\n }\n if (!visitorId) {\n visitorId = crypto.randomUUID ? crypto.randomUUID() : (`${Date.now()}-${Math.random().toString(36).slice(2, 11)}`);\n }\n // Persist in both localStorage and cookie (cookie survives Safari ITP clearing localStorage)\n try { localStorage.setItem(VID_KEY, visitorId); } catch { /* ignore */ }\n try {\n const maxAge = 365 * 24 * 60 * 60; // 1 year\n d.cookie = `${VID_KEY}=${encodeURIComponent(visitorId)};path=/;max-age=${maxAge};SameSite=Lax`;\n } catch { /* ignore */ }\n }\n\n // --- Visitor beacon: track page view even without chat (skip if opted out) ---\n if (!optedOut) {\n runWhenIdle(() => {\n try {\n const utmParams = new URLSearchParams(location.search);\n const utm: Record<string, string> = {};\n for (const key of [\"utm_source\", \"utm_medium\", \"utm_campaign\", \"utm_term\", \"utm_content\"]) {\n const val = utmParams.get(key);\n if (val) utm[key] = val;\n }\n const beaconPayload = JSON.stringify({\n tenant_slug: slug,\n visitor_id: visitorId,\n url: location.href,\n referrer: d.referrer || undefined,\n ...(Object.keys(utm).length > 0 ? { utm } : {}),\n });\n const beaconUrl = `${baseUrl}/api/widget/impression`;\n if (typeof navigator.sendBeacon === \"function\") {\n navigator.sendBeacon(beaconUrl, new Blob([beaconPayload], { type: \"application/json\" }));\n } else {\n fetch(beaconUrl, { method: \"POST\", body: beaconPayload, headers: { \"Content-Type\": \"application/json\" }, keepalive: true }).catch(() => {});\n }\n } catch { /* ignore */ }\n }, 2000);\n }\n\n // --- Auto-identify visitor from form submissions on host page ---\n let lastIdentitySignature = \"\";\n let lastIdentityFingerprint = \"\";\n let lastIdentitySentAt = 0;\n try {\n lastIdentitySignature = sessionStorage.getItem(IDENTITY_SIGNATURE_KEY) || \"\";\n lastIdentityFingerprint = sessionStorage.getItem(IDENTITY_FINGERPRINT_KEY) || \"\";\n const storedAt = parseInt(sessionStorage.getItem(IDENTITY_SENT_AT_KEY) || \"0\", 10);\n if (Number.isFinite(storedAt) && storedAt > 0) {\n lastIdentitySentAt = storedAt;\n }\n } catch {\n // ignore\n }\n\n const dispatchIdentify = (payloadInput: IdentifyRequestPayload, scopeSignature = \"\") => {\n if (optedOut || !visitorId) return;\n\n const payload: IdentifyRequestPayload = {};\n const name = normalizeText(payloadInput.name, 140);\n const email = normalizeEmail(payloadInput.email);\n const phone = normalizePhone(payloadInput.phone);\n const company = normalizeText(payloadInput.company, 160);\n const externalUserId = normalizeText(payloadInput.external_user_id, 140);\n const requestSignature = normalizeText(payloadInput.signature, 260);\n const signedAtRaw = Number(payloadInput.signed_at);\n\n if (name) payload.name = name;\n if (email) payload.email = email;\n if (phone) payload.phone = phone;\n if (company) payload.company = company;\n if (externalUserId) payload.external_user_id = externalUserId;\n if (requestSignature) payload.signature = requestSignature;\n if (Number.isFinite(signedAtRaw) && signedAtRaw > 0) {\n payload.signed_at = Math.floor(signedAtRaw);\n }\n if (payloadInput.signature_version === \"v1\" || payload.signature) {\n payload.signature_version = \"v1\";\n }\n\n if (!payload.name && !payload.email && !payload.phone && !payload.company && !payload.external_user_id) {\n return;\n }\n\n const identityFingerprint = buildIdentityFingerprint(payload);\n const dedupeSignature = [scopeSignature.toLowerCase(), identityFingerprint].filter(Boolean).join(\"|\");\n\n const now = Date.now();\n const insideDedupWindow = now - lastIdentitySentAt < IDENTITY_DEDUPE_WINDOW_MS;\n if (insideDedupWindow && (dedupeSignature === lastIdentitySignature || identityFingerprint === lastIdentityFingerprint)) {\n return;\n }\n\n lastIdentitySignature = dedupeSignature;\n lastIdentityFingerprint = identityFingerprint;\n lastIdentitySentAt = now;\n try {\n sessionStorage.setItem(IDENTITY_SIGNATURE_KEY, dedupeSignature);\n sessionStorage.setItem(IDENTITY_FINGERPRINT_KEY, identityFingerprint);\n sessionStorage.setItem(IDENTITY_SENT_AT_KEY, String(now));\n } catch {\n // ignore\n }\n\n try {\n const requestBody = JSON.stringify({\n tenant_slug: slug,\n visitor_id: visitorId,\n url: location.href,\n referrer: d.referrer || undefined,\n ...payload,\n });\n const identifyUrl = `${baseUrl}/api/widget/identify`;\n if (typeof navigator.sendBeacon === \"function\") {\n navigator.sendBeacon(identifyUrl, new Blob([requestBody], { type: \"application/json\" }));\n } else {\n fetch(identifyUrl, { method: \"POST\", body: requestBody, headers: { \"Content-Type\": \"application/json\" }, keepalive: true }).catch(() => {});\n }\n } catch {\n // ignore\n }\n };\n\n const handleFormSubmit = (event: Event) => {\n if (optedOut || !autoIdentify || !visitorId) return;\n\n const form = event.target instanceof HTMLFormElement\n ? event.target\n : event.target instanceof Element\n ? event.target.closest(\"form\")\n : null;\n if (!(form instanceof HTMLFormElement)) return;\n\n const formIdentifySetting = (form.getAttribute(\"data-bp-identify\") || form.getAttribute(\"data-bitpalm-identify\") || \"\").toLowerCase();\n if (formIdentifySetting === \"off\" || formIdentifySetting === \"false\" || formIdentifySetting === \"0\") return;\n\n const identity = extractIdentityFromForm(form);\n if (!identity) return;\n\n const formSignature = [\n form.getAttribute(\"id\") || \"\",\n form.getAttribute(\"name\") || \"\",\n form.getAttribute(\"action\") || \"\",\n ].join(\"|\");\n\n dispatchIdentify(identity, formSignature);\n };\n\n if (!optedOut && autoIdentify) {\n d.addEventListener(\"submit\", handleFormSubmit, true);\n }\n\n // --- Visitor Intelligence: page counter + history ---\n let pageCount = parseInt(sessionStorage.getItem(`${STORAGE_PREFIX}pages`) || \"0\") + 1;\n sessionStorage.setItem(`${STORAGE_PREFIX}pages`, String(pageCount));\n\n let hist: string[] = JSON.parse(sessionStorage.getItem(`${STORAGE_PREFIX}hist`) || \"[]\");\n hist.push(location.href);\n if (hist.length > 20) hist = hist.slice(-20);\n sessionStorage.setItem(`${STORAGE_PREFIX}hist`, JSON.stringify(hist));\n\n const loadedAt = Date.now();\n let siteStart = parseInt(sessionStorage.getItem(`${STORAGE_PREFIX}site_start`) || \"0\");\n if (!siteStart) {\n siteStart = loadedAt;\n sessionStorage.setItem(`${STORAGE_PREFIX}site_start`, String(siteStart));\n }\n\n const contextRetryTimers: ReturnType<typeof setTimeout>[] = [];\n sendParentContext = () => {\n let returning = false;\n try {\n returning = !!localStorage.getItem(`${STORAGE_PREFIX}visited`);\n } catch {\n returning = false;\n }\n iframe.contentWindow?.postMessage({\n type: \"bitpalm-parent-context\",\n url: location.href,\n title: d.title,\n returning,\n pageCount,\n pageHistory: hist,\n loadedAt,\n siteStart,\n locale,\n visitorId: optedOut ? \"\" : visitorId,\n }, \"*\");\n if (!returning && !optedOut) {\n try { localStorage.setItem(`${STORAGE_PREFIX}visited`, \"1\"); } catch { /* ignore */ }\n }\n };\n\n // --- Send parent context on iframe load ---\n iframe.addEventListener(\"load\", () => {\n iframeReady = true;\n sendParentContext();\n [120, 450, 1100].forEach((delay) => {\n const timer = setTimeout(() => sendParentContext(), delay);\n contextRetryTimers.push(timer);\n });\n if (pendingOpen) {\n pendingOpen = false;\n sendOpenSignal();\n }\n });\n\n // Lazy-mount iframe after initial paint/idle to reduce impact on host load.\n if (d.readyState === \"loading\") {\n d.addEventListener(\"DOMContentLoaded\", () => runWhenIdle(mountIframe, 1600), { once: true });\n } else {\n runWhenIdle(mountIframe, 1600);\n }\n\n // --- SPA navigation detection ---\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n const onNav = () => {\n pageCount++;\n sessionStorage.setItem(`${STORAGE_PREFIX}pages`, String(pageCount));\n const h: string[] = JSON.parse(sessionStorage.getItem(`${STORAGE_PREFIX}hist`) || \"[]\");\n h.push(location.href);\n if (h.length > 20) h.splice(0, h.length - 20);\n hist = h;\n sessionStorage.setItem(`${STORAGE_PREFIX}hist`, JSON.stringify(h));\n iframe.contentWindow?.postMessage({\n type: \"bitpalm-page-change\",\n url: location.href,\n title: d.title,\n pageCount,\n pageHistory: h,\n loadedAt: Date.now(),\n }, \"*\");\n // Track page view for visitor (skip if opted out)\n if (!optedOut) {\n try {\n const navPayload = JSON.stringify({ tenant_slug: slug, visitor_id: visitorId, url: location.href });\n const navUrl = `${baseUrl}/api/widget/impression`;\n if (typeof navigator.sendBeacon === \"function\") {\n navigator.sendBeacon(navUrl, new Blob([navPayload], { type: \"application/json\" }));\n } else {\n fetch(navUrl, { method: \"POST\", body: navPayload, headers: { \"Content-Type\": \"application/json\" }, keepalive: true }).catch(() => {});\n }\n } catch { /* ignore */ }\n }\n };\n\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\n origPush(...args);\n onNav();\n };\n history.replaceState = function (...args: Parameters<typeof history.replaceState>) {\n origReplace(...args);\n onNav();\n };\n window.addEventListener(\"popstate\", onNav);\n\n // --- Scroll depth tracking ---\n let lastScrollDepth = -1;\n let scrollTimeout: ReturnType<typeof setTimeout>;\n const handleScroll = () => {\n clearTimeout(scrollTimeout);\n scrollTimeout = setTimeout(() => {\n const total = Math.max(d.documentElement.scrollHeight, d.body.scrollHeight) - window.innerHeight;\n const pct = total > 0 ? Math.round(window.scrollY / total * 100) : 100;\n if (pct !== lastScrollDepth) {\n lastScrollDepth = pct;\n iframe.contentWindow?.postMessage({ type: \"bitpalm-scroll-depth\", percent: pct }, \"*\");\n }\n }, 500);\n };\n window.addEventListener(\"scroll\", handleScroll, { passive: true });\n\n // --- Exit intent ---\n const handleMouseOut = (e: MouseEvent) => {\n if (e.clientY <= 0) {\n iframe.contentWindow?.postMessage({ type: \"bitpalm-exit-intent\" }, \"*\");\n }\n };\n d.addEventListener(\"mouseout\", handleMouseOut);\n\n // --- Inactivity detection (15s) ---\n let idleTimer: ReturnType<typeof setTimeout>;\n let idleFired = false;\n const resetIdle = () => {\n clearTimeout(idleTimer);\n if (idleFired) return;\n idleTimer = setTimeout(() => {\n idleFired = true;\n iframe.contentWindow?.postMessage({ type: \"bitpalm-inactivity\" }, \"*\");\n }, 15_000);\n };\n const idleEvents = [\"mousemove\", \"keydown\", \"scroll\", \"touchstart\"] as const;\n idleEvents.forEach((ev) => d.addEventListener(ev, resetIdle, { passive: true }));\n resetIdle();\n\n sendOpenSignal = () => {\n // Primary: postMessage\n iframe.contentWindow?.postMessage({ type: \"bitpalm-open\" }, \"*\");\n // Fallback for mobile: trigger hashchange inside iframe (no reload)\n const base = iframe.src.split(\"#\")[0];\n iframe.src = `${base}#bp-open-${Date.now()}`;\n };\n\n // --- Public API ---\n const openWidget = () => {\n btn.style.display = \"none\";\n removeBubble();\n prepareIframeForOpen();\n mountIframe();\n if (!iframeReady) {\n pendingOpen = true;\n return;\n }\n sendOpenSignal();\n };\n\n const closeWidget = () => {\n unlockMobilePageScroll();\n iframe.contentWindow?.postMessage({ type: \"bitpalm-close\" }, \"*\");\n };\n\n const identify = (input: BitPalmIdentifyPayload) => {\n if (!input || typeof input !== \"object\") return;\n dispatchIdentify({\n external_user_id: normalizeText(input.externalUserId, 140) || undefined,\n name: normalizeText(input.name, 140) || undefined,\n email: normalizeEmail(input.email) || undefined,\n phone: normalizePhone(input.phone) || undefined,\n company: normalizeText(input.company, 160) || undefined,\n signature: normalizeText(input.signature, 260) || undefined,\n signed_at: Number.isFinite(Number(input.signedAt)) ? Math.floor(Number(input.signedAt)) : undefined,\n signature_version: input.signatureVersion === \"v1\" ? \"v1\" : undefined,\n }, \"manual\");\n };\n\n const handleIdentifyEvent = (event: Event) => {\n const customEvent = event as CustomEvent<BitPalmIdentifyPayload & { slug?: string }>;\n const detail = customEvent.detail;\n if (!detail || typeof detail !== \"object\") return;\n const targetSlug = normalizeText(detail.slug, 120);\n if (targetSlug && targetSlug !== slug) return;\n identify(detail);\n };\n\n window.addEventListener(\"bitpalm-identify\", handleIdentifyEvent as EventListener);\n\n const destroy = () => {\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"scroll\", handleScroll);\n window.removeEventListener(\"popstate\", onNav);\n d.removeEventListener(\"mouseout\", handleMouseOut);\n d.removeEventListener(\"submit\", handleFormSubmit, true);\n idleEvents.forEach((ev) => d.removeEventListener(ev, resetIdle));\n clearTimeout(scrollTimeout);\n clearTimeout(idleTimer);\n contextRetryTimers.forEach((t) => clearTimeout(t));\n history.pushState = origPush;\n history.replaceState = origReplace;\n window.removeEventListener(\"bitpalm-identify\", handleIdentifyEvent as EventListener);\n unlockMobilePageScroll();\n removeBubble();\n btn.remove();\n iframe.remove();\n };\n\n return { open: openWidget, close: closeWidget, identify, destroy };\n}\n"],"mappings":"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","names":["src_exports","__export","createWidget","__toCommonJS","DEFAULT_BASE_URL","STORAGE_PREFIX","IGNORED_INPUT_TYPES","IDENTITY_DEDUPE_WINDOW_MS","IDENTITY_SIGNATURE_KEY","IDENTITY_FINGERPRINT_KEY","IDENTITY_SENT_AT_KEY","buildIdentityFingerprint","payload","normalizeText","value","maxLen","normalizeTokens","includesAny","haystack","needles","needle","isEmail","normalizePhone","trimmed","hasPlus","digits","normalizeEmail","normalized","getExplicitValue","form","selectors","selector","el","getFieldHint","escapeAttrSelectorValue","collectElementTokenParts","parts","pushText","clean","seenLabels","pushLabel","label","forLabel","nearestLabel","ariaLabelledBy","id","ref","extractIdentityFromForm","email","phone","name","firstName","lastName","company","rawEl","fieldHint","explicitField","type","tokens","emailLike","phoneLike","companyLike","firstNameLike","lastNameLike","fullNameLike","identity","detectLocale","lang","runWhenIdle","task","timeout","isMobileWidgetDevice","userAgent","coarsePointer","noHover","minScreenSide","createWidget","options","slug","locale","baseUrl","token","zIndex","autoIdentify","d","iframe","widgetUrl","qs","origin","btn","openWidget","s","bubble","launcherReady","widgetBlocked","iframeMounted","iframeReady","pendingOpen","mountIframe","mobileScrollLocked","scrollLockY","prevHtmlStyle","prevBodyStyle","lockMobilePageScroll","html","body","unlockMobilePageScroll","prepareIframeForOpen","mobile","removeBubble","sendParentContext","sendOpenSignal","handleMessage","ic","sp","svg","attr","sv","isOpen","msg","close","ev","optedOut","VID_KEY","visitorId","match","utmParams","utm","key","val","beaconPayload","beaconUrl","lastIdentitySignature","lastIdentityFingerprint","lastIdentitySentAt","storedAt","dispatchIdentify","payloadInput","scopeSignature","externalUserId","requestSignature","signedAtRaw","identityFingerprint","dedupeSignature","now","requestBody","identifyUrl","handleFormSubmit","event","formIdentifySetting","formSignature","pageCount","hist","loadedAt","siteStart","contextRetryTimers","returning","delay","timer","origPush","origReplace","onNav","h","navPayload","navUrl","args","lastScrollDepth","scrollTimeout","handleScroll","total","pct","handleMouseOut","idleTimer","idleFired","resetIdle","idleEvents","base","closeWidget","identify","input","handleIdentifyEvent","detail","targetSlug","t","parseBoolean","value","normalized","script","init","createWidget"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -16,15 +16,38 @@ interface BitPalmAgentOptions {
|
|
|
16
16
|
*/
|
|
17
17
|
autoIdentify?: boolean;
|
|
18
18
|
}
|
|
19
|
+
interface BitPalmIdentifyPayload {
|
|
20
|
+
/** Stable user id from the host platform (required for signed identify). */
|
|
21
|
+
externalUserId?: string;
|
|
22
|
+
/** Optional profile fields for visitor stitching. */
|
|
23
|
+
name?: string;
|
|
24
|
+
email?: string;
|
|
25
|
+
phone?: string;
|
|
26
|
+
company?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Optional backend-generated signature for signed identify flows.
|
|
29
|
+
* Forwarded as `signature` to `/api/widget/identify`.
|
|
30
|
+
*/
|
|
31
|
+
signature?: string;
|
|
32
|
+
/** Optional unix timestamp (seconds) for signed identify flows. */
|
|
33
|
+
signedAt?: number;
|
|
34
|
+
/** Signature schema version. Defaults to "v1". */
|
|
35
|
+
signatureVersion?: "v1";
|
|
36
|
+
}
|
|
19
37
|
interface BitPalmAgentInstance {
|
|
20
38
|
/** Open the chat widget programmatically. */
|
|
21
39
|
open: () => void;
|
|
22
40
|
/** Close the chat widget programmatically. */
|
|
23
41
|
close: () => void;
|
|
42
|
+
/**
|
|
43
|
+
* Manually identify the current visitor with trusted platform user data.
|
|
44
|
+
* Use this after your user login state is known.
|
|
45
|
+
*/
|
|
46
|
+
identify: (payload: BitPalmIdentifyPayload) => void;
|
|
24
47
|
/** Remove the widget and clean up all event listeners. */
|
|
25
48
|
destroy: () => void;
|
|
26
49
|
}
|
|
27
50
|
|
|
28
51
|
declare function createWidget(options: BitPalmAgentOptions): BitPalmAgentInstance;
|
|
29
52
|
|
|
30
|
-
export { type BitPalmAgentInstance, type BitPalmAgentOptions, createWidget };
|
|
53
|
+
export { type BitPalmAgentInstance, type BitPalmAgentOptions, type BitPalmIdentifyPayload, createWidget };
|
package/dist/index.d.ts
CHANGED
|
@@ -16,15 +16,38 @@ interface BitPalmAgentOptions {
|
|
|
16
16
|
*/
|
|
17
17
|
autoIdentify?: boolean;
|
|
18
18
|
}
|
|
19
|
+
interface BitPalmIdentifyPayload {
|
|
20
|
+
/** Stable user id from the host platform (required for signed identify). */
|
|
21
|
+
externalUserId?: string;
|
|
22
|
+
/** Optional profile fields for visitor stitching. */
|
|
23
|
+
name?: string;
|
|
24
|
+
email?: string;
|
|
25
|
+
phone?: string;
|
|
26
|
+
company?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Optional backend-generated signature for signed identify flows.
|
|
29
|
+
* Forwarded as `signature` to `/api/widget/identify`.
|
|
30
|
+
*/
|
|
31
|
+
signature?: string;
|
|
32
|
+
/** Optional unix timestamp (seconds) for signed identify flows. */
|
|
33
|
+
signedAt?: number;
|
|
34
|
+
/** Signature schema version. Defaults to "v1". */
|
|
35
|
+
signatureVersion?: "v1";
|
|
36
|
+
}
|
|
19
37
|
interface BitPalmAgentInstance {
|
|
20
38
|
/** Open the chat widget programmatically. */
|
|
21
39
|
open: () => void;
|
|
22
40
|
/** Close the chat widget programmatically. */
|
|
23
41
|
close: () => void;
|
|
42
|
+
/**
|
|
43
|
+
* Manually identify the current visitor with trusted platform user data.
|
|
44
|
+
* Use this after your user login state is known.
|
|
45
|
+
*/
|
|
46
|
+
identify: (payload: BitPalmIdentifyPayload) => void;
|
|
24
47
|
/** Remove the widget and clean up all event listeners. */
|
|
25
48
|
destroy: () => void;
|
|
26
49
|
}
|
|
27
50
|
|
|
28
51
|
declare function createWidget(options: BitPalmAgentOptions): BitPalmAgentInstance;
|
|
29
52
|
|
|
30
|
-
export { type BitPalmAgentInstance, type BitPalmAgentOptions, createWidget };
|
|
53
|
+
export { type BitPalmAgentInstance, type BitPalmAgentOptions, type BitPalmIdentifyPayload, createWidget };
|