waybetter 0.1.1 → 0.7.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 (537) hide show
  1. package/README.md +139 -6
  2. package/bin/waybetter.mjs +43 -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/release.mjs +437 -0
  9. package/cli/releasecheck.mjs +15 -0
  10. package/cli/remote.mjs +260 -0
  11. package/cli/store.mjs +378 -0
  12. package/cli/strings.mjs +123 -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 +61 -0
  74. package/dist/runtime/stringPackTranslate.js +267 -0
  75. package/dist/runtime/stringPackTranslate.js.map +1 -0
  76. package/dist/runtime/stringPacks.d.ts +248 -0
  77. package/dist/runtime/stringPacks.js +610 -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/themeBar.d.ts +28 -0
  89. package/dist/runtime/themeBar.js +82 -0
  90. package/dist/runtime/themeBar.js.map +1 -0
  91. package/dist/runtime/themeChoice.d.ts +52 -0
  92. package/dist/runtime/themeChoice.js +69 -0
  93. package/dist/runtime/themeChoice.js.map +1 -0
  94. package/dist/runtime/themeComponents.d.ts +435 -0
  95. package/dist/runtime/themeComponents.js +476 -0
  96. package/dist/runtime/themeComponents.js.map +1 -0
  97. package/dist/runtime/themeDecor.d.ts +73 -0
  98. package/dist/runtime/themeDecor.js +133 -0
  99. package/dist/runtime/themeDecor.js.map +1 -0
  100. package/dist/runtime/themeDerive.d.ts +69 -0
  101. package/dist/runtime/themeDerive.js +117 -0
  102. package/dist/runtime/themeDerive.js.map +1 -0
  103. package/dist/runtime/themeDoctor.d.ts +52 -0
  104. package/dist/runtime/themeDoctor.js +112 -0
  105. package/dist/runtime/themeDoctor.js.map +1 -0
  106. package/dist/runtime/themeGuards.d.ts +60 -0
  107. package/dist/runtime/themeGuards.js +235 -0
  108. package/dist/runtime/themeGuards.js.map +1 -0
  109. package/dist/runtime/themeIcons.d.ts +130 -0
  110. package/dist/runtime/themeIcons.js +271 -0
  111. package/dist/runtime/themeIcons.js.map +1 -0
  112. package/dist/runtime/themeInk.d.ts +37 -0
  113. package/dist/runtime/themeInk.js +111 -0
  114. package/dist/runtime/themeInk.js.map +1 -0
  115. package/dist/runtime/themeInvariants.d.ts +39 -0
  116. package/dist/runtime/themeInvariants.js +273 -0
  117. package/dist/runtime/themeInvariants.js.map +1 -0
  118. package/dist/runtime/themeRuntime.d.ts +114 -0
  119. package/dist/runtime/themeRuntime.js +570 -0
  120. package/dist/runtime/themeRuntime.js.map +1 -0
  121. package/dist/runtime/themeSchema.d.ts +10 -0
  122. package/dist/runtime/themeSchema.js +150 -0
  123. package/dist/runtime/themeSchema.js.map +1 -0
  124. package/dist/runtime/themeSpec.d.ts +263 -0
  125. package/dist/runtime/themeSpec.js +435 -0
  126. package/dist/runtime/themeSpec.js.map +1 -0
  127. package/dist/runtime/themeTokens.d.ts +12 -0
  128. package/dist/runtime/themeTokens.js +14 -6
  129. package/dist/runtime/themeTokens.js.map +1 -1
  130. package/dist/runtime/themeVariants.d.ts +30 -0
  131. package/dist/runtime/themeVariants.js +53 -0
  132. package/dist/runtime/themeVariants.js.map +1 -0
  133. package/dist/runtime/ui.d.ts +192 -0
  134. package/dist/runtime/ui.js +926 -0
  135. package/dist/runtime/ui.js.map +1 -0
  136. package/dist/shell/InstallDialog.d.ts +40 -0
  137. package/dist/shell/InstallDialog.js +176 -0
  138. package/dist/shell/InstallDialog.js.map +1 -0
  139. package/dist/shell/StoreView.d.ts +78 -0
  140. package/dist/shell/StoreView.js +108 -0
  141. package/dist/shell/StoreView.js.map +1 -0
  142. package/dist/shell/addressModel.js.map +1 -1
  143. package/dist/shell/chrome.js.map +1 -1
  144. package/dist/shell/deckModel.d.ts +117 -0
  145. package/dist/shell/deckModel.js +267 -0
  146. package/dist/shell/deckModel.js.map +1 -0
  147. package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
  148. package/dist/shell/frame/AccountSwitcher.js +243 -0
  149. package/dist/shell/frame/AccountSwitcher.js.map +1 -0
  150. package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
  151. package/dist/shell/frame/AddColumnDialog.js +81 -0
  152. package/dist/shell/frame/AddColumnDialog.js.map +1 -0
  153. package/dist/shell/frame/AppMenu.d.ts +44 -0
  154. package/dist/shell/frame/AppMenu.js +721 -0
  155. package/dist/shell/frame/AppMenu.js.map +1 -0
  156. package/dist/shell/frame/CommandPalette.d.ts +7 -0
  157. package/dist/shell/frame/CommandPalette.js +118 -0
  158. package/dist/shell/frame/CommandPalette.js.map +1 -0
  159. package/dist/shell/frame/DeckView.d.ts +13 -0
  160. package/dist/shell/frame/DeckView.js +287 -0
  161. package/dist/shell/frame/DeckView.js.map +1 -0
  162. package/dist/shell/frame/FindBar.d.ts +10 -0
  163. package/dist/shell/frame/FindBar.js +108 -0
  164. package/dist/shell/frame/FindBar.js.map +1 -0
  165. package/dist/shell/frame/MediaPanel.d.ts +8 -0
  166. package/dist/shell/frame/MediaPanel.js +76 -0
  167. package/dist/shell/frame/MediaPanel.js.map +1 -0
  168. package/dist/shell/frame/NewTabPage.d.ts +9 -0
  169. package/dist/shell/frame/NewTabPage.js +71 -0
  170. package/dist/shell/frame/NewTabPage.js.map +1 -0
  171. package/dist/shell/frame/PaneTheme.d.ts +16 -0
  172. package/dist/shell/frame/PaneTheme.js +67 -0
  173. package/dist/shell/frame/PaneTheme.js.map +1 -0
  174. package/dist/shell/frame/ReportDialog.d.ts +3 -0
  175. package/dist/shell/frame/ReportDialog.js +95 -0
  176. package/dist/shell/frame/ReportDialog.js.map +1 -0
  177. package/dist/shell/frame/Shell.d.ts +9 -0
  178. package/dist/shell/frame/Shell.js +1139 -0
  179. package/dist/shell/frame/Shell.js.map +1 -0
  180. package/dist/shell/frame/Titlebar.d.ts +17 -0
  181. package/dist/shell/frame/Titlebar.js +79 -0
  182. package/dist/shell/frame/Titlebar.js.map +1 -0
  183. package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
  184. package/dist/shell/frame/TitlebarExtras.js +202 -0
  185. package/dist/shell/frame/TitlebarExtras.js.map +1 -0
  186. package/dist/shell/frame/WebPanel.d.ts +4 -0
  187. package/dist/shell/frame/WebPanel.js +185 -0
  188. package/dist/shell/frame/WebPanel.js.map +1 -0
  189. package/dist/shell/frame/accountModel.d.ts +49 -0
  190. package/dist/shell/frame/accountModel.js +67 -0
  191. package/dist/shell/frame/accountModel.js.map +1 -0
  192. package/dist/shell/frame/accountSwitcher.css +91 -0
  193. package/dist/shell/frame/appI18n.d.ts +44 -0
  194. package/dist/shell/frame/appI18n.js +64 -0
  195. package/dist/shell/frame/appI18n.js.map +1 -0
  196. package/dist/shell/frame/appMenu.css +127 -0
  197. package/dist/shell/frame/backupModel.d.ts +38 -0
  198. package/dist/shell/frame/backupModel.js +192 -0
  199. package/dist/shell/frame/backupModel.js.map +1 -0
  200. package/dist/shell/frame/boot.d.ts +8 -0
  201. package/dist/shell/frame/boot.js +37 -0
  202. package/dist/shell/frame/boot.js.map +1 -0
  203. package/dist/shell/frame/brand.d.ts +1 -0
  204. package/dist/shell/frame/brand.js +4 -0
  205. package/dist/shell/frame/brand.js.map +1 -0
  206. package/dist/shell/frame/bridge.d.ts +35 -0
  207. package/dist/shell/frame/bridge.js +70 -0
  208. package/dist/shell/frame/bridge.js.map +1 -0
  209. package/dist/shell/frame/chromeTheme.d.ts +47 -0
  210. package/dist/shell/frame/chromeTheme.js +118 -0
  211. package/dist/shell/frame/chromeTheme.js.map +1 -0
  212. package/dist/shell/frame/deck.css +209 -0
  213. package/dist/shell/frame/deckStore.d.ts +89 -0
  214. package/dist/shell/frame/deckStore.js +239 -0
  215. package/dist/shell/frame/deckStore.js.map +1 -0
  216. package/dist/shell/frame/devHost.d.ts +35 -0
  217. package/dist/shell/frame/devHost.js +80 -0
  218. package/dist/shell/frame/devHost.js.map +1 -0
  219. package/dist/shell/frame/devModel.d.ts +7 -0
  220. package/dist/shell/frame/devModel.js +17 -0
  221. package/dist/shell/frame/devModel.js.map +1 -0
  222. package/dist/shell/frame/diag.d.ts +7 -0
  223. package/dist/shell/frame/diag.js +39 -0
  224. package/dist/shell/frame/diag.js.map +1 -0
  225. package/dist/shell/frame/edges.css +159 -0
  226. package/dist/shell/frame/findBar.css +14 -0
  227. package/dist/shell/frame/frameMessages.d.ts +248 -0
  228. package/dist/shell/frame/frameMessages.js +252 -0
  229. package/dist/shell/frame/frameMessages.js.map +1 -0
  230. package/dist/shell/frame/hooks.d.ts +39 -0
  231. package/dist/shell/frame/hooks.js +97 -0
  232. package/dist/shell/frame/hooks.js.map +1 -0
  233. package/dist/shell/frame/i18n.d.ts +27 -0
  234. package/dist/shell/frame/i18n.js +66 -0
  235. package/dist/shell/frame/i18n.js.map +1 -0
  236. package/dist/shell/frame/iconPack.d.ts +11 -0
  237. package/dist/shell/frame/iconPack.js +45 -0
  238. package/dist/shell/frame/iconPack.js.map +1 -0
  239. package/dist/shell/frame/icons.d.ts +71 -0
  240. package/dist/shell/frame/icons.js +75 -0
  241. package/dist/shell/frame/icons.js.map +1 -0
  242. package/dist/shell/frame/index.d.ts +34 -0
  243. package/dist/shell/frame/index.js +43 -0
  244. package/dist/shell/frame/index.js.map +1 -0
  245. package/dist/shell/frame/language.d.ts +58 -0
  246. package/dist/shell/frame/language.js +165 -0
  247. package/dist/shell/frame/language.js.map +1 -0
  248. package/dist/shell/frame/mediaModel.d.ts +47 -0
  249. package/dist/shell/frame/mediaModel.js +67 -0
  250. package/dist/shell/frame/mediaModel.js.map +1 -0
  251. package/dist/shell/frame/menuMessages.en.json +96 -0
  252. package/dist/shell/frame/menuModel.d.ts +319 -0
  253. package/dist/shell/frame/menuModel.js +301 -0
  254. package/dist/shell/frame/menuModel.js.map +1 -0
  255. package/dist/shell/frame/nativeMenu.d.ts +5 -0
  256. package/dist/shell/frame/nativeMenu.js +178 -0
  257. package/dist/shell/frame/nativeMenu.js.map +1 -0
  258. package/dist/shell/frame/nativeMenuModel.d.ts +102 -0
  259. package/dist/shell/frame/nativeMenuModel.js +186 -0
  260. package/dist/shell/frame/nativeMenuModel.js.map +1 -0
  261. package/dist/shell/frame/paletteModel.d.ts +139 -0
  262. package/dist/shell/frame/paletteModel.js +114 -0
  263. package/dist/shell/frame/paletteModel.js.map +1 -0
  264. package/dist/shell/frame/paneTheme.css +9 -0
  265. package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
  266. package/dist/shell/frame/pluginCommandStore.js +70 -0
  267. package/dist/shell/frame/pluginCommandStore.js.map +1 -0
  268. package/dist/shell/frame/reportModel.d.ts +52 -0
  269. package/dist/shell/frame/reportModel.js +105 -0
  270. package/dist/shell/frame/reportModel.js.map +1 -0
  271. package/dist/shell/frame/safeStore.d.ts +7 -0
  272. package/dist/shell/frame/safeStore.js +40 -0
  273. package/dist/shell/frame/safeStore.js.map +1 -0
  274. package/dist/shell/frame/searchInput.d.ts +2 -0
  275. package/dist/shell/frame/searchInput.js +11 -0
  276. package/dist/shell/frame/searchInput.js.map +1 -0
  277. package/dist/shell/frame/shell.css +634 -0
  278. package/dist/shell/frame/site.d.ts +206 -0
  279. package/dist/shell/frame/site.js +22 -0
  280. package/dist/shell/frame/site.js.map +1 -0
  281. package/dist/shell/frame/state.d.ts +101 -0
  282. package/dist/shell/frame/state.js +286 -0
  283. package/dist/shell/frame/state.js.map +1 -0
  284. package/dist/shell/frame/syncGate.d.ts +10 -0
  285. package/dist/shell/frame/syncGate.js +36 -0
  286. package/dist/shell/frame/syncGate.js.map +1 -0
  287. package/dist/shell/frame/syncHost.d.ts +35 -0
  288. package/dist/shell/frame/syncHost.js +85 -0
  289. package/dist/shell/frame/syncHost.js.map +1 -0
  290. package/dist/shell/frame/tabStill.d.ts +2 -0
  291. package/dist/shell/frame/tabStill.js +62 -0
  292. package/dist/shell/frame/tabStill.js.map +1 -0
  293. package/dist/shell/frame/themeScopes.d.ts +29 -0
  294. package/dist/shell/frame/themeScopes.js +61 -0
  295. package/dist/shell/frame/themeScopes.js.map +1 -0
  296. package/dist/shell/frame/themeStore.d.ts +99 -0
  297. package/dist/shell/frame/themeStore.js +267 -0
  298. package/dist/shell/frame/themeStore.js.map +1 -0
  299. package/dist/shell/frame/windowBinding.d.ts +2 -0
  300. package/dist/shell/frame/windowBinding.js +7 -0
  301. package/dist/shell/frame/windowBinding.js.map +1 -0
  302. package/dist/shell/frame/workspaceModel.d.ts +82 -0
  303. package/dist/shell/frame/workspaceModel.js +250 -0
  304. package/dist/shell/frame/workspaceModel.js.map +1 -0
  305. package/dist/shell/frame/workspaces.css +84 -0
  306. package/dist/shell/frame/workspaces.d.ts +22 -0
  307. package/dist/shell/frame/workspaces.js +125 -0
  308. package/dist/shell/frame/workspaces.js.map +1 -0
  309. package/dist/shell/frame/zoomStore.d.ts +10 -0
  310. package/dist/shell/frame/zoomStore.js +65 -0
  311. package/dist/shell/frame/zoomStore.js.map +1 -0
  312. package/dist/shell/installController.d.ts +137 -0
  313. package/dist/shell/installController.js +172 -0
  314. package/dist/shell/installController.js.map +1 -0
  315. package/dist/shell/installerMessages.d.ts +30 -0
  316. package/dist/shell/installerMessages.js +36 -0
  317. package/dist/shell/installerMessages.js.map +1 -0
  318. package/dist/shell/linkDrop.js.map +1 -1
  319. package/dist/shell/messages.d.ts +16 -0
  320. package/dist/shell/messages.js +27 -0
  321. package/dist/shell/messages.js.map +1 -0
  322. package/dist/shell/palette.js.map +1 -1
  323. package/dist/shell/paneModel.d.ts +22 -0
  324. package/dist/shell/paneModel.js +24 -1
  325. package/dist/shell/paneModel.js.map +1 -1
  326. package/dist/shell/panel/Appearance.d.ts +8 -0
  327. package/dist/shell/panel/Appearance.js +265 -0
  328. package/dist/shell/panel/Appearance.js.map +1 -0
  329. package/dist/shell/panel/BackupPanel.d.ts +5 -0
  330. package/dist/shell/panel/BackupPanel.js +198 -0
  331. package/dist/shell/panel/BackupPanel.js.map +1 -0
  332. package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
  333. package/dist/shell/panel/DeveloperPanel.js +51 -0
  334. package/dist/shell/panel/DeveloperPanel.js.map +1 -0
  335. package/dist/shell/panel/FeatureToggles.d.ts +13 -0
  336. package/dist/shell/panel/FeatureToggles.js +42 -0
  337. package/dist/shell/panel/FeatureToggles.js.map +1 -0
  338. package/dist/shell/panel/Home.d.ts +3 -0
  339. package/dist/shell/panel/Home.js +23 -0
  340. package/dist/shell/panel/Home.js.map +1 -0
  341. package/dist/shell/panel/IconPackInstall.d.ts +15 -0
  342. package/dist/shell/panel/IconPackInstall.js +41 -0
  343. package/dist/shell/panel/IconPackInstall.js.map +1 -0
  344. package/dist/shell/panel/LanguageSettings.d.ts +1 -0
  345. package/dist/shell/panel/LanguageSettings.js +54 -0
  346. package/dist/shell/panel/LanguageSettings.js.map +1 -0
  347. package/dist/shell/panel/MakePanel.d.ts +3 -0
  348. package/dist/shell/panel/MakePanel.js +237 -0
  349. package/dist/shell/panel/MakePanel.js.map +1 -0
  350. package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
  351. package/dist/shell/panel/MarkdownDoc.js +35 -0
  352. package/dist/shell/panel/MarkdownDoc.js.map +1 -0
  353. package/dist/shell/panel/Modes.d.ts +40 -0
  354. package/dist/shell/panel/Modes.js +270 -0
  355. package/dist/shell/panel/Modes.js.map +1 -0
  356. package/dist/shell/panel/NavIcon.d.ts +4 -0
  357. package/dist/shell/panel/NavIcon.js +6 -0
  358. package/dist/shell/panel/NavIcon.js.map +1 -0
  359. package/dist/shell/panel/Panel.d.ts +7 -0
  360. package/dist/shell/panel/Panel.js +139 -0
  361. package/dist/shell/panel/Panel.js.map +1 -0
  362. package/dist/shell/panel/PluginFeatures.d.ts +24 -0
  363. package/dist/shell/panel/PluginFeatures.js +165 -0
  364. package/dist/shell/panel/PluginFeatures.js.map +1 -0
  365. package/dist/shell/panel/Plugins.d.ts +33 -0
  366. package/dist/shell/panel/Plugins.js +112 -0
  367. package/dist/shell/panel/Plugins.js.map +1 -0
  368. package/dist/shell/panel/PowerSettings.d.ts +4 -0
  369. package/dist/shell/panel/PowerSettings.js +52 -0
  370. package/dist/shell/panel/PowerSettings.js.map +1 -0
  371. package/dist/shell/panel/Settings.d.ts +23 -0
  372. package/dist/shell/panel/Settings.js +117 -0
  373. package/dist/shell/panel/Settings.js.map +1 -0
  374. package/dist/shell/panel/ShareSetup.d.ts +8 -0
  375. package/dist/shell/panel/ShareSetup.js +130 -0
  376. package/dist/shell/panel/ShareSetup.js.map +1 -0
  377. package/dist/shell/panel/StoreSection.d.ts +7 -0
  378. package/dist/shell/panel/StoreSection.js +78 -0
  379. package/dist/shell/panel/StoreSection.js.map +1 -0
  380. package/dist/shell/panel/StringPacks.d.ts +20 -0
  381. package/dist/shell/panel/StringPacks.js +131 -0
  382. package/dist/shell/panel/StringPacks.js.map +1 -0
  383. package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
  384. package/dist/shell/panel/ThemeBuilder.js +205 -0
  385. package/dist/shell/panel/ThemeBuilder.js.map +1 -0
  386. package/dist/shell/panel/backup.css +34 -0
  387. package/dist/shell/panel/builder.css +240 -0
  388. package/dist/shell/panel/builderModel.d.ts +55 -0
  389. package/dist/shell/panel/builderModel.js +95 -0
  390. package/dist/shell/panel/builderModel.js.map +1 -0
  391. package/dist/shell/panel/compare.d.ts +10 -0
  392. package/dist/shell/panel/compare.js +51 -0
  393. package/dist/shell/panel/compare.js.map +1 -0
  394. package/dist/shell/panel/controls.d.ts +135 -0
  395. package/dist/shell/panel/controls.js +213 -0
  396. package/dist/shell/panel/controls.js.map +1 -0
  397. package/dist/shell/panel/featureModel.d.ts +69 -0
  398. package/dist/shell/panel/featureModel.js +79 -0
  399. package/dist/shell/panel/featureModel.js.map +1 -0
  400. package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
  401. package/dist/shell/panel/fonts/FontBrowser.js +189 -0
  402. package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
  403. package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
  404. package/dist/shell/panel/fonts/FontRoles.js +77 -0
  405. package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
  406. package/dist/shell/panel/fonts/catalog.d.ts +37 -0
  407. package/dist/shell/panel/fonts/catalog.js +68 -0
  408. package/dist/shell/panel/fonts/catalog.js.map +1 -0
  409. package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
  410. package/dist/shell/panel/index.d.ts +20 -0
  411. package/dist/shell/panel/index.js +34 -0
  412. package/dist/shell/panel/index.js.map +1 -0
  413. package/dist/shell/panel/languageModel.d.ts +5 -0
  414. package/dist/shell/panel/languageModel.js +7 -0
  415. package/dist/shell/panel/languageModel.js.map +1 -0
  416. package/dist/shell/panel/make.css +73 -0
  417. package/dist/shell/panel/makeModel.d.ts +32 -0
  418. package/dist/shell/panel/makeModel.js +84 -0
  419. package/dist/shell/panel/makeModel.js.map +1 -0
  420. package/dist/shell/panel/markdown.d.ts +46 -0
  421. package/dist/shell/panel/markdown.js +100 -0
  422. package/dist/shell/panel/markdown.js.map +1 -0
  423. package/dist/shell/panel/nav.d.ts +12 -0
  424. package/dist/shell/panel/nav.js +50 -0
  425. package/dist/shell/panel/nav.js.map +1 -0
  426. package/dist/shell/panel/panel.css +401 -0
  427. package/dist/shell/panel/panelMessages.d.ts +803 -0
  428. package/dist/shell/panel/panelMessages.js +779 -0
  429. package/dist/shell/panel/panelMessages.js.map +1 -0
  430. package/dist/shell/panel/plugins.css +59 -0
  431. package/dist/shell/panel/setupModel.d.ts +87 -0
  432. package/dist/shell/panel/setupModel.js +152 -0
  433. package/dist/shell/panel/setupModel.js.map +1 -0
  434. package/dist/shell/panel/site.d.ts +259 -0
  435. package/dist/shell/panel/site.js +25 -0
  436. package/dist/shell/panel/site.js.map +1 -0
  437. package/dist/shell/panel/strings.css +7 -0
  438. package/dist/shell/panel/themes.d.ts +10 -0
  439. package/dist/shell/panel/themes.js +8 -0
  440. package/dist/shell/panel/themes.js.map +1 -0
  441. package/dist/shell/profileModel.d.ts +3 -2
  442. package/dist/shell/profileModel.js +7 -5
  443. package/dist/shell/profileModel.js.map +1 -1
  444. package/dist/shell/store.css +250 -0
  445. package/dist/shell/storeMessages.d.ts +193 -0
  446. package/dist/shell/storeMessages.js +196 -0
  447. package/dist/shell/storeMessages.js.map +1 -0
  448. package/dist/shell/storeModel.d.ts +205 -0
  449. package/dist/shell/storeModel.js +146 -0
  450. package/dist/shell/storeModel.js.map +1 -0
  451. package/dist/shell/stringPacksModel.d.ts +44 -0
  452. package/dist/shell/stringPacksModel.js +99 -0
  453. package/dist/shell/stringPacksModel.js.map +1 -0
  454. package/dist/shell/updateModel.d.ts +2 -1
  455. package/dist/shell/updateModel.js +5 -4
  456. package/dist/shell/updateModel.js.map +1 -1
  457. package/dist/shell/windowControls.d.ts +4 -0
  458. package/dist/shell/windowControls.js +5 -0
  459. package/dist/shell/windowControls.js.map +1 -1
  460. package/i18n-config.schema.json +29 -0
  461. package/i18n-meta.schema.json +26 -0
  462. package/i18n.schema.json +42 -0
  463. package/icons.schema.json +655 -0
  464. package/languages.schema.json +23 -0
  465. package/locales/ar-x-fm.json +11 -0
  466. package/locales/ar.json +1388 -0
  467. package/locales/bg.json +1387 -0
  468. package/locales/bn.json +1387 -0
  469. package/locales/ca.json +1387 -0
  470. package/locales/cs.json +1387 -0
  471. package/locales/da.json +1387 -0
  472. package/locales/de.json +1387 -0
  473. package/locales/el.json +1387 -0
  474. package/locales/en-GB.json +27 -0
  475. package/locales/en.json +1386 -0
  476. package/locales/en.meta.json +51 -0
  477. package/locales/es.json +1387 -0
  478. package/locales/eu.json +1387 -0
  479. package/locales/fa.json +1388 -0
  480. package/locales/fi.json +1387 -0
  481. package/locales/fil.json +1387 -0
  482. package/locales/fr.json +1387 -0
  483. package/locales/ga.json +1387 -0
  484. package/locales/gl.json +1387 -0
  485. package/locales/gu.json +1387 -0
  486. package/locales/ha.json +1387 -0
  487. package/locales/he.json +1388 -0
  488. package/locales/hi.json +1387 -0
  489. package/locales/hr.json +1387 -0
  490. package/locales/hu.json +1387 -0
  491. package/locales/id.json +1387 -0
  492. package/locales/ig.json +1387 -0
  493. package/locales/it.json +1387 -0
  494. package/locales/ja.json +1387 -0
  495. package/locales/kn.json +1387 -0
  496. package/locales/ko.json +1387 -0
  497. package/locales/mr.json +1387 -0
  498. package/locales/ms.json +1387 -0
  499. package/locales/nb.json +1387 -0
  500. package/locales/nl.json +1387 -0
  501. package/locales/pl.json +1387 -0
  502. package/locales/pt.json +1387 -0
  503. package/locales/ro.json +1387 -0
  504. package/locales/ru.json +1387 -0
  505. package/locales/sk.json +1387 -0
  506. package/locales/sr.json +1387 -0
  507. package/locales/sv.json +1387 -0
  508. package/locales/ta.json +1387 -0
  509. package/locales/th.json +1387 -0
  510. package/locales/tr.json +1387 -0
  511. package/locales/uk.json +1387 -0
  512. package/locales/ur.json +1388 -0
  513. package/locales/vi.json +1387 -0
  514. package/locales/yo.json +1387 -0
  515. package/locales/zh-Hans.json +1387 -0
  516. package/locales/zh-Hant.json +1387 -0
  517. package/package.json +138 -5
  518. package/store-catalog.schema.json +78 -0
  519. package/theme.schema.json +4668 -0
  520. package/windows/installer.nsi +946 -0
  521. package/windows/languages/Basque.nsh +28 -0
  522. package/windows/languages/Catalan.nsh +28 -0
  523. package/windows/languages/Croatian.nsh +28 -0
  524. package/windows/languages/Czech.nsh +28 -0
  525. package/windows/languages/Danish.nsh +28 -0
  526. package/windows/languages/Finnish.nsh +28 -0
  527. package/windows/languages/Galician.nsh +28 -0
  528. package/windows/languages/Greek.nsh +28 -0
  529. package/windows/languages/Hungarian.nsh +28 -0
  530. package/windows/languages/Indonesian.nsh +28 -0
  531. package/windows/languages/Irish.nsh +28 -0
  532. package/windows/languages/Malay.nsh +28 -0
  533. package/windows/languages/Polish.nsh +28 -0
  534. package/windows/languages/Romanian.nsh +28 -0
  535. package/windows/languages/Serbian.nsh +28 -0
  536. package/windows/languages/Slovak.nsh +28 -0
  537. package/windows/languages/Thai.nsh +28 -0
