@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.
- package/.babelrc.js +1 -1
- package/CHANGELOG.md +29 -0
- package/dist/es/index.css +4361 -0
- package/dist/es/index.js +7 -1
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +4361 -0
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/strings.js +148 -46
- package/package.json +50 -4
- package/src/README.md +35 -0
- package/src/__stories__/item-renderer.stories.jsx +27 -0
- package/src/__stories__/server-item-renderer.stories.jsx +27 -0
- package/src/__testdata__/item-renderer_testdata.js +161 -0
- package/src/__testdata__/renderer_testdata.js +123 -0
- package/src/__tests__/__snapshots__/item-renderer_test.jsx.snap +233 -0
- package/src/__tests__/__snapshots__/perseus-markdown_test.jsx.snap +516 -0
- package/src/__tests__/__snapshots__/pure-markdown_test.js.snap +113 -0
- package/src/__tests__/__snapshots__/renderer_test.jsx.snap +576 -0
- package/src/__tests__/__snapshots__/server-item-renderer_test.jsx.snap +306 -0
- package/src/__tests__/a11y_test.jsx +304 -0
- package/src/__tests__/item-renderer_test.jsx +892 -0
- package/src/__tests__/mock-asset-loading-widget.jsx +57 -0
- package/src/__tests__/mock-widget.jsx +35 -0
- package/src/__tests__/perseus-markdown_test.jsx +747 -0
- package/src/__tests__/pure-markdown_test.js +552 -0
- package/src/__tests__/renderability_test.jsx +481 -0
- package/src/__tests__/renderer-api_test.jsx +333 -0
- package/src/__tests__/renderer_test.jsx +1792 -0
- package/src/__tests__/server-item-renderer_test.jsx +516 -0
- package/src/__tests__/test-items/image-item.js +25 -0
- package/src/__tests__/test-items/input-number-1-item.js +27 -0
- package/src/__tests__/test-items/input-number-2-item.js +39 -0
- package/src/__tests__/test-items/table-item.js +30 -0
- package/src/__tests__/tex-wrangler_test.js +83 -0
- package/src/__tests__/util_test.js +41 -0
- package/src/a11y.js +46 -0
- package/src/all-widgets.js +9 -0
- package/src/article-renderer.jsx +215 -0
- package/src/asset-context.js +30 -0
- package/src/basic-widgets.js +13 -0
- package/src/components/__stories__/button-group.stories.jsx +61 -0
- package/src/components/__stories__/fixed-to-responsive.stories.jsx +132 -0
- package/src/components/__stories__/graph.stories.jsx +27 -0
- package/src/components/__stories__/graphie.stories.jsx +28 -0
- package/src/components/__stories__/hud.stories.jsx +36 -0
- package/src/components/__stories__/icon.stories.jsx +56 -0
- package/src/components/__stories__/image-loader.stories.jsx +60 -0
- package/src/components/__stories__/info-tip.stories.jsx +33 -0
- package/src/components/__stories__/inline-icon.stories.jsx +39 -0
- package/src/components/__stories__/input-with-examples.stories.jsx +51 -0
- package/src/components/__stories__/lint.stories.jsx +40 -0
- package/src/components/__stories__/math-input.stories.jsx +29 -0
- package/src/components/__stories__/math-output.stories.jsx +24 -0
- package/src/components/__stories__/multi-button-group.stories.jsx +69 -0
- package/src/components/__stories__/number-input.stories.jsx +42 -0
- package/src/components/__stories__/possible-answers.stories.jsx +22 -0
- package/src/components/__stories__/prop-check-box.stories.jsx +62 -0
- package/src/components/__stories__/range-input.stories.jsx +28 -0
- package/src/components/__stories__/simple-keypad-input.stories.jsx +28 -0
- package/src/components/__stories__/sortable.stories.jsx +73 -0
- package/src/components/__stories__/stub-tag-editor.stories.jsx +44 -0
- package/src/components/__stories__/svg-image.stories.jsx +60 -0
- package/src/components/__stories__/tex.stories.jsx +18 -0
- package/src/components/__stories__/text-buttons.stories.jsx +51 -0
- package/src/components/__stories__/text-input.stories.jsx +34 -0
- package/src/components/__stories__/text-list-editor.stories.jsx +33 -0
- package/src/components/__stories__/zoomable-tex.stories.jsx +39 -0
- package/src/components/__stories__/zoomable.stories.jsx +40 -0
- package/src/components/__testdata__/sorter_testdata.js +20 -0
- package/src/components/__tests__/__snapshots__/sortable_test.jsx.snap +79 -0
- package/src/components/__tests__/__snapshots__/sorter_test.jsx.snap +297 -0
- package/src/components/__tests__/number-input_test.jsx +112 -0
- package/src/components/__tests__/sortable_test.jsx +234 -0
- package/src/components/__tests__/sorter_test.jsx +111 -0
- package/src/components/__tests__/zoomable_test.jsx +388 -0
- package/src/components/button-group.jsx +131 -0
- package/src/components/constants.js +15 -0
- package/src/components/fixed-to-responsive.jsx +164 -0
- package/src/components/graph.jsx +415 -0
- package/src/components/graphie-classes.jsx +148 -0
- package/src/components/graphie-movables.jsx +342 -0
- package/src/components/graphie.jsx +353 -0
- package/src/components/highlighting/highlightable-content.jsx +245 -0
- package/src/components/highlighting/highlights.js +208 -0
- package/src/components/highlighting/ranges.js +299 -0
- package/src/components/highlighting/types.js +73 -0
- package/src/components/highlighting/ui/highlight-renderer.jsx +179 -0
- package/src/components/highlighting/ui/highlight-set-renderer.jsx +190 -0
- package/src/components/highlighting/ui/highlight-tooltip.jsx +153 -0
- package/src/components/highlighting/ui/highlighting-ui.jsx +163 -0
- package/src/components/highlighting/ui/selection-tracker.jsx +195 -0
- package/src/components/highlighting/ui/types.js +21 -0
- package/src/components/highlighting/ui/util.js +166 -0
- package/src/components/highlighting/word-indexer.jsx +155 -0
- package/src/components/hud.jsx +179 -0
- package/src/components/icon.jsx +149 -0
- package/src/components/image-loader.jsx +175 -0
- package/src/components/info-tip/info-tip.jsx +146 -0
- package/src/components/info-tip.jsx +38 -0
- package/src/components/inline-icon.jsx +81 -0
- package/src/components/input-with-examples.jsx +231 -0
- package/src/components/lint.jsx +454 -0
- package/src/components/math-input.jsx +282 -0
- package/src/components/math-output.jsx +128 -0
- package/src/components/multi-button-group.jsx +137 -0
- package/src/components/new-tooltip/README.md +110 -0
- package/src/components/new-tooltip/__stories__/flexible-position.stories.jsx +437 -0
- package/src/components/new-tooltip/__stories__/new-tooltip.stories.jsx +665 -0
- package/src/components/new-tooltip/__stories__/tooltip-arrow.stories.jsx +70 -0
- package/src/components/new-tooltip/__stories__/tooltip-bubble.stories.jsx +98 -0
- package/src/components/new-tooltip/__tests__/style-constants_test.js +8 -0
- package/src/components/new-tooltip/__tests__/util_test.js +47 -0
- package/src/components/new-tooltip/flexible-position.jsx +182 -0
- package/src/components/new-tooltip/new-tooltip.jsx +399 -0
- package/src/components/new-tooltip/style-constants.js +13 -0
- package/src/components/new-tooltip/tooltip-arrow.jsx +184 -0
- package/src/components/new-tooltip/tooltip-bubble.jsx +223 -0
- package/src/components/new-tooltip/tooltip-portal.jsx +101 -0
- package/src/components/new-tooltip/tooltip-positioner.jsx +529 -0
- package/src/components/new-tooltip/types.js +183 -0
- package/src/components/new-tooltip/util.js +27 -0
- package/src/components/number-input.jsx +253 -0
- package/src/components/possible-answers.jsx +36 -0
- package/src/components/prop-check-box.jsx +80 -0
- package/src/components/range-input.jsx +61 -0
- package/src/components/simple-keypad-input.jsx +91 -0
- package/src/components/sortable.jsx +873 -0
- package/src/components/stub-tag-editor.jsx +54 -0
- package/src/components/svg-image.jsx +762 -0
- package/src/components/tex-buttons.jsx +322 -0
- package/src/components/tex.jsx +70 -0
- package/src/components/text-input.jsx +82 -0
- package/src/components/text-list-editor.jsx +157 -0
- package/src/components/tooltip.jsx +395 -0
- package/src/components/visibility-observer/__stories__/visibility-observer.stories.jsx +140 -0
- package/src/components/visibility-observer/get-scroll-parent.js +45 -0
- package/src/components/visibility-observer/visibility-observer.js +109 -0
- package/src/components/visibility-observer/visibility-observer.jsx +123 -0
- package/src/components/zoomable-tex.jsx +70 -0
- package/src/components/zoomable.jsx +304 -0
- package/src/components.js +17 -0
- package/src/dependencies.js +22 -0
- package/src/error-boundary.jsx +48 -0
- package/src/extra-widgets.js +75 -0
- package/src/gorgon/README +40 -0
- package/src/gorgon/__tests__/matcher_test.js +497 -0
- package/src/gorgon/__tests__/rule_test.js +101 -0
- package/src/gorgon/__tests__/rules_test.js +487 -0
- package/src/gorgon/__tests__/selector-parser_test.js +52 -0
- package/src/gorgon/__tests__/tree-transformer_test.js +446 -0
- package/src/gorgon/gorgon.js +290 -0
- package/src/gorgon/proptypes.js +29 -0
- package/src/gorgon/rule.js +413 -0
- package/src/gorgon/rules/absolute-url.js +24 -0
- package/src/gorgon/rules/all-rules.js +72 -0
- package/src/gorgon/rules/blockquoted-math.js +10 -0
- package/src/gorgon/rules/blockquoted-widget.js +10 -0
- package/src/gorgon/rules/double-spacing-after-terminal.js +12 -0
- package/src/gorgon/rules/extra-content-spacing.js +12 -0
- package/src/gorgon/rules/heading-level-1.js +14 -0
- package/src/gorgon/rules/heading-level-skip.js +20 -0
- package/src/gorgon/rules/heading-sentence-case.js +11 -0
- package/src/gorgon/rules/heading-title-case.js +63 -0
- package/src/gorgon/rules/image-alt-text.js +21 -0
- package/src/gorgon/rules/image-in-table.js +10 -0
- package/src/gorgon/rules/image-spaces-around-urls.js +35 -0
- package/src/gorgon/rules/image-widget.js +50 -0
- package/src/gorgon/rules/link-click-here.js +11 -0
- package/src/gorgon/rules/lint-utils.js +48 -0
- package/src/gorgon/rules/long-paragraph.js +14 -0
- package/src/gorgon/rules/math-adjacent.js +10 -0
- package/src/gorgon/rules/math-align-extra-break.js +11 -0
- package/src/gorgon/rules/math-align-linebreaks.js +43 -0
- package/src/gorgon/rules/math-empty.js +10 -0
- package/src/gorgon/rules/math-font-size.js +12 -0
- package/src/gorgon/rules/math-frac.js +10 -0
- package/src/gorgon/rules/math-nested.js +11 -0
- package/src/gorgon/rules/math-starts-with-space.js +12 -0
- package/src/gorgon/rules/math-text-empty.js +10 -0
- package/src/gorgon/rules/math-without-dollars.js +14 -0
- package/src/gorgon/rules/nested-lists.js +11 -0
- package/src/gorgon/rules/profanity.js +10 -0
- package/src/gorgon/rules/table-missing-cells.js +20 -0
- package/src/gorgon/rules/unbalanced-code-delimiters.js +14 -0
- package/src/gorgon/rules/unescaped-dollar.js +10 -0
- package/src/gorgon/rules/widget-in-table.js +10 -0
- package/src/gorgon/selector.js +506 -0
- package/src/gorgon/tree-transformer.js +588 -0
- package/src/hint-renderer.jsx +159 -0
- package/src/hints-renderer.jsx +359 -0
- package/src/icon-paths.js +120 -0
- package/src/index.js +149 -2
- package/src/init.js +49 -0
- package/src/interaction-tracker.js +60 -0
- package/src/interactive2/__tests__/movable-mock.js +48 -0
- package/src/interactive2/__tests__/movable-point_test.js +146 -0
- package/src/interactive2/interactive-util.js +152 -0
- package/src/interactive2/movable-helper-methods.js +160 -0
- package/src/interactive2/movable-line-options.js +392 -0
- package/src/interactive2/movable-line.js +322 -0
- package/src/interactive2/movable-point-options.js +190 -0
- package/src/interactive2/movable-point.jsx +603 -0
- package/src/interactive2/movable-polygon-options.js +351 -0
- package/src/interactive2/movable-polygon.js +368 -0
- package/src/interactive2/movable.js +273 -0
- package/src/interactive2/objective_.js +79 -0
- package/src/interactive2/types.js +3 -0
- package/src/interactive2/wrapped-defaults.js +86 -0
- package/src/interactive2/wrapped-ellipse.js +87 -0
- package/src/interactive2/wrapped-line.js +109 -0
- package/src/interactive2/wrapped-path.js +47 -0
- package/src/interactive2.js +91 -0
- package/src/item-renderer.jsx +518 -0
- package/src/item-version.js +12 -0
- package/src/jipt-paragraphs.js +44 -0
- package/src/jquery.mobile.vmouse.js +545 -0
- package/src/keypad-context.js +33 -0
- package/src/loading-context.js +20 -0
- package/src/logging/log.js +107 -0
- package/src/logging/log_test.js +41 -0
- package/src/mixins/changeable.jsx +115 -0
- package/src/mixins/editor-jsonify.jsx +13 -0
- package/src/mixins/provide-keypad.jsx +129 -0
- package/src/mixins/widget-jsonify-deprecated.jsx +23 -0
- package/src/mixins/widget-prop-blacklist.js +36 -0
- package/src/multi-items/__stories__/multi-renderer.stories.js +88 -0
- package/src/multi-items/__testdata__/multi-renderer_testdata.js +174 -0
- package/src/multi-items/__tests__/__snapshots__/multi-renderer_test.js.snap +994 -0
- package/src/multi-items/__tests__/items_test.js +245 -0
- package/src/multi-items/__tests__/multi-renderer_test.js +903 -0
- package/src/multi-items/__tests__/prop-type-builders_test.js +134 -0
- package/src/multi-items/__tests__/shapes_test.js +44 -0
- package/src/multi-items/__tests__/trees_test.js +316 -0
- package/src/multi-items/item-types.js +55 -0
- package/src/multi-items/items.js +176 -0
- package/src/multi-items/multi-renderer.jsx +543 -0
- package/src/multi-items/prop-type-builders.js +105 -0
- package/src/multi-items/shape-types.js +47 -0
- package/src/multi-items/shapes.js +53 -0
- package/src/multi-items/tree-types.js +42 -0
- package/src/multi-items/trees.js +345 -0
- package/src/multi-items.js +76 -0
- package/src/not-gorgon.js +129 -0
- package/src/perseus-api.jsx +270 -0
- package/src/perseus-env.js +26 -0
- package/src/perseus-error.js +19 -0
- package/src/perseus-markdown.jsx +433 -0
- package/src/perseus-types.js +1597 -0
- package/src/pure-markdown.js +347 -0
- package/src/question-paragraph.jsx +30 -0
- package/src/renderability.jsx +108 -0
- package/src/renderer.jsx +1932 -0
- package/src/server-item-renderer.jsx +467 -0
- package/src/sigfigs.jsx +492 -0
- package/src/styles/articles.less +748 -0
- package/src/styles/constants.js +119 -0
- package/src/styles/global-constants.js +350 -0
- package/src/styles/global-styles.js +307 -0
- package/src/styles/khan-exercise.css +1304 -0
- package/src/styles/media-queries.js +48 -0
- package/src/styles/perseus-renderer.less +1007 -0
- package/src/styles/shared.js +132 -0
- package/src/styles/util.less +47 -0
- package/src/styles/variables.boostrap.less +301 -0
- package/src/styles/variables.less +68 -0
- package/src/styles/variables.shared.less +356 -0
- package/src/styles/widgets/categorizer.less +39 -0
- package/src/styles/widgets/definition.less +86 -0
- package/src/styles/widgets/dropdown.less +3 -0
- package/src/styles/widgets/expression.less +147 -0
- package/src/styles/widgets/graded-group.less +36 -0
- package/src/styles/widgets/grapher.less +11 -0
- package/src/styles/widgets/group.less +19 -0
- package/src/styles/widgets/image.less +29 -0
- package/src/styles/widgets/interactive-graph.less +61 -0
- package/src/styles/widgets/label-image.less +41 -0
- package/src/styles/widgets/matcher.less +8 -0
- package/src/styles/widgets/matrix.less +120 -0
- package/src/styles/widgets/measurer.less +20 -0
- package/src/styles/widgets/orderer.less +97 -0
- package/src/styles/widgets/passage.less +151 -0
- package/src/styles/widgets/plotter.less +33 -0
- package/src/styles/widgets/radio.less +52 -0
- package/src/styles/widgets/reaction-diagram.less +35 -0
- package/src/styles/widgets/sequence.less +5 -0
- package/src/styles/widgets/sortable.less +127 -0
- package/src/styles/widgets/table.less +56 -0
- package/src/styles/widgets/transformer.less +28 -0
- package/src/styles/widgets/unit.less +14 -0
- package/src/tex-wrangler.js +176 -0
- package/src/traversal.jsx +141 -0
- package/src/types.js +538 -0
- package/src/util/a11y.js +24 -0
- package/src/util/answer-types.js +862 -0
- package/src/util/answer-types_test.js +115 -0
- package/src/util/colors.js +94 -0
- package/src/util/fix-passage-refs.jsx +122 -0
- package/src/util/graph-utils.js +16 -0
- package/src/util/graphie.js +1586 -0
- package/src/util/interactive.js +4078 -0
- package/src/util/katex-preprocess.js +16 -0
- package/src/util/math.js +296 -0
- package/src/util/mobile-native-utils.js +14 -0
- package/src/util/mobile-native-utils_test.js +24 -0
- package/src/util/register-all-widgets-for-testing.js +12 -0
- package/src/util/scroll-utils.js +162 -0
- package/src/util/sizing-utils.js +46 -0
- package/src/util/tex.js +203 -0
- package/src/util/url-utils.js +36 -0
- package/src/util.js +990 -0
- package/src/version.js +11 -0
- package/src/widget-container.jsx +174 -0
- package/src/widgets/__stories__/categorizer.stories.jsx +15 -0
- package/src/widgets/__stories__/cs-program.stories.jsx +15 -0
- package/src/widgets/__stories__/definition.stories.jsx +38 -0
- package/src/widgets/__stories__/dropdown.stories.jsx +15 -0
- package/src/widgets/__stories__/explanation.stories.jsx +19 -0
- package/src/widgets/__stories__/expression.stories.jsx +26 -0
- package/src/widgets/__stories__/graded-group-set.stories.jsx +32 -0
- package/src/widgets/__stories__/graded-group.stories.jsx +32 -0
- package/src/widgets/__stories__/grapher.stories.jsx +47 -0
- package/src/widgets/__stories__/group.stories.jsx +15 -0
- package/src/widgets/__stories__/iframe.stories.jsx +15 -0
- package/src/widgets/__stories__/image.stories.jsx +62 -0
- package/src/widgets/__stories__/input-number.stories.jsx +90 -0
- package/src/widgets/__stories__/interaction.stories.jsx +15 -0
- package/src/widgets/__stories__/interactive-graph.stories.jsx +61 -0
- package/src/widgets/__stories__/matcher.stories.jsx +15 -0
- package/src/widgets/__stories__/matrix.stories.jsx +15 -0
- package/src/widgets/__stories__/number-line.stories.jsx +15 -0
- package/src/widgets/__stories__/numeric-input.stories.jsx +19 -0
- package/src/widgets/__stories__/orderer.stories.jsx +15 -0
- package/src/widgets/__stories__/passage-ref.stories.jsx +19 -0
- package/src/widgets/__stories__/passage.stories.jsx +19 -0
- package/src/widgets/__stories__/radio.stories.jsx +82 -0
- package/src/widgets/__stories__/sorter.stories.jsx +15 -0
- package/src/widgets/__stories__/transformer.stories.jsx +15 -0
- package/src/widgets/__stories__/unit.stories.jsx +45 -0
- package/src/widgets/__stories__/video-transcript-link.stories.jsx +24 -0
- package/src/widgets/__stories__/video.stories.jsx +15 -0
- package/src/widgets/__testdata__/categorizer_testdata.js +50 -0
- package/src/widgets/__testdata__/cs-program_testdata.js +28 -0
- package/src/widgets/__testdata__/dropdown_testdata.js +34 -0
- package/src/widgets/__testdata__/explanation_testdata.js +56 -0
- package/src/widgets/__testdata__/expression_testdata.js +95 -0
- package/src/widgets/__testdata__/graded-group-set_testdata.js +358 -0
- package/src/widgets/__testdata__/graded-group_testdata.js +79 -0
- package/src/widgets/__testdata__/grapher_testdata.js +376 -0
- package/src/widgets/__testdata__/group_testdata.js +156 -0
- package/src/widgets/__testdata__/iframe_testdata.js +36 -0
- package/src/widgets/__testdata__/image_testdata.js +38 -0
- package/src/widgets/__testdata__/input-number_testdata.js +73 -0
- package/src/widgets/__testdata__/interaction_testdata.js +264 -0
- package/src/widgets/__testdata__/interactive-graph_testdata.js +646 -0
- package/src/widgets/__testdata__/matcher_testdata.js +34 -0
- package/src/widgets/__testdata__/matrix_testdata.js +29 -0
- package/src/widgets/__testdata__/number-line_testdata.js +31 -0
- package/src/widgets/__testdata__/numeric-input_testdata.js +266 -0
- package/src/widgets/__testdata__/orderer_testdata.js +58 -0
- package/src/widgets/__testdata__/passage-ref_testdata.js +41 -0
- package/src/widgets/__testdata__/passage_testdata.js +71 -0
- package/src/widgets/__testdata__/radio_testdata.js +210 -0
- package/src/widgets/__testdata__/sorter_testdata.js +20 -0
- package/src/widgets/__testdata__/transformer_testdata.js +109 -0
- package/src/widgets/__testdata__/video_testdata.js +22 -0
- package/src/widgets/__tests__/__snapshots__/categorizer_test.jsx.snap +928 -0
- package/src/widgets/__tests__/__snapshots__/cs-program_test.jsx.snap +75 -0
- package/src/widgets/__tests__/__snapshots__/definition_test.js.snap +99 -0
- package/src/widgets/__tests__/__snapshots__/dropdown_test.jsx.snap +143 -0
- package/src/widgets/__tests__/__snapshots__/explanation_test.js.snap +473 -0
- package/src/widgets/__tests__/__snapshots__/expression_test.jsx.snap +38 -0
- package/src/widgets/__tests__/__snapshots__/graded-group-set-jipt_test.jsx.snap +754 -0
- package/src/widgets/__tests__/__snapshots__/graded-group-set_test.jsx.snap +310 -0
- package/src/widgets/__tests__/__snapshots__/graded-group_test.jsx.snap +863 -0
- package/src/widgets/__tests__/__snapshots__/grapher_test.jsx.snap +2880 -0
- package/src/widgets/__tests__/__snapshots__/group_test.jsx.snap +1154 -0
- package/src/widgets/__tests__/__snapshots__/iframe_test.jsx.snap +69 -0
- package/src/widgets/__tests__/__snapshots__/image_test.jsx.snap +388 -0
- package/src/widgets/__tests__/__snapshots__/input-number_test.jsx.snap +978 -0
- package/src/widgets/__tests__/__snapshots__/interaction_test.jsx.snap +311 -0
- package/src/widgets/__tests__/__snapshots__/interactive-graph_test.jsx.snap +2915 -0
- package/src/widgets/__tests__/__snapshots__/matcher_test.jsx.snap +1039 -0
- package/src/widgets/__tests__/__snapshots__/matrix_test.jsx.snap +450 -0
- package/src/widgets/__tests__/__snapshots__/number-line_test.jsx.snap +888 -0
- package/src/widgets/__tests__/__snapshots__/numeric-input_test.jsx.snap +930 -0
- package/src/widgets/__tests__/__snapshots__/orderer_test.jsx.snap +275 -0
- package/src/widgets/__tests__/__snapshots__/passage-ref_test.jsx.snap +446 -0
- package/src/widgets/__tests__/__snapshots__/passage_test.jsx.snap +1988 -0
- package/src/widgets/__tests__/__snapshots__/radio_test.jsx.snap +7107 -0
- package/src/widgets/__tests__/__snapshots__/video_test.jsx.snap +163 -0
- package/src/widgets/__tests__/categorizer_test.jsx +205 -0
- package/src/widgets/__tests__/cs-program_test.jsx +45 -0
- package/src/widgets/__tests__/definition_test.js +152 -0
- package/src/widgets/__tests__/dropdown_test.jsx +106 -0
- package/src/widgets/__tests__/explanation_test.js +199 -0
- package/src/widgets/__tests__/expression_test.jsx +439 -0
- package/src/widgets/__tests__/graded-group-set-jipt_test.jsx +33 -0
- package/src/widgets/__tests__/graded-group-set_test.jsx +270 -0
- package/src/widgets/__tests__/graded-group_test.jsx +233 -0
- package/src/widgets/__tests__/grapher.cypress.jsx +486 -0
- package/src/widgets/__tests__/grapher_test.jsx +35 -0
- package/src/widgets/__tests__/group_test.jsx +512 -0
- package/src/widgets/__tests__/iframe_test.jsx +47 -0
- package/src/widgets/__tests__/image_test.jsx +65 -0
- package/src/widgets/__tests__/input-number_test.jsx +360 -0
- package/src/widgets/__tests__/interaction_test.jsx +33 -0
- package/src/widgets/__tests__/interactive-graph.cypress.jsx +697 -0
- package/src/widgets/__tests__/interactive-graph_test.jsx +105 -0
- package/src/widgets/__tests__/matcher_test.jsx +157 -0
- package/src/widgets/__tests__/matrix_test.jsx +84 -0
- package/src/widgets/__tests__/number-line_test.jsx +81 -0
- package/src/widgets/__tests__/numeric-input_test.jsx +574 -0
- package/src/widgets/__tests__/orderer_test.jsx +75 -0
- package/src/widgets/__tests__/passage-ref_test.jsx +166 -0
- package/src/widgets/__tests__/passage_test.jsx +133 -0
- package/src/widgets/__tests__/radio/base-radio_test.jsx +82 -0
- package/src/widgets/__tests__/radio_test.jsx +651 -0
- package/src/widgets/__tests__/renderQuestion.jsx +66 -0
- package/src/widgets/__tests__/unit_test.jsx +144 -0
- package/src/widgets/__tests__/video_test.jsx +55 -0
- package/src/widgets/categorizer.jsx +338 -0
- package/src/widgets/cs-program.jsx +227 -0
- package/src/widgets/definition.jsx +141 -0
- package/src/widgets/dropdown.jsx +143 -0
- package/src/widgets/explanation.jsx +315 -0
- package/src/widgets/expression.jsx +652 -0
- package/src/widgets/graded-group-answer-bar.jsx +152 -0
- package/src/widgets/graded-group-set.jsx +285 -0
- package/src/widgets/graded-group.jsx +448 -0
- package/src/widgets/grapher/util.jsx +806 -0
- package/src/widgets/grapher.jsx +663 -0
- package/src/widgets/group.jsx +213 -0
- package/src/widgets/iframe.jsx +198 -0
- package/src/widgets/image.jsx +310 -0
- package/src/widgets/input-number.jsx +411 -0
- package/src/widgets/interaction/arrow-picker.jsx +39 -0
- package/src/widgets/interaction/color-picker.jsx +69 -0
- package/src/widgets/interaction/dash-picker.jsx +46 -0
- package/src/widgets/interaction/element-container.jsx +97 -0
- package/src/widgets/interaction.jsx +742 -0
- package/src/widgets/interactive-graph.jsx +2820 -0
- package/src/widgets/label-image/__stories__/answer-choices.stories.jsx +93 -0
- package/src/widgets/label-image/__stories__/marker.stories.jsx +172 -0
- package/src/widgets/label-image/answer-choices.jsx +311 -0
- package/src/widgets/label-image/marker.jsx +365 -0
- package/src/widgets/label-image/types.js +33 -0
- package/src/widgets/label-image.jsx +841 -0
- package/src/widgets/label-image_test.js +840 -0
- package/src/widgets/lights-puzzle.jsx +356 -0
- package/src/widgets/matcher.jsx +271 -0
- package/src/widgets/matrix.jsx +616 -0
- package/src/widgets/measurer.jsx +215 -0
- package/src/widgets/molecule/__tests__/layout_test.jsx +159 -0
- package/src/widgets/molecule/__tests__/parser_test.jsx +142 -0
- package/src/widgets/molecule/molecule-drawing.jsx +175 -0
- package/src/widgets/molecule/molecule-layout.jsx +367 -0
- package/src/widgets/molecule/smiles-parser.jsx +300 -0
- package/src/widgets/molecule.jsx +172 -0
- package/src/widgets/number-line.jsx +858 -0
- package/src/widgets/numeric-input.jsx +622 -0
- package/src/widgets/orderer.jsx +753 -0
- package/src/widgets/passage/__tests__/passage-markdown_test.jsx +382 -0
- package/src/widgets/passage/get-line-height-for-node.js +10 -0
- package/src/widgets/passage/passage-markdown.jsx +416 -0
- package/src/widgets/passage-ref-target.jsx +70 -0
- package/src/widgets/passage-ref.jsx +198 -0
- package/src/widgets/passage.jsx +601 -0
- package/src/widgets/plotter.jsx +1198 -0
- package/src/widgets/radio/__stories__/base-radio.stories.jsx +40 -0
- package/src/widgets/radio/__stories__/choice-icon.stories.jsx +157 -0
- package/src/widgets/radio/__stories__/choice-none-above.stories.jsx +26 -0
- package/src/widgets/radio/__stories__/cross-out-button.stories.jsx +64 -0
- package/src/widgets/radio/__stories__/cross-out-menu.stories.jsx +59 -0
- package/src/widgets/radio/__stories__/cross-out-tooltip.stories.jsx +59 -0
- package/src/widgets/radio/__stories__/focus-ring.stories.jsx +38 -0
- package/src/widgets/radio/__stories__/option-status.stories.jsx +118 -0
- package/src/widgets/radio/__stories__/toggleable-radio-button.stories.jsx +28 -0
- package/src/widgets/radio/base-radio.jsx +642 -0
- package/src/widgets/radio/choice-icon.jsx +468 -0
- package/src/widgets/radio/choice-none-above.jsx +54 -0
- package/src/widgets/radio/choice.jsx +692 -0
- package/src/widgets/radio/choice.jsx.fixture.js +64 -0
- package/src/widgets/radio/cross-out-button.jsx +136 -0
- package/src/widgets/radio/cross-out-menu-wrapper.jsx +492 -0
- package/src/widgets/radio/cross-out-tooltip.jsx +129 -0
- package/src/widgets/radio/focus-ring.jsx +51 -0
- package/src/widgets/radio/option-status.jsx +89 -0
- package/src/widgets/radio/toggleable-radio-button.jsx +133 -0
- package/src/widgets/radio/util.js +32 -0
- package/src/widgets/radio/util_test.js +19 -0
- package/src/widgets/radio/widget.jsx +470 -0
- package/src/widgets/radio.jsx +156 -0
- package/src/widgets/reaction-diagram.jsx +137 -0
- package/src/widgets/sequence.jsx +140 -0
- package/src/widgets/simulator.jsx +808 -0
- package/src/widgets/sorter.jsx +146 -0
- package/src/widgets/table.jsx +394 -0
- package/src/widgets/transformer.jsx +2876 -0
- package/src/widgets/unit.jsx +372 -0
- package/src/widgets/video-transcript-link.jsx +84 -0
- package/src/widgets/video-transcript-link_test.js +211 -0
- package/src/widgets/video.jsx +126 -0
- package/src/widgets.js +431 -0
- package/src/zoom.js +539 -0
- package/README.md +0 -3
- package/src/__tests__/index.test.js +0 -14
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import {testDependencies} from "../../../../testing/test-dependencies.js";
|
|
4
|
+
import {setDependencies} from "../dependencies.js";
|
|
5
|
+
|
|
6
|
+
import {Errors, Log} from "./log.js";
|
|
7
|
+
|
|
8
|
+
describe("Perseus logging", () => {
|
|
9
|
+
it("should proxy log() calls to the logger provided through setDependencies", () => {
|
|
10
|
+
// Arrange
|
|
11
|
+
const logSpy = jest.spyOn(testDependencies.Log, "log");
|
|
12
|
+
setDependencies(testDependencies);
|
|
13
|
+
|
|
14
|
+
// Act
|
|
15
|
+
Log.log("test message", {a: 1, b: "two"});
|
|
16
|
+
|
|
17
|
+
// Assert
|
|
18
|
+
expect(logSpy).toHaveBeenCalledWith("test message", {a: 1, b: "two"});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should proxy error() calls to the logger provided through setDependencies", () => {
|
|
22
|
+
// Arrange
|
|
23
|
+
const errorSpy = jest.spyOn(testDependencies.Log, "error");
|
|
24
|
+
setDependencies(testDependencies);
|
|
25
|
+
|
|
26
|
+
// Act
|
|
27
|
+
Log.error("test error", Errors.NotAllowed, {
|
|
28
|
+
cause: new Error("Something baaad"),
|
|
29
|
+
loggedMetadata: {a: 1, b: "two"},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Assert
|
|
33
|
+
expect(errorSpy).toHaveBeenCalledWith("test error", "NotAllowed", {
|
|
34
|
+
cause: expect.any(Error),
|
|
35
|
+
loggedMetadata: {
|
|
36
|
+
a: 1,
|
|
37
|
+
b: "two",
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* eslint-disable @babel/no-invalid-this */
|
|
2
|
+
// @flow
|
|
3
|
+
/**
|
|
4
|
+
* Changeable
|
|
5
|
+
*
|
|
6
|
+
* Adds a this.change() function to a component
|
|
7
|
+
*
|
|
8
|
+
* This.change takes prop changes as parameters, and calls
|
|
9
|
+
* this.props.onChange with the modified props.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import PropTypes from "prop-types";
|
|
13
|
+
import _ from "underscore";
|
|
14
|
+
|
|
15
|
+
import {Errors} from "../logging/log.js";
|
|
16
|
+
import {PerseusError} from "../perseus-error.js";
|
|
17
|
+
|
|
18
|
+
import WIDGET_PROP_BLACKLIST from "./widget-prop-blacklist.js";
|
|
19
|
+
|
|
20
|
+
import type {ChangeFn} from "../types.js";
|
|
21
|
+
|
|
22
|
+
const USAGE =
|
|
23
|
+
"Usage:\n" +
|
|
24
|
+
" this.change({propName: 5}, callback);\n" +
|
|
25
|
+
' this.change("propName", 5, callback);\n' +
|
|
26
|
+
' this.change("propName")';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Primary helper function for this.change()
|
|
30
|
+
*
|
|
31
|
+
* Takes the parameters in a consistent style, once this.change() has
|
|
32
|
+
* figured out which way it was called.
|
|
33
|
+
*/
|
|
34
|
+
const _changeMultiple = function (component, newProps, callback) {
|
|
35
|
+
// Omit "default" props:
|
|
36
|
+
// ref and key come from react, and don't actually represent
|
|
37
|
+
// the conceptual state of our component
|
|
38
|
+
// onChange comes from our parent to allow this modification,
|
|
39
|
+
// and doesn't conceptually represent the state of our component
|
|
40
|
+
const currProps = _.omit(component.props, WIDGET_PROP_BLACKLIST);
|
|
41
|
+
const nextProps = _.extend(currProps, newProps);
|
|
42
|
+
component.props.onChange(nextProps, callback);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Helper function for changing a single prop
|
|
47
|
+
*/
|
|
48
|
+
const _changeSingle = function (component, propName: string, value, callback) {
|
|
49
|
+
if (value === undefined) {
|
|
50
|
+
// If called with a single prop name, return a lambda to change
|
|
51
|
+
// a single prop on the current object
|
|
52
|
+
return _.partial(_changeSingle, component, propName);
|
|
53
|
+
}
|
|
54
|
+
// If called with two values, change a single prop of the
|
|
55
|
+
// current object
|
|
56
|
+
const newProps = {};
|
|
57
|
+
newProps[propName] = value;
|
|
58
|
+
_changeMultiple(component, newProps, callback);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* this.change()
|
|
63
|
+
*
|
|
64
|
+
* Can be called as follows:
|
|
65
|
+
* this.change(newProps, callback);
|
|
66
|
+
*
|
|
67
|
+
* this.change(propName, propValue, callback);
|
|
68
|
+
*
|
|
69
|
+
* this.change(propName) -> returns a lambda that takes a prop value to
|
|
70
|
+
* set and a callback to call after having set that value.
|
|
71
|
+
*/
|
|
72
|
+
// TODO(WEB-1727): use proper flow syntax for overloaded functions
|
|
73
|
+
export const change: ChangeFn = function (
|
|
74
|
+
newPropsOrSinglePropName,
|
|
75
|
+
propValue,
|
|
76
|
+
callback,
|
|
77
|
+
) {
|
|
78
|
+
if (_.isObject(newPropsOrSinglePropName) && callback === undefined) {
|
|
79
|
+
// Called with an object of multiple props to change
|
|
80
|
+
callback = propValue;
|
|
81
|
+
return _changeMultiple(
|
|
82
|
+
this,
|
|
83
|
+
newPropsOrSinglePropName, // object newProps
|
|
84
|
+
callback,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (typeof newPropsOrSinglePropName === "string") {
|
|
88
|
+
// Called with a string propName of a single prop to change
|
|
89
|
+
return _changeSingle(
|
|
90
|
+
this,
|
|
91
|
+
newPropsOrSinglePropName, // string propName
|
|
92
|
+
propValue,
|
|
93
|
+
callback,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
throw new PerseusError(
|
|
97
|
+
"Invalid types sent to this.change(): " +
|
|
98
|
+
_.toArray(arguments).join() +
|
|
99
|
+
"\n" +
|
|
100
|
+
USAGE,
|
|
101
|
+
Errors.Internal,
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const propTypes = {
|
|
106
|
+
onChange: PropTypes.func.isRequired,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export type ChangeableProps = {|
|
|
110
|
+
onChange: (
|
|
111
|
+
values: {[string]: any, ...},
|
|
112
|
+
callback?: ?() => mixed,
|
|
113
|
+
silent?: boolean,
|
|
114
|
+
) => mixed,
|
|
115
|
+
|};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import _ from "underscore";
|
|
3
|
+
|
|
4
|
+
import WIDGET_PROP_BLACKLIST from "./widget-prop-blacklist.js";
|
|
5
|
+
|
|
6
|
+
const EditorJsonify = {
|
|
7
|
+
serialize: function (): $FlowFixMe {
|
|
8
|
+
// Omit props that get passed to all widgets
|
|
9
|
+
return _.omit(this.props, WIDGET_PROP_BLACKLIST);
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default EditorJsonify;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
/**
|
|
3
|
+
* A mixin that renders a custom software keypad in additional to the base
|
|
4
|
+
* component. The base component will receive blur events when the keypad is
|
|
5
|
+
* dismissed and can access the keypad element itself so as to manage its
|
|
6
|
+
* activation and dismissal.
|
|
7
|
+
*
|
|
8
|
+
* TODO(charlie): This would make a nicer higher-order component, except that
|
|
9
|
+
* we need to expose methods on the base component (i.e., `ItemRenderer`). When
|
|
10
|
+
* `ItemRenderer` and friends are written as ES6 Classes, we can have them
|
|
11
|
+
* extend a `ProvideKeypad` component instead of using this mixin.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {Keypad} from "@khanacademy/math-input";
|
|
15
|
+
import PropTypes from "prop-types";
|
|
16
|
+
import * as React from "react";
|
|
17
|
+
import ReactDOM from "react-dom";
|
|
18
|
+
|
|
19
|
+
export type KeypadProps = {|
|
|
20
|
+
// An Aphrodite style object, to be applied to the keypad container.
|
|
21
|
+
// Note that, given our awkward structure of injecting the keypad, this
|
|
22
|
+
// style won't be applied or updated dynamically. Rather, it will only
|
|
23
|
+
// be applied in `componentDidMount`.
|
|
24
|
+
keypadStyle?: any,
|
|
25
|
+
|};
|
|
26
|
+
|
|
27
|
+
export type KeypadApiOptions = {|
|
|
28
|
+
customKeypad: boolean,
|
|
29
|
+
// eslint-disable-next-line flowtype/no-weak-types
|
|
30
|
+
nativeKeypadProxy: Function,
|
|
31
|
+
|};
|
|
32
|
+
|
|
33
|
+
// NOTE: This is not a real component. It's a collection of methods used to
|
|
34
|
+
// create and manage a Keypad instances.
|
|
35
|
+
// TODO(LP-10789): replace this with a React Context object to pass information
|
|
36
|
+
// between Perseus and the Keypad.
|
|
37
|
+
const ProvideKeypad = {
|
|
38
|
+
propTypes: {
|
|
39
|
+
apiOptions: (PropTypes.shape({
|
|
40
|
+
customKeypad: PropTypes.bool,
|
|
41
|
+
nativeKeypadProxy: PropTypes.func,
|
|
42
|
+
}): React$PropType$Primitive<{
|
|
43
|
+
customKeypad?: boolean,
|
|
44
|
+
nativeKeypadProxy?: (...a: $ReadOnlyArray<any>) => mixed,
|
|
45
|
+
...
|
|
46
|
+
}>),
|
|
47
|
+
// An Aphrodite style object, to be applied to the keypad container.
|
|
48
|
+
// Note that, given our awkward structure of injecting the keypad, this
|
|
49
|
+
// style won't be applied or updated dynamically. Rather, it will only
|
|
50
|
+
// be applied in `componentDidMount`.
|
|
51
|
+
keypadStyle: PropTypes.any,
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
getInitialState(): {|keypadElement: any | null|} {
|
|
55
|
+
// $FlowFixMe[object-this-reference]
|
|
56
|
+
const _this = this;
|
|
57
|
+
let keypadElement = null;
|
|
58
|
+
if (
|
|
59
|
+
_this.props.apiOptions &&
|
|
60
|
+
_this.props.apiOptions.customKeypad &&
|
|
61
|
+
_this.props.apiOptions.nativeKeypadProxy
|
|
62
|
+
) {
|
|
63
|
+
keypadElement = _this.props.apiOptions.nativeKeypadProxy(
|
|
64
|
+
() => _this.blur && _this.blur(),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return {keypadElement};
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
componentDidMount() {
|
|
71
|
+
// $FlowFixMe[object-this-reference]
|
|
72
|
+
const _this = this;
|
|
73
|
+
if (
|
|
74
|
+
_this.props.apiOptions &&
|
|
75
|
+
_this.props.apiOptions.customKeypad &&
|
|
76
|
+
!_this.props.apiOptions.nativeKeypadProxy
|
|
77
|
+
) {
|
|
78
|
+
// TODO(charlie): Render this and the wrapped component in the same
|
|
79
|
+
// React tree. We may also want to add this keypad asynchronously
|
|
80
|
+
// or on-demand in the future.
|
|
81
|
+
_this._keypadContainer = document.createElement("div");
|
|
82
|
+
document.body?.appendChild(_this._keypadContainer);
|
|
83
|
+
|
|
84
|
+
// TODO(LP-11406): Replace with React Portal
|
|
85
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
86
|
+
ReactDOM.render(
|
|
87
|
+
<Keypad
|
|
88
|
+
onElementMounted={(element) => {
|
|
89
|
+
// NOTE(kevinb): The reason why this setState works is
|
|
90
|
+
// b/c we're calling it manually from item-renderer.jsx
|
|
91
|
+
// and we're manually setting the 'this' by using 'call'
|
|
92
|
+
_this.setState({
|
|
93
|
+
keypadElement: element,
|
|
94
|
+
});
|
|
95
|
+
}}
|
|
96
|
+
onDismiss={() => {
|
|
97
|
+
_this.blur && _this.blur();
|
|
98
|
+
}}
|
|
99
|
+
style={_this.props.keypadStyle}
|
|
100
|
+
/>,
|
|
101
|
+
_this._keypadContainer,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
componentWillUnmount() {
|
|
107
|
+
// $FlowFixMe[object-this-reference]
|
|
108
|
+
const _this = this;
|
|
109
|
+
if (_this._keypadContainer) {
|
|
110
|
+
ReactDOM.unmountComponentAtNode(_this._keypadContainer);
|
|
111
|
+
if (_this._keypadContainer.parentNode) {
|
|
112
|
+
// Note ChildNode.remove() isn't available in older Android
|
|
113
|
+
// webviews.
|
|
114
|
+
_this._keypadContainer.parentNode.removeChild(
|
|
115
|
+
_this._keypadContainer,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
_this._keypadContainer = null;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
keypadElement(): any {
|
|
123
|
+
// $FlowFixMe[object-this-reference]
|
|
124
|
+
const _this = this;
|
|
125
|
+
return _this.state.keypadElement;
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export default ProvideKeypad;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
/* Free implementation of getUserInput. This should be used sparingly, since it
|
|
3
|
+
* just returns all the widget's props rather than picking out those which were
|
|
4
|
+
* input by the user.
|
|
5
|
+
*/
|
|
6
|
+
import _ from "underscore";
|
|
7
|
+
|
|
8
|
+
import WIDGET_PROP_BLACKLIST from "./widget-prop-blacklist.js";
|
|
9
|
+
|
|
10
|
+
const WidgetJsonifyDeprecated = {
|
|
11
|
+
getUserInput: function (): $FlowFixMe {
|
|
12
|
+
// Omit props that get passed to all widgets
|
|
13
|
+
return _.omit(this.props, WIDGET_PROP_BLACKLIST);
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
// Static version of `WidgetJsonifyDeprecated.getUserInput`
|
|
17
|
+
getUserInputFromProps: function (props: $FlowFixMe): $FlowFixMe {
|
|
18
|
+
// Omit props that get passed to all widgets
|
|
19
|
+
return _.omit(props, WIDGET_PROP_BLACKLIST);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default WidgetJsonifyDeprecated;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
/**
|
|
3
|
+
* These are things that widgets should exclude when serializing themselves.
|
|
4
|
+
*
|
|
5
|
+
* The use of this list needs to die. Basically, there are codepaths that
|
|
6
|
+
* blindly serialize the "props" of a widget so that it can pass around its
|
|
7
|
+
* info. Unfortunately, props aren't guaranteed to be serializable, and
|
|
8
|
+
* automatically serializing schemaless list of attributes causes issues (e.g.
|
|
9
|
+
* circular JSON structures sometimes).
|
|
10
|
+
*
|
|
11
|
+
* This blacklists things that we know don't need to be serialized.
|
|
12
|
+
*/
|
|
13
|
+
export default [
|
|
14
|
+
// standard props "added" by react
|
|
15
|
+
// (technically the renderer still adds them)
|
|
16
|
+
"key",
|
|
17
|
+
"ref",
|
|
18
|
+
// added by src/renderer.jsx
|
|
19
|
+
"containerSizeClass",
|
|
20
|
+
"widgetId",
|
|
21
|
+
"onChange",
|
|
22
|
+
"problemNum",
|
|
23
|
+
"apiOptions",
|
|
24
|
+
"questionCompleted",
|
|
25
|
+
"findWidgets",
|
|
26
|
+
// added by src/editor.jsx, for widgets removing themselves
|
|
27
|
+
// this is soooo not the right place for this, but alas.
|
|
28
|
+
"onRemove",
|
|
29
|
+
// also added by src/editor.jsx
|
|
30
|
+
"id",
|
|
31
|
+
// Callbacks and items for interaction handling
|
|
32
|
+
"onBlur",
|
|
33
|
+
"onFocus",
|
|
34
|
+
"trackInteraction",
|
|
35
|
+
"keypadElement",
|
|
36
|
+
];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
4
|
+
import * as i18n from "@khanacademy/wonder-blocks-i18n";
|
|
5
|
+
import {HeadingSmall} from "@khanacademy/wonder-blocks-typography";
|
|
6
|
+
import {StyleSheet} from "aphrodite";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
|
|
9
|
+
import {MultiItemRendererWithDebugUI} from "../../../../../testing/multi-item-renderer-with-debug-ui.jsx";
|
|
10
|
+
import {question1} from "../__testdata__/multi-renderer_testdata.js";
|
|
11
|
+
|
|
12
|
+
type StoryArgs = {||};
|
|
13
|
+
|
|
14
|
+
type Story = {|
|
|
15
|
+
title: string,
|
|
16
|
+
|};
|
|
17
|
+
|
|
18
|
+
export const SingleItem = (args: StoryArgs): React.Node => {
|
|
19
|
+
const item = {
|
|
20
|
+
_multi: {
|
|
21
|
+
// $FlowFixMe[not-an-object]
|
|
22
|
+
...question1._multi,
|
|
23
|
+
blurb: {
|
|
24
|
+
// $FlowFixMe[not-an-object]
|
|
25
|
+
// $FlowFixMe[prop-missing]
|
|
26
|
+
...question1._multi.blurb,
|
|
27
|
+
content:
|
|
28
|
+
"This is a short snippet to help you understand the context of the question. We call it the 'blurb'.",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
return (
|
|
33
|
+
<MultiItemRendererWithDebugUI simpleItem={item}>
|
|
34
|
+
{({renderers}) => {
|
|
35
|
+
const {blurb, question, hints} = renderers;
|
|
36
|
+
return (
|
|
37
|
+
<View>
|
|
38
|
+
<View style={styles.section}>
|
|
39
|
+
<HeadingSmall style={styles.heading}>
|
|
40
|
+
{i18n.doNotTranslate("Blurb")}
|
|
41
|
+
</HeadingSmall>
|
|
42
|
+
{blurb}
|
|
43
|
+
</View>
|
|
44
|
+
<View style={styles.section}>
|
|
45
|
+
<HeadingSmall style={styles.heading}>
|
|
46
|
+
{i18n.doNotTranslate("Question")}
|
|
47
|
+
</HeadingSmall>
|
|
48
|
+
{question}
|
|
49
|
+
</View>
|
|
50
|
+
<View style={styles.section}>
|
|
51
|
+
<HeadingSmall style={styles.heading}>
|
|
52
|
+
{i18n.doNotTranslate("Hints")}
|
|
53
|
+
</HeadingSmall>
|
|
54
|
+
<View style={styles.hints}>
|
|
55
|
+
{
|
|
56
|
+
// $FlowFixMe[prop-missing]
|
|
57
|
+
hints?.firstN(2)
|
|
58
|
+
}
|
|
59
|
+
</View>
|
|
60
|
+
</View>
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
}}
|
|
64
|
+
</MultiItemRendererWithDebugUI>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const styles = StyleSheet.create({
|
|
69
|
+
section: {
|
|
70
|
+
backgroundColor: "#F5F5F5",
|
|
71
|
+
padding: "5px",
|
|
72
|
+
borderWidth: "1px",
|
|
73
|
+
marginTop: "5px",
|
|
74
|
+
marginBottom: "5px",
|
|
75
|
+
},
|
|
76
|
+
heading: {
|
|
77
|
+
backgroundColor: "#A9A9A9",
|
|
78
|
+
margin: "-5px",
|
|
79
|
+
padding: "5px",
|
|
80
|
+
},
|
|
81
|
+
hints: {
|
|
82
|
+
marginLeft: "50px",
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export default ({
|
|
87
|
+
title: "Perseus/Renderers/Multi Renderer",
|
|
88
|
+
}: Story);
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import shapes from "../shapes.js";
|
|
4
|
+
|
|
5
|
+
import type {Item} from "../item-types.js";
|
|
6
|
+
import type {Shape} from "../shape-types.js";
|
|
7
|
+
|
|
8
|
+
export const simpleQuestionShape: Shape = shapes.shape({
|
|
9
|
+
blurb: shapes.content,
|
|
10
|
+
question: shapes.content,
|
|
11
|
+
hints: shapes.hints,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Shape: simpleQuestionShape
|
|
15
|
+
export const question1: Item = {
|
|
16
|
+
_multi: {
|
|
17
|
+
blurb: {
|
|
18
|
+
__type: "content",
|
|
19
|
+
content: "",
|
|
20
|
+
images: {},
|
|
21
|
+
widgets: {},
|
|
22
|
+
},
|
|
23
|
+
hints: [
|
|
24
|
+
{
|
|
25
|
+
__type: "hint",
|
|
26
|
+
content:
|
|
27
|
+
"If two triangles are congruent, then they have the same side lengths and angle measures.",
|
|
28
|
+
images: {},
|
|
29
|
+
replace: false,
|
|
30
|
+
widgets: {},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
__type: "hint",
|
|
34
|
+
content:
|
|
35
|
+
"A triangle congruent to triangle $ABC$ must also have side lengths of $12$, $14$ and $20$.",
|
|
36
|
+
images: {},
|
|
37
|
+
replace: false,
|
|
38
|
+
widgets: {},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
__type: "hint",
|
|
42
|
+
content:
|
|
43
|
+
"The following triangle is congruent to triangle $ABC$:\n\n* A triangle with side lengths of $12$, $14$, and $20$",
|
|
44
|
+
images: {},
|
|
45
|
+
replace: false,
|
|
46
|
+
widgets: {},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
question: {
|
|
50
|
+
__type: "content",
|
|
51
|
+
content:
|
|
52
|
+
"Triangle $ABC$ has side lengths of $12$, $14$, and $20$. Which of the following triangles is congruent to triangle $ABC$ ?\n\n[[☃ radio 1]]\n\nEnter the number 3 into this field: [[☃ input-number 1]]",
|
|
53
|
+
widgets: {
|
|
54
|
+
"radio 1": {
|
|
55
|
+
alignment: "default",
|
|
56
|
+
graded: true,
|
|
57
|
+
options: {
|
|
58
|
+
choices: [
|
|
59
|
+
{
|
|
60
|
+
clue: "Congruent triangles have the same side lengths.",
|
|
61
|
+
content:
|
|
62
|
+
"A triangle with side lengths of $3$, $4$, and $5$",
|
|
63
|
+
correct: false,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
clue: "Congruent triangles have the same side lengths.\n\nThis choice is similar to triangle $ABC$.",
|
|
67
|
+
content:
|
|
68
|
+
"A triangle with side lengths of $6$, $7$, and $10$",
|
|
69
|
+
correct: false,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
clue: "Congruent triangles have the same side lengths.",
|
|
73
|
+
content:
|
|
74
|
+
"A triangle with side lengths of $10$, $12$, and $18$",
|
|
75
|
+
correct: false,
|
|
76
|
+
isNoneOfTheAbove: false,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
clue: "Congruent triangles have the same side lengths.",
|
|
80
|
+
content:
|
|
81
|
+
"A triangle with side lengths of $12$, $14$, and $20$",
|
|
82
|
+
correct: true,
|
|
83
|
+
isNoneOfTheAbove: false,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
clue: "Congruent triangles have the same side lengths.\n\nThis choice is similar to triangle $ABC$.",
|
|
87
|
+
content:
|
|
88
|
+
"A triangle with side lengths of $24$, $28$, and $40$",
|
|
89
|
+
correct: false,
|
|
90
|
+
isNoneOfTheAbove: false,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
countChoices: false,
|
|
94
|
+
deselectEnabled: false,
|
|
95
|
+
displayCount: null,
|
|
96
|
+
hasNoneOfTheAbove: false,
|
|
97
|
+
multipleSelect: false,
|
|
98
|
+
randomize: false,
|
|
99
|
+
},
|
|
100
|
+
static: false,
|
|
101
|
+
type: "radio",
|
|
102
|
+
version: {
|
|
103
|
+
major: 1,
|
|
104
|
+
minor: 0,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
"input-number 1": {
|
|
108
|
+
type: "input-number",
|
|
109
|
+
graded: true,
|
|
110
|
+
options: {
|
|
111
|
+
answerType: "number",
|
|
112
|
+
value: "-42",
|
|
113
|
+
simplify: "required",
|
|
114
|
+
size: "normal",
|
|
115
|
+
inexact: false,
|
|
116
|
+
maxError: 0.1,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const mockWidgetConfig = {
|
|
125
|
+
graded: true,
|
|
126
|
+
version: {major: 0, minor: 0},
|
|
127
|
+
static: false,
|
|
128
|
+
type: "mock-widget",
|
|
129
|
+
options: {static: false, smiling: true},
|
|
130
|
+
alignment: "default",
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Shape: simpleQuestionShape
|
|
134
|
+
export const mockedQuestion1: Item = {
|
|
135
|
+
_multi: {
|
|
136
|
+
blurb: {
|
|
137
|
+
__type: "content",
|
|
138
|
+
content: "Here's a blurb [[☃ mock-widget 1]]",
|
|
139
|
+
images: {},
|
|
140
|
+
widgets: {
|
|
141
|
+
"mock-widget 1": mockWidgetConfig,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
hints: [
|
|
145
|
+
{
|
|
146
|
+
__type: "hint",
|
|
147
|
+
content: "Hint #1 [[☃ mock-widget 2]]",
|
|
148
|
+
images: {},
|
|
149
|
+
replace: false,
|
|
150
|
+
widgets: {
|
|
151
|
+
"mock-widget 2": mockWidgetConfig,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
__type: "hint",
|
|
156
|
+
content: "Hint #1 [[☃ mock-widget 3]]",
|
|
157
|
+
images: {},
|
|
158
|
+
replace: false,
|
|
159
|
+
widgets: {
|
|
160
|
+
"mock-widget 3": mockWidgetConfig,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
question: {
|
|
165
|
+
__type: "content",
|
|
166
|
+
content:
|
|
167
|
+
"What is the answer to this?\n\n[[☃ mock-widget 4]]\n\n[[☃ mock-widget 5]]",
|
|
168
|
+
widgets: {
|
|
169
|
+
"mock-widget 4": mockWidgetConfig,
|
|
170
|
+
"mock-widget 5": mockWidgetConfig,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
};
|