@khanacademy/perseus 36.1.2 → 37.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/all-widgets.d.ts +1 -0
- package/dist/basic-widgets.d.ts +1 -0
- package/dist/components/math-input.d.ts +1 -1
- package/dist/es/index.js +447 -612
- package/dist/es/index.js.map +1 -1
- package/dist/extra-widgets.d.ts +1 -0
- package/dist/index.js +412 -588
- package/dist/index.js.map +1 -1
- package/dist/renderer-util.d.ts +8 -0
- package/dist/renderer.d.ts +19 -20
- package/dist/server-item-renderer.d.ts +3 -1
- package/dist/types.d.ts +11 -3
- package/dist/util.d.ts +4 -0
- package/dist/validation.types.d.ts +14 -6
- package/dist/widgets/categorizer/categorizer.d.ts +3 -5
- package/dist/widgets/cs-program/cs-program.d.ts +2 -3
- package/dist/widgets/definition/definition.d.ts +3 -4
- package/dist/widgets/deprecated-standin/deprecated-standin.d.ts +35 -0
- package/dist/widgets/deprecated-standin/index.d.ts +1 -37
- package/dist/widgets/dropdown/dropdown.d.ts +2 -3
- package/dist/widgets/explanation/explanation.d.ts +4 -5
- package/dist/widgets/expression/expression.d.ts +4 -8
- package/dist/widgets/graded-group/graded-group.d.ts +1 -0
- package/dist/widgets/graded-group-set/graded-group-set.d.ts +1 -0
- package/dist/widgets/grapher/grapher.d.ts +2 -3
- package/dist/widgets/group/group.d.ts +8 -5
- package/dist/widgets/iframe/iframe.d.ts +2 -3
- package/dist/widgets/image/image.d.ts +3 -4
- package/dist/widgets/input-number/input-number.d.ts +2 -5
- package/dist/widgets/interaction/interaction.d.ts +3 -4
- package/dist/widgets/interactive-graph.d.ts +2 -4
- package/dist/widgets/label-image/label-image.d.ts +3 -4
- package/dist/widgets/matcher/matcher.d.ts +2 -3
- package/dist/widgets/matrix/matrix.d.ts +3 -5
- package/dist/widgets/measurer/measurer.d.ts +2 -4
- package/dist/widgets/molecule/molecule.d.ts +2 -4
- package/dist/widgets/number-line/number-line.d.ts +3 -4
- package/dist/widgets/numeric-input/numeric-input.d.ts +2 -3
- package/dist/widgets/orderer/orderer.d.ts +2 -3
- package/dist/widgets/passage/passage.d.ts +3 -9
- package/dist/widgets/passage-ref/passage-ref.d.ts +3 -4
- package/dist/widgets/passage-ref-target/passage-ref-target.d.ts +2 -4
- package/dist/widgets/phet-simulation/phet-simulation.d.ts +2 -2
- package/dist/widgets/plotter/plotter.d.ts +2 -3
- package/dist/widgets/python-program/python-program.d.ts +1 -0
- package/dist/widgets/radio/radio-component.d.ts +2 -5
- package/dist/widgets/radio/radio.d.ts +1 -0
- package/dist/widgets/sorter/sorter.d.ts +2 -3
- package/dist/widgets/table/table.d.ts +3 -5
- package/dist/widgets/video/video.d.ts +2 -8
- package/dist/widgets.d.ts +2 -1
- package/package.json +2 -2
- package/dist/widgets/expression/expression.types.d.ts +0 -2
package/dist/index.js
CHANGED
|
@@ -2386,23 +2386,11 @@ const anglicizeOperators = tex => {
|
|
|
2386
2386
|
const normalizeTex = tex => {
|
|
2387
2387
|
return anglicizeOperators(tex);
|
|
2388
2388
|
};
|
|
2389
|
-
const deriveKeypadVersion = apiOptions => {
|
|
2390
|
-
// We can derive which version of the keypad is in use. This is
|
|
2391
|
-
// a bit tricky, but this code will be relatively short-lived
|
|
2392
|
-
// as we coalesce onto the new, v2 Keypad, at which point we
|
|
2393
|
-
// can remove this `virtualKeypadVersion` field entirely.
|
|
2394
|
-
return apiOptions.nativeKeypadProxy != null ? "REACT_NATIVE_KEYPAD" : "MATH_INPUT_KEYPAD_V2";
|
|
2395
|
-
};
|
|
2396
2389
|
// The new, MathQuill input expression widget
|
|
2397
2390
|
class Expression extends React__namespace.Component {
|
|
2398
2391
|
static contextType = PerseusI18nContext;
|
|
2399
2392
|
_textareaId = `expression_textarea_${Date.now()}`;
|
|
2400
2393
|
_isMounted = false;
|
|
2401
|
-
|
|
2402
|
-
// TODO remove this in favor of just using expressionValidator
|
|
2403
|
-
static validate(userInput, rubric, strings, locale) {
|
|
2404
|
-
return expressionValidator(userInput, rubric, strings, locale);
|
|
2405
|
-
}
|
|
2406
2394
|
static getUserInputFromProps(props) {
|
|
2407
2395
|
return normalizeTex(props.value);
|
|
2408
2396
|
}
|
|
@@ -2478,26 +2466,6 @@ class Expression extends React__namespace.Component {
|
|
|
2478
2466
|
});
|
|
2479
2467
|
}
|
|
2480
2468
|
};
|
|
2481
|
-
simpleValidate = _ref => {
|
|
2482
|
-
let {
|
|
2483
|
-
scoring,
|
|
2484
|
-
...rubric
|
|
2485
|
-
} = _ref;
|
|
2486
|
-
const score = expressionValidator(this.getUserInput(), rubric, this.context.strings, this.context.locale);
|
|
2487
|
-
|
|
2488
|
-
// "scoring" is a flag that indicates when we are checking answers.
|
|
2489
|
-
// otherwise, we may just be checking validity after changes.
|
|
2490
|
-
if (scoring && score.type !== "invalid") {
|
|
2491
|
-
this.props.analytics?.onAnalyticsEvent({
|
|
2492
|
-
type: "perseus:expression-evaluated",
|
|
2493
|
-
payload: {
|
|
2494
|
-
result: score.earned === score.total ? "correct" : "incorrect",
|
|
2495
|
-
virtualKeypadVersion: deriveKeypadVersion(this.props.apiOptions)
|
|
2496
|
-
}
|
|
2497
|
-
});
|
|
2498
|
-
}
|
|
2499
|
-
return score;
|
|
2500
|
-
};
|
|
2501
2469
|
getUserInput() {
|
|
2502
2470
|
return Expression.getUserInputFromProps(this.props);
|
|
2503
2471
|
}
|
|
@@ -2796,7 +2764,8 @@ var Expression$1 = {
|
|
|
2796
2764
|
},
|
|
2797
2765
|
propUpgrades: propUpgrades$2,
|
|
2798
2766
|
// For use by the editor
|
|
2799
|
-
isLintable: true
|
|
2767
|
+
isLintable: true,
|
|
2768
|
+
validator: expressionValidator
|
|
2800
2769
|
};
|
|
2801
2770
|
|
|
2802
2771
|
/**
|
|
@@ -3026,6 +2995,9 @@ function combineScores(scoreA, scoreB) {
|
|
|
3026
2995
|
}
|
|
3027
2996
|
});
|
|
3028
2997
|
}
|
|
2998
|
+
function flattenScores(widgetScoreMap) {
|
|
2999
|
+
return Object.values(widgetScoreMap).reduce(combineScores, noScore);
|
|
3000
|
+
}
|
|
3029
3001
|
function isCorrect(score) {
|
|
3030
3002
|
return score.type === "points" && score.earned >= score.total;
|
|
3031
3003
|
}
|
|
@@ -3556,6 +3528,7 @@ const Util = {
|
|
|
3556
3528
|
shuffle: shuffle$3,
|
|
3557
3529
|
split,
|
|
3558
3530
|
combineScores,
|
|
3531
|
+
flattenScores,
|
|
3559
3532
|
keScoreFromPerseusScore,
|
|
3560
3533
|
firstNumericalParse: firstNumericalParse$1,
|
|
3561
3534
|
stringArrayOfSize: stringArrayOfSize$1,
|
|
@@ -10094,6 +10067,8 @@ const setLabelMargins = function (span, size) {
|
|
|
10094
10067
|
marginTop: -height / 2 - y * scale
|
|
10095
10068
|
});
|
|
10096
10069
|
} else {
|
|
10070
|
+
const currentHeightMatchesProps = span.scrollHeight === height;
|
|
10071
|
+
|
|
10097
10072
|
// We are using jQuery to collect information and calculate a scale
|
|
10098
10073
|
// since we don't have a way to pass it to this function.
|
|
10099
10074
|
// We need the width of the container in order to calculate the scale to apply to the label.
|
|
@@ -10115,6 +10090,17 @@ const setLabelMargins = function (span, size) {
|
|
|
10115
10090
|
// Inherited line-height values can really mess up placement.
|
|
10116
10091
|
$container.css("line-height", "normal");
|
|
10117
10092
|
|
|
10093
|
+
// TODO: Verify that this change doesn't impact other graphies
|
|
10094
|
+
// Check the full list of consuming widgets.
|
|
10095
|
+
|
|
10096
|
+
// If the change in line-height affected the height of the element,
|
|
10097
|
+
// then the height used for calculations should be updated.
|
|
10098
|
+
// This can happen when the first label in the container calls this method,
|
|
10099
|
+
// and the line-height was different when the height measurement was originally referenced.
|
|
10100
|
+
if (currentHeightMatchesProps && span.scrollHeight !== height) {
|
|
10101
|
+
height = span.scrollHeight;
|
|
10102
|
+
}
|
|
10103
|
+
|
|
10118
10104
|
// The expected width of the graphie is found in the "max-width" property on ".svg-image" containers,
|
|
10119
10105
|
// and is found in the "width" property on ".graphie" containers.
|
|
10120
10106
|
const widthValues = $container.css(["max-width", "width"]) ?? {
|
|
@@ -14777,7 +14763,7 @@ const mapObject$1 = function (obj, lambda) {
|
|
|
14777
14763
|
* });
|
|
14778
14764
|
* {a: 'aa', b: 'bb'}
|
|
14779
14765
|
*/
|
|
14780
|
-
const mapObjectFromArray
|
|
14766
|
+
const mapObjectFromArray = function (arr, lambda) {
|
|
14781
14767
|
const result = {};
|
|
14782
14768
|
___default["default"].each(arr, function (elem) {
|
|
14783
14769
|
result[elem] = lambda(elem);
|
|
@@ -14787,7 +14773,7 @@ const mapObjectFromArray$1 = function (arr, lambda) {
|
|
|
14787
14773
|
var objective_ = {
|
|
14788
14774
|
pluck: pluck,
|
|
14789
14775
|
mapObject: mapObject$1,
|
|
14790
|
-
mapObjectFromArray: mapObjectFromArray
|
|
14776
|
+
mapObjectFromArray: mapObjectFromArray
|
|
14791
14777
|
};
|
|
14792
14778
|
|
|
14793
14779
|
/**
|
|
@@ -19003,169 +18989,6 @@ class QuestionParagraph extends React__namespace.Component {
|
|
|
19003
18989
|
}
|
|
19004
18990
|
}
|
|
19005
18991
|
|
|
19006
|
-
/**
|
|
19007
|
-
* TranslationLinter asynchronously calls Khan Academy's poentry linter.
|
|
19008
|
-
*
|
|
19009
|
-
* The poentry linter checks for issues that prevent content from being
|
|
19010
|
-
* translated. This linter is KA-specific and so TranslationLinter does not do
|
|
19011
|
-
* anything in non-KA environments.
|
|
19012
|
-
*/
|
|
19013
|
-
|
|
19014
|
-
// A LintCB is called once the linter has been run.
|
|
19015
|
-
|
|
19016
|
-
// msec to wait before we actually call the linter after receiving the
|
|
19017
|
-
// last call. The timer is reset if the lint is called during the wait.
|
|
19018
|
-
const DEBOUNCE_TIMEOUT = 1000;
|
|
19019
|
-
class TranslationLinter {
|
|
19020
|
-
// To avoid linting when nothing has changed.
|
|
19021
|
-
previousContent = null;
|
|
19022
|
-
|
|
19023
|
-
/**
|
|
19024
|
-
* Runs the poentry linter on the given perseus string asynchronously.
|
|
19025
|
-
*
|
|
19026
|
-
* It doesn't do anything unless we're in a KA environment.
|
|
19027
|
-
*
|
|
19028
|
-
* onLintErrorsGenerated is called even if there are no errors. It is not
|
|
19029
|
-
* called if perseusStr is unchanged from the last call.
|
|
19030
|
-
*
|
|
19031
|
-
* Linting is relatively expensive -- so we debounce linting each instance
|
|
19032
|
-
* for some amount of time.
|
|
19033
|
-
*/
|
|
19034
|
-
runLinter = _.debounce((perseusStr, onLintErrorsGenerated) => {
|
|
19035
|
-
// TODO(FEI-5003): Do we still need to check for 'KA'?
|
|
19036
|
-
if (typeof KA === "undefined") {
|
|
19037
|
-
return;
|
|
19038
|
-
}
|
|
19039
|
-
if (perseusStr === this.previousContent) {
|
|
19040
|
-
return;
|
|
19041
|
-
}
|
|
19042
|
-
this.previousContent = perseusStr;
|
|
19043
|
-
if (perseusStr === "") {
|
|
19044
|
-
onLintErrorsGenerated([]);
|
|
19045
|
-
return;
|
|
19046
|
-
}
|
|
19047
|
-
fetch("/api/internal/translations/lint_poentry?preview=1&lang=en", {
|
|
19048
|
-
headers: {
|
|
19049
|
-
"Content-Type": "application/json"
|
|
19050
|
-
},
|
|
19051
|
-
body: JSON.stringify({
|
|
19052
|
-
// The poentry linter verifies that the translation from
|
|
19053
|
-
// the original text to the translated text is sane. We
|
|
19054
|
-
// want to ensure that the translation from English to
|
|
19055
|
-
// English is sane, so msgid === mstr.
|
|
19056
|
-
msgid: perseusStr,
|
|
19057
|
-
// msgid is the original text
|
|
19058
|
-
msgstr: perseusStr,
|
|
19059
|
-
// msgstr is the translated text
|
|
19060
|
-
format: "perseus_text",
|
|
19061
|
-
filename: ""
|
|
19062
|
-
}),
|
|
19063
|
-
method: "POST"
|
|
19064
|
-
}).then(response => {
|
|
19065
|
-
if (response.status >= 400) {
|
|
19066
|
-
return {
|
|
19067
|
-
status: "error",
|
|
19068
|
-
message: "Could not run i18n linter."
|
|
19069
|
-
};
|
|
19070
|
-
}
|
|
19071
|
-
return response.json();
|
|
19072
|
-
}, rejection => {
|
|
19073
|
-
return {
|
|
19074
|
-
status: "error",
|
|
19075
|
-
message: "Could not run i18n linter."
|
|
19076
|
-
};
|
|
19077
|
-
}).then(json => {
|
|
19078
|
-
if (json.status === "error") {
|
|
19079
|
-
onLintErrorsGenerated(["Some part of this text makes it untranslatable. " + "The specific message from the i18n linter was: " + json.message.replace(/\n/g, " ")]);
|
|
19080
|
-
} else {
|
|
19081
|
-
onLintErrorsGenerated([]);
|
|
19082
|
-
}
|
|
19083
|
-
});
|
|
19084
|
-
}, DEBOUNCE_TIMEOUT);
|
|
19085
|
-
|
|
19086
|
-
/**
|
|
19087
|
-
* Applies an array of errors generated by linters without position
|
|
19088
|
-
* information (TranslationLinter and the legacy getSaveWarnings()) to the
|
|
19089
|
-
* top of a Perseus tree.
|
|
19090
|
-
*/
|
|
19091
|
-
applyLintErrors(parsedMarkdown, translationLintErrors) {
|
|
19092
|
-
// These lint errors do not have position data associated with
|
|
19093
|
-
// them, so we just plop them at the top.
|
|
19094
|
-
if (translationLintErrors.length) {
|
|
19095
|
-
const errorText = translationLintErrors.join("\n\n");
|
|
19096
|
-
parsedMarkdown.unshift({
|
|
19097
|
-
content: {
|
|
19098
|
-
type: "text",
|
|
19099
|
-
content: ""
|
|
19100
|
-
},
|
|
19101
|
-
insideTable: false,
|
|
19102
|
-
message: errorText,
|
|
19103
|
-
ruleName: "legacy-error",
|
|
19104
|
-
severity: PerseusLinter.Rule.Severity.ERROR,
|
|
19105
|
-
type: "lint"
|
|
19106
|
-
});
|
|
19107
|
-
}
|
|
19108
|
-
}
|
|
19109
|
-
}
|
|
19110
|
-
|
|
19111
|
-
/**
|
|
19112
|
-
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
19113
|
-
* to things is does.
|
|
19114
|
-
*/
|
|
19115
|
-
var preprocessTex = (texCode => texCode
|
|
19116
|
-
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
19117
|
-
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
19118
|
-
// the same is supported by KaTeX. It does the same for align*.
|
|
19119
|
-
// TODO(kevinb) update content to use aligned instead of align.
|
|
19120
|
-
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
19121
|
-
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
19122
|
-
// "aligned").
|
|
19123
|
-
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
19124
|
-
// Replace non-breaking spaces with regular spaces.
|
|
19125
|
-
.replace(/[\u00a0]/g, " "));
|
|
19126
|
-
|
|
19127
|
-
const {
|
|
19128
|
-
interactiveSizes
|
|
19129
|
-
} = constants$1;
|
|
19130
|
-
|
|
19131
|
-
// Note: these size cutoffs represent content-width cutoffs as specified in
|
|
19132
|
-
// http://zpl.io/1mVmvU (broken link - we no longer use Zeplin)
|
|
19133
|
-
// TODO(benkomalo): these values aren't used in JS outside of this file, but
|
|
19134
|
-
// are coupled to the values in styles/styles.less - DRY it up at some point
|
|
19135
|
-
const smMax = articleMaxWidthTableInPx;
|
|
19136
|
-
const mdMax = articleMaxWidthInPx;
|
|
19137
|
-
const containerSizeClass = {
|
|
19138
|
-
SMALL: "small",
|
|
19139
|
-
MEDIUM: "medium",
|
|
19140
|
-
LARGE: "large",
|
|
19141
|
-
XLARGE: "xlarge"
|
|
19142
|
-
};
|
|
19143
|
-
const getClassFromWidth = width => {
|
|
19144
|
-
if (!width) {
|
|
19145
|
-
return containerSizeClass.MEDIUM;
|
|
19146
|
-
}
|
|
19147
|
-
if (width <= smMax) {
|
|
19148
|
-
return containerSizeClass.SMALL;
|
|
19149
|
-
}
|
|
19150
|
-
if (width <= mdMax) {
|
|
19151
|
-
return containerSizeClass.MEDIUM;
|
|
19152
|
-
}
|
|
19153
|
-
return containerSizeClass.LARGE;
|
|
19154
|
-
};
|
|
19155
|
-
const getInteractiveBoxFromSizeClass = sizeClass => {
|
|
19156
|
-
if (sizeClass === containerSizeClass.SMALL) {
|
|
19157
|
-
return [interactiveSizes.defaultBoxSizeSmall, interactiveSizes.defaultBoxSizeSmall];
|
|
19158
|
-
}
|
|
19159
|
-
return [interactiveSizes.defaultBoxSize, interactiveSizes.defaultBoxSize];
|
|
19160
|
-
};
|
|
19161
|
-
|
|
19162
|
-
var sizingUtils = /*#__PURE__*/Object.freeze({
|
|
19163
|
-
__proto__: null,
|
|
19164
|
-
containerSizeClass: containerSizeClass,
|
|
19165
|
-
getClassFromWidth: getClassFromWidth,
|
|
19166
|
-
getInteractiveBoxFromSizeClass: getInteractiveBoxFromSizeClass
|
|
19167
|
-
});
|
|
19168
|
-
|
|
19169
18992
|
const DEFAULT_ALIGNMENT$1 = "block";
|
|
19170
18993
|
// NOTE(kevinb): "default" is not one in `validAlignments`.
|
|
19171
18994
|
const DEFAULT_SUPPORTED_ALIGNMENTS = ["default"];
|
|
@@ -19264,6 +19087,9 @@ const getWidget = name => {
|
|
|
19264
19087
|
}
|
|
19265
19088
|
return widgets[name].widget;
|
|
19266
19089
|
};
|
|
19090
|
+
const getWidgetValidator = name => {
|
|
19091
|
+
return widgets[name]?.validator ?? null;
|
|
19092
|
+
};
|
|
19267
19093
|
const getEditor = name => {
|
|
19268
19094
|
return ___default["default"].has(editors, name) ? editors[name] : null;
|
|
19269
19095
|
};
|
|
@@ -19569,6 +19395,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
19569
19395
|
replaceEditor: replaceEditor,
|
|
19570
19396
|
replaceDeprecatedEditors: replaceDeprecatedEditors,
|
|
19571
19397
|
getWidget: getWidget,
|
|
19398
|
+
getWidgetValidator: getWidgetValidator,
|
|
19572
19399
|
getEditor: getEditor,
|
|
19573
19400
|
getTransform: getTransform,
|
|
19574
19401
|
getVersion: getVersion,
|
|
@@ -19588,6 +19415,222 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
19588
19415
|
isLintable: isLintable
|
|
19589
19416
|
});
|
|
19590
19417
|
|
|
19418
|
+
function emptyWidgetsFunctional(widgets,
|
|
19419
|
+
// This is a port of old code, I'm not sure why
|
|
19420
|
+
// we need widgetIds vs the keys of the widgets object
|
|
19421
|
+
widgetIds, userInputMap, strings, locale) {
|
|
19422
|
+
return widgetIds.filter(id => {
|
|
19423
|
+
const widget = widgets[id];
|
|
19424
|
+
if (!widget || widget.static) {
|
|
19425
|
+
// Static widgets shouldn't count as empty
|
|
19426
|
+
return false;
|
|
19427
|
+
}
|
|
19428
|
+
let score = null;
|
|
19429
|
+
const userInput = userInputMap[id];
|
|
19430
|
+
const validator = getWidgetValidator(widget.type);
|
|
19431
|
+
if (widget.type === "group") {
|
|
19432
|
+
const scores = scoreWidgetsFunctional(widget.options.widgets, Object.keys(widget.options.widgets), userInputMap[id], strings, locale);
|
|
19433
|
+
score = Util.flattenScores(scores);
|
|
19434
|
+
} else if (validator) {
|
|
19435
|
+
score = validator(userInput, widget.options, strings, locale);
|
|
19436
|
+
}
|
|
19437
|
+
if (score) {
|
|
19438
|
+
return Util.scoreIsEmpty(score);
|
|
19439
|
+
}
|
|
19440
|
+
});
|
|
19441
|
+
}
|
|
19442
|
+
function scoreWidgetsFunctional(widgets,
|
|
19443
|
+
// This is a port of old code, I'm not sure why
|
|
19444
|
+
// we need widgetIds vs the keys of the widgets object
|
|
19445
|
+
widgetIds, userInputMap, strings, locale) {
|
|
19446
|
+
const gradedWidgetIds = widgetIds.filter(id => {
|
|
19447
|
+
const props = widgets[id];
|
|
19448
|
+
const widgetIsGraded = props?.graded == null || props.graded;
|
|
19449
|
+
const widgetIsStatic = !!props?.static;
|
|
19450
|
+
// Ungraded widgets or widgets set to static shouldn't be graded.
|
|
19451
|
+
return widgetIsGraded && !widgetIsStatic;
|
|
19452
|
+
});
|
|
19453
|
+
const widgetScores = {};
|
|
19454
|
+
gradedWidgetIds.forEach(id => {
|
|
19455
|
+
const widget = widgets[id];
|
|
19456
|
+
if (!widget) {
|
|
19457
|
+
return;
|
|
19458
|
+
}
|
|
19459
|
+
const userInput = userInputMap[id];
|
|
19460
|
+
const validator = getWidgetValidator(widget.type);
|
|
19461
|
+
if (widget.type === "group") {
|
|
19462
|
+
const scores = scoreWidgetsFunctional(widget.options.widgets, Object.keys(widget.options.widgets), userInputMap[id], strings, locale);
|
|
19463
|
+
widgetScores[id] = Util.flattenScores(scores);
|
|
19464
|
+
} else if (validator) {
|
|
19465
|
+
widgetScores[id] = validator(userInput, widget.options, strings, locale);
|
|
19466
|
+
}
|
|
19467
|
+
});
|
|
19468
|
+
return widgetScores;
|
|
19469
|
+
}
|
|
19470
|
+
|
|
19471
|
+
/**
|
|
19472
|
+
* TranslationLinter asynchronously calls Khan Academy's poentry linter.
|
|
19473
|
+
*
|
|
19474
|
+
* The poentry linter checks for issues that prevent content from being
|
|
19475
|
+
* translated. This linter is KA-specific and so TranslationLinter does not do
|
|
19476
|
+
* anything in non-KA environments.
|
|
19477
|
+
*/
|
|
19478
|
+
|
|
19479
|
+
// A LintCB is called once the linter has been run.
|
|
19480
|
+
|
|
19481
|
+
// msec to wait before we actually call the linter after receiving the
|
|
19482
|
+
// last call. The timer is reset if the lint is called during the wait.
|
|
19483
|
+
const DEBOUNCE_TIMEOUT = 1000;
|
|
19484
|
+
class TranslationLinter {
|
|
19485
|
+
// To avoid linting when nothing has changed.
|
|
19486
|
+
previousContent = null;
|
|
19487
|
+
|
|
19488
|
+
/**
|
|
19489
|
+
* Runs the poentry linter on the given perseus string asynchronously.
|
|
19490
|
+
*
|
|
19491
|
+
* It doesn't do anything unless we're in a KA environment.
|
|
19492
|
+
*
|
|
19493
|
+
* onLintErrorsGenerated is called even if there are no errors. It is not
|
|
19494
|
+
* called if perseusStr is unchanged from the last call.
|
|
19495
|
+
*
|
|
19496
|
+
* Linting is relatively expensive -- so we debounce linting each instance
|
|
19497
|
+
* for some amount of time.
|
|
19498
|
+
*/
|
|
19499
|
+
runLinter = _.debounce((perseusStr, onLintErrorsGenerated) => {
|
|
19500
|
+
// TODO(FEI-5003): Do we still need to check for 'KA'?
|
|
19501
|
+
if (typeof KA === "undefined") {
|
|
19502
|
+
return;
|
|
19503
|
+
}
|
|
19504
|
+
if (perseusStr === this.previousContent) {
|
|
19505
|
+
return;
|
|
19506
|
+
}
|
|
19507
|
+
this.previousContent = perseusStr;
|
|
19508
|
+
if (perseusStr === "") {
|
|
19509
|
+
onLintErrorsGenerated([]);
|
|
19510
|
+
return;
|
|
19511
|
+
}
|
|
19512
|
+
fetch("/api/internal/translations/lint_poentry?preview=1&lang=en", {
|
|
19513
|
+
headers: {
|
|
19514
|
+
"Content-Type": "application/json"
|
|
19515
|
+
},
|
|
19516
|
+
body: JSON.stringify({
|
|
19517
|
+
// The poentry linter verifies that the translation from
|
|
19518
|
+
// the original text to the translated text is sane. We
|
|
19519
|
+
// want to ensure that the translation from English to
|
|
19520
|
+
// English is sane, so msgid === mstr.
|
|
19521
|
+
msgid: perseusStr,
|
|
19522
|
+
// msgid is the original text
|
|
19523
|
+
msgstr: perseusStr,
|
|
19524
|
+
// msgstr is the translated text
|
|
19525
|
+
format: "perseus_text",
|
|
19526
|
+
filename: ""
|
|
19527
|
+
}),
|
|
19528
|
+
method: "POST"
|
|
19529
|
+
}).then(response => {
|
|
19530
|
+
if (response.status >= 400) {
|
|
19531
|
+
return {
|
|
19532
|
+
status: "error",
|
|
19533
|
+
message: "Could not run i18n linter."
|
|
19534
|
+
};
|
|
19535
|
+
}
|
|
19536
|
+
return response.json();
|
|
19537
|
+
}, rejection => {
|
|
19538
|
+
return {
|
|
19539
|
+
status: "error",
|
|
19540
|
+
message: "Could not run i18n linter."
|
|
19541
|
+
};
|
|
19542
|
+
}).then(json => {
|
|
19543
|
+
if (json.status === "error") {
|
|
19544
|
+
onLintErrorsGenerated(["Some part of this text makes it untranslatable. " + "The specific message from the i18n linter was: " + json.message.replace(/\n/g, " ")]);
|
|
19545
|
+
} else {
|
|
19546
|
+
onLintErrorsGenerated([]);
|
|
19547
|
+
}
|
|
19548
|
+
});
|
|
19549
|
+
}, DEBOUNCE_TIMEOUT);
|
|
19550
|
+
|
|
19551
|
+
/**
|
|
19552
|
+
* Applies an array of errors generated by linters without position
|
|
19553
|
+
* information (TranslationLinter and the legacy getSaveWarnings()) to the
|
|
19554
|
+
* top of a Perseus tree.
|
|
19555
|
+
*/
|
|
19556
|
+
applyLintErrors(parsedMarkdown, translationLintErrors) {
|
|
19557
|
+
// These lint errors do not have position data associated with
|
|
19558
|
+
// them, so we just plop them at the top.
|
|
19559
|
+
if (translationLintErrors.length) {
|
|
19560
|
+
const errorText = translationLintErrors.join("\n\n");
|
|
19561
|
+
parsedMarkdown.unshift({
|
|
19562
|
+
content: {
|
|
19563
|
+
type: "text",
|
|
19564
|
+
content: ""
|
|
19565
|
+
},
|
|
19566
|
+
insideTable: false,
|
|
19567
|
+
message: errorText,
|
|
19568
|
+
ruleName: "legacy-error",
|
|
19569
|
+
severity: PerseusLinter.Rule.Severity.ERROR,
|
|
19570
|
+
type: "lint"
|
|
19571
|
+
});
|
|
19572
|
+
}
|
|
19573
|
+
}
|
|
19574
|
+
}
|
|
19575
|
+
|
|
19576
|
+
/**
|
|
19577
|
+
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
19578
|
+
* to things is does.
|
|
19579
|
+
*/
|
|
19580
|
+
var preprocessTex = (texCode => texCode
|
|
19581
|
+
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
19582
|
+
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
19583
|
+
// the same is supported by KaTeX. It does the same for align*.
|
|
19584
|
+
// TODO(kevinb) update content to use aligned instead of align.
|
|
19585
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
19586
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
19587
|
+
// "aligned").
|
|
19588
|
+
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
19589
|
+
// Replace non-breaking spaces with regular spaces.
|
|
19590
|
+
.replace(/[\u00a0]/g, " "));
|
|
19591
|
+
|
|
19592
|
+
const {
|
|
19593
|
+
interactiveSizes
|
|
19594
|
+
} = constants$1;
|
|
19595
|
+
|
|
19596
|
+
// Note: these size cutoffs represent content-width cutoffs as specified in
|
|
19597
|
+
// http://zpl.io/1mVmvU (broken link - we no longer use Zeplin)
|
|
19598
|
+
// TODO(benkomalo): these values aren't used in JS outside of this file, but
|
|
19599
|
+
// are coupled to the values in styles/styles.less - DRY it up at some point
|
|
19600
|
+
const smMax = articleMaxWidthTableInPx;
|
|
19601
|
+
const mdMax = articleMaxWidthInPx;
|
|
19602
|
+
const containerSizeClass = {
|
|
19603
|
+
SMALL: "small",
|
|
19604
|
+
MEDIUM: "medium",
|
|
19605
|
+
LARGE: "large",
|
|
19606
|
+
XLARGE: "xlarge"
|
|
19607
|
+
};
|
|
19608
|
+
const getClassFromWidth = width => {
|
|
19609
|
+
if (!width) {
|
|
19610
|
+
return containerSizeClass.MEDIUM;
|
|
19611
|
+
}
|
|
19612
|
+
if (width <= smMax) {
|
|
19613
|
+
return containerSizeClass.SMALL;
|
|
19614
|
+
}
|
|
19615
|
+
if (width <= mdMax) {
|
|
19616
|
+
return containerSizeClass.MEDIUM;
|
|
19617
|
+
}
|
|
19618
|
+
return containerSizeClass.LARGE;
|
|
19619
|
+
};
|
|
19620
|
+
const getInteractiveBoxFromSizeClass = sizeClass => {
|
|
19621
|
+
if (sizeClass === containerSizeClass.SMALL) {
|
|
19622
|
+
return [interactiveSizes.defaultBoxSizeSmall, interactiveSizes.defaultBoxSizeSmall];
|
|
19623
|
+
}
|
|
19624
|
+
return [interactiveSizes.defaultBoxSize, interactiveSizes.defaultBoxSize];
|
|
19625
|
+
};
|
|
19626
|
+
|
|
19627
|
+
var sizingUtils = /*#__PURE__*/Object.freeze({
|
|
19628
|
+
__proto__: null,
|
|
19629
|
+
containerSizeClass: containerSizeClass,
|
|
19630
|
+
getClassFromWidth: getClassFromWidth,
|
|
19631
|
+
getInteractiveBoxFromSizeClass: getInteractiveBoxFromSizeClass
|
|
19632
|
+
});
|
|
19633
|
+
|
|
19591
19634
|
class WidgetContainer extends React__namespace.Component {
|
|
19592
19635
|
widgetRef = /*#__PURE__*/React__namespace.createRef();
|
|
19593
19636
|
static defaultProps = {
|
|
@@ -19734,8 +19777,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
19734
19777
|
}
|
|
19735
19778
|
|
|
19736
19779
|
const {
|
|
19737
|
-
mapObject
|
|
19738
|
-
mapObjectFromArray
|
|
19780
|
+
mapObject
|
|
19739
19781
|
} = objective_;
|
|
19740
19782
|
const rContainsNonWhitespace = /\S/;
|
|
19741
19783
|
const rImageURL = /(web\+graphie|https):\/\/[^\s]*/;
|
|
@@ -19762,6 +19804,7 @@ const isIdPathPrefix = function (prefixArray, wholeArray) {
|
|
|
19762
19804
|
});
|
|
19763
19805
|
};
|
|
19764
19806
|
class Renderer extends React__namespace.Component {
|
|
19807
|
+
static contextType = PerseusI18nContext;
|
|
19765
19808
|
_currentFocus;
|
|
19766
19809
|
// @ts-expect-error - TS2564 - Property '_foundTextNodes' has no initializer and is not definitely assigned in the constructor.
|
|
19767
19810
|
_foundTextNodes;
|
|
@@ -20065,11 +20108,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20065
20108
|
}
|
|
20066
20109
|
let interactionTracker = this._interactionTrackers[id];
|
|
20067
20110
|
if (!interactionTracker) {
|
|
20068
|
-
interactionTracker = this._interactionTrackers[id] = new InteractionTracker(apiOptions.trackInteraction,
|
|
20069
|
-
// @ts-expect-error - TS2345 - Argument of type 'string | null | undefined' is not assignable to parameter of type 'string'.
|
|
20070
|
-
widgetInfo && widgetInfo.type, id,
|
|
20071
|
-
// @ts-expect-error - TS2345 - Argument of type 'string | null | undefined' is not assignable to parameter of type 'string'.
|
|
20072
|
-
getTracking(widgetInfo && widgetInfo.type));
|
|
20111
|
+
interactionTracker = this._interactionTrackers[id] = new InteractionTracker(apiOptions.trackInteraction, widgetInfo && widgetInfo.type, id, getTracking(widgetInfo && widgetInfo.type));
|
|
20073
20112
|
}
|
|
20074
20113
|
return {
|
|
20075
20114
|
...widgetProps,
|
|
@@ -20883,23 +20922,9 @@ class Renderer extends React__namespace.Component {
|
|
|
20883
20922
|
}, this);
|
|
20884
20923
|
return state;
|
|
20885
20924
|
};
|
|
20886
|
-
emptyWidgets
|
|
20887
|
-
|
|
20888
|
-
|
|
20889
|
-
const widgetInfo = this._getWidgetInfo(id);
|
|
20890
|
-
if (widgetInfo.static) {
|
|
20891
|
-
// Static widgets shouldn't count as empty
|
|
20892
|
-
return false;
|
|
20893
|
-
}
|
|
20894
|
-
const widget = this.getWidgetInstance(id);
|
|
20895
|
-
if (widget && widget.simpleValidate) {
|
|
20896
|
-
const score = widget.simpleValidate(widgetInfo.options,
|
|
20897
|
-
// @ts-expect-error - TS2345 - Argument of type 'null' is not assignable to parameter of type '((widgetId: any, value: string, message?: string | null | undefined) => unknown) | undefined'.
|
|
20898
|
-
null);
|
|
20899
|
-
return Util.scoreIsEmpty(score);
|
|
20900
|
-
}
|
|
20901
|
-
});
|
|
20902
|
-
};
|
|
20925
|
+
emptyWidgets() {
|
|
20926
|
+
return emptyWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.props.strings, this.context.locale);
|
|
20927
|
+
}
|
|
20903
20928
|
_setWidgetProps = (id, newProps, cb, silent) => {
|
|
20904
20929
|
this.setState(prevState => {
|
|
20905
20930
|
const widgetProps = {
|
|
@@ -20963,8 +20988,11 @@ class Renderer extends React__namespace.Component {
|
|
|
20963
20988
|
|
|
20964
20989
|
/**
|
|
20965
20990
|
* Returns an array of the widget `.getUserInput()` results
|
|
20991
|
+
*
|
|
20992
|
+
* TODO: can we remove this?
|
|
20993
|
+
* @deprecated use getUserInputMap
|
|
20966
20994
|
*/
|
|
20967
|
-
getUserInput
|
|
20995
|
+
getUserInput() {
|
|
20968
20996
|
return this.widgetIds.map(id => {
|
|
20969
20997
|
const widget = this.getWidgetInstance(id);
|
|
20970
20998
|
if (widget && widget.getUserInput) {
|
|
@@ -20973,7 +21001,24 @@ class Renderer extends React__namespace.Component {
|
|
|
20973
21001
|
return widget.getUserInput();
|
|
20974
21002
|
}
|
|
20975
21003
|
});
|
|
20976
|
-
}
|
|
21004
|
+
}
|
|
21005
|
+
|
|
21006
|
+
/**
|
|
21007
|
+
* Returns an object of the widget `.getUserInput()` results
|
|
21008
|
+
*/
|
|
21009
|
+
getUserInputMap() {
|
|
21010
|
+
const userInputMap = {};
|
|
21011
|
+
this.widgetIds.forEach(id => {
|
|
21012
|
+
const widget = this.getWidgetInstance(id);
|
|
21013
|
+
// Handle Groups, which have their own sets of widgets
|
|
21014
|
+
if (widget?.getUserInputMap) {
|
|
21015
|
+
userInputMap[id] = widget.getUserInputMap();
|
|
21016
|
+
} else if (widget?.getUserInput) {
|
|
21017
|
+
userInputMap[id] = widget.getUserInput();
|
|
21018
|
+
}
|
|
21019
|
+
});
|
|
21020
|
+
return userInputMap;
|
|
21021
|
+
}
|
|
20977
21022
|
|
|
20978
21023
|
/**
|
|
20979
21024
|
* Returns an array of all widget IDs in the order they occur in
|
|
@@ -20983,59 +21028,23 @@ class Renderer extends React__namespace.Component {
|
|
|
20983
21028
|
return this.widgetIds;
|
|
20984
21029
|
};
|
|
20985
21030
|
|
|
20986
|
-
/**
|
|
20987
|
-
* Returns the result of `.getUserInput()` for each widget, in
|
|
20988
|
-
* a map from widgetId to userInput.
|
|
20989
|
-
* NOTE(jeremy): This function is hauntingly similar to `getUserInput` with
|
|
20990
|
-
* the major difference being that this function returns a map of
|
|
20991
|
-
* `widgetID` => UserInput and `getUserInput` simply returns an array. It
|
|
20992
|
-
* would be trivial to map between the results of each of these functions,
|
|
20993
|
-
* so we should aim to remove one of these functions.
|
|
20994
|
-
*/
|
|
20995
|
-
getUserInputForWidgets = () => {
|
|
20996
|
-
return mapObjectFromArray(this.widgetIds, id => {
|
|
20997
|
-
const widget = this.getWidgetInstance(id);
|
|
20998
|
-
if (widget && widget.getUserInput) {
|
|
20999
|
-
return widget.getUserInput();
|
|
21000
|
-
}
|
|
21001
|
-
});
|
|
21002
|
-
};
|
|
21003
|
-
|
|
21004
21031
|
/**
|
|
21005
21032
|
* Returns an object mapping from widget ID to perseus-style score.
|
|
21006
21033
|
* The keys of this object are the values of the array returned
|
|
21007
21034
|
* from `getWidgetIds`.
|
|
21008
21035
|
*/
|
|
21009
|
-
scoreWidgets
|
|
21010
|
-
|
|
21011
|
-
|
|
21012
|
-
const props = widgetProps[id];
|
|
21013
|
-
const widgetIsGraded = props?.graded == null || props.graded;
|
|
21014
|
-
const widgetIsStatic = !!props?.static;
|
|
21015
|
-
// Ungraded widgets or widgets set to static shouldn't be graded.
|
|
21016
|
-
return widgetIsGraded && !widgetIsStatic;
|
|
21017
|
-
});
|
|
21018
|
-
const widgetScores = {};
|
|
21019
|
-
___default["default"].each(gradedWidgetIds, id => {
|
|
21020
|
-
const props = widgetProps[id];
|
|
21021
|
-
const widget = this.getWidgetInstance(id);
|
|
21022
|
-
// widget can be undefined if it hasn't yet been rendered
|
|
21023
|
-
if (widget && widget.simpleValidate) {
|
|
21024
|
-
widgetScores[id] = widget.simpleValidate({
|
|
21025
|
-
...props?.options,
|
|
21026
|
-
scoring: true
|
|
21027
|
-
});
|
|
21028
|
-
}
|
|
21029
|
-
});
|
|
21030
|
-
return widgetScores;
|
|
21031
|
-
};
|
|
21036
|
+
scoreWidgets() {
|
|
21037
|
+
return scoreWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.props.strings, this.context.locale);
|
|
21038
|
+
}
|
|
21032
21039
|
|
|
21033
21040
|
/**
|
|
21034
21041
|
* Grades the content.
|
|
21035
21042
|
*/
|
|
21036
|
-
score
|
|
21037
|
-
|
|
21038
|
-
|
|
21043
|
+
score() {
|
|
21044
|
+
const scores = this.scoreWidgets();
|
|
21045
|
+
const combinedScore = Util.flattenScores(scores);
|
|
21046
|
+
return combinedScore;
|
|
21047
|
+
}
|
|
21039
21048
|
guessAndScore = () => {
|
|
21040
21049
|
const totalGuess = this.getUserInput();
|
|
21041
21050
|
const totalScore = this.score();
|
|
@@ -21147,12 +21156,12 @@ class Renderer extends React__namespace.Component {
|
|
|
21147
21156
|
// If highlightLint is true and lint is detected, this call
|
|
21148
21157
|
// will modify the parse tree by adding lint nodes that will
|
|
21149
21158
|
// serve to highlight the lint when rendered
|
|
21150
|
-
const
|
|
21159
|
+
const fullLinterContext = {
|
|
21151
21160
|
content: this.props.content,
|
|
21152
21161
|
widgets: this.props.widgets,
|
|
21153
21162
|
...this.props.linterContext
|
|
21154
21163
|
};
|
|
21155
|
-
PerseusLinter__namespace.runLinter(parsedMarkdown,
|
|
21164
|
+
PerseusLinter__namespace.runLinter(parsedMarkdown, fullLinterContext, true);
|
|
21156
21165
|
|
|
21157
21166
|
// Apply the lint errors from the last TranslationLinter run.
|
|
21158
21167
|
// TODO(joshuan): Support overlapping dots.
|
|
@@ -21974,9 +21983,6 @@ class InputNumber extends React__namespace.Component {
|
|
|
21974
21983
|
apiOptions: ApiOptions.defaults,
|
|
21975
21984
|
linterContext: PerseusLinter.linterContextDefault
|
|
21976
21985
|
};
|
|
21977
|
-
static validate(state, rubric, strings) {
|
|
21978
|
-
return inputNumberValidator(state, rubric, strings);
|
|
21979
|
-
}
|
|
21980
21986
|
static getUserInputFromProps(props) {
|
|
21981
21987
|
return {
|
|
21982
21988
|
currentValue: props.currentValue
|
|
@@ -22047,9 +22053,6 @@ class InputNumber extends React__namespace.Component {
|
|
|
22047
22053
|
getUserInput() {
|
|
22048
22054
|
return InputNumber.getUserInputFromProps(this.props);
|
|
22049
22055
|
}
|
|
22050
|
-
simpleValidate(rubric) {
|
|
22051
|
-
return inputNumberValidator(this.getUserInput(), rubric, this.context.strings);
|
|
22052
|
-
}
|
|
22053
22056
|
examples = () => {
|
|
22054
22057
|
const {
|
|
22055
22058
|
strings
|
|
@@ -22152,7 +22155,8 @@ var InputNumber$1 = {
|
|
|
22152
22155
|
hidden: true,
|
|
22153
22156
|
widget: InputNumber,
|
|
22154
22157
|
transform: propTransform$3,
|
|
22155
|
-
isLintable: true
|
|
22158
|
+
isLintable: true,
|
|
22159
|
+
validator: inputNumberValidator
|
|
22156
22160
|
};
|
|
22157
22161
|
|
|
22158
22162
|
const ParseTex = TexWrangler.parseTex;
|
|
@@ -22359,9 +22363,6 @@ class NumericInput extends React__namespace.Component {
|
|
|
22359
22363
|
}
|
|
22360
22364
|
return answerStrings[0];
|
|
22361
22365
|
}
|
|
22362
|
-
static validate(userInput, rubric, strings) {
|
|
22363
|
-
return numericInputValidator(userInput, rubric, strings);
|
|
22364
|
-
}
|
|
22365
22366
|
state = {
|
|
22366
22367
|
// keeps track of the other set of values when switching
|
|
22367
22368
|
// between 0 and finite solutions
|
|
@@ -22394,9 +22395,6 @@ class NumericInput extends React__namespace.Component {
|
|
|
22394
22395
|
const allFormsAccepted = answerFormNames.length >= Object.keys(formExamples).length;
|
|
22395
22396
|
return !noFormsAccepted && !allFormsAccepted;
|
|
22396
22397
|
};
|
|
22397
|
-
simpleValidate(rubric) {
|
|
22398
|
-
return numericInputValidator(this.getUserInput(), rubric, this.context.strings);
|
|
22399
|
-
}
|
|
22400
22398
|
focus = () => {
|
|
22401
22399
|
this.inputRef?.focus();
|
|
22402
22400
|
return true;
|
|
@@ -22550,7 +22548,8 @@ var NumericInput$1 = {
|
|
|
22550
22548
|
accessible: true,
|
|
22551
22549
|
widget: NumericInput,
|
|
22552
22550
|
transform: propsTransform,
|
|
22553
|
-
isLintable: true
|
|
22551
|
+
isLintable: true,
|
|
22552
|
+
validator: numericInputValidator
|
|
22554
22553
|
};
|
|
22555
22554
|
|
|
22556
22555
|
/**
|
|
@@ -24371,16 +24370,15 @@ class Passage extends React__namespace.Component {
|
|
|
24371
24370
|
highlights: {},
|
|
24372
24371
|
linterContext: PerseusLinter.linterContextDefault
|
|
24373
24372
|
};
|
|
24373
|
+
|
|
24374
|
+
// this just helps with TS weak typing when a Widget
|
|
24375
|
+
// doesn't implement any Widget methods
|
|
24376
|
+
isWidget = true;
|
|
24374
24377
|
state = {
|
|
24375
24378
|
nLines: null,
|
|
24376
24379
|
startLineNumbersAfter: 0,
|
|
24377
24380
|
stylesAreApplied: false
|
|
24378
24381
|
};
|
|
24379
|
-
|
|
24380
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24381
|
-
static validate() {
|
|
24382
|
-
return noopValidator();
|
|
24383
|
-
}
|
|
24384
24382
|
componentDidMount() {
|
|
24385
24383
|
this._updateState();
|
|
24386
24384
|
|
|
@@ -24589,21 +24587,6 @@ class Passage extends React__namespace.Component {
|
|
|
24589
24587
|
};
|
|
24590
24588
|
}
|
|
24591
24589
|
|
|
24592
|
-
/**
|
|
24593
|
-
* Misc functions
|
|
24594
|
-
*
|
|
24595
|
-
* These are misc widget functions used for the widget API
|
|
24596
|
-
*/
|
|
24597
|
-
|
|
24598
|
-
getUserInput() {
|
|
24599
|
-
return null;
|
|
24600
|
-
}
|
|
24601
|
-
|
|
24602
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24603
|
-
simpleValidate() {
|
|
24604
|
-
return noopValidator();
|
|
24605
|
-
}
|
|
24606
|
-
|
|
24607
24590
|
/**
|
|
24608
24591
|
* Rendering
|
|
24609
24592
|
*
|
|
@@ -24747,7 +24730,8 @@ var Passage$1 = {
|
|
|
24747
24730
|
transform: editorProps => {
|
|
24748
24731
|
return ___default["default"].pick(editorProps, "passageTitle", "passageText", "footnotes", "showLineNumbers");
|
|
24749
24732
|
},
|
|
24750
|
-
isLintable: true
|
|
24733
|
+
isLintable: true,
|
|
24734
|
+
validator: () => noopValidator()
|
|
24751
24735
|
};
|
|
24752
24736
|
|
|
24753
24737
|
/**
|
|
@@ -24777,15 +24761,14 @@ class PassageRef extends React__namespace.Component {
|
|
|
24777
24761
|
referenceNumber: 1,
|
|
24778
24762
|
summaryText: ""
|
|
24779
24763
|
};
|
|
24764
|
+
|
|
24765
|
+
// this just helps with TS weak typing when a Widget
|
|
24766
|
+
// doesn't implement any Widget methods
|
|
24767
|
+
isWidget = true;
|
|
24780
24768
|
state = {
|
|
24781
24769
|
lineRange: null,
|
|
24782
24770
|
content: null
|
|
24783
24771
|
};
|
|
24784
|
-
|
|
24785
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24786
|
-
static validate() {
|
|
24787
|
-
return noopValidator();
|
|
24788
|
-
}
|
|
24789
24772
|
componentDidMount() {
|
|
24790
24773
|
// TODO(scottgrant): This is a hack to remove the deprecated call to
|
|
24791
24774
|
// this.isMounted() but is still considered an anti-pattern.
|
|
@@ -24804,11 +24787,6 @@ class PassageRef extends React__namespace.Component {
|
|
|
24804
24787
|
window.removeEventListener("resize", this._throttledUpdateRange);
|
|
24805
24788
|
this._isMounted = false;
|
|
24806
24789
|
}
|
|
24807
|
-
|
|
24808
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24809
|
-
getUserInput() {
|
|
24810
|
-
return null;
|
|
24811
|
-
}
|
|
24812
24790
|
change = (() => {
|
|
24813
24791
|
var _this = this;
|
|
24814
24792
|
return function () {
|
|
@@ -24838,11 +24816,6 @@ class PassageRef extends React__namespace.Component {
|
|
|
24838
24816
|
}
|
|
24839
24817
|
}
|
|
24840
24818
|
};
|
|
24841
|
-
|
|
24842
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24843
|
-
simpleValidate() {
|
|
24844
|
-
return noopValidator();
|
|
24845
|
-
}
|
|
24846
24819
|
render() {
|
|
24847
24820
|
const {
|
|
24848
24821
|
strings
|
|
@@ -24891,7 +24864,9 @@ var PassageRef$1 = {
|
|
|
24891
24864
|
version: {
|
|
24892
24865
|
major: 0,
|
|
24893
24866
|
minor: 1
|
|
24894
|
-
}
|
|
24867
|
+
},
|
|
24868
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
24869
|
+
validator: () => noopValidator()
|
|
24895
24870
|
};
|
|
24896
24871
|
|
|
24897
24872
|
/**
|
|
@@ -26310,9 +26285,6 @@ class Radio$1 extends React__namespace.Component {
|
|
|
26310
26285
|
linterContext: PerseusLinter.linterContextDefault,
|
|
26311
26286
|
showSolutions: "none"
|
|
26312
26287
|
};
|
|
26313
|
-
static validate(userInput, rubric, strings) {
|
|
26314
|
-
return radioValidator(userInput, rubric, strings);
|
|
26315
|
-
}
|
|
26316
26288
|
static getUserInputFromProps(props) {
|
|
26317
26289
|
// Return checked inputs in the form {choicesSelected: [bool]}. (Dear
|
|
26318
26290
|
// future timeline implementers: this used to be {value: i} before
|
|
@@ -26499,9 +26471,6 @@ class Radio$1 extends React__namespace.Component {
|
|
|
26499
26471
|
getUserInput() {
|
|
26500
26472
|
return Radio$1.getUserInputFromProps(this.props);
|
|
26501
26473
|
}
|
|
26502
|
-
simpleValidate(rubric) {
|
|
26503
|
-
return radioValidator(this.getUserInput(), rubric, this.context.strings);
|
|
26504
|
-
}
|
|
26505
26474
|
|
|
26506
26475
|
/**
|
|
26507
26476
|
* Turn on rationale display for the currently selected choices. Note that
|
|
@@ -26514,7 +26483,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
26514
26483
|
choiceStates
|
|
26515
26484
|
} = this.props;
|
|
26516
26485
|
if (choiceStates) {
|
|
26517
|
-
const score = this.
|
|
26486
|
+
const score = radioValidator(this.getUserInput(), rubric, this.context.strings);
|
|
26518
26487
|
const widgetCorrect = score.type === "points" && score.total === score.earned;
|
|
26519
26488
|
const newStates = choiceStates.map(state => ({
|
|
26520
26489
|
...state,
|
|
@@ -26794,7 +26763,8 @@ var Radio = {
|
|
|
26794
26763
|
minor: 0
|
|
26795
26764
|
},
|
|
26796
26765
|
propUpgrades: propUpgrades$1,
|
|
26797
|
-
isLintable: true
|
|
26766
|
+
isLintable: true,
|
|
26767
|
+
validator: radioValidator
|
|
26798
26768
|
};
|
|
26799
26769
|
|
|
26800
26770
|
/* eslint-disable import/no-named-as-default */
|
|
@@ -26837,9 +26807,6 @@ class Categorizer extends React__namespace.Component {
|
|
|
26837
26807
|
state = {
|
|
26838
26808
|
uniqueId: ___default["default"].uniqueId("perseus_radio_")
|
|
26839
26809
|
};
|
|
26840
|
-
static validate(userInput, rubric, strings) {
|
|
26841
|
-
return categorizerValidator(userInput, rubric, strings);
|
|
26842
|
-
}
|
|
26843
26810
|
static getUserInputFromProps(props) {
|
|
26844
26811
|
return {
|
|
26845
26812
|
values: props.values
|
|
@@ -26865,9 +26832,6 @@ class Categorizer extends React__namespace.Component {
|
|
|
26865
26832
|
this.change("values", values);
|
|
26866
26833
|
this.props.trackInteraction();
|
|
26867
26834
|
}
|
|
26868
|
-
simpleValidate(rubric) {
|
|
26869
|
-
return categorizerValidator(this.getUserInput(), rubric, this.context.strings);
|
|
26870
|
-
}
|
|
26871
26835
|
render() {
|
|
26872
26836
|
const self = this;
|
|
26873
26837
|
|
|
@@ -27006,7 +26970,8 @@ var Categorizer$1 = {
|
|
|
27006
26970
|
staticTransform: editorProps => {
|
|
27007
26971
|
return ___default["default"].pick(editorProps, "items", "categories", "values", "randomizeItems");
|
|
27008
26972
|
},
|
|
27009
|
-
isLintable: true
|
|
26973
|
+
isLintable: true,
|
|
26974
|
+
validator: categorizerValidator
|
|
27010
26975
|
};
|
|
27011
26976
|
|
|
27012
26977
|
/**
|
|
@@ -27111,11 +27076,6 @@ class CSProgram extends React__namespace.Component {
|
|
|
27111
27076
|
// optional message
|
|
27112
27077
|
message: null
|
|
27113
27078
|
};
|
|
27114
|
-
|
|
27115
|
-
// The widget's grading function
|
|
27116
|
-
static validate(state) {
|
|
27117
|
-
return csProgramValidator(state);
|
|
27118
|
-
}
|
|
27119
27079
|
componentDidMount() {
|
|
27120
27080
|
$__default["default"](window).on("message", this.handleMessageEvent);
|
|
27121
27081
|
}
|
|
@@ -27157,9 +27117,6 @@ class CSProgram extends React__namespace.Component {
|
|
|
27157
27117
|
message: this.props.message
|
|
27158
27118
|
};
|
|
27159
27119
|
}
|
|
27160
|
-
simpleValidate() {
|
|
27161
|
-
return csProgramValidator(this.getUserInput());
|
|
27162
|
-
}
|
|
27163
27120
|
render() {
|
|
27164
27121
|
if (!this.props.programID) {
|
|
27165
27122
|
return /*#__PURE__*/React__namespace.createElement("div", null);
|
|
@@ -27234,7 +27191,8 @@ var CSProgram$1 = {
|
|
|
27234
27191
|
displayName: "CS Program",
|
|
27235
27192
|
supportedAlignments: ["block", "full-width"],
|
|
27236
27193
|
widget: CSProgram,
|
|
27237
|
-
hidden: true
|
|
27194
|
+
hidden: true,
|
|
27195
|
+
validator: csProgramValidator
|
|
27238
27196
|
};
|
|
27239
27197
|
|
|
27240
27198
|
class Definition extends React__namespace.Component {
|
|
@@ -27244,18 +27202,9 @@ class Definition extends React__namespace.Component {
|
|
|
27244
27202
|
definition: "definition goes here"
|
|
27245
27203
|
};
|
|
27246
27204
|
|
|
27247
|
-
//
|
|
27248
|
-
|
|
27249
|
-
|
|
27250
|
-
}
|
|
27251
|
-
getUserInput() {
|
|
27252
|
-
return {};
|
|
27253
|
-
}
|
|
27254
|
-
|
|
27255
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27256
|
-
simpleValidate() {
|
|
27257
|
-
return noopValidator();
|
|
27258
|
-
}
|
|
27205
|
+
// this just helps with TS weak typing when a Widget
|
|
27206
|
+
// doesn't implement any Widget methods
|
|
27207
|
+
isWidget = true;
|
|
27259
27208
|
render() {
|
|
27260
27209
|
return /*#__PURE__*/React__namespace.createElement(DefinitionConsumer, null, _ref => {
|
|
27261
27210
|
let {
|
|
@@ -27311,24 +27260,18 @@ var Definition$1 = {
|
|
|
27311
27260
|
accessible: true,
|
|
27312
27261
|
defaultAlignment: "inline",
|
|
27313
27262
|
widget: Definition,
|
|
27314
|
-
transform: x => x
|
|
27263
|
+
transform: x => x,
|
|
27264
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
27265
|
+
validator: () => noopValidator()
|
|
27315
27266
|
};
|
|
27316
27267
|
|
|
27317
27268
|
// The props are type `any` on purpose so that this can receive props
|
|
27318
27269
|
// from any deprecated widget
|
|
27319
27270
|
class DeprecatedStandin extends React__default["default"].Component {
|
|
27320
27271
|
static contextType = PerseusI18nContext;
|
|
27321
|
-
|
|
27322
|
-
|
|
27323
|
-
|
|
27324
|
-
return noopValidator(1);
|
|
27325
|
-
}
|
|
27326
|
-
getUserInput() {
|
|
27327
|
-
return {};
|
|
27328
|
-
}
|
|
27329
|
-
simpleValidate() {
|
|
27330
|
-
return noopValidator(1);
|
|
27331
|
-
}
|
|
27272
|
+
// this just helps with TS weak typing when a Widget
|
|
27273
|
+
// doesn't implement any Widget methods
|
|
27274
|
+
isWidget = true;
|
|
27332
27275
|
render() {
|
|
27333
27276
|
return /*#__PURE__*/React__default["default"].createElement("div", {
|
|
27334
27277
|
style: {
|
|
@@ -27346,7 +27289,9 @@ var DeprecatedStandin$1 = {
|
|
|
27346
27289
|
name: "deprecated-standin",
|
|
27347
27290
|
displayName: "Deprecated Standin",
|
|
27348
27291
|
widget: DeprecatedStandin,
|
|
27349
|
-
hidden: true
|
|
27292
|
+
hidden: true,
|
|
27293
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
27294
|
+
validator: () => noopValidator(1)
|
|
27350
27295
|
};
|
|
27351
27296
|
|
|
27352
27297
|
function dropdownValidator(userInput, rubric) {
|
|
@@ -27373,9 +27318,6 @@ class Dropdown extends React__namespace.Component {
|
|
|
27373
27318
|
placeholder: "",
|
|
27374
27319
|
apiOptions: ApiOptions.defaults
|
|
27375
27320
|
};
|
|
27376
|
-
static validate(userInput, rubric) {
|
|
27377
|
-
return dropdownValidator(userInput, rubric);
|
|
27378
|
-
}
|
|
27379
27321
|
focus = () => {
|
|
27380
27322
|
// TODO(LP-10797): This focus() call doesn't do anything because our
|
|
27381
27323
|
// root element is a <div> and that cannot be focused without a
|
|
@@ -27398,9 +27340,6 @@ class Dropdown extends React__namespace.Component {
|
|
|
27398
27340
|
value: this.props.selected
|
|
27399
27341
|
};
|
|
27400
27342
|
}
|
|
27401
|
-
simpleValidate(rubric) {
|
|
27402
|
-
return dropdownValidator(this.getUserInput(), rubric);
|
|
27403
|
-
}
|
|
27404
27343
|
render() {
|
|
27405
27344
|
const children = [/*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
27406
27345
|
key: "placeholder",
|
|
@@ -27441,7 +27380,8 @@ var Dropdown$1 = {
|
|
|
27441
27380
|
defaultAlignment: "inline-block",
|
|
27442
27381
|
accessible: true,
|
|
27443
27382
|
widget: Dropdown,
|
|
27444
|
-
transform: optionsTransform
|
|
27383
|
+
transform: optionsTransform,
|
|
27384
|
+
validator: dropdownValidator
|
|
27445
27385
|
};
|
|
27446
27386
|
|
|
27447
27387
|
// transform = _.identity
|
|
@@ -27454,10 +27394,6 @@ function mediaQueryIsMatched(mediaQuery) {
|
|
|
27454
27394
|
}
|
|
27455
27395
|
class Explanation extends React__namespace.Component {
|
|
27456
27396
|
static contextType = PerseusI18nContext;
|
|
27457
|
-
state = {
|
|
27458
|
-
expanded: false
|
|
27459
|
-
};
|
|
27460
|
-
_mounted = false;
|
|
27461
27397
|
static defaultProps = {
|
|
27462
27398
|
showPrompt: "Explain",
|
|
27463
27399
|
hidePrompt: "Hide explanation",
|
|
@@ -27466,10 +27402,13 @@ class Explanation extends React__namespace.Component {
|
|
|
27466
27402
|
linterContext: PerseusLinter.linterContextDefault
|
|
27467
27403
|
};
|
|
27468
27404
|
|
|
27469
|
-
//
|
|
27470
|
-
|
|
27471
|
-
|
|
27472
|
-
|
|
27405
|
+
// this just helps with TS weak typing when a Widget
|
|
27406
|
+
// doesn't implement any Widget methods
|
|
27407
|
+
isWidget = true;
|
|
27408
|
+
state = {
|
|
27409
|
+
expanded: false
|
|
27410
|
+
};
|
|
27411
|
+
_mounted = false;
|
|
27473
27412
|
componentDidMount() {
|
|
27474
27413
|
this._mounted = true;
|
|
27475
27414
|
}
|
|
@@ -27491,14 +27430,6 @@ class Explanation extends React__namespace.Component {
|
|
|
27491
27430
|
});
|
|
27492
27431
|
this.props.trackInteraction();
|
|
27493
27432
|
};
|
|
27494
|
-
getUserInput() {
|
|
27495
|
-
return {};
|
|
27496
|
-
}
|
|
27497
|
-
|
|
27498
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27499
|
-
simpleValidate() {
|
|
27500
|
-
return noopValidator();
|
|
27501
|
-
}
|
|
27502
27433
|
render() {
|
|
27503
27434
|
const promptText = this.state.expanded ? this.props.hidePrompt : this.props.showPrompt;
|
|
27504
27435
|
const caretIcon = this.state.expanded ? caretUp__default["default"] : caretDown__default["default"];
|
|
@@ -27604,7 +27535,9 @@ var Explanation$1 = {
|
|
|
27604
27535
|
defaultAlignment: "inline",
|
|
27605
27536
|
widget: Explanation,
|
|
27606
27537
|
transform: ___default["default"].identity,
|
|
27607
|
-
isLintable: true
|
|
27538
|
+
isLintable: true,
|
|
27539
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
27540
|
+
validator: () => noopValidator()
|
|
27608
27541
|
};
|
|
27609
27542
|
|
|
27610
27543
|
class GradedGroupAnswerBar extends React__namespace.Component {
|
|
@@ -29136,9 +29069,6 @@ class Grapher extends React__namespace.Component {
|
|
|
29136
29069
|
horizHairline;
|
|
29137
29070
|
vertHairline;
|
|
29138
29071
|
static defaultProps = DEFAULT_GRAPHER_PROPS;
|
|
29139
|
-
static validate(state, rubric) {
|
|
29140
|
-
return grapherValidator(state, rubric);
|
|
29141
|
-
}
|
|
29142
29072
|
static getUserInputFromProps(props) {
|
|
29143
29073
|
return props.plot;
|
|
29144
29074
|
}
|
|
@@ -29241,9 +29171,6 @@ class Grapher extends React__namespace.Component {
|
|
|
29241
29171
|
this.vertHairline.hide();
|
|
29242
29172
|
}
|
|
29243
29173
|
};
|
|
29244
|
-
simpleValidate(rubric) {
|
|
29245
|
-
return grapherValidator(this.getUserInput(), rubric);
|
|
29246
|
-
}
|
|
29247
29174
|
getUserInput() {
|
|
29248
29175
|
return Grapher.getUserInputFromProps(this.props);
|
|
29249
29176
|
}
|
|
@@ -29335,7 +29262,8 @@ var Grapher$1 = {
|
|
|
29335
29262
|
hidden: true,
|
|
29336
29263
|
widget: Grapher,
|
|
29337
29264
|
transform: propTransform$2,
|
|
29338
|
-
staticTransform: staticTransform$4
|
|
29265
|
+
staticTransform: staticTransform$4,
|
|
29266
|
+
validator: grapherValidator
|
|
29339
29267
|
};
|
|
29340
29268
|
|
|
29341
29269
|
// exports has no 'transform'
|
|
@@ -29364,6 +29292,13 @@ class Group extends React__namespace.Component {
|
|
|
29364
29292
|
return change.apply(_this, args);
|
|
29365
29293
|
};
|
|
29366
29294
|
})();
|
|
29295
|
+
getUserInputMap() {
|
|
29296
|
+
return this.rendererRef?.getUserInputMap();
|
|
29297
|
+
}
|
|
29298
|
+
|
|
29299
|
+
/**
|
|
29300
|
+
* @deprecated getUserInputMap should be used for Groups
|
|
29301
|
+
*/
|
|
29367
29302
|
getUserInput() {
|
|
29368
29303
|
return this.rendererRef?.getUserInput();
|
|
29369
29304
|
}
|
|
@@ -29376,11 +29311,6 @@ class Group extends React__namespace.Component {
|
|
|
29376
29311
|
// (all our changes were in state):
|
|
29377
29312
|
return null;
|
|
29378
29313
|
};
|
|
29379
|
-
simpleValidate() {
|
|
29380
|
-
return this.rendererRef?.score() ?? {
|
|
29381
|
-
type: "invalid"
|
|
29382
|
-
};
|
|
29383
|
-
}
|
|
29384
29314
|
|
|
29385
29315
|
// Mobile API:
|
|
29386
29316
|
getInputPaths() {
|
|
@@ -29530,9 +29460,6 @@ class Iframe extends React__namespace.Component {
|
|
|
29530
29460
|
allowFullScreen: false,
|
|
29531
29461
|
allowTopNavigation: false
|
|
29532
29462
|
};
|
|
29533
|
-
static validate(state) {
|
|
29534
|
-
return iframeValidator(state);
|
|
29535
|
-
}
|
|
29536
29463
|
componentDidMount() {
|
|
29537
29464
|
$__default["default"](window).on("message", this.handleMessageEvent);
|
|
29538
29465
|
}
|
|
@@ -29574,9 +29501,6 @@ class Iframe extends React__namespace.Component {
|
|
|
29574
29501
|
return change.apply(_this, args);
|
|
29575
29502
|
};
|
|
29576
29503
|
})();
|
|
29577
|
-
simpleValidate() {
|
|
29578
|
-
return iframeValidator(this.getUserInput());
|
|
29579
|
-
}
|
|
29580
29504
|
render() {
|
|
29581
29505
|
const style = {
|
|
29582
29506
|
width: String(this.props.width),
|
|
@@ -29644,7 +29568,8 @@ var Iframe$1 = {
|
|
|
29644
29568
|
displayName: "Iframe (deprecated)",
|
|
29645
29569
|
widget: Iframe,
|
|
29646
29570
|
// Let's not expose it to all content creators yet
|
|
29647
|
-
hidden: true
|
|
29571
|
+
hidden: true,
|
|
29572
|
+
validator: iframeValidator
|
|
29648
29573
|
};
|
|
29649
29574
|
|
|
29650
29575
|
const defaultBoxSize = 400;
|
|
@@ -29673,10 +29598,9 @@ class ImageWidget extends React__namespace.Component {
|
|
|
29673
29598
|
linterContext: PerseusLinter.linterContextDefault
|
|
29674
29599
|
};
|
|
29675
29600
|
|
|
29676
|
-
//
|
|
29677
|
-
|
|
29678
|
-
|
|
29679
|
-
}
|
|
29601
|
+
// this just helps with TS weak typing when a Widget
|
|
29602
|
+
// doesn't implement any Widget methods
|
|
29603
|
+
isWidget = true;
|
|
29680
29604
|
change = (() => {
|
|
29681
29605
|
var _this = this;
|
|
29682
29606
|
return function () {
|
|
@@ -29686,14 +29610,6 @@ class ImageWidget extends React__namespace.Component {
|
|
|
29686
29610
|
return change.apply(_this, args);
|
|
29687
29611
|
};
|
|
29688
29612
|
})();
|
|
29689
|
-
getUserInput() {
|
|
29690
|
-
return null;
|
|
29691
|
-
}
|
|
29692
|
-
|
|
29693
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
29694
|
-
simpleValidate() {
|
|
29695
|
-
return noopValidator();
|
|
29696
|
-
}
|
|
29697
29613
|
render() {
|
|
29698
29614
|
let image;
|
|
29699
29615
|
const alt = this.props.caption === this.props.alt ? "" : this.props.alt;
|
|
@@ -29839,7 +29755,9 @@ var Image$1 = {
|
|
|
29839
29755
|
supportedAlignments: editorAlignments,
|
|
29840
29756
|
displayName: "Image",
|
|
29841
29757
|
widget: ImageWidget,
|
|
29842
|
-
isLintable: true
|
|
29758
|
+
isLintable: true,
|
|
29759
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
29760
|
+
validator: () => noopValidator()
|
|
29843
29761
|
};
|
|
29844
29762
|
|
|
29845
29763
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -29918,10 +29836,9 @@ class Interaction extends React__namespace.Component {
|
|
|
29918
29836
|
elements: []
|
|
29919
29837
|
};
|
|
29920
29838
|
|
|
29921
|
-
//
|
|
29922
|
-
|
|
29923
|
-
|
|
29924
|
-
}
|
|
29839
|
+
// this just helps with TS weak typing when a Widget
|
|
29840
|
+
// doesn't implement any Widget methods
|
|
29841
|
+
isWidget = true;
|
|
29925
29842
|
state = {
|
|
29926
29843
|
variables: _getInitialVariables(this.props.elements),
|
|
29927
29844
|
functions: _getInitialFunctions(this.props.elements)
|
|
@@ -30029,18 +29946,6 @@ class Interaction extends React__namespace.Component {
|
|
|
30029
29946
|
return change.apply(_this, args);
|
|
30030
29947
|
};
|
|
30031
29948
|
})();
|
|
30032
|
-
getUserInput() {
|
|
30033
|
-
// TODO(eater): Perhaps we want to be able to record the state of the
|
|
30034
|
-
// user's interaction. Unfortunately sending all the props will
|
|
30035
|
-
// probably make the attempt payload too large. So for now, don't send
|
|
30036
|
-
// anything.
|
|
30037
|
-
return {};
|
|
30038
|
-
}
|
|
30039
|
-
|
|
30040
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
30041
|
-
simpleValidate() {
|
|
30042
|
-
return noopValidator();
|
|
30043
|
-
}
|
|
30044
29949
|
render() {
|
|
30045
29950
|
const range = this.props.graph.range;
|
|
30046
29951
|
let labels = this.props.graph.labels;
|
|
@@ -30448,7 +30353,9 @@ var Interactive = {
|
|
|
30448
30353
|
displayName: "Interaction",
|
|
30449
30354
|
widget: Interaction,
|
|
30450
30355
|
transform: ___default["default"].identity,
|
|
30451
|
-
hidden: true
|
|
30356
|
+
hidden: true,
|
|
30357
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
30358
|
+
validator: () => noopValidator()
|
|
30452
30359
|
};
|
|
30453
30360
|
|
|
30454
30361
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -37605,9 +37512,6 @@ class LegacyInteractiveGraph extends React__namespace.Component {
|
|
|
37605
37512
|
getUserInput() {
|
|
37606
37513
|
return InteractiveGraph.getUserInputFromProps(this.props);
|
|
37607
37514
|
}
|
|
37608
|
-
simpleValidate(rubric) {
|
|
37609
|
-
return interactiveGraphValidator(this.getUserInput(), rubric);
|
|
37610
|
-
}
|
|
37611
37515
|
focus = $__default["default"].noop;
|
|
37612
37516
|
render() {
|
|
37613
37517
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
@@ -37680,9 +37584,6 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
37680
37584
|
}
|
|
37681
37585
|
throw new perseusCore.PerseusError("Cannot getUserInput from a graph that has never rendered", perseusCore.Errors.NotAllowed);
|
|
37682
37586
|
}
|
|
37683
|
-
simpleValidate(rubric) {
|
|
37684
|
-
return interactiveGraphValidator(this.getUserInput(), rubric);
|
|
37685
|
-
}
|
|
37686
37587
|
render() {
|
|
37687
37588
|
// Mafs shim
|
|
37688
37589
|
const mafsFlags = this.props.apiOptions?.flags?.["mafs"];
|
|
@@ -38013,9 +37914,6 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
38013
37914
|
const angle = getClockwiseAngle(coords, allowReflexAngles);
|
|
38014
37915
|
return angle.toFixed(0) + "\u00B0 angle" + " at (" + coords[1].join(", ") + ")";
|
|
38015
37916
|
}
|
|
38016
|
-
static validate(userInput, rubric) {
|
|
38017
|
-
return interactiveGraphValidator(userInput, rubric);
|
|
38018
|
-
}
|
|
38019
37917
|
static getUserInputFromProps(props) {
|
|
38020
37918
|
return props.graph;
|
|
38021
37919
|
}
|
|
@@ -38052,7 +37950,8 @@ var InteractiveGraph$1 = {
|
|
|
38052
37950
|
name: "interactive-graph",
|
|
38053
37951
|
displayName: "Interactive graph (Assessments only)",
|
|
38054
37952
|
widget: InteractiveGraph,
|
|
38055
|
-
staticTransform: staticTransform$3
|
|
37953
|
+
staticTransform: staticTransform$3,
|
|
37954
|
+
validator: interactiveGraphValidator
|
|
38056
37955
|
};
|
|
38057
37956
|
|
|
38058
37957
|
const black = "#000000";
|
|
@@ -39428,9 +39327,6 @@ class LabelImage extends React__namespace.Component {
|
|
|
39428
39327
|
// The rendered markers on the question image for labeling.
|
|
39429
39328
|
_markers;
|
|
39430
39329
|
_mounted = false;
|
|
39431
|
-
static validate(state, rubric) {
|
|
39432
|
-
return labelImageValidator(state);
|
|
39433
|
-
}
|
|
39434
39330
|
|
|
39435
39331
|
/**
|
|
39436
39332
|
* Test whether point is contained within triangle.
|
|
@@ -39623,9 +39519,6 @@ class LabelImage extends React__namespace.Component {
|
|
|
39623
39519
|
componentWillUnmount() {
|
|
39624
39520
|
this._mounted = false;
|
|
39625
39521
|
}
|
|
39626
|
-
simpleValidate(rubric) {
|
|
39627
|
-
return labelImageValidator(this.getUserInput());
|
|
39628
|
-
}
|
|
39629
39522
|
getUserInput() {
|
|
39630
39523
|
const {
|
|
39631
39524
|
markers
|
|
@@ -39991,19 +39884,13 @@ const LabelImageWithDependencies = /*#__PURE__*/React__namespace.forwardRef((pro
|
|
|
39991
39884
|
analytics: deps.analytics
|
|
39992
39885
|
}, props));
|
|
39993
39886
|
});
|
|
39994
|
-
|
|
39995
|
-
// HACK: Propogate "static" methods onto our wrapper component.
|
|
39996
|
-
// In the future we should adjust client apps to not depend on these static
|
|
39997
|
-
// methods and instead adjust Peresus to provide these facilities through
|
|
39998
|
-
// instance methods on our Renderers.
|
|
39999
|
-
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type
|
|
40000
|
-
LabelImageWithDependencies.validate = labelImageValidator;
|
|
40001
39887
|
var LabelImage$1 = {
|
|
40002
39888
|
name: "label-image",
|
|
40003
39889
|
displayName: "Label Image",
|
|
40004
39890
|
widget: LabelImageWithDependencies,
|
|
40005
39891
|
accessible: true,
|
|
40006
|
-
isLintable: true
|
|
39892
|
+
isLintable: true,
|
|
39893
|
+
validator: labelImageValidator
|
|
40007
39894
|
};
|
|
40008
39895
|
|
|
40009
39896
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -40745,9 +40632,6 @@ class Matcher extends React__namespace.Component {
|
|
|
40745
40632
|
rightHeight: 0,
|
|
40746
40633
|
texRendererLoaded: false
|
|
40747
40634
|
};
|
|
40748
|
-
static validate(state, rubric) {
|
|
40749
|
-
return matcherValidator(state, rubric);
|
|
40750
|
-
}
|
|
40751
40635
|
changeAndTrack = e => {
|
|
40752
40636
|
this.props.onChange(e);
|
|
40753
40637
|
this.props.trackInteraction();
|
|
@@ -40799,9 +40683,6 @@ class Matcher extends React__namespace.Component {
|
|
|
40799
40683
|
// @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
|
|
40800
40684
|
this.refs.right.moveOptionToIndex(option, index);
|
|
40801
40685
|
};
|
|
40802
|
-
simpleValidate(rubric) {
|
|
40803
|
-
return matcherValidator(this.getUserInput(), rubric);
|
|
40804
|
-
}
|
|
40805
40686
|
render() {
|
|
40806
40687
|
// To minimize layout shift, we display a spinner until our math
|
|
40807
40688
|
// renderer is ready to render the math inside the matcher. To
|
|
@@ -40928,7 +40809,8 @@ var Matcher$1 = {
|
|
|
40928
40809
|
name: "matcher",
|
|
40929
40810
|
displayName: "Matcher (two column)",
|
|
40930
40811
|
widget: Matcher,
|
|
40931
|
-
isLintable: true
|
|
40812
|
+
isLintable: true,
|
|
40813
|
+
validator: matcherValidator
|
|
40932
40814
|
};
|
|
40933
40815
|
|
|
40934
40816
|
function matrixValidator(state, rubric, strings) {
|
|
@@ -41069,9 +40951,6 @@ class Matrix extends React__namespace.Component {
|
|
|
41069
40951
|
apiOptions: ApiOptions.defaults,
|
|
41070
40952
|
linterContext: PerseusLinter.linterContextDefault
|
|
41071
40953
|
};
|
|
41072
|
-
static validate(state, rubric, strings) {
|
|
41073
|
-
return matrixValidator(state, rubric, strings);
|
|
41074
|
-
}
|
|
41075
40954
|
state = {
|
|
41076
40955
|
enterTheMatrix: 0
|
|
41077
40956
|
};
|
|
@@ -41214,9 +41093,6 @@ class Matrix extends React__namespace.Component {
|
|
|
41214
41093
|
answers: this.props.answers
|
|
41215
41094
|
};
|
|
41216
41095
|
}
|
|
41217
|
-
simpleValidate(rubric) {
|
|
41218
|
-
return matrixValidator(this.getUserInput(), rubric, this.context.strings);
|
|
41219
|
-
}
|
|
41220
41096
|
render() {
|
|
41221
41097
|
// Set the input sizes through JS so we can control the size of the
|
|
41222
41098
|
// brackets. (If we set them in CSS we won't know values until the
|
|
@@ -41401,7 +41277,8 @@ var Matrix$1 = {
|
|
|
41401
41277
|
widget: Matrix,
|
|
41402
41278
|
transform: propTransform$1,
|
|
41403
41279
|
staticTransform: staticTransform$2,
|
|
41404
|
-
isLintable: true
|
|
41280
|
+
isLintable: true,
|
|
41281
|
+
validator: matrixValidator
|
|
41405
41282
|
};
|
|
41406
41283
|
|
|
41407
41284
|
const defaultImage = {
|
|
@@ -41410,7 +41287,6 @@ const defaultImage = {
|
|
|
41410
41287
|
left: 0
|
|
41411
41288
|
};
|
|
41412
41289
|
class Measurer extends React__namespace.Component {
|
|
41413
|
-
static validate = noopValidator;
|
|
41414
41290
|
static defaultProps = {
|
|
41415
41291
|
box: [480, 480],
|
|
41416
41292
|
image: {},
|
|
@@ -41423,6 +41299,10 @@ class Measurer extends React__namespace.Component {
|
|
|
41423
41299
|
rulerPixels: 40,
|
|
41424
41300
|
rulerLength: 10
|
|
41425
41301
|
};
|
|
41302
|
+
|
|
41303
|
+
// this just helps with TS weak typing when a Widget
|
|
41304
|
+
// doesn't implement any Widget methods
|
|
41305
|
+
isWidget = true;
|
|
41426
41306
|
state = {};
|
|
41427
41307
|
ruler;
|
|
41428
41308
|
protractor;
|
|
@@ -41475,12 +41355,6 @@ class Measurer extends React__namespace.Component {
|
|
|
41475
41355
|
});
|
|
41476
41356
|
}
|
|
41477
41357
|
}
|
|
41478
|
-
getUserInput() {
|
|
41479
|
-
return {};
|
|
41480
|
-
}
|
|
41481
|
-
simpleValidate() {
|
|
41482
|
-
return noopValidator(1);
|
|
41483
|
-
}
|
|
41484
41358
|
render() {
|
|
41485
41359
|
const image = ___default["default"].extend({}, defaultImage, this.props.image);
|
|
41486
41360
|
|
|
@@ -41527,7 +41401,9 @@ var Measurer$1 = {
|
|
|
41527
41401
|
major: 1,
|
|
41528
41402
|
minor: 0
|
|
41529
41403
|
},
|
|
41530
|
-
propUpgrades: propUpgrades
|
|
41404
|
+
propUpgrades: propUpgrades,
|
|
41405
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
41406
|
+
validator: () => noopValidator(1)
|
|
41531
41407
|
};
|
|
41532
41408
|
|
|
41533
41409
|
/**
|
|
@@ -42400,18 +42276,9 @@ class MoleculeWidget extends React__namespace.Component {
|
|
|
42400
42276
|
rotationAngle: 0
|
|
42401
42277
|
};
|
|
42402
42278
|
|
|
42403
|
-
//
|
|
42404
|
-
|
|
42405
|
-
|
|
42406
|
-
}
|
|
42407
|
-
getUserInput() {
|
|
42408
|
-
return [];
|
|
42409
|
-
}
|
|
42410
|
-
|
|
42411
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
42412
|
-
validate() {
|
|
42413
|
-
return noopValidator();
|
|
42414
|
-
}
|
|
42279
|
+
// this just helps with TS weak typing when a Widget
|
|
42280
|
+
// doesn't implement any Widget methods
|
|
42281
|
+
isWidget = true;
|
|
42415
42282
|
render() {
|
|
42416
42283
|
return /*#__PURE__*/React__namespace.createElement(Molecule, {
|
|
42417
42284
|
widgetId: this.props.widgetId,
|
|
@@ -42424,7 +42291,8 @@ var Molecule$1 = {
|
|
|
42424
42291
|
name: "molecule-renderer",
|
|
42425
42292
|
displayName: "Molecule renderer",
|
|
42426
42293
|
hidden: true,
|
|
42427
|
-
widget: MoleculeWidget
|
|
42294
|
+
widget: MoleculeWidget,
|
|
42295
|
+
validator: () => noopValidator()
|
|
42428
42296
|
};
|
|
42429
42297
|
|
|
42430
42298
|
function numberLineValidator(state, rubric) {
|
|
@@ -42569,18 +42437,16 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
|
|
|
42569
42437
|
results.push(graphie.line([x, -0.2], [x, 0.2]));
|
|
42570
42438
|
const labelTicks = props.labelTicks;
|
|
42571
42439
|
if (labelTicks || props.labelStyle === "decimal ticks") {
|
|
42572
|
-
|
|
42440
|
+
if (x === leftLabel || x === rightLabel) {
|
|
42441
|
+
results.push(graphie.style({
|
|
42442
|
+
color: KhanColors.BLUE
|
|
42443
|
+
}, () => _label(graphie, props.labelStyle, x, x, base)));
|
|
42444
|
+
} else {
|
|
42445
|
+
results.push(_label(graphie, props.labelStyle, x, x, base));
|
|
42446
|
+
}
|
|
42573
42447
|
}
|
|
42574
42448
|
}
|
|
42575
42449
|
|
|
42576
|
-
// Render the text labels
|
|
42577
|
-
results.push(graphie.style(props.isMobile ? {
|
|
42578
|
-
color: KhanColors.BLUE
|
|
42579
|
-
} : {}, () => _label(graphie, props.labelStyle, leftLabel, leftLabel, base)));
|
|
42580
|
-
results.push(graphie.style(props.isMobile ? {
|
|
42581
|
-
color: KhanColors.BLUE
|
|
42582
|
-
} : {}, () => _label(graphie, props.labelStyle, rightLabel, rightLabel, base)));
|
|
42583
|
-
|
|
42584
42450
|
// Render the labels' lines
|
|
42585
42451
|
graphie.style({
|
|
42586
42452
|
stroke: KhanColors.BLUE,
|
|
@@ -42613,9 +42479,6 @@ class NumberLine extends React__namespace.Component {
|
|
|
42613
42479
|
state = {
|
|
42614
42480
|
numDivisionsEmpty: false
|
|
42615
42481
|
};
|
|
42616
|
-
static validate(state, rubric) {
|
|
42617
|
-
return numberLineValidator(state, rubric);
|
|
42618
|
-
}
|
|
42619
42482
|
change = (() => {
|
|
42620
42483
|
var _this = this;
|
|
42621
42484
|
return function () {
|
|
@@ -42908,9 +42771,6 @@ class NumberLine extends React__namespace.Component {
|
|
|
42908
42771
|
divisionRange: this.props.divisionRange
|
|
42909
42772
|
};
|
|
42910
42773
|
}
|
|
42911
|
-
simpleValidate(rubric) {
|
|
42912
|
-
return numberLineValidator(this.getUserInput(), rubric);
|
|
42913
|
-
}
|
|
42914
42774
|
render() {
|
|
42915
42775
|
const {
|
|
42916
42776
|
strings
|
|
@@ -43014,7 +42874,8 @@ var NumberLine$1 = {
|
|
|
43014
42874
|
displayName: "Number line",
|
|
43015
42875
|
widget: NumberLine,
|
|
43016
42876
|
transform: numberLineTransform,
|
|
43017
|
-
staticTransform: staticTransform$1
|
|
42877
|
+
staticTransform: staticTransform$1,
|
|
42878
|
+
validator: numberLineValidator
|
|
43018
42879
|
};
|
|
43019
42880
|
|
|
43020
42881
|
function ordererValidator(userInput, rubric) {
|
|
@@ -43224,9 +43085,6 @@ class Orderer extends React__namespace.Component {
|
|
|
43224
43085
|
animateTo: null,
|
|
43225
43086
|
grabPos: null
|
|
43226
43087
|
};
|
|
43227
|
-
static validate(userInput, rubric) {
|
|
43228
|
-
return ordererValidator(userInput, rubric);
|
|
43229
|
-
}
|
|
43230
43088
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
43231
43089
|
if (!___default["default"].isEqual(this.props.current, nextProps.current)) {
|
|
43232
43090
|
this.setState({
|
|
@@ -43466,9 +43324,6 @@ class Orderer extends React__namespace.Component {
|
|
|
43466
43324
|
})
|
|
43467
43325
|
};
|
|
43468
43326
|
}
|
|
43469
|
-
simpleValidate(rubric) {
|
|
43470
|
-
return ordererValidator(this.getUserInput(), rubric);
|
|
43471
|
-
}
|
|
43472
43327
|
render() {
|
|
43473
43328
|
// This is the card we are currently dragging
|
|
43474
43329
|
const dragging = this.state.dragging && /*#__PURE__*/React__namespace.createElement(Card
|
|
@@ -43578,7 +43433,8 @@ var Orderer$1 = {
|
|
|
43578
43433
|
displayName: "Orderer",
|
|
43579
43434
|
hidden: true,
|
|
43580
43435
|
widget: Orderer,
|
|
43581
|
-
isLintable: true
|
|
43436
|
+
isLintable: true,
|
|
43437
|
+
validator: ordererValidator
|
|
43582
43438
|
};
|
|
43583
43439
|
|
|
43584
43440
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -43589,15 +43445,9 @@ class PassageRefTarget extends React__namespace.Component {
|
|
|
43589
43445
|
linterContext: PerseusLinter.linterContextDefault
|
|
43590
43446
|
};
|
|
43591
43447
|
|
|
43592
|
-
//
|
|
43593
|
-
|
|
43594
|
-
|
|
43595
|
-
}
|
|
43596
|
-
|
|
43597
|
-
// TODO passage-ref-target isn't interactive; remove
|
|
43598
|
-
getUserInput() {
|
|
43599
|
-
return null;
|
|
43600
|
-
}
|
|
43448
|
+
// this just helps with TS weak typing when a Widget
|
|
43449
|
+
// doesn't implement any Widget methods
|
|
43450
|
+
isWidget = true;
|
|
43601
43451
|
|
|
43602
43452
|
// TODO passage-ref-target isn't interactive; remove
|
|
43603
43453
|
change = (() => {
|
|
@@ -43609,11 +43459,6 @@ class PassageRefTarget extends React__namespace.Component {
|
|
|
43609
43459
|
return change.apply(_this, args);
|
|
43610
43460
|
};
|
|
43611
43461
|
})();
|
|
43612
|
-
|
|
43613
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43614
|
-
simpleValidate() {
|
|
43615
|
-
return noopValidator();
|
|
43616
|
-
}
|
|
43617
43462
|
render() {
|
|
43618
43463
|
return /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
43619
43464
|
content: this.props.content
|
|
@@ -43642,7 +43487,9 @@ var PassageRefTarget$1 = {
|
|
|
43642
43487
|
major: 0,
|
|
43643
43488
|
minor: 0
|
|
43644
43489
|
},
|
|
43645
|
-
isLintable: true
|
|
43490
|
+
isLintable: true,
|
|
43491
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
43492
|
+
validator: () => noopValidator()
|
|
43646
43493
|
};
|
|
43647
43494
|
|
|
43648
43495
|
/**
|
|
@@ -43654,6 +43501,10 @@ class PhetSimulation extends React__namespace.Component {
|
|
|
43654
43501
|
static contextType = PerseusI18nContext;
|
|
43655
43502
|
iframeRef = /*#__PURE__*/React__namespace.createRef();
|
|
43656
43503
|
locale;
|
|
43504
|
+
|
|
43505
|
+
// this just helps with TS weak typing when a Widget
|
|
43506
|
+
// doesn't implement any Widget methods
|
|
43507
|
+
isWidget = true;
|
|
43657
43508
|
state = {
|
|
43658
43509
|
url: null,
|
|
43659
43510
|
banner: null
|
|
@@ -43672,11 +43523,6 @@ class PhetSimulation extends React__namespace.Component {
|
|
|
43672
43523
|
}
|
|
43673
43524
|
}
|
|
43674
43525
|
|
|
43675
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43676
|
-
getUserInput() {
|
|
43677
|
-
return null;
|
|
43678
|
-
}
|
|
43679
|
-
|
|
43680
43526
|
// kaLocales and PhET locales use different formats and abbreviations.
|
|
43681
43527
|
// PhET accepts different formats, i.e. kaLocale's hyphens, but it does not accept
|
|
43682
43528
|
// different abbreviations, so in points of divergence of abbreviations, we need to
|
|
@@ -43896,9 +43742,6 @@ class Plotter extends React__namespace.Component {
|
|
|
43896
43742
|
// bottom label.
|
|
43897
43743
|
categoryHeights: {}
|
|
43898
43744
|
};
|
|
43899
|
-
static validate(userInput, rubric) {
|
|
43900
|
-
return plotterValidator(userInput, rubric);
|
|
43901
|
-
}
|
|
43902
43745
|
componentDidMount() {
|
|
43903
43746
|
this._isMounted = true;
|
|
43904
43747
|
this.setupGraphie(this.state);
|
|
@@ -44643,9 +44486,6 @@ class Plotter extends React__namespace.Component {
|
|
|
44643
44486
|
getUserInput() {
|
|
44644
44487
|
return this.state.values;
|
|
44645
44488
|
}
|
|
44646
|
-
simpleValidate(rubric) {
|
|
44647
|
-
return plotterValidator(this.getUserInput(), rubric);
|
|
44648
|
-
}
|
|
44649
44489
|
render() {
|
|
44650
44490
|
// TODO(kevinb) actually compute the size of the graphie correctly and
|
|
44651
44491
|
// make it that size so we don't have to add extra padding. The value
|
|
@@ -44671,7 +44511,8 @@ var Plotter$1 = {
|
|
|
44671
44511
|
displayName: "Plotter",
|
|
44672
44512
|
hidden: true,
|
|
44673
44513
|
widget: Plotter,
|
|
44674
|
-
staticTransform: staticTransform
|
|
44514
|
+
staticTransform: staticTransform,
|
|
44515
|
+
validator: plotterValidator
|
|
44675
44516
|
};
|
|
44676
44517
|
|
|
44677
44518
|
/**
|
|
@@ -44766,9 +44607,6 @@ class Sorter extends React__namespace.Component {
|
|
|
44766
44607
|
onChange: function () {},
|
|
44767
44608
|
linterContext: PerseusLinter.linterContextDefault
|
|
44768
44609
|
};
|
|
44769
|
-
static validate(userInput, rubric) {
|
|
44770
|
-
return sorterValidator(userInput, rubric);
|
|
44771
|
-
}
|
|
44772
44610
|
state = {
|
|
44773
44611
|
changed: false
|
|
44774
44612
|
};
|
|
@@ -44811,9 +44649,6 @@ class Sorter extends React__namespace.Component {
|
|
|
44811
44649
|
// @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
|
|
44812
44650
|
this.refs.sortable.moveOptionToIndex(option, index);
|
|
44813
44651
|
};
|
|
44814
|
-
simpleValidate(rubric) {
|
|
44815
|
-
return sorterValidator(this.getUserInput(), rubric);
|
|
44816
|
-
}
|
|
44817
44652
|
render() {
|
|
44818
44653
|
const options = shuffle(this.props.correct, this.props.problemNum, /* ensurePermuted */true);
|
|
44819
44654
|
const {
|
|
@@ -44839,7 +44674,8 @@ var Sorter$1 = {
|
|
|
44839
44674
|
name: "sorter",
|
|
44840
44675
|
displayName: "Sorter",
|
|
44841
44676
|
widget: Sorter,
|
|
44842
|
-
isLintable: true
|
|
44677
|
+
isLintable: true,
|
|
44678
|
+
validator: sorterValidator
|
|
44843
44679
|
};
|
|
44844
44680
|
|
|
44845
44681
|
function tableValidator(state, rubric, strings) {
|
|
@@ -44947,9 +44783,6 @@ class Table extends React__namespace.Component {
|
|
|
44947
44783
|
linterContext: PerseusLinter.linterContextDefault
|
|
44948
44784
|
};
|
|
44949
44785
|
}();
|
|
44950
|
-
static validate(state, rubric, strings) {
|
|
44951
|
-
return tableValidator(state, rubric, strings);
|
|
44952
|
-
}
|
|
44953
44786
|
_getRows = () => {
|
|
44954
44787
|
return this.props.answers.length;
|
|
44955
44788
|
};
|
|
@@ -44978,9 +44811,6 @@ class Table extends React__namespace.Component {
|
|
|
44978
44811
|
headers: headers
|
|
44979
44812
|
});
|
|
44980
44813
|
};
|
|
44981
|
-
simpleValidate(rubric) {
|
|
44982
|
-
return tableValidator(this.getUserInput(), rubric, this.context.strings);
|
|
44983
|
-
}
|
|
44984
44814
|
_handleFocus = inputPath => {
|
|
44985
44815
|
this.props.onFocus(inputPath);
|
|
44986
44816
|
};
|
|
@@ -45124,7 +44954,8 @@ var Table$1 = {
|
|
|
45124
44954
|
widget: Table,
|
|
45125
44955
|
transform: propTransform,
|
|
45126
44956
|
hidden: true,
|
|
45127
|
-
isLintable: true
|
|
44957
|
+
isLintable: true,
|
|
44958
|
+
validator: tableValidator
|
|
45128
44959
|
};
|
|
45129
44960
|
|
|
45130
44961
|
/**
|
|
@@ -45210,22 +45041,9 @@ const IS_VIMEO = /(vimeo\.com)/;
|
|
|
45210
45041
|
*/
|
|
45211
45042
|
class Video extends React__namespace.Component {
|
|
45212
45043
|
static contextType = PerseusI18nContext;
|
|
45213
|
-
|
|
45214
|
-
|
|
45215
|
-
|
|
45216
|
-
* of Khan Academy videos.
|
|
45217
|
-
*/ // TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
45218
|
-
static validate() {
|
|
45219
|
-
return noopValidator();
|
|
45220
|
-
}
|
|
45221
|
-
getUserInput = () => {
|
|
45222
|
-
return null;
|
|
45223
|
-
};
|
|
45224
|
-
|
|
45225
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
45226
|
-
simpleValidate() {
|
|
45227
|
-
return noopValidator();
|
|
45228
|
-
}
|
|
45044
|
+
// this just helps with TS weak typing when a Widget
|
|
45045
|
+
// doesn't implement any Widget methods
|
|
45046
|
+
isWidget = true;
|
|
45229
45047
|
change = (() => {
|
|
45230
45048
|
var _this = this;
|
|
45231
45049
|
return function () {
|
|
@@ -45294,7 +45112,9 @@ var Video$1 = {
|
|
|
45294
45112
|
displayName: "Video",
|
|
45295
45113
|
defaultAlignment: "block",
|
|
45296
45114
|
supportedAlignments: ["block", "float-left", "float-right", "full-width"],
|
|
45297
|
-
widget: Video
|
|
45115
|
+
widget: Video,
|
|
45116
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
45117
|
+
validator: () => noopValidator()
|
|
45298
45118
|
};
|
|
45299
45119
|
|
|
45300
45120
|
/* eslint-disable import/no-named-as-default */
|
|
@@ -45338,7 +45158,7 @@ const init = function (options) {
|
|
|
45338
45158
|
|
|
45339
45159
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45340
45160
|
const libName = "@khanacademy/perseus";
|
|
45341
|
-
const libVersion = "
|
|
45161
|
+
const libVersion = "37.0.0";
|
|
45342
45162
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45343
45163
|
|
|
45344
45164
|
const apiVersion = {
|
|
@@ -46064,7 +45884,7 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
46064
45884
|
});
|
|
46065
45885
|
|
|
46066
45886
|
// Call the interactionCallback, if it exists, with the current user input data
|
|
46067
|
-
this.props.apiOptions?.interactionCallback?.(this.questionRenderer.
|
|
45887
|
+
this.props.apiOptions?.interactionCallback?.(this.questionRenderer.getUserInputMap());
|
|
46068
45888
|
};
|
|
46069
45889
|
focus() {
|
|
46070
45890
|
return this.questionRenderer.focus();
|
|
@@ -48690,11 +48510,12 @@ function parsePerseusItem(json) {
|
|
|
48690
48510
|
throw new Error("Something went wrong.");
|
|
48691
48511
|
}
|
|
48692
48512
|
function buildRandomString() {
|
|
48513
|
+
let capitalize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
48693
48514
|
let randomString = "";
|
|
48694
48515
|
const randomLength = Math.floor(Math.random() * 8) + 3;
|
|
48695
48516
|
for (let i = 0; i < randomLength; i++) {
|
|
48696
48517
|
const randomLetter = String.fromCharCode(97 + Math.floor(Math.random() * 26));
|
|
48697
|
-
randomString += randomLetter;
|
|
48518
|
+
randomString += capitalize && i === 0 ? randomLetter.toUpperCase() : randomLetter;
|
|
48698
48519
|
}
|
|
48699
48520
|
return randomString;
|
|
48700
48521
|
}
|
|
@@ -48702,9 +48523,12 @@ function buildRandomPhrase() {
|
|
|
48702
48523
|
const phrases = [];
|
|
48703
48524
|
const randomLength = Math.floor(Math.random() * 10) + 5;
|
|
48704
48525
|
for (let i = 0; i < randomLength; i++) {
|
|
48705
|
-
phrases.push(buildRandomString());
|
|
48526
|
+
phrases.push(buildRandomString(i === 0));
|
|
48706
48527
|
}
|
|
48707
|
-
|
|
48528
|
+
const modifierStart = ["**", "$"];
|
|
48529
|
+
const modifierEnd = ["**", "$"];
|
|
48530
|
+
const modifierIndex = Math.floor(Math.random() * modifierStart.length);
|
|
48531
|
+
return `${modifierStart[modifierIndex]}${phrases.join(" ")}${modifierEnd[modifierIndex]}`;
|
|
48708
48532
|
}
|
|
48709
48533
|
function buildTestData(testObject) {
|
|
48710
48534
|
return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`;
|