react-cheminfo 0.64.1 → 0.66.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 (827) hide show
  1. package/README.md +293 -6
  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/ir/core/analysisSpectra.d.ts +23 -6
  132. package/lib/ir/core/analysisSpectra.d.ts.map +1 -1
  133. package/lib/ir/core/analysisSpectra.js.map +1 -1
  134. package/lib/ir/core/bandLabelPlan.d.ts.map +1 -1
  135. package/lib/ir/core/bandLabelPlan.js +11 -6
  136. package/lib/ir/core/bandLabelPlan.js.map +1 -1
  137. package/lib/ir/core/index.d.ts +13 -9
  138. package/lib/ir/core/index.d.ts.map +1 -1
  139. package/lib/ir/core/index.js +9 -6
  140. package/lib/ir/core/index.js.map +1 -1
  141. package/lib/ir/core/irBand.d.ts +45 -14
  142. package/lib/ir/core/irBand.d.ts.map +1 -1
  143. package/lib/ir/core/irBand.js +28 -6
  144. package/lib/ir/core/irBand.js.map +1 -1
  145. package/lib/ir/core/irCommands.d.ts +11 -0
  146. package/lib/ir/core/irCommands.d.ts.map +1 -1
  147. package/lib/ir/core/irCommands.js +11 -1
  148. package/lib/ir/core/irCommands.js.map +1 -1
  149. package/lib/ir/core/irDomain.d.ts +4 -3
  150. package/lib/ir/core/irDomain.d.ts.map +1 -1
  151. package/lib/ir/core/irDomain.js +10 -7
  152. package/lib/ir/core/irDomain.js.map +1 -1
  153. package/lib/ir/core/irFormat.d.ts +14 -2
  154. package/lib/ir/core/irFormat.d.ts.map +1 -1
  155. package/lib/ir/core/irFormat.js +33 -4
  156. package/lib/ir/core/irFormat.js.map +1 -1
  157. package/lib/ir/core/irMode.d.ts +35 -8
  158. package/lib/ir/core/irMode.d.ts.map +1 -1
  159. package/lib/ir/core/irMode.js +38 -10
  160. package/lib/ir/core/irMode.js.map +1 -1
  161. package/lib/ir/core/irReducer.d.ts +0 -28
  162. package/lib/ir/core/irReducer.d.ts.map +1 -1
  163. package/lib/ir/core/irReducer.js +1 -24
  164. package/lib/ir/core/irReducer.js.map +1 -1
  165. package/lib/ir/core/irSpectrum.d.ts +52 -26
  166. package/lib/ir/core/irSpectrum.d.ts.map +1 -1
  167. package/lib/ir/core/irSpectrum.js +21 -15
  168. package/lib/ir/core/irSpectrum.js.map +1 -1
  169. package/lib/ir/core/irState.d.ts +40 -2
  170. package/lib/ir/core/irState.d.ts.map +1 -1
  171. package/lib/ir/core/irState.js +38 -1
  172. package/lib/ir/core/irState.js.map +1 -1
  173. package/lib/ir/core/irTechnique.d.ts +94 -0
  174. package/lib/ir/core/irTechnique.d.ts.map +1 -0
  175. package/lib/ir/core/irTechnique.js +87 -0
  176. package/lib/ir/core/irTechnique.js.map +1 -0
  177. package/lib/ir/core/irTechniqueCommands.d.ts +26 -0
  178. package/lib/ir/core/irTechniqueCommands.d.ts.map +1 -0
  179. package/lib/ir/core/irTechniqueCommands.js +68 -0
  180. package/lib/ir/core/irTechniqueCommands.js.map +1 -0
  181. package/lib/ir/core/pickBands.d.ts +6 -5
  182. package/lib/ir/core/pickBands.d.ts.map +1 -1
  183. package/lib/ir/core/pickBands.js +49 -26
  184. package/lib/ir/core/pickBands.js.map +1 -1
  185. package/lib/ir/core/ramanBands.d.ts +30 -0
  186. package/lib/ir/core/ramanBands.d.ts.map +1 -0
  187. package/lib/ir/core/ramanBands.js +83 -0
  188. package/lib/ir/core/ramanBands.js.map +1 -0
  189. package/lib/ir/core/spectrumJcamp.d.ts +10 -5
  190. package/lib/ir/core/spectrumJcamp.d.ts.map +1 -1
  191. package/lib/ir/core/spectrumJcamp.js +63 -15
  192. package/lib/ir/core/spectrumJcamp.js.map +1 -1
  193. package/lib/ir/core/toIrSpectrum.d.ts.map +1 -1
  194. package/lib/ir/core/toIrSpectrum.js +17 -2
  195. package/lib/ir/core/toIrSpectrum.js.map +1 -1
  196. package/lib/ir/ui/BandRow.d.ts +30 -0
  197. package/lib/ir/ui/BandRow.d.ts.map +1 -0
  198. package/lib/ir/ui/BandRow.js +42 -0
  199. package/lib/ir/ui/BandRow.js.map +1 -0
  200. package/lib/ir/ui/BandsPanel.d.ts +4 -0
  201. package/lib/ir/ui/BandsPanel.d.ts.map +1 -1
  202. package/lib/ir/ui/BandsPanel.js +14 -59
  203. package/lib/ir/ui/BandsPanel.js.map +1 -1
  204. package/lib/ir/ui/IrAboutDialog.d.ts +7 -0
  205. package/lib/ir/ui/IrAboutDialog.d.ts.map +1 -1
  206. package/lib/ir/ui/IrAboutDialog.js +16 -3
  207. package/lib/ir/ui/IrAboutDialog.js.map +1 -1
  208. package/lib/ir/ui/IrCanvas.d.ts.map +1 -1
  209. package/lib/ir/ui/IrCanvas.js +2 -2
  210. package/lib/ir/ui/IrCanvas.js.map +1 -1
  211. package/lib/ir/ui/IrChart.d.ts +2 -1
  212. package/lib/ir/ui/IrChart.d.ts.map +1 -1
  213. package/lib/ir/ui/IrChart.js +18 -21
  214. package/lib/ir/ui/IrChart.js.map +1 -1
  215. package/lib/ir/ui/IrCommandProvider.d.ts +7 -0
  216. package/lib/ir/ui/IrCommandProvider.d.ts.map +1 -1
  217. package/lib/ir/ui/IrCommandProvider.js +2 -2
  218. package/lib/ir/ui/IrCommandProvider.js.map +1 -1
  219. package/lib/ir/ui/IrCommandTooltip.d.ts +7 -0
  220. package/lib/ir/ui/IrCommandTooltip.d.ts.map +1 -1
  221. package/lib/ir/ui/IrCommandTooltip.js +3 -2
  222. package/lib/ir/ui/IrCommandTooltip.js.map +1 -1
  223. package/lib/ir/ui/IrDocumentationDialog.d.ts +8 -1
  224. package/lib/ir/ui/IrDocumentationDialog.d.ts.map +1 -1
  225. package/lib/ir/ui/IrDocumentationDialog.js +30 -7
  226. package/lib/ir/ui/IrDocumentationDialog.js.map +1 -1
  227. package/lib/ir/ui/IrEditor.d.ts +3 -1
  228. package/lib/ir/ui/IrEditor.d.ts.map +1 -1
  229. package/lib/ir/ui/IrEditor.js +3 -20
  230. package/lib/ir/ui/IrEditor.js.map +1 -1
  231. package/lib/ir/ui/IrHeader.d.ts.map +1 -1
  232. package/lib/ir/ui/IrHeader.js +5 -1
  233. package/lib/ir/ui/IrHeader.js.map +1 -1
  234. package/lib/ir/ui/IrLogo.d.ts +11 -3
  235. package/lib/ir/ui/IrLogo.d.ts.map +1 -1
  236. package/lib/ir/ui/IrLogo.js +14 -5
  237. package/lib/ir/ui/IrLogo.js.map +1 -1
  238. package/lib/ir/ui/IrShell.d.ts.map +1 -1
  239. package/lib/ir/ui/IrShell.js +23 -56
  240. package/lib/ir/ui/IrShell.js.map +1 -1
  241. package/lib/ir/ui/IrStatusBar.d.ts +3 -2
  242. package/lib/ir/ui/IrStatusBar.d.ts.map +1 -1
  243. package/lib/ir/ui/IrStatusBar.js +14 -9
  244. package/lib/ir/ui/IrStatusBar.js.map +1 -1
  245. package/lib/ir/ui/IrToolbar.d.ts +3 -0
  246. package/lib/ir/ui/IrToolbar.d.ts.map +1 -1
  247. package/lib/ir/ui/IrToolbar.js +10 -3
  248. package/lib/ir/ui/IrToolbar.js.map +1 -1
  249. package/lib/ir/ui/IrTraces.d.ts +4 -1
  250. package/lib/ir/ui/IrTraces.d.ts.map +1 -1
  251. package/lib/ir/ui/IrTraces.js +2 -0
  252. package/lib/ir/ui/IrTraces.js.map +1 -1
  253. package/lib/ir/ui/RamanEditor.d.ts +46 -0
  254. package/lib/ir/ui/RamanEditor.d.ts.map +1 -0
  255. package/lib/ir/ui/RamanEditor.js +17 -0
  256. package/lib/ir/ui/RamanEditor.js.map +1 -0
  257. package/lib/ir/ui/SpectraPanel.d.ts.map +1 -1
  258. package/lib/ir/ui/SpectraPanel.js +2 -2
  259. package/lib/ir/ui/SpectraPanel.js.map +1 -1
  260. package/lib/ir/ui/SpectrumRow.d.ts +7 -0
  261. package/lib/ir/ui/SpectrumRow.d.ts.map +1 -1
  262. package/lib/ir/ui/SpectrumRow.js +4 -5
  263. package/lib/ir/ui/SpectrumRow.js.map +1 -1
  264. package/lib/ir/ui/VibrationalEditor.d.ts +48 -0
  265. package/lib/ir/ui/VibrationalEditor.d.ts.map +1 -0
  266. package/lib/ir/ui/VibrationalEditor.js +31 -0
  267. package/lib/ir/ui/VibrationalEditor.js.map +1 -0
  268. package/lib/ir/ui/bandsTsv.d.ts +19 -0
  269. package/lib/ir/ui/bandsTsv.d.ts.map +1 -0
  270. package/lib/ir/ui/bandsTsv.js +38 -0
  271. package/lib/ir/ui/bandsTsv.js.map +1 -0
  272. package/lib/ir/ui/irChartProps.d.ts +14 -4
  273. package/lib/ir/ui/irChartProps.d.ts.map +1 -1
  274. package/lib/ir/ui/irChartProps.js +3 -2
  275. package/lib/ir/ui/irChartProps.js.map +1 -1
  276. package/lib/ir/ui/irCommandContext.d.ts +8 -0
  277. package/lib/ir/ui/irCommandContext.d.ts.map +1 -1
  278. package/lib/ir/ui/irCommandContext.js +14 -3
  279. package/lib/ir/ui/irCommandContext.js.map +1 -1
  280. package/lib/ir/ui/useIrEditor.d.ts +3 -3
  281. package/lib/ir/ui/useIrEditor.d.ts.map +1 -1
  282. package/lib/ir/ui/useIrEditor.js +13 -4
  283. package/lib/ir/ui/useIrEditor.js.map +1 -1
  284. package/lib/ir/ui/useIrHandle.d.ts +14 -0
  285. package/lib/ir/ui/useIrHandle.d.ts.map +1 -0
  286. package/lib/ir/ui/useIrHandle.js +39 -0
  287. package/lib/ir/ui/useIrHandle.js.map +1 -0
  288. package/lib/ir/ui/useIrText.d.ts +40 -0
  289. package/lib/ir/ui/useIrText.d.ts.map +1 -0
  290. package/lib/ir/ui/useIrText.js +118 -0
  291. package/lib/ir/ui/useIrText.js.map +1 -0
  292. package/lib/ir/ui/useIrZoom.d.ts +7 -0
  293. package/lib/ir/ui/useIrZoom.d.ts.map +1 -1
  294. package/lib/ir/ui/useIrZoom.js +5 -4
  295. package/lib/ir/ui/useIrZoom.js.map +1 -1
  296. package/lib/ir/ui/useValueAxisZoom.d.ts +20 -0
  297. package/lib/ir/ui/useValueAxisZoom.d.ts.map +1 -0
  298. package/lib/ir/ui/useValueAxisZoom.js +54 -0
  299. package/lib/ir/ui/useValueAxisZoom.js.map +1 -0
  300. package/lib/ir.d.ts +3 -0
  301. package/lib/ir.d.ts.map +1 -1
  302. package/lib/ir.js +3 -0
  303. package/lib/ir.js.map +1 -1
  304. package/lib/locales/de.json +57 -1
  305. package/lib/locales/en.json +57 -1
  306. package/lib/locales/es.json +57 -1
  307. package/lib/locales/fr.json +57 -1
  308. package/lib/locales/it.json +57 -1
  309. package/lib/moleculesClient/core/index.d.ts +5 -0
  310. package/lib/moleculesClient/core/index.d.ts.map +1 -0
  311. package/lib/moleculesClient/core/index.js +3 -0
  312. package/lib/moleculesClient/core/index.js.map +1 -0
  313. package/lib/moleculesClient/core/moleculesClient.d.ts +12 -0
  314. package/lib/moleculesClient/core/moleculesClient.d.ts.map +1 -0
  315. package/lib/moleculesClient/core/moleculesClient.js +105 -0
  316. package/lib/moleculesClient/core/moleculesClient.js.map +1 -0
  317. package/lib/moleculesClient/core/moleculesClientApi.d.ts +100 -0
  318. package/lib/moleculesClient/core/moleculesClientApi.d.ts.map +1 -0
  319. package/lib/moleculesClient/core/moleculesClientApi.js +20 -0
  320. package/lib/moleculesClient/core/moleculesClientApi.js.map +1 -0
  321. package/lib/moleculesClient/core/moleculesTypes.d.ts +154 -0
  322. package/lib/moleculesClient/core/moleculesTypes.d.ts.map +1 -0
  323. package/lib/moleculesClient/core/moleculesTypes.js +2 -0
  324. package/lib/moleculesClient/core/moleculesTypes.js.map +1 -0
  325. package/lib/moleculesClient/core/requestRetry.d.ts +50 -0
  326. package/lib/moleculesClient/core/requestRetry.d.ts.map +1 -0
  327. package/lib/moleculesClient/core/requestRetry.js +108 -0
  328. package/lib/moleculesClient/core/requestRetry.js.map +1 -0
  329. package/lib/molstar/core/camera.d.ts +2 -1
  330. package/lib/molstar/core/camera.d.ts.map +1 -1
  331. package/lib/molstar/core/camera.js +3 -2
  332. package/lib/molstar/core/camera.js.map +1 -1
  333. package/lib/molstar/core/framing.d.ts +102 -0
  334. package/lib/molstar/core/framing.d.ts.map +1 -0
  335. package/lib/molstar/core/framing.js +120 -0
  336. package/lib/molstar/core/framing.js.map +1 -0
  337. package/lib/molstar/core/hover.d.ts +16 -0
  338. package/lib/molstar/core/hover.d.ts.map +1 -1
  339. package/lib/molstar/core/hover.js +14 -0
  340. package/lib/molstar/core/hover.js.map +1 -1
  341. package/lib/molstar/core/index.d.ts +4 -1
  342. package/lib/molstar/core/index.d.ts.map +1 -1
  343. package/lib/molstar/core/index.js +2 -1
  344. package/lib/molstar/core/index.js.map +1 -1
  345. package/lib/pedagogy/core/answers.d.ts +46 -0
  346. package/lib/pedagogy/core/answers.d.ts.map +1 -0
  347. package/lib/pedagogy/core/answers.js +77 -0
  348. package/lib/pedagogy/core/answers.js.map +1 -0
  349. package/lib/pedagogy/core/attempts.d.ts +86 -0
  350. package/lib/pedagogy/core/attempts.d.ts.map +1 -0
  351. package/lib/pedagogy/core/attempts.js +117 -0
  352. package/lib/pedagogy/core/attempts.js.map +1 -0
  353. package/lib/pedagogy/core/index.d.ts +8 -0
  354. package/lib/pedagogy/core/index.d.ts.map +1 -1
  355. package/lib/pedagogy/core/index.js +4 -0
  356. package/lib/pedagogy/core/index.js.map +1 -1
  357. package/lib/pedagogy/core/progressController.d.ts +64 -0
  358. package/lib/pedagogy/core/progressController.d.ts.map +1 -0
  359. package/lib/pedagogy/core/progressController.js +56 -0
  360. package/lib/pedagogy/core/progressController.js.map +1 -0
  361. package/lib/pedagogy/core/seed.d.ts +96 -0
  362. package/lib/pedagogy/core/seed.d.ts.map +1 -0
  363. package/lib/pedagogy/core/seed.js +128 -0
  364. package/lib/pedagogy/core/seed.js.map +1 -0
  365. package/lib/pedagogy/core/series.d.ts +77 -0
  366. package/lib/pedagogy/core/series.d.ts.map +1 -0
  367. package/lib/pedagogy/core/series.js +10 -0
  368. package/lib/pedagogy/core/series.js.map +1 -0
  369. package/lib/pedagogy/ui/AnswerFields.d.ts +21 -0
  370. package/lib/pedagogy/ui/AnswerFields.d.ts.map +1 -0
  371. package/lib/pedagogy/ui/AnswerFields.js +24 -0
  372. package/lib/pedagogy/ui/AnswerFields.js.map +1 -0
  373. package/lib/pedagogy/ui/ExerciseList.d.ts +82 -0
  374. package/lib/pedagogy/ui/ExerciseList.d.ts.map +1 -0
  375. package/lib/pedagogy/ui/ExerciseList.js +53 -0
  376. package/lib/pedagogy/ui/ExerciseList.js.map +1 -0
  377. package/lib/pedagogy/ui/ExerciseSeries.d.ts +95 -0
  378. package/lib/pedagogy/ui/ExerciseSeries.d.ts.map +1 -0
  379. package/lib/pedagogy/ui/ExerciseSeries.js +74 -0
  380. package/lib/pedagogy/ui/ExerciseSeries.js.map +1 -0
  381. package/lib/pedagogy/ui/QuestionCard.d.ts +64 -0
  382. package/lib/pedagogy/ui/QuestionCard.d.ts.map +1 -0
  383. package/lib/pedagogy/ui/QuestionCard.js +73 -0
  384. package/lib/pedagogy/ui/QuestionCard.js.map +1 -0
  385. package/lib/pedagogy/ui/index.d.ts +10 -0
  386. package/lib/pedagogy/ui/index.d.ts.map +1 -1
  387. package/lib/pedagogy/ui/index.js +6 -0
  388. package/lib/pedagogy/ui/index.js.map +1 -1
  389. package/lib/pedagogy/ui/seriesCounts.d.ts +17 -0
  390. package/lib/pedagogy/ui/seriesCounts.d.ts.map +1 -0
  391. package/lib/pedagogy/ui/seriesCounts.js +27 -0
  392. package/lib/pedagogy/ui/seriesCounts.js.map +1 -0
  393. package/lib/pedagogy/ui/seriesParts.d.ts +55 -0
  394. package/lib/pedagogy/ui/seriesParts.d.ts.map +1 -0
  395. package/lib/pedagogy/ui/seriesParts.js +38 -0
  396. package/lib/pedagogy/ui/seriesParts.js.map +1 -0
  397. package/lib/pedagogy/ui/useAttemptRecords.d.ts +10 -0
  398. package/lib/pedagogy/ui/useAttemptRecords.d.ts.map +1 -0
  399. package/lib/pedagogy/ui/useAttemptRecords.js +11 -0
  400. package/lib/pedagogy/ui/useAttemptRecords.js.map +1 -0
  401. package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
  402. package/lib/periodic/ui/PeriodicTable.js +6 -3
  403. package/lib/periodic/ui/PeriodicTable.js.map +1 -1
  404. package/lib/property/core/copyableText.d.ts +14 -0
  405. package/lib/property/core/copyableText.d.ts.map +1 -0
  406. package/lib/property/core/copyableText.js +21 -0
  407. package/lib/property/core/copyableText.js.map +1 -0
  408. package/lib/property/core/index.d.ts +2 -0
  409. package/lib/property/core/index.d.ts.map +1 -0
  410. package/lib/property/core/index.js +2 -0
  411. package/lib/property/core/index.js.map +1 -0
  412. package/lib/property/ui/PropertyTable.d.ts +43 -0
  413. package/lib/property/ui/PropertyTable.d.ts.map +1 -0
  414. package/lib/property/ui/PropertyTable.js +19 -0
  415. package/lib/property/ui/PropertyTable.js.map +1 -0
  416. package/lib/property/ui/index.d.ts +3 -0
  417. package/lib/property/ui/index.d.ts.map +1 -0
  418. package/lib/property/ui/index.js +2 -0
  419. package/lib/property/ui/index.js.map +1 -0
  420. package/lib/raman.d.ts +16 -0
  421. package/lib/raman.d.ts.map +1 -0
  422. package/lib/raman.js +12 -0
  423. package/lib/raman.js.map +1 -0
  424. package/lib/router/core/history.d.ts +24 -3
  425. package/lib/router/core/history.d.ts.map +1 -1
  426. package/lib/router/core/history.js +55 -7
  427. package/lib/router/core/history.js.map +1 -1
  428. package/lib/router/core/index.d.ts +3 -3
  429. package/lib/router/core/index.d.ts.map +1 -1
  430. package/lib/router/core/index.js +2 -2
  431. package/lib/router/core/index.js.map +1 -1
  432. package/lib/router/core/languageRoute.d.ts +61 -0
  433. package/lib/router/core/languageRoute.d.ts.map +1 -0
  434. package/lib/router/core/languageRoute.js +96 -0
  435. package/lib/router/core/languageRoute.js.map +1 -0
  436. package/lib/router/core/siteAddresses.d.ts +23 -0
  437. package/lib/router/core/siteAddresses.d.ts.map +1 -1
  438. package/lib/router/core/siteAddresses.js +26 -0
  439. package/lib/router/core/siteAddresses.js.map +1 -1
  440. package/lib/router/core/tabRouter.d.ts +2 -108
  441. package/lib/router/core/tabRouter.d.ts.map +1 -1
  442. package/lib/router/core/tabRouter.js +38 -5
  443. package/lib/router/core/tabRouter.js.map +1 -1
  444. package/lib/router/core/tabRouterTypes.d.ts +154 -0
  445. package/lib/router/core/tabRouterTypes.d.ts.map +1 -0
  446. package/lib/router/core/tabRouterTypes.js +2 -0
  447. package/lib/router/core/tabRouterTypes.js.map +1 -0
  448. package/lib/seo/core/fitDescription.d.ts +40 -0
  449. package/lib/seo/core/fitDescription.d.ts.map +1 -0
  450. package/lib/seo/core/fitDescription.js +45 -0
  451. package/lib/seo/core/fitDescription.js.map +1 -0
  452. package/lib/seo/core/index.d.ts +7 -0
  453. package/lib/seo/core/index.d.ts.map +1 -1
  454. package/lib/seo/core/index.js +4 -0
  455. package/lib/seo/core/index.js.map +1 -1
  456. package/lib/seo/core/limits.d.ts +24 -0
  457. package/lib/seo/core/limits.d.ts.map +1 -0
  458. package/lib/seo/core/limits.js +24 -0
  459. package/lib/seo/core/limits.js.map +1 -0
  460. package/lib/seo/core/pageContent.d.ts +25 -0
  461. package/lib/seo/core/pageContent.d.ts.map +1 -0
  462. package/lib/seo/core/pageContent.js +25 -0
  463. package/lib/seo/core/pageContent.js.map +1 -0
  464. package/lib/seo/core/plainDescription.d.ts.map +1 -1
  465. package/lib/seo/core/plainDescription.js +3 -2
  466. package/lib/seo/core/plainDescription.js.map +1 -1
  467. package/lib/seo/core/routeProblems.d.ts.map +1 -1
  468. package/lib/seo/core/routeProblems.js +1 -6
  469. package/lib/seo/core/routeProblems.js.map +1 -1
  470. package/lib/seo/core/routeTable.d.ts +31 -0
  471. package/lib/seo/core/routeTable.d.ts.map +1 -0
  472. package/lib/seo/core/routeTable.js +96 -0
  473. package/lib/seo/core/routeTable.js.map +1 -0
  474. package/lib/seo/vite/index.d.ts +2 -0
  475. package/lib/seo/vite/index.d.ts.map +1 -1
  476. package/lib/seo/vite/index.js +1 -0
  477. package/lib/seo/vite/index.js.map +1 -1
  478. package/lib/seo/vite/prerender.d.ts +10 -0
  479. package/lib/seo/vite/prerender.d.ts.map +1 -1
  480. package/lib/seo/vite/prerender.js +12 -1
  481. package/lib/seo/vite/prerender.js.map +1 -1
  482. package/lib/seo/vite/routeTable.d.ts +40 -0
  483. package/lib/seo/vite/routeTable.d.ts.map +1 -0
  484. package/lib/seo/vite/routeTable.js +44 -0
  485. package/lib/seo/vite/routeTable.js.map +1 -0
  486. package/lib/server/answerAddresses.d.ts +51 -0
  487. package/lib/server/answerAddresses.d.ts.map +1 -0
  488. package/lib/server/answerAddresses.js +72 -0
  489. package/lib/server/answerAddresses.js.map +1 -0
  490. package/lib/server/cardMeta.d.ts +57 -0
  491. package/lib/server/cardMeta.d.ts.map +1 -0
  492. package/lib/server/cardMeta.js +52 -0
  493. package/lib/server/cardMeta.js.map +1 -0
  494. package/lib/server/config.d.ts +72 -0
  495. package/lib/server/config.d.ts.map +1 -0
  496. package/lib/server/config.js +67 -0
  497. package/lib/server/config.js.map +1 -0
  498. package/lib/server/envNumber.d.ts +35 -0
  499. package/lib/server/envNumber.d.ts.map +1 -0
  500. package/lib/server/envNumber.js +42 -0
  501. package/lib/server/envNumber.js.map +1 -0
  502. package/lib/server/healthRoute.d.ts +26 -0
  503. package/lib/server/healthRoute.d.ts.map +1 -0
  504. package/lib/server/healthRoute.js +22 -0
  505. package/lib/server/healthRoute.js.map +1 -0
  506. package/lib/server/listenSite.d.ts +38 -0
  507. package/lib/server/listenSite.d.ts.map +1 -0
  508. package/lib/server/listenSite.js +60 -0
  509. package/lib/server/listenSite.js.map +1 -0
  510. package/lib/server/mcpServer.d.ts +8 -0
  511. package/lib/server/mcpServer.d.ts.map +1 -0
  512. package/lib/server/mcpServer.js +11 -0
  513. package/lib/server/mcpServer.js.map +1 -0
  514. package/lib/server/repositoryVersion.d.ts +16 -0
  515. package/lib/server/repositoryVersion.d.ts.map +1 -0
  516. package/lib/server/repositoryVersion.js +33 -0
  517. package/lib/server/repositoryVersion.js.map +1 -0
  518. package/lib/server/routeOptions.d.ts +23 -0
  519. package/lib/server/routeOptions.d.ts.map +1 -0
  520. package/lib/server/routeOptions.js +20 -0
  521. package/lib/server/routeOptions.js.map +1 -0
  522. package/lib/server/routeTable.d.ts +14 -0
  523. package/lib/server/routeTable.d.ts.map +1 -0
  524. package/lib/server/routeTable.js +32 -0
  525. package/lib/server/routeTable.js.map +1 -0
  526. package/lib/server/siteView.d.ts +29 -0
  527. package/lib/server/siteView.d.ts.map +1 -0
  528. package/lib/server/siteView.js +21 -0
  529. package/lib/server/siteView.js.map +1 -0
  530. package/lib/server/spaPages.d.ts +32 -0
  531. package/lib/server/spaPages.d.ts.map +1 -0
  532. package/lib/server/spaPages.js +126 -0
  533. package/lib/server/spaPages.js.map +1 -0
  534. package/lib/server/spaSite.d.ts +30 -0
  535. package/lib/server/spaSite.d.ts.map +1 -0
  536. package/lib/server/spaSite.js +170 -0
  537. package/lib/server/spaSite.js.map +1 -0
  538. package/lib/server/spaSiteOptions.d.ts +126 -0
  539. package/lib/server/spaSiteOptions.d.ts.map +1 -0
  540. package/lib/server/spaSiteOptions.js +2 -0
  541. package/lib/server/spaSiteOptions.js.map +1 -0
  542. package/lib/server/staticSite.d.ts +9 -0
  543. package/lib/server/staticSite.d.ts.map +1 -1
  544. package/lib/server/staticSite.js +41 -19
  545. package/lib/server/staticSite.js.map +1 -1
  546. package/lib/server/toolSiteServer.d.ts +77 -0
  547. package/lib/server/toolSiteServer.d.ts.map +1 -0
  548. package/lib/server/toolSiteServer.js +58 -0
  549. package/lib/server/toolSiteServer.js.map +1 -0
  550. package/lib/server/trustProxy.d.ts +20 -0
  551. package/lib/server/trustProxy.d.ts.map +1 -0
  552. package/lib/server/trustProxy.js +32 -0
  553. package/lib/server/trustProxy.js.map +1 -0
  554. package/lib/server/types.d.ts +13 -0
  555. package/lib/server/types.d.ts.map +1 -0
  556. package/lib/server/types.js +2 -0
  557. package/lib/server/types.js.map +1 -0
  558. package/lib/server.d.ts +22 -0
  559. package/lib/server.d.ts.map +1 -1
  560. package/lib/server.js +12 -0
  561. package/lib/server.js.map +1 -1
  562. package/lib/share/core/config.d.ts +18 -0
  563. package/lib/share/core/config.d.ts.map +1 -1
  564. package/lib/share/core/config.js +33 -2
  565. package/lib/share/core/config.js.map +1 -1
  566. package/lib/share/core/index.d.ts +3 -1
  567. package/lib/share/core/index.d.ts.map +1 -1
  568. package/lib/share/core/index.js +2 -1
  569. package/lib/share/core/index.js.map +1 -1
  570. package/lib/share/core/keySetParam.d.ts +40 -0
  571. package/lib/share/core/keySetParam.d.ts.map +1 -0
  572. package/lib/share/core/keySetParam.js +60 -0
  573. package/lib/share/core/keySetParam.js.map +1 -0
  574. package/lib/share/core/vocabulary.d.ts +8 -0
  575. package/lib/share/core/vocabulary.d.ts.map +1 -1
  576. package/lib/shell/ui/ShareControl.d.ts +75 -0
  577. package/lib/shell/ui/ShareControl.d.ts.map +1 -0
  578. package/lib/shell/ui/ShareControl.js +40 -0
  579. package/lib/shell/ui/ShareControl.js.map +1 -0
  580. package/lib/shell/ui/ShellFrame.d.ts +14 -0
  581. package/lib/shell/ui/ShellFrame.d.ts.map +1 -0
  582. package/lib/shell/ui/ShellFrame.js +45 -0
  583. package/lib/shell/ui/ShellFrame.js.map +1 -0
  584. package/lib/shell/ui/SiteShell.d.ts +251 -0
  585. package/lib/shell/ui/SiteShell.d.ts.map +1 -0
  586. package/lib/shell/ui/SiteShell.js +39 -0
  587. package/lib/shell/ui/SiteShell.js.map +1 -0
  588. package/lib/shell/ui/index.d.ts +5 -0
  589. package/lib/shell/ui/index.d.ts.map +1 -0
  590. package/lib/shell/ui/index.js +3 -0
  591. package/lib/shell/ui/index.js.map +1 -0
  592. package/lib/state/core/index.d.ts +1 -0
  593. package/lib/state/core/index.d.ts.map +1 -1
  594. package/lib/state/core/index.js.map +1 -1
  595. package/lib/state/core/legacyEntries.d.ts +30 -0
  596. package/lib/state/core/legacyEntries.d.ts.map +1 -0
  597. package/lib/state/core/legacyEntries.js +51 -0
  598. package/lib/state/core/legacyEntries.js.map +1 -0
  599. package/lib/state/core/persistBucket.d.ts +26 -2
  600. package/lib/state/core/persistBucket.d.ts.map +1 -1
  601. package/lib/state/core/persistBucket.js +26 -9
  602. package/lib/state/core/persistBucket.js.map +1 -1
  603. package/lib/state/core/persistSignalBucket.d.ts +26 -0
  604. package/lib/state/core/persistSignalBucket.d.ts.map +1 -1
  605. package/lib/state/core/persistSignalBucket.js +31 -0
  606. package/lib/state/core/persistSignalBucket.js.map +1 -1
  607. package/lib/state/core/storageEntry.d.ts +15 -0
  608. package/lib/state/core/storageEntry.d.ts.map +1 -1
  609. package/lib/state/core/storageEntry.js +33 -0
  610. package/lib/state/core/storageEntry.js.map +1 -1
  611. package/lib/structure/ui/StructureExportButton.d.ts +27 -0
  612. package/lib/structure/ui/StructureExportButton.d.ts.map +1 -0
  613. package/lib/structure/ui/StructureExportButton.js +21 -0
  614. package/lib/structure/ui/StructureExportButton.js.map +1 -0
  615. package/lib/structure/ui/index.d.ts +4 -0
  616. package/lib/structure/ui/index.d.ts.map +1 -1
  617. package/lib/structure/ui/index.js +2 -0
  618. package/lib/structure/ui/index.js.map +1 -1
  619. package/lib/structure/ui/useStructureDraft.d.ts +32 -0
  620. package/lib/structure/ui/useStructureDraft.d.ts.map +1 -0
  621. package/lib/structure/ui/useStructureDraft.js +20 -0
  622. package/lib/structure/ui/useStructureDraft.js.map +1 -0
  623. package/lib/ui.d.ts +2 -0
  624. package/lib/ui.d.ts.map +1 -1
  625. package/lib/ui.js +2 -0
  626. package/lib/ui.js.map +1 -1
  627. package/lib/worker/core/index.d.ts +1 -1
  628. package/lib/worker/core/index.d.ts.map +1 -1
  629. package/lib/worker/core/messages.d.ts +4 -2
  630. package/lib/worker/core/messages.d.ts.map +1 -1
  631. package/lib/worker/core/messages.js.map +1 -1
  632. package/lib/worker/core/oclResourcesUrl.d.ts +16 -0
  633. package/lib/worker/core/oclResourcesUrl.d.ts.map +1 -0
  634. package/lib/worker/core/oclResourcesUrl.js +19 -0
  635. package/lib/worker/core/oclResourcesUrl.js.map +1 -0
  636. package/lib/worker/core/serveWorkerRequests.d.ts +8 -0
  637. package/lib/worker/core/serveWorkerRequests.d.ts.map +1 -1
  638. package/lib/worker/core/serveWorkerRequests.js +15 -2
  639. package/lib/worker/core/serveWorkerRequests.js.map +1 -1
  640. package/lib/worker/core/workerChannel.d.ts +3 -4
  641. package/lib/worker/core/workerChannel.d.ts.map +1 -1
  642. package/lib/worker/core/workerChannel.js +72 -67
  643. package/lib/worker/core/workerChannel.js.map +1 -1
  644. package/lib/worker/core/workerChannelParts.d.ts +17 -6
  645. package/lib/worker/core/workerChannelParts.d.ts.map +1 -1
  646. package/lib/worker/core/workerChannelParts.js +20 -4
  647. package/lib/worker/core/workerChannelParts.js.map +1 -1
  648. package/lib/worker/core/workerChannelTypes.d.ts +46 -2
  649. package/lib/worker/core/workerChannelTypes.d.ts.map +1 -1
  650. package/lib/worker/core/workerSlot.d.ts +66 -0
  651. package/lib/worker/core/workerSlot.d.ts.map +1 -0
  652. package/lib/worker/core/workerSlot.js +107 -0
  653. package/lib/worker/core/workerSlot.js.map +1 -0
  654. package/package.json +17 -1
  655. package/src/card/core/cardAddress.ts +100 -0
  656. package/src/card/core/cardPageUrl.ts +97 -0
  657. package/src/card/core/index.ts +6 -0
  658. package/src/card/core/panelRoom.ts +66 -0
  659. package/src/card/ui/CardDetailsButton.tsx +104 -0
  660. package/src/card/ui/CardFigure.tsx +86 -0
  661. package/src/card/ui/CardFrame.tsx +46 -0
  662. package/src/card/ui/CopyTableButton.tsx +81 -0
  663. package/src/card/ui/cardTooltip.ts +18 -0
  664. package/src/card/ui/embed.ts +27 -0
  665. package/src/card/ui/fitCardToFrame.ts +76 -0
  666. package/src/card/ui/holdRoomForPanels.ts +83 -0
  667. package/src/card/ui/index.ts +14 -0
  668. package/src/card/ui/openPanels.ts +106 -0
  669. package/src/card.ts +13 -0
  670. package/src/conformers.ts +4 -0
  671. package/src/core.ts +5 -0
  672. package/src/fetch/core/apiError.ts +65 -0
  673. package/src/fetch/core/fetchJson.ts +129 -0
  674. package/src/fetch/core/index.ts +4 -0
  675. package/src/formula/core/formulaText.ts +96 -0
  676. package/src/formula/core/index.ts +20 -0
  677. package/src/formula/core/normalizeFormula.ts +50 -0
  678. package/src/formula/core/readFormula.ts +211 -0
  679. package/src/formula/ui/CopyableFormula.tsx +51 -0
  680. package/src/formula/ui/FormulaInput.tsx +50 -0
  681. package/src/formula/ui/QuestionFormula.tsx +20 -0
  682. package/src/formula/ui/index.ts +6 -0
  683. package/src/formula.ts +11 -0
  684. package/src/hooks/ui/index.ts +1 -0
  685. package/src/hooks/ui/keyTargets.ts +5 -3
  686. package/src/hooks/ui/useAsync.ts +50 -14
  687. package/src/ir/core/analysisSpectra.ts +26 -10
  688. package/src/ir/core/bandLabelPlan.ts +21 -10
  689. package/src/ir/core/index.ts +25 -5
  690. package/src/ir/core/irBand.ts +52 -14
  691. package/src/ir/core/irCommands.ts +15 -1
  692. package/src/ir/core/irDomain.ts +9 -7
  693. package/src/ir/core/irFormat.ts +39 -6
  694. package/src/ir/core/irMode.ts +42 -10
  695. package/src/ir/core/irReducer.ts +1 -49
  696. package/src/ir/core/irSpectrum.ts +59 -30
  697. package/src/ir/core/irState.ts +67 -2
  698. package/src/ir/core/irTechnique.ts +115 -0
  699. package/src/ir/core/irTechniqueCommands.ts +82 -0
  700. package/src/ir/core/pickBands.ts +63 -28
  701. package/src/ir/core/ramanBands.ts +105 -0
  702. package/src/ir/core/spectrumJcamp.ts +65 -16
  703. package/src/ir/core/toIrSpectrum.ts +20 -2
  704. package/src/ir/ui/BandRow.tsx +107 -0
  705. package/src/ir/ui/BandsPanel.tsx +32 -125
  706. package/src/ir/ui/IrAboutDialog.tsx +69 -28
  707. package/src/ir/ui/IrCanvas.tsx +2 -1
  708. package/src/ir/ui/IrChart.tsx +20 -24
  709. package/src/ir/ui/IrCommandProvider.tsx +10 -3
  710. package/src/ir/ui/IrCommandTooltip.tsx +11 -2
  711. package/src/ir/ui/IrDocumentationDialog.tsx +99 -55
  712. package/src/ir/ui/IrEditor.tsx +5 -36
  713. package/src/ir/ui/IrHeader.tsx +10 -3
  714. package/src/ir/ui/IrLogo.tsx +28 -9
  715. package/src/ir/ui/IrShell.tsx +27 -75
  716. package/src/ir/ui/IrStatusBar.tsx +17 -12
  717. package/src/ir/ui/IrToolbar.tsx +26 -15
  718. package/src/ir/ui/IrTraces.tsx +5 -1
  719. package/src/ir/ui/RamanEditor.tsx +53 -0
  720. package/src/ir/ui/SpectraPanel.tsx +2 -1
  721. package/src/ir/ui/SpectrumRow.tsx +14 -5
  722. package/src/ir/ui/VibrationalEditor.tsx +94 -0
  723. package/src/ir/ui/bandsTsv.ts +46 -0
  724. package/src/ir/ui/irChartProps.ts +14 -4
  725. package/src/ir/ui/irCommandContext.tsx +18 -3
  726. package/src/ir/ui/useIrEditor.ts +20 -8
  727. package/src/ir/ui/useIrHandle.ts +51 -0
  728. package/src/ir/ui/useIrText.ts +170 -0
  729. package/src/ir/ui/useIrZoom.ts +12 -3
  730. package/src/ir/ui/useValueAxisZoom.ts +67 -0
  731. package/src/ir.ts +3 -0
  732. package/src/locales/de.json +57 -1
  733. package/src/locales/en.json +57 -1
  734. package/src/locales/es.json +57 -1
  735. package/src/locales/fr.json +57 -1
  736. package/src/locales/it.json +57 -1
  737. package/src/moleculesClient/core/index.ts +19 -0
  738. package/src/moleculesClient/core/moleculesClient.ts +175 -0
  739. package/src/moleculesClient/core/moleculesClientApi.ts +120 -0
  740. package/src/moleculesClient/core/moleculesTypes.ts +163 -0
  741. package/src/moleculesClient/core/requestRetry.ts +118 -0
  742. package/src/molstar/core/camera.ts +3 -2
  743. package/src/molstar/core/framing.ts +200 -0
  744. package/src/molstar/core/hover.ts +26 -0
  745. package/src/molstar/core/index.ts +21 -1
  746. package/src/pedagogy/core/answers.ts +94 -0
  747. package/src/pedagogy/core/attempts.ts +205 -0
  748. package/src/pedagogy/core/index.ts +36 -0
  749. package/src/pedagogy/core/progressController.ts +116 -0
  750. package/src/pedagogy/core/seed.ts +177 -0
  751. package/src/pedagogy/core/series.ts +82 -0
  752. package/src/pedagogy/ui/AnswerFields.tsx +63 -0
  753. package/src/pedagogy/ui/ExerciseList.tsx +202 -0
  754. package/src/pedagogy/ui/ExerciseSeries.tsx +250 -0
  755. package/src/pedagogy/ui/QuestionCard.tsx +231 -0
  756. package/src/pedagogy/ui/index.ts +18 -0
  757. package/src/pedagogy/ui/seriesCounts.ts +34 -0
  758. package/src/pedagogy/ui/seriesParts.tsx +127 -0
  759. package/src/pedagogy/ui/useAttemptRecords.ts +16 -0
  760. package/src/periodic/ui/PeriodicTable.tsx +6 -3
  761. package/src/property/core/copyableText.ts +20 -0
  762. package/src/property/core/index.ts +1 -0
  763. package/src/property/ui/PropertyTable.tsx +83 -0
  764. package/src/property/ui/index.ts +2 -0
  765. package/src/raman.ts +19 -0
  766. package/src/router/core/history.ts +61 -7
  767. package/src/router/core/index.ts +3 -2
  768. package/src/router/core/languageRoute.ts +136 -0
  769. package/src/router/core/siteAddresses.ts +38 -0
  770. package/src/router/core/tabRouter.ts +59 -117
  771. package/src/router/core/tabRouterTypes.ts +158 -0
  772. package/src/seo/core/fitDescription.ts +74 -0
  773. package/src/seo/core/index.ts +17 -0
  774. package/src/seo/core/limits.ts +27 -0
  775. package/src/seo/core/pageContent.ts +42 -0
  776. package/src/seo/core/plainDescription.ts +4 -2
  777. package/src/seo/core/routeProblems.ts +1 -7
  778. package/src/seo/core/routeTable.ts +103 -0
  779. package/src/seo/vite/index.ts +2 -0
  780. package/src/seo/vite/prerender.ts +26 -1
  781. package/src/seo/vite/routeTable.ts +79 -0
  782. package/src/server/answerAddresses.ts +92 -0
  783. package/src/server/cardMeta.ts +88 -0
  784. package/src/server/config.ts +125 -0
  785. package/src/server/envNumber.ts +65 -0
  786. package/src/server/healthRoute.ts +42 -0
  787. package/src/server/listenSite.ts +90 -0
  788. package/src/server/mcpServer.ts +14 -0
  789. package/src/server/repositoryVersion.ts +33 -0
  790. package/src/server/routeOptions.ts +26 -0
  791. package/src/server/routeTable.ts +35 -0
  792. package/src/server/siteView.ts +42 -0
  793. package/src/server/spaPages.ts +179 -0
  794. package/src/server/spaSite.ts +216 -0
  795. package/src/server/spaSiteOptions.ts +133 -0
  796. package/src/server/staticSite.ts +65 -35
  797. package/src/server/toolSiteServer.ts +127 -0
  798. package/src/server/trustProxy.ts +32 -0
  799. package/src/server/types.ts +25 -0
  800. package/src/server.ts +40 -0
  801. package/src/share/core/config.ts +45 -2
  802. package/src/share/core/index.ts +4 -0
  803. package/src/share/core/keySetParam.ts +92 -0
  804. package/src/share/core/vocabulary.ts +8 -0
  805. package/src/shell/ui/ShareControl.tsx +150 -0
  806. package/src/shell/ui/ShellFrame.tsx +180 -0
  807. package/src/shell/ui/SiteShell.tsx +297 -0
  808. package/src/shell/ui/index.ts +9 -0
  809. package/src/state/core/index.ts +1 -0
  810. package/src/state/core/legacyEntries.ts +76 -0
  811. package/src/state/core/persistBucket.ts +50 -10
  812. package/src/state/core/persistSignalBucket.ts +52 -0
  813. package/src/state/core/storageEntry.ts +32 -0
  814. package/src/structure/ui/StructureExportButton.tsx +57 -0
  815. package/src/structure/ui/index.ts +4 -0
  816. package/src/structure/ui/useStructureDraft.ts +47 -0
  817. package/src/ui.ts +2 -0
  818. package/src/worker/core/index.ts +1 -0
  819. package/src/worker/core/messages.ts +4 -3
  820. package/src/worker/core/oclResourcesUrl.ts +21 -0
  821. package/src/worker/core/serveWorkerRequests.ts +30 -2
  822. package/src/worker/core/workerChannel.ts +74 -74
  823. package/src/worker/core/workerChannelParts.ts +33 -13
  824. package/src/worker/core/workerChannelTypes.ts +47 -2
  825. package/src/worker/core/workerSlot.ts +181 -0
  826. package/styles/card.css +145 -0
  827. package/styles/chrome.css +248 -0
