react-cheminfo 0.64.1 → 0.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. package/README.md +282 -0
  2. package/lib/card/core/cardAddress.d.ts +70 -0
  3. package/lib/card/core/cardAddress.d.ts.map +1 -0
  4. package/lib/card/core/cardAddress.js +59 -0
  5. package/lib/card/core/cardAddress.js.map +1 -0
  6. package/lib/card/core/cardPageUrl.d.ts +49 -0
  7. package/lib/card/core/cardPageUrl.d.ts.map +1 -0
  8. package/lib/card/core/cardPageUrl.js +59 -0
  9. package/lib/card/core/cardPageUrl.js.map +1 -0
  10. package/lib/card/core/index.d.ts +7 -0
  11. package/lib/card/core/index.d.ts.map +1 -0
  12. package/lib/card/core/index.js +4 -0
  13. package/lib/card/core/index.js.map +1 -0
  14. package/lib/card/core/panelRoom.d.ts +40 -0
  15. package/lib/card/core/panelRoom.d.ts.map +1 -0
  16. package/lib/card/core/panelRoom.js +40 -0
  17. package/lib/card/core/panelRoom.js.map +1 -0
  18. package/lib/card/ui/CardDetailsButton.d.ts +38 -0
  19. package/lib/card/ui/CardDetailsButton.d.ts.map +1 -0
  20. package/lib/card/ui/CardDetailsButton.js +50 -0
  21. package/lib/card/ui/CardDetailsButton.js.map +1 -0
  22. package/lib/card/ui/CardFigure.d.ts +51 -0
  23. package/lib/card/ui/CardFigure.d.ts.map +1 -0
  24. package/lib/card/ui/CardFigure.js +27 -0
  25. package/lib/card/ui/CardFigure.js.map +1 -0
  26. package/lib/card/ui/CardFrame.d.ts +30 -0
  27. package/lib/card/ui/CardFrame.d.ts.map +1 -0
  28. package/lib/card/ui/CardFrame.js +20 -0
  29. package/lib/card/ui/CardFrame.js.map +1 -0
  30. package/lib/card/ui/CopyTableButton.d.ts +37 -0
  31. package/lib/card/ui/CopyTableButton.d.ts.map +1 -0
  32. package/lib/card/ui/CopyTableButton.js +19 -0
  33. package/lib/card/ui/CopyTableButton.js.map +1 -0
  34. package/lib/card/ui/cardTooltip.d.ts +14 -0
  35. package/lib/card/ui/cardTooltip.d.ts.map +1 -0
  36. package/lib/card/ui/cardTooltip.js +15 -0
  37. package/lib/card/ui/cardTooltip.js.map +1 -0
  38. package/lib/card/ui/embed.d.ts +15 -0
  39. package/lib/card/ui/embed.d.ts.map +1 -0
  40. package/lib/card/ui/embed.js +24 -0
  41. package/lib/card/ui/embed.js.map +1 -0
  42. package/lib/card/ui/fitCardToFrame.d.ts +31 -0
  43. package/lib/card/ui/fitCardToFrame.d.ts.map +1 -0
  44. package/lib/card/ui/fitCardToFrame.js +66 -0
  45. package/lib/card/ui/fitCardToFrame.js.map +1 -0
  46. package/lib/card/ui/holdRoomForPanels.d.ts +16 -0
  47. package/lib/card/ui/holdRoomForPanels.d.ts.map +1 -0
  48. package/lib/card/ui/holdRoomForPanels.js +76 -0
  49. package/lib/card/ui/holdRoomForPanels.js.map +1 -0
  50. package/lib/card/ui/index.d.ts +11 -0
  51. package/lib/card/ui/index.d.ts.map +1 -0
  52. package/lib/card/ui/index.js +7 -0
  53. package/lib/card/ui/index.js.map +1 -0
  54. package/lib/card/ui/openPanels.d.ts +25 -0
  55. package/lib/card/ui/openPanels.d.ts.map +1 -0
  56. package/lib/card/ui/openPanels.js +85 -0
  57. package/lib/card/ui/openPanels.js.map +1 -0
  58. package/lib/card.d.ts +13 -0
  59. package/lib/card.d.ts.map +1 -0
  60. package/lib/card.js +13 -0
  61. package/lib/card.js.map +1 -0
  62. package/lib/conformers.d.ts +1 -0
  63. package/lib/conformers.d.ts.map +1 -1
  64. package/lib/conformers.js +1 -0
  65. package/lib/conformers.js.map +1 -1
  66. package/lib/core.d.ts +4 -0
  67. package/lib/core.d.ts.map +1 -1
  68. package/lib/core.js +5 -0
  69. package/lib/core.js.map +1 -1
  70. package/lib/fetch/core/apiError.d.ts +56 -0
  71. package/lib/fetch/core/apiError.d.ts.map +1 -0
  72. package/lib/fetch/core/apiError.js +43 -0
  73. package/lib/fetch/core/apiError.js.map +1 -0
  74. package/lib/fetch/core/fetchJson.d.ts +47 -0
  75. package/lib/fetch/core/fetchJson.d.ts.map +1 -0
  76. package/lib/fetch/core/fetchJson.js +109 -0
  77. package/lib/fetch/core/fetchJson.js.map +1 -0
  78. package/lib/fetch/core/index.d.ts +5 -0
  79. package/lib/fetch/core/index.d.ts.map +1 -0
  80. package/lib/fetch/core/index.js +3 -0
  81. package/lib/fetch/core/index.js.map +1 -0
  82. package/lib/formula/core/formulaText.d.ts +46 -0
  83. package/lib/formula/core/formulaText.d.ts.map +1 -0
  84. package/lib/formula/core/formulaText.js +74 -0
  85. package/lib/formula/core/formulaText.js.map +1 -0
  86. package/lib/formula/core/index.d.ts +6 -0
  87. package/lib/formula/core/index.d.ts.map +1 -0
  88. package/lib/formula/core/index.js +4 -0
  89. package/lib/formula/core/index.js.map +1 -0
  90. package/lib/formula/core/normalizeFormula.d.ts +22 -0
  91. package/lib/formula/core/normalizeFormula.d.ts.map +1 -0
  92. package/lib/formula/core/normalizeFormula.js +46 -0
  93. package/lib/formula/core/normalizeFormula.js.map +1 -0
  94. package/lib/formula/core/readFormula.d.ts +73 -0
  95. package/lib/formula/core/readFormula.d.ts.map +1 -0
  96. package/lib/formula/core/readFormula.js +132 -0
  97. package/lib/formula/core/readFormula.js.map +1 -0
  98. package/lib/formula/ui/CopyableFormula.d.ts +31 -0
  99. package/lib/formula/ui/CopyableFormula.d.ts.map +1 -0
  100. package/lib/formula/ui/CopyableFormula.js +19 -0
  101. package/lib/formula/ui/CopyableFormula.js.map +1 -0
  102. package/lib/formula/ui/FormulaInput.d.ts +29 -0
  103. package/lib/formula/ui/FormulaInput.d.ts.map +1 -0
  104. package/lib/formula/ui/FormulaInput.js +16 -0
  105. package/lib/formula/ui/FormulaInput.js.map +1 -0
  106. package/lib/formula/ui/QuestionFormula.d.ts +14 -0
  107. package/lib/formula/ui/QuestionFormula.d.ts.map +1 -0
  108. package/lib/formula/ui/QuestionFormula.js +13 -0
  109. package/lib/formula/ui/QuestionFormula.js.map +1 -0
  110. package/lib/formula/ui/index.d.ts +7 -0
  111. package/lib/formula/ui/index.d.ts.map +1 -0
  112. package/lib/formula/ui/index.js +4 -0
  113. package/lib/formula/ui/index.js.map +1 -0
  114. package/lib/formula.d.ts +11 -0
  115. package/lib/formula.d.ts.map +1 -0
  116. package/lib/formula.js +11 -0
  117. package/lib/formula.js.map +1 -0
  118. package/lib/hooks/ui/index.d.ts +1 -0
  119. package/lib/hooks/ui/index.d.ts.map +1 -1
  120. package/lib/hooks/ui/index.js.map +1 -1
  121. package/lib/hooks/ui/keyTargets.d.ts +4 -2
  122. package/lib/hooks/ui/keyTargets.d.ts.map +1 -1
  123. package/lib/hooks/ui/keyTargets.js +5 -3
  124. package/lib/hooks/ui/keyTargets.js.map +1 -1
  125. package/lib/hooks/ui/useAsync.d.ts +20 -5
  126. package/lib/hooks/ui/useAsync.d.ts.map +1 -1
  127. package/lib/hooks/ui/useAsync.js +29 -14
  128. package/lib/hooks/ui/useAsync.js.map +1 -1
  129. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  130. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  131. package/lib/locales/de.json +37 -0
  132. package/lib/locales/en.json +37 -0
  133. package/lib/locales/es.json +37 -0
  134. package/lib/locales/fr.json +37 -0
  135. package/lib/locales/it.json +37 -0
  136. package/lib/moleculesClient/core/index.d.ts +5 -0
  137. package/lib/moleculesClient/core/index.d.ts.map +1 -0
  138. package/lib/moleculesClient/core/index.js +3 -0
  139. package/lib/moleculesClient/core/index.js.map +1 -0
  140. package/lib/moleculesClient/core/moleculesClient.d.ts +12 -0
  141. package/lib/moleculesClient/core/moleculesClient.d.ts.map +1 -0
  142. package/lib/moleculesClient/core/moleculesClient.js +105 -0
  143. package/lib/moleculesClient/core/moleculesClient.js.map +1 -0
  144. package/lib/moleculesClient/core/moleculesClientApi.d.ts +100 -0
  145. package/lib/moleculesClient/core/moleculesClientApi.d.ts.map +1 -0
  146. package/lib/moleculesClient/core/moleculesClientApi.js +20 -0
  147. package/lib/moleculesClient/core/moleculesClientApi.js.map +1 -0
  148. package/lib/moleculesClient/core/moleculesTypes.d.ts +154 -0
  149. package/lib/moleculesClient/core/moleculesTypes.d.ts.map +1 -0
  150. package/lib/moleculesClient/core/moleculesTypes.js +2 -0
  151. package/lib/moleculesClient/core/moleculesTypes.js.map +1 -0
  152. package/lib/moleculesClient/core/requestRetry.d.ts +50 -0
  153. package/lib/moleculesClient/core/requestRetry.d.ts.map +1 -0
  154. package/lib/moleculesClient/core/requestRetry.js +108 -0
  155. package/lib/moleculesClient/core/requestRetry.js.map +1 -0
  156. package/lib/molstar/core/camera.d.ts +2 -1
  157. package/lib/molstar/core/camera.d.ts.map +1 -1
  158. package/lib/molstar/core/camera.js +3 -2
  159. package/lib/molstar/core/camera.js.map +1 -1
  160. package/lib/molstar/core/framing.d.ts +102 -0
  161. package/lib/molstar/core/framing.d.ts.map +1 -0
  162. package/lib/molstar/core/framing.js +120 -0
  163. package/lib/molstar/core/framing.js.map +1 -0
  164. package/lib/molstar/core/hover.d.ts +16 -0
  165. package/lib/molstar/core/hover.d.ts.map +1 -1
  166. package/lib/molstar/core/hover.js +14 -0
  167. package/lib/molstar/core/hover.js.map +1 -1
  168. package/lib/molstar/core/index.d.ts +4 -1
  169. package/lib/molstar/core/index.d.ts.map +1 -1
  170. package/lib/molstar/core/index.js +2 -1
  171. package/lib/molstar/core/index.js.map +1 -1
  172. package/lib/pedagogy/core/answers.d.ts +46 -0
  173. package/lib/pedagogy/core/answers.d.ts.map +1 -0
  174. package/lib/pedagogy/core/answers.js +77 -0
  175. package/lib/pedagogy/core/answers.js.map +1 -0
  176. package/lib/pedagogy/core/attempts.d.ts +86 -0
  177. package/lib/pedagogy/core/attempts.d.ts.map +1 -0
  178. package/lib/pedagogy/core/attempts.js +117 -0
  179. package/lib/pedagogy/core/attempts.js.map +1 -0
  180. package/lib/pedagogy/core/index.d.ts +8 -0
  181. package/lib/pedagogy/core/index.d.ts.map +1 -1
  182. package/lib/pedagogy/core/index.js +4 -0
  183. package/lib/pedagogy/core/index.js.map +1 -1
  184. package/lib/pedagogy/core/progressController.d.ts +64 -0
  185. package/lib/pedagogy/core/progressController.d.ts.map +1 -0
  186. package/lib/pedagogy/core/progressController.js +56 -0
  187. package/lib/pedagogy/core/progressController.js.map +1 -0
  188. package/lib/pedagogy/core/seed.d.ts +96 -0
  189. package/lib/pedagogy/core/seed.d.ts.map +1 -0
  190. package/lib/pedagogy/core/seed.js +128 -0
  191. package/lib/pedagogy/core/seed.js.map +1 -0
  192. package/lib/pedagogy/core/series.d.ts +77 -0
  193. package/lib/pedagogy/core/series.d.ts.map +1 -0
  194. package/lib/pedagogy/core/series.js +10 -0
  195. package/lib/pedagogy/core/series.js.map +1 -0
  196. package/lib/pedagogy/ui/AnswerFields.d.ts +21 -0
  197. package/lib/pedagogy/ui/AnswerFields.d.ts.map +1 -0
  198. package/lib/pedagogy/ui/AnswerFields.js +24 -0
  199. package/lib/pedagogy/ui/AnswerFields.js.map +1 -0
  200. package/lib/pedagogy/ui/ExerciseList.d.ts +82 -0
  201. package/lib/pedagogy/ui/ExerciseList.d.ts.map +1 -0
  202. package/lib/pedagogy/ui/ExerciseList.js +53 -0
  203. package/lib/pedagogy/ui/ExerciseList.js.map +1 -0
  204. package/lib/pedagogy/ui/ExerciseSeries.d.ts +95 -0
  205. package/lib/pedagogy/ui/ExerciseSeries.d.ts.map +1 -0
  206. package/lib/pedagogy/ui/ExerciseSeries.js +74 -0
  207. package/lib/pedagogy/ui/ExerciseSeries.js.map +1 -0
  208. package/lib/pedagogy/ui/QuestionCard.d.ts +64 -0
  209. package/lib/pedagogy/ui/QuestionCard.d.ts.map +1 -0
  210. package/lib/pedagogy/ui/QuestionCard.js +73 -0
  211. package/lib/pedagogy/ui/QuestionCard.js.map +1 -0
  212. package/lib/pedagogy/ui/index.d.ts +10 -0
  213. package/lib/pedagogy/ui/index.d.ts.map +1 -1
  214. package/lib/pedagogy/ui/index.js +6 -0
  215. package/lib/pedagogy/ui/index.js.map +1 -1
  216. package/lib/pedagogy/ui/seriesCounts.d.ts +17 -0
  217. package/lib/pedagogy/ui/seriesCounts.d.ts.map +1 -0
  218. package/lib/pedagogy/ui/seriesCounts.js +27 -0
  219. package/lib/pedagogy/ui/seriesCounts.js.map +1 -0
  220. package/lib/pedagogy/ui/seriesParts.d.ts +55 -0
  221. package/lib/pedagogy/ui/seriesParts.d.ts.map +1 -0
  222. package/lib/pedagogy/ui/seriesParts.js +38 -0
  223. package/lib/pedagogy/ui/seriesParts.js.map +1 -0
  224. package/lib/pedagogy/ui/useAttemptRecords.d.ts +10 -0
  225. package/lib/pedagogy/ui/useAttemptRecords.d.ts.map +1 -0
  226. package/lib/pedagogy/ui/useAttemptRecords.js +11 -0
  227. package/lib/pedagogy/ui/useAttemptRecords.js.map +1 -0
  228. package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
  229. package/lib/periodic/ui/PeriodicTable.js +6 -3
  230. package/lib/periodic/ui/PeriodicTable.js.map +1 -1
  231. package/lib/property/core/copyableText.d.ts +14 -0
  232. package/lib/property/core/copyableText.d.ts.map +1 -0
  233. package/lib/property/core/copyableText.js +21 -0
  234. package/lib/property/core/copyableText.js.map +1 -0
  235. package/lib/property/core/index.d.ts +2 -0
  236. package/lib/property/core/index.d.ts.map +1 -0
  237. package/lib/property/core/index.js +2 -0
  238. package/lib/property/core/index.js.map +1 -0
  239. package/lib/property/ui/PropertyTable.d.ts +43 -0
  240. package/lib/property/ui/PropertyTable.d.ts.map +1 -0
  241. package/lib/property/ui/PropertyTable.js +19 -0
  242. package/lib/property/ui/PropertyTable.js.map +1 -0
  243. package/lib/property/ui/index.d.ts +3 -0
  244. package/lib/property/ui/index.d.ts.map +1 -0
  245. package/lib/property/ui/index.js +2 -0
  246. package/lib/property/ui/index.js.map +1 -0
  247. package/lib/router/core/history.d.ts +24 -3
  248. package/lib/router/core/history.d.ts.map +1 -1
  249. package/lib/router/core/history.js +55 -7
  250. package/lib/router/core/history.js.map +1 -1
  251. package/lib/router/core/index.d.ts +3 -3
  252. package/lib/router/core/index.d.ts.map +1 -1
  253. package/lib/router/core/index.js +2 -2
  254. package/lib/router/core/index.js.map +1 -1
  255. package/lib/router/core/languageRoute.d.ts +61 -0
  256. package/lib/router/core/languageRoute.d.ts.map +1 -0
  257. package/lib/router/core/languageRoute.js +96 -0
  258. package/lib/router/core/languageRoute.js.map +1 -0
  259. package/lib/router/core/siteAddresses.d.ts +23 -0
  260. package/lib/router/core/siteAddresses.d.ts.map +1 -1
  261. package/lib/router/core/siteAddresses.js +26 -0
  262. package/lib/router/core/siteAddresses.js.map +1 -1
  263. package/lib/router/core/tabRouter.d.ts +2 -108
  264. package/lib/router/core/tabRouter.d.ts.map +1 -1
  265. package/lib/router/core/tabRouter.js +38 -5
  266. package/lib/router/core/tabRouter.js.map +1 -1
  267. package/lib/router/core/tabRouterTypes.d.ts +154 -0
  268. package/lib/router/core/tabRouterTypes.d.ts.map +1 -0
  269. package/lib/router/core/tabRouterTypes.js +2 -0
  270. package/lib/router/core/tabRouterTypes.js.map +1 -0
  271. package/lib/seo/core/fitDescription.d.ts +40 -0
  272. package/lib/seo/core/fitDescription.d.ts.map +1 -0
  273. package/lib/seo/core/fitDescription.js +45 -0
  274. package/lib/seo/core/fitDescription.js.map +1 -0
  275. package/lib/seo/core/index.d.ts +7 -0
  276. package/lib/seo/core/index.d.ts.map +1 -1
  277. package/lib/seo/core/index.js +4 -0
  278. package/lib/seo/core/index.js.map +1 -1
  279. package/lib/seo/core/limits.d.ts +24 -0
  280. package/lib/seo/core/limits.d.ts.map +1 -0
  281. package/lib/seo/core/limits.js +24 -0
  282. package/lib/seo/core/limits.js.map +1 -0
  283. package/lib/seo/core/pageContent.d.ts +25 -0
  284. package/lib/seo/core/pageContent.d.ts.map +1 -0
  285. package/lib/seo/core/pageContent.js +25 -0
  286. package/lib/seo/core/pageContent.js.map +1 -0
  287. package/lib/seo/core/plainDescription.d.ts.map +1 -1
  288. package/lib/seo/core/plainDescription.js +3 -2
  289. package/lib/seo/core/plainDescription.js.map +1 -1
  290. package/lib/seo/core/routeProblems.d.ts.map +1 -1
  291. package/lib/seo/core/routeProblems.js +1 -6
  292. package/lib/seo/core/routeProblems.js.map +1 -1
  293. package/lib/seo/core/routeTable.d.ts +31 -0
  294. package/lib/seo/core/routeTable.d.ts.map +1 -0
  295. package/lib/seo/core/routeTable.js +96 -0
  296. package/lib/seo/core/routeTable.js.map +1 -0
  297. package/lib/seo/vite/index.d.ts +2 -0
  298. package/lib/seo/vite/index.d.ts.map +1 -1
  299. package/lib/seo/vite/index.js +1 -0
  300. package/lib/seo/vite/index.js.map +1 -1
  301. package/lib/seo/vite/prerender.d.ts +10 -0
  302. package/lib/seo/vite/prerender.d.ts.map +1 -1
  303. package/lib/seo/vite/prerender.js +12 -1
  304. package/lib/seo/vite/prerender.js.map +1 -1
  305. package/lib/seo/vite/routeTable.d.ts +40 -0
  306. package/lib/seo/vite/routeTable.d.ts.map +1 -0
  307. package/lib/seo/vite/routeTable.js +44 -0
  308. package/lib/seo/vite/routeTable.js.map +1 -0
  309. package/lib/server/answerAddresses.d.ts +51 -0
  310. package/lib/server/answerAddresses.d.ts.map +1 -0
  311. package/lib/server/answerAddresses.js +72 -0
  312. package/lib/server/answerAddresses.js.map +1 -0
  313. package/lib/server/cardMeta.d.ts +57 -0
  314. package/lib/server/cardMeta.d.ts.map +1 -0
  315. package/lib/server/cardMeta.js +52 -0
  316. package/lib/server/cardMeta.js.map +1 -0
  317. package/lib/server/config.d.ts +72 -0
  318. package/lib/server/config.d.ts.map +1 -0
  319. package/lib/server/config.js +67 -0
  320. package/lib/server/config.js.map +1 -0
  321. package/lib/server/envNumber.d.ts +35 -0
  322. package/lib/server/envNumber.d.ts.map +1 -0
  323. package/lib/server/envNumber.js +42 -0
  324. package/lib/server/envNumber.js.map +1 -0
  325. package/lib/server/healthRoute.d.ts +26 -0
  326. package/lib/server/healthRoute.d.ts.map +1 -0
  327. package/lib/server/healthRoute.js +22 -0
  328. package/lib/server/healthRoute.js.map +1 -0
  329. package/lib/server/listenSite.d.ts +38 -0
  330. package/lib/server/listenSite.d.ts.map +1 -0
  331. package/lib/server/listenSite.js +60 -0
  332. package/lib/server/listenSite.js.map +1 -0
  333. package/lib/server/mcpServer.d.ts +8 -0
  334. package/lib/server/mcpServer.d.ts.map +1 -0
  335. package/lib/server/mcpServer.js +11 -0
  336. package/lib/server/mcpServer.js.map +1 -0
  337. package/lib/server/repositoryVersion.d.ts +16 -0
  338. package/lib/server/repositoryVersion.d.ts.map +1 -0
  339. package/lib/server/repositoryVersion.js +33 -0
  340. package/lib/server/repositoryVersion.js.map +1 -0
  341. package/lib/server/routeOptions.d.ts +23 -0
  342. package/lib/server/routeOptions.d.ts.map +1 -0
  343. package/lib/server/routeOptions.js +20 -0
  344. package/lib/server/routeOptions.js.map +1 -0
  345. package/lib/server/routeTable.d.ts +14 -0
  346. package/lib/server/routeTable.d.ts.map +1 -0
  347. package/lib/server/routeTable.js +32 -0
  348. package/lib/server/routeTable.js.map +1 -0
  349. package/lib/server/siteView.d.ts +29 -0
  350. package/lib/server/siteView.d.ts.map +1 -0
  351. package/lib/server/siteView.js +21 -0
  352. package/lib/server/siteView.js.map +1 -0
  353. package/lib/server/spaPages.d.ts +32 -0
  354. package/lib/server/spaPages.d.ts.map +1 -0
  355. package/lib/server/spaPages.js +126 -0
  356. package/lib/server/spaPages.js.map +1 -0
  357. package/lib/server/spaSite.d.ts +30 -0
  358. package/lib/server/spaSite.d.ts.map +1 -0
  359. package/lib/server/spaSite.js +170 -0
  360. package/lib/server/spaSite.js.map +1 -0
  361. package/lib/server/spaSiteOptions.d.ts +126 -0
  362. package/lib/server/spaSiteOptions.d.ts.map +1 -0
  363. package/lib/server/spaSiteOptions.js +2 -0
  364. package/lib/server/spaSiteOptions.js.map +1 -0
  365. package/lib/server/staticSite.d.ts +9 -0
  366. package/lib/server/staticSite.d.ts.map +1 -1
  367. package/lib/server/staticSite.js +41 -19
  368. package/lib/server/staticSite.js.map +1 -1
  369. package/lib/server/toolSiteServer.d.ts +77 -0
  370. package/lib/server/toolSiteServer.d.ts.map +1 -0
  371. package/lib/server/toolSiteServer.js +58 -0
  372. package/lib/server/toolSiteServer.js.map +1 -0
  373. package/lib/server/trustProxy.d.ts +20 -0
  374. package/lib/server/trustProxy.d.ts.map +1 -0
  375. package/lib/server/trustProxy.js +32 -0
  376. package/lib/server/trustProxy.js.map +1 -0
  377. package/lib/server/types.d.ts +13 -0
  378. package/lib/server/types.d.ts.map +1 -0
  379. package/lib/server/types.js +2 -0
  380. package/lib/server/types.js.map +1 -0
  381. package/lib/server.d.ts +22 -0
  382. package/lib/server.d.ts.map +1 -1
  383. package/lib/server.js +12 -0
  384. package/lib/server.js.map +1 -1
  385. package/lib/share/core/config.d.ts +18 -0
  386. package/lib/share/core/config.d.ts.map +1 -1
  387. package/lib/share/core/config.js +33 -2
  388. package/lib/share/core/config.js.map +1 -1
  389. package/lib/share/core/index.d.ts +3 -1
  390. package/lib/share/core/index.d.ts.map +1 -1
  391. package/lib/share/core/index.js +2 -1
  392. package/lib/share/core/index.js.map +1 -1
  393. package/lib/share/core/keySetParam.d.ts +40 -0
  394. package/lib/share/core/keySetParam.d.ts.map +1 -0
  395. package/lib/share/core/keySetParam.js +60 -0
  396. package/lib/share/core/keySetParam.js.map +1 -0
  397. package/lib/share/core/vocabulary.d.ts +8 -0
  398. package/lib/share/core/vocabulary.d.ts.map +1 -1
  399. package/lib/shell/ui/ShareControl.d.ts +75 -0
  400. package/lib/shell/ui/ShareControl.d.ts.map +1 -0
  401. package/lib/shell/ui/ShareControl.js +40 -0
  402. package/lib/shell/ui/ShareControl.js.map +1 -0
  403. package/lib/shell/ui/ShellFrame.d.ts +14 -0
  404. package/lib/shell/ui/ShellFrame.d.ts.map +1 -0
  405. package/lib/shell/ui/ShellFrame.js +45 -0
  406. package/lib/shell/ui/ShellFrame.js.map +1 -0
  407. package/lib/shell/ui/SiteShell.d.ts +251 -0
  408. package/lib/shell/ui/SiteShell.d.ts.map +1 -0
  409. package/lib/shell/ui/SiteShell.js +39 -0
  410. package/lib/shell/ui/SiteShell.js.map +1 -0
  411. package/lib/shell/ui/index.d.ts +5 -0
  412. package/lib/shell/ui/index.d.ts.map +1 -0
  413. package/lib/shell/ui/index.js +3 -0
  414. package/lib/shell/ui/index.js.map +1 -0
  415. package/lib/state/core/index.d.ts +1 -0
  416. package/lib/state/core/index.d.ts.map +1 -1
  417. package/lib/state/core/index.js.map +1 -1
  418. package/lib/state/core/legacyEntries.d.ts +30 -0
  419. package/lib/state/core/legacyEntries.d.ts.map +1 -0
  420. package/lib/state/core/legacyEntries.js +51 -0
  421. package/lib/state/core/legacyEntries.js.map +1 -0
  422. package/lib/state/core/persistBucket.d.ts +26 -2
  423. package/lib/state/core/persistBucket.d.ts.map +1 -1
  424. package/lib/state/core/persistBucket.js +26 -9
  425. package/lib/state/core/persistBucket.js.map +1 -1
  426. package/lib/state/core/persistSignalBucket.d.ts +26 -0
  427. package/lib/state/core/persistSignalBucket.d.ts.map +1 -1
  428. package/lib/state/core/persistSignalBucket.js +31 -0
  429. package/lib/state/core/persistSignalBucket.js.map +1 -1
  430. package/lib/state/core/storageEntry.d.ts +15 -0
  431. package/lib/state/core/storageEntry.d.ts.map +1 -1
  432. package/lib/state/core/storageEntry.js +33 -0
  433. package/lib/state/core/storageEntry.js.map +1 -1
  434. package/lib/structure/ui/StructureExportButton.d.ts +27 -0
  435. package/lib/structure/ui/StructureExportButton.d.ts.map +1 -0
  436. package/lib/structure/ui/StructureExportButton.js +21 -0
  437. package/lib/structure/ui/StructureExportButton.js.map +1 -0
  438. package/lib/structure/ui/index.d.ts +4 -0
  439. package/lib/structure/ui/index.d.ts.map +1 -1
  440. package/lib/structure/ui/index.js +2 -0
  441. package/lib/structure/ui/index.js.map +1 -1
  442. package/lib/structure/ui/useStructureDraft.d.ts +32 -0
  443. package/lib/structure/ui/useStructureDraft.d.ts.map +1 -0
  444. package/lib/structure/ui/useStructureDraft.js +20 -0
  445. package/lib/structure/ui/useStructureDraft.js.map +1 -0
  446. package/lib/ui.d.ts +2 -0
  447. package/lib/ui.d.ts.map +1 -1
  448. package/lib/ui.js +2 -0
  449. package/lib/ui.js.map +1 -1
  450. package/lib/worker/core/index.d.ts +1 -1
  451. package/lib/worker/core/index.d.ts.map +1 -1
  452. package/lib/worker/core/messages.d.ts +4 -2
  453. package/lib/worker/core/messages.d.ts.map +1 -1
  454. package/lib/worker/core/messages.js.map +1 -1
  455. package/lib/worker/core/oclResourcesUrl.d.ts +16 -0
  456. package/lib/worker/core/oclResourcesUrl.d.ts.map +1 -0
  457. package/lib/worker/core/oclResourcesUrl.js +19 -0
  458. package/lib/worker/core/oclResourcesUrl.js.map +1 -0
  459. package/lib/worker/core/serveWorkerRequests.d.ts +8 -0
  460. package/lib/worker/core/serveWorkerRequests.d.ts.map +1 -1
  461. package/lib/worker/core/serveWorkerRequests.js +15 -2
  462. package/lib/worker/core/serveWorkerRequests.js.map +1 -1
  463. package/lib/worker/core/workerChannel.d.ts +3 -4
  464. package/lib/worker/core/workerChannel.d.ts.map +1 -1
  465. package/lib/worker/core/workerChannel.js +72 -67
  466. package/lib/worker/core/workerChannel.js.map +1 -1
  467. package/lib/worker/core/workerChannelParts.d.ts +17 -6
  468. package/lib/worker/core/workerChannelParts.d.ts.map +1 -1
  469. package/lib/worker/core/workerChannelParts.js +20 -4
  470. package/lib/worker/core/workerChannelParts.js.map +1 -1
  471. package/lib/worker/core/workerChannelTypes.d.ts +46 -2
  472. package/lib/worker/core/workerChannelTypes.d.ts.map +1 -1
  473. package/lib/worker/core/workerSlot.d.ts +66 -0
  474. package/lib/worker/core/workerSlot.d.ts.map +1 -0
  475. package/lib/worker/core/workerSlot.js +107 -0
  476. package/lib/worker/core/workerSlot.js.map +1 -0
  477. package/package.json +16 -1
  478. package/src/card/core/cardAddress.ts +100 -0
  479. package/src/card/core/cardPageUrl.ts +97 -0
  480. package/src/card/core/index.ts +6 -0
  481. package/src/card/core/panelRoom.ts +66 -0
  482. package/src/card/ui/CardDetailsButton.tsx +104 -0
  483. package/src/card/ui/CardFigure.tsx +86 -0
  484. package/src/card/ui/CardFrame.tsx +46 -0
  485. package/src/card/ui/CopyTableButton.tsx +81 -0
  486. package/src/card/ui/cardTooltip.ts +18 -0
  487. package/src/card/ui/embed.ts +27 -0
  488. package/src/card/ui/fitCardToFrame.ts +76 -0
  489. package/src/card/ui/holdRoomForPanels.ts +83 -0
  490. package/src/card/ui/index.ts +14 -0
  491. package/src/card/ui/openPanels.ts +106 -0
  492. package/src/card.ts +13 -0
  493. package/src/conformers.ts +4 -0
  494. package/src/core.ts +5 -0
  495. package/src/fetch/core/apiError.ts +65 -0
  496. package/src/fetch/core/fetchJson.ts +129 -0
  497. package/src/fetch/core/index.ts +4 -0
  498. package/src/formula/core/formulaText.ts +96 -0
  499. package/src/formula/core/index.ts +20 -0
  500. package/src/formula/core/normalizeFormula.ts +50 -0
  501. package/src/formula/core/readFormula.ts +211 -0
  502. package/src/formula/ui/CopyableFormula.tsx +51 -0
  503. package/src/formula/ui/FormulaInput.tsx +50 -0
  504. package/src/formula/ui/QuestionFormula.tsx +20 -0
  505. package/src/formula/ui/index.ts +6 -0
  506. package/src/formula.ts +11 -0
  507. package/src/hooks/ui/index.ts +1 -0
  508. package/src/hooks/ui/keyTargets.ts +5 -3
  509. package/src/hooks/ui/useAsync.ts +50 -14
  510. package/src/locales/de.json +37 -0
  511. package/src/locales/en.json +37 -0
  512. package/src/locales/es.json +37 -0
  513. package/src/locales/fr.json +37 -0
  514. package/src/locales/it.json +37 -0
  515. package/src/moleculesClient/core/index.ts +19 -0
  516. package/src/moleculesClient/core/moleculesClient.ts +175 -0
  517. package/src/moleculesClient/core/moleculesClientApi.ts +120 -0
  518. package/src/moleculesClient/core/moleculesTypes.ts +163 -0
  519. package/src/moleculesClient/core/requestRetry.ts +118 -0
  520. package/src/molstar/core/camera.ts +3 -2
  521. package/src/molstar/core/framing.ts +200 -0
  522. package/src/molstar/core/hover.ts +26 -0
  523. package/src/molstar/core/index.ts +21 -1
  524. package/src/pedagogy/core/answers.ts +94 -0
  525. package/src/pedagogy/core/attempts.ts +205 -0
  526. package/src/pedagogy/core/index.ts +36 -0
  527. package/src/pedagogy/core/progressController.ts +116 -0
  528. package/src/pedagogy/core/seed.ts +177 -0
  529. package/src/pedagogy/core/series.ts +82 -0
  530. package/src/pedagogy/ui/AnswerFields.tsx +63 -0
  531. package/src/pedagogy/ui/ExerciseList.tsx +202 -0
  532. package/src/pedagogy/ui/ExerciseSeries.tsx +250 -0
  533. package/src/pedagogy/ui/QuestionCard.tsx +231 -0
  534. package/src/pedagogy/ui/index.ts +18 -0
  535. package/src/pedagogy/ui/seriesCounts.ts +34 -0
  536. package/src/pedagogy/ui/seriesParts.tsx +127 -0
  537. package/src/pedagogy/ui/useAttemptRecords.ts +16 -0
  538. package/src/periodic/ui/PeriodicTable.tsx +6 -3
  539. package/src/property/core/copyableText.ts +20 -0
  540. package/src/property/core/index.ts +1 -0
  541. package/src/property/ui/PropertyTable.tsx +83 -0
  542. package/src/property/ui/index.ts +2 -0
  543. package/src/router/core/history.ts +61 -7
  544. package/src/router/core/index.ts +3 -2
  545. package/src/router/core/languageRoute.ts +136 -0
  546. package/src/router/core/siteAddresses.ts +38 -0
  547. package/src/router/core/tabRouter.ts +59 -117
  548. package/src/router/core/tabRouterTypes.ts +158 -0
  549. package/src/seo/core/fitDescription.ts +74 -0
  550. package/src/seo/core/index.ts +17 -0
  551. package/src/seo/core/limits.ts +27 -0
  552. package/src/seo/core/pageContent.ts +42 -0
  553. package/src/seo/core/plainDescription.ts +4 -2
  554. package/src/seo/core/routeProblems.ts +1 -7
  555. package/src/seo/core/routeTable.ts +103 -0
  556. package/src/seo/vite/index.ts +2 -0
  557. package/src/seo/vite/prerender.ts +26 -1
  558. package/src/seo/vite/routeTable.ts +79 -0
  559. package/src/server/answerAddresses.ts +92 -0
  560. package/src/server/cardMeta.ts +88 -0
  561. package/src/server/config.ts +125 -0
  562. package/src/server/envNumber.ts +65 -0
  563. package/src/server/healthRoute.ts +42 -0
  564. package/src/server/listenSite.ts +90 -0
  565. package/src/server/mcpServer.ts +14 -0
  566. package/src/server/repositoryVersion.ts +33 -0
  567. package/src/server/routeOptions.ts +26 -0
  568. package/src/server/routeTable.ts +35 -0
  569. package/src/server/siteView.ts +42 -0
  570. package/src/server/spaPages.ts +179 -0
  571. package/src/server/spaSite.ts +216 -0
  572. package/src/server/spaSiteOptions.ts +133 -0
  573. package/src/server/staticSite.ts +65 -35
  574. package/src/server/toolSiteServer.ts +127 -0
  575. package/src/server/trustProxy.ts +32 -0
  576. package/src/server/types.ts +25 -0
  577. package/src/server.ts +40 -0
  578. package/src/share/core/config.ts +45 -2
  579. package/src/share/core/index.ts +4 -0
  580. package/src/share/core/keySetParam.ts +92 -0
  581. package/src/share/core/vocabulary.ts +8 -0
  582. package/src/shell/ui/ShareControl.tsx +150 -0
  583. package/src/shell/ui/ShellFrame.tsx +180 -0
  584. package/src/shell/ui/SiteShell.tsx +297 -0
  585. package/src/shell/ui/index.ts +9 -0
  586. package/src/state/core/index.ts +1 -0
  587. package/src/state/core/legacyEntries.ts +76 -0
  588. package/src/state/core/persistBucket.ts +50 -10
  589. package/src/state/core/persistSignalBucket.ts +52 -0
  590. package/src/state/core/storageEntry.ts +32 -0
  591. package/src/structure/ui/StructureExportButton.tsx +57 -0
  592. package/src/structure/ui/index.ts +4 -0
  593. package/src/structure/ui/useStructureDraft.ts +47 -0
  594. package/src/ui.ts +2 -0
  595. package/src/worker/core/index.ts +1 -0
  596. package/src/worker/core/messages.ts +4 -3
  597. package/src/worker/core/oclResourcesUrl.ts +21 -0
  598. package/src/worker/core/serveWorkerRequests.ts +30 -2
  599. package/src/worker/core/workerChannel.ts +74 -74
  600. package/src/worker/core/workerChannelParts.ts +33 -13
  601. package/src/worker/core/workerChannelTypes.ts +47 -2
  602. package/src/worker/core/workerSlot.ts +181 -0
  603. package/styles/card.css +145 -0
  604. package/styles/chrome.css +248 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Reading what a student typed into an answer box, and the verdicts a grader
