@khanacademy/perseus 12.1.0 → 12.3.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 +31 -0
- package/dist/article-renderer.d.ts +5 -2
- package/dist/error-boundary.d.ts +1 -0
- package/dist/es/index.css +4 -66
- package/dist/es/index.js +112 -87
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +4 -66
- package/dist/index.js +103 -75
- 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/__stories__/article-renderer.stories.tsx +28 -2
- package/src/__testdata__/article-renderer.testdata.ts +85 -0
- package/src/__tests__/article-renderer.test.tsx +131 -0
- package/src/__tests__/renderer-api.test.tsx +18 -23
- package/src/article-renderer.tsx +73 -58
- package/src/error-boundary.tsx +3 -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/constants.ts +4 -4
- package/src/styles/perseus-renderer.less +1 -10
- 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 +32 -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__/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/transformer.tsx +1 -2
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/index.css
CHANGED
|
@@ -2613,6 +2613,7 @@ img.zoom-img {
|
|
|
2613
2613
|
}
|
|
2614
2614
|
/* Widget CSS */
|
|
2615
2615
|
.perseus-graph-padding {
|
|
2616
|
+
box-sizing: content-box;
|
|
2616
2617
|
padding: 25px 25px 0 0;
|
|
2617
2618
|
}
|
|
2618
2619
|
.categorizer-container {
|
|
@@ -2683,72 +2684,8 @@ body.mobile .categorizer-container td.category input[type="radio"] + span:active
|
|
|
2683
2684
|
#answer_area .perseus-widget-expression .error-tooltip .tooltipContainer > div:first-child {
|
|
2684
2685
|
visibility: hidden !important;
|
|
2685
2686
|
}
|
|
2686
|
-
.perseus-widget-expression-old,
|
|
2687
|
-
.perseus-widget-expression-old > .output,
|
|
2688
|
-
.perseus-widget-expression-old > .output > .tex,
|
|
2689
|
-
.perseus-widget-expression-old > .output > .placeholder {
|
|
2690
|
-
display: block;
|
|
2691
|
-
}
|
|
2692
|
-
.perseus-widget-expression-old input,
|
|
2693
|
-
#answer_area .perseus-widget-expression-old input {
|
|
2694
|
-
direction: ltr;
|
|
2695
|
-
border: 1px solid #a4a4a4;
|
|
2696
|
-
border-radius: 5px;
|
|
2697
|
-
box-sizing: border-box;
|
|
2698
|
-
font-size: 14px;
|
|
2699
|
-
margin-bottom: 5px;
|
|
2700
|
-
max-width: 240px;
|
|
2701
|
-
padding: 6px;
|
|
2702
|
-
width: 100%;
|
|
2703
|
-
}
|
|
2704
|
-
.perseus-widget-expression-old > .output {
|
|
2705
|
-
background: #f2f2f2;
|
|
2706
|
-
border-radius: 5px;
|
|
2707
|
-
padding: 10px;
|
|
2708
|
-
margin: 10px 0;
|
|
2709
|
-
}
|
|
2710
|
-
#answer_area .perseus-widget-expression-old > .output {
|
|
2711
|
-
background: #f7f7f7;
|
|
2712
|
-
}
|
|
2713
|
-
.perseus-widget-expression-old > .output > .tex {
|
|
2714
|
-
overflow-x: auto;
|
|
2715
|
-
padding: 5px;
|
|
2716
|
-
}
|
|
2717
|
-
.perseus-widget-expression-old > .output > .placeholder {
|
|
2718
|
-
position: relative;
|
|
2719
|
-
height: 40px;
|
|
2720
|
-
overflow-y: hidden;
|
|
2721
|
-
}
|
|
2722
|
-
.perseus-widget-expression-old > .output > .placeholder > .error {
|
|
2723
|
-
border-radius: 10px;
|
|
2724
|
-
background: #f7f7f7;
|
|
2725
|
-
border: 1px solid #ddd;
|
|
2726
|
-
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
|
|
2727
|
-
color: #000;
|
|
2728
|
-
display: none;
|
|
2729
|
-
font-weight: normal;
|
|
2730
|
-
min-height: 22px;
|
|
2731
|
-
width: 168px;
|
|
2732
|
-
position: absolute;
|
|
2733
|
-
top: 0px;
|
|
2734
|
-
left: 40px;
|
|
2735
|
-
margin: auto;
|
|
2736
|
-
}
|
|
2737
|
-
.perseus-widget-expression-old > .output > .placeholder > .error > .buddy {
|
|
2738
|
-
background-image: url(/images/perseus/error-buddy.png);
|
|
2739
|
-
background-size: 100%;
|
|
2740
|
-
height: 36px;
|
|
2741
|
-
width: 40px;
|
|
2742
|
-
position: absolute;
|
|
2743
|
-
top: -3px;
|
|
2744
|
-
left: -42px;
|
|
2745
|
-
}
|
|
2746
|
-
.perseus-widget-expression-old > .output > .placeholder > .error > .message {
|
|
2747
|
-
font: 12px inherit;
|
|
2748
|
-
line-height: 1.4em;
|
|
2749
|
-
margin: 0px 4px;
|
|
2750
|
-
}
|
|
2751
2687
|
.perseus-widget-grapher {
|
|
2688
|
+
box-sizing: content-box;
|
|
2752
2689
|
padding: 25px 25px 0 0;
|
|
2753
2690
|
}
|
|
2754
2691
|
.perseus-widget-grapher > .graphie-container {
|
|
@@ -2836,6 +2773,7 @@ body.mobile .categorizer-container td.category input[type="radio"] + span:active
|
|
|
2836
2773
|
margin-top: 5px;
|
|
2837
2774
|
}
|
|
2838
2775
|
.perseus-widget-interactive-graph {
|
|
2776
|
+
box-sizing: content-box;
|
|
2839
2777
|
padding: 25px 25px 0 0;
|
|
2840
2778
|
}
|
|
2841
2779
|
.perseus-widget-interactive-graph > .graphie-container {
|
|
@@ -3118,7 +3056,7 @@ body.mobile .perseus-matrix .math-output {
|
|
|
3118
3056
|
}
|
|
3119
3057
|
.framework-perseus.perseus-article .perseus-renderer .perseus-widget-passage-container .perseus-widget-passage div.paragraph,
|
|
3120
3058
|
.perseus-widget-passage-container .perseus-widget-passage div.paragraph {
|
|
3121
|
-
font-family:
|
|
3059
|
+
font-family: KaTeX_Main, Times, "Times New Roman", serif;
|
|
3122
3060
|
}
|
|
3123
3061
|
.framework-perseus.perseus-article .perseus-renderer .perseus-widget-passage-container .perseus-widget-passage .passage-title div.paragraph,
|
|
3124
3062
|
.perseus-widget-passage-container .perseus-widget-passage .passage-title div.paragraph {
|
package/dist/index.js
CHANGED
|
@@ -2007,11 +2007,26 @@ class Expression extends React__namespace.Component {
|
|
|
2007
2007
|
});
|
|
2008
2008
|
}
|
|
2009
2009
|
});
|
|
2010
|
-
_defineProperty(this, "simpleValidate", (
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2010
|
+
_defineProperty(this, "simpleValidate", (_ref, onInputError) => {
|
|
2011
|
+
let {
|
|
2012
|
+
scoring,
|
|
2013
|
+
...rubric
|
|
2014
|
+
} = _ref;
|
|
2015
|
+
const score = Expression.validate(this.getUserInput(), rubric, onInputError || function () {});
|
|
2016
|
+
|
|
2017
|
+
// "scoring" is a flag that indicates when we are checking answers.
|
|
2018
|
+
// otherwise, we may just be checking validity after changes.
|
|
2019
|
+
if (scoring && score.type !== "invalid") {
|
|
2020
|
+
var _this$props$analytics;
|
|
2021
|
+
(_this$props$analytics = this.props.analytics) === null || _this$props$analytics === void 0 ? void 0 : _this$props$analytics.onAnalyticsEvent({
|
|
2022
|
+
type: "perseus:expression-evaluated",
|
|
2023
|
+
payload: {
|
|
2024
|
+
result: score.earned === score.total ? "correct" : "incorrect",
|
|
2025
|
+
virtualKeypadVersion: deriveKeypadVersion(this.props.apiOptions)
|
|
2026
|
+
}
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
2029
|
+
return score;
|
|
2015
2030
|
});
|
|
2016
2031
|
_defineProperty(this, "getUserInput", () => {
|
|
2017
2032
|
return Expression.getUserInputFromProps(this.props);
|
|
@@ -2036,8 +2051,8 @@ class Expression extends React__namespace.Component {
|
|
|
2036
2051
|
this.props.trackInteraction();
|
|
2037
2052
|
});
|
|
2038
2053
|
_defineProperty(this, "_handleFocus", () => {
|
|
2039
|
-
var _this$props$
|
|
2040
|
-
(_this$props$
|
|
2054
|
+
var _this$props$analytics2;
|
|
2055
|
+
(_this$props$analytics2 = this.props.analytics) === null || _this$props$analytics2 === void 0 ? void 0 : _this$props$analytics2.onAnalyticsEvent({
|
|
2041
2056
|
type: "perseus:expression-focused",
|
|
2042
2057
|
payload: null
|
|
2043
2058
|
});
|
|
@@ -2244,16 +2259,6 @@ class Expression extends React__namespace.Component {
|
|
|
2244
2259
|
// @ts-expect-error - TS2339 - Property 'insert' does not exist on type 'ReactInstance'.
|
|
2245
2260
|
this.refs.input.insert(keyPressed);
|
|
2246
2261
|
}
|
|
2247
|
-
sendExpressionEvaluatedEvent(result) {
|
|
2248
|
-
var _this$props$analytics2;
|
|
2249
|
-
(_this$props$analytics2 = this.props.analytics) === null || _this$props$analytics2 === void 0 ? void 0 : _this$props$analytics2.onAnalyticsEvent({
|
|
2250
|
-
type: "perseus:expression-evaluated",
|
|
2251
|
-
payload: {
|
|
2252
|
-
result,
|
|
2253
|
-
virtualKeypadVersion: deriveKeypadVersion(this.props.apiOptions)
|
|
2254
|
-
}
|
|
2255
|
-
});
|
|
2256
|
-
}
|
|
2257
2262
|
render() {
|
|
2258
2263
|
var _this$props$keypadCon, _this$props$analytics3;
|
|
2259
2264
|
if (this.props.apiOptions.customKeypad) {
|
|
@@ -3739,10 +3744,10 @@ Zoom.prototype.dispose = function () {
|
|
|
3739
3744
|
};
|
|
3740
3745
|
const ZoomService = new ZoomServiceClass();
|
|
3741
3746
|
|
|
3742
|
-
// @baseFontFamily: "
|
|
3743
|
-
const baseFontFamily$1 = "'
|
|
3744
|
-
// @boldFontFamily: "
|
|
3745
|
-
const boldFontFamily = "'
|
|
3747
|
+
// @baseFontFamily: "Lato", sans-serif;
|
|
3748
|
+
const baseFontFamily$1 = "'Lato', sans-serif";
|
|
3749
|
+
// @boldFontFamily: "Lato-Bold", "Lato", sans-serif;
|
|
3750
|
+
const boldFontFamily = "'Lato-Bold', 'Lato', sans-serif";
|
|
3746
3751
|
// @green: #76a005;
|
|
3747
3752
|
const green$1 = "#76A005";
|
|
3748
3753
|
// @kaGreen: #71b307;
|
|
@@ -18763,6 +18768,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
18763
18768
|
class WidgetContainer extends React__namespace.Component {
|
|
18764
18769
|
constructor() {
|
|
18765
18770
|
super(...arguments);
|
|
18771
|
+
_defineProperty(this, "widgetRef", /*#__PURE__*/React__namespace.createRef());
|
|
18766
18772
|
_defineProperty(this, "state", {
|
|
18767
18773
|
// TODO(benkomalo): before we're mounted, we don't know how big
|
|
18768
18774
|
// we're going to be, so just default to MEDIUM for now. :/ In the
|
|
@@ -18772,8 +18778,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18772
18778
|
widgetProps: this.props.initialProps
|
|
18773
18779
|
});
|
|
18774
18780
|
_defineProperty(this, "getWidget", () => {
|
|
18775
|
-
|
|
18776
|
-
return this.refs.widget;
|
|
18781
|
+
return this.widgetRef.current;
|
|
18777
18782
|
});
|
|
18778
18783
|
_defineProperty(this, "replaceWidgetProps", newWidgetProps => {
|
|
18779
18784
|
this.setState({
|
|
@@ -18868,14 +18873,30 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18868
18873
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
18869
18874
|
className: className,
|
|
18870
18875
|
style: isStatic ? staticContainerStyles : {}
|
|
18871
|
-
}, /*#__PURE__*/React__namespace.createElement(
|
|
18872
|
-
|
|
18873
|
-
|
|
18874
|
-
|
|
18875
|
-
,
|
|
18876
|
-
|
|
18877
|
-
|
|
18878
|
-
|
|
18876
|
+
}, /*#__PURE__*/React__namespace.createElement(DependenciesContext.Consumer, null, _ref => {
|
|
18877
|
+
let {
|
|
18878
|
+
analytics
|
|
18879
|
+
} = _ref;
|
|
18880
|
+
return /*#__PURE__*/React__namespace.createElement(ErrorBoundary, {
|
|
18881
|
+
metadata: {
|
|
18882
|
+
widget_type: type,
|
|
18883
|
+
widget_id: this.props.id
|
|
18884
|
+
},
|
|
18885
|
+
onError: error => {
|
|
18886
|
+
analytics.onAnalyticsEvent({
|
|
18887
|
+
type: "perseus:widget-rendering-error",
|
|
18888
|
+
payload: {
|
|
18889
|
+
widgetType: type
|
|
18890
|
+
}
|
|
18891
|
+
});
|
|
18892
|
+
}
|
|
18893
|
+
}, /*#__PURE__*/React__namespace.createElement(WidgetType, _extends({}, this.state.widgetProps, {
|
|
18894
|
+
linterContext: linterContext,
|
|
18895
|
+
containerSizeClass: this.state.sizeClass,
|
|
18896
|
+
ref: this.widgetRef
|
|
18897
|
+
})), isStatic && /*#__PURE__*/React__namespace.createElement("div", {
|
|
18898
|
+
style: staticOverlayStyles
|
|
18899
|
+
}));
|
|
18879
18900
|
}));
|
|
18880
18901
|
}
|
|
18881
18902
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
@@ -18899,6 +18920,7 @@ const rContainsNonWhitespace = /\S/;
|
|
|
18899
18920
|
const rImageURL = /(web\+graphie|https):\/\/[^\s]*/;
|
|
18900
18921
|
const noopOnRender = () => {};
|
|
18901
18922
|
const SHOULD_CLEAR_WIDGETS_PROP_LIST = ["content", "problemNum", "widgets"];
|
|
18923
|
+
const makeContainerId = id => "container:" + id;
|
|
18902
18924
|
|
|
18903
18925
|
// Check if one focus path / id path is a prefix of another
|
|
18904
18926
|
// The focus path null will never be a prefix of any non-null
|
|
@@ -18945,6 +18967,7 @@ class Renderer extends React__namespace.Component {
|
|
|
18945
18967
|
_defineProperty(this, "_isMounted", void 0);
|
|
18946
18968
|
_defineProperty(this, "_isTwoColumn", void 0);
|
|
18947
18969
|
_defineProperty(this, "_translationLinter", void 0);
|
|
18970
|
+
_defineProperty(this, "_widgetContainers", new Map());
|
|
18948
18971
|
_defineProperty(this, "lastRenderedMarkdown", void 0);
|
|
18949
18972
|
_defineProperty(this, "reuseMarkdown", void 0);
|
|
18950
18973
|
_defineProperty(this, "translationIndex", void 0);
|
|
@@ -19018,19 +19041,22 @@ class Renderer extends React__namespace.Component {
|
|
|
19018
19041
|
// By this point we should have no duplicates, which are
|
|
19019
19042
|
// filtered out in this.render(), so we shouldn't have to
|
|
19020
19043
|
// worry about using this widget key and ref:
|
|
19021
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
19022
|
-
key:
|
|
19023
|
-
|
|
19024
|
-
|
|
19025
|
-
|
|
19026
|
-
|
|
19027
|
-
|
|
19028
|
-
|
|
19044
|
+
return /*#__PURE__*/React__namespace.createElement(WidgetContainer, {
|
|
19045
|
+
key: makeContainerId(id),
|
|
19046
|
+
id: id,
|
|
19047
|
+
ref: node => {
|
|
19048
|
+
const containerId = makeContainerId(id);
|
|
19049
|
+
if (node != null) {
|
|
19050
|
+
this._widgetContainers.set(containerId, node);
|
|
19051
|
+
} else {
|
|
19052
|
+
this._widgetContainers.delete(containerId);
|
|
19053
|
+
}
|
|
19054
|
+
},
|
|
19029
19055
|
type: type,
|
|
19030
19056
|
initialProps: this.getWidgetProps(id),
|
|
19031
19057
|
shouldHighlight: shouldHighlight,
|
|
19032
19058
|
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "widget")
|
|
19033
|
-
})
|
|
19059
|
+
});
|
|
19034
19060
|
}
|
|
19035
19061
|
return null;
|
|
19036
19062
|
});
|
|
@@ -19058,7 +19084,6 @@ class Renderer extends React__namespace.Component {
|
|
|
19058
19084
|
}
|
|
19059
19085
|
return {
|
|
19060
19086
|
...widgetProps,
|
|
19061
|
-
ref: id,
|
|
19062
19087
|
widgetId: id,
|
|
19063
19088
|
alignment: widgetInfo && widgetInfo.alignment,
|
|
19064
19089
|
// When determining if a widget is static, we verify that the widget is not an
|
|
@@ -19191,12 +19216,10 @@ class Renderer extends React__namespace.Component {
|
|
|
19191
19216
|
return [...this.findInternalWidgets(filterCriterion), ...this.props.findExternalWidgets(filterCriterion)];
|
|
19192
19217
|
});
|
|
19193
19218
|
_defineProperty(this, "getWidgetInstance", id => {
|
|
19194
|
-
|
|
19195
|
-
const ref = this.refs["container:" + id];
|
|
19219
|
+
const ref = this._widgetContainers.get(makeContainerId(id));
|
|
19196
19220
|
if (!ref) {
|
|
19197
19221
|
return null;
|
|
19198
19222
|
}
|
|
19199
|
-
// @ts-expect-error - TS2339 - Property 'getWidget' does not exist on type 'ReactInstance'.
|
|
19200
19223
|
return ref.getWidget();
|
|
19201
19224
|
});
|
|
19202
19225
|
_defineProperty(this, "_onWidgetFocus", function (id) {
|
|
@@ -19910,7 +19933,10 @@ class Renderer extends React__namespace.Component {
|
|
|
19910
19933
|
const widget = this.getWidgetInstance(id);
|
|
19911
19934
|
// widget can be undefined if it hasn't yet been rendered
|
|
19912
19935
|
if (widget && widget.simpleValidate) {
|
|
19913
|
-
widgetScores[id] = widget.simpleValidate(
|
|
19936
|
+
widgetScores[id] = widget.simpleValidate({
|
|
19937
|
+
...(props === null || props === void 0 ? void 0 : props.options),
|
|
19938
|
+
scoring: true
|
|
19939
|
+
}, onInputError);
|
|
19914
19940
|
}
|
|
19915
19941
|
});
|
|
19916
19942
|
return widgetScores;
|
|
@@ -20061,9 +20087,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20061
20087
|
// they are re-rendered, so even if they've been
|
|
20062
20088
|
// re-rendered we need to call these methods on them.
|
|
20063
20089
|
___default["default"].each(this.widgetIds, id => {
|
|
20064
|
-
|
|
20065
|
-
const container = this.refs["container:" + id];
|
|
20066
|
-
// @ts-expect-error - TS2339 - Property 'replaceWidgetProps' does not exist on type 'ReactInstance'.
|
|
20090
|
+
const container = this._widgetContainers.get(makeContainerId(id));
|
|
20067
20091
|
container && container.replaceWidgetProps(this.getWidgetProps(id));
|
|
20068
20092
|
});
|
|
20069
20093
|
if (this.props.serializedState && !___default["default"].isEqual(this.props.serializedState, this.getSerializedState())) {
|
|
@@ -42366,8 +42390,7 @@ class Transformer extends React__namespace.Component {
|
|
|
42366
42390
|
// @ts-expect-error - TS2345 - Argument of type '{ type: "dilation"; center: any; scale: number; }' is not assignable to parameter of type 'PerseusTransformerTransformation'.
|
|
42367
42391
|
self.doTransform({
|
|
42368
42392
|
type: "dilation",
|
|
42369
|
-
|
|
42370
|
-
// will still be defined here. center: self.dilationCircle.centerPoint.coord,
|
|
42393
|
+
center: self.dilationCircle.centerPoint.coord,
|
|
42371
42394
|
scale: newRadius / oldRadius
|
|
42372
42395
|
});
|
|
42373
42396
|
},
|
|
@@ -44015,7 +44038,7 @@ const init = function (options) {
|
|
|
44015
44038
|
|
|
44016
44039
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44017
44040
|
const libName = "@khanacademy/perseus";
|
|
44018
|
-
const libVersion = "12.
|
|
44041
|
+
const libVersion = "12.3.0";
|
|
44019
44042
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44020
44043
|
|
|
44021
44044
|
const apiVersion = {
|
|
@@ -44037,6 +44060,7 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44037
44060
|
constructor(props) {
|
|
44038
44061
|
super(props);
|
|
44039
44062
|
_defineProperty(this, "_currentFocus", void 0);
|
|
44063
|
+
_defineProperty(this, "sectionRenderers", []);
|
|
44040
44064
|
_defineProperty(this, "_handleFocusChange", (newFocusPath, oldFocusPath) => {
|
|
44041
44065
|
// TODO(charlie): DRY this up--some of this logic is repeated in
|
|
44042
44066
|
// ItemRenderer.
|
|
@@ -44061,17 +44085,17 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44061
44085
|
// paths, so as to check whether the focused path represents an
|
|
44062
44086
|
// input.
|
|
44063
44087
|
let didFocusInput = false;
|
|
44088
|
+
let focusedInput;
|
|
44064
44089
|
if (this._currentFocus) {
|
|
44065
|
-
const [
|
|
44066
|
-
|
|
44067
|
-
// @ts-expect-error - TS2339 - Property 'getInputPaths' does not exist on type 'ReactInstance'.
|
|
44068
|
-
const inputPaths = this.refs[sectionRef].getInputPaths();
|
|
44090
|
+
const [sectionIndex, ...focusPath] = this._currentFocus;
|
|
44091
|
+
const inputPaths = this.sectionRenderers[sectionIndex].getInputPaths();
|
|
44069
44092
|
didFocusInput = inputPaths.some(inputPath => {
|
|
44070
44093
|
return Util.inputPathsEqual(inputPath, focusPath);
|
|
44071
44094
|
});
|
|
44095
|
+
focusedInput = this.sectionRenderers[sectionIndex].getDOMNodeForPath(focusPath);
|
|
44072
44096
|
}
|
|
44073
44097
|
if (this.props.apiOptions.onFocusChange != null) {
|
|
44074
|
-
this.props.apiOptions.onFocusChange(this._currentFocus, prevFocusPath, didFocusInput ? keypadElement === null || keypadElement === void 0 ? void 0 : keypadElement.getDOMNode() : null);
|
|
44098
|
+
this.props.apiOptions.onFocusChange(this._currentFocus, prevFocusPath, didFocusInput ? keypadElement === null || keypadElement === void 0 ? void 0 : keypadElement.getDOMNode() : null, didFocusInput ? focusedInput : null);
|
|
44075
44099
|
}
|
|
44076
44100
|
if (keypadElement && isMobile) {
|
|
44077
44101
|
if (didFocusInput) {
|
|
@@ -44103,10 +44127,8 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44103
44127
|
});
|
|
44104
44128
|
_defineProperty(this, "blur", () => {
|
|
44105
44129
|
if (this._currentFocus) {
|
|
44106
|
-
const [
|
|
44107
|
-
|
|
44108
|
-
// @ts-expect-error - TS2339 - Property 'blurPath' does not exist on type 'ReactInstance'.
|
|
44109
|
-
this.refs[sectionRef].blurPath(inputPath);
|
|
44130
|
+
const [sectionIndex, ...inputPath] = this._currentFocus;
|
|
44131
|
+
this.sectionRenderers[sectionIndex].blurPath(inputPath);
|
|
44110
44132
|
}
|
|
44111
44133
|
});
|
|
44112
44134
|
_defineProperty(this, "_sections", () => {
|
|
@@ -44134,34 +44156,40 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44134
44156
|
});
|
|
44135
44157
|
|
|
44136
44158
|
// TODO(alex): Add mobile api functions and pass them down here
|
|
44137
|
-
|
|
44138
|
-
|
|
44139
|
-
|
|
44140
|
-
|
|
44141
|
-
|
|
44142
|
-
key:
|
|
44159
|
+
// We're using the index as the key here because we don't have a unique
|
|
44160
|
+
// identifier for each section. This should be fine as we never remove
|
|
44161
|
+
// or reorder sections.
|
|
44162
|
+
const sections = this._sections().map((section, sectionIndex) => {
|
|
44163
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
44164
|
+
key: sectionIndex,
|
|
44143
44165
|
className: "clearfix"
|
|
44144
44166
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, section, {
|
|
44145
|
-
ref:
|
|
44146
|
-
|
|
44147
|
-
|
|
44167
|
+
ref: elem => {
|
|
44168
|
+
if (elem) {
|
|
44169
|
+
this.sectionRenderers[sectionIndex] = elem;
|
|
44170
|
+
}
|
|
44171
|
+
},
|
|
44172
|
+
key: sectionIndex,
|
|
44173
|
+
key_: sectionIndex,
|
|
44148
44174
|
keypadElement: this.props.keypadElement,
|
|
44149
44175
|
apiOptions: {
|
|
44150
44176
|
...apiOptions,
|
|
44151
44177
|
onFocusChange: (newFocusPath, oldFocusPath) => {
|
|
44152
|
-
// Prefix the paths with the relevant section,
|
|
44178
|
+
// Prefix the paths with the relevant section index,
|
|
44153
44179
|
// so as to allow us to distinguish between
|
|
44154
44180
|
// equivalently-named inputs across Renderers.
|
|
44155
|
-
this._handleFocusChange(newFocusPath && [
|
|
44181
|
+
this._handleFocusChange(newFocusPath && [sectionIndex].concat(newFocusPath), oldFocusPath && [sectionIndex].concat(oldFocusPath));
|
|
44156
44182
|
}
|
|
44157
44183
|
},
|
|
44158
44184
|
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "article"),
|
|
44159
44185
|
legacyPerseusLint: this.props.legacyPerseusLint
|
|
44160
|
-
})))
|
|
44186
|
+
}, this.props.dependencies)));
|
|
44161
44187
|
});
|
|
44162
44188
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
44163
44189
|
className: classes
|
|
44164
|
-
},
|
|
44190
|
+
}, /*#__PURE__*/React__namespace.createElement(DependenciesContext.Provider, {
|
|
44191
|
+
value: this.props.dependencies
|
|
44192
|
+
}, sections));
|
|
44165
44193
|
}
|
|
44166
44194
|
}
|
|
44167
44195
|
_defineProperty(ArticleRenderer, "defaultProps", {
|
|
@@ -45251,7 +45279,7 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
45251
45279
|
};
|
|
45252
45280
|
const questionRenderer = /*#__PURE__*/React__namespace.createElement(context$1.Provider, {
|
|
45253
45281
|
value: contextValue
|
|
45254
|
-
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
45282
|
+
}, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({
|
|
45255
45283
|
keypadElement: this.props.keypadElement,
|
|
45256
45284
|
problemNum: this.props.problemNum,
|
|
45257
45285
|
onInteractWithWidget: this.handleInteractWithWidget,
|
|
@@ -45267,7 +45295,7 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
45267
45295
|
content: this.props.item.question.content,
|
|
45268
45296
|
widgets: this.props.item.question.widgets,
|
|
45269
45297
|
images: this.props.item.question.images
|
|
45270
|
-
}));
|
|
45298
|
+
}, this.props.dependencies)));
|
|
45271
45299
|
const hintsRenderer = /*#__PURE__*/React__namespace.createElement(HintsRenderer, {
|
|
45272
45300
|
hints: this.props.item.hints,
|
|
45273
45301
|
hintsVisible: this.props.hintsVisible,
|