useyuva 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +89 -1
  2. package/dist/esm/chat.js +2 -2
  3. package/dist/esm/docs.js +134 -0
  4. package/dist/esm/index-dj5dhqc1.js +12 -0
  5. package/dist/esm/index-e2tek7yk.js +2 -0
  6. package/dist/esm/index-jdxce2se.js +4 -0
  7. package/dist/esm/index-rdzxvj2r.js +2 -0
  8. package/dist/esm/index.js +1 -1
  9. package/dist/esm/nuxt/module.js +20 -0
  10. package/dist/esm/nuxt/runtime/components.js +88 -0
  11. package/dist/esm/react.js +1 -1
  12. package/dist/esm/thread-3ydc3xfc.js +61 -0
  13. package/dist/esm/{yuva-chat-tebg111a.js → yuva-chat-86e4mz63.js} +2 -4
  14. package/dist/types/client/api.d.ts +17 -0
  15. package/dist/types/client/client.d.ts +23 -1
  16. package/dist/types/client/reader.d.ts +12 -0
  17. package/dist/types/docs/base.d.ts +43 -0
  18. package/dist/types/docs/define.d.ts +1 -0
  19. package/dist/types/docs/discussions.d.ts +22 -0
  20. package/dist/types/docs/dom.d.ts +1 -0
  21. package/dist/types/docs/feedback.d.ts +21 -0
  22. package/dist/types/docs/page.d.ts +2 -0
  23. package/dist/types/docs/preview.d.ts +1 -0
  24. package/dist/types/docs/thread.d.ts +71 -0
  25. package/dist/types/docs.d.ts +7 -0
  26. package/dist/types/element.d.ts +0 -1
  27. package/dist/types/i18n.d.ts +1 -1
  28. package/dist/types/index.d.ts +3 -2
  29. package/dist/types/locales/en/docs.d.ts +2 -0
  30. package/dist/types/locales/en/thread.d.ts +2 -0
  31. package/dist/types/locales/tr/docs.d.ts +2 -0
  32. package/dist/types/locales/tr/thread.d.ts +2 -0
  33. package/dist/types/nuxt/module.d.ts +12 -0
  34. package/dist/types/nuxt/runtime/components.d.ts +88 -0
  35. package/dist/types/react.d.ts +26 -2
  36. package/dist/types/schema.gen.d.ts +6638 -3874
  37. package/dist/types/translate.d.ts +2 -0
  38. package/dist/types/types.d.ts +1 -0
  39. package/dist/widget/yuva-docs-thread-4580g2ny.js +61 -0
  40. package/dist/yuva-chat.js +8 -8
  41. package/dist/yuva-docs.js +144 -0
  42. package/dist/yuva.js +2 -2
  43. package/package.json +39 -8
  44. package/dist/esm/index-d1vxbqpr.js +0 -12
  45. package/dist/esm/index-r5vcg0sx.js +0 -2