package/README.md CHANGED
@@ -33,10 +33,12 @@ only when it drags a heavy dependency behind it.
33
33
  | Import | Holds | Costs |
34
34
  | ---------------------------------- | ----------------------------------------------------- | ------------------------------------------------ |
35
35
  | `react-cheminfo/core` | every framework-free helper — 140 value exports | nothing |
36
+ | `react-cheminfo/formula` | formulas: read, compared, drawn and copied | mf-parser, react-mf; React on the components |
36
37
  | `react-cheminfo/ui` | every React component and hook — 60 value exports | React |
37
38
  | `react-cheminfo/vite` | the prerender plugin and the OG card | nothing; React on the card |
38
39
  | `react-cheminfo/pages` | the Cloudflare Pages analytics middleware | nothing |
39
40
  | `react-cheminfo/server` | the prerendered build, served from Node | fastify, @fastify/static; Node only |
41
+ | `react-cheminfo/card` | the card an answer is shown as in a chat | React; cheminfo-mcp-server, an optional peer |
40
42
  | `react-cheminfo/orbital` | the 3D atomic-orbital viewer | React, molstar |
41
43
  | `react-cheminfo/molecule3d` | the 3D molecule viewer and its toolbar | React, molstar |
42
44
  | `react-cheminfo/structure` | the structure editor and renderer | React, react-ocl, OCL |
