react-cheminfo 0.64.1 → 0.65.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 (604) hide show
  1. package/README.md +282 -0
  2. package/lib/card/core/cardAddress.d.ts +70 -0
  3. package/lib/card/core/cardAddress.d.ts.map +1 -0
  4. package/lib/card/core/cardAddress.js +59 -0
  5. package/lib/card/core/cardAddress.js.map +1 -0
  6. package/lib/card/core/cardPageUrl.d.ts +49 -0
  7. package/lib/card/core/cardPageUrl.d.ts.map +1 -0
  8. package/lib/card/core/cardPageUrl.js +59 -0
  9. package/lib/card/core/cardPageUrl.js.map +1 -0
  10. package/lib/card/core/index.d.ts +7 -0
  11. package/lib/card/core/index.d.ts.map +1 -0
  12. package/lib/card/core/index.js +4 -0
  13. package/lib/card/core/index.js.map +1 -0
  14. package/lib/card/core/panelRoom.d.ts +40 -0
  15. package/lib/card/core/panelRoom.d.ts.map +1 -0
  16. package/lib/card/core/panelRoom.js +40 -0
  17. package/lib/card/core/panelRoom.js.map +1 -0
  18. package/lib/card/ui/CardDetailsButton.d.ts +38 -0
  19. package/lib/card/ui/CardDetailsButton.d.ts.map +1 -0
  20. package/lib/card/ui/CardDetailsButton.js +50 -0
  21. package/lib/card/ui/CardDetailsButton.js.map +1 -0
  22. package/lib/card/ui/CardFigure.d.ts +51 -0
  23. package/lib/card/ui/CardFigure.d.ts.map +1 -0
  24. package/lib/card/ui/CardFigure.js +27 -0
  25. package/lib/card/ui/CardFigure.js.map +1 -0
  26. package/lib/card/ui/CardFrame.d.ts +30 -0
  27. package/lib/card/ui/CardFrame.d.ts.map +1 -0
  28. package/lib/card/ui/CardFrame.js +20 -0
  29. package/lib/card/ui/CardFrame.js.map +1 -0
  30. package/lib/card/ui/CopyTableButton.d.ts +37 -0
  31. package/lib/card/ui/CopyTableButton.d.ts.map +1 -0
  32. package/lib/card/ui/CopyTableButton.js +19 -0
  33. package/lib/card/ui/CopyTableButton.js.map +1 -0
  34. package/lib/card/ui/cardTooltip.d.ts +14 -0
  35. package/lib/card/ui/cardTooltip.d.ts.map +1 -0
  36. package/lib/card/ui/cardTooltip.js +15 -0
  37. package/lib/card/ui/cardTooltip.js.map +1 -0
  38. package/lib/card/ui/embed.d.ts +15 -0
  39. package/lib/card/ui/embed.d.ts.map +1 -0
  40. package/lib/card/ui/embed.js +24 -0
  41. package/lib/card/ui/embed.js.map +1 -0
  42. package/lib/card/ui/fitCardToFrame.d.ts +31 -0
  43. package/lib/card/ui/fitCardToFrame.d.ts.map +1 -0
  44. package/lib/card/ui/fitCardToFrame.js +66 -0
  45. package/lib/card/ui/fitCardToFrame.js.map +1 -0
  46. package/lib/card/ui/holdRoomForPanels.d.ts +16 -0
  47. package/lib/card/ui/holdRoomForPanels.d.ts.map +1 -0
  48. package/lib/card/ui/holdRoomForPanels.js +76 -0
  49. package/lib/card/ui/holdRoomForPanels.js.map +1 -0
  50. package/lib/card/ui/index.d.ts +11 -0
  51. package/lib/card/ui/index.d.ts.map +1 -0
  52. package/lib/card/ui/index.js +7 -0
  53. package/lib/card/ui/index.js.map +1 -0
  54. package/lib/card/ui/openPanels.d.ts +25 -0
  55. package/lib/card/ui/openPanels.d.ts.map +1 -0
  56. package/lib/card/ui/openPanels.js +85 -0
  57. package/lib/card/ui/openPanels.js.map +1 -0
  58. package/lib/card.d.ts +13 -0
  59. package/lib/card.d.ts.map +1 -0
  60. package/lib/card.js +13 -0
  61. package/lib/card.js.map +1 -0
  62. package/lib/conformers.d.ts +1 -0
  63. package/lib/conformers.d.ts.map +1 -1
  64. package/lib/conformers.js +1 -0
  65. package/lib/conformers.js.map +1 -1
  66. package/lib/core.d.ts +4 -0
  67. package/lib/core.d.ts.map +1 -1
  68. package/lib/core.js +5 -0
  69. package/lib/core.js.map +1 -1
  70. package/lib/fetch/core/apiError.d.ts +56 -0
  71. package/lib/fetch/core/apiError.d.ts.map +1 -0
  72. package/lib/fetch/core/apiError.js +43 -0
  73. package/lib/fetch/core/apiError.js.map +1 -0
  74. package/lib/fetch/core/fetchJson.d.ts +47 -0
  75. package/lib/fetch/core/fetchJson.d.ts.map +1 -0
  76. package/lib/fetch/core/fetchJson.js +109 -0
  77. package/lib/fetch/core/fetchJson.js.map +1 -0
  78. package/lib/fetch/core/index.d.ts +5 -0
  79. package/lib/fetch/core/index.d.ts.map +1 -0
  80. package/lib/fetch/core/index.js +3 -0
  81. package/lib/fetch/core/index.js.map +1 -0
  82. package/lib/formula/core/formulaText.d.ts +46 -0
  83. package/lib/formula/core/formulaText.d.ts.map +1 -0
  84. package/lib/formula/core/formulaText.js +74 -0
  85. package/lib/formula/core/formulaText.js.map +1 -0
  86. package/lib/formula/core/index.d.ts +6 -0
  87. package/lib/formula/core/index.d.ts.map +1 -0
  88. package/lib/formula/core/index.js +4 -0
  89. package/lib/formula/core/index.js.map +1 -0
  90. package/lib/formula/core/normalizeFormula.d.ts +22 -0
  91. package/lib/formula/core/normalizeFormula.d.ts.map +1 -0
  92. package/lib/formula/core/normalizeFormula.js +46 -0
  93. package/lib/formula/core/normalizeFormula.js.map +1 -0
  94. package/lib/formula/core/readFormula.d.ts +73 -0
  95. package/lib/formula/core/readFormula.d.ts.map +1 -0
  96. package/lib/formula/core/readFormula.js +132 -0
  97. package/lib/formula/core/readFormula.js.map +1 -0
  98. package/lib/formula/ui/CopyableFormula.d.ts +31 -0
  99. package/lib/formula/ui/CopyableFormula.d.ts.map +1 -0
  100. package/lib/formula/ui/CopyableFormula.js +19 -0
  101. package/lib/formula/ui/CopyableFormula.js.map +1 -0
  102. package/lib/formula/ui/FormulaInput.d.ts +29 -0
  103. package/lib/formula/ui/FormulaInput.d.ts.map +1 -0
  104. package/lib/formula/ui/FormulaInput.js +16 -0
  105. package/lib/formula/ui/FormulaInput.js.map +1 -0
  106. package/lib/formula/ui/QuestionFormula.d.ts +14 -0
  107. package/lib/formula/ui/QuestionFormula.d.ts.map +1 -0
  108. package/lib/formula/ui/QuestionFormula.js +13 -0
  109. package/lib/formula/ui/QuestionFormula.js.map +1 -0
  110. package/lib/formula/ui/index.d.ts +7 -0
  111. package/lib/formula/ui/index.d.ts.map +1 -0
  112. package/lib/formula/ui/index.js +4 -0
  113. package/lib/formula/ui/index.js.map +1 -0
  114. package/lib/formula.d.ts +11 -0
  115. package/lib/formula.d.ts.map +1 -0
  116. package/lib/formula.js +11 -0
  117. package/lib/formula.js.map +1 -0
  118. package/lib/hooks/ui/index.d.ts +1 -0
  119. package/lib/hooks/ui/index.d.ts.map +1 -1
  120. package/lib/hooks/ui/index.js.map +1 -1
  121. package/lib/hooks/ui/keyTargets.d.ts +4 -2
  122. package/lib/hooks/ui/keyTargets.d.ts.map +1 -1
  123. package/lib/hooks/ui/keyTargets.js +5 -3
  124. package/lib/hooks/ui/keyTargets.js.map +1 -1
  125. package/lib/hooks/ui/useAsync.d.ts +20 -5
  126. package/lib/hooks/ui/useAsync.d.ts.map +1 -1
  127. package/lib/hooks/ui/useAsync.js +29 -14
  128. package/lib/hooks/ui/useAsync.js.map +1 -1
  129. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  130. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  131. package/lib/locales/de.json +37 -0
  132. package/lib/locales/en.json +37 -0
  133. package/lib/locales/es.json +37 -0
  134. package/lib/locales/fr.json +37 -0
  135. package/lib/locales/it.json +37 -0
  136. package/lib/moleculesClient/core/index.d.ts +5 -0
  137. package/lib/moleculesClient/core/index.d.ts.map +1 -0
  138. package/lib/moleculesClient/core/index.js +3 -0
  139. package/lib/moleculesClient/core/index.js.map +1 -0
  140. package/lib/moleculesClient/core/moleculesClient.d.ts +12 -0
  141. package/lib/moleculesClient/core/moleculesClient.d.ts.map +1 -0
  142. package/lib/moleculesClient/core/moleculesClient.js +105 -0
  143. package/lib/moleculesClient/core/moleculesClient.js.map +1 -0
  144. package/lib/moleculesClient/core/moleculesClientApi.d.ts +100 -0
  145. package/lib/moleculesClient/core/moleculesClientApi.d.ts.map +1 -0
  146. package/lib/moleculesClient/core/moleculesClientApi.js +20 -0
  147. package/lib/moleculesClient/core/moleculesClientApi.js.map +1 -0
  148. package/lib/moleculesClient/core/moleculesTypes.d.ts +154 -0
  149. package/lib/moleculesClient/core/moleculesTypes.d.ts.map +1 -0
  150. package/lib/moleculesClient/core/moleculesTypes.js +2 -0
  151. package/lib/moleculesClient/core/moleculesTypes.js.map +1 -0
  152. package/lib/moleculesClient/core/requestRetry.d.ts +50 -0
  153. package/lib/moleculesClient/core/requestRetry.d.ts.map +1 -0
  154. package/lib/moleculesClient/core/requestRetry.js +108 -0
  155. package/lib/moleculesClient/core/requestRetry.js.map +1 -0
  156. package/lib/molstar/core/camera.d.ts +2 -1
  157. package/lib/molstar/core/camera.d.ts.map +1 -1
  158. package/lib/molstar/core/camera.js +3 -2
  159. package/lib/molstar/core/camera.js.map +1 -1
  160. package/lib/molstar/core/framing.d.ts +102 -0
  161. package/lib/molstar/core/framing.d.ts.map +1 -0
  162. package/lib/molstar/core/framing.js +120 -0
  163. package/lib/molstar/core/framing.js.map +1 -0
  164. package/lib/molstar/core/hover.d.ts +16 -0
  165. package/lib/molstar/core/hover.d.ts.map +1 -1
  166. package/lib/molstar/core/hover.js +14 -0
  167. package/lib/molstar/core/hover.js.map +1 -1
  168. package/lib/molstar/core/index.d.ts +4 -1
  169. package/lib/molstar/core/index.d.ts.map +1 -1
  170. package/lib/molstar/core/index.js +2 -1
  171. package/lib/molstar/core/index.js.map +1 -1
  172. package/lib/pedagogy/core/answers.d.ts +46 -0
  173. package/lib/pedagogy/core/answers.d.ts.map +1 -0
  174. package/lib/pedagogy/core/answers.js +77 -0
  175. package/lib/pedagogy/core/answers.js.map +1 -0
  176. package/lib/pedagogy/core/attempts.d.ts +86 -0
  177. package/lib/pedagogy/core/attempts.d.ts.map +1 -0
  178. package/lib/pedagogy/core/attempts.js +117 -0
  179. package/lib/pedagogy/core/attempts.js.map +1 -0
  180. package/lib/pedagogy/core/index.d.ts +8 -0
  181. package/lib/pedagogy/core/index.d.ts.map +1 -1
  182. package/lib/pedagogy/core/index.js +4 -0
  183. package/lib/pedagogy/core/index.js.map +1 -1
  184. package/lib/pedagogy/core/progressController.d.ts +64 -0
  185. package/lib/pedagogy/core/progressController.d.ts.map +1 -0
  186. package/lib/pedagogy/core/progressController.js +56 -0
  187. package/lib/pedagogy/core/progressController.js.map +1 -0
  188. package/lib/pedagogy/core/seed.d.ts +96 -0
  189. package/lib/pedagogy/core/seed.d.ts.map +1 -0
  190. package/lib/pedagogy/core/seed.js +128 -0
  191. package/lib/pedagogy/core/seed.js.map +1 -0
  192. package/lib/pedagogy/core/series.d.ts +77 -0
  193. package/lib/pedagogy/core/series.d.ts.map +1 -0
  194. package/lib/pedagogy/core/series.js +10 -0
  195. package/lib/pedagogy/core/series.js.map +1 -0
  196. package/lib/pedagogy/ui/AnswerFields.d.ts +21 -0
  197. package/lib/pedagogy/ui/AnswerFields.d.ts.map +1 -0
  198. package/lib/pedagogy/ui/AnswerFields.js +24 -0
  199. package/lib/pedagogy/ui/AnswerFields.js.map +1 -0
  200. package/lib/pedagogy/ui/ExerciseList.d.ts +82 -0
  201. package/lib/pedagogy/ui/ExerciseList.d.ts.map +1 -0
  202. package/lib/pedagogy/ui/ExerciseList.js +53 -0
  203. package/lib/pedagogy/ui/ExerciseList.js.map +1 -0
  204. package/lib/pedagogy/ui/ExerciseSeries.d.ts +95 -0
  205. package/lib/pedagogy/ui/ExerciseSeries.d.ts.map +1 -0
  206. package/lib/pedagogy/ui/ExerciseSeries.js +74 -0
  207. package/lib/pedagogy/ui/ExerciseSeries.js.map +1 -0
  208. package/lib/pedagogy/ui/QuestionCard.d.ts +64 -0
  209. package/lib/pedagogy/ui/QuestionCard.d.ts.map +1 -0
  210. package/lib/pedagogy/ui/QuestionCard.js +73 -0
  211. package/lib/pedagogy/ui/QuestionCard.js.map +1 -0
  212. package/lib/pedagogy/ui/index.d.ts +10 -0
  213. package/lib/pedagogy/ui/index.d.ts.map +1 -1
  214. package/lib/pedagogy/ui/index.js +6 -0
  215. package/lib/pedagogy/ui/index.js.map +1 -1
  216. package/lib/pedagogy/ui/seriesCounts.d.ts +17 -0
  217. package/lib/pedagogy/ui/seriesCounts.d.ts.map +1 -0
  218. package/lib/pedagogy/ui/seriesCounts.js +27 -0
  219. package/lib/pedagogy/ui/seriesCounts.js.map +1 -0
  220. package/lib/pedagogy/ui/seriesParts.d.ts +55 -0
  221. package/lib/pedagogy/ui/seriesParts.d.ts.map +1 -0
  222. package/lib/pedagogy/ui/seriesParts.js +38 -0
  223. package/lib/pedagogy/ui/seriesParts.js.map +1 -0
  224. package/lib/pedagogy/ui/useAttemptRecords.d.ts +10 -0
  225. package/lib/pedagogy/ui/useAttemptRecords.d.ts.map +1 -0
  226. package/lib/pedagogy/ui/useAttemptRecords.js +11 -0
  227. package/lib/pedagogy/ui/useAttemptRecords.js.map +1 -0
  228. package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
  229. package/lib/periodic/ui/PeriodicTable.js +6 -3
  230. package/lib/periodic/ui/PeriodicTable.js.map +1 -1
  231. package/lib/property/core/copyableText.d.ts +14 -0
  232. package/lib/property/core/copyableText.d.ts.map +1 -0
  233. package/lib/property/core/copyableText.js +21 -0
  234. package/lib/property/core/copyableText.js.map +1 -0
  235. package/lib/property/core/index.d.ts +2 -0
  236. package/lib/property/core/index.d.ts.map +1 -0
  237. package/lib/property/core/index.js +2 -0
  238. package/lib/property/core/index.js.map +1 -0
  239. package/lib/property/ui/PropertyTable.d.ts +43 -0
  240. package/lib/property/ui/PropertyTable.d.ts.map +1 -0
  241. package/lib/property/ui/PropertyTable.js +19 -0
  242. package/lib/property/ui/PropertyTable.js.map +1 -0
  243. package/lib/property/ui/index.d.ts +3 -0
  244. package/lib/property/ui/index.d.ts.map +1 -0
  245. package/lib/property/ui/index.js +2 -0
  246. package/lib/property/ui/index.js.map +1 -0
  247. package/lib/router/core/history.d.ts +24 -3
  248. package/lib/router/core/history.d.ts.map +1 -1
  249. package/lib/router/core/history.js +55 -7
  250. package/lib/router/core/history.js.map +1 -1
  251. package/lib/router/core/index.d.ts +3 -3
  252. package/lib/router/core/index.d.ts.map +1 -1
  253. package/lib/router/core/index.js +2 -2
  254. package/lib/router/core/index.js.map +1 -1
  255. package/lib/router/core/languageRoute.d.ts +61 -0
  256. package/lib/router/core/languageRoute.d.ts.map +1 -0
  257. package/lib/router/core/languageRoute.js +96 -0
  258. package/lib/router/core/languageRoute.js.map +1 -0
  259. package/lib/router/core/siteAddresses.d.ts +23 -0
  260. package/lib/router/core/siteAddresses.d.ts.map +1 -1
  261. package/lib/router/core/siteAddresses.js +26 -0
  262. package/lib/router/core/siteAddresses.js.map +1 -1
  263. package/lib/router/core/tabRouter.d.ts +2 -108
  264. package/lib/router/core/tabRouter.d.ts.map +1 -1
  265. package/lib/router/core/tabRouter.js +38 -5
  266. package/lib/router/core/tabRouter.js.map +1 -1
  267. package/lib/router/core/tabRouterTypes.d.ts +154 -0
  268. package/lib/router/core/tabRouterTypes.d.ts.map +1 -0
  269. package/lib/router/core/tabRouterTypes.js +2 -0
  270. package/lib/router/core/tabRouterTypes.js.map +1 -0
  271. package/lib/seo/core/fitDescription.d.ts +40 -0
  272. package/lib/seo/core/fitDescription.d.ts.map +1 -0
  273. package/lib/seo/core/fitDescription.js +45 -0
  274. package/lib/seo/core/fitDescription.js.map +1 -0
  275. package/lib/seo/core/index.d.ts +7 -0
  276. package/lib/seo/core/index.d.ts.map +1 -1
  277. package/lib/seo/core/index.js +4 -0
  278. package/lib/seo/core/index.js.map +1 -1
  279. package/lib/seo/core/limits.d.ts +24 -0
  280. package/lib/seo/core/limits.d.ts.map +1 -0
  281. package/lib/seo/core/limits.js +24 -0
  282. package/lib/seo/core/limits.js.map +1 -0
  283. package/lib/seo/core/pageContent.d.ts +25 -0
  284. package/lib/seo/core/pageContent.d.ts.map +1 -0
  285. package/lib/seo/core/pageContent.js +25 -0
  286. package/lib/seo/core/pageContent.js.map +1 -0
  287. package/lib/seo/core/plainDescription.d.ts.map +1 -1
  288. package/lib/seo/core/plainDescription.js +3 -2
  289. package/lib/seo/core/plainDescription.js.map +1 -1
  290. package/lib/seo/core/routeProblems.d.ts.map +1 -1
  291. package/lib/seo/core/routeProblems.js +1 -6
  292. package/lib/seo/core/routeProblems.js.map +1 -1
  293. package/lib/seo/core/routeTable.d.ts +31 -0
  294. package/lib/seo/core/routeTable.d.ts.map +1 -0
  295. package/lib/seo/core/routeTable.js +96 -0
  296. package/lib/seo/core/routeTable.js.map +1 -0
  297. package/lib/seo/vite/index.d.ts +2 -0
  298. package/lib/seo/vite/index.d.ts.map +1 -1
  299. package/lib/seo/vite/index.js +1 -0
  300. package/lib/seo/vite/index.js.map +1 -1
  301. package/lib/seo/vite/prerender.d.ts +10 -0
  302. package/lib/seo/vite/prerender.d.ts.map +1 -1
  303. package/lib/seo/vite/prerender.js +12 -1
  304. package/lib/seo/vite/prerender.js.map +1 -1
  305. package/lib/seo/vite/routeTable.d.ts +40 -0
  306. package/lib/seo/vite/routeTable.d.ts.map +1 -0
  307. package/lib/seo/vite/routeTable.js +44 -0
  308. package/lib/seo/vite/routeTable.js.map +1 -0
  309. package/lib/server/answerAddresses.d.ts +51 -0
  310. package/lib/server/answerAddresses.d.ts.map +1 -0
  311. package/lib/server/answerAddresses.js +72 -0
  312. package/lib/server/answerAddresses.js.map +1 -0
  313. package/lib/server/cardMeta.d.ts +57 -0
  314. package/lib/server/cardMeta.d.ts.map +1 -0
  315. package/lib/server/cardMeta.js +52 -0
  316. package/lib/server/cardMeta.js.map +1 -0
  317. package/lib/server/config.d.ts +72 -0
  318. package/lib/server/config.d.ts.map +1 -0
  319. package/lib/server/config.js +67 -0
  320. package/lib/server/config.js.map +1 -0
  321. package/lib/server/envNumber.d.ts +35 -0
  322. package/lib/server/envNumber.d.ts.map +1 -0
  323. package/lib/server/envNumber.js +42 -0
  324. package/lib/server/envNumber.js.map +1 -0
  325. package/lib/server/healthRoute.d.ts +26 -0
  326. package/lib/server/healthRoute.d.ts.map +1 -0
  327. package/lib/server/healthRoute.js +22 -0
  328. package/lib/server/healthRoute.js.map +1 -0
  329. package/lib/server/listenSite.d.ts +38 -0
  330. package/lib/server/listenSite.d.ts.map +1 -0
  331. package/lib/server/listenSite.js +60 -0
  332. package/lib/server/listenSite.js.map +1 -0
  333. package/lib/server/mcpServer.d.ts +8 -0
  334. package/lib/server/mcpServer.d.ts.map +1 -0
  335. package/lib/server/mcpServer.js +11 -0
  336. package/lib/server/mcpServer.js.map +1 -0
  337. package/lib/server/repositoryVersion.d.ts +16 -0
  338. package/lib/server/repositoryVersion.d.ts.map +1 -0
  339. package/lib/server/repositoryVersion.js +33 -0
  340. package/lib/server/repositoryVersion.js.map +1 -0
  341. package/lib/server/routeOptions.d.ts +23 -0
  342. package/lib/server/routeOptions.d.ts.map +1 -0
  343. package/lib/server/routeOptions.js +20 -0
  344. package/lib/server/routeOptions.js.map +1 -0
  345. package/lib/server/routeTable.d.ts +14 -0
  346. package/lib/server/routeTable.d.ts.map +1 -0
  347. package/lib/server/routeTable.js +32 -0
  348. package/lib/server/routeTable.js.map +1 -0
  349. package/lib/server/siteView.d.ts +29 -0
  350. package/lib/server/siteView.d.ts.map +1 -0
  351. package/lib/server/siteView.js +21 -0
  352. package/lib/server/siteView.js.map +1 -0
  353. package/lib/server/spaPages.d.ts +32 -0
  354. package/lib/server/spaPages.d.ts.map +1 -0
  355. package/lib/server/spaPages.js +126 -0
  356. package/lib/server/spaPages.js.map +1 -0
  357. package/lib/server/spaSite.d.ts +30 -0
  358. package/lib/server/spaSite.d.ts.map +1 -0
  359. package/lib/server/spaSite.js +170 -0
  360. package/lib/server/spaSite.js.map +1 -0
  361. package/lib/server/spaSiteOptions.d.ts +126 -0
  362. package/lib/server/spaSiteOptions.d.ts.map +1 -0
  363. package/lib/server/spaSiteOptions.js +2 -0
  364. package/lib/server/spaSiteOptions.js.map +1 -0
  365. package/lib/server/staticSite.d.ts +9 -0
  366. package/lib/server/staticSite.d.ts.map +1 -1
  367. package/lib/server/staticSite.js +41 -19
  368. package/lib/server/staticSite.js.map +1 -1
  369. package/lib/server/toolSiteServer.d.ts +77 -0
  370. package/lib/server/toolSiteServer.d.ts.map +1 -0
  371. package/lib/server/toolSiteServer.js +58 -0
  372. package/lib/server/toolSiteServer.js.map +1 -0
  373. package/lib/server/trustProxy.d.ts +20 -0
  374. package/lib/server/trustProxy.d.ts.map +1 -0
  375. package/lib/server/trustProxy.js +32 -0
  376. package/lib/server/trustProxy.js.map +1 -0
  377. package/lib/server/types.d.ts +13 -0
  378. package/lib/server/types.d.ts.map +1 -0
  379. package/lib/server/types.js +2 -0
  380. package/lib/server/types.js.map +1 -0
  381. package/lib/server.d.ts +22 -0
  382. package/lib/server.d.ts.map +1 -1
  383. package/lib/server.js +12 -0
  384. package/lib/server.js.map +1 -1
  385. package/lib/share/core/config.d.ts +18 -0
  386. package/lib/share/core/config.d.ts.map +1 -1
  387. package/lib/share/core/config.js +33 -2
  388. package/lib/share/core/config.js.map +1 -1
  389. package/lib/share/core/index.d.ts +3 -1
  390. package/lib/share/core/index.d.ts.map +1 -1
  391. package/lib/share/core/index.js +2 -1
  392. package/lib/share/core/index.js.map +1 -1
  393. package/lib/share/core/keySetParam.d.ts +40 -0
  394. package/lib/share/core/keySetParam.d.ts.map +1 -0
  395. package/lib/share/core/keySetParam.js +60 -0
  396. package/lib/share/core/keySetParam.js.map +1 -0
  397. package/lib/share/core/vocabulary.d.ts +8 -0
  398. package/lib/share/core/vocabulary.d.ts.map +1 -1
  399. package/lib/shell/ui/ShareControl.d.ts +75 -0
  400. package/lib/shell/ui/ShareControl.d.ts.map +1 -0
  401. package/lib/shell/ui/ShareControl.js +40 -0
  402. package/lib/shell/ui/ShareControl.js.map +1 -0
  403. package/lib/shell/ui/ShellFrame.d.ts +14 -0
  404. package/lib/shell/ui/ShellFrame.d.ts.map +1 -0
  405. package/lib/shell/ui/ShellFrame.js +45 -0
  406. package/lib/shell/ui/ShellFrame.js.map +1 -0
  407. package/lib/shell/ui/SiteShell.d.ts +251 -0
  408. package/lib/shell/ui/SiteShell.d.ts.map +1 -0
  409. package/lib/shell/ui/SiteShell.js +39 -0
  410. package/lib/shell/ui/SiteShell.js.map +1 -0
  411. package/lib/shell/ui/index.d.ts +5 -0
  412. package/lib/shell/ui/index.d.ts.map +1 -0
  413. package/lib/shell/ui/index.js +3 -0
  414. package/lib/shell/ui/index.js.map +1 -0
  415. package/lib/state/core/index.d.ts +1 -0
  416. package/lib/state/core/index.d.ts.map +1 -1
  417. package/lib/state/core/index.js.map +1 -1
  418. package/lib/state/core/legacyEntries.d.ts +30 -0
  419. package/lib/state/core/legacyEntries.d.ts.map +1 -0
  420. package/lib/state/core/legacyEntries.js +51 -0
  421. package/lib/state/core/legacyEntries.js.map +1 -0
  422. package/lib/state/core/persistBucket.d.ts +26 -2
  423. package/lib/state/core/persistBucket.d.ts.map +1 -1
  424. package/lib/state/core/persistBucket.js +26 -9
  425. package/lib/state/core/persistBucket.js.map +1 -1
  426. package/lib/state/core/persistSignalBucket.d.ts +26 -0
  427. package/lib/state/core/persistSignalBucket.d.ts.map +1 -1
  428. package/lib/state/core/persistSignalBucket.js +31 -0
  429. package/lib/state/core/persistSignalBucket.js.map +1 -1
  430. package/lib/state/core/storageEntry.d.ts +15 -0
  431. package/lib/state/core/storageEntry.d.ts.map +1 -1
  432. package/lib/state/core/storageEntry.js +33 -0
  433. package/lib/state/core/storageEntry.js.map +1 -1
  434. package/lib/structure/ui/StructureExportButton.d.ts +27 -0
  435. package/lib/structure/ui/StructureExportButton.d.ts.map +1 -0
  436. package/lib/structure/ui/StructureExportButton.js +21 -0
  437. package/lib/structure/ui/StructureExportButton.js.map +1 -0
  438. package/lib/structure/ui/index.d.ts +4 -0
  439. package/lib/structure/ui/index.d.ts.map +1 -1
  440. package/lib/structure/ui/index.js +2 -0
  441. package/lib/structure/ui/index.js.map +1 -1
  442. package/lib/structure/ui/useStructureDraft.d.ts +32 -0
  443. package/lib/structure/ui/useStructureDraft.d.ts.map +1 -0
  444. package/lib/structure/ui/useStructureDraft.js +20 -0
  445. package/lib/structure/ui/useStructureDraft.js.map +1 -0
  446. package/lib/ui.d.ts +2 -0
  447. package/lib/ui.d.ts.map +1 -1
  448. package/lib/ui.js +2 -0
  449. package/lib/ui.js.map +1 -1
  450. package/lib/worker/core/index.d.ts +1 -1
  451. package/lib/worker/core/index.d.ts.map +1 -1
  452. package/lib/worker/core/messages.d.ts +4 -2
  453. package/lib/worker/core/messages.d.ts.map +1 -1
  454. package/lib/worker/core/messages.js.map +1 -1
  455. package/lib/worker/core/oclResourcesUrl.d.ts +16 -0
  456. package/lib/worker/core/oclResourcesUrl.d.ts.map +1 -0
  457. package/lib/worker/core/oclResourcesUrl.js +19 -0
  458. package/lib/worker/core/oclResourcesUrl.js.map +1 -0
  459. package/lib/worker/core/serveWorkerRequests.d.ts +8 -0
  460. package/lib/worker/core/serveWorkerRequests.d.ts.map +1 -1
  461. package/lib/worker/core/serveWorkerRequests.js +15 -2
  462. package/lib/worker/core/serveWorkerRequests.js.map +1 -1
  463. package/lib/worker/core/workerChannel.d.ts +3 -4
  464. package/lib/worker/core/workerChannel.d.ts.map +1 -1
  465. package/lib/worker/core/workerChannel.js +72 -67
  466. package/lib/worker/core/workerChannel.js.map +1 -1
  467. package/lib/worker/core/workerChannelParts.d.ts +17 -6
  468. package/lib/worker/core/workerChannelParts.d.ts.map +1 -1
  469. package/lib/worker/core/workerChannelParts.js +20 -4
  470. package/lib/worker/core/workerChannelParts.js.map +1 -1
  471. package/lib/worker/core/workerChannelTypes.d.ts +46 -2
  472. package/lib/worker/core/workerChannelTypes.d.ts.map +1 -1
  473. package/lib/worker/core/workerSlot.d.ts +66 -0
  474. package/lib/worker/core/workerSlot.d.ts.map +1 -0
  475. package/lib/worker/core/workerSlot.js +107 -0
  476. package/lib/worker/core/workerSlot.js.map +1 -0
  477. package/package.json +16 -1
  478. package/src/card/core/cardAddress.ts +100 -0
  479. package/src/card/core/cardPageUrl.ts +97 -0
  480. package/src/card/core/index.ts +6 -0
  481. package/src/card/core/panelRoom.ts +66 -0
  482. package/src/card/ui/CardDetailsButton.tsx +104 -0
  483. package/src/card/ui/CardFigure.tsx +86 -0
  484. package/src/card/ui/CardFrame.tsx +46 -0
  485. package/src/card/ui/CopyTableButton.tsx +81 -0
  486. package/src/card/ui/cardTooltip.ts +18 -0
  487. package/src/card/ui/embed.ts +27 -0
  488. package/src/card/ui/fitCardToFrame.ts +76 -0
  489. package/src/card/ui/holdRoomForPanels.ts +83 -0
  490. package/src/card/ui/index.ts +14 -0
  491. package/src/card/ui/openPanels.ts +106 -0
  492. package/src/card.ts +13 -0
  493. package/src/conformers.ts +4 -0
  494. package/src/core.ts +5 -0
  495. package/src/fetch/core/apiError.ts +65 -0
  496. package/src/fetch/core/fetchJson.ts +129 -0
  497. package/src/fetch/core/index.ts +4 -0
  498. package/src/formula/core/formulaText.ts +96 -0
  499. package/src/formula/core/index.ts +20 -0
  500. package/src/formula/core/normalizeFormula.ts +50 -0
  501. package/src/formula/core/readFormula.ts +211 -0
  502. package/src/formula/ui/CopyableFormula.tsx +51 -0
  503. package/src/formula/ui/FormulaInput.tsx +50 -0
  504. package/src/formula/ui/QuestionFormula.tsx +20 -0
  505. package/src/formula/ui/index.ts +6 -0
  506. package/src/formula.ts +11 -0
  507. package/src/hooks/ui/index.ts +1 -0
  508. package/src/hooks/ui/keyTargets.ts +5 -3
  509. package/src/hooks/ui/useAsync.ts +50 -14
  510. package/src/locales/de.json +37 -0
  511. package/src/locales/en.json +37 -0
  512. package/src/locales/es.json +37 -0
  513. package/src/locales/fr.json +37 -0
  514. package/src/locales/it.json +37 -0
  515. package/src/moleculesClient/core/index.ts +19 -0
  516. package/src/moleculesClient/core/moleculesClient.ts +175 -0
  517. package/src/moleculesClient/core/moleculesClientApi.ts +120 -0
  518. package/src/moleculesClient/core/moleculesTypes.ts +163 -0
  519. package/src/moleculesClient/core/requestRetry.ts +118 -0
  520. package/src/molstar/core/camera.ts +3 -2
  521. package/src/molstar/core/framing.ts +200 -0
  522. package/src/molstar/core/hover.ts +26 -0
  523. package/src/molstar/core/index.ts +21 -1
  524. package/src/pedagogy/core/answers.ts +94 -0
  525. package/src/pedagogy/core/attempts.ts +205 -0
  526. package/src/pedagogy/core/index.ts +36 -0
  527. package/src/pedagogy/core/progressController.ts +116 -0
  528. package/src/pedagogy/core/seed.ts +177 -0
  529. package/src/pedagogy/core/series.ts +82 -0
  530. package/src/pedagogy/ui/AnswerFields.tsx +63 -0
  531. package/src/pedagogy/ui/ExerciseList.tsx +202 -0
  532. package/src/pedagogy/ui/ExerciseSeries.tsx +250 -0
  533. package/src/pedagogy/ui/QuestionCard.tsx +231 -0
  534. package/src/pedagogy/ui/index.ts +18 -0
  535. package/src/pedagogy/ui/seriesCounts.ts +34 -0
  536. package/src/pedagogy/ui/seriesParts.tsx +127 -0
  537. package/src/pedagogy/ui/useAttemptRecords.ts +16 -0
  538. package/src/periodic/ui/PeriodicTable.tsx +6 -3
  539. package/src/property/core/copyableText.ts +20 -0
  540. package/src/property/core/index.ts +1 -0
  541. package/src/property/ui/PropertyTable.tsx +83 -0
  542. package/src/property/ui/index.ts +2 -0
  543. package/src/router/core/history.ts +61 -7
  544. package/src/router/core/index.ts +3 -2
  545. package/src/router/core/languageRoute.ts +136 -0
  546. package/src/router/core/siteAddresses.ts +38 -0
  547. package/src/router/core/tabRouter.ts +59 -117
  548. package/src/router/core/tabRouterTypes.ts +158 -0
  549. package/src/seo/core/fitDescription.ts +74 -0
  550. package/src/seo/core/index.ts +17 -0
  551. package/src/seo/core/limits.ts +27 -0
  552. package/src/seo/core/pageContent.ts +42 -0
  553. package/src/seo/core/plainDescription.ts +4 -2
  554. package/src/seo/core/routeProblems.ts +1 -7
  555. package/src/seo/core/routeTable.ts +103 -0
  556. package/src/seo/vite/index.ts +2 -0
  557. package/src/seo/vite/prerender.ts +26 -1
  558. package/src/seo/vite/routeTable.ts +79 -0
  559. package/src/server/answerAddresses.ts +92 -0
  560. package/src/server/cardMeta.ts +88 -0
  561. package/src/server/config.ts +125 -0
  562. package/src/server/envNumber.ts +65 -0
  563. package/src/server/healthRoute.ts +42 -0
  564. package/src/server/listenSite.ts +90 -0
  565. package/src/server/mcpServer.ts +14 -0
  566. package/src/server/repositoryVersion.ts +33 -0
  567. package/src/server/routeOptions.ts +26 -0
  568. package/src/server/routeTable.ts +35 -0
  569. package/src/server/siteView.ts +42 -0
  570. package/src/server/spaPages.ts +179 -0
  571. package/src/server/spaSite.ts +216 -0
  572. package/src/server/spaSiteOptions.ts +133 -0
  573. package/src/server/staticSite.ts +65 -35
  574. package/src/server/toolSiteServer.ts +127 -0
  575. package/src/server/trustProxy.ts +32 -0
  576. package/src/server/types.ts +25 -0
  577. package/src/server.ts +40 -0
  578. package/src/share/core/config.ts +45 -2
  579. package/src/share/core/index.ts +4 -0
  580. package/src/share/core/keySetParam.ts +92 -0
  581. package/src/share/core/vocabulary.ts +8 -0
  582. package/src/shell/ui/ShareControl.tsx +150 -0
  583. package/src/shell/ui/ShellFrame.tsx +180 -0
  584. package/src/shell/ui/SiteShell.tsx +297 -0
  585. package/src/shell/ui/index.ts +9 -0
  586. package/src/state/core/index.ts +1 -0
  587. package/src/state/core/legacyEntries.ts +76 -0
  588. package/src/state/core/persistBucket.ts +50 -10
  589. package/src/state/core/persistSignalBucket.ts +52 -0
  590. package/src/state/core/storageEntry.ts +32 -0
  591. package/src/structure/ui/StructureExportButton.tsx +57 -0
  592. package/src/structure/ui/index.ts +4 -0
  593. package/src/structure/ui/useStructureDraft.ts +47 -0
  594. package/src/ui.ts +2 -0
  595. package/src/worker/core/index.ts +1 -0
  596. package/src/worker/core/messages.ts +4 -3
  597. package/src/worker/core/oclResourcesUrl.ts +21 -0
  598. package/src/worker/core/serveWorkerRequests.ts +30 -2
  599. package/src/worker/core/workerChannel.ts +74 -74
  600. package/src/worker/core/workerChannelParts.ts +33 -13
  601. package/src/worker/core/workerChannelTypes.ts +47 -2
  602. package/src/worker/core/workerSlot.ts +181 -0
  603. package/styles/card.css +145 -0
  604. package/styles/chrome.css +248 -0
