waybetter 0.1.0 → 0.6.0

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 (515) hide show
  1. package/README.md +143 -9
  2. package/bin/waybetter.mjs +46 -0
  3. package/build/runtime.mjs +105 -0
  4. package/cli/buildenv.mjs +130 -0
  5. package/cli/dev.mjs +97 -0
  6. package/cli/i18n.mjs +382 -0
  7. package/cli/manifests.mjs +383 -0
  8. package/cli/privacy.mjs +768 -0
  9. package/cli/release.mjs +444 -0
  10. package/cli/remote.mjs +260 -0
  11. package/cli/store.mjs +326 -0
  12. package/cli/strings.mjs +121 -0
  13. package/dist/runtime/column.d.ts +93 -0
  14. package/dist/runtime/column.js +451 -0
  15. package/dist/runtime/column.js.map +1 -0
  16. package/dist/runtime/commandReport.d.ts +19 -0
  17. package/dist/runtime/commandReport.js +47 -0
  18. package/dist/runtime/commandReport.js.map +1 -0
  19. package/dist/runtime/commands.d.ts +72 -0
  20. package/dist/runtime/commands.js +214 -0
  21. package/dist/runtime/commands.js.map +1 -0
  22. package/dist/runtime/devErrors.d.ts +16 -0
  23. package/dist/runtime/devErrors.js +30 -0
  24. package/dist/runtime/devErrors.js.map +1 -0
  25. package/dist/runtime/domHub.d.ts +21 -0
  26. package/dist/runtime/domHub.js +139 -4
  27. package/dist/runtime/domHub.js.map +1 -1
  28. package/dist/runtime/featureModules.d.ts +157 -0
  29. package/dist/runtime/featureModules.js +484 -0
  30. package/dist/runtime/featureModules.js.map +1 -0
  31. package/dist/runtime/featureTable.d.ts +144 -0
  32. package/dist/runtime/featureTable.js +223 -0
  33. package/dist/runtime/featureTable.js.map +1 -0
  34. package/dist/runtime/fonts.d.ts +22 -0
  35. package/dist/runtime/fonts.js +72 -0
  36. package/dist/runtime/fonts.js.map +1 -0
  37. package/dist/runtime/i18n.d.ts +138 -0
  38. package/dist/runtime/i18n.js +614 -0
  39. package/dist/runtime/i18n.js.map +1 -0
  40. package/dist/runtime/i18nCheck.d.ts +30 -0
  41. package/dist/runtime/i18nCheck.js +224 -0
  42. package/dist/runtime/i18nCheck.js.map +1 -0
  43. package/dist/runtime/pageLang.d.ts +8 -0
  44. package/dist/runtime/pageLang.js +64 -0
  45. package/dist/runtime/pageLang.js.map +1 -0
  46. package/dist/runtime/pageStrings.d.ts +35 -0
  47. package/dist/runtime/pageStrings.js +76 -0
  48. package/dist/runtime/pageStrings.js.map +1 -0
  49. package/dist/runtime/panelButton.d.ts +33 -0
  50. package/dist/runtime/panelButton.js +83 -0
  51. package/dist/runtime/panelButton.js.map +1 -0
  52. package/dist/runtime/permissions.d.ts +47 -0
  53. package/dist/runtime/permissions.js +141 -0
  54. package/dist/runtime/permissions.js.map +1 -0
  55. package/dist/runtime/pluginApi.d.ts +51 -2
  56. package/dist/runtime/pluginApi.js +137 -22
  57. package/dist/runtime/pluginApi.js.map +1 -1
  58. package/dist/runtime/pluginI18n.d.ts +29 -0
  59. package/dist/runtime/pluginI18n.js +119 -0
  60. package/dist/runtime/pluginI18n.js.map +1 -0
  61. package/dist/runtime/settingsForm.d.ts +66 -0
  62. package/dist/runtime/settingsForm.js +114 -0
  63. package/dist/runtime/settingsForm.js.map +1 -0
  64. package/dist/runtime/site.d.ts +5 -0
  65. package/dist/runtime/site.js +1 -1
  66. package/dist/runtime/site.js.map +1 -1
  67. package/dist/runtime/siteRuntime.d.ts +144 -0
  68. package/dist/runtime/siteRuntime.js +175 -0
  69. package/dist/runtime/siteRuntime.js.map +1 -0
  70. package/dist/runtime/stringPackHook.d.ts +84 -0
  71. package/dist/runtime/stringPackHook.js +220 -0
  72. package/dist/runtime/stringPackHook.js.map +1 -0
  73. package/dist/runtime/stringPackTranslate.d.ts +59 -0
  74. package/dist/runtime/stringPackTranslate.js +264 -0
  75. package/dist/runtime/stringPackTranslate.js.map +1 -0
  76. package/dist/runtime/stringPacks.d.ts +200 -0
  77. package/dist/runtime/stringPacks.js +474 -0
  78. package/dist/runtime/stringPacks.js.map +1 -0
  79. package/dist/runtime/styles.d.ts +15 -0
  80. package/dist/runtime/styles.js +81 -0
  81. package/dist/runtime/styles.js.map +1 -0
  82. package/dist/runtime/textNet.d.ts +15 -0
  83. package/dist/runtime/textNet.js +131 -0
  84. package/dist/runtime/textNet.js.map +1 -0
  85. package/dist/runtime/themeApi.d.ts +121 -0
  86. package/dist/runtime/themeApi.js +220 -0
  87. package/dist/runtime/themeApi.js.map +1 -0
  88. package/dist/runtime/themeChoice.d.ts +52 -0
  89. package/dist/runtime/themeChoice.js +69 -0
  90. package/dist/runtime/themeChoice.js.map +1 -0
  91. package/dist/runtime/themeComponents.d.ts +435 -0
  92. package/dist/runtime/themeComponents.js +463 -0
  93. package/dist/runtime/themeComponents.js.map +1 -0
  94. package/dist/runtime/themeDecor.d.ts +73 -0
  95. package/dist/runtime/themeDecor.js +131 -0
  96. package/dist/runtime/themeDecor.js.map +1 -0
  97. package/dist/runtime/themeDoctor.d.ts +11 -0
  98. package/dist/runtime/themeDoctor.js +51 -0
  99. package/dist/runtime/themeDoctor.js.map +1 -0
  100. package/dist/runtime/themeIcons.d.ts +130 -0
  101. package/dist/runtime/themeIcons.js +263 -0
  102. package/dist/runtime/themeIcons.js.map +1 -0
  103. package/dist/runtime/themeRuntime.d.ts +100 -0
  104. package/dist/runtime/themeRuntime.js +497 -0
  105. package/dist/runtime/themeRuntime.js.map +1 -0
  106. package/dist/runtime/themeSchema.d.ts +10 -0
  107. package/dist/runtime/themeSchema.js +150 -0
  108. package/dist/runtime/themeSchema.js.map +1 -0
  109. package/dist/runtime/themeSpec.d.ts +259 -0
  110. package/dist/runtime/themeSpec.js +439 -0
  111. package/dist/runtime/themeSpec.js.map +1 -0
  112. package/dist/runtime/themeTokens.d.ts +12 -0
  113. package/dist/runtime/themeTokens.js +14 -6
  114. package/dist/runtime/themeTokens.js.map +1 -1
  115. package/dist/runtime/themeVariants.d.ts +30 -0
  116. package/dist/runtime/themeVariants.js +53 -0
  117. package/dist/runtime/themeVariants.js.map +1 -0
  118. package/dist/runtime/ui.d.ts +192 -0
  119. package/dist/runtime/ui.js +926 -0
  120. package/dist/runtime/ui.js.map +1 -0
  121. package/dist/shell/InstallDialog.d.ts +40 -0
  122. package/dist/shell/InstallDialog.js +170 -0
  123. package/dist/shell/InstallDialog.js.map +1 -0
  124. package/dist/shell/StoreView.d.ts +66 -0
  125. package/dist/shell/StoreView.js +103 -0
  126. package/dist/shell/StoreView.js.map +1 -0
  127. package/dist/shell/addressModel.js.map +1 -1
  128. package/dist/shell/chrome.js.map +1 -1
  129. package/dist/shell/deckModel.d.ts +117 -0
  130. package/dist/shell/deckModel.js +267 -0
  131. package/dist/shell/deckModel.js.map +1 -0
  132. package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
  133. package/dist/shell/frame/AccountSwitcher.js +243 -0
  134. package/dist/shell/frame/AccountSwitcher.js.map +1 -0
  135. package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
  136. package/dist/shell/frame/AddColumnDialog.js +81 -0
  137. package/dist/shell/frame/AddColumnDialog.js.map +1 -0
  138. package/dist/shell/frame/AppMenu.d.ts +21 -0
  139. package/dist/shell/frame/AppMenu.js +642 -0
  140. package/dist/shell/frame/AppMenu.js.map +1 -0
  141. package/dist/shell/frame/CommandPalette.d.ts +7 -0
  142. package/dist/shell/frame/CommandPalette.js +118 -0
  143. package/dist/shell/frame/CommandPalette.js.map +1 -0
  144. package/dist/shell/frame/DeckView.d.ts +13 -0
  145. package/dist/shell/frame/DeckView.js +287 -0
  146. package/dist/shell/frame/DeckView.js.map +1 -0
  147. package/dist/shell/frame/FindBar.d.ts +10 -0
  148. package/dist/shell/frame/FindBar.js +108 -0
  149. package/dist/shell/frame/FindBar.js.map +1 -0
  150. package/dist/shell/frame/MediaPanel.d.ts +8 -0
  151. package/dist/shell/frame/MediaPanel.js +76 -0
  152. package/dist/shell/frame/MediaPanel.js.map +1 -0
  153. package/dist/shell/frame/NewTabPage.d.ts +9 -0
  154. package/dist/shell/frame/NewTabPage.js +71 -0
  155. package/dist/shell/frame/NewTabPage.js.map +1 -0
  156. package/dist/shell/frame/PaneTheme.d.ts +16 -0
  157. package/dist/shell/frame/PaneTheme.js +67 -0
  158. package/dist/shell/frame/PaneTheme.js.map +1 -0
  159. package/dist/shell/frame/ReportDialog.d.ts +3 -0
  160. package/dist/shell/frame/ReportDialog.js +95 -0
  161. package/dist/shell/frame/ReportDialog.js.map +1 -0
  162. package/dist/shell/frame/Shell.d.ts +8 -0
  163. package/dist/shell/frame/Shell.js +1131 -0
  164. package/dist/shell/frame/Shell.js.map +1 -0
  165. package/dist/shell/frame/Titlebar.d.ts +16 -0
  166. package/dist/shell/frame/Titlebar.js +77 -0
  167. package/dist/shell/frame/Titlebar.js.map +1 -0
  168. package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
  169. package/dist/shell/frame/TitlebarExtras.js +202 -0
  170. package/dist/shell/frame/TitlebarExtras.js.map +1 -0
  171. package/dist/shell/frame/WebPanel.d.ts +4 -0
  172. package/dist/shell/frame/WebPanel.js +182 -0
  173. package/dist/shell/frame/WebPanel.js.map +1 -0
  174. package/dist/shell/frame/accountModel.d.ts +49 -0
  175. package/dist/shell/frame/accountModel.js +67 -0
  176. package/dist/shell/frame/accountModel.js.map +1 -0
  177. package/dist/shell/frame/accountSwitcher.css +91 -0
  178. package/dist/shell/frame/appI18n.d.ts +44 -0
  179. package/dist/shell/frame/appI18n.js +64 -0
  180. package/dist/shell/frame/appI18n.js.map +1 -0
  181. package/dist/shell/frame/appMenu.css +121 -0
  182. package/dist/shell/frame/backupModel.d.ts +38 -0
  183. package/dist/shell/frame/backupModel.js +192 -0
  184. package/dist/shell/frame/backupModel.js.map +1 -0
  185. package/dist/shell/frame/boot.d.ts +8 -0
  186. package/dist/shell/frame/boot.js +35 -0
  187. package/dist/shell/frame/boot.js.map +1 -0
  188. package/dist/shell/frame/brand.d.ts +1 -0
  189. package/dist/shell/frame/brand.js +4 -0
  190. package/dist/shell/frame/brand.js.map +1 -0
  191. package/dist/shell/frame/bridge.d.ts +35 -0
  192. package/dist/shell/frame/bridge.js +70 -0
  193. package/dist/shell/frame/bridge.js.map +1 -0
  194. package/dist/shell/frame/chromeTheme.d.ts +29 -0
  195. package/dist/shell/frame/chromeTheme.js +81 -0
  196. package/dist/shell/frame/chromeTheme.js.map +1 -0
  197. package/dist/shell/frame/deck.css +209 -0
  198. package/dist/shell/frame/deckStore.d.ts +89 -0
  199. package/dist/shell/frame/deckStore.js +239 -0
  200. package/dist/shell/frame/deckStore.js.map +1 -0
  201. package/dist/shell/frame/devHost.d.ts +35 -0
  202. package/dist/shell/frame/devHost.js +80 -0
  203. package/dist/shell/frame/devHost.js.map +1 -0
  204. package/dist/shell/frame/devModel.d.ts +7 -0
  205. package/dist/shell/frame/devModel.js +17 -0
  206. package/dist/shell/frame/devModel.js.map +1 -0
  207. package/dist/shell/frame/diag.d.ts +7 -0
  208. package/dist/shell/frame/diag.js +39 -0
  209. package/dist/shell/frame/diag.js.map +1 -0
  210. package/dist/shell/frame/findBar.css +14 -0
  211. package/dist/shell/frame/frameMessages.d.ts +248 -0
  212. package/dist/shell/frame/frameMessages.js +252 -0
  213. package/dist/shell/frame/frameMessages.js.map +1 -0
  214. package/dist/shell/frame/hooks.d.ts +39 -0
  215. package/dist/shell/frame/hooks.js +97 -0
  216. package/dist/shell/frame/hooks.js.map +1 -0
  217. package/dist/shell/frame/i18n.d.ts +27 -0
  218. package/dist/shell/frame/i18n.js +66 -0
  219. package/dist/shell/frame/i18n.js.map +1 -0
  220. package/dist/shell/frame/iconPack.d.ts +11 -0
  221. package/dist/shell/frame/iconPack.js +45 -0
  222. package/dist/shell/frame/iconPack.js.map +1 -0
  223. package/dist/shell/frame/icons.d.ts +71 -0
  224. package/dist/shell/frame/icons.js +75 -0
  225. package/dist/shell/frame/icons.js.map +1 -0
  226. package/dist/shell/frame/index.d.ts +34 -0
  227. package/dist/shell/frame/index.js +43 -0
  228. package/dist/shell/frame/index.js.map +1 -0
  229. package/dist/shell/frame/language.d.ts +58 -0
  230. package/dist/shell/frame/language.js +165 -0
  231. package/dist/shell/frame/language.js.map +1 -0
  232. package/dist/shell/frame/mediaModel.d.ts +34 -0
  233. package/dist/shell/frame/mediaModel.js +53 -0
  234. package/dist/shell/frame/mediaModel.js.map +1 -0
  235. package/dist/shell/frame/menuMessages.en.json +54 -0
  236. package/dist/shell/frame/menuModel.d.ts +277 -0
  237. package/dist/shell/frame/menuModel.js +293 -0
  238. package/dist/shell/frame/menuModel.js.map +1 -0
  239. package/dist/shell/frame/paletteModel.d.ts +139 -0
  240. package/dist/shell/frame/paletteModel.js +112 -0
  241. package/dist/shell/frame/paletteModel.js.map +1 -0
  242. package/dist/shell/frame/paneTheme.css +9 -0
  243. package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
  244. package/dist/shell/frame/pluginCommandStore.js +70 -0
  245. package/dist/shell/frame/pluginCommandStore.js.map +1 -0
  246. package/dist/shell/frame/reportModel.d.ts +52 -0
  247. package/dist/shell/frame/reportModel.js +105 -0
  248. package/dist/shell/frame/reportModel.js.map +1 -0
  249. package/dist/shell/frame/safeStore.d.ts +7 -0
  250. package/dist/shell/frame/safeStore.js +40 -0
  251. package/dist/shell/frame/safeStore.js.map +1 -0
  252. package/dist/shell/frame/searchInput.d.ts +2 -0
  253. package/dist/shell/frame/searchInput.js +11 -0
  254. package/dist/shell/frame/searchInput.js.map +1 -0
  255. package/dist/shell/frame/shell.css +629 -0
  256. package/dist/shell/frame/site.d.ts +206 -0
  257. package/dist/shell/frame/site.js +22 -0
  258. package/dist/shell/frame/site.js.map +1 -0
  259. package/dist/shell/frame/state.d.ts +99 -0
  260. package/dist/shell/frame/state.js +284 -0
  261. package/dist/shell/frame/state.js.map +1 -0
  262. package/dist/shell/frame/syncGate.d.ts +10 -0
  263. package/dist/shell/frame/syncGate.js +36 -0
  264. package/dist/shell/frame/syncGate.js.map +1 -0
  265. package/dist/shell/frame/syncHost.d.ts +35 -0
  266. package/dist/shell/frame/syncHost.js +85 -0
  267. package/dist/shell/frame/syncHost.js.map +1 -0
  268. package/dist/shell/frame/tabStill.d.ts +2 -0
  269. package/dist/shell/frame/tabStill.js +62 -0
  270. package/dist/shell/frame/tabStill.js.map +1 -0
  271. package/dist/shell/frame/themeScopes.d.ts +29 -0
  272. package/dist/shell/frame/themeScopes.js +61 -0
  273. package/dist/shell/frame/themeScopes.js.map +1 -0
  274. package/dist/shell/frame/themeStore.d.ts +99 -0
  275. package/dist/shell/frame/themeStore.js +252 -0
  276. package/dist/shell/frame/themeStore.js.map +1 -0
  277. package/dist/shell/frame/windowBinding.d.ts +2 -0
  278. package/dist/shell/frame/windowBinding.js +7 -0
  279. package/dist/shell/frame/windowBinding.js.map +1 -0
  280. package/dist/shell/frame/workspaceModel.d.ts +82 -0
  281. package/dist/shell/frame/workspaceModel.js +250 -0
  282. package/dist/shell/frame/workspaceModel.js.map +1 -0
  283. package/dist/shell/frame/workspaces.css +84 -0
  284. package/dist/shell/frame/workspaces.d.ts +22 -0
  285. package/dist/shell/frame/workspaces.js +125 -0
  286. package/dist/shell/frame/workspaces.js.map +1 -0
  287. package/dist/shell/frame/zoomStore.d.ts +10 -0
  288. package/dist/shell/frame/zoomStore.js +65 -0
  289. package/dist/shell/frame/zoomStore.js.map +1 -0
  290. package/dist/shell/installController.d.ts +122 -0
  291. package/dist/shell/installController.js +146 -0
  292. package/dist/shell/installController.js.map +1 -0
  293. package/dist/shell/installerMessages.d.ts +30 -0
  294. package/dist/shell/installerMessages.js +36 -0
  295. package/dist/shell/installerMessages.js.map +1 -0
  296. package/dist/shell/linkDrop.js.map +1 -1
  297. package/dist/shell/messages.d.ts +16 -0
  298. package/dist/shell/messages.js +27 -0
  299. package/dist/shell/messages.js.map +1 -0
  300. package/dist/shell/palette.js.map +1 -1
  301. package/dist/shell/paneModel.d.ts +22 -0
  302. package/dist/shell/paneModel.js +24 -1
  303. package/dist/shell/paneModel.js.map +1 -1
  304. package/dist/shell/panel/Appearance.d.ts +8 -0
  305. package/dist/shell/panel/Appearance.js +256 -0
  306. package/dist/shell/panel/Appearance.js.map +1 -0
  307. package/dist/shell/panel/BackupPanel.d.ts +5 -0
  308. package/dist/shell/panel/BackupPanel.js +198 -0
  309. package/dist/shell/panel/BackupPanel.js.map +1 -0
  310. package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
  311. package/dist/shell/panel/DeveloperPanel.js +51 -0
  312. package/dist/shell/panel/DeveloperPanel.js.map +1 -0
  313. package/dist/shell/panel/FeatureToggles.d.ts +13 -0
  314. package/dist/shell/panel/FeatureToggles.js +42 -0
  315. package/dist/shell/panel/FeatureToggles.js.map +1 -0
  316. package/dist/shell/panel/Home.d.ts +3 -0
  317. package/dist/shell/panel/Home.js +23 -0
  318. package/dist/shell/panel/Home.js.map +1 -0
  319. package/dist/shell/panel/IconPackInstall.d.ts +15 -0
  320. package/dist/shell/panel/IconPackInstall.js +41 -0
  321. package/dist/shell/panel/IconPackInstall.js.map +1 -0
  322. package/dist/shell/panel/LanguageSettings.d.ts +1 -0
  323. package/dist/shell/panel/LanguageSettings.js +54 -0
  324. package/dist/shell/panel/LanguageSettings.js.map +1 -0
  325. package/dist/shell/panel/MakePanel.d.ts +3 -0
  326. package/dist/shell/panel/MakePanel.js +237 -0
  327. package/dist/shell/panel/MakePanel.js.map +1 -0
  328. package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
  329. package/dist/shell/panel/MarkdownDoc.js +35 -0
  330. package/dist/shell/panel/MarkdownDoc.js.map +1 -0
  331. package/dist/shell/panel/Modes.d.ts +40 -0
  332. package/dist/shell/panel/Modes.js +270 -0
  333. package/dist/shell/panel/Modes.js.map +1 -0
  334. package/dist/shell/panel/NavIcon.d.ts +4 -0
  335. package/dist/shell/panel/NavIcon.js +6 -0
  336. package/dist/shell/panel/NavIcon.js.map +1 -0
  337. package/dist/shell/panel/Panel.d.ts +7 -0
  338. package/dist/shell/panel/Panel.js +139 -0
  339. package/dist/shell/panel/Panel.js.map +1 -0
  340. package/dist/shell/panel/PluginFeatures.d.ts +24 -0
  341. package/dist/shell/panel/PluginFeatures.js +165 -0
  342. package/dist/shell/panel/PluginFeatures.js.map +1 -0
  343. package/dist/shell/panel/Plugins.d.ts +33 -0
  344. package/dist/shell/panel/Plugins.js +112 -0
  345. package/dist/shell/panel/Plugins.js.map +1 -0
  346. package/dist/shell/panel/PowerSettings.d.ts +4 -0
  347. package/dist/shell/panel/PowerSettings.js +52 -0
  348. package/dist/shell/panel/PowerSettings.js.map +1 -0
  349. package/dist/shell/panel/Settings.d.ts +23 -0
  350. package/dist/shell/panel/Settings.js +116 -0
  351. package/dist/shell/panel/Settings.js.map +1 -0
  352. package/dist/shell/panel/ShareSetup.d.ts +8 -0
  353. package/dist/shell/panel/ShareSetup.js +130 -0
  354. package/dist/shell/panel/ShareSetup.js.map +1 -0
  355. package/dist/shell/panel/StoreSection.d.ts +6 -0
  356. package/dist/shell/panel/StoreSection.js +48 -0
  357. package/dist/shell/panel/StoreSection.js.map +1 -0
  358. package/dist/shell/panel/StringPacks.d.ts +11 -0
  359. package/dist/shell/panel/StringPacks.js +106 -0
  360. package/dist/shell/panel/StringPacks.js.map +1 -0
  361. package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
  362. package/dist/shell/panel/ThemeBuilder.js +205 -0
  363. package/dist/shell/panel/ThemeBuilder.js.map +1 -0
  364. package/dist/shell/panel/backup.css +34 -0
  365. package/dist/shell/panel/builder.css +232 -0
  366. package/dist/shell/panel/builderModel.d.ts +55 -0
  367. package/dist/shell/panel/builderModel.js +95 -0
  368. package/dist/shell/panel/builderModel.js.map +1 -0
  369. package/dist/shell/panel/compare.d.ts +10 -0
  370. package/dist/shell/panel/compare.js +51 -0
  371. package/dist/shell/panel/compare.js.map +1 -0
  372. package/dist/shell/panel/controls.d.ts +135 -0
  373. package/dist/shell/panel/controls.js +213 -0
  374. package/dist/shell/panel/controls.js.map +1 -0
  375. package/dist/shell/panel/featureModel.d.ts +69 -0
  376. package/dist/shell/panel/featureModel.js +79 -0
  377. package/dist/shell/panel/featureModel.js.map +1 -0
  378. package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
  379. package/dist/shell/panel/fonts/FontBrowser.js +189 -0
  380. package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
  381. package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
  382. package/dist/shell/panel/fonts/FontRoles.js +77 -0
  383. package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
  384. package/dist/shell/panel/fonts/catalog.d.ts +37 -0
  385. package/dist/shell/panel/fonts/catalog.js +68 -0
  386. package/dist/shell/panel/fonts/catalog.js.map +1 -0
  387. package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
  388. package/dist/shell/panel/index.d.ts +20 -0
  389. package/dist/shell/panel/index.js +34 -0
  390. package/dist/shell/panel/index.js.map +1 -0
  391. package/dist/shell/panel/languageModel.d.ts +5 -0
  392. package/dist/shell/panel/languageModel.js +7 -0
  393. package/dist/shell/panel/languageModel.js.map +1 -0
  394. package/dist/shell/panel/make.css +72 -0
  395. package/dist/shell/panel/makeModel.d.ts +32 -0
  396. package/dist/shell/panel/makeModel.js +84 -0
  397. package/dist/shell/panel/makeModel.js.map +1 -0
  398. package/dist/shell/panel/markdown.d.ts +46 -0
  399. package/dist/shell/panel/markdown.js +100 -0
  400. package/dist/shell/panel/markdown.js.map +1 -0
  401. package/dist/shell/panel/nav.d.ts +12 -0
  402. package/dist/shell/panel/nav.js +50 -0
  403. package/dist/shell/panel/nav.js.map +1 -0
  404. package/dist/shell/panel/panel.css +401 -0
  405. package/dist/shell/panel/panelMessages.d.ts +763 -0
  406. package/dist/shell/panel/panelMessages.js +767 -0
  407. package/dist/shell/panel/panelMessages.js.map +1 -0
  408. package/dist/shell/panel/plugins.css +59 -0
  409. package/dist/shell/panel/setupModel.d.ts +87 -0
  410. package/dist/shell/panel/setupModel.js +152 -0
  411. package/dist/shell/panel/setupModel.js.map +1 -0
  412. package/dist/shell/panel/site.d.ts +259 -0
  413. package/dist/shell/panel/site.js +25 -0
  414. package/dist/shell/panel/site.js.map +1 -0
  415. package/dist/shell/panel/strings.css +7 -0
  416. package/dist/shell/panel/themes.d.ts +10 -0
  417. package/dist/shell/panel/themes.js +8 -0
  418. package/dist/shell/panel/themes.js.map +1 -0
  419. package/dist/shell/profileModel.d.ts +3 -2
  420. package/dist/shell/profileModel.js +7 -5
  421. package/dist/shell/profileModel.js.map +1 -1
  422. package/dist/shell/store.css +230 -0
  423. package/dist/shell/storeMessages.d.ts +169 -0
  424. package/dist/shell/storeMessages.js +172 -0
  425. package/dist/shell/storeMessages.js.map +1 -0
  426. package/dist/shell/storeModel.d.ts +181 -0
  427. package/dist/shell/storeModel.js +133 -0
  428. package/dist/shell/storeModel.js.map +1 -0
  429. package/dist/shell/stringPacksModel.d.ts +44 -0
  430. package/dist/shell/stringPacksModel.js +94 -0
  431. package/dist/shell/stringPacksModel.js.map +1 -0
  432. package/dist/shell/updateModel.d.ts +2 -1
  433. package/dist/shell/updateModel.js +5 -4
  434. package/dist/shell/updateModel.js.map +1 -1
  435. package/dist/shell/windowControls.d.ts +4 -0
  436. package/dist/shell/windowControls.js +5 -0
  437. package/dist/shell/windowControls.js.map +1 -1
  438. package/i18n-config.schema.json +29 -0
  439. package/i18n-meta.schema.json +26 -0
  440. package/i18n.schema.json +42 -0
  441. package/icons.schema.json +646 -0
  442. package/languages.schema.json +23 -0
  443. package/locales/ar-x-fm.json +11 -0
  444. package/locales/ar.json +1281 -0
  445. package/locales/bg.json +1280 -0
  446. package/locales/bn.json +1280 -0
  447. package/locales/ca.json +1280 -0
  448. package/locales/cs.json +1280 -0
  449. package/locales/da.json +1280 -0
  450. package/locales/de.json +1280 -0
  451. package/locales/el.json +1280 -0
  452. package/locales/en-GB.json +27 -0
  453. package/locales/en.json +1280 -0
  454. package/locales/en.meta.json +51 -0
  455. package/locales/es.json +1280 -0
  456. package/locales/eu.json +1280 -0
  457. package/locales/fa.json +1281 -0
  458. package/locales/fi.json +1280 -0
  459. package/locales/fil.json +1280 -0
  460. package/locales/fr.json +1280 -0
  461. package/locales/ga.json +1280 -0
  462. package/locales/gl.json +1280 -0
  463. package/locales/gu.json +1280 -0
  464. package/locales/ha.json +1280 -0
  465. package/locales/he.json +1281 -0
  466. package/locales/hi.json +1280 -0
  467. package/locales/hr.json +1280 -0
  468. package/locales/hu.json +1279 -0
  469. package/locales/id.json +1280 -0
  470. package/locales/ig.json +1280 -0
  471. package/locales/it.json +1280 -0
  472. package/locales/ja.json +1280 -0
  473. package/locales/kn.json +1280 -0
  474. package/locales/ko.json +1280 -0
  475. package/locales/mr.json +1280 -0
  476. package/locales/ms.json +1280 -0
  477. package/locales/nb.json +1280 -0
  478. package/locales/nl.json +1280 -0
  479. package/locales/pl.json +1280 -0
  480. package/locales/pt.json +1280 -0
  481. package/locales/ro.json +1280 -0
  482. package/locales/ru.json +1280 -0
  483. package/locales/sk.json +1280 -0
  484. package/locales/sr.json +1280 -0
  485. package/locales/sv.json +1280 -0
  486. package/locales/ta.json +1280 -0
  487. package/locales/th.json +1280 -0
  488. package/locales/tr.json +1280 -0
  489. package/locales/uk.json +1280 -0
  490. package/locales/ur.json +1281 -0
  491. package/locales/vi.json +1280 -0
  492. package/locales/yo.json +1280 -0
  493. package/locales/zh-Hans.json +1280 -0
  494. package/locales/zh-Hant.json +1280 -0
  495. package/package.json +148 -6
  496. package/store-catalog.schema.json +65 -0
  497. package/theme.schema.json +4659 -0
  498. package/windows/installer.nsi +926 -0
  499. package/windows/languages/Basque.nsh +28 -0
  500. package/windows/languages/Catalan.nsh +28 -0
  501. package/windows/languages/Croatian.nsh +28 -0
  502. package/windows/languages/Czech.nsh +28 -0
  503. package/windows/languages/Danish.nsh +28 -0
  504. package/windows/languages/Finnish.nsh +28 -0
  505. package/windows/languages/Galician.nsh +28 -0
  506. package/windows/languages/Greek.nsh +28 -0
  507. package/windows/languages/Hungarian.nsh +28 -0
  508. package/windows/languages/Indonesian.nsh +28 -0
  509. package/windows/languages/Irish.nsh +28 -0
  510. package/windows/languages/Malay.nsh +28 -0
  511. package/windows/languages/Polish.nsh +28 -0
  512. package/windows/languages/Romanian.nsh +28 -0
  513. package/windows/languages/Serbian.nsh +28 -0
  514. package/windows/languages/Slovak.nsh +28 -0
  515. package/windows/languages/Thai.nsh +28 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deckModel.js","sourceRoot":"","sources":["../../../../../shell/src/deckModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Power User Mode: a deck of narrow site columns (TweetDeck-style). Pure model (no Tauri/DOM), so\n// it is unit-tested under node. Every column is a real site tab webview in its own account profile;\n// this model only says which columns exist, which page of them is on screen and where each one\n// goes. What a column shows is the site adapter's business (`urlFor`), what it hides is the page\n// runtime's (runtime/column.ts). Paging, not pixel scrolling: a page is as many whole columns as\n// fit the viewport; the rest are parked off-page (hidden, low memory).\n\n/** A column's content, named by the site adapter (e.g. `{ kind: 'search', value: 'from:me' }`). */\nexport type ColumnSource = { kind: string; value?: string };\n\n/** Per-column filters, applied by the page runtime to the site's items (runtime/column.ts). */\nexport type ColumnFilters = {\n /** Keywords (case-insensitive) or `/regex/flags`; a match hides the item. */\n terms: string[];\n hideReplies: boolean;\n hideReposts: boolean;\n mediaOnly: boolean;\n};\n\nexport type DeckColumn = {\n id: string;\n /** The tab webview id this column runs in (`tab-<tabId>` natively). */\n tabId: string;\n /** Account profile of the column's webview. */\n profile: string;\n source: ColumnSource;\n /** Preferred width in px; a page stretches its columns to fill the viewport. */\n width: number;\n /** Per-column feature flags over the global ones (allow-listed natively). */\n flags: Record<string, boolean>;\n filters: ColumnFilters;\n /** Optional title the user gave the column. */\n title?: string;\n};\n\nexport type Deck = { id: string; name: string; columns: DeckColumn[] };\n\nexport const COLUMN_WIDTHS = [320, 360, 400, 480] as const;\nexport const DEFAULT_COLUMN_WIDTH = 360;\nexport const MIN_COLUMN_WIDTH = 280;\nexport const MAX_COLUMN_WIDTH = 640;\nexport const MAX_COLUMNS = 24;\nexport const MAX_DECKS = 12;\nexport const MAX_TERMS = 32;\nexport const MAX_TERM_CHARS = 200;\nexport const MAX_FLAGS = 16;\n/** Visible columns per page before the memory guard warns. */\nexport const DEFAULT_MAX_VISIBLE = 6;\n/** Gap between columns in px. */\nexport const COLUMN_GAP = 8;\n\nexport const emptyFilters = (): ColumnFilters => ({ terms: [], hideReplies: false, hideReposts: false, mediaOnly: false });\n\nconst ID = /^[a-z0-9][a-z0-9-]{0,39}$/i;\nexport const validColumnId = (id: unknown): id is string => typeof id === 'string' && ID.test(id);\n\n// eslint-disable-next-line no-control-regex\nconst CONTROL = /[\\u0000-\\u001f\\u007f-\\u009f]/;\nfunction cleanText(value: unknown, max: number): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (!trimmed || [...trimmed].length > max || CONTROL.test(trimmed)) return null;\n return trimmed;\n}\n\nexport function normalizeFilters(value: unknown): ColumnFilters {\n const raw = (value && typeof value === 'object' ? value : {}) as Partial<Record<keyof ColumnFilters, unknown>>;\n const terms: string[] = [];\n for (const term of Array.isArray(raw.terms) ? raw.terms : []) {\n const clean = cleanText(term, MAX_TERM_CHARS);\n if (clean && !terms.includes(clean) && terms.length < MAX_TERMS) terms.push(clean);\n }\n return { terms, hideReplies: raw.hideReplies === true, hideReposts: raw.hideReposts === true, mediaOnly: raw.mediaOnly === true };\n}\n\nexport function normalizeFlags(value: unknown, allowed?: readonly string[]): Record<string, boolean> {\n const flags: Record<string, boolean> = {};\n if (!value || typeof value !== 'object') return flags;\n for (const [key, flag] of Object.entries(value as Record<string, unknown>)) {\n if (typeof flag !== 'boolean' || !/^[a-zA-Z][a-zA-Z0-9]{0,47}$/.test(key)) continue;\n if (allowed && !allowed.includes(key)) continue;\n if (Object.keys(flags).length >= MAX_FLAGS) break;\n flags[key] = flag;\n }\n return flags;\n}\n\nexport const clampWidth = (width: unknown): number =>\n typeof width === 'number' && Number.isFinite(width) ? Math.round(Math.min(MAX_COLUMN_WIDTH, Math.max(MIN_COLUMN_WIDTH, width))) : DEFAULT_COLUMN_WIDTH;\n\nexport type NormalizeOptions = {\n /** Source kinds the site adapter knows; others are dropped. */\n kinds?: readonly string[];\n /** Profile ids that exist; a column of a removed profile moves to `fallbackProfile`. */\n profiles?: readonly string[];\n fallbackProfile?: string;\n /** Allow-listed per-column flags. */\n flags?: readonly string[];\n};\n\nexport function normalizeColumn(value: unknown, options: NormalizeOptions = {}): DeckColumn | null {\n const raw = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>;\n if (!validColumnId(raw.id) || !validColumnId(raw.tabId)) return null;\n const source = raw.source as Partial<ColumnSource> | undefined;\n const kind = typeof source?.kind === 'string' && /^[a-z][a-z0-9-]{0,23}$/.test(source.kind) ? source.kind : null;\n if (!kind || (options.kinds && !options.kinds.includes(kind))) return null;\n const sourceValue = source?.value === undefined ? undefined : cleanText(source.value, 512);\n if (source?.value !== undefined && sourceValue === null) return null;\n let profile = typeof raw.profile === 'string' && raw.profile ? raw.profile : options.fallbackProfile ?? 'default';\n if (options.profiles && !options.profiles.includes(profile)) profile = options.fallbackProfile ?? options.profiles[0] ?? 'default';\n const title = cleanText(raw.title, 60);\n return {\n id: raw.id,\n tabId: raw.tabId,\n profile,\n source: sourceValue ? { kind, value: sourceValue } : { kind },\n width: clampWidth(raw.width),\n flags: normalizeFlags(raw.flags, options.flags),\n filters: normalizeFilters(raw.filters),\n ...(title ? { title } : {}),\n };\n}\n\n/** Anything from storage → a bounded deck (unique column and tab ids, at most MAX_COLUMNS). */\nexport function normalizeDeck(value: unknown, options: NormalizeOptions = {}): Deck | null {\n const raw = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>;\n if (!validColumnId(raw.id)) return null;\n const name = cleanText(raw.name, 40) ?? 'Deck';\n const columns: DeckColumn[] = [];\n const ids = new Set<string>();\n for (const item of Array.isArray(raw.columns) ? raw.columns : []) {\n if (columns.length >= MAX_COLUMNS) break;\n const column = normalizeColumn(item, options);\n if (!column || ids.has(column.id) || ids.has(`tab:${column.tabId}`)) continue;\n ids.add(column.id);\n ids.add(`tab:${column.tabId}`);\n columns.push(column);\n }\n return { id: raw.id, name, columns };\n}\n\nexport function normalizeDecks(value: unknown, options: NormalizeOptions = {}): Deck[] {\n const decks: Deck[] = [];\n const tabs = new Set<string>();\n for (const item of Array.isArray(value) ? value : []) {\n if (decks.length >= MAX_DECKS) break;\n const deck = normalizeDeck(item, options);\n if (!deck || decks.some(other => other.id === deck.id)) continue;\n // A tab webview belongs to exactly one column of one deck.\n deck.columns = deck.columns.filter(column => !tabs.has(column.tabId));\n for (const column of deck.columns) tabs.add(column.tabId);\n decks.push(deck);\n }\n return decks;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Layout\n\nexport type PlacedColumn = { id: string; x: number; width: number };\nexport type DeckLayout = {\n /** The page shown (clamped into range). */\n page: number;\n pages: number;\n visible: PlacedColumn[];\n /** Columns on other pages: their webviews are hidden (and parked when the setting says so). */\n parked: string[];\n};\n\nexport type LayoutOptions = { gap?: number; maxVisible?: number };\n\n/** How many columns from `start` (forward, or backward with `step` -1) fit `viewportW` (at least one). */\nfunction fitCount(viewportW: number, widths: readonly number[], start: number, step: 1 | -1, gap: number, maxVisible: number): number {\n let used = 0;\n let count = 0;\n for (let i = start; i >= 0 && i < widths.length && count < maxVisible; i += step) {\n const needed = count ? used + gap + widths[i]! : widths[i]!;\n if (count && needed > viewportW) break;\n used = needed;\n count++;\n }\n return Math.max(1, count);\n}\n\n/**\n * Splits columns into pages of whole columns that fit `viewportW` (at least one per page). Pages\n * are filled from the left; the last page is filled from the right end instead, so it is as full as\n * the others (it may repeat columns of the page before) rather than one lone stretched column.\n */\nexport function paginate(viewportW: number, columns: readonly Pick<DeckColumn, 'id' | 'width'>[], options: LayoutOptions = {}): string[][] {\n const gap = options.gap ?? COLUMN_GAP;\n const maxVisible = Math.max(1, Math.floor(options.maxVisible ?? DEFAULT_MAX_VISIBLE));\n const widths = columns.map(column => clampWidth(column.width));\n const pages: string[][] = [];\n let start = 0;\n while (start < columns.length) {\n const count = fitCount(viewportW, widths, start, 1, gap, maxVisible);\n if (start + count >= columns.length && pages.length) {\n // The last page: as many columns as fit, counted back from the end.\n const back = fitCount(viewportW, widths, columns.length - 1, -1, gap, maxVisible);\n pages.push(columns.slice(columns.length - back).map(column => column.id));\n break;\n }\n pages.push(columns.slice(start, start + count).map(column => column.id));\n start += count;\n }\n return pages;\n}\n\n/** A page's columns stretch to fill the viewport, but never beyond this factor of their width. */\nexport const MAX_STRETCH = 2;\n\n/**\n * Where each column of `page` goes in a viewport `viewportW` px wide. The page's columns stretch\n * evenly to fill the width (no ragged gap on the right); a lone column wider than the viewport\n * is squeezed to it. Columns on other pages are `parked`.\n */\nexport function layoutColumns(viewportW: number, columns: readonly Pick<DeckColumn, 'id' | 'width'>[], page: number, options: LayoutOptions = {}): DeckLayout {\n const gap = options.gap ?? COLUMN_GAP;\n const width = Math.max(0, Math.floor(viewportW));\n const pages = paginate(width, columns, options);\n if (!pages.length) return { page: 0, pages: 0, visible: [], parked: [] };\n const index = Math.min(pages.length - 1, Math.max(0, Math.floor(Number.isFinite(page) ? page : 0)));\n const ids = pages[index]!;\n const byId = new Map(columns.map(column => [column.id, clampWidth(column.width)]));\n const preferred = ids.map(id => byId.get(id)!);\n const sum = preferred.reduce((total, w) => total + w, 0);\n const room = Math.max(ids.length, width - gap * (ids.length - 1));\n // Integer px in proportion to the preferred widths; the rounding remainder goes 1 px per column\n // from the left, so the row ends exactly at the viewport edge.\n // Stretch to fill, up to MAX_STRETCH; a page of few columns on a wide screen leaves room at the end.\n const target = Math.min(room, Math.floor(sum * MAX_STRETCH));\n const widths = preferred.map(w => Math.max(1, Math.floor((w * target) / sum)));\n let remainder = target - widths.reduce((total, w) => total + w, 0);\n for (let i = 0; remainder > 0; i = (i + 1) % widths.length, remainder--) widths[i]! += 1;\n const visible: PlacedColumn[] = [];\n let x = 0;\n ids.forEach((id, i) => {\n visible.push({ id, x, width: widths[i]! });\n x += widths[i]! + gap;\n });\n const shown = new Set(ids);\n return { page: index, pages: pages.length, visible, parked: columns.map(c => c.id).filter(id => !shown.has(id)) };\n}\n\n/**\n * The page that shows column `id`: `current` when it is on it already (so focusing a column never\n * flips pages needlessly), else the first page that holds it (0 when it is unknown).\n */\nexport function pageOf(viewportW: number, columns: readonly Pick<DeckColumn, 'id' | 'width'>[], id: string, options: LayoutOptions = {}, current?: number): number {\n const pages = paginate(Math.max(0, Math.floor(viewportW)), columns, options);\n if (current !== undefined && pages[current]?.includes(id)) return current;\n const index = pages.findIndex(page => page.includes(id));\n return index < 0 ? 0 : index;\n}\n\n/** The column `delta` steps from `focused` (clamped at the ends; the first one when none is focused). */\nexport function moveFocus(columns: readonly Pick<DeckColumn, 'id'>[], focused: string | null | undefined, delta: number): string | null {\n if (!columns.length) return null;\n const index = columns.findIndex(column => column.id === focused);\n if (index < 0) return columns[delta < 0 ? columns.length - 1 : 0]!.id;\n return columns[Math.min(columns.length - 1, Math.max(0, index + Math.trunc(delta)))]!.id;\n}\n\n/** The URL a column loads: the adapter's `urlFor`, or null for a source it does not know. */\nexport function columnUrl(source: ColumnSource, urlFor: (source: ColumnSource) => string | null): string | null {\n try {\n const url = urlFor(source);\n if (!url) return null;\n const parsed = new URL(url);\n return parsed.protocol === 'https:' && !parsed.username && !parsed.password ? parsed.href : null;\n } catch {\n return null;\n }\n}\n\n/** Unread count to show for a deck: the sum over its columns, capped like the native report (999). */\nexport const MAX_UNREAD = 999;\nexport function unreadTotal(unread: ReadonlyMap<string, number> | Record<string, number>, columns: readonly Pick<DeckColumn, 'tabId'>[]): number {\n const get = (id: string) => (unread instanceof Map ? unread.get(id) : (unread as Record<string, number>)[id]) ?? 0;\n let total = 0;\n for (const column of columns) {\n const value = get(column.tabId);\n if (Number.isFinite(value) && value > 0) total += Math.floor(value);\n }\n return Math.min(MAX_UNREAD, total);\n}\n\n/** Moves column `id` by `delta` places (clamped); returns a new array. */\nexport function moveColumn<T extends { id: string }>(columns: readonly T[], id: string, delta: number): T[] {\n const index = columns.findIndex(column => column.id === id);\n if (index < 0) return [...columns];\n const target = Math.min(columns.length - 1, Math.max(0, index + Math.trunc(delta)));\n const next = [...columns];\n const [item] = next.splice(index, 1);\n next.splice(target, 0, item!);\n return next;\n}\n\n/**\n * A column still shows its source page (origin, path with the trailing slash ignored, and query);\n * otherwise it navigated away (a post, a profile) and its header offers the way back. The page\n * runtime uses the same rule (runtime/column.ts `isSourcePage`).\n */\nexport function isSourcePage(href: string, source: string): boolean {\n try {\n const a = new URL(href);\n const b = new URL(source);\n const path = (url: URL) => url.pathname.replace(/\\/+$/, '') || '/';\n return a.origin === b.origin && path(a) === path(b) && a.search === b.search;\n } catch {\n return false;\n }\n}\n"]}