@@ -44,11 +46,13 @@ only when it drags a heavy dependency behind it.
44
46
  | `react-cheminfo/slides` | the deck format and the slideshow player | React, react-markdown |
45
47
  | `react-cheminfo/spectra` | the spectra processing settings editors | React; types only from spectra-processor, ml-pca |
46
48
  | `react-cheminfo/ir` | the infrared chart, band table and editor | React, ir-spectrum, convert-to-jcamp |
49
+ | `react-cheminfo/raman` | the Raman editor: the infrared one, read for Raman | the same as `react-cheminfo/ir` |
47
50
  | `react-cheminfo/xtb` | GFN2-xTB as a geometry relaxer | nothing on import; xtb-wasm on the first call |
48
51
  | `react-cheminfo/host` | data handed over by a page that frames the tool | nothing on import; ajv once the page is framed |
49
52
  | `react-cheminfo/host-testing` | a stand-in host and SciPeaks' messages, for e2e tests | nothing; Node only |
50
53
  | `react-cheminfo/styles/chrome.css` | the shared tokens and site-header stylesheet | nothing |
51
54
  | `react-cheminfo/styles/slides.css` | the deck stylesheet, themed on the site's colours | nothing |
55
+ | `react-cheminfo/styles/card.css` | the card’s stylesheet, on the family’s tokens | nothing |
52
56
 