@@ -0,0 +1,259 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { FeatureTable } from '../../runtime/featureTable.ts';
3
+ import type { ThemeCatalog, ThemeChoice } from '../../runtime/themeChoice.ts';
4
+ import type { FontChoice, ThemeColors, ThemeSpec } from '../../runtime/themeSpec.ts';
5
+ import type { ResolvedTheme } from '../../runtime/themeApi.ts';
6
+ import type { InstallController } from '../installController.ts';
7
+ import type { ThemeStore } from '../frame/themeStore.ts';
8
+ /** A short message at the bottom of the panel (`error`: stays longer, announced as an alert). */
9
+ export type Notify = (text: string, error?: boolean) => void;
10
+ /** What every section gets. */
11
+ export type SectionProps = {
12
+ notify: Notify;
13
+ /** Shows another section of the panel (built-in or the site's). */
14
+ openSection(id: string): void;
15
+ };
16
+ /** The sections the framework brings; each shows only when the app serves what it needs. */
17
+ export declare const BUILTIN_SECTIONS: readonly ["home", "themes", "builder", "plugins", "store", "make", "accounts", "power", "settings", "backup", "developer", "updates"];
18
+ export type BuiltinSection = typeof BUILTIN_SECTIONS[number];
19
+ /** A section of the app's own (X: Tweaks, Drafts). */
20
+ export type PanelSection = {
21
+ id: string;
22
+ label(): string;
23
+ /** The nav icon: a 16x16 stroke path (`d`). */
24
+ icon: string;
25
+ component: ComponentType<SectionProps>;
26
+ /** Its rows also show in the settings search (they filter themselves with `useSettingsQuery`). */
27
+ searchable?: boolean;
28
+ };
29
+ /** The home page: the hero, the highlight cards and the About block, in the app's words. */
30
+ export type PanelHome = {
31
+ /** The line above the title: the brand name, then what it is for ("wayBetter" + " for X"). */
32
+ kicker: {
33
+ name: string;
34
+ rest: string;
35
+ };
36
+ /** The title in three parts; the middle one is emphasized. */
37
+ title(): [string, string, string];
38
+ lede(): string;
39
+ /** Chips after the version chip ("Free & open source", "GPL-3.0"). */
40
+ chips?(): string[];
41
+ /** Hero buttons: each opens a section; the first is the primary one. */
42
+ actions?: ReadonlyArray<{
43
+ section: string;
44
+ label(): string;
45
+ }>;
46
+ /** Cards under the hero: each opens a section and carries that section's icon. */
47
+ highlights?: ReadonlyArray<{
48
+ section: string;
49
+ title(): string;
50
+ text(): string;
51
+ }>;
52
+ about?: {
53
+ title(): string;
54
+ text(): string;
55
+ /** A numbered list (the framework's layers). */
56
+ layers?: ReadonlyArray<{
57
+ name(): string;
58
+ text(): string;
59
+ }>;
60
+ /** "Made by @someone · site": the link opens in the system browser. */
61
+ foot?: {
62
+ text(): string;
63
+ by: string;
64
+ link?: {
65
+ label: string;
66
+ url: string;
67
+ };
68
+ };
69
+ };
70
+ };
71
+ /** The app's themes in the panel: Appearance, the Theme Builder, font pickers, Make's theme view. */
72
+ export type PanelThemes = {
73
+ /** The app's theme store (the same one the frame gets as `site.themes`). */
74
+ store: ThemeStore<ThemeChoice, ThemeSpec>;
75
+ /** The site's built-in themes (`createThemeCatalog`); the first is the site's own look. */
76
+ catalog: ThemeCatalog;
77
+ /** Accent swatches offered in Appearance. */
78
+ accents: readonly string[];
79
+ /** A miniature of the site drawn from a theme document (the gallery, the builder, the install screen). */
80
+ Preview: ComponentType<{
81
+ theme: ThemeSpec;
82
+ className?: string;
83
+ }>;
84
+ /** The name of the site's own typeface, shown where a font role keeps it ("X's Chirp"). */
85
+ siteFont: string;
86
+ /** Named font stacks offered besides Google Fonts (default: the runtime's `FONT_CHOICES`). */
87
+ fontChoices?: readonly FontChoice[];
88
+ /** The palette a draft starts from when a theme keeps the site's own colors. */
89
+ draftColors: Pick<ThemeColors, 'bg' | 'text' | 'accent'>;
90
+ /** Swatches for the builder's three base colors (defaults are neutral). */
91
+ baseSwatches?: {
92
+ bg: string[];
93
+ text: string[];
94
+ accent: string[];
95
+ };
96
+ /** File name suffix of an exported theme (default `.theme.json`). */
97
+ fileSuffix?: string;
98
+ /** Icon packs the owner can pick in Appearance (theme engine v2); absent: no Icons row. */
99
+ iconPacks?: ReadonlyArray<{
100
+ id: string;
101
+ name: string;
102
+ description?: string;
103
+ }>;
104
+ /** The builder's chrome preview: tab titles and the address chip. */
105
+ chromePreview?: {
106
+ tabs: [string, string, string];
107
+ chip: string;
108
+ page: string;
109
+ };
110
+ /**
111
+ * Make's theme view: the active theme as plugins see it. `modes` are the site's own display modes
112
+ * (X: Default, Dim, Lights out), offered while the theme keeps the site's colors.
113
+ */
114
+ resolved?(choice: ThemeChoice, mode: string): ResolvedTheme;
115
+ modes?: {
116
+ label(): string;
117
+ initial: string;
118
+ options: ReadonlyArray<{
119
+ value: string;
120
+ label(): string;
121
+ }>;
122
+ };
123
+ };
124
+ /** A plugin example in Make's editor. */
125
+ export type PluginExample = {
126
+ id: string;
127
+ title: string;
128
+ blurb: string;
129
+ file: string;
130
+ source: string;
131
+ };
132
+ /** Make: example plugins, a theme file and the bundled docs, all the app's. */
133
+ export type PanelMake = {
134
+ examples: readonly PluginExample[];
135
+ /** An example theme file (JSON text) and the name it downloads as. */
136
+ themeExample?: {
137
+ file: string;
138
+ source: string;
139
+ };
140
+ /** Bundled Markdown docs by file name; the first is opened by default. */
141
+ docs?: Readonly<Record<string, string>>;
142
+ /** The page runtime's global in the code samples (default `wayBetter`). */
143
+ global?: string;
144
+ };
145
+ /** A feature flag group for `FeatureToggles` (the app's page tweaks). */
146
+ export type FeatureGroup = {
147
+ id: string;
148
+ features: readonly string[];
149
+ };
150
+ /** One language the app has a catalog for (the app's `languages.json`). */
151
+ export type PanelLanguage = {
152
+ code: string;
153
+ name: string;
154
+ englishName: string;
155
+ dir: 'ltr' | 'rtl';
156
+ status: 'source' | 'machine' | 'reviewed';
157
+ /** `community` languages are listed apart and never chosen automatically. */
158
+ tier: 'supported' | 'community';
159
+ coverage: number;
160
+ };
161
+ /** The app's language state (frame/language.ts `createLanguage`). */
162
+ export type PanelLanguages = {
163
+ list: readonly PanelLanguage[];
164
+ state(): {
165
+ preference: string;
166
+ siteLang: string | null;
167
+ system: readonly string[];
168
+ locale: string;
169
+ community: string | null;
170
+ };
171
+ subscribe(listener: () => void): () => void;
172
+ set(preference: string): Promise<void>;
173
+ /** The contributor guide ("Help translate"), opened in the system browser. */
174
+ translateUrl?: string;
175
+ };
176
+ export type PanelSite = {
177
+ /** The header: the brand's name and logo (an image URL). */
178
+ brand: {
179
+ name: string;
180
+ logo: string;
181
+ };
182
+ home: PanelHome;
183
+ /** The app's version for the home page's chip. */
184
+ version?(): Promise<string>;
185
+ /** The app's own sections. */
186
+ sections?: readonly PanelSection[];
187
+ /** Nav order (built-in and site ids). Default: the built-in ones, then the site's. */
188
+ order?: readonly string[];
189
+ /** Themes (Appearance, Theme Builder); omit for an app without them. */
190
+ themes?: PanelThemes;
191
+ /** What the app adds to Appearance, above the custom CSS editor (X: its logo and wording). */
192
+ appearance?: {
193
+ extra?: ReadonlyArray<ComponentType<SectionProps>>;
194
+ };
195
+ /**
196
+ * Area plugins and modes: the app's feature table (waybetter/runtime/featureTable). With it the
197
+ * Plugins section lists one card per area with a toggle per feature, then the core flags as
198
+ * "Fixes"; with modes in the table, the first-run screen and Settings offer them.
199
+ */
200
+ features?: {
201
+ table: FeatureTable;
202
+ /** Core flags that have a control of their own elsewhere (not listed under Fixes). */
203
+ elsewhere?: readonly string[];
204
+ /** Runs after a mode was chosen and its flags were saved (the app's own step for that mode). */
205
+ onMode?(mode: string): void | Promise<void>;
206
+ /** The illustration on a mode's card of the first-run screen (default: plain bars). */
207
+ ModeArt?: ComponentType<{
208
+ mode: string;
209
+ }>;
210
+ };
211
+ /** The install screen's controller: the Store section, and removing a plugin from the list. */
212
+ store?: {
213
+ controller: InstallController<ThemeSpec>;
214
+ };
215
+ make?: PanelMake;
216
+ /** The language picker in Settings; omit for an app in one language. */
217
+ languages?: PanelLanguages;
218
+ /** Settings: keyword alerts (`alerts_get/set`) and what the app adds under the framework's rows. */
219
+ settings?: {
220
+ alerts?: boolean;
221
+ extra?: ReadonlyArray<ComponentType<SectionProps>>;
222
+ /** Extra search words for the "links to the site's pages" row ("x twitter"). */
223
+ linkKeywords?: string;
224
+ };
225
+ /** Placeholder CSS in the editors, written with the site's own selectors: custom CSS, a theme's CSS, the builder's. */
226
+ cssExamples?: {
227
+ custom?: string;
228
+ theme?: string;
229
+ builder?: string;
230
+ };
231
+ /** Power User (with `site.deck`): what the settings list besides the frame's own. */
232
+ power?: {
233
+ /** Column flags offered as deck defaults (default: the flags `site.deck.defaultFlags` names). */
234
+ defaultFlags?: readonly string[];
235
+ /** What one column was measured to take, in MB (shown with the columns-per-page guard). */
236
+ memory?: {
237
+ perColumn: number;
238
+ range: string;
239
+ };
240
+ /** A line above the deck keys (which of the site's own keys keep working in a column). */
241
+ keysHint?(): string;
242
+ };
243
+ /** Backup & export (`backup_*`); the sync part needs the frame's `sync` feature. */
244
+ backup?: boolean;
245
+ /**
246
+ * "Share my setup" under Backup & sync (ShareSetup.tsx; needs `features`): the app's id, which a
247
+ * setup carries so it never applies to another app. Absent: no such section.
248
+ */
249
+ setup?: {
250
+ app: string;
251
+ };
252
+ /** The native updater (`app_ready`, `update_status`, `apply_update`). */
253
+ updates?: boolean;
254
+ };
255
+ /** Sets the panel's site (createPanel). */
256
+ export declare function configurePanel(value: PanelSite): void;
257
+ export declare function panelSite(): PanelSite;
258
+ /** The app's themes (Appearance, the builder and the font pickers only render with them). */
259
+ export declare function panelThemes(): PanelThemes;
@@ -0,0 +1,25 @@
1
+ // What a wayBetter app tells the panel (its own tab: settings, themes, plugins, the Store, Make,
2
+ // accounts, backup, developer mode, updates): the brand and the home page's words, its theme
3
+ // catalog and preview, its own sections and what its native side serves. `createPanel(site)` sets
4
+ // it; every panel module reads it through `panelSite()`. The shell frame's site (`site()`,
5
+ // frame/site.ts) is read too: the deck (Power User), the media panel and the native features.
6
+ /** The sections the framework brings; each shows only when the app serves what it needs. */
7
+ export const BUILTIN_SECTIONS = ['home', 'themes', 'builder', 'plugins', 'store', 'make', 'accounts', 'power', 'settings', 'backup', 'developer', 'updates'];
8
+ let current = null;
9
+ /** Sets the panel's site (createPanel). */
10
+ export function configurePanel(value) {
11
+ current = value;
12
+ }
13
+ export function panelSite() {
14
+ if (!current)
15
+ throw new Error('wayBetter panel: createPanel(site) first');
16
+ return current;
17
+ }
18
+ /** The app's themes (Appearance, the builder and the font pickers only render with them). */
19
+ export function panelThemes() {
20
+ const themes = panelSite().themes;
21
+ if (!themes)
22
+ throw new Error('wayBetter panel: this app has no themes (PanelSite.themes)');
23
+ return themes;
24
+ }
25
+ //# sourceMappingURL=site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/site.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,6FAA6F;AAC7F,kGAAkG;AAClG,2FAA2F;AAC3F,8FAA8F;AAoB9F,4FAA4F;AAC5F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AA0KtK,IAAI,OAAO,GAAqB,IAAI,CAAC;AAErC,2CAA2C;AAC3C,MAAM,UAAU,cAAc,CAAC,KAAgB;IAC7C,OAAO,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC1E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAC3F,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["// What a wayBetter app tells the panel (its own tab: settings, themes, plugins, the Store, Make,\n// accounts, backup, developer mode, updates): the brand and the home page's words, its theme\n// catalog and preview, its own sections and what its native side serves. `createPanel(site)` sets\n// it; every panel module reads it through `panelSite()`. The shell frame's site (`site()`,\n// frame/site.ts) is read too: the deck (Power User), the media panel and the native features.\n\nimport type { ComponentType } from 'react';\nimport type { FeatureTable } from '../../../runtime/src/featureTable.ts';\nimport type { ThemeCatalog, ThemeChoice } from '../../../runtime/src/themeChoice.ts';\nimport type { FontChoice, ThemeColors, ThemeSpec } from '../../../runtime/src/themeSpec.ts';\nimport type { ResolvedTheme } from '../../../runtime/src/themeApi.ts';\nimport type { InstallController } from '../installController.ts';\nimport type { ThemeStore } from '../frame/themeStore.ts';\n\n/** A short message at the bottom of the panel (`error`: stays longer, announced as an alert). */\nexport type Notify = (text: string, error?: boolean) => void;\n\n/** What every section gets. */\nexport type SectionProps = {\n notify: Notify;\n /** Shows another section of the panel (built-in or the site's). */\n openSection(id: string): void;\n};\n\n/** The sections the framework brings; each shows only when the app serves what it needs. */\nexport const BUILTIN_SECTIONS = ['home', 'themes', 'builder', 'plugins', 'store', 'make', 'accounts', 'power', 'settings', 'backup', 'developer', 'updates'] as const;\nexport type BuiltinSection = typeof BUILTIN_SECTIONS[number];\n\n/** A section of the app's own (X: Tweaks, Drafts). */\nexport type PanelSection = {\n id: string;\n label(): string;\n /** The nav icon: a 16x16 stroke path (`d`). */\n icon: string;\n component: ComponentType<SectionProps>;\n /** Its rows also show in the settings search (they filter themselves with `useSettingsQuery`). */\n searchable?: boolean;\n};\n\n/** The home page: the hero, the highlight cards and the About block, in the app's words. */\nexport type PanelHome = {\n /** The line above the title: the brand name, then what it is for (\"wayBetter\" + \" for X\"). */\n kicker: { name: string; rest: string };\n /** The title in three parts; the middle one is emphasized. */\n title(): [string, string, string];\n lede(): string;\n /** Chips after the version chip (\"Free & open source\", \"GPL-3.0\"). */\n chips?(): string[];\n /** Hero buttons: each opens a section; the first is the primary one. */\n actions?: ReadonlyArray<{ section: string; label(): string }>;\n /** Cards under the hero: each opens a section and carries that section's icon. */\n highlights?: ReadonlyArray<{ section: string; title(): string; text(): string }>;\n about?: {\n title(): string;\n text(): string;\n /** A numbered list (the framework's layers). */\n layers?: ReadonlyArray<{ name(): string; text(): string }>;\n /** \"Made by @someone · site\": the link opens in the system browser. */\n foot?: { text(): string; by: string; link?: { label: string; url: string } };\n };\n};\n\n/** The app's themes in the panel: Appearance, the Theme Builder, font pickers, Make's theme view. */\nexport type PanelThemes = {\n /** The app's theme store (the same one the frame gets as `site.themes`). */\n store: ThemeStore<ThemeChoice, ThemeSpec>;\n /** The site's built-in themes (`createThemeCatalog`); the first is the site's own look. */\n catalog: ThemeCatalog;\n /** Accent swatches offered in Appearance. */\n accents: readonly string[];\n /** A miniature of the site drawn from a theme document (the gallery, the builder, the install screen). */\n Preview: ComponentType<{ theme: ThemeSpec; className?: string }>;\n /** The name of the site's own typeface, shown where a font role keeps it (\"X's Chirp\"). */\n siteFont: string;\n /** Named font stacks offered besides Google Fonts (default: the runtime's `FONT_CHOICES`). */\n fontChoices?: readonly FontChoice[];\n /** The palette a draft starts from when a theme keeps the site's own colors. */\n draftColors: Pick<ThemeColors, 'bg' | 'text' | 'accent'>;\n /** Swatches for the builder's three base colors (defaults are neutral). */\n baseSwatches?: { bg: string[]; text: string[]; accent: string[] };\n /** File name suffix of an exported theme (default `.theme.json`). */\n fileSuffix?: string;\n /** Icon packs the owner can pick in Appearance (theme engine v2); absent: no Icons row. */\n iconPacks?: ReadonlyArray<{ id: string; name: string; description?: string }>;\n /** The builder's chrome preview: tab titles and the address chip. */\n chromePreview?: { tabs: [string, string, string]; chip: string; page: string };\n /**\n * Make's theme view: the active theme as plugins see it. `modes` are the site's own display modes\n * (X: Default, Dim, Lights out), offered while the theme keeps the site's colors.\n */\n resolved?(choice: ThemeChoice, mode: string): ResolvedTheme;\n modes?: { label(): string; initial: string; options: ReadonlyArray<{ value: string; label(): string }> };\n};\n\n/** A plugin example in Make's editor. */\nexport type PluginExample = { id: string; title: string; blurb: string; file: string; source: string };\n\n/** Make: example plugins, a theme file and the bundled docs, all the app's. */\nexport type PanelMake = {\n examples: readonly PluginExample[];\n /** An example theme file (JSON text) and the name it downloads as. */\n themeExample?: { file: string; source: string };\n /** Bundled Markdown docs by file name; the first is opened by default. */\n docs?: Readonly<Record<string, string>>;\n /** The page runtime's global in the code samples (default `wayBetter`). */\n global?: string;\n};\n\n/** A feature flag group for `FeatureToggles` (the app's page tweaks). */\nexport type FeatureGroup = { id: string; features: readonly string[] };\n\n/** One language the app has a catalog for (the app's `languages.json`). */\nexport type PanelLanguage = {\n code: string;\n name: string;\n englishName: string;\n dir: 'ltr' | 'rtl';\n status: 'source' | 'machine' | 'reviewed';\n /** `community` languages are listed apart and never chosen automatically. */\n tier: 'supported' | 'community';\n coverage: number;\n};\n\n/** The app's language state (frame/language.ts `createLanguage`). */\nexport type PanelLanguages = {\n list: readonly PanelLanguage[];\n state(): { preference: string; siteLang: string | null; system: readonly string[]; locale: string; community: string | null };\n subscribe(listener: () => void): () => void;\n set(preference: string): Promise<void>;\n /** The contributor guide (\"Help translate\"), opened in the system browser. */\n translateUrl?: string;\n};\n\nexport type PanelSite = {\n /** The header: the brand's name and logo (an image URL). */\n brand: { name: string; logo: string };\n home: PanelHome;\n /** The app's version for the home page's chip. */\n version?(): Promise<string>;\n /** The app's own sections. */\n sections?: readonly PanelSection[];\n /** Nav order (built-in and site ids). Default: the built-in ones, then the site's. */\n order?: readonly string[];\n /** Themes (Appearance, Theme Builder); omit for an app without them. */\n themes?: PanelThemes;\n /** What the app adds to Appearance, above the custom CSS editor (X: its logo and wording). */\n appearance?: { extra?: ReadonlyArray<ComponentType<SectionProps>> };\n /**\n * Area plugins and modes: the app's feature table (waybetter/runtime/featureTable). With it the\n * Plugins section lists one card per area with a toggle per feature, then the core flags as\n * \"Fixes\"; with modes in the table, the first-run screen and Settings offer them.\n */\n features?: {\n table: FeatureTable;\n /** Core flags that have a control of their own elsewhere (not listed under Fixes). */\n elsewhere?: readonly string[];\n /** Runs after a mode was chosen and its flags were saved (the app's own step for that mode). */\n onMode?(mode: string): void | Promise<void>;\n /** The illustration on a mode's card of the first-run screen (default: plain bars). */\n ModeArt?: ComponentType<{ mode: string }>;\n };\n /** The install screen's controller: the Store section, and removing a plugin from the list. */\n store?: { controller: InstallController<ThemeSpec> };\n make?: PanelMake;\n /** The language picker in Settings; omit for an app in one language. */\n languages?: PanelLanguages;\n /** Settings: keyword alerts (`alerts_get/set`) and what the app adds under the framework's rows. */\n settings?: {\n alerts?: boolean;\n extra?: ReadonlyArray<ComponentType<SectionProps>>;\n /** Extra search words for the \"links to the site's pages\" row (\"x twitter\"). */\n linkKeywords?: string;\n };\n /** Placeholder CSS in the editors, written with the site's own selectors: custom CSS, a theme's CSS, the builder's. */\n cssExamples?: { custom?: string; theme?: string; builder?: string };\n /** Power User (with `site.deck`): what the settings list besides the frame's own. */\n power?: {\n /** Column flags offered as deck defaults (default: the flags `site.deck.defaultFlags` names). */\n defaultFlags?: readonly string[];\n /** What one column was measured to take, in MB (shown with the columns-per-page guard). */\n memory?: { perColumn: number; range: string };\n /** A line above the deck keys (which of the site's own keys keep working in a column). */\n keysHint?(): string;\n };\n /** Backup & export (`backup_*`); the sync part needs the frame's `sync` feature. */\n backup?: boolean;\n /**\n * \"Share my setup\" under Backup & sync (ShareSetup.tsx; needs `features`): the app's id, which a\n * setup carries so it never applies to another app. Absent: no such section.\n */\n setup?: { app: string };\n /** The native updater (`app_ready`, `update_status`, `apply_update`). */\n updates?: boolean;\n};\n\nlet current: PanelSite | null = null;\n\n/** Sets the panel's site (createPanel). */\nexport function configurePanel(value: PanelSite) {\n current = value;\n}\n\nexport function panelSite(): PanelSite {\n if (!current) throw new Error('wayBetter panel: createPanel(site) first');\n return current;\n}\n\n/** The app's themes (Appearance, the builder and the font pickers only render with them). */\nexport function panelThemes(): PanelThemes {\n const themes = panelSite().themes;\n if (!themes) throw new Error('wayBetter panel: this app has no themes (PanelSite.themes)');\n return themes;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /* The Languages section (StringPacks.tsx): one row per installed string pack. */
2
+ .btp-strings { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
3
+ .btp-strings-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: calc(10px * var(--bt-rs, 1)); background: var(--c-surface-2, var(--c-surface)); }
4
+ .btp-strings-row.is-on { box-shadow: inset 0 0 0 1px var(--c-accent); }
5
+ .btp-strings-text { flex: 1; min-width: 0; display: grid; gap: 2px; }
6
+ .btp-strings-text small { color: var(--c-text-2, var(--c-muted)); overflow-wrap: anywhere; }
7
+ .btp-strings-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
@@ -0,0 +1,10 @@
1
+ /** The app's theme store (fonts, choice, scopes, preview). */
2
+ export declare const themeStore: () => import("../frame/themeStore.ts").ThemeStore<import("../../runtime/themeChoice.ts").ThemeChoice, import("../../runtime/themeSpec.ts").ThemeSpec>;
3
+ /** The theme state (global choice, scopes, installed fonts, preview); re-renders on change. */
4
+ export declare const useThemeState: () => {
5
+ ready: boolean;
6
+ choice: import("../../runtime/themeChoice.ts").ThemeChoice;
7
+ scopes: import("../frame/themeScopes.ts").ThemeScopes;
8
+ fonts: import("../frame/themeStore.ts").InstalledFont[];
9
+ preview: import("../../runtime/themeSpec.ts").ThemeSpec | null;
10
+ };
@@ -0,0 +1,8 @@
1
+ // The app's theme store as the panel's components use it (`PanelSite.themes.store`).
2
+ import { useThemeState as useThemeStateCore } from "../frame/hooks.js";
3
+ import { panelThemes } from "./site.js";
4
+ /** The app's theme store (fonts, choice, scopes, preview). */
5
+ export const themeStore = () => panelThemes().store;
6
+ /** The theme state (global choice, scopes, installed fonts, preview); re-renders on change. */
7
+ export const useThemeState = () => useThemeStateCore(panelThemes().store);
8
+ //# sourceMappingURL=themes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/themes.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;AAEpD,+FAA+F;AAC/F,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC","sourcesContent":["// The app's theme store as the panel's components use it (`PanelSite.themes.store`).\nimport { useThemeState as useThemeStateCore } from '../frame/hooks.ts';\nimport { panelThemes } from './site.ts';\n\n/** The app's theme store (fonts, choice, scopes, preview). */\nexport const themeStore = () => panelThemes().store;\n\n/** The theme state (global choice, scopes, installed fonts, preview); re-renders on change. */\nexport const useThemeState = () => useThemeStateCore(panelThemes().store);\n"]}
@@ -1,3 +1,4 @@
1
+ import { type ShellText } from './messages.ts';
1
2
  /** The login inside a profile, as native code last saw it (read-only here; see profiles.rs). */