@@ -0,0 +1,127 @@
1
+ import type { FastifyInstance, FastifyServerOptions } from 'fastify';
2
+
3
+ import { siteById } from '../ecosystem/core/lookup.ts';
4
+ import type { SiteId } from '../ecosystem/core/sites.ts';
5
+
6
+ import type { ServerConfig } from './config.ts';
7
+ import type { ListenSiteOptions } from './listenSite.ts';
8
+ import { listenSite } from './listenSite.ts';
9
+ import { readRepositoryVersion } from './repositoryVersion.ts';
10
+ import { DEFAULT_RESERVED } from './routeOptions.ts';
11
+ import { staticSite } from './staticSite.ts';
12
+
13
+ /** What a site's API is registered with. */
14
+ export interface ToolSiteContext {
15
+ /** The site, as `ECOSYSTEM_SITES` names it. */
16
+ siteId: SiteId;
17
+ /** Its host, `osiris.cheminfo.org`: what the tool server and its documentation are called. */
18
+ name: string;
19
+ /** The release the repository is at. */
20
+ version: string;
21
+ /** The configuration the server was built with. */
22
+ config: ServerConfig;
23
+ }
24
+
25
+ /** Options of {@link toolSiteServer}. */
26
+ export interface ToolSiteServerOptions {
27
+ /** The site, as `ECOSYSTEM_SITES` names it. */
28
+ siteId: SiteId;
29
+ /** The configuration, from `readServerConfig`. */
30
+ config: ServerConfig;
31
+ /**
32
+ * Register the API beside the pages: the tool routes of
33
+ * `cheminfo-mcp-server` under `/v1`, their documentation at `/docs`.
34
+ */
35
+ registerApi: (
36
+ app: FastifyInstance,
37
+ context: ToolSiteContext,
38
+ ) => void | Promise<void>;
39
+ /**
40
+ * Addresses the site does not have any more, and the one that does their
41
+ * work; the query is carried over.
42
+ * @default {}
43
+ */
44
+ redirects?: Readonly<Record<string, string>>;
45
+ /**
46
+ * Whether, and how, Fastify logs.
47
+ * @default true
48
+ */
49
+ logger?: FastifyServerOptions['logger'];
50
+ /**
51
+ * Address prefixes the API answers, which never answer a page.
52
+ * @default ['/v1/', '/docs']
53
+ */
54
+ reserved?: readonly string[];
55
+ /**
56
+ * The release the API reports.
57
+ * @default the root `package.json` of the repository the process runs in
58
+ */
59
+ version?: string;
60
+ }
61
+
62
+ /**
63
+ * Build a tool site's server without listening: the API the site registers,
64
+ * then the same build the static host serves, by the static hosts' rules.
65
+ *
66
+ * The page never calls the API — it computes in the browser — so the server only
67
+ * adds: the tools under `/v1` for chats and MCP clients, documented at `/docs`.
68
+ *
69
+ * const app = await toolSiteServer({
70
+ * siteId: 'osiris',
71
+ * config,
72
+ * registerApi: (app, { name, version }) => registerTools(app, name, version),
73
+ * });
74
+ * @param options - The site, its configuration and its API.
75
+ * @returns The server, ready to listen or to be injected in tests.
76
+ */
77
+ export async function toolSiteServer(
78
+ options: ToolSiteServerOptions,
79
+ ): Promise<FastifyInstance> {
80
+ const {
81
+ siteId,
82
+ config,
83
+ registerApi,
84
+ redirects = {},
85
+ logger = true,
86
+ reserved = DEFAULT_RESERVED,
87
+ } = options;
88
+ // An optional peer, installed only by a site that has a server.
89
+ const { fastify } = await import('fastify');
90
+ const app = fastify({ logger, trustProxy: config.trustProxy });
91
+ const version = options.version ?? readRepositoryVersion(process.cwd());
92
+ await registerApi(app, {
93
+ siteId,
94
+ name: siteById(siteId).host,
95
+ version,
96
+ config,
97
+ });
98
+ await app.register(staticSite, {
99
+ root: config.root,
100
+ trackingScript: config.trackingScript,
101
+ redirects,
102
+ reserved,
103
+ basePath: config.basePath,
104
+ });
105
+ return app;
106
+ }
107
+
108
+ /**
109
+ * Build a site's server from its configuration, listen where it says, and close
110
+ * cleanly when the container is stopped — the whole of a `main.ts`:
111
+ *
112
+ * await startToolServer(buildServer, readServerConfig(process.env, SITE));
113
+ * @param build - Builds the server, e.g. with {@link toolSiteServer}.
114
+ * @param config - The configuration, from `readServerConfig`.
115
+ * @param options - What else to stop, and on which signals.
116
+ * @returns The server, listening.
117
+ * @throws {Error} When the server cannot listen, after it has been closed.
118
+ */
119
+ export async function startToolServer(
120
+ build: (config: ServerConfig) => FastifyInstance | Promise<FastifyInstance>,
121
+ config: ServerConfig,
122
+ options: Pick<ListenSiteOptions, 'onClose' | 'signals'> = {},
123
+ ): Promise<FastifyInstance> {
124
+ const app = await build(config);
125
+ await listenSite(app, { ...options, port: config.port, host: config.host });
126
+ return app;
127
+ }
@@ -0,0 +1,32 @@
1
+ /** A value that is only digits: a hop count. */
2
+ const HOP_COUNT = /^\d+$/;
3
+
4
+ /**
5
+ * Read which reverse proxies a deployment names, for Fastify's `trustProxy`.
6
+ *
7
+ * Behind a proxy, `request.ip` is the proxy's address on every request and
8
+ * `request.protocol` reads `http` for an HTTPS client, so the variable names the
9
+ * proxy whose `X-Forwarded-For` is believed: an address, a CIDR range, or a
10
+ * comma-separated list of either. `true` believes any peer, which is only safe
11
+ * when the port is unreachable except through the proxy.
12
+ *
13
+ * A hop count is refused. Fastify 5.12.7 and later trust nothing for a number,
14
+ * since a hop count cannot tell the proxy from a client, so the service would
15
+ * silently log the proxy's address again — and a function over the hop, the
16
+ * usual way around it, believes any peer that sends enough addresses.
17
+ * @param value - `TRUST_PROXY`, as written.
18
+ * @returns The proxies as written, `true` to believe any peer, or `false` when
19
+ * the variable is unset, blank or `false`.
20
+ * @throws {Error} When the value is a hop count.
21
+ */
22
+ export function parseTrustProxy(value: string | undefined): boolean | string {
23
+ const text = value?.trim();
24
+ if (!text || text.toLowerCase() === 'false') return false;
25
+ if (text.toLowerCase() === 'true') return true;
26
+ if (HOP_COUNT.test(text)) {
27
+ throw new Error(
28
+ `TRUST_PROXY=${text} is a hop count, which trusts nothing. Name the proxy's address or CIDR instead.`,
29
+ );
30
+ }
31
+ return text;
32
+ }
@@ -0,0 +1,25 @@
1
+ import type { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
2
+ import type {
3
+ FastifyBaseLogger,
4
+ FastifyInstance,
5
+ RawReplyDefaultExpression,
6
+ RawRequestDefaultExpression,
7
+ RawServerDefault,
8
+ } from 'fastify';
9
+
10
+ /**
11
+ * A Fastify instance whose routes are typed from their TypeBox schemas: the
12
+ * `body`, `params`, `querystring` and response of a route registered on it are
13
+ * inferred. A route module takes it as its parameter, and the server is built
14
+ * with `fastify(options).withTypeProvider<TypeBoxTypeProvider>()`.
15
+ *
16
+ * Types only: `@fastify/type-provider-typebox` is an optional peer, installed by
17
+ * the backends that type their routes this way.
18
+ */
19
+ export type FastifyTyped = FastifyInstance<
20
+ RawServerDefault,
21
+ RawRequestDefaultExpression,
22
+ RawReplyDefaultExpression,
23
+ FastifyBaseLogger,
24
+ TypeBoxTypeProvider
25
+ >;
package/src/server.ts CHANGED
@@ -5,3 +5,43 @@ export {
5
5
  listSiteFiles,
6
6
  resolveAddress,
7
7
  } from './server/siteFiles.ts';
8
+ export type {
9
+ ServerConfig,
10
+ ServerConfigOptions,
11
+ ServerEnvironment,
12
+ } from './server/config.ts';
13
+ export { readHttpAddress, readServerConfig } from './server/config.ts';
14
+ export type { ReadEnvNumberOptions } from './server/envNumber.ts';
15
+ export { readEnvNumber } from './server/envNumber.ts';
16
+ export type { HealthRouteOptions } from './server/healthRoute.ts';
17
+ export { healthRoute } from './server/healthRoute.ts';
18
+ export type { ListenSiteOptions } from './server/listenSite.ts';
19
+ export { listenSite } from './server/listenSite.ts';
20
+ export { readRepositoryVersion } from './server/repositoryVersion.ts';
21
+ export { readRouteTable } from './server/routeTable.ts';
22
+ export { spaSite } from './server/spaSite.ts';
23
+ export type {
24
+ SpaPage,
25
+ SpaSiteOptions,
26
+ SpaStructuredData,
27
+ } from './server/spaSiteOptions.ts';
28
+ export type {
29
+ ToolSiteContext,
30
+ ToolSiteServerOptions,
31
+ } from './server/toolSiteServer.ts';
32
+ export { startToolServer, toolSiteServer } from './server/toolSiteServer.ts';
33
+ export { parseTrustProxy } from './server/trustProxy.ts';
34
+ export type { FastifyTyped } from './server/types.ts';
35
+ export type {
36
+ AnswerAddresses,
37
+ AnswerAddressesInput,
38
+ } from './server/answerAddresses.ts';
39
+ export {
40
+ answerAddresses,
41
+ joinAddress,
42
+ viewOrigins,
43
+ } from './server/answerAddresses.ts';
44
+ export type { CardMetaOptions, PageAnswer } from './server/cardMeta.ts';
45
+ export { cardMeta, pageAnswer } from './server/cardMeta.ts';
46
+ export type { SiteViewOptions } from './server/siteView.ts';
47
+ export { siteView } from './server/siteView.ts';
@@ -41,9 +41,12 @@ export function parseShareConfig<
41
41
  >(search: string, vocabulary: ShareVocabulary<Codecs>): ShareConfig<Codecs> {
42
42
  const values = firstValues(parseQuery(search));
43
43
  const embed = values.get(EMBED_PARAM);
44
+ const asked = splitHidden(values.get(HIDE_PARAM));
44
45
  return {
45
- embed: embed !== undefined && embed !== '0',
46
- hidden: orderHidden(splitHidden(values.get(HIDE_PARAM)), vocabulary.parts),
46
+ embed:
47
+ (embed !== undefined && embed !== '0') ||
48
+ namesAny(asked, vocabulary.legacyEmbedParts ?? []),
49
+ hidden: orderHidden(asked, vocabulary.parts),
47
50
  params: readParams(values, vocabulary.params) as ShareParamValues<Codecs>,
48
51
  };
49
52
  }
@@ -154,6 +157,46 @@ export function suggestedShareConfig<
154
157
  return { ...parseShareConfig('', vocabulary), embed: true, hidden };
155
158
  }