53
57
  A backend serving an RIS endpoint, a prerender script writing a sitemap, and
54
58
  every unit test of that logic therefore load no React at all — and a worker
@@ -65,11 +69,15 @@ module scope: a site that never imports that door bundles none of it.
65
69
  usual reason: reading a spectrum drags the formats one may arrive in —
66
70
  `ir-spectrum` for the band correlations and the absorbance/transmittance pair,
67
71
  `convert-to-jcamp` for writing them back out, and a JCAMP or SPC reader fetched
68
- only once the bytes turn out to need it. The chart it is drawn with is **not**
69
- behind that door: scales, ticks, plot geometry, the zoom gestures, the label
70
- placement and the panel chrome are in `core` and `ui`, because a spectrum of any
71
- kind is drawn with them and the next viewer built on them should find them
72
- already there rather than reach through an infrared package for them.
72
+ only once the bytes turn out to need it. `react-cheminfo/raman` opens the same
73
+ viewer for Raman spectra — one value axis, the Raman shift running left to
74
+ right, the bands picked on intensity and no correlation table — so a page
75
+ imports each technique's viewer by name while both share one shell. The chart
76
+ it is drawn with is **not** behind that door: scales, ticks, plot geometry, the
77
+ zoom gestures, the label placement and the panel chrome are in `core` and `ui`,
78
+ because a spectrum of any kind is drawn with them and the next viewer built on
79
+ them should find them already there rather than reach through an infrared
80
+ package for them.
73
81
 