2
3
  export type Account = {
3
4
  handle: string;
@@ -33,7 +34,7 @@ export declare function cleanName(name: string): string | null;
33
34
  export declare function normalizeProfiles(value: unknown, rules: AccountRules): ProfileSettings;
34
35
  export declare function normalizeAccount(value: unknown, rules: AccountRules): Account | undefined;
35
36
  /** What the switcher shows for a profile: the login once seen, the profile name before. */
36
- export declare function accountLabel(profile: Profile, rules: Pick<AccountRules, 'handlePrefix'>): {
37
+ export declare function accountLabel(profile: Profile, rules: Pick<AccountRules, 'handlePrefix'>, text?: ShellText): {
37
38
  title: string;
38
39
  detail: string;
39
40
  state: 'signed-in' | 'signed-out' | 'new';
@@ -42,7 +43,7 @@ export declare function newProfileId(random?: () => number): string;
42
43
  export declare function nextColor(settings: ProfileSettings): string;
43
44
  /** Adds a profile and makes it active. Unlimited count (Rust caps absurd sizes). Its name follows the
44
45
  * account once someone signs in there; until then it is a placeholder. */
45
- export declare function addProfile(settings: ProfileSettings, name?: string, id?: string): ProfileSettings;
46
+ export declare function addProfile(settings: ProfileSettings, name?: string, id?: string, text?: ShellText): ProfileSettings;
46
47
  export declare function renameProfile(settings: ProfileSettings, id: string, name: string): ProfileSettings;
47
48
  export declare function recolorProfile(settings: ProfileSettings, id: string, color: string): ProfileSettings;
48
49
  /** The default profile cannot be removed; removing the active one falls back to default. */
@@ -1,5 +1,6 @@
1
1
  // Pure model for account profiles (no Tauri imports, so it is unit-tested under node).
2
2
  // Mirrors `ProfileSettings` in waybetter-host `profiles.rs`; Rust validates again on save.
3
+ import { shellText } from "./messages.js";
3
4
  export const DEFAULT_PROFILE = 'default';
4
5
  export const PROFILE_COLORS = ['#1d9bf0', '#f91880', '#00ba7c', '#ffd400', '#7856ff', '#ff7a00', '#22d3ee', '#a3a3a3'];
5
6
  export const defaultProfiles = () => ({
@@ -41,12 +42,13 @@ export function normalizeAccount(value, rules) {
41
42
  return { handle: raw.handle, name: typeof raw.name === 'string' && raw.name.trim() ? raw.name : raw.handle, signedIn: raw.signedIn === true, ...(avatar ? { avatar } : {}) };
42
43
  }
43
44
  /** What the switcher shows for a profile: the login once seen, the profile name before. */
44
- export function accountLabel(profile, rules) {
45
+ export function accountLabel(profile, rules, text) {
45
46
  if (!profile.account)
46
- return { title: profile.name, detail: 'Not signed in yet', state: 'new' };
47
+ return { title: profile.name, detail: shellText('wb.account.notSignedIn', {}, text), state: 'new' };
48
+ const handle = `${rules.handlePrefix}${profile.account.handle}`;
47
49
  return {
48
50
  title: profile.account.name,
49
- detail: `${rules.handlePrefix}${profile.account.handle}${profile.account.signedIn ? '' : ' · signed out'}`,
51
+ detail: profile.account.signedIn ? handle : shellText('wb.account.signedOut', { handle }, text),
50
52
  state: profile.account.signedIn ? 'signed-in' : 'signed-out',
51
53
  };
52
54
  }
@@ -59,8 +61,8 @@ export function nextColor(settings) {
59
61
  }
60
62
  /** Adds a profile and makes it active. Unlimited count (Rust caps absurd sizes). Its name follows the
61
63
  * account once someone signs in there; until then it is a placeholder. */
62
- export function addProfile(settings, name = '', id = newProfileId()) {
63
- const clean = cleanName(name) ?? 'New account';
64
+ export function addProfile(settings, name = '', id = newProfileId(), text) {
65
+ const clean = cleanName(name) ?? shellText('wb.account.newName', {}, text);
64
66
  if (!validProfileId(id) || settings.profiles.some(p => p.id === id))
65
67
  throw new Error('VALIDATION: invalid profile id');
66
68
  return { profiles: [...settings.profiles, { id, name: clean, color: nextColor(settings) }], active: id };
@@ -1 +1 @@
1
- {"version":3,"file":"profileModel.js","sourceRoot":"","sources":["../../../shell/src/profileModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure model for account profiles (no Tauri imports, so it is unit-tested under node).\n// Mirrors `ProfileSettings` in waybetter-host `profiles.rs`; Rust validates again on save.\n\n/** The login inside a profile, as native code last saw it (read-only here; see profiles.rs). */\nexport type Account = { handle: string; name: string; avatar?: string; signedIn: boolean };\nexport type Profile = { id: string; name: string; color: string; account?: Account };\nexport type ProfileSettings = { profiles: Profile[]; active: string };\n\n/** The site's account rules, as in the native `AccountRules`. */\nexport type AccountRules = {\n handle: RegExp;\n /** Avatar URLs must start with one of these. */\n avatarPrefixes: readonly string[];\n /** Shown before the handle in the switcher, e.g. '@'. */\n handlePrefix: string;\n};\n\nexport const DEFAULT_PROFILE = 'default';\nexport const PROFILE_COLORS = ['#1d9bf0', '#f91880', '#00ba7c', '#ffd400', '#7856ff', '#ff7a00', '#22d3ee', '#a3a3a3'];\n\nexport const defaultProfiles = (): ProfileSettings => ({\n profiles: [{ id: DEFAULT_PROFILE, name: 'Main', color: PROFILE_COLORS[0]! }],\n active: DEFAULT_PROFILE,\n});\n\nexport const validProfileId = (id: unknown): id is string =>\n typeof id === 'string' && (id === DEFAULT_PROFILE || /^p[a-z0-9]{1,32}$/.test(id));\n\nexport const validColor = (color: unknown): color is string => typeof color === 'string' && /^#[0-9a-fA-F]{6}$/.test(color);\n\nexport function cleanName(name: string): string | null {\n const trimmed = name.trim();\n // eslint-disable-next-line no-control-regex\n if (!trimmed || [...trimmed].length > 40 || /[\\u0000-\\u001f\\u007f-\\u009f]/.test(trimmed)) return null;\n return trimmed;\n}\n\n/** Anything from storage or IPC → a usable settings object (always has the default profile). */\nexport function normalizeProfiles(value: unknown, rules: AccountRules): ProfileSettings {\n const input = value as Partial<ProfileSettings> | null;\n const seen = new Set<string>();\n const profiles: Profile[] = [];\n for (const raw of Array.isArray(input?.profiles) ? input!.profiles : []) {\n const name = typeof raw?.name === 'string' ? cleanName(raw.name) : null;\n if (!validProfileId(raw?.id) || seen.has(raw.id) || !name || !validColor(raw.color)) continue;\n seen.add(raw.id);\n const account = normalizeAccount(raw.account, rules);\n profiles.push({ id: raw.id, name, color: raw.color.toLowerCase(), ...(account ? { account } : {}) });\n }\n if (!seen.has(DEFAULT_PROFILE)) profiles.unshift(defaultProfiles().profiles[0]!);\n const active = typeof input?.active === 'string' && profiles.some(p => p.id === input.active) ? input.active : DEFAULT_PROFILE;\n return { profiles, active };\n}\n\nexport function normalizeAccount(value: unknown, rules: AccountRules): Account | undefined {\n const raw = value as Partial<Account> | null | undefined;\n if (!raw || typeof raw.handle !== 'string' || !rules.handle.test(raw.handle)) return undefined;\n const avatar = typeof raw.avatar === 'string' && rules.avatarPrefixes.some(prefix => raw.avatar!.startsWith(prefix)) ? raw.avatar : undefined;\n return { handle: raw.handle, name: typeof raw.name === 'string' && raw.name.trim() ? raw.name : raw.handle, signedIn: raw.signedIn === true, ...(avatar ? { avatar } : {}) };\n}\n\n/** What the switcher shows for a profile: the login once seen, the profile name before. */\nexport function accountLabel(profile: Profile, rules: Pick<AccountRules, 'handlePrefix'>): { title: string; detail: string; state: 'signed-in' | 'signed-out' | 'new' } {\n if (!profile.account) return { title: profile.name, detail: 'Not signed in yet', state: 'new' };\n return {\n title: profile.account.name,\n detail: `${rules.handlePrefix}${profile.account.handle}${profile.account.signedIn ? '' : ' · signed out'}`,\n state: profile.account.signedIn ? 'signed-in' : 'signed-out',\n };\n}\n\nexport function newProfileId(random: () => number = Math.random): string {\n return `p${Date.now().toString(36)}${Math.floor(random() * 36 ** 6).toString(36)}`.slice(0, 33);\n}\n\nexport function nextColor(settings: ProfileSettings): string {\n const used = new Set(settings.profiles.map(p => p.color));\n return PROFILE_COLORS.find(color => !used.has(color)) ?? PROFILE_COLORS[settings.profiles.length % PROFILE_COLORS.length]!;\n}\n\n/** Adds a profile and makes it active. Unlimited count (Rust caps absurd sizes). Its name follows the\n * account once someone signs in there; until then it is a placeholder. */\nexport function addProfile(settings: ProfileSettings, name = '', id = newProfileId()): ProfileSettings {\n const clean = cleanName(name) ?? 'New account';\n if (!validProfileId(id) || settings.profiles.some(p => p.id === id)) throw new Error('VALIDATION: invalid profile id');\n return { profiles: [...settings.profiles, { id, name: clean, color: nextColor(settings) }], active: id };\n}\n\nexport function renameProfile(settings: ProfileSettings, id: string, name: string): ProfileSettings {\n const clean = cleanName(name);\n if (!clean) return settings;\n return { ...settings, profiles: settings.profiles.map(p => (p.id === id ? { ...p, name: clean } : p)) };\n}\n\nexport function recolorProfile(settings: ProfileSettings, id: string, color: string): ProfileSettings {\n if (!validColor(color)) return settings;\n return { ...settings, profiles: settings.profiles.map(p => (p.id === id ? { ...p, color: color.toLowerCase() } : p)) };\n}\n\n/** The default profile cannot be removed; removing the active one falls back to default. */\nexport function removeProfile(settings: ProfileSettings, id: string): ProfileSettings {\n if (id === DEFAULT_PROFILE) return settings;\n const profiles = settings.profiles.filter(p => p.id !== id);\n return { profiles, active: settings.active === id ? DEFAULT_PROFILE : settings.active };\n}\n\nexport const setActiveProfile = (settings: ProfileSettings, id: string): ProfileSettings =>\n settings.profiles.some(p => p.id === id) ? { ...settings, active: id } : settings;\n\n/** The profile a tab really runs in: unknown or missing ids (old layouts) use the default. */\nexport function tabProfile(settings: ProfileSettings, id: string | undefined): Profile {\n return settings.profiles.find(p => p.id === id) ?? settings.profiles.find(p => p.id === DEFAULT_PROFILE) ?? defaultProfiles().profiles[0]!;\n}\n"]}
1
+ {"version":3,"file":"profileModel.js","sourceRoot":"","sources":["../../../../../shell/src/profileModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure model for account profiles (no Tauri imports, so it is unit-tested under node).\n// Mirrors `ProfileSettings` in waybetter-host `profiles.rs`; Rust validates again on save.\n\nimport { shellText, type ShellText } from './messages.ts';\n\n/** The login inside a profile, as native code last saw it (read-only here; see profiles.rs). */\nexport type Account = { handle: string; name: string; avatar?: string; signedIn: boolean };\nexport type Profile = { id: string; name: string; color: string; account?: Account };\nexport type ProfileSettings = { profiles: Profile[]; active: string };\n\n/** The site's account rules, as in the native `AccountRules`. */\nexport type AccountRules = {\n handle: RegExp;\n /** Avatar URLs must start with one of these. */\n avatarPrefixes: readonly string[];\n /** Shown before the handle in the switcher, e.g. '@'. */\n handlePrefix: string;\n};\n\nexport const DEFAULT_PROFILE = 'default';\nexport const PROFILE_COLORS = ['#1d9bf0', '#f91880', '#00ba7c', '#ffd400', '#7856ff', '#ff7a00', '#22d3ee', '#a3a3a3'];\n\nexport const defaultProfiles = (): ProfileSettings => ({\n profiles: [{ id: DEFAULT_PROFILE, name: 'Main', color: PROFILE_COLORS[0]! }],\n active: DEFAULT_PROFILE,\n});\n\nexport const validProfileId = (id: unknown): id is string =>\n typeof id === 'string' && (id === DEFAULT_PROFILE || /^p[a-z0-9]{1,32}$/.test(id));\n\nexport const validColor = (color: unknown): color is string => typeof color === 'string' && /^#[0-9a-fA-F]{6}$/.test(color);\n\nexport function cleanName(name: string): string | null {\n const trimmed = name.trim();\n // eslint-disable-next-line no-control-regex\n if (!trimmed || [...trimmed].length > 40 || /[\\u0000-\\u001f\\u007f-\\u009f]/.test(trimmed)) return null;\n return trimmed;\n}\n\n/** Anything from storage or IPC → a usable settings object (always has the default profile). */\nexport function normalizeProfiles(value: unknown, rules: AccountRules): ProfileSettings {\n const input = value as Partial<ProfileSettings> | null;\n const seen = new Set<string>();\n const profiles: Profile[] = [];\n for (const raw of Array.isArray(input?.profiles) ? input!.profiles : []) {\n const name = typeof raw?.name === 'string' ? cleanName(raw.name) : null;\n if (!validProfileId(raw?.id) || seen.has(raw.id) || !name || !validColor(raw.color)) continue;\n seen.add(raw.id);\n const account = normalizeAccount(raw.account, rules);\n profiles.push({ id: raw.id, name, color: raw.color.toLowerCase(), ...(account ? { account } : {}) });\n }\n if (!seen.has(DEFAULT_PROFILE)) profiles.unshift(defaultProfiles().profiles[0]!);\n const active = typeof input?.active === 'string' && profiles.some(p => p.id === input.active) ? input.active : DEFAULT_PROFILE;\n return { profiles, active };\n}\n\nexport function normalizeAccount(value: unknown, rules: AccountRules): Account | undefined {\n const raw = value as Partial<Account> | null | undefined;\n if (!raw || typeof raw.handle !== 'string' || !rules.handle.test(raw.handle)) return undefined;\n const avatar = typeof raw.avatar === 'string' && rules.avatarPrefixes.some(prefix => raw.avatar!.startsWith(prefix)) ? raw.avatar : undefined;\n return { handle: raw.handle, name: typeof raw.name === 'string' && raw.name.trim() ? raw.name : raw.handle, signedIn: raw.signedIn === true, ...(avatar ? { avatar } : {}) };\n}\n\n/** What the switcher shows for a profile: the login once seen, the profile name before. */\nexport function accountLabel(profile: Profile, rules: Pick<AccountRules, 'handlePrefix'>, text?: ShellText): { title: string; detail: string; state: 'signed-in' | 'signed-out' | 'new' } {\n if (!profile.account) return { title: profile.name, detail: shellText('wb.account.notSignedIn', {}, text), state: 'new' };\n const handle = `${rules.handlePrefix}${profile.account.handle}`;\n return {\n title: profile.account.name,\n detail: profile.account.signedIn ? handle : shellText('wb.account.signedOut', { handle }, text),\n state: profile.account.signedIn ? 'signed-in' : 'signed-out',\n };\n}\n\nexport function newProfileId(random: () => number = Math.random): string {\n return `p${Date.now().toString(36)}${Math.floor(random() * 36 ** 6).toString(36)}`.slice(0, 33);\n}\n\nexport function nextColor(settings: ProfileSettings): string {\n const used = new Set(settings.profiles.map(p => p.color));\n return PROFILE_COLORS.find(color => !used.has(color)) ?? PROFILE_COLORS[settings.profiles.length % PROFILE_COLORS.length]!;\n}\n\n/** Adds a profile and makes it active. Unlimited count (Rust caps absurd sizes). Its name follows the\n * account once someone signs in there; until then it is a placeholder. */\nexport function addProfile(settings: ProfileSettings, name = '', id = newProfileId(), text?: ShellText): ProfileSettings {\n const clean = cleanName(name) ?? shellText('wb.account.newName', {}, text);\n if (!validProfileId(id) || settings.profiles.some(p => p.id === id)) throw new Error('VALIDATION: invalid profile id');\n return { profiles: [...settings.profiles, { id, name: clean, color: nextColor(settings) }], active: id };\n}\n\nexport function renameProfile(settings: ProfileSettings, id: string, name: string): ProfileSettings {\n const clean = cleanName(name);\n if (!clean) return settings;\n return { ...settings, profiles: settings.profiles.map(p => (p.id === id ? { ...p, name: clean } : p)) };\n}\n\nexport function recolorProfile(settings: ProfileSettings, id: string, color: string): ProfileSettings {\n if (!validColor(color)) return settings;\n return { ...settings, profiles: settings.profiles.map(p => (p.id === id ? { ...p, color: color.toLowerCase() } : p)) };\n}\n\n/** The default profile cannot be removed; removing the active one falls back to default. */\nexport function removeProfile(settings: ProfileSettings, id: string): ProfileSettings {\n if (id === DEFAULT_PROFILE) return settings;\n const profiles = settings.profiles.filter(p => p.id !== id);\n return { profiles, active: settings.active === id ? DEFAULT_PROFILE : settings.active };\n}\n\nexport const setActiveProfile = (settings: ProfileSettings, id: string): ProfileSettings =>\n settings.profiles.some(p => p.id === id) ? { ...settings, active: id } : settings;\n\n/** The profile a tab really runs in: unknown or missing ids (old layouts) use the default. */\nexport function tabProfile(settings: ProfileSettings, id: string | undefined): Profile {\n return settings.profiles.find(p => p.id === id) ?? settings.profiles.find(p => p.id === DEFAULT_PROFILE) ?? defaultProfiles().profiles[0]!;\n}\n"]}