waybetter 0.1.1 → 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 +140 -6
  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 +139 -5
  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,198 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Settings → Backup & sync: export everything into one `.waybetter` file, import one with a preview
3
+ // and a checkbox per section, and the optional encrypted sync through a folder the owner already
4
+ // syncs (OneDrive, iCloud Drive, Dropbox...). Files, crypto and the key stay native
5
+ // (waybetter-host backup.rs and sync.rs behind the app's `backup_*` and `sync_*` commands); nothing
6
+ // here talks to a server. The sync part shows only with the frame's `sync` feature.
7
+ import { useEffect, useState } from 'react';
8
+ import { ago, diffSections, pickSections } from "../frame/backupModel.js";
9
+ import { invoke } from "../frame/bridge.js";
10
+ import { replaceDecks } from "../frame/deckStore.js";
11
+ import { useSync, useT } from "../frame/hooks.js";
12
+ import { formatDate } from "../frame/i18n.js";
13
+ import { hasFeature } from "../frame/site.js";
14
+ import { setProfiles } from "../frame/state.js";
15
+ import { checkNewer, clearNewer, pushNow, refreshSync, setSyncStatus, shellSections } from "../frame/syncHost.js";
16
+ import { loadWorkspaces } from "../frame/workspaces.js";
17
+ import { Badge, Button, InputRow, Row, Section, Toggle } from "./controls.js";
18
+ import { panelSite } from "./site.js";
19
+ import './backup.css';
20
+ const getError = (error) => (error instanceof Error ? error.message : String(error)).replace(/^(BACKUP|SYNC|VALIDATION): /, '');
21
+ /** Tells the rest of the shell that settings changed under it (import, pull). */
22
+ async function refreshAfterImport() {
23
+ await Promise.allSettled([
24
+ panelSite().themes?.store.loadThemes(),
25
+ invoke('profiles_get').then(setProfiles),
26
+ hasFeature('workspaces') ? loadWorkspaces() : undefined,
27
+ ]);
28
+ window.dispatchEvent(new CustomEvent('bt-settings-imported'));
29
+ }
30
+ export function BackupPanel({ notify }) {
31
+ const t = useT();
32
+ const [preview, setPreview] = useState(null);
33
+ const sync = useSync();
34
+ // The titlebar chip "Settings from <computer>" opens this section and asks to review that snapshot.
35
+ useEffect(() => {
36
+ const onReview = (event) => { const name = event.detail; if (name)
37
+ void review(name); };
38
+ window.addEventListener('bt-sync-review', onReview);
39
+ return () => window.removeEventListener('bt-sync-review', onReview);
40
+ }, []);
41
+ async function review(name) {
42
+ try {
43
+ const sections = await invoke('sync_open', { name });
44
+ const info = syncStateSnapshot(name);
45
+ setPreview({ title: t('wb.backup.fromDevice', { device: info?.deviceName ?? t('wb.backup.anotherComputer') }), subtitle: info ? t('wb.backup.syncedAgo', { when: ago(info.createdAt) }) : t('wb.backup.encryptedSnapshot'), sections, snapshot: name });
46
+ }
47
+ catch (error) {
48
+ notify(getError(error), true);
49
+ }
50
+ }
51
+ const syncStateSnapshot = (name) => sync.status?.snapshots.find(item => item.name === name) ?? (sync.newer?.name === name ? sync.newer : null);
52
+ if (preview) {
53
+ return _jsx(ImportPreview, { ...preview, notify: notify, onCancel: async () => {
54
+ if (preview.snapshot) {
55
+ await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => { });
56
+ clearNewer();
57
+ }
58
+ setPreview(null);
59
+ }, onDone: async () => {
60
+ if (preview.snapshot) {
61
+ await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => { });
62
+ clearNewer();
63
+ void refreshSync();
64
+ }
65
+ setPreview(null);
66
+ } });
67
+ }
68
+ return _jsxs(_Fragment, { children: [_jsx(ExportSection, { notify: notify, onOpen: (title, subtitle, sections) => setPreview({ title, subtitle, sections }) }), hasFeature('sync') && _jsx(SyncSection, { notify: notify, onReview: review })] });
69
+ }
70
+ function ExportSection({ notify, onOpen }) {
71
+ const t = useT();
72
+ const [drafts, setDrafts] = useState(false);
73
+ const [busy, setBusy] = useState(false);
74
+ async function exportFile() {
75
+ setBusy(true);
76
+ try {
77
+ const path = await invoke('backup_export_file', { includeDrafts: drafts, extra: shellSections() });
78
+ if (path)
79
+ notify(t('wb.backup.saved', { file: path.split(/[\\/]/).pop() ?? path }));
80
+ }
81
+ catch (error) {
82
+ notify(getError(error), true);
83
+ }
84
+ finally {
85
+ setBusy(false);
86
+ }
87
+ }
88
+ async function importFile() {
89
+ try {
90
+ const opened = await invoke('backup_open_file');
91
+ if (!opened)
92
+ return;
93
+ const when = opened.createdAt ? formatDate(opened.createdAt, { dateStyle: 'medium', timeStyle: 'short' }) : t('wb.backup.unknownDate');
94
+ onOpen(t('wb.backup.importFile', { file: opened.file }), `${t('wb.backup.exportedAt', { when })}${opened.appVersion ? ` · ${panelSite().brand.name} ${opened.appVersion}` : ''}`, opened.sections);
95
+ }
96
+ catch (error) {
97
+ notify(getError(error), true);
98
+ }
99
+ }
100
+ return _jsxs(Section, { title: t('wb.backup.title'), hint: t('wb.backup.hint'), children: [_jsx(Row, { label: t('wb.backup.export'), hint: t('wb.backup.exportHint'), keywords: "backup export save file move computer", wide: true, children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { tone: "primary", disabled: busy, onClick: () => void exportFile(), children: busy ? t('wb.backup.exporting') : t('wb.backup.exportButton') }), _jsxs("label", { className: "btb-check", children: [_jsx("input", { type: "checkbox", checked: drafts, onChange: event => setDrafts(event.target.checked) }), t('wb.backup.includeDrafts')] })] }) }), _jsx(Row, { label: t('wb.backup.import'), hint: t('wb.backup.importHint'), keywords: "restore import load file", children: _jsx(Button, { onClick: () => void importFile(), children: t('wb.backup.importButton') }) })] });
101
+ }
102
+ function ImportPreview({ title, subtitle, sections, notify, onCancel, onDone }) {
103
+ const t = useT();
104
+ const [rows, setRows] = useState(null);
105
+ const [chosen, setChosen] = useState(new Set());
106
+ const [busy, setBusy] = useState(false);
107
+ useEffect(() => {
108
+ let alive = true;
109
+ invoke('backup_collect', { includeDrafts: false })
110
+ .catch(() => ({}))
111
+ .then(current => {
112
+ if (!alive)
113
+ return;
114
+ const next = diffSections({ ...current, ...shellSections() }, sections);
115
+ setRows(next);
116
+ setChosen(new Set(next.filter(row => row.checked).map(row => row.section)));
117
+ });
118
+ return () => { alive = false; };
119
+ }, [sections]);
120
+ async function apply() {
121
+ const { native, local } = pickSections(sections, chosen);
122
+ setBusy(true);
123
+ try {
124
+ const result = Object.keys(native).length ? await invoke('backup_apply', { sections: native }) : { applied: [], notes: [] };
125
+ const decks = local.decks;
126
+ if (decks)
127
+ replaceDecks(decks.decks, decks.settings);
128
+ await refreshAfterImport();
129
+ const count = result.applied.length + (decks ? 1 : 0);
130
+ notify([t('wb.backup.applied', { count }), ...result.notes].join(' '));
131
+ onDone();
132
+ }
133
+ catch (error) {
134
+ notify(getError(error), true);
135
+ }
136
+ finally {
137
+ setBusy(false);
138
+ }
139
+ }
140
+ const toggle = (section, on) => setChosen(previous => { const next = new Set(previous); if (on)
141
+ next.add(section);
142
+ else
143
+ next.delete(section); return next; });
144
+ return _jsxs(Section, { title: title, hint: subtitle, action: _jsx(Button, { tone: "ghost", size: "sm", onClick: onCancel, children: t('wb.common.cancel') }), children: [!rows && _jsx("div", { className: "btb-loading", children: t('wb.backup.comparing') }), rows && rows.length === 0 && _jsx("div", { className: "btb-loading", children: t('wb.backup.noKnown') }), rows && rows.map(row => _jsxs("label", { className: `btb-row is-${row.status}`, children: [_jsx("input", { type: "checkbox", checked: chosen.has(row.section), onChange: event => toggle(row.section, event.target.checked), "aria-label": t('wb.backup.applySection', { section: row.label }) }), _jsxs("span", { className: "btb-row-body", children: [_jsxs("span", { className: "btb-row-title", children: [row.label, row.status === 'same' ? _jsx(Badge, { children: t('wb.backup.status.same') }) : row.status === 'new' ? _jsx(Badge, { tone: "accent", children: t('wb.backup.status.new') }) : _jsx(Badge, { tone: "warn", children: t('wb.backup.status.changes') })] }), row.details.map((line, index) => _jsx("span", { className: "btb-row-line", children: line }, index))] })] }, row.section)), rows && rows.length > 0 && _jsxs("div", { className: "btb-actions", children: [_jsx("span", { className: "btb-actions-note", children: t('wb.backup.chosen', { count: chosen.size, total: rows.length }) }), _jsx(Button, { tone: "primary", disabled: busy || chosen.size === 0, onClick: () => void apply(), children: busy ? t('wb.backup.applying') : t('wb.backup.applySelected') })] })] });
145
+ }
146
+ function SyncSection({ notify, onReview }) {
147
+ const t = useT();
148
+ const sync = useSync();
149
+ const status = sync.status;
150
+ const [passphrase, setPassphrase] = useState('');
151
+ const [confirm, setConfirm] = useState('');
152
+ const [remember, setRemember] = useState(true);
153
+ const [busy, setBusy] = useState(null);
154
+ const [deviceName, setDeviceName] = useState('');
155
+ useEffect(() => { if (!status)
156
+ void refreshSync(); }, []);
157
+ useEffect(() => { if (status)
158
+ setDeviceName(status.deviceName); }, [status?.deviceName]);
159
+ async function act(label, action, done) {
160
+ setBusy(label);
161
+ try {
162
+ const result = await action();
163
+ if (result && typeof result === 'object' && 'device' in result)
164
+ setSyncStatus(result);
165
+ if (done)
166
+ notify(done);
167
+ }
168
+ catch (error) {
169
+ notify(getError(error), true);
170
+ }
171
+ finally {
172
+ setBusy(null);
173
+ }
174
+ }
175
+ const hint = t('wb.sync.hint');
176
+ const title = t('wb.sync.title');
177
+ if (!status)
178
+ return _jsx(Section, { title: title, hint: hint, children: _jsx("div", { className: "btb-loading", children: t('wb.common.loading') }) });
179
+ if (!status.folder) {
180
+ return _jsx(Section, { title: title, hint: hint, children: _jsx(Row, { label: t('wb.sync.folder'), hint: t('wb.sync.folderHint'), keywords: "sync cloud onedrive icloud dropbox folder encrypted", children: _jsx(Button, { tone: "primary", onClick: () => void act('folder', () => invoke('sync_choose_folder')), children: t('wb.sync.chooseFolder') }) }) });
181
+ }
182
+ const folderRow = _jsx(Row, { label: t('wb.sync.folder'), hint: _jsx("span", { className: "btb-path", title: status.folder, children: status.folder }), keywords: "sync folder change stop", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", onClick: () => void act('folder', () => invoke('sync_choose_folder')), children: t('wb.sync.change') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void act('disable', () => invoke('sync_disable'), t('wb.sync.stopped')), children: t('wb.sync.stop') })] }) });
183
+ if (!status.unlocked) {
184
+ const creating = !status.initialized;
185
+ const mismatch = creating && confirm.length > 0 && confirm !== passphrase;
186
+ const ready = passphrase.length >= 8 && (!creating || confirm === passphrase);
187
+ return _jsxs(Section, { title: title, hint: hint, children: [folderRow, status.error && _jsx(Row, { label: t('wb.sync.problem'), hint: status.error }), _jsx(Row, { label: creating ? t('wb.sync.choosePass') : t('wb.sync.unlockPass'), hint: creating ? t('wb.sync.choosePassHint') : t('wb.sync.unlockPassHint'), keywords: "passphrase password unlock encrypt", wide: true, children: _jsxs("form", { className: "btb-pass", onSubmit: event => { event.preventDefault(); if (ready)
188
+ void act('unlock', () => invoke('sync_unlock', { passphrase, remember }).then(result => { setPassphrase(''); setConfirm(''); return result; }), creating ? t('wb.sync.setUpDone') : t('wb.sync.unlocked')); }, children: [_jsx("input", { className: "bt-input", type: "password", autoComplete: "new-password", placeholder: t('wb.sync.passphrase'), "aria-label": t('wb.sync.passphraseLabel'), value: passphrase, onChange: event => setPassphrase(event.target.value) }), creating && _jsx("input", { className: "bt-input", type: "password", autoComplete: "new-password", placeholder: t('wb.sync.repeat'), "aria-label": t('wb.sync.repeatLabel'), value: confirm, onChange: event => setConfirm(event.target.value) }), _jsxs("label", { className: "btb-check", children: [_jsx("input", { type: "checkbox", checked: remember, onChange: event => setRemember(event.target.checked) }), t('wb.sync.remember')] }), _jsx(Button, { tone: "primary", type: "submit", disabled: !ready || busy === 'unlock', children: busy === 'unlock' ? t('wb.sync.deriving') : creating ? t('wb.sync.setUp') : t('wb.sync.unlock') }), mismatch && _jsx("span", { className: "btb-error", children: t('wb.sync.differ') })] }) })] });
189
+ }
190
+ const others = status.snapshots.filter(snapshot => snapshot.device !== status.device);
191
+ const mine = status.snapshots.filter(snapshot => snapshot.device === status.device);
192
+ return _jsxs(Section, { title: title, hint: hint, action: _jsx(Badge, { tone: "ok", children: t('wb.sync.on') }), children: [folderRow, _jsx(Row, { label: t('wb.sync.thisComputer'), hint: t('wb.sync.thisComputerHint'), keywords: "device name computer", children: _jsx(InputRow, { label: t('wb.sync.computerName'), value: deviceName, onChange: setDeviceName, button: t('wb.sync.rename'), disabled: !deviceName.trim() || deviceName === status.deviceName, onSubmit: () => void act('name', () => invoke('sync_configure', { autoPush: status.autoPush, deviceName })) }) }), _jsx(Row, { label: t('wb.sync.auto'), hint: t('wb.sync.autoHint'), keywords: "auto push automatic", children: _jsx(Toggle, { label: t('wb.sync.auto'), checked: status.autoPush, onChange: next => void act('auto', () => invoke('sync_configure', { autoPush: next, deviceName: status.deviceName })) }) }), _jsx(Row, { label: t('wb.sync.last'), hint: status.lastPushedAt ? t('wb.sync.lastHint', { when: ago(status.lastPushedAt), count: mine.length }) : t('wb.sync.notYet'), keywords: "sync now push", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", disabled: busy === 'push', onClick: () => void act('push', () => pushNow(true), t('wb.sync.written')), children: busy === 'push' ? t('wb.sync.syncing') : t('wb.sync.now') }), _jsx(Button, { size: "sm", tone: "ghost", disabled: busy === 'check', onClick: () => void act('check', async () => { const newer = await checkNewer(); notify(newer ? t('wb.sync.newerFrom', { device: newer.deviceName }) : t('wb.sync.nothingNewer')); }), children: t('wb.sync.check') })] }) }), _jsx(Row, { label: t('wb.sync.others'), hint: others.length ? t('wb.sync.othersHint') : t('wb.sync.othersEmpty'), keywords: "pull snapshots other computer", wide: true, children: others.length > 0 && _jsx("div", { className: "btb-snapshots", children: others.slice(0, 6).map(snapshot => _jsx(SnapshotRow, { snapshot: snapshot, fresh: snapshot.createdAt > status.lastPulled, onReview: () => onReview(snapshot.name) }, snapshot.name)) }) }), _jsx(Row, { label: t('wb.sync.lock'), hint: status.remembered ? t('wb.sync.lockRemembered') : t('wb.sync.lockSession'), keywords: "lock forget key passphrase", children: _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void act('lock', () => invoke('sync_lock'), t('wb.sync.locked')), children: t('wb.sync.lock') }) })] });
193
+ }
194
+ function SnapshotRow({ snapshot, fresh, onReview }) {
195
+ const t = useT();
196
+ return _jsxs("div", { className: `btb-snapshot${fresh ? ' is-fresh' : ''}`, children: [_jsx("span", { className: "btb-snapshot-device", children: snapshot.deviceName }), _jsxs("span", { className: "btb-snapshot-when", children: [ago(snapshot.createdAt), fresh ? ` · ${t('wb.sync.new')}` : ''] }), _jsx(Button, { size: "sm", tone: fresh ? 'primary' : 'plain', onClick: onReview, children: t('wb.sync.review') })] });
197
+ }
198
+ //# sourceMappingURL=BackupPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackupPanel.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/BackupPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["// Settings → Backup & sync: export everything into one `.waybetter` file, import one with a preview\n// and a checkbox per section, and the optional encrypted sync through a folder the owner already\n// syncs (OneDrive, iCloud Drive, Dropbox...). Files, crypto and the key stay native\n// (waybetter-host backup.rs and sync.rs behind the app's `backup_*` and `sync_*` commands); nothing\n// here talks to a server. The sync part shows only with the frame's `sync` feature.\n\nimport { useEffect, useState } from 'react';\nimport { ago, diffSections, pickSections, type SectionRow } from '../frame/backupModel.ts';\nimport { invoke } from '../frame/bridge.ts';\nimport { replaceDecks } from '../frame/deckStore.ts';\nimport { useSync, useT } from '../frame/hooks.ts';\nimport { formatDate } from '../frame/i18n.ts';\nimport { hasFeature } from '../frame/site.ts';\nimport { setProfiles } from '../frame/state.ts';\nimport { checkNewer, clearNewer, pushNow, refreshSync, setSyncStatus, shellSections, type SnapshotInfo, type SyncStatus } from '../frame/syncHost.ts';\nimport { loadWorkspaces } from '../frame/workspaces.ts';\nimport { Badge, Button, InputRow, Row, Section, Toggle } from './controls.tsx';\nimport { panelSite, type Notify } from './site.ts';\nimport './backup.css';\n\ntype Json = Record<string, unknown>;\nconst getError = (error: unknown) => (error instanceof Error ? error.message : String(error)).replace(/^(BACKUP|SYNC|VALIDATION): /, '');\n\n/** Tells the rest of the shell that settings changed under it (import, pull). */\nasync function refreshAfterImport() {\n await Promise.allSettled([\n panelSite().themes?.store.loadThemes(),\n invoke('profiles_get').then(setProfiles),\n hasFeature('workspaces') ? loadWorkspaces() : undefined,\n ]);\n window.dispatchEvent(new CustomEvent('bt-settings-imported'));\n}\n\nexport function BackupPanel({ notify }: { notify: Notify }) {\n const t = useT();\n const [preview, setPreview] = useState<{ title: string; subtitle: string; sections: Json; snapshot?: string } | null>(null);\n const sync = useSync();\n\n // The titlebar chip \"Settings from <computer>\" opens this section and asks to review that snapshot.\n useEffect(() => {\n const onReview = (event: Event) => { const name = (event as CustomEvent<string | undefined>).detail; if (name) void review(name); };\n window.addEventListener('bt-sync-review', onReview);\n return () => window.removeEventListener('bt-sync-review', onReview);\n }, []);\n\n async function review(name: string) {\n try {\n const sections = await invoke<Json>('sync_open', { name });\n const info = syncStateSnapshot(name);\n setPreview({ title: t('wb.backup.fromDevice', { device: info?.deviceName ?? t('wb.backup.anotherComputer') }), subtitle: info ? t('wb.backup.syncedAgo', { when: ago(info.createdAt) }) : t('wb.backup.encryptedSnapshot'), sections, snapshot: name });\n } catch (error) { notify(getError(error), true); }\n }\n const syncStateSnapshot = (name: string) => sync.status?.snapshots.find(item => item.name === name) ?? (sync.newer?.name === name ? sync.newer : null);\n\n if (preview) {\n return <ImportPreview {...preview} notify={notify}\n onCancel={async () => {\n if (preview.snapshot) { await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => {}); clearNewer(); }\n setPreview(null);\n }}\n onDone={async () => {\n if (preview.snapshot) { await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => {}); clearNewer(); void refreshSync(); }\n setPreview(null);\n }}/>;\n }\n return <>\n <ExportSection notify={notify} onOpen={(title, subtitle, sections) => setPreview({ title, subtitle, sections })}/>\n {hasFeature('sync') && <SyncSection notify={notify} onReview={review}/>}\n </>;\n}\n\nfunction ExportSection({ notify, onOpen }: { notify: Notify; onOpen(title: string, subtitle: string, sections: Json): void }) {\n const t = useT();\n const [drafts, setDrafts] = useState(false);\n const [busy, setBusy] = useState(false);\n async function exportFile() {\n setBusy(true);\n try {\n const path = await invoke<string | null>('backup_export_file', { includeDrafts: drafts, extra: shellSections() });\n if (path) notify(t('wb.backup.saved', { file: path.split(/[\\\\/]/).pop() ?? path }));\n } catch (error) { notify(getError(error), true); } finally { setBusy(false); }\n }\n async function importFile() {\n try {\n const opened = await invoke<{ file: string; createdAt?: string; appVersion?: string; sections: Json } | null>('backup_open_file');\n if (!opened) return;\n const when = opened.createdAt ? formatDate(opened.createdAt, { dateStyle: 'medium', timeStyle: 'short' }) : t('wb.backup.unknownDate');\n onOpen(t('wb.backup.importFile', { file: opened.file }), `${t('wb.backup.exportedAt', { when })}${opened.appVersion ? ` · ${panelSite().brand.name} ${opened.appVersion}` : ''}`, opened.sections);\n } catch (error) { notify(getError(error), true); }\n }\n return <Section title={t('wb.backup.title')} hint={t('wb.backup.hint')}>\n <Row label={t('wb.backup.export')} hint={t('wb.backup.exportHint')} keywords=\"backup export save file move computer\" wide>\n <div className=\"bt-inline\">\n <Button tone=\"primary\" disabled={busy} onClick={() => void exportFile()}>{busy ? t('wb.backup.exporting') : t('wb.backup.exportButton')}</Button>\n <label className=\"btb-check\"><input type=\"checkbox\" checked={drafts} onChange={event => setDrafts(event.target.checked)}/>{t('wb.backup.includeDrafts')}</label>\n </div>\n </Row>\n <Row label={t('wb.backup.import')} hint={t('wb.backup.importHint')} keywords=\"restore import load file\" >\n <Button onClick={() => void importFile()}>{t('wb.backup.importButton')}</Button>\n </Row>\n </Section>;\n}\n\nfunction ImportPreview({ title, subtitle, sections, notify, onCancel, onDone }: { title: string; subtitle: string; sections: Json; notify: Notify; onCancel(): void; onDone(): void }) {\n const t = useT();\n const [rows, setRows] = useState<SectionRow[] | null>(null);\n const [chosen, setChosen] = useState<Set<string>>(new Set());\n const [busy, setBusy] = useState(false);\n useEffect(() => {\n let alive = true;\n invoke<Json>('backup_collect', { includeDrafts: false })\n .catch(() => ({}))\n .then(current => {\n if (!alive) return;\n const next = diffSections({ ...current, ...shellSections() }, sections);\n setRows(next);\n setChosen(new Set(next.filter(row => row.checked).map(row => row.section)));\n });\n return () => { alive = false; };\n }, [sections]);\n\n async function apply() {\n const { native, local } = pickSections(sections, chosen);\n setBusy(true);\n try {\n const result = Object.keys(native).length ? await invoke<{ applied: string[]; notes: string[] }>('backup_apply', { sections: native }) : { applied: [], notes: [] };\n const decks = local.decks as { decks?: unknown; settings?: unknown } | undefined;\n if (decks) replaceDecks(decks.decks, decks.settings);\n await refreshAfterImport();\n const count = result.applied.length + (decks ? 1 : 0);\n notify([t('wb.backup.applied', { count }), ...result.notes].join(' '));\n onDone();\n } catch (error) { notify(getError(error), true); } finally { setBusy(false); }\n }\n\n const toggle = (section: string, on: boolean) => setChosen(previous => { const next = new Set(previous); if (on) next.add(section); else next.delete(section); return next; });\n return <Section title={title} hint={subtitle} action={<Button tone=\"ghost\" size=\"sm\" onClick={onCancel}>{t('wb.common.cancel')}</Button>}>\n {!rows && <div className=\"btb-loading\">{t('wb.backup.comparing')}</div>}\n {rows && rows.length === 0 && <div className=\"btb-loading\">{t('wb.backup.noKnown')}</div>}\n {rows && rows.map(row => <label key={row.section} className={`btb-row is-${row.status}`}>\n <input type=\"checkbox\" checked={chosen.has(row.section)} onChange={event => toggle(row.section, event.target.checked)} aria-label={t('wb.backup.applySection', { section: row.label })}/>\n <span className=\"btb-row-body\">\n <span className=\"btb-row-title\">{row.label}\n {row.status === 'same' ? <Badge>{t('wb.backup.status.same')}</Badge> : row.status === 'new' ? <Badge tone=\"accent\">{t('wb.backup.status.new')}</Badge> : <Badge tone=\"warn\">{t('wb.backup.status.changes')}</Badge>}\n </span>\n {row.details.map((line, index) => <span key={index} className=\"btb-row-line\">{line}</span>)}\n </span>\n </label>)}\n {rows && rows.length > 0 && <div className=\"btb-actions\">\n <span className=\"btb-actions-note\">{t('wb.backup.chosen', { count: chosen.size, total: rows.length })}</span>\n <Button tone=\"primary\" disabled={busy || chosen.size === 0} onClick={() => void apply()}>{busy ? t('wb.backup.applying') : t('wb.backup.applySelected')}</Button>\n </div>}\n </Section>;\n}\n\nfunction SyncSection({ notify, onReview }: { notify: Notify; onReview(name: string): void }) {\n const t = useT();\n const sync = useSync();\n const status = sync.status;\n const [passphrase, setPassphrase] = useState('');\n const [confirm, setConfirm] = useState('');\n const [remember, setRemember] = useState(true);\n const [busy, setBusy] = useState<string | null>(null);\n const [deviceName, setDeviceName] = useState('');\n useEffect(() => { if (!status) void refreshSync(); }, []);\n useEffect(() => { if (status) setDeviceName(status.deviceName); }, [status?.deviceName]);\n\n async function act(label: string, action: () => Promise<SyncStatus | unknown>, done?: string) {\n setBusy(label);\n try {\n const result = await action();\n if (result && typeof result === 'object' && 'device' in (result as object)) setSyncStatus(result as SyncStatus);\n if (done) notify(done);\n } catch (error) { notify(getError(error), true); } finally { setBusy(null); }\n }\n\n const hint = t('wb.sync.hint');\n const title = t('wb.sync.title');\n if (!status) return <Section title={title} hint={hint}><div className=\"btb-loading\">{t('wb.common.loading')}</div></Section>;\n if (!status.folder) {\n return <Section title={title} hint={hint}>\n <Row label={t('wb.sync.folder')} hint={t('wb.sync.folderHint')} keywords=\"sync cloud onedrive icloud dropbox folder encrypted\">\n <Button tone=\"primary\" onClick={() => void act('folder', () => invoke('sync_choose_folder'))}>{t('wb.sync.chooseFolder')}</Button>\n </Row>\n </Section>;\n }\n const folderRow = <Row label={t('wb.sync.folder')} hint={<span className=\"btb-path\" title={status.folder}>{status.folder}</span>} keywords=\"sync folder change stop\">\n <div className=\"bt-inline\">\n <Button size=\"sm\" onClick={() => void act('folder', () => invoke('sync_choose_folder'))}>{t('wb.sync.change')}</Button>\n <Button size=\"sm\" tone=\"ghost\" onClick={() => void act('disable', () => invoke('sync_disable'), t('wb.sync.stopped'))}>{t('wb.sync.stop')}</Button>\n </div>\n </Row>;\n\n if (!status.unlocked) {\n const creating = !status.initialized;\n const mismatch = creating && confirm.length > 0 && confirm !== passphrase;\n const ready = passphrase.length >= 8 && (!creating || confirm === passphrase);\n return <Section title={title} hint={hint}>\n {folderRow}\n {status.error && <Row label={t('wb.sync.problem')} hint={status.error}/>}\n <Row label={creating ? t('wb.sync.choosePass') : t('wb.sync.unlockPass')}\n hint={creating ? t('wb.sync.choosePassHint') : t('wb.sync.unlockPassHint')}\n keywords=\"passphrase password unlock encrypt\" wide>\n <form className=\"btb-pass\" onSubmit={event => { event.preventDefault(); if (ready) void act('unlock', () => invoke('sync_unlock', { passphrase, remember }).then(result => { setPassphrase(''); setConfirm(''); return result; }), creating ? t('wb.sync.setUpDone') : t('wb.sync.unlocked')); }}>\n <input className=\"bt-input\" type=\"password\" autoComplete=\"new-password\" placeholder={t('wb.sync.passphrase')} aria-label={t('wb.sync.passphraseLabel')} value={passphrase} onChange={event => setPassphrase(event.target.value)}/>\n {creating && <input className=\"bt-input\" type=\"password\" autoComplete=\"new-password\" placeholder={t('wb.sync.repeat')} aria-label={t('wb.sync.repeatLabel')} value={confirm} onChange={event => setConfirm(event.target.value)}/>}\n <label className=\"btb-check\"><input type=\"checkbox\" checked={remember} onChange={event => setRemember(event.target.checked)}/>{t('wb.sync.remember')}</label>\n <Button tone=\"primary\" type=\"submit\" disabled={!ready || busy === 'unlock'}>{busy === 'unlock' ? t('wb.sync.deriving') : creating ? t('wb.sync.setUp') : t('wb.sync.unlock')}</Button>\n {mismatch && <span className=\"btb-error\">{t('wb.sync.differ')}</span>}\n </form>\n </Row>\n </Section>;\n }\n\n const others = status.snapshots.filter(snapshot => snapshot.device !== status.device);\n const mine = status.snapshots.filter(snapshot => snapshot.device === status.device);\n return <Section title={title} hint={hint} action={<Badge tone=\"ok\">{t('wb.sync.on')}</Badge>}>\n {folderRow}\n <Row label={t('wb.sync.thisComputer')} hint={t('wb.sync.thisComputerHint')} keywords=\"device name computer\">\n <InputRow label={t('wb.sync.computerName')} value={deviceName} onChange={setDeviceName} button={t('wb.sync.rename')} disabled={!deviceName.trim() || deviceName === status.deviceName}\n onSubmit={() => void act('name', () => invoke('sync_configure', { autoPush: status.autoPush, deviceName }))}/>\n </Row>\n <Row label={t('wb.sync.auto')} hint={t('wb.sync.autoHint')} keywords=\"auto push automatic\">\n <Toggle label={t('wb.sync.auto')} checked={status.autoPush} onChange={next => void act('auto', () => invoke('sync_configure', { autoPush: next, deviceName: status.deviceName }))}/>\n </Row>\n <Row label={t('wb.sync.last')} hint={status.lastPushedAt ? t('wb.sync.lastHint', { when: ago(status.lastPushedAt), count: mine.length }) : t('wb.sync.notYet')} keywords=\"sync now push\">\n <div className=\"bt-inline\">\n <Button size=\"sm\" disabled={busy === 'push'} onClick={() => void act('push', () => pushNow(true), t('wb.sync.written'))}>{busy === 'push' ? t('wb.sync.syncing') : t('wb.sync.now')}</Button>\n <Button size=\"sm\" tone=\"ghost\" disabled={busy === 'check'} onClick={() => void act('check', async () => { const newer = await checkNewer(); notify(newer ? t('wb.sync.newerFrom', { device: newer.deviceName }) : t('wb.sync.nothingNewer')); })}>{t('wb.sync.check')}</Button>\n </div>\n </Row>\n <Row label={t('wb.sync.others')} hint={others.length ? t('wb.sync.othersHint') : t('wb.sync.othersEmpty')} keywords=\"pull snapshots other computer\" wide>\n {others.length > 0 && <div className=\"btb-snapshots\">\n {others.slice(0, 6).map(snapshot => <SnapshotRow key={snapshot.name} snapshot={snapshot} fresh={snapshot.createdAt > status.lastPulled} onReview={() => onReview(snapshot.name)}/>)}\n </div>}\n </Row>\n <Row label={t('wb.sync.lock')} hint={status.remembered ? t('wb.sync.lockRemembered') : t('wb.sync.lockSession')} keywords=\"lock forget key passphrase\">\n <Button size=\"sm\" tone=\"ghost\" onClick={() => void act('lock', () => invoke('sync_lock'), t('wb.sync.locked'))}>{t('wb.sync.lock')}</Button>\n </Row>\n </Section>;\n}\n\nfunction SnapshotRow({ snapshot, fresh, onReview }: { snapshot: SnapshotInfo; fresh: boolean; onReview(): void }) {\n const t = useT();\n return <div className={`btb-snapshot${fresh ? ' is-fresh' : ''}`}>\n <span className=\"btb-snapshot-device\">{snapshot.deviceName}</span>\n <span className=\"btb-snapshot-when\">{ago(snapshot.createdAt)}{fresh ? ` · ${t('wb.sync.new')}` : ''}</span>\n <Button size=\"sm\" tone={fresh ? 'primary' : 'plain'} onClick={onReview}>{t('wb.sync.review')}</Button>\n </div>;\n}\n\n"]}
@@ -0,0 +1,4 @@
1
+ import { type Notify } from './site.ts';
2
+ export declare function DeveloperPanel({ notify }: {
3
+ notify: Notify;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Settings → Developer: the live-reload developer mode (off by default). Native code watches the
3
+ // plugins folder, custom.css and one theme file (waybetter-host devmode.rs); a saved change reloads
4
+ // in every site tab at once: theme, then custom CSS, then plugins (the old version stopped before
5
+ // the new one starts). Syntax errors are caught here before anything reloads; errors show with
6
+ // file, line and column (this list, the titlebar chip and a toast in the site's tabs).
7
+ import { useEffect, useState } from 'react';
8
+ import { invoke } from "../frame/bridge.js";
9
+ import { setDevEnabled, setDevErrors } from "../frame/devHost.js";
10
+ import { useDev, useT } from "../frame/hooks.js";
11
+ import { Badge, Button, Row, Section, Toggle } from "./controls.js";
12
+ import { panelSite } from "./site.js";
13
+ const getError = (error) => (error instanceof Error ? error.message : String(error)).replace(/^(DEV|VALIDATION): /, '');
14
+ const where = (error) => `${error.file}${error.line ? `:${error.line}${error.column ? `:${error.column}` : ''}` : ''}`;
15
+ export function DeveloperPanel({ notify }) {
16
+ const t = useT();
17
+ const dev = useDev();
18
+ const [status, setStatus] = useState(null);
19
+ const [events, setEvents] = useState([]);
20
+ const apply = (next) => { setStatus(next); setDevEnabled(next.enabled); setDevErrors(next.errors); };
21
+ useEffect(() => { invoke('dev_get').then(apply).catch(() => setStatus(null)); }, []);
22
+ useEffect(() => {
23
+ const onEvent = (event) => {
24
+ const detail = event.detail;
25
+ if (detail.kind !== 'reloaded')
26
+ return;
27
+ setEvents(previous => [{ text: t('wb.dev.reloaded', { file: detail.file ?? detail.target ?? '' }), at: Date.now() }, ...previous].slice(0, 6));
28
+ };
29
+ window.addEventListener('bt-dev-event', onEvent);
30
+ return () => window.removeEventListener('bt-dev-event', onEvent);
31
+ }, []);
32
+ async function run(action, message) {
33
+ try {
34
+ apply(await action());
35
+ if (message)
36
+ notify(message);
37
+ }
38
+ catch (error) {
39
+ notify(getError(error), true);
40
+ }
41
+ }
42
+ if (!status)
43
+ return _jsx(Section, { title: t('wb.dev.title'), hint: t('wb.dev.desktopOnly'), children: _jsx("div", { className: "btb-loading", children: t('wb.dev.notAvailable') }) });
44
+ const errors = dev.errors;
45
+ return _jsxs(_Fragment, { children: [_jsxs(Section, { title: t('wb.dev.title'), hint: t('wb.dev.hint'), action: status.enabled ? _jsx(Badge, { tone: "ok", children: t('wb.dev.watching') }) : undefined, children: [_jsx(Row, { label: t('wb.dev.mode'), hint: t('wb.dev.modeHint'), keywords: "developer dev mode live reload hot reload watch", children: _jsx(Toggle, { label: t('wb.dev.mode'), checked: status.enabled, onChange: next => void run(() => invoke('dev_set', { enabled: next }), next ? t('wb.dev.on') : t('wb.dev.off')) }) }), _jsx(Row, { label: t('wb.dev.pluginsFolder'), hint: _jsx("span", { className: "btb-path", title: status.pluginsFolder, children: status.pluginsFolder }), keywords: "plugins folder open", children: _jsx(Button, { size: "sm", onClick: () => void invoke('plugins_open_folder').catch(error => notify(getError(error), true)), children: t('wb.plugins.openFolder') }) }), panelSite().themes && _jsx(Row, { label: t('wb.dev.themeFile'), hint: status.themeFile
46
+ ? _jsx("span", { className: "btb-path", title: status.themeFile, children: status.themeFile })
47
+ : t('wb.dev.themeFileHint'), keywords: "theme json file watch preview", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", onClick: () => void run(() => invoke('dev_pick_theme')), children: status.themeFile ? t('wb.sync.change') : t('wb.dev.chooseTheme') }), status.themeFile && _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void run(() => invoke('dev_clear_theme'), t('wb.dev.stoppedTheme')), children: t('wb.dev.stopWatching') })] }) })] }), _jsx(Section, { title: t('wb.dev.errors'), hint: t('wb.dev.errorsHint'), action: errors.length ? _jsx(Badge, { tone: "warn", children: errors.length }) : undefined, children: errors.length === 0
48
+ ? _jsx(Row, { label: t('wb.dev.noErrors'), hint: events.length ? events.map(event => event.text).slice(0, 3).join(' · ') : status.enabled ? t('wb.dev.saveToReload') : t('wb.dev.turnOn') })
49
+ : errors.map((error, index) => _jsxs("div", { className: "btd-error", children: [_jsx("code", { className: "btd-where", children: where(error) }), _jsx("span", { className: "btd-message", children: error.message })] }, `${error.file}-${index}`)) })] });
50
+ }
51
+ //# sourceMappingURL=DeveloperPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeveloperPanel.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/DeveloperPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["// Settings → Developer: the live-reload developer mode (off by default). Native code watches the\n// plugins folder, custom.css and one theme file (waybetter-host devmode.rs); a saved change reloads\n// in every site tab at once: theme, then custom CSS, then plugins (the old version stopped before\n// the new one starts). Syntax errors are caught here before anything reloads; errors show with\n// file, line and column (this list, the titlebar chip and a toast in the site's tabs).\n\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { setDevEnabled, setDevErrors, type DevErrorInfo } from '../frame/devHost.ts';\nimport { useDev, useT } from '../frame/hooks.ts';\nimport { Badge, Button, Row, Section, Toggle } from './controls.tsx';\nimport { panelSite, type Notify } from './site.ts';\ntype DevStatus = { enabled: boolean; themeFile: string | null; pluginsFolder: string; errors: DevErrorInfo[] };\nconst getError = (error: unknown) => (error instanceof Error ? error.message : String(error)).replace(/^(DEV|VALIDATION): /, '');\nconst where = (error: DevErrorInfo) => `${error.file}${error.line ? `:${error.line}${error.column ? `:${error.column}` : ''}` : ''}`;\n\nexport function DeveloperPanel({ notify }: { notify: Notify }) {\n const t = useT();\n const dev = useDev();\n const [status, setStatus] = useState<DevStatus | null>(null);\n const [events, setEvents] = useState<Array<{ text: string; at: number }>>([]);\n\n const apply = (next: DevStatus) => { setStatus(next); setDevEnabled(next.enabled); setDevErrors(next.errors); };\n useEffect(() => { invoke<DevStatus>('dev_get').then(apply).catch(() => setStatus(null)); }, []);\n useEffect(() => {\n const onEvent = (event: Event) => {\n const detail = (event as CustomEvent<{ kind: string; target?: string; file?: string | null }>).detail;\n if (detail.kind !== 'reloaded') return;\n setEvents(previous => [{ text: t('wb.dev.reloaded', { file: detail.file ?? detail.target ?? '' }), at: Date.now() }, ...previous].slice(0, 6));\n };\n window.addEventListener('bt-dev-event', onEvent);\n return () => window.removeEventListener('bt-dev-event', onEvent);\n }, []);\n\n async function run(action: () => Promise<DevStatus>, message?: string) {\n try { apply(await action()); if (message) notify(message); } catch (error) { notify(getError(error), true); }\n }\n\n if (!status) return <Section title={t('wb.dev.title')} hint={t('wb.dev.desktopOnly')}><div className=\"btb-loading\">{t('wb.dev.notAvailable')}</div></Section>;\n const errors = dev.errors;\n return <>\n <Section title={t('wb.dev.title')} hint={t('wb.dev.hint')}\n action={status.enabled ? <Badge tone=\"ok\">{t('wb.dev.watching')}</Badge> : undefined}>\n <Row label={t('wb.dev.mode')} hint={t('wb.dev.modeHint')} keywords=\"developer dev mode live reload hot reload watch\">\n <Toggle label={t('wb.dev.mode')} checked={status.enabled}\n onChange={next => void run(() => invoke<DevStatus>('dev_set', { enabled: next }), next ? t('wb.dev.on') : t('wb.dev.off'))}/>\n </Row>\n <Row label={t('wb.dev.pluginsFolder')} hint={<span className=\"btb-path\" title={status.pluginsFolder}>{status.pluginsFolder}</span>} keywords=\"plugins folder open\">\n <Button size=\"sm\" onClick={() => void invoke('plugins_open_folder').catch(error => notify(getError(error), true))}>{t('wb.plugins.openFolder')}</Button>\n </Row>\n {panelSite().themes && <Row label={t('wb.dev.themeFile')} hint={status.themeFile\n ? <span className=\"btb-path\" title={status.themeFile}>{status.themeFile}</span>\n : t('wb.dev.themeFileHint')} keywords=\"theme json file watch preview\">\n <div className=\"bt-inline\">\n <Button size=\"sm\" onClick={() => void run(() => invoke<DevStatus>('dev_pick_theme'))}>{status.themeFile ? t('wb.sync.change') : t('wb.dev.chooseTheme')}</Button>\n {status.themeFile && <Button size=\"sm\" tone=\"ghost\" onClick={() => void run(() => invoke<DevStatus>('dev_clear_theme'), t('wb.dev.stoppedTheme'))}>{t('wb.dev.stopWatching')}</Button>}\n </div>\n </Row>}\n </Section>\n <Section title={t('wb.dev.errors')} hint={t('wb.dev.errorsHint')}\n action={errors.length ? <Badge tone=\"warn\">{errors.length}</Badge> : undefined}>\n {errors.length === 0\n ? <Row label={t('wb.dev.noErrors')} hint={events.length ? events.map(event => event.text).slice(0, 3).join(' · ') : status.enabled ? t('wb.dev.saveToReload') : t('wb.dev.turnOn')}/>\n : errors.map((error, index) => <div key={`${error.file}-${index}`} className=\"btd-error\">\n <code className=\"btd-where\">{where(error)}</code>\n <span className=\"btd-message\">{error.message}</span>\n </div>)}\n </Section>\n </>;\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { FeatureGroup, Notify } from './site.ts';
2
+ /**
3
+ * The saved flags (normalized by the app) and a setter that shows a change at once, saves it and
4
+ * reverts when native code refuses it. Null until loaded.
5
+ */
6
+ export declare function useFeatures<Config extends Record<string, boolean>>(normalize: (value: unknown) => Config, notify: Notify): [Config | null, (patch: Partial<Config>) => Promise<void>];
7
+ /** One section per group, one toggle per flag; flags that are on by default carry a badge. */
8
+ export declare function FeatureGroups<Config extends Record<string, boolean>>({ groups, defaults, features, choose }: {
9
+ groups: readonly FeatureGroup[];
10
+ defaults: Config;
11
+ features: Config;
12
+ choose(patch: Partial<Config>): void | Promise<void>;
13
+ }): import("react").JSX.Element;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Page tweaks as on/off rows: the app's feature flags (booleans the page runtime applies live in
3
+ // every site tab), stored natively (waybetter-host `features_get/set`). The mechanism is the
4
+ // framework's; which flags exist, their groups and their words are the app's: the catalog has
5
+ // `features.group.<group>`, `features.<flag>.label` and `features.<flag>.description`.
6
+ //
7
+ // const [features, choose] = useFeatures(normalizeFeatures, notify);
8
+ // return features && <FeatureGroups groups={FEATURE_GROUPS} defaults={FEATURE_DEFAULTS} features={features} choose={choose}/>;
9
+ import { useEffect, useState } from 'react';
10
+ import { invoke } from "../frame/bridge.js";
11
+ import { useT } from "../frame/hooks.js";
12
+ import { tx } from "../frame/i18n.js";
13
+ import { Badge, Row, Section, Toggle } from "./controls.js";
14
+ const getError = (error) => error instanceof Error ? error.message : String(error);
15
+ /**
16
+ * The saved flags (normalized by the app) and a setter that shows a change at once, saves it and
17
+ * reverts when native code refuses it. Null until loaded.
18
+ */
19
+ export function useFeatures(normalize, notify) {
20
+ const [features, setFeatures] = useState(null);
21
+ useEffect(() => { invoke('features_get').then(value => setFeatures(normalize(value))).catch(err => notify(getError(err), true)); }, []);
22
+ async function choose(patch) {
23
+ if (!features)
24
+ return;
25
+ const next = { ...features, ...patch };
26
+ setFeatures(next);
27
+ try {
28
+ await invoke('features_set', { features: next });
29
+ }
30
+ catch (err) {
31
+ setFeatures(features);
32
+ notify(getError(err), true);
33
+ }
34
+ }
35
+ return [features, choose];
36
+ }
37
+ /** One section per group, one toggle per flag; flags that are on by default carry a badge. */
38
+ export function FeatureGroups({ groups, defaults, features, choose }) {
39
+ const t = useT();
40
+ return _jsx(_Fragment, { children: groups.map(group => _jsx(Section, { title: tx(`features.group.${group.id}`), children: group.features.map(feature => _jsx(Row, { label: tx(`features.${feature}.label`), hint: tx(`features.${feature}.description`), keywords: feature, badge: defaults[feature] ? _jsx(Badge, { children: t('wb.features.default') }) : undefined, children: _jsx(Toggle, { label: tx(`features.${feature}.label`), checked: !!features[feature], onChange: next => void choose({ [feature]: next }) }) }, feature)) }, group.id)) });
41
+ }
42
+ //# sourceMappingURL=FeatureToggles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureToggles.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/FeatureToggles.tsx"],"names":[],"mappings":"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","sourcesContent":["// Page tweaks as on/off rows: the app's feature flags (booleans the page runtime applies live in\n// every site tab), stored natively (waybetter-host `features_get/set`). The mechanism is the\n// framework's; which flags exist, their groups and their words are the app's: the catalog has\n// `features.group.<group>`, `features.<flag>.label` and `features.<flag>.description`.\n//\n// const [features, choose] = useFeatures(normalizeFeatures, notify);\n// return features && <FeatureGroups groups={FEATURE_GROUPS} defaults={FEATURE_DEFAULTS} features={features} choose={choose}/>;\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { tx } from '../frame/i18n.ts';\nimport { Badge, Row, Section, Toggle } from './controls.tsx';\nimport type { FeatureGroup, Notify } from './site.ts';\n\nconst getError = (error: unknown) => error instanceof Error ? error.message : String(error);\n\n/**\n * The saved flags (normalized by the app) and a setter that shows a change at once, saves it and\n * reverts when native code refuses it. Null until loaded.\n */\nexport function useFeatures<Config extends Record<string, boolean>>(normalize: (value: unknown) => Config, notify: Notify): [Config | null, (patch: Partial<Config>) => Promise<void>] {\n const [features, setFeatures] = useState<Config | null>(null);\n useEffect(() => { invoke<unknown>('features_get').then(value => setFeatures(normalize(value))).catch(err => notify(getError(err), true)); }, []);\n async function choose(patch: Partial<Config>) {\n if (!features) return;\n const next = { ...features, ...patch };\n setFeatures(next);\n try { await invoke('features_set', { features: next }); }\n catch (err) { setFeatures(features); notify(getError(err), true); }\n }\n return [features, choose];\n}\n\n/** One section per group, one toggle per flag; flags that are on by default carry a badge. */\nexport function FeatureGroups<Config extends Record<string, boolean>>({ groups, defaults, features, choose }: {\n groups: readonly FeatureGroup[];\n defaults: Config;\n features: Config;\n choose(patch: Partial<Config>): void | Promise<void>;\n}) {\n const t = useT();\n return <>\n {groups.map(group => <Section key={group.id} title={tx(`features.group.${group.id}`)}>\n {group.features.map(feature => <Row key={feature} label={tx(`features.${feature}.label`)} hint={tx(`features.${feature}.description`)} keywords={feature} badge={defaults[feature] ? <Badge>{t('wb.features.default')}</Badge> : undefined}>\n <Toggle label={tx(`features.${feature}.label`)} checked={!!features[feature]} onChange={next => void choose({ [feature]: next } as Partial<Config>)}/>\n </Row>)}\n </Section>)}\n </>;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export declare function Home({ go }: {
2
+ go(section: string): void;
3
+ }): import("react").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // The panel's home page: the hero (logo, title, version and license chips, two actions), highlight
3
+ // cards that open sections and the About block. The layout is the framework's; the words are the
4
+ // app's (`PanelSite.home`).
5
+ import { useEffect, useState } from 'react';
6
+ import { invoke } from "../frame/bridge.js";
7
+ import { useT } from "../frame/hooks.js";
8
+ import { NAV_ICONS, navEntries } from "./nav.js";
9
+ import { NavIcon } from "./NavIcon.js";
10
+ import { panelSite } from "./site.js";
11
+ export function Home({ go }) {
12
+ useT();
13
+ const panel = panelSite();
14
+ const { home, brand } = panel;
15
+ const [version, setVersion] = useState('');
16
+ useEffect(() => { panel.version?.().then(setVersion).catch(() => { }); }, []);
17
+ const entries = navEntries(panel);
18
+ const icon = (section) => entries.find(entry => entry.id === section)?.icon ?? NAV_ICONS[section] ?? NAV_ICONS.home;
19
+ const [before, emphasis, after] = home.title();
20
+ const foot = home.about?.foot;
21
+ return _jsxs("div", { className: "btp-home", children: [_jsxs("section", { className: "btp-hero", children: [_jsx("div", { className: "btp-hero-glow", "aria-hidden": "true" }), _jsx("div", { className: "btp-hero-mark", children: _jsx("img", { src: brand.logo, alt: "", width: 64, height: 64 }) }), _jsxs("p", { className: "btp-hero-kicker", children: [_jsx("span", { className: "btp-hero-name", children: home.kicker.name }), home.kicker.rest] }), _jsxs("h1", { className: "btp-hero-title", children: [before, _jsx("em", { children: emphasis }), after] }), _jsx("p", { className: "btp-hero-lede", children: home.lede() }), _jsxs("div", { className: "btp-hero-chips", children: [version && _jsxs("span", { className: "btp-chip", children: ["v", version] }), (home.chips?.() ?? []).map(chip => _jsx("span", { className: "btp-chip", children: chip }, chip))] }), home.actions && home.actions.length > 0 && _jsx("div", { className: "btp-hero-actions", children: home.actions.map((action, index) => _jsx("button", { className: `btp-btn${index === 0 ? ' is-primary' : ''}`, onClick: () => go(action.section), children: action.label() }, action.section)) })] }), home.highlights && home.highlights.length > 0 && _jsx("div", { className: "btp-highlights", children: home.highlights.map(item => _jsxs("button", { className: "btp-highlight", onClick: () => go(item.section), children: [_jsx(NavIcon, { d: icon(item.section) }), _jsx("strong", { children: item.title() }), _jsx("span", { children: item.text() })] }, item.section)) }), home.about && _jsxs("section", { className: "btp-about", children: [_jsxs("div", { className: "btp-group-head", children: [_jsx("h2", { children: home.about.title() }), _jsx("p", { children: home.about.text() })] }), home.about.layers && _jsx("ol", { className: "btp-layers", children: home.about.layers.map((layer, index) => _jsxs("li", { children: [_jsx("span", { className: "btp-layer-n", children: String(index + 1).padStart(2, '0') }), _jsxs("div", { children: [_jsx("strong", { children: layer.name() }), _jsx("span", { children: layer.text() })] })] }, index)) }), foot && _jsxs("p", { className: "btp-about-foot", children: [foot.text(), " ", _jsx("b", { children: foot.by }), foot.link && _jsxs(_Fragment, { children: [" \u00B7 ", _jsx("button", { className: "btp-link", onClick: () => { invoke('open_external_url', { url: foot.link.url }).catch(() => { }); }, children: foot.link.label })] })] })] })] });
22
+ }
23
+ //# sourceMappingURL=Home.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Home.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/Home.tsx"],"names":[],"mappings":"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","sourcesContent":["// The panel's home page: the hero (logo, title, version and license chips, two actions), highlight\n// cards that open sections and the About block. The layout is the framework's; the words are the\n// app's (`PanelSite.home`).\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { NAV_ICONS, navEntries } from './nav.ts';\nimport { NavIcon } from './NavIcon.tsx';\nimport { panelSite, type BuiltinSection } from './site.ts';\n\nexport function Home({ go }: { go(section: string): void }) {\n useT();\n const panel = panelSite();\n const { home, brand } = panel;\n const [version, setVersion] = useState('');\n useEffect(() => { panel.version?.().then(setVersion).catch(() => {}); }, []);\n const entries = navEntries(panel);\n const icon = (section: string) => entries.find(entry => entry.id === section)?.icon ?? NAV_ICONS[section as BuiltinSection] ?? NAV_ICONS.home;\n const [before, emphasis, after] = home.title();\n const foot = home.about?.foot;\n return <div className=\"btp-home\">\n <section className=\"btp-hero\">\n <div className=\"btp-hero-glow\" aria-hidden=\"true\"/>\n <div className=\"btp-hero-mark\"><img src={brand.logo} alt=\"\" width={64} height={64}/></div>\n <p className=\"btp-hero-kicker\"><span className=\"btp-hero-name\">{home.kicker.name}</span>{home.kicker.rest}</p>\n <h1 className=\"btp-hero-title\">{before}<em>{emphasis}</em>{after}</h1>\n <p className=\"btp-hero-lede\">{home.lede()}</p>\n <div className=\"btp-hero-chips\">\n {version && <span className=\"btp-chip\">v{version}</span>}\n {(home.chips?.() ?? []).map(chip => <span key={chip} className=\"btp-chip\">{chip}</span>)}\n </div>\n {home.actions && home.actions.length > 0 && <div className=\"btp-hero-actions\">\n {home.actions.map((action, index) => <button key={action.section} className={`btp-btn${index === 0 ? ' is-primary' : ''}`} onClick={() => go(action.section)}>{action.label()}</button>)}\n </div>}\n </section>\n {home.highlights && home.highlights.length > 0 && <div className=\"btp-highlights\">\n {home.highlights.map(item => <button key={item.section} className=\"btp-highlight\" onClick={() => go(item.section)}>\n <NavIcon d={icon(item.section)}/><strong>{item.title()}</strong><span>{item.text()}</span>\n </button>)}\n </div>}\n {home.about && <section className=\"btp-about\">\n <div className=\"btp-group-head\"><h2>{home.about.title()}</h2>\n <p>{home.about.text()}</p></div>\n {home.about.layers && <ol className=\"btp-layers\">\n {home.about.layers.map((layer, index) => <li key={index}><span className=\"btp-layer-n\">{String(index + 1).padStart(2, '0')}</span><div><strong>{layer.name()}</strong><span>{layer.text()}</span></div></li>)}\n </ol>}\n {foot && <p className=\"btp-about-foot\">{foot.text()} <b>{foot.by}</b>{foot.link && <> · <button className=\"btp-link\" onClick={() => { invoke('open_external_url', { url: foot.link!.url }).catch(() => {}); }}>{foot.link.label}</button></>}</p>}\n </section>}\n </div>;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import { type IconPack } from '../../runtime/themeIcons.ts';
2
+ /** The install screen for one parsed pack. */
3
+ export declare function IconPackReview({ pack, warnings, bytes, replaces, onInstall, onCancel }: {
4
+ pack: IconPack;
5
+ warnings: string[];
6
+ bytes: number;
7
+ replaces: boolean;
8
+ onInstall(): void;
9
+ onCancel(): void;
10
+ }): import("react").JSX.Element;
11
+ /** The "Import icon pack…" button: reads a picked file and hands the parsed pack (or an error) back. */
12
+ export declare function IconPackImport({ onParsed, onError }: {
13
+ onParsed(pack: IconPack, warnings: string[], bytes: number): void;
14
+ onError(message: string): void;
15
+ }): import("react").JSX.Element;
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Importing an icon pack (a `*.icons.json` document) in Appearance: pick or drop the file, see what
3
+ // it is (name, author, licence, source, credits, every glyph, size, "data only") and install it into
4
+ // the theme choice, from where it reaches every site tab and the Icons picker. Nothing installs
5
+ // without this screen; a pack is data (path data, colored layers, small PNGs), never code.
6
+ import { useRef, useState } from 'react';
7
+ import { parseIconPackJson } from "../../runtime/themeIcons.js";
8
+ import { GlyphPaths } from "../frame/iconPack.js";
9
+ import { t } from "../frame/i18n.js";
10
+ import { Button } from "./controls.js";
11
+ const kb = (bytes) => `${Math.max(1, Math.round(bytes / 1024))} KB`;
12
+ /** The install screen for one parsed pack. */
13
+ export function IconPackReview({ pack, warnings, bytes, replaces, onInstall, onCancel }) {
14
+ const names = Object.keys(pack.glyphs);
15
+ return _jsx("div", { className: "bt-import wb-ask wb-pack-review", role: "alertdialog", "aria-label": t('wb.appearance.icons.review', { name: pack.name }), children: _jsxs("div", { className: "bt-import-drop", children: [_jsx("strong", { children: t('wb.appearance.icons.review', { name: pack.name }) }), _jsxs("dl", { className: "wb-pack-facts", children: [_jsx("dt", { children: t('wb.appearance.icons.author') }), _jsx("dd", { children: pack.author || '—' }), _jsx("dt", { children: t('wb.appearance.icons.license') }), _jsx("dd", { children: pack.license }), pack.source && _jsxs(_Fragment, { children: [_jsx("dt", { children: t('wb.appearance.icons.source') }), _jsx("dd", { children: pack.source })] }), pack.credits && _jsxs(_Fragment, { children: [_jsx("dt", { children: t('wb.appearance.icons.credits') }), _jsx("dd", { children: pack.credits })] }), _jsx("dt", { children: t('wb.appearance.icons.size') }), _jsx("dd", { children: t('wb.appearance.icons.sizeValue', { count: names.length, size: kb(bytes) }) })] }), _jsx("p", { children: t('wb.appearance.icons.dataOnly') }), _jsx("div", { className: "wb-pack-grid", "aria-hidden": "true", children: names.map(name => _jsx("span", { title: name, children: _jsx("svg", { className: "bt-glyph", viewBox: "0 0 24 24", children: _jsx(GlyphPaths, { glyph: pack.glyphs[name], pack: pack }) }) }, name)) }), warnings.map(warning => _jsx("p", { className: "wb-pack-warning", children: warning }, warning)), replaces && _jsx("p", { children: t('wb.appearance.icons.replaces', { name: pack.name }) }), _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", tone: "primary", onClick: onInstall, children: t('wb.appearance.icons.install') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: onCancel, children: t('wb.common.cancel') })] })] }) });
16
+ }
17
+ /** The "Import icon pack…" button: reads a picked file and hands the parsed pack (or an error) back. */
18
+ export function IconPackImport({ onParsed, onError }) {
19
+ const input = useRef(null);
20
+ const [busy, setBusy] = useState(false);
21
+ async function read(file) {
22
+ if (!file)
23
+ return;
24
+ setBusy(true);
25
+ try {
26
+ const text = await file.text();
27
+ const parsed = parseIconPackJson(text);
28
+ if ('error' in parsed)
29
+ onError(parsed.error);
30
+ else
31
+ onParsed(parsed.pack, parsed.warnings, text.length);
32
+ }
33
+ finally {
34
+ setBusy(false);
35
+ if (input.current)
36
+ input.current.value = '';
37
+ }
38
+ }
39
+ return _jsxs(_Fragment, { children: [_jsx("input", { ref: input, type: "file", accept: ".json,application/json", hidden: true, onChange: event => void read(event.target.files?.[0]) }), _jsx(Button, { size: "sm", tone: "ghost", disabled: busy, onClick: () => input.current?.click(), children: t('wb.appearance.icons.import') })] });
40
+ }
41
+ //# sourceMappingURL=IconPackInstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IconPackInstall.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/IconPackInstall.tsx"],"names":[],"mappings":"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","sourcesContent":["// Importing an icon pack (a `*.icons.json` document) in Appearance: pick or drop the file, see what\n// it is (name, author, licence, source, credits, every glyph, size, \"data only\") and install it into\n// the theme choice, from where it reaches every site tab and the Icons picker. Nothing installs\n// without this screen; a pack is data (path data, colored layers, small PNGs), never code.\n\nimport { useRef, useState } from 'react';\nimport { parseIconPackJson, type IconPack } from '../../../runtime/src/themeIcons.ts';\nimport { GlyphPaths } from '../frame/iconPack.tsx';\nimport { t } from '../frame/i18n.ts';\nimport { Button } from './controls.tsx';\n\nconst kb = (bytes: number) => `${Math.max(1, Math.round(bytes / 1024))} KB`;\n\n/** The install screen for one parsed pack. */\nexport function IconPackReview({ pack, warnings, bytes, replaces, onInstall, onCancel }: { pack: IconPack; warnings: string[]; bytes: number; replaces: boolean; onInstall(): void; onCancel(): void }) {\n const names = Object.keys(pack.glyphs) as Array<keyof IconPack['glyphs']>;\n return <div className=\"bt-import wb-ask wb-pack-review\" role=\"alertdialog\" aria-label={t('wb.appearance.icons.review', { name: pack.name })}>\n <div className=\"bt-import-drop\">\n <strong>{t('wb.appearance.icons.review', { name: pack.name })}</strong>\n <dl className=\"wb-pack-facts\">\n <dt>{t('wb.appearance.icons.author')}</dt><dd>{pack.author || '—'}</dd>\n <dt>{t('wb.appearance.icons.license')}</dt><dd>{pack.license}</dd>\n {pack.source && <><dt>{t('wb.appearance.icons.source')}</dt><dd>{pack.source}</dd></>}\n {pack.credits && <><dt>{t('wb.appearance.icons.credits')}</dt><dd>{pack.credits}</dd></>}\n <dt>{t('wb.appearance.icons.size')}</dt><dd>{t('wb.appearance.icons.sizeValue', { count: names.length, size: kb(bytes) })}</dd>\n </dl>\n <p>{t('wb.appearance.icons.dataOnly')}</p>\n <div className=\"wb-pack-grid\" aria-hidden=\"true\">\n {names.map(name => <span key={name} title={name}><svg className=\"bt-glyph\" viewBox=\"0 0 24 24\"><GlyphPaths glyph={pack.glyphs[name]!} pack={pack}/></svg></span>)}\n </div>\n {warnings.map(warning => <p key={warning} className=\"wb-pack-warning\">{warning}</p>)}\n {replaces && <p>{t('wb.appearance.icons.replaces', { name: pack.name })}</p>}\n <div className=\"bt-inline\"><Button size=\"sm\" tone=\"primary\" onClick={onInstall}>{t('wb.appearance.icons.install')}</Button><Button size=\"sm\" tone=\"ghost\" onClick={onCancel}>{t('wb.common.cancel')}</Button></div>\n </div>\n </div>;\n}\n\n/** The \"Import icon pack…\" button: reads a picked file and hands the parsed pack (or an error) back. */\nexport function IconPackImport({ onParsed, onError }: { onParsed(pack: IconPack, warnings: string[], bytes: number): void; onError(message: string): void }) {\n const input = useRef<HTMLInputElement>(null);\n const [busy, setBusy] = useState(false);\n async function read(file: File | undefined) {\n if (!file) return;\n setBusy(true);\n try {\n const text = await file.text();\n const parsed = parseIconPackJson(text);\n if ('error' in parsed) onError(parsed.error);\n else onParsed(parsed.pack, parsed.warnings, text.length);\n } finally { setBusy(false); if (input.current) input.current.value = ''; }\n }\n return <>\n <input ref={input} type=\"file\" accept=\".json,application/json\" hidden onChange={event => void read(event.target.files?.[0])}/>\n <Button size=\"sm\" tone=\"ghost\" disabled={busy} onClick={() => input.current?.click()}>{t('wb.appearance.icons.import')}</Button>\n </>;\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function LanguageSettings(): import("react").JSX.Element;