74
82
  `react-cheminfo/xtb` is the door a page opens only when a visitor asks for a
75
83
  better number. `refineConformers` in
@@ -100,16 +108,21 @@ through a wildcard subpath exactly as `react-science` serves its own.
100
108
  | **Routing & head** | `createTabRouter`, `readRoute`, `writeRoute`, `subscribeToRoute`, `adoptLegacyHashAddress`, `writeDocumentMeta`, `pageLocation`, `pageHistory` | `useTabRoute` |
101
109
  | **Indexing** | `injectPageMeta`, `pageHeadTags`, `pageDocumentMeta`, `fill`, `PAGE_HEAD_MARKER`, `PAGE_BODY_MARKER`, `robotsTxt`, `sitemapXml`, `noscriptIndex`, `structuredDataScript`, `assertRoutes`, `routeFor`, `homeRoute` | `cheminfoPrerender`, `ogCardHtml`, `OG_WIDTH`, `OG_HEIGHT` (all `/vite`) |
102
110
  | **Pedagogy** | `parseGlossaryMarkers`, `localStorageProgressStore`, `progressSummary`, `finishValidation` | `GlossaryText`, `SyntaxTooltip`, `HintLadder`, `ExerciseActions`, `ExerciseProgressHeader`, `TutorialStepStrip`, `ReferenceGrid`, `TestCaseList` |
111
+ | **Graded series** | `pickSeeded`, `freshSeed`, `parseSeed`, `seedParam`, `createAttemptStore`, `createProgressController`, `readAnswerNumber`, `emptyCase`, `unreadableCase` | `ExerciseSeries`, `QuestionCard`, `AnswerFields`, `ExerciseList`, `useAttemptRecords` |
112
+ | **Formulas** | `readFormula`, `normalizeFormula`, `canonicalFormula`, `atomCounts`, `formulaHtml`, `formulaText` (all `/formula`) | `CopyableFormula`, `QuestionFormula`, `FormulaInput` (all `/formula`) |
113
+ | **Site shell** | `pageContentOf`; the `pages` option of `cheminfoPrerender` (`/vite`) | `SiteShell`, `ShareControl` |
114
+ | **Properties** | `copyableText` | `PropertyTable` |
103
115
  | **Clipboard & files** | `writeToClipboard`, `downloadBlob`, `downloadText`, `sanitizeFileName`, `toDelimited`, `readDelimited`, `downloadFigure`, `figureSvg`, `figurePng`, `figureSize` | `ClickToCopy`, `CopyButton`, `CopyableValue`, `CodeBlock`, `DelimitedTextDialog`, `FigureDownload` |
104
116
  | **Formatting & colour** | `formatInteger`, `formatDecimal`, `formatBytes`, `pluralize`, `readableInk`, `contrastRatio`, `COLOR_SCALES`, `resolveColorScale`, `formatColorScale`, `colorAt`, `swatchAt`, `sampleScale`, `colorScaleGradient`, `rgbToHsv` | `ColorScaleLegend`, `ColorScaleSelect`, `ColorScaleEditor`, `ColorScaleBar` |
105
117
  | **Number entry** | `readNumber`, `numberText`, `isPartialNumber`, `stepNumber`, `snapToStep` | `NumberInput` |
106
118
  | **Range filter** | `isRangeBounded`, `isRangeDomain`, `rangeHandles`, `movedRange`, `settleHandles`, `sameRange`, `rangeHistogramPath`, `OPEN_RANGE` | `RangeSlider` |
107
119
  | **Widgets** | `CREDITS`, `credits` | `ErrorBoundary`, `CollapsibleSection`, `CapsuleFilter`, `HelpTooltip`, `CreditsList` |
