useyuva 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/chat.js +2 -2
- package/dist/esm/docs.js +4 -4
- package/dist/esm/{index-c6q8br7d.js → index-9vqd1b2a.js} +1 -1
- package/dist/esm/index-r9f9ttb2.js +2 -0
- package/dist/esm/subscribe.js +2 -2
- package/dist/esm/{thread-btm71nxt.js → thread-6dcd0yms.js} +1 -1
- package/dist/esm/{yuva-chat-kf9vz8r3.js → yuva-chat-025wzr6w.js} +2 -2
- package/dist/types/styles.d.ts +2 -0
- package/dist/yuva-chat.js +6 -6
- package/dist/yuva-docs.js +6 -6
- package/dist/yuva-subscribe.js +2 -2
- package/dist/yuva.js +2 -2
- package/package.json +1 -1
- package/dist/esm/index-98r96a7e.js +0 -2
package/dist/esm/chat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{resolveLocale,catalogFor,translatePlain}from"./index-
|
|
1
|
+
import{resolveLocale,catalogFor,translatePlain}from"./index-9vqd1b2a.js";import{directionOf,addStyles,launcherOf,contrastOn,readStored,writeStored}from"./index-r9f9ttb2.js";var styles=`
|
|
2
2
|
:host {
|
|
3
3
|
--yuva-accent: #2563eb;
|
|
4
4
|
--yuva-on-accent: #ffffff;
|
|
@@ -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
|
-
`,
|
|
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 fallbackStyle=addStyles(this.#root,styles),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-025wzr6w.js");define();export{YuvaChatElement,define};
|
package/dist/esm/docs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createYuvaClient2}from"./index-6brgxahe.js";import{resolveLocale,translatePlain}from"./index-
|
|
1
|
+
import{createYuvaClient2}from"./index-6brgxahe.js";import{resolveLocale,translatePlain}from"./index-9vqd1b2a.js";import{el}from"./index-rdzxvj2r.js";import{ApiError2}from"./index-gk84nm8f.js";import{directionOf,setStyles,launcherOf,contrastOn,readStored,writeStored}from"./index-r9f9ttb2.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;
|
|
@@ -46,7 +46,7 @@ textarea:focus-visible, input:focus-visible { outline: 2px solid var(--yuva-acce
|
|
|
46
46
|
.send:focus-visible, .link:focus-visible { outline: 2px solid var(--yuva-accent); outline-offset: 2px; }
|
|
47
47
|
.link { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; opacity: 0.8; }
|
|
48
48
|
@media (max-width: 480px) { textarea, input { font-size: 16px; } }
|
|
49
|
-
`;class YuvaDocsElement extends Base{static observedAttributes=["channel","server","locale","dir","page","page-title","identity-token"];root;inbox=null;pageUrl="";refused=!1;direction="ltr";#messages=messages;#client=null;#identity=null;#unfollow=null;#settingsFor="";#connected=!1;#accentColor="";constructor(){super();this.root=this.attachShadow({mode:"open"})}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 resolveLocale(this.getAttribute("locale"),navigator.language)}set locale(value){this.#attribute("locale",value)}get page(){return this.pageUrl||pageOf(this.getAttribute("page"))}set page(value){this.#attribute("page",value)}get pageTitle(){return this.getAttribute("page-title")||document.title}set pageTitle(value){this.#attribute("page-title",value)}#attribute(name,value){if(value===null||value===void 0||value==="")this.removeAttribute(name);else this.setAttribute(name,value)}setIdentityToken(source){if(this.#identity=source,this.#client?.setIdentityToken(()=>this.#identityToken()),this.#connected&&!this.refused)this.render()}connectedCallback(){this.#connected=!0,this.#unfollow??=followPage(()=>this.#syncPage()),this.pageUrl=pageOf(this.getAttribute("page")),this.#applyLocale(),this.#loadSettings(),this.render(),this.pageChanged()}disconnectedCallback(){this.#connected=!1,this.#unfollow?.(),this.#unfollow=null}attributeChangedCallback(name,previous,value){if(!this.#connected||previous===value)return;if(name==="channel"||name==="server"){this.#client?.reset(),this.#client=null,this.refused=!1,this.inbox=null,this.#settingsFor="",this.#loadSettings(),this.reset(),this.render(),this.pageChanged();return}if(name==="page")return this.#syncPage();if(name==="identity-token")this.#client?.setIdentityToken(()=>this.#identityToken());if(name==="locale"||name==="dir")this.#applyLocale();this.render()}t(descriptor){return translatePlain(this.#messages,descriptor,messages)}client(){return this.#client??=createYuvaClient2({server:this.server,channel:this.channel??"",identityToken:()=>this.#identityToken()}),this.#client}get identified(){return!!this.#identity||this.hasAttribute("identity-token")}get canWrite(){return this.identified||this.inbox?.chat.allow_anonymous!==!1}emit(type,detail){this.dispatchEvent(new CustomEvent(type,{detail,bubbles:!0,composed:!0}))}refusal(error,channelRequest=!0){let refused=error instanceof ApiError2&&(error.code==="origin_not_allowed"||error.code==="page_origin"||channelRequest&&error.status===404);if(refused&&!this.refused)this.refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown or does not allow ${this.pageUrl}`),this.root.replaceChildren();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==="anonymous_not_allowed"||code==="invalid_identity_token")return this.t({id:"uuIskV"});return this.t({id:"tAL5wg"})}frame(css,...children){let
|
|
49
|
+
`;class YuvaDocsElement extends Base{static observedAttributes=["channel","server","locale","dir","page","page-title","identity-token"];root;inbox=null;pageUrl="";refused=!1;direction="ltr";#messages=messages;#client=null;#identity=null;#unfollow=null;#settingsFor="";#connected=!1;#accentColor="";constructor(){super();this.root=this.attachShadow({mode:"open"})}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 resolveLocale(this.getAttribute("locale"),navigator.language)}set locale(value){this.#attribute("locale",value)}get page(){return this.pageUrl||pageOf(this.getAttribute("page"))}set page(value){this.#attribute("page",value)}get pageTitle(){return this.getAttribute("page-title")||document.title}set pageTitle(value){this.#attribute("page-title",value)}#attribute(name,value){if(value===null||value===void 0||value==="")this.removeAttribute(name);else this.setAttribute(name,value)}setIdentityToken(source){if(this.#identity=source,this.#client?.setIdentityToken(()=>this.#identityToken()),this.#connected&&!this.refused)this.render()}connectedCallback(){this.#connected=!0,this.#unfollow??=followPage(()=>this.#syncPage()),this.pageUrl=pageOf(this.getAttribute("page")),this.#applyLocale(),this.#loadSettings(),this.render(),this.pageChanged()}disconnectedCallback(){this.#connected=!1,this.#unfollow?.(),this.#unfollow=null}attributeChangedCallback(name,previous,value){if(!this.#connected||previous===value)return;if(name==="channel"||name==="server"){this.#client?.reset(),this.#client=null,this.refused=!1,this.inbox=null,this.#settingsFor="",this.#loadSettings(),this.reset(),this.render(),this.pageChanged();return}if(name==="page")return this.#syncPage();if(name==="identity-token")this.#client?.setIdentityToken(()=>this.#identityToken());if(name==="locale"||name==="dir")this.#applyLocale();this.render()}t(descriptor){return translatePlain(this.#messages,descriptor,messages)}client(){return this.#client??=createYuvaClient2({server:this.server,channel:this.channel??"",identityToken:()=>this.#identityToken()}),this.#client}get identified(){return!!this.#identity||this.hasAttribute("identity-token")}get canWrite(){return this.identified||this.inbox?.chat.allow_anonymous!==!1}emit(type,detail){this.dispatchEvent(new CustomEvent(type,{detail,bubbles:!0,composed:!0}))}refusal(error,channelRequest=!0){let refused=error instanceof ApiError2&&(error.code==="origin_not_allowed"||error.code==="page_origin"||channelRequest&&error.status===404);if(refused&&!this.refused)this.refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown or does not allow ${this.pageUrl}`),this.root.replaceChildren();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==="anonymous_not_allowed"||code==="invalid_identity_token")return this.t({id:"uuIskV"});return this.t({id:"tAL5wg"})}frame(css,...children){let fallback=setStyles(this.root,baseStyles+css),wrapper=el("div","frame");if(wrapper.dir=this.direction,wrapper.lang=this.locale,this.#accentColor)wrapper.style.setProperty("--yuva-accent",this.#accentColor),wrapper.style.setProperty("--yuva-on-accent",contrastOn(this.#accentColor));wrapper.append(...children);let focused=null;try{focused=this.root.activeElement}catch{}if(this.root.replaceChildren(...fallback?[fallback]:[],wrapper),focused instanceof HTMLElement&&focused.isConnected)focused.focus({preventScroll:!0})}async#identityToken(){return this.#identity?await this.#identity()??null:this.getAttribute("identity-token")}#syncPage(){if(!this.#connected)return;let page=pageOf(this.getAttribute("page"));if(page===this.pageUrl)return;this.pageUrl=page,this.reset(),this.render(),this.pageChanged()}#applyLocale(){let locale=this.locale;this.#messages=catalogs[locale]??messages,this.direction=this.getAttribute("dir")==="rtl"?"rtl":this.getAttribute("dir")==="ltr"?"ltr":directionOf(locale)}#loadSettings(){let channel=this.channel,key=`${this.server} ${channel}`;if(!channel||this.#settingsFor===key)return;this.#settingsFor=key;let stored=readStored(channel).launcher;if(stored?.color)this.#accent(stored.color);let request=settings.get(key);if(!request)request=this.client().channelSettings(),settings.set(key,request),request.catch(()=>settings.delete(key));request.then((inbox)=>{if(this.channel!==channel)return;this.inbox=inbox;let launcher=launcherOf(inbox);if(launcher.color)this.#accent(launcher.color);if(writeStored(channel,{...readStored(channel),launcher}),!this.refused)this.render()}).catch((error)=>{if(this.channel===channel)this.refusal(error)})}#accent(color){if(!/^#[0-9a-f]{6}$/i.test(color))return;this.#accentColor=color}}var hashPrefix="#yuva-discussion-",cacheFor=60000,loads=new Map;function forget(prefix){for(let key of loads.keys())if(key.startsWith(prefix))loads.delete(key)}var svg=(path)=>`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${path}</svg>`,icons={up:svg('<path d="M12 19V5M5 12l7-7 7 7"/>'),comment:svg('<path d="M21 12a8 8 0 01-11.6 7.1L4 20l1-4.6A8 8 0 1121 12z"/>'),check:svg('<path d="M20 6L9 17l-5-5"/>'),lock:svg('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 018 0v4"/>'),clock:svg('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>')},styles=`
|
|
50
50
|
.frame { display: flex; flex-direction: column; gap: 16px; }
|
|
51
51
|
:host { --yuva-success: #1a7f37; --yuva-warn: #9a6700; }
|
|
52
52
|
@media (prefers-color-scheme: dark) { :host { --yuva-success: #3fb950; --yuva-warn: #d29922; } }
|
|
@@ -110,7 +110,7 @@ button { font: inherit; color: inherit; }
|
|
|
110
110
|
.item .avatar { display: none; }
|
|
111
111
|
.bar .send { inline-size: 100%; }
|
|
112
112
|
}
|
|
113
|
-
`;function hue(text){let hash=0;for(let char of text)hash=hash*31+char.charCodeAt(0)|0;return Math.abs(hash)%360}function excerptOf(html){let template=document.createElement("template");return template.innerHTML=html,(template.content.textContent??"").replace(/\s+/g," ").trim().slice(0,240)}class YuvaDiscussionsElement extends YuvaDocsElement{static loadThread;#s={view:{kind:"list"},items:[],thread:null,threadState:"loading",writer:null,reader:null,busy:new Set,notice:"",error:"",confirm:"",focus:""};#sort="new";#cursor;#listState="loading";#loadedFor="";#offReader=null;#thread=null;#threadLoad=null;#threadStyles="";get discussions(){return this.#s.items}get reader(){return this.#s.reader}#hashChanged=()=>this.#fromHash();connectedCallback(){super.connectedCallback(),window.addEventListener("hashchange",this.#hashChanged),this.#watchReader()}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("hashchange",this.#hashChanged),this.#offReader?.(),this.#offReader=null}attributeChangedCallback(name,previous,value){if(super.attributeChangedCallback(name,previous,value),previous===value||!this.isConnected)return;if(name==="channel"||name==="server")this.#offReader?.(),this.#offReader=null,this.#watchReader();else if(name==="identity-token")this.#refreshWriter(!0)}setIdentityToken(source){super.setIdentityToken(source),this.#refreshWriter(!0)}#watchReader(){if(!this.channel||this.#offReader)return;let client=this.client();this.#s.reader=client.reader,this.#offReader=client.on("reader",(reader)=>{this.#s.reader=reader,this.emit("yuva-reader",reader?reader.reader:null),this.#refreshWriter(!0)}),this.#refreshWriter(!1)}async#refreshWriter(reload){if(!this.channel)return;let writer=await this.client().discussionWriter().catch(()=>null),changed=writer!==this.#s.writer;if(this.#s.writer=writer,reload&&changed){if(this.#loadedFor="",this.#load(!1),this.#s.view.kind==="thread")this.#open(this.#s.view.id,!1)}this.render()}reset(){let s=this.#s;s.view={kind:"list"},s.items=[],this.#cursor=void 0,this.#listState="loading",this.#loadedFor="",s.thread=null,s.notice="",s.error="",s.confirm="",this.#thread?.reset()}pageChanged(){this.#load(!1),this.#fromHash()}#linked(){let hash=location.hash;return hash.startsWith(hashPrefix)?decodeURIComponent(hash.slice(hashPrefix.length)):""}#fromHash(){let id=this.#linked();if(!id||!this.channel||this.refused)return;if(this.#s.view.kind==="thread"&&this.#s.view.id===id)return;this.#thread?.close(),this.#s.confirm="",this.#open(id,!0),this.scrollIntoView({block:"start"})}#prefetchOn(button){let prefetch=()=>void this.#loadThread();button.addEventListener("pointerenter",prefetch,{once:!0}),button.addEventListener("focus",prefetch,{once:!0})}#loadThread(){return this.#threadLoad??=YuvaDiscussionsElement.loadThread().then((module)=>{if(this.#threadStyles=module.styles,this.#thread=module.createThread(this.#host),this.#s.view.kind!=="list")this.render();return this.#thread},()=>{if(this.#threadLoad=null,this.#s.view.kind!=="list")this.#s.view={kind:"list"},this.#s.error=this.t({id:"D16wQE"}),this.render();return null}),this.#threadLoad}#host=this.#makeHost();#makeHost(){return{s:this.#s,icons,root:this.root,locale:()=>this.locale,direction:()=>this.direction,page:()=>this.pageUrl,pageTitle:()=>this.pageTitle,mode:()=>this.#mode,client:()=>this.client(),render:()=>this.render(),emit:(type,detail)=>this.emit(type,detail),act:(key,action)=>this.#act(key,action),signIn:()=>this.signIn(),open:(id,focus)=>this.#open(id,focus),toList:()=>this.#toList(),forget:()=>forget(this.#prefix),button:(className,text,key,onClick,html)=>this.#button(className,text,key,onClick,html),avatar:(author,small)=>this.#avatar(author,small),badge:(kind,short)=>this.#badge(kind,short),time:(value)=>this.#time(value),authorName:(author)=>this.#authorName(author),noticeBox:(text,icon)=>this.#noticeBox(text,icon)}}reload(){return this.#load(!0)}open(id){return this.#open(id,!0)}signIn(){return this.#s.error="",this.client().readerSignIn().then(()=>{return}).catch((error)=>{let code=error instanceof ApiError2?error.code:"";if(code==="sign_in_cancelled")return;this.#s.error=code==="popup_blocked"?this.t({id:"nW3go1"}):this.#failure(error),this.render()})}signOut(){return this.client().readerSignOut()}get#prefix(){return`${this.server} ${this.channel} ${this.pageUrl} `}async#load(force,more=!1){let page=this.pageUrl;if(!this.channel||!page||this.refused)return;let reader=this.client().reader,auth=reader?reader.token.slice(-12):this.#s.writer??"-",key=`${this.#prefix}${this.#sort} ${auth}`;if(!force&&!more&&this.#loadedFor===key)return;this.#loadedFor=key;let request;if(more)request=this.client().listDiscussions(page,{sort:this.#sort,cursor:this.#cursor});else{let load=loads.get(key);if(force||!load||Date.now()-load.at>cacheFor){load={at:Date.now(),request:this.client().listDiscussions(page,{sort:this.#sort})},loads.set(key,load);let current=load;load.request.catch(()=>loads.get(key)===current&&loads.delete(key))}if(request=load.request,!this.#s.items.length)this.#listState="loading"}if(more)this.#s.busy.add("more");this.render();try{let result=await request;if(this.#loadedFor!==key)return;this.#s.items=more?[...this.#s.items,...result.items.filter((d)=>!this.#s.items.some((i)=>i.id===d.id))]:result.items,this.#cursor=result.next_cursor,this.#listState="ready"}catch(error){if(this.#loadedFor!==key||this.refusal(error))return;if(!more)this.#loadedFor="";if(this.#listState=error instanceof ApiError2&&error.code==="discussions_off"?"off":more?"ready":"error",more)this.#s.error=this.#failure(error)}finally{this.#s.busy.delete("more")}this.render()}async#open(id,focus){let s=this.#s,page=this.pageUrl,known=s.thread?.discussion.id===id?s.thread:null;this.#loadThread(),s.view={kind:"thread",id};let listed=s.items.find((d)=>d.id===id);if(s.thread=known??(listed?{discussion:listed,posts:[]}:null),s.threadState=known?"ready":"loading",focus)s.notice=known?s.notice:"",s.error="",s.focus="thread-title";this.render();try{let detail=await this.client().getDiscussion(id);if(this.pageUrl!==page||s.view.kind!=="thread"||s.view.id!==id)return;let titled=!!s.thread;if(s.thread=detail,s.threadState="ready",focus&&!titled)s.focus="thread-title";s.items=s.items.map((d)=>d.id===id?detail.discussion:d)}catch(error){if(this.pageUrl!==page||s.view.kind!=="thread"||s.view.id!==id)return;if(this.refusal(error,!1))return;s.threadState=error instanceof ApiError2&&error.status===404?"missing":"error"}this.render()}#toList(){let s=this.#s;if(this.#linked()){let url=new URL(location.href);url.hash="",history.replaceState(history.state,"",url.href)}s.view={kind:"list"},this.#thread?.close(),s.confirm="",s.error="",s.focus=s.thread?`open-${s.thread.discussion.id}`:"start",this.render(),this.#load(!1)}#failure(error){let code=error instanceof ApiError2?error.code:"";if(code==="sign_in_required")return this.t({id:"LwDe8g"});if(code==="discussion_locked")return this.t({id:"KEjhwb"});if(code==="edit_window_closed")return this.t({id:"b_f4xj"});if(code==="discussions_off")return this.t({id:"tayT8P"});if(code==="forbidden")return this.t({id:"8Ekoev"});if(code==="validation_failed")return this.t({id:"Su3Vyp"});return this.errorText(error)}async#act(key,action){let s=this.#s;if(s.busy.has(key))return;s.busy.add(key),s.error="",this.render();try{return await action()}catch(error){if(!this.refusal(error,!1))s.error=this.#failure(error);if(error instanceof ApiError2&&error.code==="sign_in_required")this.#refreshWriter(!1);return}finally{s.busy.delete(key),this.render()}}get#mode(){return this.inbox?.chat.discussions??"moderated"}#button(className,text,key,onClick,html=""){let button=el("button",className);if(button.type="button",html)button.innerHTML=html;return button.append(text),button.dataset.key=key,button.addEventListener("click",onClick),button}#authorName(author){if(author.deleted)return author.kind==="member"?this.t({id:"-UxBoG"}):this.t({id:"FMWGhb"});if(author.kind==="anonymous")return this.t({id:"D9CFV5"});return author.name||(author.kind==="member"?this.t({id:"nLqMRA"}):this.t({id:"zmA6sS"}))}#avatar(author,small=!1){let avatar=el("span",`avatar${small?" small":""}`,author.deleted?"":author.initials||"?");if(avatar.setAttribute("aria-hidden","true"),author.deleted||author.kind==="anonymous")avatar.classList.add("gone");else if(author.kind==="member")avatar.classList.add("team");else avatar.style.setProperty("--avatar",`hsl(${hue(author.name||author.initials)} 45% 42%)`);return avatar}#badge(kind,short=!1){let text=kind==="answered"?this.t({id:"GqCA_t"}):kind==="pending"?short?this.t({id:"UbRKMZ"}):this.t({id:"lWv8id"}):kind==="team"?this.t({id:"KM6m8p"}):this.t({id:"G2fuEb"}),badge=el("span",`badge ${kind}`);if(kind!=="team")badge.innerHTML=kind==="answered"?icons.check:kind==="pending"?icons.clock:icons.lock;return badge.append(text),badge}#time(value){let time=el("time");time.dateTime=value;let date=new Date(value);time.title=date.toLocaleString(this.locale);let seconds=(date.getTime()-Date.now())/1000,steps=[["second",60],["minute",60],["hour",24],["day",30],["month",12],["year",1/0]],amount=seconds;for(let[unit,size]of steps){if(Math.abs(amount)<size){time.textContent=unit==="second"?this.t({id:"xOTzt5"}):new Intl.RelativeTimeFormat(this.locale,{numeric:"auto"}).format(Math.round(amount),unit);break}amount/=size}return time}#header(){let head=el("div","head");head.append(el("h2","",this.t({id:"7oGBMv"})));let who=el("div","who"),reader=this.#s.reader;if(reader){let name=reader.reader.name||this.t({id:"zmA6sS"});who.append(this.#avatar({kind:"reader",name,initials:reader.reader.initials,deleted:!1},!0)),who.append(el("span","",name)),who.append(this.#button("plain",this.t({id:"fcWrnU"}),"sign-out",()=>void this.signOut()))}else if(!this.#s.writer&&this.#mode!=="off")who.append(this.#button("ghost",this.t({id:"5lWFkC"}),"sign-in",()=>void this.signIn()));return head.append(who),head}#listView(){let nodes=[],bar=el("div","bar"),tabs=el("div","tabs");tabs.setAttribute("role","tablist"),tabs.setAttribute("aria-label",this.t({id:"78dEKp"}));let sorts=[["new",this.t({id:"isRobC"})],["top",this.t({id:"WWy8TN"})],["unanswered",this.t({id:"2lF8Zj"})]];sorts.forEach(([sort,label],index)=>{let tab=this.#button("tab",label,`sort-${sort}`,()=>this.#setSort(sort));tab.setAttribute("role","tab"),tab.setAttribute("aria-selected",String(this.#sort===sort)),tab.setAttribute("aria-controls","yuva-discussion-list"),tab.tabIndex=this.#sort===sort?0:-1,tab.addEventListener("keydown",(event)=>{let step=event.key==="ArrowRight"?1:event.key==="ArrowLeft"?-1:0;if(!step)return;event.preventDefault();let forward=this.direction==="rtl"?-step:step,next=sorts[(index+forward+sorts.length)%sorts.length];if(next)this.#setSort(next[0])}),tabs.append(tab)});let start=this.#button("send",this.t({id:"z1qf6l"}),"start",()=>{this.#loadThread(),this.#s.view={kind:"new"},this.#s.error="",this.#s.notice="",this.#s.focus="new-title",this.render()});if(this.#prefetchOn(start),bar.append(tabs,start),nodes.push(bar),this.#listState==="loading"&&!this.#s.items.length){let skeleton=el("div","skeleton");return skeleton.setAttribute("aria-busy","true"),skeleton.setAttribute("aria-label",this.t({id:"pzatAP"})),nodes.push(skeleton),nodes}if(this.#listState==="error"&&!this.#s.items.length){let box=el("div","empty");box.append(el("p","",this.t({id:"MDmQKn"})));let retry=this.#button("ghost",this.t({id:"KDw4GX"}),"retry",()=>void this.#load(!0));return retry.style.marginBlockStart="8px",box.append(retry),nodes.push(box),nodes}if(!this.#s.items.length){let box=el("div","empty");if(box.append(el("p","",this.#sort==="unanswered"?this.t({id:"twEQ41"}):this.t({id:"rpfOwz"}))),this.#sort!=="unanswered")box.append(el("p","muted",this.t({id:"b6Orhy"})));return nodes.push(box),nodes}let list=el("ul","list");list.id="yuva-discussion-list",list.setAttribute("aria-label",this.t({id:"j-3eim"})),list.setAttribute("aria-busy",String(this.#listState==="loading"));for(let discussion of this.#s.items){let item=el("li","item");item.append(this.#avatar(discussion.author));let main=el("div","main"),title=this.#button("title",discussion.title,`open-${discussion.id}`,()=>void this.#open(discussion.id,!0));title.dir="auto",this.#prefetchOn(title),main.append(title);let excerpt=discussion.deleted?"":excerptOf(discussion.body_html);if(excerpt){let text=el("p","excerpt",excerpt);text.dir="auto",main.append(text)}let meta=el("div","meta");if(meta.append(el("span","",this.#authorName(discussion.author)),this.#time(discussion.created_at)),discussion.author.kind==="member"&&!discussion.author.deleted)meta.append(this.#badge("team"));if(discussion.answer_post_id)meta.append(this.#badge("answered"));if(discussion.state==="pending")meta.append(this.#badge("pending"));if(discussion.locked)meta.append(this.#badge("locked"));main.append(meta);let counts=el("div","counts"),votes=el("span","count");votes.innerHTML=icons.up,votes.append(String(discussion.votes)),votes.setAttribute("aria-label",this.t({id:"8ntmc1",values:{0:discussion.votes}})),votes.title=votes.getAttribute("aria-label")??"";let replies=el("span","count");replies.innerHTML=icons.comment,replies.append(String(discussion.reply_count)),replies.setAttribute("aria-label",this.t({id:"Hw3P48",values:{0:discussion.reply_count}})),replies.title=replies.getAttribute("aria-label")??"",counts.append(votes,replies),item.append(main,counts),list.append(item)}if(nodes.push(list),this.#cursor){let more=this.#button("ghost more",this.#s.busy.has("more")?this.t({id:"Pwqkdw"}):this.t({id:"fMPkxb"}),"more",()=>void this.#load(!1,!0));more.disabled=this.#s.busy.has("more"),nodes.push(more)}return nodes}#setSort(sort){if(this.#sort===sort)return;this.#sort=sort,this.#s.items=[],this.#cursor=void 0,this.#listState="loading",this.#s.focus=`sort-${sort}`,this.#load(!1)}#noticeBox(text,icon=icons.clock){let box=el("div","notice");return box.setAttribute("role","status"),box.innerHTML=icon,box.append(el("p","",text)),box}render(){if(this.refused||!this.channel){this.root.replaceChildren();return}let focused="";try{focused=this.root.activeElement?.dataset?.key??""}catch{}let children=[this.#header()];if(this.#mode==="off"||this.#listState==="off")children.push(el("p","muted",this.t({id:"tayT8P"})));else if(this.#s.view.kind!=="list"){let thread=this.#thread;if(thread)children.push(...this.#s.view.kind==="thread"?thread.threadView():thread.newView());else{let skeleton=el("div","skeleton");skeleton.setAttribute("aria-busy","true"),skeleton.setAttribute("aria-label",this.t({id:"Pwqkdw"})),children.push(skeleton)}}else{if(this.#s.notice)children.push(this.#noticeBox(this.#s.notice));children.push(...this.#listView())}if(this.#s.error){let error=el("p","error",this.#s.error);error.setAttribute("role","alert"),children.push(error)}if(this.frame(styles+this.#threadStyles,...children),this.#s.view.kind!=="list"&&!this.#thread)return;this.#thread?.syncSend();let wanted=this.#s.focus;this.#s.focus="";let key=wanted||focused;if(!key)return;let active=null;try{active=this.root.activeElement}catch{}if(active instanceof HTMLElement&&active.dataset.key===key)return;[...this.root.querySelectorAll("[data-key]")].find((node)=>node.dataset.key===key)?.focus({preventScroll:!wanted})}}var maxRemembered=500,thumb=(down)=>`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"${down?' style="transform:scaleY(-1)"':""}><path d="M7 10v11H3V10zM7 10l4-8a3 3 0 013 3v4h6a2 2 0 012 2.3l-1.4 8A2 2 0 0118.6 21H7"/></svg>`,styles2=`
|
|
113
|
+
`;function hue(text){let hash=0;for(let char of text)hash=hash*31+char.charCodeAt(0)|0;return Math.abs(hash)%360}function excerptOf(html){let template=document.createElement("template");return template.innerHTML=html,(template.content.textContent??"").replace(/\s+/g," ").trim().slice(0,240)}class YuvaDiscussionsElement extends YuvaDocsElement{static loadThread;#s={view:{kind:"list"},items:[],thread:null,threadState:"loading",writer:null,reader:null,busy:new Set,notice:"",error:"",confirm:"",focus:""};#sort="new";#cursor;#listState="loading";#loadedFor="";#offReader=null;#thread=null;#threadLoad=null;#threadStyles="";get discussions(){return this.#s.items}get reader(){return this.#s.reader}#hashChanged=()=>this.#fromHash();connectedCallback(){super.connectedCallback(),window.addEventListener("hashchange",this.#hashChanged),this.#watchReader()}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("hashchange",this.#hashChanged),this.#offReader?.(),this.#offReader=null}attributeChangedCallback(name,previous,value){if(super.attributeChangedCallback(name,previous,value),previous===value||!this.isConnected)return;if(name==="channel"||name==="server")this.#offReader?.(),this.#offReader=null,this.#watchReader();else if(name==="identity-token")this.#refreshWriter(!0)}setIdentityToken(source){super.setIdentityToken(source),this.#refreshWriter(!0)}#watchReader(){if(!this.channel||this.#offReader)return;let client=this.client();this.#s.reader=client.reader,this.#offReader=client.on("reader",(reader)=>{this.#s.reader=reader,this.emit("yuva-reader",reader?reader.reader:null),this.#refreshWriter(!0)}),this.#refreshWriter(!1)}async#refreshWriter(reload){if(!this.channel)return;let writer=await this.client().discussionWriter().catch(()=>null),changed=writer!==this.#s.writer;if(this.#s.writer=writer,reload&&changed){if(this.#loadedFor="",this.#load(!1),this.#s.view.kind==="thread")this.#open(this.#s.view.id,!1)}this.render()}reset(){let s=this.#s;s.view={kind:"list"},s.items=[],this.#cursor=void 0,this.#listState="loading",this.#loadedFor="",s.thread=null,s.notice="",s.error="",s.confirm="",this.#thread?.reset()}pageChanged(){this.#load(!1),this.#fromHash()}#linked(){let hash=location.hash;return hash.startsWith(hashPrefix)?decodeURIComponent(hash.slice(hashPrefix.length)):""}#fromHash(){let id=this.#linked();if(!id||!this.channel||this.refused)return;if(this.#s.view.kind==="thread"&&this.#s.view.id===id)return;this.#thread?.close(),this.#s.confirm="",this.#open(id,!0),this.scrollIntoView({block:"start"})}#prefetchOn(button){let prefetch=()=>void this.#loadThread();button.addEventListener("pointerenter",prefetch,{once:!0}),button.addEventListener("focus",prefetch,{once:!0})}#loadThread(){return this.#threadLoad??=YuvaDiscussionsElement.loadThread().then((module)=>{if(this.#threadStyles=module.styles,this.#thread=module.createThread(this.#host),this.#s.view.kind!=="list")this.render();return this.#thread},()=>{if(this.#threadLoad=null,this.#s.view.kind!=="list")this.#s.view={kind:"list"},this.#s.error=this.t({id:"D16wQE"}),this.render();return null}),this.#threadLoad}#host=this.#makeHost();#makeHost(){return{s:this.#s,icons,root:this.root,locale:()=>this.locale,direction:()=>this.direction,page:()=>this.pageUrl,pageTitle:()=>this.pageTitle,mode:()=>this.#mode,client:()=>this.client(),render:()=>this.render(),emit:(type,detail)=>this.emit(type,detail),act:(key,action)=>this.#act(key,action),signIn:()=>this.signIn(),open:(id,focus)=>this.#open(id,focus),toList:()=>this.#toList(),forget:()=>forget(this.#prefix),button:(className,text,key,onClick,html)=>this.#button(className,text,key,onClick,html),avatar:(author,small)=>this.#avatar(author,small),badge:(kind,short)=>this.#badge(kind,short),time:(value)=>this.#time(value),authorName:(author)=>this.#authorName(author),noticeBox:(text,icon)=>this.#noticeBox(text,icon)}}reload(){return this.#load(!0)}open(id){return this.#open(id,!0)}signIn(){return this.#s.error="",this.client().readerSignIn().then(()=>{return}).catch((error)=>{let code=error instanceof ApiError2?error.code:"";if(code==="sign_in_cancelled")return;this.#s.error=code==="popup_blocked"?this.t({id:"nW3go1"}):this.#failure(error),this.render()})}signOut(){return this.client().readerSignOut()}get#prefix(){return`${this.server} ${this.channel} ${this.pageUrl} `}async#load(force,more=!1){let page=this.pageUrl;if(!this.channel||!page||this.refused)return;let reader=this.client().reader,auth=reader?reader.token.slice(-12):this.#s.writer??"-",key=`${this.#prefix}${this.#sort} ${auth}`;if(!force&&!more&&this.#loadedFor===key)return;this.#loadedFor=key;let request;if(more)request=this.client().listDiscussions(page,{sort:this.#sort,cursor:this.#cursor});else{let load=loads.get(key);if(force||!load||Date.now()-load.at>cacheFor){load={at:Date.now(),request:this.client().listDiscussions(page,{sort:this.#sort})},loads.set(key,load);let current=load;load.request.catch(()=>loads.get(key)===current&&loads.delete(key))}if(request=load.request,!this.#s.items.length)this.#listState="loading"}if(more)this.#s.busy.add("more");this.render();try{let result=await request;if(this.#loadedFor!==key)return;this.#s.items=more?[...this.#s.items,...result.items.filter((d)=>!this.#s.items.some((i)=>i.id===d.id))]:result.items,this.#cursor=result.next_cursor,this.#listState="ready"}catch(error){if(this.#loadedFor!==key||this.refusal(error))return;if(!more)this.#loadedFor="";if(this.#listState=error instanceof ApiError2&&error.code==="discussions_off"?"off":more?"ready":"error",more)this.#s.error=this.#failure(error)}finally{this.#s.busy.delete("more")}this.render()}async#open(id,focus){let s=this.#s,page=this.pageUrl,known=s.thread?.discussion.id===id?s.thread:null;this.#loadThread(),s.view={kind:"thread",id};let listed=s.items.find((d)=>d.id===id);if(s.thread=known??(listed?{discussion:listed,posts:[]}:null),s.threadState=known?"ready":"loading",focus)s.notice=known?s.notice:"",s.error="",s.focus="thread-title";this.render();try{let detail=await this.client().getDiscussion(id);if(this.pageUrl!==page||s.view.kind!=="thread"||s.view.id!==id)return;let titled=!!s.thread;if(s.thread=detail,s.threadState="ready",focus&&!titled)s.focus="thread-title";s.items=s.items.map((d)=>d.id===id?detail.discussion:d)}catch(error){if(this.pageUrl!==page||s.view.kind!=="thread"||s.view.id!==id)return;if(this.refusal(error,!1))return;s.threadState=error instanceof ApiError2&&error.status===404?"missing":"error"}this.render()}#toList(){let s=this.#s;if(this.#linked()){let url=new URL(location.href);url.hash="",history.replaceState(history.state,"",url.href)}s.view={kind:"list"},this.#thread?.close(),s.confirm="",s.error="",s.focus=s.thread?`open-${s.thread.discussion.id}`:"start",this.render(),this.#load(!1)}#failure(error){let code=error instanceof ApiError2?error.code:"";if(code==="sign_in_required")return this.t({id:"LwDe8g"});if(code==="discussion_locked")return this.t({id:"KEjhwb"});if(code==="edit_window_closed")return this.t({id:"b_f4xj"});if(code==="discussions_off")return this.t({id:"tayT8P"});if(code==="forbidden")return this.t({id:"8Ekoev"});if(code==="validation_failed")return this.t({id:"Su3Vyp"});return this.errorText(error)}async#act(key,action){let s=this.#s;if(s.busy.has(key))return;s.busy.add(key),s.error="",this.render();try{return await action()}catch(error){if(!this.refusal(error,!1))s.error=this.#failure(error);if(error instanceof ApiError2&&error.code==="sign_in_required")this.#refreshWriter(!1);return}finally{s.busy.delete(key),this.render()}}get#mode(){return this.inbox?.chat.discussions??"moderated"}#button(className,text,key,onClick,html=""){let button=el("button",className);if(button.type="button",html)button.innerHTML=html;return button.append(text),button.dataset.key=key,button.addEventListener("click",onClick),button}#authorName(author){if(author.deleted)return author.kind==="member"?this.t({id:"-UxBoG"}):this.t({id:"FMWGhb"});if(author.kind==="anonymous")return this.t({id:"D9CFV5"});return author.name||(author.kind==="member"?this.t({id:"nLqMRA"}):this.t({id:"zmA6sS"}))}#avatar(author,small=!1){let avatar=el("span",`avatar${small?" small":""}`,author.deleted?"":author.initials||"?");if(avatar.setAttribute("aria-hidden","true"),author.deleted||author.kind==="anonymous")avatar.classList.add("gone");else if(author.kind==="member")avatar.classList.add("team");else avatar.style.setProperty("--avatar",`hsl(${hue(author.name||author.initials)} 45% 42%)`);return avatar}#badge(kind,short=!1){let text=kind==="answered"?this.t({id:"GqCA_t"}):kind==="pending"?short?this.t({id:"UbRKMZ"}):this.t({id:"lWv8id"}):kind==="team"?this.t({id:"KM6m8p"}):this.t({id:"G2fuEb"}),badge=el("span",`badge ${kind}`);if(kind!=="team")badge.innerHTML=kind==="answered"?icons.check:kind==="pending"?icons.clock:icons.lock;return badge.append(text),badge}#time(value){let time=el("time");time.dateTime=value;let date=new Date(value);time.title=date.toLocaleString(this.locale);let seconds=(date.getTime()-Date.now())/1000,steps=[["second",60],["minute",60],["hour",24],["day",30],["month",12],["year",1/0]],amount=seconds;for(let[unit,size]of steps){if(Math.abs(amount)<size){time.textContent=unit==="second"?this.t({id:"xOTzt5"}):new Intl.RelativeTimeFormat(this.locale,{numeric:"auto"}).format(Math.round(amount),unit);break}amount/=size}return time}#header(){let head=el("div","head");head.append(el("h2","",this.t({id:"7oGBMv"})));let who=el("div","who"),reader=this.#s.reader;if(reader){let name=reader.reader.name||this.t({id:"zmA6sS"});who.append(this.#avatar({kind:"reader",name,initials:reader.reader.initials,deleted:!1},!0)),who.append(el("span","",name)),who.append(this.#button("plain",this.t({id:"fcWrnU"}),"sign-out",()=>void this.signOut()))}else if(!this.#s.writer&&this.#mode!=="off")who.append(this.#button("ghost",this.t({id:"5lWFkC"}),"sign-in",()=>void this.signIn()));return head.append(who),head}#listView(){let nodes=[],bar=el("div","bar"),tabs=el("div","tabs");tabs.setAttribute("role","tablist"),tabs.setAttribute("aria-label",this.t({id:"78dEKp"}));let sorts=[["new",this.t({id:"isRobC"})],["top",this.t({id:"WWy8TN"})],["unanswered",this.t({id:"2lF8Zj"})]];sorts.forEach(([sort,label],index)=>{let tab=this.#button("tab",label,`sort-${sort}`,()=>this.#setSort(sort));tab.setAttribute("role","tab"),tab.setAttribute("aria-selected",String(this.#sort===sort)),tab.setAttribute("aria-controls","yuva-discussion-list"),tab.tabIndex=this.#sort===sort?0:-1,tab.addEventListener("keydown",(event)=>{let step=event.key==="ArrowRight"?1:event.key==="ArrowLeft"?-1:0;if(!step)return;event.preventDefault();let forward=this.direction==="rtl"?-step:step,next=sorts[(index+forward+sorts.length)%sorts.length];if(next)this.#setSort(next[0])}),tabs.append(tab)});let start=this.#button("send",this.t({id:"z1qf6l"}),"start",()=>{this.#loadThread(),this.#s.view={kind:"new"},this.#s.error="",this.#s.notice="",this.#s.focus="new-title",this.render()});if(this.#prefetchOn(start),bar.append(tabs,start),nodes.push(bar),this.#listState==="loading"&&!this.#s.items.length){let skeleton=el("div","skeleton");return skeleton.setAttribute("aria-busy","true"),skeleton.setAttribute("aria-label",this.t({id:"pzatAP"})),nodes.push(skeleton),nodes}if(this.#listState==="error"&&!this.#s.items.length){let box=el("div","empty");box.append(el("p","",this.t({id:"MDmQKn"})));let retry=this.#button("ghost",this.t({id:"KDw4GX"}),"retry",()=>void this.#load(!0));return retry.style.marginBlockStart="8px",box.append(retry),nodes.push(box),nodes}if(!this.#s.items.length){let box=el("div","empty");if(box.append(el("p","",this.#sort==="unanswered"?this.t({id:"twEQ41"}):this.t({id:"rpfOwz"}))),this.#sort!=="unanswered")box.append(el("p","muted",this.t({id:"b6Orhy"})));return nodes.push(box),nodes}let list=el("ul","list");list.id="yuva-discussion-list",list.setAttribute("aria-label",this.t({id:"j-3eim"})),list.setAttribute("aria-busy",String(this.#listState==="loading"));for(let discussion of this.#s.items){let item=el("li","item");item.append(this.#avatar(discussion.author));let main=el("div","main"),title=this.#button("title",discussion.title,`open-${discussion.id}`,()=>void this.#open(discussion.id,!0));title.dir="auto",this.#prefetchOn(title),main.append(title);let excerpt=discussion.deleted?"":excerptOf(discussion.body_html);if(excerpt){let text=el("p","excerpt",excerpt);text.dir="auto",main.append(text)}let meta=el("div","meta");if(meta.append(el("span","",this.#authorName(discussion.author)),this.#time(discussion.created_at)),discussion.author.kind==="member"&&!discussion.author.deleted)meta.append(this.#badge("team"));if(discussion.answer_post_id)meta.append(this.#badge("answered"));if(discussion.state==="pending")meta.append(this.#badge("pending"));if(discussion.locked)meta.append(this.#badge("locked"));main.append(meta);let counts=el("div","counts"),votes=el("span","count");votes.innerHTML=icons.up,votes.append(String(discussion.votes)),votes.setAttribute("aria-label",this.t({id:"8ntmc1",values:{0:discussion.votes}})),votes.title=votes.getAttribute("aria-label")??"";let replies=el("span","count");replies.innerHTML=icons.comment,replies.append(String(discussion.reply_count)),replies.setAttribute("aria-label",this.t({id:"Hw3P48",values:{0:discussion.reply_count}})),replies.title=replies.getAttribute("aria-label")??"",counts.append(votes,replies),item.append(main,counts),list.append(item)}if(nodes.push(list),this.#cursor){let more=this.#button("ghost more",this.#s.busy.has("more")?this.t({id:"Pwqkdw"}):this.t({id:"fMPkxb"}),"more",()=>void this.#load(!1,!0));more.disabled=this.#s.busy.has("more"),nodes.push(more)}return nodes}#setSort(sort){if(this.#sort===sort)return;this.#sort=sort,this.#s.items=[],this.#cursor=void 0,this.#listState="loading",this.#s.focus=`sort-${sort}`,this.#load(!1)}#noticeBox(text,icon=icons.clock){let box=el("div","notice");return box.setAttribute("role","status"),box.innerHTML=icon,box.append(el("p","",text)),box}render(){if(this.refused||!this.channel){this.root.replaceChildren();return}let focused="";try{focused=this.root.activeElement?.dataset?.key??""}catch{}let children=[this.#header()];if(this.#mode==="off"||this.#listState==="off")children.push(el("p","muted",this.t({id:"tayT8P"})));else if(this.#s.view.kind!=="list"){let thread=this.#thread;if(thread)children.push(...this.#s.view.kind==="thread"?thread.threadView():thread.newView());else{let skeleton=el("div","skeleton");skeleton.setAttribute("aria-busy","true"),skeleton.setAttribute("aria-label",this.t({id:"Pwqkdw"})),children.push(skeleton)}}else{if(this.#s.notice)children.push(this.#noticeBox(this.#s.notice));children.push(...this.#listView())}if(this.#s.error){let error=el("p","error",this.#s.error);error.setAttribute("role","alert"),children.push(error)}if(this.frame(styles+this.#threadStyles,...children),this.#s.view.kind!=="list"&&!this.#thread)return;this.#thread?.syncSend();let wanted=this.#s.focus;this.#s.focus="";let key=wanted||focused;if(!key)return;let active=null;try{active=this.root.activeElement}catch{}if(active instanceof HTMLElement&&active.dataset.key===key)return;[...this.root.querySelectorAll("[data-key]")].find((node)=>node.dataset.key===key)?.focus({preventScroll:!wanted})}}var maxRemembered=500,thumb=(down)=>`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path${down?' transform="matrix(1 0 0 -1 0 24)"':""} d="M7 10v11H3V10zM7 10l4-8a3 3 0 013 3v4h6a2 2 0 012 2.3l-1.4 8A2 2 0 0118.6 21H7"/></svg>`,styles2=`
|
|
114
114
|
.frame { display: flex; flex-direction: column; gap: 12px; }
|
|
115
115
|
.ask { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
|
|
116
116
|
.question { font-weight: 600; }
|
|
@@ -131,4 +131,4 @@ button { font: inherit; color: inherit; }
|
|
|
131
131
|
.choice[aria-pressed="true"] { background: var(--yuva-soft); }
|
|
132
132
|
.choice:disabled { cursor: default; }
|
|
133
133
|
.choice:focus-visible { outline: 2px solid var(--yuva-accent); outline-offset: 2px; }
|
|
134
|
-
`;function storageKey(channel){return`yuva:${channel}:page-ratings`}function remembered(channel){try{let raw=localStorage.getItem(storageKey(channel));return raw?JSON.parse(raw):{}}catch{return{}}}function remember(channel,page,rating){try{let ratings=remembered(channel);delete ratings[page],ratings[page]=rating;let pages=Object.keys(ratings);for(let old of pages.slice(0,Math.max(0,pages.length-maxRemembered)))delete ratings[old];localStorage.setItem(storageKey(channel),JSON.stringify(ratings))}catch{}}class YuvaPageFeedbackElement extends YuvaDocsElement{#phase="ask";#rating;#error="";#comment=el("textarea");#email=el("input");constructor(){super();this.#comment.rows=3,this.#comment.maxLength=5000,this.#comment.dir="auto",this.#comment.addEventListener("input",()=>this.#syncSend()),this.#email.type="email",this.#email.autocomplete="email"}get rating(){return this.#rating??null}reset(){this.#phase="ask",this.#error="",this.#comment.value="",this.#rating=this.channel?remembered(this.channel)[this.pageUrl]:void 0}pageChanged(){if(this.#phase==="ask"&&!this.#error)this.#rating=this.channel?remembered(this.channel)[this.pageUrl]:void 0;this.render()}async rate(rating){let channel=this.channel;if(!channel||this.refused||this.#phase==="rating"||this.#phase==="sending")return;let page=this.pageUrl,previous=remembered(channel)[page];if(this.#error="",previous===rating){this.#rating=rating,this.#phase=this.canWrite?"form":"thanks",this.render(),this.#comment.focus({preventScroll:!0});return}this.#phase="rating",this.#rating=rating,this.render();try{await this.client().ratePage({page,title:this.pageTitle||void 0,rating,previous})}catch(error){if(this.pageUrl!==page||this.refusal(error))return;this.#rating=previous,this.#phase="ask",this.#error=this.errorText(error),this.render();return}if(remember(channel,page,rating),this.emit("yuva-rating",{page,rating,previous:previous??null}),this.pageUrl!==page)return;this.#phase=this.canWrite?"form":"thanks",this.render(),this.#comment.focus({preventScroll:!0})}async#send(){let body=this.#comment.value.trim(),email=this.#email.value.trim(),rating=this.#rating;if(!body||this.#phase!=="form")return;if(email&&!this.#email.checkValidity()){this.#error=this.t({id:"E_qvzP"}),this.render();return}let page=this.pageUrl;this.#phase="sending",this.#error="",this.render();try{let{conversation}=await this.client().sendFeedback({page_url:page,page_title:this.pageTitle||void 0,rating,body,locale:this.locale,allow_email:this.identified||!!email,email:!this.identified&&email?email:void 0});if(this.emit("yuva-feedback",{page,rating:rating??null,conversation_id:conversation.id}),this.pageUrl!==page)return;this.#comment.value="",this.#phase="thanks"}catch(error){if(this.pageUrl!==page||this.refusal(error,!1))return;this.#phase="form",this.#error=this.errorText(error)}this.render()}#syncSend(){let send=this.root.querySelector(".send");if(send)send.disabled=this.#phase!=="form"||this.#comment.value.trim()===""}render(){if(this.refused||!this.channel){this.root.replaceChildren();return}let question=this.t({id:"SOvBw9"}),ask=el("div","ask");ask.setAttribute("role","group"),ask.setAttribute("aria-label",question);let choices=el("div","choices");for(let value of["up","down"]){let button=el("button","choice");button.type="button",button.innerHTML=thumb(value==="down"),button.append(el("span","",value==="up"?this.t({id:"l75CjT"}):this.t({id:"1UzENP"}))),button.setAttribute("aria-pressed",String(this.#rating===value)),button.disabled=this.#phase==="rating"||this.#phase==="sending",button.addEventListener("click",()=>void this.rate(value)),choices.append(button)}ask.append(el("p","question",question),choices);let children=[ask];if(this.#phase==="form"||this.#phase==="sending"){let form=el("form");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#send()});let prompt=this.#rating==="down"?this.t({id:"U7H5Fm"}):this.t({id:"EmiQvf"});if(this.#comment.placeholder=prompt,this.#comment.setAttribute("aria-label",prompt),this.#comment.disabled=this.#phase==="sending",form.append(this.#comment),!this.identified)this.#email.placeholder=this.t({id:"a_qtPP"}),this.#email.setAttribute("aria-label",this.t({id:"XJURKP"})),this.#email.disabled=this.#phase==="sending",form.append(this.#email);let skip=el("button","link",this.t({id:"tA4dAO"}));skip.type="button",skip.disabled=this.#phase==="sending",skip.addEventListener("click",()=>{this.#phase="thanks",this.#error="",this.render()});let send=el("button","send",this.#phase==="sending"?this.t({id:"Sad2tK"}):this.t({id:"JlFcis"}));send.type="submit";let actions=el("div","actions");actions.append(skip,send),form.append(actions),children.push(form)}else if(this.#phase==="thanks"){let thanks=el("p","muted",this.t({id:"d6N994"}));thanks.setAttribute("role","status"),children.push(thanks)}if(this.#error){let error=el("p","error",this.#error);error.setAttribute("role","alert"),children.push(error)}this.frame(styles2,...children),this.#syncSend()}}function defineDocs(){if(typeof customElements>"u")return;if(!customElements.get("yuva-discussions"))customElements.define("yuva-discussions",YuvaDiscussionsElement);if(!customElements.get("yuva-page-feedback"))customElements.define("yuva-page-feedback",YuvaPageFeedbackElement)}YuvaDiscussionsElement.loadThread=()=>import("./thread-
|
|
134
|
+
`;function storageKey(channel){return`yuva:${channel}:page-ratings`}function remembered(channel){try{let raw=localStorage.getItem(storageKey(channel));return raw?JSON.parse(raw):{}}catch{return{}}}function remember(channel,page,rating){try{let ratings=remembered(channel);delete ratings[page],ratings[page]=rating;let pages=Object.keys(ratings);for(let old of pages.slice(0,Math.max(0,pages.length-maxRemembered)))delete ratings[old];localStorage.setItem(storageKey(channel),JSON.stringify(ratings))}catch{}}class YuvaPageFeedbackElement extends YuvaDocsElement{#phase="ask";#rating;#error="";#comment=el("textarea");#email=el("input");constructor(){super();this.#comment.rows=3,this.#comment.maxLength=5000,this.#comment.dir="auto",this.#comment.addEventListener("input",()=>this.#syncSend()),this.#email.type="email",this.#email.autocomplete="email"}get rating(){return this.#rating??null}reset(){this.#phase="ask",this.#error="",this.#comment.value="",this.#rating=this.channel?remembered(this.channel)[this.pageUrl]:void 0}pageChanged(){if(this.#phase==="ask"&&!this.#error)this.#rating=this.channel?remembered(this.channel)[this.pageUrl]:void 0;this.render()}async rate(rating){let channel=this.channel;if(!channel||this.refused||this.#phase==="rating"||this.#phase==="sending")return;let page=this.pageUrl,previous=remembered(channel)[page];if(this.#error="",previous===rating){this.#rating=rating,this.#phase=this.canWrite?"form":"thanks",this.render(),this.#comment.focus({preventScroll:!0});return}this.#phase="rating",this.#rating=rating,this.render();try{await this.client().ratePage({page,title:this.pageTitle||void 0,rating,previous})}catch(error){if(this.pageUrl!==page||this.refusal(error))return;this.#rating=previous,this.#phase="ask",this.#error=this.errorText(error),this.render();return}if(remember(channel,page,rating),this.emit("yuva-rating",{page,rating,previous:previous??null}),this.pageUrl!==page)return;this.#phase=this.canWrite?"form":"thanks",this.render(),this.#comment.focus({preventScroll:!0})}async#send(){let body=this.#comment.value.trim(),email=this.#email.value.trim(),rating=this.#rating;if(!body||this.#phase!=="form")return;if(email&&!this.#email.checkValidity()){this.#error=this.t({id:"E_qvzP"}),this.render();return}let page=this.pageUrl;this.#phase="sending",this.#error="",this.render();try{let{conversation}=await this.client().sendFeedback({page_url:page,page_title:this.pageTitle||void 0,rating,body,locale:this.locale,allow_email:this.identified||!!email,email:!this.identified&&email?email:void 0});if(this.emit("yuva-feedback",{page,rating:rating??null,conversation_id:conversation.id}),this.pageUrl!==page)return;this.#comment.value="",this.#phase="thanks"}catch(error){if(this.pageUrl!==page||this.refusal(error,!1))return;this.#phase="form",this.#error=this.errorText(error)}this.render()}#syncSend(){let send=this.root.querySelector(".send");if(send)send.disabled=this.#phase!=="form"||this.#comment.value.trim()===""}render(){if(this.refused||!this.channel){this.root.replaceChildren();return}let question=this.t({id:"SOvBw9"}),ask=el("div","ask");ask.setAttribute("role","group"),ask.setAttribute("aria-label",question);let choices=el("div","choices");for(let value of["up","down"]){let button=el("button","choice");button.type="button",button.innerHTML=thumb(value==="down"),button.append(el("span","",value==="up"?this.t({id:"l75CjT"}):this.t({id:"1UzENP"}))),button.setAttribute("aria-pressed",String(this.#rating===value)),button.disabled=this.#phase==="rating"||this.#phase==="sending",button.addEventListener("click",()=>void this.rate(value)),choices.append(button)}ask.append(el("p","question",question),choices);let children=[ask];if(this.#phase==="form"||this.#phase==="sending"){let form=el("form");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#send()});let prompt=this.#rating==="down"?this.t({id:"U7H5Fm"}):this.t({id:"EmiQvf"});if(this.#comment.placeholder=prompt,this.#comment.setAttribute("aria-label",prompt),this.#comment.disabled=this.#phase==="sending",form.append(this.#comment),!this.identified)this.#email.placeholder=this.t({id:"a_qtPP"}),this.#email.setAttribute("aria-label",this.t({id:"XJURKP"})),this.#email.disabled=this.#phase==="sending",form.append(this.#email);let skip=el("button","link",this.t({id:"tA4dAO"}));skip.type="button",skip.disabled=this.#phase==="sending",skip.addEventListener("click",()=>{this.#phase="thanks",this.#error="",this.render()});let send=el("button","send",this.#phase==="sending"?this.t({id:"Sad2tK"}):this.t({id:"JlFcis"}));send.type="submit";let actions=el("div","actions");actions.append(skip,send),form.append(actions),children.push(form)}else if(this.#phase==="thanks"){let thanks=el("p","muted",this.t({id:"d6N994"}));thanks.setAttribute("role","status"),children.push(thanks)}if(this.#error){let error=el("p","error",this.#error);error.setAttribute("role","alert"),children.push(error)}this.frame(styles2,...children),this.#syncSend()}}function defineDocs(){if(typeof customElements>"u")return;if(!customElements.get("yuva-discussions"))customElements.define("yuva-discussions",YuvaDiscussionsElement);if(!customElements.get("yuva-page-feedback"))customElements.define("yuva-page-feedback",YuvaPageFeedbackElement)}YuvaDiscussionsElement.loadThread=()=>import("./thread-6dcd0yms.js");defineDocs();export{YuvaDiscussionsElement,YuvaPageFeedbackElement,defineDocs};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{translate,localeIn}from"./index-
|
|
1
|
+
import{translate,localeIn}from"./index-r9f9ttb2.js";var messages=JSON.parse('{"6I7cJR":["Open chat"],"OkHvGB":["Open chat, ",["count"]," unread"],"pqZJT2":["Close chat"]}');var messages2=JSON.parse('{"6I7cJR":["Chat öffnen"],"OkHvGB":["Chat öffnen, ",["count"]," ungelesen"],"pqZJT2":["Chat schließen"]}');var messages3=JSON.parse('{"6I7cJR":["Sohbeti aç"],"OkHvGB":["Sohbeti aç, ",["count"]," okunmamış"],"pqZJT2":["Sohbeti kapat"]}');var catalogs={en:messages,tr:messages3,de:messages2};function resolveLocale(...candidates){return localeIn(catalogs,candidates)}function catalogFor(locale){return catalogs[locale]??messages}function translatePlain(messages2,descriptor,fallback=messages){return translate(messages2,descriptor,fallback)}
|
|
2
2
|
export{resolveLocale,catalogFor,translatePlain};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function translate(messages,descriptor,fallback){let entry=messages[descriptor.id]??fallback[descriptor.id],values=descriptor.values??{};if(typeof entry==="string")return entry;if(Array.isArray(entry))return entry.map((part)=>typeof part==="string"?part:Array.isArray(part)?String(values[part[0]]??""):"").join("");return descriptor.message??descriptor.id}var rtlLanguages=new Set(["ar","fa","he","ur"]),sourceLocale="en";function localeIn(catalogs,candidates){for(let candidate of candidates){if(!candidate)continue;let tag=candidate.toLowerCase();if(catalogs[tag])return tag;let language=tag.split(/[-_]/)[0]??"";if(catalogs[language])return language}return sourceLocale}function directionOf(locale){return rtlLanguages.has(locale.split(/[-_]/)[0]??"")?"rtl":"ltr"}var sheets=new Map;function sheetFor(css){if(typeof CSSStyleSheet>"u"||!("replaceSync"in CSSStyleSheet.prototype))return null;let sheet=sheets.get(css);if(!sheet)sheet=new CSSStyleSheet,sheet.replaceSync(css),sheets.set(css,sheet);return sheet}function fallback(css){let style=document.createElement("style");return style.textContent=css,style}function addStyles(root,css){let sheet=sheetFor(css);if(!sheet||!(root instanceof ShadowRoot))return fallback(css);if(!root.adoptedStyleSheets.includes(sheet))root.adoptedStyleSheets=[...root.adoptedStyleSheets,sheet];return null}function setStyles(root,css){let sheet=sheetFor(css);if(!sheet)return fallback(css);return root.adoptedStyleSheets=[sheet],null}function launcherOf(inbox){return{position:inbox.chat.launcher_position,color:inbox.chat.launcher_color??inbox.branding.color}}function contrastOn(color){let n=Number.parseInt(color.slice(1),16),[r,g,b]=[n>>16&255,n>>8&255,n&255].map((c)=>{let s=c/255;return s<=0.03928?s/12.92:((s+0.055)/1.055)**2.4});return 0.2126*r+0.7152*g+0.0722*b>0.4?"#111827":"#ffffff"}function storageKey(channel){return`yuva:${channel}`}function readStored(channel){try{let raw=localStorage.getItem(storageKey(channel));return raw?JSON.parse(raw):{}}catch{return{}}}function writeStored(channel,state){try{localStorage.setItem(storageKey(channel),JSON.stringify(state))}catch{}}
|
|
2
|
+
export{translate,localeIn,directionOf,addStyles,setStyles,launcherOf,contrastOn,readStored,writeStored};
|
package/dist/esm/subscribe.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{el}from"./index-rdzxvj2r.js";import{ApiError2,call,mailingLists,createSubscription}from"./index-gk84nm8f.js";import{translate,localeIn,directionOf,contrastOn}from"./index-
|
|
1
|
+
import{el}from"./index-rdzxvj2r.js";import{ApiError2,call,mailingLists,createSubscription}from"./index-gk84nm8f.js";import{translate,localeIn,directionOf,setStyles,contrastOn}from"./index-r9f9ttb2.js";var messages=JSON.parse('{"-g5O6h":["Choose at least one list."],"1w51t9":["Subscribing…"],"EDl9kS":["Subscribe"],"E_LjOR":["Enter your name."],"E_qvzP":["Enter a valid e-mail address."],"GQVIIl":["You seem to be offline."],"ScJ9fj":["Privacy policy"],"XJURKP":["E-mail address"],"YnOaHp":["Your name (optional)"],"dMJfG5":["I want to receive e-mails about ",["list"]," from ",["inbox"],". I can unsubscribe at any time."],"eku1-t":["Your account has no e-mail address yet."],"h16FyT":["Lists"],"jWgNnM":["Could not subscribe. Try again."],"lDEbTy":["Tick the box to agree."],"q8yluz":["Your name"],"rgySXy":["Thanks! You are subscribed."],"tzsBOP":["Too many attempts. Wait a moment and try again."],"x6dU53":["Check your inbox to confirm."],"y3k2zM":["Almost done. Check your inbox and confirm your subscription."]}');var messages2=JSON.parse('{"-g5O6h":["Wählen Sie mindestens eine Liste."],"1w51t9":["Wird angemeldet…"],"EDl9kS":["Abonnieren"],"E_LjOR":["Geben Sie Ihren Namen ein."],"E_qvzP":["Geben Sie eine gültige E-Mail-Adresse ein."],"GQVIIl":["Sie scheinen offline zu sein."],"ScJ9fj":["Datenschutzerklärung"],"XJURKP":["E-Mail-Adresse"],"YnOaHp":["Ihr Name (optional)"],"dMJfG5":["Ich möchte E-Mails von ",["inbox"]," zu ",["list"]," erhalten. Ich kann mich jederzeit abmelden."],"eku1-t":["Ihr Konto hat noch keine E-Mail-Adresse."],"h16FyT":["Listen"],"jWgNnM":["Anmeldung fehlgeschlagen. Versuchen Sie es erneut."],"lDEbTy":["Setzen Sie das Häkchen, um zuzustimmen."],"q8yluz":["Ihr Name"],"rgySXy":["Danke! Sie sind angemeldet."],"tzsBOP":["Zu viele Versuche. Warten Sie einen Moment und versuchen Sie es erneut."],"x6dU53":["Sehen Sie zur Bestätigung in Ihr Postfach."],"y3k2zM":["Fast geschafft. Sehen Sie in Ihr Postfach und bestätigen Sie Ihr Abonnement."]}');var messages3=JSON.parse('{"-g5O6h":["En az bir liste seçin."],"1w51t9":["Abone olunuyor…"],"EDl9kS":["Abone ol"],"E_LjOR":["Adınızı girin."],"E_qvzP":["Geçerli bir e-posta adresi girin."],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"ScJ9fj":["Gizlilik politikası"],"XJURKP":["E-posta adresi"],"YnOaHp":["Adınız (isteğe bağlı)"],"dMJfG5":[["list"]," hakkında ",["inbox"]," tarafından gönderilen e-postaları almak istiyorum. Aboneliğimi istediğim zaman bırakabilirim."],"eku1-t":["Hesabınızda henüz bir e-posta adresi yok."],"h16FyT":["Listeler"],"jWgNnM":["Abone olunamadı. Yeniden deneyin."],"lDEbTy":["Onaylamak için kutuyu işaretleyin."],"q8yluz":["Adınız"],"rgySXy":["Teşekkürler! Abone oldunuz."],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"x6dU53":["Onaylamak için gelen kutunuza bakın."],"y3k2zM":["Neredeyse bitti. Gelen kutunuza bakın ve aboneliğinizi onaylayın."]}');var catalogs={en:messages,tr:messages3,de:messages2},tokenMinimumAge=2100,fetcher=(url,init)=>fetch(url,init),Base=typeof HTMLElement>"u"?class{}:HTMLElement,scriptSrc=typeof document<"u"&&document.currentScript instanceof HTMLScriptElement?document.currentScript.src:"",styles=`
|
|
2
2
|
:host{display:block;line-height:1.5}
|
|
3
3
|
:host([hidden]),[hidden]{display:none!important}
|
|
4
4
|
*{box-sizing:border-box}
|
|
@@ -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-ebw9d6ms.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 fallback=setStyles(this.#root,styles);this.#root.replaceChildren(...fallback?[fallback]:[],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{el}from"./index-rdzxvj2r.js";import{inlineNodes}from"./index-jdxce2se.js";import{translate}from"./index-
|
|
1
|
+
import{el}from"./index-rdzxvj2r.js";import{inlineNodes}from"./index-jdxce2se.js";import{translate}from"./index-r9f9ttb2.js";var messages=JSON.parse('{"2Hlmdt":["Write a reply…"],"3CApMv":["All discussions"],"3PqJQG":["Nothing to preview."],"4-S4QM":["Unmark as answer"],"5lWFkC":["Sign in"],"8wRl7c":["The opening post was deleted."],"99w-GZ":["Sign in to start a discussion. Your name is shown with your post."],"F_vGso":["Your reply"],"HkXOWm":["This reply was deleted."],"Hw3P48":["Replies: ",["0"]],"ImOQa9":["Reply"],"JfAIiv":["This discussion is locked. New replies are closed."],"Kl3TuI":["Get an e-mail when someone replies or an answer is accepted."],"Klsidc":["Delete this reply?"],"MHrjPM":["Title"],"MKEPCY":["Follow"],"NjUiZ4":["Ask a question, share an idea or describe a problem with this page."],"NrGspR":["Thanks! Your discussion will appear for everyone once the team approves it."],"OVijcR":["Remove your vote (",["0"]," votes)"],"PL0621":["Sign in to reply, vote and follow this discussion."],"PN38hZ":["Your question or idea"],"PZ_kxo":["Keep"],"Pwqkdw":["Loading…"],"RqsQKK":["Your first posts are checked by the team before they appear for everyone."],"Sad2tK":["Sending…"],"VGqKyv":["This discussion is no longer available."],"Vwy_nT":["Markdown is supported."],"YZayoP":["Thanks! Your reply will appear for everyone once the team approves it."],"cnGeoo":["Delete"],"dEgA5A":["Cancel"],"dNOvhg":["Upvote (",["0"]," votes)"],"ePK91l":["Edit"],"i4_LY_":["Write"],"jhu92n":["Mark as answer"],"k4b5_X":["edited"],"n5vqdp":["Start discussion"],"qzVesX":["Edit your post"],"rAl91-":["Delete this discussion?"],"rdUucN":["Preview"],"tfDRzk":["Save"],"y-KXxN":["Accepted answer"],"y6sq5j":["Following"],"z1qf6l":["Start a discussion"]}');var messages2=JSON.parse('{"2Hlmdt":["Antwort schreiben…"],"3CApMv":["Alle Diskussionen"],"3PqJQG":["Noch nichts für die Vorschau."],"4-S4QM":["Antwortmarkierung entfernen"],"5lWFkC":["Anmelden"],"8wRl7c":["Der erste Beitrag wurde gelöscht."],"99w-GZ":["Melden Sie sich an, um eine Diskussion zu starten. Ihr Name wird mit Ihrem Beitrag angezeigt."],"F_vGso":["Ihre Antwort"],"HkXOWm":["Diese Antwort wurde gelöscht."],"Hw3P48":["Antworten: ",["0"]],"ImOQa9":["Antworten"],"JfAIiv":["Diese Diskussion ist gesperrt. Neue Antworten sind nicht möglich."],"Kl3TuI":["Erhalten Sie eine E-Mail, wenn jemand antwortet oder eine Antwort akzeptiert wird."],"Klsidc":["Diese Antwort löschen?"],"MHrjPM":["Titel"],"MKEPCY":["Folgen"],"NjUiZ4":["Stellen Sie eine Frage, teilen Sie eine Idee oder beschreiben Sie ein Problem mit dieser Seite."],"NrGspR":["Danke! Ihre Diskussion ist für alle sichtbar, sobald das Team sie freigibt."],"OVijcR":["Stimme zurückziehen (",["0"]," Stimmen)"],"PL0621":["Melden Sie sich an, um zu antworten, abzustimmen und dieser Diskussion zu folgen."],"PN38hZ":["Ihre Frage oder Idee"],"PZ_kxo":["Behalten"],"Pwqkdw":["Wird geladen…"],"RqsQKK":["Ihre ersten Beiträge prüft das Team, bevor sie für alle sichtbar sind."],"Sad2tK":["Wird gesendet…"],"VGqKyv":["Diese Diskussion ist nicht mehr verfügbar."],"Vwy_nT":["Markdown wird unterstützt."],"YZayoP":["Danke! Ihre Antwort ist für alle sichtbar, sobald das Team sie freigibt."],"cnGeoo":["Löschen"],"dEgA5A":["Abbrechen"],"dNOvhg":["Zustimmen (",["0"]," Stimmen)"],"ePK91l":["Bearbeiten"],"i4_LY_":["Schreiben"],"jhu92n":["Als Antwort markieren"],"k4b5_X":["bearbeitet"],"n5vqdp":["Diskussion starten"],"qzVesX":["Beitrag bearbeiten"],"rAl91-":["Diese Diskussion löschen?"],"rdUucN":["Vorschau"],"tfDRzk":["Speichern"],"y-KXxN":["Akzeptierte Antwort"],"y6sq5j":["Gefolgt"],"z1qf6l":["Diskussion starten"]}');var messages3=JSON.parse('{"2Hlmdt":["Bir yanıt yazın…"],"3CApMv":["Tüm tartışmalar"],"3PqJQG":["Önizlenecek bir şey yok."],"4-S4QM":["Yanıt işaretini kaldır"],"5lWFkC":["Giriş yap"],"8wRl7c":["Açılış gönderisi silindi."],"99w-GZ":["Tartışma başlatmak için giriş yapın. Adınız gönderinizle birlikte gösterilir."],"F_vGso":["Yanıtınız"],"HkXOWm":["Bu yanıt silindi."],"Hw3P48":["Yanıtlar: ",["0"]],"ImOQa9":["Yanıtla"],"JfAIiv":["Bu tartışma kilitli. Yeni yanıt yazılamaz."],"Kl3TuI":["Biri yanıt yazdığında ya da bir yanıt kabul edildiğinde e-posta alın."],"Klsidc":["Bu yanıt silinsin mi?"],"MHrjPM":["Başlık"],"MKEPCY":["Takip et"],"NjUiZ4":["Bir soru sorun, bir fikir paylaşın ya da bu sayfadaki bir sorunu anlatın."],"NrGspR":["Teşekkürler! Tartışmanız ekip onayladığında herkese görünecek."],"OVijcR":["Oyunuzu geri alın (",["0"]," oy)"],"PL0621":["Bu tartışmada yanıt yazmak, oy vermek ve takip etmek için giriş yapın."],"PN38hZ":["Sorunuz ya da fikriniz"],"PZ_kxo":["Kalsın"],"Pwqkdw":["Yükleniyor…"],"RqsQKK":["İlk gönderileriniz herkese görünmeden önce ekip tarafından kontrol edilir."],"Sad2tK":["Gönderiliyor…"],"VGqKyv":["Bu tartışma artık mevcut değil."],"Vwy_nT":["Markdown desteklenir."],"YZayoP":["Teşekkürler! Yanıtınız ekip onayladığında herkese görünecek."],"cnGeoo":["Sil"],"dEgA5A":["Vazgeç"],"dNOvhg":["Oy ver (",["0"]," oy)"],"ePK91l":["Düzenle"],"i4_LY_":["Yaz"],"jhu92n":["Yanıt olarak işaretle"],"k4b5_X":["düzenlendi"],"n5vqdp":["Tartışmayı başlat"],"qzVesX":["Gönderinizi düzenleyin"],"rAl91-":["Bu tartışma silinsin mi?"],"rdUucN":["Önizleme"],"tfDRzk":["Kaydet"],"y-KXxN":["Kabul edilen yanıt"],"y6sq5j":["Takip ediliyor"],"z1qf6l":["Tartışma başlat"]}');var linkPattern=/\[([^\]\n]+)\]\(([^)\s]+)\)/g;function inline(text){let nodes=[],last=0;for(let match of text.matchAll(linkPattern)){let index=match.index??0;if(index>last)nodes.push(...inlineNodes(text.slice(last,index)));let[whole,label="",href=""]=match,url=null;try{url=new URL(href)}catch{}if(url&&(url.protocol==="http:"||url.protocol==="https:")){let a=document.createElement("a");a.href=url.href,a.target="_blank",a.rel="nofollow ugc noopener",a.append(...inlineNodes(label)),nodes.push(a)}else nodes.push(document.createTextNode(whole));last=index+whole.length}if(last<text.length)nodes.push(...inlineNodes(text.slice(last)));return nodes}function block(tag,lines){let element=document.createElement(tag);return element.append(...inline(lines.join(" "))),element}function preview(markdown){let fragment=document.createDocumentFragment(),lines=markdown.replace(/\r\n?/g,`
|
|
2
2
|
`).split(`
|
|
3
3
|
`),paragraph=[],list=null,quote=[],flush=()=>{if(paragraph.length)fragment.append(block("p",paragraph));if(quote.length){let element=document.createElement("blockquote");element.append(preview(quote.join(`
|
|
4
4
|
`))),fragment.append(element)}paragraph=[],quote=[],list=null};for(let i=0;i<lines.length;i++){let line=lines[i]??"",fence=/^\s*(```|~~~)/.exec(line);if(fence){flush();let code=[];while(++i<lines.length&&!(lines[i]??"").trimStart().startsWith(fence[1]??"```"))code.push(lines[i]??"");let pre=document.createElement("pre");pre.append(Object.assign(document.createElement("code"),{textContent:code.join(`
|