3
+ * gives a box it cannot grade.
4
+ */
5
+ import { CHROME_CATALOG } from "../../i18n/core/chromeCatalog.js";
6
+ import { DEFAULT_LANGUAGE } from "../../i18n/core/languages.js";
7
+ import { catalogTranslate } from "../../i18n/core/translate.js";
8
+ import { readNumber } from "../../number/core/numberText.js";
9
+ /**
10
+ * Read a number the way a student types it: `42`, `+5`, `−3` with a real minus
11
+ * sign, `1,5` with a decimal comma, `75.8 %`, `1 000`.
12
+ *
13
+ * What a typed answer carries beyond a number box — a typographic minus, a
14
+ * percent sign, a space between thousands — is taken off first; the number
15
+ * itself is read by `readNumber`, as every box of the family reads one.
16
+ * @param text - What was typed.
17
+ * @param integer - Whether only a whole number is an answer.
18
+ * @default integer false
19
+ * @returns The number, or undefined when the text is not one.
20
+ */
21
+ export function readAnswerNumber(text, integer = false) {
22
+ const cleaned = text
23
+ .trim()
24
+ .replaceAll(/[−–]/gu, '-')
25
+ .replace(/\s*%$/u, '')
26
+ .replaceAll(/\s/gu, '');
27
+ return readNumber(cleaned, integer);
28
+ }
29
+ /**
30
+ * Write a signed whole number the way an oxidation state or a charge is
31
+ * written: `+5`, `−2`, `0`.
32
+ * @param value - The number.
33
+ * @returns The number with its sign, and a true minus sign.
34
+ */
35
+ export function formatSigned(value) {
36
+ if (value > 0)
37
+ return `+${value}`;
38
+ if (value < 0)
39
+ return `−${-value}`;
40
+ return '0';
41
+ }
42
+ /**
43
+ * The verdict on a field left empty.
44
+ * @param label - The field, as its box labels it.
45
+ * @param what - What the box asks for, e.g. `a number of electrons`.
46
+ * @param language - The language the reason is written in.
47
+ * @default language 'en'
48
+ * @returns A failed case that says what to type.
49
+ */
50
+ export function emptyCase(label, what, language = DEFAULT_LANGUAGE) {
51
+ const t = catalogTranslate(CHROME_CATALOG, language);
52
+ return {
53
+ label,
54
+ passed: false,
55
+ reason: t('pedagogy.answerEmpty', { what }),
56
+ actual: null,
57
+ };
58
+ }
59
+ /**
60
+ * The verdict on a field that does not read as the kind of value it asks for.
61
+ * @param label - The field, as its box labels it.
62
+ * @param typed - What was typed.
63
+ * @param what - What the box asks for, e.g. `a whole number`.
64
+ * @param language - The language the reason is written in.
65
+ * @default language 'en'
66
+ * @returns A failed case quoting what was typed.
67
+ */
68
+ export function unreadableCase(label, typed, what, language = DEFAULT_LANGUAGE) {
69
+ const t = catalogTranslate(CHROME_CATALOG, language);
70
+ return {
71
+ label,
72
+ passed: false,
73
+ reason: t('pedagogy.answerUnreadable', { typed: typed.trim(), what }),
74
+ actual: typed,
75
+ };
76
+ }
77
+ //# sourceMappingURL=answers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answers.js","sourceRoot":"","sources":["../../../src/pedagogy/core/answers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAI7D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,OAAO,GAAG,KAAK;IAEf,MAAM,OAAO,GAAG,IAAI;SACjB,IAAI,EAAE;SACN,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC;SACzB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,OAAO,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,IAAI,KAAK,EAAE,CAAC;IAClC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACnC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CACvB,KAAa,EACb,IAAY,EACZ,WAAqB,gBAAgB;IAErC,MAAM,CAAC,GAAG,gBAAgB,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACrD,OAAO;QACL,KAAK;QACL,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,CAAC;QAC3C,MAAM,EAAE,IAAI;KACb,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,KAAa,EACb,IAAY,EACZ,WAAqB,gBAAgB;IAErC,MAAM,CAAC,GAAG,gBAAgB,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACrD,OAAO;QACL,KAAK;QACL,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,CAAC,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC;QACrE,MAAM,EAAE,KAAK;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * How far a student has got on a graded series, kept in this browser.
3
+ *
4
+ * Best effort and never a precondition: a framed page whose storage is
5
+ * partitioned still works, it just forgets. An attempt is keyed by tool, series
6
+ * and question, so a new series starts clean and a shared link reopens its own.
7
+ * The store is a plain subscribable value, so a page reads it with React's
8
+ * `useSyncExternalStore` or from a signal of its own, and the series components
9
+ * re-render on it without knowing which.
10
+ */
11
+ import type { ProgressRecords, ProgressStore } from './progress.ts';
12
+ import type { ExerciseStatus } from './types.ts';
13
+ /** One question as the student left it. */
14
+ export interface Attempt {
15
+ /** Where the student stands on it. */
16
+ status: ExerciseStatus;
17
+ /** What was typed, or drawn, field by field. */
18
+ answers: Record<string, string>;
19
+ /** The answers as they were when last checked, so a change hides the verdict. */
20
+ checked: string | null;
21
+ /** How many hints of the ladder are open. */
22
+ hintsRevealed: number;
23
+ /** Whether the worked answer is on screen. */
24
+ showSolution: boolean;
25
+ }
26
+ /**
27
+ * What a question looks like before anything is typed into it.
28
+ * @returns A fresh attempt.
29
+ */
30
+ export declare function emptyAttempt(): Attempt;
31
+ /**
32
+ * The key an attempt is kept under.
33
+ * @param tool - The tool.
34
+ * @param seed - The series.
35
+ * @param question - The question's key in the tool's pool.
36
+ * @returns `tool/seed/question`.
37
+ */
38
+ export declare function attemptKey(tool: string, seed: number, question: string): string;
39
+ /** What {@link createAttemptStore} is built from. */
40
+ export interface AttemptStoreOptions {
41
+ /**
42
+ * The site, which namespaces both entries: `atoms` keeps its attempts under
43
+ * `atoms:attempts:v1` and the series each tool was last on under
44
+ * `atoms:seeds:v1`.
45
+ */
46
+ key: string;
47
+ /**
48
+ * Where the attempts are kept, for a course that keeps them itself.
49
+ * @default the browser's `localStorage`, under `<key>:attempts:v1`
50
+ */
51
+ binding?: ProgressStore<Attempt>;
52
+ /**
53
+ * Called when a save was refused because the store is full.
54
+ * @default undefined
55
+ */
56
+ onQuotaExceeded?: (error: unknown) => void;
57
+ }
58
+ /** The attempts of a site, and the series each of its tools was last on. */
59
+ export interface AttemptStore {
60
+ /** Every attempt this browser remembers; a new object after each change. */
61
+ records: () => ProgressRecords<Attempt>;
62
+ /** Be told after each change; returns the function that stops it. */
63
+ subscribe: (listener: () => void) => () => void;
64
+ /** One question's attempt, or a fresh one. */
65
+ attemptFor: (key: string) => Attempt;
66
+ /** Change one attempt and keep it. */
67
+ updateAttempt: (key: string, change: Partial<Attempt>) => void;
68
+ /** Forget the attempts of some questions. */
69
+ clearAttempts: (keys: readonly string[]) => void;
70
+ /**
71
+ * Forget every series of a tool but one, so storage does not grow with every
72
+ * new series drawn.
73
+ */
74
+ forgetOtherSeries: (tool: string, seed: number) => void;
75
+ /** The series a tool was last on in this browser, or null. */
76
+ storedSeed: (tool: string) => number | null;
77
+ /** Remember the series a tool is on. */
78
+ storeSeed: (tool: string, seed: number) => void;
79
+ }
80
+ /**
81
+ * The attempts of a site's graded series, kept in this browser.
82
+ * @param options - The site's namespace, and where else to keep them.
83
+ * @returns The store.
84
+ */
85
+ export declare function createAttemptStore(options: AttemptStoreOptions): AttemptStore;
86
+ //# sourceMappingURL=attempts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempts.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/core/attempts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,sCAAsC;IACtC,MAAM,EAAE,cAAc,CAAC;IACvB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,iFAAiF;IACjF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,6CAA6C;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAQtC;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,MAAM,CAER;AAED,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACjC;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,OAAO,EAAE,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,qEAAqE;IACrE,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IAChD,8CAA8C;IAC9C,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACrC,sCAAsC;IACtC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC/D,6CAA6C;IAC7C,aAAa,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;IACjD;;;OAGG;IACH,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,8DAA8D;IAC9D,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C,wCAAwC;IACxC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAqF7E"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * How far a student has got on a graded series, kept in this browser.
3
+ *
4
+ * Best effort and never a precondition: a framed page whose storage is
5
+ * partitioned still works, it just forgets. An attempt is keyed by tool, series
6
+ * and question, so a new series starts clean and a shared link reopens its own.
7
+ * The store is a plain subscribable value, so a page reads it with React's
8
+ * `useSyncExternalStore` or from a signal of its own, and the series components
9
+ * re-render on it without knowing which.
10
+ */
11
+ import { persistBucket } from "../../state/core/persistBucket.js";
12
+ import { localStorageProgressStore } from "./progress.js";
13
+ /**
14
+ * What a question looks like before anything is typed into it.
15
+ * @returns A fresh attempt.
16
+ */
17
+ export function emptyAttempt() {
18
+ return {
19
+ status: 'idle',
20
+ answers: {},
21
+ checked: null,
22
+ hintsRevealed: 0,
23
+ showSolution: false,
24
+ };
25
+ }
26
+ /**
27
+ * The key an attempt is kept under.
28
+ * @param tool - The tool.
29
+ * @param seed - The series.
30
+ * @param question - The question's key in the tool's pool.
31
+ * @returns `tool/seed/question`.
32
+ */
33
+ export function attemptKey(tool, seed, question) {
34
+ return `${tool}/${seed}/${question}`;
35
+ }
36
+ /**
37
+ * The attempts of a site's graded series, kept in this browser.
38
+ * @param options - The site's namespace, and where else to keep them.
39
+ * @returns The store.
40
+ */
41
+ export function createAttemptStore(options) {
42
+ const { key, onQuotaExceeded } = options;
43
+ const binding = options.binding ??
44
+ localStorageProgressStore({
45
+ key: `${key}:attempts`,
46
+ version: 1,
47
+ defaults: emptyAttempt(),
48
+ onQuotaExceeded,
49
+ });
50
+ const seeds = persistBucket({
51
+ key: `${key}:seeds`,
52
+ version: 1,
53
+ defaults: {},
54
+ onQuotaExceeded,
55
+ });
56
+ const listeners = new Set();
57
+ let current = {};
58
+ // Kept in memory as well, so a framed page whose storage is blocked still
59
+ // reopens the series it is on for as long as it stays open.
60
+ let seedsByTool = seeds.read().value;
61
+ function publish(next, save) {
62
+ current = next;
63
+ if (save)
64
+ void binding.save(next);
65
+ for (const listener of listeners)
66
+ listener();
67
+ }
68
+ const loaded = binding.load();
69
+ if (loaded instanceof Promise) {
70
+ void loaded.then((records) => {
71
+ publish(records, false);
72
+ }, () => {
73
+ // A binding that cannot answer leaves the page working from nothing.
74
+ });
75
+ }
76
+ else {
77
+ current = loaded;
78
+ }
79
+ function attemptFor(attempt) {
80
+ return current[attempt] ?? emptyAttempt();
81
+ }
82
+ return {
83
+ records: () => current,
84
+ subscribe(listener) {
85
+ listeners.add(listener);
86
+ return () => {
87
+ listeners.delete(listener);
88
+ };
89
+ },
90
+ attemptFor,
91
+ updateAttempt(attempt, change) {
92
+ publish({ ...current, [attempt]: { ...attemptFor(attempt), ...change } }, true);
93
+ },
94
+ clearAttempts(keys) {
95
+ const cleared = new Set(keys);
96
+ publish(keep(current, (attempt) => !cleared.has(attempt)), true);
97
+ },
98
+ forgetOtherSeries(tool, seed) {
99
+ const kept = `${tool}/${seed}/`;
100
+ publish(keep(current, (attempt) => !attempt.startsWith(`${tool}/`) || attempt.startsWith(kept)), true);
101
+ },
102
+ storedSeed: (tool) => seedsByTool[tool] ?? null,
103
+ storeSeed(tool, seed) {
104
+ seedsByTool = { ...seedsByTool, [tool]: seed };
105
+ seeds.write(seedsByTool);
106
+ },
107
+ };
108
+ }
109
+ function keep(records, wanted) {
110
+ const next = {};
111
+ for (const [key, attempt] of Object.entries(records)) {
112
+ if (wanted(key))
113
+ next[key] = attempt;
114
+ }
115
+ return next;
116
+ }
117
+ //# sourceMappingURL=attempts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempts.js","sourceRoot":"","sources":["../../../src/pedagogy/core/attempts.ts"],"names":[],"mappings":"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"}
@@ -11,4 +11,12 @@ export { emptyProgress, localStorageProgressStore, mergeExerciseProgress, progre
11
11
  export type { BaseExercise, ExerciseLevel, ExerciseSet, ExerciseStatus, TutorialStep, } from './types.ts';
12
12
  export type { FinishValidationOptions, TestCaseResult, ValidationResult, } from './validation.ts';
13
13
  export { failedValidation, finishValidation } from './validation.ts';
14
+ export { emptyCase, formatSigned, readAnswerNumber, unreadableCase, } from './answers.ts';
15
+ export type { Attempt, AttemptStore, AttemptStoreOptions } from './attempts.ts';
16
+ export { attemptKey, createAttemptStore, emptyAttempt } from './attempts.ts';
17
+ export type { ControlledProgress, ProgressController, ProgressControllerOptions, ProgressSignal, } from './progressController.ts';
18
+ export { createProgressController } from './progressController.ts';
19
+ export type { PickSeededOptions, SeedDraw, SeedRange, SeedValue, } from './seed.ts';
20
+ export { EACH_SEED, LARGEST_SEED, freshSeed, parseSeed, pickSeeded, seedParam, } from './seed.ts';
21
+ export type { AnswerCheck, AnswerField, Answers, FieldCase, SeriesTool, } from './series.ts';
14
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EACV,0BAA0B,EAC1B,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EACV,gBAAgB,EAChB,gCAAgC,EAChC,eAAe,EACf,aAAa,EACb,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EACV,0BAA0B,EAC1B,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EACV,gBAAgB,EAChB,gCAAgC,EAChC,eAAe,EACf,aAAa,EACb,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EACL,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7E,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EACV,iBAAiB,EACjB,QAAQ,EACR,SAAS,EACT,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,SAAS,EACT,YAAY,EACZ,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,SAAS,EACT,UAAU,GACX,MAAM,aAAa,CAAC"}
@@ -4,4 +4,8 @@ export { parseInlineMarks } from "./inlineMarks.js";
4
4
  export { bucketProgressStore } from "./bucketProgressStore.js";
5
5
  export { emptyProgress, localStorageProgressStore, mergeExerciseProgress, progressSummary, } from "./progress.js";
6
6
  export { failedValidation, finishValidation } from "./validation.js";
7
+ export { emptyCase, formatSigned, readAnswerNumber, unreadableCase, } from "./answers.js";
8
+ export { attemptKey, createAttemptStore, emptyAttempt } from "./attempts.js";
9
+ export { createProgressController } from "./progressController.js";
10
+ export { EACH_SEED, LARGEST_SEED, freshSeed, parseSeed, pickSeeded, seedParam, } from "./seed.js";
7
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/pedagogy/core/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAKpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAQ/D,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,GAChB,MAAM,eAAe,CAAC;AAavB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/pedagogy/core/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAKpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAQ/D,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,GAChB,MAAM,eAAe,CAAC;AAavB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EACL,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAO7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAOnE,OAAO,EACL,SAAS,EACT,YAAY,EACZ,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,GACV,MAAM,WAAW,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The handful of actions every exercise page performs on the progress it keeps:
3
+ * read one record, mark it, open a hint, show the answer, forget it.
4
+ *
5
+ * The records live in whatever the page already holds its state in — a signal
6
+ * of `@preact/signals-react`, or anything with a writable `value` — and every
7
+ * action replaces that value rather than mutating it, so whatever renders from
8
+ * it is told.
9
+ */
10
+ import type { ExerciseProgress, ProgressRecords } from './progress.ts';
11
+ import type { ExerciseStatus } from './types.ts';
12
+ /** A writable box holding the records, which a signal is. */
13
+ export interface ProgressSignal<TProgress> {
14
+ /** The records by exercise id; replaced, never mutated. */
15
+ value: ProgressRecords<TProgress>;
16
+ }
17
+ /** The least a record has to carry for the controller to act on it. */
18
+ export interface ControlledProgress {
19
+ /** Where the student stands. */
20
+ status: ExerciseStatus;
21
+ /** How many hints are open. */
22
+ hintsRevealed: number;
23
+ /** Whether the sample answer is on screen. */
24
+ showSolution: boolean;
25
+ }
26
+ /** What {@link createProgressController} is built with. */
27
+ export interface ProgressControllerOptions<TProgress> {
28
+ /**
29
+ * The record an exercise nobody has touched reads as.
30
+ * @default emptyProgress — status, answer, hints and solution
31
+ */
32
+ empty?: () => TProgress;
33
+ }
34
+ /** The actions on one page's progress. */
35
+ export interface ProgressController<TProgress extends ControlledProgress> {
36
+ /** One exercise's record, defaults included; reads the signal. */
37
+ getExerciseProgress: (id: string) => TProgress;
38
+ /** Record an attempt or a success. */
39
+ setExerciseStatus: (id: string, status: ExerciseStatus) => void;
40
+ /** Change any fields of one record, the others kept. */
41
+ updateProgress: (id: string, patch: Partial<TProgress>) => void;
42
+ /**
43
+ * Open the next hint, one at a time, stopping at the last when the count is
44
+ * given.
45
+ */
46
+ revealNextHint: (id: string, hintCount?: number) => void;
47
+ /** Show or hide the sample answer. */
48
+ setShowSolution: (id: string, show: boolean) => void;
49
+ /** Forget one exercise. */
50
+ resetExercise: (id: string) => void;
51
+ /**
52
+ * Forget every exercise. The page puts this behind a confirmation dialog,
53
+ * because it wipes a week of a student's work.
54
+ */
55
+ clearAllProgress: () => void;
56
+ }
57
+ /**
58
+ * The actions on the progress a page keeps in a signal.
59
+ * @param progress - The signal holding the records by exercise id.
60
+ * @param options - What an untouched exercise reads as.
61
+ * @returns The actions.
62
+ */
63
+ export declare function createProgressController<TProgress extends ControlledProgress = ExerciseProgress>(progress: ProgressSignal<TProgress>, options?: ProgressControllerOptions<TProgress>): ProgressController<TProgress>;
64
+ //# sourceMappingURL=progressController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressController.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/core/progressController.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,6DAA6D;AAC7D,MAAM,WAAW,cAAc,CAAC,SAAS;IACvC,2DAA2D;IAC3D,KAAK,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;CACnC;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,MAAM,EAAE,cAAc,CAAC;IACvB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,2DAA2D;AAC3D,MAAM,WAAW,yBAAyB,CAAC,SAAS;IAClD;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,SAAS,CAAC;CACzB;AAED,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB,CAAC,SAAS,SAAS,kBAAkB;IACtE,kEAAkE;IAClE,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,SAAS,CAAC;IAC/C,sCAAsC;IACtC,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAChE,wDAAwD;IACxD,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;IAChE;;;OAGG;IACH,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,sCAAsC;IACtC,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,2BAA2B;IAC3B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC;;;OAGG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,SAAS,kBAAkB,GAAG,gBAAgB,EAEvD,QAAQ,EAAE,cAAc,CAAC,SAAS,CAAC,EACnC,OAAO,GAAE,yBAAyB,CAAC,SAAS,CAAM,GACjD,kBAAkB,CAAC,SAAS,CAAC,CAyC/B"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The handful of actions every exercise page performs on the progress it keeps:
3
+ * read one record, mark it, open a hint, show the answer, forget it.
4
+ *
5
+ * The records live in whatever the page already holds its state in — a signal
6
+ * of `@preact/signals-react`, or anything with a writable `value` — and every
7
+ * action replaces that value rather than mutating it, so whatever renders from
8
+ * it is told.
9
+ */
10
+ import { emptyProgress } from "./progress.js";
11
+ /**
12
+ * The actions on the progress a page keeps in a signal.
13
+ * @param progress - The signal holding the records by exercise id.
14
+ * @param options - What an untouched exercise reads as.
15
+ * @returns The actions.
16
+ */
17
+ export function createProgressController(progress, options = {}) {
18
+ const empty = options.empty ?? emptyProgress;
19
+ function getExerciseProgress(id) {
20
+ return { ...empty(), ...progress.value[id] };
21
+ }
22
+ function updateProgress(id, patch) {
23
+ progress.value = {
24
+ ...progress.value,
25
+ [id]: { ...getExerciseProgress(id), ...patch },
26
+ };
27
+ }
28
+ return {
29
+ getExerciseProgress,
30
+ updateProgress,
31
+ setExerciseStatus(id, status) {
32
+ updateProgress(id, { status });
33
+ },
34
+ revealNextHint(id, hintCount) {
35
+ const revealed = getExerciseProgress(id).hintsRevealed + 1;
36
+ updateProgress(id, {
37
+ hintsRevealed: hintCount === undefined ? revealed : Math.min(revealed, hintCount),
38
+ });
39
+ },
40
+ setShowSolution(id, show) {
41
+ updateProgress(id, { showSolution: show });
42
+ },
43
+ resetExercise(id) {
44
+ const next = {};
45
+ for (const [key, value] of Object.entries(progress.value)) {
46
+ if (key !== id)
47
+ next[key] = value;
48
+ }
49
+ progress.value = next;
50
+ },
51
+ clearAllProgress() {
52
+ progress.value = {};
53
+ },
54
+ };
55
+ }
56
+ //# sourceMappingURL=progressController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressController.js","sourceRoot":"","sources":["../../../src/pedagogy/core/progressController.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoD9C;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAGtC,QAAmC,EACnC,UAAgD,EAAE;IAElD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAK,aAA4C,CAAC;IAE7E,SAAS,mBAAmB,CAAC,EAAU;QACrC,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED,SAAS,cAAc,CAAC,EAAU,EAAE,KAAyB;QAC3D,QAAQ,CAAC,KAAK,GAAG;YACf,GAAG,QAAQ,CAAC,KAAK;YACjB,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,mBAAmB,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE;SAC/C,CAAC;IACJ,CAAC;IAED,OAAO;QACL,mBAAmB;QACnB,cAAc;QACd,iBAAiB,CAAC,EAAE,EAAE,MAAM;YAC1B,cAAc,CAAC,EAAE,EAAE,EAAE,MAAM,EAAwB,CAAC,CAAC;QACvD,CAAC;QACD,cAAc,CAAC,EAAE,EAAE,SAAS;YAC1B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC;YAC3D,cAAc,CAAC,EAAE,EAAE;gBACjB,aAAa,EACX,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC;aAC/C,CAAC,CAAC;QAC3B,CAAC;QACD,eAAe,CAAC,EAAE,EAAE,IAAI;YACtB,cAAc,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAwB,CAAC,CAAC;QACnE,CAAC;QACD,aAAa,CAAC,EAAE;YACd,MAAM,IAAI,GAA+B,EAAE,CAAC;YAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1D,IAAI,GAAG,KAAK,EAAE;oBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACpC,CAAC;YACD,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,gBAAgB;YACd,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * The seed a series is drawn from, and the drawing itself.
3
+ *
4
+ * A series is a link: `?seed=4271` hands the same questions, in the same order,
5
+ * to everybody who opens it, on every machine and in every browser. So the
6
+ * drawing goes through `ml-xsadd` and nothing else — a hand-rolled generator
7
+ * silently changes its sequence the day somebody improves it, and every link
8
+ * that pinned a seed then opens a different problem set.
9
+ */
10
+ import type { ShareParamCodec } from '../../share/core/params.ts';
11
+ /** The largest seed a link may carry: an unsigned 32-bit integer. */
12
+ export declare const LARGEST_SEED: number;
13
+ /** The seeds a link may pin, both ends included. */
14
+ export interface SeedRange {
15
+ /** The smallest seed. */
16
+ min: number;
17
+ /** The largest seed. */
18
+ max: number;
19
+ }
20
+ /**
21
+ * Which call of the generator a shuffle draws from. Both are reproducible; they
22
+ * are two different sequences, so a site keeps the one its links were written
23
+ * with.
24
+ */
25
+ export type SeedDraw = 'getFloat' | 'getUint32';
26
+ /** How {@link pickSeeded} draws. */
27
+ export interface PickSeededOptions {
28
+ /**
29
+ * The generator call the shuffle is driven by: `getFloat`, scaled to the
30
+ * remaining positions, or `getUint32`, taken modulo them.
31
+ * @default 'getFloat'
32
+ */
33
+ draw?: SeedDraw;
34
+ /**
35
+ * Whether a series longer than the pool goes round it again, so it is always
36
+ * exactly as long as asked. Otherwise it stops at the pool.
37
+ * @default false
38
+ */
39
+ wrap?: boolean;
40
+ }
41
+ /**
42
+ * Pick `count` items out of a pool, the same ones in the same order for the
43
+ * same seed.
44
+ *
45
+ * The pool is shuffled by Fisher–Yates driven by XSadd and the series is the
46
+ * head of that shuffle, so asking for more questions from the same seed keeps
47
+ * the ones already on screen. The pool itself is never reordered.
48
+ * @param pool - Everything a series can draw from.
49
+ * @param count - How many to take; more than the pool holds takes them all,
50
+ * or goes round again with `wrap`.
51
+ * @param seed - An unsigned 32-bit integer.
52
+ * @param options - Which generator call drives the shuffle, and whether the
53
+ * series wraps.
54
+ * @returns The picked items, in drawn order.
55
+ */
56
+ export declare function pickSeeded<T>(pool: readonly T[], count: number, seed: number, options?: PickSeededOptions): T[];
57
+ /**
58
+ * A seed for a series nobody has asked for yet.
59
+ *
60
+ * `ml-xsadd` unseeded rather than `Math.random`, so the one generator the page
61
+ * draws from is the one every link pins.
62
+ * @param range - The seeds a link may carry, so a drawn one is one of them.
63
+ * @default range { min: 0, max: LARGEST_SEED }
64
+ * @returns A whole number inside the range.
65
+ */
66
+ export declare function freshSeed(range?: SeedRange): number;
67
+ /**
68
+ * Read a seed out of an address, strictly: anything that is not a whole number
69
+ * inside the range reads as no seed at all.
70
+ * @param raw - The `seed` parameter, as typed or as a link carries it.
71
+ * @param range - The seeds a link may carry.
72
+ * @default range { min: 0, max: LARGEST_SEED }
73
+ * @returns The seed, or null when the parameter is absent or not one.
74
+ */
75
+ export declare function parseSeed(raw: string | null | undefined, range?: SeedRange): number | null;
76
+ /** What a link writes to ask for a series per student rather than one per class. */
77
+ export declare const EACH_SEED = "each";
78
+ /**
79
+ * What `?seed=` can say: a pinned series, a series per student, or no series —
80
+ * `null` rather than a number for the last, because `0` is a seed somebody may
81
+ * pin.
82
+ */
83
+ export type SeedValue = number | typeof EACH_SEED | null;
84
+ /**
85
+ * The codec of a `?seed=` that also understands `each`.
86
+ *
87
+ * A number is a problem set handed to a whole class; `each` is one link under
88
+ * which no two students work on the same set, the site drawing one seed per
89
+ * browser the first time it opens. A number outside the range is brought back
90
+ * inside it, and anything else reads as no series, so a hand-edited
91
+ * `?seed=today` still opens something.
92
+ * @param range - The seeds a link may pin.
93
+ * @returns The codec.
94
+ */
95
+ export declare function seedParam(range: SeedRange): ShareParamCodec<SeedValue>;
96
+ //# sourceMappingURL=seed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/core/seed.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,qEAAqE;AACrE,eAAO,MAAM,YAAY,QAAc,CAAC;AAExC,oDAAoD;AACpD,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;AAEhD,oCAAoC;AACpC,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,CAAC,EAAE,CAWL;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAKnD;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC9B,KAAK,CAAC,EAAE,SAAS,GAChB,MAAM,GAAG,IAAI,CAOf;AAED,oFAAoF;AACpF,eAAO,MAAM,SAAS,SAAS,CAAC;AAEhC;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,SAAS,GAAG,IAAI,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC,CAiBtE"}