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,81 @@
1
+ // Styles for roots the runtime (or a plugin) creates: a constructable stylesheet adopted by the
2
+ // shadow root (or document) instead of a `<style>` element.
3
+ //
4
+ // Why: a site's Content-Security-Policy governs `<style>` elements (a `style-src` with a nonce or
5
+ // hash and no 'unsafe-inline' refuses them, in shadow roots too), but not constructed sheets
6
+ // (`new CSSStyleSheet()` + `replaceSync`), which are also parsed once instead of per element and
7
+ // stay adopted when their host is moved to another parent in the same document (a modal
8
+ // re-rendered by the site, a card lifted into the top layer). Engines without constructable
9
+ // sheets (or a root from another realm that refuses the sheet) get the `<style>` element.
10
+ const DOCUMENT_NODE = 9;
11
+ const isDocument = (root) => root.nodeType === DOCUMENT_NODE;
12
+ const documentOf = (root) => (isDocument(root) ? root : root.ownerDocument);
13
+ /** A sheet built in `root`'s own realm (a sheet from another document cannot be adopted). */
14
+ function construct(root, css) {
15
+ if (!root.adoptedStyleSheets)
16
+ return null;
17
+ const Sheet = documentOf(root).defaultView?.CSSStyleSheet;
18
+ if (typeof Sheet !== 'function' || typeof Sheet.prototype.replaceSync !== 'function')
19
+ return null;
20
+ try {
21
+ const sheet = new Sheet();
22
+ sheet.replaceSync(css);
23
+ return sheet;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ /**
30
+ * Styles `root` with `css`. Adopted sheets come after the root's `<style>` elements in the cascade
31
+ * (like a `<style>` appended last), and several calls stack in call order.
32
+ */
33
+ export function adoptStyles(root, css) {
34
+ const target = root;
35
+ const sheet = construct(target, css);
36
+ if (sheet) {
37
+ let on = false;
38
+ const attach = () => {
39
+ try {
40
+ target.adoptedStyleSheets = [...(target.adoptedStyleSheets ?? []), sheet];
41
+ on = true;
42
+ }
43
+ catch {
44
+ on = false;
45
+ }
46
+ };
47
+ attach();
48
+ if (on) {
49
+ return {
50
+ sheet,
51
+ adopted: true,
52
+ update(next) { try {
53
+ sheet.replaceSync(next);
54
+ }
55
+ catch { /* Keeps the last good rules. */ } },
56
+ remove() {
57
+ if (!on)
58
+ return;
59
+ on = false;
60
+ try {
61
+ target.adoptedStyleSheets = (target.adoptedStyleSheets ?? []).filter(item => item !== sheet);
62
+ }
63
+ catch { /* Root gone. */ }
64
+ },
65
+ };
66
+ }
67
+ }
68
+ // Fallback: a `<style>` element as the root's last child (a document: its <head>).
69
+ const doc = documentOf(target);
70
+ const style = doc.createElement('style');
71
+ style.textContent = css;
72
+ const parent = isDocument(target) ? (target.head ?? target.documentElement) : target;
73
+ parent.appendChild(style);
74
+ return {
75
+ get sheet() { return style.sheet; },
76
+ adopted: false,
77
+ update(next) { style.textContent = next; },
78
+ remove() { style.remove(); },
79
+ };
80
+ }
81
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../runtime/src/styles.ts"],"names":[],"mappings":"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","sourcesContent":["// Styles for roots the runtime (or a plugin) creates: a constructable stylesheet adopted by the\n// shadow root (or document) instead of a `<style>` element.\n//\n// Why: a site's Content-Security-Policy governs `<style>` elements (a `style-src` with a nonce or\n// hash and no 'unsafe-inline' refuses them, in shadow roots too), but not constructed sheets\n// (`new CSSStyleSheet()` + `replaceSync`), which are also parsed once instead of per element and\n// stay adopted when their host is moved to another parent in the same document (a modal\n// re-rendered by the site, a card lifted into the top layer). Engines without constructable\n// sheets (or a root from another realm that refuses the sheet) get the `<style>` element.\n\nexport type RootStyles = {\n /** The live sheet (insertRule/deleteRule work on it), or null when nothing could be parsed. */\n readonly sheet: CSSStyleSheet | null;\n /** True when the sheet is adopted (CSP-proof); false for the `<style>` fallback. */\n readonly adopted: boolean;\n /** Replaces the rules. */\n update(css: string): void;\n /** Takes the rules off the root (idempotent). */\n remove(): void;\n};\n\ntype StyleRoot = (ShadowRoot | Document) & { adoptedStyleSheets?: CSSStyleSheet[] };\n\nconst DOCUMENT_NODE = 9;\nconst isDocument = (root: StyleRoot): root is Document & StyleRoot => root.nodeType === DOCUMENT_NODE;\nconst documentOf = (root: StyleRoot): Document => (isDocument(root) ? root : (root as ShadowRoot).ownerDocument);\n\n/** A sheet built in `root`'s own realm (a sheet from another document cannot be adopted). */\nfunction construct(root: StyleRoot, css: string): CSSStyleSheet | null {\n if (!root.adoptedStyleSheets) return null;\n const Sheet = (documentOf(root).defaultView as (Window & typeof globalThis) | null)?.CSSStyleSheet;\n if (typeof Sheet !== 'function' || typeof Sheet.prototype.replaceSync !== 'function') return null;\n try {\n const sheet = new Sheet();\n sheet.replaceSync(css);\n return sheet;\n } catch {\n return null;\n }\n}\n\n/**\n * Styles `root` with `css`. Adopted sheets come after the root's `<style>` elements in the cascade\n * (like a `<style>` appended last), and several calls stack in call order.\n */\nexport function adoptStyles(root: ShadowRoot | Document, css: string): RootStyles {\n const target = root as StyleRoot;\n const sheet = construct(target, css);\n if (sheet) {\n let on = false;\n const attach = () => {\n try {\n target.adoptedStyleSheets = [...(target.adoptedStyleSheets ?? []), sheet];\n on = true;\n } catch { on = false; }\n };\n attach();\n if (on) {\n return {\n sheet,\n adopted: true,\n update(next) { try { sheet.replaceSync(next); } catch { /* Keeps the last good rules. */ } },\n remove() {\n if (!on) return;\n on = false;\n try { target.adoptedStyleSheets = (target.adoptedStyleSheets ?? []).filter(item => item !== sheet); } catch { /* Root gone. */ }\n },\n };\n }\n }\n // Fallback: a `<style>` element as the root's last child (a document: its <head>).\n const doc = documentOf(target);\n const style = doc.createElement('style');\n style.textContent = css;\n const parent: Node = isDocument(target) ? (target.head ?? target.documentElement) : target;\n parent.appendChild(style);\n return {\n get sheet() { return style.sheet; },\n adopted: false,\n update(next) { style.textContent = next; },\n remove() { style.remove(); },\n };\n}\n"]}
@@ -0,0 +1,15 @@
1
+ export type TextNetOptions = {
2
+ /** Exact original text -> replacement. A text that is not a key is left alone. */
3
+ map: ReadonlyMap<string, string>;
4
+ /** Attributes to cover (default `aria-label`, `placeholder`, `title`). */
5
+ attributes?: readonly string[];
6
+ /** Elements whose content is never touched (default: scripts, styles, editable text). */
7
+ skip?: string;
8
+ };
9
+ export type TextNetHandle = {
10
+ /** Text nodes and attributes currently replaced. */
11
+ count(): number;
12
+ /** Restores every node and attribute to the site's own value and stops observing. */
13
+ dispose(): void;
14
+ };
15
+ export declare function installTextNet(win: Window, options: TextNetOptions): TextNetHandle;
@@ -0,0 +1,131 @@
1
+ // A DOM safety net for strings a catalog hook cannot reach (published as
2
+ // `waybetter/runtime/textNet`): labels the server sends already worded, or text that is painted
3
+ // before the hook can act. It replaces exact texts in text nodes and in `aria-label`,
4
+ // `placeholder` and `title`, keeps the site's own value per node, and puts everything back when it
5
+ // is disposed. It is secondary to a catalog hook: it cannot see parameters or plural forms, and a
6
+ // rendered text only maps back to one key in a language without homonyms.
7
+ //
8
+ // Text is written through `nodeValue` / `setAttribute` (never `textContent` or HTML), so the site's
9
+ // framework keeps owning its nodes; when the site rewrites a node, the net looks at it again.
10
+ const DEFAULT_ATTRIBUTES = ['aria-label', 'placeholder', 'title'];
11
+ const DEFAULT_SKIP = 'script, style, noscript, textarea, [contenteditable=""], [contenteditable="true"]';
12
+ const TEXT_NODE = 3;
13
+ const ELEMENT_NODE = 1;
14
+ const SHOW_TEXT = 4;
15
+ export function installTextNet(win, options) {
16
+ const doc = win.document;
17
+ const attributes = options.attributes ?? DEFAULT_ATTRIBUTES;
18
+ const skip = options.skip ?? DEFAULT_SKIP;
19
+ const map = options.map;
20
+ /** The site's own value and ours, per text node. */
21
+ const texts = new WeakMap();
22
+ /** The same per element and attribute. */
23
+ const attrs = new WeakMap();
24
+ let count = 0;
25
+ let active = true;
26
+ const skipped = (element) => !!element && !!skip && !!element.closest(skip);
27
+ const text = (node) => {
28
+ const value = node.nodeValue ?? '';
29
+ const kept = texts.get(node);
30
+ if (kept) {
31
+ if (value === kept.applied)
32
+ return;
33
+ // The site wrote the node again: what it wrote is the new original.
34
+ texts.delete(node);
35
+ count -= 1;
36
+ }
37
+ const next = map.get(value);
38
+ if (next === undefined || next === value || skipped(node.parentElement))
39
+ return;
40
+ texts.set(node, { original: value, applied: next });
41
+ count += 1;
42
+ node.nodeValue = next;
43
+ };
44
+ const attribute = (element, name) => {
45
+ const value = element.getAttribute(name);
46
+ const kept = attrs.get(element)?.get(name);
47
+ if (kept) {
48
+ if (value === kept.applied)
49
+ return;
50
+ attrs.get(element).delete(name);
51
+ count -= 1;
52
+ }
53
+ if (value === null)
54
+ return;
55
+ const next = map.get(value);
56
+ if (next === undefined || next === value || skipped(element))
57
+ return;
58
+ let own = attrs.get(element);
59
+ if (!own)
60
+ attrs.set(element, own = new Map());
61
+ own.set(name, { original: value, applied: next });
62
+ count += 1;
63
+ element.setAttribute(name, next);
64
+ };
65
+ const sweep = (root) => {
66
+ if (root.nodeType === TEXT_NODE) {
67
+ text(root);
68
+ return;
69
+ }
70
+ if (root.nodeType !== ELEMENT_NODE)
71
+ return;
72
+ const element = root;
73
+ const walker = doc.createTreeWalker(element, SHOW_TEXT);
74
+ while (walker.nextNode())
75
+ text(walker.currentNode);
76
+ for (const name of attributes) {
77
+ if (element.hasAttribute(name))
78
+ attribute(element, name);
79
+ for (const child of element.querySelectorAll(`[${name}]`))
80
+ attribute(child, name);
81
+ }
82
+ };
83
+ const observer = new win.MutationObserver(records => {
84
+ if (!active)
85
+ return;
86
+ for (const record of records) {
87
+ if (record.type === 'characterData')
88
+ text(record.target);
89
+ else if (record.type === 'attributes') {
90
+ if (record.attributeName)
91
+ attribute(record.target, record.attributeName);
92
+ }
93
+ else
94
+ for (const node of record.addedNodes)
95
+ sweep(node);
96
+ }
97
+ });
98
+ if (map.size) {
99
+ if (doc.documentElement)
100
+ sweep(doc.documentElement);
101
+ observer.observe(doc, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: [...attributes] });
102
+ }
103
+ return {
104
+ count: () => count,
105
+ dispose() {
106
+ if (!active)
107
+ return;
108
+ active = false;
109
+ observer.disconnect();
110
+ if (!doc.documentElement)
111
+ return;
112
+ const walker = doc.createTreeWalker(doc.documentElement, SHOW_TEXT);
113
+ while (walker.nextNode()) {
114
+ const node = walker.currentNode;
115
+ const kept = texts.get(node);
116
+ if (kept && node.nodeValue === kept.applied)
117
+ node.nodeValue = kept.original;
118
+ texts.delete(node);
119
+ }
120
+ for (const name of attributes) {
121
+ for (const element of doc.querySelectorAll(`[${name}]`)) {
122
+ const kept = attrs.get(element)?.get(name);
123
+ if (kept && element.getAttribute(name) === kept.applied)
124
+ element.setAttribute(name, kept.original);
125
+ }
126
+ }
127
+ count = 0;
128
+ },
129
+ };
130
+ }
131
+ //# sourceMappingURL=textNet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textNet.js","sourceRoot":"","sources":["../../../runtime/src/textNet.ts"],"names":[],"mappings":"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","sourcesContent":["// A DOM safety net for strings a catalog hook cannot reach (published as\n// `waybetter/runtime/textNet`): labels the server sends already worded, or text that is painted\n// before the hook can act. It replaces exact texts in text nodes and in `aria-label`,\n// `placeholder` and `title`, keeps the site's own value per node, and puts everything back when it\n// is disposed. It is secondary to a catalog hook: it cannot see parameters or plural forms, and a\n// rendered text only maps back to one key in a language without homonyms.\n//\n// Text is written through `nodeValue` / `setAttribute` (never `textContent` or HTML), so the site's\n// framework keeps owning its nodes; when the site rewrites a node, the net looks at it again.\n\nexport type TextNetOptions = {\n /** Exact original text -> replacement. A text that is not a key is left alone. */\n map: ReadonlyMap<string, string>;\n /** Attributes to cover (default `aria-label`, `placeholder`, `title`). */\n attributes?: readonly string[];\n /** Elements whose content is never touched (default: scripts, styles, editable text). */\n skip?: string;\n};\n\nexport type TextNetHandle = {\n /** Text nodes and attributes currently replaced. */\n count(): number;\n /** Restores every node and attribute to the site's own value and stops observing. */\n dispose(): void;\n};\n\nconst DEFAULT_ATTRIBUTES = ['aria-label', 'placeholder', 'title'];\nconst DEFAULT_SKIP = 'script, style, noscript, textarea, [contenteditable=\"\"], [contenteditable=\"true\"]';\nconst TEXT_NODE = 3;\nconst ELEMENT_NODE = 1;\nconst SHOW_TEXT = 4;\n\nexport function installTextNet(win: Window, options: TextNetOptions): TextNetHandle {\n const doc = win.document;\n const attributes = options.attributes ?? DEFAULT_ATTRIBUTES;\n const skip = options.skip ?? DEFAULT_SKIP;\n const map = options.map;\n /** The site's own value and ours, per text node. */\n const texts = new WeakMap<Node, { original: string; applied: string }>();\n /** The same per element and attribute. */\n const attrs = new WeakMap<Element, Map<string, { original: string; applied: string }>>();\n let count = 0;\n let active = true;\n\n const skipped = (element: Element | null) => !!element && !!skip && !!element.closest(skip);\n\n const text = (node: Node) => {\n const value = node.nodeValue ?? '';\n const kept = texts.get(node);\n if (kept) {\n if (value === kept.applied) return;\n // The site wrote the node again: what it wrote is the new original.\n texts.delete(node);\n count -= 1;\n }\n const next = map.get(value);\n if (next === undefined || next === value || skipped(node.parentElement)) return;\n texts.set(node, { original: value, applied: next });\n count += 1;\n node.nodeValue = next;\n };\n\n const attribute = (element: Element, name: string) => {\n const value = element.getAttribute(name);\n const kept = attrs.get(element)?.get(name);\n if (kept) {\n if (value === kept.applied) return;\n attrs.get(element)!.delete(name);\n count -= 1;\n }\n if (value === null) return;\n const next = map.get(value);\n if (next === undefined || next === value || skipped(element)) return;\n let own = attrs.get(element);\n if (!own) attrs.set(element, own = new Map());\n own.set(name, { original: value, applied: next });\n count += 1;\n element.setAttribute(name, next);\n };\n\n const sweep = (root: Node) => {\n if (root.nodeType === TEXT_NODE) { text(root); return; }\n if (root.nodeType !== ELEMENT_NODE) return;\n const element = root as Element;\n const walker = doc.createTreeWalker(element, SHOW_TEXT);\n while (walker.nextNode()) text(walker.currentNode);\n for (const name of attributes) {\n if (element.hasAttribute(name)) attribute(element, name);\n for (const child of element.querySelectorAll(`[${name}]`)) attribute(child, name);\n }\n };\n\n const observer = new (win as unknown as { MutationObserver: typeof MutationObserver }).MutationObserver(records => {\n if (!active) return;\n for (const record of records) {\n if (record.type === 'characterData') text(record.target);\n else if (record.type === 'attributes') { if (record.attributeName) attribute(record.target as Element, record.attributeName); }\n else for (const node of record.addedNodes) sweep(node);\n }\n });\n if (map.size) {\n if (doc.documentElement) sweep(doc.documentElement);\n observer.observe(doc, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: [...attributes] });\n }\n\n return {\n count: () => count,\n dispose() {\n if (!active) return;\n active = false;\n observer.disconnect();\n if (!doc.documentElement) return;\n const walker = doc.createTreeWalker(doc.documentElement, SHOW_TEXT);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const kept = texts.get(node);\n if (kept && node.nodeValue === kept.applied) node.nodeValue = kept.original;\n texts.delete(node);\n }\n for (const name of attributes) {\n for (const element of doc.querySelectorAll(`[${name}]`)) {\n const kept = attrs.get(element)?.get(name);\n if (kept && element.getAttribute(name) === kept.applied) element.setAttribute(name, kept.original);\n }\n }\n count = 0;\n },\n };\n}\n"]}
@@ -0,0 +1,121 @@
1
+ export type ThemeMode = 'light' | 'dark';
2
+ /** Every color role a theme has, resolved (derived roles filled in, legibility enforced). */
3
+ export type ResolvedColors = {
4
+ /** The main surface behind content (the site's column background). */
5
+ bg: string;
6
+ /** A raised surface (cards, inputs). */
7
+ surface: string;
8
+ /** Hover / selected surface, one step above `surface`. */
9
+ elevated: string;
10
+ border: string;
11
+ text: string;
12
+ /** Secondary text. */
13
+ muted: string;
14
+ accent: string;
15
+ /** Readable text on `accent`. */
16
+ onAccent: string;
17
+ /** The site's filled primary button and its label. */
18
+ inverse: string;
19
+ onInverse: string;
20
+ /** The canvas behind the columns (equals `bg` unless the theme paints a page). */
21
+ page: string;
22
+ };
23
+ export type ResolvedTheme = {
24
+ /** Theme id (`x` for the site's own look). */
25
+ id: string;
26
+ name: string;
27
+ mode: ThemeMode;
28
+ /** True when the site's own colors are shown (no theme colors). */
29
+ siteDefault: boolean;
30
+ colors: ResolvedColors;
31
+ /** Card / dialog corner radius in px. */
32
+ radius: number;
33
+ /** Button corner radius in px (9999 = pill). */
34
+ buttonRadius: number;
35
+ /** CSS `font-family` stack of the interface. */
36
+ font: string;
37
+ /**
38
+ * Which font goes where: every role resolved (a role that inherits carries the stack it inherits).
39
+ * Always present after `normalizeResolved`; adapters without font roles may leave it out.
40
+ */
41
+ fonts?: ResolvedFonts;
42
+ };
43
+ /**
44
+ * Font roles: `interface` (the site's UI), `post` (main content text), `heading` (names and
45
+ * headings), `numbers` (counts), `mono` (code), `chrome` (the app's own window: tabs, address bar,
46
+ * panel) and `dialog` (plugin dialogs and toasts from the UI kit).
47
+ */
48
+ export declare const FONT_ROLE_NAMES: readonly ["interface", "post", "heading", "numbers", "mono", "chrome", "dialog"];
49
+ export type FontRoleName = typeof FONT_ROLE_NAMES[number];
50
+ export type ResolvedFont = {
51
+ /** CSS `font-family` stack. */
52
+ stack: string;
53
+ /** Weight the role asks for, or null to keep the text's own. */
54
+ weight: number | null;
55
+ /** Size relative to the site's (1 = unchanged). */
56
+ size: number;
57
+ /** Letter spacing in em, or null to keep the text's own. */
58
+ tracking: number | null;
59
+ /** Tabular (fixed-width) figures. */
60
+ tabular: boolean;
61
+ /** True when the role inherits its family from another role or the site. */
62
+ inherited: boolean;
63
+ };
64
+ export type ResolvedFonts = Record<FontRoleName, ResolvedFont>;
65
+ /** Monospaced families, in order: what a `mono` role that inherits (or a source without fonts) gets. */
66
+ export declare const MONO_FAMILIES: string[];
67
+ export declare const MONO_FONT: string;
68
+ /** What a site adapter provides: the current resolved theme and change notifications. */
69
+ export type ThemeSource = {
70
+ current(): ResolvedTheme | null;
71
+ onChange(listener: () => void): () => void;
72
+ };
73
+ export type ThemeApi = {
74
+ /** The active theme, resolved. A frozen snapshot: call again after `onChange`. */
75
+ current(): ResolvedTheme;
76
+ /** Calls `listener(theme)` after the theme (or the site's light/dark mode) changes. Returns a dispose. */
77
+ onChange(listener: (theme: ResolvedTheme) => void): () => void;
78
+ };
79
+ /** Where the theme file JSON Schema is published with the `waybetter` npm package (`"$schema"` in theme files). */
80
+ export declare const THEME_SCHEMA_URL = "https://unpkg.com/waybetter/theme.schema.json";
81
+ export declare const FALLBACK_FONT = "system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif";
82
+ /** `#rrggbb` → [r, g, b]. */
83
+ export declare function hexToRgb(hex: string): [number, number, number];
84
+ /** WCAG relative luminance of `#rrggbb`. */
85
+ export declare function relativeLuminance(hex: string): number;
86
+ /** WCAG contrast ratio of two `#rrggbb` colors (1–21). */
87
+ export declare function contrastRatio(a: string, b: string): number;
88
+ /** White when it reaches 4.5:1 on `hex`, otherwise whichever of black and white reads better. */
89
+ export declare function readableOn(hex: string): string;
90
+ /** `rgb(…)` / `rgba(…)` / `#rgb` / `#rrggbb` to `#rrggbb`; null when it is transparent or unparsable. */
91
+ export declare function toHex(value: string | null | undefined): string | null;
92
+ /** `a` moved toward `b` by `t` (0–1), per channel. */
93
+ export declare function mix(a: string, b: string, t: number): string;
94
+ /**
95
+ * A complete resolved theme from a few page colors (background, text, accent), for sites or moments
96
+ * without a theme engine. Surfaces, border and muted text sit between background and text.
97
+ */
98
+ export declare function themeFromColors(bg: string, text: string, accent: string, extra?: Partial<Omit<ResolvedTheme, 'colors'>>): ResolvedTheme;
99
+ /** The page's own colors (computed body background and text), used when no theme source exists. */
100
+ export declare function readPageTheme(win: Window, accent?: string): ResolvedTheme;
101
+ /** Fills in any role a source left out and freezes the result. */
102
+ export declare function normalizeResolved(theme: ResolvedTheme): ResolvedTheme;
103
+ /** Every role filled in: missing roles inherit the interface font (`mono` a monospaced stack). */
104
+ export declare function normalizeFonts(fonts: Partial<Record<FontRoleName, Partial<ResolvedFont>>> | undefined, font: string): ResolvedFonts;
105
+ /**
106
+ * The theme as CSS custom properties: `--wb-bg`, `--wb-surface`, `--wb-elevated`, `--wb-border`,
107
+ * `--wb-text`, `--wb-muted`, `--wb-accent`, `--wb-on-accent`, `--wb-inverse`, `--wb-on-inverse`,
108
+ * `--wb-page`, `--wb-radius`, `--wb-button-radius`, `--wb-font`, `--wb-mode` (`light`/`dark`), and
109
+ * one stack per font role: `--wb-font-interface`, `--wb-font-post`, `--wb-font-heading`,
110
+ * `--wb-font-numbers`, `--wb-font-mono`, `--wb-font-chrome`, `--wb-font-dialog`.
111
+ */
112
+ export declare function themeVars(theme: ResolvedTheme): Record<string, string>;
113
+ /** `:root{--wb-…}` for a `<style>` element (values come from a resolved theme, never raw input). */
114
+ export declare function themeVarsCss(theme: ResolvedTheme, selector?: string): string;
115
+ /** A stable key: equal keys mean nothing visible changed. */
116
+ export declare const themeKey: (theme: ResolvedTheme) => string;
117
+ /**
118
+ * `api.theme`. With a site `source` it reports the site's resolved theme (falling back to the page's
119
+ * computed colors while the source has none); without one, only the page's colors.
120
+ */
121
+ export declare function createThemeApi(win: Window, source?: ThemeSource, fallbackAccent?: string): ThemeApi;
@@ -0,0 +1,220 @@
1
+ // `api.theme`: the active theme as plain values, so plugins (and the UI kit) can match it. The site
2
+ // adapter resolves its own theme document into a `ResolvedTheme` (colors by role, radius, font,
3
+ // mode) and says when it changes; this module turns that into `--wb-*` CSS custom properties and
4
+ // a small `current()` / `onChange()` API. When the site keeps its own colors (no theme, e.g. X
5
+ // default), the adapter still resolves the site's palette, so plugins always see real colors.
6
+ //
7
+ // Pure except `createThemeApi` / `readPageTheme`, which read the page.
8
+ /**
9
+ * Font roles: `interface` (the site's UI), `post` (main content text), `heading` (names and
10
+ * headings), `numbers` (counts), `mono` (code), `chrome` (the app's own window: tabs, address bar,
11
+ * panel) and `dialog` (plugin dialogs and toasts from the UI kit).
12
+ */
13
+ export const FONT_ROLE_NAMES = ['interface', 'post', 'heading', 'numbers', 'mono', 'chrome', 'dialog'];
14
+ /** Monospaced families, in order: what a `mono` role that inherits (or a source without fonts) gets. */
15
+ export const MONO_FAMILIES = ['Cascadia Mono', 'SF Mono', 'Consolas', 'Menlo', 'ui-monospace', 'monospace'];
16
+ export const MONO_FONT = MONO_FAMILIES.map(name => (/^(ui-monospace|monospace)$/.test(name) ? name : `"${name}"`)).join(', ');
17
+ /** Where the theme file JSON Schema is published with the `waybetter` npm package (`"$schema"` in theme files). */
18
+ export const THEME_SCHEMA_URL = 'https://unpkg.com/waybetter/theme.schema.json';
19
+ export const FALLBACK_FONT = 'system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
20
+ const HEX = /^#[0-9a-f]{6}$/i;
21
+ /** `#rrggbb` → [r, g, b]. */
22
+ export function hexToRgb(hex) {
23
+ const n = parseInt(hex.slice(1, 7), 16);
24
+ return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
25
+ }
26
+ /** WCAG relative luminance of `#rrggbb`. */
27
+ export function relativeLuminance(hex) {
28
+ const [r, g, b] = hexToRgb(hex).map(v => { const c = v / 255; return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4; });
29
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
30
+ }
31
+ /** WCAG contrast ratio of two `#rrggbb` colors (1–21). */
32
+ export function contrastRatio(a, b) {
33
+ const [x, y] = [relativeLuminance(a), relativeLuminance(b)].sort((m, n) => n - m);
34
+ return (x + 0.05) / (y + 0.05);
35
+ }
36
+ /** White when it reaches 4.5:1 on `hex`, otherwise whichever of black and white reads better. */
37
+ export function readableOn(hex) {
38
+ const white = contrastRatio(hex, '#ffffff');
39
+ return white >= 4.5 || white >= contrastRatio(hex, '#000000') ? '#ffffff' : '#000000';
40
+ }
41
+ /** `rgb(…)` / `rgba(…)` / `#rgb` / `#rrggbb` to `#rrggbb`; null when it is transparent or unparsable. */
42
+ export function toHex(value) {
43
+ const text = (value ?? '').trim();
44
+ if (HEX.test(text))
45
+ return text.toLowerCase();
46
+ const short = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(text);
47
+ if (short)
48
+ return `#${short[1]}${short[1]}${short[2]}${short[2]}${short[3]}${short[3]}`.toLowerCase();
49
+ const match = /^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)(?:\s*[,/]\s*([\d.]+%?))?\s*\)$/.exec(text);
50
+ if (!match)
51
+ return null;
52
+ if (match[4] !== undefined && parseFloat(match[4]) === 0)
53
+ return null;
54
+ return `#${[match[1], match[2], match[3]].map(v => Math.min(255, Number(v)).toString(16).padStart(2, '0')).join('')}`;
55
+ }
56
+ /** `a` moved toward `b` by `t` (0–1), per channel. */
57
+ export function mix(a, b, t) {
58
+ const [x, y] = [hexToRgb(a), hexToRgb(b)];
59
+ return `#${x.map((v, i) => Math.round(v + (y[i] - v) * t).toString(16).padStart(2, '0')).join('')}`;
60
+ }
61
+ /**
62
+ * A complete resolved theme from a few page colors (background, text, accent), for sites or moments
63
+ * without a theme engine. Surfaces, border and muted text sit between background and text.
64
+ */
65
+ export function themeFromColors(bg, text, accent, extra = {}) {
66
+ const dark = relativeLuminance(bg) < relativeLuminance(text);
67
+ const colors = {
68
+ bg, text, accent,
69
+ surface: mix(bg, text, dark ? 0.05 : 0.03),
70
+ elevated: mix(bg, text, dark ? 0.1 : 0.07),
71
+ border: mix(bg, text, dark ? 0.2 : 0.15),
72
+ muted: mix(bg, text, 0.62),
73
+ onAccent: readableOn(accent),
74
+ inverse: text,
75
+ onInverse: bg,
76
+ page: bg,
77
+ };
78
+ return { id: 'page', name: 'Page colors', mode: dark ? 'dark' : 'light', siteDefault: true, radius: 16, buttonRadius: 9999, font: FALLBACK_FONT, ...extra, colors };
79
+ }
80
+ /** The page's own colors (computed body background and text), used when no theme source exists. */
81
+ export function readPageTheme(win, accent = '#1d9bf0') {
82
+ let bg = null;
83
+ let text = null;
84
+ let font = '';
85
+ try {
86
+ const body = win.document.body;
87
+ if (body) {
88
+ const style = win.getComputedStyle(body);
89
+ bg = toHex(style.backgroundColor) ?? toHex(win.getComputedStyle(win.document.documentElement).backgroundColor);
90
+ text = toHex(style.color);
91
+ font = style.fontFamily;
92
+ }
93
+ }
94
+ catch { /* No layout yet. */ }
95
+ const dark = !!win.matchMedia?.('(prefers-color-scheme: dark)').matches;
96
+ bg ??= dark ? '#000000' : '#ffffff';
97
+ text ??= relativeLuminance(bg) < 0.2 ? '#e7e9ea' : '#0f1419';
98
+ if (contrastRatio(bg, text) < 3)
99
+ text = readableOn(bg);
100
+ return themeFromColors(bg, text, accent, font ? { font } : {});
101
+ }
102
+ /** Fills in any role a source left out and freezes the result. */
103
+ export function normalizeResolved(theme) {
104
+ const bg = toHex(theme.colors?.bg) ?? '#ffffff';
105
+ let text = toHex(theme.colors?.text) ?? readableOn(bg);
106
+ if (contrastRatio(bg, text) < 3)
107
+ text = readableOn(bg);
108
+ const base = themeFromColors(bg, text, toHex(theme.colors?.accent) ?? '#1d9bf0');
109
+ const colors = { ...base.colors };
110
+ for (const key of Object.keys(colors)) {
111
+ const value = theme.colors?.[key];
112
+ if (key !== 'bg' && key !== 'text' && typeof value === 'string' && HEX.test(value))
113
+ colors[key] = value.toLowerCase();
114
+ }
115
+ if (!HEX.test(theme.colors.onAccent ?? ''))
116
+ colors.onAccent = readableOn(colors.accent);
117
+ const radius = Number.isFinite(theme.radius) ? Math.max(0, Math.min(28, theme.radius)) : 16;
118
+ const buttonRadius = Number.isFinite(theme.buttonRadius) ? Math.max(0, theme.buttonRadius) : 9999;
119
+ const font = theme.font || FALLBACK_FONT;
120
+ return Object.freeze({
121
+ id: String(theme.id || 'theme'), name: String(theme.name || ''), mode: theme.mode === 'light' ? 'light' : 'dark',
122
+ siteDefault: !!theme.siteDefault, radius, buttonRadius, font,
123
+ colors: Object.freeze(colors),
124
+ fonts: normalizeFonts(theme.fonts, font),
125
+ });
126
+ }
127
+ const cssSafe = (value) => value.replace(/[;{}<>\\]/g, '');
128
+ const finite = (value, min, max) => typeof value === 'number' && Number.isFinite(value) ? Math.min(max, Math.max(min, value)) : null;
129
+ /** Every role filled in: missing roles inherit the interface font (`mono` a monospaced stack). */
130
+ export function normalizeFonts(fonts, font) {
131
+ const out = {};
132
+ const base = fonts?.interface?.stack ? cssSafe(fonts.interface.stack) : font;
133
+ for (const role of FONT_ROLE_NAMES) {
134
+ const given = fonts?.[role];
135
+ const stack = given?.stack ? cssSafe(given.stack) : role === 'mono' ? MONO_FONT : base;
136
+ out[role] = Object.freeze({
137
+ stack,
138
+ weight: finite(given?.weight, 100, 900),
139
+ size: finite(given?.size, 0.5, 2) ?? 1,
140
+ tracking: finite(given?.tracking, -0.1, 0.2),
141
+ tabular: !!given?.tabular,
142
+ inherited: given ? !!given.inherited : true,
143
+ });
144
+ }
145
+ return Object.freeze(out);
146
+ }
147
+ const VAR_NAMES = {
148
+ bg: '--wb-bg', surface: '--wb-surface', elevated: '--wb-elevated', border: '--wb-border', text: '--wb-text', muted: '--wb-muted',
149
+ accent: '--wb-accent', onAccent: '--wb-on-accent', inverse: '--wb-inverse', onInverse: '--wb-on-inverse', page: '--wb-page',
150
+ };
151
+ /**
152
+ * The theme as CSS custom properties: `--wb-bg`, `--wb-surface`, `--wb-elevated`, `--wb-border`,
153
+ * `--wb-text`, `--wb-muted`, `--wb-accent`, `--wb-on-accent`, `--wb-inverse`, `--wb-on-inverse`,
154
+ * `--wb-page`, `--wb-radius`, `--wb-button-radius`, `--wb-font`, `--wb-mode` (`light`/`dark`), and
155
+ * one stack per font role: `--wb-font-interface`, `--wb-font-post`, `--wb-font-heading`,
156
+ * `--wb-font-numbers`, `--wb-font-mono`, `--wb-font-chrome`, `--wb-font-dialog`.
157
+ */
158
+ export function themeVars(theme) {
159
+ const vars = {};
160
+ for (const [key, name] of Object.entries(VAR_NAMES))
161
+ vars[name] = theme.colors[key];
162
+ vars['--wb-radius'] = `${theme.radius}px`;
163
+ vars['--wb-button-radius'] = `${theme.buttonRadius}px`;
164
+ vars['--wb-font'] = theme.font;
165
+ const fonts = theme.fonts ?? normalizeFonts(undefined, theme.font);
166
+ for (const role of FONT_ROLE_NAMES)
167
+ vars[`--wb-font-${role}`] = fonts[role].stack;
168
+ vars['--wb-mode'] = theme.mode;
169
+ return vars;
170
+ }
171
+ /** `:root{--wb-…}` for a `<style>` element (values come from a resolved theme, never raw input). */
172
+ export function themeVarsCss(theme, selector = ':root') {
173
+ const safe = (value) => value.replace(/[;{}<>\\]/g, '');
174
+ return `${selector}{${Object.entries(themeVars(theme)).map(([name, value]) => `${name}:${safe(value)}`).join(';')}}`;
175
+ }
176
+ /** A stable key: equal keys mean nothing visible changed. */
177
+ export const themeKey = (theme) => JSON.stringify(theme);
178
+ /**
179
+ * `api.theme`. With a site `source` it reports the site's resolved theme (falling back to the page's
180
+ * computed colors while the source has none); without one, only the page's colors.
181
+ */
182
+ export function createThemeApi(win, source, fallbackAccent) {
183
+ const report = (error) => console.error('[wayBetter] theme listener failed', error);
184
+ const current = () => {
185
+ let resolved = null;
186
+ try {
187
+ resolved = source?.current() ?? null;
188
+ }
189
+ catch (error) {
190
+ report(error);
191
+ }
192
+ return normalizeResolved(resolved ?? readPageTheme(win, fallbackAccent));
193
+ };
194
+ return Object.freeze({
195
+ current,
196
+ onChange(listener) {
197
+ if (!source)
198
+ return () => { };
199
+ let last = '';
200
+ try {
201
+ last = themeKey(current());
202
+ }
203
+ catch { /* Reported by current(). */ }
204
+ return source.onChange(() => {
205
+ const next = current();
206
+ const key = themeKey(next);
207
+ if (key === last)
208
+ return;
209
+ last = key;
210
+ try {
211
+ listener(next);
212
+ }
213
+ catch (error) {
214
+ report(error);
215
+ }
216
+ });
217
+ },
218
+ });
219
+ }
220
+ //# sourceMappingURL=themeApi.js.map