@doenet/doenetml 0.6.0-alpha1

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 (549) hide show
  1. package/.prettierrc +3 -0
  2. package/LICENSE +661 -0
  3. package/README.md +146 -0
  4. package/cypress/e2e/ActivityViewer/activityVariants.cy.js +1770 -0
  5. package/cypress/e2e/ActivityViewer/compiledActivity.cy.js +83 -0
  6. package/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js +697 -0
  7. package/cypress/e2e/answerValidation/errorinnumbers.cy.js +2125 -0
  8. package/cypress/e2e/answerValidation/factoring.cy.js +1945 -0
  9. package/cypress/e2e/answerValidation/factoringOldAlgorithm.cy.js +892 -0
  10. package/cypress/e2e/answerValidation/functionanswers.cy.js +314 -0
  11. package/cypress/e2e/answerValidation/matchingpatterns.cy.js +287 -0
  12. package/cypress/e2e/answerValidation/matchpartial.cy.js +6711 -0
  13. package/cypress/e2e/answerValidation/pointlocation.cy.js +3989 -0
  14. package/cypress/e2e/answerValidation/symbolicequality.cy.js +1893 -0
  15. package/cypress/e2e/answerValidation/videoProgress.cy.js +210 -0
  16. package/cypress/e2e/assignNames/basiccopy.cy.js +2376 -0
  17. package/cypress/e2e/assignNames/collections.cy.js +9247 -0
  18. package/cypress/e2e/assignNames/selects.cy.js +105 -0
  19. package/cypress/e2e/assignNames/sequences.cy.js +1964 -0
  20. package/cypress/e2e/baseComponent/basecomponentproperties.cy.js +999 -0
  21. package/cypress/e2e/baseComponent/doenetMLtext.cy.js +427 -0
  22. package/cypress/e2e/chemistry/atom.cy.js +201 -0
  23. package/cypress/e2e/chemistry/ion.cy.js +608 -0
  24. package/cypress/e2e/chemistry/ioniccompound.cy.js +133 -0
  25. package/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +2653 -0
  26. package/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js +311 -0
  27. package/cypress/e2e/dynamicalsystem/equilibriumline.cy.js +279 -0
  28. package/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js +283 -0
  29. package/cypress/e2e/dynamicalsystem/odesystem.cy.js +1834 -0
  30. package/cypress/e2e/equality/mathexpressions.cy.js +948 -0
  31. package/cypress/e2e/graphing/graphreferences.cy.js +978 -0
  32. package/cypress/e2e/graphing/graphreferences2.cy.js +615 -0
  33. package/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js +401 -0
  34. package/cypress/e2e/tagSpecific/angle.cy.js +3898 -0
  35. package/cypress/e2e/tagSpecific/animatefromsequence.cy.js +2306 -0
  36. package/cypress/e2e/tagSpecific/answer.cy.js +31647 -0
  37. package/cypress/e2e/tagSpecific/bestfitline.cy.js +612 -0
  38. package/cypress/e2e/tagSpecific/blockquote.cy.js +30 -0
  39. package/cypress/e2e/tagSpecific/boolean.cy.js +742 -0
  40. package/cypress/e2e/tagSpecific/booleaninput.cy.js +1283 -0
  41. package/cypress/e2e/tagSpecific/booleanlist.cy.js +588 -0
  42. package/cypress/e2e/tagSpecific/booleanoperators.cy.js +596 -0
  43. package/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js +498 -0
  44. package/cypress/e2e/tagSpecific/callaction.cy.js +2835 -0
  45. package/cypress/e2e/tagSpecific/choiceinput.cy.js +3205 -0
  46. package/cypress/e2e/tagSpecific/circle.cy.js +22036 -0
  47. package/cypress/e2e/tagSpecific/codeeditor.cy.js +1995 -0
  48. package/cypress/e2e/tagSpecific/collect.cy.js +5035 -0
  49. package/cypress/e2e/tagSpecific/componentsize.cy.js +502 -0
  50. package/cypress/e2e/tagSpecific/conditionalcontent.cy.js +3495 -0
  51. package/cypress/e2e/tagSpecific/contentBrowser.cy.js +335 -0
  52. package/cypress/e2e/tagSpecific/contentpicker.cy.js +261 -0
  53. package/cypress/e2e/tagSpecific/copy.cy.js +12627 -0
  54. package/cypress/e2e/tagSpecific/copy2.cy.js +5698 -0
  55. package/cypress/e2e/tagSpecific/curve.bezier.cy.js +12440 -0
  56. package/cypress/e2e/tagSpecific/curve.cy.js +1716 -0
  57. package/cypress/e2e/tagSpecific/curve.function.cy.js +1471 -0
  58. package/cypress/e2e/tagSpecific/curve.parametrized.cy.js +920 -0
  59. package/cypress/e2e/tagSpecific/document.cy.js +234 -0
  60. package/cypress/e2e/tagSpecific/endpoint.cy.js +197 -0
  61. package/cypress/e2e/tagSpecific/evaluate.cy.js +8895 -0
  62. package/cypress/e2e/tagSpecific/extract.cy.js +2282 -0
  63. package/cypress/e2e/tagSpecific/feedback.cy.js +2941 -0
  64. package/cypress/e2e/tagSpecific/function.cy.js +9450 -0
  65. package/cypress/e2e/tagSpecific/functioniterates.cy.js +1178 -0
  66. package/cypress/e2e/tagSpecific/functionoperators.cy.js +4047 -0
  67. package/cypress/e2e/tagSpecific/graph.cy.js +2491 -0
  68. package/cypress/e2e/tagSpecific/group.cy.js +683 -0
  69. package/cypress/e2e/tagSpecific/hint.cy.js +204 -0
  70. package/cypress/e2e/tagSpecific/image.cy.js +770 -0
  71. package/cypress/e2e/tagSpecific/integer.cy.js +206 -0
  72. package/cypress/e2e/tagSpecific/label.cy.js +800 -0
  73. package/cypress/e2e/tagSpecific/legend.cy.js +1001 -0
  74. package/cypress/e2e/tagSpecific/line.cy.js +12167 -0
  75. package/cypress/e2e/tagSpecific/linesegment.cy.js +4749 -0
  76. package/cypress/e2e/tagSpecific/lorem.cy.js +289 -0
  77. package/cypress/e2e/tagSpecific/map.cy.js +4476 -0
  78. package/cypress/e2e/tagSpecific/matchespattern.cy.js +693 -0
  79. package/cypress/e2e/tagSpecific/math.cy.js +10990 -0
  80. package/cypress/e2e/tagSpecific/mathdisplay.cy.js +2689 -0
  81. package/cypress/e2e/tagSpecific/mathinput.cy.js +15628 -0
  82. package/cypress/e2e/tagSpecific/mathinputgraph.cy.js +566 -0
  83. package/cypress/e2e/tagSpecific/mathlist.cy.js +4073 -0
  84. package/cypress/e2e/tagSpecific/mathoperators.cy.js +13851 -0
  85. package/cypress/e2e/tagSpecific/matrix.cy.js +8825 -0
  86. package/cypress/e2e/tagSpecific/matrixinput.cy.js +16277 -0
  87. package/cypress/e2e/tagSpecific/module.cy.js +1771 -0
  88. package/cypress/e2e/tagSpecific/number.cy.js +2221 -0
  89. package/cypress/e2e/tagSpecific/numberlist.cy.js +1285 -0
  90. package/cypress/e2e/tagSpecific/p.cy.js +72 -0
  91. package/cypress/e2e/tagSpecific/paginator.cy.js +2983 -0
  92. package/cypress/e2e/tagSpecific/parabola.cy.js +14331 -0
  93. package/cypress/e2e/tagSpecific/paragraphmarkup.cy.js +104 -0
  94. package/cypress/e2e/tagSpecific/periodicset.cy.js +1439 -0
  95. package/cypress/e2e/tagSpecific/piecewisefunction.cy.js +1055 -0
  96. package/cypress/e2e/tagSpecific/pluralize.cy.js +274 -0
  97. package/cypress/e2e/tagSpecific/point.cy.js +8895 -0
  98. package/cypress/e2e/tagSpecific/point2.cy.js +10259 -0
  99. package/cypress/e2e/tagSpecific/polygon.cy.js +5039 -0
  100. package/cypress/e2e/tagSpecific/polyline.cy.js +4704 -0
  101. package/cypress/e2e/tagSpecific/problem.cy.js +2768 -0
  102. package/cypress/e2e/tagSpecific/ray.cy.js +10770 -0
  103. package/cypress/e2e/tagSpecific/rectangle.cy.js +2143 -0
  104. package/cypress/e2e/tagSpecific/ref.cy.js +420 -0
  105. package/cypress/e2e/tagSpecific/regularPolygon.cy.js +1006 -0
  106. package/cypress/e2e/tagSpecific/regularPolygon2.cy.js +100 -0
  107. package/cypress/e2e/tagSpecific/regularPolygon3.cy.js +777 -0
  108. package/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js +3619 -0
  109. package/cypress/e2e/tagSpecific/sectioning.cy.js +3530 -0
  110. package/cypress/e2e/tagSpecific/select.cy.js +5376 -0
  111. package/cypress/e2e/tagSpecific/selectfromsequence.cy.js +3846 -0
  112. package/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js +2914 -0
  113. package/cypress/e2e/tagSpecific/sequence.cy.js +2093 -0
  114. package/cypress/e2e/tagSpecific/shuffle.cy.js +490 -0
  115. package/cypress/e2e/tagSpecific/sidebyside.cy.js +8057 -0
  116. package/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js +72 -0
  117. package/cypress/e2e/tagSpecific/slider.cy.js +914 -0
  118. package/cypress/e2e/tagSpecific/solution.cy.js +109 -0
  119. package/cypress/e2e/tagSpecific/solveequations.cy.js +1026 -0
  120. package/cypress/e2e/tagSpecific/sort.cy.js +1685 -0
  121. package/cypress/e2e/tagSpecific/spreadsheet.cy.js +5971 -0
  122. package/cypress/e2e/tagSpecific/subsetofreals.cy.js +2725 -0
  123. package/cypress/e2e/tagSpecific/substitute.cy.js +2646 -0
  124. package/cypress/e2e/tagSpecific/tabular.cy.js +36 -0
  125. package/cypress/e2e/tagSpecific/text.cy.js +975 -0
  126. package/cypress/e2e/tagSpecific/textinput.cy.js +2177 -0
  127. package/cypress/e2e/tagSpecific/textlist.cy.js +369 -0
  128. package/cypress/e2e/tagSpecific/triangle.cy.js +1936 -0
  129. package/cypress/e2e/tagSpecific/triggerset.cy.js +2023 -0
  130. package/cypress/e2e/tagSpecific/updatevalue.cy.js +3288 -0
  131. package/cypress/e2e/tagSpecific/vector.cy.js +20183 -0
  132. package/cypress/e2e/tagSpecific/video.cy.js +612 -0
  133. package/cypress/e2e/tagSpecific/when.cy.js +202 -0
  134. package/cypress/e2e/variants/specifysinglevariant.cy.js +6726 -0
  135. package/cypress/e2e/variants/uniquevariants.cy.js +4846 -0
  136. package/cypress/fixtures/example.json +5 -0
  137. package/cypress/support/commands.js +32 -0
  138. package/cypress/support/e2e.js +31 -0
  139. package/cypress.config.js +18 -0
  140. package/docs/codeSnippet.jsx +11 -0
  141. package/docs/index.html +133 -0
  142. package/docs/index.jsx +138 -0
  143. package/docs/prism.css +3 -0
  144. package/index.html +14 -0
  145. package/index.js +21 -0
  146. package/media/answer_example.png +0 -0
  147. package/media/graph_example.png +0 -0
  148. package/media/graph_markup_example.png +0 -0
  149. package/package.json +83 -0
  150. package/public/favicon.ico +0 -0
  151. package/public/fonts/files/open-sans-v18-latin-700.woff +0 -0
  152. package/public/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
  153. package/public/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
  154. package/public/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
  155. package/public/fonts/files/open-sans-v18-latin-italic.woff +0 -0
  156. package/public/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
  157. package/public/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
  158. package/public/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
  159. package/public/fonts/files/open-sans-v18-latin-light.woff +0 -0
  160. package/public/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
  161. package/public/fonts/files/open-sans-v18-latin-regular.woff +0 -0
  162. package/public/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
  163. package/src/Core/ComponentTypes.js +426 -0
  164. package/src/Core/Core.js +11852 -0
  165. package/src/Core/CoreWorker.js +127 -0
  166. package/src/Core/Dependencies.js +8226 -0
  167. package/src/Core/Numerics.js +473 -0
  168. package/src/Core/ParameterStack.js +36 -0
  169. package/src/Core/ReadOnlyProxyHandler.js +41 -0
  170. package/src/Core/StateProxyHandler.js +88 -0
  171. package/src/Core/components/Aliases.js +67 -0
  172. package/src/Core/components/Angle.js +758 -0
  173. package/src/Core/components/AnimateFromSequence.js +922 -0
  174. package/src/Core/components/Answer.js +2087 -0
  175. package/src/Core/components/AsList.js +83 -0
  176. package/src/Core/components/AttractTo.js +245 -0
  177. package/src/Core/components/AttractToAngles.js +262 -0
  178. package/src/Core/components/AttractToConstraint.js +104 -0
  179. package/src/Core/components/AttractToGrid.js +315 -0
  180. package/src/Core/components/Award.js +906 -0
  181. package/src/Core/components/BestFitLine.js +318 -0
  182. package/src/Core/components/BezierControls.js +719 -0
  183. package/src/Core/components/BlockQuote.js +35 -0
  184. package/src/Core/components/Boolean.js +500 -0
  185. package/src/Core/components/BooleanInput.js +330 -0
  186. package/src/Core/components/BooleanList.js +396 -0
  187. package/src/Core/components/BooleanOperators.js +35 -0
  188. package/src/Core/components/BooleanOperatorsOfMath.js +148 -0
  189. package/src/Core/components/CallAction.js +261 -0
  190. package/src/Core/components/Caption.js +73 -0
  191. package/src/Core/components/Case.js +56 -0
  192. package/src/Core/components/Cell.js +439 -0
  193. package/src/Core/components/CellBlock.js +64 -0
  194. package/src/Core/components/Chart.js +795 -0
  195. package/src/Core/components/Choice.js +266 -0
  196. package/src/Core/components/ChoiceInput.js +1407 -0
  197. package/src/Core/components/Circle.js +2884 -0
  198. package/src/Core/components/CodeEditor.js +647 -0
  199. package/src/Core/components/CodeViewer.js +294 -0
  200. package/src/Core/components/CollaborateGroupSetup.js +46 -0
  201. package/src/Core/components/CollaborateGroups.js +119 -0
  202. package/src/Core/components/Collect.js +850 -0
  203. package/src/Core/components/Column.js +608 -0
  204. package/src/Core/components/ConditionalContent.js +468 -0
  205. package/src/Core/components/ConsiderAsResponses.js +49 -0
  206. package/src/Core/components/ConstrainTo.js +161 -0
  207. package/src/Core/components/ConstrainToAngles.js +244 -0
  208. package/src/Core/components/ConstrainToGraph.js +142 -0
  209. package/src/Core/components/ConstrainToGrid.js +175 -0
  210. package/src/Core/components/ConstraintUnion.js +119 -0
  211. package/src/Core/components/Constraints.js +497 -0
  212. package/src/Core/components/ContentBrowser.js +441 -0
  213. package/src/Core/components/ContentPicker.js +263 -0
  214. package/src/Core/components/ControlVectors.js +25 -0
  215. package/src/Core/components/Coords.js +63 -0
  216. package/src/Core/components/Copy.js +3412 -0
  217. package/src/Core/components/Curve.js +4130 -0
  218. package/src/Core/components/CustomAttribute.js +175 -0
  219. package/src/Core/components/DataFrame.js +357 -0
  220. package/src/Core/components/DiscreteSimulationResultList.js +342 -0
  221. package/src/Core/components/DiscreteSimulationResultPolyline.js +581 -0
  222. package/src/Core/components/Divisions.js +55 -0
  223. package/src/Core/components/Document.js +888 -0
  224. package/src/Core/components/Embed.js +65 -0
  225. package/src/Core/components/Endpoint.js +62 -0
  226. package/src/Core/components/Evaluate.js +321 -0
  227. package/src/Core/components/Extract.js +656 -0
  228. package/src/Core/components/Extrema.js +556 -0
  229. package/src/Core/components/Feedback.js +200 -0
  230. package/src/Core/components/FeedbackDefinitions.js +97 -0
  231. package/src/Core/components/Figure.js +148 -0
  232. package/src/Core/components/Footnote.js +73 -0
  233. package/src/Core/components/Function.js +5344 -0
  234. package/src/Core/components/FunctionIterates.js +306 -0
  235. package/src/Core/components/FunctionOperators.js +702 -0
  236. package/src/Core/components/Graph.js +1679 -0
  237. package/src/Core/components/Group.js +7 -0
  238. package/src/Core/components/HasSameFactoring.js +407 -0
  239. package/src/Core/components/Hint.js +241 -0
  240. package/src/Core/components/Image.js +524 -0
  241. package/src/Core/components/Indexing.js +79 -0
  242. package/src/Core/components/IntComma.js +64 -0
  243. package/src/Core/components/Integer.js +81 -0
  244. package/src/Core/components/Intersection.js +328 -0
  245. package/src/Core/components/Interval.js +29 -0
  246. package/src/Core/components/Label.js +492 -0
  247. package/src/Core/components/Latex.js +104 -0
  248. package/src/Core/components/Legend.js +329 -0
  249. package/src/Core/components/Line.js +2040 -0
  250. package/src/Core/components/LineSegment.js +882 -0
  251. package/src/Core/components/Lists.js +180 -0
  252. package/src/Core/components/Lorem.js +249 -0
  253. package/src/Core/components/MMeMen.js +377 -0
  254. package/src/Core/components/Map.js +873 -0
  255. package/src/Core/components/Markers.js +101 -0
  256. package/src/Core/components/MatchesPattern.js +339 -0
  257. package/src/Core/components/Math.js +2552 -0
  258. package/src/Core/components/MathInput.js +948 -0
  259. package/src/Core/components/MathList.js +828 -0
  260. package/src/Core/components/MathOperators.js +1286 -0
  261. package/src/Core/components/Matrix.js +497 -0
  262. package/src/Core/components/MatrixInput.js +3157 -0
  263. package/src/Core/components/MdMdnMrow.js +394 -0
  264. package/src/Core/components/Module.js +16 -0
  265. package/src/Core/components/Number.js +1031 -0
  266. package/src/Core/components/NumberList.js +550 -0
  267. package/src/Core/components/Option.js +24 -0
  268. package/src/Core/components/P.js +71 -0
  269. package/src/Core/components/Paginator.js +338 -0
  270. package/src/Core/components/Panel.js +126 -0
  271. package/src/Core/components/Parabola.js +1561 -0
  272. package/src/Core/components/ParagraphMarkup.js +59 -0
  273. package/src/Core/components/Pegboard.js +43 -0
  274. package/src/Core/components/PeriodicSet.js +291 -0
  275. package/src/Core/components/PiecewiseFunction.js +832 -0
  276. package/src/Core/components/Pluralize.js +198 -0
  277. package/src/Core/components/Point.js +1295 -0
  278. package/src/Core/components/Polygon.js +408 -0
  279. package/src/Core/components/Polyline.js +841 -0
  280. package/src/Core/components/RandomizedTextList.js +225 -0
  281. package/src/Core/components/Ray.js +1737 -0
  282. package/src/Core/components/Rectangle.js +1535 -0
  283. package/src/Core/components/Ref.js +350 -0
  284. package/src/Core/components/RegionBetweenCurveXAxis.js +124 -0
  285. package/src/Core/components/RegionHalfPlane.js +107 -0
  286. package/src/Core/components/RegularPolygon.js +2118 -0
  287. package/src/Core/components/RenderDoenetML.js +181 -0
  288. package/src/Core/components/Row.js +780 -0
  289. package/src/Core/components/SampleRandomNumbers.js +653 -0
  290. package/src/Core/components/Sectioning.js +303 -0
  291. package/src/Core/components/Select.js +947 -0
  292. package/src/Core/components/SelectFromSequence.js +1242 -0
  293. package/src/Core/components/SelectRandomNumbers.js +225 -0
  294. package/src/Core/components/Sequence.js +444 -0
  295. package/src/Core/components/Setup.js +53 -0
  296. package/src/Core/components/Shuffle.js +470 -0
  297. package/src/Core/components/SideBySide.js +2130 -0
  298. package/src/Core/components/SingleCharacterComponents.js +41 -0
  299. package/src/Core/components/Slider.js +819 -0
  300. package/src/Core/components/SolutionContainer.js +67 -0
  301. package/src/Core/components/Solutions.js +334 -0
  302. package/src/Core/components/SolveEquations.js +568 -0
  303. package/src/Core/components/Sort.js +398 -0
  304. package/src/Core/components/Sources.js +108 -0
  305. package/src/Core/components/Split.js +205 -0
  306. package/src/Core/components/Spreadsheet.js +1507 -0
  307. package/src/Core/components/StyleDefinitions.js +111 -0
  308. package/src/Core/components/SubsetOfReals.js +348 -0
  309. package/src/Core/components/SubsetOfRealsInput.js +1474 -0
  310. package/src/Core/components/Substitute.js +496 -0
  311. package/src/Core/components/SummaryStatistics.js +652 -0
  312. package/src/Core/components/Table.js +145 -0
  313. package/src/Core/components/Tabular.js +384 -0
  314. package/src/Core/components/Template.js +360 -0
  315. package/src/Core/components/Text.js +341 -0
  316. package/src/Core/components/TextInput.js +566 -0
  317. package/src/Core/components/TextList.js +442 -0
  318. package/src/Core/components/TextListFromString.js +137 -0
  319. package/src/Core/components/TextOperatorsOfMath.js +21 -0
  320. package/src/Core/components/Triangle.js +280 -0
  321. package/src/Core/components/TriggerSet.js +189 -0
  322. package/src/Core/components/TupleList.js +43 -0
  323. package/src/Core/components/UpdateValue.js +435 -0
  324. package/src/Core/components/VariantControl.js +36 -0
  325. package/src/Core/components/Vector.js +2478 -0
  326. package/src/Core/components/Verbatim.js +125 -0
  327. package/src/Core/components/Video.js +673 -0
  328. package/src/Core/components/When.js +198 -0
  329. package/src/Core/components/abstract/AngleListComponent.js +140 -0
  330. package/src/Core/components/abstract/BaseComponent.js +1496 -0
  331. package/src/Core/components/abstract/BlockComponent.js +5 -0
  332. package/src/Core/components/abstract/BooleanBaseOperator.js +88 -0
  333. package/src/Core/components/abstract/BooleanBaseOperatorOfMath.js +100 -0
  334. package/src/Core/components/abstract/BooleanBaseOperatorOneInput.js +44 -0
  335. package/src/Core/components/abstract/ComponentSize.js +789 -0
  336. package/src/Core/components/abstract/ComponentWithSelectableType.js +537 -0
  337. package/src/Core/components/abstract/CompositeComponent.js +142 -0
  338. package/src/Core/components/abstract/ConstraintComponent.js +19 -0
  339. package/src/Core/components/abstract/FunctionBaseOperator.js +680 -0
  340. package/src/Core/components/abstract/GraphicalComponent.js +56 -0
  341. package/src/Core/components/abstract/InlineComponent.js +5 -0
  342. package/src/Core/components/abstract/InlineRenderInlineChildren.js +63 -0
  343. package/src/Core/components/abstract/Input.js +192 -0
  344. package/src/Core/components/abstract/IntervalListComponent.js +218 -0
  345. package/src/Core/components/abstract/LineListComponent.js +114 -0
  346. package/src/Core/components/abstract/MathBaseOperator.js +631 -0
  347. package/src/Core/components/abstract/MathBaseOperatorOneInput.js +112 -0
  348. package/src/Core/components/abstract/PointListComponent.js +238 -0
  349. package/src/Core/components/abstract/SectioningComponent.js +1262 -0
  350. package/src/Core/components/abstract/SingleCharacterInline.js +23 -0
  351. package/src/Core/components/abstract/TextBaseOperatorOfMath.js +47 -0
  352. package/src/Core/components/abstract/TextOrInline.js +66 -0
  353. package/src/Core/components/abstract/VariableName.js +31 -0
  354. package/src/Core/components/abstract/VariableNameList.js +83 -0
  355. package/src/Core/components/abstract/VectorListComponent.js +235 -0
  356. package/src/Core/components/chemistry/Atom.js +910 -0
  357. package/src/Core/components/chemistry/ElectronConfiguration.js +36 -0
  358. package/src/Core/components/chemistry/Ion.js +684 -0
  359. package/src/Core/components/chemistry/IonicCompound.js +189 -0
  360. package/src/Core/components/chemistry/OrbitalDiagram.js +175 -0
  361. package/src/Core/components/chemistry/OrbitalDiagramInput.js +753 -0
  362. package/src/Core/components/chemistry/index.js +6 -0
  363. package/src/Core/components/commonsugar/breakstrings.js +627 -0
  364. package/src/Core/components/commonsugar/lists.js +177 -0
  365. package/src/Core/components/dynamicalSystems/CobwebPolyline.js +913 -0
  366. package/src/Core/components/dynamicalSystems/EquilibriumCurve.js +95 -0
  367. package/src/Core/components/dynamicalSystems/EquilibriumLine.js +93 -0
  368. package/src/Core/components/dynamicalSystems/EquilibriumPoint.js +93 -0
  369. package/src/Core/components/dynamicalSystems/ODESystem.js +943 -0
  370. package/src/Core/components/dynamicalSystems/index.js +5 -0
  371. package/src/Core/components/linearAlgebra/EigenDecomposition.js +294 -0
  372. package/src/Core/utils/array.js +30 -0
  373. package/src/Core/utils/booleanLogic.js +965 -0
  374. package/src/Core/utils/checkEquality.js +818 -0
  375. package/src/Core/utils/cid.js +29 -0
  376. package/src/Core/utils/componentInfoObjects.js +100 -0
  377. package/src/Core/utils/constraints.js +23 -0
  378. package/src/Core/utils/copy.js +572 -0
  379. package/src/Core/utils/deepFunctions.js +173 -0
  380. package/src/Core/utils/descendants.js +252 -0
  381. package/src/Core/utils/enumeration.js +234 -0
  382. package/src/Core/utils/feedback.js +84 -0
  383. package/src/Core/utils/function.js +1343 -0
  384. package/src/Core/utils/graphical.js +196 -0
  385. package/src/Core/utils/label.js +396 -0
  386. package/src/Core/utils/math.js +1056 -0
  387. package/src/Core/utils/naming.js +45 -0
  388. package/src/Core/utils/periodicSetEquality.js +403 -0
  389. package/src/Core/utils/randomNumbers.js +70 -0
  390. package/src/Core/utils/retrieveMedia.js +98 -0
  391. package/src/Core/utils/retrieveTextFile.js +140 -0
  392. package/src/Core/utils/returnAllPossibleVariants.js +73 -0
  393. package/src/Core/utils/rounding.js +316 -0
  394. package/src/Core/utils/sequence.js +754 -0
  395. package/src/Core/utils/serializedStateProcessing.js +4049 -0
  396. package/src/Core/utils/size.js +22 -0
  397. package/src/Core/utils/stateVariables.js +138 -0
  398. package/src/Core/utils/style.js +535 -0
  399. package/src/Core/utils/subset-of-reals.js +796 -0
  400. package/src/Core/utils/table.js +41 -0
  401. package/src/Core/utils/text.js +16 -0
  402. package/src/Core/utils/triggering.js +167 -0
  403. package/src/Core/utils/variants.js +477 -0
  404. package/src/DoenetML.css +308 -0
  405. package/src/DoenetML.jsx +201 -0
  406. package/src/Parser/doenet.grammar +90 -0
  407. package/src/Parser/doenet.js +33 -0
  408. package/src/Parser/doenet.terms.js +20 -0
  409. package/src/Parser/parser.js +266 -0
  410. package/src/Parser/tokens.js +129 -0
  411. package/src/Tools/CodeMirror.jsx +440 -0
  412. package/src/Tools/DarkmodeController.jsx +21 -0
  413. package/src/Tools/Footers/MathInputSelector.jsx +34 -0
  414. package/src/Tools/Footers/VirtualKeyboard.jsx +751 -0
  415. package/src/Tools/cypressTest/CypressTest.jsx +341 -0
  416. package/src/Tools/cypressTest/index.html +102 -0
  417. package/src/Tools/cypressTest/index.jsx +40 -0
  418. package/src/Viewer/ActivityViewer.jsx +1461 -0
  419. package/src/Viewer/PageViewer.jsx +1329 -0
  420. package/src/Viewer/renderers/alert.jsx +17 -0
  421. package/src/Viewer/renderers/angle.jsx +209 -0
  422. package/src/Viewer/renderers/answer.jsx +206 -0
  423. package/src/Viewer/renderers/asList.jsx +25 -0
  424. package/src/Viewer/renderers/blockQuote.jsx +41 -0
  425. package/src/Viewer/renderers/boolean.jsx +17 -0
  426. package/src/Viewer/renderers/booleanInput.css +105 -0
  427. package/src/Viewer/renderers/booleanInput.jsx +636 -0
  428. package/src/Viewer/renderers/button.jsx +369 -0
  429. package/src/Viewer/renderers/c.jsx +17 -0
  430. package/src/Viewer/renderers/callAction.jsx +18 -0
  431. package/src/Viewer/renderers/cell.jsx +59 -0
  432. package/src/Viewer/renderers/chart.jsx +83 -0
  433. package/src/Viewer/renderers/choiceInput.css +223 -0
  434. package/src/Viewer/renderers/choiceInput.jsx +535 -0
  435. package/src/Viewer/renderers/circle.jsx +990 -0
  436. package/src/Viewer/renderers/cobwebPolyline.jsx +442 -0
  437. package/src/Viewer/renderers/codeEditor.jsx +248 -0
  438. package/src/Viewer/renderers/codeViewer.jsx +105 -0
  439. package/src/Viewer/renderers/containerBlock.jsx +41 -0
  440. package/src/Viewer/renderers/containerInline.jsx +17 -0
  441. package/src/Viewer/renderers/contentBrowser.jsx +159 -0
  442. package/src/Viewer/renderers/contentPicker.jsx +160 -0
  443. package/src/Viewer/renderers/curve.jsx +1072 -0
  444. package/src/Viewer/renderers/ellipsis.jsx +17 -0
  445. package/src/Viewer/renderers/em.jsx +17 -0
  446. package/src/Viewer/renderers/embed.jsx +110 -0
  447. package/src/Viewer/renderers/feedback.jsx +74 -0
  448. package/src/Viewer/renderers/figure.jsx +131 -0
  449. package/src/Viewer/renderers/footnote.jsx +52 -0
  450. package/src/Viewer/renderers/graph.jsx +925 -0
  451. package/src/Viewer/renderers/hint.jsx +142 -0
  452. package/src/Viewer/renderers/image.jsx +581 -0
  453. package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs +2 -0
  454. package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs.map +1 -0
  455. package/src/Viewer/renderers/label.jsx +470 -0
  456. package/src/Viewer/renderers/legend.jsx +306 -0
  457. package/src/Viewer/renderers/line.jsx +511 -0
  458. package/src/Viewer/renderers/lineSegment.jsx +754 -0
  459. package/src/Viewer/renderers/list.jsx +111 -0
  460. package/src/Viewer/renderers/lq.jsx +12 -0
  461. package/src/Viewer/renderers/lsq.jsx +12 -0
  462. package/src/Viewer/renderers/math.jsx +582 -0
  463. package/src/Viewer/renderers/mathInput.css +10 -0
  464. package/src/Viewer/renderers/mathInput.jsx +425 -0
  465. package/src/Viewer/renderers/mathInputog.jsx +534 -0
  466. package/src/Viewer/renderers/mathList.jsx +39 -0
  467. package/src/Viewer/renderers/matrixInput.jsx +317 -0
  468. package/src/Viewer/renderers/mdash.jsx +12 -0
  469. package/src/Viewer/renderers/nbsp.jsx +12 -0
  470. package/src/Viewer/renderers/ndash.jsx +12 -0
  471. package/src/Viewer/renderers/number.jsx +454 -0
  472. package/src/Viewer/renderers/numberList.jsx +35 -0
  473. package/src/Viewer/renderers/orbitalDiagram.jsx +247 -0
  474. package/src/Viewer/renderers/orbitalDiagramInput.jsx +450 -0
  475. package/src/Viewer/renderers/p.jsx +38 -0
  476. package/src/Viewer/renderers/paginatorControls.jsx +41 -0
  477. package/src/Viewer/renderers/pegboard.jsx +239 -0
  478. package/src/Viewer/renderers/point.jsx +649 -0
  479. package/src/Viewer/renderers/polygon.jsx +612 -0
  480. package/src/Viewer/renderers/polyline.jsx +608 -0
  481. package/src/Viewer/renderers/pre.jsx +34 -0
  482. package/src/Viewer/renderers/q.jsx +17 -0
  483. package/src/Viewer/renderers/ray.jsx +410 -0
  484. package/src/Viewer/renderers/ref.jsx +149 -0
  485. package/src/Viewer/renderers/regionBetweenCurveXAxis.jsx +182 -0
  486. package/src/Viewer/renderers/renderDoenetML.jsx +56 -0
  487. package/src/Viewer/renderers/row.jsx +31 -0
  488. package/src/Viewer/renderers/rq.jsx +12 -0
  489. package/src/Viewer/renderers/rsq.jsx +12 -0
  490. package/src/Viewer/renderers/section.jsx +427 -0
  491. package/src/Viewer/renderers/sideBySide.jsx +80 -0
  492. package/src/Viewer/renderers/slider.jsx +800 -0
  493. package/src/Viewer/renderers/solution.jsx +134 -0
  494. package/src/Viewer/renderers/spreadsheet.jsx +83 -0
  495. package/src/Viewer/renderers/sq.jsx +17 -0
  496. package/src/Viewer/renderers/styles/global.css +14 -0
  497. package/src/Viewer/renderers/subsetOfRealsInput.jsx +392 -0
  498. package/src/Viewer/renderers/summaryStatistics.jsx +83 -0
  499. package/src/Viewer/renderers/table.jsx +78 -0
  500. package/src/Viewer/renderers/tabular.jsx +58 -0
  501. package/src/Viewer/renderers/tag.jsx +26 -0
  502. package/src/Viewer/renderers/text.jsx +439 -0
  503. package/src/Viewer/renderers/textInput.jsx +774 -0
  504. package/src/Viewer/renderers/textList.jsx +30 -0
  505. package/src/Viewer/renderers/triggerSet.jsx +52 -0
  506. package/src/Viewer/renderers/updateValue.jsx +30 -0
  507. package/src/Viewer/renderers/utils/css.js +13 -0
  508. package/src/Viewer/renderers/utils/graph.js +159 -0
  509. package/src/Viewer/renderers/utils/offGraphIndicators.js +91 -0
  510. package/src/Viewer/renderers/vector.jsx +678 -0
  511. package/src/Viewer/renderers/video.jsx +494 -0
  512. package/src/Viewer/useDoenetRenderer.jsx +128 -0
  513. package/src/main.jsx +16 -0
  514. package/src/media/fonts/files/open-sans-v18-latin-700.woff +0 -0
  515. package/src/media/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
  516. package/src/media/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
  517. package/src/media/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
  518. package/src/media/fonts/files/open-sans-v18-latin-italic.woff +0 -0
  519. package/src/media/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
  520. package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
  521. package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
  522. package/src/media/fonts/files/open-sans-v18-latin-light.woff +0 -0
  523. package/src/media/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
  524. package/src/media/fonts/files/open-sans-v18-latin-regular.woff +0 -0
  525. package/src/media/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
  526. package/src/test/testCode.doenet +26 -0
  527. package/src/test/testViewer.jsx +158 -0
  528. package/src/uiComponents/ActionButton.jsx +157 -0
  529. package/src/uiComponents/ActionButtonGroup.jsx +93 -0
  530. package/src/uiComponents/Button.jsx +160 -0
  531. package/src/uiComponents/ButtonGroup.jsx +56 -0
  532. package/src/uiComponents/ToggleButton.jsx +194 -0
  533. package/src/uiComponents/ToggleButtonGroup.jsx +77 -0
  534. package/src/utils/activityUtils.js +713 -0
  535. package/src/utils/array.js +17 -0
  536. package/src/utils/cid.js +34 -0
  537. package/src/utils/componentInfoObjects.js +89 -0
  538. package/src/utils/deepFunctions.js +165 -0
  539. package/src/utils/enumeration.js +226 -0
  540. package/src/utils/math.js +624 -0
  541. package/src/utils/naming.js +44 -0
  542. package/src/utils/retrieveTextFile.js +156 -0
  543. package/src/utils/returnAllPossibleVariants.js +81 -0
  544. package/src/utils/sequence.js +715 -0
  545. package/src/utils/serialize.js +29 -0
  546. package/src/utils/serializedStateProcessing.js +2587 -0
  547. package/src/utils/subset-of-reals.js +783 -0
  548. package/src/utils/url.js +19 -0
  549. package/vite.config.js +14 -0