108
120
  | **Hooks & state** | `createWorkerChannel`, `persistBucket`, `persistSignalBucket` | `useDebouncedValue`, `useContainerSize`, `useListKeyboardNavigation`, `useDisclosure` |
121
+ | **Requests** | `fetchJson`, `ApiError`, `readApiError`, `keySetParam`, `readHiddenParts`, `formatHiddenParts`, `fitDescription`, `DESCRIPTION_MIN`, `DESCRIPTION_MAX`, `openingRoute`, `anchorHref` | `useAsync` (signal, `pending`) |
109
122
  | **Chemistry** | `atomicOrbitalsOf`, `configurationOf`, `classifyMolfile`, `readStructure`, `toMolfileExport` | `AtomicOrbitalViewer` (`/orbital`), `StructureEditor`, `Structure` (`/structure`) |
110
123
  | **Conformers** | `generateConformers`, `continueConformers`, `refineConformers`, `conformerShape`, `isSameMinimum`, `rankByEnergy`, `minimiseConformer`, `DEFAULT_CONFORMER_OPTIONS`, `CONFORMER_STRATEGIES` (all `/conformers`); `GeometryRelaxer`, `readRelaxableGeometry`, `centredRmsd` | — |
111
124
  | **Spectrum charts** | `chartScale`, `chartAxisScale`, `plotRect`, `zoomDomain`, `zoomSelection`, `labelStackBaselines`, `layoutAnnotationBoxes`, `profilePath`, `stickPath`, `guidePlacement`, `readoutPlacement`, `stackCapacity`, `nextSpectrumColor`, `panelStyles`, `statusBar` | `Axes`, `AxisGuide`, `ChartTracker`, `ChartStack`, `SelectionRect`, `TraceLegend`, `PlotCaption`, `useChartZoom`, `useChartPointer`, `useChartSize`, `SidePanelStack`, `PanelRail`, `Section`, `FilterInput`, `AboutDialogFrame`, `DocumentationDialogFrame`, `FigureDownload`, `useFigureDownload` |
112
- | **Infrared** | `loadIrSpectra`, `toIrSpectrum`, `pickBands`, `assignBands`, `BAND_ASSIGNMENTS`, `irSpectrumToJcamp`, `IR_MODE_RULES`, `nearestBandAt`, `planBandLabels`, `irReducer` (all `/ir`) | `IrEditor`, `IrChart`, `BandsPanel`, `SpectraPanel`, `MetadataPanel`, `useIrEditor` (all `/ir`) |
125
+ | **Infrared and Raman** | `loadIrSpectra`, `toIrSpectrum`, `pickBands`, `assignBands`, `BAND_ASSIGNMENTS`, `irSpectrumToJcamp`, `IR_MODE_RULES`, `IR_TECHNIQUE_RULES`, `nearestBandAt`, `planBandLabels`, `irReducer` (all `/ir`) | `IrEditor`, `IrChart`, `BandsPanel`, `SpectraPanel`, `MetadataPanel`, `useIrEditor` (all `/ir`); `RamanEditor` (`/raman`) |
113
126
  | **Spectra** | `FILTER_CATALOG`, `filterMenu`, `settingsProblems`, `normalizationFilters`, `addFilter`, `moveFilter`, `setFilterOption`, `principalComponentChoices`, `clampPrincipalComponents`, `EMPTY_SETTINGS` (all `/spectra`) | `SpectraSettingsEditor`, `FilterChainEditor`, `PrincipalComponentSelect` (all `/spectra`) |
114
127
  | **About** | `resolveAbout`, `aboutProblems` | `AboutPage` |
115
128
  | **Which build is running** | `formatBuiltAt`, `shortCommit`, `BuildInfo` | `AboutVersion`, `cheminfoBuildInfo` (`/vite`) |
@@ -121,6 +134,7 @@ through a wildcard subpath exactly as `react-science` serves its own.
121
134
  | **Periodic table** | `PERIODIC_ELEMENTS`, `elementBySymbol`, `elementByAtomicNumber`, `cellOf`, `placedElements`, `elementByArrowKey`, `EMPTY_BLOCK`, `categorySwatch`, `CATEGORY_LABELS` | `PeriodicTable`, `ElementCell`, `CategoryLegend` |
122
135
  | **Taxonomy** | `TAXON_RANKS`, `PRINCIPAL_RANKS`, `rankOrder`, `isPrincipalRank`, `isGenusOrBelow`, `isAboveGenus`, `principalLineage`, `lineageFromNodes`, `lineageFromRanks`, `genusOrBelow`, `ncbiTaxonomyUrl`, `splitOrganismName` | `TaxonLineage`, `OrganismName`, `useRankLabel` |
123
136
  | **Framed by a host** | `hostStructureLoader`, `readHostMolecule`, `STRUCTURE_KINDS`, `connectHost`, `selectInputs`, `checkValue`, `kindAccepts`, `parseRequest` (all `/host`); `startStandInHost`, `SCIPEAKS_ETHYLBENZENE_LOAD` (`/host-testing`) | `useHostConnection` (`/host`) |
137
+ | **Answer cards** | `CARD_PARAM`, `isCardAddress`, `sitePageUrl`, `cardPageUrl`, `framedPageUrl`, `roomForPanels`; `answerAddresses`, `joinAddress`, `viewOrigins`, `cardMeta`, `pageAnswer`, `siteView` (all `/server`) | `CardFrame`, `CardDetailsButton`, `CardFigure`, `CopyTableButton`, `fitCardToFrame`, `useFitCardToFrame`, `useOverlayRoom`, `holdRoomForPanels` (all `/card`); `StructureExportButton`, `useStructureDraft` (`/structure`) |
124
138
 
125
139
  Everything in that table is exported from `./core`, `./ui`, `./slides`,
126
140
  `./vite` or `./structure` and nothing else is: the sub-components a component is built
