@khanacademy/perseus 12.2.0 → 12.4.0
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 +42 -0
- package/dist/article-renderer.d.ts +3 -2
- package/dist/error-boundary.d.ts +1 -0
- package/dist/es/index.css +4 -69
- package/dist/es/index.js +135 -78
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +4 -69
- package/dist/index.js +130 -67
- package/dist/index.js.map +1 -1
- package/dist/renderer.d.ts +4 -1
- package/dist/styles/constants.d.ts +2 -2
- package/dist/widget-container.d.ts +2 -0
- package/dist/widgets/expression.d.ts +5 -4
- package/package.json +8 -8
- package/src/__tests__/renderer-api.test.tsx +18 -23
- package/src/__tests__/widget-container.test.tsx +126 -0
- package/src/article-renderer.tsx +15 -13
- package/src/error-boundary.tsx +4 -0
- package/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap +5 -5
- package/src/renderer.tsx +29 -27
- package/src/server-item-renderer.tsx +1 -0
- package/src/styles/articles.less +3 -1
- package/src/styles/constants.ts +4 -4
- package/src/styles/perseus-renderer.less +1 -11
- package/src/styles/variables.less +2 -2
- package/src/styles/variables.shared.less +2 -2
- package/src/styles/widgets/expression.less +0 -77
- package/src/styles/widgets/passage.less +1 -19
- package/src/widget-container.tsx +33 -10
- package/src/widgets/__stories__/label-image.stories.tsx +30 -0
- package/src/widgets/__testdata__/label-image.testdata.ts +63 -0
- package/src/widgets/__tests__/__snapshots__/graded-group-set.test.ts.snap +50 -19
- package/src/widgets/__tests__/__snapshots__/group.test.tsx.snap +5 -5
- package/src/widgets/__tests__/__snapshots__/radio.test.ts.snap +28 -28
- package/src/widgets/__tests__/expression.test.tsx +12 -9
- package/src/widgets/__tests__/renderQuestion.tsx +30 -13
- package/src/widgets/expression.tsx +19 -25
- package/src/widgets/graded-group-set.tsx +70 -25
- package/src/widgets/transformer.tsx +1 -2
- package/tsconfig-build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# @khanacademy/perseus
|
|
2
2
|
|
|
3
|
+
## 12.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#784](https://github.com/Khan/perseus/pull/784) [`cfff6ad1`](https://github.com/Khan/perseus/commit/cfff6ad16a3923418a3c75816af7c99689b94da4) Thanks [@nedredmond](https://github.com/nedredmond)! - Graded Group Set indicator dots now have a 24x24 clickable area as well as hover/focus states. Stretching issue on mobile resolved as well.
|
|
8
|
+
|
|
9
|
+
* [#783](https://github.com/Khan/perseus/pull/783) [`79403e06`](https://github.com/Khan/perseus/commit/79403e06eedb597d7818d6c858bbba6f51ff3fe1) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Adds 'widgetId' to the 'perseus:widget-rendering-error' analytics event.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`79403e06`](https://github.com/Khan/perseus/commit/79403e06eedb597d7818d6c858bbba6f51ff3fe1), [`ed00ee59`](https://github.com/Khan/perseus/commit/ed00ee59dcdeb20a66709c6b7d3474da55d58e4d)]:
|
|
14
|
+
- @khanacademy/perseus-core@1.3.0
|
|
15
|
+
- @khanacademy/math-input@14.2.2
|
|
16
|
+
- @khanacademy/kas@0.3.5
|
|
17
|
+
- @khanacademy/kmath@0.1.6
|
|
18
|
+
- @khanacademy/perseus-linter@0.3.8
|
|
19
|
+
- @khanacademy/pure-markdown@0.2.10
|
|
20
|
+
- @khanacademy/simple-markdown@0.10.4
|
|
21
|
+
|
|
22
|
+
## 12.3.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- [#780](https://github.com/Khan/perseus/pull/780) [`376eb0e4`](https://github.com/Khan/perseus/commit/376eb0e4aaaa4c7a90fd6107a84bb74d382b077c) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Adds an `onError` callback prop to the ErrorBoundary component. Uses this new callback in the WidgetContainer component to report all widget rendering failures through the analytics API.
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- [#759](https://github.com/Khan/perseus/pull/759) [`c431c4b8`](https://github.com/Khan/perseus/commit/c431c4b8147ae0630df2d2b19b0f5a5b5f04d4bf) Thanks [@handeyeco](https://github.com/handeyeco)! - Remove references to unused font families
|
|
31
|
+
|
|
32
|
+
* [#775](https://github.com/Khan/perseus/pull/775) [`cb529549`](https://github.com/Khan/perseus/commit/cb5295497fe74e3f4cc00eef0f99da9f83f58e4d) Thanks [@nedredmond](https://github.com/nedredmond)! - Added flag to `simpleValidate` call from Renderer to ensure we call analytics on MathInputEvaluated only when the answer is submitted
|
|
33
|
+
|
|
34
|
+
- [#781](https://github.com/Khan/perseus/pull/781) [`9b9dfd4f`](https://github.com/Khan/perseus/commit/9b9dfd4f6779d129040d9afcf3205f1863a64c25) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Fix for broken dilation tool in the Transformer Widget
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [[`c431c4b8`](https://github.com/Khan/perseus/commit/c431c4b8147ae0630df2d2b19b0f5a5b5f04d4bf), [`fb84640d`](https://github.com/Khan/perseus/commit/fb84640de911a8e8817829985fe9956e83a7f7d1), [`376eb0e4`](https://github.com/Khan/perseus/commit/376eb0e4aaaa4c7a90fd6107a84bb74d382b077c), [`33cc24c3`](https://github.com/Khan/perseus/commit/33cc24c33f62cd87de7594ba575d311fd465e2e0)]:
|
|
37
|
+
- @khanacademy/math-input@14.2.1
|
|
38
|
+
- @khanacademy/perseus-core@1.2.0
|
|
39
|
+
- @khanacademy/kas@0.3.4
|
|
40
|
+
- @khanacademy/kmath@0.1.5
|
|
41
|
+
- @khanacademy/perseus-linter@0.3.7
|
|
42
|
+
- @khanacademy/pure-markdown@0.2.9
|
|
43
|
+
- @khanacademy/simple-markdown@0.10.3
|
|
44
|
+
|
|
3
45
|
## 12.2.0
|
|
4
46
|
|
|
5
47
|
### Minor Changes
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* composed of multiple (Renderer) sections concatenated together.
|
|
4
4
|
*/
|
|
5
5
|
import * as React from "react";
|
|
6
|
+
import { DependenciesContext } from "./dependencies";
|
|
6
7
|
import Renderer from "./renderer";
|
|
7
8
|
import type { KeypadProps } from "./mixins/provide-keypad";
|
|
8
9
|
import type { PerseusRenderer } from "./perseus-types";
|
|
@@ -10,7 +11,7 @@ import type { APIOptions, PerseusDependenciesV2 } from "./types";
|
|
|
10
11
|
import type { KeypadAPI } from "@khanacademy/math-input";
|
|
11
12
|
import type { KeypadContextRendererInterface } from "@khanacademy/perseus-core";
|
|
12
13
|
import type { LinterContextProps } from "@khanacademy/perseus-linter";
|
|
13
|
-
type Props = {
|
|
14
|
+
type Props = Partial<React.ContextType<typeof DependenciesContext>> & KeypadProps & {
|
|
14
15
|
apiOptions: APIOptions;
|
|
15
16
|
json: PerseusRenderer | ReadonlyArray<PerseusRenderer>;
|
|
16
17
|
/**
|
|
@@ -21,7 +22,7 @@ type Props = {
|
|
|
21
22
|
legacyPerseusLint?: ReadonlyArray<string>;
|
|
22
23
|
keypadElement?: KeypadAPI | null | undefined;
|
|
23
24
|
dependencies: PerseusDependenciesV2;
|
|
24
|
-
}
|
|
25
|
+
};
|
|
25
26
|
type DefaultProps = {
|
|
26
27
|
apiOptions: Props["apiOptions"];
|
|
27
28
|
useNewStyles: Props["useNewStyles"];
|
package/dist/error-boundary.d.ts
CHANGED
package/dist/es/index.css
CHANGED
|
@@ -1742,11 +1742,11 @@ body.mobile ul.inequalities-one-line-radios > li {
|
|
|
1742
1742
|
.framework-perseus.perseus-mobile .clearfix > .perseus-renderer {
|
|
1743
1743
|
margin-bottom: 32px;
|
|
1744
1744
|
}
|
|
1745
|
-
.framework-perseus.perseus-mobile .perseus-renderer > .paragraph ul:not(.perseus-widget-radio) {
|
|
1745
|
+
.framework-perseus.perseus-mobile .perseus-renderer > .paragraph ul:not(.perseus-widget-radio, .indicatorContainer) {
|
|
1746
1746
|
margin: 0 0 0 1em;
|
|
1747
1747
|
padding: 0;
|
|
1748
1748
|
}
|
|
1749
|
-
.framework-perseus.perseus-mobile .perseus-renderer > .paragraph ul:not(.perseus-widget-radio) > li {
|
|
1749
|
+
.framework-perseus.perseus-mobile .perseus-renderer > .paragraph ul:not(.perseus-widget-radio, .indicatorContainer) > li {
|
|
1750
1750
|
padding-left: 10px;
|
|
1751
1751
|
margin-bottom: 24px;
|
|
1752
1752
|
}
|
|
@@ -2394,7 +2394,7 @@ img.zoom-img {
|
|
|
2394
2394
|
.framework-perseus .perseus-renderer > .paragraph > ol {
|
|
2395
2395
|
margin: -11px 0px 22px 0px;
|
|
2396
2396
|
}
|
|
2397
|
-
.framework-perseus .paragraph ul:not(.perseus-widget-radio) {
|
|
2397
|
+
.framework-perseus .paragraph ul:not(.perseus-widget-radio, .indicatorContainer) {
|
|
2398
2398
|
padding-left: 35px;
|
|
2399
2399
|
list-style-type: disc;
|
|
2400
2400
|
}
|
|
@@ -2684,71 +2684,6 @@ body.mobile .categorizer-container td.category input[type="radio"] + span:active
|
|
|
2684
2684
|
#answer_area .perseus-widget-expression .error-tooltip .tooltipContainer > div:first-child {
|
|
2685
2685
|
visibility: hidden !important;
|
|
2686
2686
|
}
|
|
2687
|
-
.perseus-widget-expression-old,
|
|
2688
|
-
.perseus-widget-expression-old > .output,
|
|
2689
|
-
.perseus-widget-expression-old > .output > .tex,
|
|
2690
|
-
.perseus-widget-expression-old > .output > .placeholder {
|
|
2691
|
-
display: block;
|
|
2692
|
-
}
|
|
2693
|
-
.perseus-widget-expression-old input,
|
|
2694
|
-
#answer_area .perseus-widget-expression-old input {
|
|
2695
|
-
direction: ltr;
|
|
2696
|
-
border: 1px solid #a4a4a4;
|
|
2697
|
-
border-radius: 5px;
|
|
2698
|
-
box-sizing: border-box;
|
|
2699
|
-
font-size: 14px;
|
|
2700
|
-
margin-bottom: 5px;
|
|
2701
|
-
max-width: 240px;
|
|
2702
|
-
padding: 6px;
|
|
2703
|
-
width: 100%;
|
|
2704
|
-
}
|
|
2705
|
-
.perseus-widget-expression-old > .output {
|
|
2706
|
-
background: #f2f2f2;
|
|
2707
|
-
border-radius: 5px;
|
|
2708
|
-
padding: 10px;
|
|
2709
|
-
margin: 10px 0;
|
|
2710
|
-
}
|
|
2711
|
-
#answer_area .perseus-widget-expression-old > .output {
|
|
2712
|
-
background: #f7f7f7;
|
|
2713
|
-
}
|
|
2714
|
-
.perseus-widget-expression-old > .output > .tex {
|
|
2715
|
-
overflow-x: auto;
|
|
2716
|
-
padding: 5px;
|
|
2717
|
-
}
|
|
2718
|
-
.perseus-widget-expression-old > .output > .placeholder {
|
|
2719
|
-
position: relative;
|
|
2720
|
-
height: 40px;
|
|
2721
|
-
overflow-y: hidden;
|
|
2722
|
-
}
|
|
2723
|
-
.perseus-widget-expression-old > .output > .placeholder > .error {
|
|
2724
|
-
border-radius: 10px;
|
|
2725
|
-
background: #f7f7f7;
|
|
2726
|
-
border: 1px solid #ddd;
|
|
2727
|
-
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
|
|
2728
|
-
color: #000;
|
|
2729
|
-
display: none;
|
|
2730
|
-
font-weight: normal;
|
|
2731
|
-
min-height: 22px;
|
|
2732
|
-
width: 168px;
|
|
2733
|
-
position: absolute;
|
|
2734
|
-
top: 0px;
|
|
2735
|
-
left: 40px;
|
|
2736
|
-
margin: auto;
|
|
2737
|
-
}
|
|
2738
|
-
.perseus-widget-expression-old > .output > .placeholder > .error > .buddy {
|
|
2739
|
-
background-image: url(/images/perseus/error-buddy.png);
|
|
2740
|
-
background-size: 100%;
|
|
2741
|
-
height: 36px;
|
|
2742
|
-
width: 40px;
|
|
2743
|
-
position: absolute;
|
|
2744
|
-
top: -3px;
|
|
2745
|
-
left: -42px;
|
|
2746
|
-
}
|
|
2747
|
-
.perseus-widget-expression-old > .output > .placeholder > .error > .message {
|
|
2748
|
-
font: 12px inherit;
|
|
2749
|
-
line-height: 1.4em;
|
|
2750
|
-
margin: 0px 4px;
|
|
2751
|
-
}
|
|
2752
2687
|
.perseus-widget-grapher {
|
|
2753
2688
|
box-sizing: content-box;
|
|
2754
2689
|
padding: 25px 25px 0 0;
|
|
@@ -3121,7 +3056,7 @@ body.mobile .perseus-matrix .math-output {
|
|
|
3121
3056
|
}
|
|
3122
3057
|
.framework-perseus.perseus-article .perseus-renderer .perseus-widget-passage-container .perseus-widget-passage div.paragraph,
|
|
3123
3058
|
.perseus-widget-passage-container .perseus-widget-passage div.paragraph {
|
|
3124
|
-
font-family:
|
|
3059
|
+
font-family: KaTeX_Main, Times, "Times New Roman", serif;
|
|
3125
3060
|
}
|
|
3126
3061
|
.framework-perseus.perseus-article .perseus-renderer .perseus-widget-passage-container .perseus-widget-passage .passage-title div.paragraph,
|
|
3127
3062
|
.perseus-widget-passage-container .perseus-widget-passage .passage-title div.paragraph {
|
package/dist/es/index.js
CHANGED
|
@@ -49,6 +49,21 @@ function _extends() {
|
|
|
49
49
|
return _extends.apply(this, arguments);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
53
|
+
if (source == null) return {};
|
|
54
|
+
var target = {};
|
|
55
|
+
var sourceKeys = Object.keys(source);
|
|
56
|
+
var key, i;
|
|
57
|
+
|
|
58
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
59
|
+
key = sourceKeys[i];
|
|
60
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
61
|
+
target[key] = source[key];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return target;
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
const customKeyTranslator = _extends({}, keyTranslator, {
|
|
53
68
|
// If there's something in the input that can become part of a
|
|
54
69
|
// fraction, typing "/" puts it in the numerator. If not, typing
|
|
@@ -1870,6 +1885,7 @@ const KhanAnswerTypes = {
|
|
|
1870
1885
|
}
|
|
1871
1886
|
};
|
|
1872
1887
|
|
|
1888
|
+
const _excluded$4 = ["scoring"];
|
|
1873
1889
|
const ERROR_TITLE = i18n._("Oops!");
|
|
1874
1890
|
const ERROR_MESSAGE = i18n._("Sorry, I don't understand that!");
|
|
1875
1891
|
const insertBraces = value => {
|
|
@@ -1947,11 +1963,26 @@ class Expression extends React.Component {
|
|
|
1947
1963
|
});
|
|
1948
1964
|
}
|
|
1949
1965
|
};
|
|
1950
|
-
this.simpleValidate = (
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1966
|
+
this.simpleValidate = (_ref, onInputError) => {
|
|
1967
|
+
let {
|
|
1968
|
+
scoring
|
|
1969
|
+
} = _ref,
|
|
1970
|
+
rubric = _objectWithoutPropertiesLoose(_ref, _excluded$4);
|
|
1971
|
+
const score = Expression.validate(this.getUserInput(), rubric, onInputError || function () {});
|
|
1972
|
+
|
|
1973
|
+
// "scoring" is a flag that indicates when we are checking answers.
|
|
1974
|
+
// otherwise, we may just be checking validity after changes.
|
|
1975
|
+
if (scoring && score.type !== "invalid") {
|
|
1976
|
+
var _this$props$analytics;
|
|
1977
|
+
(_this$props$analytics = this.props.analytics) == null ? void 0 : _this$props$analytics.onAnalyticsEvent({
|
|
1978
|
+
type: "perseus:expression-evaluated",
|
|
1979
|
+
payload: {
|
|
1980
|
+
result: score.earned === score.total ? "correct" : "incorrect",
|
|
1981
|
+
virtualKeypadVersion: deriveKeypadVersion(this.props.apiOptions)
|
|
1982
|
+
}
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
return score;
|
|
1955
1986
|
};
|
|
1956
1987
|
this.getUserInput = () => {
|
|
1957
1988
|
return Expression.getUserInputFromProps(this.props);
|
|
@@ -1973,8 +2004,8 @@ class Expression extends React.Component {
|
|
|
1973
2004
|
this.props.trackInteraction();
|
|
1974
2005
|
};
|
|
1975
2006
|
this._handleFocus = () => {
|
|
1976
|
-
var _this$props$
|
|
1977
|
-
(_this$props$
|
|
2007
|
+
var _this$props$analytics2;
|
|
2008
|
+
(_this$props$analytics2 = this.props.analytics) == null ? void 0 : _this$props$analytics2.onAnalyticsEvent({
|
|
1978
2009
|
type: "perseus:expression-focused",
|
|
1979
2010
|
payload: null
|
|
1980
2011
|
});
|
|
@@ -2182,16 +2213,6 @@ class Expression extends React.Component {
|
|
|
2182
2213
|
// @ts-expect-error - TS2339 - Property 'insert' does not exist on type 'ReactInstance'.
|
|
2183
2214
|
this.refs.input.insert(keyPressed);
|
|
2184
2215
|
}
|
|
2185
|
-
sendExpressionEvaluatedEvent(result) {
|
|
2186
|
-
var _this$props$analytics2;
|
|
2187
|
-
(_this$props$analytics2 = this.props.analytics) == null ? void 0 : _this$props$analytics2.onAnalyticsEvent({
|
|
2188
|
-
type: "perseus:expression-evaluated",
|
|
2189
|
-
payload: {
|
|
2190
|
-
result,
|
|
2191
|
-
virtualKeypadVersion: deriveKeypadVersion(this.props.apiOptions)
|
|
2192
|
-
}
|
|
2193
|
-
});
|
|
2194
|
-
}
|
|
2195
2216
|
render() {
|
|
2196
2217
|
var _this$props$keypadCon, _this$props$analytics3;
|
|
2197
2218
|
if (this.props.apiOptions.customKeypad) {
|
|
@@ -3680,10 +3701,10 @@ Zoom.prototype.dispose = function () {
|
|
|
3680
3701
|
};
|
|
3681
3702
|
const ZoomService = new ZoomServiceClass();
|
|
3682
3703
|
|
|
3683
|
-
// @baseFontFamily: "
|
|
3684
|
-
const baseFontFamily$1 = "'
|
|
3685
|
-
// @boldFontFamily: "
|
|
3686
|
-
const boldFontFamily = "'
|
|
3704
|
+
// @baseFontFamily: "Lato", sans-serif;
|
|
3705
|
+
const baseFontFamily$1 = "'Lato', sans-serif";
|
|
3706
|
+
// @boldFontFamily: "Lato-Bold", "Lato", sans-serif;
|
|
3707
|
+
const boldFontFamily = "'Lato-Bold', 'Lato', sans-serif";
|
|
3687
3708
|
// @green: #76a005;
|
|
3688
3709
|
const green$1 = "#76A005";
|
|
3689
3710
|
// @kaGreen: #71b307;
|
|
@@ -17328,9 +17349,11 @@ class ErrorBoundary extends React.Component {
|
|
|
17328
17349
|
};
|
|
17329
17350
|
}
|
|
17330
17351
|
componentDidCatch(error, info) {
|
|
17352
|
+
var _this$props$onError, _this$props;
|
|
17331
17353
|
this.setState({
|
|
17332
17354
|
error: error.toString()
|
|
17333
17355
|
});
|
|
17356
|
+
(_this$props$onError = (_this$props = this.props).onError) == null ? void 0 : _this$props$onError.call(_this$props, error, info);
|
|
17334
17357
|
Log.error("Perseus error boundary caught error", Errors.Internal, {
|
|
17335
17358
|
cause: error,
|
|
17336
17359
|
loggedMetadata: _extends({
|
|
@@ -18675,6 +18698,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
18675
18698
|
class WidgetContainer extends React.Component {
|
|
18676
18699
|
constructor(...args) {
|
|
18677
18700
|
super(...args);
|
|
18701
|
+
this.widgetRef = /*#__PURE__*/React.createRef();
|
|
18678
18702
|
this.state = {
|
|
18679
18703
|
// TODO(benkomalo): before we're mounted, we don't know how big
|
|
18680
18704
|
// we're going to be, so just default to MEDIUM for now. :/ In the
|
|
@@ -18684,8 +18708,7 @@ class WidgetContainer extends React.Component {
|
|
|
18684
18708
|
widgetProps: this.props.initialProps
|
|
18685
18709
|
};
|
|
18686
18710
|
this.getWidget = () => {
|
|
18687
|
-
|
|
18688
|
-
return this.refs.widget;
|
|
18711
|
+
return this.widgetRef.current;
|
|
18689
18712
|
};
|
|
18690
18713
|
this.replaceWidgetProps = newWidgetProps => {
|
|
18691
18714
|
this.setState({
|
|
@@ -18779,15 +18802,29 @@ class WidgetContainer extends React.Component {
|
|
|
18779
18802
|
return /*#__PURE__*/React.createElement("div", {
|
|
18780
18803
|
className: className,
|
|
18781
18804
|
style: isStatic ? staticContainerStyles : {}
|
|
18805
|
+
}, /*#__PURE__*/React.createElement(DependenciesContext.Consumer, null, ({
|
|
18806
|
+
analytics
|
|
18807
|
+
}) => /*#__PURE__*/React.createElement(ErrorBoundary, {
|
|
18808
|
+
metadata: {
|
|
18809
|
+
widget_type: type,
|
|
18810
|
+
widget_id: this.props.id
|
|
18811
|
+
},
|
|
18812
|
+
onError: () => {
|
|
18813
|
+
analytics.onAnalyticsEvent({
|
|
18814
|
+
type: "perseus:widget-rendering-error",
|
|
18815
|
+
payload: {
|
|
18816
|
+
widgetType: type,
|
|
18817
|
+
widgetId: this.props.id
|
|
18818
|
+
}
|
|
18819
|
+
});
|
|
18820
|
+
}
|
|
18782
18821
|
}, /*#__PURE__*/React.createElement(WidgetType, _extends({}, this.state.widgetProps, {
|
|
18783
18822
|
linterContext: linterContext,
|
|
18784
|
-
containerSizeClass: this.state.sizeClass
|
|
18785
|
-
|
|
18786
|
-
,
|
|
18787
|
-
ref: "widget"
|
|
18823
|
+
containerSizeClass: this.state.sizeClass,
|
|
18824
|
+
ref: this.widgetRef
|
|
18788
18825
|
})), isStatic && /*#__PURE__*/React.createElement("div", {
|
|
18789
18826
|
style: staticOverlayStyles
|
|
18790
|
-
}));
|
|
18827
|
+
}))));
|
|
18791
18828
|
}
|
|
18792
18829
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
18793
18830
|
if (this.props.type !== nextProps.type) {
|
|
@@ -18810,6 +18847,7 @@ const rContainsNonWhitespace = /\S/;
|
|
|
18810
18847
|
const rImageURL = /(web\+graphie|https):\/\/[^\s]*/;
|
|
18811
18848
|
const noopOnRender = () => {};
|
|
18812
18849
|
const SHOULD_CLEAR_WIDGETS_PROP_LIST = ["content", "problemNum", "widgets"];
|
|
18850
|
+
const makeContainerId = id => "container:" + id;
|
|
18813
18851
|
|
|
18814
18852
|
// Check if one focus path / id path is a prefix of another
|
|
18815
18853
|
// The focus path null will never be a prefix of any non-null
|
|
@@ -18854,6 +18892,7 @@ class Renderer extends React.Component {
|
|
|
18854
18892
|
this._isMounted = void 0;
|
|
18855
18893
|
this._isTwoColumn = void 0;
|
|
18856
18894
|
this._translationLinter = void 0;
|
|
18895
|
+
this._widgetContainers = new Map();
|
|
18857
18896
|
this.lastRenderedMarkdown = void 0;
|
|
18858
18897
|
this.reuseMarkdown = void 0;
|
|
18859
18898
|
this.translationIndex = void 0;
|
|
@@ -18924,19 +18963,22 @@ class Renderer extends React.Component {
|
|
|
18924
18963
|
// By this point we should have no duplicates, which are
|
|
18925
18964
|
// filtered out in this.render(), so we shouldn't have to
|
|
18926
18965
|
// worry about using this widget key and ref:
|
|
18927
|
-
return /*#__PURE__*/React.createElement(
|
|
18928
|
-
key:
|
|
18929
|
-
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
|
|
18934
|
-
|
|
18966
|
+
return /*#__PURE__*/React.createElement(WidgetContainer, {
|
|
18967
|
+
key: makeContainerId(id),
|
|
18968
|
+
id: id,
|
|
18969
|
+
ref: node => {
|
|
18970
|
+
const containerId = makeContainerId(id);
|
|
18971
|
+
if (node != null) {
|
|
18972
|
+
this._widgetContainers.set(containerId, node);
|
|
18973
|
+
} else {
|
|
18974
|
+
this._widgetContainers.delete(containerId);
|
|
18975
|
+
}
|
|
18976
|
+
},
|
|
18935
18977
|
type: type,
|
|
18936
18978
|
initialProps: this.getWidgetProps(id),
|
|
18937
18979
|
shouldHighlight: shouldHighlight,
|
|
18938
18980
|
linterContext: PerseusLinter.pushContextStack(this.props.linterContext, "widget")
|
|
18939
|
-
})
|
|
18981
|
+
});
|
|
18940
18982
|
}
|
|
18941
18983
|
return null;
|
|
18942
18984
|
};
|
|
@@ -18963,7 +19005,6 @@ class Renderer extends React.Component {
|
|
|
18963
19005
|
getTracking(widgetInfo && widgetInfo.type));
|
|
18964
19006
|
}
|
|
18965
19007
|
return _extends({}, widgetProps, {
|
|
18966
|
-
ref: id,
|
|
18967
19008
|
widgetId: id,
|
|
18968
19009
|
alignment: widgetInfo && widgetInfo.alignment,
|
|
18969
19010
|
// When determining if a widget is static, we verify that the widget is not an
|
|
@@ -19095,12 +19136,10 @@ class Renderer extends React.Component {
|
|
|
19095
19136
|
return [...this.findInternalWidgets(filterCriterion), ...this.props.findExternalWidgets(filterCriterion)];
|
|
19096
19137
|
};
|
|
19097
19138
|
this.getWidgetInstance = id => {
|
|
19098
|
-
|
|
19099
|
-
const ref = this.refs["container:" + id];
|
|
19139
|
+
const ref = this._widgetContainers.get(makeContainerId(id));
|
|
19100
19140
|
if (!ref) {
|
|
19101
19141
|
return null;
|
|
19102
19142
|
}
|
|
19103
|
-
// @ts-expect-error - TS2339 - Property 'getWidget' does not exist on type 'ReactInstance'.
|
|
19104
19143
|
return ref.getWidget();
|
|
19105
19144
|
};
|
|
19106
19145
|
this._onWidgetFocus = (id, focusPath = []) => {
|
|
@@ -19788,7 +19827,9 @@ class Renderer extends React.Component {
|
|
|
19788
19827
|
const widget = this.getWidgetInstance(id);
|
|
19789
19828
|
// widget can be undefined if it hasn't yet been rendered
|
|
19790
19829
|
if (widget && widget.simpleValidate) {
|
|
19791
|
-
widgetScores[id] = widget.simpleValidate(props == null ? void 0 : props.options,
|
|
19830
|
+
widgetScores[id] = widget.simpleValidate(_extends({}, props == null ? void 0 : props.options, {
|
|
19831
|
+
scoring: true
|
|
19832
|
+
}), onInputError);
|
|
19792
19833
|
}
|
|
19793
19834
|
});
|
|
19794
19835
|
return widgetScores;
|
|
@@ -19938,9 +19979,7 @@ class Renderer extends React.Component {
|
|
|
19938
19979
|
// they are re-rendered, so even if they've been
|
|
19939
19980
|
// re-rendered we need to call these methods on them.
|
|
19940
19981
|
_.each(this.widgetIds, id => {
|
|
19941
|
-
|
|
19942
|
-
const container = this.refs["container:" + id];
|
|
19943
|
-
// @ts-expect-error - TS2339 - Property 'replaceWidgetProps' does not exist on type 'ReactInstance'.
|
|
19982
|
+
const container = this._widgetContainers.get(makeContainerId(id));
|
|
19944
19983
|
container && container.replaceWidgetProps(this.getWidgetProps(id));
|
|
19945
19984
|
});
|
|
19946
19985
|
if (this.props.serializedState && !_.isEqual(this.props.serializedState, this.getSerializedState())) {
|
|
@@ -20858,21 +20897,6 @@ InputWithExamples.defaultProps = {
|
|
|
20858
20897
|
className: ""
|
|
20859
20898
|
};
|
|
20860
20899
|
|
|
20861
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
20862
|
-
if (source == null) return {};
|
|
20863
|
-
var target = {};
|
|
20864
|
-
var sourceKeys = Object.keys(source);
|
|
20865
|
-
var key, i;
|
|
20866
|
-
|
|
20867
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
20868
|
-
key = sourceKeys[i];
|
|
20869
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
20870
|
-
target[key] = source[key];
|
|
20871
|
-
}
|
|
20872
|
-
|
|
20873
|
-
return target;
|
|
20874
|
-
}
|
|
20875
|
-
|
|
20876
20900
|
const _excluded$3 = ["keypadElement", "onFocus", "value"];
|
|
20877
20901
|
class SimpleKeypadInput extends React.Component {
|
|
20878
20902
|
constructor(...args) {
|
|
@@ -24884,22 +24908,33 @@ class Indicators extends React.Component {
|
|
|
24884
24908
|
}
|
|
24885
24909
|
render() {
|
|
24886
24910
|
return /*#__PURE__*/React.createElement("ul", {
|
|
24887
|
-
|
|
24911
|
+
// reduntantly add class name for use in .less files--
|
|
24912
|
+
// the styles object key gets hashed
|
|
24913
|
+
className: classNames(css(styles$j.indicatorContainer), "indicatorContainer")
|
|
24888
24914
|
}, this.props.gradedGroups.map(({
|
|
24889
24915
|
title
|
|
24890
24916
|
}, i) => /*#__PURE__*/React.createElement("li", {
|
|
24917
|
+
className: css(styles$j.indicator),
|
|
24918
|
+
key: title
|
|
24919
|
+
}, /*#__PURE__*/React.createElement(Clickable, {
|
|
24891
24920
|
role: "button",
|
|
24892
24921
|
"aria-label": i18n._("Skip to %(title)s", {
|
|
24893
24922
|
title
|
|
24894
24923
|
}),
|
|
24895
|
-
|
|
24896
|
-
className: css(styles$j.indicator, i === this.props.currentGroup && styles$j.selectedIndicator),
|
|
24897
|
-
tabIndex: 0,
|
|
24924
|
+
style: styles$j.indicatorButton,
|
|
24898
24925
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
24899
24926
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
24900
|
-
},
|
|
24927
|
+
}, ({
|
|
24928
|
+
hovered,
|
|
24929
|
+
focused,
|
|
24930
|
+
pressed
|
|
24931
|
+
}) => /*#__PURE__*/React.createElement(View, {
|
|
24932
|
+
style: [styles$j.indicatorDot, (hovered || focused || pressed) && styles$j.indicatorDotFocused]
|
|
24933
|
+
}, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
|
|
24934
|
+
style: styles$j.indicatorDotActive
|
|
24935
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
24901
24936
|
className: css(a11y.srOnly)
|
|
24902
|
-
}, i18n._("Current")))));
|
|
24937
|
+
}, i18n._("Current"))))))));
|
|
24903
24938
|
}
|
|
24904
24939
|
}
|
|
24905
24940
|
// TODO(jared): find a better name for this :) and for GradedGroup; the names
|
|
@@ -25047,19 +25082,42 @@ const styles$j = StyleSheet.create({
|
|
|
25047
25082
|
display: "flex",
|
|
25048
25083
|
flexDirection: "row",
|
|
25049
25084
|
listStyle: "none",
|
|
25050
|
-
margin: "unset"
|
|
25085
|
+
margin: "unset",
|
|
25086
|
+
paddingInlineStart: "unset",
|
|
25087
|
+
flexWrap: "wrap"
|
|
25051
25088
|
},
|
|
25052
25089
|
indicator: {
|
|
25090
|
+
width: 24,
|
|
25091
|
+
height: 24
|
|
25092
|
+
},
|
|
25093
|
+
indicatorButton: {
|
|
25094
|
+
width: "100%",
|
|
25095
|
+
height: "100%",
|
|
25096
|
+
display: "flex",
|
|
25097
|
+
flexWrap: "wrap",
|
|
25098
|
+
placeContent: "center",
|
|
25099
|
+
cursor: "pointer",
|
|
25100
|
+
":focus": {
|
|
25101
|
+
outline: "none"
|
|
25102
|
+
}
|
|
25103
|
+
},
|
|
25104
|
+
indicatorDot: {
|
|
25105
|
+
boxSizing: "content-box",
|
|
25053
25106
|
width: 10,
|
|
25054
25107
|
height: 10,
|
|
25055
25108
|
borderRadius: "100%",
|
|
25056
|
-
|
|
25109
|
+
borderWidth: 2,
|
|
25057
25110
|
borderColor: Color.blue,
|
|
25058
|
-
|
|
25059
|
-
cursor: "pointer"
|
|
25111
|
+
borderStyle: "solid"
|
|
25060
25112
|
},
|
|
25061
|
-
|
|
25062
|
-
|
|
25113
|
+
indicatorDotFocused: {
|
|
25114
|
+
borderWidth: 5,
|
|
25115
|
+
borderStyle: "double"
|
|
25116
|
+
},
|
|
25117
|
+
indicatorDotActive: {
|
|
25118
|
+
backgroundColor: Color.blue,
|
|
25119
|
+
width: "100%",
|
|
25120
|
+
height: "100%"
|
|
25063
25121
|
},
|
|
25064
25122
|
container: {
|
|
25065
25123
|
borderTop: `1px solid ${gray76}`,
|
|
@@ -42117,8 +42175,7 @@ class Transformer extends React.Component {
|
|
|
42117
42175
|
// @ts-expect-error - TS2345 - Argument of type '{ type: "dilation"; center: any; scale: number; }' is not assignable to parameter of type 'PerseusTransformerTransformation'.
|
|
42118
42176
|
self.doTransform({
|
|
42119
42177
|
type: "dilation",
|
|
42120
|
-
|
|
42121
|
-
// will still be defined here. center: self.dilationCircle.centerPoint.coord,
|
|
42178
|
+
center: self.dilationCircle.centerPoint.coord,
|
|
42122
42179
|
scale: newRadius / oldRadius
|
|
42123
42180
|
});
|
|
42124
42181
|
},
|
|
@@ -43748,7 +43805,7 @@ const init = function init(options) {
|
|
|
43748
43805
|
|
|
43749
43806
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43750
43807
|
const libName = "@khanacademy/perseus";
|
|
43751
|
-
const libVersion = "12.
|
|
43808
|
+
const libVersion = "12.4.0";
|
|
43752
43809
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43753
43810
|
|
|
43754
43811
|
const apiVersion = {
|
|
@@ -43890,7 +43947,7 @@ class ArticleRenderer extends React.Component {
|
|
|
43890
43947
|
}),
|
|
43891
43948
|
linterContext: PerseusLinter.pushContextStack(this.props.linterContext, "article"),
|
|
43892
43949
|
legacyPerseusLint: this.props.legacyPerseusLint
|
|
43893
|
-
})));
|
|
43950
|
+
}, this.props.dependencies)));
|
|
43894
43951
|
});
|
|
43895
43952
|
return /*#__PURE__*/React.createElement("div", {
|
|
43896
43953
|
className: classes
|
|
@@ -44975,7 +45032,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
44975
45032
|
};
|
|
44976
45033
|
const questionRenderer = /*#__PURE__*/React.createElement(context$1.Provider, {
|
|
44977
45034
|
value: contextValue
|
|
44978
|
-
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
45035
|
+
}, /*#__PURE__*/React.createElement(Renderer, _extends({
|
|
44979
45036
|
keypadElement: this.props.keypadElement,
|
|
44980
45037
|
problemNum: this.props.problemNum,
|
|
44981
45038
|
onInteractWithWidget: this.handleInteractWithWidget,
|
|
@@ -44991,7 +45048,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
44991
45048
|
content: this.props.item.question.content,
|
|
44992
45049
|
widgets: this.props.item.question.widgets,
|
|
44993
45050
|
images: this.props.item.question.images
|
|
44994
|
-
}));
|
|
45051
|
+
}, this.props.dependencies)));
|
|
44995
45052
|
const hintsRenderer = /*#__PURE__*/React.createElement(HintsRenderer, {
|
|
44996
45053
|
hints: this.props.item.hints,
|
|
44997
45054
|
hintsVisible: this.props.hintsVisible,
|