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
@@ -5,12 +5,52 @@
5
5
  // text, a named attribute) and they run together in the next frame: layout readers first, then DOM
6
6
  // writers, so a reader never forces a synchronous layout behind another feature's write. Features
7
7
  // marked `offOnHeavy` do not run on the site's heavy pages (see `configureDomHub`), e.g. a WASM chat.
8
- const config = { label: 'wayBetter', heavyPath: null };
8
+ //
9
+ // A site that renders a part of itself inside an open shadow root (X's chat, since 2026-10-01, in
10
+ // the shadow root of its embed host) names the host in `shadowHosts`: the hub's one observer then
11
+ // observes each such root too (picked up when the host appears or gets its root, dropped with the
12
+ // observer), selector observers look inside, and `domRoots` gives features the roots to query.
13
+ const config = { label: 'wayBetter', heavyPath: null, shadowHosts: [] };
9
14
  const hubs = new WeakMap();
10
15
  /** Set once by the site adapter, before features register. */
11
16
  export function configureDomHub(next) {
12
17
  Object.assign(config, next);
13
18
  }
19
+ /** The page's roots: the document, then the open shadow roots of the configured hosts now in it. */
20
+ export function domRoots(win) {
21
+ const doc = win.document;
22
+ const out = [doc];
23
+ if (!config.shadowHosts.length)
24
+ return out;
25
+ let hosts = [];
26
+ try {
27
+ hosts = Array.from(doc.querySelectorAll(config.shadowHosts.join(',')));
28
+ }
29
+ catch {
30
+ return out;
31
+ }
32
+ for (const host of hosts) {
33
+ const root = host.shadowRoot;
34
+ if (root)
35
+ out.push(root);
36
+ }
37
+ return out;
38
+ }
39
+ /** The site names hosts whose shadow roots are part of the page. */
40
+ export function hasShadowHosts() {
41
+ return config.shadowHosts.length > 0;
42
+ }
43
+ /** A configured host is in the page but has no open shadow root yet (it may attach one later). */
44
+ function hostWithoutRoot(doc) {
45
+ if (!config.shadowHosts.length)
46
+ return false;
47
+ try {
48
+ return Array.from(doc.querySelectorAll(config.shadowHosts.join(','))).some(host => !host.shadowRoot);
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
14
54
  export function isHeavyPath(pathname) {
15
55
  return !!config.heavyPath && config.heavyPath.test(pathname);
16
56
  }
@@ -22,6 +62,34 @@ function hubFor(win) {
22
62
  let frameRequested = false;
23
63
  let observer = null;
24
64
  let observing = '';
65
+ let options = { childList: true, subtree: true };
66
+ // Shadow roots the observer already observes (with the current options).
67
+ let roots = new WeakSet();
68
+ let retries = 0;
69
+ let retry = null;
70
+ /** Observes configured shadow roots that are new; a new one marks every feature (its content is new to them). */
71
+ const observeRoots = () => {
72
+ if (!observer || !config.shadowHosts.length)
73
+ return;
74
+ let added = false;
75
+ for (const root of domRoots(win).slice(1)) {
76
+ if (roots.has(root))
77
+ continue;
78
+ roots.add(root);
79
+ observer.observe(root, options);
80
+ added = true;
81
+ }
82
+ if (added) {
83
+ retries = 0;
84
+ for (const sub of hub.subs)
85
+ hub.mark(sub);
86
+ }
87
+ // attachShadow makes no mutation: a host that has no root yet is looked at again, a few times.
88
+ if (!retry && retries < 20 && hostWithoutRoot(doc)) {
89
+ retries += 1;
90
+ retry = setTimeout(() => { retry = null; observeRoots(); }, 300);
91
+ }
92
+ };
25
93
  const frame = () => {
26
94
  frameRequested = false;
27
95
  const heavy = isHeavyPath(win.location.pathname ?? '');
@@ -56,6 +124,8 @@ function hubFor(win) {
56
124
  (attributes ??= new Set()).add(record.attributeName);
57
125
  }
58
126
  }
127
+ if (!known || childList)
128
+ observeRoots();
59
129
  for (const sub of hub.subs) {
60
130
  if (!known || childList || (characterData && sub.opts.characterData)
61
131
  || (attributes && sub.opts.attributes?.some(name => attributes.has(name))))
@@ -72,12 +142,15 @@ function hubFor(win) {
72
142
  return;
73
143
  observer ??= new win.MutationObserver(onRecords);
74
144
  observing = key;
75
- // Re-observing the same node replaces its options.
76
- observer.observe(doc.body, {
145
+ options = {
77
146
  childList: true, subtree: true,
78
147
  ...(characterData ? { characterData: true } : {}),
79
148
  ...(filter.length ? { attributes: true, attributeFilter: filter } : {}),
80
- });
149
+ };
150
+ // Re-observing the same node replaces its options (the shadow roots get them again too).
151
+ observer.observe(doc.body, options);
152
+ roots = new WeakSet();
153
+ observeRoots();
81
154
  };
82
155
  const hub = {
83
156
  subs: [],
@@ -93,6 +166,11 @@ function hubFor(win) {
93
166
  observer?.disconnect();
94
167
  observer = null;
95
168
  observing = '';
169
+ roots = new WeakSet();
170
+ if (retry) {
171
+ clearTimeout(retry);
172
+ retry = null;
173
+ }
96
174
  doc.removeEventListener('DOMContentLoaded', start);
97
175
  hubs.delete(win);
98
176
  return;
@@ -106,6 +184,63 @@ function hubFor(win) {
106
184
  hubs.set(win, hub);
107
185
  return hub;
108
186
  }
187
+ // One per window and heavy-page behaviour: every selector observer of that kind shares its watch.
188
+ const selectorHubs = new WeakMap();
189
+ /**
190
+ * Calls `callback` once for every element matching `selector`, now and as the page renders more.
191
+ * Every call shares the hub's one MutationObserver and one frame: a page with a hundred selector
192
+ * observers still has one observer, and a mutation costs one frame in which each observer looks
193
+ * for elements it has not seen yet. Returns the disposer.
194
+ */
195
+ export function observeSelector(win, selector, callback, options = {}) {
196
+ const offOnHeavy = !!options.offOnHeavy;
197
+ let kinds = selectorHubs.get(win);
198
+ if (!kinds) {
199
+ kinds = new Map();
200
+ selectorHubs.set(win, kinds);
201
+ }
202
+ let hub = kinds.get(offOnHeavy);
203
+ if (!hub) {
204
+ hub = { subs: [], handle: null };
205
+ kinds.set(offOnHeavy, hub);
206
+ }
207
+ const owner = hub;
208
+ const report = options.report ?? ((error) => console.error(`[${config.label}] DOM feature failed`, error));
209
+ const sub = { selector, callback, seen: new WeakSet(), report };
210
+ const scan = (target) => {
211
+ for (const root of domRoots(win)) {
212
+ for (const element of Array.from(root.querySelectorAll(target.selector))) {
213
+ if (target.seen.has(element))
214
+ continue;
215
+ target.seen.add(element);
216
+ try {
217
+ target.callback(element);
218
+ }
219
+ catch (error) {
220
+ target.report(error);
221
+ }
222
+ }
223
+ }
224
+ };
225
+ owner.subs.push(sub);
226
+ owner.handle ??= watchDom(win, () => { for (const item of owner.subs.slice())
227
+ scan(item); }, { offOnHeavy });
228
+ if (!(offOnHeavy && isHeavyPath(win.location.pathname ?? '')))
229
+ scan(sub);
230
+ let active = true;
231
+ return () => {
232
+ if (!active)
233
+ return;
234
+ active = false;
235
+ const index = owner.subs.indexOf(sub);
236
+ if (index >= 0)
237
+ owner.subs.splice(index, 1);
238
+ if (!owner.subs.length) {
239
+ owner.handle?.dispose();
240
+ owner.handle = null;
241
+ }
242
+ };
243
+ }
109
244
  /**
110
245
  * Runs `run` in the next animation frame after body mutations of the watched kinds (child list
111
246
  * always), or whenever `schedule()` is called (scroll, popstate, input, ...). Several calls in one
@@ -1 +1 @@
1
- {"version":3,"file":"domHub.js","sourceRoot":"","sources":["../../../runtime/src/domHub.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,kGAAkG;AAClG,mGAAmG;AACnG,qGAAqG;AACrG,mGAAmG;AACnG,kGAAkG;AAClG,sGAAsG;AA8BtG,MAAM,MAAM,GAAiB,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACrE,MAAM,IAAI,GAAG,IAAI,OAAO,EAAe,CAAC;AAExC,8DAA8D;AAC9D,MAAM,UAAU,eAAe,CAAC,IAA2B;IACzD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,MAAM,CAAC,GAAc;IAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;IACzB,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,QAAQ,GAA4B,IAAI,CAAC;IAC7C,IAAI,SAAS,GAAG,EAAE,CAAC;IAEnB,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,cAAc,GAAG,KAAK,CAAC;QACvB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QACvD,KAAK,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,OAAO,CAAU,EAAE,CAAC;YAC/C,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,KAAK;oBAAE,SAAS;gBACpE,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;gBACpB,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU;oBAAE,SAAS;gBAC3C,IAAI,CAAC;oBAAC,GAAG,CAAC,GAAG,EAAE,CAAC;gBAAC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,sBAAsB,EAAE,KAAK,CAAC,CAAC;gBAAC,CAAC;YACpG,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,SAAS,GAAG,CAAC,OAAyB,EAAE,EAAE;QAC9C,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,IAAI,UAAU,GAAuB,IAAI,CAAC;QAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAC3D,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW;oBAAE,SAAS,GAAG,IAAI,CAAC;qBAC7C,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe;oBAAE,aAAa,GAAG,IAAI,CAAC;qBAC1D,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,aAAa;oBAAE,CAAC,UAAU,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YACtH,CAAC;QACH,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,IAAI,SAAS,IAAI,CAAC,aAAa,IAAI,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC;mBAC/D,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,UAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAC1C,MAAM,aAAa,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnE,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvF,MAAM,GAAG,GAAG,GAAG,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,IAAI,QAAQ,IAAI,SAAS,KAAK,GAAG;YAAE,OAAO;QAC1C,QAAQ,KAAK,IAAI,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACjD,SAAS,GAAG,GAAG,CAAC;QAChB,mDAAmD;QACnD,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE;YACzB,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI;YAC9B,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxE,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,GAAG,GAAQ;QACf,IAAI,EAAE,EAAE;QACR,IAAI,CAAC,GAAG;YACN,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,cAAc,EAAE,CAAC;gBAAC,cAAc,GAAG,IAAI,CAAC;gBAAC,GAAG,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAAC,CAAC;QACnF,CAAC;QACD,OAAO;YACL,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACrB,QAAQ,EAAE,UAAU,EAAE,CAAC;gBACvB,QAAQ,GAAG,IAAI,CAAC;gBAChB,SAAS,GAAG,EAAE,CAAC;gBACf,GAAG,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;gBACnD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,IAAI,GAAG,CAAC,IAAI;gBAAE,KAAK,EAAE,CAAC;;gBACjB,GAAG,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,CAAC;KACF,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACnB,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAc,EAAE,GAAe,EAAE,OAAiB,EAAE;IAC3E,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACxB,MAAM,GAAG,GAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC/C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,GAAG,CAAC,OAAO,EAAE,CAAC;IACd,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,MAAM;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO;YACL,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,MAAM,GAAG,KAAK,CAAC;YACf,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,KAAK,IAAI,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1C,GAAG,CAAC,OAAO,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// One MutationObserver and one animation frame per page for every DOM feature of a site runtime.\n// Without it, each feature (nav items, tweaks, buttons, fixes, viewers) observes the whole <body>\n// subtree and schedules its own frame, so every mutation the site makes costs one callback and one\n// frame of scans per feature. Here a mutation marks the features interested in its kind (child list,\n// text, a named attribute) and they run together in the next frame: layout readers first, then DOM\n// writers, so a reader never forces a synchronous layout behind another feature's write. Features\n// marked `offOnHeavy` do not run on the site's heavy pages (see `configureDomHub`), e.g. a WASM chat.\n\nexport type DomWatch = {\n /** Also run on text changes (characterData). */\n characterData?: boolean;\n /** Also run when one of these attributes changes. */\n attributes?: string[];\n /** Skip on the site's heavy pages (`DomHubConfig.heavyPath`). */\n offOnHeavy?: boolean;\n /** 'read' features (layout reads) run before 'write' features (the default) in a frame. */\n phase?: 'read' | 'write';\n};\nexport type DomWatchHandle = { schedule(): void; dispose(): void };\n\nexport type DomHubConfig = {\n /** Console prefix for feature failures, e.g. \"wayBetter for X\". */\n label: string;\n /** Pathnames where `offOnHeavy` features are skipped; null = none. */\n heavyPath: RegExp | null;\n};\n\nexport type DomWindow = {\n document: Document;\n location: { pathname: string };\n MutationObserver: typeof MutationObserver;\n requestAnimationFrame(callback: FrameRequestCallback): number;\n};\ntype Sub = { run: () => void; opts: DomWatch; pending: boolean };\ntype Hub = { subs: Sub[]; mark(sub: Sub): void; refresh(): void };\n\nconst config: DomHubConfig = { label: 'wayBetter', heavyPath: null };\nconst hubs = new WeakMap<object, Hub>();\n\n/** Set once by the site adapter, before features register. */\nexport function configureDomHub(next: Partial<DomHubConfig>): void {\n Object.assign(config, next);\n}\n\nexport function isHeavyPath(pathname: string): boolean {\n return !!config.heavyPath && config.heavyPath.test(pathname);\n}\n\nfunction hubFor(win: DomWindow): Hub {\n const existing = hubs.get(win);\n if (existing) return existing;\n const doc = win.document;\n let frameRequested = false;\n let observer: MutationObserver | null = null;\n let observing = '';\n\n const frame = () => {\n frameRequested = false;\n const heavy = isHeavyPath(win.location.pathname ?? '');\n for (const phase of ['read', 'write'] as const) {\n for (const sub of hub.subs.slice()) {\n if (!sub.pending || (sub.opts.phase ?? 'write') !== phase) continue;\n sub.pending = false;\n if (heavy && sub.opts.offOnHeavy) continue;\n try { sub.run(); } catch (error) { console.error(`[${config.label}] DOM feature failed`, error); }\n }\n }\n };\n const onRecords = (records: MutationRecord[]) => {\n let childList = false;\n let characterData = false;\n let attributes: Set<string> | null = null;\n const known = Array.isArray(records) && records.length > 0;\n if (known) {\n for (const record of records) {\n if (record.type === 'childList') childList = true;\n else if (record.type === 'characterData') characterData = true;\n else if (record.type === 'attributes' && record.attributeName) (attributes ??= new Set()).add(record.attributeName);\n }\n }\n for (const sub of hub.subs) {\n if (!known || childList || (characterData && sub.opts.characterData)\n || (attributes && sub.opts.attributes?.some(name => attributes!.has(name)))) hub.mark(sub);\n }\n };\n const start = () => {\n if (!doc.body || !hub.subs.length) return;\n const characterData = hub.subs.some(sub => sub.opts.characterData);\n const filter = [...new Set(hub.subs.flatMap(sub => sub.opts.attributes ?? []))].sort();\n const key = `${characterData}|${filter.join(',')}`;\n if (observer && observing === key) return;\n observer ??= new win.MutationObserver(onRecords);\n observing = key;\n // Re-observing the same node replaces its options.\n observer.observe(doc.body, {\n childList: true, subtree: true,\n ...(characterData ? { characterData: true } : {}),\n ...(filter.length ? { attributes: true, attributeFilter: filter } : {}),\n });\n };\n\n const hub: Hub = {\n subs: [],\n mark(sub) {\n sub.pending = true;\n if (!frameRequested) { frameRequested = true; win.requestAnimationFrame(frame); }\n },\n refresh() {\n if (!hub.subs.length) {\n observer?.disconnect();\n observer = null;\n observing = '';\n doc.removeEventListener('DOMContentLoaded', start);\n hubs.delete(win);\n return;\n }\n if (doc.body) start();\n else doc.addEventListener('DOMContentLoaded', start, { once: true });\n },\n };\n hubs.set(win, hub);\n return hub;\n}\n\n/**\n * Runs `run` in the next animation frame after body mutations of the watched kinds (child list\n * always), or whenever `schedule()` is called (scroll, popstate, input, ...). Several calls in one\n * frame run it once.\n */\nexport function watchDom(win: DomWindow, run: () => void, opts: DomWatch = {}): DomWatchHandle {\n const hub = hubFor(win);\n const sub: Sub = { run, opts, pending: false };\n hub.subs.push(sub);\n hub.refresh();\n let active = true;\n return {\n schedule: () => { if (active) hub.mark(sub); },\n dispose() {\n if (!active) return;\n active = false;\n const index = hub.subs.indexOf(sub);\n if (index >= 0) hub.subs.splice(index, 1);\n hub.refresh();\n },\n };\n}\n"]}
1
+ {"version":3,"file":"domHub.js","sourceRoot":"","sources":["../../../runtime/src/domHub.ts"],"names":[],"mappings":"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","sourcesContent":["// One MutationObserver and one animation frame per page for every DOM feature of a site runtime.\n// Without it, each feature (nav items, tweaks, buttons, fixes, viewers) observes the whole <body>\n// subtree and schedules its own frame, so every mutation the site makes costs one callback and one\n// frame of scans per feature. Here a mutation marks the features interested in its kind (child list,\n// text, a named attribute) and they run together in the next frame: layout readers first, then DOM\n// writers, so a reader never forces a synchronous layout behind another feature's write. Features\n// marked `offOnHeavy` do not run on the site's heavy pages (see `configureDomHub`), e.g. a WASM chat.\n//\n// A site that renders a part of itself inside an open shadow root (X's chat, since 2026-10-01, in\n// the shadow root of its embed host) names the host in `shadowHosts`: the hub's one observer then\n// observes each such root too (picked up when the host appears or gets its root, dropped with the\n// observer), selector observers look inside, and `domRoots` gives features the roots to query.\n\nexport type DomWatch = {\n /** Also run on text changes (characterData). */\n characterData?: boolean;\n /** Also run when one of these attributes changes. */\n attributes?: string[];\n /** Skip on the site's heavy pages (`DomHubConfig.heavyPath`). */\n offOnHeavy?: boolean;\n /** 'read' features (layout reads) run before 'write' features (the default) in a frame. */\n phase?: 'read' | 'write';\n};\nexport type DomWatchHandle = { schedule(): void; dispose(): void };\n\nexport type DomHubConfig = {\n /** Console prefix for feature failures, e.g. \"wayBetter for X\". */\n label: string;\n /** Pathnames where `offOnHeavy` features are skipped; null = none. */\n heavyPath: RegExp | null;\n /** Selectors of hosts whose open shadow roots are part of the page (observed and searched like it). */\n shadowHosts: readonly string[];\n};\n\nexport type DomWindow = {\n document: Document;\n location: { pathname: string };\n MutationObserver: typeof MutationObserver;\n requestAnimationFrame(callback: FrameRequestCallback): number;\n};\ntype Sub = { run: () => void; opts: DomWatch; pending: boolean };\ntype Hub = { subs: Sub[]; mark(sub: Sub): void; refresh(): void };\n\nconst config: DomHubConfig = { label: 'wayBetter', heavyPath: null, shadowHosts: [] };\nconst hubs = new WeakMap<object, Hub>();\n\n/** Set once by the site adapter, before features register. */\nexport function configureDomHub(next: Partial<DomHubConfig>): void {\n Object.assign(config, next);\n}\n\n/** The page's roots: the document, then the open shadow roots of the configured hosts now in it. */\nexport function domRoots(win: { document: Document }): Array<Document | ShadowRoot> {\n const doc = win.document;\n const out: Array<Document | ShadowRoot> = [doc];\n if (!config.shadowHosts.length) return out;\n let hosts: Element[] = [];\n try { hosts = Array.from(doc.querySelectorAll(config.shadowHosts.join(','))); } catch { return out; }\n for (const host of hosts) {\n const root = (host as Element & { shadowRoot?: ShadowRoot | null }).shadowRoot;\n if (root) out.push(root);\n }\n return out;\n}\n\n/** The site names hosts whose shadow roots are part of the page. */\nexport function hasShadowHosts(): boolean {\n return config.shadowHosts.length > 0;\n}\n\n/** A configured host is in the page but has no open shadow root yet (it may attach one later). */\nfunction hostWithoutRoot(doc: Document): boolean {\n if (!config.shadowHosts.length) return false;\n try { return Array.from(doc.querySelectorAll(config.shadowHosts.join(','))).some(host => !(host as Element & { shadowRoot?: ShadowRoot | null }).shadowRoot); } catch { return false; }\n}\n\nexport function isHeavyPath(pathname: string): boolean {\n return !!config.heavyPath && config.heavyPath.test(pathname);\n}\n\nfunction hubFor(win: DomWindow): Hub {\n const existing = hubs.get(win);\n if (existing) return existing;\n const doc = win.document;\n let frameRequested = false;\n let observer: MutationObserver | null = null;\n let observing = '';\n let options: MutationObserverInit = { childList: true, subtree: true };\n // Shadow roots the observer already observes (with the current options).\n let roots = new WeakSet<Node>();\n let retries = 0;\n let retry: ReturnType<typeof setTimeout> | null = null;\n /** Observes configured shadow roots that are new; a new one marks every feature (its content is new to them). */\n const observeRoots = () => {\n if (!observer || !config.shadowHosts.length) return;\n let added = false;\n for (const root of domRoots(win).slice(1)) {\n if (roots.has(root)) continue;\n roots.add(root);\n observer.observe(root, options);\n added = true;\n }\n if (added) { retries = 0; for (const sub of hub.subs) hub.mark(sub); }\n // attachShadow makes no mutation: a host that has no root yet is looked at again, a few times.\n if (!retry && retries < 20 && hostWithoutRoot(doc)) {\n retries += 1;\n retry = setTimeout(() => { retry = null; observeRoots(); }, 300);\n }\n };\n\n const frame = () => {\n frameRequested = false;\n const heavy = isHeavyPath(win.location.pathname ?? '');\n for (const phase of ['read', 'write'] as const) {\n for (const sub of hub.subs.slice()) {\n if (!sub.pending || (sub.opts.phase ?? 'write') !== phase) continue;\n sub.pending = false;\n if (heavy && sub.opts.offOnHeavy) continue;\n try { sub.run(); } catch (error) { console.error(`[${config.label}] DOM feature failed`, error); }\n }\n }\n };\n const onRecords = (records: MutationRecord[]) => {\n let childList = false;\n let characterData = false;\n let attributes: Set<string> | null = null;\n const known = Array.isArray(records) && records.length > 0;\n if (known) {\n for (const record of records) {\n if (record.type === 'childList') childList = true;\n else if (record.type === 'characterData') characterData = true;\n else if (record.type === 'attributes' && record.attributeName) (attributes ??= new Set()).add(record.attributeName);\n }\n }\n if (!known || childList) observeRoots();\n for (const sub of hub.subs) {\n if (!known || childList || (characterData && sub.opts.characterData)\n || (attributes && sub.opts.attributes?.some(name => attributes!.has(name)))) hub.mark(sub);\n }\n };\n const start = () => {\n if (!doc.body || !hub.subs.length) return;\n const characterData = hub.subs.some(sub => sub.opts.characterData);\n const filter = [...new Set(hub.subs.flatMap(sub => sub.opts.attributes ?? []))].sort();\n const key = `${characterData}|${filter.join(',')}`;\n if (observer && observing === key) return;\n observer ??= new win.MutationObserver(onRecords);\n observing = key;\n options = {\n childList: true, subtree: true,\n ...(characterData ? { characterData: true } : {}),\n ...(filter.length ? { attributes: true, attributeFilter: filter } : {}),\n };\n // Re-observing the same node replaces its options (the shadow roots get them again too).\n observer.observe(doc.body, options);\n roots = new WeakSet();\n observeRoots();\n };\n\n const hub: Hub = {\n subs: [],\n mark(sub) {\n sub.pending = true;\n if (!frameRequested) { frameRequested = true; win.requestAnimationFrame(frame); }\n },\n refresh() {\n if (!hub.subs.length) {\n observer?.disconnect();\n observer = null;\n observing = '';\n roots = new WeakSet();\n if (retry) { clearTimeout(retry); retry = null; }\n doc.removeEventListener('DOMContentLoaded', start);\n hubs.delete(win);\n return;\n }\n if (doc.body) start();\n else doc.addEventListener('DOMContentLoaded', start, { once: true });\n },\n };\n hubs.set(win, hub);\n return hub;\n}\n\ntype SelectorSub = { selector: string; callback: (element: Element) => void; seen: WeakSet<Element>; report(error: unknown): void };\ntype SelectorHub = { subs: SelectorSub[]; handle: DomWatchHandle | null };\n// One per window and heavy-page behaviour: every selector observer of that kind shares its watch.\nconst selectorHubs = new WeakMap<object, Map<boolean, SelectorHub>>();\n\nexport type ObserveOptions = {\n /** Skip on the site's heavy pages (default false). */\n offOnHeavy?: boolean;\n /** A callback that throws is handed here (default: the hub's console line). */\n report?(error: unknown): void;\n};\n\n/**\n * Calls `callback` once for every element matching `selector`, now and as the page renders more.\n * Every call shares the hub's one MutationObserver and one frame: a page with a hundred selector\n * observers still has one observer, and a mutation costs one frame in which each observer looks\n * for elements it has not seen yet. Returns the disposer.\n */\nexport function observeSelector(win: DomWindow, selector: string, callback: (element: Element) => void, options: ObserveOptions = {}): () => void {\n const offOnHeavy = !!options.offOnHeavy;\n let kinds = selectorHubs.get(win);\n if (!kinds) { kinds = new Map(); selectorHubs.set(win, kinds); }\n let hub = kinds.get(offOnHeavy);\n if (!hub) { hub = { subs: [], handle: null }; kinds.set(offOnHeavy, hub); }\n const owner = hub;\n const report = options.report ?? ((error: unknown) => console.error(`[${config.label}] DOM feature failed`, error));\n const sub: SelectorSub = { selector, callback, seen: new WeakSet(), report };\n const scan = (target: SelectorSub) => {\n for (const root of domRoots(win)) {\n for (const element of Array.from(root.querySelectorAll(target.selector))) {\n if (target.seen.has(element)) continue;\n target.seen.add(element);\n try { target.callback(element); } catch (error) { target.report(error); }\n }\n }\n };\n owner.subs.push(sub);\n owner.handle ??= watchDom(win, () => { for (const item of owner.subs.slice()) scan(item); }, { offOnHeavy });\n if (!(offOnHeavy && isHeavyPath(win.location.pathname ?? ''))) scan(sub);\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n const index = owner.subs.indexOf(sub);\n if (index >= 0) owner.subs.splice(index, 1);\n if (!owner.subs.length) { owner.handle?.dispose(); owner.handle = null; }\n };\n}\n\n/**\n * Runs `run` in the next animation frame after body mutations of the watched kinds (child list\n * always), or whenever `schedule()` is called (scroll, popstate, input, ...). Several calls in one\n * frame run it once.\n */\nexport function watchDom(win: DomWindow, run: () => void, opts: DomWatch = {}): DomWatchHandle {\n const hub = hubFor(win);\n const sub: Sub = { run, opts, pending: false };\n hub.subs.push(sub);\n hub.refresh();\n let active = true;\n return {\n schedule: () => { if (active) hub.mark(sub); },\n dispose() {\n if (!active) return;\n active = false;\n const index = hub.subs.indexOf(sub);\n if (index >= 0) hub.subs.splice(index, 1);\n hub.refresh();\n },\n };\n}\n"]}
@@ -0,0 +1,157 @@
1
+ import { type DomWatch, type DomWatchHandle } from './domHub.ts';
2
+ import { type AreaSpec, type FeatureTable, type Flags } from './featureTable.ts';
3
+ import { type Params } from './i18n.ts';
4
+ import type { CommandDefinition } from './commands.ts';
5
+ import type { PluginI18n } from './pluginI18n.ts';
6
+ import type { Dispose, PluginScope, PluginStorage } from './pluginApi.ts';
7
+ import { type SettingValues, type SettingsSchema } from './settingsForm.ts';
8
+ import { type UiKit } from './ui.ts';
9
+ /** Palette commands one area may register: its "settings" entry and four actions (the tab reports at most 48). */
10
+ export declare const AREA_COMMAND_BUDGET = 5;
11
+ /** Misses in a row (separate visits) before a feature pauses itself. */
12
+ export declare const PROBE_STRIKES = 3;
13
+ /**
14
+ * A selector a feature depends on. `english`: it reads an English label, so it only counts on an
15
+ * English page. `when`: it only counts while this selector matches (the part of the page it lives
16
+ * in is there: a column the site drops in a narrow window is no verdict).
17
+ */
18
+ export type Probe = string | {
19
+ selector: string;
20
+ english?: boolean;
21
+ when?: string;
22
+ };
23
+ export type FeatureSettings = {
24
+ /** The stored values, normalized by the schema. */
25
+ get(): SettingValues;
26
+ /** Saves (merged over the current values). False when storage refused it. */
27
+ set(patch: SettingValues): boolean;
28
+ /** Calls `callback(values)` after a save, until the feature stops. */
29
+ onChange(callback: (values: SettingValues) => void): void;
30
+ /** Opens this feature's settings dialog. */
31
+ open(): void;
32
+ };
33
+ export type FeatureContext<Api> = {
34
+ /** The flag id and the feature's own name (`navigation.focusMode` -> `focusMode`). */
35
+ readonly id: string;
36
+ readonly name: string;
37
+ readonly area: AreaSpec;
38
+ /** The app's plugin API, unrestricted: a feature module is the app's own code. */
39
+ readonly api: Api;
40
+ /** The page's window (use it and its `document` instead of the globals: tests run without them). */
41
+ readonly win: Window & typeof globalThis;
42
+ /** This feature's stylesheet (one per `name`, replaced in place, cleared by an empty string; removed on stop). It also styles the site's configured open shadow roots (domHub `shadowHosts`). */
43
+ css(css: string, name?: string): void;
44
+ /** `callback` once per element matching `selector`, through the shared hub; paused on heavy pages unless the feature says `heavy`. */
45
+ observe(selector: string, callback: (element: Element) => void): void;
46
+ /** A raw hub subscription (domHub `watchDom`), disposed on stop. */
47
+ watch(run: () => void, options?: DomWatch): DomWatchHandle;
48
+ on(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
49
+ onKey(callback: (event: KeyboardEvent, item: Element | null) => void): void;
50
+ onRouteChange(callback: (href: string, previous: string) => void): void;
51
+ /** Tracks a node the feature inserted; removed on stop. */
52
+ add<T extends Node>(node: T): T;
53
+ /** Runs `fn` on stop. */
54
+ defer(fn: Dispose): void;
55
+ /** The UI kit; what the feature opened is closed on stop. */
56
+ readonly ui: UiKit;
57
+ /** A palette command under the area's name (counts towards `AREA_COMMAND_BUDGET`), removed on stop. */
58
+ command(definition: CommandDefinition): void;
59
+ /**
60
+ * The feature's word `key`: `plugin.<area namespace>.<name>.<key>` in the app's catalog, or
61
+ * `plugin.<words>.<key>` for a module that names its own namespace (`words`). (Not
62
+ * named `t`: the i18n tools read `t('…')` as a whole catalog key.)
63
+ */
64
+ text(key: string, params?: Params): string;
65
+ /** The feature's storage (its module's `storage` namespace). */
66
+ readonly storage: PluginStorage;
67
+ /** Its settings (a module with a `settings` schema; otherwise empty values). */
68
+ readonly settings: FeatureSettings;
69
+ /** The selector of probe `name` (a hotfix override wins). */
70
+ selector(name: string): string;
71
+ /** The surfaces the page is on right now. */
72
+ surfaces(): readonly string[];
73
+ };
74
+ export type FeatureModule<Api> = {
75
+ /** The flag id; the table must list it with `backing: 'module'`. */
76
+ id: string;
77
+ /** Selectors it depends on, by name (read them back with `ctx.selector(name)`). */
78
+ probes?: Readonly<Record<string, Probe>>;
79
+ /**
80
+ * Where its words are in the catalog. Default: `plugin.<area namespace>.<name>.<key>`. A feature
81
+ * ported from a plugin names that plugin's namespace (`focus-mode`) and keeps its keys
82
+ * (`plugin.focus-mode.<key>`, its label `plugin.focus-mode.name`): nothing is retranslated.
83
+ */
84
+ words?: string;
85
+ /** Storage namespace (default `<area namespace>.<name>`; a ported plugin keeps its old one). */
86
+ storage?: string;
87
+ /** The key its settings are stored under (default `settings`). */
88
+ settingsKey?: string;
89
+ settings?: SettingsSchema;
90
+ start(ctx: FeatureContext<Api>): void;
91
+ };
92
+ /** What the registry needs of the plugin API (the core API has all of it). */
93
+ export type RegistryApi = {
94
+ scope(): PluginScope;
95
+ injectCSS(id: string, css: string): void;
96
+ clearCSS(id: string): void;
97
+ storage(namespace: string): PluginStorage;
98
+ onRouteChange(callback: (href: string, previous: string) => void): Dispose;
99
+ ui: UiKit;
100
+ i18n: PluginI18n;
101
+ commands: {
102
+ withOwner<T>(owner: string, fn: () => T): T;
103
+ };
104
+ };
105
+ export type HotfixData = {
106
+ selectors?: Readonly<Record<string, unknown>>;
107
+ flags?: Readonly<Record<string, unknown>>;
108
+ };
109
+ export type FeatureHealth = {
110
+ id: string;
111
+ area: string;
112
+ state: 'paused' | 'needs-english';
113
+ probes: string[];
114
+ };
115
+ export type FeatureRegistryOptions<Api extends RegistryApi> = {
116
+ win: Window & typeof globalThis;
117
+ table: FeatureTable;
118
+ api: Api;
119
+ /** Console prefix (the app's name). */
120
+ label: string;
121
+ /** The surfaces the page is on (`['timeline', 'home']`); the app's classifier. */
122
+ surfaces(): readonly string[];
123
+ /** The app catalog's message for `key` in the active language (the registry's words are the kit's: `kit.feature.*`, `kit.save`). */
124
+ message?(key: string): string | undefined;
125
+ locale?(): string;
126
+ /** The signed hotfix data, when the app has any (selector overrides and kill flags). */
127
+ hotfix?(): HotfixData | null | undefined;
128
+ /** The page has rendered its content (the site's main column is there); default: the body has children. */
129
+ settled?(): boolean;
130
+ /** The page's language is English (probes marked `english` only count then); default: `<html lang>` starts with `en`. */
131
+ english?(): boolean;
132
+ /** ms after the page settled before probes are judged (default 3000) and between settle checks (default 500). */
133
+ settleMs?: number;
134
+ pollMs?: number;
135
+ timers?: {
136
+ setTimeout(fn: () => void, ms: number): unknown;
137
+ clearTimeout(id: unknown): void;
138
+ };
139
+ };
140
+ export type FeatureRegistry<Api> = {
141
+ define(module: FeatureModule<Api>): void;
142
+ /** The effective flags (featureTable `effectiveFlags`): starts and stops modules to match. */
143
+ setFlags(flags: Readonly<Flags>): void;
144
+ /** Re-checks surfaces (the registry also does it on every route change). */
145
+ refresh(): void;
146
+ /** The ids of the modules running right now. */
147
+ active(): string[];
148
+ /** Paused features and features waiting for an English page. */
149
+ health(): FeatureHealth[];
150
+ /** Opens the settings dialog of an area (or of one feature). False when nothing in it has settings right now. */
151
+ openSettings(area: string, feature?: string): boolean;
152
+ /** Stops everything (the runtime is going away; tests). */
153
+ dispose(): void;
154
+ };
155
+ export declare function createFeatureRegistry<Api extends RegistryApi>(options: FeatureRegistryOptions<Api>): FeatureRegistry<Api>;
156
+ /** Whether an area's switch is on in `flags` (a missing value counts as on). */
157
+ export declare const areaEnabled: (flags: Readonly<Flags>, area: string) => boolean;