waybetter 0.1.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (537) hide show
  1. package/README.md +139 -6
  2. package/bin/waybetter.mjs +43 -0
  3. package/build/runtime.mjs +105 -0
  4. package/cli/buildenv.mjs +130 -0
  5. package/cli/dev.mjs +97 -0
  6. package/cli/i18n.mjs +382 -0
  7. package/cli/manifests.mjs +383 -0
  8. package/cli/release.mjs +437 -0
  9. package/cli/releasecheck.mjs +15 -0
  10. package/cli/remote.mjs +260 -0
  11. package/cli/store.mjs +378 -0
  12. package/cli/strings.mjs +123 -0
  13. package/dist/runtime/column.d.ts +93 -0
  14. package/dist/runtime/column.js +451 -0
  15. package/dist/runtime/column.js.map +1 -0
  16. package/dist/runtime/commandReport.d.ts +19 -0
  17. package/dist/runtime/commandReport.js +47 -0
  18. package/dist/runtime/commandReport.js.map +1 -0
  19. package/dist/runtime/commands.d.ts +72 -0
  20. package/dist/runtime/commands.js +214 -0
  21. package/dist/runtime/commands.js.map +1 -0
  22. package/dist/runtime/devErrors.d.ts +16 -0
  23. package/dist/runtime/devErrors.js +30 -0
  24. package/dist/runtime/devErrors.js.map +1 -0
  25. package/dist/runtime/domHub.d.ts +21 -0
  26. package/dist/runtime/domHub.js +139 -4
  27. package/dist/runtime/domHub.js.map +1 -1
  28. package/dist/runtime/featureModules.d.ts +157 -0
  29. package/dist/runtime/featureModules.js +484 -0
  30. package/dist/runtime/featureModules.js.map +1 -0
  31. package/dist/runtime/featureTable.d.ts +144 -0
  32. package/dist/runtime/featureTable.js +223 -0
  33. package/dist/runtime/featureTable.js.map +1 -0
  34. package/dist/runtime/fonts.d.ts +22 -0
  35. package/dist/runtime/fonts.js +72 -0
  36. package/dist/runtime/fonts.js.map +1 -0
  37. package/dist/runtime/i18n.d.ts +138 -0
  38. package/dist/runtime/i18n.js +614 -0
  39. package/dist/runtime/i18n.js.map +1 -0
  40. package/dist/runtime/i18nCheck.d.ts +30 -0
  41. package/dist/runtime/i18nCheck.js +224 -0
  42. package/dist/runtime/i18nCheck.js.map +1 -0
  43. package/dist/runtime/pageLang.d.ts +8 -0
  44. package/dist/runtime/pageLang.js +64 -0
  45. package/dist/runtime/pageLang.js.map +1 -0
  46. package/dist/runtime/pageStrings.d.ts +35 -0
  47. package/dist/runtime/pageStrings.js +76 -0
  48. package/dist/runtime/pageStrings.js.map +1 -0
  49. package/dist/runtime/panelButton.d.ts +33 -0
  50. package/dist/runtime/panelButton.js +83 -0
  51. package/dist/runtime/panelButton.js.map +1 -0
  52. package/dist/runtime/permissions.d.ts +47 -0
  53. package/dist/runtime/permissions.js +141 -0
  54. package/dist/runtime/permissions.js.map +1 -0
  55. package/dist/runtime/pluginApi.d.ts +51 -2
  56. package/dist/runtime/pluginApi.js +137 -22
  57. package/dist/runtime/pluginApi.js.map +1 -1
  58. package/dist/runtime/pluginI18n.d.ts +29 -0
  59. package/dist/runtime/pluginI18n.js +119 -0
  60. package/dist/runtime/pluginI18n.js.map +1 -0
  61. package/dist/runtime/settingsForm.d.ts +66 -0
  62. package/dist/runtime/settingsForm.js +114 -0
  63. package/dist/runtime/settingsForm.js.map +1 -0
  64. package/dist/runtime/site.d.ts +5 -0
  65. package/dist/runtime/site.js +1 -1
  66. package/dist/runtime/site.js.map +1 -1
  67. package/dist/runtime/siteRuntime.d.ts +144 -0
  68. package/dist/runtime/siteRuntime.js +175 -0
  69. package/dist/runtime/siteRuntime.js.map +1 -0
  70. package/dist/runtime/stringPackHook.d.ts +84 -0
  71. package/dist/runtime/stringPackHook.js +220 -0
  72. package/dist/runtime/stringPackHook.js.map +1 -0
  73. package/dist/runtime/stringPackTranslate.d.ts +61 -0
  74. package/dist/runtime/stringPackTranslate.js +267 -0
  75. package/dist/runtime/stringPackTranslate.js.map +1 -0
  76. package/dist/runtime/stringPacks.d.ts +248 -0
  77. package/dist/runtime/stringPacks.js +610 -0
  78. package/dist/runtime/stringPacks.js.map +1 -0
  79. package/dist/runtime/styles.d.ts +15 -0
  80. package/dist/runtime/styles.js +81 -0
  81. package/dist/runtime/styles.js.map +1 -0
  82. package/dist/runtime/textNet.d.ts +15 -0
  83. package/dist/runtime/textNet.js +131 -0
  84. package/dist/runtime/textNet.js.map +1 -0
  85. package/dist/runtime/themeApi.d.ts +121 -0
  86. package/dist/runtime/themeApi.js +220 -0
  87. package/dist/runtime/themeApi.js.map +1 -0
  88. package/dist/runtime/themeBar.d.ts +28 -0
  89. package/dist/runtime/themeBar.js +82 -0
  90. package/dist/runtime/themeBar.js.map +1 -0
  91. package/dist/runtime/themeChoice.d.ts +52 -0
  92. package/dist/runtime/themeChoice.js +69 -0
  93. package/dist/runtime/themeChoice.js.map +1 -0
  94. package/dist/runtime/themeComponents.d.ts +435 -0
  95. package/dist/runtime/themeComponents.js +476 -0
  96. package/dist/runtime/themeComponents.js.map +1 -0
  97. package/dist/runtime/themeDecor.d.ts +73 -0
  98. package/dist/runtime/themeDecor.js +133 -0
  99. package/dist/runtime/themeDecor.js.map +1 -0
  100. package/dist/runtime/themeDerive.d.ts +69 -0
  101. package/dist/runtime/themeDerive.js +117 -0
  102. package/dist/runtime/themeDerive.js.map +1 -0
  103. package/dist/runtime/themeDoctor.d.ts +52 -0
  104. package/dist/runtime/themeDoctor.js +112 -0
  105. package/dist/runtime/themeDoctor.js.map +1 -0
  106. package/dist/runtime/themeGuards.d.ts +60 -0
  107. package/dist/runtime/themeGuards.js +235 -0
  108. package/dist/runtime/themeGuards.js.map +1 -0
  109. package/dist/runtime/themeIcons.d.ts +130 -0
  110. package/dist/runtime/themeIcons.js +271 -0
  111. package/dist/runtime/themeIcons.js.map +1 -0
  112. package/dist/runtime/themeInk.d.ts +37 -0
  113. package/dist/runtime/themeInk.js +111 -0
  114. package/dist/runtime/themeInk.js.map +1 -0
  115. package/dist/runtime/themeInvariants.d.ts +39 -0
  116. package/dist/runtime/themeInvariants.js +273 -0
  117. package/dist/runtime/themeInvariants.js.map +1 -0
  118. package/dist/runtime/themeRuntime.d.ts +114 -0
  119. package/dist/runtime/themeRuntime.js +570 -0
  120. package/dist/runtime/themeRuntime.js.map +1 -0
  121. package/dist/runtime/themeSchema.d.ts +10 -0
  122. package/dist/runtime/themeSchema.js +150 -0
  123. package/dist/runtime/themeSchema.js.map +1 -0
  124. package/dist/runtime/themeSpec.d.ts +263 -0
  125. package/dist/runtime/themeSpec.js +435 -0
  126. package/dist/runtime/themeSpec.js.map +1 -0
  127. package/dist/runtime/themeTokens.d.ts +12 -0
  128. package/dist/runtime/themeTokens.js +14 -6
  129. package/dist/runtime/themeTokens.js.map +1 -1
  130. package/dist/runtime/themeVariants.d.ts +30 -0
  131. package/dist/runtime/themeVariants.js +53 -0
  132. package/dist/runtime/themeVariants.js.map +1 -0
  133. package/dist/runtime/ui.d.ts +192 -0
  134. package/dist/runtime/ui.js +926 -0
  135. package/dist/runtime/ui.js.map +1 -0
  136. package/dist/shell/InstallDialog.d.ts +40 -0
  137. package/dist/shell/InstallDialog.js +176 -0
  138. package/dist/shell/InstallDialog.js.map +1 -0
  139. package/dist/shell/StoreView.d.ts +78 -0
  140. package/dist/shell/StoreView.js +108 -0
  141. package/dist/shell/StoreView.js.map +1 -0
  142. package/dist/shell/addressModel.js.map +1 -1
  143. package/dist/shell/chrome.js.map +1 -1
  144. package/dist/shell/deckModel.d.ts +117 -0
  145. package/dist/shell/deckModel.js +267 -0
  146. package/dist/shell/deckModel.js.map +1 -0
  147. package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
  148. package/dist/shell/frame/AccountSwitcher.js +243 -0
  149. package/dist/shell/frame/AccountSwitcher.js.map +1 -0
  150. package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
  151. package/dist/shell/frame/AddColumnDialog.js +81 -0
  152. package/dist/shell/frame/AddColumnDialog.js.map +1 -0
  153. package/dist/shell/frame/AppMenu.d.ts +44 -0
  154. package/dist/shell/frame/AppMenu.js +721 -0
  155. package/dist/shell/frame/AppMenu.js.map +1 -0
  156. package/dist/shell/frame/CommandPalette.d.ts +7 -0
  157. package/dist/shell/frame/CommandPalette.js +118 -0
  158. package/dist/shell/frame/CommandPalette.js.map +1 -0
  159. package/dist/shell/frame/DeckView.d.ts +13 -0
  160. package/dist/shell/frame/DeckView.js +287 -0
  161. package/dist/shell/frame/DeckView.js.map +1 -0
  162. package/dist/shell/frame/FindBar.d.ts +10 -0
  163. package/dist/shell/frame/FindBar.js +108 -0
  164. package/dist/shell/frame/FindBar.js.map +1 -0
  165. package/dist/shell/frame/MediaPanel.d.ts +8 -0
  166. package/dist/shell/frame/MediaPanel.js +76 -0
  167. package/dist/shell/frame/MediaPanel.js.map +1 -0
  168. package/dist/shell/frame/NewTabPage.d.ts +9 -0
  169. package/dist/shell/frame/NewTabPage.js +71 -0
  170. package/dist/shell/frame/NewTabPage.js.map +1 -0
  171. package/dist/shell/frame/PaneTheme.d.ts +16 -0
  172. package/dist/shell/frame/PaneTheme.js +67 -0
  173. package/dist/shell/frame/PaneTheme.js.map +1 -0
  174. package/dist/shell/frame/ReportDialog.d.ts +3 -0
  175. package/dist/shell/frame/ReportDialog.js +95 -0
  176. package/dist/shell/frame/ReportDialog.js.map +1 -0
  177. package/dist/shell/frame/Shell.d.ts +9 -0
  178. package/dist/shell/frame/Shell.js +1139 -0
  179. package/dist/shell/frame/Shell.js.map +1 -0
  180. package/dist/shell/frame/Titlebar.d.ts +17 -0
  181. package/dist/shell/frame/Titlebar.js +79 -0
  182. package/dist/shell/frame/Titlebar.js.map +1 -0
  183. package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
  184. package/dist/shell/frame/TitlebarExtras.js +202 -0
  185. package/dist/shell/frame/TitlebarExtras.js.map +1 -0
  186. package/dist/shell/frame/WebPanel.d.ts +4 -0
  187. package/dist/shell/frame/WebPanel.js +185 -0
  188. package/dist/shell/frame/WebPanel.js.map +1 -0
  189. package/dist/shell/frame/accountModel.d.ts +49 -0
  190. package/dist/shell/frame/accountModel.js +67 -0
  191. package/dist/shell/frame/accountModel.js.map +1 -0
  192. package/dist/shell/frame/accountSwitcher.css +91 -0
  193. package/dist/shell/frame/appI18n.d.ts +44 -0
  194. package/dist/shell/frame/appI18n.js +64 -0
  195. package/dist/shell/frame/appI18n.js.map +1 -0
  196. package/dist/shell/frame/appMenu.css +127 -0
  197. package/dist/shell/frame/backupModel.d.ts +38 -0
  198. package/dist/shell/frame/backupModel.js +192 -0
  199. package/dist/shell/frame/backupModel.js.map +1 -0
  200. package/dist/shell/frame/boot.d.ts +8 -0
  201. package/dist/shell/frame/boot.js +37 -0
  202. package/dist/shell/frame/boot.js.map +1 -0
  203. package/dist/shell/frame/brand.d.ts +1 -0
  204. package/dist/shell/frame/brand.js +4 -0
  205. package/dist/shell/frame/brand.js.map +1 -0
  206. package/dist/shell/frame/bridge.d.ts +35 -0
  207. package/dist/shell/frame/bridge.js +70 -0
  208. package/dist/shell/frame/bridge.js.map +1 -0
  209. package/dist/shell/frame/chromeTheme.d.ts +47 -0
  210. package/dist/shell/frame/chromeTheme.js +118 -0
  211. package/dist/shell/frame/chromeTheme.js.map +1 -0
  212. package/dist/shell/frame/deck.css +209 -0
  213. package/dist/shell/frame/deckStore.d.ts +89 -0
  214. package/dist/shell/frame/deckStore.js +239 -0
  215. package/dist/shell/frame/deckStore.js.map +1 -0
  216. package/dist/shell/frame/devHost.d.ts +35 -0
  217. package/dist/shell/frame/devHost.js +80 -0
  218. package/dist/shell/frame/devHost.js.map +1 -0
  219. package/dist/shell/frame/devModel.d.ts +7 -0
  220. package/dist/shell/frame/devModel.js +17 -0
  221. package/dist/shell/frame/devModel.js.map +1 -0
  222. package/dist/shell/frame/diag.d.ts +7 -0
  223. package/dist/shell/frame/diag.js +39 -0
  224. package/dist/shell/frame/diag.js.map +1 -0
  225. package/dist/shell/frame/edges.css +159 -0
  226. package/dist/shell/frame/findBar.css +14 -0
  227. package/dist/shell/frame/frameMessages.d.ts +248 -0
  228. package/dist/shell/frame/frameMessages.js +252 -0
  229. package/dist/shell/frame/frameMessages.js.map +1 -0
  230. package/dist/shell/frame/hooks.d.ts +39 -0
  231. package/dist/shell/frame/hooks.js +97 -0
  232. package/dist/shell/frame/hooks.js.map +1 -0
  233. package/dist/shell/frame/i18n.d.ts +27 -0
  234. package/dist/shell/frame/i18n.js +66 -0
  235. package/dist/shell/frame/i18n.js.map +1 -0
  236. package/dist/shell/frame/iconPack.d.ts +11 -0
  237. package/dist/shell/frame/iconPack.js +45 -0
  238. package/dist/shell/frame/iconPack.js.map +1 -0
  239. package/dist/shell/frame/icons.d.ts +71 -0
  240. package/dist/shell/frame/icons.js +75 -0
  241. package/dist/shell/frame/icons.js.map +1 -0
  242. package/dist/shell/frame/index.d.ts +34 -0
  243. package/dist/shell/frame/index.js +43 -0
  244. package/dist/shell/frame/index.js.map +1 -0
  245. package/dist/shell/frame/language.d.ts +58 -0
  246. package/dist/shell/frame/language.js +165 -0
  247. package/dist/shell/frame/language.js.map +1 -0
  248. package/dist/shell/frame/mediaModel.d.ts +47 -0
  249. package/dist/shell/frame/mediaModel.js +67 -0
  250. package/dist/shell/frame/mediaModel.js.map +1 -0
  251. package/dist/shell/frame/menuMessages.en.json +96 -0
  252. package/dist/shell/frame/menuModel.d.ts +319 -0
  253. package/dist/shell/frame/menuModel.js +301 -0
  254. package/dist/shell/frame/menuModel.js.map +1 -0
  255. package/dist/shell/frame/nativeMenu.d.ts +5 -0
  256. package/dist/shell/frame/nativeMenu.js +178 -0
  257. package/dist/shell/frame/nativeMenu.js.map +1 -0
  258. package/dist/shell/frame/nativeMenuModel.d.ts +102 -0
  259. package/dist/shell/frame/nativeMenuModel.js +186 -0
  260. package/dist/shell/frame/nativeMenuModel.js.map +1 -0
  261. package/dist/shell/frame/paletteModel.d.ts +139 -0
  262. package/dist/shell/frame/paletteModel.js +114 -0
  263. package/dist/shell/frame/paletteModel.js.map +1 -0
  264. package/dist/shell/frame/paneTheme.css +9 -0
  265. package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
  266. package/dist/shell/frame/pluginCommandStore.js +70 -0
  267. package/dist/shell/frame/pluginCommandStore.js.map +1 -0
  268. package/dist/shell/frame/reportModel.d.ts +52 -0
  269. package/dist/shell/frame/reportModel.js +105 -0
  270. package/dist/shell/frame/reportModel.js.map +1 -0
  271. package/dist/shell/frame/safeStore.d.ts +7 -0
  272. package/dist/shell/frame/safeStore.js +40 -0
  273. package/dist/shell/frame/safeStore.js.map +1 -0
  274. package/dist/shell/frame/searchInput.d.ts +2 -0
  275. package/dist/shell/frame/searchInput.js +11 -0
  276. package/dist/shell/frame/searchInput.js.map +1 -0
  277. package/dist/shell/frame/shell.css +634 -0
  278. package/dist/shell/frame/site.d.ts +206 -0
  279. package/dist/shell/frame/site.js +22 -0
  280. package/dist/shell/frame/site.js.map +1 -0
  281. package/dist/shell/frame/state.d.ts +101 -0
  282. package/dist/shell/frame/state.js +286 -0
  283. package/dist/shell/frame/state.js.map +1 -0
  284. package/dist/shell/frame/syncGate.d.ts +10 -0
  285. package/dist/shell/frame/syncGate.js +36 -0
  286. package/dist/shell/frame/syncGate.js.map +1 -0
  287. package/dist/shell/frame/syncHost.d.ts +35 -0
  288. package/dist/shell/frame/syncHost.js +85 -0
  289. package/dist/shell/frame/syncHost.js.map +1 -0
  290. package/dist/shell/frame/tabStill.d.ts +2 -0
  291. package/dist/shell/frame/tabStill.js +62 -0
  292. package/dist/shell/frame/tabStill.js.map +1 -0
  293. package/dist/shell/frame/themeScopes.d.ts +29 -0
  294. package/dist/shell/frame/themeScopes.js +61 -0
  295. package/dist/shell/frame/themeScopes.js.map +1 -0
  296. package/dist/shell/frame/themeStore.d.ts +99 -0
  297. package/dist/shell/frame/themeStore.js +267 -0
  298. package/dist/shell/frame/themeStore.js.map +1 -0
  299. package/dist/shell/frame/windowBinding.d.ts +2 -0
  300. package/dist/shell/frame/windowBinding.js +7 -0
  301. package/dist/shell/frame/windowBinding.js.map +1 -0
  302. package/dist/shell/frame/workspaceModel.d.ts +82 -0
  303. package/dist/shell/frame/workspaceModel.js +250 -0
  304. package/dist/shell/frame/workspaceModel.js.map +1 -0
  305. package/dist/shell/frame/workspaces.css +84 -0
  306. package/dist/shell/frame/workspaces.d.ts +22 -0
  307. package/dist/shell/frame/workspaces.js +125 -0
  308. package/dist/shell/frame/workspaces.js.map +1 -0
  309. package/dist/shell/frame/zoomStore.d.ts +10 -0
  310. package/dist/shell/frame/zoomStore.js +65 -0
  311. package/dist/shell/frame/zoomStore.js.map +1 -0
  312. package/dist/shell/installController.d.ts +137 -0
  313. package/dist/shell/installController.js +172 -0
  314. package/dist/shell/installController.js.map +1 -0
  315. package/dist/shell/installerMessages.d.ts +30 -0
  316. package/dist/shell/installerMessages.js +36 -0
  317. package/dist/shell/installerMessages.js.map +1 -0
  318. package/dist/shell/linkDrop.js.map +1 -1
  319. package/dist/shell/messages.d.ts +16 -0
  320. package/dist/shell/messages.js +27 -0
  321. package/dist/shell/messages.js.map +1 -0
  322. package/dist/shell/palette.js.map +1 -1
  323. package/dist/shell/paneModel.d.ts +22 -0
  324. package/dist/shell/paneModel.js +24 -1
  325. package/dist/shell/paneModel.js.map +1 -1
  326. package/dist/shell/panel/Appearance.d.ts +8 -0
  327. package/dist/shell/panel/Appearance.js +265 -0
  328. package/dist/shell/panel/Appearance.js.map +1 -0
  329. package/dist/shell/panel/BackupPanel.d.ts +5 -0
  330. package/dist/shell/panel/BackupPanel.js +198 -0
  331. package/dist/shell/panel/BackupPanel.js.map +1 -0
  332. package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
  333. package/dist/shell/panel/DeveloperPanel.js +51 -0
  334. package/dist/shell/panel/DeveloperPanel.js.map +1 -0
  335. package/dist/shell/panel/FeatureToggles.d.ts +13 -0
  336. package/dist/shell/panel/FeatureToggles.js +42 -0
  337. package/dist/shell/panel/FeatureToggles.js.map +1 -0
  338. package/dist/shell/panel/Home.d.ts +3 -0
  339. package/dist/shell/panel/Home.js +23 -0
  340. package/dist/shell/panel/Home.js.map +1 -0
  341. package/dist/shell/panel/IconPackInstall.d.ts +15 -0
  342. package/dist/shell/panel/IconPackInstall.js +41 -0
  343. package/dist/shell/panel/IconPackInstall.js.map +1 -0
  344. package/dist/shell/panel/LanguageSettings.d.ts +1 -0
  345. package/dist/shell/panel/LanguageSettings.js +54 -0
  346. package/dist/shell/panel/LanguageSettings.js.map +1 -0
  347. package/dist/shell/panel/MakePanel.d.ts +3 -0
  348. package/dist/shell/panel/MakePanel.js +237 -0
  349. package/dist/shell/panel/MakePanel.js.map +1 -0
  350. package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
  351. package/dist/shell/panel/MarkdownDoc.js +35 -0
  352. package/dist/shell/panel/MarkdownDoc.js.map +1 -0
  353. package/dist/shell/panel/Modes.d.ts +40 -0
  354. package/dist/shell/panel/Modes.js +270 -0
  355. package/dist/shell/panel/Modes.js.map +1 -0
  356. package/dist/shell/panel/NavIcon.d.ts +4 -0
  357. package/dist/shell/panel/NavIcon.js +6 -0
  358. package/dist/shell/panel/NavIcon.js.map +1 -0
  359. package/dist/shell/panel/Panel.d.ts +7 -0
  360. package/dist/shell/panel/Panel.js +139 -0
  361. package/dist/shell/panel/Panel.js.map +1 -0
  362. package/dist/shell/panel/PluginFeatures.d.ts +24 -0
  363. package/dist/shell/panel/PluginFeatures.js +165 -0
  364. package/dist/shell/panel/PluginFeatures.js.map +1 -0
  365. package/dist/shell/panel/Plugins.d.ts +33 -0
  366. package/dist/shell/panel/Plugins.js +112 -0
  367. package/dist/shell/panel/Plugins.js.map +1 -0
  368. package/dist/shell/panel/PowerSettings.d.ts +4 -0
  369. package/dist/shell/panel/PowerSettings.js +52 -0
  370. package/dist/shell/panel/PowerSettings.js.map +1 -0
  371. package/dist/shell/panel/Settings.d.ts +23 -0
  372. package/dist/shell/panel/Settings.js +117 -0
  373. package/dist/shell/panel/Settings.js.map +1 -0
  374. package/dist/shell/panel/ShareSetup.d.ts +8 -0
  375. package/dist/shell/panel/ShareSetup.js +130 -0
  376. package/dist/shell/panel/ShareSetup.js.map +1 -0
  377. package/dist/shell/panel/StoreSection.d.ts +7 -0
  378. package/dist/shell/panel/StoreSection.js +78 -0
  379. package/dist/shell/panel/StoreSection.js.map +1 -0
  380. package/dist/shell/panel/StringPacks.d.ts +20 -0
  381. package/dist/shell/panel/StringPacks.js +131 -0
  382. package/dist/shell/panel/StringPacks.js.map +1 -0
  383. package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
  384. package/dist/shell/panel/ThemeBuilder.js +205 -0
  385. package/dist/shell/panel/ThemeBuilder.js.map +1 -0
  386. package/dist/shell/panel/backup.css +34 -0
  387. package/dist/shell/panel/builder.css +240 -0
  388. package/dist/shell/panel/builderModel.d.ts +55 -0
  389. package/dist/shell/panel/builderModel.js +95 -0
  390. package/dist/shell/panel/builderModel.js.map +1 -0
  391. package/dist/shell/panel/compare.d.ts +10 -0
  392. package/dist/shell/panel/compare.js +51 -0
  393. package/dist/shell/panel/compare.js.map +1 -0
  394. package/dist/shell/panel/controls.d.ts +135 -0
  395. package/dist/shell/panel/controls.js +213 -0
  396. package/dist/shell/panel/controls.js.map +1 -0
  397. package/dist/shell/panel/featureModel.d.ts +69 -0
  398. package/dist/shell/panel/featureModel.js +79 -0
  399. package/dist/shell/panel/featureModel.js.map +1 -0
  400. package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
  401. package/dist/shell/panel/fonts/FontBrowser.js +189 -0
  402. package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
  403. package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
  404. package/dist/shell/panel/fonts/FontRoles.js +77 -0
  405. package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
  406. package/dist/shell/panel/fonts/catalog.d.ts +37 -0
  407. package/dist/shell/panel/fonts/catalog.js +68 -0
  408. package/dist/shell/panel/fonts/catalog.js.map +1 -0
  409. package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
  410. package/dist/shell/panel/index.d.ts +20 -0
  411. package/dist/shell/panel/index.js +34 -0
  412. package/dist/shell/panel/index.js.map +1 -0
  413. package/dist/shell/panel/languageModel.d.ts +5 -0
  414. package/dist/shell/panel/languageModel.js +7 -0
  415. package/dist/shell/panel/languageModel.js.map +1 -0
  416. package/dist/shell/panel/make.css +73 -0
  417. package/dist/shell/panel/makeModel.d.ts +32 -0
  418. package/dist/shell/panel/makeModel.js +84 -0
  419. package/dist/shell/panel/makeModel.js.map +1 -0
  420. package/dist/shell/panel/markdown.d.ts +46 -0
  421. package/dist/shell/panel/markdown.js +100 -0
  422. package/dist/shell/panel/markdown.js.map +1 -0
  423. package/dist/shell/panel/nav.d.ts +12 -0
  424. package/dist/shell/panel/nav.js +50 -0
  425. package/dist/shell/panel/nav.js.map +1 -0
  426. package/dist/shell/panel/panel.css +401 -0
  427. package/dist/shell/panel/panelMessages.d.ts +803 -0
  428. package/dist/shell/panel/panelMessages.js +779 -0
  429. package/dist/shell/panel/panelMessages.js.map +1 -0
  430. package/dist/shell/panel/plugins.css +59 -0
  431. package/dist/shell/panel/setupModel.d.ts +87 -0
  432. package/dist/shell/panel/setupModel.js +152 -0
  433. package/dist/shell/panel/setupModel.js.map +1 -0
  434. package/dist/shell/panel/site.d.ts +259 -0
  435. package/dist/shell/panel/site.js +25 -0
  436. package/dist/shell/panel/site.js.map +1 -0
  437. package/dist/shell/panel/strings.css +7 -0
  438. package/dist/shell/panel/themes.d.ts +10 -0
  439. package/dist/shell/panel/themes.js +8 -0
  440. package/dist/shell/panel/themes.js.map +1 -0
  441. package/dist/shell/profileModel.d.ts +3 -2
  442. package/dist/shell/profileModel.js +7 -5
  443. package/dist/shell/profileModel.js.map +1 -1
  444. package/dist/shell/store.css +250 -0
  445. package/dist/shell/storeMessages.d.ts +193 -0
  446. package/dist/shell/storeMessages.js +196 -0
  447. package/dist/shell/storeMessages.js.map +1 -0
  448. package/dist/shell/storeModel.d.ts +205 -0
  449. package/dist/shell/storeModel.js +146 -0
  450. package/dist/shell/storeModel.js.map +1 -0
  451. package/dist/shell/stringPacksModel.d.ts +44 -0
  452. package/dist/shell/stringPacksModel.js +99 -0
  453. package/dist/shell/stringPacksModel.js.map +1 -0
  454. package/dist/shell/updateModel.d.ts +2 -1
  455. package/dist/shell/updateModel.js +5 -4
  456. package/dist/shell/updateModel.js.map +1 -1
  457. package/dist/shell/windowControls.d.ts +4 -0
  458. package/dist/shell/windowControls.js +5 -0
  459. package/dist/shell/windowControls.js.map +1 -1
  460. package/i18n-config.schema.json +29 -0
  461. package/i18n-meta.schema.json +26 -0
  462. package/i18n.schema.json +42 -0
  463. package/icons.schema.json +655 -0
  464. package/languages.schema.json +23 -0
  465. package/locales/ar-x-fm.json +11 -0
  466. package/locales/ar.json +1388 -0
  467. package/locales/bg.json +1387 -0
  468. package/locales/bn.json +1387 -0
  469. package/locales/ca.json +1387 -0
  470. package/locales/cs.json +1387 -0
  471. package/locales/da.json +1387 -0
  472. package/locales/de.json +1387 -0
  473. package/locales/el.json +1387 -0
  474. package/locales/en-GB.json +27 -0
  475. package/locales/en.json +1386 -0
  476. package/locales/en.meta.json +51 -0
  477. package/locales/es.json +1387 -0
  478. package/locales/eu.json +1387 -0
  479. package/locales/fa.json +1388 -0
  480. package/locales/fi.json +1387 -0
  481. package/locales/fil.json +1387 -0
  482. package/locales/fr.json +1387 -0
  483. package/locales/ga.json +1387 -0
  484. package/locales/gl.json +1387 -0
  485. package/locales/gu.json +1387 -0
  486. package/locales/ha.json +1387 -0
  487. package/locales/he.json +1388 -0
  488. package/locales/hi.json +1387 -0
  489. package/locales/hr.json +1387 -0
  490. package/locales/hu.json +1387 -0
  491. package/locales/id.json +1387 -0
  492. package/locales/ig.json +1387 -0
  493. package/locales/it.json +1387 -0
  494. package/locales/ja.json +1387 -0
  495. package/locales/kn.json +1387 -0
  496. package/locales/ko.json +1387 -0
  497. package/locales/mr.json +1387 -0
  498. package/locales/ms.json +1387 -0
  499. package/locales/nb.json +1387 -0
  500. package/locales/nl.json +1387 -0
  501. package/locales/pl.json +1387 -0
  502. package/locales/pt.json +1387 -0
  503. package/locales/ro.json +1387 -0
  504. package/locales/ru.json +1387 -0
  505. package/locales/sk.json +1387 -0
  506. package/locales/sr.json +1387 -0
  507. package/locales/sv.json +1387 -0
  508. package/locales/ta.json +1387 -0
  509. package/locales/th.json +1387 -0
  510. package/locales/tr.json +1387 -0
  511. package/locales/uk.json +1387 -0
  512. package/locales/ur.json +1388 -0
  513. package/locales/vi.json +1387 -0
  514. package/locales/yo.json +1387 -0
  515. package/locales/zh-Hans.json +1387 -0
  516. package/locales/zh-Hant.json +1387 -0
  517. package/package.json +138 -5
  518. package/store-catalog.schema.json +78 -0
  519. package/theme.schema.json +4668 -0
  520. package/windows/installer.nsi +946 -0
  521. package/windows/languages/Basque.nsh +28 -0
  522. package/windows/languages/Catalan.nsh +28 -0
  523. package/windows/languages/Croatian.nsh +28 -0
  524. package/windows/languages/Czech.nsh +28 -0
  525. package/windows/languages/Danish.nsh +28 -0
  526. package/windows/languages/Finnish.nsh +28 -0
  527. package/windows/languages/Galician.nsh +28 -0
  528. package/windows/languages/Greek.nsh +28 -0
  529. package/windows/languages/Hungarian.nsh +28 -0
  530. package/windows/languages/Indonesian.nsh +28 -0
  531. package/windows/languages/Irish.nsh +28 -0
  532. package/windows/languages/Malay.nsh +28 -0
  533. package/windows/languages/Polish.nsh +28 -0
  534. package/windows/languages/Romanian.nsh +28 -0
  535. package/windows/languages/Serbian.nsh +28 -0
  536. package/windows/languages/Slovak.nsh +28 -0
  537. package/windows/languages/Thai.nsh +28 -0
