@khanacademy/perseus 1.3.6 → 1.4.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/CHANGELOG.md +34 -0
- package/dist/es/index.css +3 -2
- package/dist/es/index.js +80 -59
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +3 -2
- package/dist/index.js +76 -49
- package/dist/index.js.map +1 -1
- package/package.json +37 -37
- package/src/components/__stories__/tex.stories.jsx +8 -2
- package/src/index.js +1 -1
- package/src/interactive2/movable-point.jsx +2 -4
- package/src/item-renderer.jsx +3 -6
- package/src/mixins/__tests__/{widget-prop-blacklist_test.js → widget-prop-denylist_test.js} +1 -1
- package/src/mixins/changeable.jsx +2 -2
- package/src/mixins/editor-jsonify.jsx +2 -2
- package/src/mixins/provide-keypad.jsx +3 -3
- package/src/mixins/widget-jsonify-deprecated.jsx +3 -3
- package/src/mixins/{widget-prop-blacklist.js → widget-prop-denylist.js} +2 -3
- package/src/multi-items/__tests__/__snapshots__/multi-renderer_test.js.snap +0 -10
- package/src/styles/perseus-renderer.less +0 -3
- package/src/styles/widgets/radio.less +4 -0
- package/src/types.js +1 -7
- package/src/util/react-render.js +27 -0
- package/src/util.js +1 -1
- package/src/widget-container.jsx +1 -1
- package/src/widgets/__stories__/on-screen-keypad.stories.jsx +118 -0
- package/src/widgets/__tests__/__snapshots__/categorizer_test.jsx.snap +6 -6
- package/src/widgets/__tests__/__snapshots__/definition_test.js.snap +0 -2
- package/src/widgets/__tests__/__snapshots__/graded-group-set-jipt_test.jsx.snap +3 -6
- package/src/widgets/__tests__/__snapshots__/graded-group-set_test.jsx.snap +15 -13
- package/src/widgets/__tests__/__snapshots__/graded-group_test.jsx.snap +6 -7
- package/src/widgets/__tests__/__snapshots__/group_test.jsx.snap +0 -10
- package/src/widgets/__tests__/__snapshots__/radio_test.jsx.snap +0 -104
- package/src/widgets/__tests__/__snapshots__/video_test.jsx.snap +2 -4
- package/src/widgets/__tests__/graded-group-set_test.jsx +29 -9
- package/src/widgets/categorizer.jsx +6 -1
- package/src/widgets/cs-program.jsx +1 -1
- package/src/widgets/graded-group-set.jsx +43 -39
- package/src/widgets/graded-group.jsx +3 -3
- package/src/widgets/iframe.jsx +1 -1
- package/src/widgets/passage-ref.jsx +2 -2
- package/src/widgets/radio/widget.jsx +7 -6
- package/src/widgets/radio.jsx +2 -2
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Core Perseus API (includes renderers and widgets)",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.4.1",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@khanacademy/kas": "^0.2.7",
|
|
25
25
|
"@khanacademy/kmath": "^0.0.8",
|
|
26
|
-
"@khanacademy/math-input": "^0.6.
|
|
27
|
-
"@khanacademy/perseus-linter": "^0.2.
|
|
28
|
-
"@khanacademy/pure-markdown": "^0.1.
|
|
26
|
+
"@khanacademy/math-input": "^0.6.7",
|
|
27
|
+
"@khanacademy/perseus-linter": "^0.2.5",
|
|
28
|
+
"@khanacademy/pure-markdown": "^0.1.5",
|
|
29
29
|
"@khanacademy/simple-markdown": "^0.8.6",
|
|
30
30
|
"mathquill": "git+https://git@github.com/Khan/mathquill.git#a9ae54e057c5c1acc8244a5627acbff29901d992"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@khanacademy/wonder-blocks-button": "^
|
|
34
|
-
"@khanacademy/wonder-blocks-clickable": "^2.
|
|
35
|
-
"@khanacademy/wonder-blocks-color": "^1.1
|
|
36
|
-
"@khanacademy/wonder-blocks-core": "^4.
|
|
37
|
-
"@khanacademy/wonder-blocks-data": "^
|
|
38
|
-
"@khanacademy/wonder-blocks-dropdown": "^2.10.
|
|
39
|
-
"@khanacademy/wonder-blocks-form": "^
|
|
40
|
-
"@khanacademy/wonder-blocks-i18n": "^1.2.
|
|
41
|
-
"@khanacademy/wonder-blocks-layout": "^1.4.
|
|
42
|
-
"@khanacademy/wonder-blocks-link": "^3.
|
|
43
|
-
"@khanacademy/wonder-blocks-modal": "^
|
|
44
|
-
"@khanacademy/wonder-blocks-popover": "^1.1.
|
|
45
|
-
"@khanacademy/wonder-blocks-progress-spinner": "^1.1.
|
|
33
|
+
"@khanacademy/wonder-blocks-button": "^3.0.14",
|
|
34
|
+
"@khanacademy/wonder-blocks-clickable": "^2.4.5",
|
|
35
|
+
"@khanacademy/wonder-blocks-color": "^1.2.1",
|
|
36
|
+
"@khanacademy/wonder-blocks-core": "^4.7.0",
|
|
37
|
+
"@khanacademy/wonder-blocks-data": "^10.1.0",
|
|
38
|
+
"@khanacademy/wonder-blocks-dropdown": "^2.10.7",
|
|
39
|
+
"@khanacademy/wonder-blocks-form": "^3.1.11",
|
|
40
|
+
"@khanacademy/wonder-blocks-i18n": "^1.2.4",
|
|
41
|
+
"@khanacademy/wonder-blocks-layout": "^1.4.16",
|
|
42
|
+
"@khanacademy/wonder-blocks-link": "^3.9.1",
|
|
43
|
+
"@khanacademy/wonder-blocks-modal": "^3.0.7",
|
|
44
|
+
"@khanacademy/wonder-blocks-popover": "^1.1.30",
|
|
45
|
+
"@khanacademy/wonder-blocks-progress-spinner": "^1.1.40",
|
|
46
46
|
"@khanacademy/wonder-blocks-spacing": "^3.0.5",
|
|
47
|
-
"@khanacademy/wonder-blocks-tooltip": "^1.4.
|
|
48
|
-
"@khanacademy/wonder-blocks-typography": "^1.1.
|
|
49
|
-
"@khanacademy/wonder-stuff-core": "^
|
|
47
|
+
"@khanacademy/wonder-blocks-tooltip": "^1.4.6",
|
|
48
|
+
"@khanacademy/wonder-blocks-typography": "^1.1.38",
|
|
49
|
+
"@khanacademy/wonder-stuff-core": "^1.2.1",
|
|
50
50
|
"aphrodite": "^1.2.5",
|
|
51
51
|
"classnames": "^1.1.4",
|
|
52
52
|
"create-react-class": "^15.6.3",
|
|
@@ -63,23 +63,23 @@
|
|
|
63
63
|
"underscore": "^1.4.4"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
-
"@khanacademy/wonder-blocks-button": "^
|
|
67
|
-
"@khanacademy/wonder-blocks-clickable": "^2.
|
|
68
|
-
"@khanacademy/wonder-blocks-color": "^1.1
|
|
69
|
-
"@khanacademy/wonder-blocks-core": "^4.
|
|
70
|
-
"@khanacademy/wonder-blocks-data": "^
|
|
71
|
-
"@khanacademy/wonder-blocks-dropdown": "^2.10.
|
|
72
|
-
"@khanacademy/wonder-blocks-form": "^
|
|
73
|
-
"@khanacademy/wonder-blocks-i18n": "^1.2.
|
|
74
|
-
"@khanacademy/wonder-blocks-layout": "^1.4.
|
|
75
|
-
"@khanacademy/wonder-blocks-link": "^3.
|
|
76
|
-
"@khanacademy/wonder-blocks-modal": "^
|
|
77
|
-
"@khanacademy/wonder-blocks-popover": "^1.1.
|
|
78
|
-
"@khanacademy/wonder-blocks-progress-spinner": "^1.1.
|
|
66
|
+
"@khanacademy/wonder-blocks-button": "^3.0.14",
|
|
67
|
+
"@khanacademy/wonder-blocks-clickable": "^2.4.5",
|
|
68
|
+
"@khanacademy/wonder-blocks-color": "^1.2.1",
|
|
69
|
+
"@khanacademy/wonder-blocks-core": "^4.7.0",
|
|
70
|
+
"@khanacademy/wonder-blocks-data": "^10.1.0",
|
|
71
|
+
"@khanacademy/wonder-blocks-dropdown": "^2.10.7",
|
|
72
|
+
"@khanacademy/wonder-blocks-form": "^3.1.11",
|
|
73
|
+
"@khanacademy/wonder-blocks-i18n": "^1.2.4",
|
|
74
|
+
"@khanacademy/wonder-blocks-layout": "^1.4.16",
|
|
75
|
+
"@khanacademy/wonder-blocks-link": "^3.9.1",
|
|
76
|
+
"@khanacademy/wonder-blocks-modal": "^3.0.7",
|
|
77
|
+
"@khanacademy/wonder-blocks-popover": "^1.1.30",
|
|
78
|
+
"@khanacademy/wonder-blocks-progress-spinner": "^1.1.40",
|
|
79
79
|
"@khanacademy/wonder-blocks-spacing": "^3.0.5",
|
|
80
|
-
"@khanacademy/wonder-blocks-tooltip": "^1.4.
|
|
81
|
-
"@khanacademy/wonder-blocks-typography": "^1.1.
|
|
82
|
-
"@khanacademy/wonder-stuff-core": "^
|
|
80
|
+
"@khanacademy/wonder-blocks-tooltip": "^1.4.6",
|
|
81
|
+
"@khanacademy/wonder-blocks-typography": "^1.1.38",
|
|
82
|
+
"@khanacademy/wonder-stuff-core": "^1.2.1",
|
|
83
83
|
"aphrodite": "^1.2.5",
|
|
84
84
|
"classnames": "^1.1.4",
|
|
85
85
|
"create-react-class": "^15.6.3",
|
|
@@ -92,4 +92,4 @@
|
|
|
92
92
|
"underscore": "^1.4.4"
|
|
93
93
|
},
|
|
94
94
|
"keywords": []
|
|
95
|
-
}
|
|
95
|
+
}
|
|
@@ -3,16 +3,22 @@ import * as React from "react";
|
|
|
3
3
|
|
|
4
4
|
import TeX from "../tex.jsx";
|
|
5
5
|
|
|
6
|
-
type StoryArgs = {
|
|
6
|
+
type StoryArgs = {|
|
|
7
|
+
equation: string,
|
|
8
|
+
|};
|
|
7
9
|
|
|
8
10
|
type Story = {|
|
|
9
11
|
title: string,
|
|
12
|
+
args: StoryArgs,
|
|
10
13
|
|};
|
|
11
14
|
|
|
12
15
|
export default ({
|
|
13
16
|
title: "Perseus/Components/Tex",
|
|
17
|
+
args: {
|
|
18
|
+
equation: "f(x) = x + 1",
|
|
19
|
+
},
|
|
14
20
|
}: Story);
|
|
15
21
|
|
|
16
22
|
export const BasicOperation = (args: StoryArgs): React.Node => {
|
|
17
|
-
return <TeX setAssetStatus={() => {}} children=
|
|
23
|
+
return <TeX setAssetStatus={() => {}} children={args.equation} />;
|
|
18
24
|
};
|
package/src/index.js
CHANGED
|
@@ -87,7 +87,7 @@ export * as SizingUtils from "./util/sizing-utils.js";
|
|
|
87
87
|
export * as Changeable from "./mixins/changeable.jsx";
|
|
88
88
|
export {default as EditorJsonify} from "./mixins/editor-jsonify.jsx";
|
|
89
89
|
export {default as WidgetJsonifyDeprecated} from "./mixins/widget-jsonify-deprecated.jsx";
|
|
90
|
-
export {default as
|
|
90
|
+
export {default as WIDGET_PROP_DENYLIST} from "./mixins/widget-prop-denylist.js";
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
* Types
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
*/
|
|
53
53
|
import {point as kpoint, vector as kvector} from "@khanacademy/kmath";
|
|
54
54
|
import * as React from "react";
|
|
55
|
-
import * as ReactDOM from "react-dom";
|
|
56
55
|
import _ from "underscore";
|
|
57
56
|
|
|
58
57
|
import InlineIcon from "../components/inline-icon.jsx";
|
|
59
58
|
import {iconTrash} from "../icon-paths.js";
|
|
60
59
|
import KhanColors from "../util/colors.js";
|
|
60
|
+
import reactRender from "../util/react-render.js";
|
|
61
61
|
import Tex from "../util/tex.js";
|
|
62
62
|
|
|
63
63
|
import InteractiveUtil from "./interactive-util.js";
|
|
@@ -275,9 +275,7 @@ _.extend(MovablePoint.prototype, {
|
|
|
275
275
|
|
|
276
276
|
const showTrashTooltip = () => {
|
|
277
277
|
this._showTooltip((container) => {
|
|
278
|
-
|
|
279
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
280
|
-
ReactDOM.render(
|
|
278
|
+
reactRender(
|
|
281
279
|
<span style={{fontSize: "2em"}}>
|
|
282
280
|
<InlineIcon
|
|
283
281
|
{...iconTrash}
|
package/src/item-renderer.jsx
CHANGED
|
@@ -12,6 +12,7 @@ import ProvideKeypad from "./mixins/provide-keypad.jsx";
|
|
|
12
12
|
import {ApiOptions} from "./perseus-api.jsx";
|
|
13
13
|
import Renderer from "./renderer.jsx";
|
|
14
14
|
import Util from "./util.js";
|
|
15
|
+
import reactRender from "./util/react-render.js";
|
|
15
16
|
|
|
16
17
|
import type {KeypadProps} from "./mixins/provide-keypad.jsx";
|
|
17
18
|
import type {PerseusItem} from "./perseus-types.js";
|
|
@@ -177,9 +178,7 @@ class ItemRenderer extends React.Component<Props, State> {
|
|
|
177
178
|
// that have completely different places in the DOM, we have to do this
|
|
178
179
|
// strangeness instead of relying on React's normal render() method.
|
|
179
180
|
// TODO(alpert): Figure out how to clean this up somehow
|
|
180
|
-
|
|
181
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
182
|
-
ReactDOM.render(
|
|
181
|
+
reactRender(
|
|
183
182
|
// metadata (from item.question, aka PerseusRenderer)
|
|
184
183
|
// replace (also item.question, aka PerseusRenderer)
|
|
185
184
|
// savedState (I _think_ this is serializedState on Renderer)
|
|
@@ -218,9 +217,7 @@ class ItemRenderer extends React.Component<Props, State> {
|
|
|
218
217
|
workArea,
|
|
219
218
|
);
|
|
220
219
|
|
|
221
|
-
|
|
222
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
223
|
-
ReactDOM.render(
|
|
220
|
+
reactRender(
|
|
224
221
|
<HintsRenderer
|
|
225
222
|
ref={(node) => (this.hintsRenderer = node)}
|
|
226
223
|
hints={this.props.item.hints}
|
|
@@ -15,7 +15,7 @@ import _ from "underscore";
|
|
|
15
15
|
import {Errors} from "../logging/log.js";
|
|
16
16
|
import {PerseusError} from "../perseus-error.js";
|
|
17
17
|
|
|
18
|
-
import
|
|
18
|
+
import WIDGET_PROP_DENYLIST from "./widget-prop-denylist.js";
|
|
19
19
|
|
|
20
20
|
import type {ChangeFn} from "../types.js";
|
|
21
21
|
|
|
@@ -37,7 +37,7 @@ const _changeMultiple = function (component, newProps, callback) {
|
|
|
37
37
|
// the conceptual state of our component
|
|
38
38
|
// onChange comes from our parent to allow this modification,
|
|
39
39
|
// and doesn't conceptually represent the state of our component
|
|
40
|
-
const currProps = _.omit(component.props,
|
|
40
|
+
const currProps = _.omit(component.props, WIDGET_PROP_DENYLIST);
|
|
41
41
|
const nextProps = _.extend(currProps, newProps);
|
|
42
42
|
component.props.onChange(nextProps, callback);
|
|
43
43
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import _ from "underscore";
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import WIDGET_PROP_DENYLIST from "./widget-prop-denylist.js";
|
|
5
5
|
|
|
6
6
|
const EditorJsonify = {
|
|
7
7
|
serialize: function (): $FlowFixMe {
|
|
8
8
|
// Omit props that get passed to all widgets
|
|
9
|
-
return _.omit(this.props,
|
|
9
|
+
return _.omit(this.props, WIDGET_PROP_DENYLIST);
|
|
10
10
|
},
|
|
11
11
|
};
|
|
12
12
|
|
|
@@ -16,6 +16,8 @@ import PropTypes from "prop-types";
|
|
|
16
16
|
import * as React from "react";
|
|
17
17
|
import ReactDOM from "react-dom";
|
|
18
18
|
|
|
19
|
+
import reactRender from "../util/react-render.js";
|
|
20
|
+
|
|
19
21
|
import type {CSSProperties} from "aphrodite";
|
|
20
22
|
|
|
21
23
|
export type KeypadProps = {|
|
|
@@ -83,9 +85,7 @@ const ProvideKeypad = {
|
|
|
83
85
|
_this._keypadContainer = document.createElement("div");
|
|
84
86
|
document.body?.appendChild(_this._keypadContainer);
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
88
|
-
ReactDOM.render(
|
|
88
|
+
reactRender(
|
|
89
89
|
<Keypad
|
|
90
90
|
onElementMounted={(element) => {
|
|
91
91
|
// NOTE(kevinb): The reason why this setState works is
|
|
@@ -5,18 +5,18 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import _ from "underscore";
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import WIDGET_PROP_DENYLIST from "./widget-prop-denylist.js";
|
|
9
9
|
|
|
10
10
|
const WidgetJsonifyDeprecated = {
|
|
11
11
|
getUserInput: function (): $FlowFixMe {
|
|
12
12
|
// Omit props that get passed to all widgets
|
|
13
|
-
return _.omit(this.props,
|
|
13
|
+
return _.omit(this.props, WIDGET_PROP_DENYLIST);
|
|
14
14
|
},
|
|
15
15
|
|
|
16
16
|
// Static version of `WidgetJsonifyDeprecated.getUserInput`
|
|
17
17
|
getUserInputFromProps: function (props: $FlowFixMe): $FlowFixMe {
|
|
18
18
|
// Omit props that get passed to all widgets
|
|
19
|
-
return _.omit(props,
|
|
19
|
+
return _.omit(props, WIDGET_PROP_DENYLIST);
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
22
|
|
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
* automatically serializing schemaless list of attributes causes issues (e.g.
|
|
9
9
|
* circular JSON structures sometimes).
|
|
10
10
|
*
|
|
11
|
-
* This
|
|
12
|
-
*
|
|
13
|
-
* TODO(TB): Go through and update usage of BLACKLIST to DENYLIST: https://khanacademy.atlassian.net/browse/LP-13149?atlOrigin=eyJpIjoiNTI0Y2UwNzQ0MzA4NDYzOGI1YWRmNjEwY2E5YzZlZWUiLCJwIjoiaiJ9
|
|
11
|
+
* This blocks things that we know don't need to be serialized.
|
|
14
12
|
*/
|
|
13
|
+
|
|
15
14
|
const denylist = [
|
|
16
15
|
// standard props "added" by react
|
|
17
16
|
// (technically the renderer still adds them)
|
|
@@ -214,9 +214,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
214
214
|
<button
|
|
215
215
|
aria-disabled="false"
|
|
216
216
|
aria-hidden="true"
|
|
217
|
-
aria-label=""
|
|
218
217
|
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-inlineStyles_1jvwfht"
|
|
219
|
-
tabindex="0"
|
|
220
218
|
type="button"
|
|
221
219
|
>
|
|
222
220
|
<div
|
|
@@ -391,9 +389,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
391
389
|
<button
|
|
392
390
|
aria-disabled="false"
|
|
393
391
|
aria-hidden="true"
|
|
394
|
-
aria-label=""
|
|
395
392
|
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-inlineStyles_1jvwfht"
|
|
396
|
-
tabindex="0"
|
|
397
393
|
type="button"
|
|
398
394
|
>
|
|
399
395
|
<div
|
|
@@ -568,9 +564,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
568
564
|
<button
|
|
569
565
|
aria-disabled="false"
|
|
570
566
|
aria-hidden="true"
|
|
571
|
-
aria-label=""
|
|
572
567
|
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-inlineStyles_1jvwfht"
|
|
573
|
-
tabindex="0"
|
|
574
568
|
type="button"
|
|
575
569
|
>
|
|
576
570
|
<div
|
|
@@ -745,9 +739,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
745
739
|
<button
|
|
746
740
|
aria-disabled="false"
|
|
747
741
|
aria-hidden="true"
|
|
748
|
-
aria-label=""
|
|
749
742
|
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-inlineStyles_1jvwfht"
|
|
750
|
-
tabindex="0"
|
|
751
743
|
type="button"
|
|
752
744
|
>
|
|
753
745
|
<div
|
|
@@ -922,9 +914,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
922
914
|
<button
|
|
923
915
|
aria-disabled="false"
|
|
924
916
|
aria-hidden="true"
|
|
925
|
-
aria-label=""
|
|
926
917
|
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-inlineStyles_1jvwfht"
|
|
927
|
-
tabindex="0"
|
|
928
918
|
type="button"
|
|
929
919
|
>
|
|
930
920
|
<div
|
package/src/types.js
CHANGED
|
@@ -9,7 +9,7 @@ import * as React from "react";
|
|
|
9
9
|
import type {SerializedHighlightSet} from "./components/highlighting/types.js";
|
|
10
10
|
import type {ILogger} from "./logging/log.js";
|
|
11
11
|
import type {Item} from "./multi-items/item-types.js";
|
|
12
|
-
import type {PerseusWidget
|
|
12
|
+
import type {PerseusWidget} from "./perseus-types.js";
|
|
13
13
|
import type {SizeClass} from "./util/sizing-utils.js";
|
|
14
14
|
import type {Result} from "@khanacademy/wonder-blocks-data";
|
|
15
15
|
|
|
@@ -85,12 +85,6 @@ export type ChoiceState = {|
|
|
|
85
85
|
readOnly: boolean,
|
|
86
86
|
|};
|
|
87
87
|
|
|
88
|
-
export type RadioChoiceWithMetadata = {|
|
|
89
|
-
...PerseusRadioChoice,
|
|
90
|
-
originalIndex: number,
|
|
91
|
-
correct: boolean,
|
|
92
|
-
|};
|
|
93
|
-
|
|
94
88
|
export type ChangeHandler = (
|
|
95
89
|
{|
|
|
96
90
|
hints?: $ReadOnlyArray<Hint>,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import {RenderStateRoot} from "@khanacademy/wonder-blocks-core";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import ReactDOM from "react-dom";
|
|
5
|
+
|
|
6
|
+
export default function render<ElementType: React$ElementType>(
|
|
7
|
+
element: React.Node,
|
|
8
|
+
container: HTMLElement,
|
|
9
|
+
callback?: () => void,
|
|
10
|
+
): React$ElementRef<ElementType> {
|
|
11
|
+
// TODO(LP-11406): Replace this, or callers, with React Portal
|
|
12
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
13
|
+
return ReactDOM.render(
|
|
14
|
+
/**
|
|
15
|
+
* `RenderStateRoot` is responsible for tracking whether it's
|
|
16
|
+
* the initial render or subsequent renders. It's used by
|
|
17
|
+
* `useUniqueId` and will be used by `UniqueIDProvider` and
|
|
18
|
+
* `WithSSRPlaceholder` in the future. We're placing it as
|
|
19
|
+
* high up in the render tree as possible to ensure that any
|
|
20
|
+
* components using that hook or those components will function
|
|
21
|
+
* correctly.
|
|
22
|
+
*/
|
|
23
|
+
<RenderStateRoot throwIfNested={false}>{element}</RenderStateRoot>,
|
|
24
|
+
container,
|
|
25
|
+
callback,
|
|
26
|
+
);
|
|
27
|
+
}
|
package/src/util.js
CHANGED
package/src/widget-container.jsx
CHANGED
|
@@ -119,7 +119,7 @@ class WidgetContainer extends React.Component<Props, State> {
|
|
|
119
119
|
|
|
120
120
|
// Note: if you add more props here, please consider whether or not
|
|
121
121
|
// it should be auto-serialized (e.g. used in scoreInput()). See
|
|
122
|
-
// widget-jsonify-deprecated.jsx and widget-prop-
|
|
122
|
+
// widget-jsonify-deprecated.jsx and widget-prop-denylist.jsx
|
|
123
123
|
|
|
124
124
|
// We default to an empty object for style instead of null
|
|
125
125
|
// because of a strange bug where the static styles aren't applied
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import {Keypad} from "@khanacademy/math-input";
|
|
3
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
4
|
+
import {StyleSheet} from "aphrodite";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
|
|
7
|
+
import {ItemRenderer} from "../../index.js";
|
|
8
|
+
import KeypadContext from "../../keypad-context.js";
|
|
9
|
+
import {expressionItem3} from "../__testdata__/expression_testdata.js";
|
|
10
|
+
|
|
11
|
+
type StoryArgs = {||};
|
|
12
|
+
|
|
13
|
+
type Story = {|
|
|
14
|
+
title: string,
|
|
15
|
+
|};
|
|
16
|
+
|
|
17
|
+
export default ({
|
|
18
|
+
title: "Perseus/Demos/On Screen Keypad",
|
|
19
|
+
}: Story);
|
|
20
|
+
|
|
21
|
+
const Content = (): React.Node => {
|
|
22
|
+
return (
|
|
23
|
+
<KeypadContext.Consumer>
|
|
24
|
+
{({keypadElement, setRenderer, scrollableElement}) => (
|
|
25
|
+
<>
|
|
26
|
+
<ItemRenderer
|
|
27
|
+
ref={setRenderer}
|
|
28
|
+
problemNum={0}
|
|
29
|
+
apiOptions={{
|
|
30
|
+
customKeypad: true,
|
|
31
|
+
onFocusChange: (
|
|
32
|
+
newFocusPath,
|
|
33
|
+
oldFocusPath,
|
|
34
|
+
keypadElement,
|
|
35
|
+
focusedElement,
|
|
36
|
+
) => {},
|
|
37
|
+
}}
|
|
38
|
+
item={expressionItem3}
|
|
39
|
+
savedState={null}
|
|
40
|
+
/>
|
|
41
|
+
<div id="workarea" />
|
|
42
|
+
<div id="hintsarea" />
|
|
43
|
+
</>
|
|
44
|
+
)}
|
|
45
|
+
</KeypadContext.Consumer>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const Footer = (): React.Node => {
|
|
50
|
+
return (
|
|
51
|
+
<View
|
|
52
|
+
style={[
|
|
53
|
+
styles.keypadContainer,
|
|
54
|
+
{
|
|
55
|
+
// NOTE: in webapp we normally get this from problemProgress
|
|
56
|
+
// from the exercise state store.
|
|
57
|
+
height: 240,
|
|
58
|
+
},
|
|
59
|
+
]}
|
|
60
|
+
>
|
|
61
|
+
<KeypadContext.Consumer>
|
|
62
|
+
{({keypadElement, setKeypadElement, renderer}) => (
|
|
63
|
+
<Keypad
|
|
64
|
+
onElementMounted={setKeypadElement}
|
|
65
|
+
onDismiss={() => renderer && renderer.blur()}
|
|
66
|
+
style={styles.keypad}
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
69
|
+
</KeypadContext.Consumer>
|
|
70
|
+
</View>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const Demo = () => {
|
|
75
|
+
const [keypadElement, setKeypadElement] = React.useState(null);
|
|
76
|
+
const [renderer, setRenderer] = React.useState(null);
|
|
77
|
+
const [scrollableElement, setScrollableElement] = React.useState(
|
|
78
|
+
document.body,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<KeypadContext.Provider
|
|
83
|
+
value={{
|
|
84
|
+
setKeypadElement,
|
|
85
|
+
keypadElement,
|
|
86
|
+
setRenderer,
|
|
87
|
+
renderer,
|
|
88
|
+
setScrollableElement,
|
|
89
|
+
scrollableElement,
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<Content />
|
|
93
|
+
<Footer />
|
|
94
|
+
</KeypadContext.Provider>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const CustomKeypad = (args: StoryArgs): React.Node => <Demo />;
|
|
99
|
+
|
|
100
|
+
const styles = StyleSheet.create({
|
|
101
|
+
keypad: {
|
|
102
|
+
position: "absolute",
|
|
103
|
+
// The keypad itself needs to respond to events even though
|
|
104
|
+
// we've set its container to pointer-events: none;
|
|
105
|
+
pointerEvents: "all",
|
|
106
|
+
},
|
|
107
|
+
keypadContainer: {
|
|
108
|
+
position: "absolute",
|
|
109
|
+
width: "100%",
|
|
110
|
+
bottom: 0,
|
|
111
|
+
// Hide the overflow of this container so when the keypad is
|
|
112
|
+
// dismissed, it doesn't overlap the toolbar.
|
|
113
|
+
overflow: "hidden",
|
|
114
|
+
// Prevent container from swallowing events that the exercise
|
|
115
|
+
// below it needs to respond to.
|
|
116
|
+
pointerEvents: "none",
|
|
117
|
+
},
|
|
118
|
+
});
|
|
@@ -62,9 +62,9 @@ exports[`categorizer widget should snapshot on mobile: first mobile render 1`] =
|
|
|
62
62
|
>
|
|
63
63
|
<thead>
|
|
64
64
|
<tr>
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
<td
|
|
66
|
+
class="emptyHeaderCell_1mttrgd"
|
|
67
|
+
/>
|
|
68
68
|
<th
|
|
69
69
|
class="header_whrfk4"
|
|
70
70
|
>
|
|
@@ -509,9 +509,9 @@ exports[`categorizer widget should snapshot: first render 1`] = `
|
|
|
509
509
|
>
|
|
510
510
|
<thead>
|
|
511
511
|
<tr>
|
|
512
|
-
<
|
|
513
|
-
|
|
514
|
-
|
|
512
|
+
<td
|
|
513
|
+
class="emptyHeaderCell_1mttrgd"
|
|
514
|
+
/>
|
|
515
515
|
<th
|
|
516
516
|
class="header_whrfk4"
|
|
517
517
|
>
|
|
@@ -39,7 +39,6 @@ exports[`Definition widget should have a default snapshot: first render 1`] = `
|
|
|
39
39
|
aria-disabled="false"
|
|
40
40
|
class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1hl5pu8"
|
|
41
41
|
role="button"
|
|
42
|
-
tabindex="0"
|
|
43
42
|
type="button"
|
|
44
43
|
>
|
|
45
44
|
<span
|
|
@@ -97,7 +96,6 @@ exports[`Definition widget should have an open state snapshot: open state 1`] =
|
|
|
97
96
|
aria-disabled="false"
|
|
98
97
|
class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1hl5pu8"
|
|
99
98
|
role="button"
|
|
100
|
-
tabindex="0"
|
|
101
99
|
type="button"
|
|
102
100
|
>
|
|
103
101
|
<span
|
|
@@ -250,7 +250,6 @@ exports[`graded-group-set should render all graded groups 1`] = `
|
|
|
250
250
|
aria-disabled="false"
|
|
251
251
|
class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1w5v67"
|
|
252
252
|
role="button"
|
|
253
|
-
tabindex="0"
|
|
254
253
|
type="button"
|
|
255
254
|
>
|
|
256
255
|
<span
|
|
@@ -260,7 +259,7 @@ exports[`graded-group-set should render all graded groups 1`] = `
|
|
|
260
259
|
</span>
|
|
261
260
|
</button>
|
|
262
261
|
<button
|
|
263
|
-
class="
|
|
262
|
+
class="showHintLink_oak3yy"
|
|
264
263
|
tabindex="0"
|
|
265
264
|
>
|
|
266
265
|
Explain
|
|
@@ -487,7 +486,6 @@ exports[`graded-group-set should render all graded groups 1`] = `
|
|
|
487
486
|
aria-disabled="false"
|
|
488
487
|
class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1w5v67"
|
|
489
488
|
role="button"
|
|
490
|
-
tabindex="0"
|
|
491
489
|
type="button"
|
|
492
490
|
>
|
|
493
491
|
<span
|
|
@@ -497,7 +495,7 @@ exports[`graded-group-set should render all graded groups 1`] = `
|
|
|
497
495
|
</span>
|
|
498
496
|
</button>
|
|
499
497
|
<button
|
|
500
|
-
class="
|
|
498
|
+
class="showHintLink_oak3yy"
|
|
501
499
|
tabindex="0"
|
|
502
500
|
>
|
|
503
501
|
Explain
|
|
@@ -724,7 +722,6 @@ exports[`graded-group-set should render all graded groups 1`] = `
|
|
|
724
722
|
aria-disabled="false"
|
|
725
723
|
class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1w5v67"
|
|
726
724
|
role="button"
|
|
727
|
-
tabindex="0"
|
|
728
725
|
type="button"
|
|
729
726
|
>
|
|
730
727
|
<span
|
|
@@ -734,7 +731,7 @@ exports[`graded-group-set should render all graded groups 1`] = `
|
|
|
734
731
|
</span>
|
|
735
732
|
</button>
|
|
736
733
|
<button
|
|
737
|
-
class="
|
|
734
|
+
class="showHintLink_oak3yy"
|
|
738
735
|
tabindex="0"
|
|
739
736
|
>
|
|
740
737
|
Explain
|