@khanacademy/perseus 43.0.1 → 44.0.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/dist/all-widgets.d.ts +2 -23
- package/dist/basic-widgets.d.ts +2 -23
- package/dist/components/graph.d.ts +1 -0
- package/dist/components/icon.d.ts +0 -1
- package/dist/components/multi-button-group.d.ts +1 -0
- package/dist/components/number-input.d.ts +5 -3
- package/dist/components/text-input.d.ts +4 -2
- package/dist/components/tooltip.d.ts +1 -0
- package/dist/es/index.js +476 -261
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +4 -2
- package/dist/es/strings.js.map +1 -1
- package/dist/extra-widgets.d.ts +2 -23
- package/dist/index.d.ts +2 -2
- package/dist/index.js +465 -250
- package/dist/index.js.map +1 -1
- package/dist/interactive2/interactive-util.d.ts +1 -1
- package/dist/interactive2/movable-point-options.d.ts +2 -2
- package/dist/interactive2/movable-point.d.ts +7 -7
- package/dist/interactive2/objective_.d.ts +1 -1
- package/dist/jipt-paragraphs.d.ts +2 -2
- package/dist/perseus-api.d.ts +2 -77
- package/dist/perseus-types.d.ts +17 -17
- package/dist/server-item-renderer.d.ts +26 -49
- package/dist/strings.d.ts +1 -0
- package/dist/strings.js +4 -2
- package/dist/strings.js.map +1 -1
- package/dist/styles/global-styles.d.ts +0 -1
- package/dist/styles/shared.d.ts +0 -1
- package/dist/traversal.d.ts +1 -1
- package/dist/util/a11y.d.ts +0 -1
- package/dist/util/debounce.d.ts +1 -1
- package/dist/util/parse-perseus-json/general-purpose-parsers/defaulted.d.ts +1 -1
- package/dist/util/parse-perseus-json/general-purpose-parsers/index.d.ts +2 -0
- package/dist/util/parse-perseus-json/general-purpose-parsers/pipe-parsers.d.ts +7 -0
- package/dist/util/parse-perseus-json/general-purpose-parsers/pipe-parsers.typetest.d.ts +1 -0
- package/dist/util/parse-perseus-json/general-purpose-parsers/unknown.d.ts +2 -0
- package/dist/util/parse-perseus-json/perseus-parsers/graded-group-widget.d.ts +2 -2
- package/dist/util/parse-perseus-json/perseus-parsers/images-map.d.ts +5 -0
- package/dist/util/parse-perseus-json/perseus-parsers/widget.d.ts +4 -0
- package/dist/validation.types.d.ts +14 -6
- package/dist/widgets/categorizer/categorizer.d.ts +2 -2
- package/dist/widgets/categorizer/score-categorizer.d.ts +2 -2
- package/dist/widgets/categorizer/validate-categorizer.d.ts +15 -0
- package/dist/widgets/definition/definition.d.ts +1 -1
- package/dist/widgets/deprecated-standin/deprecated-standin.d.ts +1 -1
- package/dist/widgets/dropdown/dropdown.d.ts +9 -1
- package/dist/widgets/dropdown/validate-dropdown.d.ts +10 -0
- package/dist/widgets/explanation/explanation.d.ts +1 -1
- package/dist/widgets/expression/expression.d.ts +92 -217
- package/dist/widgets/image/image.d.ts +1 -1
- package/dist/widgets/interaction/interaction.d.ts +1 -1
- package/dist/widgets/interactive-graphs/graphs/components/movable-point.d.ts +11 -7
- package/dist/widgets/interactive-graphs/graphs/components/use-control-point.d.ts +7 -3
- package/dist/widgets/interactive-graphs/graphs/quadratic.d.ts +1 -1
- package/dist/widgets/interactive-graphs/types.d.ts +1 -0
- package/dist/widgets/label-image/answer-pill.d.ts +0 -1
- package/dist/widgets/label-image/label-image.d.ts +5 -65
- package/dist/widgets/label-image/marker.d.ts +0 -1
- package/dist/widgets/matrix/matrix.d.ts +12 -5
- package/dist/widgets/measurer/measurer.d.ts +2 -2
- package/dist/widgets/molecule/molecule.d.ts +1 -1
- package/dist/widgets/orderer/validate-orderer.d.ts +12 -0
- package/dist/widgets/passage/passage-markdown.d.ts +2 -2
- package/dist/widgets/passage/passage.d.ts +1 -1
- package/dist/widgets/passage-ref/passage-ref.d.ts +1 -1
- package/dist/widgets/passage-ref-target/passage-ref-target.d.ts +1 -1
- package/dist/widgets/plotter/plotter.d.ts +2 -2
- package/dist/widgets/plotter/score-plotter.d.ts +2 -2
- package/dist/widgets/plotter/validate-plotter.d.ts +12 -0
- package/dist/widgets/radio/choice-icon/shared-styles.d.ts +0 -1
- package/dist/widgets/radio/choice-none-above.d.ts +1 -1
- package/dist/widgets/radio/radio.d.ts +3 -3
- package/dist/widgets/radio/validate-radio.d.ts +14 -0
- package/dist/widgets/sorter/validate-sorter.d.ts +13 -0
- package/dist/widgets/video/video.d.ts +1 -1
- package/package.json +5 -5
- package/dist/util/parse-perseus-json/general-purpose-parsers/compose-parsers.d.ts +0 -2
package/dist/es/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as PerseusLinter from '@khanacademy/perseus-linter';
|
|
|
4
4
|
import { linterContextDefault, Rule } from '@khanacademy/perseus-linter';
|
|
5
5
|
import { View, RenderStateRoot, UniqueIDProvider, useOnMountEffect, useLatestRef, useUniqueIdWithMock, Text as Text$2 } from '@khanacademy/wonder-blocks-core';
|
|
6
6
|
import Tooltip$1 from '@khanacademy/wonder-blocks-tooltip';
|
|
7
|
-
import { HeadingMedium, LabelSmall, Body, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
7
|
+
import { HeadingMedium, LabelSmall, LabelLarge, Body, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
8
8
|
import { StyleSheet, css } from 'aphrodite';
|
|
9
9
|
import classNames$1 from 'classnames';
|
|
10
10
|
import * as React from 'react';
|
|
@@ -249,7 +249,8 @@ const mockStrings = {
|
|
|
249
249
|
srInteractiveElements: ({
|
|
250
250
|
elements
|
|
251
251
|
}) => `Interactive elements: ${elements}`,
|
|
252
|
-
srNoInteractiveElements: "No interactive elements"
|
|
252
|
+
srNoInteractiveElements: "No interactive elements",
|
|
253
|
+
selectAnAnswer: "Select an answer"
|
|
253
254
|
};
|
|
254
255
|
|
|
255
256
|
/**
|
|
@@ -2760,8 +2761,6 @@ async function getImageSizeModern(url) {
|
|
|
2760
2761
|
});
|
|
2761
2762
|
}
|
|
2762
2763
|
|
|
2763
|
-
/* eslint-disable @babel/no-invalid-this, getter-return, one-var */
|
|
2764
|
-
|
|
2765
2764
|
// TODO: dedupe this with Coord in interactive2/types.js
|
|
2766
2765
|
|
|
2767
2766
|
let supportsPassive = false;
|
|
@@ -2837,8 +2836,8 @@ function shuffle$3(array, randomSeed, ensurePermuted = false) {
|
|
|
2837
2836
|
do {
|
|
2838
2837
|
// Fischer-Yates shuffle
|
|
2839
2838
|
for (let top = shuffled.length; top > 0; top--) {
|
|
2840
|
-
const newEnd = Math.floor(random() * top)
|
|
2841
|
-
|
|
2839
|
+
const newEnd = Math.floor(random() * top);
|
|
2840
|
+
const temp = shuffled[newEnd];
|
|
2842
2841
|
|
|
2843
2842
|
// @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
|
|
2844
2843
|
shuffled[newEnd] = shuffled[top - 1];
|
|
@@ -3170,13 +3169,13 @@ function eq$4(x, y) {
|
|
|
3170
3169
|
* Deep approximate equality on primitives, numbers, arrays, and objects.
|
|
3171
3170
|
* Recursive.
|
|
3172
3171
|
*/
|
|
3173
|
-
function deepEq$
|
|
3172
|
+
function deepEq$7(x, y) {
|
|
3174
3173
|
if (Array.isArray(x) && Array.isArray(y)) {
|
|
3175
3174
|
if (x.length !== y.length) {
|
|
3176
3175
|
return false;
|
|
3177
3176
|
}
|
|
3178
3177
|
for (let i = 0; i < x.length; i++) {
|
|
3179
|
-
if (!deepEq$
|
|
3178
|
+
if (!deepEq$7(x[i], y[i])) {
|
|
3180
3179
|
return false;
|
|
3181
3180
|
}
|
|
3182
3181
|
}
|
|
@@ -3194,10 +3193,10 @@ function deepEq$6(x, y) {
|
|
|
3194
3193
|
if (typeof x === "object" && typeof y === "object" && !!x && !!y) {
|
|
3195
3194
|
return x === y || _.all(x, function (v, k) {
|
|
3196
3195
|
// @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
|
|
3197
|
-
return deepEq$
|
|
3196
|
+
return deepEq$7(y[k], v);
|
|
3198
3197
|
}) && _.all(y, function (v, k) {
|
|
3199
3198
|
// @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
|
|
3200
|
-
return deepEq$
|
|
3199
|
+
return deepEq$7(x[k], v);
|
|
3201
3200
|
});
|
|
3202
3201
|
}
|
|
3203
3202
|
if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
|
|
@@ -3478,7 +3477,7 @@ const Util = {
|
|
|
3478
3477
|
tickStepFromNumTicks,
|
|
3479
3478
|
constrainedTickStepsFromTickSteps,
|
|
3480
3479
|
eq: eq$4,
|
|
3481
|
-
deepEq: deepEq$
|
|
3480
|
+
deepEq: deepEq$7,
|
|
3482
3481
|
parseQueryString,
|
|
3483
3482
|
updateQueryString: updateQueryString$2,
|
|
3484
3483
|
strongEncodeURIComponent,
|
|
@@ -10509,7 +10508,9 @@ const getClipPoint = function getClipPoint(graph, coord, angle) {
|
|
|
10509
10508
|
return clipPoint;
|
|
10510
10509
|
};
|
|
10511
10510
|
|
|
10512
|
-
|
|
10511
|
+
/**
|
|
10512
|
+
* Default methods for a wrapped movable.
|
|
10513
|
+
*/
|
|
10513
10514
|
|
|
10514
10515
|
/*
|
|
10515
10516
|
* attr() and animate() simply pass the
|
|
@@ -10767,7 +10768,7 @@ class WrappedLine extends WrappedDrawing {
|
|
|
10767
10768
|
*/
|
|
10768
10769
|
const {
|
|
10769
10770
|
eq: eq$3,
|
|
10770
|
-
deepEq: deepEq$
|
|
10771
|
+
deepEq: deepEq$6
|
|
10771
10772
|
} = Util;
|
|
10772
10773
|
|
|
10773
10774
|
// This should really be a readonly tuple of [number, number]
|
|
@@ -10927,7 +10928,7 @@ function similar(coords1, coords2, tolerance) {
|
|
|
10927
10928
|
angles = rotate(angles, i);
|
|
10928
10929
|
// @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
|
|
10929
10930
|
sides = rotate(sides, i);
|
|
10930
|
-
if (deepEq$
|
|
10931
|
+
if (deepEq$6(angles1, angles)) {
|
|
10931
10932
|
const sidePairs = _.zip(sides1, sides);
|
|
10932
10933
|
const factors = _.map(sidePairs, function (pair) {
|
|
10933
10934
|
return pair[0] / pair[1];
|
|
@@ -13865,7 +13866,7 @@ _.extend(MovableAngle.prototype, {
|
|
|
13865
13866
|
|
|
13866
13867
|
/* eslint-disable @babel/no-invalid-this */
|
|
13867
13868
|
const nestedMap$1 = Util.nestedMap;
|
|
13868
|
-
const deepEq$
|
|
13869
|
+
const deepEq$5 = Util.deepEq;
|
|
13869
13870
|
|
|
13870
13871
|
/**
|
|
13871
13872
|
* A base class for all Graphie Movables
|
|
@@ -13962,7 +13963,7 @@ const createSimpleClass = function createSimpleClass(addFunction) {
|
|
|
13962
13963
|
this._prevProps = this.props;
|
|
13963
13964
|
},
|
|
13964
13965
|
modify: function (graphie) {
|
|
13965
|
-
if (!deepEq$
|
|
13966
|
+
if (!deepEq$5(this.props, this._prevProps)) {
|
|
13966
13967
|
this.remove();
|
|
13967
13968
|
this.add(graphie);
|
|
13968
13969
|
this._prevProps = this.props;
|
|
@@ -16576,7 +16577,7 @@ var Movables = {
|
|
|
16576
16577
|
const GraphieMovable = GraphieClasses.GraphieMovable;
|
|
16577
16578
|
const createGraphie = GraphUtils.createGraphie;
|
|
16578
16579
|
const {
|
|
16579
|
-
deepEq: deepEq$
|
|
16580
|
+
deepEq: deepEq$4,
|
|
16580
16581
|
nestedMap
|
|
16581
16582
|
} = Util;
|
|
16582
16583
|
const {
|
|
@@ -16629,7 +16630,7 @@ class Graphie extends React.Component {
|
|
|
16629
16630
|
};
|
|
16630
16631
|
this._setupGraphie = () => {
|
|
16631
16632
|
this._removeMovables();
|
|
16632
|
-
const graphieDiv =
|
|
16633
|
+
const graphieDiv = this.graphieDivRef.current;
|
|
16633
16634
|
if (graphieDiv == null || graphieDiv instanceof Text) {
|
|
16634
16635
|
throw new Error("No graphie container div found");
|
|
16635
16636
|
}
|
|
@@ -16818,7 +16819,7 @@ class Graphie extends React.Component {
|
|
|
16818
16819
|
if (this.props.setup !== prevProps.setup) {
|
|
16819
16820
|
Log.error("<Graphie> was given a new setup function. " + "This is a bad idea; please refactor your code to give " + "the same setup function reference to <Graphie> on " + "every render.", Errors.Internal);
|
|
16820
16821
|
}
|
|
16821
|
-
if (!deepEq$
|
|
16822
|
+
if (!deepEq$4(this.props.options, prevProps.options) || !deepEq$4(this.props.box, prevProps.box) || !deepEq$4(this.props.range, prevProps.range)) {
|
|
16822
16823
|
this._setupGraphie();
|
|
16823
16824
|
}
|
|
16824
16825
|
this._updateMovables();
|
|
@@ -18536,7 +18537,7 @@ const rules$1 = _extends({}, pureMarkdownRules, {
|
|
|
18536
18537
|
// The href prop should always be here, but just in case somehow the article's
|
|
18537
18538
|
// link was not put together properly, let's make sure it's there so we
|
|
18538
18539
|
// don't break the entire page.
|
|
18539
|
-
const isKAUrl = href ? href.match(/https?:\/\/[
|
|
18540
|
+
const isKAUrl = href ? href.match(/https?:\/\/[^/]*khanacademy.org|^\//) : false;
|
|
18540
18541
|
if (!isKAUrl) {
|
|
18541
18542
|
// Prevents "reverse tabnabbing" phishing attacks
|
|
18542
18543
|
// @ts-expect-error - TS2322 - Type '"noopener noreferrer"' is not assignable to type 'null'.
|
|
@@ -20889,36 +20890,36 @@ function uniqueIdForInput(prefix = "input-") {
|
|
|
20889
20890
|
class TextInput extends React.Component {
|
|
20890
20891
|
constructor(props) {
|
|
20891
20892
|
super(props);
|
|
20893
|
+
this.inputRef = /*#__PURE__*/React.createRef();
|
|
20892
20894
|
this.id = void 0;
|
|
20895
|
+
this._getInput = () => {
|
|
20896
|
+
if (!this.inputRef.current) {
|
|
20897
|
+
throw new PerseusError("Input ref accessed before set", Errors.Internal);
|
|
20898
|
+
}
|
|
20899
|
+
return this.inputRef.current;
|
|
20900
|
+
};
|
|
20893
20901
|
this.focus = () => {
|
|
20894
|
-
|
|
20895
|
-
ReactDOM__default.findDOMNode(this).focus();
|
|
20902
|
+
this._getInput().focus();
|
|
20896
20903
|
};
|
|
20897
20904
|
this.blur = () => {
|
|
20898
|
-
|
|
20899
|
-
ReactDOM__default.findDOMNode(this).blur();
|
|
20905
|
+
this._getInput().blur();
|
|
20900
20906
|
};
|
|
20901
20907
|
this.getValue = () => {
|
|
20902
|
-
var
|
|
20903
|
-
|
|
20904
|
-
return (_ReactDOM$findDOMNode = ReactDOM__default.findDOMNode(this)) == null ? void 0 : _ReactDOM$findDOMNode.value;
|
|
20908
|
+
var _this$inputRef$curren;
|
|
20909
|
+
return (_this$inputRef$curren = this.inputRef.current) == null ? void 0 : _this$inputRef$curren.value;
|
|
20905
20910
|
};
|
|
20906
20911
|
this.getStringValue = () => {
|
|
20907
|
-
var
|
|
20908
|
-
|
|
20909
|
-
return (_ReactDOM$findDOMNode2 = ReactDOM__default.findDOMNode(this)) == null ? void 0 : _ReactDOM$findDOMNode2.value.toString();
|
|
20912
|
+
var _this$inputRef$curren2;
|
|
20913
|
+
return (_this$inputRef$curren2 = this.inputRef.current) == null ? void 0 : _this$inputRef$curren2.value.toString();
|
|
20910
20914
|
};
|
|
20911
20915
|
this.setSelectionRange = (selectionStart, selectionEnd) => {
|
|
20912
|
-
|
|
20913
|
-
ReactDOM__default.findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
20916
|
+
this._getInput().setSelectionRange(selectionStart, selectionEnd);
|
|
20914
20917
|
};
|
|
20915
20918
|
this.getSelectionStart = () => {
|
|
20916
|
-
|
|
20917
|
-
return ReactDOM__default.findDOMNode(this).selectionStart;
|
|
20919
|
+
return this._getInput().selectionStart;
|
|
20918
20920
|
};
|
|
20919
20921
|
this.getSelectionEnd = () => {
|
|
20920
|
-
|
|
20921
|
-
return ReactDOM__default.findDOMNode(this).selectionEnd;
|
|
20922
|
+
return this._getInput().selectionEnd;
|
|
20922
20923
|
};
|
|
20923
20924
|
if (props.id) {
|
|
20924
20925
|
this.id = props.id;
|
|
@@ -20939,6 +20940,7 @@ class TextInput extends React.Component {
|
|
|
20939
20940
|
} = this.props;
|
|
20940
20941
|
const formattedValue = value === null ? "" : value.toString();
|
|
20941
20942
|
return /*#__PURE__*/React.createElement(TextField, {
|
|
20943
|
+
ref: this.inputRef,
|
|
20942
20944
|
style: style,
|
|
20943
20945
|
disabled: disabled,
|
|
20944
20946
|
id: this.id,
|
|
@@ -20973,7 +20975,7 @@ function _objectWithoutPropertiesLoose(r, e) {
|
|
|
20973
20975
|
return t;
|
|
20974
20976
|
}
|
|
20975
20977
|
|
|
20976
|
-
const _excluded$
|
|
20978
|
+
const _excluded$8 = ["position", "visibility", "left", "top"];
|
|
20977
20979
|
const zIndex = 10;
|
|
20978
20980
|
let HorizontalDirection = /*#__PURE__*/function (HorizontalDirection) {
|
|
20979
20981
|
HorizontalDirection["Left"] = "left";
|
|
@@ -21024,7 +21026,7 @@ const TooltipArrow = _ref => {
|
|
|
21024
21026
|
left = 100,
|
|
21025
21027
|
top = 0
|
|
21026
21028
|
} = _ref,
|
|
21027
|
-
props = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
21029
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded$8);
|
|
21028
21030
|
// TODO(aria): Think about adding a box-shadow to the triangle here
|
|
21029
21031
|
// See http://css-tricks.com/triangle-with-shadow/
|
|
21030
21032
|
|
|
@@ -21134,6 +21136,7 @@ const HORIZONTAL_ALIGNMNENTS = {
|
|
|
21134
21136
|
class Tooltip extends React.Component {
|
|
21135
21137
|
constructor(...args) {
|
|
21136
21138
|
super(...args);
|
|
21139
|
+
this.tooltipContainerRef = /*#__PURE__*/React.createRef();
|
|
21137
21140
|
this.state = {
|
|
21138
21141
|
height: null // used for offsetting "top" positioned tooltips
|
|
21139
21142
|
};
|
|
@@ -21208,8 +21211,7 @@ class Tooltip extends React.Component {
|
|
|
21208
21211
|
display: this.props.show ? "block" : "none"
|
|
21209
21212
|
}
|
|
21210
21213
|
}, /*#__PURE__*/React.createElement("div", {
|
|
21211
|
-
|
|
21212
|
-
ref: "tooltipContainer",
|
|
21214
|
+
ref: this.tooltipContainerRef,
|
|
21213
21215
|
className: "tooltipContainer",
|
|
21214
21216
|
style: {
|
|
21215
21217
|
position: "absolute",
|
|
@@ -21236,10 +21238,8 @@ class Tooltip extends React.Component {
|
|
|
21236
21238
|
}, this.props.children.slice(1)), arrowBelow));
|
|
21237
21239
|
}
|
|
21238
21240
|
_updateHeight() {
|
|
21239
|
-
const tooltipContainer =
|
|
21240
|
-
|
|
21241
|
-
this.refs.tooltipContainer);
|
|
21242
|
-
const height = tooltipContainer.offsetHeight;
|
|
21241
|
+
const tooltipContainer = this.tooltipContainerRef.current;
|
|
21242
|
+
const height = (tooltipContainer == null ? void 0 : tooltipContainer.offsetHeight) || 0;
|
|
21243
21243
|
if (height !== this.state.height) {
|
|
21244
21244
|
this.setState({
|
|
21245
21245
|
height
|
|
@@ -21384,7 +21384,7 @@ InputWithExamples.defaultProps = {
|
|
|
21384
21384
|
className: ""
|
|
21385
21385
|
};
|
|
21386
21386
|
|
|
21387
|
-
const _excluded$
|
|
21387
|
+
const _excluded$7 = ["keypadElement", "onFocus", "value"];
|
|
21388
21388
|
class SimpleKeypadInput extends React.Component {
|
|
21389
21389
|
constructor(...args) {
|
|
21390
21390
|
super(...args);
|
|
@@ -21429,7 +21429,7 @@ class SimpleKeypadInput extends React.Component {
|
|
|
21429
21429
|
onFocus,
|
|
21430
21430
|
value
|
|
21431
21431
|
} = _this$props,
|
|
21432
|
-
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$
|
|
21432
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$7);
|
|
21433
21433
|
return (
|
|
21434
21434
|
/*#__PURE__*/
|
|
21435
21435
|
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
@@ -21991,7 +21991,7 @@ function maybeParsePercentInput(inputValue, normalizedAnswerExpected) {
|
|
|
21991
21991
|
return value / 100;
|
|
21992
21992
|
}
|
|
21993
21993
|
|
|
21994
|
-
// Otherwise, we return input
|
|
21994
|
+
// Otherwise, we return input value (number) stripped of the "%".
|
|
21995
21995
|
return value;
|
|
21996
21996
|
}
|
|
21997
21997
|
function scoreNumericInput(userInput, rubric, strings) {
|
|
@@ -25662,14 +25662,14 @@ var Choice$1 = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.
|
|
|
25662
25662
|
forwardedRef: ref
|
|
25663
25663
|
})));
|
|
25664
25664
|
|
|
25665
|
-
const _excluded$
|
|
25665
|
+
const _excluded$6 = ["content", "forwardedRef", "showContent"];
|
|
25666
25666
|
const ChoiceNoneAbove = function ChoiceNoneAbove(_ref) {
|
|
25667
25667
|
let {
|
|
25668
25668
|
content,
|
|
25669
25669
|
forwardedRef,
|
|
25670
25670
|
showContent = true
|
|
25671
25671
|
} = _ref,
|
|
25672
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
25672
|
+
rest = _objectWithoutPropertiesLoose(_ref, _excluded$6);
|
|
25673
25673
|
const {
|
|
25674
25674
|
strings
|
|
25675
25675
|
} = usePerseusI18n();
|
|
@@ -26040,7 +26040,15 @@ const styles$p = StyleSheet.create({
|
|
|
26040
26040
|
}
|
|
26041
26041
|
});
|
|
26042
26042
|
|
|
26043
|
-
|
|
26043
|
+
/**
|
|
26044
|
+
* Checks if the user has selected at least one option. Additional validation
|
|
26045
|
+
* is done in scoreRadio to check if the number of selected options is correct
|
|
26046
|
+
* and if the user has selected both a correct option and the "none of the above"
|
|
26047
|
+
* option.
|
|
26048
|
+
* @param userInput
|
|
26049
|
+
* @see `scoreRadio` for the additional validation logic and the scoring logic.
|
|
26050
|
+
*/
|
|
26051
|
+
function validateRadio(userInput) {
|
|
26044
26052
|
const numSelected = userInput.choicesSelected.reduce((sum, selected) => {
|
|
26045
26053
|
return sum + (selected ? 1 : 0);
|
|
26046
26054
|
}, 0);
|
|
@@ -26050,6 +26058,17 @@ function scoreRadio(userInput, rubric, strings) {
|
|
|
26050
26058
|
message: null
|
|
26051
26059
|
};
|
|
26052
26060
|
}
|
|
26061
|
+
return null;
|
|
26062
|
+
}
|
|
26063
|
+
|
|
26064
|
+
function scoreRadio(userInput, rubric, strings) {
|
|
26065
|
+
const validationError = validateRadio(userInput);
|
|
26066
|
+
if (validationError) {
|
|
26067
|
+
return validationError;
|
|
26068
|
+
}
|
|
26069
|
+
const numSelected = userInput.choicesSelected.reduce((sum, selected) => {
|
|
26070
|
+
return sum + (selected ? 1 : 0);
|
|
26071
|
+
}, 0);
|
|
26053
26072
|
const numCorrect = rubric.choices.reduce((sum, currentChoice) => {
|
|
26054
26073
|
return currentChoice.correct ? sum + 1 : sum;
|
|
26055
26074
|
}, 0);
|
|
@@ -26426,6 +26445,7 @@ Radio$1.defaultProps = {
|
|
|
26426
26445
|
showSolutions: "none"
|
|
26427
26446
|
};
|
|
26428
26447
|
|
|
26448
|
+
const _excluded$5 = ["noneOfTheAbove"];
|
|
26429
26449
|
const {
|
|
26430
26450
|
shuffle: shuffle$2,
|
|
26431
26451
|
random
|
|
@@ -26514,17 +26534,15 @@ const transform = (widgetOptions, strings, problemNum) => {
|
|
|
26514
26534
|
};
|
|
26515
26535
|
const propUpgrades$1 = {
|
|
26516
26536
|
"1": v0props => {
|
|
26517
|
-
|
|
26518
|
-
|
|
26519
|
-
|
|
26520
|
-
|
|
26521
|
-
|
|
26522
|
-
} else {
|
|
26537
|
+
const {
|
|
26538
|
+
noneOfTheAbove
|
|
26539
|
+
} = v0props,
|
|
26540
|
+
rest = _objectWithoutPropertiesLoose(v0props, _excluded$5);
|
|
26541
|
+
if (noneOfTheAbove) {
|
|
26523
26542
|
throw new Error("radio widget v0 no longer supports auto noneOfTheAbove");
|
|
26524
26543
|
}
|
|
26525
|
-
return
|
|
26526
|
-
|
|
26527
|
-
hasNoneOfTheAbove: hasNoneOfTheAbove
|
|
26544
|
+
return _extends({}, rest, {
|
|
26545
|
+
hasNoneOfTheAbove: false
|
|
26528
26546
|
});
|
|
26529
26547
|
}
|
|
26530
26548
|
};
|
|
@@ -26562,23 +26580,36 @@ const getPromptJSON$n = (renderProps, userInput) => {
|
|
|
26562
26580
|
};
|
|
26563
26581
|
};
|
|
26564
26582
|
|
|
26565
|
-
|
|
26566
|
-
|
|
26567
|
-
|
|
26568
|
-
|
|
26569
|
-
|
|
26570
|
-
|
|
26571
|
-
|
|
26572
|
-
|
|
26573
|
-
|
|
26574
|
-
|
|
26575
|
-
|
|
26576
|
-
if (!completed) {
|
|
26583
|
+
/**
|
|
26584
|
+
* Checks userInput from the categorizer widget to see if the user has selected
|
|
26585
|
+
* a category for each item.
|
|
26586
|
+
* @param userInput - The user's input corresponding to an array of indices that
|
|
26587
|
+
* represent the selected category for each row/item.
|
|
26588
|
+
* @param validationData - An array of strings corresponding to each row/item
|
|
26589
|
+
* @param strings - Used to provide a validation message
|
|
26590
|
+
*/
|
|
26591
|
+
function validateCategorizer(userInput, validationData, strings) {
|
|
26592
|
+
const incomplete = validationData.items.some((_, i) => userInput.values[i] == null);
|
|
26593
|
+
if (incomplete) {
|
|
26577
26594
|
return {
|
|
26578
26595
|
type: "invalid",
|
|
26579
26596
|
message: strings.invalidSelection
|
|
26580
26597
|
};
|
|
26581
26598
|
}
|
|
26599
|
+
return null;
|
|
26600
|
+
}
|
|
26601
|
+
|
|
26602
|
+
function scoreCategorizer(userInput, scoringData, strings) {
|
|
26603
|
+
const validationError = validateCategorizer(userInput, scoringData, strings);
|
|
26604
|
+
if (validationError) {
|
|
26605
|
+
return validationError;
|
|
26606
|
+
}
|
|
26607
|
+
let allCorrect = true;
|
|
26608
|
+
scoringData.values.forEach((value, i) => {
|
|
26609
|
+
if (userInput.values[i] !== value) {
|
|
26610
|
+
allCorrect = false;
|
|
26611
|
+
}
|
|
26612
|
+
});
|
|
26582
26613
|
return {
|
|
26583
26614
|
type: "points",
|
|
26584
26615
|
earned: allCorrect ? 1 : 0,
|
|
@@ -27124,15 +27155,26 @@ const getPromptJSON$k = (renderProps, userInput) => {
|
|
|
27124
27155
|
};
|
|
27125
27156
|
};
|
|
27126
27157
|
|
|
27127
|
-
|
|
27128
|
-
|
|
27129
|
-
|
|
27158
|
+
/**
|
|
27159
|
+
* Checks if the user has selected an item from the dropdown before scoring.
|
|
27160
|
+
* This is shown with a userInput value / index other than 0.
|
|
27161
|
+
*/
|
|
27162
|
+
function validateDropdown(userInput) {
|
|
27163
|
+
if (userInput.value === 0) {
|
|
27130
27164
|
return {
|
|
27131
27165
|
type: "invalid",
|
|
27132
27166
|
message: null
|
|
27133
27167
|
};
|
|
27134
27168
|
}
|
|
27135
|
-
|
|
27169
|
+
return null;
|
|
27170
|
+
}
|
|
27171
|
+
|
|
27172
|
+
function scoreDropdown(userInput, rubric) {
|
|
27173
|
+
const validationError = validateDropdown(userInput);
|
|
27174
|
+
if (validationError) {
|
|
27175
|
+
return validationError;
|
|
27176
|
+
}
|
|
27177
|
+
const correct = rubric.choices[userInput.value - 1].correct;
|
|
27136
27178
|
return {
|
|
27137
27179
|
type: "points",
|
|
27138
27180
|
earned: correct ? 1 : 0,
|
|
@@ -27181,23 +27223,40 @@ class Dropdown extends React.Component {
|
|
|
27181
27223
|
value: String(i + 1),
|
|
27182
27224
|
label: choice
|
|
27183
27225
|
}))];
|
|
27184
|
-
return /*#__PURE__*/React.createElement(
|
|
27185
|
-
|
|
27186
|
-
|
|
27226
|
+
return /*#__PURE__*/React.createElement(UniqueIDProvider, {
|
|
27227
|
+
scope: "dropdown-widget",
|
|
27228
|
+
mockOnFirstRender: true
|
|
27229
|
+
}, ids => /*#__PURE__*/React.createElement(View
|
|
27230
|
+
// NOTE(jared): These are required to prevent weird behavior
|
|
27231
|
+
// When there's a dropdown in a zoomable table.
|
|
27232
|
+
, {
|
|
27187
27233
|
onClick: e => {
|
|
27188
27234
|
e.stopPropagation();
|
|
27189
27235
|
},
|
|
27190
27236
|
onTouchStart: e => {
|
|
27191
27237
|
e.stopPropagation();
|
|
27192
27238
|
}
|
|
27193
|
-
}, /*#__PURE__*/React.createElement(
|
|
27239
|
+
}, this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelLarge, {
|
|
27240
|
+
tag: "label",
|
|
27241
|
+
id: ids.get("dropdown-label")
|
|
27242
|
+
}, this.props.visibleLabel), /*#__PURE__*/React.createElement(SingleSelect, {
|
|
27243
|
+
id: ids.get("dropdown"),
|
|
27194
27244
|
placeholder: "",
|
|
27195
27245
|
onChange: value => this._handleChange(parseInt(value)),
|
|
27196
27246
|
selectedValue: String(this.props.selected),
|
|
27197
|
-
disabled: this.props.apiOptions.readOnly
|
|
27198
|
-
|
|
27247
|
+
disabled: this.props.apiOptions.readOnly,
|
|
27248
|
+
"aria-label": this.props.ariaLabel || this.context.strings.selectAnAnswer,
|
|
27249
|
+
"aria-labelledby": ids.get("dropdown-label")
|
|
27250
|
+
// This is currently necessary for SRs to read the labels properly.
|
|
27251
|
+
// However, WB is working on a change to add the "combobox" role to
|
|
27252
|
+
// all dropdowns.
|
|
27253
|
+
// See https://khanacademy.atlassian.net/browse/WB-1671
|
|
27254
|
+
,
|
|
27255
|
+
role: "combobox"
|
|
27256
|
+
}, children)));
|
|
27199
27257
|
}
|
|
27200
27258
|
}
|
|
27259
|
+
Dropdown.contextType = PerseusI18nContext;
|
|
27201
27260
|
Dropdown.defaultProps = {
|
|
27202
27261
|
choices: [],
|
|
27203
27262
|
selected: 0,
|
|
@@ -27207,6 +27266,8 @@ Dropdown.defaultProps = {
|
|
|
27207
27266
|
const optionsTransform = widgetOptions => {
|
|
27208
27267
|
return {
|
|
27209
27268
|
placeholder: widgetOptions.placeholder,
|
|
27269
|
+
visibleLabel: widgetOptions.visibleLabel,
|
|
27270
|
+
ariaLabel: widgetOptions.ariaLabel,
|
|
27210
27271
|
choices: widgetOptions.choices.map(choice => choice.content)
|
|
27211
27272
|
};
|
|
27212
27273
|
};
|
|
@@ -27519,8 +27580,6 @@ const getNextState = (currentState, answerable) => {
|
|
|
27519
27580
|
}
|
|
27520
27581
|
};
|
|
27521
27582
|
|
|
27522
|
-
// exports has no 'transform'
|
|
27523
|
-
|
|
27524
27583
|
// A Graded Group is more or less a Group widget that displays a check
|
|
27525
27584
|
// answer button below the rendered content. When clicked, the widget grades
|
|
27526
27585
|
// the stuff inside and displays feedback about whether the inputted answer was
|
|
@@ -28184,7 +28243,6 @@ const getPromptJSON$g = (renderProps, userInput) => {
|
|
|
28184
28243
|
};
|
|
28185
28244
|
};
|
|
28186
28245
|
|
|
28187
|
-
/* eslint-disable one-var */
|
|
28188
28246
|
// @ts-expect-error - TS2339 - Property 'Plot' does not exist on type 'typeof Graphie'.
|
|
28189
28247
|
const Plot$1 = Graphie.Plot;
|
|
28190
28248
|
const DEFAULT_BACKGROUND_IMAGE = {
|
|
@@ -28285,14 +28343,14 @@ const Linear = _.extend({}, PlotDefaults, {
|
|
|
28285
28343
|
return [m, b];
|
|
28286
28344
|
},
|
|
28287
28345
|
getFunctionForCoeffs: function (coeffs, x) {
|
|
28288
|
-
const m = coeffs[0]
|
|
28289
|
-
|
|
28346
|
+
const m = coeffs[0];
|
|
28347
|
+
const b = coeffs[1];
|
|
28290
28348
|
return m * x + b;
|
|
28291
28349
|
},
|
|
28292
28350
|
getEquationString: function (coords) {
|
|
28293
28351
|
const coeffs = this.getCoefficients(coords);
|
|
28294
|
-
const m = coeffs[0]
|
|
28295
|
-
|
|
28352
|
+
const m = coeffs[0];
|
|
28353
|
+
const b = coeffs[1];
|
|
28296
28354
|
return "y = " + m.toFixed(3) + "x + " + b.toFixed(3);
|
|
28297
28355
|
}
|
|
28298
28356
|
});
|
|
@@ -28316,9 +28374,9 @@ const Quadratic = _.extend({}, PlotDefaults, {
|
|
|
28316
28374
|
return [a, b, c];
|
|
28317
28375
|
},
|
|
28318
28376
|
getFunctionForCoeffs: function (coeffs, x) {
|
|
28319
|
-
const a = coeffs[0]
|
|
28320
|
-
|
|
28321
|
-
|
|
28377
|
+
const a = coeffs[0];
|
|
28378
|
+
const b = coeffs[1];
|
|
28379
|
+
const c = coeffs[2];
|
|
28322
28380
|
return (a * x + b) * x + c;
|
|
28323
28381
|
},
|
|
28324
28382
|
getPropsForCoeffs: function (coeffs) {
|
|
@@ -28330,9 +28388,9 @@ const Quadratic = _.extend({}, PlotDefaults, {
|
|
|
28330
28388
|
},
|
|
28331
28389
|
getEquationString: function (coords) {
|
|
28332
28390
|
const coeffs = this.getCoefficients(coords);
|
|
28333
|
-
const a = coeffs[0]
|
|
28334
|
-
|
|
28335
|
-
|
|
28391
|
+
const a = coeffs[0];
|
|
28392
|
+
const b = coeffs[1];
|
|
28393
|
+
const c = coeffs[2];
|
|
28336
28394
|
return "y = " + a.toFixed(3) + "x^2 + " + b.toFixed(3) + "x + " + c.toFixed(3);
|
|
28337
28395
|
}
|
|
28338
28396
|
});
|
|
@@ -28351,10 +28409,10 @@ const Sinusoid = _.extend({}, PlotDefaults, {
|
|
|
28351
28409
|
return [a, b, c, d];
|
|
28352
28410
|
},
|
|
28353
28411
|
getFunctionForCoeffs: function (coeffs, x) {
|
|
28354
|
-
const a = coeffs[0]
|
|
28355
|
-
|
|
28356
|
-
|
|
28357
|
-
|
|
28412
|
+
const a = coeffs[0];
|
|
28413
|
+
const b = coeffs[1];
|
|
28414
|
+
const c = coeffs[2];
|
|
28415
|
+
const d = coeffs[3];
|
|
28358
28416
|
return a * Math.sin(b * x - c) + d;
|
|
28359
28417
|
},
|
|
28360
28418
|
getPropsForCoeffs: function (coeffs) {
|
|
@@ -28367,10 +28425,10 @@ const Sinusoid = _.extend({}, PlotDefaults, {
|
|
|
28367
28425
|
},
|
|
28368
28426
|
getEquationString: function (coords) {
|
|
28369
28427
|
const coeffs = this.getCoefficients(coords);
|
|
28370
|
-
const a = coeffs[0]
|
|
28371
|
-
|
|
28372
|
-
|
|
28373
|
-
|
|
28428
|
+
const a = coeffs[0];
|
|
28429
|
+
const b = coeffs[1];
|
|
28430
|
+
const c = coeffs[2];
|
|
28431
|
+
const d = coeffs[3];
|
|
28374
28432
|
return "y = " + a.toFixed(3) + " sin(" + b.toFixed(3) + "x - " + c.toFixed(3) + ") + " + d.toFixed(3);
|
|
28375
28433
|
},
|
|
28376
28434
|
areEqual: function (coeffs1, coeffs2) {
|
|
@@ -28390,18 +28448,18 @@ const Tangent = _.extend({}, PlotDefaults, {
|
|
|
28390
28448
|
return [a, b, c, d];
|
|
28391
28449
|
},
|
|
28392
28450
|
getFunctionForCoeffs: function (coeffs, x) {
|
|
28393
|
-
const a = coeffs[0]
|
|
28394
|
-
|
|
28395
|
-
|
|
28396
|
-
|
|
28451
|
+
const a = coeffs[0];
|
|
28452
|
+
const b = coeffs[1];
|
|
28453
|
+
const c = coeffs[2];
|
|
28454
|
+
const d = coeffs[3];
|
|
28397
28455
|
return a * Math.tan(b * x - c) + d;
|
|
28398
28456
|
},
|
|
28399
28457
|
getEquationString: function (coords) {
|
|
28400
28458
|
const coeffs = this.getCoefficients(coords);
|
|
28401
|
-
const a = coeffs[0]
|
|
28402
|
-
|
|
28403
|
-
|
|
28404
|
-
|
|
28459
|
+
const a = coeffs[0];
|
|
28460
|
+
const b = coeffs[1];
|
|
28461
|
+
const c = coeffs[2];
|
|
28462
|
+
const d = coeffs[3];
|
|
28405
28463
|
return "y = " + a.toFixed(3) + " sin(" + b.toFixed(3) + "x - " + c.toFixed(3) + ") + " + d.toFixed(3);
|
|
28406
28464
|
},
|
|
28407
28465
|
areEqual: function (coeffs1, coeffs2) {
|
|
@@ -28460,9 +28518,9 @@ const Exponential = _.extend({}, PlotDefaults, {
|
|
|
28460
28518
|
return [a, b, c];
|
|
28461
28519
|
},
|
|
28462
28520
|
getFunctionForCoeffs: function (coeffs, x) {
|
|
28463
|
-
const a = coeffs[0]
|
|
28464
|
-
|
|
28465
|
-
|
|
28521
|
+
const a = coeffs[0];
|
|
28522
|
+
const b = coeffs[1];
|
|
28523
|
+
const c = coeffs[2];
|
|
28466
28524
|
return a * Math.exp(b * x) + c;
|
|
28467
28525
|
},
|
|
28468
28526
|
getEquationString: function (coords, asymptote) {
|
|
@@ -28470,9 +28528,9 @@ const Exponential = _.extend({}, PlotDefaults, {
|
|
|
28470
28528
|
return null;
|
|
28471
28529
|
}
|
|
28472
28530
|
const coeffs = this.getCoefficients(coords, asymptote);
|
|
28473
|
-
const a = coeffs[0]
|
|
28474
|
-
|
|
28475
|
-
|
|
28531
|
+
const a = coeffs[0];
|
|
28532
|
+
const b = coeffs[1];
|
|
28533
|
+
const c = coeffs[2];
|
|
28476
28534
|
return "y = " + a.toFixed(3) + "e^(" + b.toFixed(3) + "x) + " + c.toFixed(3);
|
|
28477
28535
|
}
|
|
28478
28536
|
});
|
|
@@ -28517,9 +28575,9 @@ const Logarithm = _.extend({}, PlotDefaults, {
|
|
|
28517
28575
|
}
|
|
28518
28576
|
},
|
|
28519
28577
|
getFunctionForCoeffs: function (coeffs, x, asymptote) {
|
|
28520
|
-
const a = coeffs[0]
|
|
28521
|
-
|
|
28522
|
-
|
|
28578
|
+
const a = coeffs[0];
|
|
28579
|
+
const b = coeffs[1];
|
|
28580
|
+
const c = coeffs[2];
|
|
28523
28581
|
return a * Math.log(b * x + c);
|
|
28524
28582
|
},
|
|
28525
28583
|
getEquationString: function (coords, asymptote) {
|
|
@@ -28527,9 +28585,9 @@ const Logarithm = _.extend({}, PlotDefaults, {
|
|
|
28527
28585
|
return null;
|
|
28528
28586
|
}
|
|
28529
28587
|
const coeffs = this.getCoefficients(coords, asymptote);
|
|
28530
|
-
const a = coeffs[0]
|
|
28531
|
-
|
|
28532
|
-
|
|
28588
|
+
const a = coeffs[0];
|
|
28589
|
+
const b = coeffs[1];
|
|
28590
|
+
const c = coeffs[2];
|
|
28533
28591
|
return "y = ln(" + a.toFixed(3) + "x + " + b.toFixed(3) + ") + " + c.toFixed(3);
|
|
28534
28592
|
}
|
|
28535
28593
|
});
|
|
@@ -28553,16 +28611,16 @@ const AbsoluteValue = _.extend({}, PlotDefaults, {
|
|
|
28553
28611
|
return [m, horizontalOffset, verticalOffset];
|
|
28554
28612
|
},
|
|
28555
28613
|
getFunctionForCoeffs: function (coeffs, x) {
|
|
28556
|
-
const m = coeffs[0]
|
|
28557
|
-
|
|
28558
|
-
|
|
28614
|
+
const m = coeffs[0];
|
|
28615
|
+
const horizontalOffset = coeffs[1];
|
|
28616
|
+
const verticalOffset = coeffs[2];
|
|
28559
28617
|
return m * Math.abs(x - horizontalOffset) + verticalOffset;
|
|
28560
28618
|
},
|
|
28561
28619
|
getEquationString: function (coords) {
|
|
28562
28620
|
const coeffs = this.getCoefficients(coords);
|
|
28563
|
-
const m = coeffs[0]
|
|
28564
|
-
|
|
28565
|
-
|
|
28621
|
+
const m = coeffs[0];
|
|
28622
|
+
const horizontalOffset = coeffs[1];
|
|
28623
|
+
const verticalOffset = coeffs[2];
|
|
28566
28624
|
return "y = " + m.toFixed(3) + "| x - " + horizontalOffset.toFixed(3) + "| + " + verticalOffset.toFixed(3);
|
|
28567
28625
|
}
|
|
28568
28626
|
});
|
|
@@ -30305,6 +30363,7 @@ function numSteps$1(range, step) {
|
|
|
30305
30363
|
class Graph extends React.Component {
|
|
30306
30364
|
constructor(...args) {
|
|
30307
30365
|
super(...args);
|
|
30366
|
+
this.graphieDivRef = /*#__PURE__*/React.createRef();
|
|
30308
30367
|
this.protractor = void 0;
|
|
30309
30368
|
this.ruler = void 0;
|
|
30310
30369
|
this._graphie = void 0;
|
|
@@ -30348,9 +30407,7 @@ class Graph extends React.Component {
|
|
|
30348
30407
|
if (this._hasSetupGraphieThisUpdate) {
|
|
30349
30408
|
return;
|
|
30350
30409
|
}
|
|
30351
|
-
|
|
30352
|
-
// eslint-disable-next-line react/no-string-refs
|
|
30353
|
-
const graphieDiv = ReactDOM__default.findDOMNode(this.refs.graphieDiv);
|
|
30410
|
+
const graphieDiv = this.graphieDivRef.current;
|
|
30354
30411
|
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'empty' does not exist on type 'JQueryStatic'.
|
|
30355
30412
|
$(graphieDiv).empty();
|
|
30356
30413
|
|
|
@@ -30558,7 +30615,7 @@ class Graph extends React.Component {
|
|
|
30558
30615
|
onClick: this.onClick
|
|
30559
30616
|
}, image, /*#__PURE__*/React.createElement("div", {
|
|
30560
30617
|
className: "graphie",
|
|
30561
|
-
ref:
|
|
30618
|
+
ref: this.graphieDivRef
|
|
30562
30619
|
}));
|
|
30563
30620
|
}
|
|
30564
30621
|
}
|
|
@@ -31646,6 +31703,7 @@ class InfoTip extends React.Component {
|
|
|
31646
31703
|
class MultiButtonGroup extends React.Component {
|
|
31647
31704
|
constructor(...args) {
|
|
31648
31705
|
super(...args);
|
|
31706
|
+
this.buttonContainerRef = /*#__PURE__*/React.createRef();
|
|
31649
31707
|
this.toggleSelect = newValue => {
|
|
31650
31708
|
const values = (this.props.values || []).slice(0);
|
|
31651
31709
|
const allowEmpty = this.props.allowEmpty;
|
|
@@ -31662,9 +31720,8 @@ class MultiButtonGroup extends React.Component {
|
|
|
31662
31720
|
};
|
|
31663
31721
|
}
|
|
31664
31722
|
focus() {
|
|
31665
|
-
var
|
|
31666
|
-
|
|
31667
|
-
(_ReactDOM$findDOMNode = ReactDOM.findDOMNode(this)) == null || _ReactDOM$findDOMNode.focus();
|
|
31723
|
+
var _this$buttonContainer;
|
|
31724
|
+
(_this$buttonContainer = this.buttonContainerRef.current) == null || _this$buttonContainer.focus();
|
|
31668
31725
|
return true;
|
|
31669
31726
|
}
|
|
31670
31727
|
render() {
|
|
@@ -31685,7 +31742,8 @@ class MultiButtonGroup extends React.Component {
|
|
|
31685
31742
|
display: "inline-block"
|
|
31686
31743
|
};
|
|
31687
31744
|
return /*#__PURE__*/React.createElement("div", {
|
|
31688
|
-
style: outerStyle
|
|
31745
|
+
style: outerStyle,
|
|
31746
|
+
ref: this.buttonContainerRef
|
|
31689
31747
|
}, buttons);
|
|
31690
31748
|
}
|
|
31691
31749
|
}
|
|
@@ -31726,7 +31784,7 @@ const styles$e = StyleSheet.create({
|
|
|
31726
31784
|
}
|
|
31727
31785
|
});
|
|
31728
31786
|
|
|
31729
|
-
const _excluded$
|
|
31787
|
+
const _excluded$4 = ["onFormatChange", "checkValidity", "useArrowKeys"];
|
|
31730
31788
|
const {
|
|
31731
31789
|
firstNumericalParse,
|
|
31732
31790
|
captureScratchpadTouchStart
|
|
@@ -31756,22 +31814,25 @@ const getNumericFormat = KhanMath.getNumericFormat;
|
|
|
31756
31814
|
class NumberInput extends React.Component {
|
|
31757
31815
|
constructor(...args) {
|
|
31758
31816
|
super(...args);
|
|
31817
|
+
this.inputRef = /*#__PURE__*/React.createRef();
|
|
31759
31818
|
this.state = {
|
|
31760
31819
|
format: this.props.format
|
|
31761
31820
|
};
|
|
31821
|
+
this._getInput = () => {
|
|
31822
|
+
if (!this.inputRef.current) {
|
|
31823
|
+
throw new PerseusError("Input ref accessed before set", Errors.Internal);
|
|
31824
|
+
}
|
|
31825
|
+
return this.inputRef.current;
|
|
31826
|
+
};
|
|
31762
31827
|
/* Return the current "value" of this input
|
|
31763
31828
|
* If empty, it returns the placeholder (if it is a number) or null
|
|
31764
31829
|
*/
|
|
31765
31830
|
this.getValue = () => {
|
|
31766
|
-
return this.parseInputValue(
|
|
31767
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
31768
|
-
ReactDOM__default.findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
31769
|
-
);
|
|
31831
|
+
return this.parseInputValue(this._getInput().value);
|
|
31770
31832
|
};
|
|
31771
31833
|
/* Return the current string value of this input */
|
|
31772
31834
|
this.getStringValue = () => {
|
|
31773
|
-
|
|
31774
|
-
return ReactDOM__default.findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
31835
|
+
return this._getInput().toString();
|
|
31775
31836
|
};
|
|
31776
31837
|
this.parseInputValue = value => {
|
|
31777
31838
|
if (value === "") {
|
|
@@ -31783,26 +31844,21 @@ class NumberInput extends React.Component {
|
|
|
31783
31844
|
};
|
|
31784
31845
|
/* Set text input focus to this input */
|
|
31785
31846
|
this.focus = () => {
|
|
31786
|
-
|
|
31787
|
-
ReactDOM__default.findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
31847
|
+
this._getInput().focus();
|
|
31788
31848
|
this._handleFocus();
|
|
31789
31849
|
};
|
|
31790
31850
|
this.blur = () => {
|
|
31791
|
-
|
|
31792
|
-
ReactDOM__default.findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
31851
|
+
this._getInput().blur();
|
|
31793
31852
|
this._handleBlur();
|
|
31794
31853
|
};
|
|
31795
31854
|
this.setSelectionRange = (selectionStart, selectionEnd) => {
|
|
31796
|
-
|
|
31797
|
-
ReactDOM__default.findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
31855
|
+
this._getInput().setSelectionRange(selectionStart, selectionEnd);
|
|
31798
31856
|
};
|
|
31799
31857
|
this.getSelectionStart = () => {
|
|
31800
|
-
|
|
31801
|
-
return ReactDOM__default.findDOMNode(this).selectionStart;
|
|
31858
|
+
return this._getInput().selectionStart;
|
|
31802
31859
|
};
|
|
31803
31860
|
this.getSelectionEnd = () => {
|
|
31804
|
-
|
|
31805
|
-
return ReactDOM__default.findDOMNode(this).selectionEnd;
|
|
31861
|
+
return this._getInput().selectionEnd;
|
|
31806
31862
|
};
|
|
31807
31863
|
this._checkValidity = value => {
|
|
31808
31864
|
if (value == null) {
|
|
@@ -31862,9 +31918,7 @@ class NumberInput extends React.Component {
|
|
|
31862
31918
|
}
|
|
31863
31919
|
};
|
|
31864
31920
|
this._setValue = (val, format) => {
|
|
31865
|
-
|
|
31866
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
31867
|
-
$(ReactDOM__default.findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
31921
|
+
this._getInput().value = toNumericString(val, format);
|
|
31868
31922
|
};
|
|
31869
31923
|
}
|
|
31870
31924
|
componentDidUpdate(prevProps) {
|
|
@@ -31884,13 +31938,11 @@ class NumberInput extends React.Component {
|
|
|
31884
31938
|
classes = classes + " " + this.props.className;
|
|
31885
31939
|
}
|
|
31886
31940
|
const _this$props = this.props,
|
|
31887
|
-
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$
|
|
31941
|
+
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$4);
|
|
31888
31942
|
return /*#__PURE__*/React.createElement("input", _extends({}, restProps, {
|
|
31889
31943
|
className: classes,
|
|
31890
|
-
type: "text"
|
|
31891
|
-
|
|
31892
|
-
,
|
|
31893
|
-
ref: "input",
|
|
31944
|
+
type: "text",
|
|
31945
|
+
ref: this.inputRef,
|
|
31894
31946
|
onChange: this._handleChange,
|
|
31895
31947
|
onFocus: this._handleFocus,
|
|
31896
31948
|
onBlur: this._handleBlur,
|
|
@@ -32811,12 +32863,12 @@ const MafsCssTransformWrapper = ({
|
|
|
32811
32863
|
}
|
|
32812
32864
|
}, children);
|
|
32813
32865
|
|
|
32814
|
-
const _excluded$
|
|
32866
|
+
const _excluded$3 = ["children"];
|
|
32815
32867
|
const TextLabel = _ref => {
|
|
32816
32868
|
let {
|
|
32817
32869
|
children
|
|
32818
32870
|
} = _ref,
|
|
32819
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
32871
|
+
rest = _objectWithoutPropertiesLoose(_ref, _excluded$3);
|
|
32820
32872
|
return /*#__PURE__*/React__default.createElement(Text$1, _extends({
|
|
32821
32873
|
size: 16,
|
|
32822
32874
|
svgTextProps: {
|
|
@@ -33397,15 +33449,18 @@ function useControlPoint(params) {
|
|
|
33397
33449
|
} = useGraphConfig();
|
|
33398
33450
|
const {
|
|
33399
33451
|
point,
|
|
33400
|
-
|
|
33452
|
+
ariaDescribedBy,
|
|
33453
|
+
ariaLabel,
|
|
33454
|
+
ariaLive = "polite",
|
|
33401
33455
|
color,
|
|
33402
|
-
cursor,
|
|
33403
33456
|
constrain = p => snap(snapStep, p),
|
|
33457
|
+
cursor,
|
|
33458
|
+
forwardedRef = noop$1,
|
|
33459
|
+
sequenceNumber = 1,
|
|
33404
33460
|
onMove = noop$1,
|
|
33405
33461
|
onClick = noop$1,
|
|
33406
33462
|
onFocus = noop$1,
|
|
33407
|
-
onBlur = noop$1
|
|
33408
|
-
forwardedRef = noop$1
|
|
33463
|
+
onBlur = noop$1
|
|
33409
33464
|
} = params;
|
|
33410
33465
|
const {
|
|
33411
33466
|
strings,
|
|
@@ -33428,6 +33483,13 @@ function useControlPoint(params) {
|
|
|
33428
33483
|
onMove,
|
|
33429
33484
|
constrainKeyboardMovement: constrain
|
|
33430
33485
|
});
|
|
33486
|
+
|
|
33487
|
+
// if custom aria label is not provided, will use default of sequence number and point coordinates
|
|
33488
|
+
const pointAriaLabel = ariaLabel || strings.srPointAtCoordinates({
|
|
33489
|
+
num: sequenceNumber,
|
|
33490
|
+
x: srFormatNumber(point[X], locale),
|
|
33491
|
+
y: srFormatNumber(point[Y], locale)
|
|
33492
|
+
});
|
|
33431
33493
|
useLayoutEffect(() => {
|
|
33432
33494
|
setForwardedRef(forwardedRef, focusableHandleRef.current);
|
|
33433
33495
|
}, [forwardedRef]);
|
|
@@ -33437,15 +33499,9 @@ function useControlPoint(params) {
|
|
|
33437
33499
|
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
33438
33500
|
ref: focusableHandleRef,
|
|
33439
33501
|
role: "button",
|
|
33440
|
-
"aria-
|
|
33441
|
-
|
|
33442
|
-
|
|
33443
|
-
y: srFormatNumber(point[Y], locale)
|
|
33444
|
-
})
|
|
33445
|
-
// aria-live="assertive" causes the new location of the point to be
|
|
33446
|
-
// announced immediately on move.
|
|
33447
|
-
,
|
|
33448
|
-
"aria-live": "assertive",
|
|
33502
|
+
"aria-describedby": ariaDescribedBy,
|
|
33503
|
+
"aria-label": pointAriaLabel,
|
|
33504
|
+
"aria-live": ariaLive,
|
|
33449
33505
|
onFocus: event => {
|
|
33450
33506
|
onFocus(event);
|
|
33451
33507
|
setFocused(true);
|
|
@@ -36451,7 +36507,7 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
36451
36507
|
});
|
|
36452
36508
|
|
|
36453
36509
|
const eq$1 = Util.eq;
|
|
36454
|
-
const deepEq$
|
|
36510
|
+
const deepEq$3 = Util.deepEq;
|
|
36455
36511
|
function scoreInteractiveGraph(userInput, rubric) {
|
|
36456
36512
|
// None-type graphs are not graded
|
|
36457
36513
|
if (userInput.type === "none" && rubric.correct.type === "none") {
|
|
@@ -36501,7 +36557,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36501
36557
|
// If the parabola coefficients match, it's correct.
|
|
36502
36558
|
const guessCoeffs = getQuadraticCoefficients(userInput.coords);
|
|
36503
36559
|
const correctCoeffs = getQuadraticCoefficients(rubric.correct.coords);
|
|
36504
|
-
if (deepEq$
|
|
36560
|
+
if (deepEq$3(guessCoeffs, correctCoeffs)) {
|
|
36505
36561
|
return {
|
|
36506
36562
|
type: "points",
|
|
36507
36563
|
earned: 1,
|
|
@@ -36515,7 +36571,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36515
36571
|
const canonicalGuessCoeffs = canonicalSineCoefficients$1(guessCoeffs);
|
|
36516
36572
|
const canonicalCorrectCoeffs = canonicalSineCoefficients$1(correctCoeffs);
|
|
36517
36573
|
// If the canonical coefficients match, it's correct.
|
|
36518
|
-
if (deepEq$
|
|
36574
|
+
if (deepEq$3(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
|
|
36519
36575
|
return {
|
|
36520
36576
|
type: "points",
|
|
36521
36577
|
earned: 1,
|
|
@@ -36524,7 +36580,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36524
36580
|
};
|
|
36525
36581
|
}
|
|
36526
36582
|
} else if (userInput.type === "circle" && rubric.correct.type === "circle") {
|
|
36527
|
-
if (deepEq$
|
|
36583
|
+
if (deepEq$3(userInput.center, rubric.correct.center) && eq$1(userInput.radius, rubric.correct.radius)) {
|
|
36528
36584
|
return {
|
|
36529
36585
|
type: "points",
|
|
36530
36586
|
earned: 1,
|
|
@@ -36546,7 +36602,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36546
36602
|
guess == null || guess.sort();
|
|
36547
36603
|
// @ts-expect-error - TS2339 - Property 'sort' does not exist on type 'readonly Coord[]'.
|
|
36548
36604
|
correct.sort();
|
|
36549
|
-
if (deepEq$
|
|
36605
|
+
if (deepEq$3(guess, correct)) {
|
|
36550
36606
|
return {
|
|
36551
36607
|
type: "points",
|
|
36552
36608
|
earned: 1,
|
|
@@ -36568,7 +36624,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36568
36624
|
/* exact */
|
|
36569
36625
|
guess.sort();
|
|
36570
36626
|
correct.sort();
|
|
36571
|
-
match = deepEq$
|
|
36627
|
+
match = deepEq$3(guess, correct);
|
|
36572
36628
|
}
|
|
36573
36629
|
if (match) {
|
|
36574
36630
|
return {
|
|
@@ -36583,7 +36639,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36583
36639
|
let correct = Util.deepClone(rubric.correct.coords);
|
|
36584
36640
|
guess = _.invoke(guess, "sort").sort();
|
|
36585
36641
|
correct = _.invoke(correct, "sort").sort();
|
|
36586
|
-
if (deepEq$
|
|
36642
|
+
if (deepEq$3(guess, correct)) {
|
|
36587
36643
|
return {
|
|
36588
36644
|
type: "points",
|
|
36589
36645
|
earned: 1,
|
|
@@ -36594,7 +36650,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36594
36650
|
} else if (userInput.type === "ray" && rubric.correct.type === "ray" && userInput.coords != null) {
|
|
36595
36651
|
const guess = userInput.coords;
|
|
36596
36652
|
const correct = rubric.correct.coords;
|
|
36597
|
-
if (deepEq$
|
|
36653
|
+
if (deepEq$3(guess[0], correct[0]) && collinear(correct[0], correct[1], guess[1])) {
|
|
36598
36654
|
return {
|
|
36599
36655
|
type: "points",
|
|
36600
36656
|
earned: 1,
|
|
@@ -36621,7 +36677,7 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
36621
36677
|
/* exact */
|
|
36622
36678
|
match =
|
|
36623
36679
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
36624
|
-
deepEq$
|
|
36680
|
+
deepEq$3(guess[1], correct[1]) &&
|
|
36625
36681
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
36626
36682
|
collinear(correct[1], correct[0], guess[0]) &&
|
|
36627
36683
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
@@ -40795,6 +40851,7 @@ const getPromptJSON$7 = () => {
|
|
|
40795
40851
|
return getUnsupportedPromptJSON("measurer");
|
|
40796
40852
|
};
|
|
40797
40853
|
|
|
40854
|
+
const _excluded$2 = ["imageUrl", "imageTop", "imageLeft"];
|
|
40798
40855
|
const defaultImage = {
|
|
40799
40856
|
url: null,
|
|
40800
40857
|
top: 0,
|
|
@@ -40901,14 +40958,19 @@ Measurer.defaultProps = {
|
|
|
40901
40958
|
};
|
|
40902
40959
|
const propUpgrades = {
|
|
40903
40960
|
"1": v0props => {
|
|
40904
|
-
const
|
|
40961
|
+
const {
|
|
40962
|
+
imageUrl,
|
|
40963
|
+
imageTop,
|
|
40964
|
+
imageLeft
|
|
40965
|
+
} = v0props,
|
|
40966
|
+
rest = _objectWithoutPropertiesLoose(v0props, _excluded$2);
|
|
40967
|
+
return _extends({}, rest, {
|
|
40905
40968
|
image: {
|
|
40906
|
-
url:
|
|
40907
|
-
top:
|
|
40908
|
-
left:
|
|
40969
|
+
url: imageUrl,
|
|
40970
|
+
top: imageTop,
|
|
40971
|
+
left: imageLeft
|
|
40909
40972
|
}
|
|
40910
|
-
})
|
|
40911
|
-
return v1props;
|
|
40973
|
+
});
|
|
40912
40974
|
}
|
|
40913
40975
|
};
|
|
40914
40976
|
var Measurer$1 = {
|
|
@@ -42436,14 +42498,28 @@ const getPromptJSON$5 = (renderProps, userInput) => {
|
|
|
42436
42498
|
};
|
|
42437
42499
|
};
|
|
42438
42500
|
|
|
42439
|
-
|
|
42501
|
+
/**
|
|
42502
|
+
* Checks user input from the orderer widget to see if the user has started
|
|
42503
|
+
* ordering the options, making the widget scorable.
|
|
42504
|
+
* @param userInput
|
|
42505
|
+
* @see `scoreOrderer` for more details.
|
|
42506
|
+
*/
|
|
42507
|
+
function validateOrderer(userInput) {
|
|
42440
42508
|
if (userInput.current.length === 0) {
|
|
42441
42509
|
return {
|
|
42442
42510
|
type: "invalid",
|
|
42443
42511
|
message: null
|
|
42444
42512
|
};
|
|
42445
42513
|
}
|
|
42446
|
-
|
|
42514
|
+
return null;
|
|
42515
|
+
}
|
|
42516
|
+
|
|
42517
|
+
function scoreOrderer(userInput, rubric) {
|
|
42518
|
+
const validateError = validateOrderer(userInput);
|
|
42519
|
+
if (validateError) {
|
|
42520
|
+
return validateError;
|
|
42521
|
+
}
|
|
42522
|
+
const correct = _.isEqual(userInput.current, rubric.correctOptions.map(option => option.content));
|
|
42447
42523
|
return {
|
|
42448
42524
|
type: "points",
|
|
42449
42525
|
earned: correct ? 1 : 0,
|
|
@@ -42623,8 +42699,6 @@ Card.defaultProps = {
|
|
|
42623
42699
|
animating: false,
|
|
42624
42700
|
linterContext: linterContextDefault
|
|
42625
42701
|
};
|
|
42626
|
-
const NORMAL = "normal";
|
|
42627
|
-
const HORIZONTAL = "horizontal";
|
|
42628
42702
|
class Orderer extends React.Component {
|
|
42629
42703
|
constructor(...args) {
|
|
42630
42704
|
super(...args);
|
|
@@ -42771,7 +42845,7 @@ class Orderer extends React.Component {
|
|
|
42771
42845
|
};
|
|
42772
42846
|
this.findCorrectIndex = (draggable, list) => {
|
|
42773
42847
|
// Find the correct index for a card given the current cards.
|
|
42774
|
-
const isHorizontal = this.props.layout ===
|
|
42848
|
+
const isHorizontal = this.props.layout === "horizontal";
|
|
42775
42849
|
// eslint-disable-next-line react/no-string-refs
|
|
42776
42850
|
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
42777
42851
|
const $dragList = $(ReactDOM__default.findDOMNode(this.refs.dragList));
|
|
@@ -42821,28 +42895,24 @@ class Orderer extends React.Component {
|
|
|
42821
42895
|
if (draggable == null) {
|
|
42822
42896
|
return false;
|
|
42823
42897
|
}
|
|
42824
|
-
const isHorizontal = this.props.layout ===
|
|
42825
|
-
|
|
42826
|
-
|
|
42827
|
-
|
|
42828
|
-
|
|
42829
|
-
|
|
42830
|
-
|
|
42831
|
-
|
|
42832
|
-
|
|
42833
|
-
|
|
42834
|
-
|
|
42835
|
-
|
|
42836
|
-
|
|
42837
|
-
|
|
42838
|
-
|
|
42839
|
-
|
|
42840
|
-
|
|
42841
|
-
|
|
42842
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'width' does not exist on type 'JQueryStatic'.
|
|
42843
|
-
$(dragList).width();
|
|
42844
|
-
const // @ts-expect-error - TS2339 - Property 'outerWidth' does not exist on type 'JQueryStatic'.
|
|
42845
|
-
draggableWidth = $draggable.outerWidth(true);
|
|
42898
|
+
const isHorizontal = this.props.layout === "horizontal";
|
|
42899
|
+
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
42900
|
+
const $draggable = $(ReactDOM__default.findDOMNode(draggable));
|
|
42901
|
+
// eslint-disable-next-line react/no-string-refs
|
|
42902
|
+
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
42903
|
+
const $bank = $(ReactDOM__default.findDOMNode(this.refs.bank));
|
|
42904
|
+
// @ts-expect-error - TS2339 - Property 'offset' does not exist on type 'JQueryStatic'.
|
|
42905
|
+
const draggableOffset = $draggable.offset();
|
|
42906
|
+
// @ts-expect-error - TS2339 - Property 'offset' does not exist on type 'JQueryStatic'.
|
|
42907
|
+
const bankOffset = $bank.offset();
|
|
42908
|
+
// @ts-expect-error - TS2339 - Property 'outerHeight' does not exist on type 'JQueryStatic'.
|
|
42909
|
+
const draggableHeight = $draggable.outerHeight(true);
|
|
42910
|
+
// @ts-expect-error - TS2339 - Property 'outerHeight' does not exist on type 'JQueryStatic'.
|
|
42911
|
+
const bankHeight = $bank.outerHeight(true);
|
|
42912
|
+
// @ts-expect-error - TS2339 - Property 'outerWidth' does not exist on type 'JQueryStatic'.
|
|
42913
|
+
const bankWidth = $bank.outerWidth(true);
|
|
42914
|
+
// @ts-expect-error - TS2339 - Property 'outerWidth' does not exist on type 'JQueryStatic'.
|
|
42915
|
+
const draggableWidth = $draggable.outerWidth(true);
|
|
42846
42916
|
if (isHorizontal) {
|
|
42847
42917
|
return draggableOffset.top + draggableHeight / 2 < bankOffset.top + bankHeight;
|
|
42848
42918
|
}
|
|
@@ -42991,8 +43061,8 @@ Orderer.defaultProps = {
|
|
|
42991
43061
|
current: [],
|
|
42992
43062
|
options: [],
|
|
42993
43063
|
correctOptions: [],
|
|
42994
|
-
height:
|
|
42995
|
-
layout:
|
|
43064
|
+
height: "normal",
|
|
43065
|
+
layout: "horizontal",
|
|
42996
43066
|
linterContext: linterContextDefault
|
|
42997
43067
|
};
|
|
42998
43068
|
var Orderer$1 = {
|
|
@@ -43271,18 +43341,36 @@ const getPromptJSON$3 = () => {
|
|
|
43271
43341
|
};
|
|
43272
43342
|
|
|
43273
43343
|
const {
|
|
43274
|
-
deepEq: deepEq$
|
|
43344
|
+
deepEq: deepEq$2
|
|
43275
43345
|
} = Util;
|
|
43276
|
-
|
|
43277
|
-
|
|
43346
|
+
|
|
43347
|
+
/**
|
|
43348
|
+
* Checks user input to confirm it is not the same as the starting values for the graph.
|
|
43349
|
+
* This means the user has modified the graph, and the question can be scored.
|
|
43350
|
+
*
|
|
43351
|
+
* @see 'scorePlotter' for more details on scoring.
|
|
43352
|
+
*/
|
|
43353
|
+
function validatePlotter(userInput, validationData) {
|
|
43354
|
+
if (deepEq$2(userInput, validationData.starting)) {
|
|
43278
43355
|
return {
|
|
43279
43356
|
type: "invalid",
|
|
43280
43357
|
message: null
|
|
43281
43358
|
};
|
|
43282
43359
|
}
|
|
43360
|
+
return null;
|
|
43361
|
+
}
|
|
43362
|
+
|
|
43363
|
+
const {
|
|
43364
|
+
deepEq: deepEq$1
|
|
43365
|
+
} = Util;
|
|
43366
|
+
function scorePlotter(userInput, scoringData) {
|
|
43367
|
+
const validationError = validatePlotter(userInput, scoringData);
|
|
43368
|
+
if (validationError) {
|
|
43369
|
+
return validationError;
|
|
43370
|
+
}
|
|
43283
43371
|
return {
|
|
43284
43372
|
type: "points",
|
|
43285
|
-
earned: deepEq$1(userInput,
|
|
43373
|
+
earned: deepEq$1(userInput, scoringData.correct) ? 1 : 0,
|
|
43286
43374
|
total: 1,
|
|
43287
43375
|
message: null
|
|
43288
43376
|
};
|
|
@@ -44167,7 +44255,14 @@ const getPromptJSON$1 = userInput => {
|
|
|
44167
44255
|
};
|
|
44168
44256
|
};
|
|
44169
44257
|
|
|
44170
|
-
|
|
44258
|
+
/**
|
|
44259
|
+
* Checks user input for the sorter widget to ensure that the user has made
|
|
44260
|
+
* changes before attempting to score the widget.
|
|
44261
|
+
* @param userInput
|
|
44262
|
+
* @see 'scoreSorter' in 'packages/perseus/src/widgets/sorter/score-sorter.ts'
|
|
44263
|
+
* for more details on how the sorter widget is scored.
|
|
44264
|
+
*/
|
|
44265
|
+
function validateSorter(userInput) {
|
|
44171
44266
|
// If the sorter widget hasn't been changed yet, we treat it as "empty" which
|
|
44172
44267
|
// prevents the "Check" button from becoming active. We want the user
|
|
44173
44268
|
// to make a change before trying to move forward. This makes an
|
|
@@ -44180,6 +44275,14 @@ function scoreSorter(userInput, rubric) {
|
|
|
44180
44275
|
message: null
|
|
44181
44276
|
};
|
|
44182
44277
|
}
|
|
44278
|
+
return null;
|
|
44279
|
+
}
|
|
44280
|
+
|
|
44281
|
+
function scoreSorter(userInput, rubric) {
|
|
44282
|
+
const validationError = validateSorter(userInput);
|
|
44283
|
+
if (validationError) {
|
|
44284
|
+
return validationError;
|
|
44285
|
+
}
|
|
44183
44286
|
const correct = Util.deepEq(userInput.options, rubric.correct);
|
|
44184
44287
|
return {
|
|
44185
44288
|
type: "points",
|
|
@@ -44758,7 +44861,7 @@ const init = function init() {
|
|
|
44758
44861
|
|
|
44759
44862
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44760
44863
|
const libName = "@khanacademy/perseus";
|
|
44761
|
-
const libVersion = "
|
|
44864
|
+
const libVersion = "44.0.0";
|
|
44762
44865
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44763
44866
|
|
|
44764
44867
|
const apiVersion = {
|
|
@@ -46362,7 +46465,7 @@ const str = {
|
|
|
46362
46465
|
}
|
|
46363
46466
|
};
|
|
46364
46467
|
|
|
46365
|
-
const _excluded = ["item", "children", "shape", "serializedState", "onSerializedStateUpdated"];
|
|
46468
|
+
const _excluded$1 = ["item", "children", "shape", "serializedState", "onSerializedStateUpdated"];
|
|
46366
46469
|
|
|
46367
46470
|
// TODO(mdr)
|
|
46368
46471
|
// TODO(mdr)
|
|
@@ -46447,7 +46550,7 @@ class MultiRenderer extends React.Component {
|
|
|
46447
46550
|
// explicitly pulling them out of `this.props` so I don't pass them to
|
|
46448
46551
|
// `<Renderer>`. I'm not sure how else to do this.
|
|
46449
46552
|
const _this$props = this.props,
|
|
46450
|
-
otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded);
|
|
46553
|
+
otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
|
|
46451
46554
|
return _extends({}, otherProps, {
|
|
46452
46555
|
strings: this.context.strings
|
|
46453
46556
|
});
|
|
@@ -48251,6 +48354,27 @@ function pair(parseA, parseB) {
|
|
|
48251
48354
|
};
|
|
48252
48355
|
}
|
|
48253
48356
|
|
|
48357
|
+
function pipeParsers(p) {
|
|
48358
|
+
return new ParserPipeline(p);
|
|
48359
|
+
}
|
|
48360
|
+
class ParserPipeline {
|
|
48361
|
+
constructor(parser) {
|
|
48362
|
+
this.parser = parser;
|
|
48363
|
+
}
|
|
48364
|
+
then(nextParser) {
|
|
48365
|
+
return new ParserPipeline(composeParsers(this.parser, nextParser));
|
|
48366
|
+
}
|
|
48367
|
+
}
|
|
48368
|
+
function composeParsers(parserA, parserB) {
|
|
48369
|
+
return (rawValue, ctx) => {
|
|
48370
|
+
const partialResult = parserA(rawValue, ctx);
|
|
48371
|
+
if (isFailure(partialResult)) {
|
|
48372
|
+
return partialResult;
|
|
48373
|
+
}
|
|
48374
|
+
return parserB(partialResult.value, ctx);
|
|
48375
|
+
};
|
|
48376
|
+
}
|
|
48377
|
+
|
|
48254
48378
|
function record(parseKey, parseValue) {
|
|
48255
48379
|
return (rawValue, ctx) => {
|
|
48256
48380
|
if (!isObject(rawValue)) {
|
|
@@ -48331,6 +48455,20 @@ function either(parseA, parseB) {
|
|
|
48331
48455
|
};
|
|
48332
48456
|
}
|
|
48333
48457
|
|
|
48458
|
+
function defaulted(parser, fallback) {
|
|
48459
|
+
return (rawValue, ctx) => {
|
|
48460
|
+
if (rawValue == null) {
|
|
48461
|
+
return success(fallback(rawValue));
|
|
48462
|
+
}
|
|
48463
|
+
return parser(rawValue, ctx);
|
|
48464
|
+
};
|
|
48465
|
+
}
|
|
48466
|
+
|
|
48467
|
+
const parseImages = defaulted(record(string, object({
|
|
48468
|
+
width: number,
|
|
48469
|
+
height: number
|
|
48470
|
+
})), () => ({}));
|
|
48471
|
+
|
|
48334
48472
|
function parseWidget(parseType, parseOptions) {
|
|
48335
48473
|
return object({
|
|
48336
48474
|
type: parseType,
|
|
@@ -48339,10 +48477,21 @@ function parseWidget(parseType, parseOptions) {
|
|
|
48339
48477
|
alignment: optional(string),
|
|
48340
48478
|
options: parseOptions,
|
|
48341
48479
|
key: optional(number),
|
|
48342
|
-
version: object({
|
|
48480
|
+
version: optional(object({
|
|
48343
48481
|
major: number,
|
|
48344
48482
|
minor: number
|
|
48345
|
-
})
|
|
48483
|
+
}))
|
|
48484
|
+
});
|
|
48485
|
+
}
|
|
48486
|
+
function parseWidgetWithVersion(parseVersion, parseType, parseOptions) {
|
|
48487
|
+
return object({
|
|
48488
|
+
type: parseType,
|
|
48489
|
+
static: optional(boolean),
|
|
48490
|
+
graded: optional(boolean),
|
|
48491
|
+
alignment: optional(string),
|
|
48492
|
+
options: parseOptions,
|
|
48493
|
+
key: optional(number),
|
|
48494
|
+
version: parseVersion
|
|
48346
48495
|
});
|
|
48347
48496
|
}
|
|
48348
48497
|
|
|
@@ -48350,7 +48499,7 @@ const parseCategorizerWidget = parseWidget(constant("categorizer"), object({
|
|
|
48350
48499
|
items: array(string),
|
|
48351
48500
|
categories: array(string),
|
|
48352
48501
|
randomizeItems: boolean,
|
|
48353
|
-
static: boolean,
|
|
48502
|
+
static: defaulted(boolean, () => false),
|
|
48354
48503
|
values: array(number),
|
|
48355
48504
|
highlightLint: optional(boolean),
|
|
48356
48505
|
linterContext: optional(object({
|
|
@@ -48382,7 +48531,9 @@ const parseDefinitionWidget = parseWidget(constant("definition"), object({
|
|
|
48382
48531
|
|
|
48383
48532
|
const parseDropdownWidget = parseWidget(constant("dropdown"), object({
|
|
48384
48533
|
placeholder: string,
|
|
48385
|
-
|
|
48534
|
+
ariaLabel: optional(string),
|
|
48535
|
+
visibleLabel: optional(string),
|
|
48536
|
+
static: defaulted(boolean, () => false),
|
|
48386
48537
|
choices: array(object({
|
|
48387
48538
|
content: string,
|
|
48388
48539
|
correct: boolean
|
|
@@ -48405,9 +48556,12 @@ const parseAnswerForm = object({
|
|
|
48405
48556
|
form: boolean,
|
|
48406
48557
|
simplify: boolean,
|
|
48407
48558
|
considered: enumeration("correct", "wrong", "ungraded"),
|
|
48408
|
-
key: optional(string)
|
|
48559
|
+
key: pipeParsers(optional(union(string).or(number).parser)).then((key, ctx) => ctx.success(String(key))).parser
|
|
48409
48560
|
});
|
|
48410
|
-
const
|
|
48561
|
+
const parseExpressionWidgetV1 = parseWidgetWithVersion(object({
|
|
48562
|
+
major: constant(1),
|
|
48563
|
+
minor: number
|
|
48564
|
+
}), constant("expression"), object({
|
|
48411
48565
|
answerForms: array(parseAnswerForm),
|
|
48412
48566
|
functions: array(string),
|
|
48413
48567
|
times: boolean,
|
|
@@ -48416,23 +48570,68 @@ const parseExpressionWidget = parseWidget(constant("expression"), object({
|
|
|
48416
48570
|
buttonSets: array(enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations")),
|
|
48417
48571
|
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48418
48572
|
}));
|
|
48573
|
+
const parseExpressionWidgetV0 = parseWidgetWithVersion(optional(object({
|
|
48574
|
+
major: constant(0),
|
|
48575
|
+
minor: number
|
|
48576
|
+
})), constant("expression"), object({
|
|
48577
|
+
functions: array(string),
|
|
48578
|
+
times: boolean,
|
|
48579
|
+
visibleLabel: optional(string),
|
|
48580
|
+
ariaLabel: optional(string),
|
|
48581
|
+
form: boolean,
|
|
48582
|
+
simplify: boolean,
|
|
48583
|
+
value: string,
|
|
48584
|
+
buttonSets: array(enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations")),
|
|
48585
|
+
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48586
|
+
}));
|
|
48587
|
+
function migrateV0ToV1(widget, ctx) {
|
|
48588
|
+
const {
|
|
48589
|
+
options
|
|
48590
|
+
} = widget;
|
|
48591
|
+
return ctx.success(_extends({}, widget, {
|
|
48592
|
+
version: {
|
|
48593
|
+
major: 1,
|
|
48594
|
+
minor: 0
|
|
48595
|
+
},
|
|
48596
|
+
options: {
|
|
48597
|
+
times: options.times,
|
|
48598
|
+
buttonSets: options.buttonSets,
|
|
48599
|
+
functions: options.functions,
|
|
48600
|
+
buttonsVisible: options.buttonsVisible,
|
|
48601
|
+
visibleLabel: options.visibleLabel,
|
|
48602
|
+
ariaLabel: options.ariaLabel,
|
|
48603
|
+
answerForms: [{
|
|
48604
|
+
considered: "correct",
|
|
48605
|
+
form: options.form,
|
|
48606
|
+
simplify: options.simplify,
|
|
48607
|
+
value: options.value
|
|
48608
|
+
}]
|
|
48609
|
+
}
|
|
48610
|
+
}));
|
|
48611
|
+
}
|
|
48612
|
+
const parseExpressionWidget = union(parseExpressionWidgetV1).or(pipeParsers(parseExpressionWidgetV0).then(migrateV0ToV1).parser).parser;
|
|
48419
48613
|
|
|
48420
|
-
const parsePerseusRenderer = object({
|
|
48421
|
-
|
|
48614
|
+
const parsePerseusRenderer = defaulted(object({
|
|
48615
|
+
// TODO(benchristel): content is also defaulted to empty string in
|
|
48616
|
+
// renderer.tsx. See if we can remove one default or the other.
|
|
48617
|
+
content: defaulted(string, () => ""),
|
|
48422
48618
|
// This module has an import cycle with parseWidgetsMap, because the
|
|
48423
48619
|
// `group` widget can contain another renderer.
|
|
48424
48620
|
// The anonymous function below ensures that we don't try to access
|
|
48425
48621
|
// parseWidgetsMap before it's defined.
|
|
48426
|
-
widgets: (rawVal, ctx) => parseWidgetsMap(rawVal, ctx),
|
|
48622
|
+
widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => ({})),
|
|
48427
48623
|
metadata: optional(array(string)),
|
|
48428
|
-
images:
|
|
48429
|
-
|
|
48430
|
-
|
|
48431
|
-
|
|
48432
|
-
|
|
48624
|
+
images: parseImages
|
|
48625
|
+
}),
|
|
48626
|
+
// Default value
|
|
48627
|
+
() => ({
|
|
48628
|
+
content: "",
|
|
48629
|
+
widgets: {},
|
|
48630
|
+
images: {}
|
|
48631
|
+
}));
|
|
48433
48632
|
|
|
48434
48633
|
const parseGradedGroupWidgetOptions = object({
|
|
48435
|
-
title: string,
|
|
48634
|
+
title: defaulted(string, () => ""),
|
|
48436
48635
|
hasHint: optional(nullable(boolean)),
|
|
48437
48636
|
// This module has an import cycle with parsePerseusRenderer.
|
|
48438
48637
|
// The anonymous function below ensures that we don't try to access
|
|
@@ -48526,7 +48725,7 @@ const parseIframeWidget = parseWidget(constant("iframe"), object({
|
|
|
48526
48725
|
height: union(number).or(string).parser,
|
|
48527
48726
|
allowFullScreen: boolean,
|
|
48528
48727
|
allowTopNavigation: optional(boolean),
|
|
48529
|
-
static: boolean
|
|
48728
|
+
static: defaulted(boolean, () => false)
|
|
48530
48729
|
}));
|
|
48531
48730
|
|
|
48532
48731
|
const parsePerseusImageBackground = object({
|
|
@@ -48905,13 +49104,13 @@ const parseMatcherWidget = parseWidget(constant("matcher"), object({
|
|
|
48905
49104
|
padding: boolean
|
|
48906
49105
|
}));
|
|
48907
49106
|
|
|
48908
|
-
const parseMatrixWidget = parseWidget(constant("matrix"), object({
|
|
48909
|
-
prefix: string,
|
|
48910
|
-
suffix: string,
|
|
49107
|
+
const parseMatrixWidget = parseWidget(defaulted(constant("matrix"), () => "matrix"), object({
|
|
49108
|
+
prefix: optional(string),
|
|
49109
|
+
suffix: optional(string),
|
|
48911
49110
|
answers: array(array(number)),
|
|
48912
|
-
cursorPosition: array(number),
|
|
49111
|
+
cursorPosition: optional(array(number)),
|
|
48913
49112
|
matrixBoardSize: array(number),
|
|
48914
|
-
static: boolean
|
|
49113
|
+
static: optional(boolean)
|
|
48915
49114
|
}));
|
|
48916
49115
|
|
|
48917
49116
|
const parseMeasurerWidget = parseWidget(constant("measurer"), object({
|
|
@@ -48981,8 +49180,8 @@ const parseOrdererWidget = parseWidget(constant("orderer"), object({
|
|
|
48981
49180
|
options: array(parseRenderer),
|
|
48982
49181
|
correctOptions: array(parseRenderer),
|
|
48983
49182
|
otherOptions: array(parseRenderer),
|
|
48984
|
-
height:
|
|
48985
|
-
layout:
|
|
49183
|
+
height: enumeration("normal", "auto"),
|
|
49184
|
+
layout: enumeration("horizontal", "vertical")
|
|
48986
49185
|
}));
|
|
48987
49186
|
|
|
48988
49187
|
const parsePassageRefWidget = parseWidget(constant("passage-ref"), object({
|
|
@@ -49027,7 +49226,7 @@ const parsePythonProgramWidget = parseWidget(constant("python-program"), object(
|
|
|
49027
49226
|
|
|
49028
49227
|
const parseRadioWidget = parseWidget(constant("radio"), object({
|
|
49029
49228
|
choices: array(object({
|
|
49030
|
-
content: string,
|
|
49229
|
+
content: defaulted(string, () => ""),
|
|
49031
49230
|
clue: optional(string),
|
|
49032
49231
|
correct: optional(boolean),
|
|
49033
49232
|
isNoneOfTheAbove: optional(boolean),
|
|
@@ -49188,26 +49387,42 @@ const parseWidgetMapKeyComponents = pair(string, parseStringToPositiveInt);
|
|
|
49188
49387
|
const parseHint = object({
|
|
49189
49388
|
replace: optional(boolean),
|
|
49190
49389
|
content: string,
|
|
49191
|
-
widgets: parseWidgetsMap,
|
|
49390
|
+
widgets: defaulted(parseWidgetsMap, () => ({})),
|
|
49192
49391
|
metadata: optional(array(string)),
|
|
49193
|
-
images:
|
|
49194
|
-
width: number,
|
|
49195
|
-
height: number
|
|
49196
|
-
}))
|
|
49392
|
+
images: parseImages
|
|
49197
49393
|
});
|
|
49198
49394
|
|
|
49395
|
+
const _excluded = ["type", "options"];
|
|
49199
49396
|
object({
|
|
49200
49397
|
question: parsePerseusRenderer,
|
|
49201
|
-
hints: array(parseHint),
|
|
49202
|
-
answerArea: record(enumeration(...ItemExtras), boolean),
|
|
49203
|
-
itemDataVersion: object({
|
|
49398
|
+
hints: defaulted(array(parseHint), () => []),
|
|
49399
|
+
answerArea: pipeParsers(defaulted(object({}), () => ({}))).then(migrateAnswerArea).then(record(enumeration(...ItemExtras), boolean)).parser,
|
|
49400
|
+
itemDataVersion: optional(object({
|
|
49204
49401
|
major: number,
|
|
49205
49402
|
minor: number
|
|
49206
|
-
}),
|
|
49403
|
+
})),
|
|
49207
49404
|
// Deprecated field
|
|
49208
49405
|
answer: any
|
|
49209
49406
|
});
|
|
49210
49407
|
|
|
49408
|
+
// Some answerAreas have extra fields, like:
|
|
49409
|
+
//
|
|
49410
|
+
// "answerArea": {
|
|
49411
|
+
// "type": "multiple",
|
|
49412
|
+
// "options": {
|
|
49413
|
+
// "content": "",
|
|
49414
|
+
// "images": {},
|
|
49415
|
+
// "widgets": {}
|
|
49416
|
+
// }
|
|
49417
|
+
// }
|
|
49418
|
+
//
|
|
49419
|
+
// The "type" and "options" fields don't seem to be used anywhere. This
|
|
49420
|
+
// migration function removes them.
|
|
49421
|
+
function migrateAnswerArea(rawValue, ctx) {
|
|
49422
|
+
const rest = _objectWithoutPropertiesLoose(rawValue, _excluded);
|
|
49423
|
+
return ctx.success(rest);
|
|
49424
|
+
}
|
|
49425
|
+
|
|
49211
49426
|
/**
|
|
49212
49427
|
* Helper to parse PerseusItem JSON
|
|
49213
49428
|
* Why not just use JSON.parse? We want:
|