@khanacademy/perseus 0.0.1 → 0.2.1

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 (507) hide show
  1. package/.babelrc.js +1 -1
  2. package/CHANGELOG.md +29 -0
  3. package/dist/es/index.css +4361 -0
  4. package/dist/es/index.js +7 -1
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/index.css +4361 -0
  7. package/dist/index.js +7 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/strings.js +148 -46
  10. package/package.json +50 -4
  11. package/src/README.md +35 -0
  12. package/src/__stories__/item-renderer.stories.jsx +27 -0
  13. package/src/__stories__/server-item-renderer.stories.jsx +27 -0
  14. package/src/__testdata__/item-renderer_testdata.js +161 -0
  15. package/src/__testdata__/renderer_testdata.js +123 -0
  16. package/src/__tests__/__snapshots__/item-renderer_test.jsx.snap +233 -0
  17. package/src/__tests__/__snapshots__/perseus-markdown_test.jsx.snap +516 -0
  18. package/src/__tests__/__snapshots__/pure-markdown_test.js.snap +113 -0
  19. package/src/__tests__/__snapshots__/renderer_test.jsx.snap +576 -0
  20. package/src/__tests__/__snapshots__/server-item-renderer_test.jsx.snap +306 -0
  21. package/src/__tests__/a11y_test.jsx +304 -0
  22. package/src/__tests__/item-renderer_test.jsx +892 -0
  23. package/src/__tests__/mock-asset-loading-widget.jsx +57 -0
  24. package/src/__tests__/mock-widget.jsx +35 -0
  25. package/src/__tests__/perseus-markdown_test.jsx +747 -0
  26. package/src/__tests__/pure-markdown_test.js +552 -0
  27. package/src/__tests__/renderability_test.jsx +481 -0
  28. package/src/__tests__/renderer-api_test.jsx +333 -0
  29. package/src/__tests__/renderer_test.jsx +1792 -0
  30. package/src/__tests__/server-item-renderer_test.jsx +516 -0
  31. package/src/__tests__/test-items/image-item.js +25 -0
  32. package/src/__tests__/test-items/input-number-1-item.js +27 -0
  33. package/src/__tests__/test-items/input-number-2-item.js +39 -0
  34. package/src/__tests__/test-items/table-item.js +30 -0
  35. package/src/__tests__/tex-wrangler_test.js +83 -0
  36. package/src/__tests__/util_test.js +41 -0
  37. package/src/a11y.js +46 -0
  38. package/src/all-widgets.js +9 -0
  39. package/src/article-renderer.jsx +215 -0
  40. package/src/asset-context.js +30 -0
  41. package/src/basic-widgets.js +13 -0
  42. package/src/components/__stories__/button-group.stories.jsx +61 -0
  43. package/src/components/__stories__/fixed-to-responsive.stories.jsx +132 -0
  44. package/src/components/__stories__/graph.stories.jsx +27 -0
  45. package/src/components/__stories__/graphie.stories.jsx +28 -0
  46. package/src/components/__stories__/hud.stories.jsx +36 -0
  47. package/src/components/__stories__/icon.stories.jsx +56 -0
  48. package/src/components/__stories__/image-loader.stories.jsx +60 -0
  49. package/src/components/__stories__/info-tip.stories.jsx +33 -0
  50. package/src/components/__stories__/inline-icon.stories.jsx +39 -0
  51. package/src/components/__stories__/input-with-examples.stories.jsx +51 -0
  52. package/src/components/__stories__/lint.stories.jsx +40 -0
  53. package/src/components/__stories__/math-input.stories.jsx +29 -0
  54. package/src/components/__stories__/math-output.stories.jsx +24 -0
  55. package/src/components/__stories__/multi-button-group.stories.jsx +69 -0
  56. package/src/components/__stories__/number-input.stories.jsx +42 -0
  57. package/src/components/__stories__/possible-answers.stories.jsx +22 -0
  58. package/src/components/__stories__/prop-check-box.stories.jsx +62 -0
  59. package/src/components/__stories__/range-input.stories.jsx +28 -0
  60. package/src/components/__stories__/simple-keypad-input.stories.jsx +28 -0
  61. package/src/components/__stories__/sortable.stories.jsx +73 -0
  62. package/src/components/__stories__/stub-tag-editor.stories.jsx +44 -0
  63. package/src/components/__stories__/svg-image.stories.jsx +60 -0
  64. package/src/components/__stories__/tex.stories.jsx +18 -0
  65. package/src/components/__stories__/text-buttons.stories.jsx +51 -0
  66. package/src/components/__stories__/text-input.stories.jsx +34 -0
  67. package/src/components/__stories__/text-list-editor.stories.jsx +33 -0
  68. package/src/components/__stories__/zoomable-tex.stories.jsx +39 -0
  69. package/src/components/__stories__/zoomable.stories.jsx +40 -0
  70. package/src/components/__testdata__/sorter_testdata.js +20 -0
  71. package/src/components/__tests__/__snapshots__/sortable_test.jsx.snap +79 -0
  72. package/src/components/__tests__/__snapshots__/sorter_test.jsx.snap +297 -0
  73. package/src/components/__tests__/number-input_test.jsx +112 -0
  74. package/src/components/__tests__/sortable_test.jsx +234 -0
  75. package/src/components/__tests__/sorter_test.jsx +111 -0
  76. package/src/components/__tests__/zoomable_test.jsx +388 -0
  77. package/src/components/button-group.jsx +131 -0
  78. package/src/components/constants.js +15 -0
  79. package/src/components/fixed-to-responsive.jsx +164 -0
  80. package/src/components/graph.jsx +415 -0
  81. package/src/components/graphie-classes.jsx +148 -0
  82. package/src/components/graphie-movables.jsx +342 -0
  83. package/src/components/graphie.jsx +353 -0
  84. package/src/components/highlighting/highlightable-content.jsx +245 -0
  85. package/src/components/highlighting/highlights.js +208 -0
  86. package/src/components/highlighting/ranges.js +299 -0
  87. package/src/components/highlighting/types.js +73 -0
  88. package/src/components/highlighting/ui/highlight-renderer.jsx +179 -0
  89. package/src/components/highlighting/ui/highlight-set-renderer.jsx +190 -0
  90. package/src/components/highlighting/ui/highlight-tooltip.jsx +153 -0
  91. package/src/components/highlighting/ui/highlighting-ui.jsx +163 -0
  92. package/src/components/highlighting/ui/selection-tracker.jsx +195 -0
  93. package/src/components/highlighting/ui/types.js +21 -0
  94. package/src/components/highlighting/ui/util.js +166 -0
  95. package/src/components/highlighting/word-indexer.jsx +155 -0
  96. package/src/components/hud.jsx +179 -0
  97. package/src/components/icon.jsx +149 -0
  98. package/src/components/image-loader.jsx +175 -0
  99. package/src/components/info-tip/info-tip.jsx +146 -0
  100. package/src/components/info-tip.jsx +38 -0
  101. package/src/components/inline-icon.jsx +81 -0
  102. package/src/components/input-with-examples.jsx +231 -0
  103. package/src/components/lint.jsx +454 -0
  104. package/src/components/math-input.jsx +282 -0
  105. package/src/components/math-output.jsx +128 -0
  106. package/src/components/multi-button-group.jsx +137 -0
  107. package/src/components/new-tooltip/README.md +110 -0
  108. package/src/components/new-tooltip/__stories__/flexible-position.stories.jsx +437 -0
  109. package/src/components/new-tooltip/__stories__/new-tooltip.stories.jsx +665 -0
  110. package/src/components/new-tooltip/__stories__/tooltip-arrow.stories.jsx +70 -0
  111. package/src/components/new-tooltip/__stories__/tooltip-bubble.stories.jsx +98 -0
  112. package/src/components/new-tooltip/__tests__/style-constants_test.js +8 -0
  113. package/src/components/new-tooltip/__tests__/util_test.js +47 -0
  114. package/src/components/new-tooltip/flexible-position.jsx +182 -0
  115. package/src/components/new-tooltip/new-tooltip.jsx +399 -0
  116. package/src/components/new-tooltip/style-constants.js +13 -0
  117. package/src/components/new-tooltip/tooltip-arrow.jsx +184 -0
  118. package/src/components/new-tooltip/tooltip-bubble.jsx +223 -0
  119. package/src/components/new-tooltip/tooltip-portal.jsx +101 -0
  120. package/src/components/new-tooltip/tooltip-positioner.jsx +529 -0
  121. package/src/components/new-tooltip/types.js +183 -0
  122. package/src/components/new-tooltip/util.js +27 -0
  123. package/src/components/number-input.jsx +253 -0
  124. package/src/components/possible-answers.jsx +36 -0
  125. package/src/components/prop-check-box.jsx +80 -0
  126. package/src/components/range-input.jsx +61 -0
  127. package/src/components/simple-keypad-input.jsx +91 -0
  128. package/src/components/sortable.jsx +873 -0
  129. package/src/components/stub-tag-editor.jsx +54 -0
  130. package/src/components/svg-image.jsx +762 -0
  131. package/src/components/tex-buttons.jsx +322 -0
  132. package/src/components/tex.jsx +70 -0
  133. package/src/components/text-input.jsx +82 -0
  134. package/src/components/text-list-editor.jsx +157 -0
  135. package/src/components/tooltip.jsx +395 -0
  136. package/src/components/visibility-observer/__stories__/visibility-observer.stories.jsx +140 -0
  137. package/src/components/visibility-observer/get-scroll-parent.js +45 -0
  138. package/src/components/visibility-observer/visibility-observer.js +109 -0
  139. package/src/components/visibility-observer/visibility-observer.jsx +123 -0
  140. package/src/components/zoomable-tex.jsx +70 -0
  141. package/src/components/zoomable.jsx +304 -0
  142. package/src/components.js +17 -0
  143. package/src/dependencies.js +22 -0
  144. package/src/error-boundary.jsx +48 -0
  145. package/src/extra-widgets.js +75 -0
  146. package/src/gorgon/README +40 -0
  147. package/src/gorgon/__tests__/matcher_test.js +497 -0
  148. package/src/gorgon/__tests__/rule_test.js +101 -0
  149. package/src/gorgon/__tests__/rules_test.js +487 -0
  150. package/src/gorgon/__tests__/selector-parser_test.js +52 -0
  151. package/src/gorgon/__tests__/tree-transformer_test.js +446 -0
  152. package/src/gorgon/gorgon.js +290 -0
  153. package/src/gorgon/proptypes.js +29 -0
  154. package/src/gorgon/rule.js +413 -0
  155. package/src/gorgon/rules/absolute-url.js +24 -0
  156. package/src/gorgon/rules/all-rules.js +72 -0
  157. package/src/gorgon/rules/blockquoted-math.js +10 -0
  158. package/src/gorgon/rules/blockquoted-widget.js +10 -0
  159. package/src/gorgon/rules/double-spacing-after-terminal.js +12 -0
  160. package/src/gorgon/rules/extra-content-spacing.js +12 -0
  161. package/src/gorgon/rules/heading-level-1.js +14 -0
  162. package/src/gorgon/rules/heading-level-skip.js +20 -0
  163. package/src/gorgon/rules/heading-sentence-case.js +11 -0
  164. package/src/gorgon/rules/heading-title-case.js +63 -0
  165. package/src/gorgon/rules/image-alt-text.js +21 -0
  166. package/src/gorgon/rules/image-in-table.js +10 -0
  167. package/src/gorgon/rules/image-spaces-around-urls.js +35 -0
  168. package/src/gorgon/rules/image-widget.js +50 -0
  169. package/src/gorgon/rules/link-click-here.js +11 -0
  170. package/src/gorgon/rules/lint-utils.js +48 -0
  171. package/src/gorgon/rules/long-paragraph.js +14 -0
  172. package/src/gorgon/rules/math-adjacent.js +10 -0
  173. package/src/gorgon/rules/math-align-extra-break.js +11 -0
  174. package/src/gorgon/rules/math-align-linebreaks.js +43 -0
  175. package/src/gorgon/rules/math-empty.js +10 -0
  176. package/src/gorgon/rules/math-font-size.js +12 -0
  177. package/src/gorgon/rules/math-frac.js +10 -0
  178. package/src/gorgon/rules/math-nested.js +11 -0
  179. package/src/gorgon/rules/math-starts-with-space.js +12 -0
  180. package/src/gorgon/rules/math-text-empty.js +10 -0
  181. package/src/gorgon/rules/math-without-dollars.js +14 -0
  182. package/src/gorgon/rules/nested-lists.js +11 -0
  183. package/src/gorgon/rules/profanity.js +10 -0
  184. package/src/gorgon/rules/table-missing-cells.js +20 -0
  185. package/src/gorgon/rules/unbalanced-code-delimiters.js +14 -0
  186. package/src/gorgon/rules/unescaped-dollar.js +10 -0
  187. package/src/gorgon/rules/widget-in-table.js +10 -0
  188. package/src/gorgon/selector.js +506 -0
  189. package/src/gorgon/tree-transformer.js +588 -0
  190. package/src/hint-renderer.jsx +159 -0
  191. package/src/hints-renderer.jsx +359 -0
  192. package/src/icon-paths.js +120 -0
  193. package/src/index.js +149 -2
  194. package/src/init.js +49 -0
  195. package/src/interaction-tracker.js +60 -0
  196. package/src/interactive2/__tests__/movable-mock.js +48 -0
  197. package/src/interactive2/__tests__/movable-point_test.js +146 -0
  198. package/src/interactive2/interactive-util.js +152 -0
  199. package/src/interactive2/movable-helper-methods.js +160 -0
  200. package/src/interactive2/movable-line-options.js +392 -0
  201. package/src/interactive2/movable-line.js +322 -0
  202. package/src/interactive2/movable-point-options.js +190 -0
  203. package/src/interactive2/movable-point.jsx +603 -0
  204. package/src/interactive2/movable-polygon-options.js +351 -0
  205. package/src/interactive2/movable-polygon.js +368 -0
  206. package/src/interactive2/movable.js +273 -0
  207. package/src/interactive2/objective_.js +79 -0
  208. package/src/interactive2/types.js +3 -0
  209. package/src/interactive2/wrapped-defaults.js +86 -0
  210. package/src/interactive2/wrapped-ellipse.js +87 -0
  211. package/src/interactive2/wrapped-line.js +109 -0
  212. package/src/interactive2/wrapped-path.js +47 -0
  213. package/src/interactive2.js +91 -0
  214. package/src/item-renderer.jsx +518 -0
  215. package/src/item-version.js +12 -0
  216. package/src/jipt-paragraphs.js +44 -0
  217. package/src/jquery.mobile.vmouse.js +545 -0
  218. package/src/keypad-context.js +33 -0
  219. package/src/loading-context.js +20 -0
  220. package/src/logging/log.js +107 -0
  221. package/src/logging/log_test.js +41 -0
  222. package/src/mixins/changeable.jsx +115 -0
  223. package/src/mixins/editor-jsonify.jsx +13 -0
  224. package/src/mixins/provide-keypad.jsx +129 -0
  225. package/src/mixins/widget-jsonify-deprecated.jsx +23 -0
  226. package/src/mixins/widget-prop-blacklist.js +36 -0
  227. package/src/multi-items/__stories__/multi-renderer.stories.js +88 -0
  228. package/src/multi-items/__testdata__/multi-renderer_testdata.js +174 -0
  229. package/src/multi-items/__tests__/__snapshots__/multi-renderer_test.js.snap +994 -0
  230. package/src/multi-items/__tests__/items_test.js +245 -0
  231. package/src/multi-items/__tests__/multi-renderer_test.js +903 -0
  232. package/src/multi-items/__tests__/prop-type-builders_test.js +134 -0
  233. package/src/multi-items/__tests__/shapes_test.js +44 -0
  234. package/src/multi-items/__tests__/trees_test.js +316 -0
  235. package/src/multi-items/item-types.js +55 -0
  236. package/src/multi-items/items.js +176 -0
  237. package/src/multi-items/multi-renderer.jsx +543 -0
  238. package/src/multi-items/prop-type-builders.js +105 -0
  239. package/src/multi-items/shape-types.js +47 -0
  240. package/src/multi-items/shapes.js +53 -0
  241. package/src/multi-items/tree-types.js +42 -0
  242. package/src/multi-items/trees.js +345 -0
  243. package/src/multi-items.js +76 -0
  244. package/src/not-gorgon.js +129 -0
  245. package/src/perseus-api.jsx +270 -0
  246. package/src/perseus-env.js +26 -0
  247. package/src/perseus-error.js +19 -0
  248. package/src/perseus-markdown.jsx +433 -0
  249. package/src/perseus-types.js +1597 -0
  250. package/src/pure-markdown.js +347 -0
  251. package/src/question-paragraph.jsx +30 -0
  252. package/src/renderability.jsx +108 -0
  253. package/src/renderer.jsx +1932 -0
  254. package/src/server-item-renderer.jsx +467 -0
  255. package/src/sigfigs.jsx +492 -0
  256. package/src/styles/articles.less +748 -0
  257. package/src/styles/constants.js +119 -0
  258. package/src/styles/global-constants.js +350 -0
  259. package/src/styles/global-styles.js +307 -0
  260. package/src/styles/khan-exercise.css +1304 -0
  261. package/src/styles/media-queries.js +48 -0
  262. package/src/styles/perseus-renderer.less +1007 -0
  263. package/src/styles/shared.js +132 -0
  264. package/src/styles/util.less +47 -0
  265. package/src/styles/variables.boostrap.less +301 -0
  266. package/src/styles/variables.less +68 -0
  267. package/src/styles/variables.shared.less +356 -0
  268. package/src/styles/widgets/categorizer.less +39 -0
  269. package/src/styles/widgets/definition.less +86 -0
  270. package/src/styles/widgets/dropdown.less +3 -0
  271. package/src/styles/widgets/expression.less +147 -0
  272. package/src/styles/widgets/graded-group.less +36 -0
  273. package/src/styles/widgets/grapher.less +11 -0
  274. package/src/styles/widgets/group.less +19 -0
  275. package/src/styles/widgets/image.less +29 -0
  276. package/src/styles/widgets/interactive-graph.less +61 -0
  277. package/src/styles/widgets/label-image.less +41 -0
  278. package/src/styles/widgets/matcher.less +8 -0
  279. package/src/styles/widgets/matrix.less +120 -0
  280. package/src/styles/widgets/measurer.less +20 -0
  281. package/src/styles/widgets/orderer.less +97 -0
  282. package/src/styles/widgets/passage.less +151 -0
  283. package/src/styles/widgets/plotter.less +33 -0
  284. package/src/styles/widgets/radio.less +52 -0
  285. package/src/styles/widgets/reaction-diagram.less +35 -0
  286. package/src/styles/widgets/sequence.less +5 -0
  287. package/src/styles/widgets/sortable.less +127 -0
  288. package/src/styles/widgets/table.less +56 -0
  289. package/src/styles/widgets/transformer.less +28 -0
  290. package/src/styles/widgets/unit.less +14 -0
  291. package/src/tex-wrangler.js +176 -0
  292. package/src/traversal.jsx +141 -0
  293. package/src/types.js +538 -0
  294. package/src/util/a11y.js +24 -0
  295. package/src/util/answer-types.js +862 -0
  296. package/src/util/answer-types_test.js +115 -0
  297. package/src/util/colors.js +94 -0
  298. package/src/util/fix-passage-refs.jsx +122 -0
  299. package/src/util/graph-utils.js +16 -0
  300. package/src/util/graphie.js +1586 -0
  301. package/src/util/interactive.js +4078 -0
  302. package/src/util/katex-preprocess.js +16 -0
  303. package/src/util/math.js +296 -0
  304. package/src/util/mobile-native-utils.js +14 -0
  305. package/src/util/mobile-native-utils_test.js +24 -0
  306. package/src/util/register-all-widgets-for-testing.js +12 -0
  307. package/src/util/scroll-utils.js +162 -0
  308. package/src/util/sizing-utils.js +46 -0
  309. package/src/util/tex.js +203 -0
  310. package/src/util/url-utils.js +36 -0
  311. package/src/util.js +990 -0
  312. package/src/version.js +11 -0
  313. package/src/widget-container.jsx +174 -0
  314. package/src/widgets/__stories__/categorizer.stories.jsx +15 -0
  315. package/src/widgets/__stories__/cs-program.stories.jsx +15 -0
  316. package/src/widgets/__stories__/definition.stories.jsx +38 -0
  317. package/src/widgets/__stories__/dropdown.stories.jsx +15 -0
  318. package/src/widgets/__stories__/explanation.stories.jsx +19 -0
  319. package/src/widgets/__stories__/expression.stories.jsx +26 -0
  320. package/src/widgets/__stories__/graded-group-set.stories.jsx +32 -0
  321. package/src/widgets/__stories__/graded-group.stories.jsx +32 -0
  322. package/src/widgets/__stories__/grapher.stories.jsx +47 -0
  323. package/src/widgets/__stories__/group.stories.jsx +15 -0
  324. package/src/widgets/__stories__/iframe.stories.jsx +15 -0
  325. package/src/widgets/__stories__/image.stories.jsx +62 -0
  326. package/src/widgets/__stories__/input-number.stories.jsx +90 -0
  327. package/src/widgets/__stories__/interaction.stories.jsx +15 -0
  328. package/src/widgets/__stories__/interactive-graph.stories.jsx +61 -0
  329. package/src/widgets/__stories__/matcher.stories.jsx +15 -0
  330. package/src/widgets/__stories__/matrix.stories.jsx +15 -0
  331. package/src/widgets/__stories__/number-line.stories.jsx +15 -0
  332. package/src/widgets/__stories__/numeric-input.stories.jsx +19 -0
  333. package/src/widgets/__stories__/orderer.stories.jsx +15 -0
  334. package/src/widgets/__stories__/passage-ref.stories.jsx +19 -0
  335. package/src/widgets/__stories__/passage.stories.jsx +19 -0
  336. package/src/widgets/__stories__/radio.stories.jsx +82 -0
  337. package/src/widgets/__stories__/sorter.stories.jsx +15 -0
  338. package/src/widgets/__stories__/transformer.stories.jsx +15 -0
  339. package/src/widgets/__stories__/unit.stories.jsx +45 -0
  340. package/src/widgets/__stories__/video-transcript-link.stories.jsx +24 -0
  341. package/src/widgets/__stories__/video.stories.jsx +15 -0
  342. package/src/widgets/__testdata__/categorizer_testdata.js +50 -0
  343. package/src/widgets/__testdata__/cs-program_testdata.js +28 -0
  344. package/src/widgets/__testdata__/dropdown_testdata.js +34 -0
  345. package/src/widgets/__testdata__/explanation_testdata.js +56 -0
  346. package/src/widgets/__testdata__/expression_testdata.js +95 -0
  347. package/src/widgets/__testdata__/graded-group-set_testdata.js +358 -0
  348. package/src/widgets/__testdata__/graded-group_testdata.js +79 -0
  349. package/src/widgets/__testdata__/grapher_testdata.js +376 -0
  350. package/src/widgets/__testdata__/group_testdata.js +156 -0
  351. package/src/widgets/__testdata__/iframe_testdata.js +36 -0
  352. package/src/widgets/__testdata__/image_testdata.js +38 -0
  353. package/src/widgets/__testdata__/input-number_testdata.js +73 -0
  354. package/src/widgets/__testdata__/interaction_testdata.js +264 -0
  355. package/src/widgets/__testdata__/interactive-graph_testdata.js +646 -0
  356. package/src/widgets/__testdata__/matcher_testdata.js +34 -0
  357. package/src/widgets/__testdata__/matrix_testdata.js +29 -0
  358. package/src/widgets/__testdata__/number-line_testdata.js +31 -0
  359. package/src/widgets/__testdata__/numeric-input_testdata.js +266 -0
  360. package/src/widgets/__testdata__/orderer_testdata.js +58 -0
  361. package/src/widgets/__testdata__/passage-ref_testdata.js +41 -0
  362. package/src/widgets/__testdata__/passage_testdata.js +71 -0
  363. package/src/widgets/__testdata__/radio_testdata.js +210 -0
  364. package/src/widgets/__testdata__/sorter_testdata.js +20 -0
  365. package/src/widgets/__testdata__/transformer_testdata.js +109 -0
  366. package/src/widgets/__testdata__/video_testdata.js +22 -0
  367. package/src/widgets/__tests__/__snapshots__/categorizer_test.jsx.snap +928 -0
  368. package/src/widgets/__tests__/__snapshots__/cs-program_test.jsx.snap +75 -0
  369. package/src/widgets/__tests__/__snapshots__/definition_test.js.snap +99 -0
  370. package/src/widgets/__tests__/__snapshots__/dropdown_test.jsx.snap +143 -0
  371. package/src/widgets/__tests__/__snapshots__/explanation_test.js.snap +473 -0
  372. package/src/widgets/__tests__/__snapshots__/expression_test.jsx.snap +38 -0
  373. package/src/widgets/__tests__/__snapshots__/graded-group-set-jipt_test.jsx.snap +754 -0
  374. package/src/widgets/__tests__/__snapshots__/graded-group-set_test.jsx.snap +310 -0
  375. package/src/widgets/__tests__/__snapshots__/graded-group_test.jsx.snap +863 -0
  376. package/src/widgets/__tests__/__snapshots__/grapher_test.jsx.snap +2880 -0
  377. package/src/widgets/__tests__/__snapshots__/group_test.jsx.snap +1154 -0
  378. package/src/widgets/__tests__/__snapshots__/iframe_test.jsx.snap +69 -0
  379. package/src/widgets/__tests__/__snapshots__/image_test.jsx.snap +388 -0
  380. package/src/widgets/__tests__/__snapshots__/input-number_test.jsx.snap +978 -0
  381. package/src/widgets/__tests__/__snapshots__/interaction_test.jsx.snap +311 -0
  382. package/src/widgets/__tests__/__snapshots__/interactive-graph_test.jsx.snap +2915 -0
  383. package/src/widgets/__tests__/__snapshots__/matcher_test.jsx.snap +1039 -0
  384. package/src/widgets/__tests__/__snapshots__/matrix_test.jsx.snap +450 -0
  385. package/src/widgets/__tests__/__snapshots__/number-line_test.jsx.snap +888 -0
  386. package/src/widgets/__tests__/__snapshots__/numeric-input_test.jsx.snap +930 -0
  387. package/src/widgets/__tests__/__snapshots__/orderer_test.jsx.snap +275 -0
  388. package/src/widgets/__tests__/__snapshots__/passage-ref_test.jsx.snap +446 -0
  389. package/src/widgets/__tests__/__snapshots__/passage_test.jsx.snap +1988 -0
  390. package/src/widgets/__tests__/__snapshots__/radio_test.jsx.snap +7107 -0
  391. package/src/widgets/__tests__/__snapshots__/video_test.jsx.snap +163 -0
  392. package/src/widgets/__tests__/categorizer_test.jsx +205 -0
  393. package/src/widgets/__tests__/cs-program_test.jsx +45 -0
  394. package/src/widgets/__tests__/definition_test.js +152 -0
  395. package/src/widgets/__tests__/dropdown_test.jsx +106 -0
  396. package/src/widgets/__tests__/explanation_test.js +199 -0
  397. package/src/widgets/__tests__/expression_test.jsx +439 -0
  398. package/src/widgets/__tests__/graded-group-set-jipt_test.jsx +33 -0
  399. package/src/widgets/__tests__/graded-group-set_test.jsx +270 -0
  400. package/src/widgets/__tests__/graded-group_test.jsx +233 -0
  401. package/src/widgets/__tests__/grapher.cypress.jsx +486 -0
  402. package/src/widgets/__tests__/grapher_test.jsx +35 -0
  403. package/src/widgets/__tests__/group_test.jsx +512 -0
  404. package/src/widgets/__tests__/iframe_test.jsx +47 -0
  405. package/src/widgets/__tests__/image_test.jsx +65 -0
  406. package/src/widgets/__tests__/input-number_test.jsx +360 -0
  407. package/src/widgets/__tests__/interaction_test.jsx +33 -0
  408. package/src/widgets/__tests__/interactive-graph.cypress.jsx +697 -0
  409. package/src/widgets/__tests__/interactive-graph_test.jsx +105 -0
  410. package/src/widgets/__tests__/matcher_test.jsx +157 -0
  411. package/src/widgets/__tests__/matrix_test.jsx +84 -0
  412. package/src/widgets/__tests__/number-line_test.jsx +81 -0
  413. package/src/widgets/__tests__/numeric-input_test.jsx +574 -0
  414. package/src/widgets/__tests__/orderer_test.jsx +75 -0
  415. package/src/widgets/__tests__/passage-ref_test.jsx +166 -0
  416. package/src/widgets/__tests__/passage_test.jsx +133 -0
  417. package/src/widgets/__tests__/radio/base-radio_test.jsx +82 -0
  418. package/src/widgets/__tests__/radio_test.jsx +651 -0
  419. package/src/widgets/__tests__/renderQuestion.jsx +66 -0
  420. package/src/widgets/__tests__/unit_test.jsx +144 -0
  421. package/src/widgets/__tests__/video_test.jsx +55 -0
  422. package/src/widgets/categorizer.jsx +338 -0
  423. package/src/widgets/cs-program.jsx +227 -0
  424. package/src/widgets/definition.jsx +141 -0
  425. package/src/widgets/dropdown.jsx +143 -0
  426. package/src/widgets/explanation.jsx +315 -0
  427. package/src/widgets/expression.jsx +652 -0
  428. package/src/widgets/graded-group-answer-bar.jsx +152 -0
  429. package/src/widgets/graded-group-set.jsx +285 -0
  430. package/src/widgets/graded-group.jsx +448 -0
  431. package/src/widgets/grapher/util.jsx +806 -0
  432. package/src/widgets/grapher.jsx +663 -0
  433. package/src/widgets/group.jsx +213 -0
  434. package/src/widgets/iframe.jsx +198 -0
  435. package/src/widgets/image.jsx +310 -0
  436. package/src/widgets/input-number.jsx +411 -0
  437. package/src/widgets/interaction/arrow-picker.jsx +39 -0
  438. package/src/widgets/interaction/color-picker.jsx +69 -0
  439. package/src/widgets/interaction/dash-picker.jsx +46 -0
  440. package/src/widgets/interaction/element-container.jsx +97 -0
  441. package/src/widgets/interaction.jsx +742 -0
  442. package/src/widgets/interactive-graph.jsx +2820 -0
  443. package/src/widgets/label-image/__stories__/answer-choices.stories.jsx +93 -0
  444. package/src/widgets/label-image/__stories__/marker.stories.jsx +172 -0
  445. package/src/widgets/label-image/answer-choices.jsx +311 -0
  446. package/src/widgets/label-image/marker.jsx +365 -0
  447. package/src/widgets/label-image/types.js +33 -0
  448. package/src/widgets/label-image.jsx +841 -0
  449. package/src/widgets/label-image_test.js +840 -0
  450. package/src/widgets/lights-puzzle.jsx +356 -0
  451. package/src/widgets/matcher.jsx +271 -0
  452. package/src/widgets/matrix.jsx +616 -0
  453. package/src/widgets/measurer.jsx +215 -0
  454. package/src/widgets/molecule/__tests__/layout_test.jsx +159 -0
  455. package/src/widgets/molecule/__tests__/parser_test.jsx +142 -0
  456. package/src/widgets/molecule/molecule-drawing.jsx +175 -0
  457. package/src/widgets/molecule/molecule-layout.jsx +367 -0
  458. package/src/widgets/molecule/smiles-parser.jsx +300 -0
  459. package/src/widgets/molecule.jsx +172 -0
  460. package/src/widgets/number-line.jsx +858 -0
  461. package/src/widgets/numeric-input.jsx +622 -0
  462. package/src/widgets/orderer.jsx +753 -0
  463. package/src/widgets/passage/__tests__/passage-markdown_test.jsx +382 -0
  464. package/src/widgets/passage/get-line-height-for-node.js +10 -0
  465. package/src/widgets/passage/passage-markdown.jsx +416 -0
  466. package/src/widgets/passage-ref-target.jsx +70 -0
  467. package/src/widgets/passage-ref.jsx +198 -0
  468. package/src/widgets/passage.jsx +601 -0
  469. package/src/widgets/plotter.jsx +1198 -0
  470. package/src/widgets/radio/__stories__/base-radio.stories.jsx +40 -0
  471. package/src/widgets/radio/__stories__/choice-icon.stories.jsx +157 -0
  472. package/src/widgets/radio/__stories__/choice-none-above.stories.jsx +26 -0
  473. package/src/widgets/radio/__stories__/cross-out-button.stories.jsx +64 -0
  474. package/src/widgets/radio/__stories__/cross-out-menu.stories.jsx +59 -0
  475. package/src/widgets/radio/__stories__/cross-out-tooltip.stories.jsx +59 -0
  476. package/src/widgets/radio/__stories__/focus-ring.stories.jsx +38 -0
  477. package/src/widgets/radio/__stories__/option-status.stories.jsx +118 -0
  478. package/src/widgets/radio/__stories__/toggleable-radio-button.stories.jsx +28 -0
  479. package/src/widgets/radio/base-radio.jsx +642 -0
  480. package/src/widgets/radio/choice-icon.jsx +468 -0
  481. package/src/widgets/radio/choice-none-above.jsx +54 -0
  482. package/src/widgets/radio/choice.jsx +692 -0
  483. package/src/widgets/radio/choice.jsx.fixture.js +64 -0
  484. package/src/widgets/radio/cross-out-button.jsx +136 -0
  485. package/src/widgets/radio/cross-out-menu-wrapper.jsx +492 -0
  486. package/src/widgets/radio/cross-out-tooltip.jsx +129 -0
  487. package/src/widgets/radio/focus-ring.jsx +51 -0
  488. package/src/widgets/radio/option-status.jsx +89 -0
  489. package/src/widgets/radio/toggleable-radio-button.jsx +133 -0
  490. package/src/widgets/radio/util.js +32 -0
  491. package/src/widgets/radio/util_test.js +19 -0
  492. package/src/widgets/radio/widget.jsx +470 -0
  493. package/src/widgets/radio.jsx +156 -0
  494. package/src/widgets/reaction-diagram.jsx +137 -0
  495. package/src/widgets/sequence.jsx +140 -0
  496. package/src/widgets/simulator.jsx +808 -0
  497. package/src/widgets/sorter.jsx +146 -0
  498. package/src/widgets/table.jsx +394 -0
  499. package/src/widgets/transformer.jsx +2876 -0
  500. package/src/widgets/unit.jsx +372 -0
  501. package/src/widgets/video-transcript-link.jsx +84 -0
  502. package/src/widgets/video-transcript-link_test.js +211 -0
  503. package/src/widgets/video.jsx +126 -0
  504. package/src/widgets.js +431 -0
  505. package/src/zoom.js +539 -0
  506. package/README.md +0 -3
  507. package/src/__tests__/index.test.js +0 -14
