@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,603 @@
1
+ // @flow
2
+ /**
3
+ * Creates and adds a point to the graph that can be dragged around.
4
+ * It allows constraints on its movement and draws when moves happen.
5
+ *
6
+ * Options can be passed to the constructor to control how the point behaves:
7
+ * coord: [x, y]
8
+ * The initial position of the point
9
+ * pointSize:
10
+ * changes the size of the point. defaults to 4
11
+ * static: boolean
12
+ * draw the point, but don't let it be interactable
13
+ * cursor: "move", "pointer"
14
+ * css cursor for this point
15
+ * add: [function(state)]
16
+ * called immediately when this movablePoint is added
17
+ * default: apply any constraints and draw
18
+ * draw: [function(prevState, currentState)]
19
+ * drawing functions. default to [basic, highlight]
20
+ * remove: [function(state)]
21
+ * called when this movablePoint is removed
22
+ * onMoveStart: [function(coord)]
23
+ * called when this point is clicked on
24
+ * constraints: [function(coord)]
25
+ * called when this point is dragged
26
+ * return true or nothing to accept the move
27
+ * return false to cancel the move
28
+ * return an [x, y] coordinate to override the move
29
+ * onMove: [function(coord)]
30
+ * called after all constraints functions pass and the point
31
+ * is moved to a new location
32
+ * onMoveEnd: [function(coord)]
33
+ * called when the mouse is released from a click or move
34
+ * onClick: [function(coord)]
35
+ * called when someone mouses down, doesn't move the point,
36
+ * and mouses up.
37
+ * normalStyle:
38
+ * the raphael/graphie style of the point when not hovering
39
+ * highlightStyle:
40
+ * the raphael/graphie style of the point when hovering, if
41
+ * MovablePoint.draw.highlight is used
42
+ *
43
+ * This creates a MovablePoint object with the following methods:
44
+ * setCoord: [x, y]
45
+ * changes the point's coordinate
46
+ * draw:
47
+ * redraws the coord
48
+ * modify: {options}
49
+ * modifies the original options passed to the point
50
+ * remove:
51
+ * removes the point from graphie
52
+ */
53
+ import {point as kpoint, vector as kvector} from "@khanacademy/kmath";
54
+ import * as React from "react";
55
+ import * as ReactDOM from "react-dom";
56
+ import _ from "underscore";
57
+
58
+ import InlineIcon from "../components/inline-icon.jsx";
59
+ import {iconTrash} from "../icon-paths.js";
60
+ import KhanColors from "../util/colors.js";
61
+ import Tex from "../util/tex.js";
62
+
63
+ import InteractiveUtil from "./interactive-util.js";
64
+ import MovablePointOptions from "./movable-point-options.js";
65
+ import objective_ from "./objective_.js";
66
+ import WrappedEllipse from "./wrapped-ellipse.js";
67
+
68
+ const assert = InteractiveUtil.assert;
69
+ const normalizeOptions = InteractiveUtil.normalizeOptions;
70
+
71
+ const {processMath} = Tex;
72
+
73
+ // State parameters that should be converted into an array of
74
+ // functions
75
+ const FUNCTION_ARRAY_OPTIONS = _.keys(MovablePointOptions);
76
+
77
+ // Default "props" and "state". Both are added to this.state and
78
+ // receive magic getter methods (this.coord() etc).
79
+ // However, properties in DEFAULT_PROPS are updated on `modify()`,
80
+ // while those in DEFAULT_STATE persist and are not updated.
81
+ // Things that the user might want to change should be on "props",
82
+ // while things used to render the point should be on "state".
83
+ const DEFAULT_PROPS = {
84
+ coord: [0, 0],
85
+ pointSize: 4,
86
+ static: false,
87
+ cursor: "move",
88
+ normalStyle: null, // turned into an object in this.modify
89
+ highlightStyle: null, // likewise
90
+ shadow: false,
91
+ tooltip: false,
92
+ };
93
+ const DEFAULT_STATE = {
94
+ added: false,
95
+ hasMoved: false,
96
+ visibleShape: null,
97
+ outOfBounds: false,
98
+ mouseTarget: null,
99
+ touchOffset: null,
100
+ };
101
+
102
+ const tooltipResetFunctions = [];
103
+
104
+ const MovablePoint = function (
105
+ graphie: $FlowFixMe,
106
+ movable: $FlowFixMe,
107
+ options: $FlowFixMe,
108
+ ) {
109
+ _.extend(this, {
110
+ graphie,
111
+ movable,
112
+ state: {
113
+ // Set here because this must be unique for each instance
114
+ id: _.uniqueId("movablePoint"),
115
+ },
116
+ });
117
+
118
+ // We only set DEFAULT_STATE once, here
119
+ this.modify(_.extend({}, DEFAULT_STATE, options));
120
+ };
121
+
122
+ _.extend(MovablePoint, MovablePointOptions);
123
+ InteractiveUtil.createGettersFor(
124
+ MovablePoint,
125
+ _.extend({}, DEFAULT_PROPS, DEFAULT_STATE),
126
+ );
127
+ InteractiveUtil.addMovableHelperMethodsTo(MovablePoint);
128
+
129
+ _.extend(MovablePoint.prototype, {
130
+ cloneState: function () {
131
+ return _.extend(this.movable.cloneState(), this.state);
132
+ },
133
+
134
+ _createDefaultState: function () {
135
+ return _.extend(
136
+ {
137
+ id: this.state.id,
138
+ },
139
+ normalizeOptions(
140
+ FUNCTION_ARRAY_OPTIONS,
141
+ // Defaults are copied from MovablePointOptions.*.standard
142
+ // These defaults are set here instead of DEFAULT_PROPS/STATE
143
+ // because they:
144
+ // - are objects, not primitives (and need a deeper copy)
145
+ // - they don't need getters created for them
146
+ // TODO(jack): Consider "default" once we es3ify perseus
147
+ objective_.pluck(MovablePointOptions, "standard"),
148
+
149
+ // We only update props here, because we want things on state to
150
+ // be persistent, and updated appropriately in modify()
151
+ ),
152
+ DEFAULT_PROPS,
153
+ );
154
+ },
155
+
156
+ /**
157
+ * Resets the object to its state as if it were constructed with
158
+ * `options` originally. state not on DEFAULT_PROPS is maintained.
159
+ *
160
+ * Analogous to React.js's replaceProps
161
+ */
162
+ modify: function (options) {
163
+ this.update(_.extend(this._createDefaultState(), options));
164
+ },
165
+
166
+ /**
167
+ * Displays a tooltip above the point, replacing any previous contents. If
168
+ * there is no tooltip initialized, adds the tooltip.
169
+ *
170
+ * If the type of contents is string, the contents will be rendered with
171
+ * KaTeX. Otherwise, the content will be assumed to be a DOM node and will
172
+ * be appended inside the tooltip.
173
+ */
174
+ _showTooltip: function (contents) {
175
+ if (!this._tooltip) {
176
+ this._tooltip = document.createElement("div");
177
+ this._tooltip.className = "tooltip-content";
178
+ this.state.visibleShape.wrapper.className = "tooltip";
179
+ this.state.visibleShape.wrapper.appendChild(this._tooltip);
180
+
181
+ // Only one tooltip should be displayed at a time, so store a list
182
+ // of all the tooltips initialized.
183
+ tooltipResetFunctions.push(() => {
184
+ if (this.state.added) {
185
+ this._hideTooltip();
186
+ }
187
+ });
188
+ }
189
+
190
+ if (this._tooltip.firstChild) {
191
+ this._tooltip.removeChild(this._tooltip.firstChild);
192
+ }
193
+
194
+ this.state.visibleShape.wrapper.className = "tooltip visible";
195
+ this._tooltip.appendChild(document.createElement("span"));
196
+
197
+ if (typeof contents === "string") {
198
+ processMath(this._tooltip.firstChild, contents, false);
199
+ } else if (typeof contents === "function") {
200
+ contents(this._tooltip.firstChild);
201
+ } else {
202
+ this._tooltip.firstChild.appendChild(contents);
203
+ }
204
+ },
205
+
206
+ _hideTooltip: function () {
207
+ if (this._tooltip) {
208
+ // Without the visible class, tooltips have display: none set
209
+ this.state.visibleShape.wrapper.className = "tooltip";
210
+ }
211
+ },
212
+
213
+ /**
214
+ * Adjusts constructor parameters without changing previous settings
215
+ * for any option not specified
216
+ *
217
+ * Analogous to React.js's setProps
218
+ */
219
+ update: function (options) {
220
+ const self = this;
221
+ const graphie = self.graphie;
222
+ const state = _.extend(
223
+ self.state,
224
+ normalizeOptions(FUNCTION_ARRAY_OPTIONS, options),
225
+ );
226
+
227
+ assert(kpoint.is(state.coord));
228
+
229
+ // Default things inside the state.normalStyle object, because
230
+ // _.extend is not deep.
231
+ // We use _.extend instead of _.defaults because we don't want
232
+ // to modify the passed-in copy (especially if it's from
233
+ // DEFAULT_PROPS/STATE!)
234
+ const normalColor = state.static
235
+ ? KhanColors.DYNAMIC
236
+ : KhanColors.INTERACTIVE;
237
+ state.normalStyle = _.extend(
238
+ {
239
+ fill: normalColor,
240
+ stroke: normalColor,
241
+ scale: 1,
242
+ },
243
+ state.normalStyle,
244
+ );
245
+
246
+ state.highlightStyle = _.extend(
247
+ {
248
+ fill: KhanColors.INTERACTING,
249
+ stroke: KhanColors.INTERACTING,
250
+ scale: 2,
251
+ },
252
+ state.highlightStyle,
253
+ );
254
+
255
+ if (!state.static) {
256
+ // the invisible shape in front of the point that gets mouse events
257
+ if (!state.mouseTarget) {
258
+ const center = self.state.coord;
259
+ const radii = graphie.unscaleVector(24);
260
+ const options = {
261
+ mouselayer: true,
262
+ padding: 0,
263
+ interactiveKindForTesting: "movable-point",
264
+ };
265
+ // $FlowFixMe[invalid-constructor]
266
+ state.mouseTarget = new WrappedEllipse(
267
+ graphie,
268
+ center,
269
+ radii,
270
+ options,
271
+ );
272
+ state.mouseTarget.attr({fill: "#000", opacity: 0.0});
273
+ }
274
+ }
275
+
276
+ const showTrashTooltip = () => {
277
+ this._showTooltip((container) => {
278
+ // TODO(LP-11406): Replace with React Portal
279
+ // eslint-disable-next-line no-restricted-syntax
280
+ ReactDOM.render(
281
+ <span style={{fontSize: "2em"}}>
282
+ <InlineIcon
283
+ {...iconTrash}
284
+ style={{
285
+ position: "static",
286
+ color: KhanColors.INTERACTIVE,
287
+ marginLeft: 9,
288
+ marginRight: 9,
289
+ }}
290
+ />
291
+ </span>,
292
+ container,
293
+ );
294
+ });
295
+ };
296
+
297
+ // The starting coord of any move, sent to onMoveEnd as the previous
298
+ // value
299
+ let startCoord = state.coord;
300
+
301
+ // The Movable representing this movablePoint's representation
302
+ // This handles mouse events for us, which we propagate in
303
+ // onMove
304
+ self.movable.modify(
305
+ _.extend({}, state, {
306
+ add: null,
307
+ modify: null,
308
+ draw: self.draw.bind(self),
309
+ remove: null,
310
+ onMoveStart: (startMouseCoord) => {
311
+ state.hasMoved = false;
312
+ startCoord = state.coord;
313
+
314
+ // Save the offset between the cursor and the initial coordinate
315
+ // of the point. This is tracked so as to avoid locking the
316
+ // moving point to the user's finger on touch devices, which
317
+ // would obscure it, no matter how large we made the touch
318
+ // target. Instead, we respect the offset at which the point was
319
+ // grabbed for the entirety of the gesture, if it's a
320
+ // touch-based interaction.
321
+ if (state.touchOffset == null) {
322
+ const isMouse = !("ontouchstart" in window);
323
+ state.touchOffset = isMouse
324
+ ? [0, 0]
325
+ : kvector.subtract(startCoord, startMouseCoord);
326
+ }
327
+
328
+ const svgElem = state.visibleShape.wrapper;
329
+ if (state.shadow) {
330
+ const filter = "none";
331
+ svgElem.style.webkitFilter = filter;
332
+ svgElem.style.filter = filter;
333
+ }
334
+
335
+ if (state.showHairlines) {
336
+ state.showHairlines(state.coord);
337
+ }
338
+
339
+ tooltipResetFunctions.forEach((f) => f());
340
+ if (state.tooltip) {
341
+ if (state.xOnlyTooltip) {
342
+ this._showTooltip(`${state.coord[0]}`);
343
+ } else {
344
+ this._showTooltip(
345
+ `(${state.coord[0]}, ${state.coord[1]})`,
346
+ );
347
+ }
348
+
349
+ if (state.shadow) {
350
+ const content =
351
+ svgElem.getElementsByClassName(
352
+ "tooltip-content",
353
+ )[0];
354
+ const filter =
355
+ "drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";
356
+
357
+ content.style.webkitFilter = filter;
358
+ content.style.filter = filter;
359
+ }
360
+ }
361
+
362
+ self._fireEvent(state.onMoveStart, startCoord, startCoord);
363
+ self.draw();
364
+ },
365
+ onMove: (mouseCoord, prevMouseCoord) => {
366
+ const transformedCoord = kvector.add(
367
+ mouseCoord,
368
+ state.touchOffset,
369
+ );
370
+
371
+ self.moveTo(transformedCoord);
372
+
373
+ if (state.showHairlines) {
374
+ if (!this.state.outOfBounds) {
375
+ state.showHairlines(state.coord);
376
+ } else {
377
+ state.hideHairlines();
378
+ }
379
+ }
380
+
381
+ if (state.tooltip) {
382
+ if (!this.state.outOfBounds) {
383
+ if (state.xOnlyTooltip) {
384
+ this._showTooltip(`${state.coord[0]}`);
385
+ } else {
386
+ this._showTooltip(
387
+ `(${state.coord[0]}, ${state.coord[1]})`,
388
+ );
389
+ }
390
+ }
391
+ }
392
+
393
+ if (state.onRemove && this.state.outOfBounds) {
394
+ showTrashTooltip();
395
+ }
396
+ },
397
+ onMoveEnd: () => {
398
+ if (self.isHovering() && !state.hasMoved) {
399
+ self._fireEvent(state.onClick, state.coord, startCoord);
400
+ }
401
+
402
+ const svgElem = state.visibleShape.wrapper;
403
+
404
+ if (state.shadow) {
405
+ const filter =
406
+ "drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";
407
+ svgElem.style.webkitFilter = filter;
408
+ svgElem.style.filter = filter;
409
+ }
410
+
411
+ if (state.hideHairlines) {
412
+ state.hideHairlines();
413
+ }
414
+
415
+ if (state.hasMoved) {
416
+ this._hideTooltip();
417
+ } else if (state.onRemove) {
418
+ // If we haven't moved and we should be displaying trash
419
+ // tooltips.
420
+ showTrashTooltip();
421
+
422
+ const content =
423
+ svgElem.getElementsByClassName(
424
+ "tooltip-content",
425
+ )[0];
426
+
427
+ content.style.webkitFilter = "none";
428
+ content.style.filter = "none";
429
+
430
+ this._tooltip.firstChild.addEventListener(
431
+ "touchstart",
432
+ (e) => {
433
+ // Prevent creation of a new point when the event is
434
+ // propagated up the DOM.
435
+ e.stopPropagation();
436
+ },
437
+ true,
438
+ );
439
+
440
+ this._tooltip.firstChild.addEventListener(
441
+ "touchend",
442
+ (e) => {
443
+ // Remove the point and prevent creation of a
444
+ // new point.
445
+ state.onRemove();
446
+ e.stopPropagation();
447
+ },
448
+ true,
449
+ );
450
+ } else if (state.tooltip) {
451
+ this._hideTooltip();
452
+ }
453
+
454
+ if (state.outOfBounds) {
455
+ state.onRemove();
456
+ }
457
+
458
+ self._fireEvent(state.onMoveEnd, state.coord, startCoord);
459
+ state.hasMoved = false;
460
+ state.touchOffset = null;
461
+ self.draw();
462
+ },
463
+ }),
464
+ );
465
+
466
+ // Trigger an add event if this hasn't been added before
467
+ if (!state.added) {
468
+ self.prevState = {};
469
+ self._fireEvent(state.add, self.cloneState(), self.prevState);
470
+ state.added = true;
471
+
472
+ // Update the state for `added` and in case the add event
473
+ // changed it
474
+ self.prevState = self.cloneState();
475
+ }
476
+
477
+ // Trigger a modify event
478
+ self._fireEvent(state.modify, self.cloneState(), self.prevState);
479
+ },
480
+
481
+ remove: function () {
482
+ this.state.added = false;
483
+ this._fireEvent(this.state.remove);
484
+ if (this.movable) {
485
+ this.movable.remove();
486
+ }
487
+ // TODO(jack): This should really be moved off of
488
+ // movablePoint.state and only kept on movable.state
489
+ this.state.mouseTarget = null;
490
+ },
491
+
492
+ constrain: function () {
493
+ const result = this._applyConstraints(this.coord(), this.coord());
494
+ if (kpoint.is(result)) {
495
+ this.setCoord(result);
496
+ }
497
+ return result !== false;
498
+ },
499
+
500
+ setCoord: function (coord) {
501
+ assert(kpoint.is(coord, 2));
502
+ this.state.coord = _.clone(coord);
503
+ this.draw();
504
+ },
505
+
506
+ setCoordConstrained: function (coord) {
507
+ assert(kpoint.is(coord, 2));
508
+ const result = this._applyConstraints(coord, this.coord());
509
+ if (result !== false) {
510
+ this.state.coord = _.clone(result);
511
+ this.draw();
512
+ }
513
+ },
514
+
515
+ moveTo: function (coord) {
516
+ // The caller has the option of adding an onMove() method to the
517
+ // movablePoint object we return as a sort of event handler
518
+ // By returning false from onMove(), the move can be vetoed,
519
+ // providing custom constraints on where the point can be moved.
520
+ // By returning array [x, y], the move can be overridden
521
+
522
+ const state = this.state;
523
+
524
+ this.state.outOfBounds = false;
525
+ const result = this._applyConstraints(
526
+ coord,
527
+ state.coord,
528
+ state.onRemove
529
+ ? {
530
+ onOutOfBounds: () => {
531
+ this.state.outOfBounds = true;
532
+ },
533
+ }
534
+ : {},
535
+ );
536
+
537
+ if (result === false) {
538
+ return;
539
+ }
540
+ if (kpoint.is(result)) {
541
+ coord = result;
542
+ }
543
+ if (!kpoint.equal(coord, state.coord)) {
544
+ const prevCoord = state.coord;
545
+ state.coord = coord;
546
+ state.hasMoved = true;
547
+ this._fireEvent(state.onMove, state.coord, prevCoord);
548
+ this.draw();
549
+ }
550
+ },
551
+
552
+ // Clone these for use with raphael, which modifies the input
553
+ // style parameters
554
+ normalStyle: function () {
555
+ return _.clone(this.state.normalStyle);
556
+ },
557
+
558
+ highlightStyle: function () {
559
+ return _.clone(this.state.highlightStyle);
560
+ },
561
+
562
+ // Change z-order to back
563
+ toBack: function () {
564
+ this.movable.toBack();
565
+ if (this.state.visibleShape) {
566
+ this.state.visibleShape.toBack();
567
+ }
568
+ },
569
+
570
+ // Change z-order to front
571
+ toFront: function () {
572
+ if (this.state.visibleShape) {
573
+ this.state.visibleShape.toFront();
574
+ }
575
+ this.movable.toFront();
576
+ },
577
+
578
+ /**
579
+ * Forwarding methods to this.movable:
580
+ */
581
+ isHovering: function () {
582
+ return this.movable.isHovering();
583
+ },
584
+
585
+ isDragging: function () {
586
+ return this.movable.isDragging();
587
+ },
588
+
589
+ mouseTarget: function () {
590
+ return this.movable.mouseTarget();
591
+ },
592
+
593
+ grab: function (coord) {
594
+ // Provide an explicit touchOffset override, so that we track the user's
595
+ // finger when a point has been grabbed.
596
+ this.state.touchOffset = [0, 0];
597
+
598
+ this.movable.grab(coord);
599
+ this.moveTo(coord);
600
+ },
601
+ });
602
+
603
+ export default MovablePoint;