useyuva 0.0.10 → 0.0.12

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
@@ -196,7 +196,8 @@ browser sends no preflight; events of one moment share a request, and the last o
196
196
  `sendBeacon`. A `403` from the server stops sending for the page.
197
197
 
198
198
  Nothing is put on the device and no cookie is read: the only storage access is reading
199
- `localStorage.yuva_optout`, written by `optOut()`. With `navigator.globalPrivacyControl`, Do Not
199
+ `localStorage.yuva_optout`, written by `optOut()`, unless the visitor consents to `persistent`
200
+ (below). With `navigator.globalPrivacyControl`, Do Not
200
201
  Track or `navigator.webdriver` nothing is sent at all.
201
202
 
202
203
  | Attribute | Option | |
@@ -229,9 +230,30 @@ like pageviews do. `<yuva-chat>` dispatches `yuva-open` (bubbling, composed) whe
229
230
  opens it; the embedded layout does not.
230
231
  Links to `#yuva-optout` and `#yuva-optin` opt the visitor out and back in.
231
232
 
233
+ ### Consent features
234
+
235
+ For a property whose consent features offer them, from `useyuva/analytics`, React and Nuxt, or with
236
+ the `/yuva-analytics-consent.js` script tag instead of `/yuva-analytics.js` (which leaves them out
237
+ to stay within 1.5 KB; `window.yuva` then has `identify` and `persistentId` too):
238
+
239
+ ```ts
240
+ analytics.consent({ analytics: true, persistent: true }); // from your consent tool, on every page load
241
+ analytics.identify(await fetchIdentityToken()); // after sign-in, a fresh token from your backend
242
+ analytics.persistentId(); // the id, for an erasure request (DELETE …/visitors/{persistentId})
243
+ ```
244
+
245
+ `persistent: true` keeps `{ id, createdAt }` (a random UUID) in `localStorage.yuva_pid` and sends the
246
+ id as `c.p` on every event, engagement included; a new id is made when none exists or it is 13 months
247
+ old, and none ever under GPC or Do Not Track. Without that call nothing is stored and no id is sent.
248
+ Pass `persistent: true` on every `consent` call while the visitor agrees to it:
249
+ `consent({ analytics: true })` or `persistent: false` with an id stored withdraws it, as below.
250
+ `identify(token)` needs the id; it sends the identity token once in a `yuva_consent` event and keeps
251
+ nothing. `consent(false)`, `consent` without `persistent: true` and `optOut()` send a `yuva_consent`
252
+ withdrawal for a stored id, also under GPC or Do Not Track, and delete the id.
253
+
232
254
  In React, render `<YuvaAnalytics server="…" publicKey="yuva_ak_…" outbound />` once (it renders nothing; the
233
255
  other options are props too) and call
234
- `useYuvaAnalytics()` anywhere for `pageview`, `track`, `notFound`, `consent`, `optOut` and `optIn`; calls before it has
256
+ `useYuvaAnalytics()` anywhere for `pageview`, `track`, `notFound`, `consent`, `identify`, `persistentId`, `optOut` and `optIn`; calls before it has
235
257
  loaded wait for it. The prop is `publicKey` because React keeps `key` for itself. In Nuxt, set `yuva.analytics` (below) and use `useYuvaAnalytics()`.
236
258
 
237
259
  ## Nuxt
@@ -1 +1 @@
1
- var OPT_OUT_KEY="yuva_optout",noop=()=>{};function createAnalytics(options){if(typeof window>"u"||!options.key)return{pageview:noop,track:noop,notFound:noop,consent:noop,optOut:noop,optIn:noop,destroy:noop};let nav=navigator,doc=document,storage=()=>{try{return localStorage}catch{}},url=`${options.server.replace(/\/$/,"")}/client/v1/analytics/${options.key}`,hash=options.hash,blocked=nav.globalPrivacyControl||nav.doNotTrack=="1"||nav.webdriver,off=blocked||storage()?.getItem("yuva_optout")=="1",consented=!options.consent,queue=[],view="",page="",referrer=doc.referrer,ms=0,since=0,depth=0,flush=(beacon)=>{let body=JSON.stringify(queue[1]?{e:queue}:queue[0]);if(queue[0]&&(queue=[],!(beacon&&nav.sendBeacon?.(url,body))))fetch(url,{method:"POST",body,keepalive:!0,credentials:"omit"}).then((res)=>void(res.status==403&&(off=blocked=!0)),noop)},send=(event)=>{if(off||!consented)return;if(hash)event.h=!0;if(options.consent)event.c={a:1};if(queue.push(event)<2)setTimeout(flush)},tick=()=>{let now=Date.now();if(since)ms+=now-since;since=doc.visibilityState=="visible"&&doc.hasFocus()?now:0},scroll=()=>{depth=Math.max(depth,Math.min(100,Math.round((scrollY+innerHeight)/doc.documentElement.scrollHeight*100))||0)},engagement=()=>{if(tick(),page&&ms>0)send({n:"engagement",u:page,ms:Math.min(ms,1800000),sd:depth});ms=0,depth=0,scroll()},key=()=>location.pathname+(hash?location.hash:""),pageview=(opts={})=>{if(off||!consented)return;engagement(),view=key(),page=opts.url||location.href,send({n:"pageview",u:page,r:opts.referrer??referrer,w:innerWidth}),referrer=void 0},track=(name,{props,revenue}={})=>send({n:name,u:page||location.href,p:props,$:revenue&&{a:revenue.amount,c:revenue.currency}}),auto=()=>!options.manual&&view!=key()&&pageview(),leave=()=>{engagement(),flush(!0)},optOut=()=>{off=!0,queue=[],storage()?.setItem("yuva_optout","1")},optIn=()=>{off=blocked,storage()?.removeItem("yuva_optout")},push=history.pushState,wrapped=function(...args){push.apply(this,args),auto()};history.pushState=wrapped;let on={popstate:auto,hashchange:auto,prerenderingchange:auto,scroll,focus:tick,blur:tick,pagehide:leave,visibilitychange:()=>doc.visibilityState=="hidden"?leave():tick(),click:(event)=>{let link=event.target.closest?.("a");if(!link)return;let href=link.getAttribute("href"),choice=href=="#yuva-optout"?optOut:href=="#yuva-optin"?optIn:0,name=options.files&&/\.(pdf|zip|dmg|exe|apk|csv|xlsx?|docx?|pptx?|mp[34])$/i.test(link.pathname)?"file_download":options.outbound&&link.host!=location.host&&"outbound_click";if(choice)event.preventDefault(),choice();else if(name&&/^https?:/.test(link.href))track(name,{props:{url:link.href}})}};if(options.chat)on["yuva-open"]=()=>track("chat_open");for(let t in on)addEventListener(t,on[t],!0);if(!doc.prerendering)auto();return{pageview,track,notFound:()=>track("not_found"),consent:(choice)=>{if(consented=choice===!0||!!choice.analytics,consented)auto();else queue=[]},optOut,optIn,destroy:()=>{if(leave(),off=!0,history.pushState==wrapped)history.pushState=push;for(let t in on)removeEventListener(t,on[t],!0)}}}export{OPT_OUT_KEY,createAnalytics};
1
+ var OPT_OUT_KEY="yuva_optout",PERSISTENT_KEY="yuva_pid",noop=()=>{},lite=typeof YUVA_ANALYTICS_LITE<"u",stored=()=>{try{let{id,createdAt}=JSON.parse(localStorage.getItem("yuva_pid"));if(Date.now()-createdAt<34000000000)return id}catch{}},keep=()=>{try{if(!stored())localStorage.setItem("yuva_pid",JSON.stringify({id:crypto.randomUUID(),createdAt:Date.now()}))}catch{}return stored()},withdrawal=(u)=>{let p=stored();try{localStorage.removeItem("yuva_pid")}catch{}return p?[{n:"yuva_consent",u,c:{a:0,p}}]:[]};function createAnalytics(options){if(typeof window>"u"||!options.key){let idle={pageview:noop,track:noop,notFound:noop,consent:noop,optOut:noop,optIn:noop,destroy:noop};return lite?idle:{...idle,identify:noop,persistentId:noop}}let nav=navigator,doc=document,storage=()=>{try{return localStorage}catch{}},url=`${options.server.replace(/\/$/,"")}/client/v1/analytics/${options.key}`,hash=options.hash,blocked=nav.globalPrivacyControl||nav.doNotTrack=="1"||nav.webdriver,off=blocked||storage()?.getItem("yuva_optout")=="1",consented=!options.consent,queue=[],view="",page="",referrer=doc.referrer,ms=0,since=0,depth=0,pid,flush=(beacon)=>{let body=JSON.stringify(queue[1]?{e:queue}:queue[0]);if(queue[0]&&(queue=[],!(beacon&&nav.sendBeacon?.(url,body))))fetch(url,{method:"POST",body,keepalive:!0,credentials:"omit"}).then((res)=>void(res.status==403&&(off=blocked=!0)),noop)},send=(event)=>{if(off||!consented)return;if(hash)event.h=!0;if(lite?options.consent:options.consent||pid)event.c=lite?{a:1}:{...event.c,a:1,p:pid};if(queue.push(event)<2)setTimeout(flush)},tick=()=>{let now=Date.now();if(since)ms+=now-since;since=doc.visibilityState=="visible"&&doc.hasFocus()?now:0},scroll=()=>{depth=Math.max(depth,Math.min(100,Math.round((scrollY+innerHeight)/doc.documentElement.scrollHeight*100))||0)},engagement=()=>{if(tick(),page&&ms>0)send({n:"engagement",u:page,ms:Math.min(ms,1800000),sd:depth});ms=0,depth=0,scroll()},key=()=>location.pathname+(hash?location.hash:""),pageview=(opts={})=>{if(off||!consented)return;engagement(),view=key(),page=opts.url||location.href,send({n:"pageview",u:page,r:opts.referrer??referrer,w:innerWidth}),referrer=void 0},track=(name,{props,revenue}={})=>send({n:name,u:page||location.href,p:props,$:revenue&&{a:revenue.amount,c:revenue.currency}}),auto=()=>!options.manual&&view!=key()&&pageview(),leave=()=>{engagement(),flush(!0)},optOut=()=>{if(off=!0,queue=lite?[]:withdrawal(page||location.href),!lite)pid=void 0,flush(!0);storage()?.setItem("yuva_optout","1")},optIn=()=>{off=blocked,storage()?.removeItem("yuva_optout")},push=history.pushState,wrapped=function(...args){push.apply(this,args),auto()};history.pushState=wrapped;let on={popstate:auto,hashchange:auto,prerenderingchange:auto,scroll,focus:tick,blur:tick,pagehide:leave,visibilitychange:()=>doc.visibilityState=="hidden"?leave():tick(),click:(event)=>{let link=event.target.closest?.("a");if(!link)return;let href=link.getAttribute("href"),choice=href=="#yuva-optout"?optOut:href=="#yuva-optin"?optIn:0,name=options.files&&/\.(pdf|zip|dmg|exe|apk|csv|xlsx?|docx?|pptx?|mp[34])$/i.test(link.pathname)?"file_download":options.outbound&&link.host!=location.host&&"outbound_click";if(choice)event.preventDefault(),choice();else if(name&&/^https?:/.test(link.href))track(name,{props:{url:link.href}})}};if(options.chat)on["yuva-open"]=()=>track("chat_open");for(let t in on)addEventListener(t,on[t],!0);if(!doc.prerendering)auto();let api={pageview,track,notFound:()=>track("not_found"),consent:(choice)=>{if(consented=choice===!0||!!choice.analytics,!lite){if(pid=void 0,consented&&choice.persistent&&!off)pid=keep()}if(consented)auto();else queue=[];if(!lite&&!pid){let[withdrawn]=withdrawal(page||location.href);if(withdrawn)queue.push(withdrawn),flush(!0)}},optOut,optIn,destroy:()=>{if(leave(),off=!0,history.pushState==wrapped)history.pushState=push;for(let t in on)removeEventListener(t,on[t],!0)}};return lite?api:{...api,identify:(j)=>void(pid&&send({n:"yuva_consent",u:page||location.href,c:{j}})),persistentId:()=>pid}}export{OPT_OUT_KEY,PERSISTENT_KEY,createAnalytics};
package/dist/esm/chat.js CHANGED
@@ -106,4 +106,4 @@ import{resolveLocale,catalogFor,translatePlain}from"./index-c6q8br7d.js";import{
106
106
  block-size: 100%;
107
107
  min-block-size: 320px;
108
108
  }
