@prodantix/sdk 0.1.0-beta.351 → 0.2.0-beta.357

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 CHANGED
@@ -36,9 +36,42 @@ if (await prodantix.isFeatureEnabled('new-checkout')) {
36
36
  }
37
37
  ```
38
38
 
39
- `createWebClient` wires `localStorage` persistence, `navigator.sendBeacon` delivery on page
40
- hide, and pageview + click autocapture. Pass `autocapture: false` to disable capture, or
41
- `autocaptureOptions: { pageviews, clicks }` to tune it.
39
+ `createWebClient` keeps the visitor's anonymous id and session in a first-party cookie on the
40
+ registrable domain, so `xyz.com`, `app.xyz.com` and `console.xyz.com` see one person; the
41
+ identified id stays per origin in `localStorage` and never enters the cookie. Pass `cookieDomain`
42
+ to name the domain (a site whose subdomains belong to different tenants must), or `sharedStorage`
43
+ to write no cookie. The queue persists in `localStorage`, delivery is by `navigator.sendBeacon`
44
+ on page hide, and pageviews and clicks are autocaptured. Pass `autocapture: false` to disable
45
+ capture, or `autocaptureOptions: { pageviews, clicks }` to tune it. A session id is minted per
46
+ visit (thirty minutes idle, twenty-four hours at most) and stamped on every event; pass
47
+ `sessionTracking: false` to stop it.
48
+
49
+ A cookie cannot cross a registrable domain, so a visitor who follows a link
50
+ from `example.com` to `example-app.com` would be two visitors. Pass
51
+ `linkedDomains: ['example.com', 'example-app.com']` (empty by default) and the
52
+ client decorates outbound links to those domains, on click and auxclick, with a
53
+ `_pdx` parameter carrying the anonymous id, the session id and the moment the
54
+ session started, so the session window continues across the hop. Only the
55
+ anonymous id travels, never an identified one: the destination identifies the
56
+ person itself. Same-domain links, links already carrying `_pdx`, and `mailto:`,
57
+ `tel:`, `javascript:` and hash links are left alone. On arrival `createWebClient`
58
+ adopts `_pdx` before identity is built and strips it with `history.replaceState`,
59
+ so it never appears in `$current_url`; an id this host already held is folded in
60
+ with `$create_alias`, and a host that has already identified a person keeps that
61
+ person.
62
+
63
+ The visitor's own answer about that join rides the same shared store, under
64
+ `pdx.<namespace>.consent`, so every subdomain and a server reading the cookie
65
+ through `readSharedIdentity` see the one answer. Record it with
66
+ `prodantix.setConsent({ identityLink: false })`, read it back with
67
+ `prodantix.consent()`, and pass `consent` to `createWebClient` when your app
68
+ already holds the answer (a consent banner is yours to build, and prodantix
69
+ honours what it collects). While `identityLink` is `false`, `identify` sends no
70
+ anonymous id to join to the person, and a link to a `linkedDomains` domain is
71
+ left undecorated, since carrying the id across is the same join by another
72
+ route. Unset or `true` allows both, subject to the project's own setting.
73
+ Changing the answer takes effect on the next `identify` and the next click:
74
+ nothing already joined is unjoined.
42
75
 
43
76
  ## Node / server
44
77
 
package/dist/chat.cjs CHANGED
@@ -1,14 +1,16 @@
1
- 'use strict';var I=Object.defineProperty;var O=(n,e,t)=>e in n?I(n,e,{enumerable:true,configurable:true,writable:true,value:t}):n[e]=t;var l=(n,e,t)=>O(n,typeof e!="symbol"?e+"":e,t);function w(n){if(n)return n;let e=globalThis.fetch;if(typeof e=="function")return e.bind(globalThis)}function A(n){return n.replace(/\/+$/,"")}var H="X-Prodantix-Conversation-Token",E="prodantix.chat.handle";function M(){let n=globalThis.localStorage;if(n)return {get:e=>n.getItem(e),remove:e=>n.removeItem(e),set:(e,t)=>n.setItem(e,t)}}var f=class{constructor(e){this.options=e;l(this,"fetchImpl");l(this,"host");l(this,"storage");l(this,"handle");l(this,"identity",null);this.fetchImpl=w(e.fetchImpl),this.host=A(e.host),this.storage=e.storage??M(),this.handle=this.readHandle();}get hasThread(){return this.handle!==null}get socketAuth(){return this.handle?{conversationId:this.handle.conversationId,conversationToken:this.handle.token,projectKey:this.options.apiKey}:null}identify(e){this.identity=e;}async ensureThread(e){if(this.handle)return true;let t=await this.request("POST","/v1/conversations",{body:{distinctId:this.options.distinctId,subject:e,userHash:this.identity?.userHash,userId:this.identity?.userId}});return !t?.conversationId||!t.token?false:(this.handle={conversationId:t.conversationId,token:t.token},this.storage?.set(E,JSON.stringify(this.handle)),true)}async send(e){if(!await this.ensureThread())return null;let t=this.handle;return t?(await this.request("POST",`/v1/conversations/${encodeURIComponent(t.conversationId)}/turns`,{body:{body:e},token:t.token}))?.turn??null:null}async load(){let e=this.handle;return e?this.request("GET",`/v1/conversations/${encodeURIComponent(e.conversationId)}`,{token:e.token}):null}readHandle(){let e=this.storage?.get(E);if(!e)return null;try{let t=JSON.parse(e);if(typeof t.conversationId=="string"&&typeof t.token=="string")return {conversationId:t.conversationId,token:t.token}}catch{}return this.storage?.remove(E),null}async request(e,t,r={}){let i=this.fetchImpl;if(!i)return this.options.onError?.(new Error("no fetch available for prodantix chat")),null;let a={authorization:`Bearer ${this.options.apiKey}`,"content-type":"application/json"};r.token&&(a[H]=r.token);try{let s=await i(`${this.host}${t}`,{body:r.body===void 0?void 0:JSON.stringify(r.body),headers:a,method:e}),o=await s.text();return s.ok?o?JSON.parse(o):{}:(this.options.onError?.(new Error(`prodantix chat ${t}: ${s.status}`)),null)}catch(s){return this.options.onError?.(s),null}}};var h={bubbleStyle:"tailed",launcherStyle:"circle_outlined",namePlacement:"avatar_only",skin:"concierge",timestampStyle:"cluster"},F=["concierge","console","quiet"],R=["avatar_circle","circle_filled","circle_outlined","pill_labelled","pill_team","squircle_filled"],$=["hairline","outlined","rounded","tailed"],K=["above","avatar_only","gutter","hidden","inline"],z=["cluster","latency","none","trailing","with_name"],b=(n,e,t)=>typeof n=="string"&&e.includes(n)?n:t;function y(n){let e={bubbleStyle:b(n?.bubbleStyle,$,h.bubbleStyle),launcherStyle:b(n?.launcherStyle,R,h.launcherStyle),namePlacement:b(n?.namePlacement,K,h.namePlacement),skin:b(n?.skin,F,h.skin),timestampStyle:b(n?.timestampStyle,z,h.timestampStyle)};return (e.namePlacement==="avatar_only"||e.namePlacement==="hidden")&&(e.timestampStyle==="with_name"||e.timestampStyle==="latency")&&(e.timestampStyle="trailing"),e.namePlacement==="inline"&&e.bubbleStyle==="hairline"&&(e.namePlacement="above"),e}var G={agentLabel:"Agent",aiLabel:"AI",closeLabel:"Close chat",emptyBody:"We usually reply within a few minutes.",emptyTitle:"Ask us anything.",inputPlaceholder:"Type a message",launcherLabel:"Open support chat",sendLabel:"Send",timeLabel:n=>{let e=new Date(n);return Number.isNaN(e.getTime())?"":`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`},title:"Support",unreadLabel:n=>`${n} unread`},v={accentColor:"#5b5bff",greeting:"",launcherOffsetX:20,launcherOffsetY:20,launcherPosition:"bottom_right",starterPrompts:[],...h},B={concierge:".panel{border-radius:16px;box-shadow:0 16px 40px rgba(0,0,0,.2)}.header{background:var(--a);color:#fff;flex-direction:column;align-items:flex-start;gap:14px;padding:18px 14px 20px 20px}.header h2{font-size:19px;font-weight:640}.composer{padding:12px 12px 14px;gap:8px}.composer input{border:0;background:var(--fill);height:46px;border-radius:23px;padding:0 16px}.composer button{width:46px;min-width:46px;height:46px;padding:0;border-radius:23px}.composer button .sendglyph{display:block}.composer button .sendtext{display:none}",console:".panel{border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.16)}.header{background:var(--paper);color:var(--ink);border-bottom:1px solid var(--hairline)}.close{color:var(--ink-2)}",quiet:".composer{position:relative;padding:10px 12px 12px}.composer input{height:42px;padding-right:42px}.composer button{position:absolute;top:50%;right:16px;width:34px;min-width:34px;height:34px;padding:0;background:transparent;color:var(--ink);border-radius:7px;transform:translateY(-50%)}.composer button .sendglyph{display:block;width:18px;height:18px}.composer button .sendtext{display:none}.panel{border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,.12)}.header{background:var(--paper);color:var(--ink);height:44px;padding:0 8px 0 16px;border-bottom:1px solid var(--hairline)}.header h2{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}.close{color:var(--ink-2)}"},D={avatar_circle:".launcher{width:60px;height:60px;border-radius:30px;background:var(--paper);border:1px solid var(--hairline);color:var(--ink-2)}",circle_filled:".launcher{width:56px;height:56px;border-radius:28px;background:var(--a);color:#fff}",circle_outlined:".launcher{width:46px;height:46px;border-radius:23px;background:var(--paper);border:1px solid var(--hairline);color:var(--ink-2);box-shadow:0 1px 2px rgba(0,0,0,.08);font-size:21px}.badge{background:var(--a);top:-7px;right:-7px;min-width:19px;height:19px;border-radius:10px;font-size:11.5px}",pill_labelled:".launcher{width:auto;height:52px;border-radius:26px;padding:0 22px;gap:10px;background:var(--a);color:#fff;font-size:14.5px;font-weight:600}",pill_team:".launcher{width:auto;height:54px;border-radius:27px;padding:0 20px 0 8px;gap:10px;background:var(--paper);border:1px solid var(--hairline);color:var(--ink);font-size:14px;font-weight:600}.badge{position:static;background:var(--a)}",squircle_filled:".launcher{width:56px;height:56px;border-radius:16px;background:var(--a);color:#fff}"},q={hairline:".turn{max-width:100%;padding:13px 0;border-top:1px solid var(--hairline);background:none;border-radius:0}.log>.turn:first-child{border-top:0}.turn.end_user{align-self:stretch;display:flex;flex-direction:column;align-items:flex-end}.turn.end_user .body{background:var(--fill);color:var(--ink);border-radius:8px;padding:9px 12px;max-width:85%}",outlined:".turn{background:none;border:1px solid var(--hairline);border-radius:12px}.turn.end_user{background:none;border-color:var(--a);color:var(--ink)}",rounded:".turn{border-radius:18px;padding:10px 15px}",tailed:".turn.agent,.turn.ai{border-radius:12px 12px 12px 4px}.turn.end_user{border-radius:12px 12px 4px 12px}"},U={above:"",avatar_only:".turn.agent,.turn.ai{display:flex;gap:10px;max-width:100%;background:none;padding:0}.turn .body{background:var(--fill);padding:9px 13px;border-radius:inherit}",gutter:".turn.agent,.turn.ai{display:flex;gap:10px;max-width:100%;background:none;padding:0}.turn .body{background:var(--fill);padding:9px 13px;border-radius:inherit}.author{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:600;opacity:1}",hidden:".turn.agent .author,.turn.ai .author:not(.ai){display:none}",inline:".author{display:inline;margin-right:6px;font-weight:650}"},j={cluster:'.divider{display:flex;align-items:center;gap:10px;margin:0;font-size:11px;opacity:.6}.divider:before,.divider:after{content:"";flex:1;height:1px;background:var(--hairline)}',latency:".stamp{font-size:11px;opacity:.7;margin-left:6px}.lat{font-size:11px;opacity:.7;margin-left:6px}",none:"",trailing:".stamp{display:block;font-size:11px;opacity:.7;margin-top:4px}.turn.end_user .stamp{text-align:right}",with_name:".stamp{font-size:11px;opacity:.7;margin-left:6px}"};function N(n){let e=y(n),t=n.launcherPosition==="bottom_left"?"left":"right",r=n.accentColor;return `${`
1
+ 'use strict';var $=Object.defineProperty;var z=(n,e,t)=>e in n?$(n,e,{enumerable:true,configurable:true,writable:true,value:t}):n[e]=t;var l=(n,e,t)=>z(n,typeof e!="symbol"?e+"":e,t);function A(n){if(n)return n;let e=globalThis.fetch;if(typeof e=="function")return e.bind(globalThis)}function w(n){return n.replace(/\/+$/,"")}var D="X-Prodantix-Conversation-Token",C="prodantix.chat.handle";function K(){let n=globalThis.localStorage;if(n)return {get:e=>n.getItem(e),remove:e=>n.removeItem(e),set:(e,t)=>n.setItem(e,t)}}var b=class{constructor(e){this.options=e;l(this,"fetchImpl");l(this,"host");l(this,"storage");l(this,"handle");l(this,"identity",null);this.fetchImpl=A(e.fetchImpl),this.host=w(e.host),this.storage=e.storage??K(),this.handle=this.readHandle();}get hasThread(){return this.handle!==null}get socketAuth(){return this.handle?{conversationId:this.handle.conversationId,conversationToken:this.handle.token,projectKey:this.options.apiKey}:null}identify(e){this.identity=e;}async ensureThread(e){if(this.handle)return true;let t=await this.request("POST","/v1/conversations",{body:{distinctId:this.options.distinctId,subject:e,userHash:this.identity?.userHash,userId:this.identity?.userId}});return !t?.conversationId||!t.token?false:(this.handle={conversationId:t.conversationId,token:t.token},this.storage?.set(C,JSON.stringify(this.handle)),true)}async send(e,t){if(!await this.ensureThread())return null;let r=this.handle;return r?(await this.request("POST",`/v1/conversations/${encodeURIComponent(r.conversationId)}/turns`,{body:{body:e,pageContext:t},token:r.token}))?.turn??null:null}async load(){let e=this.handle;return e?this.request("GET",`/v1/conversations/${encodeURIComponent(e.conversationId)}`,{token:e.token}):null}readHandle(){let e=this.storage?.get(C);if(!e)return null;try{let t=JSON.parse(e);if(typeof t.conversationId=="string"&&typeof t.token=="string")return {conversationId:t.conversationId,token:t.token}}catch{}return this.storage?.remove(C),null}async request(e,t,r={}){let a=this.fetchImpl;if(!a)return this.options.onError?.(new Error("no fetch available for prodantix chat")),null;let s={authorization:`Bearer ${this.options.apiKey}`,"content-type":"application/json"};r.token&&(s[D]=r.token);try{let o=await a(`${this.host}${t}`,{body:r.body===void 0?void 0:JSON.stringify(r.body),headers:s,method:e}),i=await o.text();return o.ok?i?JSON.parse(i):{}:(this.options.onError?.(new Error(`prodantix chat ${t}: ${o.status}`)),null)}catch(o){return this.options.onError?.(o),null}}};var p={bubbleStyle:"tailed",dayDividers:true,launcherContent:"glyph",launcherFill:"outlined",launcherShape:"circle",launcherSize:"small",nameAvatar:true,namePlacement:"hidden",skin:"concierge",stampContent:"time",stampPlacement:"none"},G=["concierge","console","quiet"],U=["hairline","outlined","rounded","tailed"],B=["circle","pill","squircle"],q=["filled","outlined"],Y=["avatar","glyph","team_faces"],j=["large","medium","small"],W=["above","hidden","inline"],J=["beside_name","none","under_turn"],X=["time","time_and_latency"],m=(n,e,t)=>typeof n=="string"&&e.includes(n)?n:t,L=(n,e)=>typeof n=="boolean"?n:e,V={avatar_circle:["circle","outlined","avatar","large"],circle_filled:["circle","filled","glyph","medium"],circle_outlined:["circle","outlined","glyph","small"],pill_labelled:["pill","filled","glyph","medium"],pill_team:["pill","outlined","team_faces","medium"],squircle_filled:["squircle","filled","glyph","medium"]},Z={above:["above",false],avatar_only:["hidden",true],gutter:["above",true],hidden:["hidden",false],inline:["inline",false]},Q={cluster:[true,"none","time"],latency:[false,"beside_name","time_and_latency"],none:[false,"none","time"],trailing:[false,"under_turn","time"],with_name:[false,"beside_name","time"]};function y(n){let e=typeof n=="object"&&n!==null?n:{},t=typeof e.launcherStyle=="string"?e.launcherStyle:void 0,r=t===void 0?void 0:V[t],a=typeof e.namePlacement=="string"?e.namePlacement:void 0,s=a===void 0?void 0:Z[a],o=typeof e.timestampStyle=="string"?e.timestampStyle:void 0,i=o===void 0?void 0:Q[o],c={bubbleStyle:m(e.bubbleStyle,U,p.bubbleStyle),dayDividers:L(e.dayDividers,i?.[0]??p.dayDividers),launcherContent:m(e.launcherContent,Y,r?.[2]??p.launcherContent),launcherFill:m(e.launcherFill,q,r?.[1]??p.launcherFill),launcherShape:m(e.launcherShape,B,r?.[0]??p.launcherShape),launcherSize:m(e.launcherSize,j,r?.[3]??p.launcherSize),nameAvatar:L(e.nameAvatar,s?.[1]??p.nameAvatar),namePlacement:m(e.namePlacement,W,s?.[0]??p.namePlacement),skin:m(e.skin,G,p.skin),stampContent:m(e.stampContent,X,i?.[2]??p.stampContent),stampPlacement:m(e.stampPlacement,J,i?.[1]??p.stampPlacement)};return c.stampPlacement==="beside_name"&&c.namePlacement==="hidden"&&(c.stampPlacement="under_turn"),c.namePlacement==="inline"&&c.bubbleStyle==="hairline"&&(c.namePlacement="above"),c}var ee={Fri:"fri",Mon:"mon",Sat:"sat",Sun:"sun",Thu:"thu",Tue:"tue",Wed:"wed"};function N(n,e){let t=new Intl.DateTimeFormat(void 0,{hour:"2-digit",hour12:false,minute:"2-digit",timeZone:n.timezone,weekday:"short"}).formatToParts(e),r=ee[t.find(i=>i.type==="weekday")?.value??""];if(!r)return false;let a=t.find(i=>i.type==="hour")?.value??"",s=t.find(i=>i.type==="minute")?.value??"",o=`${a}:${s}`;return n.windows.some(i=>i.days.includes(r)&&i.open<=o&&o<i.close)}var te="M20 11.6a7.4 7.4 0 0 1-7.4 7.4H8.2L4 21.8l1-4.1A7.4 7.4 0 1 1 20 11.6Z",ne={large:66,medium:56,small:46},re={circle:"width:var(--fab-size);height:var(--fab-size);border-radius:calc(var(--fab-size) / 2);",pill:"width:auto;height:var(--fab-size);border-radius:calc(var(--fab-size) / 2);padding:0 22px;gap:10px;",squircle:"width:var(--fab-size);height:var(--fab-size);border-radius:16px;"},ae={filled:"background:var(--a);color:#fff;",outlined:"background:var(--paper);border:1px solid var(--hairline);color:var(--ink-2);box-shadow:0 1px 2px rgba(0,0,0,.08);"},ie={avatar:".launcher .live{width:10px;height:10px;position:absolute;right:3px;bottom:3px;border-radius:50%;background:var(--online);box-shadow:0 0 0 2px var(--paper);}",glyph:".launcher svg{width:calc(var(--fab-size) * 0.375);height:calc(var(--fab-size) * 0.375);}",team_faces:".launcher .faces{display:flex;}.launcher .faces .av{box-shadow:0 0 0 2px var(--paper);}.launcher .faces .av+.av{margin-left:-10px;}.launcher .live{width:9px;height:9px;position:absolute;right:3px;bottom:3px;border-radius:50%;background:var(--online);box-shadow:0 0 0 2px var(--paper);}"},oe={circle:"",pill:".badge{position:static;box-shadow:none}",squircle:""},se={filled:"",outlined:".badge{background:var(--a);top:-7px;right:-7px;min-width:19px;height:19px;font-size:11.5px}"},le={circle:"",pill:".launcher .label{font-size:14px;font-weight:600;white-space:nowrap;}",squircle:""},ce={circle:"",pill:"@media (max-width:480px){.launcher{width:var(--fab-size);padding:0}.launcher .label{display:none}}",squircle:""};function I(n,e,t,r){return `.launcher{--fab-size:${ne[r]}px;${re[n]}${ae[e]}}${ie[t]}${oe[n]}${se[e]}${le[n]}${ce[n]}`}function H(n,e,t){let r=document.createDocumentFragment();if(n==="glyph"){let o=document.createElement("span");return o.innerHTML=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="${te}"/></svg>`,r.append(...o.childNodes),r}if(n==="avatar")return r.append(_(t[0],e),P()),r;let a=document.createElement("span");a.className="faces";let s=t.length>0?t.slice(0,2):[void 0];for(let o of s)a.append(_(o,e));return r.append(a,P()),r}function _(n,e){let t=document.createElement("span");return t.className="av",t.setAttribute("aria-hidden","true"),t.textContent=n?n.initials:e.agentLabel.slice(0,2).toUpperCase(),n&&(t.style.background=n.tone),t}function P(){let n=document.createElement("span");return n.className="live",n.setAttribute("aria-hidden","true"),n}var de={agentLabel:"Agent",aiLabel:"AI",closeLabel:"Close chat",emptyBody:"We usually reply within a few minutes.",emptyTitle:"Ask us anything.",inputPlaceholder:"Type a message",launcherLabel:"Open support chat",sendLabel:"Send",timeLabel:n=>{let e=new Date(n);return Number.isNaN(e.getTime())?"":`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`},title:"Support",unreadLabel:n=>`${n} unread`},v={accentColor:"#5b5bff",availability:{timezone:"UTC",windows:[]},awayMessage:"",greeting:"",launcherOffsetX:20,launcherOffsetY:20,launcherPosition:"bottom_right",starterPrompts:[],teamFaces:[],...p},pe={concierge:".panel{border-radius:16px;box-shadow:0 16px 40px rgba(0,0,0,.2)}.header{background:var(--a);color:#fff;flex-direction:column;align-items:flex-start;gap:14px;padding:18px 14px 20px 20px}.header h2{font-size:19px;font-weight:640}.composer{padding:12px 12px 14px;gap:8px}.composer input{border:0;background:var(--fill);height:46px;border-radius:23px;padding:0 16px}.composer button{width:46px;min-width:46px;height:46px;padding:0;border-radius:23px}.composer button .sendglyph{display:block}.composer button .sendtext{display:none}",console:".panel{border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.16)}.header{background:var(--paper);color:var(--ink);border-bottom:1px solid var(--hairline)}.close{color:var(--ink-2)}",quiet:".composer{position:relative;padding:10px 12px 12px}.composer input{height:42px;padding-right:42px}.composer button{position:absolute;top:50%;right:16px;width:34px;min-width:34px;height:34px;padding:0;background:transparent;color:var(--ink);border-radius:7px;transform:translateY(-50%)}.composer button .sendglyph{display:block;width:18px;height:18px}.composer button .sendtext{display:none}.panel{border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,.12)}.header{background:var(--paper);color:var(--ink);height:44px;padding:0 8px 0 16px;border-bottom:1px solid var(--hairline)}.header h2{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}.close{color:var(--ink-2)}"},ue={hairline:".turn{max-width:100%;padding:13px 0;border-top:1px solid var(--hairline);background:none;border-radius:0}.log>.turn:first-child{border-top:0}.turn.end_user{align-self:stretch;display:flex;flex-direction:column;align-items:flex-end}.turn.end_user .body{background:var(--fill);color:var(--ink);border-radius:8px;padding:9px 12px;max-width:85%}",outlined:".turn{background:none;border:1px solid var(--hairline);border-radius:12px}.turn.end_user{background:none;border-color:var(--a);color:var(--ink)}",rounded:".turn{border-radius:18px;padding:10px 15px}",tailed:".turn.agent,.turn.ai{border-radius:12px 12px 12px 4px}.turn.end_user{border-radius:12px 12px 4px 12px}"},he={above:"",hidden:".turn.agent .author,.turn.ai .author:not(.ai){display:none}",inline:".author{display:inline;margin-right:6px;font-weight:650}"},me=".turn.agent,.turn.ai{display:flex;gap:10px;max-width:100%;background:none;padding:0}.turn .body{background:var(--fill);padding:9px 13px;border-radius:inherit}.author{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:600;opacity:1}",ge='.divider{display:flex;align-items:center;gap:10px;margin:0;font-size:11px;opacity:.6}.divider:before,.divider:after{content:"";flex:1;height:1px;background:var(--hairline)}',fe={beside_name:".stamp{font-size:11px;opacity:.7;margin-left:6px}",none:"",under_turn:".stamp{display:block;font-size:11px;opacity:.7;margin-top:4px}.turn.end_user .stamp{text-align:right}"},be=".lat{font-size:11px;opacity:.7;margin-left:6px}";function F(n){let e=y(n),t=n.launcherPosition==="bottom_left"?"left":"right",r=n.accentColor;return `${`
2
2
  :host {
3
3
  all: initial; --a: ${r};
4
4
  --paper: #fff; --ink: #0f172a; --ink-3: var(--ink-3);
5
5
  --fill: #f1f5f9; --hairline: #e2e8f0; --field: #cbd5e1; --ink-2: rgba(0,0,0,.72);
6
+ --online: oklch(53.8% 0.1274 163.23);
6
7
  color-scheme: light dark;
7
8
  }
8
9
  @media (prefers-color-scheme: dark) {
9
10
  :host {
10
11
  --paper: oklch(24.6% 0.015 257); --ink: #fff; --ink-3: rgba(255,255,255,.55);
11
12
  --fill: rgba(255,255,255,.06); --hairline: rgba(255,255,255,.13); --field: rgba(255,255,255,.22); --ink-2: rgba(255,255,255,.70);
13
+ --online: oklch(72% 0.13 163.23);
12
14
  }
13
15
  }
14
16
  * { box-sizing: border-box; font-family: system-ui, sans-serif; }
@@ -40,6 +42,7 @@
40
42
  .turn.end_user { align-self: flex-end; background: ${r}; color: #fff; }
41
43
  .turn.agent, .turn.ai { align-self: flex-start; background: var(--fill); color: var(--ink); }
42
44
  .author { font-size: 11px; opacity: .7; margin-bottom: 2px; }
45
+ .away { background: var(--fill); border: 1px solid var(--hairline); border-radius: 8px; padding: 8px 12px; font-size: 13.5px; color: var(--ink-2); }
43
46
  .empty { display: flex; flex-direction: column; gap: 8px; padding: 20px 16px; }
44
47
  .empty h3 { margin: 0; font-size: 18px; font-weight: 640; letter-spacing: -.015em; }
45
48
  .empty p { margin: 0 0 8px; font-size: 13.5px; color: var(--ink-2); }
@@ -61,5 +64,5 @@
61
64
  .panel { animation: rise 180ms ease-out; }
62
65
  @keyframes rise { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }
63
66
  }
64
- `}${B[e.skin]}${D[e.launcherStyle]}${q[e.bubbleStyle]}${U[e.namePlacement]}${j[e.timestampStyle]}`}var W=["end_user","agent","ai"],x=class{constructor(e,t,r={},i={}){this.host=e;this.client=t;l(this,"root");l(this,"strings");l(this,"settings");l(this,"appearance");l(this,"launcher");l(this,"badge");l(this,"panel",null);l(this,"lastFocused",null);l(this,"unread",0);this.strings={...G,...r},this.appearance={...v,...i},this.settings=y({...v,...i}),this.root=e.attachShadow({mode:"closed"});let a=document.createElement("style");a.textContent=N({...v,...i}),this.root.append(a),this.launcher=document.createElement("button"),this.launcher.className="launcher",this.launcher.type="button",this.launcher.setAttribute("aria-haspopup","dialog"),this.launcher.setAttribute("aria-label",this.strings.launcherLabel),this.launcher.textContent="\u{1F4AC}",this.launcher.addEventListener("click",()=>this.toggle()),this.badge=document.createElement("span"),this.badge.className="badge",this.badge.hidden=true,this.launcher.append(this.badge),this.root.append(this.launcher);}toggle(){this.panel?this.close():this.open();}async open(){if(this.panel)return;this.lastFocused=this.host.ownerDocument.activeElement,this.unread=0,this.renderBadge();let e=document.createElement("section");e.className="panel",e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true"),e.setAttribute("aria-label",this.strings.title);let t=document.createElement("div");t.className="header";let r=document.createElement("h2");r.textContent=this.strings.title;let i=document.createElement("button");i.className="close",i.type="button",i.setAttribute("aria-label",this.strings.closeLabel),i.textContent="\xD7",i.addEventListener("click",()=>this.close()),t.append(r,i);let a=document.createElement("div");a.className="log",a.setAttribute("role","log"),a.setAttribute("aria-live","polite"),a.setAttribute("aria-label",this.strings.title);let s=document.createElement("form");s.className="composer";let o=document.createElement("input");o.type="text",o.setAttribute("aria-label",this.strings.inputPlaceholder),o.placeholder=this.strings.inputPlaceholder;let p=document.createElement("button");p.type="submit",p.setAttribute("aria-label",this.strings.sendLabel),p.innerHTML='<svg class="sendglyph" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 12 20 4.5 15 20l-3.6-5.4L4.5 12Z"/></svg>';let u=document.createElement("span");u.className="sendtext",u.textContent=this.strings.sendLabel,p.append(u),s.append(o,p),s.addEventListener("submit",g=>{g.preventDefault(),this.submit(o,a);}),e.append(t,a,s),e.addEventListener("keydown",g=>this.onKeydown(g,e,i)),this.root.append(e),this.panel=e,o.focus();let d=await this.client.load();d&&d.turns.length>0?this.renderThread(a,d):this.renderFirstRun(a,o);}renderFirstRun(e,t){let r=document.createElement("div");r.className="empty";let i=document.createElement("h3");i.textContent=this.appearance.greeting.trim()||this.strings.emptyTitle;let a=document.createElement("p");a.textContent=this.strings.emptyBody,r.append(i,a);for(let s of this.appearance.starterPrompts){let o=document.createElement("button");o.className="prompt",o.type="button",o.textContent=s,o.addEventListener("click",()=>{t.value=s,this.submit(t,e);}),r.append(o);}e.replaceChildren(r);}close(){this.panel&&(this.panel.remove(),this.panel=null,this.lastFocused instanceof HTMLElement?this.lastFocused.focus():this.launcher.focus());}onIncomingTurn(e){if(this.panel){let t=this.panel.querySelector(".log");t instanceof HTMLElement&&this.appendTurn(t,e);return}e.authorKind!=="end_user"&&(this.unread+=1,this.renderBadge());}async submit(e,t){let r=e.value.trim();if(!r)return;e.value="",t.querySelector(".empty")?.remove();let i=await this.client.send(r);i&&this.appendTurn(t,i);}renderThread(e,t){e.replaceChildren();for(let r of t.turns)this.appendTurn(e,r);}appendTurn(e,t){e.querySelector(".empty")?.remove();let r=W.includes(t.authorKind)?t.authorKind:"agent",i=this.settings,a=document.createElement("div");if(a.className=`turn ${r}`,r!=="end_user"&&(i.namePlacement==="avatar_only"||i.namePlacement==="gutter")){let d=document.createElement("span");d.className=r==="ai"?"av bot":"av",d.textContent=r==="ai"?this.strings.aiLabel:this.strings.agentLabel.slice(0,2).toUpperCase(),d.setAttribute("aria-hidden","true"),a.append(d);}let o=document.createElement("div");if(o.className="body",r!=="end_user"&&i.namePlacement!=="hidden"&&!(i.namePlacement==="avatar_only"&&r==="agent")||r==="ai"&&i.namePlacement==="hidden"){let d=document.createElement("div");d.className=r==="ai"?"author ai":"author",d.textContent=r==="ai"?this.strings.aiLabel:this.strings.agentLabel,(i.timestampStyle==="with_name"||i.timestampStyle==="latency")&&d.append(this.stamp(t)),o.append(d);}let u=document.createElement("div");u.textContent=t.body,o.append(u),i.timestampStyle==="trailing"&&o.append(this.stamp(t)),a.append(o),e.append(a),e.scrollTop=e.scrollHeight;}stamp(e){let t=document.createElement("span");return t.className="stamp",t.textContent=this.strings.timeLabel(e.createdAt),t}onKeydown(e,t,r){if(e.key==="Escape"){e.preventDefault(),this.close();return}if(e.key!=="Tab")return;let i=t.querySelectorAll('button, input, [tabindex]:not([tabindex="-1"])');if(i.length===0)return;let a=i[0],s=i[i.length-1],o=this.root.activeElement;e.shiftKey&&o===a?(e.preventDefault(),s.focus()):!e.shiftKey&&o===s?(e.preventDefault(),a.focus()):o===null&&(e.preventDefault(),r.focus());}renderBadge(){this.unread>0?(this.badge.hidden=false,this.badge.textContent=String(this.unread),this.launcher.setAttribute("aria-label",`${this.strings.launcherLabel}, ${this.strings.unreadLabel(this.unread)}`)):(this.badge.hidden=true,this.badge.textContent="",this.launcher.setAttribute("aria-label",this.strings.launcherLabel));}};function _(n){return `40${JSON.stringify(n)}`}function P(){return "3"}function L(n){let e=n.charAt(0),t=n.slice(1);if(e==="2")return {kind:"ping"};if(e==="1")return {kind:"disconnect"};if(e==="0"){let s=T(t);return {kind:"open",pingInterval:typeof s?.pingInterval=="number"?s.pingInterval:25e3,pingTimeout:typeof s?.pingTimeout=="number"?s.pingTimeout:2e4}}if(e!=="4")return {kind:"other"};let r=t.charAt(0),i=t.slice(1);if(r==="0")return {kind:"connected"};if(r==="1")return {kind:"disconnect"};if(r==="4"){let s=T(i);return {kind:"connectError",message:typeof s?.message=="string"?s.message:"refused"}}if(r!=="2")return {kind:"other"};let a=T(i);return !Array.isArray(a)||typeof a[0]!="string"?{kind:"other"}:{kind:"event",name:a[0],payload:a[1]}}function T(n){try{return JSON.parse(n)}catch{return null}}var Y="/socket.io/?EIO=4&transport=websocket",k=class{constructor(e){this.options=e;l(this,"socket",null);l(this,"heartbeat",null);l(this,"ready",false);l(this,"closed",false);l(this,"heartbeatWindow",45e3);l(this,"factory");l(this,"setTimer");l(this,"clearTimer");this.factory=e.socketFactory??J,this.setTimer=e.setTimer??((t,r)=>setTimeout(t,r)),this.clearTimer=e.clearTimer??(t=>clearTimeout(t));}open(){if(this.socket||this.closed)return;let e=`${this.options.host.replace(/^http/,"ws").replace(/\/+$/,"")}${Y}`,t;try{t=this.factory(e);}catch{this.options.onClosed(false);return}this.socket=t,t.onmessage=r=>this.receive(String(r.data)),t.onerror=()=>t.close(),t.onclose=()=>this.fell();}close(){this.closed=true,this.stopHeartbeat();let e=this.socket;this.socket=null,e?.close();}receive(e){let t=L(e);if(t.kind==="open"){this.armHeartbeat(t.pingInterval+t.pingTimeout),this.socket?.send(_(this.options.auth));return}if(t.kind==="ping"){this.armHeartbeat(),this.socket?.send(P());return}if(t.kind==="connectError"||t.kind==="disconnect"){this.stopHeartbeat(),this.socket?.close();return}if(t.kind==="event"){if(t.name==="ready"){this.ready=true,this.options.onReady();return}if(t.name==="conversation.turn"){let r=t.payload?.turn;r&&this.options.onTurn(r);}}}fell(){this.stopHeartbeat();let e=this.ready;this.socket=null,this.ready=false,this.closed||this.options.onClosed(e);}armHeartbeat(e){e!==void 0&&(this.heartbeatWindow=e),this.stopHeartbeat(),this.heartbeat=this.setTimer(()=>this.socket?.close(),this.heartbeatWindow);}stopHeartbeat(){this.heartbeat!==null&&this.clearTimer(this.heartbeat),this.heartbeat=null;}};function J(n){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket");return new e(n)}function ue(n){let e=globalThis.document;if(!e)throw new Error("prodantix chat requires a document; mount it in the browser");let t=n.mountPoint??e.createElement("div");n.mountPoint||e.body.append(t);let r=new f(n),i=new x(t,r,n.strings,n.appearance),a=new Set,s,o=null,p=n.pollIntervalMs??15e3,u=c=>{a.has(c.id)||c.authorKind==="end_user"||(a.add(c.id),i.onIncomingTurn(c));},d=async()=>{if(!r.hasThread)return;let c=await r.load();if(c){for(let m of c.turns)u(m);a=new Set(c.turns.map(m=>m.id));}},g=()=>{s||p<=0||(s=setInterval(()=>void d(),p));},C=()=>{s&&clearInterval(s),s=void 0;},S=()=>{if(o||!n.socketHost)return;let c=r.socketAuth;c&&(o=new k({auth:c,host:n.socketHost,onClosed:m=>{o=null,g(),m&&S();},onReady:C,onTurn:u,socketFactory:n.socketFactory}),o.open());};return g(),S(),{close:()=>i.close(),destroy:()=>{C(),o?.close(),o=null,i.close(),t.remove();},identify:c=>r.identify(c),open:()=>{i.open().then(S);}}}exports.ChatClient=f;exports.ChatPanel=x;exports.DEFAULT_APPEARANCE=v;exports.DEFAULT_APPEARANCE_SETTINGS=h;exports.mountChat=ue;exports.panelStyles=N;exports.resolveAppearance=y;//# sourceMappingURL=chat.cjs.map
67
+ `}${pe[e.skin]}${I(e.launcherShape,e.launcherFill,e.launcherContent,e.launcherSize)}${ue[e.bubbleStyle]}${he[e.namePlacement]}${e.nameAvatar?me:""}${e.dayDividers?ge:""}${fe[e.stampPlacement]}${e.stampContent==="time_and_latency"?be:""}`}var xe=["end_user","agent","ai"];function ye(){let n=globalThis.location;if(n)return {host:n.host,path:n.pathname,title:document.title}}var x=class{constructor(e,t,r={},a={}){this.host=e;this.client=t;l(this,"root");l(this,"strings");l(this,"settings");l(this,"appearance");l(this,"launcher");l(this,"badge");l(this,"panel",null);l(this,"lastFocused",null);l(this,"unread",0);this.strings={...de,...r},this.appearance={...v,...a},this.settings=y({...v,...a}),this.root=e.attachShadow({mode:"closed"});let s=document.createElement("style");if(s.textContent=F({...v,...a}),this.root.append(s),this.launcher=document.createElement("button"),this.launcher.className="launcher",this.launcher.type="button",this.launcher.setAttribute("aria-haspopup","dialog"),this.launcher.setAttribute("aria-label",this.strings.launcherLabel),this.launcher.append(H(this.settings.launcherContent,this.strings,this.appearance.teamFaces)),this.settings.launcherShape==="pill"){let o=document.createElement("span");o.className="label",o.textContent=this.settings.launcherContent==="team_faces"?this.strings.agentLabel:this.strings.launcherLabel,this.launcher.append(o);}this.launcher.addEventListener("click",()=>this.toggle()),this.badge=document.createElement("span"),this.badge.className="badge",this.badge.hidden=true,this.launcher.append(this.badge),this.root.append(this.launcher);}toggle(){this.panel?this.close():this.open();}async open(){if(this.panel)return;this.lastFocused=this.host.ownerDocument.activeElement,this.unread=0,this.renderBadge();let e=document.createElement("section");e.className="panel",e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true"),e.setAttribute("aria-label",this.strings.title);let t=document.createElement("div");t.className="header";let r=document.createElement("h2");r.textContent=this.strings.title;let a=document.createElement("button");a.className="close",a.type="button",a.setAttribute("aria-label",this.strings.closeLabel),a.textContent="\xD7",a.addEventListener("click",()=>this.close()),t.append(r,a);let s=document.createElement("div");s.className="log",s.setAttribute("role","log"),s.setAttribute("aria-live","polite"),s.setAttribute("aria-label",this.strings.title);let o=document.createElement("form");o.className="composer";let i=document.createElement("input");i.type="text",i.setAttribute("aria-label",this.strings.inputPlaceholder),i.placeholder=this.strings.inputPlaceholder;let c=document.createElement("button");c.type="submit",c.setAttribute("aria-label",this.strings.sendLabel),c.innerHTML='<svg class="sendglyph" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 12 20 4.5 15 20l-3.6-5.4L4.5 12Z"/></svg>';let h=document.createElement("span");h.className="sendtext",h.textContent=this.strings.sendLabel,c.append(h),o.append(i,c),o.addEventListener("submit",g=>{g.preventDefault(),this.submit(i,s);}),e.append(t,s,o),e.addEventListener("keydown",g=>this.onKeydown(g,e,a)),this.root.append(e),this.panel=e,i.focus();let d=await this.client.load();d&&d.turns.length>0?this.renderThread(s,d):this.renderFirstRun(s,i),!N(this.appearance.availability,new Date)&&this.appearance.awayMessage.trim()&&this.renderAway(s);}renderFirstRun(e,t){let r=document.createElement("div");r.className="empty";let a=document.createElement("h3");a.textContent=this.appearance.greeting.trim()||this.strings.emptyTitle;let s=document.createElement("p");s.textContent=this.strings.emptyBody,r.append(a,s);for(let o of this.appearance.starterPrompts){let i=document.createElement("button");i.className="prompt",i.type="button",i.textContent=o,i.addEventListener("click",()=>{t.value=o,this.submit(t,e);}),r.append(i);}e.replaceChildren(r);}renderAway(e){let t=document.createElement("div");t.className="away",t.textContent=this.appearance.awayMessage,e.prepend(t);}close(){this.panel&&(this.panel.remove(),this.panel=null,this.lastFocused instanceof HTMLElement?this.lastFocused.focus():this.launcher.focus());}onIncomingTurn(e){if(this.panel){let t=this.panel.querySelector(".log");t instanceof HTMLElement&&this.appendTurn(t,e);return}e.authorKind!=="end_user"&&(this.unread+=1,this.renderBadge());}async submit(e,t){let r=e.value.trim();if(!r)return;e.value="",t.querySelector(".empty")?.remove();let a=await this.client.send(r,ye());a&&this.appendTurn(t,a);}renderThread(e,t){e.replaceChildren();for(let r of t.turns)this.appendTurn(e,r);}appendTurn(e,t){e.querySelector(".empty")?.remove();let r=xe.includes(t.authorKind)?t.authorKind:"agent",a=this.settings,s=document.createElement("div");if(s.className=`turn ${r}`,r!=="end_user"&&a.nameAvatar){let d=document.createElement("span");d.className=r==="ai"?"av bot":"av",d.textContent=r==="ai"?this.strings.aiLabel:this.strings.agentLabel.slice(0,2).toUpperCase(),d.setAttribute("aria-hidden","true"),s.append(d);}let i=document.createElement("div");if(i.className="body",r!=="end_user"&&a.namePlacement!=="hidden"||r==="ai"&&a.namePlacement==="hidden"){let d=document.createElement("div");d.className=r==="ai"?"author ai":"author",d.textContent=r==="ai"?this.strings.aiLabel:this.strings.agentLabel,a.stampPlacement==="beside_name"&&d.append(this.stamp(t)),i.append(d);}let h=document.createElement("div");h.textContent=t.body,i.append(h),a.stampPlacement==="under_turn"&&i.append(this.stamp(t)),s.append(i),e.append(s),e.scrollTop=e.scrollHeight;}stamp(e){let t=document.createElement("span");return t.className="stamp",t.textContent=this.strings.timeLabel(e.createdAt),t}onKeydown(e,t,r){if(e.key==="Escape"){e.preventDefault(),this.close();return}if(e.key!=="Tab")return;let a=t.querySelectorAll('button, input, [tabindex]:not([tabindex="-1"])');if(a.length===0)return;let s=a[0],o=a[a.length-1],i=this.root.activeElement;e.shiftKey&&i===s?(e.preventDefault(),o.focus()):!e.shiftKey&&i===o?(e.preventDefault(),s.focus()):i===null&&(e.preventDefault(),r.focus());}renderBadge(){this.unread>0?(this.badge.hidden=false,this.badge.textContent=String(this.unread),this.launcher.setAttribute("aria-label",`${this.strings.launcherLabel}, ${this.strings.unreadLabel(this.unread)}`)):(this.badge.hidden=true,this.badge.textContent="",this.launcher.setAttribute("aria-label",this.strings.launcherLabel));}};function R(n){return `40${JSON.stringify(n)}`}function O(){return "3"}function M(n){let e=n.charAt(0),t=n.slice(1);if(e==="2")return {kind:"ping"};if(e==="1")return {kind:"disconnect"};if(e==="0"){let o=E(t);return {kind:"open",pingInterval:typeof o?.pingInterval=="number"?o.pingInterval:25e3,pingTimeout:typeof o?.pingTimeout=="number"?o.pingTimeout:2e4}}if(e!=="4")return {kind:"other"};let r=t.charAt(0),a=t.slice(1);if(r==="0")return {kind:"connected"};if(r==="1")return {kind:"disconnect"};if(r==="4"){let o=E(a);return {kind:"connectError",message:typeof o?.message=="string"?o.message:"refused"}}if(r!=="2")return {kind:"other"};let s=E(a);return !Array.isArray(s)||typeof s[0]!="string"?{kind:"other"}:{kind:"event",name:s[0],payload:s[1]}}function E(n){try{return JSON.parse(n)}catch{return null}}var ve="/socket.io/?EIO=4&transport=websocket",S=class{constructor(e){this.options=e;l(this,"socket",null);l(this,"heartbeat",null);l(this,"ready",false);l(this,"closed",false);l(this,"heartbeatWindow",45e3);l(this,"factory");l(this,"setTimer");l(this,"clearTimer");this.factory=e.socketFactory??Se,this.setTimer=e.setTimer??((t,r)=>setTimeout(t,r)),this.clearTimer=e.clearTimer??(t=>clearTimeout(t));}open(){if(this.socket||this.closed)return;let e=`${this.options.host.replace(/^http/,"ws").replace(/\/+$/,"")}${ve}`,t;try{t=this.factory(e);}catch{this.options.onClosed(false);return}this.socket=t,t.onmessage=r=>this.receive(String(r.data)),t.onerror=()=>t.close(),t.onclose=()=>this.fell();}close(){this.closed=true,this.stopHeartbeat();let e=this.socket;this.socket=null,e?.close();}receive(e){let t=M(e);if(t.kind==="open"){this.armHeartbeat(t.pingInterval+t.pingTimeout),this.socket?.send(R(this.options.auth));return}if(t.kind==="ping"){this.armHeartbeat(),this.socket?.send(O());return}if(t.kind==="connectError"||t.kind==="disconnect"){this.stopHeartbeat(),this.socket?.close();return}if(t.kind==="event"){if(t.name==="ready"){this.ready=true,this.options.onReady();return}if(t.name==="conversation.turn"){let r=t.payload?.turn;r&&this.options.onTurn(r);}}}fell(){this.stopHeartbeat();let e=this.ready;this.socket=null,this.ready=false,this.closed||this.options.onClosed(e);}armHeartbeat(e){e!==void 0&&(this.heartbeatWindow=e),this.stopHeartbeat(),this.heartbeat=this.setTimer(()=>this.socket?.close(),this.heartbeatWindow);}stopHeartbeat(){this.heartbeat!==null&&this.clearTimer(this.heartbeat),this.heartbeat=null;}};function Se(n){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket");return new e(n)}function Ge(n){let e=globalThis.document;if(!e)throw new Error("prodantix chat requires a document; mount it in the browser");let t=n.mountPoint??e.createElement("div");n.mountPoint||e.body.append(t);let r=new b(n),a=new x(t,r,n.strings,n.appearance),s=new Set,o,i=null,c=n.pollIntervalMs??15e3,h=u=>{s.has(u.id)||u.authorKind==="end_user"||(s.add(u.id),a.onIncomingTurn(u));},d=async()=>{if(!r.hasThread)return;let u=await r.load();if(u){for(let f of u.turns)h(f);s=new Set(u.turns.map(f=>f.id));}},g=()=>{o||c<=0||(o=setInterval(()=>void d(),c));},T=()=>{o&&clearInterval(o),o=void 0;},k=()=>{if(i||!n.socketHost)return;let u=r.socketAuth;u&&(i=new S({auth:u,host:n.socketHost,onClosed:f=>{i=null,g(),f&&k();},onReady:T,onTurn:h,socketFactory:n.socketFactory}),i.open());};return g(),k(),{close:()=>a.close(),destroy:()=>{T(),i?.close(),i=null,a.close(),t.remove();},identify:u=>r.identify(u),open:()=>{a.open().then(k);}}}exports.ChatClient=b;exports.ChatPanel=x;exports.DEFAULT_APPEARANCE=v;exports.DEFAULT_APPEARANCE_SETTINGS=p;exports.mountChat=Ge;exports.panelStyles=F;exports.resolveAppearance=y;//# sourceMappingURL=chat.cjs.map
65
68
  //# sourceMappingURL=chat.cjs.map
package/dist/chat.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { C as ChatClient, M as MessengerConfig, A as AppearanceSettings, a as ChatTurn, b as ChatIdentity, c as ChatClientOptions } from './config-OP9Csae6.cjs';
2
- export { B as BubbleStyle, d as ChatStorage, e as ChatThread, D as DEFAULT_APPEARANCE_SETTINGS, L as LauncherStyle, f as MessengerSkin, N as NamePlacement, T as TimestampStyle, r as resolveAppearance } from './config-OP9Csae6.cjs';
3
- import { S as SocketFactory } from './types-68Sc11g8.cjs';
1
+ import { C as ChatClient, M as MessengerConfig, A as AppearanceSettings, a as ChatTurn, b as ChatIdentity, c as ChatClientOptions } from './config-CWmtX8Gl.cjs';
2
+ export { B as BubbleStyle, d as ChatStorage, e as ChatThread, D as DEFAULT_APPEARANCE_SETTINGS, L as LauncherContent, f as LauncherFill, g as LauncherShape, h as LauncherSize, i as MessengerSkin, N as NamePlacement, S as StampContent, j as StampPlacement, r as resolveAppearance } from './config-CWmtX8Gl.cjs';
3
+ import { S as SocketFactory } from './types-DjMXp6Wg.cjs';
4
4
  import './http-BCh716Vs.cjs';
5
5
 
6
6
  interface ChatStrings {
@@ -16,7 +16,7 @@ interface ChatStrings {
16
16
  emptyTitle: string;
17
17
  emptyBody: string;
18
18
  }
19
- type MessengerAppearance = Pick<MessengerConfig, 'accentColor' | 'greeting' | 'launcherOffsetX' | 'launcherOffsetY' | 'launcherPosition' | 'starterPrompts'> & AppearanceSettings;
19
+ type MessengerAppearance = Pick<MessengerConfig, 'accentColor' | 'availability' | 'awayMessage' | 'greeting' | 'launcherOffsetX' | 'launcherOffsetY' | 'launcherPosition' | 'starterPrompts' | 'teamFaces'> & AppearanceSettings;
20
20
  declare const DEFAULT_APPEARANCE: MessengerAppearance;
21
21
  declare function panelStyles(appearance: MessengerAppearance): string;
22
22
  declare class ChatPanel {
@@ -35,6 +35,7 @@ declare class ChatPanel {
35
35
  private toggle;
36
36
  open(): Promise<void>;
37
37
  private renderFirstRun;
38
+ private renderAway;
38
39
  close(): void;
39
40
  onIncomingTurn(turn: ChatTurn): void;
40
41
  private submit;
package/dist/chat.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { C as ChatClient, M as MessengerConfig, A as AppearanceSettings, a as ChatTurn, b as ChatIdentity, c as ChatClientOptions } from './config-B-cTz9n1.js';
2
- export { B as BubbleStyle, d as ChatStorage, e as ChatThread, D as DEFAULT_APPEARANCE_SETTINGS, L as LauncherStyle, f as MessengerSkin, N as NamePlacement, T as TimestampStyle, r as resolveAppearance } from './config-B-cTz9n1.js';
3
- import { S as SocketFactory } from './types-68Sc11g8.js';
1
+ import { C as ChatClient, M as MessengerConfig, A as AppearanceSettings, a as ChatTurn, b as ChatIdentity, c as ChatClientOptions } from './config-DDlHv52p.js';
2
+ export { B as BubbleStyle, d as ChatStorage, e as ChatThread, D as DEFAULT_APPEARANCE_SETTINGS, L as LauncherContent, f as LauncherFill, g as LauncherShape, h as LauncherSize, i as MessengerSkin, N as NamePlacement, S as StampContent, j as StampPlacement, r as resolveAppearance } from './config-DDlHv52p.js';
3
+ import { S as SocketFactory } from './types-DjMXp6Wg.js';
4
4
  import './http-BCh716Vs.js';
5
5
 
6
6
  interface ChatStrings {
@@ -16,7 +16,7 @@ interface ChatStrings {
16
16
  emptyTitle: string;
17
17
  emptyBody: string;
18
18
  }
19
- type MessengerAppearance = Pick<MessengerConfig, 'accentColor' | 'greeting' | 'launcherOffsetX' | 'launcherOffsetY' | 'launcherPosition' | 'starterPrompts'> & AppearanceSettings;
19
+ type MessengerAppearance = Pick<MessengerConfig, 'accentColor' | 'availability' | 'awayMessage' | 'greeting' | 'launcherOffsetX' | 'launcherOffsetY' | 'launcherPosition' | 'starterPrompts' | 'teamFaces'> & AppearanceSettings;
20
20
  declare const DEFAULT_APPEARANCE: MessengerAppearance;
21
21
  declare function panelStyles(appearance: MessengerAppearance): string;
22
22
  declare class ChatPanel {
@@ -35,6 +35,7 @@ declare class ChatPanel {
35
35
  private toggle;
36
36
  open(): Promise<void>;
37
37
  private renderFirstRun;
38
+ private renderAway;
38
39
  close(): void;
39
40
  onIncomingTurn(turn: ChatTurn): void;
40
41
  private submit;
package/dist/chat.js CHANGED
@@ -1,19 +1,21 @@
1
- import {c,a as a$2,b as b$1}from'./chunk-V77KYPOF.js';import {a as a$1,d}from'./chunk-VG77TYVX.js';import {a}from'./chunk-5XGN7UAV.js';var I="X-Prodantix-Conversation-Token",T="prodantix.chat.handle";function H(){let r=globalThis.localStorage;if(r)return {get:e=>r.getItem(e),remove:e=>r.removeItem(e),set:(e,t)=>r.setItem(e,t)}}var f=class{constructor(e){this.options=e;a(this,"fetchImpl");a(this,"host");a(this,"storage");a(this,"handle");a(this,"identity",null);this.fetchImpl=a$1(e.fetchImpl),this.host=d(e.host),this.storage=e.storage??H(),this.handle=this.readHandle();}get hasThread(){return this.handle!==null}get socketAuth(){return this.handle?{conversationId:this.handle.conversationId,conversationToken:this.handle.token,projectKey:this.options.apiKey}:null}identify(e){this.identity=e;}async ensureThread(e){if(this.handle)return true;let t=await this.request("POST","/v1/conversations",{body:{distinctId:this.options.distinctId,subject:e,userHash:this.identity?.userHash,userId:this.identity?.userId}});return !t?.conversationId||!t.token?false:(this.handle={conversationId:t.conversationId,token:t.token},this.storage?.set(T,JSON.stringify(this.handle)),true)}async send(e){if(!await this.ensureThread())return null;let t=this.handle;return t?(await this.request("POST",`/v1/conversations/${encodeURIComponent(t.conversationId)}/turns`,{body:{body:e},token:t.token}))?.turn??null:null}async load(){let e=this.handle;return e?this.request("GET",`/v1/conversations/${encodeURIComponent(e.conversationId)}`,{token:e.token}):null}readHandle(){let e=this.storage?.get(T);if(!e)return null;try{let t=JSON.parse(e);if(typeof t.conversationId=="string"&&typeof t.token=="string")return {conversationId:t.conversationId,token:t.token}}catch{}return this.storage?.remove(T),null}async request(e,t,n={}){let a=this.fetchImpl;if(!a)return this.options.onError?.(new Error("no fetch available for prodantix chat")),null;let o={authorization:`Bearer ${this.options.apiKey}`,"content-type":"application/json"};n.token&&(o[I]=n.token);try{let l=await a(`${this.host}${t}`,{body:n.body===void 0?void 0:JSON.stringify(n.body),headers:o,method:e}),i=await l.text();return l.ok?i?JSON.parse(i):{}:(this.options.onError?.(new Error(`prodantix chat ${t}: ${l.status}`)),null)}catch(l){return this.options.onError?.(l),null}}};var h={bubbleStyle:"tailed",launcherStyle:"circle_outlined",namePlacement:"avatar_only",skin:"concierge",timestampStyle:"cluster"},N=["concierge","console","quiet"],M=["avatar_circle","circle_filled","circle_outlined","pill_labelled","pill_team","squircle_filled"],$=["hairline","outlined","rounded","tailed"],F=["above","avatar_only","gutter","hidden","inline"],R=["cluster","latency","none","trailing","with_name"],b=(r,e,t)=>typeof r=="string"&&e.includes(r)?r:t;function y(r){let e={bubbleStyle:b(r?.bubbleStyle,$,h.bubbleStyle),launcherStyle:b(r?.launcherStyle,M,h.launcherStyle),namePlacement:b(r?.namePlacement,F,h.namePlacement),skin:b(r?.skin,N,h.skin),timestampStyle:b(r?.timestampStyle,R,h.timestampStyle)};return (e.namePlacement==="avatar_only"||e.namePlacement==="hidden")&&(e.timestampStyle==="with_name"||e.timestampStyle==="latency")&&(e.timestampStyle="trailing"),e.namePlacement==="inline"&&e.bubbleStyle==="hairline"&&(e.namePlacement="above"),e}var O={agentLabel:"Agent",aiLabel:"AI",closeLabel:"Close chat",emptyBody:"We usually reply within a few minutes.",emptyTitle:"Ask us anything.",inputPlaceholder:"Type a message",launcherLabel:"Open support chat",sendLabel:"Send",timeLabel:r=>{let e=new Date(r);return Number.isNaN(e.getTime())?"":`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`},title:"Support",unreadLabel:r=>`${r} unread`},v={accentColor:"#5b5bff",greeting:"",launcherOffsetX:20,launcherOffsetY:20,launcherPosition:"bottom_right",starterPrompts:[],...h},z={concierge:".panel{border-radius:16px;box-shadow:0 16px 40px rgba(0,0,0,.2)}.header{background:var(--a);color:#fff;flex-direction:column;align-items:flex-start;gap:14px;padding:18px 14px 20px 20px}.header h2{font-size:19px;font-weight:640}.composer{padding:12px 12px 14px;gap:8px}.composer input{border:0;background:var(--fill);height:46px;border-radius:23px;padding:0 16px}.composer button{width:46px;min-width:46px;height:46px;padding:0;border-radius:23px}.composer button .sendglyph{display:block}.composer button .sendtext{display:none}",console:".panel{border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.16)}.header{background:var(--paper);color:var(--ink);border-bottom:1px solid var(--hairline)}.close{color:var(--ink-2)}",quiet:".composer{position:relative;padding:10px 12px 12px}.composer input{height:42px;padding-right:42px}.composer button{position:absolute;top:50%;right:16px;width:34px;min-width:34px;height:34px;padding:0;background:transparent;color:var(--ink);border-radius:7px;transform:translateY(-50%)}.composer button .sendglyph{display:block;width:18px;height:18px}.composer button .sendtext{display:none}.panel{border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,.12)}.header{background:var(--paper);color:var(--ink);height:44px;padding:0 8px 0 16px;border-bottom:1px solid var(--hairline)}.header h2{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}.close{color:var(--ink-2)}"},K={avatar_circle:".launcher{width:60px;height:60px;border-radius:30px;background:var(--paper);border:1px solid var(--hairline);color:var(--ink-2)}",circle_filled:".launcher{width:56px;height:56px;border-radius:28px;background:var(--a);color:#fff}",circle_outlined:".launcher{width:46px;height:46px;border-radius:23px;background:var(--paper);border:1px solid var(--hairline);color:var(--ink-2);box-shadow:0 1px 2px rgba(0,0,0,.08);font-size:21px}.badge{background:var(--a);top:-7px;right:-7px;min-width:19px;height:19px;border-radius:10px;font-size:11.5px}",pill_labelled:".launcher{width:auto;height:52px;border-radius:26px;padding:0 22px;gap:10px;background:var(--a);color:#fff;font-size:14.5px;font-weight:600}",pill_team:".launcher{width:auto;height:54px;border-radius:27px;padding:0 20px 0 8px;gap:10px;background:var(--paper);border:1px solid var(--hairline);color:var(--ink);font-size:14px;font-weight:600}.badge{position:static;background:var(--a)}",squircle_filled:".launcher{width:56px;height:56px;border-radius:16px;background:var(--a);color:#fff}"},B={hairline:".turn{max-width:100%;padding:13px 0;border-top:1px solid var(--hairline);background:none;border-radius:0}.log>.turn:first-child{border-top:0}.turn.end_user{align-self:stretch;display:flex;flex-direction:column;align-items:flex-end}.turn.end_user .body{background:var(--fill);color:var(--ink);border-radius:8px;padding:9px 12px;max-width:85%}",outlined:".turn{background:none;border:1px solid var(--hairline);border-radius:12px}.turn.end_user{background:none;border-color:var(--a);color:var(--ink)}",rounded:".turn{border-radius:18px;padding:10px 15px}",tailed:".turn.agent,.turn.ai{border-radius:12px 12px 12px 4px}.turn.end_user{border-radius:12px 12px 4px 12px}"},D={above:"",avatar_only:".turn.agent,.turn.ai{display:flex;gap:10px;max-width:100%;background:none;padding:0}.turn .body{background:var(--fill);padding:9px 13px;border-radius:inherit}",gutter:".turn.agent,.turn.ai{display:flex;gap:10px;max-width:100%;background:none;padding:0}.turn .body{background:var(--fill);padding:9px 13px;border-radius:inherit}.author{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:600;opacity:1}",hidden:".turn.agent .author,.turn.ai .author:not(.ai){display:none}",inline:".author{display:inline;margin-right:6px;font-weight:650}"},q={cluster:'.divider{display:flex;align-items:center;gap:10px;margin:0;font-size:11px;opacity:.6}.divider:before,.divider:after{content:"";flex:1;height:1px;background:var(--hairline)}',latency:".stamp{font-size:11px;opacity:.7;margin-left:6px}.lat{font-size:11px;opacity:.7;margin-left:6px}",none:"",trailing:".stamp{display:block;font-size:11px;opacity:.7;margin-top:4px}.turn.end_user .stamp{text-align:right}",with_name:".stamp{font-size:11px;opacity:.7;margin-left:6px}"};function _(r){let e=y(r),t=r.launcherPosition==="bottom_left"?"left":"right",n=r.accentColor;return `${`
1
+ import {c,a as a$2,b as b$1}from'./chunk-V77KYPOF.js';import {a as a$1,d}from'./chunk-VG77TYVX.js';import {a}from'./chunk-5XGN7UAV.js';var z="X-Prodantix-Conversation-Token",C="prodantix.chat.handle";function $(){let a=globalThis.localStorage;if(a)return {get:e=>a.getItem(e),remove:e=>a.removeItem(e),set:(e,t)=>a.setItem(e,t)}}var b=class{constructor(e){this.options=e;a(this,"fetchImpl");a(this,"host");a(this,"storage");a(this,"handle");a(this,"identity",null);this.fetchImpl=a$1(e.fetchImpl),this.host=d(e.host),this.storage=e.storage??$(),this.handle=this.readHandle();}get hasThread(){return this.handle!==null}get socketAuth(){return this.handle?{conversationId:this.handle.conversationId,conversationToken:this.handle.token,projectKey:this.options.apiKey}:null}identify(e){this.identity=e;}async ensureThread(e){if(this.handle)return true;let t=await this.request("POST","/v1/conversations",{body:{distinctId:this.options.distinctId,subject:e,userHash:this.identity?.userHash,userId:this.identity?.userId}});return !t?.conversationId||!t.token?false:(this.handle={conversationId:t.conversationId,token:t.token},this.storage?.set(C,JSON.stringify(this.handle)),true)}async send(e,t){if(!await this.ensureThread())return null;let n=this.handle;return n?(await this.request("POST",`/v1/conversations/${encodeURIComponent(n.conversationId)}/turns`,{body:{body:e,pageContext:t},token:n.token}))?.turn??null:null}async load(){let e=this.handle;return e?this.request("GET",`/v1/conversations/${encodeURIComponent(e.conversationId)}`,{token:e.token}):null}readHandle(){let e=this.storage?.get(C);if(!e)return null;try{let t=JSON.parse(e);if(typeof t.conversationId=="string"&&typeof t.token=="string")return {conversationId:t.conversationId,token:t.token}}catch{}return this.storage?.remove(C),null}async request(e,t,n={}){let r=this.fetchImpl;if(!r)return this.options.onError?.(new Error("no fetch available for prodantix chat")),null;let s={authorization:`Bearer ${this.options.apiKey}`,"content-type":"application/json"};n.token&&(s[z]=n.token);try{let o=await r(`${this.host}${t}`,{body:n.body===void 0?void 0:JSON.stringify(n.body),headers:s,method:e}),i=await o.text();return o.ok?i?JSON.parse(i):{}:(this.options.onError?.(new Error(`prodantix chat ${t}: ${o.status}`)),null)}catch(o){return this.options.onError?.(o),null}}};var p={bubbleStyle:"tailed",dayDividers:true,launcherContent:"glyph",launcherFill:"outlined",launcherShape:"circle",launcherSize:"small",nameAvatar:true,namePlacement:"hidden",skin:"concierge",stampContent:"time",stampPlacement:"none"},O=["concierge","console","quiet"],D=["hairline","outlined","rounded","tailed"],U=["circle","pill","squircle"],B=["filled","outlined"],K=["avatar","glyph","team_faces"],q=["large","medium","small"],Y=["above","hidden","inline"],G=["beside_name","none","under_turn"],W=["time","time_and_latency"],m=(a,e,t)=>typeof a=="string"&&e.includes(a)?a:t,_=(a,e)=>typeof a=="boolean"?a:e,j={avatar_circle:["circle","outlined","avatar","large"],circle_filled:["circle","filled","glyph","medium"],circle_outlined:["circle","outlined","glyph","small"],pill_labelled:["pill","filled","glyph","medium"],pill_team:["pill","outlined","team_faces","medium"],squircle_filled:["squircle","filled","glyph","medium"]},X={above:["above",false],avatar_only:["hidden",true],gutter:["above",true],hidden:["hidden",false],inline:["inline",false]},Z={cluster:[true,"none","time"],latency:[false,"beside_name","time_and_latency"],none:[false,"none","time"],trailing:[false,"under_turn","time"],with_name:[false,"beside_name","time"]};function y(a){let e=typeof a=="object"&&a!==null?a:{},t=typeof e.launcherStyle=="string"?e.launcherStyle:void 0,n=t===void 0?void 0:j[t],r=typeof e.namePlacement=="string"?e.namePlacement:void 0,s=r===void 0?void 0:X[r],o=typeof e.timestampStyle=="string"?e.timestampStyle:void 0,i=o===void 0?void 0:Z[o],c={bubbleStyle:m(e.bubbleStyle,D,p.bubbleStyle),dayDividers:_(e.dayDividers,i?.[0]??p.dayDividers),launcherContent:m(e.launcherContent,K,n?.[2]??p.launcherContent),launcherFill:m(e.launcherFill,B,n?.[1]??p.launcherFill),launcherShape:m(e.launcherShape,U,n?.[0]??p.launcherShape),launcherSize:m(e.launcherSize,q,n?.[3]??p.launcherSize),nameAvatar:_(e.nameAvatar,s?.[1]??p.nameAvatar),namePlacement:m(e.namePlacement,Y,s?.[0]??p.namePlacement),skin:m(e.skin,O,p.skin),stampContent:m(e.stampContent,W,i?.[2]??p.stampContent),stampPlacement:m(e.stampPlacement,G,i?.[1]??p.stampPlacement)};return c.stampPlacement==="beside_name"&&c.namePlacement==="hidden"&&(c.stampPlacement="under_turn"),c.namePlacement==="inline"&&c.bubbleStyle==="hairline"&&(c.namePlacement="above"),c}var J={Fri:"fri",Mon:"mon",Sat:"sat",Sun:"sun",Thu:"thu",Tue:"tue",Wed:"wed"};function N(a,e){let t=new Intl.DateTimeFormat(void 0,{hour:"2-digit",hour12:false,minute:"2-digit",timeZone:a.timezone,weekday:"short"}).formatToParts(e),n=J[t.find(i=>i.type==="weekday")?.value??""];if(!n)return false;let r=t.find(i=>i.type==="hour")?.value??"",s=t.find(i=>i.type==="minute")?.value??"",o=`${r}:${s}`;return a.windows.some(i=>i.days.includes(n)&&i.open<=o&&o<i.close)}var V="M20 11.6a7.4 7.4 0 0 1-7.4 7.4H8.2L4 21.8l1-4.1A7.4 7.4 0 1 1 20 11.6Z",Q={large:66,medium:56,small:46},ee={circle:"width:var(--fab-size);height:var(--fab-size);border-radius:calc(var(--fab-size) / 2);",pill:"width:auto;height:var(--fab-size);border-radius:calc(var(--fab-size) / 2);padding:0 22px;gap:10px;",squircle:"width:var(--fab-size);height:var(--fab-size);border-radius:16px;"},te={filled:"background:var(--a);color:#fff;",outlined:"background:var(--paper);border:1px solid var(--hairline);color:var(--ink-2);box-shadow:0 1px 2px rgba(0,0,0,.08);"},ne={avatar:".launcher .live{width:10px;height:10px;position:absolute;right:3px;bottom:3px;border-radius:50%;background:var(--online);box-shadow:0 0 0 2px var(--paper);}",glyph:".launcher svg{width:calc(var(--fab-size) * 0.375);height:calc(var(--fab-size) * 0.375);}",team_faces:".launcher .faces{display:flex;}.launcher .faces .av{box-shadow:0 0 0 2px var(--paper);}.launcher .faces .av+.av{margin-left:-10px;}.launcher .live{width:9px;height:9px;position:absolute;right:3px;bottom:3px;border-radius:50%;background:var(--online);box-shadow:0 0 0 2px var(--paper);}"},ae={circle:"",pill:".badge{position:static;box-shadow:none}",squircle:""},re={filled:"",outlined:".badge{background:var(--a);top:-7px;right:-7px;min-width:19px;height:19px;font-size:11.5px}"},ie={circle:"",pill:".launcher .label{font-size:14px;font-weight:600;white-space:nowrap;}",squircle:""},oe={circle:"",pill:"@media (max-width:480px){.launcher{width:var(--fab-size);padding:0}.launcher .label{display:none}}",squircle:""};function M(a,e,t,n){return `.launcher{--fab-size:${Q[n]}px;${ee[a]}${te[e]}}${ne[t]}${ae[a]}${re[e]}${ie[a]}${oe[a]}`}function F(a,e,t){let n=document.createDocumentFragment();if(a==="glyph"){let o=document.createElement("span");return o.innerHTML=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="${V}"/></svg>`,n.append(...o.childNodes),n}if(a==="avatar")return n.append(H(t[0],e),I()),n;let r=document.createElement("span");r.className="faces";let s=t.length>0?t.slice(0,2):[void 0];for(let o of s)r.append(H(o,e));return n.append(r,I()),n}function H(a,e){let t=document.createElement("span");return t.className="av",t.setAttribute("aria-hidden","true"),t.textContent=a?a.initials:e.agentLabel.slice(0,2).toUpperCase(),a&&(t.style.background=a.tone),t}function I(){let a=document.createElement("span");return a.className="live",a.setAttribute("aria-hidden","true"),a}var se={agentLabel:"Agent",aiLabel:"AI",closeLabel:"Close chat",emptyBody:"We usually reply within a few minutes.",emptyTitle:"Ask us anything.",inputPlaceholder:"Type a message",launcherLabel:"Open support chat",sendLabel:"Send",timeLabel:a=>{let e=new Date(a);return Number.isNaN(e.getTime())?"":`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`},title:"Support",unreadLabel:a=>`${a} unread`},v={accentColor:"#5b5bff",availability:{timezone:"UTC",windows:[]},awayMessage:"",greeting:"",launcherOffsetX:20,launcherOffsetY:20,launcherPosition:"bottom_right",starterPrompts:[],teamFaces:[],...p},le={concierge:".panel{border-radius:16px;box-shadow:0 16px 40px rgba(0,0,0,.2)}.header{background:var(--a);color:#fff;flex-direction:column;align-items:flex-start;gap:14px;padding:18px 14px 20px 20px}.header h2{font-size:19px;font-weight:640}.composer{padding:12px 12px 14px;gap:8px}.composer input{border:0;background:var(--fill);height:46px;border-radius:23px;padding:0 16px}.composer button{width:46px;min-width:46px;height:46px;padding:0;border-radius:23px}.composer button .sendglyph{display:block}.composer button .sendtext{display:none}",console:".panel{border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.16)}.header{background:var(--paper);color:var(--ink);border-bottom:1px solid var(--hairline)}.close{color:var(--ink-2)}",quiet:".composer{position:relative;padding:10px 12px 12px}.composer input{height:42px;padding-right:42px}.composer button{position:absolute;top:50%;right:16px;width:34px;min-width:34px;height:34px;padding:0;background:transparent;color:var(--ink);border-radius:7px;transform:translateY(-50%)}.composer button .sendglyph{display:block;width:18px;height:18px}.composer button .sendtext{display:none}.panel{border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,.12)}.header{background:var(--paper);color:var(--ink);height:44px;padding:0 8px 0 16px;border-bottom:1px solid var(--hairline)}.header h2{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}.close{color:var(--ink-2)}"},ce={hairline:".turn{max-width:100%;padding:13px 0;border-top:1px solid var(--hairline);background:none;border-radius:0}.log>.turn:first-child{border-top:0}.turn.end_user{align-self:stretch;display:flex;flex-direction:column;align-items:flex-end}.turn.end_user .body{background:var(--fill);color:var(--ink);border-radius:8px;padding:9px 12px;max-width:85%}",outlined:".turn{background:none;border:1px solid var(--hairline);border-radius:12px}.turn.end_user{background:none;border-color:var(--a);color:var(--ink)}",rounded:".turn{border-radius:18px;padding:10px 15px}",tailed:".turn.agent,.turn.ai{border-radius:12px 12px 12px 4px}.turn.end_user{border-radius:12px 12px 4px 12px}"},de={above:"",hidden:".turn.agent .author,.turn.ai .author:not(.ai){display:none}",inline:".author{display:inline;margin-right:6px;font-weight:650}"},pe=".turn.agent,.turn.ai{display:flex;gap:10px;max-width:100%;background:none;padding:0}.turn .body{background:var(--fill);padding:9px 13px;border-radius:inherit}.author{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:600;opacity:1}",ue='.divider{display:flex;align-items:center;gap:10px;margin:0;font-size:11px;opacity:.6}.divider:before,.divider:after{content:"";flex:1;height:1px;background:var(--hairline)}',he={beside_name:".stamp{font-size:11px;opacity:.7;margin-left:6px}",none:"",under_turn:".stamp{display:block;font-size:11px;opacity:.7;margin-top:4px}.turn.end_user .stamp{text-align:right}"},me=".lat{font-size:11px;opacity:.7;margin-left:6px}";function R(a){let e=y(a),t=a.launcherPosition==="bottom_left"?"left":"right",n=a.accentColor;return `${`
2
2
  :host {
3
3
  all: initial; --a: ${n};
4
4
  --paper: #fff; --ink: #0f172a; --ink-3: var(--ink-3);
5
5
  --fill: #f1f5f9; --hairline: #e2e8f0; --field: #cbd5e1; --ink-2: rgba(0,0,0,.72);
6
+ --online: oklch(53.8% 0.1274 163.23);
6
7
  color-scheme: light dark;
7
8
  }
8
9
  @media (prefers-color-scheme: dark) {
9
10
  :host {
10
11
  --paper: oklch(24.6% 0.015 257); --ink: #fff; --ink-3: rgba(255,255,255,.55);
11
12
  --fill: rgba(255,255,255,.06); --hairline: rgba(255,255,255,.13); --field: rgba(255,255,255,.22); --ink-2: rgba(255,255,255,.70);
13
+ --online: oklch(72% 0.13 163.23);
12
14
  }
13
15
  }
14
16
  * { box-sizing: border-box; font-family: system-ui, sans-serif; }
15
17
  .launcher {
16
- position: fixed; ${t}: ${r.launcherOffsetX}px; bottom: ${r.launcherOffsetY}px; width: 56px; height: 56px;
18
+ position: fixed; ${t}: ${a.launcherOffsetX}px; bottom: ${a.launcherOffsetY}px; width: 56px; height: 56px;
17
19
  border-radius: 28px; border: none; cursor: pointer;
18
20
  display: inline-flex; align-items: center; justify-content: center;
19
21
  background: ${n}; color: #fff; font-size: 24px;
@@ -26,7 +28,7 @@ import {c,a as a$2,b as b$1}from'./chunk-V77KYPOF.js';import {a as a$1,d}from'./
26
28
  display: flex; align-items: center; justify-content: center; padding: 0 4px;
27
29
  }
28
30
  .panel {
29
- position: fixed; ${t}: ${r.launcherOffsetX}px; bottom: ${r.launcherOffsetY+68}px; width: 360px; max-width: calc(100vw - 40px);
31
+ position: fixed; ${t}: ${a.launcherOffsetX}px; bottom: ${a.launcherOffsetY+68}px; width: 360px; max-width: calc(100vw - 40px);
30
32
  height: 520px; max-height: calc(100vh - 120px); background: var(--paper); color: var(--ink);
31
33
  border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,.24);
32
34
  display: flex; flex-direction: column; overflow: hidden;
@@ -40,6 +42,7 @@ import {c,a as a$2,b as b$1}from'./chunk-V77KYPOF.js';import {a as a$1,d}from'./
40
42
  .turn.end_user { align-self: flex-end; background: ${n}; color: #fff; }
41
43
  .turn.agent, .turn.ai { align-self: flex-start; background: var(--fill); color: var(--ink); }
42
44
  .author { font-size: 11px; opacity: .7; margin-bottom: 2px; }
45
+ .away { background: var(--fill); border: 1px solid var(--hairline); border-radius: 8px; padding: 8px 12px; font-size: 13.5px; color: var(--ink-2); }
43
46
  .empty { display: flex; flex-direction: column; gap: 8px; padding: 20px 16px; }
44
47
  .empty h3 { margin: 0; font-size: 18px; font-weight: 640; letter-spacing: -.015em; }
45
48
  .empty p { margin: 0 0 8px; font-size: 13.5px; color: var(--ink-2); }
@@ -61,5 +64,5 @@ import {c,a as a$2,b as b$1}from'./chunk-V77KYPOF.js';import {a as a$1,d}from'./
61
64
  .panel { animation: rise 180ms ease-out; }
62
65
  @keyframes rise { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }
63
66
  }
64
- `}${z[e.skin]}${K[e.launcherStyle]}${B[e.bubbleStyle]}${D[e.namePlacement]}${q[e.timestampStyle]}`}var U=["end_user","agent","ai"],x=class{constructor(e,t,n={},a$1={}){this.host=e;this.client=t;a(this,"root");a(this,"strings");a(this,"settings");a(this,"appearance");a(this,"launcher");a(this,"badge");a(this,"panel",null);a(this,"lastFocused",null);a(this,"unread",0);this.strings={...O,...n},this.appearance={...v,...a$1},this.settings=y({...v,...a$1}),this.root=e.attachShadow({mode:"closed"});let o=document.createElement("style");o.textContent=_({...v,...a$1}),this.root.append(o),this.launcher=document.createElement("button"),this.launcher.className="launcher",this.launcher.type="button",this.launcher.setAttribute("aria-haspopup","dialog"),this.launcher.setAttribute("aria-label",this.strings.launcherLabel),this.launcher.textContent="\u{1F4AC}",this.launcher.addEventListener("click",()=>this.toggle()),this.badge=document.createElement("span"),this.badge.className="badge",this.badge.hidden=true,this.launcher.append(this.badge),this.root.append(this.launcher);}toggle(){this.panel?this.close():this.open();}async open(){if(this.panel)return;this.lastFocused=this.host.ownerDocument.activeElement,this.unread=0,this.renderBadge();let e=document.createElement("section");e.className="panel",e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true"),e.setAttribute("aria-label",this.strings.title);let t=document.createElement("div");t.className="header";let n=document.createElement("h2");n.textContent=this.strings.title;let a=document.createElement("button");a.className="close",a.type="button",a.setAttribute("aria-label",this.strings.closeLabel),a.textContent="\xD7",a.addEventListener("click",()=>this.close()),t.append(n,a);let o=document.createElement("div");o.className="log",o.setAttribute("role","log"),o.setAttribute("aria-live","polite"),o.setAttribute("aria-label",this.strings.title);let l=document.createElement("form");l.className="composer";let i=document.createElement("input");i.type="text",i.setAttribute("aria-label",this.strings.inputPlaceholder),i.placeholder=this.strings.inputPlaceholder;let p=document.createElement("button");p.type="submit",p.setAttribute("aria-label",this.strings.sendLabel),p.innerHTML='<svg class="sendglyph" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 12 20 4.5 15 20l-3.6-5.4L4.5 12Z"/></svg>';let u=document.createElement("span");u.className="sendtext",u.textContent=this.strings.sendLabel,p.append(u),l.append(i,p),l.addEventListener("submit",g=>{g.preventDefault(),this.submit(i,o);}),e.append(t,o,l),e.addEventListener("keydown",g=>this.onKeydown(g,e,a)),this.root.append(e),this.panel=e,i.focus();let d=await this.client.load();d&&d.turns.length>0?this.renderThread(o,d):this.renderFirstRun(o,i);}renderFirstRun(e,t){let n=document.createElement("div");n.className="empty";let a=document.createElement("h3");a.textContent=this.appearance.greeting.trim()||this.strings.emptyTitle;let o=document.createElement("p");o.textContent=this.strings.emptyBody,n.append(a,o);for(let l of this.appearance.starterPrompts){let i=document.createElement("button");i.className="prompt",i.type="button",i.textContent=l,i.addEventListener("click",()=>{t.value=l,this.submit(t,e);}),n.append(i);}e.replaceChildren(n);}close(){this.panel&&(this.panel.remove(),this.panel=null,this.lastFocused instanceof HTMLElement?this.lastFocused.focus():this.launcher.focus());}onIncomingTurn(e){if(this.panel){let t=this.panel.querySelector(".log");t instanceof HTMLElement&&this.appendTurn(t,e);return}e.authorKind!=="end_user"&&(this.unread+=1,this.renderBadge());}async submit(e,t){let n=e.value.trim();if(!n)return;e.value="",t.querySelector(".empty")?.remove();let a=await this.client.send(n);a&&this.appendTurn(t,a);}renderThread(e,t){e.replaceChildren();for(let n of t.turns)this.appendTurn(e,n);}appendTurn(e,t){e.querySelector(".empty")?.remove();let n=U.includes(t.authorKind)?t.authorKind:"agent",a=this.settings,o=document.createElement("div");if(o.className=`turn ${n}`,n!=="end_user"&&(a.namePlacement==="avatar_only"||a.namePlacement==="gutter")){let d=document.createElement("span");d.className=n==="ai"?"av bot":"av",d.textContent=n==="ai"?this.strings.aiLabel:this.strings.agentLabel.slice(0,2).toUpperCase(),d.setAttribute("aria-hidden","true"),o.append(d);}let i=document.createElement("div");if(i.className="body",n!=="end_user"&&a.namePlacement!=="hidden"&&!(a.namePlacement==="avatar_only"&&n==="agent")||n==="ai"&&a.namePlacement==="hidden"){let d=document.createElement("div");d.className=n==="ai"?"author ai":"author",d.textContent=n==="ai"?this.strings.aiLabel:this.strings.agentLabel,(a.timestampStyle==="with_name"||a.timestampStyle==="latency")&&d.append(this.stamp(t)),i.append(d);}let u=document.createElement("div");u.textContent=t.body,i.append(u),a.timestampStyle==="trailing"&&i.append(this.stamp(t)),o.append(i),e.append(o),e.scrollTop=e.scrollHeight;}stamp(e){let t=document.createElement("span");return t.className="stamp",t.textContent=this.strings.timeLabel(e.createdAt),t}onKeydown(e,t,n){if(e.key==="Escape"){e.preventDefault(),this.close();return}if(e.key!=="Tab")return;let a=t.querySelectorAll('button, input, [tabindex]:not([tabindex="-1"])');if(a.length===0)return;let o=a[0],l=a[a.length-1],i=this.root.activeElement;e.shiftKey&&i===o?(e.preventDefault(),l.focus()):!e.shiftKey&&i===l?(e.preventDefault(),o.focus()):i===null&&(e.preventDefault(),n.focus());}renderBadge(){this.unread>0?(this.badge.hidden=false,this.badge.textContent=String(this.unread),this.launcher.setAttribute("aria-label",`${this.strings.launcherLabel}, ${this.strings.unreadLabel(this.unread)}`)):(this.badge.hidden=true,this.badge.textContent="",this.launcher.setAttribute("aria-label",this.strings.launcherLabel));}};var j="/socket.io/?EIO=4&transport=websocket",k=class{constructor(e){this.options=e;a(this,"socket",null);a(this,"heartbeat",null);a(this,"ready",false);a(this,"closed",false);a(this,"heartbeatWindow",45e3);a(this,"factory");a(this,"setTimer");a(this,"clearTimer");this.factory=e.socketFactory??W,this.setTimer=e.setTimer??((t,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimer??(t=>clearTimeout(t));}open(){if(this.socket||this.closed)return;let e=`${this.options.host.replace(/^http/,"ws").replace(/\/+$/,"")}${j}`,t;try{t=this.factory(e);}catch{this.options.onClosed(false);return}this.socket=t,t.onmessage=n=>this.receive(String(n.data)),t.onerror=()=>t.close(),t.onclose=()=>this.fell();}close(){this.closed=true,this.stopHeartbeat();let e=this.socket;this.socket=null,e?.close();}receive(e){let t=c(e);if(t.kind==="open"){this.armHeartbeat(t.pingInterval+t.pingTimeout),this.socket?.send(a$2(this.options.auth));return}if(t.kind==="ping"){this.armHeartbeat(),this.socket?.send(b$1());return}if(t.kind==="connectError"||t.kind==="disconnect"){this.stopHeartbeat(),this.socket?.close();return}if(t.kind==="event"){if(t.name==="ready"){this.ready=true,this.options.onReady();return}if(t.name==="conversation.turn"){let n=t.payload?.turn;n&&this.options.onTurn(n);}}}fell(){this.stopHeartbeat();let e=this.ready;this.socket=null,this.ready=false,this.closed||this.options.onClosed(e);}armHeartbeat(e){e!==void 0&&(this.heartbeatWindow=e),this.stopHeartbeat(),this.heartbeat=this.setTimer(()=>this.socket?.close(),this.heartbeatWindow);}stopHeartbeat(){this.heartbeat!==null&&this.clearTimer(this.heartbeat),this.heartbeat=null;}};function W(r){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket");return new e(r)}function oe(r){let e=globalThis.document;if(!e)throw new Error("prodantix chat requires a document; mount it in the browser");let t=r.mountPoint??e.createElement("div");r.mountPoint||e.body.append(t);let n=new f(r),a=new x(t,n,r.strings,r.appearance),o=new Set,l,i=null,p=r.pollIntervalMs??15e3,u=c=>{o.has(c.id)||c.authorKind==="end_user"||(o.add(c.id),a.onIncomingTurn(c));},d=async()=>{if(!n.hasThread)return;let c=await n.load();if(c){for(let m of c.turns)u(m);o=new Set(c.turns.map(m=>m.id));}},g=()=>{l||p<=0||(l=setInterval(()=>void d(),p));},C=()=>{l&&clearInterval(l),l=void 0;},S=()=>{if(i||!r.socketHost)return;let c=n.socketAuth;c&&(i=new k({auth:c,host:r.socketHost,onClosed:m=>{i=null,g(),m&&S();},onReady:C,onTurn:u,socketFactory:r.socketFactory}),i.open());};return g(),S(),{close:()=>a.close(),destroy:()=>{C(),i?.close(),i=null,a.close(),t.remove();},identify:c=>n.identify(c),open:()=>{a.open().then(S);}}}export{f as ChatClient,x as ChatPanel,v as DEFAULT_APPEARANCE,h as DEFAULT_APPEARANCE_SETTINGS,oe as mountChat,_ as panelStyles,y as resolveAppearance};//# sourceMappingURL=chat.js.map
67
+ `}${le[e.skin]}${M(e.launcherShape,e.launcherFill,e.launcherContent,e.launcherSize)}${ce[e.bubbleStyle]}${de[e.namePlacement]}${e.nameAvatar?pe:""}${e.dayDividers?ue:""}${he[e.stampPlacement]}${e.stampContent==="time_and_latency"?me:""}`}var ge=["end_user","agent","ai"];function fe(){let a=globalThis.location;if(a)return {host:a.host,path:a.pathname,title:document.title}}var x=class{constructor(e,t,n={},r={}){this.host=e;this.client=t;a(this,"root");a(this,"strings");a(this,"settings");a(this,"appearance");a(this,"launcher");a(this,"badge");a(this,"panel",null);a(this,"lastFocused",null);a(this,"unread",0);this.strings={...se,...n},this.appearance={...v,...r},this.settings=y({...v,...r}),this.root=e.attachShadow({mode:"closed"});let s=document.createElement("style");if(s.textContent=R({...v,...r}),this.root.append(s),this.launcher=document.createElement("button"),this.launcher.className="launcher",this.launcher.type="button",this.launcher.setAttribute("aria-haspopup","dialog"),this.launcher.setAttribute("aria-label",this.strings.launcherLabel),this.launcher.append(F(this.settings.launcherContent,this.strings,this.appearance.teamFaces)),this.settings.launcherShape==="pill"){let o=document.createElement("span");o.className="label",o.textContent=this.settings.launcherContent==="team_faces"?this.strings.agentLabel:this.strings.launcherLabel,this.launcher.append(o);}this.launcher.addEventListener("click",()=>this.toggle()),this.badge=document.createElement("span"),this.badge.className="badge",this.badge.hidden=true,this.launcher.append(this.badge),this.root.append(this.launcher);}toggle(){this.panel?this.close():this.open();}async open(){if(this.panel)return;this.lastFocused=this.host.ownerDocument.activeElement,this.unread=0,this.renderBadge();let e=document.createElement("section");e.className="panel",e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true"),e.setAttribute("aria-label",this.strings.title);let t=document.createElement("div");t.className="header";let n=document.createElement("h2");n.textContent=this.strings.title;let r=document.createElement("button");r.className="close",r.type="button",r.setAttribute("aria-label",this.strings.closeLabel),r.textContent="\xD7",r.addEventListener("click",()=>this.close()),t.append(n,r);let s=document.createElement("div");s.className="log",s.setAttribute("role","log"),s.setAttribute("aria-live","polite"),s.setAttribute("aria-label",this.strings.title);let o=document.createElement("form");o.className="composer";let i=document.createElement("input");i.type="text",i.setAttribute("aria-label",this.strings.inputPlaceholder),i.placeholder=this.strings.inputPlaceholder;let c=document.createElement("button");c.type="submit",c.setAttribute("aria-label",this.strings.sendLabel),c.innerHTML='<svg class="sendglyph" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 12 20 4.5 15 20l-3.6-5.4L4.5 12Z"/></svg>';let h=document.createElement("span");h.className="sendtext",h.textContent=this.strings.sendLabel,c.append(h),o.append(i,c),o.addEventListener("submit",g=>{g.preventDefault(),this.submit(i,s);}),e.append(t,s,o),e.addEventListener("keydown",g=>this.onKeydown(g,e,r)),this.root.append(e),this.panel=e,i.focus();let d=await this.client.load();d&&d.turns.length>0?this.renderThread(s,d):this.renderFirstRun(s,i),!N(this.appearance.availability,new Date)&&this.appearance.awayMessage.trim()&&this.renderAway(s);}renderFirstRun(e,t){let n=document.createElement("div");n.className="empty";let r=document.createElement("h3");r.textContent=this.appearance.greeting.trim()||this.strings.emptyTitle;let s=document.createElement("p");s.textContent=this.strings.emptyBody,n.append(r,s);for(let o of this.appearance.starterPrompts){let i=document.createElement("button");i.className="prompt",i.type="button",i.textContent=o,i.addEventListener("click",()=>{t.value=o,this.submit(t,e);}),n.append(i);}e.replaceChildren(n);}renderAway(e){let t=document.createElement("div");t.className="away",t.textContent=this.appearance.awayMessage,e.prepend(t);}close(){this.panel&&(this.panel.remove(),this.panel=null,this.lastFocused instanceof HTMLElement?this.lastFocused.focus():this.launcher.focus());}onIncomingTurn(e){if(this.panel){let t=this.panel.querySelector(".log");t instanceof HTMLElement&&this.appendTurn(t,e);return}e.authorKind!=="end_user"&&(this.unread+=1,this.renderBadge());}async submit(e,t){let n=e.value.trim();if(!n)return;e.value="",t.querySelector(".empty")?.remove();let r=await this.client.send(n,fe());r&&this.appendTurn(t,r);}renderThread(e,t){e.replaceChildren();for(let n of t.turns)this.appendTurn(e,n);}appendTurn(e,t){e.querySelector(".empty")?.remove();let n=ge.includes(t.authorKind)?t.authorKind:"agent",r=this.settings,s=document.createElement("div");if(s.className=`turn ${n}`,n!=="end_user"&&r.nameAvatar){let d=document.createElement("span");d.className=n==="ai"?"av bot":"av",d.textContent=n==="ai"?this.strings.aiLabel:this.strings.agentLabel.slice(0,2).toUpperCase(),d.setAttribute("aria-hidden","true"),s.append(d);}let i=document.createElement("div");if(i.className="body",n!=="end_user"&&r.namePlacement!=="hidden"||n==="ai"&&r.namePlacement==="hidden"){let d=document.createElement("div");d.className=n==="ai"?"author ai":"author",d.textContent=n==="ai"?this.strings.aiLabel:this.strings.agentLabel,r.stampPlacement==="beside_name"&&d.append(this.stamp(t)),i.append(d);}let h=document.createElement("div");h.textContent=t.body,i.append(h),r.stampPlacement==="under_turn"&&i.append(this.stamp(t)),s.append(i),e.append(s),e.scrollTop=e.scrollHeight;}stamp(e){let t=document.createElement("span");return t.className="stamp",t.textContent=this.strings.timeLabel(e.createdAt),t}onKeydown(e,t,n){if(e.key==="Escape"){e.preventDefault(),this.close();return}if(e.key!=="Tab")return;let r=t.querySelectorAll('button, input, [tabindex]:not([tabindex="-1"])');if(r.length===0)return;let s=r[0],o=r[r.length-1],i=this.root.activeElement;e.shiftKey&&i===s?(e.preventDefault(),o.focus()):!e.shiftKey&&i===o?(e.preventDefault(),s.focus()):i===null&&(e.preventDefault(),n.focus());}renderBadge(){this.unread>0?(this.badge.hidden=false,this.badge.textContent=String(this.unread),this.launcher.setAttribute("aria-label",`${this.strings.launcherLabel}, ${this.strings.unreadLabel(this.unread)}`)):(this.badge.hidden=true,this.badge.textContent="",this.launcher.setAttribute("aria-label",this.strings.launcherLabel));}};var be="/socket.io/?EIO=4&transport=websocket",S=class{constructor(e){this.options=e;a(this,"socket",null);a(this,"heartbeat",null);a(this,"ready",false);a(this,"closed",false);a(this,"heartbeatWindow",45e3);a(this,"factory");a(this,"setTimer");a(this,"clearTimer");this.factory=e.socketFactory??xe,this.setTimer=e.setTimer??((t,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimer??(t=>clearTimeout(t));}open(){if(this.socket||this.closed)return;let e=`${this.options.host.replace(/^http/,"ws").replace(/\/+$/,"")}${be}`,t;try{t=this.factory(e);}catch{this.options.onClosed(false);return}this.socket=t,t.onmessage=n=>this.receive(String(n.data)),t.onerror=()=>t.close(),t.onclose=()=>this.fell();}close(){this.closed=true,this.stopHeartbeat();let e=this.socket;this.socket=null,e?.close();}receive(e){let t=c(e);if(t.kind==="open"){this.armHeartbeat(t.pingInterval+t.pingTimeout),this.socket?.send(a$2(this.options.auth));return}if(t.kind==="ping"){this.armHeartbeat(),this.socket?.send(b$1());return}if(t.kind==="connectError"||t.kind==="disconnect"){this.stopHeartbeat(),this.socket?.close();return}if(t.kind==="event"){if(t.name==="ready"){this.ready=true,this.options.onReady();return}if(t.name==="conversation.turn"){let n=t.payload?.turn;n&&this.options.onTurn(n);}}}fell(){this.stopHeartbeat();let e=this.ready;this.socket=null,this.ready=false,this.closed||this.options.onClosed(e);}armHeartbeat(e){e!==void 0&&(this.heartbeatWindow=e),this.stopHeartbeat(),this.heartbeat=this.setTimer(()=>this.socket?.close(),this.heartbeatWindow);}stopHeartbeat(){this.heartbeat!==null&&this.clearTimer(this.heartbeat),this.heartbeat=null;}};function xe(a){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket");return new e(a)}function Re(a){let e=globalThis.document;if(!e)throw new Error("prodantix chat requires a document; mount it in the browser");let t=a.mountPoint??e.createElement("div");a.mountPoint||e.body.append(t);let n=new b(a),r=new x(t,n,a.strings,a.appearance),s=new Set,o,i=null,c=a.pollIntervalMs??15e3,h=u=>{s.has(u.id)||u.authorKind==="end_user"||(s.add(u.id),r.onIncomingTurn(u));},d=async()=>{if(!n.hasThread)return;let u=await n.load();if(u){for(let f of u.turns)h(f);s=new Set(u.turns.map(f=>f.id));}},g=()=>{o||c<=0||(o=setInterval(()=>void d(),c));},A=()=>{o&&clearInterval(o),o=void 0;},k=()=>{if(i||!a.socketHost)return;let u=n.socketAuth;u&&(i=new S({auth:u,host:a.socketHost,onClosed:f=>{i=null,g(),f&&k();},onReady:A,onTurn:h,socketFactory:a.socketFactory}),i.open());};return g(),k(),{close:()=>r.close(),destroy:()=>{A(),i?.close(),i=null,r.close(),t.remove();},identify:u=>n.identify(u),open:()=>{r.open().then(k);}}}export{b as ChatClient,x as ChatPanel,v as DEFAULT_APPEARANCE,p as DEFAULT_APPEARANCE_SETTINGS,Re as mountChat,R as panelStyles,y as resolveAppearance};//# sourceMappingURL=chat.js.map
65
68
  //# sourceMappingURL=chat.js.map
@@ -0,0 +1,2 @@
1
+ import {c as c$2,a as a$2,b as b$2}from'./chunk-V77KYPOF.js';import {a as a$1,d,b as b$1,c as c$1}from'./chunk-VG77TYVX.js';import {a}from'./chunk-5XGN7UAV.js';var h=class extends Error{constructor(t,n,i){super(n,i);a(this,"code");this.code=t,this.name="ProdantixError";}},v=class extends h{constructor(e){super("config",e),this.name="ConfigError";}},m=class extends h{constructor(t,n){super("validation",n);a(this,"field");this.field=t,this.name="ValidationError";}},c=class extends h{constructor(t,n,i){super("transport",t,i);a(this,"status");this.status=n,this.name="TransportError";}};var y=class{constructor(){a(this,"store",new Map);}getItem(e){return this.store.get(e)??null}removeItem(e){this.store.delete(e);}setItem(e,t){this.store.set(e,t);}};function _e(){try{let s=globalThis.localStorage;if(s){let e="__pdx_probe__";return s.setItem(e,"1"),s.removeItem(e),s}}catch{return new y}return new y}var D={now:()=>new Date};function S(s){return s.toISOString()}var le=/^pdx_pub_(?:(?:live|test)_)?[a-z0-9]{32}$/;var de=/^(?:\$|[a-z])[a-z0-9_.]*$/;function V(s){let e=0;for(let t of s)e+=1;return e}function j(s){return le.test(s)}function ue(s){return de.test(s)}function U(s){let e=V(s);if(e<1||e>200)throw new m("distinct_id","distinct_id must be between 1 and 200 characters")}function H(s){let e=V(s);if(e<1||e>200)throw new m("event_name","event_name must be between 1 and 200 characters");if(!ue(s))throw new m("event_name","event_name must match /^(\\$|[a-z])[a-z0-9_.]*$/")}var J="prodantix-js",z="0.0.1";function he(){return globalThis.crypto}function pe(s){s[6]=s[6]&15|64,s[8]=s[8]&63|128;let e=[];for(let t=0;t<16;t+=1)e.push(s[t].toString(16).padStart(2,"0"));return `${e[0]}${e[1]}${e[2]}${e[3]}-${e[4]}${e[5]}-${e[6]}${e[7]}-${e[8]}${e[9]}-${e[10]}${e[11]}${e[12]}${e[13]}${e[14]}${e[15]}`}function fe(){let s=he();if(s?.randomUUID)return s.randomUUID();let e=new Uint8Array(16);if(s?.getRandomValues)s.getRandomValues(e);else for(let t=0;t<16;t+=1)e[t]=Math.floor(Math.random()*256);return pe(e)}var Q={uuid:fe};var ge=s=>{};function B(s){if(!s.apiKey||!j(s.apiKey))throw new v("apiKey must be a public project key of the form pdx_pub_<32 lowercase alphanumerics>");if(!s.host)throw new v("host is required (the ingest base URL)");let e=d(s.host),t=s.defaultProperties,n=s.storage??new y;return {apiKey:s.apiKey,autocapture:s.autocapture??false,clock:s.clock??D,consent:s.consent,defaultProperties:typeof t=="function"?t:()=>t??{},flagsHost:s.flagsHost?d(s.flagsHost):e,flushAt:s.flushAt??20,flushIntervalMs:s.flushIntervalMs??1e4,host:e,ids:s.ids??Q,locale:s.locale,maxQueueSize:s.maxQueueSize??1e3,maxRetries:s.maxRetries??3,namespace:me(s.apiKey),onError:s.onError??ge,os:s.os,requestTimeoutMs:s.requestTimeoutMs??1e4,sdkName:s.sdkName??J,sdkVersion:s.sdkVersion??z,sessionTracking:s.sessionTracking??false,sharedStorage:s.sharedStorage??n,socketFactory:s.socketFactory,storage:n,streamFlags:s.streamFlags??false,transport:s.transport}}function me(s){return s.slice(0,16)}var f=Symbol("absent");function ye(s,e){if(s==="distinct_id")return e.distinctId;let t=e.properties??{};if(Object.prototype.hasOwnProperty.call(t,s))return t[s];let n=e.attributes??{};return Object.prototype.hasOwnProperty.call(n,s)?n[s]:f}function p(s){return s===f?"undefined":String(s)}function G(s){return s===f?Number.NaN:Number(s)}function W(s){return s!==f&&s!==null&&s!==""}function X(s,e){if(!Array.isArray(e))return false;let t=p(s);return e.map(n=>String(n)).includes(t)}function Y(s,e){let t=ye(s.attribute,e),n=s.value;switch(s.op){case "is_set":return W(t);case "is_not_set":return !W(t);case "eq":return p(t)===p(n===void 0?f:n);case "neq":return p(t)!==p(n===void 0?f:n);case "contains":return p(t).includes(p(n===void 0?f:n));case "in":return X(t,n);case "not_in":return Array.isArray(n)?!X(t,n):false;case "gt":return I(t,n,(i,r)=>i>r);case "gte":return I(t,n,(i,r)=>i>=r);case "lt":return I(t,n,(i,r)=>i<r);case "lte":return I(t,n,(i,r)=>i<=r);case "in_cohort":return typeof n=="string"&&n!==""&&(e.cohorts??[]).includes(n);case "not_in_cohort":return typeof n=="string"&&n!==""&&!(e.cohorts??[]).includes(n);default:return false}}function I(s,e,t){let n=G(s),i=e===void 0?Number.NaN:G(e);return Number.isNaN(n)||Number.isNaN(i)?false:t(n,i)}function Z(s,e){let t=`${s}:${e}`,n=2166136261;for(let i=0;i<t.length;i++)n^=t.charCodeAt(i),n=Math.imul(n,16777619);return (n>>>0)%100}function R(s,e){return s.targeting.length===0||s.targeting.every(t=>Y(t,e))}function ee(s,e){let t=Z(s.key,e.distinctId),n=s.variations??[];if(n.length===0)return s.rolloutPercentage>=100||t<s.rolloutPercentage?"true":"false";let i=0;for(let r=n.length-1;r>=0;r--)if(i+=n[r].weight,t<i)return n[r].key;return n[0].key}function $(s,e,t,n){for(let i of s.prerequisites??[]){if(n.includes(i.flagKey))return false;let r=e.find(l=>l.key===i.flagKey);if(!r||!r.enabled)return false;n.push(r.key);let a=$(r,e,t,n)&&R(r,t)&&ee(r,t)===i.variationKey;if(n.pop(),!a)return false}return true}function b(s,e,t){return s.enabled?$(s,e,t,[s.key])?R(s,t)?s.rolloutPercentage>=100?{enabled:true,reason:"rollout_full"}:Z(s.key,t.distinctId)<s.rolloutPercentage?{enabled:true,reason:"rollout"}:{enabled:false,reason:"rollout_excluded"}:{enabled:false,reason:"targeting"}:{enabled:false,reason:"prerequisite"}:{enabled:false,reason:"disabled"}}function Qe(s,e){return b(s,[],e)}function te(s,e){let t={};for(let n of s)t[n.key]=b(n,s,e).enabled;return t}function k(s,e,t){let n=s.variations??[],i=n[0];if(!i)return null;if(!s.enabled||!$(s,e,t,[s.key])||!R(s,t))return i;let r=ee(s,t);return n.find(a=>a.key===r)??i}function Be(s,e){return k(s,[],e)}function Ge(s,e,t){let n=s.find(i=>i.key===e);return n?k(n,s,t)?.value??null:null}function se(s){return s.some(e=>e.targeting.some(t=>t.op==="in_cohort"||t.op==="not_in_cohort"))}var F=class{constructor(e){a(this,"fetch");a(this,"host");a(this,"projectKey");a(this,"requestTimeoutMs");this.fetch=a$1(e.fetch),this.host=d(e.host),this.projectKey=e.projectKey,this.requestTimeoutMs=e.requestTimeoutMs??1e4;}async fetchAll(e){return (await this.fetchDecisions(e)).flags}async fetchDecisions(e){let t=this.fetch;if(!t)throw new c("no fetch implementation available in this runtime");let n=`${this.host}/v1/flags?distinct_id=${encodeURIComponent(e)}`,i=b$1(),r=i?setTimeout(()=>i.abort(),this.requestTimeoutMs):void 0;try{let a=await t(n,{headers:{authorization:`Bearer ${this.projectKey}`},method:"GET",signal:i?.signal});if(!a.ok)throw new c(`flags request failed with status ${a.status}`,a.status);let l=JSON.parse(await a.text());return {flags:l.flags??{},variants:l.variants??{}}}finally{r!==void 0&&clearTimeout(r);}}async snapshot(){let e=this.fetch;if(!e)throw new c("no fetch implementation available in this runtime");let t=`${this.host}/v1/flags/snapshot`,n=b$1(),i=n?setTimeout(()=>n.abort(),this.requestTimeoutMs):void 0;try{let r=await e(t,{headers:{authorization:`Bearer ${this.projectKey}`},method:"GET",signal:n?.signal});if(!r.ok)throw new c(`flag snapshot request failed with status ${r.status}`,r.status);let a=JSON.parse(await r.text()),l={flags:a.flags??[],generatedAt:a.generatedAt};return typeof a.socketUrl=="string"&&a.socketUrl!==""&&(l.socketUrl=a.socketUrl),l}finally{i!==void 0&&clearTimeout(i);}}async memberships(e){let t=this.fetch;if(!t)throw new c("no fetch implementation available in this runtime");let n=`${this.host}/v1/flags/memberships?distinct_id=${encodeURIComponent(e)}`,i=b$1(),r=i?setTimeout(()=>i.abort(),this.requestTimeoutMs):void 0;try{let a=await t(n,{headers:{authorization:`Bearer ${this.projectKey}`},method:"GET",signal:i?.signal});if(!a.ok)throw new c(`memberships request failed with status ${a.status}`,a.status);return JSON.parse(await a.text()).cohorts??[]}finally{r!==void 0&&clearTimeout(r);}}};function x(s){if(typeof s!="string")return;let e=Array.from(s).length;return e>=1&&e<=200?s:void 0}function E(s,e){return `pdx.${s}.${e}`}var ne="consent";function ve(s){if(typeof s!="string")return null;try{let e=JSON.parse(s);if(e===null||typeof e!="object"||Array.isArray(e))return null;let t=e.identityLink;return typeof t=="boolean"?{identityLink:t}:null}catch{return null}}function be(s,e){return ve(s.getItem(E(e,ne)))}function ke(s,e,t){let n=E(e,ne);if(typeof t.identityLink!="boolean"){s.removeItem(n);return}s.setItem(n,JSON.stringify({identityLink:t.identityLink}));}function tt(s,e,t,n){let i=E(t,"anonymous_id"),r=x(e.getItem(i))??x(s.getItem(i));return e.setItem(i,n),s.setItem(i,n),r!==void 0&&r!==n?r:void 0}var w=class{constructor(e,t,n,i){this.storage=e;this.shared=t;this.ids=n;this.namespace=i;a(this,"anonymousId");a(this,"distinctId");a(this,"identified");this.refresh();}refresh(){let e=x(this.shared.getItem(this.key("anonymous_id"))),t=x(this.storage.getItem(this.key("anonymous_id")));e?(this.anonymousId=e,t!==e&&this.storage.setItem(this.key("anonymous_id"),e)):t?(this.anonymousId=t,this.shared.setItem(this.key("anonymous_id"),t)):(this.anonymousId=this.ids.uuid(),this.shared.setItem(this.key("anonymous_id"),this.anonymousId),this.storage.setItem(this.key("anonymous_id"),this.anonymousId));let n=x(this.storage.getItem(this.key("distinct_id")));n?(this.distinctId=n,this.identified=true):(this.distinctId=this.anonymousId,this.identified=false);}getAnonymousId(){return this.anonymousId}getDistinctId(){return this.distinctId}isIdentified(){return this.identified}snapshot(){return {anonymousId:this.anonymousId,distinctId:this.distinctId,identified:this.identified}}consent(){return be(this.shared,this.namespace)}setConsent(e){ke(this.shared,this.namespace,e);}identify(e){let t=!this.identified||this.distinctId!==e,n=this.storage.getItem(this.key("linked_anonymous_id")),i=t||n!==this.anonymousId;return this.distinctId=e,this.identified=true,t&&this.storage.setItem(this.key("distinct_id"),e),!i||this.consent()?.identityLink===false?{changed:t}:(this.storage.setItem(this.key("linked_anonymous_id"),this.anonymousId),{anonymousToLink:this.anonymousId,changed:t})}reset(){this.anonymousId=this.ids.uuid(),this.distinctId=this.anonymousId,this.identified=false,this.shared.setItem(this.key("anonymous_id"),this.anonymousId),this.storage.setItem(this.key("anonymous_id"),this.anonymousId),this.storage.removeItem(this.key("distinct_id")),this.storage.removeItem(this.key("linked_anonymous_id"));}key(e){return E(this.namespace,e)}};var C=class{constructor(e){a(this,"fetch");a(this,"host");a(this,"projectKey");a(this,"requestTimeoutMs");this.fetch=a$1(e.fetch),this.host=d(e.host),this.projectKey=e.projectKey,this.requestTimeoutMs=e.requestTimeoutMs??1e4;}async inbox(e){let t=this.requireFetch(),n=`${this.host}/v1/messages?distinct_id=${encodeURIComponent(e)}`,i=await this.request(t,n,{headers:this.authHeaders(),method:"GET"});if(!i.ok)throw new c(`inbox request failed with status ${i.status}`,i.status);return JSON.parse(await i.text()).messages??[]}async markRead(e,t){let n=this.requireFetch(),i=`${this.host}/v1/messages/read`,r=await this.request(n,i,{body:JSON.stringify({distinct_id:t,message_id:e}),headers:{...this.authHeaders(),"content-type":"application/json"},method:"POST"});if(!r.ok)throw new c(`mark-read request failed with status ${r.status}`,r.status)}requireFetch(){if(!this.fetch)throw new c("no fetch implementation available in this runtime");return this.fetch}authHeaders(){return {authorization:`Bearer ${this.projectKey}`}}async request(e,t,n){let i=b$1(),r=i?setTimeout(()=>i.abort(),this.requestTimeoutMs):void 0;try{return await e(t,{...n,signal:i?.signal})}finally{r!==void 0&&clearTimeout(r);}}};function ie(s){return s>=400&&s<500&&s!==429}var T=class{constructor(e={}){a(this,"fetch");a(this,"maxRetries");a(this,"requestTimeoutMs");a(this,"baseDelayMs");a(this,"maxDelayMs");a(this,"sleep");a(this,"random");this.fetch=a$1(e.fetch),this.maxRetries=e.maxRetries??3,this.requestTimeoutMs=e.requestTimeoutMs??1e4,this.baseDelayMs=e.baseDelayMs??500,this.maxDelayMs=e.maxDelayMs??3e4,this.sleep=e.sleep??c$1,this.random=e.random??Math.random;}async send(e){let t=this.fetch;if(!t)throw new c("no fetch implementation available in this runtime");let n=JSON.stringify(e.body),i;for(let r=0;r<=this.maxRetries;r+=1){try{let a=await this.attempt(t,e,n);if(a.ok)return;if(ie(a.status))throw new c(`ingest rejected batch with status ${a.status}`,a.status);i=new c(`ingest transient status ${a.status}`,a.status);}catch(a){if(a instanceof c&&a.status!==void 0&&ie(a.status))throw a;i=a;}r<this.maxRetries&&await this.sleep(this.backoff(r));}throw new c("ingest delivery failed after retries",void 0,{cause:i})}async attempt(e,t,n){let i=b$1(),r=i?setTimeout(()=>i.abort(),this.requestTimeoutMs):void 0;try{return await e(t.url,{body:n,headers:{authorization:`Bearer ${t.projectKey}`,"content-type":"application/json"},method:"POST",signal:i?.signal})}finally{r!==void 0&&clearTimeout(r);}}backoff(e){return Math.min(this.maxDelayMs,this.baseDelayMs*2**e)+this.random()*this.baseDelayMs}};function re(s,e,t){H(s.eventName),U(s.distinctId);let n={distinct_id:s.distinctId,event_id:s.eventId??t.uuid(),event_name:s.eventName,properties:s.properties??{},schema_version:1,timestamp:S(s.timestamp??e.now())};return s.context&&(n.context=s.context),s.sessionId&&(n.session_id=s.sessionId),n}var xe="/socket.io/?EIO=4&transport=websocket",Se=250,_=class{constructor(e){this.options=e;a(this,"socket",null);a(this,"heartbeat",null);a(this,"pending",null);a(this,"lastKey","");a(this,"ready",false);a(this,"closed",false);a(this,"heartbeatWindow",45e3);a(this,"factory");a(this,"setTimer");a(this,"clearTimer");this.factory=e.socketFactory??Ie,this.setTimer=e.setTimer??((t,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimer??(t=>clearTimeout(t));}open(){if(this.socket||this.closed)return;let e=`${this.options.host.replace(/^http/,"ws").replace(/\/+$/,"")}${xe}`,t;try{t=this.factory(e);}catch{this.options.onClosed(false);return}this.socket=t,t.onmessage=n=>this.receive(String(n.data)),t.onerror=()=>t.close(),t.onclose=()=>this.fell();}close(){this.closed=true,this.stopHeartbeat(),this.pending!==null&&this.clearTimer(this.pending),this.pending=null;let e=this.socket;this.socket=null,e?.close();}receive(e){let t=c$2(e);if(t.kind==="open"){this.armHeartbeat(t.pingInterval+t.pingTimeout),this.socket?.send(a$2({projectKey:this.options.projectKey}));return}if(t.kind==="ping"){this.armHeartbeat(),this.socket?.send(b$2());return}if(t.kind==="connectError"||t.kind==="disconnect"){this.stopHeartbeat(),this.socket?.close();return}if(t.kind==="event"){if(t.name==="ready"){this.ready=true;return}if(t.name==="flagChange"){let n=t.payload?.key;this.lastKey=typeof n=="string"?n:"",this.pending===null&&(this.pending=this.setTimer(()=>{this.pending=null,this.options.onChange(this.lastKey);},Se));}}}fell(){this.stopHeartbeat();let e=this.ready;this.socket=null,this.ready=false,this.closed||this.options.onClosed(e);}armHeartbeat(e){e!==void 0&&(this.heartbeatWindow=e),this.stopHeartbeat(),this.heartbeat=this.setTimer(()=>this.socket?.close(),this.heartbeatWindow);}stopHeartbeat(){this.heartbeat!==null&&this.clearTimer(this.heartbeat),this.heartbeat=null;}};function Ie(s){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket");return new e(s)}var A=class{constructor(e,t){this.maxSize=e;this.onOverflow=t;a(this,"events",[]);}get size(){return this.events.length}enqueue(e){this.events.push(e),this.enforceCap();}restore(e){this.events.push(...e),this.enforceCap();}requeue(e){this.events.unshift(...e),this.enforceCap();}drain(e){let t=e===void 0?this.events.length:Math.min(e,this.events.length);return this.events.splice(0,t)}snapshot(){return [...this.events]}enforceCap(){if(this.events.length<=this.maxSize)return;let e=this.events.splice(0,this.events.length-this.maxSize);this.onOverflow?.({dropped:e});}};var Fe={idleMs:18e5,maxMs:864e5,throttleMs:1e4};function oe(s){return `pdx.${s}.session`}function kt(s,e,t,n){let i={id:t.id,lastActivityAt:n,startedAt:t.startedAt};s.setItem(oe(e),JSON.stringify(i));}var P=class{constructor(e,t,n,i,r=Fe){this.storage=e;this.ids=t;this.clock=n;this.namespace=i;this.options=r;}current(){return this.touch().id}startedAt(){return this.touch().startedAt}reset(){this.storage.removeItem(this.key());}touch(){let e=this.clock.now().getTime(),t=this.live(this.read(),e);if(t===void 0)return this.write({id:this.ids.uuid(),lastActivityAt:e,startedAt:e});if(e-t.lastActivityAt<=this.options.throttleMs)return t;let n=this.live(this.read(),e),i=n!==void 0&&n.id!==t.id?n:t;return this.write({...i,lastActivityAt:e})}live(e,t){if(e!==void 0&&!(t-e.lastActivityAt>this.options.idleMs||t-e.startedAt>this.options.maxMs))return e}write(e){return this.storage.setItem(this.key(),JSON.stringify(e)),e}read(){let e=this.storage.getItem(this.key());if(e)try{let t=JSON.parse(e);return typeof t.id=="string"&&typeof t.startedAt=="number"&&typeof t.lastActivityAt=="number"?{id:t.id,lastActivityAt:t.lastActivityAt,startedAt:t.startedAt}:void 0}catch{return}}key(){return oe(this.namespace)}};var we="queue",Ee=1e3,ae=3e4,M=s=>{let e={};return s.avatar!==void 0&&(e.$avatar=s.avatar),s.email!==void 0&&(e.$email=s.email),s.name!==void 0&&(e.$name=s.name),s.phone!==void 0&&(e.$phone=s.phone),e},q=class{constructor(e){a(this,"config");a(this,"identity");a(this,"session");a(this,"queue");a(this,"transport");a(this,"flagsClient");a(this,"messagesClient");a(this,"context");a(this,"flushTimer");a(this,"flushing",false);a(this,"cachedFlags");a(this,"cachedSnapshot");a(this,"membershipCache");a(this,"stream");a(this,"shutDown",false);a(this,"exposures",new Set);this.config=B(e),this.identity=new w(this.config.storage,this.config.sharedStorage,this.config.ids,this.config.namespace),this.config.consent!==void 0&&this.identity.setConsent(this.config.consent),this.session=this.config.sessionTracking?new P(this.config.sharedStorage,this.config.ids,this.config.clock,this.config.namespace):void 0,this.queue=new A(this.config.maxQueueSize,({dropped:t})=>{this.config.onError(new h("queue_overflow",`event queue overflow: dropped ${t.length} oldest event(s)`));}),this.transport=this.config.transport??new T({maxRetries:this.config.maxRetries,requestTimeoutMs:this.config.requestTimeoutMs}),this.flagsClient=new F({host:this.config.flagsHost,projectKey:this.config.apiKey,requestTimeoutMs:this.config.requestTimeoutMs}),this.messagesClient=new C({host:this.config.flagsHost,projectKey:this.config.apiKey,requestTimeoutMs:this.config.requestTimeoutMs}),this.context={sdk:this.config.sdkName,sdk_version:this.config.sdkVersion},this.config.os&&(this.context.os=this.config.os),this.config.locale&&(this.context.locale=this.config.locale),this.restoreQueue(),this.startTimer();}get distinctId(){return this.identity.getDistinctId()}get anonymousId(){return this.identity.getAnonymousId()}get isIdentified(){return this.identity.isIdentified()}get sessionId(){return this.session?.current()}get sessionStartedAt(){return this.session?.startedAt()}capture(e,t={}){try{this.identity.refresh();let n={...this.config.defaultProperties(),...t.properties??{}},i=re({context:this.context,distinctId:t.distinctId??this.identity.getDistinctId(),eventName:e,properties:n,sessionId:t.sessionId??this.session?.current(),timestamp:t.timestamp},this.config.clock,this.config.ids);this.enqueue(i);}catch(n){this.config.onError(n);}}identify(e,t={}){this.identity.refresh();let n=this.identity.identify(e),i={};n.anonymousToLink!==void 0&&(i.$anon_distinct_id=n.anonymousToLink);let r={...M(t.traits??{}),...t.set??{}};Object.keys(r).length>0&&(i.$set=r),this.capture("$identify",{properties:i});}link(e,t,n){let i={$anon_distinct_id:t},r=M(n??{});Object.keys(r).length>0&&(i.$set=r),this.capture("$identify",{distinctId:e,properties:i});}setConsent(e){this.identity.setConsent(e);}consent(){return this.identity.consent()}alias(e){this.capture("$create_alias",{properties:{alias:e}});}group(e,t,n){let i={$group_key:t,$group_type:e};n&&(i.$set=n),this.capture("$group",{properties:i});}setPersonProperties(e,t){let n={};e&&(n.$set=e),t&&(n.$set_once=t),this.capture("$set",{properties:n});}setPersonTraits(e){let t=M(e);Object.keys(t).length!==0&&this.capture("$set",{properties:{$set:t}});}async getAllFlags(){let e=this.identity.getDistinctId(),t=await this.flagsClient.fetchDecisions(e);return this.cachedFlags={distinctId:e,flags:t.flags,variants:t.variants??{}},t.flags}async isFeatureEnabled(e){let n=(await this.getAllFlags())[e]??false;return this.recordExposure(e,this.cachedFlags?.variants[e]?.key??String(n)),n}async getVariant(e){let t=await this.getAllFlags(),n=this.cachedFlags?.variants[e]??null;return this.recordExposure(e,n?.key??String(t[e]??false)),n}async getVariantLocal(e,t={}){let n=await this.flagSnapshot(),i=n.flags.find(ce=>ce.key===e),r=await this.localContext(t,n.flags),a=i?k(i,n.flags,r):null,l=i?b(i,n.flags,r).enabled:false;return this.recordExposure(e,a?.key??String(l)),a?{key:a.key,value:a.value}:null}recordExposure(e,t){let n=`${this.identity.getDistinctId()} ${e} ${t}`;this.exposures.has(n)||(this.exposures.add(n),this.capture("$feature_flag_called",{properties:{$feature_flag:e,$feature_flag_response:t}}));}getCachedFlag(e){if(!(!this.cachedFlags||this.cachedFlags.distinctId!==this.distinctId))return this.cachedFlags.flags[e]}async getLocalFlags(e={}){let t=await this.flagSnapshot();return te(t.flags,await this.localContext(e,t.flags))}async isFeatureEnabledLocal(e,t={}){let n=await this.flagSnapshot(),i=n.flags.find(l=>l.key===e),r=await this.localContext(t,n.flags),a=i?b(i,n.flags,r).enabled:false;return this.recordExposure(e,(i?k(i,n.flags,r)?.key:void 0)??String(a)),a}async localContext(e,t){let n=this.identity.getDistinctId(),i=e.cohorts;if(i===void 0&&se(t)){let r=this.config.clock.now().getTime();this.membershipCache&&this.membershipCache.distinctId===n&&r-this.membershipCache.fetchedAt<ae?i=this.membershipCache.cohorts:(i=await this.flagsClient.memberships(n),this.membershipCache={cohorts:i,distinctId:n,fetchedAt:r});}return {attributes:e.attributes,cohorts:i,distinctId:n,properties:e.properties}}async flagSnapshot(){let e=this.config.clock.now().getTime();if(this.cachedSnapshot&&e-this.cachedSnapshot.fetchedAt<ae)return this.cachedSnapshot.snapshot;let t=await this.flagsClient.snapshot();return this.cachedSnapshot={fetchedAt:e,snapshot:t},this.maybeStream(t),t}maybeStream(e){if(!this.config.streamFlags||this.shutDown||this.stream||!e.socketUrl)return;let t=new _({host:e.socketUrl,onChange:()=>{this.cachedSnapshot=void 0,this.flagSnapshot().catch(n=>this.config.onError(n));},onClosed:n=>{this.stream=void 0,n&&this.maybeStream(e);},projectKey:this.config.apiKey,socketFactory:this.config.socketFactory});this.stream=t,t.open();}async getInbox(){return this.messagesClient.inbox(this.identity.getDistinctId())}async markMessageRead(e){await this.messagesClient.markRead(e,this.identity.getDistinctId());}async flush(){if(this.flushing||this.queue.size===0)return;this.flushing=true;let e=this.queue.drain(Ee);try{await this.transport.send({body:{events:e,sent_at:S(this.config.clock.now())},projectKey:this.config.apiKey,url:`${this.config.host}/v1/events`}),this.persistQueue();}catch(t){this.queue.requeue(e),this.persistQueue(),this.config.onError(t);}finally{this.flushing=false;}}reset(){this.session?.reset(),this.identity.reset(),this.cachedFlags=void 0,this.cachedSnapshot=void 0,this.membershipCache=void 0;}async shutdown(){this.shutDown=true,this.stopTimer(),this.stream?.close(),this.stream=void 0,await this.flush();}enqueue(e){this.queue.enqueue(e),this.persistQueue(),this.queue.size>=this.config.flushAt&&this.flush();}persistQueue(){try{this.config.storage.setItem(this.persistKey(),JSON.stringify(this.queue.snapshot()));}catch(e){this.config.onError(e);}}restoreQueue(){try{let e=this.config.storage.getItem(this.persistKey());if(!e)return;let t=JSON.parse(e);Array.isArray(t)&&this.queue.restore(t);}catch(e){this.config.onError(e);}}startTimer(){if(this.config.flushIntervalMs<=0)return;let e=setInterval(()=>{this.flush();},this.config.flushIntervalMs),t=e;typeof t.unref=="function"&&t.unref(),this.flushTimer=e;}stopTimer(){this.flushTimer!==void 0&&(clearInterval(this.flushTimer),this.flushTimer=void 0);}persistKey(){return `pdx.${this.config.namespace}.${we}`}};function Mt(s){return new q(s)}export{h as a,v as b,m as c,c as d,y as e,_e as f,D as g,fe as h,V as i,J as j,z as k,me as l,Y as m,Z as n,Qe as o,te as p,Be as q,Ge as r,F as s,ve as t,tt as u,C as v,kt as w,T as x,q as y,Mt as z};//# sourceMappingURL=chunk-5CBVQAZ2.js.map
2
+ //# sourceMappingURL=chunk-5CBVQAZ2.js.map
@@ -1,4 +1,4 @@
1
- import { d as EventProperties, P as ProdantixConfig, e as FlagVariant, I as InboxMessage } from './types-68Sc11g8.cjs';
1
+ import { e as EventProperties, P as ProdantixConfig, b as Consent, f as FlagVariant, I as InboxMessage } from './types-DjMXp6Wg.cjs';
2
2
 
3
3
  interface LocalFlagContext {
4
4
  attributes?: EventProperties;
@@ -8,6 +8,10 @@ interface LocalFlagContext {
8
8
  properties?: EventProperties;
9
9
  }
10
10
  interface CaptureOptions {
11
+ /** Speak for someone other than this client's own identity. A server has no
12
+ * visitor of its own to lend an event, so an event it sends on a browser's
13
+ * behalf names the person directly. */
14
+ distinctId?: string;
11
15
  properties?: EventProperties;
12
16
  sessionId?: string;
13
17
  timestamp?: Date;
@@ -37,6 +41,7 @@ interface IdentifyOptions {
37
41
  declare class ProdantixClient {
38
42
  private readonly config;
39
43
  private readonly identity;
44
+ private readonly session?;
40
45
  private readonly queue;
41
46
  private readonly transport;
42
47
  private readonly flagsClient;
@@ -56,8 +61,32 @@ declare class ProdantixClient {
56
61
  constructor(config: ProdantixConfig);
57
62
  get distinctId(): string;
58
63
  get anonymousId(): string;
64
+ /** Whether this client still holds a person, from the persisted distinct id,
65
+ * so a fresh page load answers the same as the load that identified them.
66
+ * Public because a surface that has resolved to nobody must reset the client
67
+ * only when there is someone to reset: a sign-out is a hard navigation on a
68
+ * BFF surface, so no value-to-null transition ever renders. */
69
+ get isIdentified(): boolean;
70
+ get sessionId(): string | undefined;
71
+ get sessionStartedAt(): number | undefined;
59
72
  capture(eventName: string, options?: CaptureOptions): void;
60
73
  identify(distinctId: string, options?: IdentifyOptions): void;
74
+ /**
75
+ * Join a browser's anonymous trail to a person from a server. A sign-in that
76
+ * completes in a redirect renders no page, so the browser's own `identify`
77
+ * never runs there; this sends the one `$identify` it would have sent, for
78
+ * the ids given, and leaves this client's own identity as it was.
79
+ */
80
+ link(distinctId: string, anonymousId: string, traits?: PersonTraits): void;
81
+ /**
82
+ * Record the visitor's answer about the join. It rides the shared store, so
83
+ * every subdomain and the login's server read the same one, and it takes
84
+ * effect on the next identify and the next decorated click; nothing already
85
+ * joined is unjoined.
86
+ */
87
+ setConsent(consent: Consent): void;
88
+ /** The visitor's answer, or null when they have not been asked. */
89
+ consent(): Consent | null;
61
90
  alias(alias: string): void;
62
91
  group(groupType: string, groupKey: string, properties?: EventProperties): void;
63
92
  setPersonProperties(set?: EventProperties, setOnce?: EventProperties): void;
@@ -1,4 +1,4 @@
1
- import { d as EventProperties, P as ProdantixConfig, e as FlagVariant, I as InboxMessage } from './types-68Sc11g8.js';
1
+ import { e as EventProperties, P as ProdantixConfig, b as Consent, f as FlagVariant, I as InboxMessage } from './types-DjMXp6Wg.js';
2
2
 
3
3
  interface LocalFlagContext {
4
4
  attributes?: EventProperties;
@@ -8,6 +8,10 @@ interface LocalFlagContext {
8
8
  properties?: EventProperties;
9
9
  }
10
10
  interface CaptureOptions {
11
+ /** Speak for someone other than this client's own identity. A server has no
12
+ * visitor of its own to lend an event, so an event it sends on a browser's
13
+ * behalf names the person directly. */
14
+ distinctId?: string;
11
15
  properties?: EventProperties;
12
16
  sessionId?: string;
13
17
  timestamp?: Date;
@@ -37,6 +41,7 @@ interface IdentifyOptions {
37
41
  declare class ProdantixClient {
38
42
  private readonly config;
39
43
  private readonly identity;
44
+ private readonly session?;
40
45
  private readonly queue;
41
46
  private readonly transport;
42
47
  private readonly flagsClient;
@@ -56,8 +61,32 @@ declare class ProdantixClient {
56
61
  constructor(config: ProdantixConfig);
57
62
  get distinctId(): string;
58
63
  get anonymousId(): string;
64
+ /** Whether this client still holds a person, from the persisted distinct id,
65
+ * so a fresh page load answers the same as the load that identified them.
66
+ * Public because a surface that has resolved to nobody must reset the client
67
+ * only when there is someone to reset: a sign-out is a hard navigation on a
68
+ * BFF surface, so no value-to-null transition ever renders. */
69
+ get isIdentified(): boolean;
70
+ get sessionId(): string | undefined;
71
+ get sessionStartedAt(): number | undefined;
59
72
  capture(eventName: string, options?: CaptureOptions): void;
60
73
  identify(distinctId: string, options?: IdentifyOptions): void;
74
+ /**
75
+ * Join a browser's anonymous trail to a person from a server. A sign-in that
76
+ * completes in a redirect renders no page, so the browser's own `identify`
77
+ * never runs there; this sends the one `$identify` it would have sent, for
78
+ * the ids given, and leaves this client's own identity as it was.
79
+ */
80
+ link(distinctId: string, anonymousId: string, traits?: PersonTraits): void;
81
+ /**
82
+ * Record the visitor's answer about the join. It rides the shared store, so
83
+ * every subdomain and the login's server read the same one, and it takes
84
+ * effect on the next identify and the next decorated click; nothing already
85
+ * joined is unjoined.
86
+ */
87
+ setConsent(consent: Consent): void;
88
+ /** The visitor's answer, or null when they have not been asked. */
89
+ consent(): Consent | null;
61
90
  alias(alias: string): void;
62
91
  group(groupType: string, groupKey: string, properties?: EventProperties): void;
63
92
  setPersonProperties(set?: EventProperties, setOnce?: EventProperties): void;