@khanacademy/perseus 19.1.5 → 19.1.7

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 (489) hide show
  1. package/dist/components/graph.d.ts +0 -1
  2. package/dist/components/graphie.d.ts +0 -1
  3. package/dist/es/index.js +319 -212
  4. package/dist/es/index.js.map +1 -1
  5. package/dist/index.js +338 -222
  6. package/dist/index.js.map +1 -1
  7. package/dist/interactive2/movable-point.d.ts +195 -1
  8. package/dist/interactive2/movable.d.ts +1 -1
  9. package/dist/interactive2/types.d.ts +4 -2
  10. package/dist/interactive2.d.ts +2 -1
  11. package/dist/server-item-renderer.d.ts +2 -2
  12. package/dist/util/graphie.d.ts +12 -2
  13. package/dist/widgets/expression.d.ts +6 -6
  14. package/package.json +11 -8
  15. package/.babelrc.js +0 -8
  16. package/.eslintrc.js +0 -12
  17. package/CHANGELOG.md +0 -1432
  18. package/src/__stories__/article-renderer.stories.tsx +0 -100
  19. package/src/__stories__/hints-renderer.stories.tsx +0 -55
  20. package/src/__stories__/server-item-renderer.stories.tsx +0 -44
  21. package/src/__testdata__/article-renderer.testdata.ts +0 -212
  22. package/src/__testdata__/graphie.testdata.ts +0 -51
  23. package/src/__testdata__/renderer.testdata.ts +0 -274
  24. package/src/__testdata__/server-item-renderer.testdata.ts +0 -171
  25. package/src/__tests__/__snapshots__/perseus-markdown.test.ts.snap +0 -507
  26. package/src/__tests__/__snapshots__/renderer.test.tsx.snap +0 -525
  27. package/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap +0 -285
  28. package/src/__tests__/a11y.test.ts +0 -303
  29. package/src/__tests__/article-renderer.test.tsx +0 -130
  30. package/src/__tests__/error-boundary.test.tsx +0 -76
  31. package/src/__tests__/extract-perseus-data.test.ts +0 -1027
  32. package/src/__tests__/init.test.ts +0 -10
  33. package/src/__tests__/jipt-paragraphs.test.ts +0 -32
  34. package/src/__tests__/mock-asset-loading-widget.tsx +0 -53
  35. package/src/__tests__/mock-widget.tsx +0 -33
  36. package/src/__tests__/perseus-markdown.test.ts +0 -764
  37. package/src/__tests__/renderability.test.ts +0 -480
  38. package/src/__tests__/renderer-api.test.tsx +0 -302
  39. package/src/__tests__/renderer.test.tsx +0 -1816
  40. package/src/__tests__/server-item-renderer.test.tsx +0 -582
  41. package/src/__tests__/test-items/image-item.ts +0 -24
  42. package/src/__tests__/test-items/input-number-1-item.ts +0 -26
  43. package/src/__tests__/test-items/input-number-2-item.ts +0 -38
  44. package/src/__tests__/test-items/table-item.ts +0 -29
  45. package/src/__tests__/tex-wrangler.test.ts +0 -82
  46. package/src/__tests__/util.test.ts +0 -40
  47. package/src/__tests__/widget-container.test.tsx +0 -126
  48. package/src/__tests__/widgets.test.ts +0 -91
  49. package/src/a11y.ts +0 -45
  50. package/src/all-widgets.ts +0 -9
  51. package/src/article-renderer.tsx +0 -237
  52. package/src/asset-context.ts +0 -30
  53. package/src/basic-widgets.ts +0 -16
  54. package/src/components/__stories__/button-group.stories.tsx +0 -55
  55. package/src/components/__stories__/fixed-to-responsive.stories.tsx +0 -141
  56. package/src/components/__stories__/graph.stories.tsx +0 -28
  57. package/src/components/__stories__/graphie.stories.tsx +0 -33
  58. package/src/components/__stories__/hud.stories.tsx +0 -35
  59. package/src/components/__stories__/icon.stories.tsx +0 -63
  60. package/src/components/__stories__/image-loader.stories.tsx +0 -63
  61. package/src/components/__stories__/info-tip.stories.tsx +0 -31
  62. package/src/components/__stories__/inline-icon.stories.tsx +0 -40
  63. package/src/components/__stories__/input-with-examples.stories.tsx +0 -53
  64. package/src/components/__stories__/lint.stories.tsx +0 -86
  65. package/src/components/__stories__/math-input.stories.tsx +0 -43
  66. package/src/components/__stories__/math-output.stories.tsx +0 -23
  67. package/src/components/__stories__/multi-button-group.stories.tsx +0 -66
  68. package/src/components/__stories__/number-input.stories.tsx +0 -41
  69. package/src/components/__stories__/prop-check-box.stories.tsx +0 -65
  70. package/src/components/__stories__/range-input.stories.tsx +0 -29
  71. package/src/components/__stories__/simple-keypad-input.stories.tsx +0 -27
  72. package/src/components/__stories__/sortable.stories.tsx +0 -77
  73. package/src/components/__stories__/stub-tag-editor.stories.tsx +0 -45
  74. package/src/components/__stories__/svg-image.stories.tsx +0 -74
  75. package/src/components/__stories__/tex.stories.tsx +0 -23
  76. package/src/components/__stories__/text-input.stories.tsx +0 -33
  77. package/src/components/__stories__/text-list-editor.stories.tsx +0 -32
  78. package/src/components/__stories__/tooltip.stories.tsx +0 -52
  79. package/src/components/__stories__/zoomable-tex.stories.tsx +0 -41
  80. package/src/components/__stories__/zoomable.stories.tsx +0 -49
  81. package/src/components/__testdata__/sorter.testdata.ts +0 -19
  82. package/src/components/__tests__/__snapshots__/sortable.test.tsx.snap +0 -163
  83. package/src/components/__tests__/__snapshots__/sorter.test.tsx.snap +0 -265
  84. package/src/components/__tests__/math-input.test.tsx +0 -147
  85. package/src/components/__tests__/number-input.test.tsx +0 -128
  86. package/src/components/__tests__/sortable.test.tsx +0 -269
  87. package/src/components/__tests__/sorter.test.tsx +0 -114
  88. package/src/components/__tests__/zoomable.test.tsx +0 -399
  89. package/src/components/button-group.tsx +0 -130
  90. package/src/components/constants.ts +0 -14
  91. package/src/components/fixed-to-responsive.tsx +0 -169
  92. package/src/components/graph.tsx +0 -444
  93. package/src/components/graphie-classes.ts +0 -153
  94. package/src/components/graphie-movables.ts +0 -338
  95. package/src/components/graphie.tsx +0 -400
  96. package/src/components/highlighting/highlightable-content.tsx +0 -240
  97. package/src/components/highlighting/highlights.ts +0 -207
  98. package/src/components/highlighting/ranges.ts +0 -304
  99. package/src/components/highlighting/types.ts +0 -73
  100. package/src/components/highlighting/ui/highlight-renderer.tsx +0 -172
  101. package/src/components/highlighting/ui/highlight-set-renderer.tsx +0 -185
  102. package/src/components/highlighting/ui/highlight-tooltip.tsx +0 -141
  103. package/src/components/highlighting/ui/highlighting-ui.tsx +0 -143
  104. package/src/components/highlighting/ui/selection-tracker.tsx +0 -186
  105. package/src/components/highlighting/ui/types.ts +0 -21
  106. package/src/components/highlighting/ui/util.ts +0 -165
  107. package/src/components/highlighting/word-indexer.tsx +0 -152
  108. package/src/components/hud.tsx +0 -167
  109. package/src/components/icon.tsx +0 -141
  110. package/src/components/image-loader.tsx +0 -177
  111. package/src/components/info-tip/info-tip.tsx +0 -144
  112. package/src/components/info-tip.tsx +0 -39
  113. package/src/components/inline-icon.tsx +0 -60
  114. package/src/components/input-with-examples.tsx +0 -249
  115. package/src/components/lint.tsx +0 -459
  116. package/src/components/math-input.tsx +0 -474
  117. package/src/components/math-output.tsx +0 -134
  118. package/src/components/multi-button-group.tsx +0 -135
  119. package/src/components/number-input.tsx +0 -249
  120. package/src/components/prop-check-box.tsx +0 -79
  121. package/src/components/range-input.tsx +0 -60
  122. package/src/components/simple-keypad-input.tsx +0 -88
  123. package/src/components/sortable.tsx +0 -958
  124. package/src/components/stub-tag-editor.tsx +0 -53
  125. package/src/components/svg-image.tsx +0 -779
  126. package/src/components/tex.tsx +0 -67
  127. package/src/components/text-input.tsx +0 -129
  128. package/src/components/text-list-editor.tsx +0 -166
  129. package/src/components/tooltip.tsx +0 -410
  130. package/src/components/visibility-observer/__stories__/visibility-observer.stories.tsx +0 -141
  131. package/src/components/visibility-observer/create-visibility-observer.ts +0 -108
  132. package/src/components/visibility-observer/get-scroll-parent.ts +0 -46
  133. package/src/components/visibility-observer/visibility-observer.tsx +0 -124
  134. package/src/components/zoomable-tex.tsx +0 -78
  135. package/src/components/zoomable.tsx +0 -304
  136. package/src/components.ts +0 -15
  137. package/src/definition-context.tsx +0 -59
  138. package/src/dependencies.ts +0 -40
  139. package/src/error-boundary.tsx +0 -70
  140. package/src/extra-widgets.ts +0 -75
  141. package/src/hint-renderer.tsx +0 -151
  142. package/src/hints-renderer.tsx +0 -372
  143. package/src/icon-paths.ts +0 -119
  144. package/src/index.ts +0 -171
  145. package/src/init.ts +0 -56
  146. package/src/interaction-tracker.ts +0 -62
  147. package/src/interactive2/__tests__/movable-mock.ts +0 -55
  148. package/src/interactive2/__tests__/movable-point.test.ts +0 -144
  149. package/src/interactive2/interactive-util.test.ts +0 -93
  150. package/src/interactive2/interactive-util.ts +0 -159
  151. package/src/interactive2/movable-helper-methods.ts +0 -166
  152. package/src/interactive2/movable-line-options.ts +0 -419
  153. package/src/interactive2/movable-line.ts +0 -307
  154. package/src/interactive2/movable-point-options.ts +0 -224
  155. package/src/interactive2/movable-point.tsx +0 -585
  156. package/src/interactive2/movable-polygon-options.ts +0 -389
  157. package/src/interactive2/movable-polygon.ts +0 -360
  158. package/src/interactive2/movable.test.ts +0 -249
  159. package/src/interactive2/movable.ts +0 -437
  160. package/src/interactive2/objective_.ts +0 -79
  161. package/src/interactive2/types.ts +0 -17
  162. package/src/interactive2/wrapped-defaults.ts +0 -87
  163. package/src/interactive2/wrapped-ellipse.ts +0 -94
  164. package/src/interactive2/wrapped-line.ts +0 -116
  165. package/src/interactive2/wrapped-path.ts +0 -51
  166. package/src/interactive2.ts +0 -70
  167. package/src/item-version.ts +0 -10
  168. package/src/jipt-paragraphs.ts +0 -49
  169. package/src/jquery.mobile.vmouse.js +0 -545
  170. package/src/loading-context.ts +0 -21
  171. package/src/logging/log.test.ts +0 -39
  172. package/src/logging/log.ts +0 -97
  173. package/src/mixins/__tests__/widget-prop-denylist.test.ts +0 -21
  174. package/src/mixins/changeable.ts +0 -133
  175. package/src/mixins/editor-jsonify.ts +0 -13
  176. package/src/mixins/widget-jsonify-deprecated.ts +0 -23
  177. package/src/mixins/widget-prop-denylist.ts +0 -48
  178. package/src/multi-items/__stories__/multi-renderer.stories.tsx +0 -83
  179. package/src/multi-items/__testdata__/multi-renderer.testdata.ts +0 -172
  180. package/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap +0 -1164
  181. package/src/multi-items/__tests__/items.test.ts +0 -240
  182. package/src/multi-items/__tests__/multi-renderer.test.tsx +0 -914
  183. package/src/multi-items/__tests__/prop-type-builders.test.ts +0 -133
  184. package/src/multi-items/__tests__/shapes.test.ts +0 -43
  185. package/src/multi-items/__tests__/trees.test.ts +0 -317
  186. package/src/multi-items/item-types.ts +0 -56
  187. package/src/multi-items/items.ts +0 -176
  188. package/src/multi-items/multi-renderer.tsx +0 -569
  189. package/src/multi-items/prop-type-builders.ts +0 -106
  190. package/src/multi-items/shape-types.ts +0 -52
  191. package/src/multi-items/shapes.ts +0 -52
  192. package/src/multi-items/tree-types.ts +0 -47
  193. package/src/multi-items/trees.ts +0 -360
  194. package/src/multi-items.ts +0 -75
  195. package/src/perseus-api.tsx +0 -188
  196. package/src/perseus-env.ts +0 -27
  197. package/src/perseus-error.ts +0 -17
  198. package/src/perseus-markdown.tsx +0 -405
  199. package/src/perseus-types.ts +0 -1366
  200. package/src/perseus-version.ts +0 -9
  201. package/src/question-paragraph.tsx +0 -34
  202. package/src/renderability.ts +0 -109
  203. package/src/renderer.tsx +0 -2000
  204. package/src/server-item-renderer.tsx +0 -495
  205. package/src/sigfigs.ts +0 -490
  206. package/src/styles/articles.less +0 -749
  207. package/src/styles/constants.ts +0 -94
  208. package/src/styles/global-constants.ts +0 -343
  209. package/src/styles/global-styles.ts +0 -306
  210. package/src/styles/khan-exercise.css +0 -1468
  211. package/src/styles/media-queries.ts +0 -47
  212. package/src/styles/perseus-renderer.less +0 -732
  213. package/src/styles/shared.ts +0 -130
  214. package/src/styles/util.less +0 -47
  215. package/src/styles/variables.boostrap.less +0 -277
  216. package/src/styles/variables.less +0 -56
  217. package/src/styles/variables.shared.less +0 -340
  218. package/src/styles/widgets/categorizer.less +0 -38
  219. package/src/styles/widgets/dropdown.less +0 -3
  220. package/src/styles/widgets/expression.less +0 -65
  221. package/src/styles/widgets/graded-group.less +0 -36
  222. package/src/styles/widgets/grapher.less +0 -12
  223. package/src/styles/widgets/group.less +0 -19
  224. package/src/styles/widgets/image.less +0 -54
  225. package/src/styles/widgets/interactive-graph.less +0 -64
  226. package/src/styles/widgets/label-image.less +0 -57
  227. package/src/styles/widgets/matcher.less +0 -8
  228. package/src/styles/widgets/matrix.less +0 -126
  229. package/src/styles/widgets/measurer.less +0 -20
  230. package/src/styles/widgets/orderer.less +0 -98
  231. package/src/styles/widgets/passage.less +0 -154
  232. package/src/styles/widgets/plotter.less +0 -31
  233. package/src/styles/widgets/radio.less +0 -58
  234. package/src/styles/widgets/reaction-diagram.less +0 -35
  235. package/src/styles/widgets/sequence.less +0 -5
  236. package/src/styles/widgets/sortable.less +0 -113
  237. package/src/styles/widgets/table.less +0 -57
  238. package/src/styles/widgets/unit.less +0 -15
  239. package/src/tex-wrangler.ts +0 -182
  240. package/src/translation-linter.ts +0 -126
  241. package/src/traversal.ts +0 -138
  242. package/src/types.ts +0 -513
  243. package/src/util/a11y.ts +0 -23
  244. package/src/util/answer-types.test.ts +0 -114
  245. package/src/util/answer-types.ts +0 -876
  246. package/src/util/colors.ts +0 -93
  247. package/src/util/drawing-transform.test.ts +0 -67
  248. package/src/util/drawing-transform.ts +0 -102
  249. package/src/util/extract-perseus-data.ts +0 -539
  250. package/src/util/fix-passage-refs.ts +0 -121
  251. package/src/util/geometry.test.ts +0 -75
  252. package/src/util/geometry.ts +0 -312
  253. package/src/util/graph-bounds.ts +0 -23
  254. package/src/util/graph-utils.ts +0 -15
  255. package/src/util/graphie.test.ts +0 -1277
  256. package/src/util/graphie.ts +0 -1576
  257. package/src/util/interactive.ts +0 -4174
  258. package/src/util/interval.ts +0 -4
  259. package/src/util/katex-preprocess.ts +0 -14
  260. package/src/util/math.test.ts +0 -11
  261. package/src/util/math.ts +0 -294
  262. package/src/util/mobile-native-utils.test.ts +0 -22
  263. package/src/util/mobile-native-utils.ts +0 -12
  264. package/src/util/parse-perseus-json.test.ts +0 -10
  265. package/src/util/parse-perseus-json.ts +0 -13
  266. package/src/util/react-render.tsx +0 -27
  267. package/src/util/register-all-widgets-for-testing.ts +0 -13
  268. package/src/util/scroll-utils.ts +0 -155
  269. package/src/util/sizing-utils.ts +0 -46
  270. package/src/util/tex.ts +0 -73
  271. package/src/util/url-utils.ts +0 -34
  272. package/src/util.graphie.test.ts +0 -45
  273. package/src/util.graphie.ts +0 -59
  274. package/src/util.ts +0 -966
  275. package/src/version.ts +0 -10
  276. package/src/widget-container.tsx +0 -199
  277. package/src/widgets/__stories__/categorizer.stories.tsx +0 -14
  278. package/src/widgets/__stories__/cs-program.stories.tsx +0 -14
  279. package/src/widgets/__stories__/definition.stories.tsx +0 -114
  280. package/src/widgets/__stories__/dropdown.stories.tsx +0 -14
  281. package/src/widgets/__stories__/explanation.stories.tsx +0 -18
  282. package/src/widgets/__stories__/expression.stories.tsx +0 -145
  283. package/src/widgets/__stories__/graded-group-set.stories.tsx +0 -31
  284. package/src/widgets/__stories__/graded-group.stories.tsx +0 -31
  285. package/src/widgets/__stories__/grapher.stories.tsx +0 -46
  286. package/src/widgets/__stories__/group.stories.tsx +0 -14
  287. package/src/widgets/__stories__/iframe.stories.tsx +0 -14
  288. package/src/widgets/__stories__/image.stories.tsx +0 -85
  289. package/src/widgets/__stories__/input-number.stories.tsx +0 -101
  290. package/src/widgets/__stories__/interaction.stories.tsx +0 -14
  291. package/src/widgets/__stories__/interactive-graph.stories.tsx +0 -60
  292. package/src/widgets/__stories__/label-image.stories.tsx +0 -130
  293. package/src/widgets/__stories__/matcher.stories.tsx +0 -14
  294. package/src/widgets/__stories__/matrix.stories.tsx +0 -14
  295. package/src/widgets/__stories__/number-line.stories.tsx +0 -14
  296. package/src/widgets/__stories__/numeric-input.stories.tsx +0 -105
  297. package/src/widgets/__stories__/orderer.stories.tsx +0 -18
  298. package/src/widgets/__stories__/passage-ref.stories.tsx +0 -33
  299. package/src/widgets/__stories__/passage.stories.tsx +0 -39
  300. package/src/widgets/__stories__/plotter.stories.tsx +0 -27
  301. package/src/widgets/__stories__/radio.stories.tsx +0 -86
  302. package/src/widgets/__stories__/random-widgets.stories.tsx +0 -59
  303. package/src/widgets/__stories__/sorter.stories.tsx +0 -14
  304. package/src/widgets/__stories__/test-keypad-context-wrapper.tsx +0 -66
  305. package/src/widgets/__stories__/unit.stories.tsx +0 -28
  306. package/src/widgets/__stories__/video-transcript-link.stories.tsx +0 -23
  307. package/src/widgets/__stories__/video.stories.tsx +0 -22
  308. package/src/widgets/__testdata__/base-radio.testdata.ts +0 -21
  309. package/src/widgets/__testdata__/categorizer.testdata.ts +0 -89
  310. package/src/widgets/__testdata__/cs-program.testdata.ts +0 -27
  311. package/src/widgets/__testdata__/dropdown.testdata.ts +0 -71
  312. package/src/widgets/__testdata__/explanation.testdata.ts +0 -85
  313. package/src/widgets/__testdata__/expression.testdata.ts +0 -198
  314. package/src/widgets/__testdata__/graded-group-set.testdata.ts +0 -356
  315. package/src/widgets/__testdata__/graded-group.testdata.ts +0 -77
  316. package/src/widgets/__testdata__/grapher.testdata.ts +0 -374
  317. package/src/widgets/__testdata__/group.testdata.ts +0 -153
  318. package/src/widgets/__testdata__/iframe.testdata.ts +0 -35
  319. package/src/widgets/__testdata__/image.testdata.ts +0 -36
  320. package/src/widgets/__testdata__/input-number.testdata.ts +0 -72
  321. package/src/widgets/__testdata__/interaction.testdata.ts +0 -262
  322. package/src/widgets/__testdata__/interactive-graph-random.testdata.ts +0 -269
  323. package/src/widgets/__testdata__/interactive-graph.testdata.ts +0 -644
  324. package/src/widgets/__testdata__/label-image.testdata.ts +0 -308
  325. package/src/widgets/__testdata__/matcher.testdata.ts +0 -33
  326. package/src/widgets/__testdata__/matrix.testdata.ts +0 -28
  327. package/src/widgets/__testdata__/number-line.testdata.ts +0 -30
  328. package/src/widgets/__testdata__/numeric-input.testdata.ts +0 -265
  329. package/src/widgets/__testdata__/orderer.testdata.ts +0 -123
  330. package/src/widgets/__testdata__/passage-ref.testdata.ts +0 -101
  331. package/src/widgets/__testdata__/passage.testdata.ts +0 -95
  332. package/src/widgets/__testdata__/plotter.testdata.ts +0 -36
  333. package/src/widgets/__testdata__/radio.testdata.ts +0 -324
  334. package/src/widgets/__testdata__/randomizers.ts +0 -51
  335. package/src/widgets/__testdata__/sorter.testdata.ts +0 -19
  336. package/src/widgets/__testdata__/video.testdata.ts +0 -61
  337. package/src/widgets/__tests__/__snapshots__/categorizer.test.ts.snap +0 -940
  338. package/src/widgets/__tests__/__snapshots__/cs-program.test.ts.snap +0 -67
  339. package/src/widgets/__tests__/__snapshots__/definition.test.ts.snap +0 -97
  340. package/src/widgets/__tests__/__snapshots__/dropdown.test.ts.snap +0 -133
  341. package/src/widgets/__tests__/__snapshots__/explanation.test.ts.snap +0 -425
  342. package/src/widgets/__tests__/__snapshots__/graded-group-set-jipt.test.ts.snap +0 -729
  343. package/src/widgets/__tests__/__snapshots__/graded-group-set.test.ts.snap +0 -339
  344. package/src/widgets/__tests__/__snapshots__/graded-group.test.ts.snap +0 -801
  345. package/src/widgets/__tests__/__snapshots__/grapher.test.ts.snap +0 -2673
  346. package/src/widgets/__tests__/__snapshots__/group.test.tsx.snap +0 -1211
  347. package/src/widgets/__tests__/__snapshots__/iframe.test.ts.snap +0 -61
  348. package/src/widgets/__tests__/__snapshots__/image.test.ts.snap +0 -378
  349. package/src/widgets/__tests__/__snapshots__/input-number.test.ts.snap +0 -495
  350. package/src/widgets/__tests__/__snapshots__/interaction.test.ts.snap +0 -292
  351. package/src/widgets/__tests__/__snapshots__/interactive-graph.test.ts.snap +0 -2889
  352. package/src/widgets/__tests__/__snapshots__/matcher.test.tsx.snap +0 -883
  353. package/src/widgets/__tests__/__snapshots__/matrix.test.ts.snap +0 -514
  354. package/src/widgets/__tests__/__snapshots__/number-line.test.ts.snap +0 -814
  355. package/src/widgets/__tests__/__snapshots__/numeric-input.test.ts.snap +0 -470
  356. package/src/widgets/__tests__/__snapshots__/orderer.test.ts.snap +0 -243
  357. package/src/widgets/__tests__/__snapshots__/passage-ref.test.ts.snap +0 -434
  358. package/src/widgets/__tests__/__snapshots__/passage.test.tsx.snap +0 -1956
  359. package/src/widgets/__tests__/__snapshots__/plotter.test.tsx.snap +0 -827
  360. package/src/widgets/__tests__/__snapshots__/radio.test.ts.snap +0 -4237
  361. package/src/widgets/__tests__/__snapshots__/unit.test.tsx.snap +0 -20
  362. package/src/widgets/__tests__/__snapshots__/video.test.ts.snap +0 -153
  363. package/src/widgets/__tests__/categorizer.test.ts +0 -203
  364. package/src/widgets/__tests__/cs-program.test.ts +0 -43
  365. package/src/widgets/__tests__/definition.test.ts +0 -136
  366. package/src/widgets/__tests__/dropdown.test.ts +0 -105
  367. package/src/widgets/__tests__/explanation.test.ts +0 -198
  368. package/src/widgets/__tests__/expression-mobile.test.tsx +0 -363
  369. package/src/widgets/__tests__/expression.test.tsx +0 -484
  370. package/src/widgets/__tests__/graded-group-set-jipt.test.ts +0 -30
  371. package/src/widgets/__tests__/graded-group-set.test.ts +0 -288
  372. package/src/widgets/__tests__/graded-group.test.ts +0 -232
  373. package/src/widgets/__tests__/grapher.cypress.ts +0 -576
  374. package/src/widgets/__tests__/grapher.test.ts +0 -33
  375. package/src/widgets/__tests__/group.test.tsx +0 -510
  376. package/src/widgets/__tests__/iframe.test.ts +0 -45
  377. package/src/widgets/__tests__/image.test.ts +0 -62
  378. package/src/widgets/__tests__/input-number.test.ts +0 -354
  379. package/src/widgets/__tests__/interaction.test.ts +0 -31
  380. package/src/widgets/__tests__/interactive-graph.cypress.ts +0 -815
  381. package/src/widgets/__tests__/interactive-graph.test.ts +0 -106
  382. package/src/widgets/__tests__/matcher.test.tsx +0 -176
  383. package/src/widgets/__tests__/matrix.test.ts +0 -82
  384. package/src/widgets/__tests__/number-line.test.ts +0 -79
  385. package/src/widgets/__tests__/numeric-input.test.ts +0 -575
  386. package/src/widgets/__tests__/orderer.test.ts +0 -73
  387. package/src/widgets/__tests__/passage-ref.test.ts +0 -168
  388. package/src/widgets/__tests__/passage.test.tsx +0 -224
  389. package/src/widgets/__tests__/plotter.test.tsx +0 -69
  390. package/src/widgets/__tests__/radio/base-radio.test.tsx +0 -470
  391. package/src/widgets/__tests__/radio/choice-icon.test.tsx +0 -90
  392. package/src/widgets/__tests__/radio/choice.test.tsx +0 -310
  393. package/src/widgets/__tests__/radio/focus-ring.test.tsx +0 -22
  394. package/src/widgets/__tests__/radio/option-status.test.tsx +0 -77
  395. package/src/widgets/__tests__/radio.test.ts +0 -807
  396. package/src/widgets/__tests__/randomizers.test.ts +0 -53
  397. package/src/widgets/__tests__/renderQuestion.tsx +0 -101
  398. package/src/widgets/__tests__/unit.test.tsx +0 -168
  399. package/src/widgets/__tests__/video.test.ts +0 -69
  400. package/src/widgets/categorizer.tsx +0 -344
  401. package/src/widgets/cs-program.tsx +0 -227
  402. package/src/widgets/definition.tsx +0 -121
  403. package/src/widgets/deprecated-standin/__stories__/deprecated-standin.stories.tsx +0 -30
  404. package/src/widgets/deprecated-standin/__tests__/__snapshots__/deprecated-standin.test.ts.snap +0 -70
  405. package/src/widgets/deprecated-standin/__tests__/deprecated-standin.test.ts +0 -93
  406. package/src/widgets/deprecated-standin/index.tsx +0 -58
  407. package/src/widgets/dropdown.tsx +0 -142
  408. package/src/widgets/explanation.tsx +0 -317
  409. package/src/widgets/expression.tsx +0 -707
  410. package/src/widgets/graded-group-answer-bar.tsx +0 -142
  411. package/src/widgets/graded-group-set.tsx +0 -338
  412. package/src/widgets/graded-group.tsx +0 -471
  413. package/src/widgets/grapher/util.tsx +0 -799
  414. package/src/widgets/grapher.tsx +0 -660
  415. package/src/widgets/group.tsx +0 -195
  416. package/src/widgets/iframe.tsx +0 -195
  417. package/src/widgets/image.tsx +0 -312
  418. package/src/widgets/input-number.tsx +0 -412
  419. package/src/widgets/interaction/arrow-picker.tsx +0 -38
  420. package/src/widgets/interaction/color-picker.tsx +0 -69
  421. package/src/widgets/interaction/dash-picker.tsx +0 -45
  422. package/src/widgets/interaction/element-container.tsx +0 -100
  423. package/src/widgets/interaction.tsx +0 -826
  424. package/src/widgets/interactive-graph.tsx +0 -2597
  425. package/src/widgets/label-image/__stories__/answer-choices.stories.tsx +0 -91
  426. package/src/widgets/label-image/__stories__/answer-pill.stories.tsx +0 -62
  427. package/src/widgets/label-image/__stories__/marker.stories.tsx +0 -171
  428. package/src/widgets/label-image/__tests__/answer-pill.test.tsx +0 -75
  429. package/src/widgets/label-image/__tests__/hide-answers-toggle.test.tsx +0 -39
  430. package/src/widgets/label-image/answer-choices.tsx +0 -88
  431. package/src/widgets/label-image/answer-pill.tsx +0 -103
  432. package/src/widgets/label-image/hide-answers-toggle.tsx +0 -40
  433. package/src/widgets/label-image/marker.tsx +0 -268
  434. package/src/widgets/label-image/strings.ts +0 -5
  435. package/src/widgets/label-image/types.ts +0 -27
  436. package/src/widgets/label-image.test.ts +0 -928
  437. package/src/widgets/label-image.tsx +0 -819
  438. package/src/widgets/lights-puzzle.tsx +0 -359
  439. package/src/widgets/matcher.tsx +0 -298
  440. package/src/widgets/matrix.tsx +0 -634
  441. package/src/widgets/measurer.tsx +0 -222
  442. package/src/widgets/molecule/__tests__/layout.test.ts +0 -162
  443. package/src/widgets/molecule/__tests__/parser.test.ts +0 -155
  444. package/src/widgets/molecule/molecule-drawing.ts +0 -173
  445. package/src/widgets/molecule/molecule-layout.ts +0 -362
  446. package/src/widgets/molecule/smiles-parser.ts +0 -296
  447. package/src/widgets/molecule.tsx +0 -172
  448. package/src/widgets/number-line.tsx +0 -862
  449. package/src/widgets/numeric-input.tsx +0 -576
  450. package/src/widgets/orderer.tsx +0 -786
  451. package/src/widgets/passage/__tests__/passage-markdown.test.ts +0 -376
  452. package/src/widgets/passage/passage-markdown.tsx +0 -475
  453. package/src/widgets/passage-ref-target.tsx +0 -76
  454. package/src/widgets/passage-ref.tsx +0 -213
  455. package/src/widgets/passage.tsx +0 -582
  456. package/src/widgets/plotter.tsx +0 -1194
  457. package/src/widgets/radio/__stories__/base-radio.stories.tsx +0 -196
  458. package/src/widgets/radio/__stories__/choice-icon.stories.tsx +0 -166
  459. package/src/widgets/radio/__stories__/choice-none-above.stories.tsx +0 -40
  460. package/src/widgets/radio/__stories__/choice.stories.tsx +0 -137
  461. package/src/widgets/radio/__stories__/focus-ring.stories.tsx +0 -43
  462. package/src/widgets/radio/__stories__/option-status.stories.tsx +0 -103
  463. package/src/widgets/radio/base-radio.tsx +0 -511
  464. package/src/widgets/radio/choice-a11y-text.ts +0 -61
  465. package/src/widgets/radio/choice-icon/choice-icon.tsx +0 -218
  466. package/src/widgets/radio/choice-icon/cross-out-line.tsx +0 -51
  467. package/src/widgets/radio/choice-icon/shared-styles.ts +0 -15
  468. package/src/widgets/radio/choice-none-above.tsx +0 -56
  469. package/src/widgets/radio/choice.jsx.fixture.ts +0 -45
  470. package/src/widgets/radio/choice.tsx +0 -359
  471. package/src/widgets/radio/focus-ring.tsx +0 -57
  472. package/src/widgets/radio/option-status.tsx +0 -98
  473. package/src/widgets/radio/util.test.ts +0 -18
  474. package/src/widgets/radio/util.ts +0 -31
  475. package/src/widgets/radio/widget.tsx +0 -520
  476. package/src/widgets/radio.ts +0 -157
  477. package/src/widgets/reaction-diagram.tsx +0 -144
  478. package/src/widgets/sequence.tsx +0 -142
  479. package/src/widgets/simulator.tsx +0 -829
  480. package/src/widgets/sorter.tsx +0 -155
  481. package/src/widgets/table.tsx +0 -393
  482. package/src/widgets/unit.tsx +0 -374
  483. package/src/widgets/video-transcript-link.test.tsx +0 -213
  484. package/src/widgets/video-transcript-link.tsx +0 -84
  485. package/src/widgets/video.tsx +0 -135
  486. package/src/widgets.ts +0 -489
  487. package/src/zoom.ts +0 -555
  488. package/tsconfig-build.json +0 -26
  489. package/tsconfig-build.tsbuildinfo +0 -1
