useyuva 0.0.25 → 0.0.27

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 (202) hide show
  1. package/README.md +1 -0
  2. package/dist/esm/apps-5c2vy32k.js +1 -0
  3. package/dist/esm/apps-ghkaqqx8.js +128 -0
  4. package/dist/esm/chat.js +33 -16
  5. package/dist/esm/{client-ebw9d6ms.js → client-k8txer77.js} +1 -1
  6. package/dist/esm/docs.js +4 -4
  7. package/dist/esm/index-0b3zs3hm.js +2 -0
  8. package/dist/esm/index-17p275de.js +2 -0
  9. package/dist/esm/index-1tyn193t.js +2 -0
  10. package/dist/esm/index-4mayxpxs.js +2 -0
  11. package/dist/esm/index-5tfxryvn.js +2 -0
  12. package/dist/esm/index-69xd7mjq.js +12 -0
  13. package/dist/esm/index-kf733km6.js +2 -0
  14. package/dist/esm/index.js +1 -1
  15. package/dist/esm/panel-jfe47dat.js +1 -0
  16. package/dist/esm/react.js +1 -1
  17. package/dist/esm/status.js +6 -4
  18. package/dist/esm/subscribe.js +2 -2
  19. package/dist/esm/thread-3y5hexyq.js +61 -0
  20. package/dist/esm/yuva-chat-j6fbj8y2.js +282 -0
  21. package/dist/types/apps/apps.d.ts +4 -0
  22. package/dist/types/apps/feedback.d.ts +3 -0
  23. package/dist/types/apps/help.d.ts +4 -0
  24. package/dist/types/apps/roadmap.d.ts +3 -0
  25. package/dist/types/apps/status.d.ts +3 -0
  26. package/dist/types/apps/styles.d.ts +1 -0
  27. package/dist/types/apps/subscribe.d.ts +3 -0
  28. package/dist/types/apps/whatsnew.d.ts +3 -0
  29. package/dist/types/catalogs/apps.d.ts +2 -0
  30. package/dist/types/client/api.d.ts +25 -0
  31. package/dist/types/client/client.d.ts +41 -2
  32. package/dist/types/element.d.ts +2 -1
  33. package/dist/types/i18n.d.ts +1 -1
  34. package/dist/types/index.d.ts +2 -2
  35. package/dist/types/locales/ar/apps.d.ts +2 -0
  36. package/dist/types/locales/bn/apps.d.ts +2 -0
  37. package/dist/types/locales/ca/apps.d.ts +2 -0
  38. package/dist/types/locales/cs/apps.d.ts +2 -0
  39. package/dist/types/locales/da/apps.d.ts +2 -0
  40. package/dist/types/locales/de/apps.d.ts +2 -0
  41. package/dist/types/locales/el/apps.d.ts +2 -0
  42. package/dist/types/locales/en/apps.d.ts +2 -0
  43. package/dist/types/locales/es/apps.d.ts +2 -0
  44. package/dist/types/locales/es-MX/apps.d.ts +2 -0
  45. package/dist/types/locales/fi/apps.d.ts +2 -0
  46. package/dist/types/locales/fr/apps.d.ts +2 -0
  47. package/dist/types/locales/fr-CA/apps.d.ts +2 -0
  48. package/dist/types/locales/gu/apps.d.ts +2 -0
  49. package/dist/types/locales/he/apps.d.ts +2 -0
  50. package/dist/types/locales/hi/apps.d.ts +2 -0
  51. package/dist/types/locales/hr/apps.d.ts +2 -0
  52. package/dist/types/locales/hu/apps.d.ts +2 -0
  53. package/dist/types/locales/id/apps.d.ts +2 -0
  54. package/dist/types/locales/it/apps.d.ts +2 -0
  55. package/dist/types/locales/ja/apps.d.ts +2 -0
  56. package/dist/types/locales/kn/apps.d.ts +2 -0
  57. package/dist/types/locales/ko/apps.d.ts +2 -0
  58. package/dist/types/locales/ml/apps.d.ts +2 -0
  59. package/dist/types/locales/mr/apps.d.ts +2 -0
  60. package/dist/types/locales/ms/apps.d.ts +2 -0
  61. package/dist/types/locales/nb/apps.d.ts +2 -0
  62. package/dist/types/locales/nl/apps.d.ts +2 -0
  63. package/dist/types/locales/or/apps.d.ts +2 -0
  64. package/dist/types/locales/pa/apps.d.ts +2 -0
  65. package/dist/types/locales/pl/apps.d.ts +2 -0
  66. package/dist/types/locales/pt-BR/apps.d.ts +2 -0
  67. package/dist/types/locales/pt-PT/apps.d.ts +2 -0
  68. package/dist/types/locales/ro/apps.d.ts +2 -0
  69. package/dist/types/locales/ru/apps.d.ts +2 -0
  70. package/dist/types/locales/sk/apps.d.ts +2 -0
  71. package/dist/types/locales/sl/apps.d.ts +2 -0
  72. package/dist/types/locales/sv/apps.d.ts +2 -0
  73. package/dist/types/locales/ta/apps.d.ts +2 -0
  74. package/dist/types/locales/te/apps.d.ts +2 -0
  75. package/dist/types/locales/th/apps.d.ts +2 -0
  76. package/dist/types/locales/tr/apps.d.ts +2 -0
  77. package/dist/types/locales/uk/apps.d.ts +2 -0
  78. package/dist/types/locales/ur/apps.d.ts +2 -0
  79. package/dist/types/locales/vi/apps.d.ts +2 -0
  80. package/dist/types/locales/zh-Hans/apps.d.ts +2 -0
  81. package/dist/types/locales/zh-Hant/apps.d.ts +2 -0
  82. package/dist/types/panel/capture.d.ts +2 -0
  83. package/dist/types/panel/chat.d.ts +3 -1
  84. package/dist/types/panel/helpers.d.ts +15 -0
  85. package/dist/types/panel/home.d.ts +18 -0
  86. package/dist/types/panel/icons.d.ts +28 -0
  87. package/dist/types/panel/styles.d.ts +1 -1
  88. package/dist/types/react.d.ts +30 -2
  89. package/dist/types/schema.gen.d.ts +18078 -11611
  90. package/dist/types/translate.d.ts +1 -1
  91. package/dist/types/types.d.ts +33 -1
  92. package/dist/types/updates.d.ts +3 -0
  93. package/dist/widget/yuva-apps-ar-wk63tmr6.js +1 -0
  94. package/dist/widget/yuva-apps-bn-mv215pfz.js +1 -0
  95. package/dist/widget/yuva-apps-ca-mxrszyen.js +1 -0
  96. package/dist/widget/yuva-apps-cs-szpm8fq7.js +1 -0
  97. package/dist/widget/yuva-apps-da-v9sx8j55.js +1 -0
  98. package/dist/widget/yuva-apps-de-fd1snm0x.js +1 -0
  99. package/dist/widget/yuva-apps-el-wecybgxk.js +1 -0
  100. package/dist/widget/yuva-apps-en-skz2hc45.js +1 -0
  101. package/dist/widget/yuva-apps-es-18nqt6cs.js +1 -0
  102. package/dist/widget/yuva-apps-es-mx-23h92xvs.js +1 -0
  103. package/dist/widget/yuva-apps-fi-9tffjg50.js +1 -0
  104. package/dist/widget/yuva-apps-fr-ca-ma4cfsvr.js +1 -0
  105. package/dist/widget/yuva-apps-fr-v6fmnc7n.js +1 -0
  106. package/dist/widget/yuva-apps-gu-4v1dxzbn.js +1 -0
  107. package/dist/widget/yuva-apps-he-yy8ajb9j.js +1 -0
  108. package/dist/widget/yuva-apps-hi-zezzdfb4.js +1 -0
  109. package/dist/widget/yuva-apps-hr-skjtsrz6.js +1 -0
  110. package/dist/widget/yuva-apps-hu-q79hae7c.js +1 -0
  111. package/dist/widget/yuva-apps-id-rvr6g27r.js +1 -0
  112. package/dist/widget/yuva-apps-it-hkfb6swg.js +1 -0
  113. package/dist/widget/yuva-apps-ja-71z2p7a6.js +1 -0
  114. package/dist/widget/yuva-apps-kn-xm2wsv24.js +1 -0
  115. package/dist/widget/yuva-apps-ko-5b90egt2.js +1 -0
  116. package/dist/widget/yuva-apps-ml-qyjc0208.js +1 -0
  117. package/dist/widget/yuva-apps-mr-wh0985vm.js +1 -0
  118. package/dist/widget/yuva-apps-ms-2et5c44x.js +1 -0
  119. package/dist/widget/yuva-apps-nb-hnr4p136.js +1 -0
  120. package/dist/widget/yuva-apps-nl-m5z18z8w.js +1 -0
  121. package/dist/widget/yuva-apps-or-6ggz8n7c.js +1 -0
  122. package/dist/widget/yuva-apps-pa-p0zp743s.js +1 -0
  123. package/dist/widget/yuva-apps-pl-ayf5z37n.js +1 -0
  124. package/dist/widget/yuva-apps-pt-br-pmegf5s7.js +1 -0
  125. package/dist/widget/yuva-apps-pt-pt-fqqmhnsg.js +1 -0
  126. package/dist/widget/yuva-apps-ro-kq1mexyc.js +1 -0
  127. package/dist/widget/yuva-apps-ru-k3vhm4n9.js +1 -0
  128. package/dist/widget/yuva-apps-sk-n0st8g80.js +1 -0
  129. package/dist/widget/yuva-apps-sl-5yzf8nkk.js +1 -0
  130. package/dist/widget/yuva-apps-sv-bfchg8n0.js +1 -0
  131. package/dist/widget/yuva-apps-ta-zgn0hzpc.js +1 -0
  132. package/dist/widget/yuva-apps-te-eyyyp1fs.js +1 -0
  133. package/dist/widget/yuva-apps-th-tq3fdyxf.js +1 -0
  134. package/dist/widget/yuva-apps-tr-9bq6yzyy.js +1 -0
  135. package/dist/widget/yuva-apps-uk-0azd9r77.js +1 -0
  136. package/dist/widget/yuva-apps-ur-j8m34b8k.js +1 -0
  137. package/dist/widget/yuva-apps-vi-hs9e6h1q.js +1 -0
  138. package/dist/widget/yuva-apps-zh-hans-bc7j7gt0.js +1 -0
  139. package/dist/widget/yuva-apps-zh-hant-9ke56jnf.js +1 -0
  140. package/dist/widget/yuva-chat-apps-yrvvqdf9.js +128 -0
  141. package/dist/widget/{yuva-docs-thread-3594bmxy.js → yuva-docs-thread-gha4vzfm.js} +5 -5
  142. package/dist/widget/yuva-panel-ar-w9kxar7b.js +1 -0
  143. package/dist/widget/yuva-panel-bn-w0jg8rz0.js +1 -0
  144. package/dist/widget/yuva-panel-ca-3xmep2qy.js +1 -0
  145. package/dist/widget/yuva-panel-cs-jxdap7hk.js +1 -0
  146. package/dist/widget/yuva-panel-da-xy0gn2ch.js +1 -0
  147. package/dist/widget/yuva-panel-de-z1haaaf5.js +1 -0
  148. package/dist/widget/yuva-panel-el-vhskf13n.js +1 -0
  149. package/dist/widget/yuva-panel-en-yntqp1wb.js +1 -0
  150. package/dist/widget/yuva-panel-es-91gq45ad.js +1 -0
  151. package/dist/widget/yuva-panel-es-mx-593ry1sp.js +1 -0
  152. package/dist/widget/yuva-panel-fi-dw2qy2ep.js +1 -0
  153. package/dist/widget/yuva-panel-fr-ca-kwqpxepb.js +1 -0
  154. package/dist/widget/yuva-panel-fr-mksekp2w.js +1 -0
  155. package/dist/widget/yuva-panel-gu-9brj4atb.js +1 -0
  156. package/dist/widget/yuva-panel-he-kwf5a5r1.js +1 -0
  157. package/dist/widget/yuva-panel-hi-hyqwxkva.js +1 -0
  158. package/dist/widget/yuva-panel-hr-xyc32ytv.js +1 -0
  159. package/dist/widget/yuva-panel-hu-dsf2tr60.js +1 -0
  160. package/dist/widget/yuva-panel-id-egadejce.js +1 -0
  161. package/dist/widget/yuva-panel-it-dstzsdpt.js +1 -0
  162. package/dist/widget/yuva-panel-ja-5ep2nhr6.js +1 -0
  163. package/dist/widget/yuva-panel-kn-ggsqc21e.js +1 -0
  164. package/dist/widget/yuva-panel-ko-7cr7d0zc.js +1 -0
  165. package/dist/widget/yuva-panel-ml-0vb742gf.js +1 -0
  166. package/dist/widget/yuva-panel-mr-f7sn0acm.js +1 -0
  167. package/dist/widget/yuva-panel-ms-7xavwv7n.js +1 -0
  168. package/dist/widget/yuva-panel-nb-34x0g8mq.js +1 -0
  169. package/dist/widget/yuva-panel-nl-rkak2t5r.js +1 -0
  170. package/dist/widget/yuva-panel-or-q6eks6dh.js +1 -0
  171. package/dist/widget/yuva-panel-pa-26mhm7me.js +1 -0
  172. package/dist/widget/yuva-panel-pl-6bsq33w3.js +1 -0
  173. package/dist/widget/yuva-panel-pt-br-5bf6ja6w.js +1 -0
  174. package/dist/widget/yuva-panel-pt-pt-2a7vh8y9.js +1 -0
  175. package/dist/widget/yuva-panel-ro-9255bnc4.js +1 -0
  176. package/dist/widget/yuva-panel-ru-1ydh24ae.js +1 -0
  177. package/dist/widget/yuva-panel-sk-50gc8kfg.js +1 -0
  178. package/dist/widget/yuva-panel-sl-0j7nnz7k.js +1 -0
  179. package/dist/widget/yuva-panel-sv-175kbch1.js +1 -0
  180. package/dist/widget/yuva-panel-ta-x4nnzatk.js +1 -0
  181. package/dist/widget/yuva-panel-te-35y4486b.js +1 -0
  182. package/dist/widget/yuva-panel-th-rx5h6eq6.js +1 -0
  183. package/dist/widget/yuva-panel-tr-ywyzb4rn.js +1 -0
  184. package/dist/widget/yuva-panel-uk-9h1czxf0.js +1 -0
  185. package/dist/widget/yuva-panel-ur-peb4hk7h.js +1 -0
  186. package/dist/widget/yuva-panel-vi-t97hnjrg.js +1 -0
  187. package/dist/widget/yuva-panel-zh-hans-djf7yajw.js +1 -0
  188. package/dist/widget/yuva-panel-zh-hant-a9cgjbmw.js +1 -0
  189. package/dist/widget/yuva-subscribe-client-32k2vgq4.js +11 -0
  190. package/dist/yuva-chat.js +238 -158
  191. package/dist/yuva-docs.js +6 -6
  192. package/dist/yuva-status.js +9 -7
  193. package/dist/yuva-subscribe.js +2 -2
  194. package/dist/yuva.js +33 -16
  195. package/package.json +1 -1
  196. package/dist/esm/index-3wpqkv7x.js +0 -2
  197. package/dist/esm/index-6brgxahe.js +0 -12
  198. package/dist/esm/index-ceev0134.js +0 -2
  199. package/dist/esm/index-rdzxvj2r.js +0 -2
  200. package/dist/esm/thread-g9jsp0c5.js +0 -61
  201. package/dist/esm/yuva-chat-9hx7wb3q.js +0 -202
  202. package/dist/widget/yuva-subscribe-client-bx862wkt.js +0 -11