@@ -0,0 +1,1329 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import { nanoid } from "nanoid";
3
+ import {
4
+ serializedComponentsReplacer,
5
+ serializedComponentsReviver,
6
+ } from "../Core/utils/serializedStateProcessing";
7
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
8
+ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons";
9
+ import { rendererState } from "./useDoenetRenderer";
10
+ import { atom, atomFamily, useRecoilCallback, useRecoilValue } from "recoil";
11
+ import { get as idb_get, set as idb_set } from "idb-keyval";
12
+ import { cidFromText } from "../Core/utils/cid";
13
+ import { retrieveTextFileForCid } from "../Core/utils/retrieveTextFile";
14
+ import axios from "axios";
15
+ import { returnAllPossibleVariants } from "../Core/utils/returnAllPossibleVariants";
16
+ import { darkModeAtom } from "../Tools/DarkmodeController";
17
+ import { cesc } from "../utils/url";
18
+
19
+ const rendererUpdatesToIgnore = atomFamily({
20
+ key: "rendererUpdatesToIgnore",
21
+ default: {},
22
+ });
23
+
24
+ export const scrollableContainerAtom = atom({
25
+ key: "scollParentAtom",
26
+ default: null,
27
+ });
28
+
29
+ const sendAlert = (msg, type) => console.log(msg);
30
+
31
+ // Two notes about props.flags of PageViewer
32
+ // 1. In Core, flags.allowSaveState implies flags.allowLoadState
33
+ // Rationale: saving state will result in loading a new state if another device changed it,
34
+ // so having allowLoadState false in that case would lead to inconsistent behavior
35
+ // 2. In Core, if props.userId is defined, both
36
+ // flags.allowLocalState and flags.allowSaveState are set to false
37
+
38
+ export default function PageViewer(props) {
39
+ const updateRendererSVsWithRecoil = useRecoilCallback(
40
+ ({ snapshot, set }) =>
41
+ async ({
42
+ coreId,
43
+ componentName,
44
+ stateValues,
45
+ childrenInstructions,
46
+ sourceOfUpdate,
47
+ baseStateVariable,
48
+ actionId,
49
+ }) => {
50
+ let ignoreUpdate = false;
51
+
52
+ let rendererName = coreId + componentName;
53
+
54
+ if (baseStateVariable) {
55
+ let updatesToIgnore = snapshot.getLoadable(
56
+ rendererUpdatesToIgnore(rendererName),
57
+ ).contents;
58
+
59
+ if (Object.keys(updatesToIgnore).length > 0) {
60
+ let valueFromRenderer = updatesToIgnore[actionId];
61
+ let valueFromCore = stateValues[baseStateVariable];
62
+ if (
63
+ valueFromRenderer === valueFromCore ||
64
+ (Array.isArray(valueFromRenderer) &&
65
+ Array.isArray(valueFromCore) &&
66
+ valueFromRenderer.length == valueFromCore.length &&
67
+ valueFromRenderer.every((v, i) => valueFromCore[i] === v))
68
+ ) {
69
+ // console.log(`ignoring update of ${componentName} to ${valueFromCore}`)
70
+ ignoreUpdate = true;
71
+ set(rendererUpdatesToIgnore(rendererName), (was) => {
72
+ let newUpdatesToIgnore = { ...was };
73
+ delete newUpdatesToIgnore[actionId];
74
+ return newUpdatesToIgnore;
75
+ });
76
+ } else {
77
+ // since value was changed from the time the update was created
78
+ // don't ignore the remaining pending changes in updatesToIgnore
79
+ // as we changed the state used to determine they could be ignored
80
+ set(rendererUpdatesToIgnore(rendererName), {});
81
+ }
82
+ }
83
+ }
84
+
85
+ let newRendererState = {
86
+ stateValues,
87
+ childrenInstructions,
88
+ sourceOfUpdate,
89
+ ignoreUpdate,
90
+ prefixForIds: prefixForIds,
91
+ };
92
+
93
+ if (childrenInstructions === undefined) {
94
+ let previousRendererState = snapshot.getLoadable(
95
+ rendererState(rendererName),
96
+ ).contents;
97
+ newRendererState.childrenInstructions =
98
+ previousRendererState.childrenInstructions;
99
+ }
100
+
101
+ set(rendererState(rendererName), newRendererState);
102
+ },
103
+ );
104
+ const updateRendererUpdatesToIgnore = useRecoilCallback(
105
+ ({ snapshot, set }) =>
106
+ async ({ coreId, componentName, baseVariableValue, actionId }) => {
107
+ let rendererName = coreId + componentName;
108
+
109
+ // add to updates to ignore so don't apply change again
110
+ // if it comes back from core without any changes
111
+ // (possibly after a delay)
112
+ set(rendererUpdatesToIgnore(rendererName), (was) => {
113
+ let newUpdatesToIgnore = { ...was };
114
+ newUpdatesToIgnore[actionId] = baseVariableValue;
115
+ return newUpdatesToIgnore;
116
+ });
117
+ },
118
+ );
119
+
120
+ const [errMsg, setErrMsg] = useState(null);
121
+
122
+ const [cidFromProps, setCidFromProps] = useState(null);
123
+ const [doenetMLFromProps, setDoenetMLFromProps] = useState(null);
124
+ const [cid, setCid] = useState(null);
125
+ const [doenetML, setDoenetML] = useState(null);
126
+
127
+ const [pageNumber, setPageNumber] = useState(null);
128
+ const [attemptNumber, setAttemptNumber] = useState(null);
129
+ const [requestedVariantIndex, setRequestedVariantIndex] = useState(null);
130
+
131
+ const [stage, setStage] = useState("initial");
132
+ const [pageContentChanged, setPageContentChanged] = useState(false);
133
+
134
+ const [documentRenderer, setDocumentRenderer] = useState(null);
135
+
136
+ const initialCoreData = useRef({});
137
+
138
+ const rendererClasses = useRef({});
139
+ const coreInfo = useRef(null);
140
+ const coreCreated = useRef(false);
141
+ const coreId = useRef(null);
142
+
143
+ const resolveAllStateVariables = useRef(null);
144
+ const actionsBeforeCoreCreated = useRef([]);
145
+
146
+ const coreWorker = useRef(null);
147
+
148
+ const preventMoreAnimations = useRef(false);
149
+ const animationInfo = useRef({});
150
+
151
+ const resolveActionPromises = useRef({});
152
+
153
+ const prefixForIds = props.prefixForIds || "";
154
+
155
+ const previousLocationKeys = useRef([]);
156
+
157
+ const errorInitializingRenderers = useRef(false);
158
+ const errorInsideRenderers = useRef(false);
159
+
160
+ const [ignoreRendererError, setIgnoreRendererError] = useState(false);
161
+
162
+ const darkMode = useRecoilValue(darkModeAtom);
163
+
164
+ // const scrollableContainer = useRecoilValue(scrollableContainerAtom);
165
+
166
+ let navigate = props.navigate;
167
+
168
+ let location = props.location || {};
169
+ let hash = location.hash;
170
+
171
+ useEffect(() => {
172
+ if (coreWorker.current) {
173
+ coreWorker.current.onmessage = function (e) {
174
+ // console.log('message from core', e.data)
175
+ if (e.data.messageType === "updateRenderers") {
176
+ if (
177
+ e.data.init &&
178
+ coreInfo.current &&
179
+ !errorInitializingRenderers.current &&
180
+ !errorInsideRenderers.current
181
+ ) {
182
+ // we don't initialize renderer state values if already have a coreInfo
183
+ // and no errors were encountered
184
+ // as we must have already gotten the renderer information before core was created
185
+ } else {
186
+ updateRenderers(e.data.args);
187
+ if (errorInsideRenderers.current) {
188
+ setIgnoreRendererError(true);
189
+ props.setIsInErrorState?.(false);
190
+ }
191
+ }
192
+ } else if (e.data.messageType === "requestAnimationFrame") {
193
+ requestAnimationFrame(e.data.args);
194
+ } else if (e.data.messageType === "cancelAnimationFrame") {
195
+ cancelAnimationFrame(e.data.args);
196
+ } else if (e.data.messageType === "coreCreated") {
197
+ coreCreated.current = true;
198
+ preventMoreAnimations.current = false;
199
+ setStage("coreCreated");
200
+ props.coreCreatedCallback?.(coreWorker.current);
201
+ } else if (e.data.messageType === "initializeRenderers") {
202
+ if (
203
+ coreInfo.current &&
204
+ JSON.stringify(coreInfo.current) ===
205
+ JSON.stringify(e.data.args.coreInfo) &&
206
+ !errorInitializingRenderers.current &&
207
+ !errorInsideRenderers.current
208
+ ) {
209
+ // we already initialized renderers before core was created and no errors were encountered
210
+ // so don't initialize them again when core sends the initializeRenderers message
211
+ } else {
212
+ initializeRenderers(e.data.args);
213
+ if (errorInsideRenderers.current) {
214
+ setIgnoreRendererError(true);
215
+ props.setIsInErrorState?.(false);
216
+ }
217
+ }
218
+ } else if (e.data.messageType === "updateCreditAchieved") {
219
+ props.updateCreditAchievedCallback?.(e.data.args);
220
+ } else if (e.data.messageType === "savedState") {
221
+ props.saveStateCallback?.();
222
+ } else if (e.data.messageType === "sendAlert") {
223
+ console.log(`Sending alert message: ${e.data.args.message}`);
224
+ sendAlert(e.data.args.message, e.data.args.alertType);
225
+ } else if (e.data.messageType === "resolveAction") {
226
+ resolveAction(e.data.args);
227
+ } else if (e.data.messageType === "returnAllStateVariables") {
228
+ console.log(e.data.args);
229
+ resolveAllStateVariables.current(e.data.args);
230
+ } else if (e.data.messageType === "componentRangePieces") {
231
+ window["componentRangePieces" + pageNumber] =
232
+ e.data.args.componentRangePieces;
233
+ } else if (e.data.messageType === "inErrorState") {
234
+ if (props.setIsInErrorState) {
235
+ props.setIsInErrorState(true);
236
+ }
237
+ setErrMsg(e.data.args.errMsg);
238
+ } else if (e.data.messageType === "resetPage") {
239
+ resetPage(e.data.args);
240
+ } else if (e.data.messageType === "copyToClipboard") {
241
+ copyToClipboard(e.data.args);
242
+ } else if (e.data.messageType === "navigateToTarget") {
243
+ navigateToTarget(e.data.args);
244
+ } else if (e.data.messageType === "terminated") {
245
+ terminateCoreAndAnimations();
246
+ }
247
+ };
248
+ }
249
+ }, [coreWorker.current]);
250
+
251
+ useEffect(() => {
252
+ return () => {
253
+ if (coreWorker.current) {
254
+ coreWorker.current.postMessage({
255
+ messageType: "terminate",
256
+ });
257
+ }
258
+ };
259
+ }, []);
260
+
261
+ useEffect(() => {
262
+ if (pageNumber !== null) {
263
+ window["returnAllStateVariables" + pageNumber] = function () {
264
+ coreWorker.current.postMessage({
265
+ messageType: "returnAllStateVariables",
266
+ });
267
+
268
+ return new Promise((resolve, reject) => {
269
+ resolveAllStateVariables.current = resolve;
270
+ });
271
+ };
272
+
273
+ window["callAction" + pageNumber] = async function ({
274
+ actionName,
275
+ componentName,
276
+ args,
277
+ }) {
278
+ await callAction({
279
+ action: { actionName, componentName },
280
+ args,
281
+ });
282
+ };
283
+ }
284
+ }, [pageNumber]);
285
+
286
+ useEffect(() => {
287
+ return () => {
288
+ preventMoreAnimations.current = true;
289
+ for (let id in animationInfo.current) {
290
+ cancelAnimationFrame(id);
291
+ }
292
+ animationInfo.current = {};
293
+ };
294
+ }, []);
295
+
296
+ useEffect(() => {
297
+ document.addEventListener("visibilitychange", () => {
298
+ if (coreWorker.current) {
299
+ coreWorker.current.postMessage({
300
+ messageType: "visibilityChange",
301
+ args: {
302
+ visible: document.visibilityState === "visible",
303
+ },
304
+ });
305
+ }
306
+ });
307
+ }, []);
308
+
309
+ useEffect(() => {
310
+ if (hash && coreCreated.current && coreWorker.current) {
311
+ let anchor = hash.slice(1);
312
+ if (anchor.substring(0, prefixForIds.length) === prefixForIds) {
313
+ coreWorker.current.postMessage({
314
+ messageType: "navigatingToComponent",
315
+ args: {
316
+ componentName: anchor
317
+ .substring(prefixForIds.length)
318
+ .replaceAll("\\/", "/"),
319
+ },
320
+ });
321
+ }
322
+ }
323
+ }, [location, hash, coreCreated.current, coreWorker.current]);
324
+
325
+ useEffect(() => {
326
+ if (hash && documentRenderer && props.pageIsActive) {
327
+ let anchor = hash.slice(1);
328
+ if (
329
+ (!previousLocationKeys.current.includes(location.key) ||
330
+ location.key === "default") &&
331
+ anchor.length > prefixForIds.length &&
332
+ anchor.substring(0, prefixForIds.length) === prefixForIds
333
+ ) {
334
+ document.getElementById(anchor)?.scrollIntoView();
335
+ }
336
+ previousLocationKeys.current.push(location.key);
337
+ }
338
+ }, [location, hash, documentRenderer, props.pageIsActive]);
339
+
340
+ useEffect(() => {
341
+ callAction({
342
+ action: { actionName: "setTheme" },
343
+ args: { theme: darkMode },
344
+ });
345
+ }, [darkMode]);
346
+
347
+ function terminateCoreAndAnimations() {
348
+ preventMoreAnimations.current = true;
349
+ coreWorker.current.terminate();
350
+ coreWorker.current = null;
351
+ for (let id in animationInfo.current) {
352
+ cancelAnimationFrame(id);
353
+ }
354
+ animationInfo.current = {};
355
+ }
356
+
357
+ async function callAction({
358
+ action,
359
+ args,
360
+ baseVariableValue,
361
+ componentName,
362
+ rendererType,
363
+ }) {
364
+ let ignoreActionsWithoutCore =
365
+ rendererClasses.current[rendererType]?.ignoreActionsWithoutCore ||
366
+ rendererClasses.current[rendererType]?.type?.ignoreActionsWithoutCore;
367
+ if (coreCreated.current || !ignoreActionsWithoutCore?.(action.actionName)) {
368
+ let actionId = nanoid();
369
+ args = { ...args };
370
+ args.actionId = actionId;
371
+
372
+ if (baseVariableValue !== undefined && componentName) {
373
+ updateRendererUpdatesToIgnore({
374
+ coreId: coreId.current,
375
+ componentName,
376
+ baseVariableValue,
377
+ actionId,
378
+ });
379
+ }
380
+
381
+ let actionArgs = {
382
+ actionName: action.actionName,
383
+ componentName: action.componentName,
384
+ args,
385
+ };
386
+
387
+ // Note: it is possible that core has been terminated
388
+ coreWorker.current?.postMessage({
389
+ messageType: "requestAction",
390
+ args: actionArgs,
391
+ });
392
+
393
+ if (!coreCreated.current) {
394
+ actionsBeforeCoreCreated.current.push(actionArgs);
395
+ // console.log('actions before core created', actionsBeforeCoreCreated.current)
396
+ }
397
+
398
+ return new Promise((resolve, reject) => {
399
+ resolveActionPromises.current[actionId] = resolve;
400
+ });
401
+ }
402
+ }
403
+
404
+ function forceRendererState({
405
+ rendererState,
406
+ forceDisable,
407
+ forceShowCorrectness,
408
+ forceShowSolution,
409
+ forceUnsuppressCheckwork,
410
+ }) {
411
+ for (let componentName in rendererState) {
412
+ let stateValues = rendererState[componentName].stateValues;
413
+ if (forceDisable && stateValues.disabled === false) {
414
+ stateValues.disabled = true;
415
+ }
416
+ if (forceShowCorrectness && stateValues.showCorrectness === false) {
417
+ stateValues.showCorrectness = true;
418
+ }
419
+ if (forceUnsuppressCheckwork && stateValues.suppressCheckwork === true) {
420
+ stateValues.suppressCheckwork = false;
421
+ }
422
+ if (
423
+ forceShowSolution &&
424
+ rendererState[componentName].childrenInstructions?.length > 0
425
+ ) {
426
+ // look for a child that has a componentType solution
427
+ for (let childInst of rendererState[componentName]
428
+ .childrenInstructions) {
429
+ if (childInst.componentType === "solution") {
430
+ let solComponentName = childInst.componentName;
431
+ if (rendererState[solComponentName].stateValues.hidden) {
432
+ rendererState[solComponentName].stateValues.hidden = false;
433
+ }
434
+ }
435
+ }
436
+ }
437
+ }
438
+ }
439
+
440
+ function initializeRenderers(args) {
441
+ if (args.rendererState) {
442
+ delete args.rendererState.__componentNeedingUpdateValue;
443
+ if (
444
+ props.forceDisable ||
445
+ props.forceShowCorrectness ||
446
+ props.forceShowSolution ||
447
+ props.forceUnsuppressCheckwork
448
+ ) {
449
+ forceRendererState({ rendererState: args.rendererState, ...props });
450
+ }
451
+ for (let componentName in args.rendererState) {
452
+ updateRendererSVsWithRecoil({
453
+ coreId: coreId.current,
454
+ componentName,
455
+ stateValues: args.rendererState[componentName].stateValues,
456
+ childrenInstructions:
457
+ args.rendererState[componentName].childrenInstructions,
458
+ });
459
+ }
460
+ }
461
+
462
+ coreInfo.current = args.coreInfo;
463
+
464
+ if (props.generatedVariantCallback) {
465
+ props.generatedVariantCallback({
466
+ pageVariant: {
467
+ variantInfo: JSON.parse(
468
+ coreInfo.current.generatedVariantString,
469
+ serializedComponentsReviver,
470
+ ),
471
+ allPossibleVariants: coreInfo.current.allPossibleVariants,
472
+ itemNumber: props.itemNumber,
473
+ },
474
+ });
475
+ }
476
+
477
+ let renderPromises = [];
478
+ let rendererClassNames = [];
479
+ // console.log('rendererTypesInDocument');
480
+ // console.log(">>>core.rendererTypesInDocument",core.rendererTypesInDocument);
481
+ for (let rendererClassName of coreInfo.current.rendererTypesInDocument) {
482
+ rendererClassNames.push(rendererClassName);
483
+ renderPromises.push(import(`./renderers/${rendererClassName}.jsx`));
484
+ }
485
+
486
+ let documentComponentInstructions = coreInfo.current.documentToRender;
487
+
488
+ renderersloadComponent(renderPromises, rendererClassNames)
489
+ .then((newRendererClasses) => {
490
+ rendererClasses.current = newRendererClasses;
491
+ let documentRendererClass =
492
+ newRendererClasses[documentComponentInstructions.rendererType];
493
+
494
+ setDocumentRenderer(
495
+ React.createElement(documentRendererClass, {
496
+ key: coreId.current + documentComponentInstructions.componentName,
497
+ componentInstructions: documentComponentInstructions,
498
+ rendererClasses: newRendererClasses,
499
+ flags: props.flags,
500
+ coreId: coreId.current,
501
+ callAction,
502
+ navigate,
503
+ location
504
+ }),
505
+ );
506
+
507
+ props.renderersInitializedCallback?.();
508
+ })
509
+ .catch((e) => {
510
+ errorInitializingRenderers.current = true;
511
+ });
512
+ }
513
+
514
+ //offscreen then postpone that one
515
+ function updateRenderers({ updateInstructions, actionId }) {
516
+ for (let instruction of updateInstructions) {
517
+ if (instruction.instructionType === "updateRendererStates") {
518
+ for (let {
519
+ componentName,
520
+ stateValues,
521
+ rendererType,
522
+ childrenInstructions,
523
+ } of instruction.rendererStatesToUpdate) {
524
+ updateRendererSVsWithRecoil({
525
+ coreId: coreId.current,
526
+ componentName,
527
+ stateValues,
528
+ childrenInstructions,
529
+ sourceOfUpdate: instruction.sourceOfUpdate,
530
+ baseStateVariable:
531
+ rendererClasses.current[rendererType]?.baseStateVariable ||
532
+ rendererClasses.current[rendererType]?.type?.baseStateVariable,
533
+ actionId,
534
+ });
535
+ }
536
+ }
537
+ }
538
+
539
+ resolveAction({ actionId });
540
+ }
541
+
542
+ function resolveAction({ actionId }) {
543
+ if (actionId) {
544
+ resolveActionPromises.current[actionId]?.();
545
+ delete resolveActionPromises.current[actionId];
546
+ }
547
+ }
548
+
549
+ function resetPage({ changedOnDevice, newCid, newAttemptNumber }) {
550
+ // console.log('resetPage', changedOnDevice, newCid, newAttemptNumber);
551
+
552
+ if (newAttemptNumber !== attemptNumber) {
553
+ sendAlert(
554
+ `Reverted activity as attempt number changed on other device`,
555
+ "info",
556
+ );
557
+ if (props.updateAttemptNumber) {
558
+ props.updateAttemptNumber(newAttemptNumber);
559
+ } else {
560
+ // what do we do in this case?
561
+ if (props.setIsInErrorState) {
562
+ props.setIsInErrorState(true);
563
+ }
564
+ setErrMsg(
565
+ "how to reset attempt number when not given updateAttemptNumber function?",
566
+ );
567
+ }
568
+ } else {
569
+ // TODO: are there cases where will get an infinite loop here?
570
+ sendAlert(
571
+ `Reverted page to state saved on device ${changedOnDevice}`,
572
+ "info",
573
+ );
574
+
575
+ coreId.current = nanoid();
576
+ setPageContentChanged(true);
577
+ }
578
+ }
579
+
580
+ function calculateCidDoenetML() {
581
+ const coreIdWhenCalled = coreId.current;
582
+ // compare with undefined as doenetML could be empty string
583
+ if (doenetMLFromProps !== undefined) {
584
+ if (cidFromProps) {
585
+ // check to see if doenetML matches cid
586
+ cidFromText(doenetMLFromProps).then((calcCid) => {
587
+ //Guard against the possiblity that parameters changed while waiting
588
+
589
+ if (coreIdWhenCalled === coreId.current) {
590
+ if (calcCid === cidFromProps) {
591
+ setDoenetML(doenetMLFromProps);
592
+ setCid(cidFromProps);
593
+ setStage("continue");
594
+ } else {
595
+ if (props.setIsInErrorState) {
596
+ props.setIsInErrorState(true);
597
+ }
598
+ setErrMsg(
599
+ `doenetML did not match specified cid: ${cidFromProps}`,
600
+ );
601
+ }
602
+ }
603
+ });
604
+ } else {
605
+ // if have doenetML and no cid, then calculate cid
606
+ cidFromText(doenetMLFromProps).then((cid) => {
607
+ //Guard against the possiblity that parameters changed while waiting
608
+ if (coreIdWhenCalled === coreId.current) {
609
+ setDoenetML(doenetMLFromProps);
610
+ setCid(cid);
611
+ setStage("continue");
612
+ }
613
+ });
614
+ }
615
+ } else {
616
+ // if don't have doenetML, then retrieve doenetML from cid
617
+
618
+ retrieveTextFileForCid(cidFromProps, "doenet")
619
+ .then((retrievedDoenetML) => {
620
+ //Guard against the possiblity that parameters changed while waiting
621
+
622
+ if (coreIdWhenCalled === coreId.current) {
623
+ setDoenetML(retrievedDoenetML);
624
+ setCid(cidFromProps);
625
+ setStage("continue");
626
+ }
627
+ })
628
+ .catch((e) => {
629
+ //Guard against the possiblity that parameters changed while waiting
630
+
631
+ if (coreIdWhenCalled === coreId.current) {
632
+ if (props.setIsInErrorState) {
633
+ props.setIsInErrorState(true);
634
+ }
635
+ setErrMsg(`doenetML not found for cid: ${cidFromProps}`);
636
+ }
637
+ });
638
+ }
639
+ }
640
+
641
+ async function loadStateAndInitialize() {
642
+ const coreIdWhenCalled = coreId.current;
643
+ let loadedState = false;
644
+
645
+ if (props.flags.allowLocalState) {
646
+ let localInfo;
647
+
648
+ try {
649
+ localInfo = await idb_get(
650
+ `${props.activityId}|${pageNumber}|${attemptNumber}|${cid}`,
651
+ );
652
+ } catch (e) {
653
+ // ignore error
654
+ }
655
+
656
+ if (localInfo) {
657
+ if (props.flags.allowSaveState) {
658
+ // attempt to save local info to database,
659
+ // reseting data to that from database if it has changed since last save
660
+
661
+ let result = await saveLoadedLocalStateToDatabase(localInfo);
662
+
663
+ if (result.changedOnDevice) {
664
+ if (Number(result.newAttemptNumber) !== attemptNumber) {
665
+ resetPage({
666
+ changedOnDevice: result.changedOnDevice,
667
+ newCid: result.newCid,
668
+ newAttemptNumber: Number(result.newAttemptNumber),
669
+ });
670
+ return;
671
+ } else if (result.newCid !== cid) {
672
+ // if cid changes for the same attempt number, then something went wrong
673
+ if (props.setIsInErrorState) {
674
+ props.setIsInErrorState(true);
675
+ }
676
+ setErrMsg(`content changed unexpectedly!`);
677
+ }
678
+
679
+ // if just the localInfo changed, use that instead
680
+ localInfo = result.newLocalInfo;
681
+ console.log(
682
+ `sending alert: Reverted page to state saved on device ${result.changedOnDevice}`,
683
+ );
684
+ sendAlert(
685
+ `Reverted page to state saved on device ${result.changedOnDevice}`,
686
+ "info",
687
+ );
688
+ }
689
+ }
690
+
691
+ if (localInfo.rendererState.__componentNeedingUpdateValue) {
692
+ callAction({
693
+ action: {
694
+ actionName: "updateValue",
695
+ componentName:
696
+ localInfo.rendererState.__componentNeedingUpdateValue,
697
+ },
698
+ });
699
+ }
700
+
701
+ initializeRenderers({
702
+ rendererState: localInfo.rendererState,
703
+ coreInfo: localInfo.coreInfo,
704
+ });
705
+
706
+ initialCoreData.current = {
707
+ coreState: localInfo.coreState,
708
+ serverSaveId: localInfo.saveId,
709
+ requestedVariant: JSON.parse(
710
+ localInfo.coreInfo.generatedVariantString,
711
+ serializedComponentsReviver,
712
+ ),
713
+ };
714
+
715
+ loadedState = true;
716
+ }
717
+ }
718
+
719
+ if (!loadedState && props.apiURLs?.loadPageState) {
720
+ // if didn't load state from local storage, try to load from database
721
+
722
+ // even if allowLoadState is false,
723
+ // still call loadPageState, in which case it will only retrieve the initial page state
724
+
725
+ const payload = {
726
+ params: {
727
+ cid,
728
+ pageNumber,
729
+ attemptNumber,
730
+ activityId: props.activityId,
731
+ userId: props.userId,
732
+ requestedVariantIndex,
733
+ allowLoadState: props.flags.allowLoadState,
734
+ showCorrectness: props.flags.showCorrectness,
735
+ solutionDisplayMode: props.flags.solutionDisplayMode,
736
+ showFeedback: props.flags.showFeedback,
737
+ showHints: props.flags.showHints,
738
+ autoSubmit: props.flags.autoSubmit,
739
+ },
740
+ };
741
+
742
+ try {
743
+ let resp = await axios.get(props.apiURLs.loadPageState, payload);
744
+ if (!resp.data.success) {
745
+ if (props.flags.allowLoadState) {
746
+ if (props.setIsInErrorState) {
747
+ props.setIsInErrorState(true);
748
+ }
749
+ setErrMsg(`Error loading page state: ${resp.data.message}`);
750
+ return;
751
+ } else {
752
+ // ignore this error if didn't allow loading of page state
753
+ }
754
+ }
755
+
756
+ if (resp.data.loadedState) {
757
+ let coreInfo = JSON.parse(
758
+ resp.data.coreInfo,
759
+ serializedComponentsReviver,
760
+ );
761
+
762
+ let rendererState = JSON.parse(
763
+ resp.data.rendererState,
764
+ serializedComponentsReviver,
765
+ );
766
+
767
+ if (rendererState.__componentNeedingUpdateValue) {
768
+ callAction({
769
+ action: {
770
+ actionName: "updateValue",
771
+ componentName: rendererState.__componentNeedingUpdateValue,
772
+ },
773
+ });
774
+ }
775
+
776
+ initializeRenderers({
777
+ rendererState,
778
+ coreInfo,
779
+ });
780
+
781
+ initialCoreData.current = {
782
+ coreState: JSON.parse(
783
+ resp.data.coreState,
784
+ serializedComponentsReviver,
785
+ ),
786
+ serverSaveId: resp.data.saveId,
787
+ requestedVariant: JSON.parse(
788
+ coreInfo.generatedVariantString,
789
+ serializedComponentsReviver,
790
+ ),
791
+ };
792
+ }
793
+ } catch (e) {
794
+ if (props.flags.allowLoadState) {
795
+ if (props.setIsInErrorState) {
796
+ props.setIsInErrorState(true);
797
+ }
798
+ setErrMsg(`Error loading page state: ${e.message}`);
799
+ return;
800
+ } else {
801
+ // ignore this error if didn't allow loading of page state
802
+ }
803
+ }
804
+ }
805
+
806
+ //Guard against the possiblity that parameters changed while waiting
807
+ if (coreIdWhenCalled === coreId.current) {
808
+ if (props.pageIsActive) {
809
+ startCore();
810
+ } else {
811
+ setStage("readyToCreateCore");
812
+ }
813
+ }
814
+ }
815
+
816
+ async function saveLoadedLocalStateToDatabase(localInfo) {
817
+ if (!props.flags.allowSaveState || !props.apiURLs?.savePageState) {
818
+ return;
819
+ }
820
+
821
+ let serverSaveId = await idb_get(
822
+ `${props.activityId}|${pageNumber}|${attemptNumber}|${cid}|ServerSaveId`,
823
+ );
824
+
825
+ let pageStateToBeSavedToDatabase = {
826
+ cid,
827
+ coreInfo: JSON.stringify(
828
+ localInfo.coreInfo,
829
+ serializedComponentsReplacer,
830
+ ),
831
+ coreState: JSON.stringify(
832
+ localInfo.coreState,
833
+ serializedComponentsReplacer,
834
+ ),
835
+ rendererState: JSON.stringify(
836
+ localInfo.rendererState,
837
+ serializedComponentsReplacer,
838
+ ),
839
+ pageNumber,
840
+ attemptNumber,
841
+ activityId: props.activityId,
842
+ saveId: localInfo.saveId,
843
+ serverSaveId,
844
+ updateDataOnContentChange: props.updateDataOnContentChange,
845
+ };
846
+
847
+ let resp;
848
+
849
+ try {
850
+ resp = await axios.post(
851
+ props.apiURLs.savePageState,
852
+ pageStateToBeSavedToDatabase,
853
+ );
854
+ } catch (e) {
855
+ // since this is initial load, don't show error message
856
+ return { localInfo, cid, attemptNumber };
857
+ }
858
+
859
+ let data = resp.data;
860
+
861
+ if (!data.success) {
862
+ // since this is initial load, don't show error message
863
+ return { localInfo, cid, attemptNumber };
864
+ }
865
+
866
+ await idb_set(
867
+ `${props.activityId}|${pageNumber}|${attemptNumber}|${cid}|ServerSaveId`,
868
+ data.saveId,
869
+ );
870
+
871
+ if (data.stateOverwritten) {
872
+ let newLocalInfo = {
873
+ coreState: JSON.parse(data.coreState, serializedComponentsReviver),
874
+ rendererState: JSON.parse(
875
+ data.rendererState,
876
+ serializedComponentsReviver,
877
+ ),
878
+ coreInfo: JSON.parse(data.coreInfo, serializedComponentsReviver),
879
+ saveId: data.saveId,
880
+ };
881
+
882
+ await idb_set(
883
+ `${props.activityId}|${pageNumber}|${data.attemptNumber}|${data.cid}`,
884
+ newLocalInfo,
885
+ );
886
+
887
+ return {
888
+ changedOnDevice: data.device,
889
+ newLocalInfo,
890
+ newCid: data.cid,
891
+ newAttemptNumber: data.attemptNumber,
892
+ };
893
+ }
894
+
895
+ return { localInfo, cid, attemptNumber };
896
+ }
897
+
898
+ function startCore() {
899
+ //Kill the current core if it exists
900
+ if (coreWorker.current) {
901
+ terminateCoreAndAnimations();
902
+ }
903
+ // console.log(`send message to create core ${pageNumber}`)
904
+ coreWorker.current = new Worker(
905
+ new URL("../Core/CoreWorker.js", import.meta.url),
906
+ { type: "module" },
907
+ );
908
+
909
+ coreWorker.current.postMessage({
910
+ messageType: "createCore",
911
+ args: {
912
+ coreId: coreId.current,
913
+ userId: props.userId,
914
+ doenetML,
915
+ activityId: props.activityId,
916
+ previousComponentTypeCounts: props.previousComponentTypeCounts,
917
+ activityCid: props.activityCid,
918
+ flags: props.flags,
919
+ theme: darkMode,
920
+ requestedVariantIndex,
921
+ pageNumber,
922
+ attemptNumber,
923
+ itemNumber: props.itemNumber,
924
+ updateDataOnContentChange: props.updateDataOnContentChange,
925
+ serverSaveId: initialCoreData.current.serverSaveId,
926
+ activityVariantIndex: props.activityVariantIndex,
927
+ requestedVariant: initialCoreData.current.requestedVariant,
928
+ stateVariableChanges: initialCoreData.current.coreState
929
+ ? initialCoreData.current.coreState
930
+ : undefined,
931
+ apiURLs: props.apiURLs,
932
+ },
933
+ });
934
+
935
+ setStage("waitingOnCore");
936
+
937
+ for (let actionArgs of actionsBeforeCoreCreated.current) {
938
+ // Note: we protect against the possibility that core is terminated before posting message
939
+ coreWorker.current?.postMessage({
940
+ messageType: "requestAction",
941
+ args: actionArgs,
942
+ });
943
+ }
944
+ }
945
+
946
+ function requestAnimationFrame({ action, actionArgs, delay, animationId }) {
947
+ if (!preventMoreAnimations.current) {
948
+ // create new animationId
949
+
950
+ if (delay) {
951
+ // set a time out to call actual request animation frame after a delay
952
+ let timeoutId = window.setTimeout(
953
+ () => _requestAnimationFrame({ action, actionArgs, animationId }),
954
+ delay,
955
+ );
956
+ animationInfo.current[animationId] = { timeoutId };
957
+ } else {
958
+ // call actual request animation frame right away
959
+ animationInfo.current[animationId] = {};
960
+ _requestAnimationFrame({ action, actionArgs, animationId });
961
+ }
962
+ }
963
+ }
964
+
965
+ function _requestAnimationFrame({ action, actionArgs, animationId }) {
966
+ let animationFrameID = window.requestAnimationFrame(() =>
967
+ callAction({
968
+ action,
969
+ args: actionArgs,
970
+ }),
971
+ );
972
+
973
+ let animationInfoObj = animationInfo.current[animationId];
974
+ delete animationInfoObj.timeoutId;
975
+ animationInfoObj.animationFrameID = animationFrameID;
976
+ }
977
+
978
+ async function cancelAnimationFrame(animationId) {
979
+ let animationInfoObj = animationInfo.current[animationId];
980
+ let timeoutId = animationInfoObj?.timeoutId;
981
+ if (timeoutId !== undefined) {
982
+ window.clearTimeout(timeoutId);
983
+ }
984
+ let animationFrameID = animationInfoObj?.animationFrameID;
985
+ if (animationFrameID !== undefined) {
986
+ window.cancelAnimationFrame(animationFrameID);
987
+ }
988
+ delete animationInfo.current[animationId];
989
+ }
990
+
991
+ async function copyToClipboard({ text, actionId }) {
992
+ await navigator.clipboard.writeText(text);
993
+
994
+ resolveAction({ actionId });
995
+ }
996
+
997
+ async function navigateToTarget({
998
+ cid,
999
+ doenetId,
1000
+ variantIndex,
1001
+ edit,
1002
+ hash,
1003
+ page,
1004
+ uri,
1005
+ targetName,
1006
+ actionId,
1007
+ componentName,
1008
+ effectiveName,
1009
+ }) {
1010
+ let id = prefixForIds + cesc(effectiveName);
1011
+ let { targetForATag, url, haveValidTarget, externalUri } = getURLFromRef({
1012
+ cid,
1013
+ doenetId,
1014
+ variantIndex,
1015
+ edit,
1016
+ hash,
1017
+ page,
1018
+ givenUri: uri,
1019
+ targetName,
1020
+ search: location.search,
1021
+ id,
1022
+ });
1023
+
1024
+ if (haveValidTarget) {
1025
+ if (targetForATag === "_blank") {
1026
+ window.open(url, targetForATag);
1027
+ } else {
1028
+ // TODO: when fix regular ref navigation to scroll back to previous scroll position
1029
+ // when click the back button
1030
+ // add that ability to this navigation as well
1031
+
1032
+ // let scrollAttribute = scrollableContainer === window ? "scrollY" : "scrollTop";
1033
+ // let stateObj = { fromLink: true }
1034
+ // Object.defineProperty(stateObj, 'previousScrollPosition', { get: () => scrollableContainer?.[scrollAttribute], enumerable: true });
1035
+
1036
+ navigate?.(url);
1037
+ }
1038
+ }
1039
+
1040
+ resolveAction({ actionId });
1041
+ }
1042
+
1043
+ function errorHandler() {
1044
+ errorInsideRenderers.current = true;
1045
+
1046
+ if (ignoreRendererError) {
1047
+ setIgnoreRendererError(false);
1048
+ }
1049
+ }
1050
+
1051
+ // first, if cidFromProps or doenetMLFromProps don't match props
1052
+ // set state to props and record that that need a new core
1053
+
1054
+ let changedState = false;
1055
+ if (doenetMLFromProps !== props.doenetML) {
1056
+ setDoenetMLFromProps(props.doenetML);
1057
+ changedState = true;
1058
+ }
1059
+ if (cidFromProps !== props.cid) {
1060
+ setCidFromProps(props.cid);
1061
+ changedState = true;
1062
+ }
1063
+
1064
+ //If no pageNumber prop then set to '1'
1065
+ let propPageNumber = props.pageNumber;
1066
+ if (propPageNumber === undefined) {
1067
+ propPageNumber = "1";
1068
+ }
1069
+
1070
+ if (propPageNumber !== pageNumber) {
1071
+ setPageNumber(propPageNumber);
1072
+ changedState = true;
1073
+ }
1074
+
1075
+ //If no attemptNumber prop then set to 1
1076
+ let propAttemptNumber = props.attemptNumber;
1077
+ if (propAttemptNumber === undefined) {
1078
+ propAttemptNumber = 1;
1079
+ }
1080
+
1081
+ if (propAttemptNumber !== attemptNumber) {
1082
+ setAttemptNumber(propAttemptNumber);
1083
+ changedState = true;
1084
+ }
1085
+
1086
+ // attemptNumber is used for requestedVariantIndex if not specified
1087
+ let adjustedRequestedVariantIndex = props.requestedVariantIndex;
1088
+ if (adjustedRequestedVariantIndex === undefined) {
1089
+ adjustedRequestedVariantIndex = propAttemptNumber;
1090
+ }
1091
+
1092
+ if (requestedVariantIndex !== adjustedRequestedVariantIndex) {
1093
+ setRequestedVariantIndex(adjustedRequestedVariantIndex);
1094
+ changedState = true;
1095
+ }
1096
+
1097
+ // Next time through will recalculate, after state variables are set
1098
+ if (changedState) {
1099
+ if (errMsg !== null) {
1100
+ setErrMsg(null);
1101
+ if (props.setIsInErrorState) {
1102
+ props.setIsInErrorState(false);
1103
+ }
1104
+ }
1105
+
1106
+ if (coreWorker.current) {
1107
+ terminateCoreAndAnimations();
1108
+ }
1109
+ setStage("recalcParams");
1110
+ coreId.current = nanoid();
1111
+ initialCoreData.current = {};
1112
+ setPageContentChanged(true);
1113
+ return null;
1114
+ }
1115
+
1116
+ if (errMsg !== null) {
1117
+ let errorIcon = (
1118
+ <span style={{ fontSize: "1em", color: "#C1292E" }}>
1119
+ <FontAwesomeIcon icon={faExclamationCircle} />
1120
+ </span>
1121
+ );
1122
+ return (
1123
+ <div style={{ fontSize: "1.3em", marginLeft: "20px", marginTop: "20px" }}>
1124
+ {errorIcon} {errMsg}
1125
+ </div>
1126
+ );
1127
+ }
1128
+
1129
+ if (stage === "wait") {
1130
+ return null;
1131
+ }
1132
+
1133
+ if (stage == "recalcParams") {
1134
+ setStage("wait");
1135
+ calculateCidDoenetML();
1136
+ return null;
1137
+ }
1138
+
1139
+ if (pageContentChanged) {
1140
+ setPageContentChanged(false);
1141
+
1142
+ coreInfo.current = null;
1143
+ setDocumentRenderer(null);
1144
+ coreCreated.current = false;
1145
+
1146
+ setStage("wait");
1147
+
1148
+ loadStateAndInitialize();
1149
+
1150
+ return null;
1151
+ }
1152
+
1153
+ if (stage === "readyToCreateCore" && props.pageIsActive) {
1154
+ startCore();
1155
+ } else if (stage === "waitingOnCore" && !props.pageIsActive) {
1156
+ // we've moved off this page, but core is still being initialized
1157
+ // kill the core worker
1158
+
1159
+ terminateCoreAndAnimations();
1160
+
1161
+ setStage("readyToCreateCore");
1162
+ }
1163
+
1164
+ if (props.hideWhenNotCurrent && !props.pageIsCurrent) {
1165
+ return null;
1166
+ }
1167
+
1168
+ let noCoreWarning = null;
1169
+ let pageStyle = {
1170
+ maxWidth: "850px",
1171
+ paddingLeft: "20px",
1172
+ paddingRight: "20px",
1173
+ };
1174
+ if (!coreCreated.current) {
1175
+ if (!documentRenderer) {
1176
+ noCoreWarning = (
1177
+ <div style={{ backgroundColor: "lightCyan", padding: "10px" }}>
1178
+ <p>Initializing....</p>
1179
+ </div>
1180
+ );
1181
+ }
1182
+ pageStyle.backgroundColor = "#F0F0F0";
1183
+ }
1184
+
1185
+ //Spacing around the whole doenetML document
1186
+ return (
1187
+ <ErrorBoundary
1188
+ setIsInErrorState={props.setIsInErrorState}
1189
+ errorHandler={errorHandler}
1190
+ ignoreError={ignoreRendererError}
1191
+ coreCreated={coreCreated.current}
1192
+ >
1193
+ {noCoreWarning}
1194
+ <div style={pageStyle} className="doenet-viewer">
1195
+ {documentRenderer}
1196
+ </div>
1197
+ </ErrorBoundary>
1198
+ );
1199
+ }
1200
+
1201
+ export async function renderersloadComponent(promises, rendererClassNames) {
1202
+ var rendererClasses = {};
1203
+ for (let [index, promise] of promises.entries()) {
1204
+ try {
1205
+ let module = await promise;
1206
+ rendererClasses[rendererClassNames[index]] = module.default;
1207
+ } catch (error) {
1208
+ console.log("here:", error);
1209
+ throw Error(`loading ${rendererClassNames[index]} failed.`);
1210
+ }
1211
+ }
1212
+ return rendererClasses;
1213
+ }
1214
+
1215
+ class ErrorBoundary extends React.Component {
1216
+ constructor(props) {
1217
+ super(props);
1218
+ this.state = { hasError: false };
1219
+ }
1220
+
1221
+ static getDerivedStateFromError(error) {
1222
+ return { hasError: true };
1223
+ }
1224
+ componentDidCatch(error, errorInfo) {
1225
+ this.props.setIsInErrorState?.(true);
1226
+ this.props.errorHandler();
1227
+ }
1228
+ render() {
1229
+ if (this.state.hasError && !this.props.ignoreError) {
1230
+ if (!this.props.coreCreated) {
1231
+ return null;
1232
+ } else {
1233
+ return <h1>Something went wrong.</h1>;
1234
+ }
1235
+ }
1236
+ return this.props.children;
1237
+ }
1238
+ }
1239
+
1240
+ export function getURLFromRef({
1241
+ cid,
1242
+ doenetId,
1243
+ variantIndex,
1244
+ edit,
1245
+ hash,
1246
+ page,
1247
+ givenUri,
1248
+ targetName = "",
1249
+ pageToolView = {},
1250
+ inCourse = false,
1251
+ search = "",
1252
+ id = "",
1253
+ }) {
1254
+ let url = "";
1255
+ let targetForATag = "_blank";
1256
+ let haveValidTarget = false;
1257
+ let externalUri = false;
1258
+ if (cid || doenetId) {
1259
+ if (cid) {
1260
+ url = `cid=${cid}`;
1261
+ } else {
1262
+ url = `doenetId=${doenetId}`;
1263
+ }
1264
+ if (variantIndex) {
1265
+ url += `&variant=${variantIndex}`;
1266
+ }
1267
+
1268
+ let usePublic = false;
1269
+ if (pageToolView.page === "public") {
1270
+ usePublic = true;
1271
+ } else if (!inCourse) {
1272
+ usePublic = true;
1273
+ }
1274
+ if (usePublic) {
1275
+ if (
1276
+ edit === true ||
1277
+ (edit === null &&
1278
+ pageToolView.page === "public" &&
1279
+ pageToolView.tool === "editor")
1280
+ ) {
1281
+ url = `tool=editor&${url}`;
1282
+ }
1283
+ url = `/public?${url}`;
1284
+ } else if (pageToolView.page === "placementexam") {
1285
+ url = `?tool=exam&${url}`;
1286
+ } else {
1287
+ url = `?tool=assignment&${url}`;
1288
+ }
1289
+
1290
+ haveValidTarget = true;
1291
+
1292
+ if (hash) {
1293
+ url += hash;
1294
+ } else {
1295
+ if (page) {
1296
+ url += `#page${page}`;
1297
+ if (targetName) {
1298
+ url += cesc(targetName);
1299
+ }
1300
+ } else if (targetName) {
1301
+ url += "#" + cesc(targetName);
1302
+ }
1303
+ }
1304
+ } else if (givenUri) {
1305
+ url = givenUri;
1306
+ if (
1307
+ url.substring(0, 8) === "https://" ||
1308
+ url.substring(0, 7) === "http://" ||
1309
+ url.substring(0, 7) === "mailto:"
1310
+ ) {
1311
+ haveValidTarget = true;
1312
+ externalUri = true;
1313
+ }
1314
+ } else {
1315
+ url += search;
1316
+
1317
+ if (page) {
1318
+ url += `#page${page}`;
1319
+ } else {
1320
+ let firstSlash = id.indexOf("\\/");
1321
+ let prefix = id.substring(0, firstSlash);
1322
+ url += "#" + prefix;
1323
+ }
1324
+ url += cesc(targetName);
1325
+ targetForATag = null;
1326
+ haveValidTarget = true;
1327
+ }
1328
+ return { targetForATag, url, haveValidTarget, externalUri };
1329
+ }