@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/index.js
CHANGED
|
@@ -366,7 +366,10 @@ const mockStrings = {
|
|
|
366
366
|
cos: "cos",
|
|
367
367
|
tan: "tan",
|
|
368
368
|
simulationLoadFail: "Sorry, this simulation cannot load.",
|
|
369
|
-
simulationLocaleWarning: "Sorry, this simulation isn't available in your language."
|
|
369
|
+
simulationLocaleWarning: "Sorry, this simulation isn't available in your language.",
|
|
370
|
+
addPoint: "Add Point",
|
|
371
|
+
removePoint: "Remove Point",
|
|
372
|
+
graphKeyboardPrompt: "Press Shift + Enter to interact with the graph"
|
|
370
373
|
};
|
|
371
374
|
|
|
372
375
|
/**
|
|
@@ -862,7 +865,7 @@ const denylist = [
|
|
|
862
865
|
// (technically the renderer still adds them)
|
|
863
866
|
"key", "ref",
|
|
864
867
|
// added by src/renderer.jsx
|
|
865
|
-
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "questionCompleted", "findWidgets",
|
|
868
|
+
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "widgetIsOpen", "questionCompleted", "findWidgets",
|
|
866
869
|
// added by src/editor.jsx, for widgets removing themselves
|
|
867
870
|
// this is soooo not the right place for this, but alas.
|
|
868
871
|
"onRemove",
|
|
@@ -870,17 +873,6 @@ const denylist = [
|
|
|
870
873
|
"id",
|
|
871
874
|
// Callbacks and items for interaction handling
|
|
872
875
|
"onBlur", "onFocus", "trackInteraction", "keypadElement"];
|
|
873
|
-
const removeDenylistProps = props => {
|
|
874
|
-
const newProps = {
|
|
875
|
-
...props
|
|
876
|
-
};
|
|
877
|
-
for (const prop of denylist) {
|
|
878
|
-
if (prop in newProps) {
|
|
879
|
-
delete newProps[prop];
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
return newProps;
|
|
883
|
-
};
|
|
884
876
|
|
|
885
877
|
/* eslint-disable @babel/no-invalid-this */
|
|
886
878
|
const USAGE = "Usage:\n" + " this.change({propName: 5}, callback);\n" + ' this.change("propName", 5, callback);\n' + ' this.change("propName")';
|
|
@@ -1142,8 +1134,6 @@ class StubTagEditor extends React__namespace.Component {
|
|
|
1142
1134
|
* * nothing if it is purely a bug fix.
|
|
1143
1135
|
*
|
|
1144
1136
|
* Callbacks passed to Renderer/ItemRenderer:
|
|
1145
|
-
* * onInputError:
|
|
1146
|
-
* Called when there is an error grading a widget
|
|
1147
1137
|
* * onFocusChange: (newFocusPath, oldFocusPath, keypadDOMNode)
|
|
1148
1138
|
* Called when the user focus changes. The first two parameters are `path`
|
|
1149
1139
|
* arrays uniquely identifying the respect inputs. The third parameter,
|
|
@@ -1166,7 +1156,6 @@ class StubTagEditor extends React__namespace.Component {
|
|
|
1166
1156
|
const ApiOptions = {
|
|
1167
1157
|
propTypes: PropTypes__default["default"].shape({
|
|
1168
1158
|
isArticle: PropTypes__default["default"].bool.isRequired,
|
|
1169
|
-
onInputError: PropTypes__default["default"].func.isRequired,
|
|
1170
1159
|
onFocusChange: PropTypes__default["default"].func.isRequired,
|
|
1171
1160
|
GroupMetadataEditor: PropTypes__default["default"].func.isRequired,
|
|
1172
1161
|
showAlignmentOptions: PropTypes__default["default"].bool.isRequired,
|
|
@@ -1250,7 +1239,6 @@ const ApiOptions = {
|
|
|
1250
1239
|
defaults: {
|
|
1251
1240
|
isArticle: false,
|
|
1252
1241
|
isMobile: false,
|
|
1253
|
-
onInputError: function () {},
|
|
1254
1242
|
onFocusChange: function () {},
|
|
1255
1243
|
GroupMetadataEditor: StubTagEditor,
|
|
1256
1244
|
showAlignmentOptions: false,
|
|
@@ -2262,10 +2250,7 @@ const getDecimalSeparator = locale => {
|
|
|
2262
2250
|
* show the user an error. TODO(joel) - what error?
|
|
2263
2251
|
* - Otherwise, pass through the resulting points and message.
|
|
2264
2252
|
*/
|
|
2265
|
-
function expressionValidator(userInput, rubric) {
|
|
2266
|
-
let onInputError = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {};
|
|
2267
|
-
let strings = arguments.length > 3 ? arguments[3] : undefined;
|
|
2268
|
-
let locale = arguments.length > 4 ? arguments[4] : undefined;
|
|
2253
|
+
function expressionValidator(userInput, rubric, strings, locale) {
|
|
2269
2254
|
const options = ___default["default"].clone(rubric);
|
|
2270
2255
|
___default["default"].extend(options, {
|
|
2271
2256
|
decimal_separator: getDecimalSeparator(locale)
|
|
@@ -2365,14 +2350,9 @@ function expressionValidator(userInput, rubric) {
|
|
|
2365
2350
|
};
|
|
2366
2351
|
}
|
|
2367
2352
|
if (matchingAnswerForm.considered === "ungraded") {
|
|
2368
|
-
// We matched an ungraded answer form - return "invalid", which
|
|
2369
|
-
// will let the user try again with no penalty
|
|
2370
|
-
const apiResult = onInputError(null,
|
|
2371
|
-
// Reserved for some widget identifier
|
|
2372
|
-
userInput, matchMessage);
|
|
2373
2353
|
return {
|
|
2374
2354
|
type: "invalid",
|
|
2375
|
-
message:
|
|
2355
|
+
message: matchMessage
|
|
2376
2356
|
};
|
|
2377
2357
|
}
|
|
2378
2358
|
// We matched a graded answer form, so we can now tell the user
|
|
@@ -2422,11 +2402,8 @@ class Expression extends React__namespace.Component {
|
|
|
2422
2402
|
_isMounted = false;
|
|
2423
2403
|
|
|
2424
2404
|
// TODO remove this in favor of just using expressionValidator
|
|
2425
|
-
static validate(userInput, rubric) {
|
|
2426
|
-
|
|
2427
|
-
let strings = arguments.length > 3 ? arguments[3] : undefined;
|
|
2428
|
-
let locale = arguments.length > 4 ? arguments[4] : undefined;
|
|
2429
|
-
return expressionValidator(userInput, rubric, onInputError, strings, locale);
|
|
2405
|
+
static validate(userInput, rubric, strings, locale) {
|
|
2406
|
+
return expressionValidator(userInput, rubric, strings, locale);
|
|
2430
2407
|
}
|
|
2431
2408
|
static getUserInputFromProps(props) {
|
|
2432
2409
|
return normalizeTex(props.value);
|
|
@@ -2487,14 +2464,9 @@ class Expression extends React__namespace.Component {
|
|
|
2487
2464
|
showErrorStyle: false
|
|
2488
2465
|
});
|
|
2489
2466
|
if (!this.parse(this.props.value, this.props).parsed) {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
if (apiResult !== false) {
|
|
2494
|
-
this.setState({
|
|
2495
|
-
invalid: true
|
|
2496
|
-
});
|
|
2497
|
-
}
|
|
2467
|
+
this.setState({
|
|
2468
|
+
invalid: true
|
|
2469
|
+
});
|
|
2498
2470
|
}
|
|
2499
2471
|
}
|
|
2500
2472
|
};
|
|
@@ -2508,12 +2480,12 @@ class Expression extends React__namespace.Component {
|
|
|
2508
2480
|
});
|
|
2509
2481
|
}
|
|
2510
2482
|
};
|
|
2511
|
-
simpleValidate =
|
|
2483
|
+
simpleValidate = _ref => {
|
|
2512
2484
|
let {
|
|
2513
2485
|
scoring,
|
|
2514
2486
|
...rubric
|
|
2515
2487
|
} = _ref;
|
|
2516
|
-
const score = expressionValidator(this.getUserInput(), rubric,
|
|
2488
|
+
const score = expressionValidator(this.getUserInput(), rubric, this.context.strings, this.context.locale);
|
|
2517
2489
|
|
|
2518
2490
|
// "scoring" is a flag that indicates when we are checking answers.
|
|
2519
2491
|
// otherwise, we may just be checking validity after changes.
|
|
@@ -2528,9 +2500,9 @@ class Expression extends React__namespace.Component {
|
|
|
2528
2500
|
}
|
|
2529
2501
|
return score;
|
|
2530
2502
|
};
|
|
2531
|
-
getUserInput
|
|
2503
|
+
getUserInput() {
|
|
2532
2504
|
return Expression.getUserInputFromProps(this.props);
|
|
2533
|
-
}
|
|
2505
|
+
}
|
|
2534
2506
|
change = (() => {
|
|
2535
2507
|
var _this = this;
|
|
2536
2508
|
return function () {
|
|
@@ -14815,7 +14787,7 @@ const pluck = function (table, subKey) {
|
|
|
14815
14787
|
* });
|
|
14816
14788
|
* {a: 2, b: 3}
|
|
14817
14789
|
*/
|
|
14818
|
-
const mapObject$
|
|
14790
|
+
const mapObject$1 = function (obj, lambda) {
|
|
14819
14791
|
const result = {};
|
|
14820
14792
|
___default["default"].each(___default["default"].keys(obj), function (key) {
|
|
14821
14793
|
// @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
|
|
@@ -14841,7 +14813,7 @@ const mapObjectFromArray$1 = function (arr, lambda) {
|
|
|
14841
14813
|
};
|
|
14842
14814
|
var objective_ = {
|
|
14843
14815
|
pluck: pluck,
|
|
14844
|
-
mapObject: mapObject$
|
|
14816
|
+
mapObject: mapObject$1,
|
|
14845
14817
|
mapObjectFromArray: mapObjectFromArray$1
|
|
14846
14818
|
};
|
|
14847
14819
|
|
|
@@ -19789,7 +19761,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
19789
19761
|
}
|
|
19790
19762
|
|
|
19791
19763
|
const {
|
|
19792
|
-
mapObject
|
|
19764
|
+
mapObject,
|
|
19793
19765
|
mapObjectFromArray
|
|
19794
19766
|
} = objective_;
|
|
19795
19767
|
const rContainsNonWhitespace = /\S/;
|
|
@@ -19817,9 +19789,6 @@ const isIdPathPrefix = function (prefixArray, wholeArray) {
|
|
|
19817
19789
|
});
|
|
19818
19790
|
};
|
|
19819
19791
|
|
|
19820
|
-
// The return type for getUserInput. Widgets have full control of what is
|
|
19821
|
-
// returned so it's not easily typed (some widgets return a scalar (string),
|
|
19822
|
-
// some return a custom-built object
|
|
19823
19792
|
/**
|
|
19824
19793
|
* The Widget type represents the common API that the Renderer uses to interact
|
|
19825
19794
|
* with all widgets. All widgets must implement the methods in this API, unless
|
|
@@ -19829,6 +19798,7 @@ const isIdPathPrefix = function (prefixArray, wholeArray) {
|
|
|
19829
19798
|
* communicate with the individual widgets to coordinate actions such as
|
|
19830
19799
|
* scoring, state serialization/deserialization, and focus management.
|
|
19831
19800
|
*/
|
|
19801
|
+
|
|
19832
19802
|
class Renderer extends React__namespace.Component {
|
|
19833
19803
|
_currentFocus;
|
|
19834
19804
|
// @ts-expect-error - TS2564 - Property '_foundTextNodes' has no initializer and is not definitely assigned in the constructor.
|
|
@@ -20025,7 +19995,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20025
19995
|
|
|
20026
19996
|
// @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; }'.
|
|
20027
19997
|
_getAllWidgetsInfo = props => {
|
|
20028
|
-
return mapObject
|
|
19998
|
+
return mapObject(props.widgets, (widgetInfo, widgetId) => {
|
|
20029
19999
|
if (!widgetInfo.type || !widgetInfo.alignment) {
|
|
20030
20000
|
const newValues = {};
|
|
20031
20001
|
if (!widgetInfo.type) {
|
|
@@ -20172,7 +20142,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20172
20142
|
* state from that instead of the current widget props.
|
|
20173
20143
|
*/
|
|
20174
20144
|
getSerializedState = widgetProps => {
|
|
20175
|
-
return mapObject
|
|
20145
|
+
return mapObject(widgetProps || this.state.widgetProps, (props, widgetId) => {
|
|
20176
20146
|
const widget = this.getWidgetInstance(widgetId);
|
|
20177
20147
|
if (widget && widget.getSerializedState) {
|
|
20178
20148
|
return widget.getSerializedState();
|
|
@@ -20208,7 +20178,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20208
20178
|
}
|
|
20209
20179
|
};
|
|
20210
20180
|
this.setState({
|
|
20211
|
-
widgetProps: mapObject
|
|
20181
|
+
widgetProps: mapObject(serializedState, (props, widgetId) => {
|
|
20212
20182
|
const widget = this.getWidgetInstance(widgetId);
|
|
20213
20183
|
if (widget && widget.restoreSerializedState) {
|
|
20214
20184
|
// Note that we probably can't call
|
|
@@ -21083,7 +21053,6 @@ class Renderer extends React__namespace.Component {
|
|
|
21083
21053
|
*/
|
|
21084
21054
|
scoreWidgets = () => {
|
|
21085
21055
|
const widgetProps = this.state.widgetInfo;
|
|
21086
|
-
const onInputError = this.getApiOptions().onInputError;
|
|
21087
21056
|
const gradedWidgetIds = ___default["default"].filter(this.widgetIds, id => {
|
|
21088
21057
|
const props = widgetProps[id];
|
|
21089
21058
|
const widgetIsGraded = props?.graded == null || props.graded;
|
|
@@ -21100,7 +21069,7 @@ class Renderer extends React__namespace.Component {
|
|
|
21100
21069
|
widgetScores[id] = widget.simpleValidate({
|
|
21101
21070
|
...props?.options,
|
|
21102
21071
|
scoring: true
|
|
21103
|
-
}
|
|
21072
|
+
});
|
|
21104
21073
|
}
|
|
21105
21074
|
});
|
|
21106
21075
|
return widgetScores;
|
|
@@ -21973,7 +21942,6 @@ const answerTypes = {
|
|
|
21973
21942
|
}
|
|
21974
21943
|
};
|
|
21975
21944
|
function inputNumberValidator(state, rubric, strings) {
|
|
21976
|
-
let onInputError = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : () => {};
|
|
21977
21945
|
if (rubric.answerType == null) {
|
|
21978
21946
|
rubric.answerType = "number";
|
|
21979
21947
|
}
|
|
@@ -21997,13 +21965,9 @@ function inputNumberValidator(state, rubric, strings) {
|
|
|
21997
21965
|
// TODO(eater): Seems silly to translate result to this invalid/points
|
|
21998
21966
|
// thing and immediately translate it back in ItemRenderer.scoreInput()
|
|
21999
21967
|
if (result.empty) {
|
|
22000
|
-
// TODO(FEI-3867): remove null-check once we have APIOptionsInternal
|
|
22001
|
-
const apiResult = onInputError?.(null,
|
|
22002
|
-
// reserved for some widget identifier
|
|
22003
|
-
state.currentValue, result.message);
|
|
22004
21968
|
return {
|
|
22005
21969
|
type: "invalid",
|
|
22006
|
-
message:
|
|
21970
|
+
message: result.message
|
|
22007
21971
|
};
|
|
22008
21972
|
}
|
|
22009
21973
|
return {
|
|
@@ -22056,8 +22020,7 @@ class InputNumber extends React__namespace.Component {
|
|
|
22056
22020
|
linterContext: PerseusLinter.linterContextDefault
|
|
22057
22021
|
};
|
|
22058
22022
|
static validate(state, rubric, strings) {
|
|
22059
|
-
|
|
22060
|
-
return inputNumberValidator(state, rubric, strings, onInputError);
|
|
22023
|
+
return inputNumberValidator(state, rubric, strings);
|
|
22061
22024
|
}
|
|
22062
22025
|
static getUserInputFromProps(props) {
|
|
22063
22026
|
return {
|
|
@@ -22126,13 +22089,12 @@ class InputNumber extends React__namespace.Component {
|
|
|
22126
22089
|
currentValue: newValue
|
|
22127
22090
|
}, cb);
|
|
22128
22091
|
};
|
|
22129
|
-
getUserInput
|
|
22092
|
+
getUserInput() {
|
|
22130
22093
|
return InputNumber.getUserInputFromProps(this.props);
|
|
22131
|
-
}
|
|
22132
|
-
simpleValidate
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
};
|
|
22094
|
+
}
|
|
22095
|
+
simpleValidate(rubric) {
|
|
22096
|
+
return inputNumberValidator(this.getUserInput(), rubric, this.context.strings);
|
|
22097
|
+
}
|
|
22136
22098
|
examples = () => {
|
|
22137
22099
|
const {
|
|
22138
22100
|
strings
|
|
@@ -22477,9 +22439,9 @@ class NumericInput extends React__namespace.Component {
|
|
|
22477
22439
|
const allFormsAccepted = answerFormNames.length >= Object.keys(formExamples).length;
|
|
22478
22440
|
return !noFormsAccepted && !allFormsAccepted;
|
|
22479
22441
|
};
|
|
22480
|
-
simpleValidate
|
|
22442
|
+
simpleValidate(rubric) {
|
|
22481
22443
|
return numericInputValidator(this.getUserInput(), rubric, this.context.strings);
|
|
22482
|
-
}
|
|
22444
|
+
}
|
|
22483
22445
|
focus = () => {
|
|
22484
22446
|
this.inputRef?.focus();
|
|
22485
22447
|
return true;
|
|
@@ -22506,9 +22468,9 @@ class NumericInput extends React__namespace.Component {
|
|
|
22506
22468
|
currentValue: newValue
|
|
22507
22469
|
}, cb);
|
|
22508
22470
|
};
|
|
22509
|
-
getUserInput
|
|
22471
|
+
getUserInput() {
|
|
22510
22472
|
return NumericInput.getUserInputFromProps(this.props);
|
|
22511
|
-
}
|
|
22473
|
+
}
|
|
22512
22474
|
handleChange = (newValue, cb) => {
|
|
22513
22475
|
this.props.onChange({
|
|
22514
22476
|
currentValue: newValue
|
|
@@ -22695,11 +22657,10 @@ class PassageRef extends React__namespace.Component {
|
|
|
22695
22657
|
this._isMounted = false;
|
|
22696
22658
|
}
|
|
22697
22659
|
|
|
22698
|
-
// TODO(
|
|
22699
|
-
|
|
22700
|
-
|
|
22701
|
-
|
|
22702
|
-
};
|
|
22660
|
+
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
22661
|
+
getUserInput() {
|
|
22662
|
+
return null;
|
|
22663
|
+
}
|
|
22703
22664
|
change = (() => {
|
|
22704
22665
|
var _this = this;
|
|
22705
22666
|
return function () {
|
|
@@ -24143,6 +24104,56 @@ const styles$t = aphrodite.StyleSheet.create({
|
|
|
24143
24104
|
}
|
|
24144
24105
|
});
|
|
24145
24106
|
|
|
24107
|
+
function radioValidator(userInput, rubric, strings) {
|
|
24108
|
+
const numSelected = userInput.choicesSelected.reduce((sum, selected) => {
|
|
24109
|
+
return sum + (selected ? 1 : 0);
|
|
24110
|
+
}, 0);
|
|
24111
|
+
if (numSelected === 0) {
|
|
24112
|
+
return {
|
|
24113
|
+
type: "invalid",
|
|
24114
|
+
message: null
|
|
24115
|
+
};
|
|
24116
|
+
}
|
|
24117
|
+
|
|
24118
|
+
// TODO: should numCorrect actually be on the rubric
|
|
24119
|
+
// instead of the userInput?
|
|
24120
|
+
if (userInput.numCorrect && userInput.numCorrect > 1 && numSelected !== userInput.numCorrect) {
|
|
24121
|
+
return {
|
|
24122
|
+
type: "invalid",
|
|
24123
|
+
message: strings.chooseCorrectNum
|
|
24124
|
+
};
|
|
24125
|
+
// If NOTA and some other answer are checked, ...
|
|
24126
|
+
}
|
|
24127
|
+
|
|
24128
|
+
// TODO: should noneOfTheAboveSelected be replaced with a
|
|
24129
|
+
// combination of choicesSelected and noneOfTheAboveIndex?
|
|
24130
|
+
if (userInput.noneOfTheAboveSelected && numSelected > 1) {
|
|
24131
|
+
return {
|
|
24132
|
+
type: "invalid",
|
|
24133
|
+
message: strings.notNoneOfTheAbove
|
|
24134
|
+
};
|
|
24135
|
+
}
|
|
24136
|
+
const correct = userInput.choicesSelected.every((selected, i) => {
|
|
24137
|
+
let isCorrect;
|
|
24138
|
+
// TODO: should noneOfTheAboveIndex actually be on the rubric
|
|
24139
|
+
// instead of the userInput?
|
|
24140
|
+
if (userInput.noneOfTheAboveIndex === i) {
|
|
24141
|
+
isCorrect = rubric.choices.every((choice, j) => {
|
|
24142
|
+
return i === j || !choice.correct;
|
|
24143
|
+
});
|
|
24144
|
+
} else {
|
|
24145
|
+
isCorrect = !!rubric.choices[i].correct;
|
|
24146
|
+
}
|
|
24147
|
+
return isCorrect === selected;
|
|
24148
|
+
});
|
|
24149
|
+
return {
|
|
24150
|
+
type: "points",
|
|
24151
|
+
earned: correct ? 1 : 0,
|
|
24152
|
+
total: 1,
|
|
24153
|
+
message: null
|
|
24154
|
+
};
|
|
24155
|
+
}
|
|
24156
|
+
|
|
24146
24157
|
// RenderProps is the return type for radio.jsx#transform
|
|
24147
24158
|
|
|
24148
24159
|
class Radio$1 extends React__namespace.Component {
|
|
@@ -24158,46 +24169,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24158
24169
|
showSolutions: "none"
|
|
24159
24170
|
};
|
|
24160
24171
|
static validate(userInput, rubric, strings) {
|
|
24161
|
-
|
|
24162
|
-
return sum + (selected ? 1 : 0);
|
|
24163
|
-
}, 0);
|
|
24164
|
-
if (numSelected === 0) {
|
|
24165
|
-
return {
|
|
24166
|
-
type: "invalid",
|
|
24167
|
-
message: null
|
|
24168
|
-
};
|
|
24169
|
-
}
|
|
24170
|
-
if (userInput.numCorrect && userInput.numCorrect > 1 && numSelected !== userInput.numCorrect) {
|
|
24171
|
-
return {
|
|
24172
|
-
type: "invalid",
|
|
24173
|
-
message: strings.chooseCorrectNum
|
|
24174
|
-
};
|
|
24175
|
-
// If NOTA and some other answer are checked, ...
|
|
24176
|
-
}
|
|
24177
|
-
|
|
24178
|
-
if (userInput.noneOfTheAboveSelected && numSelected > 1) {
|
|
24179
|
-
return {
|
|
24180
|
-
type: "invalid",
|
|
24181
|
-
message: strings.notNoneOfTheAbove
|
|
24182
|
-
};
|
|
24183
|
-
}
|
|
24184
|
-
const correct = userInput.choicesSelected.every((selected, i) => {
|
|
24185
|
-
let isCorrect;
|
|
24186
|
-
if (userInput.noneOfTheAboveIndex === i) {
|
|
24187
|
-
isCorrect = rubric.choices.every((choice, j) => {
|
|
24188
|
-
return i === j || !choice.correct;
|
|
24189
|
-
});
|
|
24190
|
-
} else {
|
|
24191
|
-
isCorrect = !!rubric.choices[i].correct;
|
|
24192
|
-
}
|
|
24193
|
-
return isCorrect === selected;
|
|
24194
|
-
});
|
|
24195
|
-
return {
|
|
24196
|
-
type: "points",
|
|
24197
|
-
earned: correct ? 1 : 0,
|
|
24198
|
-
total: 1,
|
|
24199
|
-
message: null
|
|
24200
|
-
};
|
|
24172
|
+
return radioValidator(userInput, rubric, strings);
|
|
24201
24173
|
}
|
|
24202
24174
|
static getUserInputFromProps(props) {
|
|
24203
24175
|
// Return checked inputs in the form {choicesSelected: [bool]}. (Dear
|
|
@@ -24382,12 +24354,12 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24382
24354
|
});
|
|
24383
24355
|
this.props.trackInteraction();
|
|
24384
24356
|
};
|
|
24385
|
-
getUserInput
|
|
24357
|
+
getUserInput() {
|
|
24386
24358
|
return Radio$1.getUserInputFromProps(this.props);
|
|
24387
|
-
}
|
|
24388
|
-
simpleValidate
|
|
24389
|
-
return
|
|
24390
|
-
}
|
|
24359
|
+
}
|
|
24360
|
+
simpleValidate(rubric) {
|
|
24361
|
+
return radioValidator(this.getUserInput(), rubric, this.context.strings);
|
|
24362
|
+
}
|
|
24391
24363
|
|
|
24392
24364
|
/**
|
|
24393
24365
|
* Turn on rationale display for the currently selected choices. Note that
|
|
@@ -24741,9 +24713,9 @@ class Categorizer extends React__namespace.Component {
|
|
|
24741
24713
|
return change.apply(_this, args);
|
|
24742
24714
|
};
|
|
24743
24715
|
})();
|
|
24744
|
-
getUserInput
|
|
24716
|
+
getUserInput() {
|
|
24745
24717
|
return Categorizer.getUserInputFromProps(this.props);
|
|
24746
|
-
}
|
|
24718
|
+
}
|
|
24747
24719
|
onChange(itemNum, catNum) {
|
|
24748
24720
|
const values = [...this.props.values];
|
|
24749
24721
|
// @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'.
|
|
@@ -24751,9 +24723,9 @@ class Categorizer extends React__namespace.Component {
|
|
|
24751
24723
|
this.change("values", values);
|
|
24752
24724
|
this.props.trackInteraction();
|
|
24753
24725
|
}
|
|
24754
|
-
simpleValidate
|
|
24726
|
+
simpleValidate(rubric) {
|
|
24755
24727
|
return categorizerValidator(this.getUserInput(), rubric, this.context.strings);
|
|
24756
|
-
}
|
|
24728
|
+
}
|
|
24757
24729
|
render() {
|
|
24758
24730
|
const self = this;
|
|
24759
24731
|
|
|
@@ -25127,9 +25099,9 @@ class Definition extends React__namespace.Component {
|
|
|
25127
25099
|
static validate() {
|
|
25128
25100
|
return noopValidator();
|
|
25129
25101
|
}
|
|
25130
|
-
getUserInput
|
|
25102
|
+
getUserInput() {
|
|
25131
25103
|
return {};
|
|
25132
|
-
}
|
|
25104
|
+
}
|
|
25133
25105
|
|
|
25134
25106
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
25135
25107
|
simpleValidate() {
|
|
@@ -25272,14 +25244,14 @@ class Dropdown extends React__namespace.Component {
|
|
|
25272
25244
|
selected: selected
|
|
25273
25245
|
});
|
|
25274
25246
|
};
|
|
25275
|
-
getUserInput
|
|
25247
|
+
getUserInput() {
|
|
25276
25248
|
return {
|
|
25277
25249
|
value: this.props.selected
|
|
25278
25250
|
};
|
|
25279
|
-
}
|
|
25280
|
-
simpleValidate
|
|
25251
|
+
}
|
|
25252
|
+
simpleValidate(rubric) {
|
|
25281
25253
|
return dropdownValidator(this.getUserInput(), rubric);
|
|
25282
|
-
}
|
|
25254
|
+
}
|
|
25283
25255
|
render() {
|
|
25284
25256
|
const children = [/*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
25285
25257
|
key: "placeholder",
|
|
@@ -25370,9 +25342,9 @@ class Explanation extends React__namespace.Component {
|
|
|
25370
25342
|
});
|
|
25371
25343
|
this.props.trackInteraction();
|
|
25372
25344
|
};
|
|
25373
|
-
getUserInput
|
|
25345
|
+
getUserInput() {
|
|
25374
25346
|
return {};
|
|
25375
|
-
}
|
|
25347
|
+
}
|
|
25376
25348
|
|
|
25377
25349
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
25378
25350
|
simpleValidate() {
|
|
@@ -27008,9 +26980,6 @@ class FunctionGrapher extends React__namespace.Component {
|
|
|
27008
26980
|
}), this.props.model && this.renderPlot(), this.props.model && this.renderAsymptote(), this.props.model && points)));
|
|
27009
26981
|
}
|
|
27010
26982
|
}
|
|
27011
|
-
|
|
27012
|
-
// Really this is props.plot, I think
|
|
27013
|
-
|
|
27014
26983
|
/* Widget and editor. */
|
|
27015
26984
|
class Grapher extends React__namespace.Component {
|
|
27016
26985
|
horizHairline;
|
|
@@ -27245,9 +27214,9 @@ class Group extends React__namespace.Component {
|
|
|
27245
27214
|
return change.apply(_this, args);
|
|
27246
27215
|
};
|
|
27247
27216
|
})();
|
|
27248
|
-
getUserInput
|
|
27217
|
+
getUserInput() {
|
|
27249
27218
|
return this.rendererRef?.getUserInput();
|
|
27250
|
-
}
|
|
27219
|
+
}
|
|
27251
27220
|
getSerializedState = () => {
|
|
27252
27221
|
return this.rendererRef?.getSerializedState();
|
|
27253
27222
|
};
|
|
@@ -27257,9 +27226,9 @@ class Group extends React__namespace.Component {
|
|
|
27257
27226
|
// (all our changes were in state):
|
|
27258
27227
|
return null;
|
|
27259
27228
|
};
|
|
27260
|
-
simpleValidate
|
|
27229
|
+
simpleValidate() {
|
|
27261
27230
|
return this.rendererRef?.score();
|
|
27262
|
-
}
|
|
27231
|
+
}
|
|
27263
27232
|
|
|
27264
27233
|
// Mobile API:
|
|
27265
27234
|
getInputPaths = () => {
|
|
@@ -27569,9 +27538,9 @@ class ImageWidget extends React__namespace.Component {
|
|
|
27569
27538
|
return change.apply(_this, args);
|
|
27570
27539
|
};
|
|
27571
27540
|
})();
|
|
27572
|
-
getUserInput
|
|
27541
|
+
getUserInput() {
|
|
27573
27542
|
return null;
|
|
27574
|
-
}
|
|
27543
|
+
}
|
|
27575
27544
|
|
|
27576
27545
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27577
27546
|
simpleValidate() {
|
|
@@ -27914,13 +27883,13 @@ class Interaction extends React__namespace.Component {
|
|
|
27914
27883
|
return change.apply(_this, args);
|
|
27915
27884
|
};
|
|
27916
27885
|
})();
|
|
27917
|
-
getUserInput
|
|
27886
|
+
getUserInput() {
|
|
27918
27887
|
// TODO(eater): Perhaps we want to be able to record the state of the
|
|
27919
27888
|
// user's interaction. Unfortunately sending all the props will
|
|
27920
27889
|
// probably make the attempt payload too large. So for now, don't send
|
|
27921
27890
|
// anything.
|
|
27922
27891
|
return {};
|
|
27923
|
-
}
|
|
27892
|
+
}
|
|
27924
27893
|
|
|
27925
27894
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27926
27895
|
simpleValidate() {
|
|
@@ -29992,14 +29961,20 @@ function GraphLockedLabelsLayer(props) {
|
|
|
29992
29961
|
// Point flag + point type
|
|
29993
29962
|
flags?.["mafs"]?.["locked-point-labels"] && figure.type === "point" ||
|
|
29994
29963
|
// Line flag + line type
|
|
29995
|
-
flags?.["mafs"]?.["locked-line-labels"] && figure.type === "line"
|
|
29964
|
+
flags?.["mafs"]?.["locked-line-labels"] && figure.type === "line" ||
|
|
29965
|
+
// Vector flag + vector type
|
|
29966
|
+
flags?.["mafs"]?.["locked-vector-labels"] && figure.type === "vector" ||
|
|
29967
|
+
// Ellipse flag + ellipse type
|
|
29968
|
+
flags?.["mafs"]?.["locked-ellipse-labels"] && figure.type === "ellipse" ||
|
|
29969
|
+
// Function flag + function type
|
|
29970
|
+
flags?.["mafs"]?.["locked-function-labels"] && figure.type === "function") {
|
|
29996
29971
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, {
|
|
29997
29972
|
key: i
|
|
29998
|
-
}, figure.labels
|
|
29973
|
+
}, figure.labels?.map((label, j) => /*#__PURE__*/React__namespace.createElement(LockedLabel, _extends({
|
|
29999
29974
|
key: `${i}-label-${j}`
|
|
30000
|
-
}, label))), figure.type === "line" && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, figure.points[0].labels
|
|
29975
|
+
}, label))), figure.type === "line" && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, figure.points[0].labels?.map((label, k) => /*#__PURE__*/React__namespace.createElement(LockedLabel, _extends({
|
|
30001
29976
|
key: `locked-figure-${i}-point-1-label-${k}`
|
|
30002
|
-
}, label))), figure.points[1].labels
|
|
29977
|
+
}, label))), figure.points[1].labels?.map((label, k) => /*#__PURE__*/React__namespace.createElement(LockedLabel, _extends({
|
|
30003
29978
|
key: `locked-figure-${i}-point-2-label-${k}`
|
|
30004
29979
|
}, label)))));
|
|
30005
29980
|
}
|
|
@@ -32117,7 +32092,7 @@ function Protractor() {
|
|
|
32117
32092
|
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
32118
32093
|
// Position the protractor in the center of the graph (horizontally), and
|
|
32119
32094
|
// 95% of the way to the bottom of the graph (vertically).
|
|
32120
|
-
const initialCenter = [lerp(xMin, xMax, 0.5), lerp(yMin, yMax, 0.
|
|
32095
|
+
const initialCenter = [lerp(xMin, xMax, 0.5), lerp(yMin, yMax, 0.25)];
|
|
32121
32096
|
const [center, setCenter] = React.useState(initialCenter);
|
|
32122
32097
|
const [rotationHandleOffset, setRotationHandleOffset] = React.useState(centerToRotationHandle);
|
|
32123
32098
|
const draggableRef = React.useRef(null);
|
|
@@ -32278,6 +32253,9 @@ const MafsGraph = props => {
|
|
|
32278
32253
|
x: viewboxX,
|
|
32279
32254
|
y: viewboxY
|
|
32280
32255
|
};
|
|
32256
|
+
const {
|
|
32257
|
+
strings
|
|
32258
|
+
} = usePerseusI18n();
|
|
32281
32259
|
return /*#__PURE__*/React__namespace.createElement(GraphConfigContext.Provider, {
|
|
32282
32260
|
value: {
|
|
32283
32261
|
range: state.range,
|
|
@@ -32392,10 +32370,11 @@ const MafsGraph = props => {
|
|
|
32392
32370
|
top: "50%",
|
|
32393
32371
|
transform: "translateY(-50%)"
|
|
32394
32372
|
}
|
|
32395
|
-
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, null,
|
|
32373
|
+
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, null, strings.graphKeyboardPrompt))), renderGraphControls({
|
|
32396
32374
|
state,
|
|
32397
32375
|
dispatch,
|
|
32398
|
-
width
|
|
32376
|
+
width,
|
|
32377
|
+
strings
|
|
32399
32378
|
})));
|
|
32400
32379
|
};
|
|
32401
32380
|
const renderPointGraphControls = props => {
|
|
@@ -32404,6 +32383,10 @@ const renderPointGraphControls = props => {
|
|
|
32404
32383
|
showRemovePointButton,
|
|
32405
32384
|
focusedPointIndex
|
|
32406
32385
|
} = props.state;
|
|
32386
|
+
const {
|
|
32387
|
+
strings
|
|
32388
|
+
} = props;
|
|
32389
|
+
const shouldShowRemoveButton = showRemovePointButton && focusedPointIndex !== null;
|
|
32407
32390
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
32408
32391
|
style: {
|
|
32409
32392
|
flexDirection: "row",
|
|
@@ -32419,7 +32402,7 @@ const renderPointGraphControls = props => {
|
|
|
32419
32402
|
onClick: () => {
|
|
32420
32403
|
props.dispatch(actions.pointGraph.addPoint([0, 0]));
|
|
32421
32404
|
}
|
|
32422
|
-
},
|
|
32405
|
+
}, strings.addPoint), interactionMode === "mouse" && /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
32423
32406
|
id: REMOVE_BUTTON_ID,
|
|
32424
32407
|
kind: "secondary",
|
|
32425
32408
|
color: "destructive"
|
|
@@ -32429,18 +32412,20 @@ const renderPointGraphControls = props => {
|
|
|
32429
32412
|
tabIndex: -1,
|
|
32430
32413
|
style: {
|
|
32431
32414
|
width: "100%",
|
|
32432
|
-
marginLeft: "20px"
|
|
32415
|
+
marginLeft: "20px",
|
|
32416
|
+
visibility: shouldShowRemoveButton ? "visible" : "hidden"
|
|
32433
32417
|
},
|
|
32434
32418
|
onClick: event => {
|
|
32435
32419
|
props.dispatch(actions.pointGraph.removePoint(props.state.focusedPointIndex));
|
|
32436
32420
|
}
|
|
32437
|
-
},
|
|
32421
|
+
}, strings.removePoint));
|
|
32438
32422
|
};
|
|
32439
32423
|
const renderGraphControls = props => {
|
|
32440
32424
|
const {
|
|
32441
32425
|
state,
|
|
32442
32426
|
dispatch,
|
|
32443
|
-
width
|
|
32427
|
+
width,
|
|
32428
|
+
strings
|
|
32444
32429
|
} = props;
|
|
32445
32430
|
const {
|
|
32446
32431
|
type
|
|
@@ -32451,7 +32436,8 @@ const renderGraphControls = props => {
|
|
|
32451
32436
|
return renderPointGraphControls({
|
|
32452
32437
|
state,
|
|
32453
32438
|
dispatch,
|
|
32454
|
-
width
|
|
32439
|
+
width,
|
|
32440
|
+
strings
|
|
32455
32441
|
});
|
|
32456
32442
|
}
|
|
32457
32443
|
return null;
|
|
@@ -35069,17 +35055,17 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
35069
35055
|
type: "linear"
|
|
35070
35056
|
}
|
|
35071
35057
|
};
|
|
35072
|
-
getUserInput
|
|
35073
|
-
if (this.mafsRef.current) {
|
|
35074
|
-
return this.mafsRef.current.getUserInput
|
|
35058
|
+
getUserInput() {
|
|
35059
|
+
if (this.mafsRef.current?.getUserInput) {
|
|
35060
|
+
return this.mafsRef.current.getUserInput();
|
|
35075
35061
|
}
|
|
35076
|
-
if (this.legacyGraphRef.current) {
|
|
35062
|
+
if (this.legacyGraphRef.current?.getUserInput) {
|
|
35077
35063
|
return this.legacyGraphRef.current.getUserInput();
|
|
35078
35064
|
}
|
|
35079
35065
|
throw new perseusCore.PerseusError("Cannot getUserInput from a graph that has never rendered", perseusCore.Errors.NotAllowed);
|
|
35080
|
-
}
|
|
35066
|
+
}
|
|
35081
35067
|
simpleValidate(rubric) {
|
|
35082
|
-
return InteractiveGraph.validate(this.getUserInput
|
|
35068
|
+
return InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
35083
35069
|
}
|
|
35084
35070
|
render() {
|
|
35085
35071
|
// Mafs shim
|
|
@@ -36746,6 +36732,57 @@ const styles$h = aphrodite.StyleSheet.create({
|
|
|
36746
36732
|
}
|
|
36747
36733
|
});
|
|
36748
36734
|
|
|
36735
|
+
// Question state for marker as result of user selected answers.
|
|
36736
|
+
|
|
36737
|
+
function scoreMarker(marker) {
|
|
36738
|
+
const score = {
|
|
36739
|
+
hasAnswers: false,
|
|
36740
|
+
isCorrect: false
|
|
36741
|
+
};
|
|
36742
|
+
if (marker.selected && marker.selected.length > 0) {
|
|
36743
|
+
score.hasAnswers = true;
|
|
36744
|
+
}
|
|
36745
|
+
if (marker.answers.length > 0) {
|
|
36746
|
+
if (marker.selected && marker.selected.length === marker.answers.length) {
|
|
36747
|
+
// All correct answers are selected by the user.
|
|
36748
|
+
score.isCorrect = marker.selected.every(choice => marker.answers.includes(choice));
|
|
36749
|
+
}
|
|
36750
|
+
} else if (!marker.selected || marker.selected.length === 0) {
|
|
36751
|
+
// Correct as no answers should be selected by the user.
|
|
36752
|
+
score.isCorrect = true;
|
|
36753
|
+
}
|
|
36754
|
+
return score;
|
|
36755
|
+
}
|
|
36756
|
+
function labelImageValidator(state, rubric) {
|
|
36757
|
+
let numAnswered = 0;
|
|
36758
|
+
let numCorrect = 0;
|
|
36759
|
+
for (const marker of state.markers) {
|
|
36760
|
+
const score = scoreMarker(marker);
|
|
36761
|
+
if (score.hasAnswers) {
|
|
36762
|
+
numAnswered++;
|
|
36763
|
+
}
|
|
36764
|
+
if (score.isCorrect) {
|
|
36765
|
+
numCorrect++;
|
|
36766
|
+
}
|
|
36767
|
+
}
|
|
36768
|
+
|
|
36769
|
+
// We expect all question markers to be answered before grading.
|
|
36770
|
+
if (numAnswered !== state.markers.length) {
|
|
36771
|
+
return {
|
|
36772
|
+
type: "invalid",
|
|
36773
|
+
message: null
|
|
36774
|
+
};
|
|
36775
|
+
}
|
|
36776
|
+
return {
|
|
36777
|
+
type: "points",
|
|
36778
|
+
// Markers with no expected answers are graded as correct if user
|
|
36779
|
+
// makes no answer selection.
|
|
36780
|
+
earned: numCorrect === state.markers.length ? 1 : 0,
|
|
36781
|
+
total: 1,
|
|
36782
|
+
message: null
|
|
36783
|
+
};
|
|
36784
|
+
}
|
|
36785
|
+
|
|
36749
36786
|
const BringToFront = {
|
|
36750
36787
|
boxShadow: `0 8px 8px ${wonderBlocksTokens.color.offBlack64}`,
|
|
36751
36788
|
zIndex: 1000
|
|
@@ -37006,61 +37043,15 @@ const styles$f = aphrodite.StyleSheet.create({
|
|
|
37006
37043
|
* No diagonals allowed.
|
|
37007
37044
|
*/
|
|
37008
37045
|
|
|
37046
|
+
// TODO: should this be using WidgetProps / PerseusLabelImageWidgetOptions?
|
|
37047
|
+
|
|
37009
37048
|
class LabelImage extends React__namespace.Component {
|
|
37010
37049
|
static contextType = PerseusI18nContext;
|
|
37011
37050
|
// The rendered markers on the question image for labeling.
|
|
37012
37051
|
_markers;
|
|
37013
37052
|
_mounted = false;
|
|
37014
|
-
static gradeMarker(marker) {
|
|
37015
|
-
const score = {
|
|
37016
|
-
hasAnswers: false,
|
|
37017
|
-
isCorrect: false
|
|
37018
|
-
};
|
|
37019
|
-
if (marker.selected && marker.selected.length > 0) {
|
|
37020
|
-
// @ts-expect-error - TS2540 - Cannot assign to 'hasAnswers' because it is a read-only property.
|
|
37021
|
-
score.hasAnswers = true;
|
|
37022
|
-
}
|
|
37023
|
-
if (marker.answers.length > 0) {
|
|
37024
|
-
if (marker.selected && marker.selected.length === marker.answers.length) {
|
|
37025
|
-
// All correct answers are selected by the user.
|
|
37026
|
-
// @ts-expect-error - TS2540 - Cannot assign to 'isCorrect' because it is a read-only property.
|
|
37027
|
-
score.isCorrect = marker.selected.every(choice => marker.answers.includes(choice));
|
|
37028
|
-
}
|
|
37029
|
-
} else if (!marker.selected || marker.selected.length === 0) {
|
|
37030
|
-
// Correct as no answers should be selected by the user.
|
|
37031
|
-
// @ts-expect-error - TS2540 - Cannot assign to 'isCorrect' because it is a read-only property.
|
|
37032
|
-
score.isCorrect = true;
|
|
37033
|
-
}
|
|
37034
|
-
return score;
|
|
37035
|
-
}
|
|
37036
37053
|
static validate(state, rubric) {
|
|
37037
|
-
|
|
37038
|
-
let numCorrect = 0;
|
|
37039
|
-
for (const marker of state.markers) {
|
|
37040
|
-
const score = LabelImage.gradeMarker(marker);
|
|
37041
|
-
if (score.hasAnswers) {
|
|
37042
|
-
numAnswered++;
|
|
37043
|
-
}
|
|
37044
|
-
if (score.isCorrect) {
|
|
37045
|
-
numCorrect++;
|
|
37046
|
-
}
|
|
37047
|
-
}
|
|
37048
|
-
|
|
37049
|
-
// We expect all question markers to be answered before grading.
|
|
37050
|
-
if (numAnswered !== state.markers.length) {
|
|
37051
|
-
return {
|
|
37052
|
-
type: "invalid",
|
|
37053
|
-
message: null
|
|
37054
|
-
};
|
|
37055
|
-
}
|
|
37056
|
-
return {
|
|
37057
|
-
type: "points",
|
|
37058
|
-
// Markers with no expected answers are graded as correct if user
|
|
37059
|
-
// makes no answer selection.
|
|
37060
|
-
earned: numCorrect === state.markers.length ? 1 : 0,
|
|
37061
|
-
total: 1,
|
|
37062
|
-
message: null
|
|
37063
|
-
};
|
|
37054
|
+
return labelImageValidator(state);
|
|
37064
37055
|
}
|
|
37065
37056
|
|
|
37066
37057
|
/**
|
|
@@ -37255,7 +37246,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
37255
37246
|
this._mounted = false;
|
|
37256
37247
|
}
|
|
37257
37248
|
simpleValidate(rubric) {
|
|
37258
|
-
return
|
|
37249
|
+
return labelImageValidator(this.getUserInput());
|
|
37259
37250
|
}
|
|
37260
37251
|
getUserInput() {
|
|
37261
37252
|
const {
|
|
@@ -37273,7 +37264,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
37273
37264
|
onChange
|
|
37274
37265
|
} = this.props;
|
|
37275
37266
|
const updatedMarkers = markers.map(marker => {
|
|
37276
|
-
const score =
|
|
37267
|
+
const score = scoreMarker(marker);
|
|
37277
37268
|
return {
|
|
37278
37269
|
...marker,
|
|
37279
37270
|
// Reveal correctness state for markers with answers.
|
|
@@ -37422,7 +37413,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
37422
37413
|
bottom: "top"
|
|
37423
37414
|
}[markerPosition];
|
|
37424
37415
|
}
|
|
37425
|
-
const score =
|
|
37416
|
+
const score = scoreMarker(marker);
|
|
37426
37417
|
// Once the question is answered, show markers
|
|
37427
37418
|
// with correct answers, otherwise passthrough
|
|
37428
37419
|
// the correctness state.
|
|
@@ -37628,9 +37619,7 @@ const LabelImageWithDependencies = /*#__PURE__*/React__namespace.forwardRef((pro
|
|
|
37628
37619
|
// methods and instead adjust Peresus to provide these facilities through
|
|
37629
37620
|
// instance methods on our Renderers.
|
|
37630
37621
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type
|
|
37631
|
-
LabelImageWithDependencies.validate =
|
|
37632
|
-
// @ts-expect-error - TS2339 - Property 'gradeMarker' does not exist on type
|
|
37633
|
-
LabelImageWithDependencies.gradeMarker = LabelImage.gradeMarker;
|
|
37622
|
+
LabelImageWithDependencies.validate = labelImageValidator;
|
|
37634
37623
|
var LabelImage$1 = {
|
|
37635
37624
|
name: "label-image",
|
|
37636
37625
|
displayName: "Label Image",
|
|
@@ -38419,10 +38408,10 @@ class Matcher extends React__namespace.Component {
|
|
|
38419
38408
|
// @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
|
|
38420
38409
|
this.refs.right.moveOptionToIndex(option, index);
|
|
38421
38410
|
};
|
|
38422
|
-
simpleValidate
|
|
38411
|
+
simpleValidate(rubric) {
|
|
38423
38412
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Matcher'.
|
|
38424
38413
|
return Matcher.validate(this.getUserInput(), rubric);
|
|
38425
|
-
}
|
|
38414
|
+
}
|
|
38426
38415
|
render() {
|
|
38427
38416
|
// To minimize layout shift, we display a spinner until our math
|
|
38428
38417
|
// renderer is ready to render the math inside the matcher. To
|
|
@@ -38665,7 +38654,9 @@ class Matrix extends React__namespace.Component {
|
|
|
38665
38654
|
hasEmptyCell = true;
|
|
38666
38655
|
}
|
|
38667
38656
|
if (!incorrectSize) {
|
|
38668
|
-
const validator = createValidator(
|
|
38657
|
+
const validator = createValidator(
|
|
38658
|
+
// @ts-expect-error - TS2345 - Argument of type 'number' is not assignable to parameter of type 'string'.
|
|
38659
|
+
solution[row][col], {
|
|
38669
38660
|
simplify: true
|
|
38670
38661
|
}, strings);
|
|
38671
38662
|
const result = validator(supplied[row][col]);
|
|
@@ -38837,14 +38828,14 @@ class Matrix extends React__namespace.Component {
|
|
|
38837
38828
|
}, cb);
|
|
38838
38829
|
this.props.trackInteraction();
|
|
38839
38830
|
};
|
|
38840
|
-
getUserInput
|
|
38831
|
+
getUserInput() {
|
|
38841
38832
|
return {
|
|
38842
38833
|
answers: this.props.answers
|
|
38843
38834
|
};
|
|
38844
|
-
}
|
|
38845
|
-
simpleValidate
|
|
38835
|
+
}
|
|
38836
|
+
simpleValidate(rubric) {
|
|
38846
38837
|
return Matrix.validate(this.getUserInput(), rubric, this.context.strings);
|
|
38847
|
-
}
|
|
38838
|
+
}
|
|
38848
38839
|
render() {
|
|
38849
38840
|
// Set the input sizes through JS so we can control the size of the
|
|
38850
38841
|
// brackets. (If we set them in CSS we won't know values until the
|
|
@@ -40057,9 +40048,9 @@ class MoleculeWidget extends React__namespace.Component {
|
|
|
40057
40048
|
simpleValidate() {
|
|
40058
40049
|
return noopValidator();
|
|
40059
40050
|
}
|
|
40060
|
-
getUserInput
|
|
40051
|
+
getUserInput() {
|
|
40061
40052
|
return [];
|
|
40062
|
-
}
|
|
40053
|
+
}
|
|
40063
40054
|
|
|
40064
40055
|
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
40065
40056
|
validate() {
|
|
@@ -40205,6 +40196,9 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
|
|
|
40205
40196
|
});
|
|
40206
40197
|
return results;
|
|
40207
40198
|
});
|
|
40199
|
+
|
|
40200
|
+
// TODO: most widgets use some like Widget<Something, PerseusNumberLineWidgetOptions>
|
|
40201
|
+
// should this one?
|
|
40208
40202
|
class NumberLine extends React__namespace.Component {
|
|
40209
40203
|
static contextType = PerseusI18nContext;
|
|
40210
40204
|
static defaultProps = {
|
|
@@ -40506,18 +40500,18 @@ class NumberLine extends React__namespace.Component {
|
|
|
40506
40500
|
arrows: "->"
|
|
40507
40501
|
});
|
|
40508
40502
|
};
|
|
40509
|
-
getUserInput
|
|
40503
|
+
getUserInput() {
|
|
40510
40504
|
return {
|
|
40511
40505
|
numLinePosition: this.props.numLinePosition,
|
|
40512
40506
|
rel: this.props.isInequality ? this.props.rel : "eq",
|
|
40513
40507
|
numDivisions: this.props.numDivisions,
|
|
40514
40508
|
divisionRange: this.props.divisionRange
|
|
40515
40509
|
};
|
|
40516
|
-
}
|
|
40517
|
-
simpleValidate
|
|
40510
|
+
}
|
|
40511
|
+
simpleValidate(rubric) {
|
|
40518
40512
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof NumberLine'.
|
|
40519
40513
|
return NumberLine.validate(this.getUserInput(), rubric);
|
|
40520
|
-
}
|
|
40514
|
+
}
|
|
40521
40515
|
render() {
|
|
40522
40516
|
const {
|
|
40523
40517
|
strings
|
|
@@ -40577,6 +40571,8 @@ ___default["default"].extend(NumberLine, {
|
|
|
40577
40571
|
const correctRel = rubric.correctRel || "eq";
|
|
40578
40572
|
const correctPos = kmath.number.equal(state.numLinePosition, rubric.correctX || 0);
|
|
40579
40573
|
const outsideAllowedRange = state.numDivisions > divisionRange[1] || state.numDivisions < divisionRange[0];
|
|
40574
|
+
|
|
40575
|
+
// TODO: I don't think isTickCrtl is a thing anymore
|
|
40580
40576
|
if (state.isTickCrtl && outsideAllowedRange) {
|
|
40581
40577
|
return {
|
|
40582
40578
|
type: "invalid",
|
|
@@ -40829,8 +40825,8 @@ class Card extends React__namespace.Component {
|
|
|
40829
40825
|
}))));
|
|
40830
40826
|
}
|
|
40831
40827
|
}
|
|
40832
|
-
const NORMAL = "normal"
|
|
40833
|
-
|
|
40828
|
+
const NORMAL = "normal";
|
|
40829
|
+
const HORIZONTAL = "horizontal";
|
|
40834
40830
|
class Orderer extends React__namespace.Component {
|
|
40835
40831
|
static defaultProps = {
|
|
40836
40832
|
current: [],
|
|
@@ -41085,17 +41081,17 @@ class Orderer extends React__namespace.Component {
|
|
|
41085
41081
|
current: list
|
|
41086
41082
|
});
|
|
41087
41083
|
};
|
|
41088
|
-
getUserInput
|
|
41084
|
+
getUserInput() {
|
|
41089
41085
|
return {
|
|
41090
41086
|
current: ___default["default"].map(this.props.current, function (v) {
|
|
41091
41087
|
return v.content;
|
|
41092
41088
|
})
|
|
41093
41089
|
};
|
|
41094
|
-
}
|
|
41095
|
-
simpleValidate
|
|
41090
|
+
}
|
|
41091
|
+
simpleValidate(rubric) {
|
|
41096
41092
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Orderer'.
|
|
41097
41093
|
return Orderer.validate(this.getUserInput(), rubric);
|
|
41098
|
-
}
|
|
41094
|
+
}
|
|
41099
41095
|
render() {
|
|
41100
41096
|
// This is the card we are currently dragging
|
|
41101
41097
|
const dragging = this.state.dragging && /*#__PURE__*/React__namespace.createElement(Card
|
|
@@ -41201,14 +41197,14 @@ class Orderer extends React__namespace.Component {
|
|
|
41201
41197
|
}
|
|
41202
41198
|
}
|
|
41203
41199
|
___default["default"].extend(Orderer, {
|
|
41204
|
-
validate: function (
|
|
41205
|
-
if (
|
|
41200
|
+
validate: function (userInput, rubric) {
|
|
41201
|
+
if (userInput.current.length === 0) {
|
|
41206
41202
|
return {
|
|
41207
41203
|
type: "invalid",
|
|
41208
41204
|
message: null
|
|
41209
41205
|
};
|
|
41210
41206
|
}
|
|
41211
|
-
const correct = ___default["default"].isEqual(
|
|
41207
|
+
const correct = ___default["default"].isEqual(userInput.current, ___default["default"].pluck(rubric.correctOptions, "content"));
|
|
41212
41208
|
return {
|
|
41213
41209
|
type: "points",
|
|
41214
41210
|
earned: correct ? 1 : 0,
|
|
@@ -43418,9 +43414,9 @@ class PassageRefTarget extends React__namespace.Component {
|
|
|
43418
43414
|
}
|
|
43419
43415
|
|
|
43420
43416
|
// TODO passage-ref-target isn't interactive; remove
|
|
43421
|
-
getUserInput
|
|
43422
|
-
return;
|
|
43423
|
-
}
|
|
43417
|
+
getUserInput() {
|
|
43418
|
+
return null;
|
|
43419
|
+
}
|
|
43424
43420
|
|
|
43425
43421
|
// TODO passage-ref-target isn't interactive; remove
|
|
43426
43422
|
change = (() => {
|
|
@@ -43472,9 +43468,6 @@ var PassageRefTarget$1 = {
|
|
|
43472
43468
|
* This is a PhET simulation widget. It is used for rendering simulations
|
|
43473
43469
|
* from https://phet.colorado.edu/.
|
|
43474
43470
|
*/
|
|
43475
|
-
|
|
43476
|
-
// For returning user input, but currently the PhET widget
|
|
43477
|
-
// does not support accessing user input
|
|
43478
43471
|
// This renders the PhET sim
|
|
43479
43472
|
class PhetSimulation extends React__namespace.Component {
|
|
43480
43473
|
static contextType = PerseusI18nContext;
|
|
@@ -43497,6 +43490,8 @@ class PhetSimulation extends React__namespace.Component {
|
|
|
43497
43490
|
await this.updateSimState(this.props.url);
|
|
43498
43491
|
}
|
|
43499
43492
|
}
|
|
43493
|
+
|
|
43494
|
+
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43500
43495
|
getUserInput() {
|
|
43501
43496
|
return null;
|
|
43502
43497
|
}
|
|
@@ -44446,13 +44441,13 @@ class Plotter extends React__namespace.Component {
|
|
|
44446
44441
|
});
|
|
44447
44442
|
});
|
|
44448
44443
|
};
|
|
44449
|
-
getUserInput
|
|
44444
|
+
getUserInput() {
|
|
44450
44445
|
return this.state.values;
|
|
44451
|
-
}
|
|
44452
|
-
simpleValidate
|
|
44446
|
+
}
|
|
44447
|
+
simpleValidate(rubric) {
|
|
44453
44448
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Plotter'.
|
|
44454
44449
|
return Plotter.validate(this.getUserInput(), rubric);
|
|
44455
|
-
}
|
|
44450
|
+
}
|
|
44456
44451
|
render() {
|
|
44457
44452
|
// TODO(kevinb) actually compute the size of the graphie correctly and
|
|
44458
44453
|
// make it that size so we don't have to add extra padding. The value
|
|
@@ -44471,8 +44466,8 @@ class Plotter extends React__namespace.Component {
|
|
|
44471
44466
|
}
|
|
44472
44467
|
}
|
|
44473
44468
|
___default["default"].extend(Plotter, {
|
|
44474
|
-
validate: function (
|
|
44475
|
-
if (deepEq(
|
|
44469
|
+
validate: function (userInput, rubric) {
|
|
44470
|
+
if (deepEq(userInput, rubric.starting)) {
|
|
44476
44471
|
return {
|
|
44477
44472
|
type: "invalid",
|
|
44478
44473
|
message: null
|
|
@@ -44480,7 +44475,7 @@ ___default["default"].extend(Plotter, {
|
|
|
44480
44475
|
}
|
|
44481
44476
|
return {
|
|
44482
44477
|
type: "points",
|
|
44483
|
-
earned: deepEq(
|
|
44478
|
+
earned: deepEq(userInput, rubric.correct) ? 1 : 0,
|
|
44484
44479
|
total: 1,
|
|
44485
44480
|
message: null
|
|
44486
44481
|
};
|
|
@@ -44543,6 +44538,28 @@ var PythonProgram$1 = {
|
|
|
44543
44538
|
widget: PythonProgram
|
|
44544
44539
|
};
|
|
44545
44540
|
|
|
44541
|
+
function sorterValidator(userInput, rubric) {
|
|
44542
|
+
// If the sorter widget hasn't been changed yet, we treat it as "empty" which
|
|
44543
|
+
// prevents the "Check" button from becoming active. We want the user
|
|
44544
|
+
// to make a change before trying to move forward. This makes an
|
|
44545
|
+
// assumption that the initial order isn't the correct order! However,
|
|
44546
|
+
// this should be rare if it happens, and interacting with the list
|
|
44547
|
+
// will enable the button, so they won't be locked out of progressing.
|
|
44548
|
+
if (!userInput.changed) {
|
|
44549
|
+
return {
|
|
44550
|
+
type: "invalid",
|
|
44551
|
+
message: null
|
|
44552
|
+
};
|
|
44553
|
+
}
|
|
44554
|
+
const correct = Util.deepEq(userInput.options, rubric.correct);
|
|
44555
|
+
return {
|
|
44556
|
+
type: "points",
|
|
44557
|
+
earned: correct ? 1 : 0,
|
|
44558
|
+
total: 1,
|
|
44559
|
+
message: null
|
|
44560
|
+
};
|
|
44561
|
+
}
|
|
44562
|
+
|
|
44546
44563
|
const {
|
|
44547
44564
|
shuffle
|
|
44548
44565
|
} = Util;
|
|
@@ -44556,14 +44573,8 @@ class Sorter extends React__namespace.Component {
|
|
|
44556
44573
|
onChange: function () {},
|
|
44557
44574
|
linterContext: PerseusLinter.linterContextDefault
|
|
44558
44575
|
};
|
|
44559
|
-
static validate(
|
|
44560
|
-
|
|
44561
|
-
return {
|
|
44562
|
-
type: "points",
|
|
44563
|
-
earned: correct ? 1 : 0,
|
|
44564
|
-
total: 1,
|
|
44565
|
-
message: null
|
|
44566
|
-
};
|
|
44576
|
+
static validate(userInput, rubric) {
|
|
44577
|
+
return sorterValidator(userInput, rubric);
|
|
44567
44578
|
}
|
|
44568
44579
|
state = {
|
|
44569
44580
|
changed: false
|
|
@@ -44593,33 +44604,23 @@ class Sorter extends React__namespace.Component {
|
|
|
44593
44604
|
}, 0);
|
|
44594
44605
|
});
|
|
44595
44606
|
};
|
|
44596
|
-
getUserInput
|
|
44607
|
+
getUserInput() {
|
|
44597
44608
|
// eslint-disable-next-line react/no-string-refs
|
|
44598
44609
|
// @ts-expect-error - TS2339 - Property 'getOptions' does not exist on type 'ReactInstance'.
|
|
44610
|
+
const options = this.refs.sortable.getOptions();
|
|
44599
44611
|
return {
|
|
44600
|
-
options
|
|
44612
|
+
options,
|
|
44613
|
+
changed: this.state.changed
|
|
44601
44614
|
};
|
|
44602
|
-
}
|
|
44615
|
+
}
|
|
44603
44616
|
moveOptionToIndex = (option, index) => {
|
|
44604
44617
|
// eslint-disable-next-line react/no-string-refs
|
|
44605
44618
|
// @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
|
|
44606
44619
|
this.refs.sortable.moveOptionToIndex(option, index);
|
|
44607
44620
|
};
|
|
44608
|
-
simpleValidate
|
|
44609
|
-
|
|
44610
|
-
|
|
44611
|
-
// to make a change before trying to move forward. This makes an
|
|
44612
|
-
// assumption that the initial order isn't the correct order! However,
|
|
44613
|
-
// this should be rare if it happens, and interacting with the list
|
|
44614
|
-
// will enable the button, so they won't be locked out of progressing.
|
|
44615
|
-
if (!this.state.changed) {
|
|
44616
|
-
return {
|
|
44617
|
-
type: "invalid",
|
|
44618
|
-
message: null
|
|
44619
|
-
};
|
|
44620
|
-
}
|
|
44621
|
-
return Sorter.validate(this.getUserInput(), rubric);
|
|
44622
|
-
};
|
|
44621
|
+
simpleValidate(rubric) {
|
|
44622
|
+
return sorterValidator(this.getUserInput(), rubric);
|
|
44623
|
+
}
|
|
44623
44624
|
render() {
|
|
44624
44625
|
const options = shuffle(this.props.correct, this.props.problemNum, /* ensurePermuted */true);
|
|
44625
44626
|
const {
|
|
@@ -44699,9 +44700,9 @@ class Table extends React__namespace.Component {
|
|
|
44699
44700
|
_getColumns = () => {
|
|
44700
44701
|
return this.props.answers[0].length;
|
|
44701
44702
|
};
|
|
44702
|
-
getUserInput
|
|
44703
|
+
getUserInput() {
|
|
44703
44704
|
return ___default["default"].map(this.props.answers, ___default["default"].clone);
|
|
44704
|
-
}
|
|
44705
|
+
}
|
|
44705
44706
|
onValueChange = (row, column, eventOrValue) => {
|
|
44706
44707
|
const answers = ___default["default"].map(this.props.answers, ___default["default"].clone);
|
|
44707
44708
|
|
|
@@ -44721,10 +44722,10 @@ class Table extends React__namespace.Component {
|
|
|
44721
44722
|
headers: headers
|
|
44722
44723
|
});
|
|
44723
44724
|
};
|
|
44724
|
-
simpleValidate
|
|
44725
|
+
simpleValidate(rubric) {
|
|
44725
44726
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Table'.
|
|
44726
44727
|
return Table.validate(this.getUserInput(), rubric, this.context.strings);
|
|
44727
|
-
}
|
|
44728
|
+
}
|
|
44728
44729
|
_handleFocus = inputPath => {
|
|
44729
44730
|
this.props.onFocus(inputPath);
|
|
44730
44731
|
};
|
|
@@ -45144,7 +45145,7 @@ const init = function (options) {
|
|
|
45144
45145
|
|
|
45145
45146
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45146
45147
|
const libName = "@khanacademy/perseus";
|
|
45147
|
-
const libVersion = "
|
|
45148
|
+
const libVersion = "35.0.0";
|
|
45148
45149
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45149
45150
|
|
|
45150
45151
|
const apiVersion = {
|
|
@@ -45698,9 +45699,6 @@ const defaultContext = {
|
|
|
45698
45699
|
};
|
|
45699
45700
|
const context = /*#__PURE__*/React__namespace.createContext(defaultContext);
|
|
45700
45701
|
|
|
45701
|
-
const {
|
|
45702
|
-
mapObject
|
|
45703
|
-
} = objective_;
|
|
45704
45702
|
class ServerItemRenderer extends React__namespace.Component {
|
|
45705
45703
|
static contextType = PerseusI18nContext;
|
|
45706
45704
|
// @ts-expect-error - TS2564 - Property 'questionRenderer' has no initializer and is not definitely assigned in the constructor.
|
|
@@ -45916,20 +45914,6 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
45916
45914
|
return this.questionRenderer.getWidgetIds();
|
|
45917
45915
|
}
|
|
45918
45916
|
|
|
45919
|
-
/**
|
|
45920
|
-
* Returns an object mapping from widget ID to KE-style score.
|
|
45921
|
-
* The keys of this object are the values of the array returned
|
|
45922
|
-
* from `getWidgetIds`.
|
|
45923
|
-
*/
|
|
45924
|
-
scoreWidgets() {
|
|
45925
|
-
const qScore = this.questionRenderer.scoreWidgets();
|
|
45926
|
-
const qGuess = this.questionRenderer.getUserInputForWidgets();
|
|
45927
|
-
const state = this.questionRenderer.getSerializedState();
|
|
45928
|
-
return mapObject(qScore, (score, id) => {
|
|
45929
|
-
return Util.keScoreFromPerseusScore(score, qGuess[id], state);
|
|
45930
|
-
});
|
|
45931
|
-
}
|
|
45932
|
-
|
|
45933
45917
|
/**
|
|
45934
45918
|
* Get a representation of the current state of the item.
|
|
45935
45919
|
*/
|