@@ -0,0 +1,78 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { InstallController } from './installController.ts';
3
+ import type { StoreText } from './storeMessages.ts';
4
+ import { type StoreCatalogView, type StoreItem } from './storeModel.ts';
5
+ type ButtonProps = {
6
+ children: ReactNode;
7
+ onClick?(): void;
8
+ tone?: 'plain' | 'primary' | 'ghost' | 'danger';
9
+ size?: 'sm' | 'md';
10
+ disabled?: boolean;
11
+ title?: string;
12
+ };
13
+ type Option<T extends string> = {
14
+ value: T;
15
+ label: string;
16
+ };
17
+ export type StoreControls = {
18
+ Button(props: ButtonProps): ReactNode;
19
+ SearchField(props: {
20
+ value: string;
21
+ onChange(next: string): void;
22
+ placeholder: string;
23
+ label: string;
24
+ }): ReactNode;
25
+ Segmented<T extends string>(props: {
26
+ value: T;
27
+ options: Array<Option<T>>;
28
+ onChange(next: T): void;
29
+ label: string;
30
+ size?: 'sm' | 'md';
31
+ }): ReactNode;
32
+ EmptyState(props: {
33
+ icon?: ReactNode;
34
+ title: string;
35
+ children?: ReactNode;
36
+ action?: ReactNode;
37
+ }): ReactNode;
38
+ Badge(props: {
39
+ children: ReactNode;
40
+ }): ReactNode;
41
+ };
42
+ export declare const DEFAULT_CONTROLS: StoreControls;
43
+ export type StoreViewProps<Theme> = {
44
+ t: StoreText;
45
+ /** The site's name in messages ("X"). */
46
+ site: string;
47
+ /** `store_catalog` (the app passes `refresh => invoke('store_catalog', { refresh })`). */
48
+ load(refresh: boolean): Promise<StoreCatalogView>;
49
+ /** The install screen's controller: Install opens it; the list refreshes when it closes. */
50
+ controller: InstallController<Theme>;
51
+ /** Theme ids that ship with the app, and the owner's own theme ids now. */
52
+ builtinThemes: readonly string[];
53
+ userThemes: readonly string[];
54
+ /** The owner's installed icon pack ids now (an icon pack the owner removed in Appearance shows as installable again). */
55
+ userIcons?: readonly string[];
56
+ /**
57
+ * The app's area plugins, for items of kind `builtin`: whether the app has one by this id, whether
58
+ * its switch is on, and turning it on or off. Without it (or for an id it does not have) a built-in
59
+ * item only says it is built in.
60
+ */
61
+ areas?: {
62
+ has(id: string): boolean;
63
+ on(id: string): boolean;
64
+ set(id: string, on: boolean): Promise<void>;
65
+ };
66
+ /** Removes an installed item (plugin file, or the owner's copy of a store theme); false: nothing to remove. */
67
+ onRemove(item: StoreItem, view: StoreCatalogView): Promise<boolean>;
68
+ /** Makes a built-in theme the current one. */
69
+ onUse(item: StoreItem): Promise<void>;
70
+ notify(text: string, error?: boolean): void;
71
+ /** "3 minutes ago" for a timestamp (the app's relative-time formatter). */
72
+ relativeTime(at: number): string;
73
+ /** Window events after which the list reloads (e.g. the app's "plugins changed"). */
74
+ reloadOn?: readonly string[];
75
+ controls?: Partial<StoreControls>;
76
+ };
77
+ export declare function StoreView<Theme>(props: StoreViewProps<Theme>): import("react").JSX.Element;
78
+ export {};
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // The wayBetter Store view, shared by every wayBetter app: themes and plugins from the signed
3
+ // catalog (native code verifies its Ed25519 signature, keeps this app's items, then checks each
4
+ // download's sha256). Search, kinds, categories, cards with previews and permission badges, and
5
+ // Install / Update / Remove. Installing always goes through the install screen (InstallHost), never
6
+ // straight from here. Styles: `store.css` (framework `--wb-*` tokens). The app may pass its own
7
+ // controls (buttons, search field, segmented control) so the view matches its settings.
8
+ import { useEffect, useMemo, useState, useSyncExternalStore } from 'react';
9
+ import { categoryLabel, errorText, filterItems, itemState, permissionBadges } from "./storeModel.js";
10
+ export const DEFAULT_CONTROLS = {
11
+ Button: ({ children, onClick, tone = 'plain', size = 'md', disabled, title }) => _jsx("button", { type: "button", className: `wb-btn is-${tone} is-${size}`, disabled: disabled, title: title, onClick: onClick, children: children }),
12
+ SearchField: ({ value, onChange, placeholder, label }) => _jsx("input", { className: "wb-field", type: "search", "aria-label": label, placeholder: placeholder, value: value, onChange: event => onChange(event.target.value), onKeyDown: event => { if (event.key === 'Escape' && value) {
13
+ event.stopPropagation();
14
+ onChange('');
15
+ } } }),
16
+ Segmented: ({ value, options, onChange, label }) => _jsx("div", { className: "wb-segmented", role: "radiogroup", "aria-label": label, children: options.map(option => _jsx("button", { type: "button", role: "radio", "aria-checked": option.value === value, className: option.value === value ? 'is-on' : '', onClick: () => onChange(option.value), children: option.label }, option.value)) }),
17
+ EmptyState: ({ icon, title, children, action }) => _jsxs("div", { className: "wb-empty", children: [icon && _jsx("div", { "aria-hidden": "true", children: icon }), _jsx("strong", { children: title }), children && _jsx("p", { children: children }), action] }),
18
+ Badge: ({ children }) => _jsx("span", { className: "wb-badge", children: children }),
19
+ };
20
+ const STORE_ICON = _jsx("svg", { width: "22", height: "22", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M4 9l1.5-5h13L20 9M4 9h16v11H4zM4 9a2.7 2.7 0 0 0 5.3 0 2.7 2.7 0 0 0 5.4 0 2.7 2.7 0 0 0 5.3 0M10 20v-5h4v5", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinejoin: "round" }) });
21
+ function Preview({ item }) {
22
+ const [broken, setBroken] = useState(false);
23
+ const c = item.colors;
24
+ if (item.preview && !broken)
25
+ return _jsx("img", { className: "wbs-img", src: item.preview, alt: "", loading: "lazy", onError: () => setBroken(true) });
26
+ // Offline or not published yet: swatches from the signed catalog (themes) or a plain tile.
27
+ return _jsx("div", { className: "wbs-img wbs-swatch", style: c ? { background: c.bg } : undefined, "aria-hidden": "true", children: c ? _jsxs(_Fragment, { children: [_jsx("span", { style: { background: c.surface ?? c.bg, borderColor: c.text } }), _jsx("i", { style: { background: c.text } }), _jsx("b", { style: { background: c.accent } })] }) : _jsx("strong", { children: item.name.slice(0, 1) }) });
28
+ }
29
+ function Action({ item, state, busy, t, ui, areas, onInstall, onRemove, onUse, onArea }) {
30
+ const { Button } = ui;
31
+ const [asking, setAsking] = useState(false);
32
+ if (state.state === 'area') {
33
+ const known = areas?.has(item.id) ?? false;
34
+ const on = known && areas.on(item.id);
35
+ return _jsxs("div", { className: "wbs-actions", children: [_jsxs("span", { className: "wbs-state", children: [t('wb.store.builtinItem'), known && ` · ${on ? t('wb.store.areaOn') : t('wb.store.areaOff')}`] }), known && _jsxs("label", { className: "wbs-switch", title: t('wb.store.areaSwitch', { name: item.name }), children: [_jsx("input", { type: "checkbox", role: "switch", checked: on, "aria-label": t('wb.store.areaSwitch', { name: item.name }), onChange: event => onArea(event.target.checked) }), _jsx("span", { "aria-hidden": "true" })] })] });
36
+ }
37
+ if (state.state === 'builtin')
38
+ return _jsxs("div", { className: "wbs-actions", children: [_jsx("span", { className: "wbs-state", children: t('wb.store.builtIn') }), _jsx(Button, { size: "sm", onClick: onUse, children: t('wb.store.use') })] });
39
+ if (state.state === 'install')
40
+ return _jsx("div", { className: "wbs-actions", children: _jsx(Button, { size: "sm", tone: "primary", disabled: busy, onClick: onInstall, children: t('wb.store.install') }) });
41
+ const remove = asking
42
+ ? _jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", tone: "danger", onClick: () => { setAsking(false); onRemove(); }, children: t('wb.store.remove') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => setAsking(false), children: t('wb.store.keep') })] })
43
+ : _jsx(Button, { size: "sm", tone: "ghost", onClick: () => setAsking(true), children: t('wb.store.remove') });
44
+ if (state.state === 'update')
45
+ return _jsxs("div", { className: "wbs-actions", children: [_jsx(Button, { size: "sm", tone: "primary", disabled: busy, onClick: onInstall, children: t('wb.store.updateTo', { version: item.version }) }), remove] });
46
+ if (state.state === 'modified')
47
+ return _jsxs("div", { className: "wbs-actions", children: [_jsx("span", { className: "wbs-state", title: t('wb.store.modifiedTitle'), children: t('wb.store.modified') }), _jsx(Button, { size: "sm", disabled: busy, onClick: onInstall, children: t('wb.store.replace') }), remove] });
48
+ return _jsxs("div", { className: "wbs-actions", children: [_jsx("span", { className: "wbs-state is-ok", children: state.version ? t('wb.store.installedVersion', { version: state.version }) : t('wb.store.installed') }), remove] });
49
+ }
50
+ export function StoreView(props) {
51
+ const { t, site, controller, notify } = props;
52
+ const ui = { ...DEFAULT_CONTROLS, ...props.controls };
53
+ const { Button, SearchField, Segmented, EmptyState, Badge } = ui;
54
+ const [view, setView] = useState(null);
55
+ const [loading, setLoading] = useState(false);
56
+ const [query, setQuery] = useState('');
57
+ const [kind, setKind] = useState('all');
58
+ const [category, setCategory] = useState('all');
59
+ const request = useSyncExternalStore(controller.subscribe, controller.current, controller.current);
60
+ const load = (refresh) => {
61
+ setLoading(true);
62
+ return props.load(refresh).then(setView).catch(error => notify(errorText(error), true)).finally(() => setLoading(false));
63
+ };
64
+ useEffect(() => { void load(false); }, []);
65
+ // Installs finish in the install screen; refresh what is installed afterwards.
66
+ useEffect(() => {
67
+ const again = () => void load(false);
68
+ const events = props.reloadOn ?? [];
69
+ for (const name of events)
70
+ window.addEventListener(name, again);
71
+ return () => { for (const name of events)
72
+ window.removeEventListener(name, again); };
73
+ }, [(props.reloadOn ?? []).join(' ')]);
74
+ useEffect(() => { if (request === null)
75
+ void load(false); }, [request === null]);
76
+ const items = view?.catalog?.items ?? [];
77
+ const context = { plugins: view?.plugins ?? {}, records: view?.records.items ?? {}, builtinThemes: props.builtinThemes, userThemes: props.userThemes, userIcons: props.userIcons };
78
+ const categories = useMemo(() => [...new Set(items.filter(item => kind === 'all' || item.kind === kind).map(item => item.category))].sort(), [items, kind]);
79
+ const shown = filterItems(items, query, kind, category);
80
+ const updates = items.filter(item => itemState(item, context).state === 'update');
81
+ const ago = (iso) => {
82
+ if (!iso)
83
+ return '';
84
+ const at = Date.parse(iso);
85
+ return Number.isFinite(at) ? props.relativeTime(Math.min(at, Date.now())) : '';
86
+ };
87
+ async function removeItem(item) {
88
+ if (!view)
89
+ return;
90
+ try {
91
+ if (!(await props.onRemove(item, view)))
92
+ return;
93
+ notify(t('wb.store.removed', { name: item.name }));
94
+ await load(false);
95
+ }
96
+ catch (error) {
97
+ notify(errorText(error), true);
98
+ }
99
+ }
100
+ const status = view?.error
101
+ ? _jsx("span", { className: "wbs-status is-warn", role: "status", children: view.catalog ? t('wb.store.offline', { when: ago(view.fetchedAt), error: errorText(view.error) }) : t('wb.store.unreachableShort') })
102
+ : view?.catalog ? _jsxs("span", { className: "wbs-status is-ok", role: "status", children: [_jsx("svg", { width: "13", height: "13", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M12 3l7 3v5c0 4.6-3 8.5-7 10-4-1.5-7-5.4-7-10V6zM8.5 12l2.5 2.5 4.5-5", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }), t('wb.store.verified', { when: ago(view.fetchedAt) })] }) : null;
103
+ return _jsxs("div", { className: "wbs", children: [_jsx("p", { className: "wbs-intro", children: t('wb.store.intro') }), _jsxs("div", { className: "wbs-toolbar", children: [_jsx(SearchField, { label: t('wb.store.search'), placeholder: t('wb.store.searchPlaceholder'), value: query, onChange: setQuery }), _jsx(Segmented, { label: t('wb.store.kind'), size: "sm", value: kind, onChange: next => { setKind(next); setCategory('all'); }, options: [{ value: 'all', label: t('wb.store.all') }, { value: 'theme', label: t('wb.store.themes') }, { value: 'plugin', label: t('wb.store.pluginsTab') }, ...(items.some(item => item.kind === 'icons') ? [{ value: 'icons', label: t('wb.store.icons') }] : []), ...(items.some(item => item.kind === 'strings') ? [{ value: 'strings', label: t('wb.store.strings') }] : []), ...(items.some(item => item.kind === 'builtin') ? [{ value: 'builtin', label: t('wb.store.builtinTab') }] : [])] }), _jsx(Button, { size: "sm", tone: "ghost", disabled: loading, onClick: () => void load(true), children: loading ? t('wb.store.checking') : t('wb.store.refresh') })] }), _jsxs("div", { className: "wbs-cats", role: "group", "aria-label": t('wb.store.categories'), children: [['all', ...categories].map(id => _jsx("button", { className: category === id ? 'is-on' : '', "aria-pressed": category === id, onClick: () => setCategory(id), children: id === 'all' ? t('wb.store.everything') : categoryLabel(id, t) }, id)), _jsx("span", { className: "wbs-cats-end" }), status] }), updates.length > 0 && _jsxs("div", { className: "wbs-updates", role: "status", children: [_jsx("strong", { children: t('wb.store.updates', { count: updates.length }) }), _jsx("span", { children: updates.map(item => item.name).join(', ') })] }), !view && loading && _jsx("div", { className: "wbs-grid", "aria-busy": "true", children: Array.from({ length: 6 }, (_, i) => _jsx("div", { className: "wbs-card is-skeleton" }, i)) }), view && !view.catalog && _jsxs(EmptyState, { icon: STORE_ICON, title: t('wb.store.unreachable'), action: _jsx(Button, { size: "sm", onClick: () => void load(true), children: t('wb.store.tryAgain') }), children: [view.error ? errorText(view.error).replace(/\.?$/, '.') : t('wb.store.noCatalog'), " ", t('wb.store.nothingChanged')] }), view?.catalog && shown.length === 0 && _jsx(EmptyState, { icon: STORE_ICON, title: t('wb.store.noMatch'), children: t('wb.store.noMatchHint') }), _jsx("div", { className: "wbs-grid", children: shown.map(item => {
104
+ const state = itemState(item, context);
105
+ return _jsxs("article", { className: `wbs-card is-${item.kind}`, children: [_jsx(Preview, { item: item }), _jsxs("div", { className: "wbs-card-body", children: [_jsxs("header", { children: [_jsx("h3", { children: item.name }), _jsx(Badge, { children: item.kind === 'theme' ? t('wb.store.theme') : item.kind === 'strings' ? t('wb.store.stringsItem') : item.kind === 'icons' ? t('wb.store.iconsItem') : item.kind === 'builtin' ? t('wb.store.builtinItem') : t('wb.store.plugin') })] }), _jsxs("p", { className: "wbs-meta", children: [item.author && `${t('wb.store.by', { author: item.author })} · `, "v", item.version, " \u00B7 ", item.kind === 'strings' && item.language ? item.language : categoryLabel(item.category, t), item.license ? ` · ${item.license}` : ''] }), _jsx("p", { className: "wbs-desc", children: item.description }), item.kind === 'plugin' && _jsx("ul", { className: "wbs-perms", "aria-label": t('wb.store.permissions'), children: permissionBadges(item.permissions, t, site).map(badge => _jsx("li", { className: `is-${badge.tone}`, title: badge.detail, children: badge.label }, badge.id)) }), _jsx(Action, { item: item, state: state, busy: request !== null, t: t, ui: ui, areas: props.areas, onArea: on => void props.areas?.set(item.id, on).catch(error => notify(errorText(error), true)), onInstall: () => void controller.requestStoreItem(item), onRemove: () => void removeItem(item), onUse: () => void props.onUse(item).then(() => notify(t('wb.store.themeNow', { name: item.name }))).catch(error => notify(errorText(error), true)) })] })] }, `${item.kind}:${item.id}`);
106
+ }) }), _jsx("p", { className: "wbs-foot", children: t('wb.store.foot') })] });
107
+ }
108
+ //# sourceMappingURL=StoreView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StoreView.js","sourceRoot":"","sources":["../../../../../shell/src/StoreView.tsx"],"names":[],"mappings":";AAAA,8FAA8F;AAC9F,gGAAgG;AAChG,gGAAgG;AAChG,oGAAoG;AACpG,gGAAgG;AAChG,wFAAwF;AAExF,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAkB,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAyE,MAAM,iBAAiB,CAAC;AAY5K,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAC9E,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,aAAa,IAAI,OAAO,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,YAAG,QAAQ,GAAU;IAC1I,WAAW,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,CACvD,gBAAO,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,QAAQ,gBAAa,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EACjG,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,eAAe,EAAE,CAAC;YAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC,CAAC,CAAC,GAAG;IAC/J,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CACjD,cAAK,SAAS,EAAC,cAAc,EAAC,IAAI,EAAC,YAAY,gBAAa,KAAK,YAC9D,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,iBAA2B,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAC,OAAO,kBAAe,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,YAAG,MAAM,CAAC,KAAK,IAArL,MAAM,CAAC,KAAK,CAAmL,CAAC,GAChO;IACR,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAChD,eAAK,SAAS,EAAC,UAAU,aAAE,IAAI,IAAI,6BAAiB,MAAM,YAAE,IAAI,GAAO,EAAC,2BAAS,KAAK,GAAU,EAAC,QAAQ,IAAI,sBAAI,QAAQ,GAAK,EAAE,MAAM,IAAO;IAC/I,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,eAAM,SAAS,EAAC,UAAU,YAAE,QAAQ,GAAQ;CACtE,CAAC;AAiCF,MAAM,UAAU,GAAG,cAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,iBAAa,MAAM,YAAC,eAAM,CAAC,EAAC,8GAA8G,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,EAAC,cAAc,EAAC,OAAO,GAAE,GAAM,CAAC;AAEhS,SAAS,OAAO,CAAC,EAAE,IAAI,EAAuB;IAC5C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM;QAAE,OAAO,cAAK,SAAS,EAAC,SAAS,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAC,EAAE,EAAC,OAAO,EAAC,MAAM,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;IACxI,2FAA2F;IAC3F,OAAO,cAAK,SAAS,EAAC,oBAAoB,EAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,iBAAc,MAAM,YACvG,CAAC,CAAC,CAAC,CAAC,8BAAE,eAAM,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAA,YAAG,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAA,YAAG,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,IAAG,CAAC,CAAC,CAAC,2BAAS,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAU,GAC/L,CAAC;AACT,CAAC;AAED,SAAS,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAkN;IACrS,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACtB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;QAC3C,MAAM,EAAE,GAAG,KAAK,IAAI,KAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvC,OAAO,eAAK,SAAS,EAAC,aAAa,aAAC,gBAAM,SAAS,EAAC,WAAW,aAAE,CAAC,CAAC,sBAAsB,CAAC,EAAE,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,IAAQ,EACnK,KAAK,IAAI,iBAAO,SAAS,EAAC,YAAY,EAAC,KAAK,EAAE,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,aAC1F,gBAAO,IAAI,EAAC,UAAU,EAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,EAAE,gBAAc,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAA,8BAAkB,MAAM,GAAE,IACnL,IACJ,CAAC;IACT,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,eAAK,SAAS,EAAC,aAAa,aAAC,eAAM,SAAS,EAAC,WAAW,YAAE,CAAC,CAAC,kBAAkB,CAAC,GAAQ,EAAA,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,KAAK,YAAG,CAAC,CAAC,cAAc,CAAC,GAAU,IAAM,CAAC;IAClM,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,cAAK,SAAS,EAAC,aAAa,YAAC,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,YAAG,CAAC,CAAC,kBAAkB,CAAC,GAAU,GAAM,CAAC;IAC/K,MAAM,MAAM,GAAG,MAAM;QACnB,CAAC,CAAC,8BAAE,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,YAAG,CAAC,CAAC,iBAAiB,CAAC,GAAU,EAAA,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,YAAG,CAAC,CAAC,eAAe,CAAC,GAAU,IAAG;QACrN,CAAC,CAAC,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,YAAG,CAAC,CAAC,iBAAiB,CAAC,GAAU,CAAC;IACnG,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,eAAK,SAAS,EAAC,aAAa,aAAC,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,YAAG,CAAC,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,GAAU,EAAC,MAAM,IAAO,CAAC;IAClN,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU;QAAE,OAAO,eAAK,SAAS,EAAC,aAAa,aAAC,eAAM,SAAS,EAAC,WAAW,EAAC,KAAK,EAAE,CAAC,CAAC,wBAAwB,CAAC,YAAG,CAAC,CAAC,mBAAmB,CAAC,GAAQ,EAAA,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,YAAG,CAAC,CAAC,kBAAkB,CAAC,GAAU,EAAC,MAAM,IAAO,CAAC;IACxQ,OAAO,eAAK,SAAS,EAAC,aAAa,aAAC,eAAM,SAAS,EAAC,iBAAiB,YAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAQ,EAAC,MAAM,IAAO,CAAC;AACpM,CAAC;AAED,MAAM,UAAU,SAAS,CAAQ,KAA4B;IAC3D,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAC9C,MAAM,EAAE,GAAkB,EAAE,GAAG,gBAAgB,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IACrE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACjE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA0B,IAAI,CAAC,CAAC;IAChE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAoB,KAAK,CAAC,CAAC;IAC3D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAS,KAAK,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,oBAAoB,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAEnG,MAAM,IAAI,GAAG,CAAC,OAAgB,EAAE,EAAE;QAChC,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3H,CAAC,CAAC;IACF,SAAS,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,+EAA+E;IAC/E,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,MAAM;YAAE,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChE,OAAO,GAAG,EAAE,GAAG,KAAK,MAAM,IAAI,IAAI,MAAM;YAAE,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvF,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvC,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,KAAK,IAAI;QAAE,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC;IAEjF,MAAM,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;IACnL,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAC5J,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;IAElF,MAAM,GAAG,GAAG,CAAC,GAAkB,EAAE,EAAE;QACjC,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,CAAC,CAAC;IAEF,KAAK,UAAU,UAAU,CAAC,IAAe;QACvC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC;YACH,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAAE,OAAO;YAChD,MAAM,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;IACrD,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK;QACxB,CAAC,CAAC,eAAM,SAAS,EAAC,oBAAoB,EAAC,IAAI,EAAC,QAAQ,YAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,GAAQ;QAChM,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,gBAAM,SAAS,EAAC,kBAAkB,EAAC,IAAI,EAAC,QAAQ,aAAC,cAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,iBAAa,MAAM,YAAC,eAAM,CAAC,EAAC,uEAAuE,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,GAAG,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,GAAE,GAAM,EAAC,CAAC,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAEpY,OAAO,eAAK,SAAS,EAAC,KAAK,aACzB,YAAG,SAAS,EAAC,WAAW,YAAE,CAAC,CAAC,gBAAgB,CAAC,GAAK,EAClD,eAAK,SAAS,EAAC,aAAa,aAC1B,KAAC,WAAW,IAAC,KAAK,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,4BAA4B,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,EAC3H,KAAC,SAAS,IAAC,KAAK,EAAE,CAAC,CAAC,eAAe,CAAC,EAAE,IAAI,EAAC,IAAI,EAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,qBAAqB,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAgB,EAAE,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EACxnB,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,YAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAU,IACjJ,EACN,eAAK,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,OAAO,gBAAa,CAAC,CAAC,qBAAqB,CAAC,aACxE,CAAC,KAAK,EAAE,GAAG,UAAU,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,SAAS,EAAE,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,kBAAgB,QAAQ,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,YAAG,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC,IAA7K,EAAE,CAAqL,CAAC,EACvO,eAAM,SAAS,EAAC,cAAc,GAAE,EAC/B,MAAM,IACH,EACL,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,eAAK,SAAS,EAAC,aAAa,EAAC,IAAI,EAAC,QAAQ,aAAC,2BAAS,CAAC,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,GAAU,EAAA,yBAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAQ,IAAM,EAClM,CAAC,IAAI,IAAI,OAAO,IAAI,cAAK,SAAS,EAAC,UAAU,eAAW,MAAM,YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAa,SAAS,EAAC,sBAAsB,IAAnC,CAAC,CAAoC,CAAC,GAAO,EAC3J,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,MAAC,UAAU,IAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,YAAG,CAAC,CAAC,mBAAmB,CAAC,GAAU,aAClL,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAG,CAAC,CAAC,yBAAyB,CAAC,IACtG,EACZ,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAC,UAAU,IAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,kBAAkB,CAAC,YAAG,CAAC,CAAC,sBAAsB,CAAC,GAAc,EAC5I,cAAK,SAAS,EAAC,UAAU,YACtB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;oBAChB,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACvC,OAAO,mBAAyC,SAAS,EAAE,eAAe,IAAI,CAAC,IAAI,EAAE,aACnF,KAAC,OAAO,IAAC,IAAI,EAAE,IAAI,GAAG,EACtB,eAAK,SAAS,EAAC,eAAe,aAC5B,6BACE,uBAAK,IAAI,CAAC,IAAI,GAAM,EACpB,KAAC,KAAK,cAAE,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAS,IAC1O,EACT,aAAG,SAAS,EAAC,UAAU,aAAE,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,OAAG,IAAI,CAAC,OAAO,cAAK,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAK,EACtP,YAAG,SAAS,EAAC,UAAU,YAAE,IAAI,CAAC,WAAW,GAAK,EAC7C,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,aAAI,SAAS,EAAC,WAAW,gBAAa,CAAC,CAAC,sBAAsB,CAAC,YACvF,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,aAAmB,SAAS,EAAE,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,YAAG,KAAK,CAAC,KAAK,IAA1E,KAAK,CAAC,EAAE,CAAwE,CAAC,GACjJ,EACL,KAAC,MAAM,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EACxF,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,EAC/F,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,EACvD,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,EACrC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IACnJ,KAjBa,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAkBpC,CAAC;gBACb,CAAC,CAAC,GACE,EACN,YAAG,SAAS,EAAC,UAAU,YAAE,CAAC,CAAC,eAAe,CAAC,GAAK,IAC5C,CAAC;AACT,CAAC","sourcesContent":["// The wayBetter Store view, shared by every wayBetter app: themes and plugins from the signed\n// catalog (native code verifies its Ed25519 signature, keeps this app's items, then checks each\n// download's sha256). Search, kinds, categories, cards with previews and permission badges, and\n// Install / Update / Remove. Installing always goes through the install screen (InstallHost), never\n// straight from here. Styles: `store.css` (framework `--wb-*` tokens). The app may pass its own\n// controls (buttons, search field, segmented control) so the view matches its settings.\n\nimport { useEffect, useMemo, useState, useSyncExternalStore, type ReactNode } from 'react';\nimport type { InstallController } from './installController.ts';\nimport type { StoreText } from './storeMessages.ts';\nimport { categoryLabel, errorText, filterItems, itemState, permissionBadges, type ItemState, type StoreCatalogView, type StoreItem, type StoreKind } from './storeModel.ts';\n\ntype ButtonProps = { children: ReactNode; onClick?(): void; tone?: 'plain' | 'primary' | 'ghost' | 'danger'; size?: 'sm' | 'md'; disabled?: boolean; title?: string };\ntype Option<T extends string> = { value: T; label: string };\nexport type StoreControls = {\n Button(props: ButtonProps): ReactNode;\n SearchField(props: { value: string; onChange(next: string): void; placeholder: string; label: string }): ReactNode;\n Segmented<T extends string>(props: { value: T; options: Array<Option<T>>; onChange(next: T): void; label: string; size?: 'sm' | 'md' }): ReactNode;\n EmptyState(props: { icon?: ReactNode; title: string; children?: ReactNode; action?: ReactNode }): ReactNode;\n Badge(props: { children: ReactNode }): ReactNode;\n};\n\nexport const DEFAULT_CONTROLS: StoreControls = {\n Button: ({ children, onClick, tone = 'plain', size = 'md', disabled, title }) =>\n <button type=\"button\" className={`wb-btn is-${tone} is-${size}`} disabled={disabled} title={title} onClick={onClick}>{children}</button>,\n SearchField: ({ value, onChange, placeholder, label }) =>\n <input className=\"wb-field\" type=\"search\" aria-label={label} placeholder={placeholder} value={value}\n onChange={event => onChange(event.target.value)} onKeyDown={event => { if (event.key === 'Escape' && value) { event.stopPropagation(); onChange(''); } }}/>,\n Segmented: ({ value, options, onChange, label }) =>\n <div className=\"wb-segmented\" role=\"radiogroup\" aria-label={label}>\n {options.map(option => <button key={option.value} type=\"button\" role=\"radio\" aria-checked={option.value === value} className={option.value === value ? 'is-on' : ''} onClick={() => onChange(option.value)}>{option.label}</button>)}\n </div>,\n EmptyState: ({ icon, title, children, action }) =>\n <div className=\"wb-empty\">{icon && <div aria-hidden=\"true\">{icon}</div>}<strong>{title}</strong>{children && <p>{children}</p>}{action}</div>,\n Badge: ({ children }) => <span className=\"wb-badge\">{children}</span>,\n};\n\nexport type StoreViewProps<Theme> = {\n t: StoreText;\n /** The site's name in messages (\"X\"). */\n site: string;\n /** `store_catalog` (the app passes `refresh => invoke('store_catalog', { refresh })`). */\n load(refresh: boolean): Promise<StoreCatalogView>;\n /** The install screen's controller: Install opens it; the list refreshes when it closes. */\n controller: InstallController<Theme>;\n /** Theme ids that ship with the app, and the owner's own theme ids now. */\n builtinThemes: readonly string[];\n userThemes: readonly string[];\n /** The owner's installed icon pack ids now (an icon pack the owner removed in Appearance shows as installable again). */\n userIcons?: readonly string[];\n /**\n * The app's area plugins, for items of kind `builtin`: whether the app has one by this id, whether\n * its switch is on, and turning it on or off. Without it (or for an id it does not have) a built-in\n * item only says it is built in.\n */\n areas?: { has(id: string): boolean; on(id: string): boolean; set(id: string, on: boolean): Promise<void> };\n /** Removes an installed item (plugin file, or the owner's copy of a store theme); false: nothing to remove. */\n onRemove(item: StoreItem, view: StoreCatalogView): Promise<boolean>;\n /** Makes a built-in theme the current one. */\n onUse(item: StoreItem): Promise<void>;\n notify(text: string, error?: boolean): void;\n /** \"3 minutes ago\" for a timestamp (the app's relative-time formatter). */\n relativeTime(at: number): string;\n /** Window events after which the list reloads (e.g. the app's \"plugins changed\"). */\n reloadOn?: readonly string[];\n controls?: Partial<StoreControls>;\n};\n\nconst STORE_ICON = <svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M4 9l1.5-5h13L20 9M4 9h16v11H4zM4 9a2.7 2.7 0 0 0 5.3 0 2.7 2.7 0 0 0 5.4 0 2.7 2.7 0 0 0 5.3 0M10 20v-5h4v5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinejoin=\"round\"/></svg>;\n\nfunction Preview({ item }: { item: StoreItem }) {\n const [broken, setBroken] = useState(false);\n const c = item.colors;\n if (item.preview && !broken) return <img className=\"wbs-img\" src={item.preview} alt=\"\" loading=\"lazy\" onError={() => setBroken(true)}/>;\n // Offline or not published yet: swatches from the signed catalog (themes) or a plain tile.\n return <div className=\"wbs-img wbs-swatch\" style={c ? { background: c.bg } : undefined} aria-hidden=\"true\">\n {c ? <><span style={{ background: c.surface ?? c.bg, borderColor: c.text }}/><i style={{ background: c.text }}/><b style={{ background: c.accent }}/></> : <strong>{item.name.slice(0, 1)}</strong>}\n </div>;\n}\n\nfunction Action({ item, state, busy, t, ui, areas, onInstall, onRemove, onUse, onArea }: { item: StoreItem; state: ItemState; busy: boolean; t: StoreText; ui: StoreControls; areas?: StoreViewProps<unknown>['areas']; onInstall(): void; onRemove(): void; onUse(): void; onArea(on: boolean): void }) {\n const { Button } = ui;\n const [asking, setAsking] = useState(false);\n if (state.state === 'area') {\n const known = areas?.has(item.id) ?? false;\n const on = known && areas!.on(item.id);\n return <div className=\"wbs-actions\"><span className=\"wbs-state\">{t('wb.store.builtinItem')}{known && ` · ${on ? t('wb.store.areaOn') : t('wb.store.areaOff')}`}</span>\n {known && <label className=\"wbs-switch\" title={t('wb.store.areaSwitch', { name: item.name })}>\n <input type=\"checkbox\" role=\"switch\" checked={on} aria-label={t('wb.store.areaSwitch', { name: item.name })} onChange={event => onArea(event.target.checked)}/><span aria-hidden=\"true\"/>\n </label>}\n </div>;\n }\n if (state.state === 'builtin') return <div className=\"wbs-actions\"><span className=\"wbs-state\">{t('wb.store.builtIn')}</span><Button size=\"sm\" onClick={onUse}>{t('wb.store.use')}</Button></div>;\n if (state.state === 'install') return <div className=\"wbs-actions\"><Button size=\"sm\" tone=\"primary\" disabled={busy} onClick={onInstall}>{t('wb.store.install')}</Button></div>;\n const remove = asking\n ? <><Button size=\"sm\" tone=\"danger\" onClick={() => { setAsking(false); onRemove(); }}>{t('wb.store.remove')}</Button><Button size=\"sm\" tone=\"ghost\" onClick={() => setAsking(false)}>{t('wb.store.keep')}</Button></>\n : <Button size=\"sm\" tone=\"ghost\" onClick={() => setAsking(true)}>{t('wb.store.remove')}</Button>;\n if (state.state === 'update') return <div className=\"wbs-actions\"><Button size=\"sm\" tone=\"primary\" disabled={busy} onClick={onInstall}>{t('wb.store.updateTo', { version: item.version })}</Button>{remove}</div>;\n if (state.state === 'modified') return <div className=\"wbs-actions\"><span className=\"wbs-state\" title={t('wb.store.modifiedTitle')}>{t('wb.store.modified')}</span><Button size=\"sm\" disabled={busy} onClick={onInstall}>{t('wb.store.replace')}</Button>{remove}</div>;\n return <div className=\"wbs-actions\"><span className=\"wbs-state is-ok\">{state.version ? t('wb.store.installedVersion', { version: state.version }) : t('wb.store.installed')}</span>{remove}</div>;\n}\n\nexport function StoreView<Theme>(props: StoreViewProps<Theme>) {\n const { t, site, controller, notify } = props;\n const ui: StoreControls = { ...DEFAULT_CONTROLS, ...props.controls };\n const { Button, SearchField, Segmented, EmptyState, Badge } = ui;\n const [view, setView] = useState<StoreCatalogView | null>(null);\n const [loading, setLoading] = useState(false);\n const [query, setQuery] = useState('');\n const [kind, setKind] = useState<StoreKind | 'all'>('all');\n const [category, setCategory] = useState<string>('all');\n const request = useSyncExternalStore(controller.subscribe, controller.current, controller.current);\n\n const load = (refresh: boolean) => {\n setLoading(true);\n return props.load(refresh).then(setView).catch(error => notify(errorText(error), true)).finally(() => setLoading(false));\n };\n useEffect(() => { void load(false); }, []);\n // Installs finish in the install screen; refresh what is installed afterwards.\n useEffect(() => {\n const again = () => void load(false);\n const events = props.reloadOn ?? [];\n for (const name of events) window.addEventListener(name, again);\n return () => { for (const name of events) window.removeEventListener(name, again); };\n }, [(props.reloadOn ?? []).join(' ')]);\n useEffect(() => { if (request === null) void load(false); }, [request === null]);\n\n const items = view?.catalog?.items ?? [];\n const context = { plugins: view?.plugins ?? {}, records: view?.records.items ?? {}, builtinThemes: props.builtinThemes, userThemes: props.userThemes, userIcons: props.userIcons };\n const categories = useMemo(() => [...new Set(items.filter(item => kind === 'all' || item.kind === kind).map(item => item.category))].sort(), [items, kind]);\n const shown = filterItems(items, query, kind, category);\n const updates = items.filter(item => itemState(item, context).state === 'update');\n\n const ago = (iso: string | null) => {\n if (!iso) return '';\n const at = Date.parse(iso);\n return Number.isFinite(at) ? props.relativeTime(Math.min(at, Date.now())) : '';\n };\n\n async function removeItem(item: StoreItem) {\n if (!view) return;\n try {\n if (!(await props.onRemove(item, view))) return;\n notify(t('wb.store.removed', { name: item.name }));\n await load(false);\n } catch (error) { notify(errorText(error), true); }\n }\n\n const status = view?.error\n ? <span className=\"wbs-status is-warn\" role=\"status\">{view.catalog ? t('wb.store.offline', { when: ago(view.fetchedAt), error: errorText(view.error) }) : t('wb.store.unreachableShort')}</span>\n : view?.catalog ? <span className=\"wbs-status is-ok\" role=\"status\"><svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 3l7 3v5c0 4.6-3 8.5-7 10-4-1.5-7-5.4-7-10V6zM8.5 12l2.5 2.5 4.5-5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>{t('wb.store.verified', { when: ago(view.fetchedAt) })}</span> : null;\n\n return <div className=\"wbs\">\n <p className=\"wbs-intro\">{t('wb.store.intro')}</p>\n <div className=\"wbs-toolbar\">\n <SearchField label={t('wb.store.search')} placeholder={t('wb.store.searchPlaceholder')} value={query} onChange={setQuery}/>\n <Segmented label={t('wb.store.kind')} size=\"sm\" value={kind} onChange={next => { setKind(next); setCategory('all'); }} options={[{ value: 'all', label: t('wb.store.all') }, { value: 'theme', label: t('wb.store.themes') }, { value: 'plugin', label: t('wb.store.pluginsTab') }, ...(items.some(item => item.kind === 'icons') ? [{ value: 'icons' as const, label: t('wb.store.icons') }] : []), ...(items.some(item => item.kind === 'strings') ? [{ value: 'strings' as const, label: t('wb.store.strings') }] : []), ...(items.some(item => item.kind === 'builtin') ? [{ value: 'builtin' as const, label: t('wb.store.builtinTab') }] : [])]}/>\n <Button size=\"sm\" tone=\"ghost\" disabled={loading} onClick={() => void load(true)}>{loading ? t('wb.store.checking') : t('wb.store.refresh')}</Button>\n </div>\n <div className=\"wbs-cats\" role=\"group\" aria-label={t('wb.store.categories')}>\n {['all', ...categories].map(id => <button key={id} className={category === id ? 'is-on' : ''} aria-pressed={category === id} onClick={() => setCategory(id)}>{id === 'all' ? t('wb.store.everything') : categoryLabel(id, t)}</button>)}\n <span className=\"wbs-cats-end\"/>\n {status}\n </div>\n {updates.length > 0 && <div className=\"wbs-updates\" role=\"status\"><strong>{t('wb.store.updates', { count: updates.length })}</strong><span>{updates.map(item => item.name).join(', ')}</span></div>}\n {!view && loading && <div className=\"wbs-grid\" aria-busy=\"true\">{Array.from({ length: 6 }, (_, i) => <div key={i} className=\"wbs-card is-skeleton\"/>)}</div>}\n {view && !view.catalog && <EmptyState icon={STORE_ICON} title={t('wb.store.unreachable')} action={<Button size=\"sm\" onClick={() => void load(true)}>{t('wb.store.tryAgain')}</Button>}>\n {view.error ? errorText(view.error).replace(/\\.?$/, '.') : t('wb.store.noCatalog')} {t('wb.store.nothingChanged')}\n </EmptyState>}\n {view?.catalog && shown.length === 0 && <EmptyState icon={STORE_ICON} title={t('wb.store.noMatch')}>{t('wb.store.noMatchHint')}</EmptyState>}\n <div className=\"wbs-grid\">\n {shown.map(item => {\n const state = itemState(item, context);\n return <article key={`${item.kind}:${item.id}`} className={`wbs-card is-${item.kind}`}>\n <Preview item={item}/>\n <div className=\"wbs-card-body\">\n <header>\n <h3>{item.name}</h3>\n <Badge>{item.kind === 'theme' ? t('wb.store.theme') : item.kind === 'strings' ? t('wb.store.stringsItem') : item.kind === 'icons' ? t('wb.store.iconsItem') : item.kind === 'builtin' ? t('wb.store.builtinItem') : t('wb.store.plugin')}</Badge>\n </header>\n <p className=\"wbs-meta\">{item.author && `${t('wb.store.by', { author: item.author })} · `}v{item.version} · {item.kind === 'strings' && item.language ? item.language : categoryLabel(item.category, t)}{item.license ? ` · ${item.license}` : ''}</p>\n <p className=\"wbs-desc\">{item.description}</p>\n {item.kind === 'plugin' && <ul className=\"wbs-perms\" aria-label={t('wb.store.permissions')}>\n {permissionBadges(item.permissions, t, site).map(badge => <li key={badge.id} className={`is-${badge.tone}`} title={badge.detail}>{badge.label}</li>)}\n </ul>}\n <Action item={item} state={state} busy={request !== null} t={t} ui={ui} areas={props.areas}\n onArea={on => void props.areas?.set(item.id, on).catch(error => notify(errorText(error), true))}\n onInstall={() => void controller.requestStoreItem(item)}\n onRemove={() => void removeItem(item)}\n onUse={() => void props.onUse(item).then(() => notify(t('wb.store.themeNow', { name: item.name }))).catch(error => notify(errorText(error), true))}/>\n </div>\n </article>;\n })}\n </div>\n <p className=\"wbs-foot\">{t('wb.store.foot')}</p>\n </div>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"addressModel.js","sourceRoot":"","sources":["../../../shell/src/addressModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure, unit-testable model for the address bar's breadcrumb chips.\n// No React, no Tauri: parseAddress(url, site) -> AddressModel | null. The site adapter turns its\n// own URLs into named chips; any other site gets host + path chips.\n\nexport type Segment = { label: string; href: string; mono?: boolean; quoted?: boolean };\nexport type AddressModel<Kind extends string = string> = {\n site: { kind: Kind | 'host'; label: string; href: string };\n segments: Segment[];\n insecure: boolean;\n};\n\nexport type AddressSite<Kind extends string = string> = {\n /** `site.kind` for the adapter's own pages, e.g. 'x'. */\n kind: Kind;\n /** Hostnames (lowercase) that are the site. */\n hosts: ReadonlySet<string>;\n /** The site chip's label. */\n label: string;\n /** Where the site chip links: its home page on this origin. */\n home(origin: string): string;\n /** Named chips for one of the site's URLs, or null to show no chips (an internal page). */\n segments(url: URL): Segment[] | null;\n};\n\nexport function truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max - 1)}…` : value;\n}\n\n/** Long numeric ids shown by their last 6 characters. */\nexport function last6(id: string): string {\n return `…${id.slice(-6)}`;\n}\n\nexport function titleCase(part: string): string {\n return part\n .split(/[-_]/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n}\n\n/** Generic chips: one per path segment, then `?…` for a query. */\nexport function hostSegments(url: URL): Segment[] {\n const origin = `${url.protocol}//${url.hostname}`;\n const parts = url.pathname.split('/').filter(Boolean);\n const segments: Segment[] = [];\n parts.forEach((part, index) => {\n const href = `${origin}/${parts.slice(0, index + 1).join('/')}`;\n segments.push({ label: truncate(decodeURIComponent(part), 24), href });\n });\n if (url.search) {\n segments.push({ label: '?…', href: `${origin}${url.pathname}${url.search}` });\n }\n return segments;\n}\n\nexport function parseAddress<Kind extends string>(url: string, site?: AddressSite<Kind>): AddressModel<Kind> | null {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return null;\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return null;\n }\n const insecure = parsed.protocol === 'http:';\n const hostname = parsed.hostname.replace(/^www\\./, '');\n\n if (site && site.hosts.has(parsed.hostname.toLowerCase())) {\n const origin = `${parsed.protocol}//${parsed.hostname}`;\n const segments = site.segments(parsed);\n if (segments === null) {\n return null;\n }\n const last = segments[segments.length - 1];\n if (last) (last as Segment & { current?: boolean }).current = true;\n return {\n site: { kind: site.kind, label: site.label, href: site.home(origin) },\n segments,\n insecure,\n };\n }\n\n return {\n site: { kind: 'host', label: hostname, href: `${parsed.protocol}//${parsed.hostname}` },\n segments: hostSegments(parsed),\n insecure,\n };\n}\n"]}
1
+ {"version":3,"file":"addressModel.js","sourceRoot":"","sources":["../../../../../shell/src/addressModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure, unit-testable model for the address bar's breadcrumb chips.\n// No React, no Tauri: parseAddress(url, site) -> AddressModel | null. The site adapter turns its\n// own URLs into named chips; any other site gets host + path chips.\n\nexport type Segment = { label: string; href: string; mono?: boolean; quoted?: boolean };\nexport type AddressModel<Kind extends string = string> = {\n site: { kind: Kind | 'host'; label: string; href: string };\n segments: Segment[];\n insecure: boolean;\n};\n\nexport type AddressSite<Kind extends string = string> = {\n /** `site.kind` for the adapter's own pages, e.g. 'x'. */\n kind: Kind;\n /** Hostnames (lowercase) that are the site. */\n hosts: ReadonlySet<string>;\n /** The site chip's label. */\n label: string;\n /** Where the site chip links: its home page on this origin. */\n home(origin: string): string;\n /** Named chips for one of the site's URLs, or null to show no chips (an internal page). */\n segments(url: URL): Segment[] | null;\n};\n\nexport function truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max - 1)}…` : value;\n}\n\n/** Long numeric ids shown by their last 6 characters. */\nexport function last6(id: string): string {\n return `…${id.slice(-6)}`;\n}\n\nexport function titleCase(part: string): string {\n return part\n .split(/[-_]/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n}\n\n/** Generic chips: one per path segment, then `?…` for a query. */\nexport function hostSegments(url: URL): Segment[] {\n const origin = `${url.protocol}//${url.hostname}`;\n const parts = url.pathname.split('/').filter(Boolean);\n const segments: Segment[] = [];\n parts.forEach((part, index) => {\n const href = `${origin}/${parts.slice(0, index + 1).join('/')}`;\n segments.push({ label: truncate(decodeURIComponent(part), 24), href });\n });\n if (url.search) {\n segments.push({ label: '?…', href: `${origin}${url.pathname}${url.search}` });\n }\n return segments;\n}\n\nexport function parseAddress<Kind extends string>(url: string, site?: AddressSite<Kind>): AddressModel<Kind> | null {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return null;\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return null;\n }\n const insecure = parsed.protocol === 'http:';\n const hostname = parsed.hostname.replace(/^www\\./, '');\n\n if (site && site.hosts.has(parsed.hostname.toLowerCase())) {\n const origin = `${parsed.protocol}//${parsed.hostname}`;\n const segments = site.segments(parsed);\n if (segments === null) {\n return null;\n }\n const last = segments[segments.length - 1];\n if (last) (last as Segment & { current?: boolean }).current = true;\n return {\n site: { kind: site.kind, label: site.label, href: site.home(origin) },\n segments,\n insecure,\n };\n }\n\n return {\n site: { kind: 'host', label: hostname, href: `${parsed.protocol}//${parsed.hostname}` },\n segments: hostSegments(parsed),\n insecure,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../shell/src/chrome.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,6FAA6F;AAC7F,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC","sourcesContent":["// Layout constants for the custom window chrome (titlebar + toolbar), in logical px. TITLEBAR_H and\n// RESIZE_BORDER must match `policy::TITLEBAR_H` / `policy::RESIZE_BORDER` in waybetter-host.\nexport const TITLEBAR_H = 44;\nexport const TOOLBAR_H = 50;\nexport const RESIZE_BORDER = 5;\n"]}
1
+ {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../../../shell/src/chrome.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,6FAA6F;AAC7F,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC","sourcesContent":["// Layout constants for the custom window chrome (titlebar + toolbar), in logical px. TITLEBAR_H and\n// RESIZE_BORDER must match `policy::TITLEBAR_H` / `policy::RESIZE_BORDER` in waybetter-host.\nexport const TITLEBAR_H = 44;\nexport const TOOLBAR_H = 50;\nexport const RESIZE_BORDER = 5;\n"]}
@@ -0,0 +1,117 @@
1
+ /** A column's content, named by the site adapter (e.g. `{ kind: 'search', value: 'from:me' }`). */
2
+ export type ColumnSource = {
3
+ kind: string;
4
+ value?: string;
5
+ };
6
+ /** Per-column filters, applied by the page runtime to the site's items (runtime/column.ts). */
7
+ export type ColumnFilters = {
8
+ /** Keywords (case-insensitive) or `/regex/flags`; a match hides the item. */
9
+ terms: string[];
10
+ hideReplies: boolean;
11
+ hideReposts: boolean;
12
+ mediaOnly: boolean;
13
+ };
14
+ export type DeckColumn = {
15
+ id: string;
16
+ /** The tab webview id this column runs in (`tab-<tabId>` natively). */
17
+ tabId: string;
18
+ /** Account profile of the column's webview. */
19
+ profile: string;
20
+ source: ColumnSource;
21
+ /** Preferred width in px; a page stretches its columns to fill the viewport. */
22
+ width: number;
23
+ /** Per-column feature flags over the global ones (allow-listed natively). */
24
+ flags: Record<string, boolean>;
25
+ filters: ColumnFilters;
26
+ /** Optional title the user gave the column. */
27
+ title?: string;
28
+ };
29
+ export type Deck = {
30
+ id: string;
31
+ name: string;
32
+ columns: DeckColumn[];
33
+ };
34
+ export declare const COLUMN_WIDTHS: readonly [320, 360, 400, 480];
35
+ export declare const DEFAULT_COLUMN_WIDTH = 360;
36
+ export declare const MIN_COLUMN_WIDTH = 280;
37
+ export declare const MAX_COLUMN_WIDTH = 640;
38
+ export declare const MAX_COLUMNS = 24;
39
+ export declare const MAX_DECKS = 12;
40
+ export declare const MAX_TERMS = 32;
41
+ export declare const MAX_TERM_CHARS = 200;
42
+ export declare const MAX_FLAGS = 16;
43
+ /** Visible columns per page before the memory guard warns. */
44
+ export declare const DEFAULT_MAX_VISIBLE = 6;
45
+ /** Gap between columns in px. */
46
+ export declare const COLUMN_GAP = 8;
47
+ export declare const emptyFilters: () => ColumnFilters;
48
+ export declare const validColumnId: (id: unknown) => id is string;
49
+ export declare function normalizeFilters(value: unknown): ColumnFilters;
50
+ export declare function normalizeFlags(value: unknown, allowed?: readonly string[]): Record<string, boolean>;
51
+ export declare const clampWidth: (width: unknown) => number;
52
+ export type NormalizeOptions = {
53
+ /** Source kinds the site adapter knows; others are dropped. */
54
+ kinds?: readonly string[];
55
+ /** Profile ids that exist; a column of a removed profile moves to `fallbackProfile`. */
56
+ profiles?: readonly string[];
57
+ fallbackProfile?: string;
58
+ /** Allow-listed per-column flags. */
59
+ flags?: readonly string[];
60
+ };
61
+ export declare function normalizeColumn(value: unknown, options?: NormalizeOptions): DeckColumn | null;
62
+ /** Anything from storage → a bounded deck (unique column and tab ids, at most MAX_COLUMNS). */
63
+ export declare function normalizeDeck(value: unknown, options?: NormalizeOptions): Deck | null;
64
+ export declare function normalizeDecks(value: unknown, options?: NormalizeOptions): Deck[];
65
+ export type PlacedColumn = {
66
+ id: string;
67
+ x: number;
68
+ width: number;
69
+ };
70
+ export type DeckLayout = {
71
+ /** The page shown (clamped into range). */
72
+ page: number;
73
+ pages: number;
74
+ visible: PlacedColumn[];
75
+ /** Columns on other pages: their webviews are hidden (and parked when the setting says so). */
76
+ parked: string[];
77
+ };
78
+ export type LayoutOptions = {
79
+ gap?: number;
80
+ maxVisible?: number;
81
+ };
82
+ /**
83
+ * Splits columns into pages of whole columns that fit `viewportW` (at least one per page). Pages
84
+ * are filled from the left; the last page is filled from the right end instead, so it is as full as
85
+ * the others (it may repeat columns of the page before) rather than one lone stretched column.
86
+ */
87
+ export declare function paginate(viewportW: number, columns: readonly Pick<DeckColumn, 'id' | 'width'>[], options?: LayoutOptions): string[][];
88
+ /** A page's columns stretch to fill the viewport, but never beyond this factor of their width. */
89
+ export declare const MAX_STRETCH = 2;
90
+ /**
91
+ * Where each column of `page` goes in a viewport `viewportW` px wide. The page's columns stretch
92
+ * evenly to fill the width (no ragged gap on the right); a lone column wider than the viewport
93
+ * is squeezed to it. Columns on other pages are `parked`.
94
+ */
95
+ export declare function layoutColumns(viewportW: number, columns: readonly Pick<DeckColumn, 'id' | 'width'>[], page: number, options?: LayoutOptions): DeckLayout;
96
+ /**
97
+ * The page that shows column `id`: `current` when it is on it already (so focusing a column never
98
+ * flips pages needlessly), else the first page that holds it (0 when it is unknown).
99
+ */
100
+ export declare function pageOf(viewportW: number, columns: readonly Pick<DeckColumn, 'id' | 'width'>[], id: string, options?: LayoutOptions, current?: number): number;
101
+ /** The column `delta` steps from `focused` (clamped at the ends; the first one when none is focused). */
102
+ export declare function moveFocus(columns: readonly Pick<DeckColumn, 'id'>[], focused: string | null | undefined, delta: number): string | null;
103
+ /** The URL a column loads: the adapter's `urlFor`, or null for a source it does not know. */
104
+ export declare function columnUrl(source: ColumnSource, urlFor: (source: ColumnSource) => string | null): string | null;
105
+ /** Unread count to show for a deck: the sum over its columns, capped like the native report (999). */
106
+ export declare const MAX_UNREAD = 999;
107
+ export declare function unreadTotal(unread: ReadonlyMap<string, number> | Record<string, number>, columns: readonly Pick<DeckColumn, 'tabId'>[]): number;
108
+ /** Moves column `id` by `delta` places (clamped); returns a new array. */
109
+ export declare function moveColumn<T extends {
110
+ id: string;
111
+ }>(columns: readonly T[], id: string, delta: number): T[];
112
+ /**
113
+ * A column still shows its source page (origin, path with the trailing slash ignored, and query);
114
+ * otherwise it navigated away (a post, a profile) and its header offers the way back. The page
115
+ * runtime uses the same rule (runtime/column.ts `isSourcePage`).
116
+ */
117
+ export declare function isSourcePage(href: string, source: string): boolean;