@@ -0,0 +1,273 @@
1
+ // @flow
2
+ /**
3
+ * Movable
4
+ *
5
+ * A Movable Something, that sends onMove events based on the
6
+ * mouse coordinate (graphie unscaled, non-pixel-value) of the
7
+ * move.
8
+ *
9
+ * Other MovableThings should generally have a Movable field, and
10
+ * let this class handle all of the virtual mouse events, and then
11
+ * take appropriate action in onMoveStart, onMove, onMoveEnd
12
+ */
13
+ import {point as kpoint} from "@khanacademy/kmath";
14
+ import $ from "jquery";
15
+ import _ from "underscore";
16
+
17
+ import InteractiveUtil from "./interactive-util.js";
18
+
19
+ const normalizeOptions = InteractiveUtil.normalizeOptions;
20
+
21
+ const assert = InteractiveUtil.assert;
22
+
23
+ // state parameters that should be converted into an array of
24
+ // functions
25
+ const FUNCTION_ARRAY_OPTIONS = [
26
+ "add",
27
+ "modify",
28
+ "draw",
29
+ "remove",
30
+ "onMoveStart",
31
+ "onMove",
32
+ "onMoveEnd",
33
+ "onClick",
34
+ ];
35
+
36
+ // Default "props" and "state". Both are added to this.state and
37
+ // receive magic getter methods (this.isHovering() etc).
38
+ // However, properties in DEFAULT_PROPS are updated on `modify()`,
39
+ // while those in DEFAULT_STATE persist and are not updated.
40
+ // Things that the user might want to change should be on "props",
41
+ // while things used to render the movable should be on "state".
42
+ const DEFAULT_PROPS = {
43
+ cursor: null,
44
+ };
45
+ const DEFAULT_STATE = {
46
+ added: false,
47
+ isHovering: false,
48
+ isMouseOver: false,
49
+ isDragging: false,
50
+ mouseTarget: null,
51
+ };
52
+
53
+ const Movable = function (graphie: $FlowFixMe, options: $FlowFixMe): void {
54
+ _.extend(this, {
55
+ graphie: graphie,
56
+ state: {
57
+ // Set here because this must be unique for each instance
58
+ id: _.uniqueId("movable"),
59
+ },
60
+ });
61
+
62
+ // We only set DEFAULT_STATE once, here
63
+ this.modify(_.extend({}, DEFAULT_STATE, options));
64
+ };
65
+
66
+ InteractiveUtil.createGettersFor(
67
+ Movable,
68
+ _.extend({}, DEFAULT_PROPS, DEFAULT_STATE),
69
+ );
70
+ InteractiveUtil.addMovableHelperMethodsTo(Movable);
71
+
72
+ _.extend(Movable.prototype, {
73
+ cloneState: function () {
74
+ return _.clone(this.state);
75
+ },
76
+
77
+ _createDefaultState: function () {
78
+ return _.extend(
79
+ {
80
+ id: this.state.id,
81
+ add: [],
82
+ modify: [],
83
+ draw: [],
84
+ remove: [],
85
+ onMoveStart: [],
86
+ onMove: [],
87
+ onMoveEnd: [],
88
+ onClick: [],
89
+
90
+ // We only update props here, because we want things on state to
91
+ // be persistent, and updated appropriately in modify()
92
+ },
93
+ DEFAULT_PROPS,
94
+ );
95
+ },
96
+
97
+ /**
98
+ * Resets the object to its state as if it were constructed with
99
+ * `options` originally. The only state maintained is `state.id`
100
+ *
101
+ * Analogous to React.js's replaceProps
102
+ */
103
+ modify: function (options) {
104
+ this.update(_.extend({}, this._createDefaultState(), options));
105
+ },
106
+
107
+ /**
108
+ * Simulates a mouse grab event on the movable object.
109
+ */
110
+ grab: function (coord) {
111
+ assert(kpoint.is(coord));
112
+ const self = this;
113
+ const graphie = self.graphie;
114
+ const state = self.state;
115
+
116
+ state.isHovering = true;
117
+ state.isDragging = true;
118
+ graphie.isDragging = true;
119
+
120
+ const startMouseCoord = coord;
121
+ let prevMouseCoord = startMouseCoord;
122
+ self._fireEvent(state.onMoveStart, startMouseCoord, startMouseCoord);
123
+
124
+ const moveHandler = function (e) {
125
+ e.preventDefault();
126
+
127
+ const mouseCoord = graphie.getMouseCoord(e);
128
+ self._fireEvent(state.onMove, mouseCoord, prevMouseCoord);
129
+ self.draw();
130
+ prevMouseCoord = mouseCoord;
131
+ };
132
+
133
+ const upHandler = function (e) {
134
+ $(document).unbind("vmousemove", moveHandler);
135
+ $(document).unbind("vmouseup", upHandler);
136
+ if (state.isHovering) {
137
+ self._fireEvent(state.onClick, prevMouseCoord, startMouseCoord);
138
+ }
139
+ state.isHovering = self.state.isMouseOver;
140
+ state.isDragging = false;
141
+ graphie.isDragging = false;
142
+ self._fireEvent(state.onMoveEnd, prevMouseCoord, startMouseCoord);
143
+ self.draw();
144
+ };
145
+
146
+ $(document).bind("vmousemove", moveHandler);
147
+ $(document).bind("vmouseup", upHandler);
148
+ },
149
+
150
+ /**
151
+ * Adjusts constructor parameters without changing previous settings
152
+ * for any option not specified
153
+ *
154
+ * Analogous to React.js's setProps
155
+ */
156
+ update: function (options) {
157
+ const self = this;
158
+ const graphie = self.graphie;
159
+
160
+ const prevState = self.cloneState();
161
+ const state = _.extend(
162
+ self.state,
163
+ normalizeOptions(FUNCTION_ARRAY_OPTIONS, options),
164
+ );
165
+
166
+ // the invisible shape in front of the point that gets mouse events
167
+ if (state.mouseTarget && !prevState.mouseTarget) {
168
+ let $mouseTarget;
169
+ if (state.mouseTarget.getMouseTarget) {
170
+ $mouseTarget = $(state.mouseTarget.getMouseTarget());
171
+ } else {
172
+ $mouseTarget = $(state.mouseTarget[0]);
173
+ }
174
+
175
+ const isMouse = !("ontouchstart" in window);
176
+
177
+ if (isMouse) {
178
+ $mouseTarget.on("vmouseover", function () {
179
+ state.isMouseOver = true;
180
+ if (!graphie.isDragging) {
181
+ state.isHovering = true;
182
+ }
183
+ if (self.state.added) {
184
+ // Avoid drawing if the point has been removed
185
+ self.draw();
186
+ }
187
+ });
188
+
189
+ $mouseTarget.on("vmouseout", function () {
190
+ state.isMouseOver = false;
191
+ if (!state.isDragging) {
192
+ state.isHovering = false;
193
+ }
194
+ if (self.state.added) {
195
+ // Avoid drawing if the point has been removed
196
+ self.draw();
197
+ }
198
+ });
199
+ }
200
+
201
+ // Prevent the page from scrolling when we grab and drag the
202
+ // movable object on a mobile device.
203
+ $mouseTarget[0].addEventListener(
204
+ "touchstart",
205
+ function (event) {
206
+ event.preventDefault();
207
+ },
208
+ {passive: false},
209
+ );
210
+
211
+ $mouseTarget.on("vmousedown", function (e) {
212
+ if (e.which !== 0 && e.which !== 1) {
213
+ return;
214
+ }
215
+ e.preventDefault();
216
+
217
+ const mouseCoord = graphie.getMouseCoord(e);
218
+ self.grab(mouseCoord);
219
+ });
220
+ }
221
+
222
+ if (state.mouseTarget && state.cursor !== undefined) {
223
+ let $mouseTarget;
224
+ if (state.mouseTarget.getMouseTarget) {
225
+ $mouseTarget = $(state.mouseTarget.getMouseTarget());
226
+ } else {
227
+ $mouseTarget = $(state.mouseTarget[0]);
228
+ }
229
+
230
+ // "" removes the css cursor if state.cursor is null
231
+ $mouseTarget.css("cursor", state.cursor || "");
232
+ }
233
+
234
+ // Trigger an add event if this hasn't been added before
235
+ if (!state.added) {
236
+ self._fireEvent(state.modify, self.cloneState(), {});
237
+ state.added = true;
238
+
239
+ // Update the state for `added` and in case the add event
240
+ // changed it
241
+ self.prevState = self.cloneState();
242
+ }
243
+
244
+ // Trigger a modify event
245
+ self._fireEvent(state.modify, self.cloneState(), self.prevState);
246
+ },
247
+
248
+ remove: function () {
249
+ this.state.added = false;
250
+ this._fireEvent(this.state.remove);
251
+ if (this.state.mouseTarget) {
252
+ $(this.state.mouseTarget).off();
253
+ this.state.mouseTarget.remove();
254
+ this.state.mouseTarget = null;
255
+ }
256
+ },
257
+
258
+ // Change z-order to back
259
+ toBack: function () {
260
+ if (this.state.mouseTarget) {
261
+ this.state.mouseTarget.toBack();
262
+ }
263
+ },
264
+
265
+ // Change z-order to front
266
+ toFront: function () {
267
+ if (this.state.mouseTarget) {
268
+ this.state.mouseTarget.toFront();
269
+ }
270
+ },
271
+ });
272
+
273
+ export default Movable;
@@ -0,0 +1,79 @@
1
+ // @flow
2
+ /**
3
+ * A work-in-progress of _ methods for objects.
4
+ * That is, they take an object as a parameter,
5
+ * and return an object instead of an array.
6
+ *
7
+ * TODO(aria): Move this out of interactive2
8
+ */
9
+
10
+ import _ from "underscore";
11
+
12
+ /**
13
+ * Does a pluck on keys inside objects in an object
14
+ *
15
+ * Ex:
16
+ * tools = {
17
+ * translation: {
18
+ * enabled: true
19
+ * },
20
+ * rotation: {
21
+ * enabled: false
22
+ * }
23
+ * };
24
+ * pluckObject(tools, "enabled") returns {
25
+ * translation: true
26
+ * rotation: false
27
+ * }
28
+ */
29
+ const pluck = function (table: $FlowFixMe, subKey: string): $FlowFixMe {
30
+ return _.object(
31
+ _.map(table, function (value, key) {
32
+ return [key, value[subKey]];
33
+ }),
34
+ );
35
+ };
36
+
37
+ /**
38
+ * Maps an object to an object
39
+ *
40
+ * > mapObject({a: '1', b: '2'}, (value, key) => {
41
+ * return value + 1;
42
+ * });
43
+ * {a: 2, b: 3}
44
+ */
45
+ const mapObject = function <K: string, V, U>(
46
+ obj: {|[K]: V|},
47
+ lambda: (V, K) => U,
48
+ ): {|[K]: U|} {
49
+ const result = {};
50
+ _.each(_.keys(obj), function (key) {
51
+ result[key] = lambda(obj[key], key);
52
+ });
53
+ return result;
54
+ };
55
+
56
+ /**
57
+ * Maps an array to an object
58
+ *
59
+ * > mapObjectFromArray(['a', 'b'], function(elem) {
60
+ * return elem + elem;
61
+ * });
62
+ * {a: 'aa', b: 'bb'}
63
+ */
64
+ const mapObjectFromArray = function <K: string, V>(
65
+ arr: $ReadOnlyArray<K>,
66
+ lambda: (K) => V,
67
+ ): {|[K]: V|} {
68
+ const result = {};
69
+ _.each(arr, function (elem) {
70
+ result[elem] = lambda(elem);
71
+ });
72
+ return result;
73
+ };
74
+
75
+ export default {
76
+ pluck: pluck,
77
+ mapObject: mapObject,
78
+ mapObjectFromArray: mapObjectFromArray,
79
+ };
@@ -0,0 +1,3 @@
1
+ // @flow
2
+ export type Coord = [number, number];
3
+ export type Line = [Coord, Coord];
@@ -0,0 +1,86 @@
1
+ /* eslint-disable @babel/no-invalid-this */
2
+ // @flow
3
+ /**
4
+ * Default methods for a wrapped movable.
5
+ */
6
+
7
+ import {vector as kvector} from "@khanacademy/kmath";
8
+ import $ from "jquery";
9
+ import _ from "underscore";
10
+
11
+ import InteractiveUtil from "./interactive-util.js";
12
+ import objective_ from "./objective_.js";
13
+
14
+ /*
15
+ * These functions, when called on the wrapped object, simply pass the
16
+ * arguments to the underlying Raphael object.
17
+ */
18
+ const PASS_TO_RAPHAEL = ["attr", "animate"];
19
+
20
+ const WrappedDefaults: $FlowFixMe = _.extend(
21
+ {
22
+ transform: function (transformation) {
23
+ const prefixedTransform = InteractiveUtil.getPrefixedTransform();
24
+ this.wrapper.style[prefixedTransform] = transformation;
25
+ },
26
+
27
+ toFront: function () {
28
+ const parentNode = this.wrapper.parentNode;
29
+ // TODO(emily): Sometimes, we call `.remove()` but then hold a
30
+ // reference to this object, and sometimes call `.toFront` on it.
31
+ // Notably, this happens in the reflection transformation in the
32
+ // Transformer widget. This is a hacky fix. Make this less bad.
33
+ if (parentNode) {
34
+ parentNode.appendChild(this.wrapper);
35
+ }
36
+ },
37
+
38
+ toBack: function () {
39
+ const parentNode = this.wrapper.parentNode;
40
+ if (parentNode.firstChild !== this.wrapper) {
41
+ parentNode.insertBefore(this.wrapper, parentNode.firstChild);
42
+ }
43
+ },
44
+
45
+ remove: function () {
46
+ this.visibleShape.remove();
47
+ $(this.wrapper).remove();
48
+ },
49
+
50
+ getMouseTarget: function () {
51
+ return this.visibleShape[0];
52
+ },
53
+
54
+ moveTo: function (point) {
55
+ const delta = kvector.subtract(
56
+ this.graphie.scalePoint(point),
57
+ this.graphie.scalePoint(this.initialPoint),
58
+ );
59
+ const do3dTransform = InteractiveUtil.getCanUse3dTransform();
60
+ const transformation =
61
+ "translateX(" +
62
+ delta[0] +
63
+ "px) " +
64
+ "translateY(" +
65
+ delta[1] +
66
+ "px)" +
67
+ (do3dTransform ? " translateZ(0)" : "");
68
+ this.transform(transformation);
69
+ },
70
+
71
+ hide: function () {
72
+ this.visibleShape.hide();
73
+ },
74
+
75
+ show: function () {
76
+ this.visibleShape.show();
77
+ },
78
+ },
79
+ objective_.mapObjectFromArray(PASS_TO_RAPHAEL, function (attribute) {
80
+ return function () {
81
+ this.visibleShape[attribute](...arguments);
82
+ };
83
+ }),
84
+ );
85
+
86
+ export default WrappedDefaults;
@@ -0,0 +1,87 @@
1
+ // @flow
2
+ import {vector as kvector} from "@khanacademy/kmath";
3
+ import _ from "underscore";
4
+
5
+ import InteractiveUtil from "./interactive-util.js";
6
+ import WrappedDefaults from "./wrapped-defaults.js";
7
+
8
+ import type {Coord} from "./types.js";
9
+
10
+ const DEFAULT_OPTIONS = {
11
+ maxScale: 1,
12
+ mouselayer: false,
13
+ shadow: false,
14
+ disableMouseEventsOnWrapper: false,
15
+ };
16
+
17
+ const WrappedEllipse = function (
18
+ graphie: $FlowFixMe,
19
+ center: Coord,
20
+ radii: [number, number],
21
+ options: $FlowFixMe,
22
+ ) {
23
+ options = _.extend({}, DEFAULT_OPTIONS, options);
24
+
25
+ // Add `wrapper`, `visibleShape`, and remaining properties.
26
+ const fixedEllipse = graphie.fixedEllipse(
27
+ center,
28
+ radii,
29
+ options.maxScale,
30
+ options.padding,
31
+ );
32
+ _.extend(this, fixedEllipse, {
33
+ graphie: graphie,
34
+ initialPoint: center,
35
+ });
36
+
37
+ if (options.interactiveKindForTesting) {
38
+ this.wrapper.setAttribute(
39
+ "data-interactive-kind-for-testing",
40
+ options.interactiveKindForTesting,
41
+ );
42
+ }
43
+
44
+ // Add to appropriate graphie layer
45
+ if (options.mouselayer) {
46
+ // Disable browser handling of all panning and zooming gestures on the
47
+ // movable wrapper so that when moved the browser does not scroll page
48
+ this.wrapper.style.touchAction = "none";
49
+
50
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
51
+ } else {
52
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
53
+ }
54
+
55
+ if (options.shadow) {
56
+ const filter = "drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";
57
+ const wrapper = this.wrapper;
58
+ wrapper.style.webkitFilter = filter;
59
+ wrapper.style.filter = filter;
60
+
61
+ this.moveTo = function (point) {
62
+ const delta = kvector.subtract(
63
+ this.graphie.scalePoint(point),
64
+ this.graphie.scalePoint(this.initialPoint),
65
+ );
66
+ const do3dTransform = InteractiveUtil.getCanUse3dTransform();
67
+ const transform =
68
+ "translateX(" +
69
+ Math.round(delta[0]) +
70
+ "px) " +
71
+ "translateY(" +
72
+ Math.round(delta[1]) +
73
+ "px)" +
74
+ (do3dTransform ? " translateZ(0)" : "");
75
+ this.transform(transform);
76
+ };
77
+ }
78
+
79
+ if (options.disableMouseEventsOnWrapper) {
80
+ this.wrapper.style.pointerEvents = "none";
81
+ this.visibleShape.node.style.pointerEvents = "auto";
82
+ }
83
+ };
84
+
85
+ _.extend(WrappedEllipse.prototype, WrappedDefaults);
86
+
87
+ export default WrappedEllipse;
@@ -0,0 +1,109 @@
1
+ // @flow
2
+ import {point as kpoint, vector as kvector} from "@khanacademy/kmath";
3
+ import _ from "underscore";
4
+
5
+ import KhanMath from "../util/math.js";
6
+
7
+ import InteractiveUtil from "./interactive-util.js";
8
+ import WrappedDefaults from "./wrapped-defaults.js";
9
+
10
+ import type {Coord} from "./types.js";
11
+
12
+ const DEFAULT_OPTIONS = {
13
+ thickness: 2,
14
+ mouselayer: false,
15
+ };
16
+
17
+ const WrappedLine = function (
18
+ graphie: $FlowFixMe,
19
+ start: Coord,
20
+ end: Coord,
21
+ options: $FlowFixMe,
22
+ ) {
23
+ options = _.extend({}, DEFAULT_OPTIONS, options);
24
+
25
+ // Always make the line as large as possible and horizontal; this
26
+ // simplifies a lot of the transforms, e.g., we can rotate by exactly the
27
+ // angle of the argument points in `moveTo`.
28
+ const initialStart = [graphie.range[0][0], 0];
29
+ const initialEnd = [graphie.range[0][1], 0];
30
+
31
+ // Add `wrapper` and `visibleShape`
32
+ _.extend(
33
+ this,
34
+ graphie.fixedLine(initialStart, initialEnd, options.thickness),
35
+ );
36
+
37
+ if (options.interactiveKindForTesting) {
38
+ this.wrapper.setAttribute(
39
+ "data-interactive-kind-for-testing",
40
+ options.interactiveKindForTesting,
41
+ );
42
+ }
43
+
44
+ this.visibleShape.attr(options.normalStyle);
45
+
46
+ // Save properties for computing transformations
47
+ _.extend(this, {
48
+ graphie: graphie,
49
+ initialPoint: graphie.scalePoint(initialStart),
50
+ initialLength: kpoint.distanceToPoint(
51
+ graphie.scalePoint(initialStart),
52
+ graphie.scalePoint(initialEnd),
53
+ ),
54
+ });
55
+
56
+ // Add to appropriate graphie layer
57
+ if (options.mouselayer) {
58
+ // Disable browser handling of all panning and zooming gestures on the
59
+ // movable wrapper so that when moved the browser does not scroll page
60
+ this.wrapper.style.touchAction = "none";
61
+
62
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
63
+ } else {
64
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
65
+ }
66
+
67
+ // Move to argument points
68
+ this.moveTo(start, end);
69
+ };
70
+
71
+ _.extend(WrappedLine.prototype, WrappedDefaults, {
72
+ getMouseTarget: function () {
73
+ return this.wrapper;
74
+ },
75
+
76
+ moveTo: function (start, end) {
77
+ const scaledStart = this.graphie.scalePoint(start);
78
+ const scaledEnd = this.graphie.scalePoint(end);
79
+
80
+ // Compute transformation parameters
81
+ const polarDiff = kvector.polarDegFromCart(
82
+ kvector.subtract(scaledEnd, scaledStart),
83
+ );
84
+ const lineLength = polarDiff[0];
85
+ const angle = KhanMath.bound(polarDiff[1]);
86
+ const delta = kvector.subtract(scaledStart, this.initialPoint);
87
+ const scale = KhanMath.bound(lineLength / this.initialLength);
88
+
89
+ // Construct and apply transformation string
90
+ const do3dTransform = InteractiveUtil.getCanUse3dTransform();
91
+ const transformation =
92
+ "translateX(" +
93
+ delta[0] +
94
+ "px) " +
95
+ "translateY(" +
96
+ delta[1] +
97
+ "px) " +
98
+ (do3dTransform ? " translateZ(0)" : "") +
99
+ "rotate(" +
100
+ angle +
101
+ "deg) " +
102
+ "scaleX(" +
103
+ scale +
104
+ ") scaleY(1)";
105
+ this.transform(transformation);
106
+ },
107
+ });
108
+
109
+ export default WrappedLine;
@@ -0,0 +1,47 @@
1
+ // @flow
2
+ import _ from "underscore";
3
+
4
+ import WrappedDefaults from "./wrapped-defaults.js";
5
+
6
+ import type {Coord} from "./types.js";
7
+
8
+ const DEFAULT_OPTIONS = {
9
+ center: null, // gets ignored in `graphie.fixedPath` if `null`
10
+ createPath: null, // gets defaulted in `graphie.fixedPath` if `null`
11
+ mouselayer: false,
12
+ };
13
+
14
+ const WrappedPath = function (
15
+ graphie: $FlowFixMe,
16
+ points: $ReadOnlyArray<Coord>,
17
+ options: $FlowFixMe,
18
+ ) {
19
+ options = _.extend({}, DEFAULT_OPTIONS, options);
20
+
21
+ // Add `wrapper` and `visibleShape`
22
+ _.extend(
23
+ this,
24
+ graphie.fixedPath(points, options.center, options.createPath),
25
+ );
26
+
27
+ // Add remaining properties
28
+ _.extend(this, {
29
+ graphie: graphie,
30
+ initialPoint: graphie.scalePoint(_.head(points)),
31
+ });
32
+
33
+ // Add to appropriate graphie layer
34
+ if (options.mouselayer) {
35
+ // Disable browser handling of all panning and zooming gestures on the
36
+ // movable wrapper so that when moved the browser does not scroll page
37
+ this.wrapper.style.touchAction = "none";
38
+
39
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
40
+ } else {
41
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
42
+ }
43
+ };
44
+
45
+ _.extend(WrappedPath.prototype, WrappedDefaults);
46
+
47
+ export default WrappedPath;