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,128 @@
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 { XSadd } from 'ml-xsadd';
11
+ /** The largest seed a link may carry: an unsigned 32-bit integer. */
12
+ export const LARGEST_SEED = 2 ** 32 - 1;
13
+ /**
14
+ * Pick `count` items out of a pool, the same ones in the same order for the
15
+ * same seed.
16
+ *
17
+ * The pool is shuffled by Fisher–Yates driven by XSadd and the series is the
18
+ * head of that shuffle, so asking for more questions from the same seed keeps
19
+ * the ones already on screen. The pool itself is never reordered.
20
+ * @param pool - Everything a series can draw from.
21
+ * @param count - How many to take; more than the pool holds takes them all,
22
+ * or goes round again with `wrap`.
23
+ * @param seed - An unsigned 32-bit integer.
24
+ * @param options - Which generator call drives the shuffle, and whether the
25
+ * series wraps.
26
+ * @returns The picked items, in drawn order.
27
+ */
28
+ export function pickSeeded(pool, count, seed, options = {}) {
29
+ const { draw = 'getFloat', wrap = false } = options;
30
+ const order = shuffledOrder(pool.length, seed, draw);
31
+ const wanted = Math.max(0, Math.trunc(count));
32
+ const size = pool.length === 0 ? 0 : wrap ? wanted : Math.min(wanted, pool.length);
33
+ const picked = new Array(size);
34
+ for (let index = 0; index < size; index++) {
35
+ picked[index] = pool[order[index % order.length]];
36
+ }
37
+ return picked;
38
+ }
39
+ /**
40
+ * A seed for a series nobody has asked for yet.
41
+ *
42
+ * `ml-xsadd` unseeded rather than `Math.random`, so the one generator the page
43
+ * draws from is the one every link pins.
44
+ * @param range - The seeds a link may carry, so a drawn one is one of them.
45
+ * @default range { min: 0, max: LARGEST_SEED }
46
+ * @returns A whole number inside the range.
47
+ */
48
+ export function freshSeed(range) {
49
+ const drawn = new XSadd().getUint32();
50
+ if (range === undefined)
51
+ return drawn;
52
+ const span = range.max - range.min + 1;
53
+ return range.min + (drawn % span);
54
+ }
55
+ /**
56
+ * Read a seed out of an address, strictly: anything that is not a whole number
57
+ * inside the range reads as no seed at all.
58
+ * @param raw - The `seed` parameter, as typed or as a link carries it.
59
+ * @param range - The seeds a link may carry.
60
+ * @default range { min: 0, max: LARGEST_SEED }
61
+ * @returns The seed, or null when the parameter is absent or not one.
62
+ */
63
+ export function parseSeed(raw, range) {
64
+ if (raw === null || raw === undefined || !/^\d{1,10}$/u.test(raw)) {
65
+ return null;
66
+ }
67
+ const seed = Number(raw);
68
+ const { min = 0, max = LARGEST_SEED } = range ?? {};
69
+ return seed >= min && seed <= max ? seed : null;
70
+ }
71
+ /** What a link writes to ask for a series per student rather than one per class. */
72
+ export const EACH_SEED = 'each';
73
+ /**
74
+ * The codec of a `?seed=` that also understands `each`.
75
+ *
76
+ * A number is a problem set handed to a whole class; `each` is one link under
77
+ * which no two students work on the same set, the site drawing one seed per
78
+ * browser the first time it opens. A number outside the range is brought back
79
+ * inside it, and anything else reads as no series, so a hand-edited
80
+ * `?seed=today` still opens something.
81
+ * @param range - The seeds a link may pin.
82
+ * @returns The codec.
83
+ */
84
+ export function seedParam(range) {
85
+ return {
86
+ parse(raw) {
87
+ if (raw === null)
88
+ return null;
89
+ const text = raw.trim();
90
+ if (text === '')
91
+ return null;
92
+ if (text.toLowerCase() === EACH_SEED)
93
+ return EACH_SEED;
94
+ const parsed = Number(text);
95
+ if (Number.isNaN(parsed))
96
+ return null;
97
+ return clampSeed(parsed, range);
98
+ },
99
+ serialize(value) {
100
+ if (value === EACH_SEED)
101
+ return EACH_SEED;
102
+ if (typeof value !== 'number')
103
+ return null;
104
+ return String(clampSeed(value, range));
105
+ },
106
+ };
107
+ }
108
+ function clampSeed(value, range) {
109
+ if (!Number.isFinite(value))
110
+ return range.min;
111
+ return Math.min(range.max, Math.max(range.min, Math.round(value)));
112
+ }
113
+ function shuffledOrder(length, seed, draw) {
114
+ const generator = new XSadd(seed);
115
+ const order = new Array(length);
116
+ for (let index = 0; index < length; index++)
117
+ order[index] = index;
118
+ for (let index = length - 1; index > 0; index--) {
119
+ const other = draw === 'getUint32'
120
+ ? generator.getUint32() % (index + 1)
121
+ : Math.floor(generator.getFloat() * (index + 1));
122
+ const kept = order[index];
123
+ order[index] = order[other];
124
+ order[other] = kept;
125
+ }
126
+ return order;
127
+ }
128
+ //# sourceMappingURL=seed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../../src/pedagogy/core/seed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * A graded series: questions drawn from a tool's pool by a seed, each asking
3
+ * the student to fill a few boxes, each box graded as a test case.
4
+ *
5
+ * Nothing here knows what is asked — electrons, a formula, a mass — so a tool
6
+ * of any subject describes its questions with {@link SeriesTool} and the shared
7
+ * series components draw them.
8
+ */
9
+ import type { ExerciseLevel } from './types.ts';
10
+ import type { TestCaseResult, ValidationResult } from './validation.ts';
11
+ /** What a student has typed into a question, field by field. */
12
+ export type Answers = Readonly<Record<string, string>>;
13
+ /** One box a question asks the student to fill. */
14
+ export interface AnswerField {
15
+ /** Key of the value in {@link Answers}. */
16
+ key: string;
17
+ /** What the box is for, e.g. `Electrons` or `³⁵Cl (%)`. */
18
+ label: string;
19
+ /**
20
+ * Placeholder written in the empty box.
21
+ * @default undefined
22
+ */
23
+ placeholder?: string;
24
+ /**
25
+ * The keyboard a phone opens for the box: digits for a number, letters for
26
+ * a name or a formula.
27
+ * @default 'decimal'
28
+ */
29
+ inputMode?: 'decimal' | 'text';
30
+ }
31
+ /** The verdict on one field of an answer. */
32
+ export interface FieldCase extends TestCaseResult {
33
+ /** The field the verdict is about, as the box labels it. */
34
+ label: string;
35
+ }
36
+ /** The verdict on a whole answer. */
37
+ export type AnswerCheck = ValidationResult<FieldCase>;
38
+ /**
39
+ * One tool's exercises: the pool a series is drawn from, what a question asks
40
+ * for, and how an answer is graded, hinted at and solved. Pure: nothing here
41
+ * renders, so every part is unit-tested.
42
+ */
43
+ export interface SeriesTool<Question> {
44
+ /** Where the tool's progress and seed are kept. */
45
+ id: string;
46
+ /** Every question a series can draw. */
47
+ pool: readonly Question[];
48
+ /** A stable key for a question, unique in the pool. */
49
+ key: (question: Question) => string;
50
+ /**
51
+ * The level a question is tagged with.
52
+ * @default undefined
53
+ */
54
+ level?: (question: Question) => ExerciseLevel;
55
+ /** The boxes the question asks the student to fill. */
56
+ fields: (question: Question) => AnswerField[];
57
+ /** Grade an answer, one case per field, each reason written as a tutor says it. */
58
+ grade: (question: Question, answers: Answers) => AnswerCheck;
59
+ /** Two to four hints, vague to nearly the answer. */
60
+ hints: (question: Question) => string[];
61
+ /** The worked answer, always revealable. */
62
+ solution: (question: Question) => string;
63
+ /**
64
+ * Draw the series itself, for a tool whose questions are generated from the
65
+ * seed rather than picked out of {@link SeriesTool.pool}. It must return the
66
+ * same questions in the same order for the same seed, since a series is a
67
+ * link.
68
+ * @default undefined — the series is `pickSeeded(pool, count, seed)`
69
+ */
70
+ draw?: (count: number, seed: number) => readonly Question[];
71
+ /**
72
+ * The longest series the tool can serve, for the picker of its length.
73
+ * @default the size of the pool
74
+ */
75
+ maxCount?: number;
76
+ }
77
+ //# sourceMappingURL=series.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"series.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/core/series.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExE,gEAAgE;AAChE,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CAChC;AAED,6CAA6C;AAC7C,MAAM,WAAW,SAAU,SAAQ,cAAc;IAC/C,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qCAAqC;AACrC,MAAM,MAAM,WAAW,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAEtD;;;;GAIG;AACH,MAAM,WAAW,UAAU,CAAC,QAAQ;IAClC,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC1B,uDAAuD;IACvD,GAAG,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC;IACpC;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,aAAa,CAAC;IAC9C,uDAAuD;IACvD,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,WAAW,EAAE,CAAC;IAC9C,mFAAmF;IACnF,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,KAAK,WAAW,CAAC;IAC7D,qDAAqD;IACrD,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,EAAE,CAAC;IACxC,4CAA4C;IAC5C,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC;IACzC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,SAAS,QAAQ,EAAE,CAAC;IAC5D;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A graded series: questions drawn from a tool's pool by a seed, each asking
3
+ * the student to fill a few boxes, each box graded as a test case.
4
+ *
5
+ * Nothing here knows what is asked — electrons, a formula, a mass — so a tool
6
+ * of any subject describes its questions with {@link SeriesTool} and the shared
7
+ * series components draw them.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=series.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"series.js","sourceRoot":"","sources":["../../../src/pedagogy/core/series.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,21 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { AnswerField, Answers } from '../core/series.ts';
3
+ /** What {@link AnswerFields} needs. */
4
+ export interface AnswerFieldsProps {
5
+ /** The boxes the question asks for, in the order they are filled. */
6
+ fields: readonly AnswerField[];
7
+ /** What is typed in them so far. */
8
+ answers: Answers;
9
+ /** Called with the key of a box and its new text on every keystroke. */
10
+ onChange: (key: string, value: string) => void;
11
+ /** Called on Enter, which checks the answer. */
12
+ onSubmit: () => void;
13
+ }
14
+ /**
15
+ * The boxes a question asks the student to fill, side by side, each with the
16
+ * keyboard its value wants on a phone and every autocorrection switched off.
17
+ * @param props - The fields, what is typed in them, and what to do on a change.
18
+ * @returns The boxes.
19
+ */
20
+ export declare function AnswerFields(props: AnswerFieldsProps): ReactElement;
21
+ //# sourceMappingURL=AnswerFields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnswerFields.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/ui/AnswerFields.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAGzD,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE9D,uCAAuC;AACvC,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,wEAAwE;IACxE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,gDAAgD;IAChD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAsCnE"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { FormGroup, InputGroup } from '@blueprintjs/core';
3
+ import { useId } from 'react';
4
+ /**
5
+ * The boxes a question asks the student to fill, side by side, each with the
6
+ * keyboard its value wants on a phone and every autocorrection switched off.
7
+ * @param props - The fields, what is typed in them, and what to do on a change.
8
+ * @returns The boxes.
9
+ */
10
+ export function AnswerFields(props) {
11
+ const { fields, answers, onChange, onSubmit } = props;
12
+ const prefix = useId();
13
+ function submitOnEnter(event) {
14
+ if (event.key === 'Enter')
15
+ onSubmit();
16
+ }
17
+ return (_jsx("div", { className: "series-answers", children: fields.map((field) => {
18
+ const id = `${prefix}-${field.key}`;
19
+ return (_jsx(FormGroup, { label: field.label, labelFor: id, className: "series-answers__field", children: _jsx(InputGroup, { id: id, value: answers[field.key] ?? '', placeholder: field.placeholder, onValueChange: (value) => {
20
+ onChange(field.key, value);
21
+ }, onKeyDown: submitOnEnter, inputMode: field.inputMode ?? 'decimal', autoComplete: "off", autoCorrect: "off", autoCapitalize: "off", spellCheck: false }) }, field.key));
22
+ }) }));
23
+ }
24
+ //# sourceMappingURL=AnswerFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnswerFields.js","sourceRoot":"","sources":["../../../src/pedagogy/ui/AnswerFields.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAgB9B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACtD,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;IAEvB,SAAS,aAAa,CAAC,KAAsC;QAC3D,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO;YAAE,QAAQ,EAAE,CAAC;IACxC,CAAC;IAED,OAAO,CACL,cAAK,SAAS,EAAC,gBAAgB,YAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,EAAE,GAAG,GAAG,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YACpC,OAAO,CACL,KAAC,SAAS,IAER,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,QAAQ,EAAE,EAAE,EACZ,SAAS,EAAC,uBAAuB,YAEjC,KAAC,UAAU,IACT,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAC/B,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;wBACvB,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;oBAC7B,CAAC,EACD,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS,EACvC,YAAY,EAAC,KAAK,EAClB,WAAW,EAAC,KAAK,EACjB,cAAc,EAAC,KAAK,EACpB,UAAU,EAAE,KAAK,GACjB,IAlBG,KAAK,CAAC,GAAG,CAmBJ,CACb,CAAC;QACJ,CAAC,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,82 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ import type { ProgressRecords } from '../core/progress.ts';
3
+ import type { ExerciseLevel, ExerciseStatus } from '../core/types.ts';
4
+ /** What a row of the list reads off an exercise. */
5
+ export interface ExerciseListEntry {
6
+ /** Stable id, which is what is selected. */
7
+ id: string;
8
+ /** How the exercise is named; may carry the shared prose marks. */
9
+ title: string;
10
+ /**
11
+ * How hard it is, drawn as a coloured tag.
12
+ * @default undefined — no level tag
13
+ */
14
+ level?: ExerciseLevel;
15
+ }
16
+ /** What the list reads of the progress kept on one exercise. */
17
+ export interface ExerciseListProgress {
18
+ /** Where the student stands. */
19
+ status: ExerciseStatus;
20
+ /** How many hints were opened. */
21
+ hintsRevealed: number;
22
+ }
23
+ /** What {@link ExerciseList} needs. */
24
+ export interface ExerciseListProps<TExercise extends ExerciseListEntry> {
25
+ /** The exercises, in the order they are worked through. */
26
+ exercises: readonly TExercise[];
27
+ /** The progress kept, by exercise id; an absent one reads as untouched. */
28
+ progress: ProgressRecords<ExerciseListProgress>;
29
+ /** The exercise on screen, or `null` for none. */
30
+ activeId: string | null;
31
+ /** Called with the id of the exercise to open. */
32
+ onSelect: (id: string) => void;
33
+ /**
34
+ * Tags of the tool's own after the level — the kind of question, say.
35
+ * @default undefined
36
+ */
37
+ tags?: (exercise: TExercise) => ReactNode;
38
+ /**
39
+ * Draws the title the tool's own way.
40
+ * @default the title as inline prose, its marks drawn
41
+ */
42
+ renderTitle?: (exercise: TExercise) => ReactNode;
43
+ /**
44
+ * Whether the bar of solved exercises heads the list.
45
+ * @default true
46
+ */
47
+ progressHeader?: boolean;
48
+ /**
49
+ * Throws away every answer, behind a dialog. Without it the header only
50
+ * reports.
51
+ * @default undefined
52
+ */
53
+ onClearAll?: () => void;
54
+ /**
55
+ * What the dialog says before the work is thrown away.
56
+ * @default the header's own sentence
57
+ */
58
+ clearWarning?: ReactNode;
59
+ /**
60
+ * What a screen reader calls the list.
61
+ * @default the chrome's own word for it, in the language of the page
62
+ */
63
+ label?: string;
64
+ /**
65
+ * Class the list carries, in addition to `exercise-list`.
66
+ * @default undefined
67
+ */
68
+ className?: string;
69
+ }
70
+ /**
71
+ * The exercises of a set, each with where the student stands on it, under the
72
+ * bar of how many are solved.
73
+ *
74
+ * The hint count of a solved exercise is shown rather than hidden: it is the
75
+ * honest record of which ones were hard, which is what a student coming back a
76
+ * week later wants to know. `ArrowUp` and `ArrowDown` walk the list from
77
+ * anywhere on the page, unless a text field has the focus.
78
+ * @param props - The exercises, their progress, and the open one.
79
+ * @returns The list.
80
+ */
81
+ export declare function ExerciseList<TExercise extends ExerciseListEntry>(props: ExerciseListProps<TExercise>): ReactElement;
82
+ //# sourceMappingURL=ExerciseList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExerciseList.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/ui/ExerciseList.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMtE,oDAAoD;AACpD,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,gEAAgE;AAChE,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,MAAM,EAAE,cAAc,CAAC;IACvB,kCAAkC;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,uCAAuC;AACvC,MAAM,WAAW,iBAAiB,CAAC,SAAS,SAAS,iBAAiB;IACpE,2DAA2D;IAC3D,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAC;IAChD,kDAAkD;IAClD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kDAAkD;IAClD,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B;;;OAGG;IACH,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;IAC1C;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;IACjD;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,SAAS,SAAS,iBAAiB,EAC9D,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC,GAClC,YAAY,CAkGd"}
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Tag } from '@blueprintjs/core';
3
+ import { useDocumentListNavigation } from "../../hooks/ui/useDocumentListNavigation.js";
4
+ import { useChromeT } from "../../i18n/ui/useT.js";
5
+ import { joinClassNames } from "../../shared/ui/joinClassNames.js";
6
+ import { progressSummary } from "../core/progress.js";
7
+ import { ExerciseProgressHeader } from "./ExerciseProgressHeader.js";
8
+ import { ExerciseLevelTag, ExerciseStatusIcon } from "./ExerciseTags.js";
9
+ import { InlineText } from "./InlineText.js";
10
+ const STATUS_TITLE = {
11
+ idle: 'pedagogy.statusIdle',
12
+ attempted: 'pedagogy.statusAttempted',
13
+ solved: 'pedagogy.statusSolved',
14
+ };
15
+ /**
16
+ * The exercises of a set, each with where the student stands on it, under the
17
+ * bar of how many are solved.
18
+ *
19
+ * The hint count of a solved exercise is shown rather than hidden: it is the
20
+ * honest record of which ones were hard, which is what a student coming back a
21
+ * week later wants to know. `ArrowUp` and `ArrowDown` walk the list from
22
+ * anywhere on the page, unless a text field has the focus.
23
+ * @param props - The exercises, their progress, and the open one.
24
+ * @returns The list.
25
+ */
26
+ export function ExerciseList(props) {
27
+ const { exercises, progress, activeId, onSelect, tags, renderTitle, progressHeader = true, onClearAll, clearWarning, label, className, } = props;
28
+ const t = useChromeT();
29
+ const activeIndex = exercises.findIndex((exercise) => exercise.id === activeId);
30
+ const listRef = useDocumentListNavigation({
31
+ length: exercises.length,
32
+ selectedIndex: activeIndex,
33
+ onSelect: (index) => {
34
+ const next = exercises[index];
35
+ if (next !== undefined)
36
+ onSelect(next.id);
37
+ },
38
+ });
39
+ return (_jsxs("div", { className: joinClassNames('exercise-list', className), children: [progressHeader ? (_jsx(ExerciseProgressHeader, { summary: progressSummary(progress, exercises.map((exercise) => exercise.id)), onClearAll: onClearAll, clearWarning: clearWarning, clearDisabled: Object.keys(progress).length === 0 })) : null, _jsx("div", { ref: listRef, className: "exercise-list__rows", role: "listbox", "aria-label": label ?? t('pedagogy.exercises'), "data-testid": "exercise-list", children: exercises.map((exercise) => {
40
+ const record = progress[exercise.id];
41
+ const status = record?.status ?? 'idle';
42
+ const hints = record?.hintsRevealed ?? 0;
43
+ const active = exercise.id === activeId;
44
+ return (_jsxs("button", { type: "button", role: "option", "aria-selected": active, "data-selected": active ? 'true' : undefined, className: active
45
+ ? 'exercise-list__item exercise-list__item--active'
46
+ : 'exercise-list__item', onClick: () => {
47
+ onSelect(exercise.id);
48
+ }, children: [_jsx(ExerciseStatusIcon, { status: status, title: t(STATUS_TITLE[status]) }), _jsx("span", { className: "exercise-list__title", children: renderTitle === undefined ? (_jsx(InlineText, { text: exercise.title })) : (renderTitle(exercise)) }), _jsxs("span", { className: "exercise-list__tags", children: [exercise.level === undefined ? null : (_jsx(ExerciseLevelTag, { level: exercise.level, active: active })), tags?.(exercise), status === 'solved' && hints > 0 ? (_jsx(Tag, { minimal: true, round: true, intent: "success", children: hints === 1
49
+ ? t('pedagogy.solvedWithOneHint')
50
+ : t('pedagogy.solvedWithHints', { count: hints }) })) : null] })] }, exercise.id));
51
+ }) })] }));
52
+ }
53
+ //# sourceMappingURL=ExerciseList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExerciseList.js","sourceRoot":"","sources":["../../../src/pedagogy/ui/ExerciseList.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ import type { SplitRange } from '../../split/core/split.ts';
3
+ import type { AttemptStore } from '../core/attempts.ts';
4
+ import type { PickSeededOptions, SeedRange } from '../core/seed.ts';
5
+ import type { SeriesTool } from '../core/series.ts';
6
+ import type { QuestionRendering } from './QuestionCard.tsx';
7
+ /** What {@link ExerciseSeries} needs. */
8
+ export interface ExerciseSeriesProps<Question> extends QuestionRendering<Question> {
9
+ /** The tool the series is drawn from. */
10
+ tool: SeriesTool<Question>;
11
+ /** Where the attempts, and the series each tool was last on, are kept. */
12
+ store: AttemptStore;
13
+ /** How a question is named in the list beside the card. */
14
+ label: (question: Question) => ReactNode;
15
+ /**
16
+ * The seed the address names, read with `parseSeed`, or `null` when it names
17
+ * none — the series this browser was last on is then written into it.
18
+ */
19
+ seed: number | null;
20
+ /**
21
+ * Write a seed into the address: `replace` when the page adopts one it was
22
+ * opened without, `push` when the student draws a new series, so Back
23
+ * returns to the previous one.
24
+ */
25
+ onSeed: (seed: number, history: 'replace' | 'push') => void;
26
+ /** How many questions the student asked for; the pool caps it. */
27
+ count: number;
28
+ /** Change how many questions the series holds. */
29
+ onCount: (count: number) => void;
30
+ /**
31
+ * The lengths offered, beside the whole pool.
32
+ * @default [5, 10, 15, 20]
33
+ */
34
+ counts?: readonly number[];
35
+ /**
36
+ * The share of the row the list takes, as the address names it, or `null`
37
+ * for {@link ExerciseSeriesProps.defaultSplit}.
38
+ */
39
+ split: number | null;
40
+ /** Write the share a drag came to rest at, or `null` for the default. */
41
+ onSplit: (split: number | null) => void;
42
+ /**
43
+ * The share the list opens at: the card is the figure, so the list opens
44
+ * narrow.
45
+ * @default 22
46
+ */
47
+ defaultSplit?: number;
48
+ /**
49
+ * How far the list may be dragged, measured on the labels of the pool.
50
+ * @default { min: 15, max: 26 }
51
+ */
52
+ splitRange?: SplitRange;
53
+ /**
54
+ * The narrowest row still divided, in pixels; under it the list stacks under
55
+ * the card's row, as on a tablet held upright.
56
+ * @default SplitRow's own, 860
57
+ */
58
+ stackBelow?: number;
59
+ /**
60
+ * How the series is drawn from the pool, for a site whose links were written
61
+ * with the other generator call.
62
+ * @default { draw: 'getFloat', wrap: false }
63
+ */
64
+ pick?: PickSeededOptions;
65
+ /**
66
+ * The seeds a new series is drawn from.
67
+ * @default every unsigned 32-bit integer
68
+ */
69
+ seedRange?: SeedRange;
70
+ /**
71
+ * The heading over the series.
72
+ * @default the chrome's own word for it, in the language of the page
73
+ */
74
+ title?: ReactNode;
75
+ /**
76
+ * Id of the heading, for a section labelled by it.
77
+ * @default 'questions-heading'
78
+ */
79
+ headingId?: string;
80
+ }
81
+ /**
82
+ * A graded series drawn from a tool's pool: the list of its questions, the one
83
+ * open, and the progress over the series.
84
+ *
85
+ * The series is its seed, and the seed is in the address, so the link on
86
+ * screen reopens the same questions for anyone — a teacher hands one series to
87
+ * a whole class. How the row is divided between the list and the open question
88
+ * travels in the address too. The component reads neither: the page hands it
89
+ * the seed, the length and the share, and is told when one changes.
90
+ * @param props - The tool, where its attempts are kept, the address values,
91
+ * and how to draw a question.
92
+ * @returns The series.
93
+ */
94
+ export declare function ExerciseSeries<Question>(props: ExerciseSeriesProps<Question>): ReactElement;
95
+ //# sourceMappingURL=ExerciseSeries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExerciseSeries.d.ts","sourceRoot":"","sources":["../../../src/pedagogy/ui/ExerciseSeries.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAK5D,yCAAyC;AACzC,MAAM,WAAW,mBAAmB,CAClC,QAAQ,CACR,SAAQ,iBAAiB,CAAC,QAAQ,CAAC;IACnC,yCAAyC;IACzC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3B,0EAA0E;IAC1E,KAAK,EAAE,YAAY,CAAC;IACpB,2DAA2D;IAC3D,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,SAAS,CAAC;IACzC;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;;;OAIG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,KAAK,IAAI,CAAC;IAC5D,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yEAAyE;IACzE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EACrC,KAAK,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GACnC,YAAY,CAuId"}
@@ -0,0 +1,74 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useEffectEvent, useMemo, useState } from 'react';
3
+ import { useDocumentListNavigation } from "../../hooks/ui/useDocumentListNavigation.js";
4
+ import { clampSplit } from "../../split/core/split.js";
5
+ import { SplitRow } from "../../split/ui/SplitRow.js";
6
+ import { attemptKey } from "../core/attempts.js";
7
+ import { progressSummary } from "../core/progress.js";
8
+ import { freshSeed, pickSeeded } from "../core/seed.js";
9
+ import { ExerciseProgressHeader } from "./ExerciseProgressHeader.js";
10
+ import { QuestionCard } from "./QuestionCard.js";
11
+ import { SeriesHead, SeriesQuestionList } from "./seriesParts.js";
12
+ import { useAttemptRecords } from "./useAttemptRecords.js";
13
+ const DEFAULT_RANGE = { min: 15, max: 26 };
14
+ /**
15
+ * A graded series drawn from a tool's pool: the list of its questions, the one
16
+ * open, and the progress over the series.
17
+ *
18
+ * The series is its seed, and the seed is in the address, so the link on
19
+ * screen reopens the same questions for anyone — a teacher hands one series to
20
+ * a whole class. How the row is divided between the list and the open question
21
+ * travels in the address too. The component reads neither: the page hands it
22
+ * the seed, the length and the share, and is told when one changes.
23
+ * @param props - The tool, where its attempts are kept, the address values,
24
+ * and how to draw a question.
25
+ * @returns The series.
26
+ */
27
+ export function ExerciseSeries(props) {
28
+ const { tool, store, label, seed: addressSeed, onSeed, count: wanted, onCount, counts, split, onSplit, defaultSplit = 22, splitRange = DEFAULT_RANGE, stackBelow, pick, seedRange, title, headingId = 'questions-heading', ...rendering } = props;
29
+ const records = useAttemptRecords(store);
30
+ const [fallbackSeed] = useState(() => store.storedSeed(tool.id) ?? freshSeed(seedRange));
31
+ const seed = addressSeed ?? fallbackSeed;
32
+ const poolSize = tool.maxCount ?? tool.pool.length;
33
+ const count = Math.min(wanted, poolSize);
34
+ // The address is what the series is read from and handed out as, so a page
35
+ // opened without a seed writes the one it fell back on into it; and the
36
+ // series on screen is the one this tool reopens on the next visit.
37
+ const followSeed = useEffectEvent(() => {
38
+ if (addressSeed === null)
39
+ onSeed(fallbackSeed, 'replace');
40
+ store.storeSeed(tool.id, addressSeed ?? fallbackSeed);
41
+ });
42
+ useEffect(() => {
43
+ followSeed();
44
+ }, [seed, addressSeed, tool.id]);
45
+ const series = useMemo(() => tool.draw === undefined
46
+ ? pickSeeded(tool.pool, count, seed, pick)
47
+ : tool.draw(count, seed), [tool, count, seed, pick]);
48
+ const keys = useMemo(() => series.map((question) => attemptKey(tool.id, seed, tool.key(question))), [series, tool, seed]);
49
+ const [opened, setOpened] = useState({ seed, index: 0 });
50
+ const index = opened.seed === seed ? Math.min(opened.index, series.length - 1) : 0;
51
+ function open(next) {
52
+ setOpened({ seed, index: next });
53
+ }
54
+ const listRef = useDocumentListNavigation({
55
+ length: series.length,
56
+ selectedIndex: index,
57
+ onSelect: open,
58
+ });
59
+ const summary = progressSummary(records, keys);
60
+ const question = series[index];
61
+ const storageKey = keys[index];
62
+ return (_jsxs("div", { className: "exercise-series", children: [_jsx(SeriesHead, { title: title, headingId: headingId, count: count, poolSize: poolSize, counts: counts, onCount: onCount, onNewSeries: () => {
63
+ const next = freshSeed(seedRange);
64
+ store.forgetOtherSeries(tool.id, next);
65
+ onSeed(next, 'push');
66
+ } }), _jsx(ExerciseProgressHeader, { summary: summary, onClearAll: () => {
67
+ store.clearAttempts(keys);
68
+ }, clearDisabled: !keys.some((key) => records[key] !== undefined) }), _jsx(SplitRow, { ratio: split === null ? null : clampSplit(split, splitRange), defaultRatio: defaultSplit, min: splitRange.min, max: splitRange.max, stackBelow: stackBelow, onRatio: onSplit, start: _jsx(SeriesQuestionList, { series: series, keys: keys, records: records, index: index, onOpen: open, label: label, listRef: listRef }), end: question === undefined || storageKey === undefined ? null : (_jsx(QuestionCard, { tool: tool, question: question, store: store, storageKey: storageKey, number: index + 1, total: series.length, onNext: index + 1 < series.length
69
+ ? () => {
70
+ open(index + 1);
71
+ }
72
+ : undefined, ...rendering }, storageKey)) })] }));
73
+ }
74
+ //# sourceMappingURL=ExerciseSeries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExerciseSeries.js","sourceRoot":"","sources":["../../../src/pedagogy/ui/ExerciseSeries.tsx"],"names":[],"mappings":"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"}