@@ -0,0 +1,61 @@
1
+ import{translate}from"./index-e2tek7yk.js";import{el}from"./index-rdzxvj2r.js";import{inlineNodes}from"./index-jdxce2se.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":["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
+ `).split(`
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
+ `))),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(`
5
+ `)})),fragment.append(pre);continue}if(/^\s*$/.test(line)){flush();continue}let quoted=/^\s*>\s?(.*)$/.exec(line);if(quoted){if(paragraph.length||list)flush();quote.push(quoted[1]??"");continue}let heading=/^\s*(#{1,6})\s+(.*)$/.exec(line);if(heading){flush(),fragment.append(block(`h${Math.min(6,(heading[1]?.length??1)+2)}`,[heading[2]??""]));continue}let item=/^\s*(?:([-*+])|(\d+)[.)])\s+(.*)$/.exec(line);if(item){let tag=item[1]?"ul":"ol";if(paragraph.length||quote.length||list&&list.tagName.toLowerCase()!==tag)flush();if(!list)list=document.createElement(tag),fragment.append(list);list.append(block("li",[item[3]??""]));continue}if(quote.length)flush();if(list&&/^\s{2,}/.test(line)){list.lastElementChild?.append(" ",...inline(line.trim()));continue}list=null,paragraph.push(line.trim())}return flush(),fragment}var editWindow=1800000,catalogs={en:messages,tr:messages2},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>`,checkCircle=svg('<circle cx="12" cy="12" r="9"/><path d="M8 12l3 3 5-6"/>'),backIcon=svg('<path d="M19 12H5M12 19l-7-7 7-7"/>'),bell=svg('<path d="M18 8a6 6 0 10-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.7 21a2 2 0 01-3.4 0"/>'),styles=`
6
+ .thread { display: flex; flex-direction: column; gap: 12px; }
7
+ .thread-head { display: flex; flex-direction: column; gap: 8px; }
8
+ .post { display: flex; gap: 12px; padding: 14px; border: 1px solid var(--yuva-border); border-radius: 12px; }
9
+ .post.accepted { border-color: var(--yuva-success); box-shadow: inset 0 0 0 1px var(--yuva-success); }
10
+ .post.pending { border-style: dashed; }
11
+ .side { display: flex; flex-direction: column; align-items: center; gap: 6px; }
12
+ .vote {
13
+ display: inline-flex; flex-direction: column; align-items: center; gap: 0; min-inline-size: 40px; padding: 4px 6px;
14
+ border: 1px solid var(--yuva-border); border-radius: 8px; background: none; cursor: pointer; font-size: 0.85em; font-weight: 600;
15
+ }
16
+ .vote:hover:not(:disabled) { border-color: var(--yuva-accent); }
17
+ .vote[aria-pressed="true"] { border-color: var(--yuva-accent); color: var(--yuva-accent); background: var(--yuva-soft); }
18
+ .post-body { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 8px; }
19
+ .post-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 0.88em; }
20
+ .name { font-weight: 600; }
21
+ .answer-label { display: flex; align-items: center; gap: 6px; color: var(--yuva-success); font-weight: 600; font-size: 0.85em; }
22
+ .tools { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; }
23
+ .children { display: flex; flex-direction: column; gap: 10px; margin-block-start: 4px; padding-inline-start: 14px; border-inline-start: 2px solid var(--yuva-border); }
24
+ .children .post { padding: 10px 0; border: 0; box-shadow: none; }
25
+ .children .post + .post { border-block-start: 1px solid var(--yuva-border); border-radius: 0; }
26
+ .deleted { font-style: italic; opacity: 0.65; }
27
+ .signin { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; padding: 14px; border: 1px solid var(--yuva-border); border-radius: 12px; }
28
+ .composer { display: flex; flex-direction: column; border: 1px solid var(--yuva-border); border-radius: 12px; overflow: hidden; }
29
+ .composer:focus-within { border-color: var(--yuva-accent); }
30
+ .composer .ctabs { display: flex; gap: 4px; padding: 0 8px; border-block-end: 1px solid var(--yuva-border); }
31
+ .composer .ctab { padding: 7px 10px; border: 0; border-block-end: 2px solid transparent; background: none; cursor: pointer; font-size: 0.88em; opacity: 0.75; margin-block-end: -1px; }
32
+ .composer .ctab[aria-selected="true"] { border-block-end-color: var(--yuva-accent); font-weight: 600; opacity: 1; }
33
+ .composer .ctab:focus-visible { outline: 2px solid var(--yuva-accent); outline-offset: -2px; }
34
+ .composer textarea, .composer .preview { border: 0; border-radius: 0; min-block-size: 110px; padding: 10px 12px; }
35
+ .composer textarea:focus-visible { outline: none; }
36
+ .composer .preview { overflow-wrap: anywhere; }
37
+ .composer .foot { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: space-between; padding: 8px 10px; border-block-start: 1px solid var(--yuva-border); }
38
+ .composer .hint { font-size: 0.8em; opacity: 0.7; }
39
+ .composer .buttons { display: flex; gap: 8px; margin-inline-start: auto; }
40
+ .field-title { font-size: 1.05em; font-weight: 600; }
41
+ .form { display: flex; flex-direction: column; gap: 10px; }
42
+ .md { overflow-wrap: anywhere; }
43
+ .md > :first-child { margin-block-start: 0; }
44
+ .md > :last-child { margin-block-end: 0; }
45
+ .md p, .md ul, .md ol, .md pre, .md blockquote, .md table { margin: 0 0 0.75em; }
46
+ .md h1, .md h2, .md h3, .md h4, .md h5, .md h6 { margin: 0.9em 0 0.4em; font-size: 1em; font-weight: 600; }
47
+ .md h1, .md h3 { font-size: 1.1em; }
48
+ .md ul, .md ol { padding-inline-start: 1.5em; }
49
+ .md a { color: var(--yuva-accent); }
50
+ .md code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.88em; padding: 1px 5px; border-radius: 5px; background: var(--yuva-soft); }
51
+ .md pre { padding: 10px 12px; border-radius: 8px; background: var(--yuva-soft); overflow-x: auto; }
52
+ .md pre code { padding: 0; background: none; }
53
+ .md blockquote { padding-inline-start: 12px; border-inline-start: 3px solid var(--yuva-border); opacity: 0.85; }
54
+ .md table { border-collapse: collapse; display: block; overflow-x: auto; }
55
+ .md th, .md td { border: 1px solid var(--yuva-border); padding: 4px 8px; }
56
+ .md img { max-inline-size: 100%; }
57
+ .md hr { border: 0; border-block-start: 1px solid var(--yuva-border); }
58
+ @media (max-width: 560px) {
59
+ .post { padding: 12px; gap: 10px; }
60
+ }
61
+ `;class Composer{area=el("textarea");previewing=!1;constructor(rows){this.area.rows=rows,this.area.maxLength=20000,this.area.dir="auto"}get value(){return this.area.value.trim()}clear(){this.area.value="",this.previewing=!1}}function createThread(host){let s=host.s,t=(descriptor)=>translate(catalogs[host.locale()]??messages,descriptor,messages),reply=new Composer(4),draft=new Composer(6),title=el("input"),inline=null,edit=null;title.maxLength=200,title.dir="auto",title.className="field-title";for(let area of[reply.area,draft.area])area.addEventListener("input",()=>syncSend());title.addEventListener("input",()=>syncSend());function syncSend(){for(let button of host.root.querySelectorAll("[data-requires]")){let needs=button.dataset.requires,busy=s.busy.has(button.dataset.busy??""),ok=needs==="start"?title.value.trim().length>=3&&draft.value!=="":needs==="reply"?reply.value!=="":needs==="inline"?!!inline?.composer.value:needs==="edit"?!!edit?.composer.value&&(!!edit.post||edit.title.value.trim().length>=3):!0;button.disabled=busy||!ok}}async function start(){let heading=title.value.trim(),body=draft.value;if(heading.length<3||!body)return;let page=host.page(),discussion=await host.act("start",()=>host.client().startDiscussion({page_url:page,page_title:host.pageTitle()||void 0,title:heading,body}));if(!discussion)return;if(host.forget(),host.emit("yuva-discussion",{page,discussion_id:discussion.id,state:discussion.state}),host.page()!==page)return;title.value="",draft.clear(),s.items=[discussion,...s.items.filter((d)=>d.id!==discussion.id)],s.notice=discussion.state==="pending"?t({id:"NrGspR"}):"",s.thread={discussion,posts:[]},await host.open(discussion.id,!0)}async function send(composer,parent){let thread=s.thread,body=composer.value;if(!thread||!body)return;let page=host.page(),id=thread.discussion.id,post=await host.act(parent?`reply-${parent}`:"reply",()=>host.client().replyToDiscussion(id,{body,parent_post_id:parent}));if(!post)return;if(host.forget(),host.emit("yuva-post",{page,discussion_id:id,post_id:post.id,state:post.state}),composer.clear(),parent)inline=null;if(s.notice=post.state==="pending"?t({id:"YZayoP"}):"",s.thread?.discussion.id===id)s.thread={...s.thread,posts:[...s.thread.posts,post]},s.focus=`post-${post.id}`,host.render(),host.open(id,!1)}async function vote(post,opening){if(!s.writer)return void host.signIn();let updated=await host.act(`vote-${post.id}`,()=>host.client().voteDiscussionPost(post.id,!post.voted));if(!updated||!s.thread)return;if(host.forget(),opening){let discussion={...s.thread.discussion,votes:updated.votes,voted:updated.voted};s.thread={...s.thread,discussion},s.items=s.items.map((d)=>d.id===discussion.id?discussion:d)}else s.thread={...s.thread,posts:s.thread.posts.map((p)=>p.id===updated.id?{...p,...updated}:p)}}async function follow(){let thread=s.thread;if(!thread)return;if(!s.writer)return void host.signIn();let following=!thread.discussion.following;if(await host.act("follow",()=>host.client().followDiscussion(thread.discussion.id,following).then(()=>!0))&&s.thread?.discussion.id===thread.discussion.id)s.thread={...s.thread,discussion:{...s.thread.discussion,following}}}async function accept(post){let thread=s.thread;if(!thread)return;let discussion=await host.act(`accept-${post?.id??"clear"}`,()=>host.client().acceptDiscussionAnswer(thread.discussion.id,post?.id??null));if(!discussion)return;host.forget(),s.focus=post?`post-${post.id}`:"thread-title",await host.open(discussion.id,!1)}async function saveEdit(){let current=edit,thread=s.thread;if(!current||!thread)return;let body=current.composer.value,opening=!current.post,heading=current.title.value.trim();if(!body||opening&&heading.length<3)return;let postId=current.post?.id??thread.discussion.opening_post_id;if(!await host.act(`edit-${postId}`,()=>host.client().editDiscussionPost(postId,opening?{body,title:heading}:{body})))return;host.forget(),edit=null,s.focus=opening?"thread-title":`post-${postId}`,await host.open(thread.discussion.id,!1)}async function remove(postId,opening){let thread=s.thread;if(!thread)return;let done=await host.act(`delete-${postId}`,()=>host.client().deleteDiscussionPost(postId).then(()=>!0));if(s.confirm="",!done)return;if(host.forget(),opening)try{await host.client().getDiscussion(thread.discussion.id)}catch{return s.items=s.items.filter((d)=>d.id!==thread.discussion.id),s.thread=null,host.toList()}await host.open(thread.discussion.id,!1)}function md(html){let body=el("div","md");body.dir="auto",body.innerHTML=html;for(let link of body.querySelectorAll("a[href]"))link.setAttribute("target","_blank");return body}function composerBox(composer,options){let box=el("div","composer"),tabs=el("div","ctabs");tabs.setAttribute("role","tablist"),tabs.setAttribute("aria-label",options.label);let panelId=`p-${options.focusKey}`,write=host.button("ctab",t({id:"i4_LY_"}),`${options.focusKey}-write`,()=>{composer.previewing=!1,s.focus=options.focusKey,host.render()}),show=host.button("ctab",t({id:"rdUucN"}),`${options.focusKey}-preview`,()=>{composer.previewing=!0,host.render()});for(let[tab,selected]of[[write,!composer.previewing],[show,composer.previewing]])tab.setAttribute("role","tab"),tab.setAttribute("aria-selected",String(selected)),tab.setAttribute("aria-controls",panelId),tab.tabIndex=selected?0:-1,tab.addEventListener("keydown",(event)=>{if(event.key!=="ArrowLeft"&&event.key!=="ArrowRight")return;event.preventDefault(),composer.previewing=!composer.previewing,s.focus=`${options.focusKey}-${composer.previewing?"preview":"write"}`,host.render()});if(tabs.append(write,show),box.append(tabs),composer.previewing){let panel=el("div","preview md");if(panel.dir="auto",panel.id=panelId,panel.setAttribute("role","tabpanel"),panel.setAttribute("aria-label",t({id:"rdUucN"})),composer.value)panel.append(preview(composer.area.value));else panel.append(el("p","muted",t({id:"3PqJQG"})));box.append(panel)}else composer.area.id=panelId,composer.area.placeholder=options.placeholder,composer.area.setAttribute("aria-label",options.label),composer.area.dataset.key=options.focusKey,composer.area.disabled=s.busy.has(options.busy),composer.area.onkeydown=(event)=>{if(event.key==="Enter"&&(event.metaKey||event.ctrlKey))event.preventDefault(),options.onSubmit();else if(event.key==="Escape"&&options.onCancel)options.onCancel()},box.append(composer.area);let foot=el("div","foot");foot.append(el("span","hint",t({id:"Vwy_nT"})));let buttons=el("div","buttons");if(options.onCancel)buttons.append(host.button("ghost",t({id:"dEgA5A"}),`${options.focusKey}-cancel`,options.onCancel));let submit=host.button("send",s.busy.has(options.busy)?t({id:"Sad2tK"}):options.submit,`${options.focusKey}-submit`,options.onSubmit);return submit.dataset.requires=options.requires,submit.dataset.busy=options.busy,buttons.append(submit),foot.append(buttons),box.append(foot),box}function signInBox(text){let box=el("div","signin");return box.append(el("p","",text)),box.append(host.button("send",t({id:"5lWFkC"}),"sign-in-box",()=>void host.signIn())),box}function back(){let button=host.button("plain",t({id:"3CApMv"}),"back",()=>host.toList(),backIcon);button.style.alignSelf="flex-start",button.style.display="inline-flex",button.style.gap="6px",button.style.alignItems="center";let arrow=button.querySelector("svg");if(arrow&&host.direction()==="rtl")arrow.style.transform="scaleX(-1)";return button}function newView(){let form=el("div","form");if(form.append(el("h3","",t({id:"z1qf6l"}))),!s.writer)return form.append(signInBox(t({id:"99w-GZ"}))),[back(),form];if(title.placeholder=t({id:"MHrjPM"}),title.setAttribute("aria-label",t({id:"MHrjPM"})),title.dataset.key="new-title",title.disabled=s.busy.has("start"),form.append(title),form.append(composerBox(draft,{label:t({id:"PN38hZ"}),placeholder:t({id:"NjUiZ4"}),submit:t({id:"n5vqdp"}),busy:"start",requires:"start",focusKey:"new-body",onSubmit:()=>void start(),onCancel:()=>host.toList()})),host.mode()==="moderated"&&s.reader)form.append(el("p","muted",t({id:"RqsQKK"})));return[back(),form]}function editable(post){return!!post.mine&&!s.thread?.discussion.locked&&Date.now()-Date.parse(post.created_at)<editWindow}function postTools(post,top){let thread=s.thread;if(!thread)return null;let discussion=thread.discussion,opening=!post,id=post?.id??discussion.opening_post_id,mine=opening?!!discussion.mine:!!post.mine,deleted=opening?!!discussion.deleted:post.deleted,tools=el("div","tools");if(deleted)return null;if(!opening&&top&&!discussion.locked&&s.writer&&post.state==="published")tools.append(host.button("plain",t({id:"ImOQa9"}),`reply-to-${post.id}`,()=>{inline=inline?.target===top.id?inline:{target:top.id,composer:new Composer(3)},inline.composer.area.oninput=()=>syncSend(),s.focus=`inline-${top.id}`,host.render()}));if(!opening&&discussion.mine&&!post.parent_post_id&&post.state==="published"&&!discussion.locked){let accepted=discussion.answer_post_id===post.id,button=host.button("plain",accepted?t({id:"4-S4QM"}):t({id:"jhu92n"}),`accept-${post.id}`,()=>void accept(accepted?null:post),accepted?"":checkCircle);button.style.display="inline-flex",button.style.gap="4px",button.style.alignItems="center",button.disabled=s.busy.has(`accept-${post.id}`)||s.busy.has("accept-clear"),tools.append(button)}if(mine&&editable(opening?discussion:post))tools.append(host.button("plain",t({id:"ePK91l"}),`edit-${id}`,()=>{let composer=new Composer(opening?6:4);composer.area.value=opening?discussion.body:post.body,composer.area.oninput=()=>syncSend();let heading=el("input");heading.className="field-title",heading.maxLength=200,heading.dir="auto",heading.value=discussion.title,heading.oninput=()=>syncSend(),edit={post,composer,title:heading},s.focus=opening?"edit-title":`edit-body-${id}`,host.render()}));if(mine)if(s.confirm===id){let yes=host.button("plain danger",t({id:"cnGeoo"}),`delete-yes-${id}`,()=>void remove(id,opening));yes.disabled=s.busy.has(`delete-${id}`),tools.append(el("span","muted",opening?t({id:"rAl91-"}):t({id:"Klsidc"})),yes,host.button("plain",t({id:"PZ_kxo"}),`delete-no-${id}`,()=>{s.confirm="",s.focus=`delete-${id}`,host.render()}))}else tools.append(host.button("plain",t({id:"cnGeoo"}),`delete-${id}`,()=>{s.confirm=id,s.focus=`delete-no-${id}`,host.render()}));return tools.childElementCount?tools:null}function voteButton(target,opening){let button=host.button("vote",String(target.votes),`vote-${target.id}`,()=>void vote(target,opening),host.icons.up);return button.setAttribute("aria-pressed",String(!!target.voted)),button.setAttribute("aria-label",target.voted?t({id:"OVijcR",values:{0:target.votes}}):t({id:"dNOvhg",values:{0:target.votes}})),button.disabled=!!target.mine||!!s.thread?.discussion.locked||s.busy.has(`vote-${target.id}`),button}function postCard(post,top,children=[]){let accepted=s.thread.discussion.answer_post_id===post.id,card=el("article",`post${accepted?" accepted":""}${post.state==="pending"?" pending":""}`);card.dataset.key=`post-${post.id}`,card.tabIndex=-1,card.setAttribute("aria-label",host.authorName(post.author));let side=el("div","side");if(!post.deleted)side.append(voteButton(post,!1));if(!top||top.id===post.id)card.append(side);let body=el("div","post-body");if(accepted){let label=el("div","answer-label");label.innerHTML=checkCircle,label.append(t({id:"y-KXxN"})),body.append(label)}if(body.append(postHead(post.author,post.created_at,post.edited_at,post.state,post.deleted)),edit?.post?.id===post.id)body.append(editForm());else if(post.deleted)body.append(el("p","deleted",t({id:"HkXOWm"})));else body.append(md(post.body_html));let tools=postTools(post,top);if(tools)body.append(tools);if(children.length||inline?.target===post.id){let nested=el("div","children");for(let child of children)nested.append(postCard(child,post));if(inline?.target===post.id){let current=inline;nested.append(composerBox(current.composer,{label:t({id:"F_vGso"}),placeholder:t({id:"2Hlmdt"}),submit:t({id:"ImOQa9"}),busy:`reply-${post.id}`,requires:"inline",focusKey:`inline-${post.id}`,onSubmit:()=>void send(current.composer,post.id),onCancel:()=>{inline=null,s.focus=`reply-to-${post.id}`,host.render()}}))}body.append(nested)}return card.append(body),card}function postHead(author,created,edited,state,deleted){let head=el("div","post-head");if(!deleted){if(head.append(host.avatar(author,!0),el("span","name",host.authorName(author))),author.kind==="member"&&!author.deleted)head.append(host.badge("team"))}if(head.append(host.time(created)),edited&&!deleted)head.append(el("span","muted",t({id:"k4b5_X"})));if(state==="pending")head.append(host.badge("pending"));return head}function editForm(){let current=edit,form=el("div","form");if(!current.post)current.title.setAttribute("aria-label",t({id:"MHrjPM"})),current.title.dataset.key="edit-title",form.append(current.title);let id=current.post?.id??s.thread.discussion.opening_post_id;return form.append(composerBox(current.composer,{label:t({id:"qzVesX"}),placeholder:"",submit:t({id:"tfDRzk"}),busy:`edit-${id}`,requires:"edit",focusKey:`edit-body-${id}`,onSubmit:()=>void saveEdit(),onCancel:()=>{edit=null,s.focus=`edit-${id}`,host.render()}})),form}function threadView(){let nodes=[back()],thread=s.thread;if(!thread||s.threadState==="missing"){let box=el("div","empty");return box.append(el("p","",s.threadState==="loading"?t({id:"Pwqkdw"}):t({id:"VGqKyv"}))),nodes.push(box),nodes}let discussion=thread.discussion,view=el("div","thread"),head=el("div","thread-head");if(edit&&!edit.post)head.append(postHead(discussion.author,discussion.created_at,discussion.edited_at,discussion.state,!1)),head.append(editForm()),view.append(head);else{let heading=el("h3","",discussion.title);heading.dir="auto",heading.tabIndex=-1,heading.dataset.key="thread-title",head.append(heading);let meta=el("div","meta");if(discussion.answer_post_id)meta.append(host.badge("answered"));if(discussion.state==="pending")meta.append(host.badge("pending"));if(discussion.locked)meta.append(host.badge("locked"));if(meta.childElementCount)head.append(meta);view.append(head);let opening=el("article",`post${discussion.state==="pending"?" pending":""}`),side=el("div","side");if(!discussion.deleted)side.append(voteButton({id:discussion.opening_post_id,votes:discussion.votes,voted:discussion.voted,mine:discussion.mine},!0));let body=el("div","post-body");body.append(postHead(discussion.author,discussion.created_at,discussion.edited_at,discussion.state,!!discussion.deleted)),body.append(discussion.deleted?el("p","deleted",t({id:"8wRl7c"})):md(discussion.body_html));let tools=postTools(null,null);if(tools)body.append(tools);opening.append(side,body),view.append(opening)}let actions=el("div","bar"),followButton=host.button("ghost",discussion.following?t({id:"y6sq5j"}):t({id:"MKEPCY"}),"follow",()=>void follow(),bell);followButton.setAttribute("aria-pressed",String(!!discussion.following)),followButton.title=t({id:"Kl3TuI"}),followButton.disabled=s.busy.has("follow");let count=el("span","muted",t({id:"Hw3P48",values:{0:discussion.reply_count}}));if(actions.append(count,followButton),view.append(actions),s.threadState==="loading"&&!thread.posts.length&&discussion.reply_count>0){let skeleton=el("div","skeleton");skeleton.setAttribute("aria-busy","true"),skeleton.setAttribute("aria-label",t({id:"Pwqkdw"})),view.append(skeleton)}let tops=thread.posts.filter((p)=>!p.parent_post_id),replies=el("div","thread");for(let top of tops)replies.append(postCard(top,top,thread.posts.filter((p)=>p.parent_post_id===top.id)));if(tops.length)view.append(replies);if(s.notice)view.append(host.noticeBox(s.notice));if(discussion.locked)view.append(host.noticeBox(t({id:"JfAIiv"}),host.icons.lock));else if(!s.writer)view.append(signInBox(t({id:"PL0621"})));else view.append(composerBox(reply,{label:t({id:"F_vGso"}),placeholder:t({id:"2Hlmdt"}),submit:t({id:"ImOQa9"}),busy:"reply",requires:"reply",focusKey:"reply",onSubmit:()=>void send(reply)}));return nodes.push(view),nodes}return{threadView,newView,syncSend,close(){inline=null,edit=null},reset(){inline=null,edit=null,reply.clear()}}}export{createThread,styles};
@@ -1,4 +1,4 @@
1
- import{ApiError2,randomId,createYuvaClient2}from"./index-d1vxbqpr.js";import{launcherOf,readStored,writeStored}from"./index-r5vcg0sx.js";import{setupI18n}from"@lingui/core";var messages=JSON.parse(`{"-HY5kX":["New conversation"],"-f5Tkb":["Bad"],"09Tv5j":["Reconnecting…"],"0XGLbP":["Your sign-in has expired. Reload the page and try again."],"1EICzz":["We're away right now"],"4TqZiz":["Could not send your rating. Try again."],"6Uau97":["Skip"],"6gRgw8":["Retry"],"6lGaum":["Seen"],"ASr-r0":["Show older conversations"],"Amai22":["Chat is not available right now."],"E_qvzP":["Enter a valid e-mail address."],"GQVIIl":["You seem to be offline."],"JkW3Ph":["This file type is not accepted."],"JlFcis":["Send"],"KDw4GX":["Try again"],"M62PBt":["Nobody is available right now. Leave your e-mail and we'll send the reply there too."],"N7m8E-":["Attach files"],"NBdIgR":["Comment"],"OEEQKT":["Good"],"Pwqkdw":["Loading…"],"PxYAul":["Typing…"],"RzWUUK":["Write a message…"],"S63MQu":["All conversations"],"SOk0EB":["Thanks for your feedback"],"Sad2tK":["Sending…"],"SdV5Cn":["Send us a message and we will reply here."],"UY1vmE":["Attachment"],"VggdQJ":["Usually replies in ",["duration"]],"XJURKP":["E-mail address"],"YyNOE7":["Conversation"],"ZxJcgC":["Could not save your e-mail address. Try again."],"axQ1h6":["Anything you'd like to add? (optional)"],"eOu9Px":["The file is too large."],"h69WC6":["Sent"],"iGNUZJ":["Thanks! We'll e-mail you at ",["known"]," if you're gone when we reply."],"meAa31":["No conversations yet"],"nhTADq":["We'll reply as soon as we can"],"njBr8W":["you@example.com"],"oXOSPE":["Online"],"t7TeQU":["Messages"],"tHaDPf":[["name"]," is typing…"],"tfDRzk":["Save"],"tzsBOP":["Too many attempts. Wait a moment and try again."],"uA8iBc":["How did we do?"],"upFvcp":["Not sent."],"w61W3L":["Remove ",["0"]],"xDAtGP":["Message"],"ydzYKJ":["You:"],"yz7wBu":["Close"],"zLzEI3":["Sign in to chat with us."]}`);var messages2=JSON.parse('{"-HY5kX":["Yeni konuşma"],"-f5Tkb":["Kötü"],"09Tv5j":["Yeniden bağlanıyor…"],"0XGLbP":["Oturumunuzun süresi doldu. Sayfayı yenileyip tekrar deneyin."],"1EICzz":["Şu anda uzaktayız"],"4TqZiz":["Değerlendirmeniz gönderilemedi. Tekrar deneyin."],"6Uau97":["Geç"],"6gRgw8":["Tekrar dene"],"6lGaum":["Görüldü"],"ASr-r0":["Eski konuşmaları göster"],"Amai22":["Sohbet şu anda kullanılamıyor."],"E_qvzP":["Geçerli bir e-posta adresi girin."],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"JkW3Ph":["Bu dosya türü kabul edilmiyor."],"JlFcis":["Gönder"],"KDw4GX":["Tekrar dene"],"M62PBt":["Şu anda müsait kimse yok. E-posta adresinizi bırakın, yanıtı oraya da gönderelim."],"N7m8E-":["Dosya ekle"],"NBdIgR":["Yorum"],"OEEQKT":["İyi"],"Pwqkdw":["Yükleniyor…"],"PxYAul":["Yazıyor…"],"RzWUUK":["Bir mesaj yazın…"],"S63MQu":["Tüm konuşmalar"],"SOk0EB":["Geri bildiriminiz için teşekkürler"],"Sad2tK":["Gönderiliyor…"],"SdV5Cn":["Bize bir mesaj gönderin, yanıtımız burada görünecek."],"UY1vmE":["Ek"],"VggdQJ":["Genellikle ",["duration"]," içinde yanıt verir"],"XJURKP":["E-posta adresi"],"YyNOE7":["Konuşma"],"ZxJcgC":["E-posta adresiniz kaydedilemedi. Tekrar deneyin."],"axQ1h6":["Eklemek istediğiniz bir şey var mı? (isteğe bağlı)"],"eOu9Px":["Dosya çok büyük."],"h69WC6":["Gönderildi"],"iGNUZJ":["Teşekkürler! Yanıtladığımızda burada değilseniz ",["known"]," adresine e-posta göndereceğiz."],"meAa31":["Henüz konuşma yok"],"nhTADq":["En kısa sürede yanıt vereceğiz"],"njBr8W":["siz@ornek.com"],"oXOSPE":["Çevrimiçi"],"t7TeQU":["Mesajlar"],"tHaDPf":[["name"]," yazıyor…"],"tfDRzk":["Kaydet"],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"uA8iBc":["Nasıldık?"],"upFvcp":["Gönderilemedi."],"w61W3L":[["0"]," kaldır"],"xDAtGP":["Mesaj"],"ydzYKJ":["Siz:"],"yz7wBu":["Kapat"],"zLzEI3":["Bizimle sohbet etmek için giriş yapın."]}');var styles=`
1
+ import{launcherOf,readStored,writeStored}from"./index-e2tek7yk.js";import{ApiError2,randomId,createYuvaClient2}from"./index-dj5dhqc1.js";import{richText}from"./index-jdxce2se.js";import{setupI18n}from"@lingui/core";var messages=JSON.parse(`{"-HY5kX":["New conversation"],"-f5Tkb":["Bad"],"09Tv5j":["Reconnecting…"],"0XGLbP":["Your sign-in has expired. Reload the page and try again."],"1EICzz":["We're away right now"],"4TqZiz":["Could not send your rating. Try again."],"6Uau97":["Skip"],"6gRgw8":["Retry"],"6lGaum":["Seen"],"ASr-r0":["Show older conversations"],"Amai22":["Chat is not available right now."],"E_qvzP":["Enter a valid e-mail address."],"GQVIIl":["You seem to be offline."],"JkW3Ph":["This file type is not accepted."],"JlFcis":["Send"],"KDw4GX":["Try again"],"M62PBt":["Nobody is available right now. Leave your e-mail and we'll send the reply there too."],"N7m8E-":["Attach files"],"NBdIgR":["Comment"],"OEEQKT":["Good"],"Pwqkdw":["Loading…"],"PxYAul":["Typing…"],"RzWUUK":["Write a message…"],"S63MQu":["All conversations"],"SOk0EB":["Thanks for your feedback"],"Sad2tK":["Sending…"],"SdV5Cn":["Send us a message and we will reply here."],"UY1vmE":["Attachment"],"VggdQJ":["Usually replies in ",["duration"]],"XJURKP":["E-mail address"],"YyNOE7":["Conversation"],"ZxJcgC":["Could not save your e-mail address. Try again."],"axQ1h6":["Anything you'd like to add? (optional)"],"eOu9Px":["The file is too large."],"h69WC6":["Sent"],"iGNUZJ":["Thanks! We'll e-mail you at ",["known"]," if you're gone when we reply."],"meAa31":["No conversations yet"],"nhTADq":["We'll reply as soon as we can"],"njBr8W":["you@example.com"],"oXOSPE":["Online"],"t7TeQU":["Messages"],"tHaDPf":[["name"]," is typing…"],"tfDRzk":["Save"],"tzsBOP":["Too many attempts. Wait a moment and try again."],"uA8iBc":["How did we do?"],"upFvcp":["Not sent."],"w61W3L":["Remove ",["0"]],"xDAtGP":["Message"],"ydzYKJ":["You:"],"yz7wBu":["Close"],"zLzEI3":["Sign in to chat with us."]}`);var messages2=JSON.parse('{"-HY5kX":["Yeni konuşma"],"-f5Tkb":["Kötü"],"09Tv5j":["Yeniden bağlanıyor…"],"0XGLbP":["Oturumunuzun süresi doldu. Sayfayı yenileyip tekrar deneyin."],"1EICzz":["Şu anda uzaktayız"],"4TqZiz":["Değerlendirmeniz gönderilemedi. Tekrar deneyin."],"6Uau97":["Geç"],"6gRgw8":["Tekrar dene"],"6lGaum":["Görüldü"],"ASr-r0":["Eski konuşmaları göster"],"Amai22":["Sohbet şu anda kullanılamıyor."],"E_qvzP":["Geçerli bir e-posta adresi girin."],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"JkW3Ph":["Bu dosya türü kabul edilmiyor."],"JlFcis":["Gönder"],"KDw4GX":["Tekrar dene"],"M62PBt":["Şu anda müsait kimse yok. E-posta adresinizi bırakın, yanıtı oraya da gönderelim."],"N7m8E-":["Dosya ekle"],"NBdIgR":["Yorum"],"OEEQKT":["İyi"],"Pwqkdw":["Yükleniyor…"],"PxYAul":["Yazıyor…"],"RzWUUK":["Bir mesaj yazın…"],"S63MQu":["Tüm konuşmalar"],"SOk0EB":["Geri bildiriminiz için teşekkürler"],"Sad2tK":["Gönderiliyor…"],"SdV5Cn":["Bize bir mesaj gönderin, yanıtımız burada görünecek."],"UY1vmE":["Ek"],"VggdQJ":["Genellikle ",["duration"]," içinde yanıt verir"],"XJURKP":["E-posta adresi"],"YyNOE7":["Konuşma"],"ZxJcgC":["E-posta adresiniz kaydedilemedi. Tekrar deneyin."],"axQ1h6":["Eklemek istediğiniz bir şey var mı? (isteğe bağlı)"],"eOu9Px":["Dosya çok büyük."],"h69WC6":["Gönderildi"],"iGNUZJ":["Teşekkürler! Yanıtladığımızda burada değilseniz ",["known"]," adresine e-posta göndereceğiz."],"meAa31":["Henüz konuşma yok"],"nhTADq":["En kısa sürede yanıt vereceğiz"],"njBr8W":["siz@ornek.com"],"oXOSPE":["Çevrimiçi"],"t7TeQU":["Mesajlar"],"tHaDPf":[["name"]," yazıyor…"],"tfDRzk":["Kaydet"],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"uA8iBc":["Nasıldık?"],"upFvcp":["Gönderilemedi."],"w61W3L":[["0"]," kaldır"],"xDAtGP":["Mesaj"],"ydzYKJ":["Siz:"],"yz7wBu":["Kapat"],"zLzEI3":["Bizimle sohbet etmek için giriş yapın."]}');var styles=`
2
2
  [hidden] { display: none !important; }
3
3
  .header {
4
4
  display: flex;
@@ -190,6 +190,4 @@ import{ApiError2,randomId,createYuvaClient2}from"./index-d1vxbqpr.js";import{lau
190
190
  .banner { padding: 6px 12px; background: var(--yuva-soft); color: var(--yuva-muted); font-size: 13px; text-align: center; }
191
191
  @media (max-width: 480px) { .composer textarea, .card input, .card textarea { font-size: 16px; } }
192
192
  .sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
193
- `;var inline=/(`[^`\n]+`)|(\*\*[^*\n]+\*\*)|(\*[^*\s][^*\n]*\*|_[^_\s][^_\n]*_)|((?:https?:\/\/|www\.)[^\s<>"]*[^\s<>".,:;'!?)\]])/g;function link(href,text){let a=document.createElement("a");return a.href=href,a.textContent=text,a.target="_blank",a.rel="noopener noreferrer nofollow ugc",a}function wrap(tag,children){let element=document.createElement(tag);return element.append(...children),element}function inlineNodes(text){let nodes=[],last=0;for(let match of text.matchAll(inline)){let index=match.index??0;if(index>last)nodes.push(document.createTextNode(text.slice(last,index)));let[whole,code,bold,italic,url]=match;if(code)nodes.push(wrap("code",[document.createTextNode(code.slice(1,-1))]));else if(bold)nodes.push(wrap("strong",inlineNodes(bold.slice(2,-2))));else if(italic)nodes.push(wrap("em",inlineNodes(italic.slice(1,-1))));else if(url){let href=url.startsWith("www.")?`https://${url}`:url;try{let parsed=new URL(href);nodes.push(parsed.protocol==="http:"||parsed.protocol==="https:"?link(parsed.href,url):document.createTextNode(url))}catch{nodes.push(document.createTextNode(url))}}last=index+whole.length}if(last<text.length)nodes.push(document.createTextNode(text.slice(last)));return nodes}function richText(body){let fragment=document.createDocumentFragment(),parts=body.trim().replace(/\r\n?/g,`
194
- `).split(/^```[^\n]*\n([\s\S]*?)^```[ \t]*$/m);return parts.forEach((part,i)=>{if(i%2===1){let pre=document.createElement("pre");pre.textContent=part.replace(/\n$/,""),fragment.append(pre);return}(parts.length>1?part.replace(/^\n|\n$/g,""):part).split(`
195
- `).forEach((line,n)=>{if(n>0)fragment.append(document.createElement("br"));fragment.append(...inlineNodes(line))})}),fragment}var catalogs={en:messages,tr:messages2},maxFiles=10,groupGap=300000,icons={close:'<svg width="18" height="18" 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>',back:'<svg class="flip" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 6l-6 6 6 6"/></svg>',attach:'<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 11.5l-8.3 8.3a5 5 0 01-7-7L13 4.5a3.3 3.3 0 014.7 4.7l-8.3 8.3a1.7 1.7 0 01-2.4-2.4L14.5 7.6"/></svg>',send:'<svg class="flip" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M3.4 20.4l17.5-7.5a1 1 0 000-1.8L3.4 3.6a1 1 0 00-1.4 1.2L4.5 12l-2.5 7.2a1 1 0 001.4 1.2zM4.5 12h7"/></svg>',file:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H6v18h12V7z M14 3v4h4"/></svg>'};function el(tag,className,text){let element=document.createElement(tag);if(className)element.className=className;if(text!==void 0)element.textContent=text;return element}function iconButton(icon,label,onClick,className="icon"){let button=el("button",className);return button.type="button",button.innerHTML=icon,button.setAttribute("aria-label",label),button.title=label,button.addEventListener("click",onClick),button}var time=(value)=>Date.parse(value),byCreated=(a,b)=>time(a.created_at)-time(b.created_at),byActivity=(a,b)=>time(b.last_message_at??b.created_at)-time(a.last_message_at??a.created_at),authorKey=(m)=>m.author.type==="contact"?"contact":`${m.author.type}:${m.author.name??""}`,isImage=(a)=>/^image\/(png|jpeg|gif|webp)$/.test(a.content_type);class Chat{#host;#i18n;#client;#inbox=null;#contact=null;#phase="loading";#error="";#starting=null;#beginning=null;#conversations=new Map;#conversationCursor;#threads=new Map;#pending=[];#typing=new Map;#view=null;#reconnecting=!1;#files=[];#typingSentAt=0;#typingIdle=null;#blobs=new Map;#blobLoads=new Map;#avatars=new Map;#emailSaved=!1;#emailError="";#connectedBefore=!1;#ratings=new Map;#rateCard=el("div","card rate");#rateComment=el("textarea");#rateKey="";#rateFor=null;#header=el("header","header");#banner=el("div","banner");#body=el("div","body");#scroll=el("div","scroll");#email=el("div","card");#emailInput=el("input");#composer=el("div","composer");#chips=el("div","chips");#textarea=el("textarea");#fileInput=el("input");#sendButton;#attachButton;#live=el("div","sr");#scrollThread;#atEnd=!0;constructor(host){this.#host=host;let{server,channel}=host.config();this.#client=createYuvaClient2({server,channel:channel??"",identityToken:()=>host.identityToken()}),this.#client.on("event",(message)=>this.#event(message)),this.#client.on("connection",({state,attempt})=>{if(state!=="reconnecting")return;this.#reconnecting=attempt>0,this.#renderBanner()}),this.#client.on("session",({session,renewed})=>{if(this.#setInbox(session.inbox),this.#contact=session.contact,renewed)this.#reload()}),this.#setLocale(),this.#live.setAttribute("aria-live","polite"),this.#scroll.addEventListener("scroll",()=>{if(this.#atEnd=this.#scroll.scrollHeight-this.#scroll.scrollTop-this.#scroll.clientHeight<48,this.#scroll.scrollTop<60&&this.#view?.kind==="thread"&&this.#view.id)this.#loadMessages(this.#view.id,!0)}),this.#textarea.rows=1,this.#textarea.addEventListener("keydown",(event)=>{if(event.key==="Enter"&&!event.shiftKey&&!event.isComposing)event.preventDefault(),this.#send()}),this.#textarea.addEventListener("input",()=>{this.#autosize(),this.#syncSend(),this.#typingInput()}),this.#textarea.addEventListener("paste",(event)=>{let files=Array.from(event.clipboardData?.files??[]);if(files.length===0)return;event.preventDefault(),this.#addFiles(files)}),this.#fileInput.type="file",this.#fileInput.multiple=!0,this.#fileInput.hidden=!0,this.#fileInput.addEventListener("change",()=>{this.#addFiles(Array.from(this.#fileInput.files??[])),this.#fileInput.value=""}),this.#attachButton=iconButton(icons.attach,"",()=>this.#fileInput.click()),this.#sendButton=iconButton(icons.send,"",()=>void this.#send(),"icon send");let form=el("form");form.addEventListener("submit",(event)=>{event.preventDefault(),this.#send()}),form.append(this.#attachButton,this.#textarea,this.#sendButton,this.#fileInput),this.#composer.append(this.#chips,form),this.#emailInput.type="email",this.#emailInput.required=!0,this.#emailInput.autocomplete="email",this.#rateComment.rows=2,this.#rateComment.maxLength=2000,this.#rateComment.dir="auto",document.addEventListener("visibilitychange",this.#onVisible),window.addEventListener("online",this.#onVisible),this.#renderAll(),this.#start()}update(){this.#setLocale(),this.#renderAll()}opened(){if(this.#phase==="error"){this.#starting=null,this.#start();return}if(this.#phase==="ready")this.#client.token?this.#refreshSession():this.#preview().then(()=>this.#render()).catch(()=>{return});if(this.#render(),this.#scrollToEnd(),this.#markRead(),this.#host.config().layout==="launcher")this.#textarea.focus({preventScroll:!0})}closed(){this.#stopTyping()}identityChanged(){this.#reset(),this.#start()}async signOut(){let signingOut=this.#client.signOut();if(this.#reset(),await signingOut,this.#host.isOpen())this.#start();else this.#render()}destroy(){this.#client.reset(),this.#stopTyping(),document.removeEventListener("visibilitychange",this.#onVisible),window.removeEventListener("online",this.#onVisible);for(let url of this.#blobs.values())URL.revokeObjectURL(url)}#reset(){this.#client.reset(),this.#starting=null,this.#beginning=null,this.#inbox=null,this.#contact=null,this.#phase="loading",this.#conversations.clear(),this.#threads.clear(),this.#pending=[],this.#ratings.clear(),this.#rateKey="",this.#view=null,this.#connectedBefore=!1,this.#host.setUnread(0)}#onVisible=()=>{if(document.visibilityState!=="visible")return;this.#client.reconnect(),this.#markRead(),this.#refreshInbox()};#setLocale(){let{locale}=this.#host.config();this.#i18n=setupI18n({locale,messages:{[locale]:catalogs[locale]??messages}})}#t(descriptor){return this.#i18n._(descriptor)}#start(){return this.#starting??=(async()=>{this.#phase="loading",this.#render();let{channel}=this.#host.config();if(!channel)throw new ApiError2(0,"not_configured");if(await this.#host.identityToken()||readStored(channel).session)await this.#begin();else if(await this.#preview(),!this.#inbox?.chat.allow_anonymous)throw new ApiError2(403,"anonymous_not_allowed");if(this.#phase="ready",!this.#view){let list=this.#sorted();if(this.#view=list.length>1?{kind:"list"}:{kind:"thread",id:list[0]?.id??null},this.#view.kind==="thread"&&this.#view.id)await this.#loadMessages(this.#view.id)}this.#render(),this.#scrollToEnd(),this.#markRead()})().catch((error)=>{if(this.#starting=null,this.#refusal(error))return;this.#phase="error",this.#error=error instanceof ApiError2?error.code:"error",this.#render()}),this.#starting}async#preview(){let inbox=await this.#fetchInbox();if(!this.#client.token)this.#setInbox(inbox)}#fetchInbox(){if(!this.#host.config().channel)throw new ApiError2(0,"not_configured");return this.#client.channelSettings()}#setInbox(inbox){let{channel}=this.#host.config();this.#inbox=inbox;let launcher=launcherOf(inbox);if(this.#host.setLauncher(launcher),channel)writeStored(channel,{...readStored(channel),launcher})}async#refreshInbox(){if(this.#phase!=="ready")return;try{this.#setInbox(await this.#fetchInbox()),this.#render()}catch(error){this.#refusal(error,!0)}}#refusal(error,channelRequest=!this.#client.token){let refused=error instanceof ApiError2&&(error.code==="origin_not_allowed"||error.status===404&&channelRequest);if(refused)this.#host.refused();return refused}#begin(){return this.#beginning??=(async()=>{await this.#client.start(),await this.#loadConversations(),await this.#client.connect()})().finally(()=>{this.#beginning=null}),this.#beginning}async#refreshSession(){try{await this.#client.refresh(),this.#render()}catch{}}async#loadConversations(more=!1){let page=await this.#client.listConversations({limit:50,cursor:more?this.#conversationCursor:void 0});if(!more)this.#conversations.clear();for(let conversation of page.items)this.#conversations.set(conversation.id,conversation);this.#conversationCursor=page.next_cursor,this.#syncUnread()}async#reload(){await this.#loadConversations();let current=this.#view?.kind==="thread"?this.#view.id:null;for(let id of[...this.#threads.keys()])if(id!==current)this.#threads.delete(id);if(current)this.#threads.delete(current),await this.#loadMessages(current);this.#render()}async#loadMessages(id,older=!1){let thread=this.#threads.get(id);if(!thread)thread={messages:[],complete:!1,loading:!1},this.#threads.set(id,thread);if(thread.loading||older&&(thread.complete||!thread.cursor))return;thread.loading=!0;let before=this.#scroll.scrollHeight-this.#scroll.scrollTop;try{let page=await this.#client.listMessages(id,{order:"desc",limit:30,cursor:older?thread.cursor:void 0}),known=new Set(thread.messages.map((m)=>m.id));thread.messages=[...thread.messages,...page.items.filter((m)=>!known.has(m.id))].sort(byCreated),thread.cursor=page.next_cursor,thread.complete=!page.next_cursor}finally{thread.loading=!1}if(older)this.#render(),this.#scroll.scrollTop=this.#scroll.scrollHeight-before}#event(message){switch(message.type){case"ready":if(this.#reconnecting=!1,this.#renderBanner(),this.#connectedBefore)this.#refreshInbox();this.#connectedBefore=!0;return;case"inbox.updated":{let asked=this.#inbox?.ask_for_rating;if(this.#setInbox(message.data),asked!==void 0&&asked!==message.data.ask_for_rating)this.#loadConversations().then(()=>this.#render()).catch(()=>{return});break}case"resync_required":this.#reload();return;case"presence":if(this.#inbox)this.#inbox={...this.#inbox,presence:message.data};break;case"conversation.created":if(!this.#conversations.has(message.data.id))this.#conversations.set(message.data.id,message.data);if(this.#view?.kind==="thread"&&this.#view.id===null&&this.#conversations.size>1)this.#view=this.#pending.some((p)=>p.conversation===null)?this.#view:{kind:"list"};this.#syncUnread();break;case"conversation.updated":{let conversation=this.#conversations.get(message.data.id),{status,can_rate,rating}=message.data;if(conversation)this.#conversations.set(conversation.id,{...conversation,status,can_rate,rating});if(!can_rate)this.#ratings.delete(message.data.id);break}case"message.created":case"message.updated":this.#upsertMessage(message.data,message.type==="message.created");break;case"read":{let conversation=this.#conversations.get(message.data.conversation_id),previous=conversation?.last_read_by_member_at;if(conversation&&(!previous||time(message.data.read_at)>time(previous)))this.#conversations.set(conversation.id,{...conversation,last_read_by_member_at:message.data.read_at});break}case"typing":{let id=message.data.conversation_id,previous=this.#typing.get(id);if(previous)clearTimeout(previous.timer);if(message.data.typing){let name=message.data.author.name??"";this.#typing.set(id,{name,timer:setTimeout(()=>this.#typing.delete(id)&&this.#render(),8000)})}else this.#typing.delete(id);break}}this.#render()}#upsertMessage(message,created){let id=message.conversation_id,thread=this.#threads.get(id);if(thread){let index=thread.messages.findIndex((m)=>m.id===message.id);if(index>=0)thread.messages[index]=message;else thread.messages=[...thread.messages,message].sort(byCreated)}if(message.client_id)this.#pending=this.#pending.filter((p)=>p.client_id!==message.client_id);let conversation=this.#conversations.get(id);if(!conversation){this.#client.getConversation(id).then((c)=>{this.#conversations.set(c.id,c),this.#syncUnread(),this.#render()}).catch(()=>{return});return}if(created){let text=message.body.replace(/\s+/g," ").trim();if(this.#conversations.set(id,{...conversation,last_message:{id:message.id,author_type:message.author.type,text:text.length>140?`${text.slice(0,139)}…`:text,created_at:message.created_at},last_message_at:message.created_at,unread:conversation.unread||message.author.type!=="contact"}),message.author.type!=="contact"){let typing=this.#typing.get(id);if(typing)clearTimeout(typing.timer);this.#typing.delete(id),this.#announce(message)}}this.#syncUnread(),this.#markRead()}#announce(message){this.#live.textContent=`${message.author.name||this.#inbox?.name||""}: ${message.body.slice(0,200)}`}#syncUnread(){let count=0;for(let conversation of this.#conversations.values())if(conversation.unread)count++;this.#host.setUnread(count)}#visibleThread(){if(!this.#host.isOpen()||document.visibilityState!=="visible")return null;return this.#view?.kind==="thread"?this.#view.id:null}#markRead(){let id=this.#visibleThread(),conversation=id?this.#conversations.get(id):void 0;if(!id||!conversation?.unread)return;this.#conversations.set(id,{...conversation,unread:!1}),this.#syncUnread(),this.#client.markRead(id).catch(()=>{let current=this.#conversations.get(id);if(current)this.#conversations.set(id,{...current,unread:!0});this.#syncUnread()})}#addFiles(files){this.#files=[...this.#files,...files].slice(0,maxFiles),this.#renderChips(),this.#syncSend(),this.#textarea.focus()}#autosize(){if(this.#textarea.style.blockSize="",this.#textarea.value==="")return;this.#textarea.style.blockSize="auto",this.#textarea.style.blockSize=`${Math.max(38,Math.min(this.#textarea.scrollHeight,140))}px`}#syncSend(){this.#sendButton.disabled=this.#textarea.value.trim()===""&&this.#files.length===0}#typingInput(){let id=this.#view?.kind==="thread"?this.#view.id:null;if(!id||this.#textarea.value.trim()===""){this.#stopTyping();return}if(Date.now()-this.#typingSentAt>3000)this.#typingSentAt=Date.now(),this.#client.setTyping(id,!0).catch(()=>{return});if(this.#typingIdle)clearTimeout(this.#typingIdle);this.#typingIdle=setTimeout(()=>this.#stopTyping(),4000)}#stopTyping(){if(this.#typingIdle)clearTimeout(this.#typingIdle);if(this.#typingIdle=null,this.#typingSentAt===0)return;this.#typingSentAt=0;let id=this.#view?.kind==="thread"?this.#view.id:null;if(id)this.#client.setTyping(id,!1).catch(()=>{return})}async#send(){if(this.#phase!=="ready"||this.#view?.kind!=="thread")return;let body=this.#textarea.value.trim(),files=this.#files;if(!body&&files.length===0)return;if(this.#view.id===null&&this.#pending.some((p)=>p.conversation===null))return;this.#stopTyping(),this.#textarea.value="",this.#files=[],this.#autosize(),this.#renderChips(),this.#syncSend();let pending={client_id:randomId(),conversation:this.#view.id,body,files,state:"sending"};this.#pending.push(pending),this.#render(),this.#scrollToEnd(),await this.#deliver(pending)}async#deliver(pending){pending.state="sending",this.#render();let input={body:pending.body,files:pending.files,client_id:pending.client_id};try{if(pending.conversation===null){let created=await this.#client.startConversation(input),id=created.conversation.id;if(!this.#conversations.has(id))this.#conversations.set(id,created.conversation);if(!this.#threads.has(id))this.#threads.set(id,{messages:[],complete:!0,loading:!1});if(this.#view?.kind==="thread"&&this.#view.id===null)this.#view={kind:"thread",id};this.#upsertMessage(created.message,!1)}else{let message=await this.#client.sendMessage(pending.conversation,input);this.#upsertMessage(message,!0)}this.#pending=this.#pending.filter((p)=>p!==pending)}catch(error){let status=error instanceof ApiError2?error.status:0;pending.state=status===413||status===415?"refused":"failed",pending.status=status}this.#render(),this.#scrollToEnd()}async rate(id,rating,comment){try{let conversation=await this.#client.rate(id,rating,comment);return this.#conversations.set(conversation.id,conversation),this.#ratings.delete(id),this.#render(),conversation}catch(error){if(error instanceof ApiError2&&error.status===409){let current=await this.#client.getConversation(id).catch(()=>null);if(current)this.#conversations.set(current.id,current);this.#ratings.delete(id),this.#render()}throw error}}#choose(id,choice){if(this.#ratings.get(id)?.state==="sending")return;if(this.#ratings.set(id,{choice,state:"choosing"}),this.#render(),this.#rateComment.focus({preventScroll:!0}),this.#atEnd)this.#scrollToEnd()}async#submitRating(id,withComment){let draft=this.#ratings.get(id);if(!draft||draft.state==="sending")return;draft.state="sending",this.#render();try{await this.rate(id,draft.choice,withComment?this.#rateComment.value:void 0),this.#rateComment.value=""}catch(error){if(error instanceof ApiError2&&error.status===409)return;draft.state="failed",this.#render()}}async#saveEmail(){let email=this.#emailInput.value.trim();if(!email||!this.#emailInput.checkValidity()){this.#emailError=this.#t({id:"E_qvzP"}),this.#renderEmail();return}try{this.#contact=await this.#client.setEmail(email),this.#emailSaved=!0,this.#emailError=""}catch{this.#emailError=this.#t({id:"ZxJcgC"})}this.#renderEmail()}#attachmentUrl(attachment){let cached=this.#blobs.get(attachment.id);if(cached)return Promise.resolve(cached);let load=this.#blobLoads.get(attachment.id);if(!load)load=this.#client.attachment(attachment.id).then((blob)=>{let url=URL.createObjectURL(blob);return this.#blobs.set(attachment.id,url),url}),load.catch(()=>this.#blobLoads.delete(attachment.id)),this.#blobLoads.set(attachment.id,load);return load}async#download(attachment){let url=await this.#attachmentUrl(attachment),a=el("a");a.href=url,a.download=attachment.filename,a.rel="noopener",a.click()}#sorted(){return[...this.#conversations.values()].sort(byActivity)}#nobodyAvailable(){let inbox=this.#inbox;if(!inbox)return!1;return!inbox.open_now||inbox.mode==="async"||!inbox.presence?.available}#scrollToEnd(){this.#atEnd=!0,this.#scroll.scrollTop=this.#scroll.scrollHeight,requestAnimationFrame(()=>{if(this.#atEnd)this.#scroll.scrollTop=this.#scroll.scrollHeight})}#renderAll(){this.#textarea.placeholder=this.#t({id:"RzWUUK"}),this.#textarea.setAttribute("aria-label",this.#t({id:"xDAtGP"})),this.#attachButton.setAttribute("aria-label",this.#t({id:"N7m8E-"})),this.#attachButton.title=this.#t({id:"N7m8E-"}),this.#sendButton.setAttribute("aria-label",this.#t({id:"JlFcis"})),this.#sendButton.title=this.#t({id:"JlFcis"}),this.#emailInput.placeholder=this.#t({id:"njBr8W"}),this.#emailInput.setAttribute("aria-label",this.#t({id:"XJURKP"})),this.#syncSend(),this.#renderChips(),this.#render()}#render(){let panel=this.#host.panel;if(panel.childElementCount===0){let style=el("style");style.textContent=styles,panel.append(style,this.#header,this.#banner,this.#body,this.#live),this.#header.id="yuva-title",panel.setAttribute("aria-labelledby","yuva-title")}if(this.#renderHeader(),this.#renderBanner(),this.#phase!=="ready"){this.#scrollThread=void 0;let center=el("div","center");if(this.#phase==="loading")center.append(el("p","hint",this.#t({id:"Pwqkdw"})));else{center.append(el("p","empty",this.#errorText()));let retry=el("button","primary",this.#t({id:"KDw4GX"}));retry.type="button",retry.addEventListener("click",()=>{this.#starting=null,this.#start()}),center.append(retry)}this.#body.replaceChildren(center);return}if(this.#view?.kind==="list")this.#renderList();else this.#renderThread()}#errorText(){switch(this.#error){case"anonymous_not_allowed":return this.#t({id:"zLzEI3"});case"invalid_identity_token":return this.#t({id:"0XGLbP"});case"rate_limited":return this.#t({id:"tzsBOP"});case"network":return this.#t({id:"GQVIIl"});default:return this.#t({id:"Amai22"})}}#renderHeader(){let{layout}=this.#host.config(),inbox=this.#inbox,children=[],view=this.#view;if(this.#phase==="ready"&&view?.kind==="thread"&&(this.#conversations.size>1||view.id===null&&this.#conversations.size>0))children.push(iconButton(icons.back,this.#t({id:"S63MQu"}),()=>{this.#stopTyping(),this.#view={kind:"list"},this.#render()}));let heading=el("div","heading");if(heading.append(el("h2","title",inbox?.name||this.#t({id:"t7TeQU"}))),inbox){let status=el("div","status");if(inbox.mode==="live"&&inbox.open_now&&inbox.presence?.available){let avatars=el("div","avatars");for(let member of inbox.presence?.members.slice(0,3)??[]){let avatar=el("span","avatar",member.initials||"•");avatar.title=member.name,avatars.append(avatar)}status.append(avatars,el("span","dot"),el("span","",this.#t({id:"oXOSPE"})))}else if(!inbox.open_now||inbox.mode==="live")status.append(el("span","dot away"),el("span","",this.#t({id:"1EICzz"})));else status.append(el("span","",this.#replyTime(inbox.expected_reply_minutes)));heading.append(status)}if(children.push(heading),layout==="launcher")children.push(iconButton(icons.close,this.#t({id:"yz7wBu"}),()=>this.#host.close()));this.#header.replaceChildren(...children)}#replyTime(minutes){if(!minutes)return this.#t({id:"nhTADq"});let{locale}=this.#host.config(),[value,unit]=minutes<60?[minutes,"minute"]:minutes<1440?[Math.round(minutes/60),"hour"]:[Math.round(minutes/1440),"day"],duration=new Intl.NumberFormat(locale,{style:"unit",unit,unitDisplay:"long"}).format(value);return this.#t({id:"VggdQJ",values:{duration}})}#renderBanner(){this.#banner.hidden=!this.#reconnecting,this.#banner.textContent=this.#t({id:"09Tv5j"})}#renderList(){this.#scrollThread=void 0;let{locale}=this.#host.config(),list=el("ul","list"),today=new Date().toDateString();for(let conversation of this.#sorted()){let button=el("button",conversation.unread?"item unread":"item");button.type="button";let main=el("div","item-main"),top=el("div","item-top");top.append(el("span","item-subject",conversation.subject||this.#inbox?.name||this.#t({id:"YyNOE7"})));let at=new Date(conversation.last_message_at??conversation.created_at);top.append(el("span","item-time",new Intl.DateTimeFormat(locale,at.toDateString()===today?{timeStyle:"short"}:{month:"short",day:"numeric"}).format(at)));let preview=conversation.last_message?`${conversation.last_message.author_type==="contact"?this.#t({id:"ydzYKJ"})+" ":""}${conversation.last_message.text||this.#t({id:"UY1vmE"})}`:"",previewLine=el("div","item-preview",preview.replace(/\*\*|`/g,""));if(previewLine.dir="auto",main.append(top,previewLine),button.append(main),conversation.unread)button.append(el("span","unread-dot"));button.addEventListener("click",()=>void this.#openThread(conversation.id));let item=el("li");item.append(button),list.append(item)}if(this.#conversationCursor){let more=el("button","link",this.#t({id:"ASr-r0"}));more.type="button",more.style.margin="8px auto",more.style.display="block",more.addEventListener("click",()=>void this.#loadConversations(!0).then(()=>this.#render())),list.append(more)}let start=el("button","primary",this.#t({id:"-HY5kX"}));start.type="button",start.addEventListener("click",()=>{this.#view={kind:"thread",id:null},this.#render(),this.#textarea.focus()}),this.#body.replaceChildren(list,start)}async#openThread(id){if(this.#view={kind:"thread",id},this.#render(),!this.#threads.get(id)?.complete&&!this.#threads.get(id)?.messages.length)await this.#loadMessages(id).catch(()=>{return});this.#render(),this.#scrollToEnd(),this.#markRead()}#avatar(author){let avatar=el("span","avatar",author.initials||""),url=author.avatar_url,state=url?this.#avatars.get(url):!1;if(!url||state===!1)return avatar;let img=el("img");if(img.alt="",img.referrerPolicy="no-referrer",state)return img.src=url,avatar.replaceChildren(img),avatar;return img.addEventListener("load",()=>{if(this.#avatars.set(url,!0),avatar.isConnected)avatar.replaceChildren(img)}),img.addEventListener("error",()=>this.#avatars.set(url,!1)),img.src=url,avatar}#renderThread(){let view=this.#view;if(view?.kind!=="thread")return;let id=view.id,sameThread=this.#scrollThread===id,atEnd=this.#atEnd,thread=id?this.#threads.get(id):void 0,messages=thread?.messages??[],pending=this.#pending.filter((p)=>p.conversation===id),nodes=[],greeting=this.#inbox?.chat.greeting;if(!thread||thread.complete){if(greeting){let bubble=el("div","bubble greeting");bubble.append(richText(greeting)),nodes.push(bubble)}else if(messages.length===0&&pending.length===0){let center=el("div","center");center.append(el("p","empty",this.#t({id:"meAa31"})),el("p","hint",this.#t({id:"SdV5Cn"}))),nodes.push(center)}}else if(thread.loading)nodes.push(el("p","hint",this.#t({id:"Pwqkdw"})));messages.forEach((message,i)=>{let previous=messages[i-1],next=messages[i+1]??(pending.length>0?null:void 0),mine=message.author.type==="contact",starts=!previous||authorKey(previous)!==authorKey(message)||time(message.created_at)-time(previous.created_at)>groupGap,ends=next===void 0||(next===null?!mine:authorKey(next)!==authorKey(message)||time(next.created_at)-time(message.created_at)>groupGap);if(!mine&&starts&&message.author.name)nodes.push(el("div","author",message.author.name));let row=el("div",`row ${mine?"mine":"theirs"}${starts&&i>0?" group-gap":""}`);if(!mine){let avatar=this.#avatar(message.author);if(!ends)avatar.style.visibility="hidden";row.append(avatar)}let bubble=el("div","bubble");if(bubble.dir="auto",bubble.title=new Date(message.created_at).toLocaleString(this.#host.config().locale),message.body.trim())bubble.append(richText(message.body));if(message.attachments.length>0)bubble.append(this.#renderAttachments(message.attachments));if(row.append(bubble),nodes.push(row),ends){let meta=this.#formatTime(message.created_at);if(mine&&i===messages.length-1&&pending.length===0){let readAt=id?this.#conversations.get(id)?.last_read_by_member_at:void 0,seen=readAt&&time(readAt)>=time(message.created_at);meta+=` · ${seen?this.#t({id:"6lGaum"}):this.#t({id:"h69WC6"})}`}let line=el("div","meta",meta);if(!mine)line.style.alignSelf="flex-start";if(!mine)line.style.marginInlineStart="36px";nodes.push(line)}});let conversation=id?this.#conversations.get(id):void 0,rate=conversation?this.#renderRating(conversation):null;if(rate)nodes.push(rate);pending.forEach((item,i)=>{let row=el("div",`row mine${i===0&&messages.length>0&&messages[messages.length-1]?.author.type!=="contact"?" group-gap":""}`),bubble=el("div","bubble");if(bubble.dir="auto",item.body)bubble.append(richText(item.body));if(item.files.length>0){let files=el("div","files");for(let file of item.files)files.append(el("span","file",file.name||"image"));bubble.append(files)}if(row.append(bubble),nodes.push(row),item.state==="failed"){let line=el("div","meta failed",`${this.#t({id:"upFvcp"})} `),retry=el("button","link",this.#t({id:"6gRgw8"}));retry.type="button",retry.addEventListener("click",()=>void this.#deliver(item)),line.append(retry),nodes.push(line)}else if(item.state==="refused"){let reason=item.status===413?this.#t({id:"eOu9Px"}):this.#t({id:"JkW3Ph"});nodes.push(el("div","meta failed",`${this.#t({id:"upFvcp"})} ${reason}`))}else if(i===pending.length-1)nodes.push(el("div","meta",this.#t({id:"Sad2tK"})))});let typing=id?this.#typing.get(id):void 0;if(typing){let line=el("div","typing");line.append(el("i"),el("i"),el("i"));let name=typing.name;line.append(el("span","",name?this.#t({id:"tHaDPf",values:{name}}):this.#t({id:"PxYAul"}))),nodes.push(line)}let focused=this.#scroll.getRootNode().activeElement===this.#rateComment,{selectionStart,selectionEnd}=this.#rateComment;if(this.#scroll.replaceChildren(...nodes),focused&&this.#rateComment.isConnected)this.#rateComment.focus({preventScroll:!0}),this.#rateComment.setSelectionRange(selectionStart,selectionEnd);if(this.#renderEmail(),this.#body.firstChild!==this.#scroll)this.#body.replaceChildren(this.#scroll,this.#email,this.#composer);if(this.#scrollThread=id,!sameThread||atEnd)this.#scrollToEnd()}#renderRating(conversation){let rated=conversation.status==="closed"?conversation.rating:void 0,draft=conversation.can_rate&&this.#inbox?.ask_for_rating?this.#ratings.get(conversation.id):void 0;if(!rated&&!(conversation.can_rate&&this.#inbox?.ask_for_rating))return null;let card=this.#rateCard,key=[conversation.id,rated,draft?.choice,draft?.state,this.#host.config().locale].join(":");if(key===this.#rateKey)return card;if(this.#rateKey=key,this.#rateFor!==conversation.id)this.#rateFor=conversation.id,this.#rateComment.value="";let question=this.#t({id:"uA8iBc"});card.setAttribute("role","group"),card.setAttribute("aria-label",question);let choices=el("div","choices");for(let value of["good","bad"]){if(rated&&rated!==value)continue;let button=el("button","choice",value==="good"?"\uD83D\uDC4D":"\uD83D\uDC4E");button.type="button";let label=value==="good"?this.#t({id:"OEEQKT"}):this.#t({id:"-f5Tkb"});button.setAttribute("aria-label",label),button.title=label,button.setAttribute("aria-pressed",String((rated??draft?.choice)===value)),button.disabled=!!rated||draft?.state==="sending",button.addEventListener("click",()=>this.#choose(conversation.id,value)),choices.append(button)}if(rated)return card.replaceChildren(choices,el("p","",this.#t({id:"SOk0EB"}))),card;if(card.replaceChildren(el("p","",question),choices),!draft)return card;this.#rateComment.placeholder=this.#t({id:"axQ1h6"}),this.#rateComment.setAttribute("aria-label",this.#t({id:"NBdIgR"})),this.#rateComment.disabled=draft.state==="sending";let form=el("form");form.addEventListener("submit",(event)=>{event.preventDefault(),this.#submitRating(conversation.id,!0)});let skip=el("button","link",this.#t({id:"6Uau97"}));skip.type="button",skip.disabled=draft.state==="sending",skip.addEventListener("click",()=>void this.#submitRating(conversation.id,!1));let send=el("button","",draft.state==="sending"?this.#t({id:"Sad2tK"}):this.#t({id:"JlFcis"}));send.type="submit",send.disabled=draft.state==="sending";let actions=el("div","actions");if(actions.append(skip,send),form.append(this.#rateComment,actions),card.append(form),draft.state==="failed")card.append(el("p","error",this.#t({id:"4TqZiz"})));return card}#renderAttachments(attachments){let files=el("div","files");for(let attachment of attachments)if(isImage(attachment)){let img=el("img");img.alt=attachment.filename;let cached=this.#blobs.get(attachment.id);if(cached)img.src=cached;else this.#attachmentUrl(attachment).then((url)=>{img.src=url}).catch(()=>{return});img.addEventListener("load",()=>{if(this.#atEnd)this.#scroll.scrollTop=this.#scroll.scrollHeight}),img.addEventListener("click",()=>void this.#download(attachment)),files.append(img)}else{let button=el("button","file");button.type="button",button.innerHTML=icons.file,button.append(el("span","",attachment.filename)),button.addEventListener("click",()=>void this.#download(attachment)),files.append(button)}return files}#formatTime(value){return new Intl.DateTimeFormat(this.#host.config().locale,{timeStyle:"short"}).format(new Date(value))}#renderEmail(){let contact=this.#contact,chat=this.#inbox?.chat,sent=(this.#view?.kind==="thread"?this.#view.id:null)!==null||this.#pending.length>0,known=contact?.email||contact?.typed_email,show=!!chat?.ask_email_offline&&this.#nobodyAvailable()&&sent&&(!known||this.#emailSaved);if(this.#email.hidden=!show,!show)return;if(known&&this.#emailSaved){this.#email.replaceChildren(el("p","",this.#t({id:"iGNUZJ",values:{known}})));return}if(this.#email.querySelector("form")){let error=this.#email.querySelector(".error");if(error)error.textContent=this.#emailError;else if(this.#emailError)this.#email.append(el("p","error",this.#emailError));return}let form=el("form");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#saveEmail()});let save=el("button","",this.#t({id:"tfDRzk"}));if(save.type="submit",form.append(this.#emailInput,save),this.#email.replaceChildren(el("p","",this.#t({id:"M62PBt"})),form),this.#emailError)this.#email.append(el("p","error",this.#emailError))}#renderChips(){this.#chips.hidden=this.#files.length===0,this.#chips.replaceChildren(...this.#files.map((file,index)=>{let chip=el("span","chip");return chip.append(el("span","",file.name||"image"),iconButton(icons.close,this.#t({id:"w61W3L",values:{0:file.name}}),()=>{this.#files=this.#files.filter((_,i)=>i!==index),this.#renderChips(),this.#syncSend()})),chip}))}}function mount(host){return new Chat(host)}export{mount};
193
+ `;var catalogs={en:messages,tr:messages2},maxFiles=10,groupGap=300000,icons={close:'<svg width="18" height="18" 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>',back:'<svg class="flip" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 6l-6 6 6 6"/></svg>',attach:'<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 11.5l-8.3 8.3a5 5 0 01-7-7L13 4.5a3.3 3.3 0 014.7 4.7l-8.3 8.3a1.7 1.7 0 01-2.4-2.4L14.5 7.6"/></svg>',send:'<svg class="flip" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M3.4 20.4l17.5-7.5a1 1 0 000-1.8L3.4 3.6a1 1 0 00-1.4 1.2L4.5 12l-2.5 7.2a1 1 0 001.4 1.2zM4.5 12h7"/></svg>',file:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H6v18h12V7z M14 3v4h4"/></svg>'};function el(tag,className,text){let element=document.createElement(tag);if(className)element.className=className;if(text!==void 0)element.textContent=text;return element}function iconButton(icon,label,onClick,className="icon"){let button=el("button",className);return button.type="button",button.innerHTML=icon,button.setAttribute("aria-label",label),button.title=label,button.addEventListener("click",onClick),button}var time=(value)=>Date.parse(value),byCreated=(a,b)=>time(a.created_at)-time(b.created_at),byActivity=(a,b)=>time(b.last_message_at??b.created_at)-time(a.last_message_at??a.created_at),authorKey=(m)=>m.author.type==="contact"?"contact":`${m.author.type}:${m.author.name??""}`,isImage=(a)=>/^image\/(png|jpeg|gif|webp)$/.test(a.content_type);class Chat{#host;#i18n;#client;#inbox=null;#contact=null;#phase="loading";#error="";#starting=null;#beginning=null;#conversations=new Map;#conversationCursor;#threads=new Map;#pending=[];#typing=new Map;#view=null;#reconnecting=!1;#files=[];#typingSentAt=0;#typingIdle=null;#blobs=new Map;#blobLoads=new Map;#avatars=new Map;#emailSaved=!1;#emailError="";#connectedBefore=!1;#ratings=new Map;#rateCard=el("div","card rate");#rateComment=el("textarea");#rateKey="";#rateFor=null;#header=el("header","header");#banner=el("div","banner");#body=el("div","body");#scroll=el("div","scroll");#email=el("div","card");#emailInput=el("input");#composer=el("div","composer");#chips=el("div","chips");#textarea=el("textarea");#fileInput=el("input");#sendButton;#attachButton;#live=el("div","sr");#scrollThread;#atEnd=!0;constructor(host){this.#host=host;let{server,channel}=host.config();this.#client=createYuvaClient2({server,channel:channel??"",identityToken:()=>host.identityToken()}),this.#client.on("event",(message)=>this.#event(message)),this.#client.on("connection",({state,attempt})=>{if(state!=="reconnecting")return;this.#reconnecting=attempt>0,this.#renderBanner()}),this.#client.on("session",({session,renewed})=>{if(this.#setInbox(session.inbox),this.#contact=session.contact,renewed)this.#reload()}),this.#setLocale(),this.#live.setAttribute("aria-live","polite"),this.#scroll.addEventListener("scroll",()=>{if(this.#atEnd=this.#scroll.scrollHeight-this.#scroll.scrollTop-this.#scroll.clientHeight<48,this.#scroll.scrollTop<60&&this.#view?.kind==="thread"&&this.#view.id)this.#loadMessages(this.#view.id,!0)}),this.#textarea.rows=1,this.#textarea.addEventListener("keydown",(event)=>{if(event.key==="Enter"&&!event.shiftKey&&!event.isComposing)event.preventDefault(),this.#send()}),this.#textarea.addEventListener("input",()=>{this.#autosize(),this.#syncSend(),this.#typingInput()}),this.#textarea.addEventListener("paste",(event)=>{let files=Array.from(event.clipboardData?.files??[]);if(files.length===0)return;event.preventDefault(),this.#addFiles(files)}),this.#fileInput.type="file",this.#fileInput.multiple=!0,this.#fileInput.hidden=!0,this.#fileInput.addEventListener("change",()=>{this.#addFiles(Array.from(this.#fileInput.files??[])),this.#fileInput.value=""}),this.#attachButton=iconButton(icons.attach,"",()=>this.#fileInput.click()),this.#sendButton=iconButton(icons.send,"",()=>void this.#send(),"icon send");let form=el("form");form.addEventListener("submit",(event)=>{event.preventDefault(),this.#send()}),form.append(this.#attachButton,this.#textarea,this.#sendButton,this.#fileInput),this.#composer.append(this.#chips,form),this.#emailInput.type="email",this.#emailInput.required=!0,this.#emailInput.autocomplete="email",this.#rateComment.rows=2,this.#rateComment.maxLength=2000,this.#rateComment.dir="auto",document.addEventListener("visibilitychange",this.#onVisible),window.addEventListener("online",this.#onVisible),this.#renderAll(),this.#start()}update(){this.#setLocale(),this.#renderAll()}opened(){if(this.#phase==="error"){this.#starting=null,this.#start();return}if(this.#phase==="ready")this.#client.token?this.#refreshSession():this.#preview().then(()=>this.#render()).catch(()=>{return});if(this.#render(),this.#scrollToEnd(),this.#markRead(),this.#host.config().layout==="launcher")this.#textarea.focus({preventScroll:!0})}closed(){this.#stopTyping()}identityChanged(){this.#reset(),this.#start()}async signOut(){let signingOut=this.#client.signOut();if(this.#reset(),await signingOut,this.#host.isOpen())this.#start();else this.#render()}destroy(){this.#client.reset(),this.#stopTyping(),document.removeEventListener("visibilitychange",this.#onVisible),window.removeEventListener("online",this.#onVisible);for(let url of this.#blobs.values())URL.revokeObjectURL(url)}#reset(){this.#client.reset(),this.#starting=null,this.#beginning=null,this.#inbox=null,this.#contact=null,this.#phase="loading",this.#conversations.clear(),this.#threads.clear(),this.#pending=[],this.#ratings.clear(),this.#rateKey="",this.#view=null,this.#connectedBefore=!1,this.#host.setUnread(0)}#onVisible=()=>{if(document.visibilityState!=="visible")return;this.#client.reconnect(),this.#markRead(),this.#refreshInbox()};#setLocale(){let{locale}=this.#host.config();this.#i18n=setupI18n({locale,messages:{[locale]:catalogs[locale]??messages}})}#t(descriptor){return this.#i18n._(descriptor)}#start(){return this.#starting??=(async()=>{this.#phase="loading",this.#render();let{channel}=this.#host.config();if(!channel)throw new ApiError2(0,"not_configured");if(await this.#host.identityToken()||readStored(channel).session)await this.#begin();else if(await this.#preview(),!this.#inbox?.chat.allow_anonymous)throw new ApiError2(403,"anonymous_not_allowed");if(this.#phase="ready",!this.#view){let list=this.#sorted();if(this.#view=list.length>1?{kind:"list"}:{kind:"thread",id:list[0]?.id??null},this.#view.kind==="thread"&&this.#view.id)await this.#loadMessages(this.#view.id)}this.#render(),this.#scrollToEnd(),this.#markRead()})().catch((error)=>{if(this.#starting=null,this.#refusal(error))return;this.#phase="error",this.#error=error instanceof ApiError2?error.code:"error",this.#render()}),this.#starting}async#preview(){let inbox=await this.#fetchInbox();if(!this.#client.token)this.#setInbox(inbox)}#fetchInbox(){if(!this.#host.config().channel)throw new ApiError2(0,"not_configured");return this.#client.channelSettings()}#setInbox(inbox){let{channel}=this.#host.config();this.#inbox=inbox;let launcher=launcherOf(inbox);if(this.#host.setLauncher(launcher),channel)writeStored(channel,{...readStored(channel),launcher})}async#refreshInbox(){if(this.#phase!=="ready")return;try{this.#setInbox(await this.#fetchInbox()),this.#render()}catch(error){this.#refusal(error,!0)}}#refusal(error,channelRequest=!this.#client.token){let refused=error instanceof ApiError2&&(error.code==="origin_not_allowed"||error.status===404&&channelRequest);if(refused)this.#host.refused();return refused}#begin(){return this.#beginning??=(async()=>{await this.#client.start(),await this.#loadConversations(),await this.#client.connect()})().finally(()=>{this.#beginning=null}),this.#beginning}async#refreshSession(){try{await this.#client.refresh(),this.#render()}catch{}}async#loadConversations(more=!1){let page=await this.#client.listConversations({limit:50,cursor:more?this.#conversationCursor:void 0});if(!more)this.#conversations.clear();for(let conversation of page.items)this.#conversations.set(conversation.id,conversation);this.#conversationCursor=page.next_cursor,this.#syncUnread()}async#reload(){await this.#loadConversations();let current=this.#view?.kind==="thread"?this.#view.id:null;for(let id of this.#threads.keys())if(id!==current)this.#threads.delete(id);if(current)this.#threads.delete(current),await this.#loadMessages(current);this.#render()}async#loadMessages(id,older=!1){let thread=this.#threads.get(id);if(!thread)thread={messages:[],complete:!1,loading:!1},this.#threads.set(id,thread);if(thread.loading||older&&(thread.complete||!thread.cursor))return;thread.loading=!0;let before=this.#scroll.scrollHeight-this.#scroll.scrollTop;try{let page=await this.#client.listMessages(id,{order:"desc",limit:30,cursor:older?thread.cursor:void 0}),known=new Set(thread.messages.map((m)=>m.id));thread.messages=[...thread.messages,...page.items.filter((m)=>!known.has(m.id))].sort(byCreated),thread.cursor=page.next_cursor,thread.complete=!page.next_cursor}finally{thread.loading=!1}if(older)this.#render(),this.#scroll.scrollTop=this.#scroll.scrollHeight-before}#event(message){switch(message.type){case"ready":if(this.#reconnecting=!1,this.#renderBanner(),this.#connectedBefore)this.#refreshInbox();this.#connectedBefore=!0;return;case"inbox.updated":{let asked=this.#inbox?.ask_for_rating;if(this.#setInbox(message.data),asked!==void 0&&asked!==message.data.ask_for_rating)this.#loadConversations().then(()=>this.#render()).catch(()=>{return});break}case"resync_required":this.#reload();return;case"presence":if(this.#inbox)this.#inbox={...this.#inbox,presence:message.data};break;case"conversation.created":if(!this.#conversations.has(message.data.id))this.#conversations.set(message.data.id,message.data);if(this.#view?.kind==="thread"&&this.#view.id===null&&this.#conversations.size>1)this.#view=this.#pending.some((p)=>p.conversation===null)?this.#view:{kind:"list"};this.#syncUnread();break;case"conversation.updated":{let conversation=this.#conversations.get(message.data.id),{status,can_rate,rating}=message.data;if(conversation)this.#conversations.set(conversation.id,{...conversation,status,can_rate,rating});if(!can_rate)this.#ratings.delete(message.data.id);break}case"message.created":case"message.updated":this.#upsertMessage(message.data,message.type==="message.created");break;case"read":{let conversation=this.#conversations.get(message.data.conversation_id),previous=conversation?.last_read_by_member_at;if(conversation&&(!previous||time(message.data.read_at)>time(previous)))this.#conversations.set(conversation.id,{...conversation,last_read_by_member_at:message.data.read_at});break}case"typing":{let id=message.data.conversation_id,previous=this.#typing.get(id);if(previous)clearTimeout(previous.timer);if(message.data.typing){let name=message.data.author.name??"";this.#typing.set(id,{name,timer:setTimeout(()=>this.#typing.delete(id)&&this.#render(),8000)})}else this.#typing.delete(id);break}}this.#render()}#upsertMessage(message,created){let id=message.conversation_id,thread=this.#threads.get(id);if(thread){let index=thread.messages.findIndex((m)=>m.id===message.id);if(index>=0)thread.messages[index]=message;else thread.messages=[...thread.messages,message].sort(byCreated)}if(message.client_id)this.#pending=this.#pending.filter((p)=>p.client_id!==message.client_id);let conversation=this.#conversations.get(id);if(!conversation){this.#client.getConversation(id).then((c)=>{this.#conversations.set(c.id,c),this.#syncUnread(),this.#render()}).catch(()=>{return});return}if(created){let text=message.body.replace(/\s+/g," ").trim();if(this.#conversations.set(id,{...conversation,last_message:{id:message.id,author_type:message.author.type,text:text.length>140?`${text.slice(0,139)}…`:text,created_at:message.created_at},last_message_at:message.created_at,unread:conversation.unread||message.author.type!=="contact"}),message.author.type!=="contact"){let typing=this.#typing.get(id);if(typing)clearTimeout(typing.timer);this.#typing.delete(id),this.#announce(message)}}this.#syncUnread(),this.#markRead()}#announce(message){this.#live.textContent=`${message.author.name||this.#inbox?.name||""}: ${message.body.slice(0,200)}`}#syncUnread(){let count=0;for(let conversation of this.#conversations.values())if(conversation.unread)count++;this.#host.setUnread(count)}#visibleThread(){if(!this.#host.isOpen()||document.visibilityState!=="visible")return null;return this.#view?.kind==="thread"?this.#view.id:null}#markRead(){let id=this.#visibleThread(),conversation=id?this.#conversations.get(id):void 0;if(!id||!conversation?.unread)return;this.#conversations.set(id,{...conversation,unread:!1}),this.#syncUnread(),this.#client.markRead(id).catch(()=>{let current=this.#conversations.get(id);if(current)this.#conversations.set(id,{...current,unread:!0});this.#syncUnread()})}#addFiles(files){this.#files=[...this.#files,...files].slice(0,maxFiles),this.#renderChips(),this.#syncSend(),this.#textarea.focus()}#autosize(){if(this.#textarea.style.blockSize="",this.#textarea.value==="")return;this.#textarea.style.blockSize="auto",this.#textarea.style.blockSize=`${Math.max(38,Math.min(this.#textarea.scrollHeight,140))}px`}#syncSend(){this.#sendButton.disabled=this.#textarea.value.trim()===""&&this.#files.length===0}#typingInput(){let id=this.#view?.kind==="thread"?this.#view.id:null;if(!id||this.#textarea.value.trim()===""){this.#stopTyping();return}if(Date.now()-this.#typingSentAt>3000)this.#typingSentAt=Date.now(),this.#client.setTyping(id,!0).catch(()=>{return});if(this.#typingIdle)clearTimeout(this.#typingIdle);this.#typingIdle=setTimeout(()=>this.#stopTyping(),4000)}#stopTyping(){if(this.#typingIdle)clearTimeout(this.#typingIdle);if(this.#typingIdle=null,this.#typingSentAt===0)return;this.#typingSentAt=0;let id=this.#view?.kind==="thread"?this.#view.id:null;if(id)this.#client.setTyping(id,!1).catch(()=>{return})}async#send(){if(this.#phase!=="ready"||this.#view?.kind!=="thread")return;let body=this.#textarea.value.trim(),files=this.#files;if(!body&&files.length===0)return;if(this.#view.id===null&&this.#pending.some((p)=>p.conversation===null))return;this.#stopTyping(),this.#textarea.value="",this.#files=[],this.#autosize(),this.#renderChips(),this.#syncSend();let pending={client_id:randomId(),conversation:this.#view.id,body,files,state:"sending"};this.#pending.push(pending),this.#render(),this.#scrollToEnd(),await this.#deliver(pending)}async#deliver(pending){pending.state="sending",this.#render();let input={body:pending.body,files:pending.files,client_id:pending.client_id};try{if(pending.conversation===null){let created=await this.#client.startConversation(input),id=created.conversation.id;if(!this.#conversations.has(id))this.#conversations.set(id,created.conversation);if(!this.#threads.has(id))this.#threads.set(id,{messages:[],complete:!0,loading:!1});if(this.#view?.kind==="thread"&&this.#view.id===null)this.#view={kind:"thread",id};this.#upsertMessage(created.message,!1)}else{let message=await this.#client.sendMessage(pending.conversation,input);this.#upsertMessage(message,!0)}this.#pending=this.#pending.filter((p)=>p!==pending)}catch(error){let status=error instanceof ApiError2?error.status:0;pending.state=status===413||status===415?"refused":"failed",pending.status=status}this.#render(),this.#scrollToEnd()}async rate(id,rating,comment){try{let conversation=await this.#client.rate(id,rating,comment);return this.#conversations.set(conversation.id,conversation),this.#ratings.delete(id),this.#render(),conversation}catch(error){if(error instanceof ApiError2&&error.status===409){let current=await this.#client.getConversation(id).catch(()=>null);if(current)this.#conversations.set(current.id,current);this.#ratings.delete(id),this.#render()}throw error}}#choose(id,choice){if(this.#ratings.get(id)?.state==="sending")return;if(this.#ratings.set(id,{choice,state:"choosing"}),this.#render(),this.#rateComment.focus({preventScroll:!0}),this.#atEnd)this.#scrollToEnd()}async#submitRating(id,withComment){let draft=this.#ratings.get(id);if(!draft||draft.state==="sending")return;draft.state="sending",this.#render();try{await this.rate(id,draft.choice,withComment?this.#rateComment.value:void 0),this.#rateComment.value=""}catch(error){if(error instanceof ApiError2&&error.status===409)return;draft.state="failed",this.#render()}}async#saveEmail(){let email=this.#emailInput.value.trim();if(!email||!this.#emailInput.checkValidity()){this.#emailError=this.#t({id:"E_qvzP"}),this.#renderEmail();return}try{this.#contact=await this.#client.setEmail(email),this.#emailSaved=!0,this.#emailError=""}catch{this.#emailError=this.#t({id:"ZxJcgC"})}this.#renderEmail()}#attachmentUrl(attachment){let cached=this.#blobs.get(attachment.id);if(cached)return Promise.resolve(cached);let load=this.#blobLoads.get(attachment.id);if(!load)load=this.#client.attachment(attachment.id).then((blob)=>{let url=URL.createObjectURL(blob);return this.#blobs.set(attachment.id,url),url}),load.catch(()=>this.#blobLoads.delete(attachment.id)),this.#blobLoads.set(attachment.id,load);return load}async#download(attachment){let url=await this.#attachmentUrl(attachment),a=el("a");a.href=url,a.download=attachment.filename,a.rel="noopener",a.click()}#sorted(){return[...this.#conversations.values()].sort(byActivity)}#nobodyAvailable(){let inbox=this.#inbox;if(!inbox)return!1;return!inbox.open_now||inbox.mode==="async"||!inbox.presence?.available}#scrollToEnd(){this.#atEnd=!0,this.#scroll.scrollTop=this.#scroll.scrollHeight,requestAnimationFrame(()=>{if(this.#atEnd)this.#scroll.scrollTop=this.#scroll.scrollHeight})}#renderAll(){this.#textarea.placeholder=this.#t({id:"RzWUUK"}),this.#textarea.setAttribute("aria-label",this.#t({id:"xDAtGP"})),this.#attachButton.setAttribute("aria-label",this.#t({id:"N7m8E-"})),this.#attachButton.title=this.#t({id:"N7m8E-"}),this.#sendButton.setAttribute("aria-label",this.#t({id:"JlFcis"})),this.#sendButton.title=this.#t({id:"JlFcis"}),this.#emailInput.placeholder=this.#t({id:"njBr8W"}),this.#emailInput.setAttribute("aria-label",this.#t({id:"XJURKP"})),this.#syncSend(),this.#renderChips(),this.#render()}#render(){let panel=this.#host.panel;if(panel.childElementCount===0){let style=el("style");style.textContent=styles,panel.append(style,this.#header,this.#banner,this.#body,this.#live),this.#header.id="yuva-title",panel.setAttribute("aria-labelledby","yuva-title")}if(this.#renderHeader(),this.#renderBanner(),this.#phase!=="ready"){this.#scrollThread=void 0;let center=el("div","center");if(this.#phase==="loading")center.append(el("p","hint",this.#t({id:"Pwqkdw"})));else{center.append(el("p","empty",this.#errorText()));let retry=el("button","primary",this.#t({id:"KDw4GX"}));retry.type="button",retry.addEventListener("click",()=>{this.#starting=null,this.#start()}),center.append(retry)}this.#body.replaceChildren(center);return}if(this.#view?.kind==="list")this.#renderList();else this.#renderThread()}#errorText(){switch(this.#error){case"anonymous_not_allowed":return this.#t({id:"zLzEI3"});case"invalid_identity_token":return this.#t({id:"0XGLbP"});case"rate_limited":return this.#t({id:"tzsBOP"});case"network":return this.#t({id:"GQVIIl"});default:return this.#t({id:"Amai22"})}}#renderHeader(){let{layout}=this.#host.config(),inbox=this.#inbox,children=[],view=this.#view;if(this.#phase==="ready"&&view?.kind==="thread"&&(this.#conversations.size>1||view.id===null&&this.#conversations.size>0))children.push(iconButton(icons.back,this.#t({id:"S63MQu"}),()=>{this.#stopTyping(),this.#view={kind:"list"},this.#render()}));let heading=el("div","heading");if(heading.append(el("h2","title",inbox?.name||this.#t({id:"t7TeQU"}))),inbox){let status=el("div","status");if(inbox.mode==="live"&&inbox.open_now&&inbox.presence?.available){let avatars=el("div","avatars");for(let member of inbox.presence?.members.slice(0,3)??[]){let avatar=el("span","avatar",member.initials||"•");avatar.title=member.name,avatars.append(avatar)}status.append(avatars,el("span","dot"),el("span","",this.#t({id:"oXOSPE"})))}else if(!inbox.open_now||inbox.mode==="live")status.append(el("span","dot away"),el("span","",this.#t({id:"1EICzz"})));else status.append(el("span","",this.#replyTime(inbox.expected_reply_minutes)));heading.append(status)}if(children.push(heading),layout==="launcher")children.push(iconButton(icons.close,this.#t({id:"yz7wBu"}),()=>this.#host.close()));this.#header.replaceChildren(...children)}#replyTime(minutes){if(!minutes)return this.#t({id:"nhTADq"});let{locale}=this.#host.config(),[value,unit]=minutes<60?[minutes,"minute"]:minutes<1440?[Math.round(minutes/60),"hour"]:[Math.round(minutes/1440),"day"],duration=new Intl.NumberFormat(locale,{style:"unit",unit,unitDisplay:"long"}).format(value);return this.#t({id:"VggdQJ",values:{duration}})}#renderBanner(){this.#banner.hidden=!this.#reconnecting,this.#banner.textContent=this.#t({id:"09Tv5j"})}#renderList(){this.#scrollThread=void 0;let{locale}=this.#host.config(),list=el("ul","list"),today=new Date().toDateString();for(let conversation of this.#sorted()){let button=el("button",conversation.unread?"item unread":"item");button.type="button";let main=el("div","item-main"),top=el("div","item-top");top.append(el("span","item-subject",conversation.subject||this.#inbox?.name||this.#t({id:"YyNOE7"})));let at=new Date(conversation.last_message_at??conversation.created_at);top.append(el("span","item-time",new Intl.DateTimeFormat(locale,at.toDateString()===today?{timeStyle:"short"}:{month:"short",day:"numeric"}).format(at)));let preview=conversation.last_message?`${conversation.last_message.author_type==="contact"?this.#t({id:"ydzYKJ"})+" ":""}${conversation.last_message.text||this.#t({id:"UY1vmE"})}`:"",previewLine=el("div","item-preview",preview.replace(/\*\*|`/g,""));if(previewLine.dir="auto",main.append(top,previewLine),button.append(main),conversation.unread)button.append(el("span","unread-dot"));button.addEventListener("click",()=>void this.#openThread(conversation.id));let item=el("li");item.append(button),list.append(item)}if(this.#conversationCursor){let more=el("button","link",this.#t({id:"ASr-r0"}));more.type="button",more.style.margin="8px auto",more.style.display="block",more.addEventListener("click",()=>void this.#loadConversations(!0).then(()=>this.#render())),list.append(more)}let start=el("button","primary",this.#t({id:"-HY5kX"}));start.type="button",start.addEventListener("click",()=>{this.#view={kind:"thread",id:null},this.#render(),this.#textarea.focus()}),this.#body.replaceChildren(list,start)}async#openThread(id){if(this.#view={kind:"thread",id},this.#render(),!this.#threads.get(id)?.complete&&!this.#threads.get(id)?.messages.length)await this.#loadMessages(id).catch(()=>{return});this.#render(),this.#scrollToEnd(),this.#markRead()}#avatar(author){let avatar=el("span","avatar",author.initials||""),url=author.avatar_url,state=url?this.#avatars.get(url):!1;if(!url||state===!1)return avatar;let img=el("img");if(img.alt="",img.referrerPolicy="no-referrer",state)return img.src=url,avatar.replaceChildren(img),avatar;return img.addEventListener("load",()=>{if(this.#avatars.set(url,!0),avatar.isConnected)avatar.replaceChildren(img)}),img.addEventListener("error",()=>this.#avatars.set(url,!1)),img.src=url,avatar}#renderThread(){let view=this.#view;if(view?.kind!=="thread")return;let id=view.id,sameThread=this.#scrollThread===id,atEnd=this.#atEnd,thread=id?this.#threads.get(id):void 0,messages=thread?.messages??[],pending=this.#pending.filter((p)=>p.conversation===id),nodes=[],greeting=this.#inbox?.chat.greeting;if(!thread||thread.complete){if(greeting){let bubble=el("div","bubble greeting");bubble.append(richText(greeting)),nodes.push(bubble)}else if(messages.length===0&&pending.length===0){let center=el("div","center");center.append(el("p","empty",this.#t({id:"meAa31"})),el("p","hint",this.#t({id:"SdV5Cn"}))),nodes.push(center)}}else if(thread.loading)nodes.push(el("p","hint",this.#t({id:"Pwqkdw"})));messages.forEach((message,i)=>{let previous=messages[i-1],next=messages[i+1]??(pending.length>0?null:void 0),mine=message.author.type==="contact",starts=!previous||authorKey(previous)!==authorKey(message)||time(message.created_at)-time(previous.created_at)>groupGap,ends=next===void 0||(next===null?!mine:authorKey(next)!==authorKey(message)||time(next.created_at)-time(message.created_at)>groupGap);if(!mine&&starts&&message.author.name)nodes.push(el("div","author",message.author.name));let row=el("div",`row ${mine?"mine":"theirs"}${starts&&i>0?" group-gap":""}`);if(!mine){let avatar=this.#avatar(message.author);if(!ends)avatar.style.visibility="hidden";row.append(avatar)}let bubble=el("div","bubble");if(bubble.dir="auto",bubble.title=new Date(message.created_at).toLocaleString(this.#host.config().locale),message.body.trim())bubble.append(richText(message.body));if(message.attachments.length>0)bubble.append(this.#renderAttachments(message.attachments));if(row.append(bubble),nodes.push(row),ends){let meta=this.#formatTime(message.created_at);if(mine&&i===messages.length-1&&pending.length===0){let readAt=id?this.#conversations.get(id)?.last_read_by_member_at:void 0,seen=readAt&&time(readAt)>=time(message.created_at);meta+=` · ${seen?this.#t({id:"6lGaum"}):this.#t({id:"h69WC6"})}`}let line=el("div","meta",meta);if(!mine)line.style.alignSelf="flex-start";if(!mine)line.style.marginInlineStart="36px";nodes.push(line)}});let conversation=id?this.#conversations.get(id):void 0,rate=conversation?this.#renderRating(conversation):null;if(rate)nodes.push(rate);pending.forEach((item,i)=>{let row=el("div",`row mine${i===0&&messages.length>0&&messages[messages.length-1]?.author.type!=="contact"?" group-gap":""}`),bubble=el("div","bubble");if(bubble.dir="auto",item.body)bubble.append(richText(item.body));if(item.files.length>0){let files=el("div","files");for(let file of item.files)files.append(el("span","file",file.name||"image"));bubble.append(files)}if(row.append(bubble),nodes.push(row),item.state==="failed"){let line=el("div","meta failed",`${this.#t({id:"upFvcp"})} `),retry=el("button","link",this.#t({id:"6gRgw8"}));retry.type="button",retry.addEventListener("click",()=>void this.#deliver(item)),line.append(retry),nodes.push(line)}else if(item.state==="refused"){let reason=item.status===413?this.#t({id:"eOu9Px"}):this.#t({id:"JkW3Ph"});nodes.push(el("div","meta failed",`${this.#t({id:"upFvcp"})} ${reason}`))}else if(i===pending.length-1)nodes.push(el("div","meta",this.#t({id:"Sad2tK"})))});let typing=id?this.#typing.get(id):void 0;if(typing){let line=el("div","typing");line.append(el("i"),el("i"),el("i"));let name=typing.name;line.append(el("span","",name?this.#t({id:"tHaDPf",values:{name}}):this.#t({id:"PxYAul"}))),nodes.push(line)}let focused=this.#scroll.getRootNode().activeElement===this.#rateComment,{selectionStart,selectionEnd}=this.#rateComment;if(this.#scroll.replaceChildren(...nodes),focused&&this.#rateComment.isConnected)this.#rateComment.focus({preventScroll:!0}),this.#rateComment.setSelectionRange(selectionStart,selectionEnd);if(this.#renderEmail(),this.#body.firstChild!==this.#scroll)this.#body.replaceChildren(this.#scroll,this.#email,this.#composer);if(this.#scrollThread=id,!sameThread||atEnd)this.#scrollToEnd()}#renderRating(conversation){let rated=conversation.status==="closed"?conversation.rating:void 0,draft=conversation.can_rate&&this.#inbox?.ask_for_rating?this.#ratings.get(conversation.id):void 0;if(!rated&&!(conversation.can_rate&&this.#inbox?.ask_for_rating))return null;let card=this.#rateCard,key=[conversation.id,rated,draft?.choice,draft?.state,this.#host.config().locale].join(":");if(key===this.#rateKey)return card;if(this.#rateKey=key,this.#rateFor!==conversation.id)this.#rateFor=conversation.id,this.#rateComment.value="";let question=this.#t({id:"uA8iBc"});card.setAttribute("role","group"),card.setAttribute("aria-label",question);let choices=el("div","choices");for(let value of["good","bad"]){if(rated&&rated!==value)continue;let button=el("button","choice",value==="good"?"\uD83D\uDC4D":"\uD83D\uDC4E");button.type="button";let label=value==="good"?this.#t({id:"OEEQKT"}):this.#t({id:"-f5Tkb"});button.setAttribute("aria-label",label),button.title=label,button.setAttribute("aria-pressed",String((rated??draft?.choice)===value)),button.disabled=!!rated||draft?.state==="sending",button.addEventListener("click",()=>this.#choose(conversation.id,value)),choices.append(button)}if(rated)return card.replaceChildren(choices,el("p","",this.#t({id:"SOk0EB"}))),card;if(card.replaceChildren(el("p","",question),choices),!draft)return card;this.#rateComment.placeholder=this.#t({id:"axQ1h6"}),this.#rateComment.setAttribute("aria-label",this.#t({id:"NBdIgR"})),this.#rateComment.disabled=draft.state==="sending";let form=el("form");form.addEventListener("submit",(event)=>{event.preventDefault(),this.#submitRating(conversation.id,!0)});let skip=el("button","link",this.#t({id:"6Uau97"}));skip.type="button",skip.disabled=draft.state==="sending",skip.addEventListener("click",()=>void this.#submitRating(conversation.id,!1));let send=el("button","",draft.state==="sending"?this.#t({id:"Sad2tK"}):this.#t({id:"JlFcis"}));send.type="submit",send.disabled=draft.state==="sending";let actions=el("div","actions");if(actions.append(skip,send),form.append(this.#rateComment,actions),card.append(form),draft.state==="failed")card.append(el("p","error",this.#t({id:"4TqZiz"})));return card}#renderAttachments(attachments){let files=el("div","files");for(let attachment of attachments)if(isImage(attachment)){let img=el("img");img.alt=attachment.filename;let cached=this.#blobs.get(attachment.id);if(cached)img.src=cached;else this.#attachmentUrl(attachment).then((url)=>{img.src=url}).catch(()=>{return});img.addEventListener("load",()=>{if(this.#atEnd)this.#scroll.scrollTop=this.#scroll.scrollHeight}),img.addEventListener("click",()=>void this.#download(attachment)),files.append(img)}else{let button=el("button","file");button.type="button",button.innerHTML=icons.file,button.append(el("span","",attachment.filename)),button.addEventListener("click",()=>void this.#download(attachment)),files.append(button)}return files}#formatTime(value){return new Intl.DateTimeFormat(this.#host.config().locale,{timeStyle:"short"}).format(new Date(value))}#renderEmail(){let contact=this.#contact,chat=this.#inbox?.chat,sent=(this.#view?.kind==="thread"?this.#view.id:null)!==null||this.#pending.length>0,known=contact?.email||contact?.typed_email,show=!!chat?.ask_email_offline&&this.#nobodyAvailable()&&sent&&(!known||this.#emailSaved);if(this.#email.hidden=!show,!show)return;if(known&&this.#emailSaved){this.#email.replaceChildren(el("p","",this.#t({id:"iGNUZJ",values:{known}})));return}if(this.#email.querySelector("form")){let error=this.#email.querySelector(".error");if(error)error.textContent=this.#emailError;else if(this.#emailError)this.#email.append(el("p","error",this.#emailError));return}let form=el("form");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#saveEmail()});let save=el("button","",this.#t({id:"tfDRzk"}));if(save.type="submit",form.append(this.#emailInput,save),this.#email.replaceChildren(el("p","",this.#t({id:"M62PBt"})),form),this.#emailError)this.#email.append(el("p","error",this.#emailError))}#renderChips(){this.#chips.hidden=this.#files.length===0,this.#chips.replaceChildren(...this.#files.map((file,index)=>{let chip=el("span","chip");return chip.append(el("span","",file.name||"image"),iconButton(icons.close,this.#t({id:"w61W3L",values:{0:file.name}}),()=>{this.#files=this.#files.filter((_,i)=>i!==index),this.#renderChips(),this.#syncSend()})),chip}))}}function mount(host){return new Chat(host)}export{mount};
@@ -9,6 +9,23 @@ export type ClientConversation = Schemas["ClientConversation"];
9
9
  export type ClientConversationPage = Schemas["ClientConversationPage"];
10
10
  export type ClientConversationCreated = Schemas["ClientConversationCreated"];
11
11
  export type ClientRatingCreate = Schemas["ClientRatingCreate"];
12
+ export type ClientFeedbackCreate = Schemas["ClientFeedbackCreate"];
13
+ export type PageRating = Schemas["PageRating"];
14
+ export type PageRatingCreate = Schemas["PageRatingCreate"];
15
+ export type ClientChatSettings = Schemas["ClientChatSettings"];
16
+ export type DiscussionMode = Schemas["DiscussionMode"];
17
+ export type DiscussionState = Schemas["DiscussionState"];
18
+ export type DiscussionSort = Schemas["DiscussionSort"];
19
+ export type DiscussionAuthor = Schemas["DiscussionAuthor"];
20
+ export type Discussion = Schemas["Discussion"];
21
+ export type DiscussionPost = Schemas["DiscussionPost"];
22
+ export type DiscussionDetail = Schemas["DiscussionDetail"];
23
+ export type DiscussionPage = Schemas["DiscussionPage"];
24
+ export type ClientDiscussionCreate = Schemas["ClientDiscussionCreate"];
25
+ export type DiscussionPostCreate = Schemas["DiscussionPostCreate"];
26
+ export type ClientDiscussionPostUpdate = Schemas["ClientDiscussionPostUpdate"];
27
+ export type ReaderToken = Schemas["ReaderToken"];
28
+ export type ReaderProfile = Schemas["ReaderProfile"];
12
29
  export type Rating = Schemas["Rating"];
13
30
  export type ClientMessage = Schemas["ClientMessage"];
14
31
  export type ClientMessagePage = Schemas["ClientMessagePage"];
@@ -1,4 +1,5 @@
1
- import { type Fetch, type ClientContact, type ClientConversation, type ClientConversationCreated, type ClientConversationPage, type ClientInbox, type ClientMessage, type ClientMessagePage, type ClientReadState, type ClientRealtimeMessage, type ClientSessionInfo, type Rating } from "./api.js";
1
+ import { type Fetch, type ClientContact, type ClientConversation, type ClientConversationCreated, type ClientConversationPage, type ClientFeedbackCreate, type ClientInbox, type ClientMessage, type ClientMessagePage, type ClientDiscussionCreate, type ClientDiscussionPostUpdate, type Discussion, type DiscussionDetail, type DiscussionPage, type DiscussionPost, type DiscussionPostCreate, type DiscussionSort, type ClientReadState, type ClientRealtimeMessage, type ClientSessionInfo, type PageRatingCreate, type Rating } from "./api.js";
2
+ import { type ReaderSession, type ReaderSignInOptions } from "./reader.js";
2
3
  export type IdentityTokenSource = () => string | null | undefined | Promise<string | null | undefined>;
3
4
  export interface YuvaStorage {
4
5
  getItem(key: string): string | null;
@@ -33,6 +34,7 @@ export interface YuvaClientEvents {
33
34
  session: ClientSessionInfo;
34
35
  renewed: boolean;
35
36
  };
37
+ reader: ReaderSession | null;
36
38
  }
37
39
  export interface MessageInput {
38
40
  body?: string;
@@ -46,7 +48,11 @@ export interface Page {
46
48
  cursor?: string;
47
49
  limit?: number;
48
50
  }
51
+ export interface DiscussionListOptions extends Page {
52
+ sort?: DiscussionSort;
53
+ }
49
54
  export declare function storageKey(channel: string): string;
55
+ export declare function readerStorageKey(server: string, channel: string): string;
50
56
  export declare function randomId(): string;
51
57
  export declare class YuvaClient {
52
58
  #private;
@@ -59,6 +65,7 @@ export declare class YuvaClient {
59
65
  on<K extends keyof YuvaClientEvents>(type: K, handler: (value: YuvaClientEvents[K]) => void): () => void;
60
66
  stored(): StoredState;
61
67
  channelSettings(): Promise<ClientInbox>;
68
+ ratePage(input: PageRatingCreate): Promise<void>;
62
69
  setIdentityToken(source: IdentityTokenSource | null): void;
63
70
  start(): Promise<ClientSessionInfo>;
64
71
  refresh(): Promise<ClientSessionInfo>;
@@ -79,5 +86,20 @@ export declare class YuvaClient {
79
86
  setTyping(conversationId: string, typing: boolean): Promise<void>;
80
87
  setEmail(email: string): Promise<ClientContact>;
81
88
  attachment(id: string): Promise<Blob>;
89
+ sendFeedback(input: ClientFeedbackCreate): Promise<ClientConversationCreated>;
90
+ get reader(): ReaderSession | null;
91
+ readerSignIn(options?: ReaderSignInOptions): Promise<ReaderSession>;
92
+ setReader(reader: ReaderSession | null): void;
93
+ readerSignOut(): Promise<void>;
94
+ listDiscussions(page: string, options?: DiscussionListOptions): Promise<DiscussionPage>;
95
+ getDiscussion(id: string): Promise<DiscussionDetail>;
96
+ startDiscussion(input: ClientDiscussionCreate): Promise<Discussion>;
97
+ replyToDiscussion(discussionId: string, input: DiscussionPostCreate): Promise<DiscussionPost>;
98
+ editDiscussionPost(postId: string, input: ClientDiscussionPostUpdate): Promise<DiscussionPost>;
99
+ deleteDiscussionPost(postId: string): Promise<void>;
100
+ voteDiscussionPost(postId: string, voted?: boolean): Promise<DiscussionPost>;
101
+ followDiscussion(discussionId: string, following?: boolean): Promise<void>;
102
+ acceptDiscussionAnswer(discussionId: string, postId: string | null): Promise<Discussion>;
103
+ discussionWriter(): Promise<"reader" | "contact" | null>;
82
104
  }
83
105
  export declare function createYuvaClient(options: YuvaClientOptions): YuvaClient;
@@ -0,0 +1,12 @@
1
+ import { type ReaderProfile } from "./api.js";
2
+ export interface ReaderSession {
3
+ token: string;
4
+ expires_at: string;
5
+ reader: ReaderProfile;
6
+ }
7
+ export interface ReaderSignInOptions {
8
+ width?: number;
9
+ height?: number;
10
+ }
11
+ export declare function readerConnectUrl(server: string, channel: string, origin: string): string;
12
+ export declare function openReaderPopup(server: string, channel: string, { width, height }?: ReaderSignInOptions): Promise<ReaderSession>;
@@ -0,0 +1,43 @@
1
+ import type { MessageDescriptor } from "@lingui/core";
2
+ import { type ClientInbox } from "../client/api.js";
3
+ import { type IdentityTokenSource, type YuvaClient } from "../client/client.js";
4
+ import { el } from "./dom.js";
5
+ export { el };
6
+ declare const Base: typeof HTMLElement;
7
+ export declare const scriptSrc: string;
8
+ export declare const baseStyles = "\n:host {\n --yuva-accent: #2563eb;\n --yuva-on-accent: #ffffff;\n --yuva-border: rgb(127 127 127 / 0.35);\n --yuva-soft: rgb(127 127 127 / 0.1);\n --yuva-danger: #dc2626;\n display: block;\n color: inherit;\n font: inherit;\n line-height: 1.5;\n}\n:host([hidden]) { display: none; }\n@media (prefers-color-scheme: dark) {\n :host { --yuva-danger: #f87171; }\n}\n[hidden] { display: none !important; }\n* { box-sizing: border-box; }\np { margin: 0; }\n.muted { opacity: 0.72; font-size: 0.9em; }\n.error { color: var(--yuva-danger); font-size: 0.9em; }\nform { display: flex; flex-direction: column; gap: 8px; }\ntextarea, input {\n inline-size: 100%;\n padding: 8px 10px;\n border: 1px solid var(--yuva-border);\n border-radius: 8px;\n background: transparent;\n color: inherit;\n font: inherit;\n}\ntextarea { resize: vertical; min-block-size: 72px; }\ntextarea:focus-visible, input:focus-visible { outline: 2px solid var(--yuva-accent); outline-offset: -1px; border-color: transparent; }\n.actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: flex-end; }\n.send {\n padding: 8px 14px;\n border: 0;\n border-radius: 8px;\n background: var(--yuva-accent);\n color: var(--yuva-on-accent);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.send:disabled { opacity: 0.6; cursor: default; }\n.send:focus-visible, .link:focus-visible { outline: 2px solid var(--yuva-accent); outline-offset: 2px; }\n.link { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; opacity: 0.8; }\n@media (max-width: 480px) { textarea, input { font-size: 16px; } }\n";
9
+ export declare abstract class YuvaDocsElement extends Base {
10
+ #private;
11
+ static observedAttributes: string[];
12
+ protected root: ShadowRoot;
13
+ protected inbox: ClientInbox | null;
14
+ protected pageUrl: string;
15
+ protected refused: boolean;
16
+ protected direction: "ltr" | "rtl";
17
+ constructor();
18
+ get channel(): string | null;
19
+ set channel(value: string | null);
20
+ get server(): string;
21
+ set server(value: string | null);
22
+ get locale(): string;
23
+ set locale(value: string | null);
24
+ get page(): string;
25
+ set page(value: string | null);
26
+ get pageTitle(): string;
27
+ set pageTitle(value: string | null);
28
+ setIdentityToken(source: IdentityTokenSource | null): void;
29
+ connectedCallback(): void;
30
+ disconnectedCallback(): void;
31
+ attributeChangedCallback(name: string, previous: string | null, value: string | null): void;
32
+ protected abstract render(): void;
33
+ protected abstract pageChanged(): void;
34
+ protected abstract reset(): void;
35
+ protected t(descriptor: MessageDescriptor): string;
36
+ protected client(): YuvaClient;
37
+ protected get identified(): boolean;
38
+ protected get canWrite(): boolean;
39
+ protected emit(type: string, detail: unknown): void;
40
+ protected refusal(error: unknown, channelRequest?: boolean): boolean;
41
+ protected errorText(error: unknown): string;
42
+ protected frame(css: string, ...children: Node[]): void;
43
+ }
@@ -0,0 +1 @@
1
+ export declare function defineDocs(): void;
@@ -0,0 +1,22 @@
1
+ import { type Discussion } from "../client/api.js";
2
+ import type { ReaderSession } from "../client/reader.js";
3
+ import { YuvaDocsElement } from "./base.js";
4
+ export type { DiscussionDetailEvent, DiscussionPostDetail } from "./thread.js";
5
+ export type ThreadModule = typeof import("./thread.js");
6
+ export declare class YuvaDiscussionsElement extends YuvaDocsElement {
7
+ #private;
8
+ static loadThread: () => Promise<ThreadModule>;
9
+ get discussions(): Discussion[];
10
+ get reader(): ReaderSession | null;
11
+ connectedCallback(): void;
12
+ disconnectedCallback(): void;
13
+ attributeChangedCallback(name: string, previous: string | null, value: string | null): void;
14
+ setIdentityToken(source: Parameters<YuvaDocsElement["setIdentityToken"]>[0]): void;
15
+ protected reset(): void;
16
+ protected pageChanged(): void;
17
+ reload(): Promise<void>;
18
+ open(id: string): Promise<void>;
19
+ signIn(): Promise<void>;
20
+ signOut(): Promise<void>;
21
+ protected render(): void;
22
+ }
@@ -0,0 +1 @@
1
+ export declare function el<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string, text?: string): HTMLElementTagNameMap[K];
@@ -0,0 +1,21 @@
1
+ import type { PageRating } from "../client/api.js";
2
+ import { YuvaDocsElement } from "./base.js";
3
+ export interface PageRatingDetail {
4
+ page: string;
5
+ rating: PageRating;
6
+ previous: PageRating | null;
7
+ }
8
+ export interface PageFeedbackDetail {
9
+ page: string;
10
+ rating: PageRating | null;
11
+ conversation_id: string;
12
+ }
13
+ export declare class YuvaPageFeedbackElement extends YuvaDocsElement {
14
+ #private;
15
+ constructor();
16
+ get rating(): PageRating | null;
17
+ protected reset(): void;
18
+ protected pageChanged(): void;
19
+ rate(rating: PageRating): Promise<void>;
20
+ protected render(): void;
21
+ }
@@ -0,0 +1,2 @@
1
+ export declare function pageOf(value: string | null): string;
2
+ export declare function followPage(listener: () => void): () => void;
@@ -0,0 +1 @@
1
+ export declare function preview(markdown: string): DocumentFragment;