@@ -854,6 +868,60 @@ const included = useMemo(
854
868
  subject — a formula through `react-mf`, a structure, a name — and a readout of
855
869
  strings cannot hold any of that.
856
870
 
871
+ ## A graded series, and the shell around it
872
+
873
+ A pedagogic site that asks a series of questions writes its pool and its
874
+ grader, and nothing else. `SeriesTool` describes them; `ExerciseSeries` draws
875
+ the list beside the open question, the progress over the series, the length
876
+ picker and the new-series button. It reads no address: the page hands it the
877
+ seed, the length and the share of the row, and is told when one changes.
878
+
879
+ ```tsx
880
+ import { createAttemptStore, parseSeed } from 'react-cheminfo/core';
881
+ import { ExerciseSeries } from 'react-cheminfo/ui';
882
+
883
+ const ATTEMPTS = createAttemptStore({ key: 'atoms' }); // atoms:attempts:v1
884
+
885
+ <ExerciseSeries
886
+ tool={ELECTRONS}
887
+ store={ATTEMPTS}
888
+ label={(ion) => <QuestionFormula formula={ion.formula} />}
889
+ prompt={(ion) => <p>How many electrons has {ion.name}?</p>}
890
+ seed={parseSeed(route.params.seed)}
891
+ onSeed={(seed, history) => writeSeed(tab, seed, history)}
892
+ count={questionCount}
893
+ onCount={setQuestionCount}
894
+ split={SERIES_SPLIT.parse(route.params.split ?? null)}
895
+ onSplit={(split) => writeSplit(tab, split)}
896
+ />;
897
+ ```
898
+
899
+ `pickSeeded` draws the series. Its `draw` option names the generator call a
900
+ site's links were written with — `getFloat` for atoms, inorganic and moles,
901
+ `getUint32` with `wrap` for dbe — so every `?seed=` already handed out opens
902
+ the same questions. `seedParam` reads a seed a link pins, and `?seed=each` for
903
+ one series per student. `createProgressController(signal)` is the handful of
904
+ actions an exercise page performs on progress kept in a signal.
905
+
906
+ Formulas come from their own door, because they are read by `mf-parser` and
907
+ drawn by `react-mf`: `readFormula` reads `NO3-`, `SO4--` and `CuSO4.5H2O` the
908
+ way a student types them, which the parser alone reads as neutral or as a
909
+ decimal; `CopyableFormula` copies a formula as text and as HTML, so a paste
910
+ keeps its subscripts.
911
+
912
+ `SiteShell` is the chrome around a page: the theme, the bar with About · Cite ·
913
+ Tools · Contact · Share, the page, and the footer, with nothing but the page
914
+ under `?embed`. A site fills the slots between the shared entries
915
+ (`actionsAfterAbout`, `actionsAfterCite`, `actions`, `language`, `account`) and
916
+ never re-orders them. Given the site's router, it marks the tab on show and
917
+ serves the About tab as `AboutPage`. Its `share` takes what `ShareControl`
918
+ takes — the Share entry and its dialog in one, which is also what a header's
919
+ own `share` prop takes.
920
+
921
+ A prerendered site that writes text for a few of its pages passes them as
922
+ `pages` to `cheminfoPrerender`; every other address then says the name and the
923
+ sentence its route is indexed under.
924
+
857
925
  ## Framed by a notebook
858
926
 
859
927
  A page that frames a tool — an electronic lab notebook such as SciPeaks, a
@@ -1016,6 +1084,39 @@ Still English, with the runtime in place and no catalog yet: the spectra
1016
1084
  settings editor and the projection panels (`react-cheminfo/spectra`, the
1017
1085
  projection viewers), which no site of the family reads in a second language yet.
1018
1086
 
1087
+ ## Routing a translated site
1088
+
1089
+ A router given `languages` reads the language off the prefix and writes it
1090
+ back, English bare, so the share vocabulary, the query and the mount stay where
1091
+ they were:
1092
+
1093
+ ```ts
1094
+ const router = createTabRouter<Tab>({
1095
+ tabs: ['generator', 'exercises'],
1096
+ home: 'generator',
1097
+ languages: ['en', 'fr', 'de'],
1098
+ });
1099
+
1100
+ router.parse('/fr/exercises?embed'); // { tab: 'exercises', language: 'fr', … }
1101
+ router.format({ tab: 'exercises', language: 'de' }); // '/de/exercises'
1102
+ ```
1103
+
1104
+ `readRoute` moves a `?lang=` a sibling handed over into the path, once, in
1105
+ place; a prefix the address already carries always wins, so a deep link is
1106
+ never steered. `openingRoute(router, preferred)` opens a bare `/` in the
1107
+ language the reader last chose, and nothing else. `writeRoute` keeps the
1108
+ language on screen when the route names none.
1109
+
1110
+ Beside it: `persistSignalBucket` takes `legacyKeys` (adopted once, through a
1111
+ `migrate` when the shape changed) and `syncAcrossTabs`; `createSiteAddresses`
1112
+ answers `anchorHref` and `storedAssetSrc`; a vocabulary takes
1113
+ `legacyEmbedParts`, so `?hide=header` still opens framed; `keySetParam` writes
1114
+ `?flags=` with `none` for the empty set; `createWorkerChannel` takes a
1115
+ `failure` hook, `retryAfterWorkerFailure`, and runs in-process when a browser
1116
+ refuses the worker; `oclResourcesUrl()` comes from `./conformers`, and
1117
+ `resetCamera`, `focusPoint`, `sceneSphere` and `subscribeHoverLabel` from
1118
+ `./molstar/core`.
1119
+
1019
1120
  ## Carrying talks
1020
1121
 
1021
1122
  A deck is one Markdown file in the repository of the site whose subject it
@@ -1253,6 +1354,192 @@ answers its own 404. Without a build, `staticSite` logs it and serves the API
1253
1354
  alone. `fastify` (5) and `@fastify/static` (10) are optional peers, installed
1254
1355
  by a site that has a server.
1255
1356
 
1357
+ `basePath` (`BASE_PATH`) serves one image at a mount chosen at startup, behind a
1358
+ proxy that takes the path off: it is written into the `<base href="/">` of every
1359
+ page when the build is read, and in front of every redirect.
1360
+
1361
+ ### A tool site's server, from its environment
1362
+
1363
+ A site that serves its tools beside its pages has nothing of its own to write
1364
+ but the tools. `readServerConfig` reads the environment once and refuses a
1365
+ malformed value; `toolSiteServer` builds Fastify, registers the API the site
1366
+ passes, then `staticSite`; `startToolServer` listens and closes on `SIGTERM`
1367
+ and `SIGINT`, setting `process.exitCode = 1` when a close fails.
1368
+
1369
+ ```ts
1370
+ // server/main.ts
1371
+ import { join } from 'node:path';
1372
+
1373
+ import {
1374
+ readServerConfig,
1375
+ startToolServer,
1376
+ toolSiteServer,
1377
+ } from 'react-cheminfo/server';
1378
+
1379
+ const config = readServerConfig(process.env, {
1380
+ siteId: 'osiris',
1381
+ port: 10_620,
1382
+ root: join(import.meta.dirname, '../dist'),
1383
+ });
1384
+
1385
+ await startToolServer(
1386
+ (settings) =>
1387
+ toolSiteServer({
1388
+ siteId: 'osiris',
1389
+ config: settings,
1390
+ // name: 'osiris.cheminfo.org', version: the repository root's release
1391
+ registerApi: (app, { name, version }) =>
1392
+ registerTools(app, name, version),
1393
+ }),
1394
+ config,
1395
+ );
1396
+ ```
1397
+
1398
+ | Variable | Read as | Default |
1399
+ | ----------------- | ------------------------------------------------------------------- | ---------------------------- |
1400
+ | `PORT` | an integer from 1 to 65535 | the site's own port |
1401
+ | `HOST` | the interface listened on | `0.0.0.0` |
1402
+ | `TRACKING_SCRIPT` | the analytics snippet, verbatim | nothing loaded |
1403
+ | `SITE_URL` | the address answers link to, path kept, ending in `/` | the site's own address |
1404
+ | `PUBLIC_URL` | this server's address, which a chat frames, ending in `/` | `http://localhost:<PORT>/` |
1405
+ | `TRUST_PROXY` | an address, a CIDR, a list of either, or `true`; a hop count throws | `false` |
1406
+ | `SERVER_ROOT` | the build served | the `root` option, or `dist` |
1407
+ | `BASE_PATH` | the mount, behind a proxy that takes it off | none |
1408
+
1409
+ The pieces are exported on their own for a backend that is not a tool site:
1410
+ `parseTrustProxy`, `readEnvNumber` (blank is unset, a malformed value throws),
1411
+ `readHttpAddress`, `readRepositoryVersion` (the root `package.json`, found as
1412
+ `cheminfoBuildInfo` finds it), `healthRoute` (`GET /health`, silent),
1413
+ `listenSite` (listen, and close on a signal, then run `onClose`), and the
1414
+ type-only `FastifyTyped` (`@fastify/type-provider-typebox` is an optional peer).
1415
+
1416
+ ### A single-page app, served by its backend
1417
+
1418
+ A backend that serves a Vite single-page app answers every address the app
1419
+ routes with the built page, under the head of that address and a crawl path of
1420
+ its own. `spaSite` does that, and writes `sitemap.xml` and `robots.txt` from the
1421
+ route table at the address the site is served at; serves the build's files, with
1422
+ `assets/` kept for a year; leaves `/v1/` and `/docs` to the API; and answers
1423
+ `/health`.
1424
+
1425
+ ```ts
1426
+ await app.register(spaSite, {
1427
+ root: join(import.meta.dirname, '../../frontend/dist'),
1428
+ site: 'wikidata',
1429
+ siteUrl: process.env.SITE_URL, // blank: the origin the request arrived on
1430
+ trackingScript: process.env.TRACKING_SCRIPT,
1431
+ noscript: { heading: 'wikidata.cheminfo.org', hrefs: 'relative' },
1432
+ // A compound under its own name; undefined falls back to the table.
1433
+ page: (url) => compoundPage(db, url),
1434
+ sitemapPaths: () => db.pageIds().map((id) => `/compound/${id}`),
1435
+ });
1436
+ ```
1437
+
1438
+ The route table is the one the app reads, written beside the page at build time
1439
+ by `cheminfoRouteTable` from `react-cheminfo/vite`, which also runs
1440
+ `assertRoutes` when the build starts; `readRouteTable(root, fallback)` reads it
1441
+ back. `notFoundStatus: 404` with `knownRoute` answers an address the app does not
1442
+ route with a real 404, `structuredData` takes a function writing the whole block,
1443
+ and `indexed: false` keeps an admin site out of every index.
1444
+
1445
+ ```ts
1446
+ // frontend/vite.config.ts
1447
+ plugins: [react(), cheminfoRouteTable({ routes: ROUTES })],
1448
+ ```
1449
+
1450
+ ### Writing to molecules.cheminfo.org
1451
+
1452
+ `createMoleculesClient` from `react-cheminfo/core` is the client a site writes
1453
+ its source through: `startImport`, `importState`, `submit`, `lookup` and
1454
+ `purge`, each attempt with its own deadline, retried on 429, 502, 503, 504 or no
1455
+ answer with doubling, spread pauses that honour `Retry-After`, bodies gzipped.
1456
+ It reads no Node module.
1457
+
1458
+ ```ts
1459
+ const molecules = createMoleculesClient({
1460
+ baseUrl: 'https://molecules.cheminfo.org',
1461
+ token: process.env.MOLECULES_TOKEN_LOTUS,
1462
+ onRetry: (details) =>
1463
+ logger.warn(details, 'molecules.cheminfo.org: retrying'),
1464
+ });
1465
+ const { importKey } = await molecules.startImport();
1466
+ ```
1467
+
1468
+ ## Answers shown in a chat
1469
+
1470
+ A site's tool server answers mcp.cheminfo.org with a link to the page people
1471
+ share and a card: the same page on this server under `?embed=1&card=1`, which
1472
+ the chat frames inline, and the page itself over the full screen. The card and
1473
+ the page read the same parameters, so they never disagree about what was
1474
+ asked.
1475
+
1476
+ The server writes both addresses with `react-cheminfo/server`. `siteUrl` and
1477
+ `publicUrl` may be an origin or an origin and a mount, with or without a
1478
+ trailing slash, and a page is named from the site's own root: every helper
1479
+ joins them with exactly one slash.
1480
+
1481
+ ```ts
1482
+ import {
1483
+ answerAddresses,
1484
+ cardMeta,
1485
+ pageAnswer,
1486
+ siteView,
1487
+ } from 'react-cheminfo/server';
1488
+
1489
+ const addresses = answerAddresses({ siteUrl, publicUrl });
1490
+ // { link: 'https://equilibrium.cheminfo.org/titration?ind=thymol', meta }
1491
+ const answer = pageAnswer(addresses, '/titration', { ind: 'thymol' });
1492
+ // A query written by the site's own codec, and what only the card reads.
1493
+ const meta = cardMeta(addresses, `/?${libraryQuery}`, {
1494
+ hide: ['editor'],
1495
+ extra: { rows: '10' },
1496
+ });
1497
+ const view = siteView({ uri: 'ui://vcl/page', name, description, addresses });
1498
+ ```
1499
+
1500
+ A card address longer than `maxLength` (8000) is not carried: `meta` is then
1501
+ undefined and the chat draws the answer itself, while `link` still names the
1502
+ page. These helpers are built on `embedMeta` and `embedView`, so
1503
+ `cheminfo-mcp-server` (an optional peer) is installed by a site that imports
1504
+ `react-cheminfo/server`. The addresses alone — `CARD_PARAM`, `sitePageUrl`,
1505
+ `cardPageUrl`, `framedPageUrl` — are in `react-cheminfo/core`, for the page.
1506
+
1507
+ The card itself is drawn with `react-cheminfo/card` and
1508
+ `react-cheminfo/styles/card.css`:
1509
+
1510
+ ```tsx
1511
+ import 'react-cheminfo/styles/card.css';
1512
+ import {
1513
+ CardDetailsButton,
1514
+ CardFigure,
1515
+ CardFrame,
1516
+ CopyTableButton,
1517
+ } from 'react-cheminfo/card';
1518
+ import { StructureExportButton } from 'react-cheminfo/structure';
1519
+
1520
+ <CardFrame>
1521
+ <p className="card__header card__title">pH 8.72 at equivalence</p>
1522
+ <CardFigure
1523
+ fileName="titration"
1524
+ tools={<StructureExportButton smiles={smiles} />}
1525
+ >
1526
+ <TitrationChart />
1527
+ </CardFigure>
1528
+ <div className="card__end">
1529
+ <CopyTableButton table={() => toDelimited(rows)} />
1530
+ <CardDetailsButton address={{ cardParams: ['scale', 'ph'] }} />
1531
+ </div>
1532
+ </CardFrame>;
1533
+ ```
1534
+
1535
+ `CardFrame` reports the card's height to the frame and grows the card while a
1536
+ dialog or a popover it opened is open, so the frame holds it — only when the
1537
+ page is framed. A card that keeps its own root uses `ref={fitCardToFrame}`, or
1538
+ `useFitCardToFrame(ref)`. `CardDetailsButton` opens the card's address without
1539
+ `card`, `embed`, `hide` and the parameters only the card reads, in a new tab
1540
+ when framed and in place otherwise. Their words come from the chrome's
1541
+ catalog, in the language of the page.
1542
+
1256
1543
  ## Saying which build is running
1257
1544
 
1258
1545
  A report of something going wrong is worth answering only when we know what was
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The card of an answer, as its address says it.
3
+ *
4
+ * A chat shows a tool's answer twice: inline, as a card drawing only what the
5
+ * question asked, and over the full screen, as the site's page. The card is
6
+ * that page with `card` in its query, always with `embed`, so the card and
7
+ * the page behind it read the same parameters and can never disagree about
8
+ * what was asked. `card` is read by its presence: `?card` and `?card=1` both
9
+ * ask for it.
10
+ *
11
+ * Pure string work: the page reads these addresses, and the tool server
12
+ * writes them, in Node.
13
+ */
14
+ /** The parameter asking for the answer's card instead of the page. */
15
+ export declare const CARD_PARAM = "card";
16
+ /**
17
+ * Whether an address asks for a card.
18
+ * @param search - The query string, with or without its leading `?`.
19
+ * @returns True when it names `card`, with a value or bare.
20
+ */
21
+ export declare function isCardAddress(search: string): boolean;
22
+ /**
23
+ * The address a card is at: `globalThis.location`, a `URL`, or any record of
24
+ * the three parts.
25
+ */
26
+ export interface CardLocation {
27
+ /** Its origin, e.g. `https://equilibrium.cheminfo.org`. */
28
+ readonly origin: string;
29
+ /** Its path, the mount and a language prefix included. */
30
+ readonly pathname: string;
31
+ /** Its query string, with or without its `?`. */
32
+ readonly search: string;
33
+ }
34
+ /** How {@link sitePageUrl} tells the card's parameters from the page's. */
35
+ export interface SitePageOptions {
36
+ /**
37
+ * The parameters only the site's card reads, beside `card` itself: what a
38
+ * card draws beyond the page, e.g. `['rows']`, `['scale', 'ph']`.
39
+ * @default []
40
+ */
41
+ cardParams?: readonly string[];
42
+ /**
43
+ * Read a `+` in a key as a plus rather than as a space, as
44
+ * `parseQueryEntries` does. A key carries no `+` on any site of the family,
45
+ * so this only matters to a site that writes its own addresses with
46
+ * `URLSearchParams`.
47
+ * @default true
48
+ */
49
+ literalPlus?: boolean;
50
+ /**
51
+ * A parameter the page at a given path does not read, though another page
52
+ * of the site does: a tutorial step reads no InChI, the converter does.
53
+ * @default undefined - nothing beyond `card`, `embed`, `hide` and
54
+ * `cardParams` is left out
55
+ */
56
+ isCardOnly?: (key: string, pathname: string) => boolean;
57
+ }
58
+ /**
59
+ * The site's own page a card stands for, with its chrome: the card's address
60
+ * without `card`, `embed`, `hide` and what only the card reads. Every other
61
+ * parameter is kept exactly as it was written, so the `+` of a charged atom
62
+ * stays a plus and the commas of a list stay commas. This is the address an
63
+ * answer's `link` names, and the one the card's Details button opens.
64
+ * @param location - The card's address: `globalThis.location`, or
65
+ * `new URL(href)` for an address held as text.
66
+ * @param options - What only the site's card reads.
67
+ * @returns The page's absolute address, without a fragment.
68
+ */
69
+ export declare function sitePageUrl(location: CardLocation, options?: SitePageOptions): string;
70
+ //# sourceMappingURL=cardAddress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cardAddress.d.ts","sourceRoot":"","sources":["../../../src/card/core/cardAddress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,sEAAsE;AACtE,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAKrD;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,YAAY,EACtB,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAeR"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The card of an answer, as its address says it.
3
+ *
4
+ * A chat shows a tool's answer twice: inline, as a card drawing only what the
5
+ * question asked, and over the full screen, as the site's page. The card is
6
+ * that page with `card` in its query, always with `embed`, so the card and
7
+ * the page behind it read the same parameters and can never disagree about
8
+ * what was asked. `card` is read by its presence: `?card` and `?card=1` both
9
+ * ask for it.
10
+ *
11
+ * Pure string work: the page reads these addresses, and the tool server
12
+ * writes them, in Node.
13
+ */
14
+ import { parseQueryEntries } from "../../router/core/query.js";
15
+ import { EMBED_PARAM, HIDE_PARAM } from "../../share/core/config.js";
16
+ /** The parameter asking for the answer's card instead of the page. */
17
+ export const CARD_PARAM = 'card';
18
+ /**
19
+ * Whether an address asks for a card.
20
+ * @param search - The query string, with or without its leading `?`.
21
+ * @returns True when it names `card`, with a value or bare.
22
+ */
23
+ export function isCardAddress(search) {
24
+ for (const [key] of parseQueryEntries(search)) {
25
+ if (key === CARD_PARAM)
26
+ return true;
27
+ }
28
+ return false;
29
+ }
30
+ /**
31
+ * The site's own page a card stands for, with its chrome: the card's address
32
+ * without `card`, `embed`, `hide` and what only the card reads. Every other
33
+ * parameter is kept exactly as it was written, so the `+` of a charged atom
34
+ * stays a plus and the commas of a list stay commas. This is the address an
35
+ * answer's `link` names, and the one the card's Details button opens.
36
+ * @param location - The card's address: `globalThis.location`, or
37
+ * `new URL(href)` for an address held as text.
38
+ * @param options - What only the site's card reads.
39
+ * @returns The page's absolute address, without a fragment.
40
+ */
41
+ export function sitePageUrl(location, options = {}) {
42
+ const { cardParams = [], literalPlus = true, isCardOnly } = options;
43
+ const dropped = new Set([CARD_PARAM, EMBED_PARAM, HIDE_PARAM, ...cardParams]);
44
+ const kept = [];
45
+ const search = location.search.startsWith('?')
46
+ ? location.search.slice(1)
47
+ : location.search;
48
+ for (const part of search.split('&')) {
49
+ const [entry] = parseQueryEntries(part, { literalPlus });
50
+ if (entry === undefined || dropped.has(entry[0]))
51
+ continue;
52
+ if (isCardOnly?.(entry[0], location.pathname))
53
+ continue;
54
+ kept.push(part);
55
+ }
56
+ const query = kept.join('&');
57
+ return `${location.origin}${location.pathname}${query === '' ? '' : `?${query}`}`;
58
+ }
59
+ //# sourceMappingURL=cardAddress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cardAddress.js","sourceRoot":"","sources":["../../../src/card/core/cardAddress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAErE,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9C,IAAI,GAAG,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAwCD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CACzB,QAAsB,EACtB,UAA2B,EAAE;IAE7B,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,WAAW,GAAG,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IACpE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QAC5C,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;IACpB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;QACzD,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS;QAC3D,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC;YAAE,SAAS;QACxD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,QAAQ,GAAG,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;AACpF,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The two addresses a chat frames for one answer: the card, inline, and the
3
+ * page itself, over the full screen. Both are the site's page under `embed`,
4
+ * so neither carries the site's chrome; the card adds `card` and what only it
5
+ * reads.
6
+ */
7
+ /** How {@link framedPageUrl} frames a page. */
8
+ export interface FramedPageOptions {
9
+ /**
10
+ * The parts of the page left out, on the card and on the full page alike:
11
+ * keys of the site's `hide` vocabulary, written `hide=a,b`.
12
+ * @default []
13
+ */
14
+ hide?: readonly string[];
15
+ }
16
+ /** What {@link cardPageUrl} adds to the framed page. */
17
+ export interface CardPageOptions extends FramedPageOptions {
18
+ /**
19
+ * What `card` carries, for a site whose page draws more than one card:
20
+ * wikidata's `card=infobox`.
21
+ * @default '1'
22
+ */
23
+ card?: string;
24
+ /**
25
+ * What only the card reads, written after `card` in the order given, e.g.
26
+ * `{ rows: '10' }`. A value left `undefined` or empty is not written.
27
+ * @default {}
28
+ */
29
+ extra?: Readonly<Record<string, string | undefined>>;
30
+ }
31
+ /**
32
+ * The page under `embed=1`, and `hide` when parts are left out: what a chat
33
+ * shows over the full screen when the reader asks for more than the card.
34
+ * @param page - The site's page as people open it, with its own query and
35
+ * without `embed`, `hide` or `card`; absolute, or a path.
36
+ * @param options - The parts left out.
37
+ * @returns The framed page's address.
38
+ */
39
+ export declare function framedPageUrl(page: string, options?: FramedPageOptions): string;
40
+ /**
41
+ * The card of an answer: the framed page with `card`, and what only the card
42
+ * reads after it.
43
+ * @param page - The site's page as people open it, with its own query and
44
+ * without `embed`, `hide` or `card`; absolute, or a path.
45
+ * @param options - The parts left out, and what the card draws.
46
+ * @returns The card's address.
47
+ */
48
+ export declare function cardPageUrl(page: string, options?: CardPageOptions): string;
49
+ //# sourceMappingURL=cardPageUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cardPageUrl.d.ts","sourceRoot":"","sources":["../../../src/card/core/cardPageUrl.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CACtD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CAKR;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAOR"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The two addresses a chat frames for one answer: the card, inline, and the
3
+ * page itself, over the full screen. Both are the site's page under `embed`,
4
+ * so neither carries the site's chrome; the card adds `card` and what only it
5
+ * reads.
6
+ */
7
+ import { formatQueryEntries } from "../../router/core/query.js";
8
+ import { EMBED_PARAM, HIDE_PARAM } from "../../share/core/config.js";
9
+ import { CARD_PARAM } from "./cardAddress.js";
10
+ /**
11
+ * The page under `embed=1`, and `hide` when parts are left out: what a chat
12
+ * shows over the full screen when the reader asks for more than the card.
13
+ * @param page - The site's page as people open it, with its own query and
14
+ * without `embed`, `hide` or `card`; absolute, or a path.
15
+ * @param options - The parts left out.
16
+ * @returns The framed page's address.
17
+ */
18
+ export function framedPageUrl(page, options = {}) {
19
+ const { hide = [] } = options;
20
+ const entries = [[EMBED_PARAM, '1']];
21
+ if (hide.length > 0)
22
+ entries.push([HIDE_PARAM, hide.join(',')]);
23
+ return withQueryEntries(page, entries);
24
+ }
25
+ /**
26
+ * The card of an answer: the framed page with `card`, and what only the card
27
+ * reads after it.
28
+ * @param page - The site's page as people open it, with its own query and
29
+ * without `embed`, `hide` or `card`; absolute, or a path.
30
+ * @param options - The parts left out, and what the card draws.
31
+ * @returns The card's address.
32
+ */
33
+ export function cardPageUrl(page, options = {}) {
34
+ const { card = '1', extra = {} } = options;
35
+ const entries = [[CARD_PARAM, card]];
36
+ for (const [key, value] of Object.entries(extra)) {
37
+ if (value !== undefined && value !== '')
38
+ entries.push([key, value]);
39
+ }
40
+ return withQueryEntries(framedPageUrl(page, options), entries);
41
+ }
42
+ /**
43
+ * Append parameters to an address, before its fragment.
44
+ * @param address - The address, with or without a query.
45
+ * @param entries - The parameters, in the order they are written.
46
+ * @returns The address carrying them.
47
+ */
48
+ function withQueryEntries(address, entries) {
49
+ const hashIndex = address.indexOf('#');
50
+ const head = hashIndex === -1 ? address : address.slice(0, hashIndex);
51
+ const fragment = hashIndex === -1 ? '' : address.slice(hashIndex);
52
+ const separator = head.includes('?')
53
+ ? head.endsWith('?') || head.endsWith('&')
54
+ ? ''
55
+ : '&'
56
+ : '?';
57
+ return `${head}${separator}${formatQueryEntries(entries)}${fragment}`;
58
+ }
59
+ //# sourceMappingURL=cardPageUrl.js.map