@khanacademy/perseus 34.1.0 → 35.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/es/index.js +374 -380
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +8 -2
- package/dist/es/strings.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +286 -302
- package/dist/index.js.map +1 -1
- package/dist/mixins/widget-prop-denylist.d.ts +0 -1
- package/dist/perseus-api.d.ts +3 -5
- package/dist/perseus-types.d.ts +6 -19
- package/dist/renderer.d.ts +4 -4
- package/dist/server-item-renderer.d.ts +3 -9
- package/dist/strings.d.ts +3 -0
- package/dist/strings.js +8 -2
- package/dist/strings.js.map +1 -1
- package/dist/types.d.ts +1 -3
- package/dist/validation.types.d.ts +111 -0
- package/dist/widgets/categorizer/categorizer-validator.d.ts +2 -2
- package/dist/widgets/categorizer/categorizer.d.ts +6 -6
- package/dist/widgets/cs-program/cs-program.d.ts +4 -9
- package/dist/widgets/definition/definition.d.ts +3 -4
- package/dist/widgets/dropdown/dropdown-validator.d.ts +2 -2
- package/dist/widgets/dropdown/dropdown.d.ts +5 -5
- package/dist/widgets/explanation/explanation.d.ts +3 -2
- package/dist/widgets/expression/expression-validator.d.ts +2 -2
- package/dist/widgets/expression/expression.d.ts +32 -26
- package/dist/widgets/expression/expression.types.d.ts +0 -1
- package/dist/widgets/graded-group/graded-group.d.ts +2 -2
- package/dist/widgets/graded-group-set/graded-group-set.d.ts +2 -2
- package/dist/widgets/grapher/grapher.d.ts +6 -7
- package/dist/widgets/group/group.d.ts +3 -2
- package/dist/widgets/iframe/iframe.d.ts +4 -9
- package/dist/widgets/image/image.d.ts +3 -4
- package/dist/widgets/input-number/input-number-validator.d.ts +3 -3
- package/dist/widgets/input-number/input-number.d.ts +7 -10
- package/dist/widgets/interaction/interaction.d.ts +3 -3
- package/dist/widgets/interactive-graph.d.ts +9 -12
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +8 -2
- package/dist/widgets/interactive-graphs/stateful-mafs-graph.d.ts +5 -2
- package/dist/widgets/label-image/label-image-validator.d.ts +10 -0
- package/dist/widgets/label-image/label-image.d.ts +11 -10
- package/dist/widgets/label-image/types.d.ts +0 -4
- package/dist/widgets/matcher/matcher.d.ts +4 -4
- package/dist/widgets/matrix/matrix.d.ts +5 -5
- package/dist/widgets/molecule/molecule.d.ts +2 -1
- package/dist/widgets/number-line/number-line.d.ts +5 -3
- package/dist/widgets/numeric-input/numeric-input-validator.d.ts +2 -2
- package/dist/widgets/numeric-input/numeric-input.d.ts +7 -7
- package/dist/widgets/orderer/orderer.d.ts +4 -4
- package/dist/widgets/passage/passage.d.ts +3 -4
- package/dist/widgets/passage-ref/passage-ref.d.ts +3 -11
- package/dist/widgets/passage-ref-target/passage-ref-target.d.ts +2 -1
- package/dist/widgets/phet-simulation/phet-simulation.d.ts +2 -2
- package/dist/widgets/plotter/plotter.d.ts +5 -5
- package/dist/widgets/radio/radio-component.d.ts +6 -13
- package/dist/widgets/radio/radio-validator.d.ts +5 -0
- package/dist/widgets/sorter/sorter-validator.d.ts +4 -0
- package/dist/widgets/sorter/sorter.d.ts +7 -9
- package/dist/widgets/table/table.d.ts +5 -5
- package/dist/widgets/video/video.d.ts +2 -2
- package/package.json +1 -1
- package/dist/widgets/categorizer/categorizer.types.d.ts +0 -5
- package/dist/widgets/dropdown/dropdown.types.d.ts +0 -5
- package/dist/widgets/input-number/input-number.types.d.ts +0 -2
- package/dist/widgets/numeric-input/numeric-input.types.d.ts +0 -5
package/dist/es/index.js
CHANGED
|
@@ -246,7 +246,10 @@ const mockStrings = {
|
|
|
246
246
|
cos: "cos",
|
|
247
247
|
tan: "tan",
|
|
248
248
|
simulationLoadFail: "Sorry, this simulation cannot load.",
|
|
249
|
-
simulationLocaleWarning: "Sorry, this simulation isn't available in your language."
|
|
249
|
+
simulationLocaleWarning: "Sorry, this simulation isn't available in your language.",
|
|
250
|
+
addPoint: "Add Point",
|
|
251
|
+
removePoint: "Remove Point",
|
|
252
|
+
graphKeyboardPrompt: "Press Shift + Enter to interact with the graph"
|
|
250
253
|
};
|
|
251
254
|
|
|
252
255
|
/**
|
|
@@ -749,7 +752,7 @@ const denylist = [
|
|
|
749
752
|
// (technically the renderer still adds them)
|
|
750
753
|
"key", "ref",
|
|
751
754
|
// added by src/renderer.jsx
|
|
752
|
-
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "questionCompleted", "findWidgets",
|
|
755
|
+
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "widgetIsOpen", "questionCompleted", "findWidgets",
|
|
753
756
|
// added by src/editor.jsx, for widgets removing themselves
|
|
754
757
|
// this is soooo not the right place for this, but alas.
|
|
755
758
|
"onRemove",
|
|
@@ -757,15 +760,6 @@ const denylist = [
|
|
|
757
760
|
"id",
|
|
758
761
|
// Callbacks and items for interaction handling
|
|
759
762
|
"onBlur", "onFocus", "trackInteraction", "keypadElement"];
|
|
760
|
-
const removeDenylistProps = props => {
|
|
761
|
-
const newProps = _extends({}, props);
|
|
762
|
-
for (const prop of denylist) {
|
|
763
|
-
if (prop in newProps) {
|
|
764
|
-
delete newProps[prop];
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
return newProps;
|
|
768
|
-
};
|
|
769
763
|
|
|
770
764
|
/* eslint-disable @babel/no-invalid-this */
|
|
771
765
|
const USAGE = "Usage:\n" + " this.change({propName: 5}, callback);\n" + ' this.change("propName", 5, callback);\n' + ' this.change("propName")';
|
|
@@ -1030,8 +1024,6 @@ StubTagEditor.defaultProps = {
|
|
|
1030
1024
|
* * nothing if it is purely a bug fix.
|
|
1031
1025
|
*
|
|
1032
1026
|
* Callbacks passed to Renderer/ItemRenderer:
|
|
1033
|
-
* * onInputError:
|
|
1034
|
-
* Called when there is an error grading a widget
|
|
1035
1027
|
* * onFocusChange: (newFocusPath, oldFocusPath, keypadDOMNode)
|
|
1036
1028
|
* Called when the user focus changes. The first two parameters are `path`
|
|
1037
1029
|
* arrays uniquely identifying the respect inputs. The third parameter,
|
|
@@ -1054,7 +1046,6 @@ StubTagEditor.defaultProps = {
|
|
|
1054
1046
|
const ApiOptions = {
|
|
1055
1047
|
propTypes: PropTypes.shape({
|
|
1056
1048
|
isArticle: PropTypes.bool.isRequired,
|
|
1057
|
-
onInputError: PropTypes.func.isRequired,
|
|
1058
1049
|
onFocusChange: PropTypes.func.isRequired,
|
|
1059
1050
|
GroupMetadataEditor: PropTypes.func.isRequired,
|
|
1060
1051
|
showAlignmentOptions: PropTypes.bool.isRequired,
|
|
@@ -1138,7 +1129,6 @@ const ApiOptions = {
|
|
|
1138
1129
|
defaults: {
|
|
1139
1130
|
isArticle: false,
|
|
1140
1131
|
isMobile: false,
|
|
1141
|
-
onInputError: function () {},
|
|
1142
1132
|
onFocusChange: function () {},
|
|
1143
1133
|
GroupMetadataEditor: StubTagEditor,
|
|
1144
1134
|
showAlignmentOptions: false,
|
|
@@ -2150,9 +2140,7 @@ const getDecimalSeparator = locale => {
|
|
|
2150
2140
|
* show the user an error. TODO(joel) - what error?
|
|
2151
2141
|
* - Otherwise, pass through the resulting points and message.
|
|
2152
2142
|
*/
|
|
2153
|
-
function expressionValidator(userInput, rubric,
|
|
2154
|
-
// @ts-expect-error - TS2322 - Type '() => void' is not assignable to type 'OnInputErrorFunctionType'.
|
|
2155
|
-
onInputError = function () {}, strings, locale) {
|
|
2143
|
+
function expressionValidator(userInput, rubric, strings, locale) {
|
|
2156
2144
|
const options = _.clone(rubric);
|
|
2157
2145
|
_.extend(options, {
|
|
2158
2146
|
decimal_separator: getDecimalSeparator(locale)
|
|
@@ -2252,14 +2240,9 @@ onInputError = function () {}, strings, locale) {
|
|
|
2252
2240
|
};
|
|
2253
2241
|
}
|
|
2254
2242
|
if (matchingAnswerForm.considered === "ungraded") {
|
|
2255
|
-
// We matched an ungraded answer form - return "invalid", which
|
|
2256
|
-
// will let the user try again with no penalty
|
|
2257
|
-
const apiResult = onInputError(null,
|
|
2258
|
-
// Reserved for some widget identifier
|
|
2259
|
-
userInput, matchMessage);
|
|
2260
2243
|
return {
|
|
2261
2244
|
type: "invalid",
|
|
2262
|
-
message:
|
|
2245
|
+
message: matchMessage
|
|
2263
2246
|
};
|
|
2264
2247
|
}
|
|
2265
2248
|
// We matched a graded answer form, so we can now tell the user
|
|
@@ -2348,14 +2331,9 @@ class Expression extends React.Component {
|
|
|
2348
2331
|
showErrorStyle: false
|
|
2349
2332
|
});
|
|
2350
2333
|
if (!this.parse(this.props.value, this.props).parsed) {
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
if (apiResult !== false) {
|
|
2355
|
-
this.setState({
|
|
2356
|
-
invalid: true
|
|
2357
|
-
});
|
|
2358
|
-
}
|
|
2334
|
+
this.setState({
|
|
2335
|
+
invalid: true
|
|
2336
|
+
});
|
|
2359
2337
|
}
|
|
2360
2338
|
}
|
|
2361
2339
|
};
|
|
@@ -2369,12 +2347,12 @@ class Expression extends React.Component {
|
|
|
2369
2347
|
});
|
|
2370
2348
|
}
|
|
2371
2349
|
};
|
|
2372
|
-
this.simpleValidate =
|
|
2350
|
+
this.simpleValidate = _ref => {
|
|
2373
2351
|
let {
|
|
2374
2352
|
scoring
|
|
2375
2353
|
} = _ref,
|
|
2376
2354
|
rubric = _objectWithoutPropertiesLoose(_ref, _excluded$5);
|
|
2377
|
-
const score = expressionValidator(this.getUserInput(), rubric,
|
|
2355
|
+
const score = expressionValidator(this.getUserInput(), rubric, this.context.strings, this.context.locale);
|
|
2378
2356
|
|
|
2379
2357
|
// "scoring" is a flag that indicates when we are checking answers.
|
|
2380
2358
|
// otherwise, we may just be checking validity after changes.
|
|
@@ -2390,9 +2368,6 @@ class Expression extends React.Component {
|
|
|
2390
2368
|
}
|
|
2391
2369
|
return score;
|
|
2392
2370
|
};
|
|
2393
|
-
this.getUserInput = () => {
|
|
2394
|
-
return Expression.getUserInputFromProps(this.props);
|
|
2395
|
-
};
|
|
2396
2371
|
this.change = (...args) => {
|
|
2397
2372
|
return change.apply(this, args);
|
|
2398
2373
|
};
|
|
@@ -2465,10 +2440,8 @@ class Expression extends React.Component {
|
|
|
2465
2440
|
};
|
|
2466
2441
|
}
|
|
2467
2442
|
// TODO remove this in favor of just using expressionValidator
|
|
2468
|
-
static validate(userInput, rubric,
|
|
2469
|
-
|
|
2470
|
-
onInputError = function () {}, strings, locale) {
|
|
2471
|
-
return expressionValidator(userInput, rubric, onInputError, strings, locale);
|
|
2443
|
+
static validate(userInput, rubric, strings, locale) {
|
|
2444
|
+
return expressionValidator(userInput, rubric, strings, locale);
|
|
2472
2445
|
}
|
|
2473
2446
|
static getUserInputFromProps(props) {
|
|
2474
2447
|
return normalizeTex(props.value);
|
|
@@ -2482,6 +2455,9 @@ class Expression extends React.Component {
|
|
|
2482
2455
|
}
|
|
2483
2456
|
//#endregion
|
|
2484
2457
|
|
|
2458
|
+
getUserInput() {
|
|
2459
|
+
return Expression.getUserInputFromProps(this.props);
|
|
2460
|
+
}
|
|
2485
2461
|
// HACK(joel)
|
|
2486
2462
|
insert(keyPressed) {
|
|
2487
2463
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -14677,7 +14653,7 @@ const pluck = function pluck(table, subKey) {
|
|
|
14677
14653
|
* });
|
|
14678
14654
|
* {a: 2, b: 3}
|
|
14679
14655
|
*/
|
|
14680
|
-
const mapObject$
|
|
14656
|
+
const mapObject$1 = function mapObject(obj, lambda) {
|
|
14681
14657
|
const result = {};
|
|
14682
14658
|
_.each(_.keys(obj), function (key) {
|
|
14683
14659
|
// @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
|
|
@@ -14703,7 +14679,7 @@ const mapObjectFromArray$1 = function mapObjectFromArray(arr, lambda) {
|
|
|
14703
14679
|
};
|
|
14704
14680
|
var objective_ = {
|
|
14705
14681
|
pluck: pluck,
|
|
14706
|
-
mapObject: mapObject$
|
|
14682
|
+
mapObject: mapObject$1,
|
|
14707
14683
|
mapObjectFromArray: mapObjectFromArray$1
|
|
14708
14684
|
};
|
|
14709
14685
|
|
|
@@ -19596,7 +19572,7 @@ WidgetContainer.defaultProps = {
|
|
|
19596
19572
|
};
|
|
19597
19573
|
|
|
19598
19574
|
const {
|
|
19599
|
-
mapObject
|
|
19575
|
+
mapObject,
|
|
19600
19576
|
mapObjectFromArray
|
|
19601
19577
|
} = objective_;
|
|
19602
19578
|
const rContainsNonWhitespace = /\S/;
|
|
@@ -19624,9 +19600,6 @@ const isIdPathPrefix = function isIdPathPrefix(prefixArray, wholeArray) {
|
|
|
19624
19600
|
});
|
|
19625
19601
|
};
|
|
19626
19602
|
|
|
19627
|
-
// The return type for getUserInput. Widgets have full control of what is
|
|
19628
|
-
// returned so it's not easily typed (some widgets return a scalar (string),
|
|
19629
|
-
// some return a custom-built object
|
|
19630
19603
|
/**
|
|
19631
19604
|
* The Widget type represents the common API that the Renderer uses to interact
|
|
19632
19605
|
* with all widgets. All widgets must implement the methods in this API, unless
|
|
@@ -19636,6 +19609,7 @@ const isIdPathPrefix = function isIdPathPrefix(prefixArray, wholeArray) {
|
|
|
19636
19609
|
* communicate with the individual widgets to coordinate actions such as
|
|
19637
19610
|
* scoring, state serialization/deserialization, and focus management.
|
|
19638
19611
|
*/
|
|
19612
|
+
|
|
19639
19613
|
class Renderer extends React.Component {
|
|
19640
19614
|
constructor(_props) {
|
|
19641
19615
|
super(_props);
|
|
@@ -19670,7 +19644,7 @@ class Renderer extends React.Component {
|
|
|
19670
19644
|
};
|
|
19671
19645
|
// @ts-expect-error - TS2322 - Type '(props: Props) => Partial<Record<string, CategorizerWidget | CSProgramWidget | DefinitionWidget | DropdownWidget | ... 35 more ... | VideoWidget>>' is not assignable to type '(props: Props) => { [key: string]: PerseusWidget; }'.
|
|
19672
19646
|
this._getAllWidgetsInfo = props => {
|
|
19673
|
-
return mapObject
|
|
19647
|
+
return mapObject(props.widgets, (widgetInfo, widgetId) => {
|
|
19674
19648
|
if (!widgetInfo.type || !widgetInfo.alignment) {
|
|
19675
19649
|
const newValues = {};
|
|
19676
19650
|
if (!widgetInfo.type) {
|
|
@@ -19811,7 +19785,7 @@ class Renderer extends React.Component {
|
|
|
19811
19785
|
* state from that instead of the current widget props.
|
|
19812
19786
|
*/
|
|
19813
19787
|
this.getSerializedState = widgetProps => {
|
|
19814
|
-
return mapObject
|
|
19788
|
+
return mapObject(widgetProps || this.state.widgetProps, (props, widgetId) => {
|
|
19815
19789
|
const widget = this.getWidgetInstance(widgetId);
|
|
19816
19790
|
if (widget && widget.getSerializedState) {
|
|
19817
19791
|
return widget.getSerializedState();
|
|
@@ -19847,7 +19821,7 @@ class Renderer extends React.Component {
|
|
|
19847
19821
|
}
|
|
19848
19822
|
};
|
|
19849
19823
|
this.setState({
|
|
19850
|
-
widgetProps: mapObject
|
|
19824
|
+
widgetProps: mapObject(serializedState, (props, widgetId) => {
|
|
19851
19825
|
const widget = this.getWidgetInstance(widgetId);
|
|
19852
19826
|
if (widget && widget.restoreSerializedState) {
|
|
19853
19827
|
// Note that we probably can't call
|
|
@@ -20681,7 +20655,6 @@ class Renderer extends React.Component {
|
|
|
20681
20655
|
*/
|
|
20682
20656
|
this.scoreWidgets = () => {
|
|
20683
20657
|
const widgetProps = this.state.widgetInfo;
|
|
20684
|
-
const onInputError = this.getApiOptions().onInputError;
|
|
20685
20658
|
const gradedWidgetIds = _.filter(this.widgetIds, id => {
|
|
20686
20659
|
const props = widgetProps[id];
|
|
20687
20660
|
const widgetIsGraded = (props == null ? void 0 : props.graded) == null || props.graded;
|
|
@@ -20697,7 +20670,7 @@ class Renderer extends React.Component {
|
|
|
20697
20670
|
if (widget && widget.simpleValidate) {
|
|
20698
20671
|
widgetScores[id] = widget.simpleValidate(_extends({}, props == null ? void 0 : props.options, {
|
|
20699
20672
|
scoring: true
|
|
20700
|
-
})
|
|
20673
|
+
}));
|
|
20701
20674
|
}
|
|
20702
20675
|
});
|
|
20703
20676
|
return widgetScores;
|
|
@@ -21738,7 +21711,7 @@ const answerTypes = {
|
|
|
21738
21711
|
forms: "pi"
|
|
21739
21712
|
}
|
|
21740
21713
|
};
|
|
21741
|
-
function inputNumberValidator(state, rubric, strings
|
|
21714
|
+
function inputNumberValidator(state, rubric, strings) {
|
|
21742
21715
|
if (rubric.answerType == null) {
|
|
21743
21716
|
rubric.answerType = "number";
|
|
21744
21717
|
}
|
|
@@ -21762,13 +21735,9 @@ function inputNumberValidator(state, rubric, strings, onInputError = () => {}) {
|
|
|
21762
21735
|
// TODO(eater): Seems silly to translate result to this invalid/points
|
|
21763
21736
|
// thing and immediately translate it back in ItemRenderer.scoreInput()
|
|
21764
21737
|
if (result.empty) {
|
|
21765
|
-
// TODO(FEI-3867): remove null-check once we have APIOptionsInternal
|
|
21766
|
-
const apiResult = onInputError == null ? void 0 : onInputError(null,
|
|
21767
|
-
// reserved for some widget identifier
|
|
21768
|
-
state.currentValue, result.message);
|
|
21769
21738
|
return {
|
|
21770
21739
|
type: "invalid",
|
|
21771
|
-
message:
|
|
21740
|
+
message: result.message
|
|
21772
21741
|
};
|
|
21773
21742
|
}
|
|
21774
21743
|
return {
|
|
@@ -21864,13 +21833,6 @@ class InputNumber extends React.Component {
|
|
|
21864
21833
|
currentValue: newValue
|
|
21865
21834
|
}, cb);
|
|
21866
21835
|
};
|
|
21867
|
-
this.getUserInput = () => {
|
|
21868
|
-
return InputNumber.getUserInputFromProps(this.props);
|
|
21869
|
-
};
|
|
21870
|
-
this.simpleValidate = (rubric, onInputError) => {
|
|
21871
|
-
onInputError = onInputError || function () {};
|
|
21872
|
-
return inputNumberValidator(this.getUserInput(), rubric, this.context.strings, onInputError);
|
|
21873
|
-
};
|
|
21874
21836
|
this.examples = () => {
|
|
21875
21837
|
const {
|
|
21876
21838
|
strings
|
|
@@ -21881,8 +21843,8 @@ class InputNumber extends React.Component {
|
|
|
21881
21843
|
return [strings.yourAnswer].concat(examples);
|
|
21882
21844
|
};
|
|
21883
21845
|
}
|
|
21884
|
-
static validate(state, rubric, strings
|
|
21885
|
-
return inputNumberValidator(state, rubric, strings
|
|
21846
|
+
static validate(state, rubric, strings) {
|
|
21847
|
+
return inputNumberValidator(state, rubric, strings);
|
|
21886
21848
|
}
|
|
21887
21849
|
static getUserInputFromProps(props) {
|
|
21888
21850
|
return {
|
|
@@ -21899,6 +21861,12 @@ class InputNumber extends React.Component {
|
|
|
21899
21861
|
}
|
|
21900
21862
|
return answerString;
|
|
21901
21863
|
}
|
|
21864
|
+
getUserInput() {
|
|
21865
|
+
return InputNumber.getUserInputFromProps(this.props);
|
|
21866
|
+
}
|
|
21867
|
+
simpleValidate(rubric) {
|
|
21868
|
+
return inputNumberValidator(this.getUserInput(), rubric, this.context.strings);
|
|
21869
|
+
}
|
|
21902
21870
|
render() {
|
|
21903
21871
|
if (this.props.apiOptions.customKeypad) {
|
|
21904
21872
|
// TODO(charlie): Support "Review Mode".
|
|
@@ -22202,9 +22170,6 @@ class NumericInput extends React.Component {
|
|
|
22202
22170
|
const allFormsAccepted = answerFormNames.length >= Object.keys(formExamples).length;
|
|
22203
22171
|
return !noFormsAccepted && !allFormsAccepted;
|
|
22204
22172
|
};
|
|
22205
|
-
this.simpleValidate = rubric => {
|
|
22206
|
-
return numericInputValidator(this.getUserInput(), rubric, this.context.strings);
|
|
22207
|
-
};
|
|
22208
22173
|
this.focus = () => {
|
|
22209
22174
|
var _this$inputRef;
|
|
22210
22175
|
(_this$inputRef = this.inputRef) == null || _this$inputRef.focus();
|
|
@@ -22234,9 +22199,6 @@ class NumericInput extends React.Component {
|
|
|
22234
22199
|
currentValue: newValue
|
|
22235
22200
|
}, cb);
|
|
22236
22201
|
};
|
|
22237
|
-
this.getUserInput = () => {
|
|
22238
|
-
return NumericInput.getUserInputFromProps(this.props);
|
|
22239
|
-
};
|
|
22240
22202
|
this.handleChange = (newValue, cb) => {
|
|
22241
22203
|
this.props.onChange({
|
|
22242
22204
|
currentValue: newValue
|
|
@@ -22286,6 +22248,12 @@ class NumericInput extends React.Component {
|
|
|
22286
22248
|
static validate(userInput, rubric, strings) {
|
|
22287
22249
|
return numericInputValidator(userInput, rubric, strings);
|
|
22288
22250
|
}
|
|
22251
|
+
simpleValidate(rubric) {
|
|
22252
|
+
return numericInputValidator(this.getUserInput(), rubric, this.context.strings);
|
|
22253
|
+
}
|
|
22254
|
+
getUserInput() {
|
|
22255
|
+
return NumericInput.getUserInputFromProps(this.props);
|
|
22256
|
+
}
|
|
22289
22257
|
render() {
|
|
22290
22258
|
let labelText = this.props.labelText;
|
|
22291
22259
|
if (labelText == null || labelText === "") {
|
|
@@ -22442,11 +22410,6 @@ class PassageRef extends React.Component {
|
|
|
22442
22410
|
lineRange: null,
|
|
22443
22411
|
content: null
|
|
22444
22412
|
};
|
|
22445
|
-
// TODO(tamarab): getUserInput needs to be updated to only return
|
|
22446
|
-
// props input by the user. Currently returns all the widget's props.
|
|
22447
|
-
this.getUserInput = () => {
|
|
22448
|
-
return removeDenylistProps(this.props);
|
|
22449
|
-
};
|
|
22450
22413
|
this.change = (...args) => {
|
|
22451
22414
|
return change.apply(this, args);
|
|
22452
22415
|
};
|
|
@@ -22499,6 +22462,11 @@ class PassageRef extends React.Component {
|
|
|
22499
22462
|
window.removeEventListener("resize", this._throttledUpdateRange);
|
|
22500
22463
|
this._isMounted = false;
|
|
22501
22464
|
}
|
|
22465
|
+
|
|
22466
|
+
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
22467
|
+
getUserInput() {
|
|
22468
|
+
return null;
|
|
22469
|
+
}
|
|
22502
22470
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
22503
22471
|
simpleValidate() {
|
|
22504
22472
|
return noopValidator();
|
|
@@ -23904,6 +23872,56 @@ const styles$t = StyleSheet.create({
|
|
|
23904
23872
|
}
|
|
23905
23873
|
});
|
|
23906
23874
|
|
|
23875
|
+
function radioValidator(userInput, rubric, strings) {
|
|
23876
|
+
const numSelected = userInput.choicesSelected.reduce((sum, selected) => {
|
|
23877
|
+
return sum + (selected ? 1 : 0);
|
|
23878
|
+
}, 0);
|
|
23879
|
+
if (numSelected === 0) {
|
|
23880
|
+
return {
|
|
23881
|
+
type: "invalid",
|
|
23882
|
+
message: null
|
|
23883
|
+
};
|
|
23884
|
+
}
|
|
23885
|
+
|
|
23886
|
+
// TODO: should numCorrect actually be on the rubric
|
|
23887
|
+
// instead of the userInput?
|
|
23888
|
+
if (userInput.numCorrect && userInput.numCorrect > 1 && numSelected !== userInput.numCorrect) {
|
|
23889
|
+
return {
|
|
23890
|
+
type: "invalid",
|
|
23891
|
+
message: strings.chooseCorrectNum
|
|
23892
|
+
};
|
|
23893
|
+
// If NOTA and some other answer are checked, ...
|
|
23894
|
+
}
|
|
23895
|
+
|
|
23896
|
+
// TODO: should noneOfTheAboveSelected be replaced with a
|
|
23897
|
+
// combination of choicesSelected and noneOfTheAboveIndex?
|
|
23898
|
+
if (userInput.noneOfTheAboveSelected && numSelected > 1) {
|
|
23899
|
+
return {
|
|
23900
|
+
type: "invalid",
|
|
23901
|
+
message: strings.notNoneOfTheAbove
|
|
23902
|
+
};
|
|
23903
|
+
}
|
|
23904
|
+
const correct = userInput.choicesSelected.every((selected, i) => {
|
|
23905
|
+
let isCorrect;
|
|
23906
|
+
// TODO: should noneOfTheAboveIndex actually be on the rubric
|
|
23907
|
+
// instead of the userInput?
|
|
23908
|
+
if (userInput.noneOfTheAboveIndex === i) {
|
|
23909
|
+
isCorrect = rubric.choices.every((choice, j) => {
|
|
23910
|
+
return i === j || !choice.correct;
|
|
23911
|
+
});
|
|
23912
|
+
} else {
|
|
23913
|
+
isCorrect = !!rubric.choices[i].correct;
|
|
23914
|
+
}
|
|
23915
|
+
return isCorrect === selected;
|
|
23916
|
+
});
|
|
23917
|
+
return {
|
|
23918
|
+
type: "points",
|
|
23919
|
+
earned: correct ? 1 : 0,
|
|
23920
|
+
total: 1,
|
|
23921
|
+
message: null
|
|
23922
|
+
};
|
|
23923
|
+
}
|
|
23924
|
+
|
|
23907
23925
|
// RenderProps is the return type for radio.jsx#transform
|
|
23908
23926
|
|
|
23909
23927
|
class Radio$1 extends React.Component {
|
|
@@ -23998,12 +24016,6 @@ class Radio$1 extends React.Component {
|
|
|
23998
24016
|
});
|
|
23999
24017
|
this.props.trackInteraction();
|
|
24000
24018
|
};
|
|
24001
|
-
this.getUserInput = () => {
|
|
24002
|
-
return Radio$1.getUserInputFromProps(this.props);
|
|
24003
|
-
};
|
|
24004
|
-
this.simpleValidate = rubric => {
|
|
24005
|
-
return Radio$1.validate(this.getUserInput(), rubric, this.context.strings);
|
|
24006
|
-
};
|
|
24007
24019
|
/**
|
|
24008
24020
|
* Turn on rationale display for the currently selected choices. Note that
|
|
24009
24021
|
* this leaves rationales on for choices that are already showing
|
|
@@ -24064,46 +24076,7 @@ class Radio$1 extends React.Component {
|
|
|
24064
24076
|
};
|
|
24065
24077
|
}
|
|
24066
24078
|
static validate(userInput, rubric, strings) {
|
|
24067
|
-
|
|
24068
|
-
return sum + (selected ? 1 : 0);
|
|
24069
|
-
}, 0);
|
|
24070
|
-
if (numSelected === 0) {
|
|
24071
|
-
return {
|
|
24072
|
-
type: "invalid",
|
|
24073
|
-
message: null
|
|
24074
|
-
};
|
|
24075
|
-
}
|
|
24076
|
-
if (userInput.numCorrect && userInput.numCorrect > 1 && numSelected !== userInput.numCorrect) {
|
|
24077
|
-
return {
|
|
24078
|
-
type: "invalid",
|
|
24079
|
-
message: strings.chooseCorrectNum
|
|
24080
|
-
};
|
|
24081
|
-
// If NOTA and some other answer are checked, ...
|
|
24082
|
-
}
|
|
24083
|
-
|
|
24084
|
-
if (userInput.noneOfTheAboveSelected && numSelected > 1) {
|
|
24085
|
-
return {
|
|
24086
|
-
type: "invalid",
|
|
24087
|
-
message: strings.notNoneOfTheAbove
|
|
24088
|
-
};
|
|
24089
|
-
}
|
|
24090
|
-
const correct = userInput.choicesSelected.every((selected, i) => {
|
|
24091
|
-
let isCorrect;
|
|
24092
|
-
if (userInput.noneOfTheAboveIndex === i) {
|
|
24093
|
-
isCorrect = rubric.choices.every((choice, j) => {
|
|
24094
|
-
return i === j || !choice.correct;
|
|
24095
|
-
});
|
|
24096
|
-
} else {
|
|
24097
|
-
isCorrect = !!rubric.choices[i].correct;
|
|
24098
|
-
}
|
|
24099
|
-
return isCorrect === selected;
|
|
24100
|
-
});
|
|
24101
|
-
return {
|
|
24102
|
-
type: "points",
|
|
24103
|
-
earned: correct ? 1 : 0,
|
|
24104
|
-
total: 1,
|
|
24105
|
-
message: null
|
|
24106
|
-
};
|
|
24079
|
+
return radioValidator(userInput, rubric, strings);
|
|
24107
24080
|
}
|
|
24108
24081
|
static getUserInputFromProps(props) {
|
|
24109
24082
|
// Return checked inputs in the form {choicesSelected: [bool]}. (Dear
|
|
@@ -24192,6 +24165,12 @@ class Radio$1 extends React.Component {
|
|
|
24192
24165
|
registerFocusFunction(fun) {
|
|
24193
24166
|
this.focusFunction = fun;
|
|
24194
24167
|
}
|
|
24168
|
+
getUserInput() {
|
|
24169
|
+
return Radio$1.getUserInputFromProps(this.props);
|
|
24170
|
+
}
|
|
24171
|
+
simpleValidate(rubric) {
|
|
24172
|
+
return radioValidator(this.getUserInput(), rubric, this.context.strings);
|
|
24173
|
+
}
|
|
24195
24174
|
render() {
|
|
24196
24175
|
const {
|
|
24197
24176
|
choices
|
|
@@ -24468,12 +24447,6 @@ class Categorizer extends React.Component {
|
|
|
24468
24447
|
// @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
|
|
24469
24448
|
return change.apply(this, args);
|
|
24470
24449
|
};
|
|
24471
|
-
this.getUserInput = () => {
|
|
24472
|
-
return Categorizer.getUserInputFromProps(this.props);
|
|
24473
|
-
};
|
|
24474
|
-
this.simpleValidate = rubric => {
|
|
24475
|
-
return categorizerValidator(this.getUserInput(), rubric, this.context.strings);
|
|
24476
|
-
};
|
|
24477
24450
|
}
|
|
24478
24451
|
static validate(userInput, rubric, strings) {
|
|
24479
24452
|
return categorizerValidator(userInput, rubric, strings);
|
|
@@ -24483,6 +24456,9 @@ class Categorizer extends React.Component {
|
|
|
24483
24456
|
values: props.values
|
|
24484
24457
|
};
|
|
24485
24458
|
}
|
|
24459
|
+
getUserInput() {
|
|
24460
|
+
return Categorizer.getUserInputFromProps(this.props);
|
|
24461
|
+
}
|
|
24486
24462
|
onChange(itemNum, catNum) {
|
|
24487
24463
|
const values = [...this.props.values];
|
|
24488
24464
|
// @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'.
|
|
@@ -24490,6 +24466,9 @@ class Categorizer extends React.Component {
|
|
|
24490
24466
|
this.change("values", values);
|
|
24491
24467
|
this.props.trackInteraction();
|
|
24492
24468
|
}
|
|
24469
|
+
simpleValidate(rubric) {
|
|
24470
|
+
return categorizerValidator(this.getUserInput(), rubric, this.context.strings);
|
|
24471
|
+
}
|
|
24493
24472
|
render() {
|
|
24494
24473
|
const self = this;
|
|
24495
24474
|
|
|
@@ -24856,16 +24835,14 @@ var CSProgram$1 = {
|
|
|
24856
24835
|
};
|
|
24857
24836
|
|
|
24858
24837
|
class Definition extends React.Component {
|
|
24859
|
-
constructor(...args) {
|
|
24860
|
-
super(...args);
|
|
24861
|
-
this.getUserInput = () => {
|
|
24862
|
-
return {};
|
|
24863
|
-
};
|
|
24864
|
-
}
|
|
24865
24838
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24866
24839
|
static validate() {
|
|
24867
24840
|
return noopValidator();
|
|
24868
24841
|
}
|
|
24842
|
+
getUserInput() {
|
|
24843
|
+
return {};
|
|
24844
|
+
}
|
|
24845
|
+
|
|
24869
24846
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24870
24847
|
simpleValidate() {
|
|
24871
24848
|
return noopValidator();
|
|
@@ -25002,18 +24979,18 @@ class Dropdown extends React.Component {
|
|
|
25002
24979
|
selected: selected
|
|
25003
24980
|
});
|
|
25004
24981
|
};
|
|
25005
|
-
this.getUserInput = () => {
|
|
25006
|
-
return {
|
|
25007
|
-
value: this.props.selected
|
|
25008
|
-
};
|
|
25009
|
-
};
|
|
25010
|
-
this.simpleValidate = rubric => {
|
|
25011
|
-
return dropdownValidator(this.getUserInput(), rubric);
|
|
25012
|
-
};
|
|
25013
24982
|
}
|
|
25014
24983
|
static validate(userInput, rubric) {
|
|
25015
24984
|
return dropdownValidator(userInput, rubric);
|
|
25016
24985
|
}
|
|
24986
|
+
getUserInput() {
|
|
24987
|
+
return {
|
|
24988
|
+
value: this.props.selected
|
|
24989
|
+
};
|
|
24990
|
+
}
|
|
24991
|
+
simpleValidate(rubric) {
|
|
24992
|
+
return dropdownValidator(this.getUserInput(), rubric);
|
|
24993
|
+
}
|
|
25017
24994
|
render() {
|
|
25018
24995
|
const children = [/*#__PURE__*/React.createElement(OptionItem, {
|
|
25019
24996
|
key: "placeholder",
|
|
@@ -25087,9 +25064,6 @@ class Explanation extends React.Component {
|
|
|
25087
25064
|
});
|
|
25088
25065
|
this.props.trackInteraction();
|
|
25089
25066
|
};
|
|
25090
|
-
this.getUserInput = () => {
|
|
25091
|
-
return {};
|
|
25092
|
-
};
|
|
25093
25067
|
}
|
|
25094
25068
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
25095
25069
|
static validate() {
|
|
@@ -25101,6 +25075,10 @@ class Explanation extends React.Component {
|
|
|
25101
25075
|
componentWillUnmount() {
|
|
25102
25076
|
this._mounted = false;
|
|
25103
25077
|
}
|
|
25078
|
+
getUserInput() {
|
|
25079
|
+
return {};
|
|
25080
|
+
}
|
|
25081
|
+
|
|
25104
25082
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
25105
25083
|
simpleValidate() {
|
|
25106
25084
|
return noopValidator();
|
|
@@ -26724,7 +26702,7 @@ FunctionGrapher.defaultProps = {
|
|
|
26724
26702
|
coords: null,
|
|
26725
26703
|
asymptote: null,
|
|
26726
26704
|
isMobile: false
|
|
26727
|
-
};
|
|
26705
|
+
};
|
|
26728
26706
|
/* Widget and editor. */
|
|
26729
26707
|
class Grapher extends React.Component {
|
|
26730
26708
|
constructor(...args) {
|
|
@@ -26940,49 +26918,41 @@ class Group extends React.Component {
|
|
|
26940
26918
|
this.change = (...args) => {
|
|
26941
26919
|
return change.apply(this, args);
|
|
26942
26920
|
};
|
|
26943
|
-
this.getUserInput = () => {
|
|
26944
|
-
var _this$rendererRef;
|
|
26945
|
-
return (_this$rendererRef = this.rendererRef) == null ? void 0 : _this$rendererRef.getUserInput();
|
|
26946
|
-
};
|
|
26947
26921
|
this.getSerializedState = () => {
|
|
26948
|
-
var _this$
|
|
26949
|
-
return (_this$
|
|
26922
|
+
var _this$rendererRef;
|
|
26923
|
+
return (_this$rendererRef = this.rendererRef) == null ? void 0 : _this$rendererRef.getSerializedState();
|
|
26950
26924
|
};
|
|
26951
26925
|
this.restoreSerializedState = (state, callback) => {
|
|
26952
|
-
var _this$
|
|
26953
|
-
(_this$
|
|
26926
|
+
var _this$rendererRef2;
|
|
26927
|
+
(_this$rendererRef2 = this.rendererRef) == null || _this$rendererRef2.restoreSerializedState(state, callback);
|
|
26954
26928
|
// Tell our renderer that we have no props to change
|
|
26955
26929
|
// (all our changes were in state):
|
|
26956
26930
|
return null;
|
|
26957
26931
|
};
|
|
26958
|
-
this.simpleValidate = rubric => {
|
|
26959
|
-
var _this$rendererRef4;
|
|
26960
|
-
return (_this$rendererRef4 = this.rendererRef) == null ? void 0 : _this$rendererRef4.score();
|
|
26961
|
-
};
|
|
26962
26932
|
// Mobile API:
|
|
26963
26933
|
this.getInputPaths = () => {
|
|
26964
|
-
var _this$
|
|
26965
|
-
return (_this$
|
|
26934
|
+
var _this$rendererRef3;
|
|
26935
|
+
return (_this$rendererRef3 = this.rendererRef) == null ? void 0 : _this$rendererRef3.getInputPaths();
|
|
26966
26936
|
};
|
|
26967
26937
|
this.setInputValue = (path, newValue, callback) => {
|
|
26968
|
-
var _this$
|
|
26969
|
-
return (_this$
|
|
26938
|
+
var _this$rendererRef4;
|
|
26939
|
+
return (_this$rendererRef4 = this.rendererRef) == null ? void 0 : _this$rendererRef4.setInputValue(path, newValue, callback);
|
|
26970
26940
|
};
|
|
26971
26941
|
this.focus = () => {
|
|
26972
|
-
var _this$
|
|
26973
|
-
return (_this$
|
|
26942
|
+
var _this$rendererRef5;
|
|
26943
|
+
return (_this$rendererRef5 = this.rendererRef) == null ? void 0 : _this$rendererRef5.focus();
|
|
26974
26944
|
};
|
|
26975
26945
|
this.focusInputPath = path => {
|
|
26976
|
-
var _this$
|
|
26977
|
-
(_this$
|
|
26946
|
+
var _this$rendererRef6;
|
|
26947
|
+
(_this$rendererRef6 = this.rendererRef) == null || _this$rendererRef6.focusPath(path);
|
|
26978
26948
|
};
|
|
26979
26949
|
this.blurInputPath = path => {
|
|
26980
|
-
var _this$
|
|
26981
|
-
(_this$
|
|
26950
|
+
var _this$rendererRef7;
|
|
26951
|
+
(_this$rendererRef7 = this.rendererRef) == null || _this$rendererRef7.blurPath(path);
|
|
26982
26952
|
};
|
|
26983
26953
|
this.showRationalesForCurrentlySelectedChoices = () => {
|
|
26984
|
-
var _this$
|
|
26985
|
-
(_this$
|
|
26954
|
+
var _this$rendererRef8;
|
|
26955
|
+
(_this$rendererRef8 = this.rendererRef) == null || _this$rendererRef8.showRationalesForCurrentlySelectedChoices();
|
|
26986
26956
|
};
|
|
26987
26957
|
}
|
|
26988
26958
|
componentDidMount() {
|
|
@@ -26991,6 +26961,14 @@ class Group extends React.Component {
|
|
|
26991
26961
|
// the group with the correct number.
|
|
26992
26962
|
this.forceUpdate();
|
|
26993
26963
|
}
|
|
26964
|
+
getUserInput() {
|
|
26965
|
+
var _this$rendererRef9;
|
|
26966
|
+
return (_this$rendererRef9 = this.rendererRef) == null ? void 0 : _this$rendererRef9.getUserInput();
|
|
26967
|
+
}
|
|
26968
|
+
simpleValidate() {
|
|
26969
|
+
var _this$rendererRef10;
|
|
26970
|
+
return (_this$rendererRef10 = this.rendererRef) == null ? void 0 : _this$rendererRef10.score();
|
|
26971
|
+
}
|
|
26994
26972
|
render() {
|
|
26995
26973
|
var _this$rendererRef11;
|
|
26996
26974
|
const apiOptions = _extends({}, ApiOptions.defaults, this.props.apiOptions, {
|
|
@@ -27258,15 +27236,16 @@ class ImageWidget extends React.Component {
|
|
|
27258
27236
|
this.change = (...args) => {
|
|
27259
27237
|
return change.apply(this, args);
|
|
27260
27238
|
};
|
|
27261
|
-
this.getUserInput = () => {
|
|
27262
|
-
return null;
|
|
27263
|
-
};
|
|
27264
27239
|
this.focus = () => {};
|
|
27265
27240
|
}
|
|
27266
27241
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27267
27242
|
static validate() {
|
|
27268
27243
|
return noopValidator();
|
|
27269
27244
|
}
|
|
27245
|
+
getUserInput() {
|
|
27246
|
+
return null;
|
|
27247
|
+
}
|
|
27248
|
+
|
|
27270
27249
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27271
27250
|
simpleValidate() {
|
|
27272
27251
|
return noopValidator();
|
|
@@ -27578,13 +27557,6 @@ class Interaction extends React.Component {
|
|
|
27578
27557
|
this.change = (...args) => {
|
|
27579
27558
|
return change.apply(this, args);
|
|
27580
27559
|
};
|
|
27581
|
-
this.getUserInput = () => {
|
|
27582
|
-
// TODO(eater): Perhaps we want to be able to record the state of the
|
|
27583
|
-
// user's interaction. Unfortunately sending all the props will
|
|
27584
|
-
// probably make the attempt payload too large. So for now, don't send
|
|
27585
|
-
// anything.
|
|
27586
|
-
return {};
|
|
27587
|
-
};
|
|
27588
27560
|
}
|
|
27589
27561
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27590
27562
|
static validate() {
|
|
@@ -27608,6 +27580,14 @@ class Interaction extends React.Component {
|
|
|
27608
27580
|
});
|
|
27609
27581
|
}
|
|
27610
27582
|
}
|
|
27583
|
+
getUserInput() {
|
|
27584
|
+
// TODO(eater): Perhaps we want to be able to record the state of the
|
|
27585
|
+
// user's interaction. Unfortunately sending all the props will
|
|
27586
|
+
// probably make the attempt payload too large. So for now, don't send
|
|
27587
|
+
// anything.
|
|
27588
|
+
return {};
|
|
27589
|
+
}
|
|
27590
|
+
|
|
27611
27591
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27612
27592
|
simpleValidate() {
|
|
27613
27593
|
return noopValidator();
|
|
@@ -29662,7 +29642,7 @@ function GraphLockedLabelsLayer(props) {
|
|
|
29662
29642
|
lockedFigures
|
|
29663
29643
|
} = props;
|
|
29664
29644
|
return lockedFigures.map((figure, i) => {
|
|
29665
|
-
var _flags$mafs, _flags$mafs2;
|
|
29645
|
+
var _flags$mafs, _flags$mafs2, _flags$mafs3, _flags$mafs4, _flags$mafs5;
|
|
29666
29646
|
if (figure.type === "label") {
|
|
29667
29647
|
return /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
29668
29648
|
key: `label-${i}`
|
|
@@ -29672,14 +29652,21 @@ function GraphLockedLabelsLayer(props) {
|
|
|
29672
29652
|
// Point flag + point type
|
|
29673
29653
|
flags != null && (_flags$mafs = flags["mafs"]) != null && _flags$mafs["locked-point-labels"] && figure.type === "point" ||
|
|
29674
29654
|
// Line flag + line type
|
|
29675
|
-
flags != null && (_flags$mafs2 = flags["mafs"]) != null && _flags$mafs2["locked-line-labels"] && figure.type === "line"
|
|
29655
|
+
flags != null && (_flags$mafs2 = flags["mafs"]) != null && _flags$mafs2["locked-line-labels"] && figure.type === "line" ||
|
|
29656
|
+
// Vector flag + vector type
|
|
29657
|
+
flags != null && (_flags$mafs3 = flags["mafs"]) != null && _flags$mafs3["locked-vector-labels"] && figure.type === "vector" ||
|
|
29658
|
+
// Ellipse flag + ellipse type
|
|
29659
|
+
flags != null && (_flags$mafs4 = flags["mafs"]) != null && _flags$mafs4["locked-ellipse-labels"] && figure.type === "ellipse" ||
|
|
29660
|
+
// Function flag + function type
|
|
29661
|
+
flags != null && (_flags$mafs5 = flags["mafs"]) != null && _flags$mafs5["locked-function-labels"] && figure.type === "function") {
|
|
29662
|
+
var _figure$labels, _figure$points$0$labe, _figure$points$1$labe;
|
|
29676
29663
|
return /*#__PURE__*/React.createElement(React.Fragment, {
|
|
29677
29664
|
key: i
|
|
29678
|
-
}, figure.labels.map((label, j) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
29665
|
+
}, (_figure$labels = figure.labels) == null ? void 0 : _figure$labels.map((label, j) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
29679
29666
|
key: `${i}-label-${j}`
|
|
29680
|
-
}, label))), figure.type === "line" && /*#__PURE__*/React.createElement(React.Fragment, null, figure.points[0].labels.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
29667
|
+
}, label))), figure.type === "line" && /*#__PURE__*/React.createElement(React.Fragment, null, (_figure$points$0$labe = figure.points[0].labels) == null ? void 0 : _figure$points$0$labe.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
29681
29668
|
key: `locked-figure-${i}-point-1-label-${k}`
|
|
29682
|
-
}, label))), figure.points[1].labels.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
29669
|
+
}, label))), (_figure$points$1$labe = figure.points[1].labels) == null ? void 0 : _figure$points$1$labe.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
29683
29670
|
key: `locked-figure-${i}-point-2-label-${k}`
|
|
29684
29671
|
}, label)))));
|
|
29685
29672
|
}
|
|
@@ -31777,7 +31764,7 @@ function Protractor() {
|
|
|
31777
31764
|
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
31778
31765
|
// Position the protractor in the center of the graph (horizontally), and
|
|
31779
31766
|
// 95% of the way to the bottom of the graph (vertically).
|
|
31780
|
-
const initialCenter = [lerp(xMin, xMax, 0.5), lerp(yMin, yMax, 0.
|
|
31767
|
+
const initialCenter = [lerp(xMin, xMax, 0.5), lerp(yMin, yMax, 0.25)];
|
|
31781
31768
|
const [center, setCenter] = useState(initialCenter);
|
|
31782
31769
|
const [rotationHandleOffset, setRotationHandleOffset] = useState(centerToRotationHandle);
|
|
31783
31770
|
const draggableRef = useRef(null);
|
|
@@ -31939,6 +31926,9 @@ const MafsGraph = props => {
|
|
|
31939
31926
|
x: viewboxX,
|
|
31940
31927
|
y: viewboxY
|
|
31941
31928
|
};
|
|
31929
|
+
const {
|
|
31930
|
+
strings
|
|
31931
|
+
} = usePerseusI18n();
|
|
31942
31932
|
return /*#__PURE__*/React.createElement(GraphConfigContext.Provider, {
|
|
31943
31933
|
value: {
|
|
31944
31934
|
range: state.range,
|
|
@@ -32053,10 +32043,11 @@ const MafsGraph = props => {
|
|
|
32053
32043
|
top: "50%",
|
|
32054
32044
|
transform: "translateY(-50%)"
|
|
32055
32045
|
}
|
|
32056
|
-
}, /*#__PURE__*/React.createElement(LabelMedium, null,
|
|
32046
|
+
}, /*#__PURE__*/React.createElement(LabelMedium, null, strings.graphKeyboardPrompt))), renderGraphControls({
|
|
32057
32047
|
state,
|
|
32058
32048
|
dispatch,
|
|
32059
|
-
width
|
|
32049
|
+
width,
|
|
32050
|
+
strings
|
|
32060
32051
|
})));
|
|
32061
32052
|
};
|
|
32062
32053
|
const renderPointGraphControls = props => {
|
|
@@ -32065,6 +32056,10 @@ const renderPointGraphControls = props => {
|
|
|
32065
32056
|
showRemovePointButton,
|
|
32066
32057
|
focusedPointIndex
|
|
32067
32058
|
} = props.state;
|
|
32059
|
+
const {
|
|
32060
|
+
strings
|
|
32061
|
+
} = props;
|
|
32062
|
+
const shouldShowRemoveButton = showRemovePointButton && focusedPointIndex !== null;
|
|
32068
32063
|
return /*#__PURE__*/React.createElement(View, {
|
|
32069
32064
|
style: {
|
|
32070
32065
|
flexDirection: "row",
|
|
@@ -32080,7 +32075,7 @@ const renderPointGraphControls = props => {
|
|
|
32080
32075
|
onClick: () => {
|
|
32081
32076
|
props.dispatch(actions.pointGraph.addPoint([0, 0]));
|
|
32082
32077
|
}
|
|
32083
|
-
},
|
|
32078
|
+
}, strings.addPoint), interactionMode === "mouse" && /*#__PURE__*/React.createElement(Button, {
|
|
32084
32079
|
id: REMOVE_BUTTON_ID,
|
|
32085
32080
|
kind: "secondary",
|
|
32086
32081
|
color: "destructive"
|
|
@@ -32090,18 +32085,20 @@ const renderPointGraphControls = props => {
|
|
|
32090
32085
|
tabIndex: -1,
|
|
32091
32086
|
style: {
|
|
32092
32087
|
width: "100%",
|
|
32093
|
-
marginLeft: "20px"
|
|
32088
|
+
marginLeft: "20px",
|
|
32089
|
+
visibility: shouldShowRemoveButton ? "visible" : "hidden"
|
|
32094
32090
|
},
|
|
32095
32091
|
onClick: event => {
|
|
32096
32092
|
props.dispatch(actions.pointGraph.removePoint(props.state.focusedPointIndex));
|
|
32097
32093
|
}
|
|
32098
|
-
},
|
|
32094
|
+
}, strings.removePoint));
|
|
32099
32095
|
};
|
|
32100
32096
|
const renderGraphControls = props => {
|
|
32101
32097
|
const {
|
|
32102
32098
|
state,
|
|
32103
32099
|
dispatch,
|
|
32104
|
-
width
|
|
32100
|
+
width,
|
|
32101
|
+
strings
|
|
32105
32102
|
} = props;
|
|
32106
32103
|
const {
|
|
32107
32104
|
type
|
|
@@ -32112,7 +32109,8 @@ const renderGraphControls = props => {
|
|
|
32112
32109
|
return renderPointGraphControls({
|
|
32113
32110
|
state,
|
|
32114
32111
|
dispatch,
|
|
32115
|
-
width
|
|
32112
|
+
width,
|
|
32113
|
+
strings
|
|
32116
32114
|
});
|
|
32117
32115
|
}
|
|
32118
32116
|
return null;
|
|
@@ -34696,20 +34694,19 @@ class InteractiveGraph extends React.Component {
|
|
|
34696
34694
|
super(...args);
|
|
34697
34695
|
this.legacyGraphRef = /*#__PURE__*/React.createRef();
|
|
34698
34696
|
this.mafsRef = /*#__PURE__*/React.createRef();
|
|
34699
|
-
|
|
34700
|
-
|
|
34701
|
-
|
|
34702
|
-
|
|
34703
|
-
|
|
34704
|
-
|
|
34705
|
-
|
|
34706
|
-
|
|
34707
|
-
|
|
34708
|
-
|
|
34697
|
+
}
|
|
34698
|
+
getUserInput() {
|
|
34699
|
+
var _this$mafsRef$current, _this$legacyGraphRef$;
|
|
34700
|
+
if ((_this$mafsRef$current = this.mafsRef.current) != null && _this$mafsRef$current.getUserInput) {
|
|
34701
|
+
return this.mafsRef.current.getUserInput();
|
|
34702
|
+
}
|
|
34703
|
+
if ((_this$legacyGraphRef$ = this.legacyGraphRef.current) != null && _this$legacyGraphRef$.getUserInput) {
|
|
34704
|
+
return this.legacyGraphRef.current.getUserInput();
|
|
34705
|
+
}
|
|
34706
|
+
throw new PerseusError("Cannot getUserInput from a graph that has never rendered", Errors.NotAllowed);
|
|
34709
34707
|
}
|
|
34710
34708
|
simpleValidate(rubric) {
|
|
34711
|
-
|
|
34712
|
-
return InteractiveGraph.validate((_this$getUserInput = this.getUserInput) == null ? void 0 : _this$getUserInput.call(this), rubric, this);
|
|
34709
|
+
return InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
34713
34710
|
}
|
|
34714
34711
|
render() {
|
|
34715
34712
|
var _this$props$apiOption;
|
|
@@ -36387,6 +36384,57 @@ const styles$h = StyleSheet.create({
|
|
|
36387
36384
|
}
|
|
36388
36385
|
});
|
|
36389
36386
|
|
|
36387
|
+
// Question state for marker as result of user selected answers.
|
|
36388
|
+
|
|
36389
|
+
function scoreMarker(marker) {
|
|
36390
|
+
const score = {
|
|
36391
|
+
hasAnswers: false,
|
|
36392
|
+
isCorrect: false
|
|
36393
|
+
};
|
|
36394
|
+
if (marker.selected && marker.selected.length > 0) {
|
|
36395
|
+
score.hasAnswers = true;
|
|
36396
|
+
}
|
|
36397
|
+
if (marker.answers.length > 0) {
|
|
36398
|
+
if (marker.selected && marker.selected.length === marker.answers.length) {
|
|
36399
|
+
// All correct answers are selected by the user.
|
|
36400
|
+
score.isCorrect = marker.selected.every(choice => marker.answers.includes(choice));
|
|
36401
|
+
}
|
|
36402
|
+
} else if (!marker.selected || marker.selected.length === 0) {
|
|
36403
|
+
// Correct as no answers should be selected by the user.
|
|
36404
|
+
score.isCorrect = true;
|
|
36405
|
+
}
|
|
36406
|
+
return score;
|
|
36407
|
+
}
|
|
36408
|
+
function labelImageValidator(state, rubric) {
|
|
36409
|
+
let numAnswered = 0;
|
|
36410
|
+
let numCorrect = 0;
|
|
36411
|
+
for (const marker of state.markers) {
|
|
36412
|
+
const score = scoreMarker(marker);
|
|
36413
|
+
if (score.hasAnswers) {
|
|
36414
|
+
numAnswered++;
|
|
36415
|
+
}
|
|
36416
|
+
if (score.isCorrect) {
|
|
36417
|
+
numCorrect++;
|
|
36418
|
+
}
|
|
36419
|
+
}
|
|
36420
|
+
|
|
36421
|
+
// We expect all question markers to be answered before grading.
|
|
36422
|
+
if (numAnswered !== state.markers.length) {
|
|
36423
|
+
return {
|
|
36424
|
+
type: "invalid",
|
|
36425
|
+
message: null
|
|
36426
|
+
};
|
|
36427
|
+
}
|
|
36428
|
+
return {
|
|
36429
|
+
type: "points",
|
|
36430
|
+
// Markers with no expected answers are graded as correct if user
|
|
36431
|
+
// makes no answer selection.
|
|
36432
|
+
earned: numCorrect === state.markers.length ? 1 : 0,
|
|
36433
|
+
total: 1,
|
|
36434
|
+
message: null
|
|
36435
|
+
};
|
|
36436
|
+
}
|
|
36437
|
+
|
|
36390
36438
|
const BringToFront = {
|
|
36391
36439
|
boxShadow: `0 8px 8px ${color.offBlack64}`,
|
|
36392
36440
|
zIndex: 1000
|
|
@@ -36645,57 +36693,11 @@ const styles$f = StyleSheet.create({
|
|
|
36645
36693
|
* No diagonals allowed.
|
|
36646
36694
|
*/
|
|
36647
36695
|
|
|
36696
|
+
// TODO: should this be using WidgetProps / PerseusLabelImageWidgetOptions?
|
|
36697
|
+
|
|
36648
36698
|
class LabelImage extends React.Component {
|
|
36649
|
-
static gradeMarker(marker) {
|
|
36650
|
-
const score = {
|
|
36651
|
-
hasAnswers: false,
|
|
36652
|
-
isCorrect: false
|
|
36653
|
-
};
|
|
36654
|
-
if (marker.selected && marker.selected.length > 0) {
|
|
36655
|
-
// @ts-expect-error - TS2540 - Cannot assign to 'hasAnswers' because it is a read-only property.
|
|
36656
|
-
score.hasAnswers = true;
|
|
36657
|
-
}
|
|
36658
|
-
if (marker.answers.length > 0) {
|
|
36659
|
-
if (marker.selected && marker.selected.length === marker.answers.length) {
|
|
36660
|
-
// All correct answers are selected by the user.
|
|
36661
|
-
// @ts-expect-error - TS2540 - Cannot assign to 'isCorrect' because it is a read-only property.
|
|
36662
|
-
score.isCorrect = marker.selected.every(choice => marker.answers.includes(choice));
|
|
36663
|
-
}
|
|
36664
|
-
} else if (!marker.selected || marker.selected.length === 0) {
|
|
36665
|
-
// Correct as no answers should be selected by the user.
|
|
36666
|
-
// @ts-expect-error - TS2540 - Cannot assign to 'isCorrect' because it is a read-only property.
|
|
36667
|
-
score.isCorrect = true;
|
|
36668
|
-
}
|
|
36669
|
-
return score;
|
|
36670
|
-
}
|
|
36671
36699
|
static validate(state, rubric) {
|
|
36672
|
-
|
|
36673
|
-
let numCorrect = 0;
|
|
36674
|
-
for (const marker of state.markers) {
|
|
36675
|
-
const score = LabelImage.gradeMarker(marker);
|
|
36676
|
-
if (score.hasAnswers) {
|
|
36677
|
-
numAnswered++;
|
|
36678
|
-
}
|
|
36679
|
-
if (score.isCorrect) {
|
|
36680
|
-
numCorrect++;
|
|
36681
|
-
}
|
|
36682
|
-
}
|
|
36683
|
-
|
|
36684
|
-
// We expect all question markers to be answered before grading.
|
|
36685
|
-
if (numAnswered !== state.markers.length) {
|
|
36686
|
-
return {
|
|
36687
|
-
type: "invalid",
|
|
36688
|
-
message: null
|
|
36689
|
-
};
|
|
36690
|
-
}
|
|
36691
|
-
return {
|
|
36692
|
-
type: "points",
|
|
36693
|
-
// Markers with no expected answers are graded as correct if user
|
|
36694
|
-
// makes no answer selection.
|
|
36695
|
-
earned: numCorrect === state.markers.length ? 1 : 0,
|
|
36696
|
-
total: 1,
|
|
36697
|
-
message: null
|
|
36698
|
-
};
|
|
36700
|
+
return labelImageValidator(state);
|
|
36699
36701
|
}
|
|
36700
36702
|
|
|
36701
36703
|
/**
|
|
@@ -36893,7 +36895,7 @@ class LabelImage extends React.Component {
|
|
|
36893
36895
|
this._mounted = false;
|
|
36894
36896
|
}
|
|
36895
36897
|
simpleValidate(rubric) {
|
|
36896
|
-
return
|
|
36898
|
+
return labelImageValidator(this.getUserInput());
|
|
36897
36899
|
}
|
|
36898
36900
|
getUserInput() {
|
|
36899
36901
|
const {
|
|
@@ -36911,7 +36913,7 @@ class LabelImage extends React.Component {
|
|
|
36911
36913
|
onChange
|
|
36912
36914
|
} = this.props;
|
|
36913
36915
|
const updatedMarkers = markers.map(marker => {
|
|
36914
|
-
const score =
|
|
36916
|
+
const score = scoreMarker(marker);
|
|
36915
36917
|
return _extends({}, marker, {
|
|
36916
36918
|
// Reveal correctness state for markers with answers.
|
|
36917
36919
|
showCorrectness: score.hasAnswers ? score.isCorrect ? "correct" : "incorrect" : undefined
|
|
@@ -37058,7 +37060,7 @@ class LabelImage extends React.Component {
|
|
|
37058
37060
|
bottom: "top"
|
|
37059
37061
|
}[markerPosition];
|
|
37060
37062
|
}
|
|
37061
|
-
const score =
|
|
37063
|
+
const score = scoreMarker(marker);
|
|
37062
37064
|
// Once the question is answered, show markers
|
|
37063
37065
|
// with correct answers, otherwise passthrough
|
|
37064
37066
|
// the correctness state.
|
|
@@ -37257,9 +37259,7 @@ const LabelImageWithDependencies = /*#__PURE__*/React.forwardRef((props, ref) =>
|
|
|
37257
37259
|
// methods and instead adjust Peresus to provide these facilities through
|
|
37258
37260
|
// instance methods on our Renderers.
|
|
37259
37261
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type
|
|
37260
|
-
LabelImageWithDependencies.validate =
|
|
37261
|
-
// @ts-expect-error - TS2339 - Property 'gradeMarker' does not exist on type
|
|
37262
|
-
LabelImageWithDependencies.gradeMarker = LabelImage.gradeMarker;
|
|
37262
|
+
LabelImageWithDependencies.validate = labelImageValidator;
|
|
37263
37263
|
var LabelImage$1 = {
|
|
37264
37264
|
name: "label-image",
|
|
37265
37265
|
displayName: "Label Image",
|
|
@@ -38039,10 +38039,10 @@ class Matcher extends React.Component {
|
|
|
38039
38039
|
// @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
|
|
38040
38040
|
this.refs.right.moveOptionToIndex(option, index);
|
|
38041
38041
|
};
|
|
38042
|
-
|
|
38043
|
-
|
|
38044
|
-
|
|
38045
|
-
|
|
38042
|
+
}
|
|
38043
|
+
simpleValidate(rubric) {
|
|
38044
|
+
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Matcher'.
|
|
38045
|
+
return Matcher.validate(this.getUserInput(), rubric);
|
|
38046
38046
|
}
|
|
38047
38047
|
render() {
|
|
38048
38048
|
// To minimize layout shift, we display a spinner until our math
|
|
@@ -38406,14 +38406,6 @@ class Matrix extends React.Component {
|
|
|
38406
38406
|
}, cb);
|
|
38407
38407
|
this.props.trackInteraction();
|
|
38408
38408
|
};
|
|
38409
|
-
this.getUserInput = () => {
|
|
38410
|
-
return {
|
|
38411
|
-
answers: this.props.answers
|
|
38412
|
-
};
|
|
38413
|
-
};
|
|
38414
|
-
this.simpleValidate = rubric => {
|
|
38415
|
-
return Matrix.validate(this.getUserInput(), rubric, this.context.strings);
|
|
38416
|
-
};
|
|
38417
38409
|
}
|
|
38418
38410
|
static validate(state, rubric, strings) {
|
|
38419
38411
|
const solution = rubric.answers;
|
|
@@ -38431,7 +38423,9 @@ class Matrix extends React.Component {
|
|
|
38431
38423
|
hasEmptyCell = true;
|
|
38432
38424
|
}
|
|
38433
38425
|
if (!incorrectSize) {
|
|
38434
|
-
const validator = createValidator(
|
|
38426
|
+
const validator = createValidator(
|
|
38427
|
+
// @ts-expect-error - TS2345 - Argument of type 'number' is not assignable to parameter of type 'string'.
|
|
38428
|
+
solution[row][col], {
|
|
38435
38429
|
simplify: true
|
|
38436
38430
|
}, strings);
|
|
38437
38431
|
const result = validator(supplied[row][col]);
|
|
@@ -38470,6 +38464,14 @@ class Matrix extends React.Component {
|
|
|
38470
38464
|
// Used in the `onBlur` and `onFocus` handlers
|
|
38471
38465
|
this.cursorPosition = [0, 0];
|
|
38472
38466
|
}
|
|
38467
|
+
getUserInput() {
|
|
38468
|
+
return {
|
|
38469
|
+
answers: this.props.answers
|
|
38470
|
+
};
|
|
38471
|
+
}
|
|
38472
|
+
simpleValidate(rubric) {
|
|
38473
|
+
return Matrix.validate(this.getUserInput(), rubric, this.context.strings);
|
|
38474
|
+
}
|
|
38473
38475
|
render() {
|
|
38474
38476
|
// Set the input sizes through JS so we can control the size of the
|
|
38475
38477
|
// brackets. (If we set them in CSS we won't know values until the
|
|
@@ -39680,16 +39682,14 @@ class Molecule extends React.Component {
|
|
|
39680
39682
|
}
|
|
39681
39683
|
Molecule.contextType = PerseusI18nContext;
|
|
39682
39684
|
class MoleculeWidget extends React.Component {
|
|
39683
|
-
constructor(...args) {
|
|
39684
|
-
super(...args);
|
|
39685
|
-
this.getUserInput = () => {
|
|
39686
|
-
return [];
|
|
39687
|
-
};
|
|
39688
|
-
}
|
|
39689
39685
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
39690
39686
|
simpleValidate() {
|
|
39691
39687
|
return noopValidator();
|
|
39692
39688
|
}
|
|
39689
|
+
getUserInput() {
|
|
39690
|
+
return [];
|
|
39691
|
+
}
|
|
39692
|
+
|
|
39693
39693
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
39694
39694
|
validate() {
|
|
39695
39695
|
return noopValidator();
|
|
@@ -39837,6 +39837,9 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
|
|
|
39837
39837
|
});
|
|
39838
39838
|
return results;
|
|
39839
39839
|
});
|
|
39840
|
+
|
|
39841
|
+
// TODO: most widgets use some like Widget<Something, PerseusNumberLineWidgetOptions>
|
|
39842
|
+
// should this one?
|
|
39840
39843
|
class NumberLine extends React.Component {
|
|
39841
39844
|
constructor(..._args) {
|
|
39842
39845
|
super(..._args);
|
|
@@ -40116,19 +40119,19 @@ class NumberLine extends React.Component {
|
|
|
40116
40119
|
arrows: "->"
|
|
40117
40120
|
});
|
|
40118
40121
|
};
|
|
40119
|
-
|
|
40120
|
-
|
|
40121
|
-
|
|
40122
|
-
|
|
40123
|
-
|
|
40124
|
-
|
|
40125
|
-
|
|
40126
|
-
};
|
|
40127
|
-
this.simpleValidate = rubric => {
|
|
40128
|
-
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof NumberLine'.
|
|
40129
|
-
return NumberLine.validate(this.getUserInput(), rubric);
|
|
40122
|
+
}
|
|
40123
|
+
getUserInput() {
|
|
40124
|
+
return {
|
|
40125
|
+
numLinePosition: this.props.numLinePosition,
|
|
40126
|
+
rel: this.props.isInequality ? this.props.rel : "eq",
|
|
40127
|
+
numDivisions: this.props.numDivisions,
|
|
40128
|
+
divisionRange: this.props.divisionRange
|
|
40130
40129
|
};
|
|
40131
40130
|
}
|
|
40131
|
+
simpleValidate(rubric) {
|
|
40132
|
+
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof NumberLine'.
|
|
40133
|
+
return NumberLine.validate(this.getUserInput(), rubric);
|
|
40134
|
+
}
|
|
40132
40135
|
render() {
|
|
40133
40136
|
const {
|
|
40134
40137
|
strings
|
|
@@ -40203,6 +40206,8 @@ _.extend(NumberLine, {
|
|
|
40203
40206
|
const correctRel = rubric.correctRel || "eq";
|
|
40204
40207
|
const correctPos = number.equal(state.numLinePosition, rubric.correctX || 0);
|
|
40205
40208
|
const outsideAllowedRange = state.numDivisions > divisionRange[1] || state.numDivisions < divisionRange[0];
|
|
40209
|
+
|
|
40210
|
+
// TODO: I don't think isTickCrtl is a thing anymore
|
|
40206
40211
|
if (state.isTickCrtl && outsideAllowedRange) {
|
|
40207
40212
|
return {
|
|
40208
40213
|
type: "invalid",
|
|
@@ -40459,8 +40464,8 @@ Card.defaultProps = {
|
|
|
40459
40464
|
animating: false,
|
|
40460
40465
|
linterContext: linterContextDefault
|
|
40461
40466
|
};
|
|
40462
|
-
const NORMAL = "normal"
|
|
40463
|
-
|
|
40467
|
+
const NORMAL = "normal";
|
|
40468
|
+
const HORIZONTAL = "horizontal";
|
|
40464
40469
|
class Orderer extends React.Component {
|
|
40465
40470
|
constructor(...args) {
|
|
40466
40471
|
super(...args);
|
|
@@ -40701,17 +40706,6 @@ class Orderer extends React.Component {
|
|
|
40701
40706
|
current: list
|
|
40702
40707
|
});
|
|
40703
40708
|
};
|
|
40704
|
-
this.getUserInput = () => {
|
|
40705
|
-
return {
|
|
40706
|
-
current: _.map(this.props.current, function (v) {
|
|
40707
|
-
return v.content;
|
|
40708
|
-
})
|
|
40709
|
-
};
|
|
40710
|
-
};
|
|
40711
|
-
this.simpleValidate = rubric => {
|
|
40712
|
-
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Orderer'.
|
|
40713
|
-
return Orderer.validate(this.getUserInput(), rubric);
|
|
40714
|
-
};
|
|
40715
40709
|
}
|
|
40716
40710
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
40717
40711
|
if (!_.isEqual(this.props.current, nextProps.current)) {
|
|
@@ -40720,6 +40714,17 @@ class Orderer extends React.Component {
|
|
|
40720
40714
|
});
|
|
40721
40715
|
}
|
|
40722
40716
|
}
|
|
40717
|
+
getUserInput() {
|
|
40718
|
+
return {
|
|
40719
|
+
current: _.map(this.props.current, function (v) {
|
|
40720
|
+
return v.content;
|
|
40721
|
+
})
|
|
40722
|
+
};
|
|
40723
|
+
}
|
|
40724
|
+
simpleValidate(rubric) {
|
|
40725
|
+
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Orderer'.
|
|
40726
|
+
return Orderer.validate(this.getUserInput(), rubric);
|
|
40727
|
+
}
|
|
40723
40728
|
render() {
|
|
40724
40729
|
// This is the card we are currently dragging
|
|
40725
40730
|
const dragging = this.state.dragging && /*#__PURE__*/React.createElement(Card
|
|
@@ -40833,14 +40838,14 @@ Orderer.defaultProps = {
|
|
|
40833
40838
|
linterContext: linterContextDefault
|
|
40834
40839
|
};
|
|
40835
40840
|
_.extend(Orderer, {
|
|
40836
|
-
validate: function (
|
|
40837
|
-
if (
|
|
40841
|
+
validate: function (userInput, rubric) {
|
|
40842
|
+
if (userInput.current.length === 0) {
|
|
40838
40843
|
return {
|
|
40839
40844
|
type: "invalid",
|
|
40840
40845
|
message: null
|
|
40841
40846
|
};
|
|
40842
40847
|
}
|
|
40843
|
-
const correct = _.isEqual(
|
|
40848
|
+
const correct = _.isEqual(userInput.current, _.pluck(rubric.correctOptions, "content"));
|
|
40844
40849
|
return {
|
|
40845
40850
|
type: "points",
|
|
40846
40851
|
earned: correct ? 1 : 0,
|
|
@@ -43039,10 +43044,6 @@ class PassageRefTarget extends React.Component {
|
|
|
43039
43044
|
constructor(..._args) {
|
|
43040
43045
|
super(..._args);
|
|
43041
43046
|
// TODO passage-ref-target isn't interactive; remove
|
|
43042
|
-
this.getUserInput = () => {
|
|
43043
|
-
return;
|
|
43044
|
-
};
|
|
43045
|
-
// TODO passage-ref-target isn't interactive; remove
|
|
43046
43047
|
this.change = (...args) => {
|
|
43047
43048
|
return change.apply(this, args);
|
|
43048
43049
|
};
|
|
@@ -43051,6 +43052,11 @@ class PassageRefTarget extends React.Component {
|
|
|
43051
43052
|
static validate() {
|
|
43052
43053
|
return noopValidator();
|
|
43053
43054
|
}
|
|
43055
|
+
|
|
43056
|
+
// TODO passage-ref-target isn't interactive; remove
|
|
43057
|
+
getUserInput() {
|
|
43058
|
+
return null;
|
|
43059
|
+
}
|
|
43054
43060
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43055
43061
|
simpleValidate() {
|
|
43056
43062
|
return noopValidator();
|
|
@@ -43095,9 +43101,6 @@ var PassageRefTarget$1 = {
|
|
|
43095
43101
|
* This is a PhET simulation widget. It is used for rendering simulations
|
|
43096
43102
|
* from https://phet.colorado.edu/.
|
|
43097
43103
|
*/
|
|
43098
|
-
|
|
43099
|
-
// For returning user input, but currently the PhET widget
|
|
43100
|
-
// does not support accessing user input
|
|
43101
43104
|
// This renders the PhET sim
|
|
43102
43105
|
class PhetSimulation extends React.Component {
|
|
43103
43106
|
constructor(props) {
|
|
@@ -43146,6 +43149,8 @@ class PhetSimulation extends React.Component {
|
|
|
43146
43149
|
await this.updateSimState(this.props.url);
|
|
43147
43150
|
}
|
|
43148
43151
|
}
|
|
43152
|
+
|
|
43153
|
+
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43149
43154
|
getUserInput() {
|
|
43150
43155
|
return null;
|
|
43151
43156
|
}
|
|
@@ -44031,13 +44036,6 @@ class Plotter extends React.Component {
|
|
|
44031
44036
|
});
|
|
44032
44037
|
});
|
|
44033
44038
|
};
|
|
44034
|
-
this.getUserInput = () => {
|
|
44035
|
-
return this.state.values;
|
|
44036
|
-
};
|
|
44037
|
-
this.simpleValidate = rubric => {
|
|
44038
|
-
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Plotter'.
|
|
44039
|
-
return Plotter.validate(this.getUserInput(), rubric);
|
|
44040
|
-
};
|
|
44041
44039
|
}
|
|
44042
44040
|
componentDidMount() {
|
|
44043
44041
|
this._isMounted = true;
|
|
@@ -44062,6 +44060,13 @@ class Plotter extends React.Component {
|
|
|
44062
44060
|
componentWillUnmount() {
|
|
44063
44061
|
this._isMounted = false;
|
|
44064
44062
|
}
|
|
44063
|
+
getUserInput() {
|
|
44064
|
+
return this.state.values;
|
|
44065
|
+
}
|
|
44066
|
+
simpleValidate(rubric) {
|
|
44067
|
+
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Plotter'.
|
|
44068
|
+
return Plotter.validate(this.getUserInput(), rubric);
|
|
44069
|
+
}
|
|
44065
44070
|
render() {
|
|
44066
44071
|
// TODO(kevinb) actually compute the size of the graphie correctly and
|
|
44067
44072
|
// make it that size so we don't have to add extra padding. The value
|
|
@@ -44094,8 +44099,8 @@ Plotter.defaultProps = {
|
|
|
44094
44099
|
labelInterval: 1
|
|
44095
44100
|
};
|
|
44096
44101
|
_.extend(Plotter, {
|
|
44097
|
-
validate: function (
|
|
44098
|
-
if (deepEq(
|
|
44102
|
+
validate: function (userInput, rubric) {
|
|
44103
|
+
if (deepEq(userInput, rubric.starting)) {
|
|
44099
44104
|
return {
|
|
44100
44105
|
type: "invalid",
|
|
44101
44106
|
message: null
|
|
@@ -44103,7 +44108,7 @@ _.extend(Plotter, {
|
|
|
44103
44108
|
}
|
|
44104
44109
|
return {
|
|
44105
44110
|
type: "points",
|
|
44106
|
-
earned: deepEq(
|
|
44111
|
+
earned: deepEq(userInput, rubric.correct) ? 1 : 0,
|
|
44107
44112
|
total: 1,
|
|
44108
44113
|
message: null
|
|
44109
44114
|
};
|
|
@@ -44166,6 +44171,28 @@ var PythonProgram$1 = {
|
|
|
44166
44171
|
widget: PythonProgram
|
|
44167
44172
|
};
|
|
44168
44173
|
|
|
44174
|
+
function sorterValidator(userInput, rubric) {
|
|
44175
|
+
// If the sorter widget hasn't been changed yet, we treat it as "empty" which
|
|
44176
|
+
// prevents the "Check" button from becoming active. We want the user
|
|
44177
|
+
// to make a change before trying to move forward. This makes an
|
|
44178
|
+
// assumption that the initial order isn't the correct order! However,
|
|
44179
|
+
// this should be rare if it happens, and interacting with the list
|
|
44180
|
+
// will enable the button, so they won't be locked out of progressing.
|
|
44181
|
+
if (!userInput.changed) {
|
|
44182
|
+
return {
|
|
44183
|
+
type: "invalid",
|
|
44184
|
+
message: null
|
|
44185
|
+
};
|
|
44186
|
+
}
|
|
44187
|
+
const correct = Util.deepEq(userInput.options, rubric.correct);
|
|
44188
|
+
return {
|
|
44189
|
+
type: "points",
|
|
44190
|
+
earned: correct ? 1 : 0,
|
|
44191
|
+
total: 1,
|
|
44192
|
+
message: null
|
|
44193
|
+
};
|
|
44194
|
+
}
|
|
44195
|
+
|
|
44169
44196
|
const {
|
|
44170
44197
|
shuffle
|
|
44171
44198
|
} = Util;
|
|
@@ -44195,42 +44222,14 @@ class Sorter extends React.Component {
|
|
|
44195
44222
|
}, 0);
|
|
44196
44223
|
});
|
|
44197
44224
|
};
|
|
44198
|
-
this.getUserInput = () => {
|
|
44199
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44200
|
-
// @ts-expect-error - TS2339 - Property 'getOptions' does not exist on type 'ReactInstance'.
|
|
44201
|
-
return {
|
|
44202
|
-
options: this.refs.sortable.getOptions()
|
|
44203
|
-
};
|
|
44204
|
-
};
|
|
44205
44225
|
this.moveOptionToIndex = (option, index) => {
|
|
44206
44226
|
// eslint-disable-next-line react/no-string-refs
|
|
44207
44227
|
// @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
|
|
44208
44228
|
this.refs.sortable.moveOptionToIndex(option, index);
|
|
44209
44229
|
};
|
|
44210
|
-
this.simpleValidate = rubric => {
|
|
44211
|
-
// If this widget hasn't been changed yet, we treat it as "empty" which
|
|
44212
|
-
// prevents the "Check" button from becoming active. We want the user
|
|
44213
|
-
// to make a change before trying to move forward. This makes an
|
|
44214
|
-
// assumption that the initial order isn't the correct order! However,
|
|
44215
|
-
// this should be rare if it happens, and interacting with the list
|
|
44216
|
-
// will enable the button, so they won't be locked out of progressing.
|
|
44217
|
-
if (!this.state.changed) {
|
|
44218
|
-
return {
|
|
44219
|
-
type: "invalid",
|
|
44220
|
-
message: null
|
|
44221
|
-
};
|
|
44222
|
-
}
|
|
44223
|
-
return Sorter.validate(this.getUserInput(), rubric);
|
|
44224
|
-
};
|
|
44225
44230
|
}
|
|
44226
|
-
static validate(
|
|
44227
|
-
|
|
44228
|
-
return {
|
|
44229
|
-
type: "points",
|
|
44230
|
-
earned: correct ? 1 : 0,
|
|
44231
|
-
total: 1,
|
|
44232
|
-
message: null
|
|
44233
|
-
};
|
|
44231
|
+
static validate(userInput, rubric) {
|
|
44232
|
+
return sorterValidator(userInput, rubric);
|
|
44234
44233
|
}
|
|
44235
44234
|
componentDidMount() {
|
|
44236
44235
|
this._isMounted = true;
|
|
@@ -44238,6 +44237,18 @@ class Sorter extends React.Component {
|
|
|
44238
44237
|
componentWillUnmount() {
|
|
44239
44238
|
this._isMounted = false;
|
|
44240
44239
|
}
|
|
44240
|
+
getUserInput() {
|
|
44241
|
+
// eslint-disable-next-line react/no-string-refs
|
|
44242
|
+
// @ts-expect-error - TS2339 - Property 'getOptions' does not exist on type 'ReactInstance'.
|
|
44243
|
+
const options = this.refs.sortable.getOptions();
|
|
44244
|
+
return {
|
|
44245
|
+
options,
|
|
44246
|
+
changed: this.state.changed
|
|
44247
|
+
};
|
|
44248
|
+
}
|
|
44249
|
+
simpleValidate(rubric) {
|
|
44250
|
+
return sorterValidator(this.getUserInput(), rubric);
|
|
44251
|
+
}
|
|
44241
44252
|
render() {
|
|
44242
44253
|
const options = shuffle(this.props.correct, this.props.problemNum, /* ensurePermuted */true);
|
|
44243
44254
|
const {
|
|
@@ -44310,9 +44321,6 @@ class Table extends React.Component {
|
|
|
44310
44321
|
this._getColumns = () => {
|
|
44311
44322
|
return this.props.answers[0].length;
|
|
44312
44323
|
};
|
|
44313
|
-
this.getUserInput = () => {
|
|
44314
|
-
return _.map(this.props.answers, _.clone);
|
|
44315
|
-
};
|
|
44316
44324
|
this.onValueChange = (row, column, eventOrValue) => {
|
|
44317
44325
|
const answers = _.map(this.props.answers, _.clone);
|
|
44318
44326
|
|
|
@@ -44332,10 +44340,6 @@ class Table extends React.Component {
|
|
|
44332
44340
|
headers: headers
|
|
44333
44341
|
});
|
|
44334
44342
|
};
|
|
44335
|
-
this.simpleValidate = rubric => {
|
|
44336
|
-
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Table'.
|
|
44337
|
-
return Table.validate(this.getUserInput(), rubric, this.context.strings);
|
|
44338
|
-
};
|
|
44339
44343
|
this._handleFocus = inputPath => {
|
|
44340
44344
|
this.props.onFocus(inputPath);
|
|
44341
44345
|
};
|
|
@@ -44402,6 +44406,13 @@ class Table extends React.Component {
|
|
|
44402
44406
|
}, cb);
|
|
44403
44407
|
};
|
|
44404
44408
|
}
|
|
44409
|
+
getUserInput() {
|
|
44410
|
+
return _.map(this.props.answers, _.clone);
|
|
44411
|
+
}
|
|
44412
|
+
simpleValidate(rubric) {
|
|
44413
|
+
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Table'.
|
|
44414
|
+
return Table.validate(this.getUserInput(), rubric, this.context.strings);
|
|
44415
|
+
}
|
|
44405
44416
|
render() {
|
|
44406
44417
|
const rows = this._getRows();
|
|
44407
44418
|
const columns = this._getColumns();
|
|
@@ -44770,7 +44781,7 @@ const init = function init(options) {
|
|
|
44770
44781
|
|
|
44771
44782
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44772
44783
|
const libName = "@khanacademy/perseus";
|
|
44773
|
-
const libVersion = "
|
|
44784
|
+
const libVersion = "35.0.0";
|
|
44774
44785
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44775
44786
|
|
|
44776
44787
|
const apiVersion = {
|
|
@@ -45321,9 +45332,6 @@ const defaultContext = {
|
|
|
45321
45332
|
};
|
|
45322
45333
|
const context = /*#__PURE__*/React.createContext(defaultContext);
|
|
45323
45334
|
|
|
45324
|
-
const {
|
|
45325
|
-
mapObject
|
|
45326
|
-
} = objective_;
|
|
45327
45335
|
class ServerItemRenderer extends React.Component {
|
|
45328
45336
|
constructor(props) {
|
|
45329
45337
|
super(props);
|
|
@@ -45543,20 +45551,6 @@ class ServerItemRenderer extends React.Component {
|
|
|
45543
45551
|
return this.questionRenderer.getWidgetIds();
|
|
45544
45552
|
}
|
|
45545
45553
|
|
|
45546
|
-
/**
|
|
45547
|
-
* Returns an object mapping from widget ID to KE-style score.
|
|
45548
|
-
* The keys of this object are the values of the array returned
|
|
45549
|
-
* from `getWidgetIds`.
|
|
45550
|
-
*/
|
|
45551
|
-
scoreWidgets() {
|
|
45552
|
-
const qScore = this.questionRenderer.scoreWidgets();
|
|
45553
|
-
const qGuess = this.questionRenderer.getUserInputForWidgets();
|
|
45554
|
-
const state = this.questionRenderer.getSerializedState();
|
|
45555
|
-
return mapObject(qScore, (score, id) => {
|
|
45556
|
-
return Util.keScoreFromPerseusScore(score, qGuess[id], state);
|
|
45557
|
-
});
|
|
45558
|
-
}
|
|
45559
|
-
|
|
45560
45554
|
/**
|
|
45561
45555
|
* Get a representation of the current state of the item.
|
|
45562
45556
|
*/
|