156
159
 
160
+ /**
161
+ * Read the parts a `?hide=` value switches off, for a page that holds its
162
+ * query decoded rather than as a string.
163
+ * @param raw - The raw value, comma separated; `undefined` when absent.
164
+ * @param parts - The hideable parts, in the vocabulary order.
165
+ * @returns The keys of the parts named, in that order; a key the vocabulary
166
+ * does not list is dropped, so a hand-written link cannot hide what it cannot
167
+ * name.
168
+ */
169
+ export function readHiddenParts(
170
+ raw: string | undefined,
171
+ parts: readonly HideablePart[],
172
+ ): readonly string[] {
173
+ return orderHidden(splitHidden(raw), parts);
174
+ }
175
+
176
+ /**
177
+ * Write a `?hide=` value in the vocabulary order, so one selection always
178
+ * produces one link.
179
+ * @param hidden - The keys switched off, in any order and any collection.
180
+ * @param parts - The hideable parts, in the vocabulary order.
181
+ * @returns The value, empty when nothing the vocabulary lists is switched off.
182
+ */
183
+ export function formatHiddenParts(
184
+ hidden: Iterable<string>,
185
+ parts: readonly HideablePart[],
186
+ ): string {
187
+ return orderHidden(new Set(hidden), parts).join(',');
188
+ }
189
+
190
+ function namesAny(
191
+ asked: ReadonlySet<string>,
192
+ keys: readonly string[],
193
+ ): boolean {
194
+ for (const key of keys) {
195
+ if (asked.has(key)) return true;
196
+ }
197
+ return false;
198
+ }
199
+
157
200
  function splitHidden(raw: string | undefined): ReadonlySet<string> {
158
201
  const asked = new Set<string>();
159
202
  if (raw === undefined) return asked;
@@ -3,9 +3,11 @@ export {
3
3
  EMBED_PARAM,
4
4
  HIDE_PARAM,
5
5
  applyShareConfig,
6
+ formatHiddenParts,
6
7
  isHidden,
7
8
  isShareConfigured,
8
9
  parseShareConfig,
10
+ readHiddenParts,
9
11
  suggestedShareConfig,
10
12
  visibleShareParts,
11
13
  } from './config.ts';
@@ -17,6 +19,8 @@ export {
17
19
  sharePreviewSize,
18
20
  } from './devices.ts';
19
21
  export { escapeAttribute, escapeText } from './escape.ts';
22
+ export type { KeySetParamOptions } from './keySetParam.ts';
23
+ export { keySetParam } from './keySetParam.ts';
20
24
  export type { ShareRegion } from './regions.ts';
21
25
  export {
22
26
  SHARE_REGIONS_MESSAGE,
@@ -0,0 +1,92 @@
1
+ import type { ShareParamCodec } from './params.ts';
2
+
3
+ /** What {@link keySetParam} is configured with. */
4
+ export interface KeySetParamOptions<Key extends string> {
5
+ /**
6
+ * The word an empty set is written as. An empty value is dropped from the
7
+ * address, so a link switching every key off has to say so in a word.
8
+ * @default 'none'
9
+ */
10
+ none?: string;
11
+ /**
12
+ * The set a link carrying nothing stands for, and the one deleted rather
13
+ * than written. `null` means the link then says nothing about the keys, so
14
+ * whatever the visitor stored is left alone.
15
+ * @default null
16
+ */
17
+ default?: readonly Key[] | null;
18
+ /**
19
+ * The set deleted from a link rather than written, when it is not the
20
+ * default — a site whose absent parameter leaves the visitor's stored keys
21
+ * alone, and whose own initial keys must not grow a plain visit a query
22
+ * string.
23
+ * @default the default set
24
+ */
25
+ omitted?: readonly Key[];
26
+ }
27
+
28
+ /**
29
+ * A set of keys a link switches on — the layers a figure draws,
30
+ * `?flags=breakdown,working` — written comma separated, in the order the keys
31
+ * are listed, so one selection always produces one link.
32
+ *
33
+ * A key the tool does not list is dropped rather than refused, so a link
34
+ * written before a key was renamed still opens; the word for nothing, `none`
35
+ * by default, reads as the empty set, and an absent or empty parameter as the
36
+ * default.
37
+ * @param keys - Every key the tool understands, in the order links write them.
38
+ * @param options - The word for nothing, and the default set.
39
+ * @returns The codec.
40
+ */
41
+ export function keySetParam<Key extends string>(
42
+ keys: readonly Key[],
43
+ options: KeySetParamOptions<Key> = {},
44
+ ): ShareParamCodec<ReadonlySet<Key> | null> {
45
+ const none = options.none ?? 'none';
46
+ const fallback =
47
+ options.default === undefined || options.default === null
48
+ ? null
49
+ : orderKeys(new Set<string>(options.default), keys);
50
+ const omitted =
51
+ options.omitted === undefined
52
+ ? fallback
53
+ : orderKeys(new Set<string>(options.omitted), keys);
54
+ const omittedText = omitted === null ? null : writeKeys(omitted, keys);
55
+ return {
56
+ parse(raw) {
57
+ if (raw === null || raw.trim() === '') return fallback;
58
+ if (raw.trim() === none) return new Set<Key>();
59
+ const asked = new Set<string>();
60
+ for (const name of raw.split(',')) asked.add(name.trim());
61
+ return orderKeys(asked, keys);
62
+ },
63
+ serialize(value) {
64
+ if (value === null) return null;
65
+ const text = writeKeys(value, keys);
66
+ if (text === omittedText) return null;
67
+ return text === '' ? none : text;
68
+ },
69
+ };
70
+ }
71
+
72
+ function orderKeys<Key extends string>(
73
+ asked: ReadonlySet<string>,
74
+ keys: readonly Key[],
75
+ ): ReadonlySet<Key> {
76
+ const ordered = new Set<Key>();
77
+ for (const key of keys) {
78
+ if (asked.has(key)) ordered.add(key);
79
+ }
80
+ return ordered;
81
+ }
82
+
83
+ function writeKeys<Key extends string>(
84
+ value: ReadonlySet<Key>,
85
+ keys: readonly Key[],
86
+ ): string {
87
+ const on: string[] = [];
88
+ for (const key of keys) {
89
+ if (value.has(key)) on.push(key);
90
+ }
91
+ return on.join(',');
92
+ }
@@ -65,4 +65,12 @@ export interface ShareVocabulary<
65
65
  * @default {}
66
66
  */
67
67
  params?: Codecs;
68
+ /**
69
+ * The `?hide=` keys older links dropped the chrome with, before the site
70
+ * spoke `?embed` — `header`, `menu`. A link naming one still opens framed,
71
+ * because course pages built then must keep opening bare; the key is no part
72
+ * of the page, so it is never offered and never written back.
73
+ * @default []
74
+ */
75
+ legacyEmbedParts?: readonly string[];
68
76
  }
@@ -0,0 +1,150 @@
1
+ import type { ReactElement } from 'react';
2
+ import { useState } from 'react';
3
+
4
+ import { siteById } from '../../ecosystem/core/lookup.ts';
5
+ import type { SiteId } from '../../ecosystem/core/sites.ts';
6
+ import { useChromeT } from '../../i18n/ui/useT.ts';
7
+ import type { ShareParamCodecs } from '../../share/core/index.ts';
8
+ import type { ShareButtonVariant } from '../../share/ui/ShareButton.tsx';
9
+ import { ShareButton } from '../../share/ui/ShareButton.tsx';
10
+ import type { ShareDialogProps } from '../../share/ui/ShareDialog.tsx';
11
+ import { ShareDialog } from '../../share/ui/ShareDialog.tsx';
12
+
13
+ /** What {@link ShareControl} needs: the dialog's props, and the button's. */
14
+ export interface ShareControlProps<
15
+ Codecs extends ShareParamCodecs = Record<string, never>,
16
+ > extends Omit<
17
+ ShareDialogProps<Codecs>,
18
+ 'isOpen' | 'onClose' | 'search' | 'frameTitle'
19
+ > {
20
+ /**
21
+ * The site the page belongs to, which names the frame `<host> — <title>`.
22
+ * @default undefined — the frame is named by the title alone
23
+ */
24
+ siteId?: SiteId;
25
+ /**
26
+ * What a screen reader announces the frame as.
27
+ * @default `<host> — <title>` with a `siteId`, the title without one
28
+ */
29
+ frameTitle?: string;
30
+ /**
31
+ * The address as it stands, so the tool's inputs travel with the link. A
32
+ * function is called only while the dialog is open, so a value that is costly
33
+ * to write — a pinned preference, a list of molecules — is written when a
34
+ * link is asked for and not on every render of the header.
35
+ * @default the query string of the page
36
+ */
37
+ search?: string | (() => string | undefined);
38
+ /**
39
+ * Whether the button keeps only its icon, in a bar that has run out of room.
40
+ * @default false
41
+ */
42
+ compact?: boolean;
43
+ /**
44
+ * Text of the button.
45
+ * @default the chrome's own word for it, in the language of the page
46
+ */
47
+ buttonLabel?: string;
48
+ /**
49
+ * What the pointer is told over the button.
50
+ * @default the chrome's own line, in the language of the page
51
+ */
52
+ buttonTitle?: string;
53
+ /**
54
+ * A plain bar entry, or a Blueprint button for a toolbar made of them.
55
+ * @default 'nav-link'
56
+ */
57
+ variant?: ShareButtonVariant;
58
+ /**
59
+ * Whether the dialog is open, for a page that has to know — to compute what
60
+ * the dialog shows only while it is. Pass it with `onOpenChange`.
61
+ * @default undefined — the control keeps the state itself
62
+ */
63
+ open?: boolean;
64
+ /**
65
+ * Called when the dialog opens or closes.
66
+ * @default undefined
67
+ */
68
+ onOpenChange?: (open: boolean) => void;
69
+ /**
70
+ * Called as the button is pressed, before the dialog opens — to write the
71
+ * page's state into the address the link is read from.
72
+ * @default undefined
73
+ */
74
+ onOpen?: () => void;
75
+ }
76
+
77
+ /**
78
+ * The Share entry of a header and the dialog it opens: the page handed out as a
79
+ * link, or as the iframe that frames it in somebody else's site.
80
+ *
81
+ * It is what a header's `share` prop takes, so the entry lands after Contact on
82
+ * every site. Everything the dialog can be told is passed straight through; the
83
+ * control adds the open state, and the frame's name read off the site.
84
+ * @param props - The dialog's props, and how the button is dressed.
85
+ * @returns The button, and the dialog while it is open.
86
+ */
87
+ export function ShareControl<
88
+ Codecs extends ShareParamCodecs = Record<string, never>,
89
+ >(props: ShareControlProps<Codecs>): ReactElement {
90
+ const {
91
+ siteId,
92
+ frameTitle,
93
+ search,
94
+ compact = false,
95
+ buttonLabel,
96
+ buttonTitle,
97
+ variant,
98
+ open,
99
+ onOpenChange,
100
+ onOpen,
101
+ title,
102
+ ...dialog
103
+ } = props;
104
+ const t = useChromeT();
105
+ const [ownOpen, setOwnOpen] = useState(false);
106
+ const isOpen = open ?? ownOpen;
107
+
108
+ function setOpen(next: boolean): void {
109
+ if (open === undefined) setOwnOpen(next);
110
+ onOpenChange?.(next);
111
+ }
112
+
113
+ const host = siteId === undefined ? undefined : siteById(siteId).host;
114
+ const named =
115
+ frameTitle ??
116
+ (host === undefined ? title : t('share.frameTitle', { site: host, title }));
117
+
118
+ return (
119
+ <>
120
+ <ShareButton
121
+ compact={compact}
122
+ label={buttonLabel}
123
+ title={buttonTitle}
124
+ variant={variant}
125
+ onClick={() => {
126
+ onOpen?.();
127
+ setOpen(true);
128
+ }}
129
+ />
130
+ <ShareDialog<Codecs>
131
+ {...dialog}
132
+ title={title}
133
+ frameTitle={named}
134
+ search={
135
+ isOpen && typeof search === 'function' ? search() : searchText(search)
136
+ }
137
+ isOpen={isOpen}
138
+ onClose={() => {
139
+ setOpen(false);
140
+ }}
141
+ />
142
+ </>
143
+ );
144
+ }
145
+
146
+ function searchText(
147
+ search: string | (() => string | undefined) | undefined,
148
+ ): string | undefined {
149
+ return typeof search === 'string' ? search : undefined;
150
+ }