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,116 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Settings rows every app has: the home page, where links open and session restore (waybetter-host
3
+ // `settings_get/set`), keyword alerts (`alerts_get/set`) and the media panel's folders and
4
+ // clipboard history (`media_get/set`). Stored natively; applied live to every tab.
5
+ import { useEffect, useState } from 'react';
6
+ import { invoke } from "../frame/bridge.js";
7
+ import { useT } from "../frame/hooks.js";
8
+ import { CLIP_MAX_LIMIT, clampClipMax, folderLabel, withoutFolder } from "../frame/mediaModel.js";
9
+ import { site } from "../frame/site.js";
10
+ import { ChipList, Button, InputRow, Row, Section, Segmented, Stepper, Toggle } from "./controls.js";
11
+ import { panelSite } from "./site.js";
12
+ const getError = (error) => error instanceof Error ? error.message : String(error);
13
+ const FOLDER_ICON = _jsx("svg", { width: "13", height: "13", viewBox: "0 0 16 16", "aria-hidden": "true", children: _jsx("path", { d: "M2 4.5A1.5 1.5 0 0 1 3.5 3h3l1.5 1.5h4.5A1.5 1.5 0 0 1 14 6v5.5a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 11.5z", fill: "none", stroke: "currentColor", strokeWidth: "1.3" }) });
14
+ const OPENS = { same: 'wb.settings.links.opens.same', pane: 'wb.settings.links.opens.pane', tab: 'wb.settings.links.opens.tab', browser: 'wb.settings.links.opens.browser' };
15
+ /** Home page, where links open, session restore. Stored natively; read by the tab webviews. */
16
+ export function BrowserSettings({ notify }) {
17
+ const t = useT();
18
+ const [settings, setSettings] = useState(null);
19
+ const [home, setHome] = useState('');
20
+ useEffect(() => { invoke('settings_get').then(value => { setSettings(value); setHome(value.homeUrl); }).catch(err => notify(getError(err), true)); }, []);
21
+ async function save(next, message) {
22
+ const previous = settings;
23
+ setSettings(next);
24
+ try {
25
+ const saved = await invoke('settings_set', { settings: next });
26
+ setSettings(saved);
27
+ setHome(saved.homeUrl);
28
+ notify(message);
29
+ }
30
+ catch (err) {
31
+ setSettings(previous);
32
+ notify(getError(err), true);
33
+ }
34
+ }
35
+ if (!settings)
36
+ return null;
37
+ const siteHome = site().homeUrl;
38
+ return _jsxs(Section, { title: t('wb.settings.links.title'), hint: t('wb.settings.links.hint'), children: [_jsx(Row, { label: t('wb.settings.home.label'), hint: t('wb.settings.home.hint'), keywords: "new tab start url", wide: true, children: _jsxs("div", { className: "bt-inline", children: [_jsx(InputRow, { label: t('wb.settings.home.url'), mono: true, value: home, onChange: setHome, button: t('wb.common.save'), disabled: home === settings.homeUrl, onSubmit: () => void save({ ...settings, homeUrl: home }, t('wb.settings.home.saved')) }), settings.homeUrl !== siteHome && _jsx(Button, { tone: "ghost", size: "sm", onClick: () => void save({ ...settings, homeUrl: siteHome }, t('wb.settings.home.resetDone')), children: t('wb.settings.home.reset') })] }) }), _jsx(Row, { label: t('wb.settings.links.external'), hint: t('wb.settings.links.externalHint'), keywords: "external open browser pane split side", children: _jsx(Segmented, { label: t('wb.settings.links.external'), value: settings.externalLinks, onChange: mode => void save({ ...settings, externalLinks: mode }, t('wb.settings.links.externalSaved', { how: t(OPENS[mode]) })), options: [{ value: 'pane', label: t('wb.settings.links.beside') }, { value: 'tab', label: t('wb.settings.links.newTab') }, { value: 'browser', label: t('wb.settings.links.browser') }] }) }), _jsx(Row, { label: t('wb.settings.links.site'), hint: t('wb.settings.links.siteHint'), keywords: `${panelSite().settings?.linkKeywords ?? site().name} post profile open pane split side tab`, children: _jsx(Segmented, { label: t('wb.settings.links.site'), value: settings.siteLinks, onChange: mode => void save({ ...settings, siteLinks: mode }, t('wb.settings.links.siteSaved', { how: t(OPENS[mode]) })), options: [{ value: 'same', label: t('wb.settings.links.sameTab') }, { value: 'pane', label: t('wb.settings.links.beside') }, { value: 'tab', label: t('wb.settings.links.newTab') }, { value: 'browser', label: t('wb.settings.links.browser') }] }) }), _jsx(Row, { label: t('wb.settings.restore.label'), hint: t('wb.settings.restore.hint'), keywords: "session", children: _jsx(Toggle, { label: t('wb.settings.restore.label'), checked: settings.restoreTabs, onChange: next => void save({ ...settings, restoreTabs: next }, next ? t('wb.settings.restore.on') : t('wb.settings.restore.off')) }) })] });
39
+ }
40
+ export const parseKeywords = (text) => text.split(/[,\n]/).map(word => word.trim()).filter(Boolean);
41
+ const MAX_KEYWORDS = 32;
42
+ /** Keyword alerts: local OS notifications for keywords in items the site already loaded. Native only. */
43
+ export function AlertSettings({ notify }) {
44
+ const t = useT();
45
+ const [alerts, setAlerts] = useState(null);
46
+ const [text, setText] = useState('');
47
+ useEffect(() => { invoke('alerts_get').then(setAlerts).catch(err => notify(getError(err), true)); }, []);
48
+ async function save(next, message) {
49
+ const previous = alerts;
50
+ setAlerts(next);
51
+ try {
52
+ setAlerts(await invoke('alerts_set', { settings: next }));
53
+ notify(message);
54
+ }
55
+ catch (err) {
56
+ setAlerts(previous);
57
+ notify(getError(err), true);
58
+ }
59
+ }
60
+ function add() {
61
+ if (!alerts)
62
+ return;
63
+ const known = new Set(alerts.keywords.map(word => word.toLowerCase()));
64
+ const fresh = parseKeywords(text).filter(word => !known.has(word.toLowerCase()));
65
+ if (!fresh.length) {
66
+ setText('');
67
+ return;
68
+ }
69
+ const keywords = [...alerts.keywords, ...fresh].slice(0, MAX_KEYWORDS);
70
+ setText('');
71
+ void save({ ...alerts, keywords }, fresh.length === 1 ? t('wb.settings.alerts.watching', { word: fresh[0] }) : t('wb.settings.alerts.watchingMore', { count: fresh.length }));
72
+ }
73
+ if (!alerts)
74
+ return null;
75
+ return _jsxs(Section, { title: t('wb.settings.alerts.title'), hint: t('wb.settings.alerts.hint'), children: [_jsx(Row, { label: t('wb.settings.alerts.label'), hint: alerts.enabled ? t('wb.settings.alerts.onCount', { count: alerts.keywords.length }) : t('wb.common.off'), keywords: "keyword notification notify", children: _jsx(Toggle, { label: t('wb.settings.alerts.title'), checked: alerts.enabled, onChange: next => void save({ ...alerts, enabled: next }, next ? t('wb.settings.alerts.turnedOn') : t('wb.settings.alerts.turnedOff')) }) }), _jsx(Row, { label: t('wb.settings.alerts.keywords'), hint: t('wb.settings.alerts.keywordsHint', { max: MAX_KEYWORDS }), keywords: "alert words watch", wide: true, children: _jsxs("div", { className: "bt-stack", children: [_jsx(ChipList, { items: alerts.keywords, empty: t('wb.settings.alerts.none'), onRemove: word => void save({ ...alerts, keywords: alerts.keywords.filter(item => item !== word) }, t('wb.settings.alerts.stopped', { word })) }), _jsx(InputRow, { label: t('wb.settings.alerts.add'), placeholder: "tauri, waybetter", value: text, onChange: setText, button: t('wb.common.add'), disabled: !parseKeywords(text).length || alerts.keywords.length >= MAX_KEYWORDS, onSubmit: add })] }) })] });
76
+ }
77
+ /** Gallery folders and the opt-in clipboard history for the Media panel (Ctrl+Shift+G). Native only. */
78
+ export function MediaSettingsRows({ notify }) {
79
+ const t = useT();
80
+ const [settings, setSettings] = useState(null);
81
+ useEffect(() => { invoke('media_get').then(setSettings).catch(err => notify(getError(err), true)); }, []);
82
+ async function save(next, message) {
83
+ const previous = settings;
84
+ setSettings(next);
85
+ try {
86
+ setSettings(await invoke('media_set', { settings: next }));
87
+ if (message)
88
+ notify(message);
89
+ }
90
+ catch (err) {
91
+ setSettings(previous);
92
+ notify(getError(err), true);
93
+ }
94
+ }
95
+ async function addFolder() {
96
+ try {
97
+ setSettings(await invoke('gallery_add_folder'));
98
+ }
99
+ catch (err) {
100
+ notify(getError(err), true);
101
+ }
102
+ }
103
+ async function clearHistory() {
104
+ try {
105
+ await invoke('clip_remove', { id: null });
106
+ notify(t('wb.settings.media.cleared'));
107
+ }
108
+ catch (err) {
109
+ notify(getError(err), true);
110
+ }
111
+ }
112
+ if (!settings)
113
+ return null;
114
+ return _jsxs(Section, { title: t('wb.settings.media.title'), hint: t('wb.settings.media.hint'), children: [_jsx(Row, { label: t('wb.settings.media.folders'), hint: t('wb.settings.media.foldersHint'), keywords: "images pictures screenshots", wide: true, children: _jsxs("div", { className: "bt-stack", children: [_jsx(ChipList, { items: settings.folders, icon: FOLDER_ICON, render: folderLabel, empty: t('wb.settings.media.noFolders'), onRemove: folder => void save(withoutFolder(settings, folder), t('wb.settings.media.folderRemoved')) }), _jsx("div", { children: _jsx(Button, { size: "sm", onClick: () => void addFolder(), icon: _jsx("span", { "aria-hidden": "true", children: "\uFF0B" }), children: t('wb.settings.media.addFolder') }) })] }) }), _jsx(Row, { label: t('wb.settings.media.clipboard'), hint: t('wb.settings.media.clipboardHint'), keywords: "copy paste", children: _jsx(Toggle, { label: t('wb.settings.media.clipboard'), checked: settings.clipboardEnabled, onChange: next => void save({ ...settings, clipboardEnabled: next }, next ? t('wb.settings.media.clipboardOn') : t('wb.settings.media.clipboardOff')) }) }), settings.clipboardEnabled && _jsx(Row, { label: t('wb.settings.media.keep'), hint: t('wb.settings.media.keepHint'), keywords: "clipboard size", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Stepper, { label: t('wb.settings.media.keep'), value: settings.clipboardMax, min: 1, max: CLIP_MAX_LIMIT, onChange: value => void save({ ...settings, clipboardMax: clampClipMax(value) }) }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void clearHistory(), children: t('wb.common.clear') })] }) })] });
115
+ }
116
+ //# sourceMappingURL=Settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Settings.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/Settings.tsx"],"names":[],"mappings":"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","sourcesContent":["// Settings rows every app has: the home page, where links open and session restore (waybetter-host\n// `settings_get/set`), keyword alerts (`alerts_get/set`) and the media panel's folders and\n// clipboard history (`media_get/set`). Stored natively; applied live to every tab.\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { CLIP_MAX_LIMIT, clampClipMax, folderLabel, withoutFolder, type MediaSettings } from '../frame/mediaModel.ts';\nimport { site } from '../frame/site.ts';\nimport { ChipList, Button, InputRow, Row, Section, Segmented, Stepper, Toggle } from './controls.tsx';\nimport { panelSite, type Notify } from './site.ts';\n\n/** The shell's settings (waybetter-host `ShellSettings`). */\nexport type ShellSettings = {\n homeUrl: string;\n /** Links to other sites: beside the tab (split), a new tab, or the system browser. */\n externalLinks: 'pane' | 'tab' | 'browser';\n /** Site pages clicked in the page: the site's in-place navigation, beside, a new tab, or the system browser. */\n siteLinks: 'same' | 'pane' | 'tab' | 'browser';\n restoreTabs: boolean;\n};\n\nconst getError = (error: unknown) => error instanceof Error ? error.message : String(error);\nconst FOLDER_ICON = <svg width=\"13\" height=\"13\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M2 4.5A1.5 1.5 0 0 1 3.5 3h3l1.5 1.5h4.5A1.5 1.5 0 0 1 14 6v5.5a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 11.5z\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\"/></svg>;\n\ntype Opens = 'same' | 'pane' | 'tab' | 'browser';\nconst OPENS: Record<Opens, string> = { same: 'wb.settings.links.opens.same', pane: 'wb.settings.links.opens.pane', tab: 'wb.settings.links.opens.tab', browser: 'wb.settings.links.opens.browser' };\n\n/** Home page, where links open, session restore. Stored natively; read by the tab webviews. */\nexport function BrowserSettings({ notify }: { notify: Notify }) {\n const t = useT();\n const [settings, setSettings] = useState<ShellSettings | null>(null);\n const [home, setHome] = useState('');\n\n useEffect(() => { invoke<ShellSettings>('settings_get').then(value => { setSettings(value); setHome(value.homeUrl); }).catch(err => notify(getError(err), true)); }, []);\n\n async function save(next: ShellSettings, message: string) {\n const previous = settings;\n setSettings(next);\n try { const saved = await invoke<ShellSettings>('settings_set', { settings: next }); setSettings(saved); setHome(saved.homeUrl); notify(message); }\n catch (err) { setSettings(previous); notify(getError(err), true); }\n }\n\n if (!settings) return null;\n const siteHome = site().homeUrl;\n return <Section title={t('wb.settings.links.title')} hint={t('wb.settings.links.hint')}>\n <Row label={t('wb.settings.home.label')} hint={t('wb.settings.home.hint')} keywords=\"new tab start url\" wide>\n <div className=\"bt-inline\">\n <InputRow label={t('wb.settings.home.url')} mono value={home} onChange={setHome} button={t('wb.common.save')} disabled={home === settings.homeUrl}\n onSubmit={() => void save({ ...settings, homeUrl: home }, t('wb.settings.home.saved'))}/>\n {settings.homeUrl !== siteHome && <Button tone=\"ghost\" size=\"sm\" onClick={() => void save({ ...settings, homeUrl: siteHome }, t('wb.settings.home.resetDone'))}>{t('wb.settings.home.reset')}</Button>}\n </div>\n </Row>\n <Row label={t('wb.settings.links.external')} hint={t('wb.settings.links.externalHint')} keywords=\"external open browser pane split side\">\n <Segmented label={t('wb.settings.links.external')} value={settings.externalLinks} onChange={mode => void save({ ...settings, externalLinks: mode }, t('wb.settings.links.externalSaved', { how: t(OPENS[mode as Opens]) }))}\n options={[{ value: 'pane', label: t('wb.settings.links.beside') }, { value: 'tab', label: t('wb.settings.links.newTab') }, { value: 'browser', label: t('wb.settings.links.browser') }]}/>\n </Row>\n <Row label={t('wb.settings.links.site')} hint={t('wb.settings.links.siteHint')} keywords={`${panelSite().settings?.linkKeywords ?? site().name} post profile open pane split side tab`}>\n <Segmented label={t('wb.settings.links.site')} value={settings.siteLinks} onChange={mode => void save({ ...settings, siteLinks: mode }, t('wb.settings.links.siteSaved', { how: t(OPENS[mode as Opens]) }))}\n options={[{ value: 'same', label: t('wb.settings.links.sameTab') }, { value: 'pane', label: t('wb.settings.links.beside') }, { value: 'tab', label: t('wb.settings.links.newTab') }, { value: 'browser', label: t('wb.settings.links.browser') }]}/>\n </Row>\n <Row label={t('wb.settings.restore.label')} hint={t('wb.settings.restore.hint')} keywords=\"session\">\n <Toggle label={t('wb.settings.restore.label')} checked={settings.restoreTabs} onChange={next => void save({ ...settings, restoreTabs: next }, next ? t('wb.settings.restore.on') : t('wb.settings.restore.off'))}/>\n </Row>\n </Section>;\n}\n\ntype Alerts = { enabled: boolean; keywords: string[] };\nexport const parseKeywords = (text: string) => text.split(/[,\\n]/).map(word => word.trim()).filter(Boolean);\nconst MAX_KEYWORDS = 32;\n\n/** Keyword alerts: local OS notifications for keywords in items the site already loaded. Native only. */\nexport function AlertSettings({ notify }: { notify: Notify }) {\n const t = useT();\n const [alerts, setAlerts] = useState<Alerts | null>(null);\n const [text, setText] = useState('');\n\n useEffect(() => { invoke<Alerts>('alerts_get').then(setAlerts).catch(err => notify(getError(err), true)); }, []);\n\n async function save(next: Alerts, message: string) {\n const previous = alerts;\n setAlerts(next);\n try { setAlerts(await invoke<Alerts>('alerts_set', { settings: next })); notify(message); }\n catch (err) { setAlerts(previous); notify(getError(err), true); }\n }\n function add() {\n if (!alerts) return;\n const known = new Set(alerts.keywords.map(word => word.toLowerCase()));\n const fresh = parseKeywords(text).filter(word => !known.has(word.toLowerCase()));\n if (!fresh.length) { setText(''); return; }\n const keywords = [...alerts.keywords, ...fresh].slice(0, MAX_KEYWORDS);\n setText('');\n void save({ ...alerts, keywords }, fresh.length === 1 ? t('wb.settings.alerts.watching', { word: fresh[0]! }) : t('wb.settings.alerts.watchingMore', { count: fresh.length }));\n }\n\n if (!alerts) return null;\n return <Section title={t('wb.settings.alerts.title')} hint={t('wb.settings.alerts.hint')}>\n <Row label={t('wb.settings.alerts.label')} hint={alerts.enabled ? t('wb.settings.alerts.onCount', { count: alerts.keywords.length }) : t('wb.common.off')} keywords=\"keyword notification notify\">\n <Toggle label={t('wb.settings.alerts.title')} checked={alerts.enabled} onChange={next => void save({ ...alerts, enabled: next }, next ? t('wb.settings.alerts.turnedOn') : t('wb.settings.alerts.turnedOff'))}/>\n </Row>\n <Row label={t('wb.settings.alerts.keywords')} hint={t('wb.settings.alerts.keywordsHint', { max: MAX_KEYWORDS })} keywords=\"alert words watch\" wide>\n <div className=\"bt-stack\">\n <ChipList items={alerts.keywords} empty={t('wb.settings.alerts.none')} onRemove={word => void save({ ...alerts, keywords: alerts.keywords.filter(item => item !== word) }, t('wb.settings.alerts.stopped', { word }))}/>\n <InputRow label={t('wb.settings.alerts.add')} placeholder=\"tauri, waybetter\" value={text} onChange={setText} button={t('wb.common.add')} disabled={!parseKeywords(text).length || alerts.keywords.length >= MAX_KEYWORDS} onSubmit={add}/>\n </div>\n </Row>\n </Section>;\n}\n\n/** Gallery folders and the opt-in clipboard history for the Media panel (Ctrl+Shift+G). Native only. */\nexport function MediaSettingsRows({ notify }: { notify: Notify }) {\n const t = useT();\n const [settings, setSettings] = useState<MediaSettings | null>(null);\n useEffect(() => { invoke<MediaSettings>('media_get').then(setSettings).catch(err => notify(getError(err), true)); }, []);\n\n async function save(next: MediaSettings, message?: string) {\n const previous = settings;\n setSettings(next);\n try { setSettings(await invoke<MediaSettings>('media_set', { settings: next })); if (message) notify(message); }\n catch (err) { setSettings(previous); notify(getError(err), true); }\n }\n async function addFolder() {\n try { setSettings(await invoke<MediaSettings>('gallery_add_folder')); }\n catch (err) { notify(getError(err), true); }\n }\n async function clearHistory() {\n try { await invoke('clip_remove', { id: null }); notify(t('wb.settings.media.cleared')); }\n catch (err) { notify(getError(err), true); }\n }\n\n if (!settings) return null;\n return <Section title={t('wb.settings.media.title')} hint={t('wb.settings.media.hint')}>\n <Row label={t('wb.settings.media.folders')} hint={t('wb.settings.media.foldersHint')} keywords=\"images pictures screenshots\" wide>\n <div className=\"bt-stack\">\n <ChipList items={settings.folders} icon={FOLDER_ICON} render={folderLabel} empty={t('wb.settings.media.noFolders')}\n onRemove={folder => void save(withoutFolder(settings, folder), t('wb.settings.media.folderRemoved'))}/>\n <div><Button size=\"sm\" onClick={() => void addFolder()} icon={<span aria-hidden=\"true\">+</span>}>{t('wb.settings.media.addFolder')}</Button></div>\n </div>\n </Row>\n <Row label={t('wb.settings.media.clipboard')} hint={t('wb.settings.media.clipboardHint')} keywords=\"copy paste\">\n <Toggle label={t('wb.settings.media.clipboard')} checked={settings.clipboardEnabled} onChange={next => void save({ ...settings, clipboardEnabled: next }, next ? t('wb.settings.media.clipboardOn') : t('wb.settings.media.clipboardOff'))}/>\n </Row>\n {settings.clipboardEnabled && <Row label={t('wb.settings.media.keep')} hint={t('wb.settings.media.keepHint')} keywords=\"clipboard size\">\n <div className=\"bt-inline\">\n <Stepper label={t('wb.settings.media.keep')} value={settings.clipboardMax} min={1} max={CLIP_MAX_LIMIT} onChange={value => void save({ ...settings, clipboardMax: clampClipMax(value) })}/>\n <Button size=\"sm\" tone=\"ghost\" onClick={() => void clearHistory()}>{t('wb.common.clear')}</Button>\n </div>\n </Row>}\n </Section>;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { type Notify } from './site.ts';
2
+ /** The event the shell raises when the host hands it a `waybetter://setup` link opened from outside. */
3
+ export declare const SETUP_LINK_EVENT = "wb-setup-link";
4
+ /** Keeps a link opened from outside until the section is on screen to preview it. */
5
+ export declare function receiveSetupLink(text: string): void;
6
+ export declare function ShareSetup({ notify }: {
7
+ notify: Notify;
8
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,130 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Settings → Backup & sync → "Share my setup" (setupModel.ts): the look, the mode and which
3
+ // features are on, as one `waybetter://setup` link or one small file, and the way back in: paste a
4
+ // link, open a file, or open a link from outside (the host forwards its text, `setup-link`). Nothing
5
+ // is applied before the owner has seen "What will change" and pressed Apply. The section shows only
6
+ // when the app names itself (`PanelSite.setup`).
7
+ import { useEffect, useRef, useState } from 'react';
8
+ import { modeById, normalizeFlags, sparseFlags } from "../../runtime/featureTable.js";
9
+ import { invoke } from "../frame/bridge.js";
10
+ import { useT } from "../frame/hooks.js";
11
+ import { tx } from "../frame/i18n.js";
12
+ import { Button, InputRow, Row, Section } from "./controls.js";
13
+ import { flagName, rememberModeState } from "./Modes.js";
14
+ import { featureTable, flagsChanged } from "./PluginFeatures.js";
15
+ import { SETUP_FILE_SUFFIX, applySetup, makeSetup, readSetup, setupFile, setupLink, setupPlan } from "./setupModel.js";
16
+ import { panelSite } from "./site.js";
17
+ /** The event the shell raises when the host hands it a `waybetter://setup` link opened from outside. */
18
+ export const SETUP_LINK_EVENT = 'wb-setup-link';
19
+ let pendingLink = null;
20
+ /** Keeps a link opened from outside until the section is on screen to preview it. */
21
+ export function receiveSetupLink(text) {
22
+ pendingLink = text;
23
+ window.dispatchEvent(new CustomEvent(SETUP_LINK_EVENT));
24
+ }
25
+ async function currentState() {
26
+ const site = panelSite();
27
+ const table = featureTable();
28
+ await site.themes?.store.loadThemes();
29
+ const choice = site.themes?.store.themeState().choice;
30
+ const flags = normalizeFlags(table, await invoke('features_get'));
31
+ const mode = table.modes.length ? (await invoke('mode_get')).mode : null;
32
+ return { ...(choice ? { theme: { preset: choice.preset, accent: choice.accent, ...(choice.icons ? { icons: choice.icons } : {}) } } : {}), mode, flags };
33
+ }
34
+ function download(name, text) {
35
+ const url = URL.createObjectURL(new Blob([text], { type: 'application/json' }));
36
+ const anchor = document.createElement('a');
37
+ anchor.href = url;
38
+ anchor.download = name;
39
+ anchor.click();
40
+ setTimeout(() => URL.revokeObjectURL(url), 1000);
41
+ }
42
+ export function ShareSetup({ notify }) {
43
+ const site = panelSite();
44
+ return site.setup && featureTable() ? _jsx(ShareSetupOf, { app: site.setup.app, notify: notify }) : null;
45
+ }
46
+ function ShareSetupOf({ app, notify }) {
47
+ const t = useT();
48
+ const site = panelSite();
49
+ const table = featureTable();
50
+ const [text, setText] = useState('');
51
+ const [preview, setPreview] = useState(null);
52
+ const [busy, setBusy] = useState(false);
53
+ const file = useRef(null);
54
+ const store = site.themes?.store;
55
+ const error = (read) => read.error === 'app'
56
+ ? (read.app ? t('wb.setup.err.app', { app: read.app }) : t('wb.setup.err.appUnknown'))
57
+ : t(`wb.setup.err.${read.error}`);
58
+ async function open(input) {
59
+ const read = readSetup(input, app, table);
60
+ if (!read.ok) {
61
+ notify(error(read), true);
62
+ return;
63
+ }
64
+ try {
65
+ const now = await currentState();
66
+ const themes = new Set(store?.allThemes().map(theme => theme.id) ?? []);
67
+ const packs = new Set(site.themes?.iconPacks?.map(pack => pack.id) ?? []);
68
+ setPreview({ setup: read.setup, plan: setupPlan(table, now, read.setup, themes, packs), dropped: read.dropped, now });
69
+ }
70
+ catch (err) {
71
+ notify(err instanceof Error ? err.message : String(err), true);
72
+ }
73
+ }
74
+ // A link opened from outside (the host's `setup-link` event, forwarded by the shell).
75
+ useEffect(() => {
76
+ const take = () => { const link = pendingLink; pendingLink = null; if (link)
77
+ void open(link); };
78
+ take();
79
+ window.addEventListener(SETUP_LINK_EVENT, take);
80
+ return () => window.removeEventListener(SETUP_LINK_EVENT, take);
81
+ }, []);
82
+ async function share(kind) {
83
+ try {
84
+ const setup = makeSetup(app, table, await currentState());
85
+ if (kind === 'file') {
86
+ download(`setup${SETUP_FILE_SUFFIX}`, setupFile(setup));
87
+ return;
88
+ }
89
+ await navigator.clipboard.writeText(setupLink(setup)).then(() => notify(t('wb.setup.linkCopied')), () => notify(t('wb.common.clipboardUnavailable'), true));
90
+ }
91
+ catch (err) {
92
+ notify(err instanceof Error ? err.message : String(err), true);
93
+ }
94
+ }
95
+ async function apply() {
96
+ if (!preview)
97
+ return;
98
+ setBusy(true);
99
+ try {
100
+ const { plan, now } = preview;
101
+ const next = applySetup(table, now, plan);
102
+ if (plan.on.length || plan.off.length) {
103
+ await invoke('features_set', { features: sparseFlags(table, next.flags) });
104
+ flagsChanged();
105
+ }
106
+ if (store && next.theme && (plan.theme || plan.accent || plan.icons)) {
107
+ const choice = store.themeState().choice;
108
+ const { icons: _icons, ...rest } = choice;
109
+ await store.setChoice({ ...rest, preset: next.theme.preset, accent: next.theme.accent, ...(plan.theme ? { overrides: {} } : {}), ...(next.theme.icons ? { icons: next.theme.icons } : {}) });
110
+ }
111
+ if (plan.mode)
112
+ rememberModeState(await invoke('mode_set', { mode: next.mode, onboarded: true, preset: modeById(table, next.mode)?.flags ?? {} }));
113
+ setPreview(null);
114
+ setText('');
115
+ notify(t('wb.setup.applied'));
116
+ }
117
+ catch (err) {
118
+ notify(err instanceof Error ? err.message : String(err), true);
119
+ }
120
+ finally {
121
+ setBusy(false);
122
+ }
123
+ }
124
+ const themeName = (id) => store?.themeName(id) ?? id;
125
+ const iconName = (id) => id === undefined ? t('wb.appearance.icons.theme') : id === 'site' ? t('wb.appearance.icons.site') : site.themes?.iconPacks?.find(pack => pack.id === id)?.name ?? id;
126
+ const modeName = (id) => id ? tx(modeById(table, id)?.name ?? id, undefined, id) : t('wb.setup.modeNone');
127
+ const names = (ids) => ids.map(id => flagName(table, id)).join(', ');
128
+ return _jsxs(Section, { title: t('wb.setup.title'), hint: t('wb.setup.hint'), id: "setup", children: [_jsx(Row, { label: t('wb.setup.shareLabel'), hint: t('wb.setup.private'), keywords: "share setup link export copy send friend", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { tone: "primary", onClick: () => void share('link'), children: t('wb.setup.copyLink') }), _jsx(Button, { onClick: () => void share('file'), children: t('wb.setup.saveFile') })] }) }), _jsx(Row, { label: t('wb.setup.useLabel'), hint: t('wb.setup.useHint'), keywords: "import setup link apply", wide: true, children: _jsxs("div", { className: "bt-inline", children: [_jsx(InputRow, { value: text, onChange: setText, onSubmit: () => void open(text), placeholder: "waybetter://setup?\u2026", label: t('wb.setup.paste'), button: t('wb.setup.preview'), disabled: !text.trim(), mono: true }), _jsx(Button, { onClick: () => file.current?.click(), children: t('wb.setup.openFile') }), _jsx("input", { ref: file, type: "file", hidden: true, accept: "application/json,.json", onChange: event => { void event.target.files?.[0]?.text().then(open); event.target.value = ''; } })] }) }), preview && _jsx(Row, { label: t('wb.setup.changes'), wide: true, children: _jsxs("div", { className: "wbf-ask", role: "alertdialog", "aria-label": t('wb.setup.changes'), children: [preview.plan.same && _jsx("small", { children: t('wb.setup.same') }), preview.plan.theme && _jsx("small", { children: t('wb.setup.theme', { from: themeName(preview.plan.theme.from), to: themeName(preview.plan.theme.to) }) }), preview.plan.accent && _jsx("small", { children: t('wb.setup.accent', { to: preview.plan.accent.to ?? t('wb.setup.accentTheme') }) }), preview.plan.icons && _jsx("small", { children: t('wb.setup.icons', { to: iconName(preview.plan.icons.to) }) }), preview.plan.mode && _jsx("small", { children: t('wb.setup.mode', { from: modeName(preview.plan.mode.from), to: modeName(preview.plan.mode.to) }) }), preview.plan.on.length > 0 && _jsx("small", { children: t('wb.modes.turnsOn', { list: names(preview.plan.on) }) }), preview.plan.off.length > 0 && _jsx("small", { children: t('wb.modes.turnsOff', { list: names(preview.plan.off) }) }), preview.plan.missingTheme && _jsx("small", { children: t('wb.setup.missingTheme', { id: preview.plan.missingTheme }) }), preview.plan.missingIcons && _jsx("small", { children: t('wb.setup.missingIcons', { id: preview.plan.missingIcons }) }), preview.dropped.length > 0 && _jsx("small", { children: t('wb.setup.dropped', { list: preview.dropped.join(', ') }) }), !preview.plan.same && _jsx(Button, { size: "sm", tone: "primary", disabled: busy, onClick: () => void apply(), children: t('wb.setup.apply') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => setPreview(null), children: t('wb.common.cancel') })] }) })] });
129
+ }
130
+ //# sourceMappingURL=ShareSetup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShareSetup.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/ShareSetup.tsx"],"names":[],"mappings":"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","sourcesContent":["// Settings → Backup & sync → \"Share my setup\" (setupModel.ts): the look, the mode and which\n// features are on, as one `waybetter://setup` link or one small file, and the way back in: paste a\n// link, open a file, or open a link from outside (the host forwards its text, `setup-link`). Nothing\n// is applied before the owner has seen \"What will change\" and pressed Apply. The section shows only\n// when the app names itself (`PanelSite.setup`).\nimport { useEffect, useRef, useState } from 'react';\nimport { modeById, normalizeFlags, sparseFlags, type Flags } from '../../../runtime/src/featureTable.ts';\nimport type { ThemeChoice } from '../../../runtime/src/themeChoice.ts';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { tx } from '../frame/i18n.ts';\nimport { Button, InputRow, Row, Section } from './controls.tsx';\nimport { flagName, rememberModeState, type ModeState } from './Modes.tsx';\nimport { featureTable, flagsChanged } from './PluginFeatures.tsx';\nimport { SETUP_FILE_SUFFIX, applySetup, makeSetup, readSetup, setupFile, setupLink, setupPlan, type ReadSetup, type SetupPlan, type SetupState, type SharedSetup } from './setupModel.ts';\nimport { panelSite, type Notify } from './site.ts';\n\n/** The event the shell raises when the host hands it a `waybetter://setup` link opened from outside. */\nexport const SETUP_LINK_EVENT = 'wb-setup-link';\nlet pendingLink: string | null = null;\n\n/** Keeps a link opened from outside until the section is on screen to preview it. */\nexport function receiveSetupLink(text: string) {\n pendingLink = text;\n window.dispatchEvent(new CustomEvent(SETUP_LINK_EVENT));\n}\n\nasync function currentState(): Promise<SetupState> {\n const site = panelSite();\n const table = featureTable()!;\n await site.themes?.store.loadThemes();\n const choice = site.themes?.store.themeState().choice as ThemeChoice | undefined;\n const flags = normalizeFlags(table, await invoke<unknown>('features_get'));\n const mode = table.modes.length ? (await invoke<ModeState>('mode_get')).mode : null;\n return { ...(choice ? { theme: { preset: choice.preset, accent: choice.accent, ...(choice.icons ? { icons: choice.icons } : {}) } } : {}), mode, flags };\n}\n\nfunction download(name: string, text: string) {\n const url = URL.createObjectURL(new Blob([text], { type: 'application/json' }));\n const anchor = document.createElement('a');\n anchor.href = url; anchor.download = name; anchor.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\ntype Preview = { setup: SharedSetup; plan: SetupPlan; dropped: string[]; now: SetupState };\n\nexport function ShareSetup({ notify }: { notify: Notify }) {\n const site = panelSite();\n return site.setup && featureTable() ? <ShareSetupOf app={site.setup.app} notify={notify}/> : null;\n}\n\nfunction ShareSetupOf({ app, notify }: { app: string; notify: Notify }) {\n const t = useT();\n const site = panelSite();\n const table = featureTable()!;\n const [text, setText] = useState('');\n const [preview, setPreview] = useState<Preview | null>(null);\n const [busy, setBusy] = useState(false);\n const file = useRef<HTMLInputElement>(null);\n const store = site.themes?.store;\n\n const error = (read: Extract<ReadSetup, { ok: false }>) => read.error === 'app'\n ? (read.app ? t('wb.setup.err.app', { app: read.app }) : t('wb.setup.err.appUnknown'))\n : t(`wb.setup.err.${read.error}`);\n\n async function open(input: string) {\n const read = readSetup(input, app, table);\n if (!read.ok) { notify(error(read), true); return; }\n try {\n const now = await currentState();\n const themes = new Set(store?.allThemes().map(theme => theme.id) ?? []);\n const packs = new Set(site.themes?.iconPacks?.map(pack => pack.id) ?? []);\n setPreview({ setup: read.setup, plan: setupPlan(table, now, read.setup, themes, packs), dropped: read.dropped, now });\n } catch (err) { notify(err instanceof Error ? err.message : String(err), true); }\n }\n\n // A link opened from outside (the host's `setup-link` event, forwarded by the shell).\n useEffect(() => {\n const take = () => { const link = pendingLink; pendingLink = null; if (link) void open(link); };\n take();\n window.addEventListener(SETUP_LINK_EVENT, take);\n return () => window.removeEventListener(SETUP_LINK_EVENT, take);\n }, []);\n\n async function share(kind: 'link' | 'file') {\n try {\n const setup = makeSetup(app, table, await currentState());\n if (kind === 'file') { download(`setup${SETUP_FILE_SUFFIX}`, setupFile(setup)); return; }\n await navigator.clipboard.writeText(setupLink(setup)).then(() => notify(t('wb.setup.linkCopied')), () => notify(t('wb.common.clipboardUnavailable'), true));\n } catch (err) { notify(err instanceof Error ? err.message : String(err), true); }\n }\n\n async function apply() {\n if (!preview) return;\n setBusy(true);\n try {\n const { plan, now } = preview;\n const next = applySetup(table, now, plan);\n if (plan.on.length || plan.off.length) {\n await invoke('features_set', { features: sparseFlags(table, next.flags as Flags) });\n flagsChanged();\n }\n if (store && next.theme && (plan.theme || plan.accent || plan.icons)) {\n const choice = store.themeState().choice as ThemeChoice;\n const { icons: _icons, ...rest } = choice;\n await store.setChoice({ ...rest, preset: next.theme.preset, accent: next.theme.accent, ...(plan.theme ? { overrides: {} } : {}), ...(next.theme.icons ? { icons: next.theme.icons } : {}) });\n }\n if (plan.mode) rememberModeState(await invoke<ModeState>('mode_set', { mode: next.mode, onboarded: true, preset: modeById(table, next.mode)?.flags ?? {} }));\n setPreview(null);\n setText('');\n notify(t('wb.setup.applied'));\n } catch (err) { notify(err instanceof Error ? err.message : String(err), true); }\n finally { setBusy(false); }\n }\n\n const themeName = (id: string) => store?.themeName(id) ?? id;\n const iconName = (id: string | undefined) => id === undefined ? t('wb.appearance.icons.theme') : id === 'site' ? t('wb.appearance.icons.site') : site.themes?.iconPacks?.find(pack => pack.id === id)?.name ?? id;\n const modeName = (id: string | null) => id ? tx(modeById(table, id)?.name ?? id, undefined, id) : t('wb.setup.modeNone');\n const names = (ids: readonly string[]) => ids.map(id => flagName(table, id)).join(', ');\n\n return <Section title={t('wb.setup.title')} hint={t('wb.setup.hint')} id=\"setup\">\n <Row label={t('wb.setup.shareLabel')} hint={t('wb.setup.private')} keywords=\"share setup link export copy send friend\">\n <div className=\"bt-inline\">\n <Button tone=\"primary\" onClick={() => void share('link')}>{t('wb.setup.copyLink')}</Button>\n <Button onClick={() => void share('file')}>{t('wb.setup.saveFile')}</Button>\n </div>\n </Row>\n <Row label={t('wb.setup.useLabel')} hint={t('wb.setup.useHint')} keywords=\"import setup link apply\" wide>\n <div className=\"bt-inline\">\n <InputRow value={text} onChange={setText} onSubmit={() => void open(text)} placeholder=\"waybetter://setup?…\" label={t('wb.setup.paste')} button={t('wb.setup.preview')} disabled={!text.trim()} mono/>\n <Button onClick={() => file.current?.click()}>{t('wb.setup.openFile')}</Button>\n <input ref={file} type=\"file\" hidden accept=\"application/json,.json\" onChange={event => { void event.target.files?.[0]?.text().then(open); event.target.value = ''; }}/>\n </div>\n </Row>\n {preview && <Row label={t('wb.setup.changes')} wide>\n <div className=\"wbf-ask\" role=\"alertdialog\" aria-label={t('wb.setup.changes')}>\n {preview.plan.same && <small>{t('wb.setup.same')}</small>}\n {preview.plan.theme && <small>{t('wb.setup.theme', { from: themeName(preview.plan.theme.from), to: themeName(preview.plan.theme.to) })}</small>}\n {preview.plan.accent && <small>{t('wb.setup.accent', { to: preview.plan.accent.to ?? t('wb.setup.accentTheme') })}</small>}\n {preview.plan.icons && <small>{t('wb.setup.icons', { to: iconName(preview.plan.icons.to) })}</small>}\n {preview.plan.mode && <small>{t('wb.setup.mode', { from: modeName(preview.plan.mode.from), to: modeName(preview.plan.mode.to) })}</small>}\n {preview.plan.on.length > 0 && <small>{t('wb.modes.turnsOn', { list: names(preview.plan.on) })}</small>}\n {preview.plan.off.length > 0 && <small>{t('wb.modes.turnsOff', { list: names(preview.plan.off) })}</small>}\n {preview.plan.missingTheme && <small>{t('wb.setup.missingTheme', { id: preview.plan.missingTheme })}</small>}\n {preview.plan.missingIcons && <small>{t('wb.setup.missingIcons', { id: preview.plan.missingIcons })}</small>}\n {preview.dropped.length > 0 && <small>{t('wb.setup.dropped', { list: preview.dropped.join(', ') })}</small>}\n {!preview.plan.same && <Button size=\"sm\" tone=\"primary\" disabled={busy} onClick={() => void apply()}>{t('wb.setup.apply')}</Button>}\n <Button size=\"sm\" tone=\"ghost\" onClick={() => setPreview(null)}>{t('wb.common.cancel')}</Button>\n </div>\n </Row>}\n </Section>;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import '../store.css';
2
+ import { type Notify } from './site.ts';
3
+ import './plugins.css';
4
+ export declare function StoreSection({ notify }: {
5
+ notify: Notify;
6
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // The wayBetter Store section: the Store view (StoreView.tsx) with the panel's own controls, the
3
+ // app's built-in and own themes, and removal of installed items. Native code verifies the catalog's
4
+ // Ed25519 signature, keeps the app's items, then checks each download's sha256. Installing always
5
+ // goes through the shell's install screen (InstallDialog), never straight from here.
6
+ import { invoke } from "../frame/bridge.js";
7
+ import { useT } from "../frame/hooks.js";
8
+ import { relativeTime } from "../frame/i18n.js";
9
+ import { site } from "../frame/site.js";
10
+ import { StoreView } from "../StoreView.js";
11
+ import '../store.css';
12
+ import { Badge, Button, EmptyState, SearchField, Segmented, useSettingsQuery } from "./controls.js";
13
+ import { panelSite, panelThemes } from "./site.js";
14
+ import { useThemeState } from "./themes.js";
15
+ import './plugins.css';
16
+ const CONTROLS = { Button, SearchField, Segmented, EmptyState, Badge };
17
+ const RELOAD_ON = ['bt-plugins-changed', 'bt-store-changed', 'bt-strings-changed'];
18
+ export function StoreSection({ notify }) {
19
+ const t = useT();
20
+ const { store, catalog } = panelThemes();
21
+ const themes = useThemeState();
22
+ const settingsQuery = useSettingsQuery();
23
+ if (settingsQuery)
24
+ return null;
25
+ const userThemes = themes.choice.themes.map(theme => theme.id);
26
+ async function remove(item, view) {
27
+ if (item.kind === 'strings') {
28
+ await invoke('strings_remove', { id: item.id });
29
+ window.dispatchEvent(new CustomEvent('bt-strings-changed'));
30
+ return true;
31
+ }
32
+ if (item.kind === 'plugin' && item.file) {
33
+ await invoke('plugin_remove', { file: item.file });
34
+ window.dispatchEvent(new CustomEvent('bt-plugins-changed'));
35
+ return true;
36
+ }
37
+ const record = Object.entries(view.records.items).find(([key, value]) => key.startsWith('theme:') && value.storeId === item.id && userThemes.includes(key.slice(6)));
38
+ const id = record?.[0].slice(6);
39
+ if (!id)
40
+ return false;
41
+ const choice = themes.choice;
42
+ await store.setChoice({ ...choice, themes: choice.themes.filter(theme => theme.id !== id), ...(choice.preset === id ? { preset: catalog.defaultChoice.preset, overrides: {}, accent: null } : {}) });
43
+ await invoke('install_forget', { kind: 'theme', name: id });
44
+ return true;
45
+ }
46
+ return _jsx(StoreView, { t: t, site: site().name, load: refresh => invoke('store_catalog', { refresh }), controller: panelSite().store.controller, builtinThemes: catalog.builtins.map(theme => theme.id), userThemes: userThemes, onRemove: remove, onUse: item => store.setChoice({ ...themes.choice, preset: item.id, overrides: {}, accent: null }), notify: notify, relativeTime: relativeTime, reloadOn: RELOAD_ON, controls: CONTROLS });
47
+ }
48
+ //# sourceMappingURL=StoreSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StoreSection.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/StoreSection.tsx"],"names":[],"mappings":";AAAA,iGAAiG;AACjG,oGAAoG;AACpG,kGAAkG;AAClG,qFAAqF;AACrF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,OAAO,EAAE,SAAS,EAAsB,MAAM,iBAAkB,CAAC;AACjE,OAAO,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAgB,CAAC;AACrG,OAAO,EAAE,SAAS,EAAE,WAAW,EAAe,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,eAAe,CAAC;AAEvB,MAAM,QAAQ,GAA2B,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AAC/F,MAAM,SAAS,GAAG,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,oBAAoB,CAAC,CAAC;AAEnF,MAAM,UAAU,YAAY,CAAC,EAAE,MAAM,EAAsB;IACzD,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,IAAI,aAAa;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAE/D,KAAK,UAAU,MAAM,CAAC,IAAe,EAAE,IAAsB;QAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,MAAM,CAAC,gBAAgB,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAChD,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,MAAM,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrK,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QACtB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,MAAM,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACrM,MAAM,MAAM,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAC,SAAS,IACf,CAAC,EAAE,CAAC,EACJ,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,EACjB,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,MAAM,CAAmB,eAAe,EAAE,EAAE,OAAO,EAAE,CAAC,EACvE,UAAU,EAAE,SAAS,EAAE,CAAC,KAAM,CAAC,UAAU,EACzC,aAAa,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EACtD,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAClG,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,SAAS,EACnB,QAAQ,EAAE,QAAQ,GAClB,CAAC;AACL,CAAC","sourcesContent":["// The wayBetter Store section: the Store view (StoreView.tsx) with the panel's own controls, the\n// app's built-in and own themes, and removal of installed items. Native code verifies the catalog's\n// Ed25519 signature, keeps the app's items, then checks each download's sha256. Installing always\n// goes through the shell's install screen (InstallDialog), never straight from here.\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { relativeTime } from '../frame/i18n.ts';\nimport { site } from '../frame/site.ts';\nimport type { StoreCatalogView, StoreItem } from '../storeModel.ts';\nimport { StoreView, type StoreControls } from '../StoreView.tsx';\nimport '../store.css';\nimport { Badge, Button, EmptyState, SearchField, Segmented, useSettingsQuery } from './controls.tsx';\nimport { panelSite, panelThemes, type Notify } from './site.ts';\nimport { useThemeState } from './themes.ts';\nimport './plugins.css';\n\nconst CONTROLS: Partial<StoreControls> = { Button, SearchField, Segmented, EmptyState, Badge };\nconst RELOAD_ON = ['bt-plugins-changed', 'bt-store-changed', 'bt-strings-changed'];\n\nexport function StoreSection({ notify }: { notify: Notify }) {\n const t = useT();\n const { store, catalog } = panelThemes();\n const themes = useThemeState();\n const settingsQuery = useSettingsQuery();\n if (settingsQuery) return null;\n const userThemes = themes.choice.themes.map(theme => theme.id);\n\n async function remove(item: StoreItem, view: StoreCatalogView): Promise<boolean> {\n if (item.kind === 'strings') {\n await invoke('strings_remove', { id: item.id });\n window.dispatchEvent(new CustomEvent('bt-strings-changed'));\n return true;\n }\n if (item.kind === 'plugin' && item.file) {\n await invoke('plugin_remove', { file: item.file });\n window.dispatchEvent(new CustomEvent('bt-plugins-changed'));\n return true;\n }\n const record = Object.entries(view.records.items).find(([key, value]) => key.startsWith('theme:') && value.storeId === item.id && userThemes.includes(key.slice(6)));\n const id = record?.[0].slice(6);\n if (!id) return false;\n const choice = themes.choice;\n await store.setChoice({ ...choice, themes: choice.themes.filter(theme => theme.id !== id), ...(choice.preset === id ? { preset: catalog.defaultChoice.preset, overrides: {}, accent: null } : {}) });\n await invoke('install_forget', { kind: 'theme', name: id });\n return true;\n }\n\n return <StoreView\n t={t}\n site={site().name}\n load={refresh => invoke<StoreCatalogView>('store_catalog', { refresh })}\n controller={panelSite().store!.controller}\n builtinThemes={catalog.builtins.map(theme => theme.id)}\n userThemes={userThemes}\n onRemove={remove}\n onUse={item => store.setChoice({ ...themes.choice, preset: item.id, overrides: {}, accent: null })}\n notify={notify}\n relativeTime={relativeTime}\n reloadOn={RELOAD_ON}\n controls={CONTROLS}\n />;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import type { PageInventory } from '../../runtime/stringPacks.ts';
2
+ import { type InstalledStrings } from '../stringPacksModel.ts';
3
+ import type { PanelSection } from './site.ts';
4
+ import './strings.css';
5
+ /** Hands the site tabs the packs that are on (in `packs` order). */
6
+ export declare function applyStringPacks(inventory: PageInventory, packs?: InstalledStrings[]): Promise<void>;
7
+ export declare function createStringPacksSection(options: {
8
+ inventory: PageInventory;
9
+ id?: string;
10
+ icon?: string;
11
+ }): PanelSection;
@@ -0,0 +1,106 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // The Languages section: the installed string packs (waybetter/docs/STRING-PACKS.md), which are on
3
+ // and in which order, with each pack's coverage against the site's inventory. Every change hands the
4
+ // site tabs the new delivery (`strings_apply`: the packs that are on, in order, with the inventory
5
+ // slice their keys need); the tabs reload to show it. Packs are data only: nothing here runs code.
6
+ import { useEffect, useState } from 'react';
7
+ import { invoke } from "../frame/bridge.js";
8
+ import { useT } from "../frame/hooks.js";
9
+ import { t as translate } from "../frame/i18n.js";
10
+ import { site } from "../frame/site.js";
11
+ import { buildDelivery, coveragePercent, packSummary } from "../stringPacksModel.js";
12
+ import { Badge, Button, EmptyState, Section, Toggle, useSettingsQuery } from "./controls.js";
13
+ import './strings.css';
14
+ const MAX_ON = 8;
15
+ const TRANSLATE_KEY = 'wb.strings.translate';
16
+ const translating = () => { try {
17
+ return localStorage.getItem(TRANSLATE_KEY) === '1';
18
+ }
19
+ catch {
20
+ return false;
21
+ } };
22
+ const ICON = 'M2.5 3.5h7M6 2v1.5M8 3.5c-.6 2.9-2.6 5-5.4 6.1M4.6 6.2c.8 1.2 2 2.2 3.4 2.9M9.5 14l3-7 3 7M10.6 11.8h3.8';
23
+ /** Hands the site tabs the packs that are on (in `packs` order). */
24
+ export async function applyStringPacks(inventory, packs) {
25
+ const list = packs ?? (await invoke('strings_list')).packs;
26
+ const texts = [];
27
+ for (const pack of list)
28
+ if (pack.enabled)
29
+ texts.push(await invoke('strings_read', { id: pack.id }));
30
+ await invoke('strings_apply', { delivery: buildDelivery(texts, inventory, { translate: translating() }) });
31
+ }
32
+ export function createStringPacksSection(options) {
33
+ const { inventory } = options;
34
+ function StringPacks({ notify, openSection }) {
35
+ const t = useT();
36
+ const query = useSettingsQuery();
37
+ const name = site().name;
38
+ const [rows, setRows] = useState(null);
39
+ const [busy, setBusy] = useState(false);
40
+ const [translate, setTranslate] = useState(translating);
41
+ const load = async () => {
42
+ const { packs } = await invoke('strings_list');
43
+ const next = [];
44
+ for (const pack of packs) {
45
+ const text = await invoke('strings_read', { id: pack.id }).catch(() => '');
46
+ next.push({ ...pack, summary: text ? packSummary(text, inventory) : null });
47
+ }
48
+ setRows(next);
49
+ };
50
+ useEffect(() => {
51
+ void load().catch(error => notify(String(error), true));
52
+ const reload = () => void load().catch(() => { });
53
+ window.addEventListener('bt-strings-changed', reload);
54
+ return () => window.removeEventListener('bt-strings-changed', reload);
55
+ }, []);
56
+ /** Saves order and on/off, then hands the tabs the new delivery. */
57
+ const save = async (next) => {
58
+ setBusy(true);
59
+ try {
60
+ const { packs } = await invoke('strings_set', { order: next.map(row => row.id), enabled: next.filter(row => row.enabled).map(row => row.id) });
61
+ await applyStringPacks(inventory, packs);
62
+ setRows(packs.map(pack => ({ ...pack, summary: next.find(row => row.id === pack.id)?.summary ?? null })));
63
+ notify(t('wb.strings.applied', { site: name }));
64
+ }
65
+ catch (error) {
66
+ notify(String(error), true);
67
+ }
68
+ finally {
69
+ setBusy(false);
70
+ }
71
+ };
72
+ if (query)
73
+ return null;
74
+ if (rows === null)
75
+ return null;
76
+ const on = rows.filter(row => row.enabled).length;
77
+ const move = (index, by) => {
78
+ const next = [...rows];
79
+ const [row] = next.splice(index, 1);
80
+ next.splice(index + by, 0, row);
81
+ void save(next);
82
+ };
83
+ return _jsxs(Section, { title: t('wb.strings.title'), hint: t('wb.strings.intro', { site: name }), children: [rows.length === 0
84
+ ? _jsx(EmptyState, { title: t('wb.strings.empty'), action: _jsx(Button, { onClick: () => openSection('store'), children: t('wb.strings.openStore') }), children: t('wb.strings.emptyHint') })
85
+ : _jsx("ul", { className: "btp-strings", "aria-label": t('wb.strings.title'), children: rows.map((row, index) => _jsxs("li", { className: `btp-strings-row${row.enabled ? ' is-on' : ''}`, children: [_jsx(Toggle, { label: t('wb.strings.on', { name: row.name }), checked: row.enabled, disabled: busy || (!row.enabled && on >= MAX_ON), onChange: checked => void save(rows.map(item => (item.id === row.id ? { ...item, enabled: checked } : item))) }), _jsxs("div", { className: "btp-strings-text", children: [_jsxs("span", { className: "btp-strings-head", children: [_jsx("strong", { children: row.name }), _jsx(Badge, { children: row.language }), _jsx(Badge, { tone: "ok", children: t('wb.strings.dataOnly') })] }), _jsx("small", { children: [row.authors.length ? t('wb.strings.by', { authors: row.authors.join(', ') }) : '', row.version && `v${row.version}`,
86
+ row.summary && !row.summary.otherCatalog ? t('wb.install.strings.coverageValue', { translated: String(row.summary.translated), translatable: String(row.summary.translatable), site: name, percent: coveragePercent(row.summary) }) : t('wb.install.strings.count', { count: row.strings })]
87
+ .filter(Boolean).join(' · ') })] }), _jsx(Button, { size: "sm", label: t('wb.strings.up'), disabled: busy || index === 0, onClick: () => move(index, -1), children: "\u2191" }), _jsx(Button, { size: "sm", label: t('wb.strings.down'), disabled: busy || index === rows.length - 1, onClick: () => move(index, 1), children: "\u2193" }), _jsx(Button, { size: "sm", tone: "danger", disabled: busy, onClick: () => {
88
+ setBusy(true);
89
+ void invoke('strings_remove', { id: row.id })
90
+ .then(async ({ packs }) => { await applyStringPacks(inventory, packs); notify(t('wb.strings.removed', { name: row.name })); await load(); })
91
+ .catch(error => notify(String(error), true))
92
+ .finally(() => setBusy(false));
93
+ }, children: t('wb.strings.remove') })] }, row.id)) }), on >= MAX_ON && _jsx("p", { className: "btp-hint", children: t('wb.strings.limit') }), _jsxs("div", { className: "btp-strings-row", children: [_jsx(Toggle, { label: t('wb.strings.translate'), checked: translate, disabled: busy, onChange: checked => {
94
+ try {
95
+ localStorage.setItem(TRANSLATE_KEY, checked ? '1' : '0');
96
+ }
97
+ catch { /* it still applies once */ }
98
+ setTranslate(checked);
99
+ setBusy(true);
100
+ void applyStringPacks(inventory).then(() => notify(t('wb.strings.applied', { site: name }))).catch(error => notify(String(error), true)).finally(() => setBusy(false));
101
+ } }), _jsxs("div", { className: "btp-strings-text", children: [_jsx("strong", { children: t('wb.strings.translate') }), _jsx("small", { children: t('wb.strings.translateHint', { site: name }) })] })] })] });
102
+ }
103
+ // The nav label: the plain translator (the panel calls `label()` outside React too).
104
+ return { id: options.id ?? 'languages', label: () => translate('wb.strings.section'), icon: options.icon ?? ICON, component: StringPacks };
105
+ }
106
+ //# sourceMappingURL=StringPacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StringPacks.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/StringPacks.tsx"],"names":[],"mappings":"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","sourcesContent":["// The Languages section: the installed string packs (waybetter/docs/STRING-PACKS.md), which are on\n// and in which order, with each pack's coverage against the site's inventory. Every change hands the\n// site tabs the new delivery (`strings_apply`: the packs that are on, in order, with the inventory\n// slice their keys need); the tabs reload to show it. Packs are data only: nothing here runs code.\nimport { useEffect, useState } from 'react';\nimport type { PageInventory } from '../../../runtime/src/stringPacks.ts';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { t as translate } from '../frame/i18n.ts';\nimport { site } from '../frame/site.ts';\nimport { buildDelivery, coveragePercent, packSummary, type InstalledStrings, type StringsSummary } from '../stringPacksModel.ts';\nimport { Badge, Button, EmptyState, Section, Toggle, useSettingsQuery } from './controls.tsx';\nimport type { PanelSection, SectionProps } from './site.ts';\nimport './strings.css';\n\nconst MAX_ON = 8;\nconst TRANSLATE_KEY = 'wb.strings.translate';\nconst translating = () => { try { return localStorage.getItem(TRANSLATE_KEY) === '1'; } catch { return false; } };\nconst ICON = 'M2.5 3.5h7M6 2v1.5M8 3.5c-.6 2.9-2.6 5-5.4 6.1M4.6 6.2c.8 1.2 2 2.2 3.4 2.9M9.5 14l3-7 3 7M10.6 11.8h3.8';\n\ntype Row = InstalledStrings & { summary: StringsSummary | null };\n\n/** Hands the site tabs the packs that are on (in `packs` order). */\nexport async function applyStringPacks(inventory: PageInventory, packs?: InstalledStrings[]): Promise<void> {\n const list = packs ?? (await invoke<{ packs: InstalledStrings[] }>('strings_list')).packs;\n const texts: string[] = [];\n for (const pack of list) if (pack.enabled) texts.push(await invoke<string>('strings_read', { id: pack.id }));\n await invoke('strings_apply', { delivery: buildDelivery(texts, inventory, { translate: translating() }) });\n}\n\nexport function createStringPacksSection(options: { inventory: PageInventory; id?: string; icon?: string }): PanelSection {\n const { inventory } = options;\n\n function StringPacks({ notify, openSection }: SectionProps) {\n const t = useT();\n const query = useSettingsQuery();\n const name = site().name;\n const [rows, setRows] = useState<Row[] | null>(null);\n const [busy, setBusy] = useState(false);\n const [translate, setTranslate] = useState(translating);\n\n const load = async () => {\n const { packs } = await invoke<{ packs: InstalledStrings[] }>('strings_list');\n const next: Row[] = [];\n for (const pack of packs) {\n const text = await invoke<string>('strings_read', { id: pack.id }).catch(() => '');\n next.push({ ...pack, summary: text ? packSummary(text, inventory) : null });\n }\n setRows(next);\n };\n useEffect(() => {\n void load().catch(error => notify(String(error), true));\n const reload = () => void load().catch(() => {});\n window.addEventListener('bt-strings-changed', reload);\n return () => window.removeEventListener('bt-strings-changed', reload);\n }, []);\n\n /** Saves order and on/off, then hands the tabs the new delivery. */\n const save = async (next: Row[]) => {\n setBusy(true);\n try {\n const { packs } = await invoke<{ packs: InstalledStrings[] }>('strings_set', { order: next.map(row => row.id), enabled: next.filter(row => row.enabled).map(row => row.id) });\n await applyStringPacks(inventory, packs);\n setRows(packs.map(pack => ({ ...pack, summary: next.find(row => row.id === pack.id)?.summary ?? null })));\n notify(t('wb.strings.applied', { site: name }));\n } catch (error) {\n notify(String(error), true);\n } finally {\n setBusy(false);\n }\n };\n\n if (query) return null;\n if (rows === null) return null;\n const on = rows.filter(row => row.enabled).length;\n const move = (index: number, by: number) => {\n const next = [...rows];\n const [row] = next.splice(index, 1);\n next.splice(index + by, 0, row!);\n void save(next);\n };\n\n return <Section title={t('wb.strings.title')} hint={t('wb.strings.intro', { site: name })}>\n {rows.length === 0\n ? <EmptyState title={t('wb.strings.empty')} action={<Button onClick={() => openSection('store')}>{t('wb.strings.openStore')}</Button>}>{t('wb.strings.emptyHint')}</EmptyState>\n : <ul className=\"btp-strings\" aria-label={t('wb.strings.title')}>\n {rows.map((row, index) => <li key={row.id} className={`btp-strings-row${row.enabled ? ' is-on' : ''}`}>\n <Toggle label={t('wb.strings.on', { name: row.name })} checked={row.enabled} disabled={busy || (!row.enabled && on >= MAX_ON)}\n onChange={checked => void save(rows.map(item => (item.id === row.id ? { ...item, enabled: checked } : item)))}/>\n <div className=\"btp-strings-text\">\n <span className=\"btp-strings-head\"><strong>{row.name}</strong><Badge>{row.language}</Badge><Badge tone=\"ok\">{t('wb.strings.dataOnly')}</Badge></span>\n <small>\n {[row.authors.length ? t('wb.strings.by', { authors: row.authors.join(', ') }) : '', row.version && `v${row.version}`,\n row.summary && !row.summary.otherCatalog ? t('wb.install.strings.coverageValue', { translated: String(row.summary.translated), translatable: String(row.summary.translatable), site: name, percent: coveragePercent(row.summary) }) : t('wb.install.strings.count', { count: row.strings })]\n .filter(Boolean).join(' · ')}\n </small>\n </div>\n <Button size=\"sm\" label={t('wb.strings.up')} disabled={busy || index === 0} onClick={() => move(index, -1)}>↑</Button>\n <Button size=\"sm\" label={t('wb.strings.down')} disabled={busy || index === rows.length - 1} onClick={() => move(index, 1)}>↓</Button>\n <Button size=\"sm\" tone=\"danger\" disabled={busy} onClick={() => {\n setBusy(true);\n void invoke<{ packs: InstalledStrings[] }>('strings_remove', { id: row.id })\n .then(async ({ packs }) => { await applyStringPacks(inventory, packs); notify(t('wb.strings.removed', { name: row.name })); await load(); })\n .catch(error => notify(String(error), true))\n .finally(() => setBusy(false));\n }}>{t('wb.strings.remove')}</Button>\n </li>)}\n </ul>}\n {on >= MAX_ON && <p className=\"btp-hint\">{t('wb.strings.limit')}</p>}\n <div className=\"btp-strings-row\">\n <Toggle label={t('wb.strings.translate')} checked={translate} disabled={busy} onChange={checked => {\n try { localStorage.setItem(TRANSLATE_KEY, checked ? '1' : '0'); } catch { /* it still applies once */ }\n setTranslate(checked);\n setBusy(true);\n void applyStringPacks(inventory).then(() => notify(t('wb.strings.applied', { site: name }))).catch(error => notify(String(error), true)).finally(() => setBusy(false));\n }}/>\n <div className=\"btp-strings-text\"><strong>{t('wb.strings.translate')}</strong><small>{t('wb.strings.translateHint', { site: name })}</small></div>\n </div>\n </Section>;\n }\n\n // The nav label: the plain translator (the panel calls `label()` outside React too).\n return { id: options.id ?? 'languages', label: () => translate('wb.strings.section'), icon: options.icon ?? ICON, component: StringPacks };\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import { type Notify } from './site.ts';
2
+ import './builder.css';
3
+ export declare function ThemeBuilder({ notify }: {
4
+ notify: Notify;
5
+ }): import("react").JSX.Element;