109
- `,chatIcon='<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" aria-hidden="true"><path d="M4 5h16v11H9l-5 4z"/></svg>',closeIcon='<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>',scriptSrc=document.currentScript instanceof HTMLScriptElement?document.currentScript.src:"";class YuvaChatElement extends HTMLElement{static observedAttributes=["channel","server","layout","locale","dir","identity-token","open"];static loadPanel=()=>import(new URL("yuva-chat.js",scriptSrc||location.href).href);#root;#launcher=null;#badge=null;#panel;#controller=null;#messages={};#open=!1;#unread=0;#identity=null;#refused=!1;constructor(){super();this.#root=this.attachShadow({mode:"open"}),this.#panel=document.createElement("section"),this.#panel.className="panel",this.#panel.setAttribute("role","dialog"),this.#panel.hidden=!0,this.#panel.addEventListener("keydown",(event)=>{if(event.key==="Escape"&&this.layout==="launcher")this.close()})}get layout(){return this.getAttribute("layout")==="embedded"?"embedded":"launcher"}get channel(){return this.getAttribute("channel")}get server(){return(this.getAttribute("server")||(scriptSrc?new URL(scriptSrc).origin:location.origin)).replace(/\/+$/,"")}get locale(){return resolveLocale(this.getAttribute("locale"),navigator.language)}get isOpen(){return this.#open}get unread(){return this.#unread}setIdentityToken(source){if(this.#identity=source,this.#controller)this.#controller.then((controller)=>controller.identityChanged())}async signOut(){if(this.#identity=null,this.removeAttribute("identity-token"),this.#controller)await(await this.#controller).signOut()}async rate(conversationId,rating,comment){return(await this.#ensureController()).rate(conversationId,rating,comment)}connectedCallback(){this.#render();let channel=this.channel;if(this.layout==="embedded"||this.hasAttribute("open")||!channel)return;let stored=readStored(channel);if(stored.launcher)this.#applyLauncher(stored.launcher);let idle=()=>{if(!this.isConnected||this.#controller||this.channel!==channel)return;if(stored.session)this.#ensureController();else this.#styleLauncher(channel)};if("requestIdleCallback"in window)requestIdleCallback(idle,{timeout:3000});else setTimeout(idle,1000)}#styleLauncher(channel){fetch(`${this.server}/client/v1/channels/${encodeURIComponent(channel)}`,{credentials:"omit"}).then((response)=>{if(response.status===403||response.status===404)this.#refuse();return response.ok?response.json():null}).then((inbox)=>{if(!inbox||this.channel!==channel||this.#controller)return;let launcher=launcherOf(inbox);this.#applyLauncher(launcher),writeStored(channel,{...readStored(channel),launcher})}).catch(()=>{return})}disconnectedCallback(){let controller=this.#controller;if(this.#controller=null,controller)controller.then((c)=>c.destroy())}attributeChangedCallback(name,previous,value){if(!this.isConnected||previous===value)return;if(name==="open"){value===null?this.close():this.open();return}if(name==="identity-token"){if(this.#controller)this.#controller.then((controller)=>controller.identityChanged());return}if(name==="channel"||name==="server"){this.disconnectedCallback(),this.#refused=!1,this.#render();return}if(this.#render(),this.#controller)this.#controller.then((controller)=>controller.update())}async open(){if(this.#open||this.#refused)return;this.#open=!0,this.toggleAttribute("open-panel",!0),this.#syncLauncher();let controller=await this.#ensureController();if(!this.#open)return;if(this.#panel.hidden=!1,controller.opened(),this.layout!=="embedded")this.dispatchEvent(new Event("yuva-open",{bubbles:!0,composed:!0}))}close(){if(!this.#open||this.layout==="embedded")return;if(this.#open=!1,this.toggleAttribute("open-panel",!1),this.#panel.hidden=!0,this.#syncLauncher(),this.#launcher?.focus(),this.#controller)this.#controller.then((controller)=>controller.closed())}toggle(){return this.#open?this.close():this.open()}#config(){return{channel:this.channel,server:this.server,layout:this.layout,locale:this.locale}}#ensureController(){return this.#controller??=YuvaChatElement.loadPanel().then(({mount})=>mount({panel:this.#panel,config:()=>this.#config(),identityToken:async()=>this.#identity?await this.#identity()??null:this.getAttribute("identity-token"),isOpen:()=>this.#open,close:()=>this.close(),setUnread:(count)=>{this.#unread=count,this.#syncLauncher(),this.dispatchEvent(new CustomEvent("yuva-unread",{detail:{count}}))},setLauncher:(style)=>this.#applyLauncher(style),refused:()=>this.#refuse()})),this.#controller}#refuse(){if(this.#refused)return;this.#refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown or does not allow ${location.origin}`),this.#open=!1,this.toggleAttribute("open-panel",!1),this.disconnectedCallback(),this.#render()}#applyLauncher(style){if(this.setAttribute("position",style.position==="left"?"left":"right"),style.color&&/^#[0-9a-f]{6}$/i.test(style.color))this.style.setProperty("--yuva-accent",style.color),this.style.setProperty("--yuva-on-accent",contrastOn(style.color))}#render(){let locale=this.locale;this.#messages=catalogFor(locale),this.setAttribute("lang",locale);let style=document.createElement("style");if(style.textContent=styles,this.#panel.dir=this.getAttribute("dir")??directionOf(locale),this.#panel.setAttribute("aria-modal","false"),this.#refused){this.#launcher=null,this.#badge=null,this.#root.replaceChildren();return}if(this.layout==="embedded"){this.#launcher=null,this.#badge=null,this.#root.replaceChildren(style,this.#panel),this.#open=!1,this.open();return}let launcher=document.createElement("button");if(launcher.type="button",launcher.className="launcher",launcher.addEventListener("click",()=>void this.toggle()),this.#launcher=launcher,this.#badge=document.createElement("span"),this.#badge.className="badge",this.#badge.setAttribute("aria-hidden","true"),this.#root.replaceChildren(style,this.#panel,launcher),this.#syncLauncher(),this.hasAttribute("open")&&!this.#open)this.open()}#syncLauncher(){let launcher=this.#launcher,badge=this.#badge;if(!launcher||!badge)return;let count=this.#unread;launcher.setAttribute("aria-expanded",String(this.#open)),launcher.setAttribute("aria-label",this.#open?translatePlain(this.#messages,{id:"pqZJT2"}):count>0?translatePlain(this.#messages,{id:"OkHvGB",values:{count}}):translatePlain(this.#messages,{id:"6I7cJR"})),launcher.innerHTML=this.#open?closeIcon:chatIcon,badge.textContent=count>9?"9+":String(count),badge.hidden=this.#open||count===0,launcher.append(badge)}}function define(){if(!customElements.get("yuva-chat"))customElements.define("yuva-chat",YuvaChatElement)}YuvaChatElement.loadPanel=()=>import("./yuva-chat-nkt3xjhb.js");define();export{YuvaChatElement,define};
109
+ `,styleSheet=null;function adoptStyles(root){if(!("replaceSync"in CSSStyleSheet.prototype)){let style=document.createElement("style");return style.textContent=styles,style}return styleSheet??=new CSSStyleSheet,styleSheet.replaceSync(styles),root.adoptedStyleSheets=[styleSheet],null}var chatIcon='<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" aria-hidden="true"><path d="M4 5h16v11H9l-5 4z"/></svg>',closeIcon='<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>',scriptSrc=document.currentScript instanceof HTMLScriptElement?document.currentScript.src:"";class YuvaChatElement extends HTMLElement{static observedAttributes=["channel","server","layout","locale","dir","identity-token","open"];static loadPanel=()=>import(new URL("yuva-chat.js",scriptSrc||location.href).href);#root;#launcher=null;#badge=null;#panel;#controller=null;#messages={};#open=!1;#unread=0;#identity=null;#refused=!1;constructor(){super();this.#root=this.attachShadow({mode:"open"}),this.#panel=document.createElement("section"),this.#panel.className="panel",this.#panel.setAttribute("role","dialog"),this.#panel.hidden=!0,this.#panel.addEventListener("keydown",(event)=>{if(event.key==="Escape"&&this.layout==="launcher")this.close()})}get layout(){return this.getAttribute("layout")==="embedded"?"embedded":"launcher"}get channel(){return this.getAttribute("channel")}get server(){return(this.getAttribute("server")||(scriptSrc?new URL(scriptSrc).origin:location.origin)).replace(/\/+$/,"")}get locale(){return resolveLocale(this.getAttribute("locale"),navigator.language)}get isOpen(){return this.#open}get unread(){return this.#unread}setIdentityToken(source){if(this.#identity=source,this.#controller)this.#controller.then((controller)=>controller.identityChanged())}async signOut(){if(this.#identity=null,this.removeAttribute("identity-token"),this.#controller)await(await this.#controller).signOut()}async rate(conversationId,rating,comment){return(await this.#ensureController()).rate(conversationId,rating,comment)}connectedCallback(){this.#render();let channel=this.channel;if(this.layout==="embedded"||this.hasAttribute("open")||!channel)return;let stored=readStored(channel);if(stored.launcher)this.#applyLauncher(stored.launcher);let idle=()=>{if(!this.isConnected||this.#controller||this.channel!==channel)return;if(stored.session)this.#ensureController();else this.#styleLauncher(channel)};if("requestIdleCallback"in window)requestIdleCallback(idle,{timeout:3000});else setTimeout(idle,1000)}#styleLauncher(channel){fetch(`${this.server}/client/v1/channels/${encodeURIComponent(channel)}`,{credentials:"omit"}).then((response)=>{if(response.status===403||response.status===404)this.#refuse();return response.ok?response.json():null}).then((inbox)=>{if(!inbox||this.channel!==channel||this.#controller)return;let launcher=launcherOf(inbox);this.#applyLauncher(launcher),writeStored(channel,{...readStored(channel),launcher})}).catch(()=>{return})}disconnectedCallback(){let controller=this.#controller;if(this.#controller=null,controller)controller.then((c)=>c.destroy())}attributeChangedCallback(name,previous,value){if(!this.isConnected||previous===value)return;if(name==="open"){value===null?this.close():this.open();return}if(name==="identity-token"){if(this.#controller)this.#controller.then((controller)=>controller.identityChanged());return}if(name==="channel"||name==="server"){this.disconnectedCallback(),this.#refused=!1,this.#render();return}if(this.#render(),this.#controller)this.#controller.then((controller)=>controller.update())}async open(){if(this.#open||this.#refused)return;this.#open=!0,this.toggleAttribute("open-panel",!0),this.#syncLauncher();let controller=await this.#ensureController();if(!this.#open)return;if(this.#panel.hidden=!1,controller.opened(),this.layout!=="embedded")this.dispatchEvent(new Event("yuva-open",{bubbles:!0,composed:!0}))}close(){if(!this.#open||this.layout==="embedded")return;if(this.#open=!1,this.toggleAttribute("open-panel",!1),this.#panel.hidden=!0,this.#syncLauncher(),this.#launcher?.focus(),this.#controller)this.#controller.then((controller)=>controller.closed())}toggle(){return this.#open?this.close():this.open()}#config(){return{channel:this.channel,server:this.server,layout:this.layout,locale:this.locale}}#ensureController(){return this.#controller??=YuvaChatElement.loadPanel().then(({mount})=>mount({panel:this.#panel,config:()=>this.#config(),identityToken:async()=>this.#identity?await this.#identity()??null:this.getAttribute("identity-token"),isOpen:()=>this.#open,close:()=>this.close(),setUnread:(count)=>{this.#unread=count,this.#syncLauncher(),this.dispatchEvent(new CustomEvent("yuva-unread",{detail:{count}}))},setLauncher:(style)=>this.#applyLauncher(style),refused:()=>this.#refuse()})),this.#controller}#refuse(){if(this.#refused)return;this.#refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown or does not allow ${location.origin}`),this.#open=!1,this.toggleAttribute("open-panel",!1),this.disconnectedCallback(),this.#render()}#applyLauncher(style){if(this.setAttribute("position",style.position==="left"?"left":"right"),style.color&&/^#[0-9a-f]{6}$/i.test(style.color))this.style.setProperty("--yuva-accent",style.color),this.style.setProperty("--yuva-on-accent",contrastOn(style.color))}#render(){let locale=this.locale;this.#messages=catalogFor(locale),this.setAttribute("lang",locale);let fallbackStyle=adoptStyles(this.#root),head=fallbackStyle?[fallbackStyle]:[];if(this.#panel.dir=this.getAttribute("dir")??directionOf(locale),this.#panel.setAttribute("aria-modal","false"),this.#refused){this.#launcher=null,this.#badge=null,this.#root.replaceChildren();return}if(this.layout==="embedded"){this.#launcher=null,this.#badge=null,this.#root.replaceChildren(...head,this.#panel),this.#open=!1,this.open();return}let launcher=document.createElement("button");if(launcher.type="button",launcher.className="launcher",launcher.addEventListener("click",()=>void this.toggle()),this.#launcher=launcher,this.#badge=document.createElement("span"),this.#badge.className="badge",this.#badge.setAttribute("aria-hidden","true"),this.#root.replaceChildren(...head,this.#panel,launcher),this.#syncLauncher(),this.hasAttribute("open")&&!this.#open)this.open()}#syncLauncher(){let launcher=this.#launcher,badge=this.#badge;if(!launcher||!badge)return;let count=this.#unread;launcher.setAttribute("aria-expanded",String(this.#open)),launcher.setAttribute("aria-label",this.#open?translatePlain(this.#messages,{id:"pqZJT2"}):count>0?translatePlain(this.#messages,{id:"OkHvGB",values:{count}}):translatePlain(this.#messages,{id:"6I7cJR"})),launcher.innerHTML=this.#open?closeIcon:chatIcon,badge.textContent=count>9?"9+":String(count),badge.hidden=this.#open||count===0,launcher.append(badge)}}function define(){if(!customElements.get("yuva-chat"))customElements.define("yuva-chat",YuvaChatElement)}YuvaChatElement.loadPanel=()=>import("./yuva-chat-kf9vz8r3.js");define();export{YuvaChatElement,define};
@@ -1 +1 @@
1
- import{storageKey2,readerStorageKey2,randomId2,YuvaClient2,createYuvaClient2}from"./index-geeh5h34.js";export{YuvaClient2 as YuvaClient,createYuvaClient2 as createYuvaClient,randomId2 as randomId,readerStorageKey2 as readerStorageKey,storageKey2 as storageKey};
1
+ import{storageKey2,readerStorageKey2,randomId2,YuvaClient2,createYuvaClient2}from"./index-6brgxahe.js";export{YuvaClient2 as YuvaClient,createYuvaClient2 as createYuvaClient,randomId2 as randomId,readerStorageKey2 as readerStorageKey,storageKey2 as storageKey};
package/dist/esm/docs.js CHANGED
@@ -1,4 +1,4 @@
1
- import{createYuvaClient2}from"./index-geeh5h34.js";import{resolveLocale,translatePlain}from"./index-c6q8br7d.js";import{el}from"./index-rdzxvj2r.js";import{ApiError2}from"./index-gk84nm8f.js";import{directionOf,launcherOf,contrastOn,readStored,writeStored}from"./index-98r96a7e.js";var messages=JSON.parse(`{"-UxBoG":["Deleted member"],"1UzENP":["No"],"2lF8Zj":["Unanswered"],"5lWFkC":["Sign in"],"78dEKp":["Sort discussions"],"7oGBMv":["Discussions"],"8Ekoev":["You can't do that."],"8ntmc1":["Votes: ",["0"]],"D16wQE":["Could not open the discussion. Try again."],"D9CFV5":["Anonymous"],"E_qvzP":["Enter a valid e-mail address."],"EmiQvf":["Thanks! Anything we could add? (optional)"],"FMWGhb":["Deleted reader"],"G2fuEb":["Locked"],"GQVIIl":["You seem to be offline."],"GqCA_t":["Answered"],"Hw3P48":["Replies: ",["0"]],"JlFcis":["Send"],"KDw4GX":["Try again"],"KEjhwb":["This discussion is locked."],"KM6m8p":["Team"],"LwDe8g":["Sign in to take part in the discussion."],"MDmQKn":["Could not load the discussions."],"Pwqkdw":["Loading…"],"SOvBw9":["Was this page helpful?"],"Sad2tK":["Sending…"],"Su3Vyp":["Check the title and the text and try again."],"U7H5Fm":["Sorry about that. What was missing or unclear?"],"UbRKMZ":["Pending"],"WWy8TN":["Top"],"XJURKP":["E-mail address"],"a_qtPP":["E-mail for a reply (optional)"],"b6Orhy":["Have a question or an idea? Start the first one."],"b_f4xj":["Posts can be edited for 30 minutes after they are written."],"d6N994":["Thanks for your feedback."],"fMPkxb":["Show more"],"fcWrnU":["Sign out"],"isRobC":["New"],"j-3eim":["Discussions about this page"],"l75CjT":["Yes"],"lWv8id":["Awaiting approval"],"nLqMRA":["Team member"],"nW3go1":["Your browser blocked the sign-in window. Allow pop-ups for this site and try again."],"pzatAP":["Loading discussions…"],"rpfOwz":["No discussions about this page yet."],"tA4dAO":["No thanks"],"tAL5wg":["Could not send. Try again."],"tayT8P":["Discussions are turned off for this site."],"twEQ41":["Every discussion on this page has an answer."],"tzsBOP":["Too many attempts. Wait a moment and try again."],"uuIskV":["Sign in to write to us."],"xOTzt5":["just now"],"z1qf6l":["Start a discussion"],"zmA6sS":["Reader"]}`);var messages2=JSON.parse('{"-UxBoG":["Gelöschtes Mitglied"],"1UzENP":["Nein"],"2lF8Zj":["Unbeantwortet"],"5lWFkC":["Anmelden"],"78dEKp":["Diskussionen sortieren"],"7oGBMv":["Diskussionen"],"8Ekoev":["Das können Sie nicht tun."],"8ntmc1":["Stimmen: ",["0"]],"D16wQE":["Die Diskussion konnte nicht eröffnet werden. Versuchen Sie es erneut."],"D9CFV5":["Anonym"],"E_qvzP":["Geben Sie eine gültige E-Mail-Adresse ein."],"EmiQvf":["Danke! Können wir noch etwas ergänzen? (optional)"],"FMWGhb":["Gelöschter Leser"],"G2fuEb":["Gesperrt"],"GQVIIl":["Sie scheinen offline zu sein."],"GqCA_t":["Beantwortet"],"Hw3P48":["Antworten: ",["0"]],"JlFcis":["Senden"],"KDw4GX":["Erneut versuchen"],"KEjhwb":["Diese Diskussion ist gesperrt."],"KM6m8p":["Team"],"LwDe8g":["Melden Sie sich an, um an der Diskussion teilzunehmen."],"MDmQKn":["Die Diskussionen konnten nicht geladen werden."],"Pwqkdw":["Wird geladen…"],"SOvBw9":["War diese Seite hilfreich?"],"Sad2tK":["Wird gesendet…"],"Su3Vyp":["Prüfen Sie Titel und Text und versuchen Sie es erneut."],"U7H5Fm":["Das tut uns leid. Was hat gefehlt oder war unklar?"],"UbRKMZ":["Ausstehend"],"WWy8TN":["Beliebteste"],"XJURKP":["E-Mail-Adresse"],"a_qtPP":["E-Mail für eine Antwort (optional)"],"b6Orhy":["Haben Sie eine Frage oder eine Idee? Starten Sie die erste Diskussion."],"b_f4xj":["Beiträge können bis 30 Minuten nach dem Schreiben bearbeitet werden."],"d6N994":["Danke für Ihr Feedback."],"fMPkxb":["Mehr anzeigen"],"fcWrnU":["Abmelden"],"isRobC":["Neu"],"j-3eim":["Diskussionen zu dieser Seite"],"l75CjT":["Ja"],"lWv8id":["Wartet auf Freigabe"],"nLqMRA":["Teammitglied"],"nW3go1":["Ihr Browser hat das Anmeldefenster blockiert. Erlauben Sie Pop-ups für diese Website und versuchen Sie es erneut."],"pzatAP":["Diskussionen werden geladen…"],"rpfOwz":["Zu dieser Seite gibt es noch keine Diskussionen."],"tA4dAO":["Nein, danke"],"tAL5wg":["Senden fehlgeschlagen. Versuchen Sie es erneut."],"tayT8P":["Diskussionen sind für diese Website deaktiviert."],"twEQ41":["Jede Diskussion auf dieser Seite hat eine Antwort."],"tzsBOP":["Zu viele Versuche. Warten Sie einen Moment und versuchen Sie es erneut."],"uuIskV":["Melden Sie sich an, um uns zu schreiben."],"xOTzt5":["gerade eben"],"z1qf6l":["Diskussion starten"],"zmA6sS":["Leser"]}');var messages3=JSON.parse('{"-UxBoG":["Silinmiş üye"],"1UzENP":["Hayır"],"2lF8Zj":["Yanıtsız"],"5lWFkC":["Giriş yap"],"78dEKp":["Tartışmaları sırala"],"7oGBMv":["Tartışmalar"],"8Ekoev":["Bunu yapamazsınız."],"8ntmc1":["Oylar: ",["0"]],"D16wQE":["Tartışma açılamadı. Yeniden deneyin."],"D9CFV5":["Anonim"],"E_qvzP":["Geçerli bir e-posta adresi girin."],"EmiQvf":["Teşekkürler! Ekleyebileceğimiz bir şey var mı? (isteğe bağlı)"],"FMWGhb":["Silinmiş okuyucu"],"G2fuEb":["Kilitli"],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"GqCA_t":["Yanıtlandı"],"Hw3P48":["Yanıtlar: ",["0"]],"JlFcis":["Gönder"],"KDw4GX":["Yeniden dene"],"KEjhwb":["Bu tartışma kilitli."],"KM6m8p":["Ekip"],"LwDe8g":["Tartışmaya katılmak için giriş yapın."],"MDmQKn":["Tartışmalar yüklenemedi."],"Pwqkdw":["Yükleniyor…"],"SOvBw9":["Bu sayfa işinize yaradı mı?"],"Sad2tK":["Gönderiliyor…"],"Su3Vyp":["Başlığı ve metni kontrol edip yeniden deneyin."],"U7H5Fm":["Üzgünüz. Eksik ya da anlaşılmayan ne vardı?"],"UbRKMZ":["Bekliyor"],"WWy8TN":["En çok oy alan"],"XJURKP":["E-posta adresi"],"a_qtPP":["Yanıt için e-posta (isteğe bağlı)"],"b6Orhy":["Bir sorunuz ya da fikriniz mi var? İlk tartışmayı siz başlatın."],"b_f4xj":["Gönderiler yazıldıktan sonra 30 dakika içinde düzenlenebilir."],"d6N994":["Geri bildiriminiz için teşekkürler."],"fMPkxb":["Daha fazla göster"],"fcWrnU":["Çıkış yap"],"isRobC":["Yeni"],"j-3eim":["Bu sayfayla ilgili tartışmalar"],"l75CjT":["Evet"],"lWv8id":["Onay bekliyor"],"nLqMRA":["Ekip üyesi"],"nW3go1":["Tarayıcınız giriş penceresini engelledi. Bu site için açılır pencerelere izin verip yeniden deneyin."],"pzatAP":["Tartışmalar yükleniyor…"],"rpfOwz":["Bu sayfayla ilgili henüz bir tartışma yok."],"tA4dAO":["Hayır, teşekkürler"],"tAL5wg":["Gönderilemedi. Yeniden deneyin."],"tayT8P":["Bu sitede tartışmalar kapalı."],"twEQ41":["Bu sayfadaki her tartışmanın bir yanıtı var."],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"uuIskV":["Bize yazmak için oturum açın."],"xOTzt5":["az önce"],"z1qf6l":["Tartışma başlat"],"zmA6sS":["Okur"]}');var shared=Symbol.for("yuva.navigation");function navigation(){let win=window,target=win[shared];if(target)return target;let created=new EventTarget;target=win[shared]=created;let notify=()=>created.dispatchEvent(new Event("change"));for(let name of["pushState","replaceState"]){let original=history[name];history[name]=function(...args){let result=original.apply(this,args);return notify(),result}}return window.addEventListener("popstate",notify),window.addEventListener("hashchange",notify),target}function pageOf(value){try{let url=new URL(value||location.href,location.href);return url.search="",url.hash="",url.href}catch{return value||location.href}}function followPage(listener){let target=navigation(),scheduled=!1,changed=()=>{if(scheduled)return;scheduled=!0,queueMicrotask(()=>{scheduled=!1,listener()})};return target.addEventListener("change",changed),()=>target.removeEventListener("change",changed)}var catalogs={en:messages,tr:messages3,de:messages2},settings=new Map,Base=typeof HTMLElement>"u"?class{}:HTMLElement,scriptSrc=typeof document<"u"&&document.currentScript instanceof HTMLScriptElement?document.currentScript.src:"",baseStyles=`
1
+ import{createYuvaClient2}from"./index-6brgxahe.js";import{resolveLocale,translatePlain}from"./index-c6q8br7d.js";import{el}from"./index-rdzxvj2r.js";import{ApiError2}from"./index-gk84nm8f.js";import{directionOf,launcherOf,contrastOn,readStored,writeStored}from"./index-98r96a7e.js";var messages=JSON.parse(`{"-UxBoG":["Deleted member"],"1UzENP":["No"],"2lF8Zj":["Unanswered"],"5lWFkC":["Sign in"],"78dEKp":["Sort discussions"],"7oGBMv":["Discussions"],"8Ekoev":["You can't do that."],"8ntmc1":["Votes: ",["0"]],"D16wQE":["Could not open the discussion. Try again."],"D9CFV5":["Anonymous"],"E_qvzP":["Enter a valid e-mail address."],"EmiQvf":["Thanks! Anything we could add? (optional)"],"FMWGhb":["Deleted reader"],"G2fuEb":["Locked"],"GQVIIl":["You seem to be offline."],"GqCA_t":["Answered"],"Hw3P48":["Replies: ",["0"]],"JlFcis":["Send"],"KDw4GX":["Try again"],"KEjhwb":["This discussion is locked."],"KM6m8p":["Team"],"LwDe8g":["Sign in to take part in the discussion."],"MDmQKn":["Could not load the discussions."],"Pwqkdw":["Loading…"],"SOvBw9":["Was this page helpful?"],"Sad2tK":["Sending…"],"Su3Vyp":["Check the title and the text and try again."],"U7H5Fm":["Sorry about that. What was missing or unclear?"],"UbRKMZ":["Pending"],"WWy8TN":["Top"],"XJURKP":["E-mail address"],"a_qtPP":["E-mail for a reply (optional)"],"b6Orhy":["Have a question or an idea? Start the first one."],"b_f4xj":["Posts can be edited for 30 minutes after they are written."],"d6N994":["Thanks for your feedback."],"fMPkxb":["Show more"],"fcWrnU":["Sign out"],"isRobC":["New"],"j-3eim":["Discussions about this page"],"l75CjT":["Yes"],"lWv8id":["Awaiting approval"],"nLqMRA":["Team member"],"nW3go1":["Your browser blocked the sign-in window. Allow pop-ups for this site and try again."],"pzatAP":["Loading discussions…"],"rpfOwz":["No discussions about this page yet."],"tA4dAO":["No thanks"],"tAL5wg":["Could not send. Try again."],"tayT8P":["Discussions are turned off for this site."],"twEQ41":["Every discussion on this page has an answer."],"tzsBOP":["Too many attempts. Wait a moment and try again."],"uuIskV":["Sign in to write to us."],"xOTzt5":["just now"],"z1qf6l":["Start a discussion"],"zmA6sS":["Reader"]}`);var messages2=JSON.parse('{"-UxBoG":["Gelöschtes Mitglied"],"1UzENP":["Nein"],"2lF8Zj":["Unbeantwortet"],"5lWFkC":["Anmelden"],"78dEKp":["Diskussionen sortieren"],"7oGBMv":["Diskussionen"],"8Ekoev":["Das können Sie nicht tun."],"8ntmc1":["Stimmen: ",["0"]],"D16wQE":["Die Diskussion konnte nicht eröffnet werden. Versuchen Sie es erneut."],"D9CFV5":["Anonym"],"E_qvzP":["Geben Sie eine gültige E-Mail-Adresse ein."],"EmiQvf":["Danke! Können wir noch etwas ergänzen? (optional)"],"FMWGhb":["Gelöschter Leser"],"G2fuEb":["Gesperrt"],"GQVIIl":["Sie scheinen offline zu sein."],"GqCA_t":["Beantwortet"],"Hw3P48":["Antworten: ",["0"]],"JlFcis":["Senden"],"KDw4GX":["Erneut versuchen"],"KEjhwb":["Diese Diskussion ist gesperrt."],"KM6m8p":["Team"],"LwDe8g":["Melden Sie sich an, um an der Diskussion teilzunehmen."],"MDmQKn":["Die Diskussionen konnten nicht geladen werden."],"Pwqkdw":["Wird geladen…"],"SOvBw9":["War diese Seite hilfreich?"],"Sad2tK":["Wird gesendet…"],"Su3Vyp":["Prüfen Sie Titel und Text und versuchen Sie es erneut."],"U7H5Fm":["Das tut uns leid. Was hat gefehlt oder war unklar?"],"UbRKMZ":["Ausstehend"],"WWy8TN":["Beliebteste"],"XJURKP":["E-Mail-Adresse"],"a_qtPP":["E-Mail für eine Antwort (optional)"],"b6Orhy":["Haben Sie eine Frage oder eine Idee? Starten Sie die erste Diskussion."],"b_f4xj":["Beiträge können bis 30 Minuten nach dem Schreiben bearbeitet werden."],"d6N994":["Danke für Ihr Feedback."],"fMPkxb":["Mehr anzeigen"],"fcWrnU":["Abmelden"],"isRobC":["Neu"],"j-3eim":["Diskussionen zu dieser Seite"],"l75CjT":["Ja"],"lWv8id":["Wartet auf Freigabe"],"nLqMRA":["Teammitglied"],"nW3go1":["Ihr Browser hat das Anmeldefenster blockiert. Erlauben Sie Pop-ups für diese Website und versuchen Sie es erneut."],"pzatAP":["Diskussionen werden geladen…"],"rpfOwz":["Zu dieser Seite gibt es noch keine Diskussionen."],"tA4dAO":["Nein, danke"],"tAL5wg":["Senden fehlgeschlagen. Versuchen Sie es erneut."],"tayT8P":["Diskussionen sind für diese Website deaktiviert."],"twEQ41":["Jede Diskussion auf dieser Seite hat eine Antwort."],"tzsBOP":["Zu viele Versuche. Warten Sie einen Moment und versuchen Sie es erneut."],"uuIskV":["Melden Sie sich an, um uns zu schreiben."],"xOTzt5":["gerade eben"],"z1qf6l":["Diskussion starten"],"zmA6sS":["Leser"]}');var messages3=JSON.parse('{"-UxBoG":["Silinmiş üye"],"1UzENP":["Hayır"],"2lF8Zj":["Yanıtsız"],"5lWFkC":["Giriş yap"],"78dEKp":["Tartışmaları sırala"],"7oGBMv":["Tartışmalar"],"8Ekoev":["Bunu yapamazsınız."],"8ntmc1":["Oylar: ",["0"]],"D16wQE":["Tartışma açılamadı. Yeniden deneyin."],"D9CFV5":["Anonim"],"E_qvzP":["Geçerli bir e-posta adresi girin."],"EmiQvf":["Teşekkürler! Ekleyebileceğimiz bir şey var mı? (isteğe bağlı)"],"FMWGhb":["Silinmiş okuyucu"],"G2fuEb":["Kilitli"],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"GqCA_t":["Yanıtlandı"],"Hw3P48":["Yanıtlar: ",["0"]],"JlFcis":["Gönder"],"KDw4GX":["Yeniden dene"],"KEjhwb":["Bu tartışma kilitli."],"KM6m8p":["Ekip"],"LwDe8g":["Tartışmaya katılmak için giriş yapın."],"MDmQKn":["Tartışmalar yüklenemedi."],"Pwqkdw":["Yükleniyor…"],"SOvBw9":["Bu sayfa işinize yaradı mı?"],"Sad2tK":["Gönderiliyor…"],"Su3Vyp":["Başlığı ve metni kontrol edip yeniden deneyin."],"U7H5Fm":["Üzgünüz. Eksik ya da anlaşılmayan ne vardı?"],"UbRKMZ":["Bekliyor"],"WWy8TN":["En çok oy alan"],"XJURKP":["E-posta adresi"],"a_qtPP":["Yanıt için e-posta (isteğe bağlı)"],"b6Orhy":["Bir sorunuz ya da fikriniz mi var? İlk tartışmayı siz başlatın."],"b_f4xj":["Gönderiler yazıldıktan sonra 30 dakika içinde düzenlenebilir."],"d6N994":["Geri bildiriminiz için teşekkürler."],"fMPkxb":["Daha fazla göster"],"fcWrnU":["Çıkış yap"],"isRobC":["Yeni"],"j-3eim":["Bu sayfayla ilgili tartışmalar"],"l75CjT":["Evet"],"lWv8id":["Onay bekliyor"],"nLqMRA":["Ekip üyesi"],"nW3go1":["Tarayıcınız giriş penceresini engelledi. Bu site için açılır pencerelere izin verip yeniden deneyin."],"pzatAP":["Tartışmalar yükleniyor…"],"rpfOwz":["Bu sayfayla ilgili henüz bir tartışma yok."],"tA4dAO":["Hayır, teşekkürler"],"tAL5wg":["Gönderilemedi. Yeniden deneyin."],"tayT8P":["Bu sitede tartışmalar kapalı."],"twEQ41":["Bu sayfadaki her tartışmanın bir yanıtı var."],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"uuIskV":["Bize yazmak için oturum açın."],"xOTzt5":["az önce"],"z1qf6l":["Tartışma başlat"],"zmA6sS":["Okur"]}');var shared=Symbol.for("yuva.navigation");function navigation(){let win=window,target=win[shared];if(target)return target;let created=new EventTarget;target=win[shared]=created;let notify=()=>created.dispatchEvent(new Event("change"));for(let name of["pushState","replaceState"]){let original=history[name];history[name]=function(...args){let result=original.apply(this,args);return notify(),result}}return window.addEventListener("popstate",notify),window.addEventListener("hashchange",notify),target}function pageOf(value){try{let url=new URL(value||location.href,location.href);return url.search="",url.hash="",url.href}catch{return value||location.href}}function followPage(listener){let target=navigation(),scheduled=!1,changed=()=>{if(scheduled)return;scheduled=!0,queueMicrotask(()=>{scheduled=!1,listener()})};return target.addEventListener("change",changed),()=>target.removeEventListener("change",changed)}var catalogs={en:messages,tr:messages3,de:messages2},settings=new Map,Base=typeof HTMLElement>"u"?class{}:HTMLElement,scriptSrc=typeof document<"u"&&document.currentScript instanceof HTMLScriptElement?document.currentScript.src:"",baseStyles=`
2
2
  :host {
3
3
  --yuva-accent: #2563eb;
4
4
  --yuva-on-accent: #ffffff;
@@ -1,4 +1,4 @@
1
- import{ApiError2,call,mailingLists,createSubscription}from"./index-gk84nm8f.js";class Realtime{server;socketClass;handlers;#socket=null;#lastEventId=0;#attempt=0;#timer=null;#stopped=!0;constructor(server,socketClass,handlers){this.server=server;this.socketClass=socketClass;this.handlers=handlers}get connected(){return this.#socket?.readyState===1}start(){if(this.#stopped=!1,!this.#socket&&!this.#timer)this.#connect()}stop(){if(this.#stopped=!0,this.#timer)clearTimeout(this.#timer);this.#timer=null;let socket=this.#socket;this.#socket=null,socket?.close(1000)}reset(){this.#lastEventId=0}nudge(){if(this.#stopped||this.#socket)return;if(this.#timer)clearTimeout(this.#timer);this.#timer=null,this.#connect()}#connect(){let token=this.handlers.token();if(!token||this.#stopped)return;let url=new URL(`${this.server}/client/v1/realtime`,globalThis.location?.href);if(url.protocol=url.protocol==="https:"?"wss:":"ws:",this.#lastEventId>0)url.searchParams.set("last_event_id",String(this.#lastEventId));let socket;try{socket=new this.socketClass(url,["yuva",`yuva.token.${token}`])}catch{this.#schedule();return}this.#socket=socket,socket.onmessage=(event)=>{let message;try{message=JSON.parse(String(event.data))}catch{return}if(message.type==="ready")this.#attempt=0,this.#lastEventId=Math.max(this.#lastEventId,message.last_event_id);else if("id"in message&&typeof message.id==="number")this.#lastEventId=Math.max(this.#lastEventId,message.id);this.handlers.event(message)},socket.onclose=(event)=>{if(this.#socket!==socket)return;if(this.#socket=null,this.#stopped)return;if(event.code===1008){this.#lastEventId=0,this.handlers.sessionEnded();return}this.#schedule()}}#schedule(){if(this.#stopped||this.#timer)return;let attempt=this.#attempt++;this.handlers.reconnecting(attempt);let delay=Math.min(30000,1000*2**attempt)*(0.75+Math.random()*0.5);this.#timer=setTimeout(()=>{this.#timer=null,this.#connect()},delay)}}function readerConnectUrl2(server,channel,origin){let url=new URL("/account/connect",server);return url.searchParams.set("channel",channel),url.searchParams.set("origin",origin),url.href}function isReaderToken(value){let data=value;return!!data&&typeof data.token==="string"&&data.token.startsWith("yuva_rd_")&&typeof data.expires_at==="string"&&!Number.isNaN(Date.parse(data.expires_at))&&typeof data.channel_key==="string"&&typeof data.origin==="string"&&!!data.reader&&typeof data.reader.initials==="string"}function openReaderPopup2(server,channel,{width=460,height=640}={}){let serverOrigin=new URL(server).origin,origin=location.origin,left=Math.max(0,(window.screenX??0)+((window.outerWidth??width)-width)/2),top=Math.max(0,(window.screenY??0)+((window.outerHeight??height)-height)/2),popup=window.open(readerConnectUrl2(server,channel,origin),"yuva-reader",`popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`);if(!popup)return Promise.reject(new ApiError2(0,"popup_blocked"));return new Promise((resolve,reject)=>{let done=!1,finish=()=>{done=!0,window.removeEventListener("message",received),clearInterval(watch)},received=(event)=>{if(done||event.origin!==serverOrigin||event.source&&event.source!==popup)return;let data=event.data;if(!isReaderToken(data)||data.channel_key!==channel||data.origin!==origin)return;finish();try{popup.close()}catch{}resolve({token:data.token,expires_at:data.expires_at,reader:data.reader})},watch=setInterval(()=>{let closed=!1;try{closed=popup.closed}catch{}if(!closed)return;clearInterval(watch),setTimeout(()=>{if(done)return;finish(),reject(new ApiError2(0,"sign_in_cancelled"))},300)},500);window.addEventListener("message",received)})}function storageKey2(channel){return`yuva:${channel}`}function readerStorageKey2(server,channel){return`yuva:reader:${server} ${channel}`}function randomId2(){if(typeof crypto.randomUUID==="function")return crypto.randomUUID();return Array.from(crypto.getRandomValues(new Uint8Array(16)),(b)=>b.toString(16).padStart(2,"0")).join("")}function jwtSubject(token){try{let part=(token.split(".")[1]??"").replace(/-/g,"+").replace(/_/g,"/"),payload=JSON.parse(atob(part));return typeof payload.sub==="string"?payload.sub:null}catch{return null}}function defaultStorage(){try{let storage=globalThis.localStorage;if(storage)return storage}catch{}let memory=new Map;return{getItem:(key)=>memory.get(key)??null,setItem:(key,value)=>void memory.set(key,value)}}function query(params){let search=new URLSearchParams;for(let[name,value]of Object.entries(params))if(value!==void 0)search.set(name,String(value));let text=search.toString();return text?`?${text}`:""}function quoted(value){return value.replace(/"/g,"%22").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function multipart(fields,files,boundary){let parts=[];for(let[name,value]of fields)parts.push(`--${boundary}\r
1
+ import{ApiError2,call,mailingLists,createSubscription}from"./index-gk84nm8f.js";class Realtime{server;socketClass;handlers;#socket=null;#lastEventId=0;#attempt=0;#timer=null;#stopped=!0;constructor(server,socketClass,handlers){this.server=server;this.socketClass=socketClass;this.handlers=handlers}get connected(){return this.#socket?.readyState===1}start(){if(this.#stopped=!1,!this.#socket&&!this.#timer)this.#connect()}stop(){if(this.#stopped=!0,this.#timer)clearTimeout(this.#timer);this.#timer=null;let socket=this.#socket;this.#socket=null,socket?.close(1000)}reset(){this.#lastEventId=0}nudge(){if(this.#stopped||this.#socket)return;if(this.#timer)clearTimeout(this.#timer);this.#timer=null,this.#connect()}#connect(){let token=this.handlers.token();if(!token||this.#stopped)return;let url=new URL(`${this.server}/client/v1/realtime`,globalThis.location?.href);if(url.protocol=url.protocol==="https:"?"wss:":"ws:",this.#lastEventId>0)url.searchParams.set("last_event_id",String(this.#lastEventId));let socket;try{socket=new this.socketClass(url,["yuva",`yuva.token.${token}`])}catch{this.#schedule();return}this.#socket=socket,socket.onmessage=(event)=>{let message;try{message=JSON.parse(String(event.data))}catch{return}if(message.type==="ready")this.#attempt=0,this.#lastEventId=Math.max(this.#lastEventId,message.last_event_id);else if("id"in message&&typeof message.id==="number")this.#lastEventId=Math.max(this.#lastEventId,message.id);this.handlers.event(message)},socket.onclose=(event)=>{if(this.#socket!==socket)return;if(this.#socket=null,this.#stopped)return;if(event.code===1008){this.#lastEventId=0,this.handlers.sessionEnded();return}this.#schedule()}}#schedule(){if(this.#stopped||this.#timer)return;let attempt=this.#attempt++;this.handlers.reconnecting(attempt);let delay=Math.min(30000,1000*2**attempt)*(0.75+Math.random()*0.5);this.#timer=setTimeout(()=>{this.#timer=null,this.#connect()},delay)}}function readerConnectUrl2(server,channel,origin){let url=new URL("/account/connect",server);return url.searchParams.set("channel",channel),url.searchParams.set("origin",origin),url.href}function isReaderToken(value){let data=value;return!!data&&typeof data.token==="string"&&data.token.startsWith("yuva_rd_")&&typeof data.expires_at==="string"&&!Number.isNaN(Date.parse(data.expires_at))&&typeof data.channel_key==="string"&&typeof data.origin==="string"&&!!data.reader&&typeof data.reader.initials==="string"}function openReaderPopup2(server,channel,{width=460,height=640}={}){let serverOrigin=new URL(server).origin,origin=location.origin,left=Math.max(0,(window.screenX??0)+((window.outerWidth??width)-width)/2),top=Math.max(0,(window.screenY??0)+((window.outerHeight??height)-height)/2),popup=window.open(readerConnectUrl2(server,channel,origin),"yuva-reader",`popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`);if(!popup)return Promise.reject(new ApiError2(0,"popup_blocked"));return new Promise((resolve,reject)=>{let done=!1,finish=()=>{done=!0,window.removeEventListener("message",received),clearInterval(watch)},received=(event)=>{if(done||event.origin!==serverOrigin||event.source&&event.source!==popup)return;let data=event.data;if(!isReaderToken(data)||data.channel_key!==channel||data.origin!==origin)return;finish();try{popup.close()}catch{}resolve({token:data.token,expires_at:data.expires_at,reader:data.reader})},watch=setInterval(()=>{let closed=!1;try{closed=popup.closed}catch{}if(!closed)return;clearInterval(watch),setTimeout(()=>{if(done)return;finish(),reject(new ApiError2(0,"sign_in_cancelled"))},300)},500);window.addEventListener("message",received)})}function storageKey2(channel){return`yuva:${channel}`}function readerStorageKey2(server,channel){return`yuva:reader:${server} ${channel}`}function randomId2(){if(typeof crypto.randomUUID==="function")return crypto.randomUUID();return Array.from(crypto.getRandomValues(new Uint8Array(16)),(b)=>b.toString(16).padStart(2,"0")).join("")}function jwtSubject(token){try{let part=(token.split(".")[1]??"").replace(/-/g,"+").replace(/_/g,"/"),payload=JSON.parse(atob(part));return typeof payload.sub==="string"?payload.sub:null}catch{return null}}function currentPage(){let location2=globalThis.location;if(!location2||!/^https?:$/.test(location2.protocol))return{};let page_url=location2.origin+location2.pathname;if(page_url.length>2000)return{};let title=Array.from(globalThis.document?.title.trim()??"").slice(0,300).join("").trim();return title?{page_url,page_title:title}:{page_url}}function defaultStorage(){try{let storage=globalThis.localStorage;if(storage)return storage}catch{}let memory=new Map;return{getItem:(key)=>memory.get(key)??null,setItem:(key,value)=>void memory.set(key,value)}}function query(params){let search=new URLSearchParams;for(let[name,value]of Object.entries(params))if(value!==void 0)search.set(name,String(value));let text=search.toString();return text?`?${text}`:""}function quoted(value){return value.replace(/"/g,"%22").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function multipart(fields,files,boundary){let parts=[];for(let[name,value]of fields)parts.push(`--${boundary}\r
2
2
  Content-Disposition: form-data; name="${name}"\r
3
3
  \r
4
4
  ${value}\r
@@ -8,5 +8,5 @@ Content-Type: ${file.type||"application/octet-stream"}\r
8
8
  \r
9
9
  `,file,`\r
10
10
  `)}return parts.push(`--${boundary}--\r
11
- `),new Blob(parts)}class YuvaClient2{server;channel;#fetch;#socketClass;#storage;#identity;#idempotencyKeys;#token=null;#session=null;#starting=null;#renewing=null;#realtime=null;#reader;#handlers=new Map;constructor(options){this.server=options.server.replace(/\/+$/,""),this.channel=options.channel,this.#fetch=options.fetch??((url,init)=>fetch(url,init)),this.#socketClass=options.WebSocket??globalThis.WebSocket,this.#storage=options.storage??defaultStorage(),this.#identity=options.identityToken??null,this.#idempotencyKeys=options.idempotencyKeys??typeof globalThis.document>"u"}get session(){return this.#session}get token(){return this.#token}get connected(){return this.#realtime?.connected??!1}on(type,handler){let set=this.#handlers.get(type);if(!set)this.#handlers.set(type,set=new Set);return set.add(handler),()=>void set.delete(handler)}#emit(type,value){for(let handler of this.#handlers.get(type)??[])handler(value)}stored(){try{let raw=this.#storage.getItem(storageKey2(this.channel));return raw?JSON.parse(raw):{}}catch{return{}}}#store(state){try{this.#storage.setItem(storageKey2(this.channel),JSON.stringify(state))}catch{}}channelSettings(){return this.#call(`/client/v1/channels/${encodeURIComponent(this.channel)}`)}ratePage(input){return this.#call(`/client/v1/channels/${encodeURIComponent(this.channel)}/page-ratings`,{method:"POST",json:input})}lists(){return mailingLists(this.#fetch,this.server,this.channel)}subscribe(input){return createSubscription(this.#fetch,this.server,this.channel,input)}subscriptions(){return this.#authed("/client/v1/subscriptions")}subscribeList(listId,input){return this.#authed(`/client/v1/subscriptions/${encodeURIComponent(listId)}`,{method:"PUT",json:input})}unsubscribeList(listId){return this.#authed(`/client/v1/subscriptions/${encodeURIComponent(listId)}`,{method:"DELETE"})}setIdentityToken(source){this.#identity=source,this.reset()}start(){if(this.#session)return Promise.resolve(this.#session);return this.#starting??=this.#open(!1).then((session)=>(this.#emit("session",{session,renewed:!1}),session)).finally(()=>{this.#starting=null}),this.#starting}async refresh(){let info=await this.#authed("/client/v1/session");return this.#session={...this.#session,...info},this.#emit("session",{session:this.#session,renewed:!1}),this.#session}reset(){this.#realtime?.stop(),this.#realtime?.reset(),this.#starting=null,this.#renewing=null,this.#token=null,this.#session=null}async signOut(){let token=this.#token;this.reset();let stored=this.stored();if(delete stored.session,this.#store(stored),token)await this.#call("/client/v1/session",{method:"DELETE",token}).catch(()=>{return})}async connect(){if(!this.#socketClass)throw Error("Yuva: no WebSocket in this runtime; pass options.WebSocket");if(await this.start(),this.#realtime??=new Realtime(this.server,this.#socketClass,{token:()=>this.#token,event:(message)=>{if(message.type==="ready")this.#emit("connection",{state:"open",attempt:0});this.#emit("event",message)},sessionEnded:()=>void this.#renew().catch(()=>this.#realtime?.nudge()),reconnecting:(attempt)=>{if(this.#emit("connection",{state:"reconnecting",attempt}),attempt===2)this.#authed("/client/v1/session").catch(()=>{return})}}),!this.#realtime.connected)this.#emit("connection",{state:"connecting",attempt:0});this.#realtime.start()}disconnect(){this.#realtime?.stop(),this.#emit("connection",{state:"closed",attempt:0})}reconnect(){this.#realtime?.nudge()}listConversations(page={}){return this.#authed(`/client/v1/conversations${query({...page})}`)}getConversation(id){return this.#authed(`/client/v1/conversations/${encodeURIComponent(id)}`)}startConversation(input){return this.#authed("/client/v1/conversations",this.#messageRequest(input))}listMessages(conversationId,page={}){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/messages${query({...page})}`)}sendMessage(conversationId,input){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/messages`,this.#messageRequest(input))}markRead(conversationId,messageId){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/read`,{method:"POST",json:messageId?{message_id:messageId}:{}})}rate(conversationId,rating,comment){let body={rating,comment:comment?.trim()||void 0};return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/rating`,{method:"POST",json:body})}setTyping(conversationId,typing){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/typing`,{method:"POST",json:{typing}})}setEmail(email){return this.#authed("/client/v1/contact/email",{method:"PUT",json:{email}})}attachment(id){return this.#authed(`/client/v1/attachments/${encodeURIComponent(id)}`,{blob:!0})}sendFeedback(input){let client_id=input.client_id??randomId2();return this.#authed("/client/v1/feedback",{method:"POST",headers:this.#idempotency(client_id),json:{...input,client_id}})}get reader(){if(this.#reader===void 0)try{let raw=this.#storage.getItem(readerStorageKey2(this.server,this.channel));this.#reader=raw?JSON.parse(raw):null}catch{this.#reader=null}if(this.#reader&&Date.parse(this.#reader.expires_at)<=Date.now()+30000)this.#setReader(null);return this.#reader}#setReader(reader){let changed=this.#reader?.token!==reader?.token;this.#reader=reader;try{this.#storage.setItem(readerStorageKey2(this.server,this.channel),reader?JSON.stringify(reader):"")}catch{}if(changed)this.#emit("reader",reader)}readerSignIn(options){return openReaderPopup2(this.server,this.channel,options).then((reader)=>(this.#setReader(reader),reader))}setReader(reader){this.#setReader(reader)}async readerSignOut(){let token=this.reader?.token;if(this.#setReader(null),token)await this.#call("/client/v1/reader-token",{method:"DELETE",token}).catch(()=>{return})}listDiscussions(page,options={}){return this.#discussionCall(`/client/v1/channels/${encodeURIComponent(this.channel)}/discussions${query({page,...options})}`,{},!1)}getDiscussion(id){return this.#discussionCall(`/client/v1/channels/${encodeURIComponent(this.channel)}/discussions/${encodeURIComponent(id)}`,{},!1)}startDiscussion(input){return this.#discussionCall("/client/v1/discussions",{method:"POST",json:input})}replyToDiscussion(discussionId,input){return this.#discussionCall(`/client/v1/discussions/${encodeURIComponent(discussionId)}/posts`,{method:"POST",json:input})}editDiscussionPost(postId,input){return this.#discussionCall(`/client/v1/discussion-posts/${encodeURIComponent(postId)}`,{method:"PATCH",json:input})}deleteDiscussionPost(postId){return this.#discussionCall(`/client/v1/discussion-posts/${encodeURIComponent(postId)}`,{method:"DELETE"})}voteDiscussionPost(postId,voted=!0){return this.#discussionCall(`/client/v1/discussion-posts/${encodeURIComponent(postId)}/vote`,{method:voted?"PUT":"DELETE"})}followDiscussion(discussionId,following=!0){return this.#discussionCall(`/client/v1/discussions/${encodeURIComponent(discussionId)}/follow`,{method:following?"PUT":"DELETE"})}acceptDiscussionAnswer(discussionId,postId){let path=`/client/v1/discussions/${encodeURIComponent(discussionId)}/answer`;return this.#discussionCall(path,postId?{method:"PUT",json:{post_id:postId}}:{method:"DELETE"})}async discussionWriter(){if(this.reader)return"reader";if(this.#session)return this.#session.contact.identified?"contact":null;return await this.#identity?.()?"contact":null}async#discussionCall(path,request,write=!0){let reader=this.reader;if(reader)try{return await this.#call(path,{...request,token:reader.token})}catch(error){if(!(error instanceof ApiError2)||error.status!==401||this.#reader?.token!==reader.token)throw error;if(this.#setReader(null),write)throw new ApiError2(403,"sign_in_required")}if(await this.discussionWriter()==="contact")return this.#authed(path,request);if(write)throw new ApiError2(403,"sign_in_required");return this.#call(path,request)}#idempotency(client_id){return this.#idempotencyKeys&&/^[\x20-\x7e]{1,255}$/.test(client_id)?{"Idempotency-Key":client_id}:{}}#messageRequest({body,subject,files=[],client_id=randomId2()}){let headers=this.#idempotency(client_id);if(files.length===0)return{method:"POST",headers,json:{body,subject,client_id}};let fields=[];if(subject)fields.push(["subject",subject]);if(body)fields.push(["body",body]);fields.push(["client_id",client_id]);let boundary=`yuva-${client_id.replace(/[^\w-]/g,"").slice(0,60)}-${client_id.length}`;return headers["Content-Type"]=`multipart/form-data; boundary=${boundary}`,{method:"POST",headers,body:multipart(fields,files,boundary)}}#call(path,request){return call(this.#fetch,this.server,path,request)}async#authed(path,request={},retry=!0){if(!this.#token)await this.start();try{return await this.#call(path,{...request,token:this.#token})}catch(error){if(!retry||!(error instanceof ApiError2)||error.status!==401)throw error;return await this.#renew(),this.#authed(path,request,!1)}}#renew(){return this.#renewing??=(async()=>{let session=await this.#open(!0);if(this.#realtime)this.#realtime.stop(),this.#realtime.reset(),this.#realtime.start();this.#emit("session",{session,renewed:!0})})().finally(()=>{this.#renewing=null}),this.#renewing}async#open(fresh){let stored=this.stored(),identity=await this.#identity?.()||null,subject=identity?jwtSubject(identity):null,saved=stored.session;if(!fresh&&saved&&saved.sub===subject&&Date.parse(saved.expires_at)>Date.now()+60000)try{let info=await this.#call("/client/v1/session",{token:saved.token});return this.#apply(info,saved.token,subject)}catch(error){if(!(error instanceof ApiError2)||error.status!==401&&error.status!==403)throw error}let session=await this.#call("/client/v1/session",{method:"POST",json:{channel_key:this.channel,identity_token:identity??void 0,visitor_id:stored.visitor_id}}),{token,...info}=session;return this.#apply(info,token,subject)}#apply(info,token,subject){this.#token=token,this.#session=info;let stored=this.stored();if(stored.session={token,expires_at:info.expires_at,sub:subject},info.visitor_id)stored.visitor_id=info.visitor_id;else if(info.contact.identified)delete stored.visitor_id;return this.#store(stored),info}}function createYuvaClient2(options){return new YuvaClient2(options)}
11
+ `),new Blob(parts)}class YuvaClient2{server;channel;#fetch;#socketClass;#storage;#identity;#idempotencyKeys;#token=null;#session=null;#starting=null;#renewing=null;#realtime=null;#reader;#handlers=new Map;constructor(options){this.server=options.server.replace(/\/+$/,""),this.channel=options.channel,this.#fetch=options.fetch??((url,init)=>fetch(url,init)),this.#socketClass=options.WebSocket??globalThis.WebSocket,this.#storage=options.storage??defaultStorage(),this.#identity=options.identityToken??null,this.#idempotencyKeys=options.idempotencyKeys??typeof globalThis.document>"u"}get session(){return this.#session}get token(){return this.#token}get connected(){return this.#realtime?.connected??!1}on(type,handler){let set=this.#handlers.get(type);if(!set)this.#handlers.set(type,set=new Set);return set.add(handler),()=>void set.delete(handler)}#emit(type,value){for(let handler of this.#handlers.get(type)??[])handler(value)}stored(){try{let raw=this.#storage.getItem(storageKey2(this.channel));return raw?JSON.parse(raw):{}}catch{return{}}}#store(state){try{this.#storage.setItem(storageKey2(this.channel),JSON.stringify(state))}catch{}}channelSettings(){return this.#call(`/client/v1/channels/${encodeURIComponent(this.channel)}`)}ratePage(input){return this.#call(`/client/v1/channels/${encodeURIComponent(this.channel)}/page-ratings`,{method:"POST",json:input})}lists(){return mailingLists(this.#fetch,this.server,this.channel)}subscribe(input){return createSubscription(this.#fetch,this.server,this.channel,input)}subscriptions(){return this.#authed("/client/v1/subscriptions")}subscribeList(listId,input){return this.#authed(`/client/v1/subscriptions/${encodeURIComponent(listId)}`,{method:"PUT",json:input})}unsubscribeList(listId){return this.#authed(`/client/v1/subscriptions/${encodeURIComponent(listId)}`,{method:"DELETE"})}setIdentityToken(source){this.#identity=source,this.reset()}start(){if(this.#session)return Promise.resolve(this.#session);return this.#starting??=this.#open(!1).then((session)=>(this.#emit("session",{session,renewed:!1}),session)).finally(()=>{this.#starting=null}),this.#starting}async refresh(){let info=await this.#authed("/client/v1/session");return this.#session={...this.#session,...info},this.#emit("session",{session:this.#session,renewed:!1}),this.#session}reset(){this.#realtime?.stop(),this.#realtime?.reset(),this.#starting=null,this.#renewing=null,this.#token=null,this.#session=null}async signOut(){let token=this.#token;this.reset();let stored=this.stored();if(delete stored.session,this.#store(stored),token)await this.#call("/client/v1/session",{method:"DELETE",token}).catch(()=>{return})}async connect(){if(!this.#socketClass)throw Error("Yuva: no WebSocket in this runtime; pass options.WebSocket");if(await this.start(),this.#realtime??=new Realtime(this.server,this.#socketClass,{token:()=>this.#token,event:(message)=>{if(message.type==="ready")this.#emit("connection",{state:"open",attempt:0});this.#emit("event",message)},sessionEnded:()=>void this.#renew().catch(()=>this.#realtime?.nudge()),reconnecting:(attempt)=>{if(this.#emit("connection",{state:"reconnecting",attempt}),attempt===2)this.#authed("/client/v1/session").catch(()=>{return})}}),!this.#realtime.connected)this.#emit("connection",{state:"connecting",attempt:0});this.#realtime.start()}disconnect(){this.#realtime?.stop(),this.#emit("connection",{state:"closed",attempt:0})}reconnect(){this.#realtime?.nudge()}listConversations(page={}){return this.#authed(`/client/v1/conversations${query({...page})}`)}getConversation(id){return this.#authed(`/client/v1/conversations/${encodeURIComponent(id)}`)}startConversation(input){let request=input.page_url===void 0?{...input,...currentPage()}:input;return this.#authed("/client/v1/conversations",this.#messageRequest(request))}listMessages(conversationId,page={}){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/messages${query({...page})}`)}sendMessage(conversationId,input){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/messages`,this.#messageRequest(input))}markRead(conversationId,messageId){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/read`,{method:"POST",json:messageId?{message_id:messageId}:{}})}rate(conversationId,rating,comment){let body={rating,comment:comment?.trim()||void 0};return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/rating`,{method:"POST",json:body})}setTyping(conversationId,typing){return this.#authed(`/client/v1/conversations/${encodeURIComponent(conversationId)}/typing`,{method:"POST",json:{typing}})}setEmail(email){return this.#authed("/client/v1/contact/email",{method:"PUT",json:{email}})}attachment(id){return this.#authed(`/client/v1/attachments/${encodeURIComponent(id)}`,{blob:!0})}sendFeedback(input){let client_id=input.client_id??randomId2();return this.#authed("/client/v1/feedback",{method:"POST",headers:this.#idempotency(client_id),json:{...input,client_id}})}get reader(){if(this.#reader===void 0)try{let raw=this.#storage.getItem(readerStorageKey2(this.server,this.channel));this.#reader=raw?JSON.parse(raw):null}catch{this.#reader=null}if(this.#reader&&Date.parse(this.#reader.expires_at)<=Date.now()+30000)this.#setReader(null);return this.#reader}#setReader(reader){let changed=this.#reader?.token!==reader?.token;this.#reader=reader;try{this.#storage.setItem(readerStorageKey2(this.server,this.channel),reader?JSON.stringify(reader):"")}catch{}if(changed)this.#emit("reader",reader)}readerSignIn(options){return openReaderPopup2(this.server,this.channel,options).then((reader)=>(this.#setReader(reader),reader))}setReader(reader){this.#setReader(reader)}async readerSignOut(){let token=this.reader?.token;if(this.#setReader(null),token)await this.#call("/client/v1/reader-token",{method:"DELETE",token}).catch(()=>{return})}listDiscussions(page,options={}){return this.#discussionCall(`/client/v1/channels/${encodeURIComponent(this.channel)}/discussions${query({page,...options})}`,{},!1)}getDiscussion(id){return this.#discussionCall(`/client/v1/channels/${encodeURIComponent(this.channel)}/discussions/${encodeURIComponent(id)}`,{},!1)}startDiscussion(input){return this.#discussionCall("/client/v1/discussions",{method:"POST",json:input})}replyToDiscussion(discussionId,input){return this.#discussionCall(`/client/v1/discussions/${encodeURIComponent(discussionId)}/posts`,{method:"POST",json:input})}editDiscussionPost(postId,input){return this.#discussionCall(`/client/v1/discussion-posts/${encodeURIComponent(postId)}`,{method:"PATCH",json:input})}deleteDiscussionPost(postId){return this.#discussionCall(`/client/v1/discussion-posts/${encodeURIComponent(postId)}`,{method:"DELETE"})}voteDiscussionPost(postId,voted=!0){return this.#discussionCall(`/client/v1/discussion-posts/${encodeURIComponent(postId)}/vote`,{method:voted?"PUT":"DELETE"})}followDiscussion(discussionId,following=!0){return this.#discussionCall(`/client/v1/discussions/${encodeURIComponent(discussionId)}/follow`,{method:following?"PUT":"DELETE"})}acceptDiscussionAnswer(discussionId,postId){let path=`/client/v1/discussions/${encodeURIComponent(discussionId)}/answer`;return this.#discussionCall(path,postId?{method:"PUT",json:{post_id:postId}}:{method:"DELETE"})}async discussionWriter(){if(this.reader)return"reader";if(this.#session)return this.#session.contact.identified?"contact":null;return await this.#identity?.()?"contact":null}async#discussionCall(path,request,write=!0){let reader=this.reader;if(reader)try{return await this.#call(path,{...request,token:reader.token})}catch(error){if(!(error instanceof ApiError2)||error.status!==401||this.#reader?.token!==reader.token)throw error;if(this.#setReader(null),write)throw new ApiError2(403,"sign_in_required")}if(await this.discussionWriter()==="contact")return this.#authed(path,request);if(write)throw new ApiError2(403,"sign_in_required");return this.#call(path,request)}#idempotency(client_id){return this.#idempotencyKeys&&/^[\x20-\x7e]{1,255}$/.test(client_id)?{"Idempotency-Key":client_id}:{}}#messageRequest({body,subject,files=[],client_id=randomId2(),...page}){let headers=this.#idempotency(client_id),page_url=page.page_url??void 0,page_title=page_url?page.page_title:void 0;if(files.length===0)return{method:"POST",headers,json:{body,subject,client_id,page_url,page_title}};let fields=[];if(subject)fields.push(["subject",subject]);if(body)fields.push(["body",body]);if(fields.push(["client_id",client_id]),page_url)fields.push(["page_url",page_url]);if(page_title)fields.push(["page_title",page_title]);let boundary=`yuva-${client_id.replace(/[^\w-]/g,"").slice(0,60)}-${client_id.length}`;return headers["Content-Type"]=`multipart/form-data; boundary=${boundary}`,{method:"POST",headers,body:multipart(fields,files,boundary)}}#call(path,request){return call(this.#fetch,this.server,path,request)}async#authed(path,request={},retry=!0){if(!this.#token)await this.start();try{return await this.#call(path,{...request,token:this.#token})}catch(error){if(!retry||!(error instanceof ApiError2)||error.status!==401)throw error;return await this.#renew(),this.#authed(path,request,!1)}}#renew(){return this.#renewing??=(async()=>{let session=await this.#open(!0);if(this.#realtime)this.#realtime.stop(),this.#realtime.reset(),this.#realtime.start();this.#emit("session",{session,renewed:!0})})().finally(()=>{this.#renewing=null}),this.#renewing}async#open(fresh){let stored=this.stored(),identity=await this.#identity?.()||null,subject=identity?jwtSubject(identity):null,saved=stored.session;if(!fresh&&saved&&saved.sub===subject&&Date.parse(saved.expires_at)>Date.now()+60000)try{let info=await this.#call("/client/v1/session",{token:saved.token});return this.#apply(info,saved.token,subject)}catch(error){if(!(error instanceof ApiError2)||error.status!==401&&error.status!==403)throw error}let session=await this.#call("/client/v1/session",{method:"POST",json:{channel_key:this.channel,identity_token:identity??void 0,visitor_id:stored.visitor_id}}),{token,...info}=session;return this.#apply(info,token,subject)}#apply(info,token,subject){this.#token=token,this.#session=info;let stored=this.stored();if(stored.session={token,expires_at:info.expires_at,sub:subject},info.visitor_id)stored.visitor_id=info.visitor_id;else if(info.contact.identified)delete stored.visitor_id;return this.#store(stored),info}}function createYuvaClient2(options){return new YuvaClient2(options)}
12
12
  export{readerConnectUrl2,openReaderPopup2,storageKey2,readerStorageKey2,randomId2,YuvaClient2,createYuvaClient2};
package/dist/esm/index.js CHANGED
@@ -1 +1 @@
1
- import{readerConnectUrl2,openReaderPopup2,YuvaClient2,createYuvaClient2}from"./index-geeh5h34.js";import{ApiError2}from"./index-gk84nm8f.js";export{ApiError2 as ApiError,YuvaClient2 as YuvaClient,createYuvaClient2 as createYuvaClient,openReaderPopup2 as openReaderPopup,readerConnectUrl2 as readerConnectUrl};
1
+ import{readerConnectUrl2,openReaderPopup2,YuvaClient2,createYuvaClient2}from"./index-6brgxahe.js";import{ApiError2}from"./index-gk84nm8f.js";export{ApiError2 as ApiError,YuvaClient2 as YuvaClient,createYuvaClient2 as createYuvaClient,openReaderPopup2 as openReaderPopup,readerConnectUrl2 as readerConnectUrl};
@@ -1,6 +1,15 @@
1
1
  import { useNuxtApp } from "#imports";
2
2
  const noop = () => {};
3
- const idle = { pageview: noop, track: noop, notFound: noop, consent: noop, optOut: noop, optIn: noop };
3
+ const idle = {
4
+ pageview: noop,
5
+ track: noop,
6
+ notFound: noop,
7
+ consent: noop,
8
+ identify: noop,
9
+ persistentId: noop,
10
+ optOut: noop,
11
+ optIn: noop
12
+ };
4
13
  export function useYuvaAnalytics() {
5
14
  return useNuxtApp().$yuvaAnalytics ?? idle;
6
15
  }
package/dist/esm/react.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{createContext,createElement,useCallback,useContext,useEffect,useRef,useState}from"react";var current,pending=[],call=(name)=>(...args)=>current?current[name](...args):void pending.push([name,args]),analytics={pageview:call("pageview"),track:call("track"),notFound:call("notFound"),consent:call("consent"),optOut:call("optOut"),optIn:call("optIn")};function attachAnalytics(instance){if(current=instance,instance)for(let[name,args]of pending.splice(0))instance[name](...args)}var YuvaContext=createContext(null);function YuvaProvider({client,connect=!0,children}){return useEffect(()=>{if(!connect)return;return client.connect().catch(()=>{return}),()=>client.disconnect()},[client,connect]),createElement(YuvaContext.Provider,{value:client},children)}function useYuva(){let client=useContext(YuvaContext);if(!client)throw Error("Yuva: wrap your components in <YuvaProvider client={...}>");return client}var time=(value)=>Date.parse(value),byCreated=(a,b)=>time(a.created_at)-time(b.created_at),byActivity=(a,b)=>time(b.last_message_at??b.created_at)-time(a.last_message_at??a.created_at),initial={items:[],loading:!0,error:null};function useConversations(){let client=useYuva(),[state,setState]=useState(initial),cursor=useRef(void 0),current=useRef(state);useEffect(()=>{current.current=state});let load=useCallback(async(more)=>{setState((s)=>({...s,loading:!0}));try{let page=await client.listConversations({limit:50,cursor:more?cursor.current:void 0});cursor.current=page.next_cursor,setState((s)=>{let items=new Map((more?s.items:[]).map((c)=>[c.id,c]));for(let conversation of page.items)items.set(conversation.id,conversation);return{items:[...items.values()].sort(byActivity),cursor:page.next_cursor,loading:!1,error:null}})}catch(error){setState((s)=>({...s,loading:!1,error}))}},[client]);return useEffect(()=>{load(!1);let offSession=client.on("session",({renewed})=>void(renewed&&load(!1))),offEvent=client.on("event",(message)=>{if(message.type==="resync_required")return void load(!1);if(message.type==="conversation.created")setState((s)=>s.items.some((c)=>c.id===message.data.id)?s:{...s,items:[message.data,...s.items].sort(byActivity)});else if(message.type==="conversation.updated")setState((s)=>({...s,items:s.items.map((c)=>c.id===message.conversation_id?{...c,status:message.data.status}:c)}));else if(message.type==="message.created"){let m=message.data;if(!current.current.items.some((c)=>c.id===m.conversation_id))return void load(!1);setState((s)=>{let items=s.items.map((c)=>c.id===m.conversation_id?{...c,last_message:{id:m.id,author_type:m.author.type,text:m.body.slice(0,140),created_at:m.created_at},last_message_at:m.created_at,unread:c.unread||m.author.type!=="contact"}:c);return{...s,items:items.sort(byActivity)}})}});return()=>{offSession(),offEvent()}},[client,load]),{conversations:state.items,loading:state.loading,error:state.error,hasMore:!!state.cursor,loadMore:()=>load(!0),reload:()=>load(!1)}}function useMessages(conversationId){let client=useYuva(),[state,setState]=useState(initial),cursor=useRef(void 0),upsert=useCallback((message)=>{setState((s)=>{let items=s.items.filter((m)=>m.id!==message.id&&(!message.client_id||m.client_id!==message.client_id));return{...s,items:[...items,message].sort(byCreated)}})},[]),load=useCallback(async(older)=>{if(!conversationId){cursor.current=void 0,setState({items:[],loading:!1,error:null});return}if(older&&!cursor.current)return;setState((s)=>({...s,loading:!0}));try{let page=await client.listMessages(conversationId,{order:"desc",limit:30,cursor:older?cursor.current:void 0});cursor.current=page.next_cursor,setState((s)=>{let items=new Map((older?s.items:[]).map((m)=>[m.id,m]));for(let message of page.items)items.set(message.id,message);return{items:[...items.values()].sort(byCreated),cursor:page.next_cursor,loading:!1,error:null}})}catch(error){setState((s)=>({...s,loading:!1,error}))}},[client,conversationId]);return useEffect(()=>{if(load(!1),!conversationId)return;let offSession=client.on("session",({renewed})=>void(renewed&&load(!1))),offEvent=client.on("event",(message)=>{if(message.type==="resync_required")load(!1);else if((message.type==="message.created"||message.type==="message.updated")&&message.data.conversation_id===conversationId)upsert(message.data)});return()=>{offSession(),offEvent()}},[client,conversationId,load,upsert]),{messages:state.items,loading:state.loading,error:state.error,hasMore:!!state.cursor,loadOlder:()=>load(!0),async send(input){if(!conversationId)throw Error("Yuva: no conversation; start one with client.startConversation()");let message=await client.sendMessage(conversationId,typeof input==="string"?{body:input}:input);return upsert(message),message},async markRead(){if(conversationId)await client.markRead(conversationId)}}}function useYuvaElement(tag,load,props,extra,handlers){let[element,setElement]=useState(null),latest=useRef(handlers),loader=useRef(load);useEffect(()=>{latest.current=handlers});let{channel,server,locale,dir,identityToken,className,style}=props;useEffect(()=>{loader.current()},[]);let attributes=JSON.stringify({server,locale,dir,...extra,"identity-token":typeof identityToken==="string"?identityToken:void 0,channel});useEffect(()=>{if(!element)return;for(let[name,value]of Object.entries(JSON.parse(attributes)))if(value)element.setAttribute(name,value);else element.removeAttribute(name)},[element,attributes]),useEffect(()=>{if(!element||typeof identityToken!=="function")return;let current=!0;return customElements.whenDefined(tag).then(()=>{if(current)element.setIdentityToken(identityToken)}),()=>{current=!1}},[element,tag,identityToken]);let events=Object.keys(handlers).join(" ");return useEffect(()=>{if(!element)return;let listeners=events.split(" ").map((type)=>{let listener=(event)=>latest.current[type]?.(event.detail);return element.addEventListener(type,listener),()=>element.removeEventListener(type,listener)});return()=>listeners.forEach((off)=>off())},[element,events]),createElement(tag,{ref:setElement,className,style})}var loadDocs=()=>import("./docs.js");function YuvaPageFeedback({onRating,onFeedback,...props}){return useYuvaElement("yuva-page-feedback",loadDocs,props,{page:props.page,"page-title":props.pageTitle},{"yuva-rating":onRating,"yuva-feedback":onFeedback})}function YuvaDiscussions({onDiscussion,onPost,onReader,...props}){return useYuvaElement("yuva-discussions",loadDocs,props,{page:props.page,"page-title":props.pageTitle},{"yuva-discussion":onDiscussion,"yuva-post":onPost,"yuva-reader":onReader})}function YuvaSubscribe({onSubscribe,onError,...props}){return useYuvaElement("yuva-subscribe",()=>import("./subscribe.js"),props,{lists:props.lists?.join(","),layout:props.layout,name:props.name,"button-text":props.buttonText,consent:props.consent,"privacy-url":props.privacyUrl},{"yuva-subscribe":onSubscribe,"yuva-subscribe-error":onError})}function YuvaAnalytics({server,publicKey:key,hash,consent,manual,outbound,files,chat}){return useEffect(()=>{let instance,mounted=!0;return import("./analytics.js").then(({createAnalytics})=>{if(!mounted)return;instance=createAnalytics({server,key,hash,consent,manual,outbound,files,chat}),attachAnalytics(instance)}),()=>{mounted=!1,instance?.destroy(),attachAnalytics(void 0)}},[server,key,hash,consent,manual,outbound,files,chat]),null}function useYuvaAnalytics(){return analytics}export{YuvaAnalytics,YuvaDiscussions,YuvaPageFeedback,YuvaProvider,YuvaSubscribe,useConversations,useMessages,useYuva,useYuvaAnalytics};
2
+ import{createContext,createElement,useCallback,useContext,useEffect,useRef,useState}from"react";var current,pending=[],call=(name)=>(...args)=>current?current[name](...args):void pending.push([name,args]),analytics={pageview:call("pageview"),track:call("track"),notFound:call("notFound"),consent:call("consent"),identify:call("identify"),persistentId:()=>current?.persistentId(),optOut:call("optOut"),optIn:call("optIn")};function attachAnalytics(instance){if(current=instance,instance)for(let[name,args]of pending.splice(0))instance[name](...args)}var YuvaContext=createContext(null);function YuvaProvider({client,connect=!0,children}){return useEffect(()=>{if(!connect)return;return client.connect().catch(()=>{return}),()=>client.disconnect()},[client,connect]),createElement(YuvaContext.Provider,{value:client},children)}function useYuva(){let client=useContext(YuvaContext);if(!client)throw Error("Yuva: wrap your components in <YuvaProvider client={...}>");return client}var time=(value)=>Date.parse(value),byCreated=(a,b)=>time(a.created_at)-time(b.created_at),byActivity=(a,b)=>time(b.last_message_at??b.created_at)-time(a.last_message_at??a.created_at),initial={items:[],loading:!0,error:null};function useConversations(){let client=useYuva(),[state,setState]=useState(initial),cursor=useRef(void 0),current=useRef(state);useEffect(()=>{current.current=state});let load=useCallback(async(more)=>{setState((s)=>({...s,loading:!0}));try{let page=await client.listConversations({limit:50,cursor:more?cursor.current:void 0});cursor.current=page.next_cursor,setState((s)=>{let items=new Map((more?s.items:[]).map((c)=>[c.id,c]));for(let conversation of page.items)items.set(conversation.id,conversation);return{items:[...items.values()].sort(byActivity),cursor:page.next_cursor,loading:!1,error:null}})}catch(error){setState((s)=>({...s,loading:!1,error}))}},[client]);return useEffect(()=>{load(!1);let offSession=client.on("session",({renewed})=>void(renewed&&load(!1))),offEvent=client.on("event",(message)=>{if(message.type==="resync_required")return void load(!1);if(message.type==="conversation.created")setState((s)=>s.items.some((c)=>c.id===message.data.id)?s:{...s,items:[message.data,...s.items].sort(byActivity)});else if(message.type==="conversation.updated")setState((s)=>({...s,items:s.items.map((c)=>c.id===message.conversation_id?{...c,status:message.data.status}:c)}));else if(message.type==="message.created"){let m=message.data;if(!current.current.items.some((c)=>c.id===m.conversation_id))return void load(!1);setState((s)=>{let items=s.items.map((c)=>c.id===m.conversation_id?{...c,last_message:{id:m.id,author_type:m.author.type,text:m.body.slice(0,140),created_at:m.created_at},last_message_at:m.created_at,unread:c.unread||m.author.type!=="contact"}:c);return{...s,items:items.sort(byActivity)}})}});return()=>{offSession(),offEvent()}},[client,load]),{conversations:state.items,loading:state.loading,error:state.error,hasMore:!!state.cursor,loadMore:()=>load(!0),reload:()=>load(!1)}}function useMessages(conversationId){let client=useYuva(),[state,setState]=useState(initial),cursor=useRef(void 0),upsert=useCallback((message)=>{setState((s)=>{let items=s.items.filter((m)=>m.id!==message.id&&(!message.client_id||m.client_id!==message.client_id));return{...s,items:[...items,message].sort(byCreated)}})},[]),load=useCallback(async(older)=>{if(!conversationId){cursor.current=void 0,setState({items:[],loading:!1,error:null});return}if(older&&!cursor.current)return;setState((s)=>({...s,loading:!0}));try{let page=await client.listMessages(conversationId,{order:"desc",limit:30,cursor:older?cursor.current:void 0});cursor.current=page.next_cursor,setState((s)=>{let items=new Map((older?s.items:[]).map((m)=>[m.id,m]));for(let message of page.items)items.set(message.id,message);return{items:[...items.values()].sort(byCreated),cursor:page.next_cursor,loading:!1,error:null}})}catch(error){setState((s)=>({...s,loading:!1,error}))}},[client,conversationId]);return useEffect(()=>{if(load(!1),!conversationId)return;let offSession=client.on("session",({renewed})=>void(renewed&&load(!1))),offEvent=client.on("event",(message)=>{if(message.type==="resync_required")load(!1);else if((message.type==="message.created"||message.type==="message.updated")&&message.data.conversation_id===conversationId)upsert(message.data)});return()=>{offSession(),offEvent()}},[client,conversationId,load,upsert]),{messages:state.items,loading:state.loading,error:state.error,hasMore:!!state.cursor,loadOlder:()=>load(!0),async send(input){if(!conversationId)throw Error("Yuva: no conversation; start one with client.startConversation()");let message=await client.sendMessage(conversationId,typeof input==="string"?{body:input}:input);return upsert(message),message},async markRead(){if(conversationId)await client.markRead(conversationId)}}}function useYuvaElement(tag,load,props,extra,handlers){let[element,setElement]=useState(null),latest=useRef(handlers),loader=useRef(load);useEffect(()=>{latest.current=handlers});let{channel,server,locale,dir,identityToken,className,style}=props;useEffect(()=>{loader.current()},[]);let attributes=JSON.stringify({server,locale,dir,...extra,"identity-token":typeof identityToken==="string"?identityToken:void 0,channel});useEffect(()=>{if(!element)return;for(let[name,value]of Object.entries(JSON.parse(attributes)))if(value)element.setAttribute(name,value);else element.removeAttribute(name)},[element,attributes]),useEffect(()=>{if(!element||typeof identityToken!=="function")return;let current=!0;return customElements.whenDefined(tag).then(()=>{if(current)element.setIdentityToken(identityToken)}),()=>{current=!1}},[element,tag,identityToken]);let events=Object.keys(handlers).join(" ");return useEffect(()=>{if(!element)return;let listeners=events.split(" ").map((type)=>{let listener=(event)=>latest.current[type]?.(event.detail);return element.addEventListener(type,listener),()=>element.removeEventListener(type,listener)});return()=>listeners.forEach((off)=>off())},[element,events]),createElement(tag,{ref:setElement,className,style})}var loadDocs=()=>import("./docs.js");function YuvaPageFeedback({onRating,onFeedback,...props}){return useYuvaElement("yuva-page-feedback",loadDocs,props,{page:props.page,"page-title":props.pageTitle},{"yuva-rating":onRating,"yuva-feedback":onFeedback})}function YuvaDiscussions({onDiscussion,onPost,onReader,...props}){return useYuvaElement("yuva-discussions",loadDocs,props,{page:props.page,"page-title":props.pageTitle},{"yuva-discussion":onDiscussion,"yuva-post":onPost,"yuva-reader":onReader})}function YuvaSubscribe({onSubscribe,onError,...props}){return useYuvaElement("yuva-subscribe",()=>import("./subscribe.js"),props,{lists:props.lists?.join(","),layout:props.layout,name:props.name,"button-text":props.buttonText,consent:props.consent,"privacy-url":props.privacyUrl},{"yuva-subscribe":onSubscribe,"yuva-subscribe-error":onError})}function YuvaAnalytics({server,publicKey:key,hash,consent,manual,outbound,files,chat}){return useEffect(()=>{let instance,mounted=!0;return import("./analytics.js").then(({createAnalytics})=>{if(!mounted)return;instance=createAnalytics({server,key,hash,consent,manual,outbound,files,chat}),attachAnalytics(instance)}),()=>{mounted=!1,instance?.destroy(),attachAnalytics(void 0)}},[server,key,hash,consent,manual,outbound,files,chat]),null}function useYuvaAnalytics(){return analytics}export{YuvaAnalytics,YuvaDiscussions,YuvaPageFeedback,YuvaProvider,YuvaSubscribe,useConversations,useMessages,useYuva,useYuvaAnalytics};
@@ -30,4 +30,4 @@ legend{padding:0;margin-block-end:4px;font-weight:600}
30
30
  .error{color:var(--d)}
31
31
  .trap{position:absolute;inset-inline-start:-1e4px;inline-size:1px;overflow:hidden}
32
32
  @media (max-width:480px){input{font-size:16px}}
33
- `;class YuvaSubscribeElement extends Base{static observedAttributes=["channel","server","locale","dir","lists","layout","name","button-text","consent","privacy-url","identity-token"];static loadClient=null;#root;#messages=messages;#connected=!1;#generation=0;#phase="loading";#refused=!1;#inbox=null;#offered=[];#chosen=new Set;#token="";#tokenAt=0;#confirmation=!1;#error="";#emailError="";#nameError="";#consentError="";#identity=null;#client=null;#busy=new Set;#email=el("input");#name=el("input");#trap=el("input");#consent=el("input");#status=el("p");constructor(){super();this.#root=this.attachShadow({mode:"open"}),this.#email.type="email",this.#email.autocomplete="email",this.#email.required=!0,this.#email.maxLength=320,this.#email.id="email",this.#name.autocomplete="name",this.#name.maxLength=200,this.#name.id="name",this.#trap.name="website",this.#trap.tabIndex=-1,this.#trap.autocomplete="off",this.#consent.type="checkbox",this.#consent.id="consent",this.#consent.addEventListener("change",()=>{this.#consentError="",this.#render()});for(let input of[this.#email,this.#name])input.setAttribute("part","field"),input.dir="auto";this.#status.setAttribute("part","status"),this.#status.setAttribute("role","status"),this.#status.setAttribute("aria-live","polite")}get channel(){return this.getAttribute("channel")}set channel(value){this.#attribute("channel",value)}get server(){return(this.getAttribute("server")||(scriptSrc?new URL(scriptSrc).origin:location.origin)).replace(/\/+$/,"")}set server(value){this.#attribute("server",value)}get locale(){return localeIn(catalogs,[this.getAttribute("locale"),navigator.language])}set locale(value){this.#attribute("locale",value)}get lists(){return this.#offered.map((item)=>item.list)}setIdentityToken(source){if(this.#identity=source,this.#connected)this.#load()}connectedCallback(){this.#connected=!0,this.#load()}disconnectedCallback(){this.#connected=!1}attributeChangedCallback(name,previous,value){if(!this.#connected||previous===value)return;if(["channel","server","lists","identity-token"].includes(name))return void this.#load();this.#render()}#attribute(name,value){if(value===null||value===void 0||value==="")this.removeAttribute(name);else this.setAttribute(name,value)}#t(descriptor){return translate(this.#messages,descriptor,messages)}get#identified(){return!!this.#identity||this.hasAttribute("identity-token")}async#identityToken(){return this.#identity?await this.#identity()??null:this.getAttribute("identity-token")}#wanted(lists){let ids=(this.getAttribute("lists")??"").split(",").map((id)=>id.trim()).filter((id)=>id&&id!=="all");if(ids.length===0)return lists;let found=ids.map((id)=>lists.find((list)=>list.id===id)).filter((list)=>!!list);if(found.length<ids.length)console.warn(`Yuva: some lists in "${ids.join(",")}" are not public lists`);return found}async#load(){let generation=++this.#generation,channel=this.channel;if(this.#refused=!1,this.#phase="loading",this.#offered=[],this.#error="",this.#client=null,this.#render(),!channel)return;let server=this.server;try{let inbox=call(fetcher,server,`/client/v1/channels/${encodeURIComponent(channel)}`),offered=null;if(this.#identified&&YuvaSubscribeElement.loadClient&&await this.#identityToken()){let{createYuvaClient}=await YuvaSubscribeElement.loadClient(),client=createYuvaClient({server,channel,identityToken:()=>this.#identityToken()});try{let{items}=await client.subscriptions(),wanted=new Set(this.#wanted(items.map((item)=>item.list)));offered=items.filter((item)=>wanted.has(item.list)),this.#client=client}catch(error){if(!(error instanceof ApiError2)||error.code!=="identity_required")throw error}}if(!offered){let{lists,form_token}=await mailingLists(fetcher,server,channel);offered=this.#wanted(lists).map((list)=>({list})),this.#token=form_token,this.#tokenAt=Date.now()}if(this.#inbox=await inbox,generation!==this.#generation)return;if(this.#offered=offered,this.#chosen=new Set(offered.length===1?[offered[0].list.id]:[]),this.#phase="idle",offered.length===0)console.warn(`Yuva: channel ${channel} has no public mailing lists to offer`)}catch(error){if(generation!==this.#generation)return;if(this.#refusal(error))return;this.#phase="idle",this.#error=this.#errorText(error)}this.#render()}#refusal(error){let refused=error instanceof ApiError2&&(error.status===404||error.code==="origin_not_allowed"||error.code==="page_origin");if(refused)this.#refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown, offers no such list or does not allow ${location.origin}`),this.#render();return refused}#errorText(error){let code=error instanceof ApiError2?error.code:"";if(code==="rate_limited")return this.#t({id:"tzsBOP"});if(code==="network")return this.#t({id:"GQVIIl"});if(code==="no_email")return this.#t({id:"eku1-t"});return this.#t({id:"jWgNnM"})}#emit(type,detail){this.dispatchEvent(new CustomEvent(type,{detail,bubbles:!0,composed:!0}))}#failed(error){this.#emit("yuva-subscribe-error",{code:error instanceof ApiError2?error.code:"error"})}consentText(lists=this.#selected()){let custom=this.getAttribute("consent")?.trim();if(custom)return custom;let names=(lists.length?lists:this.lists).map((list)=>list.name),list=new Intl.ListFormat(this.locale,{type:"conjunction"}).format(names),inbox=this.#inbox?.name??"";return this.#t({id:"dMJfG5",values:{list,inbox}})}#selected(){return this.lists.filter((list)=>this.#chosen.has(list.id))}async#submit(){if(this.#phase!=="idle"||!this.channel)return;let lists=this.#selected(),email=this.#email.value.trim(),name=this.#name.value.trim(),asksName=this.getAttribute("name");if(this.#error=lists.length===0?this.#t({id:"-g5O6h"}):"",this.#emailError=this.#email.checkValidity()&&email?"":this.#t({id:"E_qvzP"}),this.#nameError=asksName==="required"&&!name?this.#t({id:"E_LjOR"}):"",this.#consentError=this.#consent.checked?"":this.#t({id:"lDEbTy"}),this.#error||this.#emailError||this.#nameError||this.#consentError){this.#render();let invalid=[this.#emailError&&this.#email,this.#nameError&&this.#name,this.#consentError&&this.#consent];for(let input of invalid)if(input)return input.focus();return}let channel=this.channel,generation=this.#generation,consent_text=this.consentText(lists);this.#phase="submitting",this.#render();let send=async(retry)=>{let wait=this.#tokenAt+tokenMinimumAge-Date.now();if(wait>0)await new Promise((resolve)=>setTimeout(resolve,wait));try{let{confirmation}=await createSubscription(fetcher,this.server,channel,{email,name:asksName==="optional"||asksName==="required"?name||void 0:void 0,list_ids:lists.map((list)=>list.id),locale:this.locale,page_url:location.href.split("#")[0].slice(0,2000),consent_text,form_token:this.#token,website:this.#trap.value||void 0});return this.#confirmation=confirmation,!0}catch(error){if(retry&&error instanceof ApiError2&&error.code==="form_token"){let fresh=await mailingLists(fetcher,this.server,channel);return this.#token=fresh.form_token,this.#tokenAt=Date.now(),send(!1)}throw error}};try{await send(!0)}catch(error){if(generation!==this.#generation)return;if(this.#failed(error),this.#phase="idle",this.#refusal(error))return;if(error instanceof ApiError2&&error.code==="invalid_email")return this.#emailError=this.#t({id:"E_qvzP"}),this.#render(),this.#email.focus();return this.#error=this.#errorText(error),this.#render()}if(generation!==this.#generation)return;this.#phase="done",this.#emit("yuva-subscribe",{lists:lists.map((list)=>list.id),confirmation:this.#confirmation}),this.#render()}async#toggle(item,on){let client=this.#client;if(!client||this.#busy.has(item.list.id))return;this.#busy.add(item.list.id),this.#error="",this.#render();try{if(on){let{state}=await client.subscribeList(item.list.id,{consent_text:this.consentText([item.list]),page_url:location.href.split("#")[0].slice(0,2000)});item.state=state,this.#emit("yuva-subscribe",{lists:[item.list.id],confirmation:state==="pending"})}else await client.unsubscribeList(item.list.id),item.state="unsubscribed"}catch(error){this.#failed(error),this.#error=this.#errorText(error)}if(this.#busy.delete(item.list.id),client===this.#client)this.#render()}#errorFor(input,text){if(input.setAttribute("aria-invalid",String(!!text)),!text)return input.removeAttribute("aria-describedby"),null;let id=`${input.id}-error`;input.setAttribute("aria-describedby",id);let error=el("p","error",text);return error.id=id,error}#check(text,checked,onChange,key){let label=el("label","check"),box=el("input");box.type="checkbox",box.checked=checked,box.dataset.key=key,box.addEventListener("change",()=>onChange(box.checked));let body=el("span","text");return body.append(...text),label.append(box,body),label}#lists(identity){if(!identity&&this.#offered.length<2)return null;let group=el("fieldset");group.append(el("legend","",this.#t({id:"h16FyT"})));for(let item of this.#offered){let text=[el("span","",item.list.name)];if(item.list.description)text.push(el("span","muted",item.list.description));if(identity){if(text.push(el("span","muted consent",this.consentText([item.list]))),item.state==="pending")text.push(el("span","muted",this.#t({id:"x6dU53"})))}let on=identity?item.state==="subscribed"||item.state==="pending":this.#chosen.has(item.list.id),label=this.#check(text,on,(checked)=>{if(identity)return void this.#toggle(item,checked);if(checked)this.#chosen.add(item.list.id);else this.#chosen.delete(item.list.id);this.#error="",this.#render()},item.list.id),box=label.querySelector("input");if(identity)box.setAttribute("role","switch"),box.setAttribute("aria-checked",String(box.checked)),box.addEventListener("keydown",(event)=>{if(event.key!=="Enter")return;event.preventDefault(),box.click()}),box.disabled=this.#busy.has(item.list.id);else box.disabled=this.#phase==="submitting";group.append(label)}return group}#form(){let form=el("form",this.getAttribute("layout")==="inline"?"inline":"");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#submit()});let busy=this.#phase==="submitting",lists=this.#lists(!1);if(lists)form.append(lists);let row=el("div","row"),errors=[],asksName=this.getAttribute("name");if(asksName==="optional"||asksName==="required"){this.#name.placeholder=asksName==="required"?this.#t({id:"q8yluz"}):this.#t({id:"YnOaHp"}),this.#name.setAttribute("aria-label",this.#name.placeholder),this.#name.required=asksName==="required",this.#name.disabled=busy,row.append(this.#name);let error=this.#errorFor(this.#name,this.#nameError);if(error)errors.push(error)}this.#email.placeholder=this.#t({id:"XJURKP"}),this.#email.setAttribute("aria-label",this.#email.placeholder),this.#email.disabled=busy,row.append(this.#email);let emailError=this.#errorFor(this.#email,this.#emailError);if(emailError)errors.push(emailError);let button=el("button","",busy?this.#t({id:"1w51t9"}):this.getAttribute("button-text")||this.#t({id:"EDl9kS"}));button.type="submit",button.disabled=busy,button.setAttribute("part","button"),row.append(button);let trap=el("div","trap");trap.setAttribute("aria-hidden","true"),trap.append(this.#trap);let consentText=el("span","",this.consentText()),consent=el("label","check consent");consent.setAttribute("part","consent"),this.#consent.disabled=busy;let body=el("span");body.append(consentText);let privacy=this.getAttribute("privacy-url");if(privacy&&/^https?:\/\//i.test(privacy)){let link=el("a","",this.#t({id:"ScJ9fj"}));link.href=privacy,link.target="_blank",link.rel="noopener noreferrer",body.append(" ",link)}consent.append(this.#consent,body);let consentError=this.#errorFor(this.#consent,this.#consentError);if(form.append(row,...errors,consent),consentError)form.append(consentError);return form.append(trap),form}#render(){if(this.#refused||!this.channel||this.#phase!=="loading"&&this.#offered.length===0&&!this.#error){this.#root.replaceChildren();return}let locale=this.locale;this.#messages=catalogs[locale]??messages;let dir=this.getAttribute("dir"),wrapper=el("div","frame");wrapper.dir=dir==="rtl"||dir==="ltr"?dir:directionOf(locale),wrapper.lang=locale;let brand=this.#inbox?.chat.launcher_color??this.#inbox?.branding.color;if(brand&&/^#[0-9a-f]{6}$/i.test(brand))wrapper.style.setProperty("--brand",brand),wrapper.style.setProperty("--brand-on",contrastOn(brand));let status="";if(this.#phase==="done")status=this.#confirmation?this.#t({id:"y3k2zM"}):this.#t({id:"rgySXy"});if(this.#status.textContent=status,this.#phase==="idle"||this.#phase==="submitting"){let content=this.#client?this.#lists(!0):this.#form();if(content)wrapper.append(content)}if(wrapper.append(this.#status),this.#error){let error=el("p","error",this.#error);error.setAttribute("role","alert"),wrapper.append(error)}let focusedKey,focused=null;try{focused=this.#root.activeElement}catch{}if(focused instanceof HTMLInputElement)focusedKey=focused.dataset.key;let style=el("style");style.textContent=styles,this.#root.replaceChildren(style,wrapper);let again=focusedKey?this.#root.querySelector(`[data-key="${focusedKey}"]`):focused;if(again instanceof HTMLElement&&again.isConnected)again.focus({preventScroll:!0})}}function defineSubscribe(){if(typeof customElements>"u")return;if(!customElements.get("yuva-subscribe"))customElements.define("yuva-subscribe",YuvaSubscribeElement)}YuvaSubscribeElement.loadClient=()=>import("./client-9wy8zy77.js");defineSubscribe();export{YuvaSubscribeElement,defineSubscribe};
33
+ `;class YuvaSubscribeElement extends Base{static observedAttributes=["channel","server","locale","dir","lists","layout","name","button-text","consent","privacy-url","identity-token"];static loadClient=null;#root;#messages=messages;#connected=!1;#generation=0;#phase="loading";#refused=!1;#inbox=null;#offered=[];#chosen=new Set;#token="";#tokenAt=0;#confirmation=!1;#error="";#emailError="";#nameError="";#consentError="";#identity=null;#client=null;#busy=new Set;#email=el("input");#name=el("input");#trap=el("input");#consent=el("input");#status=el("p");constructor(){super();this.#root=this.attachShadow({mode:"open"}),this.#email.type="email",this.#email.autocomplete="email",this.#email.required=!0,this.#email.maxLength=320,this.#email.id="email",this.#name.autocomplete="name",this.#name.maxLength=200,this.#name.id="name",this.#trap.name="website",this.#trap.tabIndex=-1,this.#trap.autocomplete="off",this.#consent.type="checkbox",this.#consent.id="consent",this.#consent.addEventListener("change",()=>{this.#consentError="",this.#render()});for(let input of[this.#email,this.#name])input.setAttribute("part","field"),input.dir="auto";this.#status.setAttribute("part","status"),this.#status.setAttribute("role","status"),this.#status.setAttribute("aria-live","polite")}get channel(){return this.getAttribute("channel")}set channel(value){this.#attribute("channel",value)}get server(){return(this.getAttribute("server")||(scriptSrc?new URL(scriptSrc).origin:location.origin)).replace(/\/+$/,"")}set server(value){this.#attribute("server",value)}get locale(){return localeIn(catalogs,[this.getAttribute("locale"),navigator.language])}set locale(value){this.#attribute("locale",value)}get lists(){return this.#offered.map((item)=>item.list)}setIdentityToken(source){if(this.#identity=source,this.#connected)this.#load()}connectedCallback(){this.#connected=!0,this.#load()}disconnectedCallback(){this.#connected=!1}attributeChangedCallback(name,previous,value){if(!this.#connected||previous===value)return;if(["channel","server","lists","identity-token"].includes(name))return void this.#load();this.#render()}#attribute(name,value){if(value===null||value===void 0||value==="")this.removeAttribute(name);else this.setAttribute(name,value)}#t(descriptor){return translate(this.#messages,descriptor,messages)}get#identified(){return!!this.#identity||this.hasAttribute("identity-token")}async#identityToken(){return this.#identity?await this.#identity()??null:this.getAttribute("identity-token")}#wanted(lists){let ids=(this.getAttribute("lists")??"").split(",").map((id)=>id.trim()).filter((id)=>id&&id!=="all");if(ids.length===0)return lists;let found=ids.map((id)=>lists.find((list)=>list.id===id)).filter((list)=>!!list);if(found.length<ids.length)console.warn(`Yuva: some lists in "${ids.join(",")}" are not public lists`);return found}async#load(){let generation=++this.#generation,channel=this.channel;if(this.#refused=!1,this.#phase="loading",this.#offered=[],this.#error="",this.#client=null,this.#render(),!channel)return;let server=this.server;try{let inbox=call(fetcher,server,`/client/v1/channels/${encodeURIComponent(channel)}`),offered=null;if(this.#identified&&YuvaSubscribeElement.loadClient&&await this.#identityToken()){let{createYuvaClient}=await YuvaSubscribeElement.loadClient(),client=createYuvaClient({server,channel,identityToken:()=>this.#identityToken()});try{let{items}=await client.subscriptions(),wanted=new Set(this.#wanted(items.map((item)=>item.list)));offered=items.filter((item)=>wanted.has(item.list)),this.#client=client}catch(error){if(!(error instanceof ApiError2)||error.code!=="identity_required")throw error}}if(!offered){let{lists,form_token}=await mailingLists(fetcher,server,channel);offered=this.#wanted(lists).map((list)=>({list})),this.#token=form_token,this.#tokenAt=Date.now()}if(this.#inbox=await inbox,generation!==this.#generation)return;if(this.#offered=offered,this.#chosen=new Set(offered.length===1?[offered[0].list.id]:[]),this.#phase="idle",offered.length===0)console.warn(`Yuva: channel ${channel} has no public mailing lists to offer`)}catch(error){if(generation!==this.#generation)return;if(this.#refusal(error))return;this.#phase="idle",this.#error=this.#errorText(error)}this.#render()}#refusal(error){let refused=error instanceof ApiError2&&(error.status===404||error.code==="origin_not_allowed"||error.code==="page_origin");if(refused)this.#refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown, offers no such list or does not allow ${location.origin}`),this.#render();return refused}#errorText(error){let code=error instanceof ApiError2?error.code:"";if(code==="rate_limited")return this.#t({id:"tzsBOP"});if(code==="network")return this.#t({id:"GQVIIl"});if(code==="no_email")return this.#t({id:"eku1-t"});return this.#t({id:"jWgNnM"})}#emit(type,detail){this.dispatchEvent(new CustomEvent(type,{detail,bubbles:!0,composed:!0}))}#failed(error){this.#emit("yuva-subscribe-error",{code:error instanceof ApiError2?error.code:"error"})}consentText(lists=this.#selected()){let custom=this.getAttribute("consent")?.trim();if(custom)return custom;let names=(lists.length?lists:this.lists).map((list)=>list.name),list=new Intl.ListFormat(this.locale,{type:"conjunction"}).format(names),inbox=this.#inbox?.name??"";return this.#t({id:"dMJfG5",values:{list,inbox}})}#selected(){return this.lists.filter((list)=>this.#chosen.has(list.id))}async#submit(){if(this.#phase!=="idle"||!this.channel)return;let lists=this.#selected(),email=this.#email.value.trim(),name=this.#name.value.trim(),asksName=this.getAttribute("name");if(this.#error=lists.length===0?this.#t({id:"-g5O6h"}):"",this.#emailError=this.#email.checkValidity()&&email?"":this.#t({id:"E_qvzP"}),this.#nameError=asksName==="required"&&!name?this.#t({id:"E_LjOR"}):"",this.#consentError=this.#consent.checked?"":this.#t({id:"lDEbTy"}),this.#error||this.#emailError||this.#nameError||this.#consentError){this.#render();let invalid=[this.#emailError&&this.#email,this.#nameError&&this.#name,this.#consentError&&this.#consent];for(let input of invalid)if(input)return input.focus();return}let channel=this.channel,generation=this.#generation,consent_text=this.consentText(lists);this.#phase="submitting",this.#render();let send=async(retry)=>{let wait=this.#tokenAt+tokenMinimumAge-Date.now();if(wait>0)await new Promise((resolve)=>setTimeout(resolve,wait));try{let{confirmation}=await createSubscription(fetcher,this.server,channel,{email,name:asksName==="optional"||asksName==="required"?name||void 0:void 0,list_ids:lists.map((list)=>list.id),locale:this.locale,page_url:location.href.split("#")[0].slice(0,2000),consent_text,form_token:this.#token,website:this.#trap.value||void 0});return this.#confirmation=confirmation,!0}catch(error){if(retry&&error instanceof ApiError2&&error.code==="form_token"){let fresh=await mailingLists(fetcher,this.server,channel);return this.#token=fresh.form_token,this.#tokenAt=Date.now(),send(!1)}throw error}};try{await send(!0)}catch(error){if(generation!==this.#generation)return;if(this.#failed(error),this.#phase="idle",this.#refusal(error))return;if(error instanceof ApiError2&&error.code==="invalid_email")return this.#emailError=this.#t({id:"E_qvzP"}),this.#render(),this.#email.focus();return this.#error=this.#errorText(error),this.#render()}if(generation!==this.#generation)return;this.#phase="done",this.#emit("yuva-subscribe",{lists:lists.map((list)=>list.id),confirmation:this.#confirmation}),this.#render()}async#toggle(item,on){let client=this.#client;if(!client||this.#busy.has(item.list.id))return;this.#busy.add(item.list.id),this.#error="",this.#render();try{if(on){let{state}=await client.subscribeList(item.list.id,{consent_text:this.consentText([item.list]),page_url:location.href.split("#")[0].slice(0,2000)});item.state=state,this.#emit("yuva-subscribe",{lists:[item.list.id],confirmation:state==="pending"})}else await client.unsubscribeList(item.list.id),item.state="unsubscribed"}catch(error){this.#failed(error),this.#error=this.#errorText(error)}if(this.#busy.delete(item.list.id),client===this.#client)this.#render()}#errorFor(input,text){if(input.setAttribute("aria-invalid",String(!!text)),!text)return input.removeAttribute("aria-describedby"),null;let id=`${input.id}-error`;input.setAttribute("aria-describedby",id);let error=el("p","error",text);return error.id=id,error}#check(text,checked,onChange,key){let label=el("label","check"),box=el("input");box.type="checkbox",box.checked=checked,box.dataset.key=key,box.addEventListener("change",()=>onChange(box.checked));let body=el("span","text");return body.append(...text),label.append(box,body),label}#lists(identity){if(!identity&&this.#offered.length<2)return null;let group=el("fieldset");group.append(el("legend","",this.#t({id:"h16FyT"})));for(let item of this.#offered){let text=[el("span","",item.list.name)];if(item.list.description)text.push(el("span","muted",item.list.description));if(identity){if(text.push(el("span","muted consent",this.consentText([item.list]))),item.state==="pending")text.push(el("span","muted",this.#t({id:"x6dU53"})))}let on=identity?item.state==="subscribed"||item.state==="pending":this.#chosen.has(item.list.id),label=this.#check(text,on,(checked)=>{if(identity)return void this.#toggle(item,checked);if(checked)this.#chosen.add(item.list.id);else this.#chosen.delete(item.list.id);this.#error="",this.#render()},item.list.id),box=label.querySelector("input");if(identity)box.setAttribute("role","switch"),box.setAttribute("aria-checked",String(box.checked)),box.addEventListener("keydown",(event)=>{if(event.key!=="Enter")return;event.preventDefault(),box.click()}),box.disabled=this.#busy.has(item.list.id);else box.disabled=this.#phase==="submitting";group.append(label)}return group}#form(){let form=el("form",this.getAttribute("layout")==="inline"?"inline":"");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#submit()});let busy=this.#phase==="submitting",lists=this.#lists(!1);if(lists)form.append(lists);let row=el("div","row"),errors=[],asksName=this.getAttribute("name");if(asksName==="optional"||asksName==="required"){this.#name.placeholder=asksName==="required"?this.#t({id:"q8yluz"}):this.#t({id:"YnOaHp"}),this.#name.setAttribute("aria-label",this.#name.placeholder),this.#name.required=asksName==="required",this.#name.disabled=busy,row.append(this.#name);let error=this.#errorFor(this.#name,this.#nameError);if(error)errors.push(error)}this.#email.placeholder=this.#t({id:"XJURKP"}),this.#email.setAttribute("aria-label",this.#email.placeholder),this.#email.disabled=busy,row.append(this.#email);let emailError=this.#errorFor(this.#email,this.#emailError);if(emailError)errors.push(emailError);let button=el("button","",busy?this.#t({id:"1w51t9"}):this.getAttribute("button-text")||this.#t({id:"EDl9kS"}));button.type="submit",button.disabled=busy,button.setAttribute("part","button"),row.append(button);let trap=el("div","trap");trap.setAttribute("aria-hidden","true"),trap.append(this.#trap);let consentText=el("span","",this.consentText()),consent=el("label","check consent");consent.setAttribute("part","consent"),this.#consent.disabled=busy;let body=el("span");body.append(consentText);let privacy=this.getAttribute("privacy-url");if(privacy&&/^https?:\/\//i.test(privacy)){let link=el("a","",this.#t({id:"ScJ9fj"}));link.href=privacy,link.target="_blank",link.rel="noopener noreferrer",body.append(" ",link)}consent.append(this.#consent,body);let consentError=this.#errorFor(this.#consent,this.#consentError);if(form.append(row,...errors,consent),consentError)form.append(consentError);return form.append(trap),form}#render(){if(this.#refused||!this.channel||this.#phase!=="loading"&&this.#offered.length===0&&!this.#error){this.#root.replaceChildren();return}let locale=this.locale;this.#messages=catalogs[locale]??messages;let dir=this.getAttribute("dir"),wrapper=el("div","frame");wrapper.dir=dir==="rtl"||dir==="ltr"?dir:directionOf(locale),wrapper.lang=locale;let brand=this.#inbox?.chat.launcher_color??this.#inbox?.branding.color;if(brand&&/^#[0-9a-f]{6}$/i.test(brand))wrapper.style.setProperty("--brand",brand),wrapper.style.setProperty("--brand-on",contrastOn(brand));let status="";if(this.#phase==="done")status=this.#confirmation?this.#t({id:"y3k2zM"}):this.#t({id:"rgySXy"});if(this.#status.textContent=status,this.#phase==="idle"||this.#phase==="submitting"){let content=this.#client?this.#lists(!0):this.#form();if(content)wrapper.append(content)}if(wrapper.append(this.#status),this.#error){let error=el("p","error",this.#error);error.setAttribute("role","alert"),wrapper.append(error)}let focusedKey,focused=null;try{focused=this.#root.activeElement}catch{}if(focused instanceof HTMLInputElement)focusedKey=focused.dataset.key;let style=el("style");style.textContent=styles,this.#root.replaceChildren(style,wrapper);let again=focusedKey?this.#root.querySelector(`[data-key="${focusedKey}"]`):focused;if(again instanceof HTMLElement&&again.isConnected)again.focus({preventScroll:!0})}}function defineSubscribe(){if(typeof customElements>"u")return;if(!customElements.get("yuva-subscribe"))customElements.define("yuva-subscribe",YuvaSubscribeElement)}YuvaSubscribeElement.loadClient=()=>import("./client-ebw9d6ms.js");defineSubscribe();export{YuvaSubscribeElement,defineSubscribe};
@@ -1,4 +1,4 @@
1
- import{randomId2,createYuvaClient2}from"./index-geeh5h34.js";import{richText}from"./index-jdxce2se.js";import{ApiError2}from"./index-gk84nm8f.js";import{launcherOf,readStored,writeStored}from"./index-98r96a7e.js";import{setupI18n}from"@lingui/core";var messages=JSON.parse(`{"-HY5kX":["New conversation"],"-f5Tkb":["Bad"],"09Tv5j":["Reconnecting…"],"0XGLbP":["Your sign-in has expired. Reload the page and try again."],"1EICzz":["We're away right now"],"4TqZiz":["Could not send your rating. Try again."],"6Uau97":["Skip"],"6gRgw8":["Retry"],"6lGaum":["Seen"],"ASr-r0":["Show older conversations"],"Amai22":["Chat is not available right now."],"E_qvzP":["Enter a valid e-mail address."],"GQVIIl":["You seem to be offline."],"JkW3Ph":["This file type is not accepted."],"JlFcis":["Send"],"KDw4GX":["Try again"],"M62PBt":["Nobody is available right now. Leave your e-mail and we'll send the reply there too."],"N7m8E-":["Attach files"],"NBdIgR":["Comment"],"OEEQKT":["Good"],"Pwqkdw":["Loading…"],"PxYAul":["Typing…"],"RzWUUK":["Write a message…"],"S63MQu":["All conversations"],"SOk0EB":["Thanks for your feedback"],"Sad2tK":["Sending…"],"SdV5Cn":["Send us a message and we will reply here."],"UY1vmE":["Attachment"],"VggdQJ":["Usually replies in ",["duration"]],"XJURKP":["E-mail address"],"YyNOE7":["Conversation"],"ZxJcgC":["Could not save your e-mail address. Try again."],"axQ1h6":["Anything you'd like to add? (optional)"],"eOu9Px":["The file is too large."],"h69WC6":["Sent"],"iGNUZJ":["Thanks! We'll e-mail you at ",["known"]," if you're gone when we reply."],"meAa31":["No conversations yet"],"nhTADq":["We'll reply as soon as we can"],"njBr8W":["you@example.com"],"oXOSPE":["Online"],"t7TeQU":["Messages"],"tHaDPf":[["name"]," is typing…"],"tfDRzk":["Save"],"tzsBOP":["Too many attempts. Wait a moment and try again."],"uA8iBc":["How did we do?"],"upFvcp":["Not sent."],"w61W3L":["Remove ",["0"]],"xDAtGP":["Message"],"ydzYKJ":["You:"],"yz7wBu":["Close"],"zLzEI3":["Sign in to chat with us."]}`);var messages2=JSON.parse('{"-HY5kX":["Neue Unterhaltung"],"-f5Tkb":["Schlecht"],"09Tv5j":["Verbindung wird wiederhergestellt…"],"0XGLbP":["Ihre Anmeldung ist abgelaufen. Laden Sie die Seite neu und versuchen Sie es erneut."],"1EICzz":["Wir sind gerade nicht da"],"4TqZiz":["Ihre Bewertung konnte nicht gesendet werden. Versuchen Sie es erneut."],"6Uau97":["Überspringen"],"6gRgw8":["Erneut versuchen"],"6lGaum":["Gesehen"],"ASr-r0":["Ältere Unterhaltungen anzeigen"],"Amai22":["Der Chat ist gerade nicht verfügbar."],"E_qvzP":["Geben Sie eine gültige E-Mail-Adresse ein."],"GQVIIl":["Sie scheinen offline zu sein."],"JkW3Ph":["Dieser Dateityp wird nicht akzeptiert."],"JlFcis":["Senden"],"KDw4GX":["Erneut versuchen"],"M62PBt":["Gerade ist niemand erreichbar. Hinterlassen Sie Ihre E-Mail-Adresse, dann senden wir die Antwort auch dorthin."],"N7m8E-":["Dateien anhängen"],"NBdIgR":["Kommentar"],"OEEQKT":["Gut"],"Pwqkdw":["Wird geladen…"],"PxYAul":["Schreibt…"],"RzWUUK":["Nachricht schreiben…"],"S63MQu":["Alle Unterhaltungen"],"SOk0EB":["Danke für Ihr Feedback"],"Sad2tK":["Wird gesendet…"],"SdV5Cn":["Schreiben Sie uns, wir antworten hier."],"UY1vmE":["Anhang"],"VggdQJ":["Übliche Antwortzeit: ",["duration"]],"XJURKP":["E-Mail-Adresse"],"YyNOE7":["Unterhaltung"],"ZxJcgC":["Ihre E-Mail-Adresse konnte nicht gespeichert werden. Versuchen Sie es erneut."],"axQ1h6":["Möchten Sie noch etwas ergänzen? (optional)"],"eOu9Px":["Die Datei ist zu groß."],"h69WC6":["Gesendet"],"iGNUZJ":["Danke! Falls Sie nicht mehr da sind, wenn wir antworten, schreiben wir Ihnen an ",["known"],"."],"meAa31":["Noch keine Unterhaltungen"],"nhTADq":["Wir antworten so schnell wie möglich"],"njBr8W":["sie@beispiel.de"],"oXOSPE":["Online"],"t7TeQU":["Nachrichten"],"tHaDPf":[["name"]," schreibt…"],"tfDRzk":["Speichern"],"tzsBOP":["Zu viele Versuche. Warten Sie einen Moment und versuchen Sie es erneut."],"uA8iBc":["Wie zufrieden waren Sie?"],"upFvcp":["Nicht gesendet."],"w61W3L":[["0"]," entfernen"],"xDAtGP":["Nachricht"],"ydzYKJ":["Sie:"],"yz7wBu":["Schließen"],"zLzEI3":["Melden Sie sich an, um mit uns zu chatten."]}');var messages3=JSON.parse('{"-HY5kX":["Yeni konuşma"],"-f5Tkb":["Kötü"],"09Tv5j":["Yeniden bağlanıyor…"],"0XGLbP":["Oturumunuzun süresi doldu. Sayfayı yenileyip tekrar deneyin."],"1EICzz":["Şu anda uzaktayız"],"4TqZiz":["Değerlendirmeniz gönderilemedi. Tekrar deneyin."],"6Uau97":["Geç"],"6gRgw8":["Tekrar dene"],"6lGaum":["Görüldü"],"ASr-r0":["Eski konuşmaları göster"],"Amai22":["Sohbet şu anda kullanılamıyor."],"E_qvzP":["Geçerli bir e-posta adresi girin."],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"JkW3Ph":["Bu dosya türü kabul edilmiyor."],"JlFcis":["Gönder"],"KDw4GX":["Tekrar dene"],"M62PBt":["Şu anda müsait kimse yok. E-posta adresinizi bırakın, yanıtı oraya da gönderelim."],"N7m8E-":["Dosya ekle"],"NBdIgR":["Yorum"],"OEEQKT":["İyi"],"Pwqkdw":["Yükleniyor…"],"PxYAul":["Yazıyor…"],"RzWUUK":["Bir mesaj yazın…"],"S63MQu":["Tüm konuşmalar"],"SOk0EB":["Geri bildiriminiz için teşekkürler"],"Sad2tK":["Gönderiliyor…"],"SdV5Cn":["Bize bir mesaj gönderin, yanıtımız burada görünecek."],"UY1vmE":["Ek"],"VggdQJ":["Genellikle ",["duration"]," içinde yanıt verir"],"XJURKP":["E-posta adresi"],"YyNOE7":["Konuşma"],"ZxJcgC":["E-posta adresiniz kaydedilemedi. Tekrar deneyin."],"axQ1h6":["Eklemek istediğiniz bir şey var mı? (isteğe bağlı)"],"eOu9Px":["Dosya çok büyük."],"h69WC6":["Gönderildi"],"iGNUZJ":["Teşekkürler! Yanıtladığımızda burada değilseniz ",["known"]," adresine e-posta göndereceğiz."],"meAa31":["Henüz konuşma yok"],"nhTADq":["En kısa sürede yanıt vereceğiz"],"njBr8W":["siz@ornek.com"],"oXOSPE":["Çevrimiçi"],"t7TeQU":["Mesajlar"],"tHaDPf":[["name"]," yazıyor…"],"tfDRzk":["Kaydet"],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"uA8iBc":["Nasıldık?"],"upFvcp":["Gönderilemedi."],"w61W3L":[["0"]," kaldır"],"xDAtGP":["Mesaj"],"ydzYKJ":["Siz:"],"yz7wBu":["Kapat"],"zLzEI3":["Bizimle sohbet etmek için giriş yapın."]}');var styles=`
1
+ import{randomId2,createYuvaClient2}from"./index-6brgxahe.js";import{richText}from"./index-jdxce2se.js";import{ApiError2}from"./index-gk84nm8f.js";import{launcherOf,readStored,writeStored}from"./index-98r96a7e.js";import{setupI18n}from"@lingui/core";var messages=JSON.parse(`{"-HY5kX":["New conversation"],"-f5Tkb":["Bad"],"09Tv5j":["Reconnecting…"],"0XGLbP":["Your sign-in has expired. Reload the page and try again."],"1EICzz":["We're away right now"],"4TqZiz":["Could not send your rating. Try again."],"6Uau97":["Skip"],"6gRgw8":["Retry"],"6lGaum":["Seen"],"ASr-r0":["Show older conversations"],"Amai22":["Chat is not available right now."],"E_qvzP":["Enter a valid e-mail address."],"GQVIIl":["You seem to be offline."],"JkW3Ph":["This file type is not accepted."],"JlFcis":["Send"],"KDw4GX":["Try again"],"M62PBt":["Nobody is available right now. Leave your e-mail and we'll send the reply there too."],"N7m8E-":["Attach files"],"NBdIgR":["Comment"],"OEEQKT":["Good"],"Pwqkdw":["Loading…"],"PxYAul":["Typing…"],"RzWUUK":["Write a message…"],"S63MQu":["All conversations"],"SOk0EB":["Thanks for your feedback"],"Sad2tK":["Sending…"],"SdV5Cn":["Send us a message and we will reply here."],"UY1vmE":["Attachment"],"VggdQJ":["Usually replies in ",["duration"]],"XJURKP":["E-mail address"],"YyNOE7":["Conversation"],"ZxJcgC":["Could not save your e-mail address. Try again."],"axQ1h6":["Anything you'd like to add? (optional)"],"eOu9Px":["The file is too large."],"h69WC6":["Sent"],"iGNUZJ":["Thanks! We'll e-mail you at ",["known"]," if you're gone when we reply."],"meAa31":["No conversations yet"],"nhTADq":["We'll reply as soon as we can"],"njBr8W":["you@example.com"],"oXOSPE":["Online"],"t7TeQU":["Messages"],"tHaDPf":[["name"]," is typing…"],"tfDRzk":["Save"],"tzsBOP":["Too many attempts. Wait a moment and try again."],"uA8iBc":["How did we do?"],"upFvcp":["Not sent."],"w61W3L":["Remove ",["0"]],"xDAtGP":["Message"],"ydzYKJ":["You:"],"yz7wBu":["Close"],"zLzEI3":["Sign in to chat with us."]}`);var messages2=JSON.parse('{"-HY5kX":["Neue Unterhaltung"],"-f5Tkb":["Schlecht"],"09Tv5j":["Verbindung wird wiederhergestellt…"],"0XGLbP":["Ihre Anmeldung ist abgelaufen. Laden Sie die Seite neu und versuchen Sie es erneut."],"1EICzz":["Wir sind gerade nicht da"],"4TqZiz":["Ihre Bewertung konnte nicht gesendet werden. Versuchen Sie es erneut."],"6Uau97":["Überspringen"],"6gRgw8":["Erneut versuchen"],"6lGaum":["Gesehen"],"ASr-r0":["Ältere Unterhaltungen anzeigen"],"Amai22":["Der Chat ist gerade nicht verfügbar."],"E_qvzP":["Geben Sie eine gültige E-Mail-Adresse ein."],"GQVIIl":["Sie scheinen offline zu sein."],"JkW3Ph":["Dieser Dateityp wird nicht akzeptiert."],"JlFcis":["Senden"],"KDw4GX":["Erneut versuchen"],"M62PBt":["Gerade ist niemand erreichbar. Hinterlassen Sie Ihre E-Mail-Adresse, dann senden wir die Antwort auch dorthin."],"N7m8E-":["Dateien anhängen"],"NBdIgR":["Kommentar"],"OEEQKT":["Gut"],"Pwqkdw":["Wird geladen…"],"PxYAul":["Schreibt…"],"RzWUUK":["Nachricht schreiben…"],"S63MQu":["Alle Unterhaltungen"],"SOk0EB":["Danke für Ihr Feedback"],"Sad2tK":["Wird gesendet…"],"SdV5Cn":["Schreiben Sie uns, wir antworten hier."],"UY1vmE":["Anhang"],"VggdQJ":["Übliche Antwortzeit: ",["duration"]],"XJURKP":["E-Mail-Adresse"],"YyNOE7":["Unterhaltung"],"ZxJcgC":["Ihre E-Mail-Adresse konnte nicht gespeichert werden. Versuchen Sie es erneut."],"axQ1h6":["Möchten Sie noch etwas ergänzen? (optional)"],"eOu9Px":["Die Datei ist zu groß."],"h69WC6":["Gesendet"],"iGNUZJ":["Danke! Falls Sie nicht mehr da sind, wenn wir antworten, schreiben wir Ihnen an ",["known"],"."],"meAa31":["Noch keine Unterhaltungen"],"nhTADq":["Wir antworten so schnell wie möglich"],"njBr8W":["sie@beispiel.de"],"oXOSPE":["Online"],"t7TeQU":["Nachrichten"],"tHaDPf":[["name"]," schreibt…"],"tfDRzk":["Speichern"],"tzsBOP":["Zu viele Versuche. Warten Sie einen Moment und versuchen Sie es erneut."],"uA8iBc":["Wie zufrieden waren Sie?"],"upFvcp":["Nicht gesendet."],"w61W3L":[["0"]," entfernen"],"xDAtGP":["Nachricht"],"ydzYKJ":["Sie:"],"yz7wBu":["Schließen"],"zLzEI3":["Melden Sie sich an, um mit uns zu chatten."]}');var messages3=JSON.parse('{"-HY5kX":["Yeni konuşma"],"-f5Tkb":["Kötü"],"09Tv5j":["Yeniden bağlanıyor…"],"0XGLbP":["Oturumunuzun süresi doldu. Sayfayı yenileyip tekrar deneyin."],"1EICzz":["Şu anda uzaktayız"],"4TqZiz":["Değerlendirmeniz gönderilemedi. Tekrar deneyin."],"6Uau97":["Geç"],"6gRgw8":["Tekrar dene"],"6lGaum":["Görüldü"],"ASr-r0":["Eski konuşmaları göster"],"Amai22":["Sohbet şu anda kullanılamıyor."],"E_qvzP":["Geçerli bir e-posta adresi girin."],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"JkW3Ph":["Bu dosya türü kabul edilmiyor."],"JlFcis":["Gönder"],"KDw4GX":["Tekrar dene"],"M62PBt":["Şu anda müsait kimse yok. E-posta adresinizi bırakın, yanıtı oraya da gönderelim."],"N7m8E-":["Dosya ekle"],"NBdIgR":["Yorum"],"OEEQKT":["İyi"],"Pwqkdw":["Yükleniyor…"],"PxYAul":["Yazıyor…"],"RzWUUK":["Bir mesaj yazın…"],"S63MQu":["Tüm konuşmalar"],"SOk0EB":["Geri bildiriminiz için teşekkürler"],"Sad2tK":["Gönderiliyor…"],"SdV5Cn":["Bize bir mesaj gönderin, yanıtımız burada görünecek."],"UY1vmE":["Ek"],"VggdQJ":["Genellikle ",["duration"]," içinde yanıt verir"],"XJURKP":["E-posta adresi"],"YyNOE7":["Konuşma"],"ZxJcgC":["E-posta adresiniz kaydedilemedi. Tekrar deneyin."],"axQ1h6":["Eklemek istediğiniz bir şey var mı? (isteğe bağlı)"],"eOu9Px":["Dosya çok büyük."],"h69WC6":["Gönderildi"],"iGNUZJ":["Teşekkürler! Yanıtladığımızda burada değilseniz ",["known"]," adresine e-posta göndereceğiz."],"meAa31":["Henüz konuşma yok"],"nhTADq":["En kısa sürede yanıt vereceğiz"],"njBr8W":["siz@ornek.com"],"oXOSPE":["Çevrimiçi"],"t7TeQU":["Mesajlar"],"tHaDPf":[["name"]," yazıyor…"],"tfDRzk":["Kaydet"],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"uA8iBc":["Nasıldık?"],"upFvcp":["Gönderilemedi."],"w61W3L":[["0"]," kaldır"],"xDAtGP":["Mesaj"],"ydzYKJ":["Siz:"],"yz7wBu":["Kapat"],"zLzEI3":["Bizimle sohbet etmek için giriş yapın."]}');var styles=`
2
2
  [hidden] { display: none !important; }
3
3
  .header {
4
4
  display: flex;
@@ -28,15 +28,22 @@ export interface TrackOptions {
28
28
  currency: string;
29
29
  };
30
30
  }
31
+ type Choice = {
32
+ analytics?: boolean;
33
+ persistent?: boolean;
34
+ };
31
35
  export interface AnalyticsMethods {
32
36
  /** A custom event. `pageview`, `engagement`, `screen` and names starting with `$` or `yuva_` are refused by the server. */
33
37
  track(name: string, options?: TrackOptions): void;
34
38
  /** Marks the current page as the site's 404 page (`not_found`, non-interactive). */
35
39
  notFound(): void;
36
40
  pageview(options?: PageviewOptions): void;
37
- consent(choice: {
38
- analytics?: boolean;
39
- } | boolean): void;
41
+ /** `persistent: true` keeps a random id on this device for 13 months and sends it on every event; never under GPC or Do Not Track. Without it a stored id is withdrawn and deleted. */
42
+ consent(choice: Choice | boolean): void;
43
+ /** Links the persistent id to a contact with a fresh identity token from your backend; needs `persistent` consent. */
44
+ identify(token: string): void;
45
+ /** The persistent id while `persistent` consent is given, for erasure requests. */
46
+ persistentId(): string | undefined;
40
47
  optOut(): void;
41
48
  optIn(): void;
42
49
  }
@@ -44,4 +51,6 @@ export interface Analytics extends AnalyticsMethods {
44
51
  destroy(): void;
45
52
  }
46
53
  export declare const OPT_OUT_KEY = "yuva_optout";
54
+ export declare const PERSISTENT_KEY = "yuva_pid";
47
55
  export declare function createAnalytics(options: AnalyticsOptions): Analytics;
56
+ export {};
@@ -1 +1 @@
1
- export { createAnalytics, OPT_OUT_KEY, type Analytics, type AnalyticsBatch, type AnalyticsEvent, type AnalyticsMethods, type AnalyticsOptions, type AnalyticsProps, type PageviewOptions, type TrackOptions, } from "./analytics/core.js";
1
+ export { createAnalytics, OPT_OUT_KEY, PERSISTENT_KEY, type Analytics, type AnalyticsBatch, type AnalyticsEvent, type AnalyticsMethods, type AnalyticsOptions, type AnalyticsProps, type PageviewOptions, type TrackOptions, } from "./analytics/core.js";
@@ -43,6 +43,8 @@ export interface MessageInput {
43
43
  }
44
44
  export interface ConversationInput extends MessageInput {
45
45
  subject?: string;
46
+ page_url?: string | null;
47
+ page_title?: string;
46
48
  }
47
49
  export interface Page {
48
50
  cursor?: string;