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
@@ -0,0 +1,250 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ import { useEffect, useEffectEvent, useMemo, useState } from 'react';
3
+
4
+ import { useDocumentListNavigation } from '../../hooks/ui/useDocumentListNavigation.ts';
5
+ import type { SplitRange } from '../../split/core/split.ts';
6
+ import { clampSplit } from '../../split/core/split.ts';
7
+ import { SplitRow } from '../../split/ui/SplitRow.tsx';
8
+ import type { AttemptStore } from '../core/attempts.ts';
9
+ import { attemptKey } from '../core/attempts.ts';
10
+ import { progressSummary } from '../core/progress.ts';
11
+ import type { PickSeededOptions, SeedRange } from '../core/seed.ts';
12
+ import { freshSeed, pickSeeded } from '../core/seed.ts';
13
+ import type { SeriesTool } from '../core/series.ts';
14
+
15
+ import { ExerciseProgressHeader } from './ExerciseProgressHeader.tsx';
16
+ import type { QuestionRendering } from './QuestionCard.tsx';
17
+ import { QuestionCard } from './QuestionCard.tsx';
18
+ import { SeriesHead, SeriesQuestionList } from './seriesParts.tsx';
19
+ import { useAttemptRecords } from './useAttemptRecords.ts';
20
+
21
+ /** What {@link ExerciseSeries} needs. */
22
+ export interface ExerciseSeriesProps<
23
+ Question,
24
+ > extends QuestionRendering<Question> {
25
+ /** The tool the series is drawn from. */
26
+ tool: SeriesTool<Question>;
27
+ /** Where the attempts, and the series each tool was last on, are kept. */
28
+ store: AttemptStore;
29
+ /** How a question is named in the list beside the card. */
30
+ label: (question: Question) => ReactNode;
31
+ /**
32
+ * The seed the address names, read with `parseSeed`, or `null` when it names
33
+ * none — the series this browser was last on is then written into it.
34
+ */
35
+ seed: number | null;
36
+ /**
37
+ * Write a seed into the address: `replace` when the page adopts one it was
38
+ * opened without, `push` when the student draws a new series, so Back
39
+ * returns to the previous one.
40
+ */
41
+ onSeed: (seed: number, history: 'replace' | 'push') => void;
42
+ /** How many questions the student asked for; the pool caps it. */
43
+ count: number;
44
+ /** Change how many questions the series holds. */
45
+ onCount: (count: number) => void;
46
+ /**
47
+ * The lengths offered, beside the whole pool.
48
+ * @default [5, 10, 15, 20]
49
+ */
50
+ counts?: readonly number[];
51
+ /**
52
+ * The share of the row the list takes, as the address names it, or `null`
53
+ * for {@link ExerciseSeriesProps.defaultSplit}.
54
+ */
55
+ split: number | null;
56
+ /** Write the share a drag came to rest at, or `null` for the default. */
57
+ onSplit: (split: number | null) => void;
58
+ /**
59
+ * The share the list opens at: the card is the figure, so the list opens
60
+ * narrow.
61
+ * @default 22
62
+ */
63
+ defaultSplit?: number;
64
+ /**
65
+ * How far the list may be dragged, measured on the labels of the pool.
66
+ * @default { min: 15, max: 26 }
67
+ */
68
+ splitRange?: SplitRange;
69
+ /**
70
+ * The narrowest row still divided, in pixels; under it the list stacks under
71
+ * the card's row, as on a tablet held upright.
72
+ * @default SplitRow's own, 860
73
+ */
74
+ stackBelow?: number;
75
+ /**
76
+ * How the series is drawn from the pool, for a site whose links were written
77
+ * with the other generator call.
78
+ * @default { draw: 'getFloat', wrap: false }
79
+ */
80
+ pick?: PickSeededOptions;
81
+ /**
82
+ * The seeds a new series is drawn from.
83
+ * @default every unsigned 32-bit integer
84
+ */
85
+ seedRange?: SeedRange;
86
+ /**
87
+ * The heading over the series.
88
+ * @default the chrome's own word for it, in the language of the page
89
+ */
90
+ title?: ReactNode;
91
+ /**
92
+ * Id of the heading, for a section labelled by it.
93
+ * @default 'questions-heading'
94
+ */
95
+ headingId?: string;
96
+ }
97
+
98
+ const DEFAULT_RANGE: SplitRange = { min: 15, max: 26 };
99
+
100
+ /**
101
+ * A graded series drawn from a tool's pool: the list of its questions, the one
102
+ * open, and the progress over the series.
103
+ *
104
+ * The series is its seed, and the seed is in the address, so the link on
105
+ * screen reopens the same questions for anyone — a teacher hands one series to
106
+ * a whole class. How the row is divided between the list and the open question
107
+ * travels in the address too. The component reads neither: the page hands it
108
+ * the seed, the length and the share, and is told when one changes.
109
+ * @param props - The tool, where its attempts are kept, the address values,
110
+ * and how to draw a question.
111
+ * @returns The series.
112
+ */
113
+ export function ExerciseSeries<Question>(
114
+ props: ExerciseSeriesProps<Question>,
115
+ ): ReactElement {
116
+ const {
117
+ tool,
118
+ store,
119
+ label,
120
+ seed: addressSeed,
121
+ onSeed,
122
+ count: wanted,
123
+ onCount,
124
+ counts,
125
+ split,
126
+ onSplit,
127
+ defaultSplit = 22,
128
+ splitRange = DEFAULT_RANGE,
129
+ stackBelow,
130
+ pick,
131
+ seedRange,
132
+ title,
133
+ headingId = 'questions-heading',
134
+ ...rendering
135
+ } = props;
136
+ const records = useAttemptRecords(store);
137
+ const [fallbackSeed] = useState(
138
+ () => store.storedSeed(tool.id) ?? freshSeed(seedRange),
139
+ );
140
+ const seed = addressSeed ?? fallbackSeed;
141
+ const poolSize = tool.maxCount ?? tool.pool.length;
142
+ const count = Math.min(wanted, poolSize);
143
+
144
+ // The address is what the series is read from and handed out as, so a page
145
+ // opened without a seed writes the one it fell back on into it; and the
146
+ // series on screen is the one this tool reopens on the next visit.
147
+ const followSeed = useEffectEvent((): void => {
148
+ if (addressSeed === null) onSeed(fallbackSeed, 'replace');
149
+ store.storeSeed(tool.id, addressSeed ?? fallbackSeed);
150
+ });
151
+ useEffect(() => {
152
+ followSeed();
153
+ }, [seed, addressSeed, tool.id]);
154
+
155
+ const series = useMemo(
156
+ () =>
157
+ tool.draw === undefined
158
+ ? pickSeeded(tool.pool, count, seed, pick)
159
+ : tool.draw(count, seed),
160
+ [tool, count, seed, pick],
161
+ );
162
+ const keys = useMemo(
163
+ () =>
164
+ series.map((question) => attemptKey(tool.id, seed, tool.key(question))),
165
+ [series, tool, seed],
166
+ );
167
+
168
+ const [opened, setOpened] = useState({ seed, index: 0 });
169
+ const index =
170
+ opened.seed === seed ? Math.min(opened.index, series.length - 1) : 0;
171
+ function open(next: number): void {
172
+ setOpened({ seed, index: next });
173
+ }
174
+ const listRef = useDocumentListNavigation<HTMLElement>({
175
+ length: series.length,
176
+ selectedIndex: index,
177
+ onSelect: open,
178
+ });
179
+
180
+ const summary = progressSummary(records, keys);
181
+ const question = series[index];
182
+ const storageKey = keys[index];
183
+
184
+ return (
185
+ <div className="exercise-series">
186
+ <SeriesHead
187
+ title={title}
188
+ headingId={headingId}
189
+ count={count}
190
+ poolSize={poolSize}
191
+ counts={counts}
192
+ onCount={onCount}
193
+ onNewSeries={() => {
194
+ const next = freshSeed(seedRange);
195
+ store.forgetOtherSeries(tool.id, next);
196
+ onSeed(next, 'push');
197
+ }}
198
+ />
199
+
200
+ <ExerciseProgressHeader
201
+ summary={summary}
202
+ onClearAll={() => {
203
+ store.clearAttempts(keys);
204
+ }}
205
+ clearDisabled={!keys.some((key) => records[key] !== undefined)}
206
+ />
207
+
208
+ <SplitRow
209
+ ratio={split === null ? null : clampSplit(split, splitRange)}
210
+ defaultRatio={defaultSplit}
211
+ min={splitRange.min}
212
+ max={splitRange.max}
213
+ stackBelow={stackBelow}
214
+ onRatio={onSplit}
215
+ start={
216
+ <SeriesQuestionList
217
+ series={series}
218
+ keys={keys}
219
+ records={records}
220
+ index={index}
221
+ onOpen={open}
222
+ label={label}
223
+ listRef={listRef}
224
+ />
225
+ }
226
+ end={
227
+ question === undefined || storageKey === undefined ? null : (
228
+ <QuestionCard
229
+ key={storageKey}
230
+ tool={tool}
231
+ question={question}
232
+ store={store}
233
+ storageKey={storageKey}
234
+ number={index + 1}
235
+ total={series.length}
236
+ onNext={
237
+ index + 1 < series.length
238
+ ? () => {
239
+ open(index + 1);
240
+ }
241
+ : undefined
242
+ }
243
+ {...rendering}
244
+ />
245
+ )
246
+ }
247
+ />
248
+ </div>
249
+ );
250
+ }
@@ -0,0 +1,231 @@
1
+ import { Button, Callout, Tag } from '@blueprintjs/core';
2
+ import type { ReactElement, ReactNode } from 'react';
3
+ import { useMemo } from 'react';
4
+
5
+ import { useChromeT } from '../../i18n/ui/useT.ts';
6
+ import { useIsHidden } from '../../share/ui/hiddenParts.ts';
7
+ import type { AttemptStore } from '../core/attempts.ts';
8
+ import { emptyAttempt } from '../core/attempts.ts';
9
+ import type { Answers, FieldCase, SeriesTool } from '../core/series.ts';
10
+
11
+ import { AnswerFields } from './AnswerFields.tsx';
12
+ import { ExerciseActions } from './ExerciseActions.tsx';
13
+ import { GlossaryText } from './GlossaryText.tsx';
14
+ import { HintLadder } from './HintLadder.tsx';
15
+ import { TestCaseList } from './TestCaseList.tsx';
16
+ import { LEVEL_INTENT } from './exerciseMeta.ts';
17
+ import { useAttemptRecords } from './useAttemptRecords.ts';
18
+
19
+ /** What a tool's own answer input is handed. */
20
+ export interface AnswerInputProps<Question> {
21
+ /** The question being answered. */
22
+ question: Question;
23
+ /** What is typed so far, field by field. */
24
+ answers: Answers;
25
+ /** Change one field. */
26
+ onChange: (key: string, value: string) => void;
27
+ /** Check the answer, as Enter does in a box. */
28
+ onSubmit: () => void;
29
+ }
30
+
31
+ /** How one tool draws the parts of a question the card does not know. */
32
+ export interface QuestionRendering<Question> {
33
+ /** The statement of the question. */
34
+ prompt: (question: Question) => ReactNode;
35
+ /**
36
+ * An input of the tool's own — a drawing canvas, a reaction to balance — in
37
+ * place of the typed boxes.
38
+ * @default undefined — one box per field of the tool
39
+ */
40
+ answer?: (props: AnswerInputProps<Question>) => ReactNode;
41
+ /**
42
+ * What the solution shows beyond its text, such as a drawn structure.
43
+ * @default undefined
44
+ */
45
+ solution?: (question: Question) => ReactNode;
46
+ }
47
+
48
+ /** What {@link QuestionCard} needs. */
49
+ export interface QuestionCardProps<
50
+ Question,
51
+ > extends QuestionRendering<Question> {
52
+ /** The tool the question belongs to. */
53
+ tool: SeriesTool<Question>;
54
+ /** The question on the card. */
55
+ question: Question;
56
+ /** Where the attempts are kept. */
57
+ store: AttemptStore;
58
+ /** The key this question's attempt is kept under, from `attemptKey`. */
59
+ storageKey: string;
60
+ /** Its position in the series, counted from 1. */
61
+ number: number;
62
+ /** How many questions the series holds. */
63
+ total: number;
64
+ /**
65
+ * Open the next question; left out on the last one.
66
+ * @default undefined
67
+ */
68
+ onNext?: () => void;
69
+ }
70
+
71
+ /**
72
+ * One question: its statement, the answer, the four actions, and — once
73
+ * checked — the verdict case by case, the hints taken and the solution.
74
+ *
75
+ * The answer is graded on every change, but the verdict is shown only for the
76
+ * answer as it was checked: a numeric answer that turned green as it was typed
77
+ * could be found by trying numbers. A link that hides the `solutions` part
78
+ * takes the solution button away.
79
+ * @param props - The tool, the question, where its attempt is kept, and how to
80
+ * draw it.
81
+ * @returns The card.
82
+ */
83
+ export function QuestionCard<Question>(
84
+ props: QuestionCardProps<Question>,
85
+ ): ReactElement {
86
+ const {
87
+ tool,
88
+ question,
89
+ store,
90
+ storageKey,
91
+ number,
92
+ total,
93
+ onNext,
94
+ prompt,
95
+ answer,
96
+ solution,
97
+ } = props;
98
+ const t = useChromeT();
99
+ const isHidden = useIsHidden();
100
+ const records = useAttemptRecords(store);
101
+ const {
102
+ answers,
103
+ checked: checkedAnswers,
104
+ hintsRevealed,
105
+ showSolution,
106
+ } = records[storageKey] ?? emptyAttempt();
107
+ const check = useMemo(
108
+ () => tool.grade(question, answers),
109
+ [tool, question, answers],
110
+ );
111
+ const hints = useMemo(() => tool.hints(question), [tool, question]);
112
+ const snapshot = JSON.stringify(answers);
113
+ const checked = checkedAnswers === snapshot;
114
+ const solutionsHidden = isHidden('solutions');
115
+ const level = tool.level?.(question);
116
+
117
+ function setAnswer(key: string, value: string): void {
118
+ store.updateAttempt(storageKey, { answers: { ...answers, [key]: value } });
119
+ }
120
+
121
+ function commit(): void {
122
+ store.updateAttempt(storageKey, {
123
+ status: check.passed ? 'solved' : 'attempted',
124
+ checked: snapshot,
125
+ });
126
+ }
127
+
128
+ return (
129
+ <article
130
+ className="series-question"
131
+ aria-label={t('pedagogy.questionNumber', { number })}
132
+ >
133
+ <div className="series-question__meta">
134
+ <span>{t('pedagogy.questionOf', { number, total })}</span>
135
+ {level === undefined ? null : (
136
+ <Tag minimal intent={LEVEL_INTENT[level]}>
137
+ {level}
138
+ </Tag>
139
+ )}
140
+ </div>
141
+ <div className="series-question__prompt">{prompt(question)}</div>
142
+
143
+ {answer ? (
144
+ answer({ question, answers, onChange: setAnswer, onSubmit: commit })
145
+ ) : (
146
+ <AnswerFields
147
+ fields={tool.fields(question)}
148
+ answers={answers}
149
+ onChange={setAnswer}
150
+ onSubmit={commit}
151
+ />
152
+ )}
153
+
154
+ <ExerciseActions
155
+ onCheck={commit}
156
+ checkDisabled={isBlank(answers)}
157
+ onRevealHint={() => {
158
+ store.updateAttempt(storageKey, {
159
+ hintsRevealed: Math.min(hintsRevealed + 1, hints.length),
160
+ });
161
+ }}
162
+ hintsRevealed={hintsRevealed}
163
+ hintCount={hints.length}
164
+ onToggleSolution={
165
+ solutionsHidden
166
+ ? undefined
167
+ : () => {
168
+ store.updateAttempt(storageKey, {
169
+ showSolution: !showSolution,
170
+ });
171
+ }
172
+ }
173
+ showSolution={showSolution}
174
+ onReset={() => {
175
+ store.updateAttempt(storageKey, emptyAttempt());
176
+ }}
177
+ />
178
+
179
+ {checked ? (
180
+ <TestCaseList<FieldCase>
181
+ results={check.cases}
182
+ label={(verdict) => verdict.label}
183
+ />
184
+ ) : null}
185
+
186
+ {checked && check.passed ? (
187
+ <Callout
188
+ intent="success"
189
+ icon="tick-circle"
190
+ title={t('pedagogy.solved')}
191
+ >
192
+ {hintsRevealed > 0
193
+ ? t('pedagogy.solvedWithHintsOf', {
194
+ revealed: hintsRevealed,
195
+ total: hints.length,
196
+ })
197
+ : t('pedagogy.solvedWithoutHint')}
198
+ {onNext ? (
199
+ <Button
200
+ className="series-question__next"
201
+ intent="success"
202
+ endIcon="arrow-right"
203
+ text={t('pedagogy.nextQuestion')}
204
+ onClick={onNext}
205
+ />
206
+ ) : null}
207
+ </Callout>
208
+ ) : null}
209
+
210
+ {hintsRevealed > 0 ? (
211
+ <HintLadder hints={hints} revealed={hintsRevealed} />
212
+ ) : null}
213
+
214
+ {showSolution && !solutionsHidden ? (
215
+ <Callout intent="warning" icon="key" title={t('pedagogy.solution')}>
216
+ <p className="series-question__solution">
217
+ <GlossaryText text={tool.solution(question)} />
218
+ </p>
219
+ {solution?.(question)}
220
+ </Callout>
221
+ ) : null}
222
+ </article>
223
+ );
224
+ }
225
+
226
+ function isBlank(answers: Answers): boolean {
227
+ for (const value of Object.values(answers)) {
228
+ if (value.trim() !== '') return false;
229
+ }
230
+ return true;
231
+ }
@@ -51,3 +51,21 @@ export type {
51
51
  export { TutorialStepStrip } from './TutorialStepStrip.tsx';
52
52
  export type { TutorialLevelColours } from './tutorialLevels.ts';
53
53
  export { TUTORIAL_LEVEL_COLOURS } from './tutorialLevels.ts';
54
+ export type { AnswerFieldsProps } from './AnswerFields.tsx';
55
+ export { AnswerFields } from './AnswerFields.tsx';
56
+ export type {
57
+ ExerciseListEntry,
58
+ ExerciseListProgress,
59
+ ExerciseListProps,
60
+ } from './ExerciseList.tsx';
61
+ export { ExerciseList } from './ExerciseList.tsx';
62
+ export type { ExerciseSeriesProps } from './ExerciseSeries.tsx';
63
+ export { ExerciseSeries } from './ExerciseSeries.tsx';
64
+ export type {
65
+ AnswerInputProps,
66
+ QuestionCardProps,
67
+ QuestionRendering,
68
+ } from './QuestionCard.tsx';
69
+ export { QuestionCard } from './QuestionCard.tsx';
70
+ export { SERIES_COUNTS } from './seriesCounts.ts';
71
+ export { useAttemptRecords } from './useAttemptRecords.ts';
@@ -0,0 +1,34 @@
1
+ import type { ChromeKey } from '../../i18n/core/chromeCatalog.ts';
2
+ import type { Translate } from '../../i18n/core/translate.ts';
3
+
4
+ /** The series lengths offered when a page names none. */
5
+ export const SERIES_COUNTS: readonly number[] = [5, 10, 15, 20];
6
+
7
+ /**
8
+ * The series lengths a pool can fill, and the whole pool last, so a pool
9
+ * smaller than the longest length is offered whole rather than overpromised.
10
+ * @param poolSize - How many questions the pool holds.
11
+ * @param counts - The lengths offered, or the family's when none.
12
+ * @param t - The chrome's formatter.
13
+ * @returns The options of the picker.
14
+ */
15
+ export function seriesCountOptions(
16
+ poolSize: number,
17
+ counts: readonly number[] | undefined,
18
+ t: Translate<ChromeKey>,
19
+ ): Array<{ value: number; label: string }> {
20
+ const options: Array<{ value: number; label: string }> = [];
21
+ for (const count of counts ?? SERIES_COUNTS) {
22
+ if (count < poolSize) {
23
+ options.push({
24
+ value: count,
25
+ label: t('pedagogy.questionCount', { count }),
26
+ });
27
+ }
28
+ }
29
+ options.push({
30
+ value: poolSize,
31
+ label: t('pedagogy.allQuestions', { count: poolSize }),
32
+ });
33
+ return options;
34
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * The two pieces of `ExerciseSeries` that are only layout: the heading row
3
+ * with the length picker and the new-series button, and the numbered list of
4
+ * questions.
5
+ */
6
+
7
+ import { Button, HTMLSelect } from '@blueprintjs/core';
8
+ import type { ReactElement, ReactNode, RefObject } from 'react';
9
+
10
+ import { useChromeT } from '../../i18n/ui/useT.ts';
11
+ import type { Attempt } from '../core/attempts.ts';
12
+ import type { ProgressRecords } from '../core/progress.ts';
13
+
14
+ import { ExerciseStatusIcon } from './ExerciseTags.tsx';
15
+ import { seriesCountOptions } from './seriesCounts.ts';
16
+
17
+ /** What {@link SeriesHead} needs. */
18
+ export interface SeriesHeadProps {
19
+ /** The heading, or the chrome's word for it. */
20
+ title: ReactNode | undefined;
21
+ /** Id of the heading. */
22
+ headingId: string;
23
+ /** The length on screen. */
24
+ count: number;
25
+ /** The largest length the tool serves. */
26
+ poolSize: number;
27
+ /** The lengths offered beside the whole pool. */
28
+ counts: readonly number[] | undefined;
29
+ /** Change the length. */
30
+ onCount: (count: number) => void;
31
+ /** Draw another series. */
32
+ onNewSeries: () => void;
33
+ }
34
+
35
+ /**
36
+ * The heading row of a series.
37
+ * @param props - See {@link SeriesHeadProps}.
38
+ * @returns The row.
39
+ */
40
+ export function SeriesHead(props: SeriesHeadProps): ReactElement {
41
+ const { title, headingId, count, poolSize, counts, onCount, onNewSeries } =
42
+ props;
43
+ const t = useChromeT();
44
+ return (
45
+ <div className="exercise-series__head">
46
+ <h2 className="exercise-series__title" id={headingId}>
47
+ {title ?? t('pedagogy.questions')}
48
+ </h2>
49
+ <div className="exercise-series__controls">
50
+ <HTMLSelect
51
+ aria-label={t('pedagogy.questionsInSeries')}
52
+ value={count}
53
+ onChange={(event) => {
54
+ onCount(Number(event.currentTarget.value));
55
+ }}
56
+ options={seriesCountOptions(poolSize, counts, t)}
57
+ />
58
+ <Button
59
+ icon="refresh"
60
+ text={t('pedagogy.newSeries')}
61
+ title={t('pedagogy.newSeriesTitle')}
62
+ onClick={onNewSeries}
63
+ />
64
+ </div>
65
+ </div>
66
+ );
67
+ }
68
+
69
+ /** What {@link SeriesQuestionList} needs. */
70
+ export interface SeriesQuestionListProps<Question> {
71
+ /** The questions of the series, in order. */
72
+ series: readonly Question[];
73
+ /** The attempt key of each, in the same order. */
74
+ keys: readonly string[];
75
+ /** Every attempt kept. */
76
+ records: ProgressRecords<Attempt>;
77
+ /** The open one. */
78
+ index: number;
79
+ /** Open one. */
80
+ onOpen: (index: number) => void;
81
+ /** How a question is named. */
82
+ label: (question: Question) => ReactNode;
83
+ /** The ref the arrow keys scroll inside. */
84
+ listRef: RefObject<HTMLElement | null>;
85
+ }
86
+
87
+ /**
88
+ * The numbered list of a series, each question with its status.
89
+ * @param props - See {@link SeriesQuestionListProps}.
90
+ * @returns The list.
91
+ */
92
+ export function SeriesQuestionList<Question>(
93
+ props: SeriesQuestionListProps<Question>,
94
+ ): ReactElement {
95
+ const { series, keys, records, index, onOpen, label, listRef } = props;
96
+ const t = useChromeT();
97
+ return (
98
+ <nav
99
+ ref={listRef}
100
+ className="exercise-series__list"
101
+ aria-label={t('pedagogy.seriesQuestions')}
102
+ >
103
+ {series.map((entry, position) => {
104
+ const key = keys[position] ?? '';
105
+ return (
106
+ <Button
107
+ key={key}
108
+ variant="minimal"
109
+ alignText="start"
110
+ fill
111
+ active={position === index}
112
+ data-selected={position === index ? 'true' : undefined}
113
+ icon={
114
+ <ExerciseStatusIcon status={records[key]?.status ?? 'idle'} />
115
+ }
116
+ onClick={() => {
117
+ onOpen(position);
118
+ }}
119
+ >
120
+ <span className="exercise-series__number">{position + 1}.</span>{' '}
121
+ {label(entry)}
122
+ </Button>
123
+ );
124
+ })}
125
+ </nav>
126
+ );
127
+ }
@@ -0,0 +1,16 @@
1
+ import { useSyncExternalStore } from 'react';
2
+
3
+ import type { Attempt, AttemptStore } from '../core/attempts.ts';
4
+ import type { ProgressRecords } from '../core/progress.ts';
5
+
6
+ /**
7
+ * Every attempt a store holds, re-rendering the component whenever one
8
+ * changes.
9
+ * @param store - The site's attempt store.
10
+ * @returns The records, keyed by attempt key.
11
+ */
12
+ export function useAttemptRecords(
13
+ store: AttemptStore,
14
+ ): ProgressRecords<Attempt> {
15
+ return useSyncExternalStore(store.subscribe, store.records, store.records);
16
+ }
@@ -77,10 +77,13 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
77
77
  // otherwise re-render all 118 cells per frame, and the engine recomputes
78
78
  // every length from the custom property on its own. A width of zero is a
79
79
  // table in a tab nobody has opened; the last measurement stands until it is
80
- // shown, and the observer fires again then.
80
+ // shown, and the observer fires again then. `data-measured` says the cells
81
+ // now follow a measured width rather than the `1cqw` fallback.
81
82
  useResizeObserver(rootRef, ({ width }) => {
82
- if (width === 0) return;
83
- rootRef.current?.style.setProperty(UNIT_PROPERTY, unitValue(width));
83
+ const root = rootRef.current;
84
+ if (width === 0 || root === null) return;
85
+ root.style.setProperty(UNIT_PROPERTY, unitValue(width));
86
+ root.dataset.measured = '';
84
87
  });
85
88
 
86
89
  useEffect(() => {