@@ -0,0 +1,42 @@
1
+ import { type Profile, type ProfileSettings } from '../profileModel.ts';
2
+ import './accountSwitcher.css';
3
+ export { useProfiles } from './hooks.ts';
4
+ /** What the switcher shows for a profile: the site login once seen, the profile name before. */
5
+ export declare function accountLabel(profile: Profile): {
6
+ title: string;
7
+ detail: string;
8
+ state: "signed-in" | "signed-out" | "new";
9
+ };
10
+ /** Saves natively (Rust validates and owns the data directories); the preview keeps it in memory. */
11
+ export declare function saveProfiles(next: ProfileSettings): Promise<void>;
12
+ export declare const ProfileDot: ({ color, title }: {
13
+ color: string;
14
+ title?: string;
15
+ }) => import("react").JSX.Element;
16
+ export declare function openTabs(profile: string): number;
17
+ /** The site's own sign-in page for that account, in a new pane beside the focused one. */
18
+ export declare function signIn(profile: string): void;
19
+ /** "Add account": a fresh login (its own cookies and storage) whose sign-in opens in a new pane. */
20
+ export declare function addAccount(settings: ProfileSettings): Promise<void>;
21
+ /**
22
+ * Removes an account after the user confirmed: its tabs close first (native code refuses to delete
23
+ * the data directory of a profile that still has a tab), then the list is saved and native code
24
+ * deletes that login's data on this computer. Never called without the explicit confirm step.
25
+ */
26
+ export declare function removeAccount(settings: ProfileSettings, id: string): Promise<void>;
27
+ export declare const AccountAvatar: ({ profile, size }: {
28
+ profile: Profile;
29
+ size: number;
30
+ }) => import("react").JSX.Element;
31
+ /** "Name (@handle)" for titles and labels. */
32
+ export declare function accountName(profile: Profile): string;
33
+ /**
34
+ * Titlebar account switcher. Every entry is a separate site login on this computer (its own
35
+ * WebView data directory) that shows the account the site itself reports as signed in there.
36
+ *
37
+ * One click shows the account: a visible pane of it gets focus, otherwise its home feed (or the
38
+ * site's sign-in) opens in a new pane beside the focused one. Shift/Ctrl-click opens a new tab
39
+ * instead. Everything else ("Open in new tab", "Use for new tabs", sign out, remove) is in the
40
+ * row's "…" menu. The button shows the focused pane's account.
41
+ */
42
+ export declare function AccountSwitcher(): import("react").JSX.Element;
@@ -0,0 +1,243 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { DEFAULT_PROFILE, accountLabel as accountLabelCore, removeProfile, tabProfile } from "../profileModel.js";
5
+ import { accountAction, addAccountProfile, focusedAccount, moveFocus, setDefaultAccount, tabsByAccount } from "./accountModel.js";
6
+ import { APP_MENU_KEYS, openAppMenu } from "./AppMenu.js";
7
+ import { invoke } from "./bridge.js";
8
+ import { decks, forgetColumn, saveDecks } from "./deckStore.js";
9
+ import { usePaneTick, useProfiles, useT } from "./hooks.js";
10
+ import { t, tx } from "./i18n.js";
11
+ import { Avatar, Icon } from "./icons.js";
12
+ import { menuText } from "./menuModel.js";
13
+ import { site } from "./site.js";
14
+ import { flushSync, paneInfos, setOverlay, setProfiles, shell } from "./state.js";
15
+ import { isTauri } from "./windowBinding.js";
16
+ import './accountSwitcher.css';
17
+ export { useProfiles } from "./hooks.js";
18
+ /** What the switcher shows for a profile: the site login once seen, the profile name before. */
19
+ export function accountLabel(profile) {
20
+ return accountLabelCore(profile, site().accounts, key => tx(key, undefined, '') || undefined);
21
+ }
22
+ /** Saves natively (Rust validates and owns the data directories); the preview keeps it in memory. */
23
+ export async function saveProfiles(next) {
24
+ if (!isTauri) {
25
+ setProfiles(next);
26
+ return;
27
+ }
28
+ setProfiles(await invoke('profiles_set', { settings: next }));
29
+ }
30
+ export const ProfileDot = ({ color, title }) => _jsx("span", { className: "bt-profile-dot", style: { background: color }, title: title, "aria-hidden": title ? undefined : true });
31
+ export function openTabs(profile) {
32
+ return tabsByAccount(shell.profiles, paneInfos()).get(profile)?.length ?? 0;
33
+ }
34
+ /** The site's own sign-in page for that account, in a new pane beside the focused one. */
35
+ export function signIn(profile) {
36
+ shell.openAccount(profile, { url: site().loginUrl });
37
+ }
38
+ /** "Add account": a fresh login (its own cookies and storage) whose sign-in opens in a new pane. */
39
+ export async function addAccount(settings) {
40
+ const next = addAccountProfile(settings);
41
+ await saveProfiles(next.settings);
42
+ signIn(next.profile);
43
+ }
44
+ /**
45
+ * Removes an account after the user confirmed: its tabs close first (native code refuses to delete
46
+ * the data directory of a profile that still has a tab), then the list is saved and native code
47
+ * deletes that login's data on this computer. Never called without the explicit confirm step.
48
+ */
49
+ export async function removeAccount(settings, id) {
50
+ if (id === DEFAULT_PROFILE)
51
+ return;
52
+ const tabs = tabsByAccount(settings, paneInfos()).get(id) ?? [];
53
+ for (const tab of tabs)
54
+ shell.api?.getPanel(tab)?.api.close();
55
+ // Start pages of that account fall back to the default one.
56
+ for (const panel of shell.api?.panels ?? []) {
57
+ const params = panel.params;
58
+ if (params?.kind === 'start' && params.profile === id)
59
+ panel.api.updateParameters({ profile: DEFAULT_PROFILE });
60
+ }
61
+ // Deck columns of that account go too (each is a webview in its profile); a compose dock in it closes.
62
+ let deckChanged = false;
63
+ decks.list = decks.list.map(deck => {
64
+ const gone = deck.columns.filter(column => column.profile === id);
65
+ if (!gone.length)
66
+ return deck;
67
+ deckChanged = true;
68
+ for (const column of gone)
69
+ forgetColumn(column.tabId);
70
+ return { ...deck, columns: deck.columns.filter(column => column.profile !== id) };
71
+ });
72
+ for (const [deckId, compose] of decks.compose)
73
+ if (compose.profile === id) {
74
+ decks.compose.delete(deckId);
75
+ deckChanged = true;
76
+ }
77
+ if (deckChanged)
78
+ saveDecks();
79
+ // dockview drops closed panels from `api.panels` synchronously (checked in the harness, whose
80
+ // profiles_set refuses like native code), so this sync no longer lists the account's tabs.
81
+ await flushSync();
82
+ try {
83
+ await saveProfiles(removeProfile(settings, id));
84
+ }
85
+ catch (failure) {
86
+ const message = String(failure);
87
+ if (/PROFILE: close this profile's tabs/.test(message))
88
+ throw new Error(t('wb.acct.notRemoved'));
89
+ throw failure;
90
+ }
91
+ }
92
+ export const AccountAvatar = ({ profile, size }) => _jsx(Avatar, { name: accountLabel(profile).title, color: profile.color, size: size, src: profile.account?.avatar });
93
+ /** "Name (@handle)" for titles and labels. */
94
+ export function accountName(profile) {
95
+ return `${accountLabel(profile).title}${profile.account ? ` (${site().accounts.handlePrefix}${profile.account.handle})` : ''}`;
96
+ }
97
+ /**
98
+ * Titlebar account switcher. Every entry is a separate site login on this computer (its own
99
+ * WebView data directory) that shows the account the site itself reports as signed in there.
100
+ *
101
+ * One click shows the account: a visible pane of it gets focus, otherwise its home feed (or the
102
+ * site's sign-in) opens in a new pane beside the focused one. Shift/Ctrl-click opens a new tab
103
+ * instead. Everything else ("Open in new tab", "Use for new tabs", sign out, remove) is in the
104
+ * row's "…" menu. The button shows the focused pane's account.
105
+ */
106
+ export function AccountSwitcher() {
107
+ const t = useT();
108
+ const settings = useProfiles();
109
+ usePaneTick();
110
+ const [open, setOpen] = useState(false);
111
+ const [rowMenu, setRowMenu] = useState(null);
112
+ const [error, setError] = useState('');
113
+ const [anchor, setAnchor] = useState({ top: 44, right: 12 });
114
+ const button = useRef(null);
115
+ const menu = useRef(null);
116
+ const panes = paneInfos();
117
+ const activeId = shell.api?.activePanel?.id;
118
+ const focused = focusedAccount(settings, panes, activeId);
119
+ const tabs = tabsByAccount(settings, panes);
120
+ const multi = settings.profiles.length > 1;
121
+ const { name: siteName, homeUrl, loginUrl, logoutUrl, isSiteUrl, accounts: rules } = site();
122
+ const handle = (profile) => `${rules.handlePrefix}${profile.account.handle}`;
123
+ useEffect(() => {
124
+ if (!open)
125
+ return;
126
+ // Native tab webviews would cover the menu.
127
+ setOverlay(1);
128
+ const onBlur = () => close();
129
+ // Escape while focus is outside the menu (a click on its padding); inside, onMenuKey handles it.
130
+ const onKey = (event) => { if (event.key === 'Escape' && !menu.current?.contains(event.target))
131
+ close(true); };
132
+ window.addEventListener('blur', onBlur);
133
+ window.addEventListener('keydown', onKey);
134
+ // Start on the focused pane's account.
135
+ // Two lookups: a selector list matches in document order, so it would always pick the first row.
136
+ requestAnimationFrame(() => (menu.current?.querySelector('.bt-acct-row.is-focused .bt-acct-main')
137
+ ?? menu.current?.querySelector('.bt-acct-main'))?.focus());
138
+ return () => { setOverlay(-1); window.removeEventListener('blur', onBlur); window.removeEventListener('keydown', onKey); };
139
+ }, [open]);
140
+ // The row menu takes focus when it opens; closing it returns focus to its row.
141
+ const lastRow = useRef(null);
142
+ useEffect(() => {
143
+ if (!open)
144
+ return;
145
+ if (rowMenu) {
146
+ lastRow.current = rowMenu.id;
147
+ requestAnimationFrame(() => menu.current?.querySelector(rowMenu.confirm ? '.bt-acct-confirm button' : '.bt-acct-sub button:not(:disabled)')?.focus());
148
+ }
149
+ else if (lastRow.current) {
150
+ const id = lastRow.current;
151
+ lastRow.current = null;
152
+ requestAnimationFrame(() => menu.current?.querySelector(`.bt-acct-row[data-profile="${id}"] .bt-acct-main`)?.focus());
153
+ }
154
+ }, [rowMenu, open]);
155
+ function close(refocus = false) {
156
+ setOpen(false);
157
+ setRowMenu(null);
158
+ setError('');
159
+ if (refocus)
160
+ button.current?.focus();
161
+ }
162
+ function toggle() {
163
+ const rect = button.current?.getBoundingClientRect();
164
+ if (rect)
165
+ setAnchor({ top: Math.round(rect.bottom + 6), right: Math.max(8, Math.round(window.innerWidth - rect.right)) });
166
+ setRowMenu(null);
167
+ setError('');
168
+ setOpen(value => !value);
169
+ }
170
+ async function run(action) {
171
+ setError('');
172
+ try {
173
+ await action();
174
+ return true;
175
+ }
176
+ catch (failure) {
177
+ setError(String(failure).replace(/^Error: /, ''));
178
+ return false;
179
+ }
180
+ }
181
+ /** The main click: focus or open beside; Shift/Ctrl (or "Open in new tab") forces a tab. */
182
+ function pick(profile, force = false) {
183
+ close();
184
+ shell.openAccount(profile, { force });
185
+ }
186
+ const onMainClick = (profile) => (event) => pick(profile, event.shiftKey || event.ctrlKey || event.metaKey);
187
+ function onMenuKey(event) {
188
+ const target = event.target;
189
+ const inSub = !!target.closest('.bt-acct-sub, .bt-acct-confirm');
190
+ if (event.key === 'Escape') {
191
+ event.preventDefault();
192
+ event.stopPropagation();
193
+ if (rowMenu)
194
+ setRowMenu(null);
195
+ else
196
+ close(true);
197
+ return;
198
+ }
199
+ if (event.key === 'Tab') {
200
+ event.preventDefault();
201
+ close(true);
202
+ return;
203
+ }
204
+ const scope = inSub ? target.closest('.bt-acct-sub, .bt-acct-confirm') : menu.current;
205
+ const items = Array.from(scope.querySelectorAll(inSub ? 'button:not(:disabled)' : '.bt-acct-main, .bt-acct-add, .bt-acct-settings'));
206
+ if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {
207
+ event.preventDefault();
208
+ items[moveFocus(items.indexOf(target), event.key, items.length)]?.focus();
209
+ return;
210
+ }
211
+ const row = target.closest('.bt-acct-row')?.dataset.profile;
212
+ if (!inSub && row && (event.key === 'ArrowRight' || event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey))) {
213
+ event.preventDefault();
214
+ setRowMenu({ id: row });
215
+ return;
216
+ }
217
+ if (inSub && event.key === 'ArrowLeft') {
218
+ event.preventDefault();
219
+ setRowMenu(null);
220
+ return;
221
+ }
222
+ // Keyboard Enter/Space clicks carry no modifiers: Shift/Ctrl+Enter forces a new tab here.
223
+ if (!inSub && row && event.key === 'Enter' && (event.shiftKey || event.ctrlKey || event.metaKey)) {
224
+ event.preventDefault();
225
+ pick(row, true);
226
+ }
227
+ }
228
+ const buttonLabel = t('wb.acct.buttonLabel', { name: accountName(focused) });
229
+ return _jsxs(_Fragment, { children: [_jsxs("button", { ref: button, className: "bt-profile-switcher", "aria-label": buttonLabel, title: multi ? t('wb.acct.buttonTitle', { pane: accountName(focused), tabs: accountName(tabProfile(settings, settings.active)) }) : accountName(focused), "aria-haspopup": "menu", "aria-expanded": open, onClick: toggle, children: [_jsx(AccountAvatar, { profile: focused, size: 22 }), _jsx("span", { className: "bt-profile-switcher-name", children: focused.account ? handle(focused) : accountLabel(focused).title }), _jsx(Icon, { name: "chevron", className: "bt-profile-switcher-chevron" })] }), open && createPortal(_jsx("div", { className: "bt-menu-backdrop", onMouseDown: () => close(), onContextMenu: event => { event.preventDefault(); close(); }, children: _jsxs("div", { ref: menu, className: "bt-menu bt-acct-menu bt-pop bt-pop--right", role: "menu", "aria-label": t('wb.acct.title'), style: { top: anchor.top, right: anchor.right }, onMouseDown: event => event.stopPropagation(), onKeyDown: onMenuKey, children: [_jsxs("div", { className: "bt-acct-head", role: "presentation", children: [_jsx("strong", { children: t('wb.acct.title') }), _jsxs("span", { children: [t('wb.acct.headBefore'), " ", _jsx("kbd", { className: "bt-kbd", children: t('wb.acct.shift') }), " ", t('wb.acct.headAfter')] })] }), settings.profiles.map(profile => {
230
+ const label = accountLabel(profile);
231
+ const count = tabs.get(profile.id)?.length ?? 0;
232
+ const isFocused = profile.id === focused.id;
233
+ const isDefault = profile.id === settings.active;
234
+ const action = accountAction(settings, panes, activeId, profile.id, { homeUrl, loginUrl, isSiteUrl });
235
+ const hint = action.type === 'focus' ? (action.paneId === activeId ? t('wb.acct.thisPane') : t('wb.acct.goToPane')) : label.state === 'signed-in' ? t('wb.acct.openBeside') : t('wb.acct.signInBeside');
236
+ const status = label.state === 'signed-in' ? handle(profile) : label.state === 'signed-out' ? t('wb.acct.signedOut', { handle: handle(profile) }) : label.detail;
237
+ const sub = rowMenu?.id === profile.id ? rowMenu : null;
238
+ return _jsxs("div", { className: `bt-acct-row${isFocused ? ' is-focused' : ''}${sub ? ' is-open' : ''}`, "data-profile": profile.id, role: "none", onContextMenu: event => { event.preventDefault(); event.stopPropagation(); setRowMenu({ id: profile.id }); }, children: [_jsxs("div", { className: "bt-acct-line", children: [_jsxs("button", { role: "menuitem", className: "bt-acct-main", "aria-current": isFocused ? 'true' : undefined, "aria-label": label.state === 'signed-in' ? t('wb.acct.rowLabel', { name: accountName(profile), hint }) : label.state === 'new' ? t('wb.acct.rowLabelNew', { name: accountName(profile), hint }) : t('wb.acct.rowLabelOut', { name: accountName(profile), hint }), onClick: onMainClick(profile.id), children: [_jsx("span", { className: `bt-acct-avatar is-${label.state}`, children: _jsx(AccountAvatar, { profile: profile, size: 32 }) }), _jsxs("span", { className: "bt-acct-text", children: [_jsxs("span", { className: "bt-acct-name", children: [label.title, isDefault && multi && _jsx("span", { className: "bt-acct-badge", title: t('wb.acct.newTabsTitle'), children: t('wb.acct.newTabs') })] }), _jsxs("span", { className: `bt-acct-meta is-${label.state}`, children: [status, count > 0 && _jsxs("span", { className: "bt-acct-count", children: [" \u00B7 ", t('wb.ws.tabs', { count })] })] })] }), _jsxs("span", { className: "bt-acct-hint", "aria-hidden": "true", children: [hint, action.type === 'open' && _jsx(Icon, { name: "split" })] })] }), _jsx("button", { className: "bt-acct-more", tabIndex: -1, "aria-haspopup": "menu", "aria-expanded": !!sub, "aria-label": t('wb.acct.moreFor', { name: accountName(profile) }), title: t('wb.acct.more'), onClick: () => setRowMenu(sub ? null : { id: profile.id }), children: _jsxs("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("circle", { cx: "6", cy: "12", r: "1.6" }), _jsx("circle", { cx: "12", cy: "12", r: "1.6" }), _jsx("circle", { cx: "18", cy: "12", r: "1.6" })] }) })] }), sub && !sub.confirm && _jsxs("div", { className: "bt-acct-sub", role: "menu", "aria-label": t('wb.acct.actions', { name: accountName(profile) }), children: [_jsxs("button", { role: "menuitem", "data-action": "tab", onClick: () => pick(profile.id, true), children: [_jsx(Icon, { name: "plus" }), _jsx("span", { className: "bt-menu-label", children: t('wb.acct.openNewTab') }), _jsx("span", { className: "bt-menu-keys", children: t('wb.acct.shiftClick') })] }), _jsxs("button", { role: "menuitemcheckbox", "aria-checked": isDefault, "data-action": "default", disabled: isDefault, onClick: () => void run(() => saveProfiles(setDefaultAccount(settings, profile.id))).then(ok => ok && setRowMenu(null)), children: [_jsx(Icon, { name: isDefault ? 'check' : 'sparkle' }), _jsx("span", { className: "bt-menu-label", children: isDefault ? t('wb.acct.newTabsOpenHere') : t('wb.acct.useForNewTabs') })] }), label.state === 'signed-in'
239
+ ? _jsxs("button", { role: "menuitem", "data-action": "signout", title: t('wb.acct.signOutTitle', { site: siteName }), onClick: () => { close(); shell.openAccount(profile.id, { url: logoutUrl }); }, children: [_jsx(Icon, { name: "external" }), _jsx("span", { className: "bt-menu-label", children: t('wb.acct.signOut', { site: siteName }) })] })
240
+ : _jsxs("button", { role: "menuitem", "data-action": "signin", onClick: () => { close(); signIn(profile.id); }, children: [_jsx(Icon, { name: "user" }), _jsx("span", { className: "bt-menu-label", children: t('wb.acct.signIn', { site: siteName }) })] }), profile.id !== DEFAULT_PROFILE && _jsxs("button", { role: "menuitem", "data-action": "remove", className: "bt-acct-danger", onClick: () => setRowMenu({ id: profile.id, confirm: true }), children: [_jsx(Icon, { name: "trash" }), _jsx("span", { className: "bt-menu-label", children: t('wb.acct.remove') })] })] }), sub?.confirm && _jsxs("div", { className: "bt-acct-confirm", role: "alertdialog", "aria-label": t('wb.common.removeItem', { item: label.title }), children: [_jsx("span", { children: t('wb.acct.removeConfirm', { name: accountName(profile), tabs: count }) }), _jsxs("div", { children: [_jsx("button", { className: "bt-acct-remove", onClick: () => void run(() => removeAccount(settings, profile.id)).then(ok => ok && setRowMenu(null)), children: t('wb.common.remove') }), _jsx("button", { className: "bt-acct-cancel", onClick: () => setRowMenu(null), children: t('wb.common.cancel') })] })] })] }, profile.id);
241
+ }), _jsx("hr", {}), _jsxs("button", { role: "menuitem", className: "bt-acct-add", onClick: () => void run(() => addAccount(settings)).then(ok => ok && close()), children: [_jsx("span", { className: "bt-acct-add-icon", children: _jsx(Icon, { name: "plus" }) }), _jsxs("span", { className: "bt-acct-text", children: [_jsx("span", { className: "bt-acct-name", children: t('wb.acct.add') }), _jsx("span", { className: "bt-acct-meta", children: t('wb.acct.addHint', { site: siteName }) })] })] }), _jsx("hr", {}), _jsxs("button", { role: "menuitem", className: "bt-acct-settings", "aria-haspopup": "menu", onClick: event => { const keyboard = event.detail === 0; close(); openAppMenu({ keyboard }); }, children: [_jsx(Icon, { name: "settings" }), _jsx("span", { className: "bt-menu-label", children: menuText('accountsRow') }), _jsx("span", { className: "bt-menu-keys", children: APP_MENU_KEYS })] }), error && _jsx("div", { className: "bt-acct-error", role: "alert", children: error })] }) }), document.body)] });
242
+ }
243
+ //# sourceMappingURL=AccountSwitcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccountSwitcher.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/AccountSwitcher.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAgF,MAAM,OAAO,CAAC;AAClI,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,YAAY,IAAI,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAsC,MAAM,oBAAoB,CAAC;AACtJ,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClI,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAe,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAClF,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,uBAAuB,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,gGAAgG;AAChG,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,OAAO,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC;AAChG,CAAC;AAED,qGAAqG;AACrG,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAqB;IACtD,IAAI,CAAC,OAAO,EAAE,CAAC;QAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC5C,WAAW,CAAC,MAAM,MAAM,CAAkB,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAqC,EAAE,EAAE,CAChF,eAAM,SAAS,EAAC,gBAAgB,EAAC,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,iBAAe,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;AAExH,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,aAAa,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,MAAM,CAAC,OAAe;IACpC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,oGAAoG;AACpG,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAyB;IACxD,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAyB,EAAE,EAAU;IACvE,IAAI,EAAE,KAAK,eAAe;QAAE,OAAO;IACnC,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IAChE,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IAC9D,4DAA4D;IAC5D,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAyD,CAAC;QAC/E,IAAI,MAAM,EAAE,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,EAAE;YAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IAClH,CAAC;IACD,uGAAuG;IACvG,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC9B,WAAW,GAAG,IAAI,CAAC;QACnB,KAAK,MAAM,MAAM,IAAI,IAAI;YAAE,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtD,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,KAAK,EAAE,CAAC,EAAE,CAAC;IACpF,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO;QAAE,IAAI,OAAO,CAAC,OAAO,KAAK,EAAE,EAAE,CAAC;YAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAAC,WAAW,GAAG,IAAI,CAAC;QAAC,CAAC;IAChI,IAAI,WAAW;QAAE,SAAS,EAAE,CAAC;IAC7B,8FAA8F;IAC9F,2FAA2F;IAC3F,MAAM,SAAS,EAAE,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,OAAO,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,oCAAoC,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACjG,MAAM,OAAO,CAAC;IAChB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAsC,EAAE,EAAE,CACrF,KAAC,MAAM,IAAC,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC;AAE/G,8CAA8C;AAC9C,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACjI,CAAC;AAID;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,WAAW,EAAE,CAAC;IACd,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAiB,IAAI,CAAC,CAAC;IAC7D,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAiC,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC;IAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3C,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;IAC5F,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,OAAO,CAAC,OAAQ,CAAC,MAAM,EAAE,CAAC;IAEvF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,4CAA4C;QAC5C,UAAU,CAAC,CAAC,CAAC,CAAC;QACd,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;QAC7B,iGAAiG;QACjG,MAAM,KAAK,GAAG,CAAC,KAAoB,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAc,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtI,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxC,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC1C,uCAAuC;QACvC,iGAAiG;QACjG,qBAAqB,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAc,uCAAuC,CAAC;eACzG,IAAI,CAAC,OAAO,EAAE,aAAa,CAAc,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,OAAO,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7H,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,+EAA+E;IAC/E,MAAM,OAAO,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;YAC7B,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAc,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,oCAAoC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACrK,CAAC;aAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;YAC3B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;YACvB,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAc,8BAA8B,EAAE,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACrI,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAEpB,SAAS,KAAK,CAAC,OAAO,GAAG,KAAK;QAC5B,OAAO,CAAC,KAAK,CAAC,CAAC;QAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC/C,IAAI,OAAO;YAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;IACvC,CAAC;IACD,SAAS,MAAM;QACb,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC;QACrD,IAAI,IAAI;YAAE,SAAS,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1H,UAAU,CAAC,IAAI,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,UAAU,GAAG,CAAC,MAA8B;QAC/C,QAAQ,CAAC,EAAE,CAAC,CAAC;QACb,IAAI,CAAC;YAAC,MAAM,MAAM,EAAE,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QACpC,OAAO,OAAO,EAAE,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IACtF,CAAC;IAED,4FAA4F;IAC5F,SAAS,IAAI,CAAC,OAAe,EAAE,KAAK,GAAG,KAAK;QAC1C,KAAK,EAAE,CAAC;QACR,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,CAAC,KAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAErI,SAAS,SAAS,CAAC,KAAyC;QAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB,CAAC;QAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;QACjE,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC3B,KAAK,CAAC,cAAc,EAAE,CAAC;YAAC,KAAK,CAAC,eAAe,EAAE,CAAC;YAChD,IAAI,OAAO;gBAAE,UAAU,CAAC,IAAI,CAAC,CAAC;;gBAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QACzE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,gCAAgC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAQ,CAAC;QACxF,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAc,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC;QAClJ,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAChE,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;YAC1E,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAc,cAAc,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;QACzE,IAAI,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,YAAY,IAAI,KAAK,CAAC,GAAG,KAAK,aAAa,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YAC5H,KAAK,CAAC,cAAc,EAAE,CAAC;YAAC,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAAC,OAAO;QAC1D,CAAC;QACD,IAAI,KAAK,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;YAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC7F,0FAA0F;QAC1F,IAAI,CAAC,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;IAChJ,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7E,OAAO,8BACL,kBAAQ,GAAG,EAAE,MAAM,EAAE,SAAS,EAAC,qBAAqB,gBAAa,WAAW,EAC1E,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,mBAC1I,MAAM,mBAAgB,IAAI,EAAE,OAAO,EAAE,MAAM,aACzD,KAAC,aAAa,IAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAA,eAAM,SAAS,EAAC,0BAA0B,YAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,GAAQ,EAC/J,KAAC,IAAI,IAAC,IAAI,EAAC,SAAS,EAAC,SAAS,EAAC,6BAA6B,GAAE,IACvD,EACR,IAAI,IAAI,YAAY,CAAC,cAAK,SAAS,EAAC,kBAAkB,EAAC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,YAC9I,eAAK,GAAG,EAAE,IAAI,EAAE,SAAS,EAAC,2CAA2C,EAAC,IAAI,EAAC,MAAM,gBAAa,CAAC,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAC/J,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,SAAS,aACnE,eAAK,SAAS,EAAC,cAAc,EAAC,IAAI,EAAC,cAAc,aAC/C,2BAAS,CAAC,CAAC,eAAe,CAAC,GAAU,EACrC,2BAAO,CAAC,CAAC,oBAAoB,CAAC,OAAE,cAAK,SAAS,EAAC,QAAQ,YAAE,CAAC,CAAC,eAAe,CAAC,GAAO,OAAE,CAAC,CAAC,mBAAmB,CAAC,IAAQ,IAC9G,EACL,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;4BAC/B,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;4BACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;4BAChD,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC;4BAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,MAAM,CAAC;4BACjD,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;4BACtG,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC;4BACxM,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;4BACjK,MAAM,GAAG,GAAG,OAAO,EAAE,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;4BACxD,OAAO,eAAsB,SAAS,EAAE,cAAc,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,kBAAgB,OAAO,CAAC,EAAE,EAAE,IAAI,EAAC,MAAM,EACnJ,aAAa,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,aAC5G,eAAK,SAAS,EAAC,cAAc,aAC3B,kBAAQ,IAAI,EAAC,UAAU,EAAC,SAAS,EAAC,cAAc,kBAAe,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,gBAC/E,KAAK,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAC/P,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,aAChC,eAAM,SAAS,EAAE,qBAAqB,KAAK,CAAC,KAAK,EAAE,YAAE,KAAC,aAAa,IAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,GAAO,EACxG,gBAAM,SAAS,EAAC,cAAc,aAC5B,gBAAM,SAAS,EAAC,cAAc,aAAE,KAAK,CAAC,KAAK,EAAE,SAAS,IAAI,KAAK,IAAI,eAAM,SAAS,EAAC,eAAe,EAAC,KAAK,EAAE,CAAC,CAAC,sBAAsB,CAAC,YAAG,CAAC,CAAC,iBAAiB,CAAC,GAAQ,IAAQ,EAC1K,gBAAM,SAAS,EAAE,mBAAmB,KAAK,CAAC,KAAK,EAAE,aAAG,MAAM,EAAE,KAAK,GAAG,CAAC,IAAI,gBAAM,SAAS,EAAC,eAAe,yBAAK,CAAC,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,IAAQ,IAAQ,IAClJ,EACP,gBAAM,SAAS,EAAC,cAAc,iBAAa,MAAM,aAAE,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,GAAE,IAAQ,IACxG,EACT,iBAAQ,SAAS,EAAC,cAAc,EAAC,QAAQ,EAAE,CAAC,CAAC,mBAAgB,MAAM,mBAAgB,CAAC,CAAC,GAAG,gBAAc,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAClL,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,YAC1D,eAAK,OAAO,EAAC,WAAW,iBAAa,MAAM,aAAC,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,KAAK,GAAE,EAAA,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,KAAK,GAAE,EAAA,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,KAAK,GAAE,IAAM,GAC7I,IACL,EACL,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,eAAK,SAAS,EAAC,aAAa,EAAC,IAAI,EAAC,MAAM,gBAAa,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,aAC/H,kBAAQ,IAAI,EAAC,UAAU,iBAAa,KAAK,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,aAC7E,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,GAAE,EAAA,eAAM,SAAS,EAAC,eAAe,YAAE,CAAC,CAAC,oBAAoB,CAAC,GAAQ,EAAA,eAAM,SAAS,EAAC,cAAc,YAAE,CAAC,CAAC,oBAAoB,CAAC,GAAQ,IAAS,EAC7J,kBAAQ,IAAI,EAAC,kBAAkB,kBAAe,SAAS,iBAAc,SAAS,EAAC,QAAQ,EAAE,SAAS,EAChG,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,aACvH,KAAC,IAAI,IAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,EAAA,eAAM,SAAS,EAAC,eAAe,YAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,GAAQ,IAAS,EACtK,KAAK,CAAC,KAAK,KAAK,WAAW;gDAC1B,CAAC,CAAC,kBAAQ,IAAI,EAAC,UAAU,iBAAa,SAAS,EAAC,KAAK,EAAE,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,aAClL,KAAC,IAAI,IAAC,IAAI,EAAC,UAAU,GAAE,EAAA,eAAM,SAAS,EAAC,eAAe,YAAE,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAQ,IAAS;gDACnH,CAAC,CAAC,kBAAQ,IAAI,EAAC,UAAU,iBAAa,QAAQ,EAAC,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAC5F,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,GAAE,EAAA,eAAM,SAAS,EAAC,eAAe,YAAE,CAAC,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAQ,IAAS,EAC/G,OAAO,CAAC,EAAE,KAAK,eAAe,IAAI,kBAAQ,IAAI,EAAC,UAAU,iBAAa,QAAQ,EAAC,SAAS,EAAC,gBAAgB,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,aACrK,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,GAAE,EAAA,eAAM,SAAS,EAAC,eAAe,YAAE,CAAC,CAAC,gBAAgB,CAAC,GAAQ,IAAS,IACvF,EACL,GAAG,EAAE,OAAO,IAAI,eAAK,SAAS,EAAC,iBAAiB,EAAC,IAAI,EAAC,aAAa,gBAAa,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,aAC/H,yBAAO,CAAC,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,GAAQ,EACtF,0BACE,iBAAQ,SAAS,EAAC,gBAAgB,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,YAAG,CAAC,CAAC,kBAAkB,CAAC,GAAU,EAC1K,iBAAQ,SAAS,EAAC,gBAAgB,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,YAAG,CAAC,CAAC,kBAAkB,CAAC,GAAU,IAChG,IACF,KAtCS,OAAO,CAAC,EAAE,CAuCrB,CAAC;wBACT,CAAC,CAAC,EACF,cAAK,EACL,kBAAQ,IAAI,EAAC,UAAU,EAAC,SAAS,EAAC,aAAa,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,KAAK,EAAE,CAAC,aAC3H,eAAM,SAAS,EAAC,kBAAkB,YAAC,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,GAAE,GAAO,EAC7D,gBAAM,SAAS,EAAC,cAAc,aAAC,eAAM,SAAS,EAAC,cAAc,YAAE,CAAC,CAAC,aAAa,CAAC,GAAQ,EAAA,eAAM,SAAS,EAAC,cAAc,YAAE,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAQ,IAAO,IACvK,EACT,cAAK,EAEL,kBAAQ,IAAI,EAAC,UAAU,EAAC,SAAS,EAAC,kBAAkB,mBAAe,MAAM,EAAC,OAAO,EAAE,KAAK,CAAC,EAAE,GAAG,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,aACtK,KAAC,IAAI,IAAC,IAAI,EAAC,UAAU,GAAE,EAAA,eAAM,SAAS,EAAC,eAAe,YAAE,QAAQ,CAAC,aAAa,CAAC,GAAQ,EAAA,eAAM,SAAS,EAAC,cAAc,YAAE,aAAa,GAAQ,IACrI,EACR,KAAK,IAAI,cAAK,SAAS,EAAC,eAAe,EAAC,IAAI,EAAC,OAAO,YAAE,KAAK,GAAO,IAC/D,GACF,EAAE,QAAQ,CAAC,IAAI,CAAC,IACrB,CAAC;AACN,CAAC","sourcesContent":["import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent, type MouseEvent as ReactMouseEvent } from 'react';\nimport { createPortal } from 'react-dom';\nimport { DEFAULT_PROFILE, accountLabel as accountLabelCore, removeProfile, tabProfile, type Profile, type ProfileSettings } from '../profileModel.ts';\nimport { accountAction, addAccountProfile, focusedAccount, moveFocus, setDefaultAccount, tabsByAccount } from './accountModel.ts';\nimport { APP_MENU_KEYS, openAppMenu } from './AppMenu.tsx';\nimport { invoke } from './bridge.ts';\nimport { decks, forgetColumn, saveDecks } from './deckStore.ts';\nimport { usePaneTick, useProfiles, useT } from './hooks.ts';\nimport { t, tx } from './i18n.ts';\nimport { Avatar, Icon } from './icons.tsx';\nimport { menuText } from './menuModel.ts';\nimport { site } from './site.ts';\nimport { flushSync, paneInfos, setOverlay, setProfiles, shell } from './state.ts';\nimport { isTauri } from './windowBinding.ts';\nimport './accountSwitcher.css';\n\nexport { useProfiles } from './hooks.ts';\n\n/** What the switcher shows for a profile: the site login once seen, the profile name before. */\nexport function accountLabel(profile: Profile) {\n return accountLabelCore(profile, site().accounts, key => tx(key, undefined, '') || undefined);\n}\n\n/** Saves natively (Rust validates and owns the data directories); the preview keeps it in memory. */\nexport async function saveProfiles(next: ProfileSettings): Promise<void> {\n if (!isTauri) { setProfiles(next); return; }\n setProfiles(await invoke<ProfileSettings>('profiles_set', { settings: next }));\n}\n\nexport const ProfileDot = ({ color, title }: { color: string; title?: string }) =>\n <span className=\"bt-profile-dot\" style={{ background: color }} title={title} aria-hidden={title ? undefined : true}/>;\n\nexport function openTabs(profile: string) {\n return tabsByAccount(shell.profiles, paneInfos()).get(profile)?.length ?? 0;\n}\n\n/** The site's own sign-in page for that account, in a new pane beside the focused one. */\nexport function signIn(profile: string) {\n shell.openAccount(profile, { url: site().loginUrl });\n}\n\n/** \"Add account\": a fresh login (its own cookies and storage) whose sign-in opens in a new pane. */\nexport async function addAccount(settings: ProfileSettings): Promise<void> {\n const next = addAccountProfile(settings);\n await saveProfiles(next.settings);\n signIn(next.profile);\n}\n\n/**\n * Removes an account after the user confirmed: its tabs close first (native code refuses to delete\n * the data directory of a profile that still has a tab), then the list is saved and native code\n * deletes that login's data on this computer. Never called without the explicit confirm step.\n */\nexport async function removeAccount(settings: ProfileSettings, id: string): Promise<void> {\n if (id === DEFAULT_PROFILE) return;\n const tabs = tabsByAccount(settings, paneInfos()).get(id) ?? [];\n for (const tab of tabs) shell.api?.getPanel(tab)?.api.close();\n // Start pages of that account fall back to the default one.\n for (const panel of shell.api?.panels ?? []) {\n const params = panel.params as { kind?: string; profile?: string } | undefined;\n if (params?.kind === 'start' && params.profile === id) panel.api.updateParameters({ profile: DEFAULT_PROFILE });\n }\n // Deck columns of that account go too (each is a webview in its profile); a compose dock in it closes.\n let deckChanged = false;\n decks.list = decks.list.map(deck => {\n const gone = deck.columns.filter(column => column.profile === id);\n if (!gone.length) return deck;\n deckChanged = true;\n for (const column of gone) forgetColumn(column.tabId);\n return { ...deck, columns: deck.columns.filter(column => column.profile !== id) };\n });\n for (const [deckId, compose] of decks.compose) if (compose.profile === id) { decks.compose.delete(deckId); deckChanged = true; }\n if (deckChanged) saveDecks();\n // dockview drops closed panels from `api.panels` synchronously (checked in the harness, whose\n // profiles_set refuses like native code), so this sync no longer lists the account's tabs.\n await flushSync();\n try {\n await saveProfiles(removeProfile(settings, id));\n } catch (failure) {\n const message = String(failure);\n if (/PROFILE: close this profile's tabs/.test(message)) throw new Error(t('wb.acct.notRemoved'));\n throw failure;\n }\n}\n\nexport const AccountAvatar = ({ profile, size }: { profile: Profile; size: number }) =>\n <Avatar name={accountLabel(profile).title} color={profile.color} size={size} src={profile.account?.avatar}/>;\n\n/** \"Name (@handle)\" for titles and labels. */\nexport function accountName(profile: Profile): string {\n return `${accountLabel(profile).title}${profile.account ? ` (${site().accounts.handlePrefix}${profile.account.handle})` : ''}`;\n}\n\ntype RowMenu = { id: string; confirm?: boolean };\n\n/**\n * Titlebar account switcher. Every entry is a separate site login on this computer (its own\n * WebView data directory) that shows the account the site itself reports as signed in there.\n *\n * One click shows the account: a visible pane of it gets focus, otherwise its home feed (or the\n * site's sign-in) opens in a new pane beside the focused one. Shift/Ctrl-click opens a new tab\n * instead. Everything else (\"Open in new tab\", \"Use for new tabs\", sign out, remove) is in the\n * row's \"…\" menu. The button shows the focused pane's account.\n */\nexport function AccountSwitcher() {\n const t = useT();\n const settings = useProfiles();\n usePaneTick();\n const [open, setOpen] = useState(false);\n const [rowMenu, setRowMenu] = useState<RowMenu | null>(null);\n const [error, setError] = useState('');\n const [anchor, setAnchor] = useState<{ top: number; right: number }>({ top: 44, right: 12 });\n const button = useRef<HTMLButtonElement>(null);\n const menu = useRef<HTMLDivElement>(null);\n const panes = paneInfos();\n const activeId = shell.api?.activePanel?.id;\n const focused = focusedAccount(settings, panes, activeId);\n const tabs = tabsByAccount(settings, panes);\n const multi = settings.profiles.length > 1;\n const { name: siteName, homeUrl, loginUrl, logoutUrl, isSiteUrl, accounts: rules } = site();\n const handle = (profile: Profile) => `${rules.handlePrefix}${profile.account!.handle}`;\n\n useEffect(() => {\n if (!open) return;\n // Native tab webviews would cover the menu.\n setOverlay(1);\n const onBlur = () => close();\n // Escape while focus is outside the menu (a click on its padding); inside, onMenuKey handles it.\n const onKey = (event: KeyboardEvent) => { if (event.key === 'Escape' && !menu.current?.contains(event.target as Node)) close(true); };\n window.addEventListener('blur', onBlur);\n window.addEventListener('keydown', onKey);\n // Start on the focused pane's account.\n // Two lookups: a selector list matches in document order, so it would always pick the first row.\n requestAnimationFrame(() => (menu.current?.querySelector<HTMLElement>('.bt-acct-row.is-focused .bt-acct-main')\n ?? menu.current?.querySelector<HTMLElement>('.bt-acct-main'))?.focus());\n return () => { setOverlay(-1); window.removeEventListener('blur', onBlur); window.removeEventListener('keydown', onKey); };\n }, [open]);\n\n // The row menu takes focus when it opens; closing it returns focus to its row.\n const lastRow = useRef<string | null>(null);\n useEffect(() => {\n if (!open) return;\n if (rowMenu) {\n lastRow.current = rowMenu.id;\n requestAnimationFrame(() => menu.current?.querySelector<HTMLElement>(rowMenu.confirm ? '.bt-acct-confirm button' : '.bt-acct-sub button:not(:disabled)')?.focus());\n } else if (lastRow.current) {\n const id = lastRow.current;\n lastRow.current = null;\n requestAnimationFrame(() => menu.current?.querySelector<HTMLElement>(`.bt-acct-row[data-profile=\"${id}\"] .bt-acct-main`)?.focus());\n }\n }, [rowMenu, open]);\n\n function close(refocus = false) {\n setOpen(false); setRowMenu(null); setError('');\n if (refocus) button.current?.focus();\n }\n function toggle() {\n const rect = button.current?.getBoundingClientRect();\n if (rect) setAnchor({ top: Math.round(rect.bottom + 6), right: Math.max(8, Math.round(window.innerWidth - rect.right)) });\n setRowMenu(null); setError('');\n setOpen(value => !value);\n }\n\n async function run(action: () => Promise<unknown>) {\n setError('');\n try { await action(); return true; }\n catch (failure) { setError(String(failure).replace(/^Error: /, '')); return false; }\n }\n\n /** The main click: focus or open beside; Shift/Ctrl (or \"Open in new tab\") forces a tab. */\n function pick(profile: string, force = false) {\n close();\n shell.openAccount(profile, { force });\n }\n\n const onMainClick = (profile: string) => (event: ReactMouseEvent) => pick(profile, event.shiftKey || event.ctrlKey || event.metaKey);\n\n function onMenuKey(event: ReactKeyboardEvent<HTMLDivElement>) {\n const target = event.target as HTMLElement;\n const inSub = !!target.closest('.bt-acct-sub, .bt-acct-confirm');\n if (event.key === 'Escape') {\n event.preventDefault(); event.stopPropagation();\n if (rowMenu) setRowMenu(null); else close(true);\n return;\n }\n if (event.key === 'Tab') { event.preventDefault(); close(true); return; }\n const scope = inSub ? target.closest('.bt-acct-sub, .bt-acct-confirm')! : menu.current!;\n const items = Array.from(scope.querySelectorAll<HTMLElement>(inSub ? 'button:not(:disabled)' : '.bt-acct-main, .bt-acct-add, .bt-acct-settings'));\n if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {\n event.preventDefault();\n items[moveFocus(items.indexOf(target), event.key, items.length)]?.focus();\n return;\n }\n const row = target.closest<HTMLElement>('.bt-acct-row')?.dataset.profile;\n if (!inSub && row && (event.key === 'ArrowRight' || event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey))) {\n event.preventDefault(); setRowMenu({ id: row }); return;\n }\n if (inSub && event.key === 'ArrowLeft') { event.preventDefault(); setRowMenu(null); return; }\n // Keyboard Enter/Space clicks carry no modifiers: Shift/Ctrl+Enter forces a new tab here.\n if (!inSub && row && event.key === 'Enter' && (event.shiftKey || event.ctrlKey || event.metaKey)) { event.preventDefault(); pick(row, true); }\n }\n\n const buttonLabel = t('wb.acct.buttonLabel', { name: accountName(focused) });\n return <>\n <button ref={button} className=\"bt-profile-switcher\" aria-label={buttonLabel}\n title={multi ? t('wb.acct.buttonTitle', { pane: accountName(focused), tabs: accountName(tabProfile(settings, settings.active)) }) : accountName(focused)}\n aria-haspopup=\"menu\" aria-expanded={open} onClick={toggle}>\n <AccountAvatar profile={focused} size={22}/><span className=\"bt-profile-switcher-name\">{focused.account ? handle(focused) : accountLabel(focused).title}</span>\n <Icon name=\"chevron\" className=\"bt-profile-switcher-chevron\"/>\n </button>\n {open && createPortal(<div className=\"bt-menu-backdrop\" onMouseDown={() => close()} onContextMenu={event => { event.preventDefault(); close(); }}>\n <div ref={menu} className=\"bt-menu bt-acct-menu bt-pop bt-pop--right\" role=\"menu\" aria-label={t('wb.acct.title')} style={{ top: anchor.top, right: anchor.right }}\n onMouseDown={event => event.stopPropagation()} onKeyDown={onMenuKey}>\n <div className=\"bt-acct-head\" role=\"presentation\">\n <strong>{t('wb.acct.title')}</strong>\n <span>{t('wb.acct.headBefore')} <kbd className=\"bt-kbd\">{t('wb.acct.shift')}</kbd> {t('wb.acct.headAfter')}</span>\n </div>\n {settings.profiles.map(profile => {\n const label = accountLabel(profile);\n const count = tabs.get(profile.id)?.length ?? 0;\n const isFocused = profile.id === focused.id;\n const isDefault = profile.id === settings.active;\n const action = accountAction(settings, panes, activeId, profile.id, { homeUrl, loginUrl, isSiteUrl });\n const hint = action.type === 'focus' ? (action.paneId === activeId ? t('wb.acct.thisPane') : t('wb.acct.goToPane')) : label.state === 'signed-in' ? t('wb.acct.openBeside') : t('wb.acct.signInBeside');\n const status = label.state === 'signed-in' ? handle(profile) : label.state === 'signed-out' ? t('wb.acct.signedOut', { handle: handle(profile) }) : label.detail;\n const sub = rowMenu?.id === profile.id ? rowMenu : null;\n return <div key={profile.id} className={`bt-acct-row${isFocused ? ' is-focused' : ''}${sub ? ' is-open' : ''}`} data-profile={profile.id} role=\"none\"\n onContextMenu={event => { event.preventDefault(); event.stopPropagation(); setRowMenu({ id: profile.id }); }}>\n <div className=\"bt-acct-line\">\n <button role=\"menuitem\" className=\"bt-acct-main\" aria-current={isFocused ? 'true' : undefined}\n aria-label={label.state === 'signed-in' ? t('wb.acct.rowLabel', { name: accountName(profile), hint }) : label.state === 'new' ? t('wb.acct.rowLabelNew', { name: accountName(profile), hint }) : t('wb.acct.rowLabelOut', { name: accountName(profile), hint })}\n onClick={onMainClick(profile.id)}>\n <span className={`bt-acct-avatar is-${label.state}`}><AccountAvatar profile={profile} size={32}/></span>\n <span className=\"bt-acct-text\">\n <span className=\"bt-acct-name\">{label.title}{isDefault && multi && <span className=\"bt-acct-badge\" title={t('wb.acct.newTabsTitle')}>{t('wb.acct.newTabs')}</span>}</span>\n <span className={`bt-acct-meta is-${label.state}`}>{status}{count > 0 && <span className=\"bt-acct-count\"> · {t('wb.ws.tabs', { count })}</span>}</span>\n </span>\n <span className=\"bt-acct-hint\" aria-hidden=\"true\">{hint}{action.type === 'open' && <Icon name=\"split\"/>}</span>\n </button>\n <button className=\"bt-acct-more\" tabIndex={-1} aria-haspopup=\"menu\" aria-expanded={!!sub} aria-label={t('wb.acct.moreFor', { name: accountName(profile) })} title={t('wb.acct.more')}\n onClick={() => setRowMenu(sub ? null : { id: profile.id })}>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle cx=\"6\" cy=\"12\" r=\"1.6\"/><circle cx=\"12\" cy=\"12\" r=\"1.6\"/><circle cx=\"18\" cy=\"12\" r=\"1.6\"/></svg>\n </button>\n </div>\n {sub && !sub.confirm && <div className=\"bt-acct-sub\" role=\"menu\" aria-label={t('wb.acct.actions', { name: accountName(profile) })}>\n <button role=\"menuitem\" data-action=\"tab\" onClick={() => pick(profile.id, true)}>\n <Icon name=\"plus\"/><span className=\"bt-menu-label\">{t('wb.acct.openNewTab')}</span><span className=\"bt-menu-keys\">{t('wb.acct.shiftClick')}</span></button>\n <button role=\"menuitemcheckbox\" aria-checked={isDefault} data-action=\"default\" disabled={isDefault}\n onClick={() => void run(() => saveProfiles(setDefaultAccount(settings, profile.id))).then(ok => ok && setRowMenu(null))}>\n <Icon name={isDefault ? 'check' : 'sparkle'}/><span className=\"bt-menu-label\">{isDefault ? t('wb.acct.newTabsOpenHere') : t('wb.acct.useForNewTabs')}</span></button>\n {label.state === 'signed-in'\n ? <button role=\"menuitem\" data-action=\"signout\" title={t('wb.acct.signOutTitle', { site: siteName })} onClick={() => { close(); shell.openAccount(profile.id, { url: logoutUrl }); }}>\n <Icon name=\"external\"/><span className=\"bt-menu-label\">{t('wb.acct.signOut', { site: siteName })}</span></button>\n : <button role=\"menuitem\" data-action=\"signin\" onClick={() => { close(); signIn(profile.id); }}>\n <Icon name=\"user\"/><span className=\"bt-menu-label\">{t('wb.acct.signIn', { site: siteName })}</span></button>}\n {profile.id !== DEFAULT_PROFILE && <button role=\"menuitem\" data-action=\"remove\" className=\"bt-acct-danger\" onClick={() => setRowMenu({ id: profile.id, confirm: true })}>\n <Icon name=\"trash\"/><span className=\"bt-menu-label\">{t('wb.acct.remove')}</span></button>}\n </div>}\n {sub?.confirm && <div className=\"bt-acct-confirm\" role=\"alertdialog\" aria-label={t('wb.common.removeItem', { item: label.title })}>\n <span>{t('wb.acct.removeConfirm', { name: accountName(profile), tabs: count })}</span>\n <div>\n <button className=\"bt-acct-remove\" onClick={() => void run(() => removeAccount(settings, profile.id)).then(ok => ok && setRowMenu(null))}>{t('wb.common.remove')}</button>\n <button className=\"bt-acct-cancel\" onClick={() => setRowMenu(null)}>{t('wb.common.cancel')}</button>\n </div>\n </div>}\n </div>;\n })}\n <hr/>\n <button role=\"menuitem\" className=\"bt-acct-add\" onClick={() => void run(() => addAccount(settings)).then(ok => ok && close())}>\n <span className=\"bt-acct-add-icon\"><Icon name=\"plus\"/></span>\n <span className=\"bt-acct-text\"><span className=\"bt-acct-name\">{t('wb.acct.add')}</span><span className=\"bt-acct-meta\">{t('wb.acct.addHint', { site: siteName })}</span></span>\n </button>\n <hr/>\n {/* Settings are looked for where the account name is: the way to the app menu. */}\n <button role=\"menuitem\" className=\"bt-acct-settings\" aria-haspopup=\"menu\" onClick={event => { const keyboard = event.detail === 0; close(); openAppMenu({ keyboard }); }}>\n <Icon name=\"settings\"/><span className=\"bt-menu-label\">{menuText('accountsRow')}</span><span className=\"bt-menu-keys\">{APP_MENU_KEYS}</span>\n </button>\n {error && <div className=\"bt-acct-error\" role=\"alert\">{error}</div>}\n </div>\n </div>, document.body)}\n </>;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { type Deck, type DeckColumn } from './deckStore.ts';
2
+ type Input = Pick<DeckColumn, 'profile' | 'source'>;
3
+ export declare function AddColumnDialog({ deck, onClose, onAdd }: {
4
+ deck: Deck;
5
+ onClose(): void;
6
+ onAdd(input: Input): void;
7
+ }): import("react").ReactPortal;
8
+ export {};
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // "Add column": pick what the column shows (the site's column kinds: `site.deck.kinds`), which
3
+ // account it runs in and, for kinds that take one, the value. The shell rises above the tab
4
+ // webviews (or hides them) while it is open, so it draws above them.
5
+ import { useEffect, useRef, useState } from 'react';
6
+ import { createPortal } from 'react-dom';
7
+ import { tabProfile } from "../profileModel.js";
8
+ import { AccountAvatar, accountLabel } from "./AccountSwitcher.js";
9
+ import { decks } from "./deckStore.js";
10
+ import { useProfiles, useT } from "./hooks.js";
11
+ import { Icon } from "./icons.js";
12
+ import { site } from "./site.js";
13
+ import { setOverlay } from "./state.js";
14
+ export function AddColumnDialog({ deck, onClose, onAdd }) {
15
+ const t = useT();
16
+ const profiles = useProfiles();
17
+ const spec = site().deck;
18
+ const types = spec.kinds;
19
+ const focused = deck.columns.find(c => c.id === decks.focus.get(deck.id));
20
+ const [kind, setKind] = useState(types[0]?.kind ?? '');
21
+ const [profile, setProfile] = useState(tabProfile(profiles, focused?.profile ?? profiles.active).id);
22
+ const [value, setValue] = useState('');
23
+ const [caret, setCaret] = useState(0);
24
+ const field = useRef(null);
25
+ const dialog = useRef(null);
26
+ const type = types.find(item => item.kind === kind);
27
+ const parsed = type.value ? spec.parseValue(kind, value) : '';
28
+ const valid = parsed !== null && (!type.value || parsed !== '') && !!spec.urlFor({ kind, ...(parsed ? { value: parsed } : {}) });
29
+ const completer = spec.completer?.(kind) ?? null;
30
+ const chips = completer ? completer.suggest(value, caret, 6) : [];
31
+ const handlePrefix = site().accounts.handlePrefix;
32
+ useEffect(() => {
33
+ setOverlay(1);
34
+ const onBlur = () => onClose();
35
+ window.addEventListener('blur', onBlur);
36
+ dialog.current?.querySelector('[aria-checked="true"]')?.focus();
37
+ return () => { setOverlay(-1); window.removeEventListener('blur', onBlur); };
38
+ }, []);
39
+ useEffect(() => { if (type.value)
40
+ requestAnimationFrame(() => field.current?.focus()); }, [kind]);
41
+ const submit = () => {
42
+ if (!valid) {
43
+ field.current?.focus();
44
+ return;
45
+ }
46
+ onAdd({ profile, source: parsed ? { kind, value: parsed } : { kind } });
47
+ };
48
+ const onKey = (event) => {
49
+ if (event.key === 'Escape') {
50
+ event.preventDefault();
51
+ onClose();
52
+ }
53
+ else if (event.key === 'Enter' && !event.target.matches('button')) {
54
+ event.preventDefault();
55
+ submit();
56
+ }
57
+ else if (['ArrowRight', 'ArrowLeft', 'ArrowDown', 'ArrowUp'].includes(event.key) && event.target.getAttribute('role') === 'radio'
58
+ && event.target.closest('.bt-addcol-types')) {
59
+ event.preventDefault();
60
+ const index = types.findIndex(item => item.kind === kind);
61
+ const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : event.key === 'ArrowDown' ? 4 : -4;
62
+ const next = types[(index + step + types.length) % types.length];
63
+ setKind(next.kind);
64
+ requestAnimationFrame(() => dialog.current?.querySelector(`[data-kind="${next.kind}"]`)?.focus());
65
+ }
66
+ };
67
+ const acceptChip = (insert) => {
68
+ if (!completer)
69
+ return;
70
+ const next = completer.apply(value, caret, insert);
71
+ setValue(next.text);
72
+ setCaret(next.caret);
73
+ requestAnimationFrame(() => { field.current?.focus(); field.current?.setSelectionRange(next.caret, next.caret); });
74
+ };
75
+ return createPortal(_jsx("div", { className: "bt-palette-backdrop bt-addcol-backdrop", onMouseDown: onClose, children: _jsxs("div", { ref: dialog, className: "bt-palette bt-addcol bt-pop", role: "dialog", "aria-modal": "true", "aria-labelledby": "bt-addcol-title", onMouseDown: event => event.stopPropagation(), onKeyDown: onKey, children: [_jsxs("header", { className: "bt-addcol-head", children: [_jsx("h2", { id: "bt-addcol-title", children: t('wb.deck.addColumn') }), _jsx("span", { children: t('wb.addcol.to', { deck: deck.name }) }), _jsx("button", { className: "bt-icon", "aria-label": t('wb.common.close'), onClick: onClose, children: _jsx(Icon, { name: "close" }) })] }), _jsx("div", { className: "bt-addcol-types", role: "radiogroup", "aria-label": t('wb.addcol.type'), children: types.map(item => _jsxs("button", { "data-kind": item.kind, role: "radio", "aria-checked": item.kind === kind, tabIndex: item.kind === kind ? 0 : -1, className: `bt-addcol-type${item.kind === kind ? ' is-on' : ''}`, onClick: () => setKind(item.kind), onDoubleClick: () => { if (!item.value)
76
+ onAdd({ profile, source: { kind: item.kind } }); }, children: [_jsx("span", { className: "bt-addcol-icon", children: _jsx(Icon, { name: item.icon }) }), _jsx("strong", { children: item.label }), _jsx("small", { children: item.hint })] }, item.kind)) }), type.value && _jsxs("div", { className: "bt-addcol-value", children: [_jsx("label", { htmlFor: "bt-addcol-field", children: type.value.label }), _jsxs("div", { className: `bt-addcol-field${value && parsed === null ? ' is-bad' : ''}`, children: [_jsx(Icon, { name: type.icon }), _jsx("input", { id: "bt-addcol-field", ref: field, spellCheck: false, autoComplete: "off", placeholder: type.value.placeholder, value: value, onChange: event => { setValue(event.target.value); setCaret(event.target.selectionStart ?? event.target.value.length); }, onSelect: () => setCaret(field.current?.selectionStart ?? value.length), onKeyDown: event => { if (event.key === 'Tab' && !event.shiftKey && chips[0]) {
77
+ event.preventDefault();
78
+ acceptChip(chips[0].insert);
79
+ } } })] }), chips.length > 0 && _jsx("div", { className: "bt-addcol-chips", role: "listbox", "aria-label": completer?.label(), children: chips.map((chip, index) => _jsx("button", { type: "button", role: "option", "aria-selected": index === 0, title: `${chip.hint}${index === 0 ? ` (${t('wb.web.tabKey')})` : ''}`, onMouseDown: event => event.preventDefault(), onClick: () => acceptChip(chip.insert), children: chip.label }, chip.insert)) }), value && parsed === null && _jsx("p", { className: "bt-addcol-error", role: "alert", children: spec.invalid(kind) })] }), _jsxs("div", { className: "bt-addcol-accounts", children: [_jsx("span", { className: "bt-addcol-label", children: t('wb.addcol.account') }), _jsx("div", { role: "radiogroup", "aria-label": t('wb.addcol.account'), children: profiles.profiles.map(p => _jsxs("button", { role: "radio", "aria-checked": p.id === profile, className: `bt-addcol-account${p.id === profile ? ' is-on' : ''}`, onClick: () => setProfile(p.id), style: { ['--bt-col-account']: p.color }, children: [_jsx(AccountAvatar, { profile: p, size: 22 }), _jsx("span", { children: p.account ? `${handlePrefix}${p.account.handle}` : accountLabel(p).title }), p.account && !p.account.signedIn && _jsx("em", { children: t('wb.addcol.signedOut') })] }, p.id)) })] }), _jsxs("footer", { className: "bt-addcol-foot", children: [_jsxs("span", { children: [_jsx("span", { className: "bt-kbd", children: "\u21B5" }), " ", t('wb.addcol.add')] }), _jsxs("span", { children: [_jsx("span", { className: "bt-kbd", children: "Esc" }), " ", t('wb.addcol.close')] }), _jsx("span", { className: "bt-palette-foot-end" }), _jsx("button", { className: "bt-deck-secondary", onClick: onClose, children: t('wb.common.cancel') }), _jsxs("button", { className: "bt-deck-primary", disabled: !valid, onClick: submit, children: [_jsx(Icon, { name: "plus" }), t('wb.addcol.submit')] })] })] }) }), document.body);
80
+ }
81
+ //# sourceMappingURL=AddColumnDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddColumnDialog.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/AddColumnDialog.tsx"],"names":[],"mappings":"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","sourcesContent":["// \"Add column\": pick what the column shows (the site's column kinds: `site.deck.kinds`), which\n// account it runs in and, for kinds that take one, the value. The shell rises above the tab\n// webviews (or hides them) while it is open, so it draws above them.\n\nimport { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent } from 'react';\nimport { createPortal } from 'react-dom';\nimport { tabProfile } from '../profileModel.ts';\nimport { AccountAvatar, accountLabel } from './AccountSwitcher.tsx';\nimport { decks, type Deck, type DeckColumn } from './deckStore.ts';\nimport { useProfiles, useT } from './hooks.ts';\nimport { Icon } from './icons.tsx';\nimport { site, type DeckSite } from './site.ts';\nimport { setOverlay } from './state.ts';\n\ntype Input = Pick<DeckColumn, 'profile' | 'source'>;\n\nexport function AddColumnDialog({ deck, onClose, onAdd }: { deck: Deck; onClose(): void; onAdd(input: Input): void }) {\n const t = useT();\n const profiles = useProfiles();\n const spec = site().deck as DeckSite;\n const types = spec.kinds;\n const focused = deck.columns.find(c => c.id === decks.focus.get(deck.id));\n const [kind, setKind] = useState<string>(types[0]?.kind ?? '');\n const [profile, setProfile] = useState(tabProfile(profiles, focused?.profile ?? profiles.active).id);\n const [value, setValue] = useState('');\n const [caret, setCaret] = useState(0);\n const field = useRef<HTMLInputElement>(null);\n const dialog = useRef<HTMLDivElement>(null);\n const type = types.find(item => item.kind === kind)!;\n const parsed = type.value ? spec.parseValue(kind, value) : '';\n const valid = parsed !== null && (!type.value || parsed !== '') && !!spec.urlFor({ kind, ...(parsed ? { value: parsed } : {}) });\n const completer = spec.completer?.(kind) ?? null;\n const chips = completer ? completer.suggest(value, caret, 6) : [];\n const handlePrefix = site().accounts.handlePrefix;\n\n useEffect(() => {\n setOverlay(1);\n const onBlur = () => onClose();\n window.addEventListener('blur', onBlur);\n (dialog.current?.querySelector('[aria-checked=\"true\"]') as HTMLElement | null)?.focus();\n return () => { setOverlay(-1); window.removeEventListener('blur', onBlur); };\n }, []);\n useEffect(() => { if (type.value) requestAnimationFrame(() => field.current?.focus()); }, [kind]);\n\n const submit = () => {\n if (!valid) { field.current?.focus(); return; }\n onAdd({ profile, source: parsed ? { kind, value: parsed } : { kind } });\n };\n const onKey = (event: ReactKeyboardEvent) => {\n if (event.key === 'Escape') { event.preventDefault(); onClose(); }\n else if (event.key === 'Enter' && !(event.target as HTMLElement).matches('button')) { event.preventDefault(); submit(); }\n else if (['ArrowRight', 'ArrowLeft', 'ArrowDown', 'ArrowUp'].includes(event.key) && (event.target as HTMLElement).getAttribute('role') === 'radio'\n && (event.target as HTMLElement).closest('.bt-addcol-types')) {\n event.preventDefault();\n const index = types.findIndex(item => item.kind === kind);\n const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : event.key === 'ArrowDown' ? 4 : -4;\n const next = types[(index + step + types.length) % types.length]!;\n setKind(next.kind);\n requestAnimationFrame(() => (dialog.current?.querySelector(`[data-kind=\"${next.kind}\"]`) as HTMLElement | null)?.focus());\n }\n };\n const acceptChip = (insert: string) => {\n if (!completer) return;\n const next = completer.apply(value, caret, insert);\n setValue(next.text);\n setCaret(next.caret);\n requestAnimationFrame(() => { field.current?.focus(); field.current?.setSelectionRange(next.caret, next.caret); });\n };\n\n return createPortal(<div className=\"bt-palette-backdrop bt-addcol-backdrop\" onMouseDown={onClose}>\n <div ref={dialog} className=\"bt-palette bt-addcol bt-pop\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"bt-addcol-title\" onMouseDown={event => event.stopPropagation()} onKeyDown={onKey}>\n <header className=\"bt-addcol-head\">\n <h2 id=\"bt-addcol-title\">{t('wb.deck.addColumn')}</h2>\n <span>{t('wb.addcol.to', { deck: deck.name })}</span>\n <button className=\"bt-icon\" aria-label={t('wb.common.close')} onClick={onClose}><Icon name=\"close\"/></button>\n </header>\n <div className=\"bt-addcol-types\" role=\"radiogroup\" aria-label={t('wb.addcol.type')}>\n {types.map(item => <button key={item.kind} data-kind={item.kind} role=\"radio\" aria-checked={item.kind === kind} tabIndex={item.kind === kind ? 0 : -1}\n className={`bt-addcol-type${item.kind === kind ? ' is-on' : ''}`} onClick={() => setKind(item.kind)} onDoubleClick={() => { if (!item.value) onAdd({ profile, source: { kind: item.kind } }); }}>\n <span className=\"bt-addcol-icon\"><Icon name={item.icon}/></span>\n <strong>{item.label}</strong>\n <small>{item.hint}</small>\n </button>)}\n </div>\n {type.value && <div className=\"bt-addcol-value\">\n <label htmlFor=\"bt-addcol-field\">{type.value.label}</label>\n <div className={`bt-addcol-field${value && parsed === null ? ' is-bad' : ''}`}>\n <Icon name={type.icon}/>\n <input id=\"bt-addcol-field\" ref={field} spellCheck={false} autoComplete=\"off\" placeholder={type.value.placeholder} value={value}\n onChange={event => { setValue(event.target.value); setCaret(event.target.selectionStart ?? event.target.value.length); }}\n onSelect={() => setCaret(field.current?.selectionStart ?? value.length)}\n onKeyDown={event => { if (event.key === 'Tab' && !event.shiftKey && chips[0]) { event.preventDefault(); acceptChip(chips[0].insert); } }}/>\n </div>\n {chips.length > 0 && <div className=\"bt-addcol-chips\" role=\"listbox\" aria-label={completer?.label()}>\n {chips.map((chip, index) => <button key={chip.insert} type=\"button\" role=\"option\" aria-selected={index === 0} title={`${chip.hint}${index === 0 ? ` (${t('wb.web.tabKey')})` : ''}`}\n onMouseDown={event => event.preventDefault()} onClick={() => acceptChip(chip.insert)}>{chip.label}</button>)}\n </div>}\n {value && parsed === null && <p className=\"bt-addcol-error\" role=\"alert\">{spec.invalid(kind)}</p>}\n </div>}\n <div className=\"bt-addcol-accounts\">\n <span className=\"bt-addcol-label\">{t('wb.addcol.account')}</span>\n <div role=\"radiogroup\" aria-label={t('wb.addcol.account')}>\n {profiles.profiles.map(p => <button key={p.id} role=\"radio\" aria-checked={p.id === profile} className={`bt-addcol-account${p.id === profile ? ' is-on' : ''}`} onClick={() => setProfile(p.id)}\n style={{ ['--bt-col-account' as string]: p.color }}>\n <AccountAvatar profile={p} size={22}/><span>{p.account ? `${handlePrefix}${p.account.handle}` : accountLabel(p).title}</span>\n {p.account && !p.account.signedIn && <em>{t('wb.addcol.signedOut')}</em>}\n </button>)}\n </div>\n </div>\n <footer className=\"bt-addcol-foot\">\n <span><span className=\"bt-kbd\">↵</span> {t('wb.addcol.add')}</span><span><span className=\"bt-kbd\">Esc</span> {t('wb.addcol.close')}</span>\n <span className=\"bt-palette-foot-end\"/>\n <button className=\"bt-deck-secondary\" onClick={onClose}>{t('wb.common.cancel')}</button>\n <button className=\"bt-deck-primary\" disabled={!valid} onClick={submit}><Icon name=\"plus\"/>{t('wb.addcol.submit')}</button>\n </footer>\n </div>\n </div>, document.body);\n}\n"]}