@@ -1,520 +0,0 @@
1
- import {linterContextDefault} from "@khanacademy/perseus-linter";
2
- import * as i18n from "@khanacademy/wonder-blocks-i18n";
3
- import * as React from "react";
4
-
5
- import Renderer from "../../renderer";
6
- import Util from "../../util";
7
- import PassageRef from "../passage-ref";
8
-
9
- import BaseRadio from "./base-radio";
10
-
11
- import type {FocusFunction, ChoiceType} from "./base-radio";
12
- import type {
13
- PerseusRadioChoice,
14
- PerseusRadioWidgetOptions,
15
- } from "../../perseus-types";
16
- import type {PerseusScore, WidgetProps, ChoiceState} from "../../types";
17
-
18
- // RenderProps is the return type for radio.jsx#transform
19
- export type RenderProps = {
20
- numCorrect: number;
21
- hasNoneOfTheAbove?: boolean;
22
- multipleSelect?: boolean;
23
- countChoices?: boolean;
24
- deselectEnabled?: boolean;
25
- choices: ReadonlyArray<RadioChoiceWithMetadata>;
26
- selectedChoices: ReadonlyArray<PerseusRadioChoice["correct"]>;
27
- choiceStates?: ReadonlyArray<ChoiceState>;
28
- // Depreciated; support for legacy way of handling changes
29
- // Adds proptype for prop that is used but was lacking type
30
- values?: ReadonlyArray<boolean>;
31
- };
32
-
33
- type UserInput = {
34
- countChoices?: boolean;
35
- choicesSelected: ReadonlyArray<boolean>;
36
- numCorrect?: number;
37
- noneOfTheAboveIndex?: number | null | undefined;
38
- noneOfTheAboveSelected?: boolean;
39
- };
40
- type Rubric = PerseusRadioWidgetOptions;
41
- type Props = WidgetProps<RenderProps, Rubric>;
42
-
43
- type DefaultProps = {
44
- choices: Props["choices"];
45
- multipleSelect: Props["multipleSelect"];
46
- countChoices: Props["countChoices"];
47
- deselectEnabled: Props["deselectEnabled"];
48
- linterContext: Props["linterContext"];
49
- };
50
-
51
- export type RadioChoiceWithMetadata = PerseusRadioChoice & {
52
- originalIndex: number;
53
- correct: boolean;
54
- };
55
-
56
- class Radio extends React.Component<Props> {
57
- // @ts-expect-error - TS2564 - Property 'focusFunction' has no initializer and is not definitely assigned in the constructor.
58
- focusFunction: FocusFunction;
59
-
60
- static defaultProps: DefaultProps = {
61
- choices: [],
62
- multipleSelect: false,
63
- countChoices: false,
64
- deselectEnabled: false,
65
- linterContext: linterContextDefault,
66
- };
67
-
68
- static validate(userInput: UserInput, rubric: Rubric): PerseusScore {
69
- const numSelected = userInput.choicesSelected.reduce(
70
- (sum, selected) => {
71
- return sum + (selected ? 1 : 0);
72
- },
73
- 0,
74
- );
75
-
76
- if (numSelected === 0) {
77
- return {
78
- type: "invalid",
79
- message: null,
80
- };
81
- }
82
-
83
- if (
84
- userInput.numCorrect &&
85
- userInput.numCorrect > 1 &&
86
- numSelected !== userInput.numCorrect
87
- ) {
88
- return {
89
- type: "invalid",
90
- message: i18n._("Please choose the correct number of answers."),
91
- };
92
- // If NOTA and some other answer are checked, ...
93
- }
94
- if (userInput.noneOfTheAboveSelected && numSelected > 1) {
95
- return {
96
- type: "invalid",
97
- message: i18n._(
98
- "'None of the above' may not be selected " +
99
- "when other answers are selected.",
100
- ),
101
- };
102
- }
103
-
104
- const correct = userInput.choicesSelected.every((selected, i) => {
105
- let isCorrect;
106
- if (userInput.noneOfTheAboveIndex === i) {
107
- isCorrect = rubric.choices.every((choice, j) => {
108
- return i === j || !choice.correct;
109
- });
110
- } else {
111
- isCorrect = !!rubric.choices[i].correct;
112
- }
113
- return isCorrect === selected;
114
- });
115
-
116
- return {
117
- type: "points",
118
- earned: correct ? 1 : 0,
119
- total: 1,
120
- message: null,
121
- };
122
- }
123
-
124
- static getUserInputFromProps(props: Props): UserInput {
125
- // Return checked inputs in the form {choicesSelected: [bool]}. (Dear
126
- // future timeline implementers: this used to be {value: i} before
127
- // multiple select was added)
128
- if (props.choiceStates) {
129
- let noneOfTheAboveIndex = null;
130
- let noneOfTheAboveSelected = false;
131
-
132
- const choiceStates = props.choiceStates;
133
- const choicesSelected = choiceStates.map(() => false);
134
- const countChoices = props.countChoices;
135
- const numCorrect = props.numCorrect;
136
-
137
- for (let i = 0; i < choicesSelected.length; i++) {
138
- const index = props.choices[i].originalIndex;
139
-
140
- choicesSelected[index] = choiceStates[i].selected;
141
-
142
- if (props.choices[i].isNoneOfTheAbove) {
143
- // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'null'.
144
- noneOfTheAboveIndex = index;
145
-
146
- if (choicesSelected[i]) {
147
- noneOfTheAboveSelected = true;
148
- }
149
- }
150
- }
151
-
152
- return {
153
- countChoices,
154
- choicesSelected,
155
- numCorrect,
156
- noneOfTheAboveIndex,
157
- noneOfTheAboveSelected,
158
- };
159
- // Support legacy choiceState implementation
160
- }
161
- /* c8 ignore if - props.values is deprecated */
162
- const {values} = props;
163
- if (values) {
164
- let noneOfTheAboveIndex = null;
165
- let noneOfTheAboveSelected = false;
166
-
167
- const choicesSelected = [...values];
168
- const countChoices = props.countChoices;
169
- const numCorrect = props.numCorrect;
170
- const valuesLength = values.length;
171
-
172
- for (let i = 0; i < valuesLength; i++) {
173
- const index = props.choices[i].originalIndex;
174
- choicesSelected[index] = values[i];
175
-
176
- if (props.choices[i].isNoneOfTheAbove) {
177
- // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'null'.
178
- noneOfTheAboveIndex = index;
179
- if (choicesSelected[i]) {
180
- noneOfTheAboveSelected = true;
181
- }
182
- }
183
- }
184
- return {
185
- choicesSelected,
186
- noneOfTheAboveIndex,
187
- noneOfTheAboveSelected,
188
- countChoices,
189
- numCorrect,
190
- };
191
- }
192
- // Nothing checked
193
- return {
194
- choicesSelected: props.choices.map(() => false),
195
- };
196
- }
197
-
198
- _renderRenderer: (content?: string) => React.ReactElement = (
199
- content = "",
200
- ) => {
201
- let nextPassageRefId = 1;
202
- const widgets: Record<string, any> = {};
203
-
204
- const modContent = content.replace(
205
- /\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,
206
- (
207
- match: string,
208
- passageNum: string,
209
- refNum: string,
210
- summaryText: string,
211
- ) => {
212
- const widgetId = "passage-ref " + nextPassageRefId;
213
- nextPassageRefId++;
214
-
215
- widgets[widgetId] = {
216
- type: "passage-ref",
217
- graded: false,
218
- options: {
219
- passageNumber: parseInt(passageNum),
220
- referenceNumber: parseInt(refNum),
221
- summaryText: summaryText,
222
- },
223
- version: PassageRef.version,
224
- };
225
-
226
- return "[[" + Util.snowman + " " + widgetId + "]]";
227
- },
228
- );
229
-
230
- // alwaysUpdate={true} so that passage-refs findWidgets
231
- // get called when the outer passage updates the renderer
232
- // TODO(aria): This is really hacky
233
- // We pass in a key here so that we avoid a semi-spurious
234
- // react warning when the ChoiceNoneAbove renders a
235
- // different renderer in the same place. Note this destroys
236
- // state, but since all we're doing is outputting
237
- // "None of the above", that is okay.
238
- // TODO(mdr): Widgets inside this Renderer are not discoverable through
239
- // the parent Renderer's `findWidgets` function.
240
- return (
241
- <Renderer
242
- key="choiceContentRenderer"
243
- content={modContent}
244
- widgets={widgets}
245
- findExternalWidgets={this.props.findWidgets}
246
- alwaysUpdate={true}
247
- linterContext={{
248
- ...this.props.linterContext,
249
- // @ts-expect-error - TS2322 - Type '{ blockHighlight: true; contentType: string; highlightLint: boolean; paths: readonly string[]; stack: readonly string[]; }' is not assignable to type 'LinterContextProps'.
250
- blockHighlight: true,
251
- }}
252
- />
253
- );
254
- };
255
-
256
- // TODO(LP-10672): I think this might be unused right now. I can't find anywhere
257
- // that we pass a value to `.focus()` and it seems to have been used for
258
- // adding hints when editing.
259
- // See: https://github.com/Khan/perseus/blame/e18582b4b69959270b90e237ef1813899711ddfa/src/widgets/radio.js#L169
260
- focus(choiceIndex?: number | null): boolean {
261
- if (this.focusFunction) {
262
- return this.focusFunction(choiceIndex);
263
- }
264
-
265
- return false;
266
- }
267
-
268
- // lets BaseRadio regiser a focus callback so widget
269
- // can focus an individual choice
270
- registerFocusFunction(fun: FocusFunction): void {
271
- this.focusFunction = fun;
272
- }
273
-
274
- // When `BaseRadio`'s `onChange` handler is called, indicating a change in
275
- // our choices' state, we need to call our `onChange` handler in order to
276
- // persist those changes in the item's Perseus state.
277
- //
278
- // So, given the new values for each choice, construct the new
279
- // `choiceStates` objects, and pass them to `this.props.onChange`.
280
- //
281
- // `newValueLists` is an object with two keys: `checked` and `crossedOut`.
282
- // Each contains an array of boolean values, specifying the new checked and
283
- // crossed-out value of each choice.
284
- //
285
- // NOTE(mdr): This method expects to be auto-bound. If this component is
286
- // converted to an ES6 class, take care to auto-bind this method!
287
- updateChoices: (
288
- newValueLists: Readonly<{
289
- checked: ReadonlyArray<boolean>;
290
- crossedOut: ReadonlyArray<boolean>;
291
- }>,
292
- ) => void = (newValueLists) => {
293
- const {choiceStates, choices} = this.props;
294
-
295
- // Construct the baseline `choiceStates` objects. If this is the user's
296
- // first interaction with the widget, we'll need to initialize them to
297
- // new objects with all fields set to the default values. Otherwise, we
298
- // should clone the old `choiceStates` objects, in preparation to
299
- // mutate them.
300
- const newChoiceStates = choiceStates
301
- ? choiceStates.map((state: ChoiceState) => ({...state}))
302
- : choices.map(() => ({
303
- selected: false,
304
- crossedOut: false,
305
- highlighted: false,
306
- rationaleShown: false,
307
- correctnessShown: false,
308
- previouslyAnswered: false,
309
- readOnly: false,
310
- }));
311
-
312
- // Mutate the new `choiceState` objects, according to the new `checked`
313
- // and `crossedOut` values provided in `newValueLists`.
314
- newChoiceStates.forEach((choiceState: ChoiceState, i) => {
315
- choiceState.selected = newValueLists.checked[i];
316
- choiceState.crossedOut = newValueLists.crossedOut[i];
317
- });
318
-
319
- this.props.onChange({choiceStates: newChoiceStates});
320
- this.props.trackInteraction();
321
- };
322
-
323
- getUserInput: () => UserInput = () => {
324
- return Radio.getUserInputFromProps(this.props);
325
- };
326
-
327
- simpleValidate: (arg1: PerseusRadioWidgetOptions) => PerseusScore = (
328
- rubric,
329
- ) => {
330
- return Radio.validate(this.getUserInput(), rubric);
331
- };
332
-
333
- /**
334
- * Turn on rationale display for the currently selected choices. Note that
335
- * this leaves rationales on for choices that are already showing
336
- * rationales.
337
- */
338
- showRationalesForCurrentlySelectedChoices: (
339
- arg1: PerseusRadioWidgetOptions,
340
- ) => void = (rubric) => {
341
- const {choiceStates} = this.props;
342
- if (choiceStates) {
343
- const score = this.simpleValidate(rubric);
344
- const widgetCorrect =
345
- score.type === "points" && score.total === score.earned;
346
-
347
- const newStates: ReadonlyArray<ChoiceState> = choiceStates.map(
348
- (state: ChoiceState): ChoiceState => ({
349
- ...state,
350
- highlighted: state.selected,
351
- // If the choice is selected, show the rationale now
352
- rationaleShown:
353
- state.selected ||
354
- // If the choice already had a rationale, keep it shown
355
- state.rationaleShown ||
356
- // If the widget is correctly answered, show the rationale
357
- // for all the choices
358
- widgetCorrect,
359
- // We use the same behavior for the readOnly flag as for
360
- // rationaleShown, but we keep it separate in case other
361
- // behaviors want to disable choices without showing rationales.
362
- readOnly: state.selected || state.readOnly || widgetCorrect,
363
- correctnessShown: state.selected || state.correctnessShown,
364
- previouslyAnswered:
365
- state.previouslyAnswered || state.selected,
366
- }),
367
- );
368
-
369
- this.props.onChange(
370
- {
371
- choiceStates: newStates,
372
- },
373
- // @ts-expect-error - TS2345 - Argument of type 'null' is not assignable to parameter of type '(() => unknown) | undefined'.
374
- null, // cb
375
- true, // silent
376
- );
377
- }
378
- };
379
-
380
- /**
381
- * Deselects any currently-selected choices that are not correct choices.
382
- */
383
- deselectIncorrectSelectedChoices: () => void = () => {
384
- if (this.props.choiceStates) {
385
- const newStates: ReadonlyArray<ChoiceState> =
386
- this.props.choiceStates.map(
387
- (state: ChoiceState, i): ChoiceState => ({
388
- ...state,
389
- selected:
390
- state.selected && !!this.props.choices[i].correct,
391
- highlighted: false,
392
- }),
393
- );
394
-
395
- this.props.onChange(
396
- {
397
- choiceStates: newStates,
398
- },
399
- // @ts-expect-error - TS2345 - Argument of type 'null' is not assignable to parameter of type '(() => unknown) | undefined'.
400
- null, // cb
401
- false, // silent
402
- );
403
- }
404
- };
405
-
406
- render(): React.ReactNode {
407
- const {choices} = this.props;
408
- let choiceStates: ReadonlyArray<ChoiceState>;
409
- if (this.props.static) {
410
- choiceStates = choices.map((choice) => ({
411
- selected: !!choice.correct,
412
- crossedOut: false,
413
- readOnly: true,
414
- highlighted: false,
415
- rationaleShown: true,
416
- correctnessShown: true,
417
- previouslyAnswered: false,
418
- }));
419
- } else if (this.props.choiceStates) {
420
- choiceStates = this.props.choiceStates;
421
- } else if (this.props.values) {
422
- // Support legacy choiceStates implementation
423
- /* c8 ignore next - props.values is deprecated */
424
- choiceStates = this.props.values.map((val) => ({
425
- selected: val,
426
- crossedOut: false,
427
- readOnly: false,
428
- highlighted: false,
429
- rationaleShown: false,
430
- correctnessShown: false,
431
- previouslyAnswered: false,
432
- }));
433
- } else {
434
- choiceStates = choices.map(() => ({
435
- selected: false,
436
- crossedOut: false,
437
- readOnly: false,
438
- highlighted: false,
439
- rationaleShown: false,
440
- correctnessShown: false,
441
- previouslyAnswered: false,
442
- }));
443
- }
444
-
445
- const choicesProp: ReadonlyArray<ChoiceType> = choices.map(
446
- (choice, i) => {
447
- const content =
448
- choice.isNoneOfTheAbove && !choice.content
449
- ? // we use i18n._ instead of $_ here because the content
450
- // sent to a renderer needs to be a string, not a react
451
- // node (/renderable/fragment).
452
- i18n._("None of the above")
453
- : choice.content;
454
-
455
- const {
456
- selected,
457
- crossedOut,
458
- rationaleShown,
459
- correctnessShown,
460
- readOnly,
461
- highlighted,
462
- previouslyAnswered,
463
- } = choiceStates[i];
464
-
465
- const reviewChoice =
466
- this.props.reviewModeRubric &&
467
- this.props.reviewModeRubric.choices[i];
468
-
469
- return {
470
- content: this._renderRenderer(content),
471
- checked: selected,
472
- // Current versions of the radio widget always pass in the
473
- // "correct" value through the choices. Old serialized state
474
- // for radio widgets doesn't have this though, so we have to
475
- // pull the correctness out of the review mode rubric. This
476
- // only works because all of the places we use
477
- // `restoreSerializedState()` also turn on reviewMode, but is
478
- // fine for now.
479
- // TODO(emily): Come up with a more comprehensive way to solve
480
- // this sort of "serialized state breaks when internal
481
- // structure changes" problem.
482
- correct:
483
- choice.correct === undefined
484
- ? !!reviewChoice && !!reviewChoice.correct
485
- : choice.correct,
486
- disabled: readOnly,
487
- hasRationale: !!choice.clue,
488
- rationale: this._renderRenderer(choice.clue),
489
- showRationale: rationaleShown,
490
- showCorrectness: correctnessShown,
491
- isNoneOfTheAbove: !!choice.isNoneOfTheAbove,
492
- revealNoneOfTheAbove: !!(
493
- this.props.questionCompleted && selected
494
- ),
495
- crossedOut,
496
- highlighted,
497
- previouslyAnswered: previouslyAnswered,
498
- };
499
- },
500
- );
501
-
502
- return (
503
- <BaseRadio
504
- labelWrap={true}
505
- multipleSelect={this.props.multipleSelect}
506
- countChoices={this.props.countChoices}
507
- numCorrect={this.props.numCorrect}
508
- choices={choicesProp}
509
- onChange={this.updateChoices}
510
- reviewModeRubric={this.props.reviewModeRubric}
511
- deselectEnabled={this.props.deselectEnabled}
512
- apiOptions={this.props.apiOptions}
513
- isLastUsedWidget={this.props.isLastUsedWidget}
514
- registerFocusFunction={(i) => this.registerFocusFunction(i)}
515
- />
516
- );
517
- }
518
- }
519
-
520
- export default Radio;
@@ -1,157 +0,0 @@
1
- import * as i18n from "@khanacademy/wonder-blocks-i18n";
2
- import _ from "underscore";
3
-
4
- import Util from "../util";
5
-
6
- import Radio from "./radio/widget";
7
-
8
- import type {RenderProps, RadioChoiceWithMetadata} from "./radio/widget";
9
- import type {PerseusRadioWidgetOptions} from "../perseus-types";
10
- import type {WidgetExports} from "../types";
11
-
12
- const {shuffle, random} = Util;
13
-
14
- // Represents choices that we automatically re-order if encountered.
15
- // Note: these are in the reversed (incorrect) order that we will swap, if
16
- // found.
17
- // Note 2: these are internationalized when compared later on.
18
- const ReversedChoices: ReadonlyArray<[string, string]> = [
19
- [i18n._("False"), i18n._("True")],
20
- [i18n._("No"), i18n._("Yes")],
21
- ];
22
-
23
- // Transforms the choices for display.
24
- const _choiceTransform = (
25
- widgetOptions: PerseusRadioWidgetOptions,
26
- problemNum?: number | null,
27
- ) => {
28
- const _maybeRandomize = function (
29
- array: ReadonlyArray<RadioChoiceWithMetadata>,
30
- ) {
31
- const randomSeed = problemNum === undefined ? random : problemNum;
32
- // NOTE: `problemNum` will only be set when the radio widget is
33
- // rendered at the root of an exercise question. It will be `undefined`
34
- // if it's rendered embedded in another widget, such as `graded-group`,
35
- // or if rendered within an article. This results in a predictable
36
- // shuffle order. To avoid this we use a random seed when `problemNum`
37
- // is `undefined`.
38
- return widgetOptions.randomize
39
- ? shuffle(array, randomSeed ?? 0)
40
- : array;
41
- };
42
-
43
- const _addNoneOfAbove = function (
44
- choices: ReadonlyArray<RadioChoiceWithMetadata>,
45
- ) {
46
- let noneOfTheAbove = null;
47
-
48
- const newChoices = choices.filter((choice, index) => {
49
- if (choice.isNoneOfTheAbove) {
50
- // @ts-expect-error - TS2322 - Type 'RadioChoiceWithMetadata' is not assignable to type 'null'.
51
- noneOfTheAbove = choice;
52
- return false;
53
- }
54
- return true;
55
- });
56
-
57
- // Place the "None of the above" options last
58
- if (noneOfTheAbove) {
59
- newChoices.push(noneOfTheAbove);
60
- }
61
-
62
- return newChoices;
63
- };
64
-
65
- const enforceOrdering = (
66
- choices: ReadonlyArray<RadioChoiceWithMetadata>,
67
- ) => {
68
- const content = choices.map((c) => c.content);
69
- if (ReversedChoices.some((reversed) => _.isEqual(content, reversed))) {
70
- return [choices[1], choices[0]];
71
- }
72
- return choices;
73
- };
74
-
75
- // Add meta-information to choices
76
- const choices: ReadonlyArray<RadioChoiceWithMetadata> =
77
- widgetOptions.choices.map((choice, i): RadioChoiceWithMetadata => {
78
- return {
79
- ...choice,
80
- originalIndex: i,
81
- correct: Boolean(choice.correct),
82
- };
83
- });
84
-
85
- // Apply all the transforms. Note that the order we call these is
86
- // important!
87
- // 3) finally add "None of the above" to the bottom
88
- return _addNoneOfAbove(
89
- // 2) then (potentially) enforce ordering (eg. False, True becomes
90
- // True, False)
91
- enforceOrdering(
92
- // 1) we randomize the order first
93
- _maybeRandomize(choices),
94
- ),
95
- );
96
- };
97
-
98
- const transform = (
99
- widgetOptions: PerseusRadioWidgetOptions,
100
- problemNum?: number | null,
101
- ): RenderProps => {
102
- const choices = _choiceTransform(widgetOptions, problemNum);
103
-
104
- const numCorrect: number = _.reduce(
105
- widgetOptions.choices,
106
- function (memo, choice) {
107
- return choice.correct ? memo + 1 : memo;
108
- },
109
- 0,
110
- );
111
-
112
- const {hasNoneOfTheAbove, multipleSelect, countChoices, deselectEnabled} =
113
- widgetOptions;
114
-
115
- return {
116
- numCorrect,
117
- hasNoneOfTheAbove,
118
- multipleSelect,
119
- countChoices,
120
- deselectEnabled,
121
- choices,
122
- selectedChoices: _.pluck(choices, "correct"),
123
- };
124
- };
125
-
126
- const propUpgrades = {
127
- "1": (v0props: any): any => {
128
- let choices;
129
- let hasNoneOfTheAbove;
130
-
131
- if (!v0props.noneOfTheAbove) {
132
- choices = v0props.choices;
133
- hasNoneOfTheAbove = false;
134
- } else {
135
- throw new Error(
136
- "radio widget v0 no longer supports auto noneOfTheAbove",
137
- );
138
- }
139
-
140
- return _.extend(_.omit(v0props, "noneOfTheAbove"), {
141
- choices: choices,
142
- hasNoneOfTheAbove: hasNoneOfTheAbove,
143
- });
144
- },
145
- } as const;
146
-
147
- export default {
148
- name: "radio",
149
- displayName: "Radio / Multiple choice",
150
- accessible: true,
151
- widget: Radio,
152
- transform: transform,
153
- staticTransform: transform,
154
- version: {major: 1, minor: 0},
155
- propUpgrades: propUpgrades,
156
- isLintable: true,
157
- } as WidgetExports<typeof Radio>;