@@ -0,0 +1,282 @@
1
+ import{randomId2,createYuvaClient2}from"./index-69xd7mjq.js";import{messages2,icons,el,iconButton,textButton,searchField,time,byCreated,byActivity,authorKey,isImage,initialsOf,fileKind,fileSize,dayLabel,sameDay,canCapture,captureScreen}from"./index-5tfxryvn.js";import{richText}from"./index-jdxce2se.js";import{countUpdates}from"./index-kf733km6.js";import{launcherOf,readStored,writeStored}from"./index-8f1n6nzn.js";import{ApiError2}from"./index-gk84nm8f.js";import{addStyles}from"./index-4mayxpxs.js";import{setupI18n}from"@lingui/core";var stateText={operational:{id:"UQbwrz"},degraded:{id:"uN55Po"},partial_outage:{id:"IyJo7F"},major_outage:{id:"n8LtxM"},maintenance:{id:"6Dd2PM"}},tone={operational:"",degraded:" warn",partial_outage:" bad",major_outage:" bad",maintenance:" maint"};function appTitle(kind){return kind==="feedback"?{id:"YirHq7"}:kind==="status"?{id:"uAQUqI"}:kind==="help"?{id:"CRzGla"}:kind==="roadmap"?{id:"_gaSVU"}:kind==="whats-new"?{id:"3ePd3I"}:{id:"9AhqBi"}}function section(label){let section=el("section","sec");return section.append(el("h2","label",label)),section}function buildHome(data){let{inbox,t,locale}=data,page=el("div","page home"),hero=el("section","sec hero"),members=inbox.mode==="live"&&inbox.open_now&&inbox.presence?.available?inbox.presence.members:[];if(members.length>0){let avatars=el("div","avatars");for(let member of members.slice(0,3)){let avatar=el("span","avatar",member.initials||"•");avatar.title=member.name,avatars.append(avatar)}hero.append(avatars)}if(hero.append(el("h1","",t({id:"4-3tRX"}))),inbox.help)hero.append(searchField(t({id:"x7I72g"}),"",(query)=>data.openApp("help",{query})));page.append(data.notice,hero);let latest=data.conversations[0],talk=section(`01 — ${latest?t({id:"xGVfLh"}):t({id:"JAKtcG"})}`);if(latest){let item=el("button",latest.unread?"item unread":"item");item.type="button";let at=new Date(latest.last_message_at??latest.created_at),main=el("div","item-main"),top=el("div","item-top");top.append(el("span","item-subject",latest.subject||inbox.name||t({id:"YyNOE7"}))),top.append(el("span","item-time",new Intl.DateTimeFormat(locale,at.toDateString()===new Date().toDateString()?{timeStyle:"short"}:{month:"short",day:"numeric"}).format(at)));let preview=latest.last_message?`${latest.last_message.author_type==="contact"?`${t({id:"ydzYKJ"})} `:""}${latest.last_message.text||t({id:"UY1vmE"})}`:"",line=el("span","item-preview",preview.replace(/\*\*|`/g,""));line.dir="auto",main.append(top,line);let mark=el("span","avatar lg",(inbox.name||"").slice(0,2));if(item.append(mark,main),latest.unread)item.append(el("span","unread-dot"));if(item.addEventListener("click",()=>data.openConversation(latest.id)),talk.append(item),data.conversations.length>1)talk.append(textButton(t({id:"S63MQu"}),"link brand",()=>data.allConversations()))}let send=el("button","primary");send.type="button",send.append(t({id:"2mtG59"})),send.insertAdjacentHTML("beforeend",icons.arrow),send.addEventListener("click",()=>data.newConversation()),talk.append(send),page.append(talk);let tiles=[];if(inbox.help)tiles.push({app:"help",icon:icons.book,title:t({id:"CRzGla"}),text:t({id:"kR9y-C"})});if(inbox.feedback_categories.length>0)tiles.push({app:"feedback",icon:icons.bubble,title:t({id:"YirHq7"}),text:t({id:"lIb9Ab"})});if(inbox.roadmap)tiles.push({app:"roadmap",icon:icons.vote,title:t({id:"_gaSVU"}),text:t({id:"-pBGNS"})});if(inbox.whats_new)tiles.push({app:"whats-new",icon:icons.sparkle,title:t({id:"3ePd3I"}),text:t({id:"R_tuBV"}),count:data.updates});if(data.mailingLists)tiles.push({app:"subscribe",icon:icons.bell,title:t({id:"9AhqBi"}),text:t({id:"3qR_b9"})});let status=inbox.status;if(tiles.length>0||status){let more=section(`02 — ${t({id:"-knPu9"})}`);if(tiles.length>0){let grid=el("div","tiles");for(let tile of tiles){let button=el("button","tile");if(button.type="button",tile.count){let top=el("span","tile-top");top.insertAdjacentHTML("beforeend",tile.icon);let count=tile.count,badge=el("span","tile-count",count>9?"9+":String(count));badge.setAttribute("aria-label",t({id:"yYSSmz",values:{count}})),top.append(badge),button.append(top)}else button.insertAdjacentHTML("beforeend",tile.icon);button.append(el("b","",tile.title),el("span","",tile.text)),button.addEventListener("click",()=>data.openApp(tile.app)),grid.append(button)}more.append(grid)}if(status){let row=el("button","statusrow");row.type="button",row.append(el("span",`tone${tone[status.state]}`),el("span","grow",t(stateText[status.state])),el("span","label",t({id:"uAQUqI"}))),row.insertAdjacentHTML("beforeend",icons.chevron),row.addEventListener("click",()=>data.openApp("status")),more.append(row)}page.append(more)}page.append(el("div","fill"));let foot=el("section","sec foot",t({id:"1CVCSY",values:{brand:"Yuva"}}));return page.append(foot),page}var cross=(side)=>`.sec::${side}{content:"";position:absolute;top:-7px;inset-inline-${side==="before"?"start":"end"}:14px;inline-size:13px;block-size:13px;z-index:3;pointer-events:none;background:linear-gradient(var(--yuva-strong),var(--yuva-strong)) center/1px 100% no-repeat,linear-gradient(var(--yuva-strong),var(--yuva-strong)) center/100% 1px no-repeat}`,styles=`
2
+ [hidden] { display: none !important; }
3
+ *, *::before, *::after { box-sizing: border-box; }
4
+ .panel::before, .panel::after {
5
+ content: "";
6
+ position: absolute;
7
+ inset-block: 0;
8
+ inline-size: 1px;
9
+ background: var(--yuva-border);
10
+ pointer-events: none;
11
+ z-index: 1;
12
+ }
13
+ .panel::before { inset-inline-start: 20px; }
14
+ .panel::after { inset-inline-end: 20px; }
15
+ ${cross("before")}
16
+ ${cross("after")}
17
+ button, input, textarea { font: inherit; color: inherit; }
18
+ button:focus-visible, a:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible { outline: 2px solid var(--yuva-brand); outline-offset: 2px; }
19
+ .flip { display: block; }
20
+ [dir="rtl"] .flip { transform: scaleX(-1); }
21
+ .mono { font-family: var(--yuva-mono); }
22
+ .label { margin: 0; font-family: var(--yuva-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--yuva-faint); }
23
+ .sec { position: relative; flex: none; padding: 18px 32px 20px; border-block-start: 1px solid var(--yuva-border); display: flex; flex-direction: column; gap: 12px; }
24
+ .header {
25
+ position: relative;
26
+ z-index: 2;
27
+ flex: none;
28
+ display: flex;
29
+ align-items: center;
30
+ gap: 6px;
31
+ min-block-size: 64px;
32
+ padding-block: 0;
33
+ padding-inline: 20px 32px;
34
+ background: var(--yuva-bg);
35
+ }
36
+ .header.home { z-index: auto; min-block-size: 56px; padding-inline: 32px 20px; background: transparent; }
37
+ .headbrand { display: flex; align-items: center; gap: 10px; flex: 1; min-inline-size: 0; }
38
+ .mark { display: grid; place-items: center; flex: none; inline-size: 26px; block-size: 26px; border-radius: 7px; background: var(--yuva-fg); color: var(--yuva-bg); font-size: 13px; font-weight: 600; overflow: hidden; }
39
+ .mark img { inline-size: 100%; block-size: 100%; object-fit: cover; }
40
+ .heading { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; margin-inline-start: 6px; }
41
+ .title { margin: 0; font-size: 15px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
42
+ .status { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--yuva-muted); }
43
+ .who { position: relative; flex: none; }
44
+ .who .dot { position: absolute; inset-inline-end: -1px; inset-block-end: -1px; inline-size: 10px; block-size: 10px; border: 2px solid var(--yuva-bg); border-radius: 50%; background: var(--yuva-ok); }
45
+ .who .dot.away { background: var(--yuva-faint); }
46
+ .avatar {
47
+ display: grid;
48
+ place-items: center;
49
+ flex: none;
50
+ inline-size: 28px;
51
+ block-size: 28px;
52
+ border-radius: 50%;
53
+ background: var(--yuva-wash);
54
+ color: var(--yuva-brand);
55
+ font-size: 11px;
56
+ font-weight: 600;
57
+ text-transform: uppercase;
58
+ overflow: hidden;
59
+ }
60
+ .avatar.lg { inline-size: 32px; block-size: 32px; font-size: 12px; }
61
+ .avatar img { inline-size: 100%; block-size: 100%; object-fit: cover; }
62
+ .avatars { display: flex; }
63
+ .avatars .avatar { inline-size: 30px; block-size: 30px; margin-inline-start: -8px; border: 2px solid var(--yuva-bg); }
64
+ .avatars .avatar:first-child { margin-inline-start: 0; }
65
+ .avatars .avatar:nth-child(2) { background: var(--yuva-deep); color: var(--yuva-muted); }
66
+ .avatars .avatar:nth-child(3) { background: var(--yuva-fg); color: var(--yuva-bg); }
67
+ .icon {
68
+ display: grid;
69
+ place-items: center;
70
+ flex: none;
71
+ inline-size: 44px;
72
+ block-size: 44px;
73
+ padding: 0;
74
+ border: 0;
75
+ border-radius: 10px;
76
+ background: transparent;
77
+ color: var(--yuva-muted);
78
+ cursor: pointer;
79
+ }
80
+ .icon:hover { color: var(--yuva-fg); }
81
+ .icon.sm { inline-size: 24px; block-size: 24px; border-radius: 6px; }
82
+ .icon.tool { inline-size: 36px; block-size: 36px; border-radius: 8px; }
83
+ .icon.tool:hover { background: var(--yuva-deep); }
84
+ .body { position: relative; flex: 1; min-block-size: 0; display: flex; flex-direction: column; border-block-start: 1px solid var(--yuva-border); }
85
+ .header.home + .body, .header.home + .banner + .body { border-block-start: 0; }
86
+ .scroll { flex: 1; min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; padding: 20px 32px 16px; display: flex; flex-direction: column; gap: 14px; -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22px); mask-image: linear-gradient(to bottom, transparent 0, #000 22px); }
87
+ .scroll > :first-child { margin-block-start: auto; }
88
+ .page { flex: 1; min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; }
89
+ .page > .fill { flex: 1; }
90
+ .center { flex: 1; display: grid; place-content: center; gap: 6px; padding: 24px 32px; text-align: center; }
91
+ .empty { margin: 0; font-weight: 600; }
92
+ .search { display: flex; align-items: center; gap: 10px; min-block-size: 44px; padding: 0 14px; border: 1px solid var(--yuva-strong); border-radius: 10px; background: var(--yuva-deep); color: var(--yuva-faint); }
93
+ .search:focus-within { border-color: var(--yuva-brand); }
94
+ .search svg { flex: none; }
95
+ .search input { flex: 1; min-inline-size: 0; border: 0; outline: 0; background: transparent; font: inherit; color: var(--yuva-fg); }
96
+ .article-card { display: flex; align-items: center; gap: 10px; max-inline-size: 88%; padding: 10px 12px; border: 1px solid var(--yuva-border); border-radius: 12px; background: var(--yuva-bg); color: var(--yuva-fg); text-decoration: none; }
97
+ .article-card:hover { background: var(--yuva-deep); }
98
+ .article-card > svg:first-child { flex: none; color: var(--yuva-brand); }
99
+ .article-card > svg:last-child { flex: none; color: var(--yuva-faint); }
100
+ .article-card-text { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }
101
+ .article-card-text b { font-weight: 500; }
102
+ .article-card-text span { font-size: 12px; color: var(--yuva-muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
103
+ .hint { margin: 0; color: var(--yuva-muted); font-size: 14px; }
104
+ .hint.resolved { text-align: center; }
105
+ .hero { padding-block: 28px 24px; gap: 14px; }
106
+ .hero h1 { margin: 0; font-size: 28px; line-height: 1.15; font-weight: 600; letter-spacing: -0.02em; }
107
+ .primary {
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ gap: 8px;
112
+ min-block-size: 44px;
113
+ padding: 0 16px;
114
+ border: 0;
115
+ border-radius: 10px;
116
+ background: var(--yuva-accent);
117
+ color: var(--yuva-on-accent);
118
+ font-weight: 500;
119
+ cursor: pointer;
120
+ }
121
+ .primary:disabled { opacity: 0.5; cursor: default; }
122
+ .center .primary { margin-block-start: 8px; }
123
+ .quiet { min-block-size: 44px; padding: 0 16px; border: 1px solid var(--yuva-strong); border-radius: 10px; background: transparent; cursor: pointer; }
124
+ .item {
125
+ display: flex;
126
+ gap: 12px;
127
+ align-items: flex-start;
128
+ inline-size: calc(100% + 24px);
129
+ margin-inline: -12px;
130
+ padding: 12px;
131
+ border: 0;
132
+ border-radius: 10px;
133
+ background: transparent;
134
+ text-align: start;
135
+ cursor: pointer;
136
+ }
137
+ .item:hover { background: var(--yuva-deep); }
138
+ .item-main { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }
139
+ .item-top { display: flex; gap: 8px; justify-content: space-between; }
140
+ .item-subject, .item-preview { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
141
+ .item-subject { font-weight: 500; }
142
+ .item-preview { color: var(--yuva-muted); }
143
+ .item.unread .item-preview { color: var(--yuva-fg); font-weight: 600; }
144
+ .item-state { flex: none; color: var(--yuva-faint); font-size: 12px; }
145
+ .item-time { flex: none; font-family: var(--yuva-mono); font-size: 11px; color: var(--yuva-faint); }
146
+ .unread-dot { flex: none; inline-size: 8px; block-size: 8px; margin-block-start: 6px; border-radius: 50%; background: var(--yuva-brand); }
147
+ .list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
148
+ .list .item { inline-size: 100%; margin-inline: 0; border-radius: 0; border-block-end: 1px solid var(--yuva-border); }
149
+ .link { padding: 0; border: 0; background: none; color: inherit; text-decoration: underline; cursor: pointer; }
150
+ .link.soft { color: var(--yuva-muted); text-decoration: none; min-block-size: 28px; }
151
+ .link.soft:hover { color: var(--yuva-fg); }
152
+ .link.brand { color: var(--yuva-brand); font-weight: 500; text-decoration: none; min-block-size: 28px; }
153
+ .tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border: 1px solid var(--yuva-border); border-radius: 12px; overflow: hidden; }
154
+ .tile { display: flex; flex-direction: column; gap: 8px; min-block-size: 44px; padding: 14px; border: 0; background: transparent; text-align: start; cursor: pointer; color: inherit; }
155
+ .tile:hover { background: var(--yuva-deep); }
156
+ .tile + .tile { border-inline-start: 1px solid var(--yuva-border); }
157
+ .tile:only-child { grid-column: 1 / -1; }
158
+ .tile svg { color: var(--yuva-brand); }
159
+ .tile .tile-top { display: flex; align-items: center; justify-content: space-between; font-size: inherit; color: inherit; }
160
+ .tile .tile-count { min-inline-size: 20px; padding: 1px 6px; border-radius: 10px; background: var(--yuva-brand); color: var(--yuva-on-accent); font-family: var(--yuva-mono); font-size: 11px; font-weight: 500; text-align: center; }
161
+ .tile b { font-weight: 500; }
162
+ .tile span { font-size: 12px; color: var(--yuva-muted); }
163
+ .statusrow { display: flex; align-items: center; gap: 10px; inline-size: 100%; min-block-size: 44px; padding: 0 14px; border: 1px solid var(--yuva-border); border-radius: 12px; background: transparent; text-align: start; cursor: pointer; }
164
+ .statusrow:hover { background: var(--yuva-deep); }
165
+ .statusrow .grow { flex: 1; }
166
+ .statusrow svg { color: var(--yuva-faint); }
167
+ .tone { flex: none; inline-size: 8px; block-size: 8px; border-radius: 50%; background: var(--yuva-ok); }
168
+ .tone.warn { background: var(--yuva-warn); }
169
+ .tone.bad { background: var(--yuva-danger); }
170
+ .tone.maint { background: var(--yuva-info); }
171
+ .foot { min-block-size: 40px; padding: 0; display: flex; align-items: center; justify-content: center; font-family: var(--yuva-mono); font-size: 11px; color: var(--yuva-faint); }
172
+ .page .sec.foot { padding: 0 32px; }
173
+ .day { display: flex; align-items: center; gap: 10px; font-family: var(--yuva-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--yuva-faint); }
174
+ .day::before, .day::after { content: ""; flex: 1; block-size: 1px; background: var(--yuva-border); }
175
+ .sys { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--yuva-muted); }
176
+ .group { display: flex; flex-direction: column; gap: 4px; }
177
+ .group.mine { align-items: flex-end; }
178
+ .row { display: flex; gap: 8px; align-items: flex-end; max-inline-size: 100%; }
179
+ .row.mine { justify-content: flex-end; }
180
+ .stack { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
181
+ .author { padding-inline-start: 12px; font-size: 12px; font-weight: 500; color: var(--yuva-muted); }
182
+ .bubble { max-inline-size: 88%; padding: 8px 12px; border-radius: 12px; overflow-wrap: anywhere; white-space: normal; }
183
+ .mine .bubble { background: var(--yuva-accent); color: var(--yuva-on-accent); max-inline-size: 80%; }
184
+ .theirs .bubble { border: 1px solid var(--yuva-border); background: var(--yuva-deep); }
185
+ .bubble a { color: inherit; text-decoration: underline; }
186
+ .bubble code { font-family: var(--yuva-mono); font-size: 13px; padding: 1px 4px; border-radius: 4px; background: rgb(127 127 127 / 0.2); }
187
+ .bubble pre { margin: 4px 0; padding: 8px; border-radius: 8px; background: rgb(127 127 127 / 0.2); font-family: var(--yuva-mono); font-size: 13px; white-space: pre-wrap; }
188
+ .bubble.greeting { align-self: flex-start; border: 1px solid var(--yuva-border); background: var(--yuva-deep); color: var(--yuva-fg); }
189
+ .bubble .files { margin-block-start: 6px; }
190
+ .bubble:has(.files):not(:has(> :not(.files))) { padding: 0; border: 0; background: transparent; }
191
+ .files { display: flex; flex-direction: column; gap: 4px; align-items: flex-end; }
192
+ .theirs .files { align-items: flex-start; }
193
+ .att { display: flex; align-items: center; gap: 10px; inline-size: 220px; max-inline-size: 100%; padding: 8px; border: 1px solid var(--yuva-strong); border-radius: 12px; background: var(--yuva-bg); color: var(--yuva-fg); font: inherit; text-align: start; cursor: pointer; }
194
+ .att:hover { background: var(--yuva-deep); }
195
+ .att .thumb { display: grid; place-items: center; flex: none; inline-size: 40px; block-size: 40px; border: 1px solid var(--yuva-border); border-radius: 8px; background: var(--yuva-deep); color: var(--yuva-muted); overflow: hidden; }
196
+ .att .thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
197
+ .att .info { flex: 1; min-inline-size: 0; line-height: 1.2; }
198
+ .att .name, .att .sub { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
199
+ .att .name { font-size: 13px; font-weight: 500; }
200
+ .att .sub { margin-block-start: 2px; font-size: 12px; color: var(--yuva-faint); }
201
+ .att.busy { cursor: default; }
202
+ .att.busy .thumb { animation: pulse 1.2s infinite; }
203
+ .att.bad { border-color: var(--yuva-danger); }
204
+ .att.bad .sub { color: var(--yuva-danger); }
205
+ .preview { display: block; max-inline-size: 100%; max-block-size: 220px; border-radius: 12px; border: 1px solid var(--yuva-border); cursor: zoom-in; }
206
+ .meta { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--yuva-faint); }
207
+ .meta.failed { color: var(--yuva-danger); }
208
+ .meta.seen svg { color: var(--yuva-brand); }
209
+ .theirs-meta { padding-inline-start: 36px; }
210
+ .typing { display: flex; gap: 8px; align-items: flex-end; }
211
+ .typing .dots { display: flex; gap: 4px; padding: 12px 14px; border: 1px solid var(--yuva-border); border-radius: 12px; background: var(--yuva-deep); }
212
+ .typing i { inline-size: 6px; block-size: 6px; border-radius: 50%; background: var(--yuva-muted); animation: blink 1.2s infinite both; }
213
+ .typing i:nth-child(2) { animation-delay: 0.15s; }
214
+ .typing i:nth-child(3) { animation-delay: 0.3s; }
215
+ @keyframes blink { 0%, 80%, 100% { opacity: 0.25; } 40% { opacity: 1; } }
216
+ @keyframes pulse { 50% { opacity: 0.5; } }
217
+ @media (prefers-reduced-motion: reduce) { .typing i, .att.busy .thumb { animation: none; } }
218
+ .card { padding: 12px; border: 1px solid var(--yuva-border); border-radius: 12px; font-size: 14px; }
219
+ .card p { margin: 0 0 8px; }
220
+ .mail { display: flex; gap: 12px; align-items: flex-start; padding: 12px; border: 1px dashed var(--yuva-strong); border-radius: 12px; font-size: 13px; }
221
+ .mail > svg { flex: none; margin-block-start: 1px; color: var(--yuva-brand); }
222
+ .mail .text { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }
223
+ .mail .text > b { font-size: 14px; font-weight: 500; }
224
+ .mail .soft { color: var(--yuva-muted); overflow-wrap: anywhere; }
225
+ .mail .soft b { color: var(--yuva-fg); font-weight: 500; }
226
+ .mail .acts { display: flex; gap: 16px; margin-block-start: 2px; }
227
+ .mail.bad { flex-direction: column; gap: 8px; border: 1px solid var(--yuva-brand); background: var(--yuva-wash); }
228
+ .mail.bad .head { display: flex; gap: 8px; align-items: center; font-size: 14px; font-weight: 500; }
229
+ .mail.bad .head svg { color: var(--yuva-brand); }
230
+ .mail.ok { border: 0; padding: 0; align-items: center; gap: 8px; color: var(--yuva-muted); }
231
+ .mail.ok > svg { color: var(--yuva-ok); margin: 0; }
232
+ .inline-form { display: flex; gap: 8px; margin: 0; }
233
+ .inline-form input { flex: 1; min-inline-size: 0; }
234
+ .field { min-block-size: 40px; padding: 0 12px; border: 1px solid var(--yuva-strong); border-radius: 8px; background: var(--yuva-bg); color: var(--yuva-fg); }
235
+ textarea.field { padding: 10px 12px; min-block-size: 96px; resize: vertical; inline-size: 100%; }
236
+ .btn { min-block-size: 40px; padding: 0 14px; border: 0; border-radius: 8px; background: var(--yuva-accent); color: var(--yuva-on-accent); font-weight: 500; cursor: pointer; }
237
+ .btn:disabled { opacity: 0.5; cursor: default; }
238
+ .error { margin: 0; font-size: 13px; color: var(--yuva-danger); }
239
+ .rate { text-align: center; }
240
+ .choices { display: flex; justify-content: center; gap: 10px; }
241
+ .card .choice { inline-size: 44px; block-size: 44px; padding: 0; border: 1px solid var(--yuva-border); border-radius: 50%; background: var(--yuva-bg); font-size: 20px; line-height: 1; cursor: pointer; }
242
+ .card .choice:hover:not(:disabled), .card .choice[aria-pressed="true"] { border-color: var(--yuva-accent); box-shadow: 0 0 0 1px var(--yuva-accent); }
243
+ .card .choice:disabled { opacity: 1; cursor: default; }
244
+ .rate .choices + p { margin: 8px 0 0; }
245
+ .rate form { display: flex; flex-direction: column; gap: 8px; margin-block-start: 10px; }
246
+ .rate textarea { inline-size: 100%; padding: 8px 10px; border: 1px solid var(--yuva-strong); border-radius: 8px; background: var(--yuva-bg); resize: vertical; }
247
+ .rate .actions { display: flex; justify-content: flex-end; align-items: center; gap: 14px; }
248
+ .rate .actions .link { color: var(--yuva-muted); text-decoration: none; }
249
+ .rate .actions button:not(.link) { min-block-size: 40px; padding: 0 14px; border: 0; border-radius: 8px; background: var(--yuva-accent); color: var(--yuva-on-accent); font-weight: 500; cursor: pointer; }
250
+ .composer { padding-block: 12px 14px; gap: 0; background: var(--yuva-bg); }
251
+ .box { border: 1px solid var(--yuva-strong); border-radius: 14px; background: var(--yuva-bg); display: flex; flex-direction: column; }
252
+ .box:focus-within { border-color: var(--yuva-brand); }
253
+ .chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 8px 0; }
254
+ .chip { display: flex; align-items: center; gap: 8px; max-inline-size: 100%; padding: 6px 6px 6px 8px; border: 1px solid var(--yuva-border); border-radius: 10px; background: var(--yuva-deep); color: var(--yuva-muted); }
255
+ .chip .two { display: flex; flex-direction: column; min-inline-size: 0; line-height: 1.2; }
256
+ .chip .two b { font-size: 12px; font-weight: 500; color: var(--yuva-fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: 150px; }
257
+ .chip .two span { font-size: 11px; color: var(--yuva-faint); }
258
+ .box textarea { display: block; inline-size: 100%; block-size: 44px; max-block-size: 140px; padding: 10px 12px 4px; border: 0; background: transparent; resize: none; outline: none; }
259
+ .tools { display: flex; align-items: center; gap: 2px; padding: 4px 6px 6px; }
260
+ .tools .grow { flex: 1; }
261
+ .hintkey { display: flex; align-items: center; gap: 4px; margin-inline-end: 6px; font-size: 11px; color: var(--yuva-faint); }
262
+ .hintkey kbd { font-family: var(--yuva-mono); padding: 1px 5px; border: 1px solid var(--yuva-strong); border-radius: 4px; background: var(--yuva-deep); }
263
+ .send { inline-size: 36px; block-size: 36px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 9px; background: var(--yuva-accent); color: var(--yuva-on-accent); cursor: pointer; }
264
+ .send:disabled { opacity: 0.4; cursor: default; }
265
+ .jump { position: absolute; inset-inline-start: 50%; inset-block-start: -48px; transform: translateX(-50%); z-index: 4; display: flex; align-items: center; gap: 6px; min-block-size: 32px; padding: 0 12px; border: 1px solid var(--yuva-strong); border-radius: 999px; background: var(--yuva-bg); color: var(--yuva-fg); font-size: 12px; font-weight: 500; box-shadow: 0 6px 16px -8px rgb(0 0 0 / 0.25); cursor: pointer; white-space: nowrap; }
266
+ [dir="rtl"] .jump { transform: translateX(50%); }
267
+ .banner { padding: 6px 12px; background: var(--yuva-deep); color: var(--yuva-muted); font-size: 13px; text-align: center; border-block-start: 1px solid var(--yuva-border); }
268
+ @media (max-width: 480px) {
269
+ .box textarea, .field, textarea.field, .inline-form input, .rate textarea { font-size: 16px; }
270
+ .hintkey { display: none; }
271
+ }
272
+ @media (hover: none) and (pointer: coarse) { .hintkey { display: none; } }
273
+ .notice { position: relative; z-index: 2; flex: none; display: flex; align-items: center; gap: 6px; margin: 8px 32px; padding-block: 6px; padding-inline: 10px 4px; border-inline-start: 3px solid var(--yuva-faint); border-radius: 8px; background: var(--yuva-deep); font-size: 13px; }
274
+ .sec > .notice { margin: 0; }
275
+ .notice-text { flex: 1; min-inline-size: 0; overflow-wrap: anywhere; }
276
+ .notice a { color: inherit; text-decoration: underline; }
277
+ .notice .icon { color: var(--yuva-muted); }
278
+ .notice.impact-minor { border-inline-start-color: var(--yuva-warn); }
279
+ .notice.impact-major { border-inline-start-color: #ea580c; }
280
+ .notice.impact-critical { border-inline-start-color: var(--yuva-danger); }
281
+ .sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
282
+ `;var loadMessages=(locale)=>typeof YUVA_PANEL_LOCALES==="string"?import(new URL(localeFile(YUVA_PANEL_LOCALES,locale),import.meta.url).href).then((module)=>module.messages).catch(()=>messages2):import("./panel-jfe47dat.js").then((module)=>module.catalogs[locale]??messages2),localeFile=(map,locale)=>JSON.parse(map)[locale]??"about:blank",loadApps=()=>typeof YUVA_CHAT_APPS==="string"?import(new URL(YUVA_CHAT_APPS,import.meta.url).href):import("./apps-ghkaqqx8.js"),impactRank={none:0,minor:1,major:2,critical:3},maxFiles=10,groupGap=300000,inboxRefreshGap=60000,maxTimer=2147483647;class Chat{#host;#i18n;#client;#inbox=null;#updates=0;#updatesKey="";#inboxAt=0;#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="";#emailNote="";#emailEditing=!1;#emailBusy=!1;#emailKey="";#emailTimer=null;#connectedBefore=!1;#ratings=new Map;#rateCard=el("div","card rate");#rateComment=el("textarea");#rateKey="";#rateFor=null;#lists=!1;#listsLoaded=!1;#app=null;#appLoad=0;#appError=!1;#helpArticle=null;#missed=0;#loaded="";ready;#header=el("header","header");#banner=el("div","banner");#body=el("div","body");#scroll=el("div","scroll");#notice=el("div","notice");#email=el("div","");#emailInput=el("input","field");#composer=el("div","sec composer");#chips=el("div","chips");#textarea=el("textarea");#fileInput=el("input");#sendButton;#attachButton;#shotButton;#jump=el("button","jump");#hint=el("span","hintkey");#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();else if(!this.#beginning)this.#client.connect().catch(()=>{return})}),this.ready=this.#setLocale(),this.#live.setAttribute("aria-live","polite"),this.#scroll.setAttribute("role","log"),this.#scroll.addEventListener("scroll",()=>{if(this.#atEnd=this.#scroll.scrollHeight-this.#scroll.scrollTop-this.#scroll.clientHeight<48,this.#atEnd)this.#missed=0;if(this.#syncJump(),this.#scroll.scrollTop<60&&this.#view?.kind==="thread"&&this.#view.id)this.#loadMessages(this.#view.id,!0)}),this.#jump.type="button",this.#jump.addEventListener("click",()=>{this.#missed=0,this.#scrollToEnd(),this.#syncJump()}),this.#textarea.rows=2,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(),"icon tool"),this.#shotButton=iconButton(icons.shot,"",()=>void this.#capture(),"icon tool"),this.#shotButton.hidden=!canCapture(),this.#sendButton=iconButton(icons.send,"",()=>void this.#send(),"send");let tools=el("div","tools");tools.append(this.#attachButton,this.#shotButton,el("span","grow"),this.#hint,this.#sendButton,this.#fileInput);let box=el("form","box");box.addEventListener("submit",(event)=>{event.preventDefault(),this.#send()}),box.append(this.#chips,this.#textarea,tools),this.#composer.append(this.#jump,box),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.ready.then(()=>{this.#renderAll(),this.#start()})}update(){this.#setLocale().then(()=>{this.#emailKey="",this.#rateKey="",this.#renderAll()})}opened(){if(this.#phase==="error"){this.#starting=null,this.#start();return}if(this.#phase==="ready"){if(this.#client.token)this.#refreshSession();else if(this.#inboxIsStale())this.#preview().then(()=>this.#render()).catch(()=>{return});this.#loadLists()}if(this.#render(),this.#scrollToEnd(),this.#markRead(),this.#host.config().layout==="launcher"&&this.#view?.kind==="thread")this.#textarea.focus({preventScroll:!0})}async openApp(kind,params={}){if(await this.ready,await this.#start(),this.#phase==="ready")await this.#openApp(kind,params)}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(){if(this.#client.reset(),this.#stopTyping(),this.#closeApp(),this.#emailTimer)clearTimeout(this.#emailTimer);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.#closeApp(),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.#lists=!1,this.#listsLoaded=!1,this.#emailSaved=!1,this.#emailEditing=!1,this.#emailKey="",this.#connectedBefore=!1,this.#missed=0,this.#host.setUnread(0),this.#updates=0,this.#updatesKey="",this.#inboxAt=0,this.#host.setUpdates(0)}#onVisible=()=>{if(document.visibilityState!=="visible")return;if(this.#client.reconnect(),this.#markRead(),this.#client.connected||this.#inboxIsStale())this.#refreshInbox()};#inboxIsStale(){return!this.#client.connected&&Date.now()-this.#inboxAt>=inboxRefreshGap}async#setLocale(){let{locale}=this.#host.config();if(this.#i18n??=setupI18n({locale:"en",messages:{en:messages2}}),this.#loaded===locale)return;let messages=await loadMessages(locale);if(locale!==this.#host.config().locale)return;this.#i18n=setupI18n({locale,messages:{[locale]:messages}}),this.#loaded=locale}#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");this.#phase="ready",this.#view??={kind:"home"},this.#loadLists(),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}#loadLists(){if(this.#listsLoaded||!this.#host.config().channel)return;this.#listsLoaded=!0,this.#client.lists().then((result)=>{this.#lists=(result?.lists.length??0)>0,this.#render()}).catch(()=>{return})}async#preview(){let inbox=await this.#fetchInbox();if(!this.#client.token)this.#setInbox(inbox)}async#fetchInbox(){if(!this.#host.config().channel)throw new ApiError2(0,"not_configured");let inbox=await this.#client.channelSettings();return this.#inboxAt=Date.now(),inbox}#setInbox(inbox){let{channel}=this.#host.config();this.#inbox=inbox;let launcher=launcherOf(inbox);if(this.#host.setLauncher(launcher),!channel)return;let stored=readStored(channel),open=new Set(inbox.status?.open.map((incident)=>incident.id)),kept=Object.fromEntries(Object.entries(stored.dismissed_status??{}).filter(([id])=>open.has(id))),next={...stored,launcher};if(Object.keys(kept).length>0)next.dismissed_status=kept;else delete next.dismissed_status;writeStored(channel,next),this.#syncUpdates()}#syncUpdates(){let{channel,server,locale}=this.#host.config(),inbox=this.#inbox;if(!channel||!inbox?.whats_new)return this.#setUpdates(0);let key=`${inbox.whats_new.latest_published_at}|${readStored(channel).whats_new_seen??""}`;if(key===this.#updatesKey)return;this.#updatesKey=key,countUpdates(server,channel,inbox,locale).then((count)=>{if(key===this.#updatesKey)this.#setUpdates(count)}).catch(()=>{if(key===this.#updatesKey)this.#updatesKey=""})}#setUpdates(count){if(count===this.#updates)return;if(this.#updates=count,this.#host.setUpdates(this.#inbox?.chat.announce_updates?count:0),this.#view?.kind==="home")this.#render()}#renderNotice(){let{channel}=this.#host.config(),dismissed=channel&&readStored(channel).dismissed_status||{},shown=[...this.#inbox?.status?.open??[]].filter((incident)=>dismissed[incident.id]!==incident.updated_at).sort((a,b)=>impactRank[b.impact]-impactRank[a.impact])[0];if(this.#notice.hidden=!shown,!shown)return this.#notice.replaceChildren();let states={investigating:{id:"WAnUgI"},identified:{id:"tddaHo"},monitoring:{id:"1gZQhL"},resolved:{id:"O6H89R"},scheduled:{id:"4ba0NE"},in_progress:{id:"_LCAwL"},completed:{id:"qqWcBV"}},link=el("a","",shown.title);link.href=shown.url,link.target="_blank",link.rel="noopener noreferrer",link.dir="auto";let text=el("div","notice-text");text.append(el("strong","",this.#t(states[shown.state]))," ",link),this.#notice.className=`notice impact-${shown.impact}`,this.#notice.replaceChildren(text,iconButton(icons.closeSmall,this.#t({id:"1QfxQT"}),()=>{if(!channel)return;let stored=readStored(channel);writeStored(channel,{...stored,dismissed_status:{...stored.dismissed_status,[shown.id]:shown.updated_at}}),this.#render()},"icon sm"))}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"contact.updated":this.#contact=message.data;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:"home"};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);if(this.#typing.delete(id),this.#announce(message),!this.#atEnd&&this.#visibleThread()===id)this.#missed++}}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()}async#capture(){let file=await captureScreen(this.#host.panel);if(file)this.#addFiles([file])}#autosize(){if(this.#textarea.style.blockSize="",this.#textarea.value==="")return;this.#textarea.style.blockSize="auto",this.#textarea.style.blockSize=`${Math.max(44,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:randomId2(),conversation:this.#view.id,body,files,state:"sending"};if(this.#view.id===null&&this.#helpArticle)pending.help_article_id=this.#helpArticle,this.#helpArticle=null;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,help_article_id:pending.help_article_id}),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(address){let email=(address??this.#emailInput.value).trim();if(!email||address===void 0&&!this.#emailInput.checkValidity()){this.#emailError=this.#t({id:"E_qvzP"}),this.#renderEmail();return}if(this.#emailBusy)return;this.#emailBusy=!0;try{this.#contact=await this.#client.setEmail(email),this.#emailSaved=!0,this.#emailEditing=!1,this.#emailError="",this.#emailNote=address===void 0?"":this.#t({id:"mj_YKf"})}catch(error){this.#emailError=error instanceof ApiError2&&error.status===429?this.#t({id:"tzsBOP"}):this.#t({id:"ZxJcgC"})}finally{this.#emailBusy=!1}this.#renderEmail(),this.#render()}#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.#missed=0,this.#scroll.scrollTop=this.#scroll.scrollHeight,requestAnimationFrame(()=>{if(this.#atEnd)this.#scroll.scrollTop=this.#scroll.scrollHeight})}#syncJump(){let show=!this.#atEnd&&this.#view?.kind==="thread";if(this.#jump.hidden=!show,!show)return;this.#jump.setAttribute("aria-label",this.#t({id:"ju1Z9b"}));let count=this.#missed;this.#jump.replaceChildren(),this.#jump.insertAdjacentHTML("beforeend",icons.down),this.#jump.append(count>0?this.#t({id:"RnNe7a",values:{count}}):this.#t({id:"ju1Z9b"}))}#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.#shotButton.setAttribute("aria-label",this.#t({id:"TZglEu"})),this.#shotButton.title=this.#t({id:"TZglEu"}),this.#sendButton.setAttribute("aria-label",this.#t({id:"JlFcis"})),this.#sendButton.title=this.#t({id:"JlFcis"}),this.#hint.replaceChildren(el("kbd","",this.#t({id:"9Vnjc9"})),this.#t({id:"0IRz4M"})),this.#emailInput.placeholder=this.#t({id:"njBr8W"}),this.#emailInput.setAttribute("aria-label",this.#t({id:"XJURKP"})),this.#scroll.setAttribute("aria-label",this.#t({id:"YyNOE7"})),this.#syncSend(),this.#renderChips(),this.#render()}#go(view){if(this.#stopTyping(),view.kind!=="thread"||view.id!==null)this.#helpArticle=null;if(view.kind!=="app")this.#closeApp();if(this.#view=view,this.#render(),view.kind==="thread")this.#scrollToEnd(),this.#textarea.focus({preventScroll:!0})}#closeApp(){this.#appLoad++,this.#appError=!1,this.#app?.handle.destroy(),this.#app=null}async#openApp(kind,params={}){this.#closeApp();let load=this.#appLoad;this.#view={kind:"app",app:kind},this.#render();try{let apps=await loadApps(),inbox=this.#inbox;if(load!==this.#appLoad||!inbox)return;let{locale}=this.#host.config(),handle=await apps.mountApp(kind,{root:this.#host.panel.getRootNode(),client:this.#client,inbox,locale,mailingLists:this.#lists,params,back:()=>this.#go({kind:"home"}),open:(next,nextParams)=>void this.#openApp(next,nextParams),ask:(articleId)=>{this.#go({kind:"thread",id:null}),this.#helpArticle=articleId??null},created:(result)=>{let id=result.conversation.id;if(!this.#conversations.has(id))this.#conversations.set(id,result.conversation);if(!this.#threads.has(id))this.#threads.set(id,{messages:[],complete:!0,loading:!1});this.#upsertMessage(result.message,!1)},viewConversation:(id)=>void this.#openThread(id),seenUpdates:()=>this.#setUpdates(0)});if(load!==this.#appLoad)return handle.destroy();this.#app={kind,handle}}catch{if(load===this.#appLoad)this.#appError=!0}if(load===this.#appLoad)this.#render()}#render(){let panel=this.#host.panel;if(panel.childElementCount===0){let fallback=addStyles(panel.getRootNode(),styles);panel.append(...fallback?[fallback]:[],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=textButton(this.#t({id:"KDw4GX"}),"primary",()=>{this.#starting=null,this.#start()});center.append(retry)}this.#body.replaceChildren(center);return}this.#renderNotice();let view=this.#view??{kind:"home"};if(view.kind==="home")this.#renderHome();else if(view.kind==="list")this.#renderList();else if(view.kind==="app")this.#renderApp();else this.#renderThread();this.#syncJump()}#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"})}}#presenceLine(inbox){if(inbox.mode==="live"&&inbox.open_now&&inbox.presence?.available)return[el("span","",this.#t({id:"oXOSPE"}))];if(!inbox.open_now||inbox.mode==="live")return[el("span","",this.#t({id:"1EICzz"}))];return[el("span","",this.#replyTime(inbox.expected_reply_minutes))]}#renderHeader(){let{layout}=this.#host.config(),inbox=this.#inbox,view=this.#phase==="ready"?this.#view??{kind:"home"}:{kind:"home"},children=[],close=layout==="launcher"?iconButton(icons.close,this.#t({id:"yz7wBu"}),()=>this.#host.close()):null;if(view.kind==="home"){this.#header.className="header home";let brand=el("div","headbrand"),mark=el("span","mark"),logo=inbox?.branding.logo_url;if(logo&&/^https?:/i.test(logo)){let img=el("img");img.alt="",img.referrerPolicy="no-referrer",img.addEventListener("error",()=>mark.replaceChildren((inbox?.name||"Y").slice(0,1))),img.src=logo,mark.append(img)}else mark.textContent=(inbox?.name||"Y").slice(0,1);brand.append(mark,el("h2","title",inbox?.name||this.#t({id:"t7TeQU"}))),children.push(brand)}else if(this.#header.className="header",children.push(iconButton(icons.back,this.#t({id:"iH8pgl"}),()=>this.#go({kind:"home"}))),view.kind==="thread"&&inbox){let who=el("div","who"),live=inbox.mode==="live"&&inbox.open_now&&inbox.presence?.available,first=live?inbox.presence?.members[0]:void 0;who.append(el("span","avatar lg",first?.initials||(inbox.name||"").slice(0,2)),el("span",live?"dot":"dot away")),who.querySelector(".dot")?.setAttribute("aria-hidden","true");let heading=el("div","heading");heading.append(el("h2","title",inbox.name||this.#t({id:"t7TeQU"})));let status=el("div","status");status.append(...this.#presenceLine(inbox)),heading.append(status),children.push(who,heading)}else{let heading=el("div","heading");heading.append(el("h2","title",view.kind==="app"?this.#t(appTitle(view.app)):this.#t({id:"S63MQu"}))),children.push(heading)}if(close)children.push(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"})}#renderHome(){this.#scrollThread=void 0;let inbox=this.#inbox;if(!inbox)return;let home=buildHome({inbox,conversations:this.#sorted(),mailingLists:this.#lists,updates:this.#updates,locale:this.#host.config().locale,t:(descriptor)=>this.#t(descriptor),notice:this.#notice,openConversation:(id)=>void this.#openThread(id),allConversations:()=>this.#go({kind:"list"}),newConversation:()=>this.#go({kind:"thread",id:null}),openApp:(kind,params)=>void this.#openApp(kind,params)});this.#body.replaceChildren(home)}#renderApp(){this.#scrollThread=void 0;let app=this.#app;if(app){if(this.#body.firstChild!==app.handle.element||this.#body.childElementCount!==1)this.#body.replaceChildren(app.handle.element);return}let center=el("div","center");if(this.#appError)center.append(el("p","empty",this.#t({id:"5isRv0"})),textButton(this.#t({id:"KDw4GX"}),"primary",()=>{let view=this.#view;if(view?.kind==="app")this.#openApp(view.app)}));else center.append(el("p","hint",this.#t({id:"Pwqkdw"})));this.#body.replaceChildren(center)}#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");if(top.append(el("span","item-subject",conversation.subject||this.#inbox?.name||this.#t({id:"YyNOE7"}))),conversation.kind==="feedback"&&conversation.status==="closed")top.append(el("span","item-state",this.#t({id:"O6H89R"})));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)}let page=el("div","page");if(page.append(this.#notice,list),this.#conversationCursor){let more=textButton(this.#t({id:"ASr-r0"}),"link soft",()=>void this.#loadConversations(!0).then(()=>this.#render()));more.style.margin="8px auto",page.append(more)}let start=textButton(this.#t({id:"-HY5kX"}),"primary",()=>this.#go({kind:"thread",id:null}));start.style.margin="16px 32px",page.append(el("div","fill"),start),this.#body.replaceChildren(page)}async#openThread(id){if(this.#closeApp(),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||initialsOf(author.name??"")),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,{locale}=this.#host.config(),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),conversation=id?this.#conversations.get(id):void 0,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"})));let entries=[...messages.map((message)=>({kind:"message",message})),...pending.map((item)=>({kind:"pending",pending:item}))],known=new Set,lastDay="",group=null,flush=(last)=>{if(!group)return;let{node,stack,mine,at}=group,meta=this.#groupMeta(entries,last,mine,at,id);if(meta){if(!mine)meta.classList.add("theirs-meta");stack.append(meta)}nodes.push(node),group=null};if(entries.forEach((entry,i)=>{let message=entry.kind==="message"?entry.message:null,created=message?.created_at??"",mine=!message||message.author.type==="contact",key=message?authorKey(message):"contact";if(message&&created&&!sameDay(created,lastDay||"1970-01-01"))flush(!1),nodes.push(el("div","day",dayLabel(locale,created))),lastDay=created;if(message&&!mine&&message.author.type==="member"&&message.author.name){let name=message.author.name;if(!known.has(name)){if(known.add(name),thread?.complete&&i>0){flush(!1);let line=el("div","sys");line.insertAdjacentHTML("beforeend",icons.person),line.append(this.#t({id:"A4P5nB",values:{name}})),nodes.push(line)}}}if(!group||group.key!==key||message&&time(created)-time(group.at)>groupGap||!1){flush(!1);let node=el("div",mine?"group mine":"row theirs"),stack=mine?node:el("div","stack");if(!mine&&message){let avatar=this.#avatar(message.author);if(avatar.style.marginBlockEnd="22px",node.append(avatar,stack),message.author.name)stack.append(el("div","author",message.author.name))}group={mine,key,at:created||new Date().toISOString(),node,stack}}if(!group)return;if(message){if(group.at=created,message.body.trim()){let bubble=el("div","bubble");bubble.dir="auto",bubble.title=new Date(created).toLocaleString(locale),bubble.append(richText(message.body)),group.stack.append(bubble)}if(message.attachments.length>0)group.stack.append(this.#renderAttachments(message.attachments,mine));for(let card of message.cards??[])group.stack.append(this.#renderCard(card))}else if(entry.kind==="pending"){let item=entry.pending;if(item.body){let bubble=el("div","bubble");bubble.dir="auto",bubble.append(richText(item.body)),group.stack.append(bubble)}if(item.files.length>0){let files=el("div","files");for(let file of item.files)files.append(this.#pendingFile(file,item));group.stack.append(files)}}}),flush(!0),conversation?.kind==="feedback"&&conversation.status==="closed")nodes.push(el("p","hint resolved",this.#t({id:"O6H89R"})));else if(conversation?.status==="closed"&&messages.length>0){let line=el("div","sys");line.insertAdjacentHTML("beforeend",icons.check),line.append(this.#t({id:"otDzIg"})),nodes.push(line)}let rate=conversation?this.#renderRating(conversation):null;if(rate)nodes.push(rate);if(this.#renderEmail(),!this.#email.hidden)nodes.push(this.#email);let typing=id?this.#typing.get(id):void 0;if(typing){let line=el("div","typing");line.setAttribute("role","status");let name=typing.name,dots=el("div","dots");dots.append(el("i"),el("i"),el("i")),line.append(this.#avatar({name}),dots,el("span","sr",name?this.#t({id:"tHaDPf",values:{name}}):this.#t({id:"PxYAul"}))),nodes.push(line)}let root=this.#scroll.getRootNode(),focused=root.activeElement===this.#rateComment||root.activeElement===this.#emailInput,active=root.activeElement,{selectionStart,selectionEnd}=this.#rateComment;if(this.#scroll.replaceChildren(...nodes),focused&&active instanceof HTMLElement&&active.isConnected){if(active.focus({preventScroll:!0}),active===this.#rateComment)this.#rateComment.setSelectionRange(selectionStart,selectionEnd)}if(this.#body.firstChild!==this.#scroll)this.#body.replaceChildren(this.#scroll,this.#notice,this.#composer);if(this.#scrollThread=id,!sameThread||atEnd)this.#scrollToEnd()}#groupMeta(entries,last,mine,at,id){let tail=entries[entries.length-1];if(!mine)return el("div","meta",this.#formatTime(at));if(last&&tail?.kind==="pending"){let item=tail.pending;if(item.state==="failed"){let line=el("div","meta failed",`${this.#t({id:"upFvcp"})} `);return line.append(textButton(this.#t({id:"6gRgw8"}),"link",()=>void this.#deliver(item))),line}if(item.state==="refused"){let reason=item.status===413?this.#t({id:"eOu9Px"}):this.#t({id:"JkW3Ph"});return el("div","meta failed",`${this.#t({id:"upFvcp"})} ${reason}`)}return el("div","meta",this.#t({id:"Sad2tK"}))}let meta=el("div","meta",this.#formatTime(at));if(last&&tail?.kind==="message"){let readAt=id?this.#conversations.get(id)?.last_read_by_member_at:void 0,seen=!!readAt&&time(readAt)>=time(tail.message.created_at);if(meta.textContent=`${seen?this.#t({id:"6lGaum"}):this.#t({id:"h69WC6"})} ${this.#formatTime(at)}`,seen)meta.classList.add("seen"),meta.insertAdjacentHTML("beforeend",icons.seen)}return meta}#pendingFile(file,item){let failed=item.state!=="sending",card=el("div",failed?"att bad":"att busy"),thumb=el("span","thumb");thumb.innerHTML=icons.file;let info=el("span","info"),{locale}=this.#host.config();return info.append(el("span","name",file.name||"image"),el("span","sub",failed?this.#t({id:"upFvcp"}):this.#t({id:"gANddk"})+" · "+fileSize(locale,file.size))),card.append(thumb,info),card}#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}#renderCard(card){let link=el("a","article-card");link.href=card.url,link.target="_blank",link.rel="noopener noreferrer",link.dir="auto";let text=el("span","article-card-text");if(text.append(el("b","",card.title)),card.excerpt)text.append(el("span","",card.excerpt));return link.insertAdjacentHTML("beforeend",icons.book),link.append(text),link.insertAdjacentHTML("beforeend",icons.chevron),link.addEventListener("click",(event)=>{if(!this.#inbox?.help||event.metaKey||event.ctrlKey||event.shiftKey)return;event.preventDefault(),this.#openApp("help",{article:card.article_id})}),link}#renderAttachments(attachments,mine){let files=el("div","files"),{locale}=this.#host.config();for(let attachment of attachments)if(isImage(attachment)){let img=el("img","preview");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 card=el("button","att");card.type="button";let thumb=el("span","thumb");thumb.innerHTML=icons.file;let info=el("span","info");info.append(el("span","name",attachment.filename),el("span","sub",[fileKind(attachment.filename,attachment.content_type),fileSize(locale,attachment.size)].filter(Boolean).join(" · "))),card.append(thumb,info),card.addEventListener("click",()=>void this.#download(attachment)),files.append(card)}if(!mine)files.style.alignItems="flex-start";return files}#formatTime(value){return new Intl.DateTimeFormat(this.#host.config().locale,{timeStyle:"short"}).format(new Date(value))}#emailMode(){let contact=this.#contact,view=this.#view;if(view?.kind!=="thread")return null;if(!(view.id!==null||this.#pending.length>0))return null;let confirmation=contact?.email_confirmation,live=confirmation?.state==="sent"&&(!confirmation.expires_at||Date.parse(confirmation.expires_at)>Date.now());if(confirmation?.state==="undeliverable"&&!this.#emailEditing)return"bad";if(live&&!this.#emailEditing)return"sent";if(confirmation?.state==="confirmed"&&!this.#emailEditing)return"confirmed";let verified=!!contact?.email;if(this.#emailEditing||confirmation?.state==="sent"&&!verified)return"ask";if(this.#emailSaved&&(verified||contact?.typed_email))return"saved";if(this.#inbox?.chat.ask_email_offline&&this.#nobodyAvailable()&&!verified)return"ask";return null}#renderEmail(){let mode=this.#emailMode();if(this.#email.hidden=!mode,this.#emailTimer)clearTimeout(this.#emailTimer);if(this.#emailTimer=null,!mode){this.#emailKey="";return}let confirmation=this.#contact?.email_confirmation,address=confirmation?.email??this.#contact?.typed_email??this.#contact?.email??"";if(mode==="sent"&&confirmation?.expires_at){let wait=Math.min(Date.parse(confirmation.expires_at)-Date.now()+100,maxTimer);this.#emailTimer=setTimeout(()=>this.#render(),Math.max(wait,0))}let key=[mode,address,this.#emailError,this.#emailNote,this.#emailBusy,this.#host.config().locale].join("|");if(key===this.#emailKey)return;if(this.#emailKey.split("|")[0]!==mode)this.#emailInput.value=mode==="bad"||mode==="ask"?address:"";this.#emailKey=key;let note=()=>this.#emailNote?[el("span","soft",this.#emailNote)]:[],failure=()=>this.#emailError?[el("p","error",this.#emailError)]:[],form=()=>{let f=el("form","inline-form");f.noValidate=!0,f.addEventListener("submit",(event)=>{event.preventDefault(),this.#saveEmail()});let save=el("button","btn",this.#t({id:"tfDRzk"}));return save.type="submit",save.disabled=this.#emailBusy,f.append(this.#emailInput,save),f},strong=(text)=>el("b","",text);if(mode==="sent"){this.#email.className="mail",this.#email.innerHTML=icons.mail;let text=el("div","text"),soft=el("span","soft"),marker="\x01",sentTo=((address)=>this.#t({id:"gmPmD9",values:{address}}))(marker),[before="",after=""]=sentTo.split(marker);soft.append(before,strong(address),after);let acts=el("div","acts");acts.append(textButton(this.#t({id:"c4RuNX"}),"link brand",()=>{this.#emailEditing=!0,this.#emailError="",this.#emailNote="",this.#render(),this.#emailInput.focus()}),textButton(this.#t({id:"J_jxKQ"}),"link soft",()=>void this.#saveEmail(address))),text.append(el("b","",this.#t({id:"5IXWmO"})),soft,acts,...note(),...failure()),this.#email.append(text)}else if(mode==="bad"){this.#email.className="mail bad";let head=el("div","head");head.insertAdjacentHTML("beforeend",icons.alert),head.append(this.#t({id:"io8YUT",values:{address}})),this.#email.replaceChildren(head,el("span","soft",this.#t({id:"7b0Aa9"})),form(),...failure())}else if(mode==="confirmed")this.#email.className="mail ok",this.#email.innerHTML=icons.check,this.#email.append(this.#t({id:"gxoeD3",values:{address}}));else if(mode==="saved"){this.#email.className="mail ok",this.#email.innerHTML=icons.check;let known=address;this.#email.append(this.#t({id:"iGNUZJ",values:{known}}))}else{this.#email.className="card";let cancel=this.#emailEditing?[textButton(this.#t({id:"dEgA5A"}),"link soft",()=>{this.#emailEditing=!1,this.#emailError="",this.#render()})]:[];this.#email.replaceChildren(el("p","",this.#t({id:"M62PBt"})),form(),...failure(),...cancel)}}#renderChips(){let{locale}=this.#host.config();this.#chips.hidden=this.#files.length===0,this.#chips.replaceChildren(...this.#files.map((file,index)=>{let chip=el("span","chip");chip.insertAdjacentHTML("beforeend",icons.file);let two=el("span","two");return two.append(el("b","",file.name||"image"),el("span","",fileSize(locale,file.size))),chip.append(two,iconButton(icons.closeSmall,this.#t({id:"w61W3L",values:{0:file.name}}),()=>{this.#files=this.#files.filter((_,i)=>i!==index),this.#renderChips(),this.#syncSend()},"icon sm")),chip}))}}function mount(host){return new Chat(host)}export{mount};
@@ -0,0 +1,4 @@
1
+ import type { MessageDescriptor } from "@lingui/core";
2
+ import type { AppContext, AppHandle, AppKind } from "../types.js";
3
+ export type Translate = (descriptor: MessageDescriptor) => string;
4
+ export declare function mountApp(kind: AppKind, context: AppContext): Promise<AppHandle>;
@@ -0,0 +1,3 @@
1
+ import type { AppContext } from "../types.js";
2
+ import type { Translate } from "./apps.js";
3
+ export declare function feedbackApp(context: AppContext, t: Translate, root: HTMLElement): () => void;
@@ -0,0 +1,4 @@
1
+ import type { AppContext } from "../types.js";
2
+ import type { Translate } from "./apps.js";
3
+ export declare function article(html: string): HTMLElement;
4
+ export declare function helpApp(context: AppContext, t: Translate, root: HTMLElement): () => void;
@@ -0,0 +1,3 @@
1
+ import type { AppContext } from "../types.js";
2
+ import type { Translate } from "./apps.js";
3
+ export declare function roadmapApp(context: AppContext, t: Translate, root: HTMLElement): () => void;
@@ -0,0 +1,3 @@
1
+ import type { AppContext } from "../types.js";
2
+ import type { Translate } from "./apps.js";
3
+ export declare function statusApp(context: AppContext, t: Translate, root: HTMLElement): () => void;
@@ -0,0 +1 @@
1
+ export declare const styles = "\n.app { flex: 1; min-block-size: 0; display: flex; flex-direction: column; }\n.app .page { flex: 1; }\n.seg { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; border: 1px solid var(--yuva-strong); border-radius: 10px; overflow: hidden; }\n.seg button { min-block-size: 44px; padding: 0 8px; border: 0; background: transparent; color: var(--yuva-muted); cursor: pointer; }\n.seg button + button { border-inline-start: 1px solid var(--yuva-strong); }\n.seg button[aria-pressed=\"true\"] { background: var(--yuva-fg); color: var(--yuva-bg); }\n.scores { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }\n.scores button { min-block-size: 48px; padding: 0; border: 1px solid var(--yuva-strong); border-radius: 10px; background: transparent; color: var(--yuva-muted); font-family: var(--yuva-mono); font-size: 15px; font-weight: 500; cursor: pointer; }\n.scores button[aria-pressed=\"true\"] { background: var(--yuva-wash); border-color: var(--yuva-brand); color: var(--yuva-brand); }\n.ends { display: flex; justify-content: space-between; font-size: 12px; color: var(--yuva-faint); }\n.attach { display: flex; align-items: center; gap: 4px; }\n.attach .chips { padding: 0; flex: 1; }\n.rowbtns { display: flex; gap: 8px; align-self: stretch; }\n.rowbtns > * { flex: 1; }\n.stat { display: flex; align-items: center; gap: 12px; }\n.stat-mark { display: grid; place-items: center; flex: none; inline-size: 40px; block-size: 40px; border-radius: 50%; background: color-mix(in srgb, var(--yuva-ok) 14%, var(--yuva-bg)); color: var(--yuva-ok); }\n.stat-mark.warn { background: color-mix(in srgb, var(--yuva-warn) 16%, var(--yuva-bg)); color: var(--yuva-warn); }\n.stat-mark.bad { background: color-mix(in srgb, var(--yuva-danger) 14%, var(--yuva-bg)); color: var(--yuva-danger); }\n.stat-mark.maint { background: color-mix(in srgb, var(--yuva-info) 14%, var(--yuva-bg)); color: var(--yuva-info); }\n.stat b { display: block; font-size: 16px; font-weight: 600; }\n.stat span { font-family: var(--yuva-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--yuva-faint); }\n.comp { display: flex; flex-direction: column; gap: 6px; }\n.comp-top { display: flex; justify-content: space-between; gap: 8px; }\n.comp-top span:last-child { font-family: var(--yuva-mono); font-size: 12px; color: var(--yuva-muted); }\n.cells { display: flex; gap: 2px; block-size: 22px; }\n.cells i { flex: 1; min-inline-size: 1px; border-radius: 1px; background: var(--yuva-ok); }\n.cells i.none { background: var(--yuva-border); }\n.cells i.warn { background: var(--yuva-warn); }\n.cells i.bad { background: var(--yuva-danger); }\n.cells i.maint { background: var(--yuva-info); }\n.inc { display: flex; flex-direction: column; gap: 2px; padding-block: 8px; border-block-end: 1px solid var(--yuva-border); }\n.inc:last-of-type { border-block-end: 0; }\n.inc a { color: inherit; font-weight: 500; text-decoration: none; }\n.inc a:hover { text-decoration: underline; }\n.inc span { font-size: 12px; color: var(--yuva-faint); }\n.lists { display: flex; flex-direction: column; gap: 8px; }\n.check { display: flex; gap: 10px; align-items: flex-start; min-block-size: 28px; font-size: 13px; color: var(--yuva-muted); }\n.check input { flex: none; inline-size: 18px; block-size: 18px; margin: 1px 0 0; accent-color: var(--yuva-accent); }\n.check b { display: block; font-weight: 500; color: var(--yuva-fg); }\n.form { display: flex; flex-direction: column; gap: 12px; }\n.form .row2 { display: flex; gap: 8px; }\n.form .row2 .field { flex: 1; min-inline-size: 0; }\n.done-card { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; padding: 8px 0; }\n.done-card svg { inline-size: 28px; block-size: 28px; color: var(--yuva-ok); }\n.done-card .rowbtns { inline-size: 100%; margin-block-start: 8px; }\n.note { margin: 0; font-size: 12px; color: var(--yuva-faint); }\n.hback { flex: none; padding: 6px 28px 0; }\n.hback .link { display: inline-flex; align-items: center; gap: 4px; }\n.hrows { display: flex; flex-direction: column; margin-block-end: -8px; }\n.hrow { display: flex; align-items: center; gap: 12px; min-block-size: 56px; padding: 8px 0; border: 0; border-block-end: 1px solid var(--yuva-border); background: transparent; color: inherit; text-align: start; cursor: pointer; }\n.hrow:last-child { border-block-end: 0; }\n.hrow-text { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }\n.hrow-text b { font-weight: 500; }\n.hrow-text span { font-size: 12px; color: var(--yuva-muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n.hrow > svg { flex: none; color: var(--yuva-faint); }\n.hrow mark, .hrow-text mark { background: var(--yuva-wash); color: inherit; border-radius: 2px; }\n.hrow:hover .hrow-text b { text-decoration: underline; }\n.pills { display: flex; flex-wrap: wrap; gap: 8px; }\n.pill { display: inline-flex; align-items: center; gap: 8px; min-block-size: 36px; padding: 0 12px; border: 1px solid var(--yuva-strong); border-radius: 999px; background: transparent; color: inherit; cursor: pointer; }\n.pill:hover { background: var(--yuva-deep); }\n.pill span { font-family: var(--yuva-mono); font-size: 11px; color: var(--yuva-faint); }\n.ask { display: flex; align-items: center; gap: 12px; }\n.ask-text { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; }\n.ask-text b { font-weight: 500; }\n.ask-text span { font-size: 12px; color: var(--yuva-muted); }\n.article-title { margin: 0; font-size: 22px; line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; overflow-wrap: anywhere; }\n.prose { overflow-wrap: anywhere; line-height: 1.55; }\n.prose > :first-child { margin-block-start: 0; }\n.prose > :last-child { margin-block-end: 0; }\n.prose h1, .prose h2, .prose h3, .prose h4 { margin: 20px 0 8px; font-size: 16px; line-height: 1.3; font-weight: 600; }\n.prose p, .prose ul, .prose ol, .prose pre, .prose blockquote, .prose table { margin: 0 0 12px; }\n.prose ul, .prose ol { padding-inline-start: 20px; }\n.prose a { color: var(--yuva-brand); }\n.prose img { max-inline-size: 100%; block-size: auto; border-radius: 8px; }\n.prose code { font-family: var(--yuva-mono); font-size: 13px; padding: 1px 4px; border-radius: 4px; background: var(--yuva-deep); }\n.prose pre { padding: 10px; border-radius: 8px; background: var(--yuva-deep); overflow-x: auto; }\n.prose pre code { padding: 0; background: none; }\n.prose blockquote { padding-inline-start: 12px; border-inline-start: 2px solid var(--yuva-strong); color: var(--yuva-muted); }\n.prose table { display: block; overflow-x: auto; border-collapse: collapse; }\n.prose th, .prose td { padding: 4px 8px; border: 1px solid var(--yuva-border); text-align: start; }\n.rm-top { gap: 12px; }\n.rm-head { display: flex; align-items: center; gap: 12px; }\n.rm-head .hint { flex: 1; min-inline-size: 0; font-size: 13px; }\n.pill.suggest { flex: none; margin-inline-start: auto; gap: 6px; min-block-size: 36px; font-size: 13px; font-weight: 500; }\n.tabs { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; border-block-end: 1px solid var(--yuva-border); margin-inline: -8px; }\n.tabs button { position: relative; display: flex; align-items: center; justify-content: center; min-block-size: 44px; padding: 0; border: 0; border-block-end: 2px solid transparent; margin-block-end: -1px; background: transparent; color: var(--yuva-faint); cursor: pointer; }\n.tabs button:hover { color: var(--yuva-muted); }\n.tabs button::after { content: attr(data-tip); position: absolute; inset-block-start: calc(100% + 6px); left: 50%; transform: translateX(-50%); z-index: 2; padding: 4px 8px; border-radius: 6px; background: var(--yuva-fg); color: var(--yuva-bg); font-family: var(--yuva-mono); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity 0.12s; }\n.tabs button:first-child::after { left: auto; inset-inline-start: 4px; transform: none; }\n.tabs button:last-child::after { left: auto; inset-inline-end: 4px; transform: none; }\n.tabs button:hover::after, .tabs button:focus-visible::after { opacity: 1; }\n.tabs button[aria-selected=\"true\"] { color: var(--yuva-fg); border-block-end-color: var(--yuva-brand); }\n.rm-list { padding-block-start: 4px; }\n.ideas { display: flex; flex-direction: column; }\n.idea { display: flex; gap: 14px; padding-block: 14px; border-block-end: 1px solid var(--yuva-border); }\n.idea:last-child { border-block-end: 0; }\n.vote { flex: none; inline-size: 48px; min-block-size: 52px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 0; border: 1px solid var(--yuva-strong); border-radius: 10px; background: transparent; color: var(--yuva-muted); cursor: pointer; }\n.vote span { font-family: var(--yuva-mono); font-size: 12px; font-weight: 500; }\n.vote[aria-pressed=\"true\"] { background: var(--yuva-wash); border-color: var(--yuva-brand); color: var(--yuva-brand); }\n.vote:disabled { cursor: default; opacity: 0.7; }\n.idea-text { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding: 0; border: 0; background: transparent; color: inherit; text-align: start; cursor: pointer; }\n.idea-text b { font-weight: 500; overflow-wrap: anywhere; }\n.idea-text:hover b { text-decoration: underline; }\n.idea .lede { font-size: 13px; color: var(--yuva-muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }\n.meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 12px; color: var(--yuva-faint); }\n.badge-line, .stage, .tag { font-family: var(--yuva-mono); font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; padding: 2px 6px; border: 1px solid var(--yuva-strong); border-radius: 4px; }\n.badge-line { color: var(--yuva-warn); border-color: currentColor; }\n.stage { color: var(--yuva-brand); border-color: currentColor; }\n.idea-top { display: flex; gap: 14px; align-items: flex-start; }\n.idea-head { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 8px; }\n.reply { display: flex; flex-direction: column; gap: 4px; padding-block: 10px; border-block-end: 1px solid var(--yuva-border); }\n.reply:last-of-type { border-block-end: 0; }\n.who-line { display: flex; align-items: center; gap: 8px; }\n.wn-list { padding-block-start: 0; }\n.wn-entry { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; inline-size: 100%; padding: 16px 0; border: 0; border-block-end: 1px solid var(--yuva-border); background: transparent; color: inherit; text-align: start; cursor: pointer; }\n.wn-entry b { font-size: 15px; font-weight: 500; overflow-wrap: anywhere; }\n.wn-entry:hover b { text-decoration: underline; }\n.wn-lede { font-size: 13px; color: var(--yuva-muted); overflow-wrap: anywhere; }\n.wn-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-family: var(--yuva-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; }\n.wn-meta .unread-dot { margin: 0; inline-size: 7px; block-size: 7px; }\n.wn-date { color: var(--yuva-faint); }\n.wn-label { padding: 2px 6px; border-radius: 4px; background: var(--yuva-deep); color: var(--yuva-fg); }\n.wn-label.new { background: var(--yuva-wash); color: var(--yuva-brand); }\n.wn-label.fixed { color: var(--yuva-muted); }\n.wn-image { display: block; max-inline-size: 100%; block-size: auto; border-radius: 10px; border: 1px solid var(--yuva-border); }\n.who-line b { font-weight: 500; }\n";
@@ -0,0 +1,3 @@
1
+ import type { AppContext } from "../types.js";
2
+ import type { Translate } from "./apps.js";
3
+ export declare function subscribeApp(context: AppContext, t: Translate, root: HTMLElement): () => void;
@@ -0,0 +1,3 @@
1
+ import { type AppContext } from "../types.js";
2
+ import type { Translate } from "./apps.js";
3
+ export declare function whatsNewApp(context: AppContext, t: Translate, root: HTMLElement): () => void;
@@ -0,0 +1,2 @@
1
+ import type { Messages } from "@lingui/core";
2
+ export declare const catalogs: Record<string, Messages>;
@@ -16,6 +16,18 @@ export type ClientChatSettings = Schemas["ClientChatSettings"];
16
16
  export type DiscussionMode = Schemas["DiscussionMode"];
17
17
  export type DiscussionState = Schemas["DiscussionState"];
18
18
  export type DiscussionSort = Schemas["DiscussionSort"];
19
+ export type DiscussionKind = Schemas["DiscussionKind"];
20
+ export type IdeaStage = Schemas["IdeaStage"];
21
+ export type RoadmapSuggestions = Schemas["RoadmapSuggestions"];
22
+ export type ClientInboxRoadmap = Schemas["ClientInboxRoadmap"];
23
+ export type ClientRoadmap = Schemas["ClientRoadmap"];
24
+ export type ClientRoadmapStages = Schemas["ClientRoadmapStages"];
25
+ export type ChangelogLabel = Schemas["ChangelogLabel"];
26
+ export type ClientInboxWhatsNew = Schemas["ClientInboxWhatsNew"];
27
+ export type ClientChangelog = Schemas["ClientChangelog"];
28
+ export type ClientWhatsNew = Schemas["ClientWhatsNew"];
29
+ export type ClientWhatsNewEntry = Schemas["ClientWhatsNewEntry"];
30
+ export type ClientWhatsNewImage = Schemas["ClientWhatsNewImage"];
19
31
  export type DiscussionAuthor = Schemas["DiscussionAuthor"];
20
32
  export type Discussion = Schemas["Discussion"];
21
33
  export type DiscussionPost = Schemas["DiscussionPost"];
@@ -28,6 +40,19 @@ export type ReaderToken = Schemas["ReaderToken"];
28
40
  export type ReaderProfile = Schemas["ReaderProfile"];
29
41
  export type Rating = Schemas["Rating"];
30
42
  export type ClientMessage = Schemas["ClientMessage"];
43
+ export type MessageCard = Schemas["MessageCard"];
44
+ export type ClientInboxHelp = Schemas["ClientInboxHelp"];
45
+ export type ClientHelp = Schemas["ClientHelp"];
46
+ export type ClientHelpCenter = Schemas["ClientHelpCenter"];
47
+ export type ClientHelpCollection = Schemas["ClientHelpCollection"];
48
+ export type ClientHelpCollectionDetail = Schemas["ClientHelpCollectionDetail"];
49
+ export type ClientHelpArticle = Schemas["ClientHelpArticle"];
50
+ export type ClientHelpArticleSummary = Schemas["ClientHelpArticleSummary"];
51
+ export type ClientHelpSearchResult = Schemas["ClientHelpSearchResult"];
52
+ export type ClientHelpSearchResults = Schemas["ClientHelpSearchResults"];
53
+ export type ClientHelpReaction = Schemas["ClientHelpReaction"];
54
+ export type ClientHelpSearchClick = Schemas["ClientHelpSearchClick"];
55
+ export type HelpHighlight = Schemas["HelpHighlight"];
31
56
  export type ClientMessagePage = Schemas["ClientMessagePage"];
32
57
  export type ClientAttachment = Schemas["ClientAttachment"];
33
58
  export type ClientReadState = Schemas["ClientReadState"];
@@ -1,4 +1,4 @@
1
- import { type Fetch, type ClientMailingLists, type ClientSubscriptionAccepted, type ClientSubscriptionCreate, type ClientSubscriptionList, type ClientSubscriptionPut, type ClientSubscriptionStatus, 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";
1
+ import { type Fetch, type ClientMailingLists, type ClientSubscriptionAccepted, type ClientSubscriptionCreate, type ClientSubscriptionList, type ClientSubscriptionPut, type ClientSubscriptionStatus, type ClientContact, type ClientConversation, type ClientConversationCreated, type ClientConversationPage, type ClientFeedbackCreate, type ClientHelp, type ClientHelpArticle, type ClientHelpCollectionDetail, type ClientHelpReaction, type ClientHelpSearchClick, type ClientHelpSearchResults, type ClientInbox, type ClientRoadmap, type ClientWhatsNew, type ClientWhatsNewEntry, type IdeaStage, 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
2
  import { type ReaderSession, type ReaderSignInOptions } from "./reader.js";
3
3
  export type IdentityTokenSource = () => string | null | undefined | Promise<string | null | undefined>;
4
4
  export interface YuvaStorage {
@@ -45,6 +45,25 @@ export interface ConversationInput extends MessageInput {
45
45
  subject?: string;
46
46
  page_url?: string | null;
47
47
  page_title?: string;
48
+ help_article_id?: string;
49
+ }
50
+ export interface HelpOptions {
51
+ locale?: string;
52
+ }
53
+ export interface HelpGetOptions extends HelpOptions {
54
+ page?: string;
55
+ }
56
+ export interface HelpSearchOptions extends HelpOptions {
57
+ limit?: number;
58
+ final?: boolean;
59
+ }
60
+ export interface Help {
61
+ get(options?: HelpGetOptions): Promise<ClientHelp>;
62
+ search(q: string, options?: HelpSearchOptions): Promise<ClientHelpSearchResults>;
63
+ collection(id: string, options?: HelpOptions): Promise<ClientHelpCollectionDetail>;
64
+ article(id: string, options?: HelpOptions): Promise<ClientHelpArticle>;
65
+ react(articleId: string, input: ClientHelpReaction): Promise<void>;
66
+ click(input: ClientHelpSearchClick): Promise<void>;
48
67
  }
49
68
  export interface Page {
50
69
  cursor?: string;
@@ -53,6 +72,18 @@ export interface Page {
53
72
  export interface DiscussionListOptions extends Page {
54
73
  sort?: DiscussionSort;
55
74
  }
75
+ export interface IdeaListOptions extends Page {
76
+ stage?: IdeaStage;
77
+ sort?: "top" | "new";
78
+ q?: string;
79
+ }
80
+ export interface WhatsNewOptions extends Page {
81
+ locale?: string;
82
+ }
83
+ export interface IdeaInput {
84
+ title: string;
85
+ body: string;
86
+ }
56
87
  export declare function storageKey(channel: string): string;
57
88
  export declare function readerStorageKey(server: string, channel: string): string;
58
89
  export declare function randomId(): string;
@@ -60,6 +91,7 @@ export declare class YuvaClient {
60
91
  #private;
61
92
  readonly server: string;
62
93
  readonly channel: string;
94
+ readonly help: Help;
63
95
  constructor(options: YuvaClientOptions);
64
96
  get session(): ClientSessionInfo | null;
65
97
  get token(): string | null;
@@ -93,12 +125,19 @@ export declare class YuvaClient {
93
125
  setTyping(conversationId: string, typing: boolean): Promise<void>;
94
126
  setEmail(email: string): Promise<ClientContact>;
95
127
  attachment(id: string): Promise<Blob>;
96
- sendFeedback(input: ClientFeedbackCreate): Promise<ClientConversationCreated>;
128
+ sendFeedback(input: ClientFeedbackCreate & {
129
+ files?: Blob[];
130
+ }): Promise<ClientConversationCreated>;
97
131
  get reader(): ReaderSession | null;
98
132
  readerSignIn(options?: ReaderSignInOptions): Promise<ReaderSession>;
99
133
  setReader(reader: ReaderSession | null): void;
100
134
  readerSignOut(): Promise<void>;
101
135
  listDiscussions(page: string, options?: DiscussionListOptions): Promise<DiscussionPage>;
136
+ roadmap(): Promise<ClientRoadmap>;
137
+ whatsNew(options?: WhatsNewOptions): Promise<ClientWhatsNew>;
138
+ whatsNewEntry(id: string, options?: HelpOptions): Promise<ClientWhatsNewEntry>;
139
+ listIdeas(options?: IdeaListOptions): Promise<DiscussionPage>;
140
+ suggestIdea(input: IdeaInput): Promise<Discussion>;
102
141
  getDiscussion(id: string): Promise<DiscussionDetail>;
103
142
  startDiscussion(input: ClientDiscussionCreate): Promise<Discussion>;
104
143
  replyToDiscussion(discussionId: string, input: DiscussionPostCreate): Promise<DiscussionPost>;
@@ -1,4 +1,4 @@
1
- import { type IdentityTokenSource, type ClientConversation, type Layout, type PanelModule, type Rating } from "./types.js";
1
+ import { type IdentityTokenSource, type AppKind, type AppParams, type ClientConversation, type Layout, type PanelModule, type Rating } from "./types.js";
2
2
  export declare class YuvaChatElement extends HTMLElement {
3
3
  #private;
4
4
  static observedAttributes: string[];
@@ -13,6 +13,7 @@ export declare class YuvaChatElement extends HTMLElement {
13
13
  setIdentityToken(source: IdentityTokenSource | null): void;
14
14
  signOut(): Promise<void>;
15
15
  rate(conversationId: string, rating: Rating, comment?: string): Promise<ClientConversation>;
16
+ openApp(kind: AppKind, params?: AppParams): Promise<void>;
16
17
  connectedCallback(): void;
17
18
  disconnectedCallback(): void;
18
19
  attributeChangedCallback(name: string, previous: string | null, value: string | null): void;