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,67 @@
1
+ // What a click in the titlebar account switcher does (pure; unit-tested under node).
2
+ //
3
+ // One click on an account shows that account: a visible pane of it is focused, otherwise its home
4
+ // feed (or the site's sign-in when it is not signed in) opens in a new pane beside the focused one.
5
+ // Only a modifier click or the row's "Open in new tab" forces a new tab. The default account
6
+ // (`ProfileSettings.active`, kept for profiles.json compatibility) is only where new tabs open.
7
+ import { addProfile, tabProfile } from "../profileModel.js";
8
+ import { tx } from "./i18n.js";
9
+ /** Where a click on this account lands: its feed once signed in, the site's sign-in otherwise. */
10
+ export function accountStartUrl(profile, pages) {
11
+ return profile.account?.signedIn ? pages.homeUrl : pages.loginUrl;
12
+ }
13
+ /** The account the focused tab runs in (the app's panel has none: the default account). */
14
+ export function focusedAccount(settings, panes, activeId) {
15
+ const pane = panes.find(item => item.id === activeId);
16
+ return tabProfile(settings, pane && pane.kind !== 'panel' ? pane.profile : settings.active);
17
+ }
18
+ /**
19
+ * The click's result. `force` (Shift/Ctrl-click, "Open in new tab") always opens a new tab in the
20
+ * focused group. Otherwise a visible web pane of the account is focused (the focused one first, then
21
+ * a pane on the site), and only when there is none does a new pane open beside the focused one.
22
+ */
23
+ export function accountAction(settings, panes, activeId, profileId, options) {
24
+ const profile = tabProfile(settings, profileId);
25
+ const url = accountStartUrl(profile, options);
26
+ if (options.force)
27
+ return { type: 'open', url, profile: profile.id, where: 'tab' };
28
+ const onSite = options.isSiteUrl ?? (() => false);
29
+ const mine = panes.filter(pane => pane.kind === 'web' && pane.visible && tabProfile(settings, pane.profile).id === profile.id);
30
+ const target = mine.find(pane => pane.id === activeId) ?? mine.find(pane => !!pane.url && onSite(pane.url)) ?? mine[0];
31
+ if (target)
32
+ return { type: 'focus', paneId: target.id };
33
+ return { type: 'open', url, profile: profile.id, where: 'beside' };
34
+ }
35
+ /** "Use for new tabs": the only thing `active` means now. Unknown ids change nothing. */
36
+ export const setDefaultAccount = (settings, id) => settings.profiles.some(profile => profile.id === id) && settings.active !== id ? { ...settings, active: id } : settings;
37
+ /** "Add account": a fresh profile for the site's sign-in. It does not become the default. */
38
+ export function addAccountProfile(settings, id) {
39
+ const next = addProfile(settings, '', id, key => tx(key, undefined, '') || undefined);
40
+ return { settings: { ...next, active: settings.active }, profile: next.active };
41
+ }
42
+ /** Open tabs per account id (for "N tabs" and for closing them before a remove). */
43
+ export function tabsByAccount(settings, panes) {
44
+ const result = new Map();
45
+ for (const pane of panes) {
46
+ if (pane.kind !== 'web')
47
+ continue;
48
+ const id = tabProfile(settings, pane.profile).id;
49
+ result.set(id, [...(result.get(id) ?? []), pane.id]);
50
+ }
51
+ return result;
52
+ }
53
+ /** Roving focus in the menu: wraps around; Home/End jump to the ends. */
54
+ export function moveFocus(index, key, count) {
55
+ if (count <= 0)
56
+ return -1;
57
+ if (key === 'Home')
58
+ return 0;
59
+ if (key === 'End')
60
+ return count - 1;
61
+ if (key === 'ArrowDown')
62
+ return index < 0 ? 0 : (index + 1) % count;
63
+ if (key === 'ArrowUp')
64
+ return index < 0 ? count - 1 : (index - 1 + count) % count;
65
+ return index;
66
+ }
67
+ //# sourceMappingURL=accountModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accountModel.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/accountModel.ts"],"names":[],"mappings":"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","sourcesContent":["// What a click in the titlebar account switcher does (pure; unit-tested under node).\n//\n// One click on an account shows that account: a visible pane of it is focused, otherwise its home\n// feed (or the site's sign-in when it is not signed in) opens in a new pane beside the focused one.\n// Only a modifier click or the row's \"Open in new tab\" forces a new tab. The default account\n// (`ProfileSettings.active`, kept for profiles.json compatibility) is only where new tabs open.\n\nimport { addProfile, tabProfile, type Profile, type ProfileSettings } from '../profileModel.ts';\nimport { tx } from './i18n.ts';\n\n/** A tab as the switcher sees it: its account and whether it is on screen right now. */\nexport type PaneInfo = {\n id: string;\n kind: 'web' | 'start' | 'panel';\n /** Profile id as stored on the tab (missing or unknown = default). */\n profile?: string;\n url?: string;\n /** Shown on screen (the visible tab of its group). */\n visible: boolean;\n};\n\nexport type AccountAction =\n | { type: 'focus'; paneId: string }\n | { type: 'open'; url: string; profile: string; where: 'beside' | 'tab' };\n\n/** The site's pages an account click opens (`site.homeUrl`, `site.loginUrl`, `site.isSiteUrl`). */\nexport type AccountPages = { homeUrl: string; loginUrl: string; isSiteUrl?: (url: string) => boolean };\n\n/** Where a click on this account lands: its feed once signed in, the site's sign-in otherwise. */\nexport function accountStartUrl(profile: Profile, pages: Pick<AccountPages, 'homeUrl' | 'loginUrl'>): string {\n return profile.account?.signedIn ? pages.homeUrl : pages.loginUrl;\n}\n\n/** The account the focused tab runs in (the app's panel has none: the default account). */\nexport function focusedAccount(settings: ProfileSettings, panes: readonly PaneInfo[], activeId: string | null | undefined): Profile {\n const pane = panes.find(item => item.id === activeId);\n return tabProfile(settings, pane && pane.kind !== 'panel' ? pane.profile : settings.active);\n}\n\n/**\n * The click's result. `force` (Shift/Ctrl-click, \"Open in new tab\") always opens a new tab in the\n * focused group. Otherwise a visible web pane of the account is focused (the focused one first, then\n * a pane on the site), and only when there is none does a new pane open beside the focused one.\n */\nexport function accountAction(\n settings: ProfileSettings,\n panes: readonly PaneInfo[],\n activeId: string | null | undefined,\n profileId: string,\n options: { force?: boolean } & AccountPages,\n): AccountAction {\n const profile = tabProfile(settings, profileId);\n const url = accountStartUrl(profile, options);\n if (options.force) return { type: 'open', url, profile: profile.id, where: 'tab' };\n const onSite = options.isSiteUrl ?? (() => false);\n const mine = panes.filter(pane => pane.kind === 'web' && pane.visible && tabProfile(settings, pane.profile).id === profile.id);\n const target = mine.find(pane => pane.id === activeId) ?? mine.find(pane => !!pane.url && onSite(pane.url)) ?? mine[0];\n if (target) return { type: 'focus', paneId: target.id };\n return { type: 'open', url, profile: profile.id, where: 'beside' };\n}\n\n/** \"Use for new tabs\": the only thing `active` means now. Unknown ids change nothing. */\nexport const setDefaultAccount = (settings: ProfileSettings, id: string): ProfileSettings =>\n settings.profiles.some(profile => profile.id === id) && settings.active !== id ? { ...settings, active: id } : settings;\n\n/** \"Add account\": a fresh profile for the site's sign-in. It does not become the default. */\nexport function addAccountProfile(settings: ProfileSettings, id?: string): { settings: ProfileSettings; profile: string } {\n const next = addProfile(settings, '', id, key => tx(key, undefined, '') || undefined);\n return { settings: { ...next, active: settings.active }, profile: next.active };\n}\n\n/** Open tabs per account id (for \"N tabs\" and for closing them before a remove). */\nexport function tabsByAccount(settings: ProfileSettings, panes: readonly PaneInfo[]): Map<string, string[]> {\n const result = new Map<string, string[]>();\n for (const pane of panes) {\n if (pane.kind !== 'web') continue;\n const id = tabProfile(settings, pane.profile).id;\n result.set(id, [...(result.get(id) ?? []), pane.id]);\n }\n return result;\n}\n\n/** Roving focus in the menu: wraps around; Home/End jump to the ends. */\nexport function moveFocus(index: number, key: string, count: number): number {\n if (count <= 0) return -1;\n if (key === 'Home') return 0;\n if (key === 'End') return count - 1;\n if (key === 'ArrowDown') return index < 0 ? 0 : (index + 1) % count;\n if (key === 'ArrowUp') return index < 0 ? count - 1 : (index - 1 + count) % count;\n return index;\n}\n"]}
@@ -0,0 +1,91 @@
1
+ /* Titlebar account switcher menu and the per-pane account marker (AccountSwitcher.tsx, WebPanel.tsx).
2
+ Tokens come from shell.css (:root --bt-*). */
3
+
4
+ .bt-acct-menu { width: 340px; max-height: calc(100vh - 64px); overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--bt-line-strong) transparent; }
5
+
6
+ .bt-acct-head { display: flex; flex-direction: column; gap: 4px; padding: 8px 10px 8px; }
7
+ .bt-acct-head strong { font: 600 13px/1.2 var(--bt-ui); color: var(--bt-text); }
8
+ .bt-acct-head span { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; font: 400 12px/1.3 var(--bt-ui); color: var(--bt-muted); }
9
+ .bt-acct-head .bt-kbd { height: 16px; min-width: 0; font: 500 10.5px/1 var(--bt-ui); }
10
+
11
+ /* One account: the whole row is the main action; "…" sits at the right edge. */
12
+ .bt-acct-row { position: relative; display: flex; flex-direction: column; border-radius: 10px; }
13
+ .bt-acct-line { position: relative; display: flex; align-items: center; }
14
+ .bt-acct-row.is-focused { background: rgb(var(--bt-accent-rgb) / .08); box-shadow: inset 0 0 0 1px rgb(var(--bt-accent-rgb) / .22); }
15
+ .bt-acct-row.is-focused::before {
16
+ content: ''; position: absolute; inset-inline-start: -5px; top: 12px; height: 24px; width: 3px; border-start-start-radius: 0; border-start-end-radius: 3px; border-end-end-radius: 3px; border-end-start-radius: 0; background: var(--bt-accent);
17
+ }
18
+ .bt-acct-row.is-open { background: rgb(var(--bt-text-rgb) / .035); }
19
+
20
+ .bt-menu .bt-acct-main { flex: 1; min-width: 0; height: auto; gap: 11px; padding-block: 8px; padding-inline: 8px 40px; border-radius: 10px; }
21
+ .bt-menu .bt-acct-main:focus-visible { box-shadow: var(--bt-ring); }
22
+ .bt-acct-avatar { position: relative; display: inline-grid; flex: none; }
23
+ .bt-acct-avatar.is-signed-out .bt-avatar, .bt-acct-avatar.is-new .bt-avatar { filter: saturate(.35); opacity: .7; }
24
+ .bt-acct-avatar.is-signed-out::after, .bt-acct-avatar.is-new::after {
25
+ content: ''; position: absolute; inset-inline-end: -1px; bottom: -1px; width: 9px; height: 9px; border-radius: 50%;
26
+ background: var(--bt-faint); box-shadow: 0 0 0 2px var(--bt-raised);
27
+ }
28
+
29
+ .bt-acct-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
30
+ .bt-acct-name { display: flex; align-items: center; gap: 6px; min-width: 0; font: 600 13.5px/1.15 var(--bt-ui); color: var(--bt-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
31
+ .bt-acct-meta { font: 400 12px/1.2 var(--bt-ui); color: var(--bt-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
32
+ .bt-acct-meta.is-signed-out, .bt-acct-meta.is-new { color: #f0b14a; }
33
+ .bt-acct-count { color: var(--bt-muted); }
34
+ .bt-acct-badge {
35
+ flex: none; padding: 2px 6px; border-radius: 999px; background: rgb(var(--bt-text-rgb) / .07); color: var(--bt-text-2);
36
+ font: 500 10.5px/1.2 var(--bt-ui); letter-spacing: .01em;
37
+ }
38
+
39
+ /* What the click will do, revealed on hover/focus so the row reads as one obvious action. */
40
+ /* Hidden until then, so a long @handle / status gets the full width. */
41
+ .bt-acct-hint { display: none; align-items: center; gap: 5px; flex: none; color: var(--bt-accent-ink); font: 500 11.5px/1 var(--bt-ui); animation: bt-acct-hint-in var(--bt-t1) var(--bt-ease-out); }
42
+ @keyframes bt-acct-hint-in { from { opacity: 0; transform: translateX(-3px); } }
43
+ .bt-acct-hint .bt-glyph { width: 13px; height: 13px; }
44
+ .bt-acct-row.is-focused .bt-acct-hint { display: inline-flex; color: var(--bt-accent-ink); }
45
+ .bt-acct-main:hover .bt-acct-hint, .bt-acct-main:focus-visible .bt-acct-hint { display: inline-flex; color: var(--bt-accent-ink); }
46
+
47
+ .bt-menu .bt-acct-more {
48
+ position: absolute; inset-inline-end: 6px; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; padding: 0; justify-content: center;
49
+ color: var(--bt-muted); opacity: 0; transition: opacity var(--bt-t1) var(--bt-ease);
50
+ }
51
+ .bt-acct-more svg { width: 16px; height: 16px; fill: currentColor; }
52
+ .bt-acct-row:hover .bt-acct-more, .bt-acct-row:focus-within .bt-acct-more, .bt-acct-more[aria-expanded=true] { opacity: 1; }
53
+ .bt-menu .bt-acct-more:hover, .bt-menu .bt-acct-more[aria-expanded=true] { color: var(--bt-text); background: var(--bt-press); }
54
+ /* Hover hint and "…" share the right edge: the hint moves left of it. */
55
+ .bt-acct-row:hover .bt-acct-hint { margin-inline-end: 2px; }
56
+
57
+ /* Row actions: inline under the row (no second floating layer over the native panes). */
58
+ .bt-acct-sub { display: flex; flex-direction: column; gap: 1px; margin-block: 0 6px; margin-inline: 49px 6px; padding-top: 2px; border-top: 1px solid var(--bt-line-soft); }
59
+ .bt-menu .bt-acct-sub button { height: 30px; font-size: 12.5px; }
60
+ .bt-acct-sub .bt-glyph { width: 15px; height: 15px; }
61
+ .bt-acct-sub .bt-menu-keys { font-size: 11px; }
62
+ .bt-menu .bt-acct-sub button[aria-checked=true]:disabled { color: var(--bt-text-2); }
63
+ .bt-menu .bt-acct-sub button[aria-checked=true]:disabled > .bt-glyph { color: var(--bt-accent); opacity: 1; }
64
+ .bt-menu .bt-acct-danger { color: #ff8a80; }
65
+ .bt-menu .bt-acct-danger > .bt-glyph { color: #ff8a80; }
66
+
67
+ .bt-acct-confirm {
68
+ display: flex; flex-direction: column; gap: 10px; margin: 2px 6px 6px; padding: 10px 12px; border-radius: 9px;
69
+ background: rgba(229, 72, 77, .08); box-shadow: inset 0 0 0 1px rgba(229, 72, 77, .25); color: var(--bt-text-2); font: 400 12.5px/1.45 var(--bt-ui);
70
+ }
71
+ .bt-acct-confirm strong { color: var(--bt-text); font-weight: 600; }
72
+ .bt-acct-confirm div { display: flex; gap: 6px; }
73
+ .bt-menu .bt-acct-confirm button { height: 28px; padding: 0 12px; font-weight: 600; font-size: 12.5px; }
74
+ .bt-menu .bt-acct-remove { background: var(--bt-danger); color: #fff; }
75
+ .bt-menu .bt-acct-remove:hover:not(:disabled), .bt-menu .bt-acct-remove:focus-visible { background: #d93d42; }
76
+ .bt-menu .bt-acct-cancel { background: var(--bt-hover); }
77
+
78
+ .bt-menu .bt-acct-add { height: auto; gap: 11px; padding: 8px; border-radius: 10px; }
79
+ .bt-menu .bt-acct-add:focus-visible { box-shadow: var(--bt-ring); }
80
+ .bt-acct-add .bt-acct-name { color: var(--bt-text-2); }
81
+ .bt-acct-add-icon { display: grid; place-items: center; width: 32px; height: 32px; flex: none; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--bt-line-strong); color: var(--bt-muted); }
82
+ .bt-acct-add-icon .bt-glyph { width: 15px; height: 15px; }
83
+ .bt-menu .bt-acct-add:hover .bt-acct-add-icon { box-shadow: inset 0 0 0 1px rgb(var(--bt-accent-rgb) / .6); color: var(--bt-accent-ink); }
84
+
85
+ .bt-acct-error { padding: 6px 10px; color: #ff8a80; font: 12px/1.4 var(--bt-ui); }
86
+
87
+ /* Each pane's account, left of its address bar (same color as the tab's account dot). */
88
+ .bt-pane-account {
89
+ display: inline-grid; place-items: center; flex: none; width: 26px; height: 26px; margin-inline-start: 4px; border-radius: 50%;
90
+ box-shadow: 0 0 0 1.5px var(--bt-pane-account, var(--bt-line-strong));
91
+ }
@@ -0,0 +1,44 @@
1
+ import { type I18n, type Messages, type Params } from '../../runtime/i18n.ts';
2
+ /** One language the app has a catalog for (a row of the app's generated `languages.json`). */
3
+ export type AppLanguage = {
4
+ code: string;
5
+ name: string;
6
+ englishName: string;
7
+ dir: 'ltr' | 'rtl';
8
+ status: 'source' | 'machine' | 'reviewed';
9
+ /** `supported`: automatic language choices may resolve to it. `community`: only when picked explicitly. */
10
+ tier: 'supported' | 'community';
11
+ reviewers: string[];
12
+ fallback?: string;
13
+ /** Share of English messages this catalog translates (its fallback's included), 0..1. */
14
+ coverage: number;
15
+ };
16
+ export type AppI18nOptions = {
17
+ /** English: the framework's messages with the app's over them. */
18
+ source: Messages;
19
+ /** Every language with a catalog, English first. */
20
+ languages: readonly AppLanguage[];
21
+ /** React's hook (`import { useSyncExternalStore } from 'react'`), for `useT` and `useLocale`. */
22
+ useSyncExternalStore<Snapshot>(subscribe: (listener: () => void) => () => void, getSnapshot: () => Snapshot, getServerSnapshot?: () => Snapshot): Snapshot;
23
+ /** A development build: untranslated and malformed messages are logged. */
24
+ dev?: boolean;
25
+ };
26
+ export type AppI18n<Key extends string> = {
27
+ i18n: I18n<Key>;
28
+ /** Registers how catalogs load (the app's lazy imports; tests may pass a map). */
29
+ setCatalogLoader(load: (locale: string) => Promise<Messages | null>): void;
30
+ /** The message for `key` in the active language. */
31
+ t(key: Key, params?: Params): string;
32
+ /** For keys assembled at runtime (feature ids, section names): `fallback` when the key is unknown. */
33
+ tx(key: string, params?: Params, fallback?: string): string;
34
+ /** Re-renders the calling component when the language changes; returns `t`. */
35
+ useT(): (key: Key, params?: Params) => string;
36
+ /** The active locale (re-renders on change). */
37
+ useLocale(): string;
38
+ /** "3 minutes ago" style text for a timestamp in the active language. */
39
+ relativeTime(then: number, now?: number): string;
40
+ /** A date (and time) in the active language: `formatDate(iso, { dateStyle: 'medium' })`. */
41
+ formatDate(value: string | number | Date, options?: Intl.DateTimeFormatOptions): string;
42
+ formatNumber(value: number, options?: Intl.NumberFormatOptions): string;
43
+ };
44
+ export declare function createAppI18n<Key extends string>(options: AppI18nOptions): AppI18n<Key>;
@@ -0,0 +1,64 @@
1
+ // An app's i18n instance for its shell webview (the shell frame, the panel, its own windows):
2
+ // English (the app's catalog over the framework's) is always loaded, other catalogs load on
3
+ // demand through the loader the app registers (its bundler's lazy imports), and components call
4
+ // `useT()` so a language switch re-renders them in place. The frame is bound to the instance.
5
+ //
6
+ // export const { i18n, t, tx, useT, setCatalogLoader } = createAppI18n<MessageKey>({
7
+ // source: { ...frameworkEn.messages, ...appEn.messages }, languages, useSyncExternalStore, dev: import.meta.env.DEV,
8
+ // });
9
+ //
10
+ // Keys are typed by the app (`MessageKey`: its English catalog's keys and the framework's). The
11
+ // app passes React's `useSyncExternalStore`, so this module has no dependency of its own and the
12
+ // app's pure modules that use `t` stay testable under node.
13
+ import { createI18n } from "../../runtime/i18n.js";
14
+ import { setShellI18n } from "./i18n.js";
15
+ export function createAppI18n(options) {
16
+ let loader = null;
17
+ const i18n = createI18n({
18
+ source: options.source,
19
+ available: options.languages.map(language => language.code),
20
+ fallbacks: Object.fromEntries(options.languages.filter(language => language.fallback).map(language => [language.code, language.fallback])),
21
+ load: locale => loader?.(locale) ?? null,
22
+ onMissing: options.dev
23
+ ? (key, locale, reason) => { if (reason !== 'key' || locale === 'en')
24
+ console.warn(`[i18n] ${reason} ${locale}: ${key}`);
25
+ else
26
+ console.debug(`[i18n] untranslated ${locale}: ${key}`); }
27
+ : undefined,
28
+ });
29
+ // The wayBetter shell frame and panel speak through this instance.
30
+ setShellI18n(i18n);
31
+ const { useSyncExternalStore } = options;
32
+ const t = (key, params) => i18n.t(key, params);
33
+ const subscribe = (listener) => i18n.onChange(listener);
34
+ const snapshot = () => i18n.locale;
35
+ return {
36
+ i18n,
37
+ setCatalogLoader(load) { loader = load; },
38
+ t,
39
+ tx: (key, params, fallback) => i18n.tx(key, params, fallback),
40
+ useT() {
41
+ useSyncExternalStore(subscribe, snapshot, snapshot);
42
+ return t;
43
+ },
44
+ useLocale: () => useSyncExternalStore(subscribe, snapshot, snapshot),
45
+ relativeTime(then, now = Date.now()) {
46
+ const seconds = Math.round((then - now) / 1000);
47
+ const abs = Math.abs(seconds);
48
+ if (abs < 45)
49
+ return i18n.relative(0, 'second');
50
+ if (abs < 3600)
51
+ return i18n.relative(Math.round(seconds / 60), 'minute');
52
+ if (abs < 86400)
53
+ return i18n.relative(Math.round(seconds / 3600), 'hour');
54
+ if (abs < 86400 * 30)
55
+ return i18n.relative(Math.round(seconds / 86400), 'day');
56
+ if (abs < 86400 * 365)
57
+ return i18n.relative(Math.round(seconds / (86400 * 30)), 'month');
58
+ return i18n.relative(Math.round(seconds / (86400 * 365)), 'year');
59
+ },
60
+ formatDate: (value, formatOptions = { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) => i18n.date(value, formatOptions),
61
+ formatNumber: (value, formatOptions) => i18n.number(value, formatOptions),
62
+ };
63
+ }
64
+ //# sourceMappingURL=appI18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appI18n.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/appI18n.ts"],"names":[],"mappings":"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","sourcesContent":["// An app's i18n instance for its shell webview (the shell frame, the panel, its own windows):\n// English (the app's catalog over the framework's) is always loaded, other catalogs load on\n// demand through the loader the app registers (its bundler's lazy imports), and components call\n// `useT()` so a language switch re-renders them in place. The frame is bound to the instance.\n//\n// export const { i18n, t, tx, useT, setCatalogLoader } = createAppI18n<MessageKey>({\n// source: { ...frameworkEn.messages, ...appEn.messages }, languages, useSyncExternalStore, dev: import.meta.env.DEV,\n// });\n//\n// Keys are typed by the app (`MessageKey`: its English catalog's keys and the framework's). The\n// app passes React's `useSyncExternalStore`, so this module has no dependency of its own and the\n// app's pure modules that use `t` stay testable under node.\n\nimport { createI18n, type I18n, type Messages, type Params } from '../../../runtime/src/i18n.ts';\nimport { setShellI18n } from './i18n.ts';\n\n/** One language the app has a catalog for (a row of the app's generated `languages.json`). */\nexport type AppLanguage = {\n code: string;\n name: string;\n englishName: string;\n dir: 'ltr' | 'rtl';\n status: 'source' | 'machine' | 'reviewed';\n /** `supported`: automatic language choices may resolve to it. `community`: only when picked explicitly. */\n tier: 'supported' | 'community';\n reviewers: string[];\n fallback?: string;\n /** Share of English messages this catalog translates (its fallback's included), 0..1. */\n coverage: number;\n};\n\nexport type AppI18nOptions = {\n /** English: the framework's messages with the app's over them. */\n source: Messages;\n /** Every language with a catalog, English first. */\n languages: readonly AppLanguage[];\n /** React's hook (`import { useSyncExternalStore } from 'react'`), for `useT` and `useLocale`. */\n useSyncExternalStore<Snapshot>(subscribe: (listener: () => void) => () => void, getSnapshot: () => Snapshot, getServerSnapshot?: () => Snapshot): Snapshot;\n /** A development build: untranslated and malformed messages are logged. */\n dev?: boolean;\n};\n\nexport type AppI18n<Key extends string> = {\n i18n: I18n<Key>;\n /** Registers how catalogs load (the app's lazy imports; tests may pass a map). */\n setCatalogLoader(load: (locale: string) => Promise<Messages | null>): void;\n /** The message for `key` in the active language. */\n t(key: Key, params?: Params): string;\n /** For keys assembled at runtime (feature ids, section names): `fallback` when the key is unknown. */\n tx(key: string, params?: Params, fallback?: string): string;\n /** Re-renders the calling component when the language changes; returns `t`. */\n useT(): (key: Key, params?: Params) => string;\n /** The active locale (re-renders on change). */\n useLocale(): string;\n /** \"3 minutes ago\" style text for a timestamp in the active language. */\n relativeTime(then: number, now?: number): string;\n /** A date (and time) in the active language: `formatDate(iso, { dateStyle: 'medium' })`. */\n formatDate(value: string | number | Date, options?: Intl.DateTimeFormatOptions): string;\n formatNumber(value: number, options?: Intl.NumberFormatOptions): string;\n};\n\nexport function createAppI18n<Key extends string>(options: AppI18nOptions): AppI18n<Key> {\n let loader: ((locale: string) => Promise<Messages | null>) | null = null;\n const i18n = createI18n<Key>({\n source: options.source,\n available: options.languages.map(language => language.code),\n fallbacks: Object.fromEntries(options.languages.filter(language => language.fallback).map(language => [language.code, language.fallback!])),\n load: locale => loader?.(locale) ?? null,\n onMissing: options.dev\n ? (key, locale, reason) => { if (reason !== 'key' || locale === 'en') console.warn(`[i18n] ${reason} ${locale}: ${key}`); else console.debug(`[i18n] untranslated ${locale}: ${key}`); }\n : undefined,\n });\n // The wayBetter shell frame and panel speak through this instance.\n setShellI18n(i18n);\n\n const { useSyncExternalStore } = options;\n const t = (key: Key, params?: Params) => i18n.t(key, params);\n const subscribe = (listener: () => void) => i18n.onChange(listener);\n const snapshot = () => i18n.locale;\n return {\n i18n,\n setCatalogLoader(load) { loader = load; },\n t,\n tx: (key, params, fallback) => i18n.tx(key, params, fallback),\n useT() {\n useSyncExternalStore(subscribe, snapshot, snapshot);\n return t;\n },\n useLocale: () => useSyncExternalStore(subscribe, snapshot, snapshot),\n relativeTime(then, now = Date.now()) {\n const seconds = Math.round((then - now) / 1000);\n const abs = Math.abs(seconds);\n if (abs < 45) return i18n.relative(0, 'second');\n if (abs < 3600) return i18n.relative(Math.round(seconds / 60), 'minute');\n if (abs < 86400) return i18n.relative(Math.round(seconds / 3600), 'hour');\n if (abs < 86400 * 30) return i18n.relative(Math.round(seconds / 86400), 'day');\n if (abs < 86400 * 365) return i18n.relative(Math.round(seconds / (86400 * 30)), 'month');\n return i18n.relative(Math.round(seconds / (86400 * 365)), 'year');\n },\n formatDate: (value, formatOptions = { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) => i18n.date(value, formatOptions),\n formatNumber: (value, formatOptions) => i18n.number(value, formatOptions),\n };\n}\n"]}
@@ -0,0 +1,121 @@
1
+ /* The app menu (AppMenu.tsx): the titlebar's "Settings and more" button, its menu and submenus.
2
+ Tokens come from shell.css (:root --bt-*), so it follows the chrome theme (and its first-frame
3
+ cache) like every other shell menu. Its width in the titlebar is reserved in --bt-tb-menu. */
4
+
5
+ /* The button: the last thing before the caption buttons. */
6
+ .bt-app-button {
7
+ align-self: center; display: inline-grid; place-items: center; width: 30px; height: 30px; flex: none; margin-right: 8px; padding: 0; box-sizing: border-box; /* rtl-ok: titlebar */
8
+ border: 1px solid transparent; border-radius: 15px; background: transparent; color: var(--bt-text-2); cursor: pointer;
9
+ transition: background-color var(--bt-t1) var(--bt-ease), border-color var(--bt-t1) var(--bt-ease), color var(--bt-t1) var(--bt-ease);
10
+ }
11
+ .bt-app-button:hover { background: var(--bt-hover); border-color: var(--bt-line-soft); color: var(--bt-text); }
12
+ .bt-app-button[aria-expanded=true] { background: var(--bt-hover); border-color: rgb(var(--bt-accent-rgb) / .5); color: var(--bt-text); }
13
+ .bt-app-button:focus-visible { outline: 0; box-shadow: var(--bt-ring); }
14
+ .bt-shell .bt-app-button svg { width: 16px; height: 16px; fill: currentColor; stroke: none; }
15
+
16
+ /* An app that shows no menu button (`<AppMenu trigger={false}/>`, the logo is the menu's home) reserves no room for it. */
17
+ html:not(:has(.bt-app-button)) { --bt-tb-menu: 0px; }
18
+
19
+ /* The logo at the start of the titlebar: the menu's second trigger (a 30px target around the 20px
20
+ mark; with its margins it takes the 50px the tab strip leaves in --bt-tb-left). */
21
+ .bt-titlebar-logo {
22
+ align-self: center; display: inline-grid; place-items: center; width: 30px; height: 30px; flex: 0 0 30px; margin: 0 9px 0 11px; padding: 0; box-sizing: border-box; /* rtl-ok: titlebar */
23
+ border: 1px solid transparent; border-radius: 9px; background: transparent; cursor: pointer; -webkit-user-drag: none;
24
+ transition: background-color var(--bt-t1) var(--bt-ease), border-color var(--bt-t1) var(--bt-ease);
25
+ }
26
+ .bt-titlebar-logo img { display: block; width: 20px; height: 20px; pointer-events: none; -webkit-user-drag: none; }
27
+ .bt-titlebar-logo:hover { background: var(--bt-hover); border-color: var(--bt-line-soft); }
28
+ .bt-titlebar-logo[aria-expanded=true] { background: var(--bt-hover); border-color: rgb(var(--bt-accent-rgb) / .5); }
29
+ .bt-titlebar-logo:focus-visible { outline: 0; box-shadow: var(--bt-ring); }
30
+
31
+ /* The menu and its submenus. `display: contents`: the layers are positioned on their own. */
32
+ .bt-app-layers { display: contents; }
33
+ .bt-menu.bt-app-menu {
34
+ width: 304px; max-width: calc(100vw - 16px); padding: 6px; overflow-y: auto; overscroll-behavior: contain;
35
+ scrollbar-width: thin; scrollbar-color: var(--bt-line-strong) transparent;
36
+ }
37
+ .bt-menu.bt-app-menu:focus { outline: 0; }
38
+ .bt-menu.bt-app-sub {
39
+ width: max-content; min-width: 224px; max-width: min(320px, calc(100vw - 16px)); z-index: 1;
40
+ animation: bt-app-sub-in var(--bt-t1) var(--bt-ease-out);
41
+ }
42
+ @keyframes bt-app-sub-in { from { opacity: 0; transform: translateX(var(--bt-app-sub-from, 6px)); } }
43
+ .bt-app-menu hr { flex: none; width: auto; align-self: stretch; }
44
+
45
+ /* Rows: one highlight, wherever it comes from (the pointer moves the focus, as the arrows do);
46
+ a row whose submenu is open keeps it; the keyboard's focus also gets a hairline in the accent. */
47
+ .bt-app-menu button { flex: none; width: 100%; min-width: 0; box-sizing: border-box; }
48
+ .bt-app-menu button:hover:not(:disabled) { background: transparent; }
49
+ .bt-app-menu button:focus:not(:disabled), .bt-app-menu button[aria-expanded=true] { background: var(--bt-hover); outline: 0; }
50
+ .bt-app-menu button:focus-visible:not(:disabled) { box-shadow: inset 0 0 0 1px rgb(var(--bt-accent-rgb) / .6); }
51
+ .bt-app-menu button:active:not(:disabled) { background: var(--bt-press); }
52
+ .bt-app-menu button:focus > .bt-glyph, .bt-app-menu button[aria-expanded=true] > .bt-glyph { color: var(--bt-text); }
53
+
54
+ /* The leading column: an icon, or the check of a choice (empty while it is not the one chosen). */
55
+ .bt-app-check { display: inline-grid; place-items: center; width: 16px; height: 16px; flex: none; }
56
+ .bt-app-check .bt-glyph { width: 15px; height: 15px; color: var(--bt-accent); stroke-width: 2.1; }
57
+ .bt-app-menu [aria-checked=true] .bt-menu-label { color: var(--bt-text); font-weight: 600; }
58
+
59
+ /* The trailing column: a quiet value (the language in use, a version), the keys, the submenu arrow. */
60
+ .bt-app-hint { flex: 0 1 auto; min-width: 0; max-width: 46%; margin-inline-start: auto; padding-inline-start: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--bt-muted); font: 400 12px/1.3 var(--bt-ui); font-variant-numeric: tabular-nums; }
61
+ .bt-app-menu .bt-menu-keys { flex: none; padding-inline-start: 12px; unicode-bidi: isolate; direction: ltr; }
62
+ .bt-app-hint + .bt-menu-keys, .bt-app-menu .wb-dots + .bt-app-hint { margin-inline-start: 0; }
63
+ .bt-app-menu .bt-app-chevron { width: 14px; height: 14px; margin-inline: 2px -4px; color: var(--bt-faint); }
64
+ .bt-app-menu .bt-app-hint + .bt-app-chevron { margin-inline-start: -4px; }
65
+ .bt-app-menu button:focus > .bt-app-chevron, .bt-app-menu button[aria-expanded=true] > .bt-app-chevron { color: var(--bt-text-2); }
66
+ [dir="rtl"] .bt-app-menu .bt-app-chevron { transform: scaleX(-1); }
67
+ .bt-app-menu .wb-dots { margin-inline-start: 8px; }
68
+
69
+ /* Zoom: one line, − 100% + and a reset. The stepper reads left to right in every language. */
70
+ .bt-app-zoom { display: flex; align-items: center; gap: 10px; height: 36px; flex: none; padding-inline: 10px 3px; color: var(--bt-text); }
71
+ .bt-app-zoom > .bt-glyph { color: var(--bt-muted); }
72
+ .bt-app-zoom.is-off > .bt-glyph, .bt-app-zoom.is-off .bt-menu-label, .bt-app-zoom.is-off .bt-app-zoom-value { color: var(--bt-faint); }
73
+ .bt-app-zoom-step { display: flex; align-items: center; flex: none; height: 28px; border-radius: 9px; direction: ltr; background: rgb(var(--bt-text-rgb) / .04); box-shadow: inset 0 0 0 1px var(--bt-line); }
74
+ .bt-app-menu .bt-app-zoom button { width: 30px; height: 28px; flex: none; padding: 0; justify-content: center; border-radius: 8px; color: var(--bt-text-2); }
75
+ .bt-app-menu .bt-app-zoom button > .bt-glyph { width: 14px; height: 14px; color: inherit; }
76
+ .bt-app-menu .bt-app-zoom button:focus { color: var(--bt-text); }
77
+ .bt-app-menu .bt-app-zoom button[aria-disabled=true] { color: var(--bt-faint); cursor: default; }
78
+ .bt-app-menu .bt-app-zoom button[aria-disabled=true]:active { background: var(--bt-hover); }
79
+ .bt-app-zoom-value { min-width: 50px; padding: 0 2px; text-align: center; color: var(--bt-text); font: 500 12px/1 var(--bt-mono); font-variant-numeric: tabular-nums; }
80
+ .bt-app-menu .bt-app-zoom .bt-app-zoom-reset { width: 28px; border-radius: 9px; }
81
+
82
+ /* Words that are not a choice: the mode question, an empty list, an error. */
83
+ .bt-app-note { display: flex; flex-direction: column; gap: 3px; max-width: 288px; padding: 8px 10px 7px; box-sizing: border-box; }
84
+ .bt-app-note strong { color: var(--bt-text); font: 600 13px/1.3 var(--bt-ui); }
85
+ .bt-app-note span { color: var(--bt-muted); font: 400 12px/1.4 var(--bt-ui); white-space: normal; }
86
+ .bt-app-note.is-error span { color: var(--bt-danger); }
87
+
88
+ /* The account menu's last row: the way here from where the account name is. */
89
+ .bt-menu .bt-acct-settings { flex: none; height: 34px; gap: 11px; padding: 0 8px; border-radius: 10px; color: var(--bt-text-2); }
90
+ .bt-menu .bt-acct-settings > .bt-glyph { width: 32px; height: 15px; }
91
+ .bt-menu .bt-acct-settings:focus-visible { box-shadow: var(--bt-ring); }
92
+
93
+ /* The titlebar's zoom chip: only while the pane in front is not at 100% (TitlebarExtras.tsx). */
94
+ .bt-zoom-chip { font-family: var(--bt-mono); font-size: 11.5px; font-variant-numeric: tabular-nums; }
95
+ .bt-zoom-chip .bt-glyph { color: var(--bt-muted); }
96
+
97
+ /* Safe mode, said in the titlebar for as long as it is on (TitlebarExtras.tsx): amber, and one click leaves it. */
98
+ .bt-safe-chip { border-color: rgba(245, 158, 11, .38); background: rgba(245, 158, 11, .1); color: var(--bt-text); font-weight: 600; }
99
+ .bt-safe-chip:hover { border-color: rgba(245, 158, 11, .6); background: rgba(245, 158, 11, .16); }
100
+ .bt-safe-chip .bt-glyph { color: #f59e0b; }
101
+ .bt-safe-leave { margin-inline-start: 2px; padding-inline-start: 9px; border-inline-start: 1px solid rgba(245, 158, 11, .35); color: var(--bt-text-2); font-weight: 500; }
102
+ .bt-safe-chip:hover .bt-safe-leave { color: var(--bt-text); }
103
+ .bt-safe-chip:disabled { opacity: .6; cursor: default; }
104
+ .bt-app-sub .bt-app-note { max-width: 300px; }
105
+
106
+ /* "Report a problem" (ReportDialog.tsx): the summary, exactly as it would be shared. */
107
+ .bt-report { width: min(560px, 100%); max-height: min(86vh, 620px); display: flex; flex-direction: column; overflow: hidden; }
108
+ .bt-report:focus { outline: 0; }
109
+ .bt-report-head { display: flex; align-items: center; gap: 8px; padding-block: 16px 4px; padding-inline: 20px 12px; }
110
+ .bt-report-head h2 { margin: 0; flex: 1; font: 700 17px/1.2 var(--bt-ui); letter-spacing: -.015em; color: var(--bt-text); }
111
+ .bt-report-lede, .bt-report-note { margin: 0; padding: 0 20px; color: var(--bt-muted); font: 400 12.5px/1.5 var(--bt-ui); }
112
+ .bt-report-note { padding-top: 10px; color: var(--bt-text-2); }
113
+ .bt-report-text {
114
+ flex: 1 1 auto; min-height: 150px; margin: 12px 20px 0; padding: 12px 14px; box-sizing: border-box; resize: none; overflow: auto;
115
+ border: 1px solid var(--bt-line); border-radius: var(--bt-r3); background: var(--bt-field); color: var(--bt-text);
116
+ font: 400 12px/1.65 var(--bt-mono); white-space: pre-wrap; overflow-wrap: anywhere; user-select: text; text-align: left; /* rtl-ok: the report is English */
117
+ }
118
+ .bt-report-text:focus-visible { outline: 0; border-color: transparent; box-shadow: var(--bt-ring); }
119
+ .bt-report-foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 14px 20px 18px; }
120
+ .bt-report-copied { margin-inline-end: auto; color: var(--bt-muted); font: 500 12px/1 var(--bt-ui); }
121
+ .bt-report-foot .bt-glyph { width: 15px; height: 15px; }
@@ -0,0 +1,38 @@
1
+ export declare const BACKUP_FORMAT = "waybetter-backup";
2
+ export declare const BACKUP_VERSION = 1;
3
+ /** Sections the shell applies itself (the rest go to native `backup_apply`). */
4
+ export declare const LOCAL_SECTIONS: readonly ["decks"];
5
+ /** Backup sections in display order; their names are `wb.backup.section.<id>` in the catalogs. */
6
+ export declare const SECTION_ORDER: string[];
7
+ export declare const sectionLabel: (section: string) => string;
8
+ type Json = Record<string, unknown>;
9
+ /** Stable JSON (sorted keys) for equality. */
10
+ export declare function canonical(value: unknown): string;
11
+ /** Secret-looking keys (same rule as native `strip_secrets`); never exported, never imported. */
12
+ export declare function isSecretKey(key: string): boolean;
13
+ export declare function stripSecrets<T>(value: T): T;
14
+ /** The shell's own sections: decks and deck settings (localStorage), never tab state. */
15
+ export declare function localSections(input: {
16
+ decks: unknown[];
17
+ deckSettings: unknown;
18
+ }): Json;
19
+ export type SectionRow = {
20
+ section: string;
21
+ label: string;
22
+ /** `same`: nothing would change; `changed`: differs from this computer; `new`: nothing here yet. */
23
+ status: 'same' | 'changed' | 'new';
24
+ /** Short lines for the preview ("Nord → Paper", "+2 plugins", ...). */
25
+ details: string[];
26
+ /** Ticked by default: changed sections, except drafts (added only when asked). */
27
+ checked: boolean;
28
+ };
29
+ /** One preview row per section present in `incoming`, in display order. */
30
+ export declare function diffSections(current: Json, incoming: Json): SectionRow[];
31
+ /** Splits the ticked sections into what native code applies and what the shell applies. */
32
+ export declare function pickSections(incoming: Json, chosen: Iterable<string>): {
33
+ native: Json;
34
+ local: Json;
35
+ };
36
+ /** "3 minutes ago" / "yesterday" for sync snapshot times, in the active language. */
37
+ export declare function ago(ms: number, now?: number): string;
38
+ export {};