@khanacademy/perseus 39.0.0 → 39.0.1

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 CHANGED
@@ -20968,7 +20968,17 @@ TextInput.defaultProps = {
20968
20968
  disabled: false
20969
20969
  };
20970
20970
 
20971
- /* eslint-disable react/no-unsafe */
20971
+ function _objectWithoutPropertiesLoose(r, e) {
20972
+ if (null == r) return {};
20973
+ var t = {};
20974
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
20975
+ if (e.includes(n)) continue;
20976
+ t[n] = r[n];
20977
+ }
20978
+ return t;
20979
+ }
20980
+
20981
+ const _excluded$5 = ["position", "visibility", "left", "top"];
20972
20982
  const zIndex = 10;
20973
20983
  let HorizontalDirection = /*#__PURE__*/function (HorizontalDirection) {
20974
20984
  HorizontalDirection["Left"] = "left";
@@ -21012,7 +21022,14 @@ const Triangle = props => {
21012
21022
  }
21013
21023
  });
21014
21024
  };
21015
- const TooltipArrow = props => {
21025
+ const TooltipArrow = _ref => {
21026
+ let {
21027
+ position = "relative",
21028
+ visibility = "visible",
21029
+ left = 100,
21030
+ top = 0
21031
+ } = _ref,
21032
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$5);
21016
21033
  // TODO(aria): Think about adding a box-shadow to the triangle here
21017
21034
  // See http://css-tricks.com/triangle-with-shadow/
21018
21035
 
@@ -21023,10 +21040,10 @@ const TooltipArrow = props => {
21023
21040
  return /*#__PURE__*/React.createElement("div", {
21024
21041
  style: {
21025
21042
  display: "block",
21026
- position: props.position,
21027
- visibility: props.visibility,
21028
- left: props.left,
21029
- top: props["top"],
21043
+ position: position,
21044
+ visibility: visibility,
21045
+ left: left,
21046
+ top: top,
21030
21047
  width: props.width + 2,
21031
21048
  height: props.height + 1,
21032
21049
  marginTop: -1,
@@ -21052,12 +21069,6 @@ const TooltipArrow = props => {
21052
21069
  height: props.height
21053
21070
  }));
21054
21071
  };
21055
- TooltipArrow.defaultProps = {
21056
- position: "relative",
21057
- visibility: "visible",
21058
- left: 0,
21059
- top: 0
21060
- };
21061
21072
  const VERTICAL_CORNERS = {
21062
21073
  top: {
21063
21074
  top: "-100%"
@@ -21340,16 +21351,6 @@ InputWithExamples.defaultProps = {
21340
21351
  className: ""
21341
21352
  };
21342
21353
 
21343
- function _objectWithoutPropertiesLoose(r, e) {
21344
- if (null == r) return {};
21345
- var t = {};
21346
- for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
21347
- if (e.includes(n)) continue;
21348
- t[n] = r[n];
21349
- }
21350
- return t;
21351
- }
21352
-
21353
21354
  const _excluded$4 = ["keypadElement", "onFocus", "value"];
21354
21355
  class SimpleKeypadInput extends React.Component {
21355
21356
  constructor(...args) {
@@ -21927,6 +21928,7 @@ function maybeParsePercentInput(inputValue, normalizedAnswerExpected) {
21927
21928
  return value;
21928
21929
  }
21929
21930
  function numericInputValidator(userInput, rubric, strings) {
21931
+ var _matchedAnswer$messag;
21930
21932
  const defaultAnswerForms = answerFormButtons.map(e => e["value"])
21931
21933
  // Don't default to validating the answer as a pi answer
21932
21934
  // if answerForm isn't set on the answer
@@ -21959,48 +21961,34 @@ function numericInputValidator(userInput, rubric, strings) {
21959
21961
  // We may have received TeX; try to parse it before grading.
21960
21962
  // If `currentValue` is not TeX, this should be a no-op.
21961
21963
  const currentValue = ParseTex(userInput.currentValue);
21962
- const correctAnswers = rubric.answers.filter(answer => answer.status === "correct");
21963
- const normalizedAnswerExpected = correctAnswers.every(answer => Math.abs(answer.value) <= 1);
21964
-
21965
- // Look through all correct answers for one that matches either
21966
- // precisely or approximately and return the appropriate message:
21967
- // - if precise, return the message that the answer came with
21968
- // - if it needs to be simplified, etc., show that message
21969
- let result = correctAnswers.map(answer => {
21970
- // The coefficient is an attribute of the widget
21971
- let localValue = currentValue;
21972
- if (rubric.coefficient) {
21973
- if (!localValue) {
21974
- localValue = 1;
21975
- } else if (localValue === "-") {
21976
- localValue = -1;
21977
- }
21978
- }
21979
- const validate = createValidator(answer);
21980
- return validate(maybeParsePercentInput(localValue, normalizedAnswerExpected));
21981
- }).find(match => match.correct || match.empty);
21982
- if (!result) {
21983
- // Otherwise, if the guess is not correct
21984
- const otherAnswers = [].concat(
21985
- // @ts-expect-error - TS2769 - No overload matches this call.
21986
- rubric.answers.filter(answer => answer.status === "ungraded"), rubric.answers.filter(answer => answer.status === "wrong"));
21987
-
21988
- // Look through all other answers and if one matches either
21989
- // precisely or approximately return the answer's message
21990
- const match = otherAnswers.find(answer => {
21991
- const validate = createValidator(answer);
21992
- return validate(maybeParsePercentInput(currentValue, normalizedAnswerExpected)).correct;
21964
+ const normalizedAnswerExpected = rubric.answers.filter(answer => answer.status === "correct").every(answer => Math.abs(answer.value) <= 1);
21965
+
21966
+ // The coefficient is an attribute of the widget
21967
+ let localValue = currentValue;
21968
+ if (rubric.coefficient) {
21969
+ if (!localValue) {
21970
+ localValue = 1;
21971
+ } else if (localValue === "-") {
21972
+ localValue = -1;
21973
+ }
21974
+ }
21975
+ const matchedAnswer = rubric.answers.map(answer => {
21976
+ const validateFn = createValidator(answer);
21977
+ const score = validateFn(maybeParsePercentInput(localValue, normalizedAnswerExpected));
21978
+ return _extends({}, answer, {
21979
+ score
21993
21980
  });
21994
- result = {
21995
- // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'never'.
21996
- empty: match ? match.status === "ungraded" : false,
21997
- // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'never'.
21998
- correct: match ? match.status === "correct" : false,
21999
- // @ts-expect-error - TS2339 - Property 'message' does not exist on type 'never'.
22000
- message: match ? match.message : null,
22001
- guess: currentValue
22002
- };
22003
- }
21981
+ }).find(answer => {
21982
+ // NOTE: "answer.score.correct" indicates a match via the validate function.
21983
+ // It does NOT indicate that the answer itself is correct.
21984
+ return answer.score.correct || answer.status === "correct" && answer.score.empty;
21985
+ });
21986
+ const result = (matchedAnswer == null ? void 0 : matchedAnswer.status) === "correct" ? matchedAnswer.score : {
21987
+ empty: (matchedAnswer == null ? void 0 : matchedAnswer.status) === "ungraded",
21988
+ correct: (matchedAnswer == null ? void 0 : matchedAnswer.status) === "correct",
21989
+ message: (_matchedAnswer$messag = matchedAnswer == null ? void 0 : matchedAnswer.message) != null ? _matchedAnswer$messag : null,
21990
+ guess: localValue
21991
+ };
22004
21992
 
22005
21993
  // TODO(eater): Seems silly to translate result to this
22006
21994
  // invalid/points thing and immediately translate it
@@ -24972,13 +24960,12 @@ function getA11yText(letter, checked, correct, crossedOut, showCorrectness, stri
24972
24960
  /**
24973
24961
  * Renders a circular selection ring around the child.
24974
24962
  */
24975
- const FocusRing = function FocusRing(props) {
24976
- const {
24977
- visible,
24978
- color,
24979
- children,
24980
- multipleSelect
24981
- } = props;
24963
+ const FocusRing = function FocusRing({
24964
+ visible = true,
24965
+ color = kaGreen$1,
24966
+ multipleSelect = false,
24967
+ children
24968
+ }) {
24982
24969
  const borderColor = visible ? color : "transparent";
24983
24970
  const borderRadius = multipleSelect ? 5 : "50%";
24984
24971
  const style = {
@@ -24991,11 +24978,6 @@ const FocusRing = function FocusRing(props) {
24991
24978
  style: style
24992
24979
  }, children);
24993
24980
  };
24994
- FocusRing.defaultProps = {
24995
- visible: true,
24996
- color: kaGreen$1,
24997
- multipleSelect: false
24998
- };
24999
24981
  const styles$v = StyleSheet.create({
25000
24982
  ring: {
25001
24983
  margin: "auto",
@@ -25528,14 +25510,14 @@ var Choice$1 = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.
25528
25510
  forwardedRef: ref
25529
25511
  })));
25530
25512
 
25531
- const _excluded$3 = ["showContent", "content", "forwardedRef"];
25532
- const ChoiceNoneAbove = function ChoiceNoneAbove(props) {
25533
- const {
25534
- showContent,
25513
+ const _excluded$3 = ["content", "forwardedRef", "showContent"];
25514
+ const ChoiceNoneAbove = function ChoiceNoneAbove(_ref) {
25515
+ let {
25535
25516
  content,
25536
- forwardedRef
25537
- } = props,
25538
- rest = _objectWithoutPropertiesLoose(props, _excluded$3);
25517
+ forwardedRef,
25518
+ showContent = true
25519
+ } = _ref,
25520
+ rest = _objectWithoutPropertiesLoose(_ref, _excluded$3);
25539
25521
  const {
25540
25522
  strings
25541
25523
  } = usePerseusI18n();
@@ -25562,9 +25544,6 @@ const ChoiceNoneAbove = function ChoiceNoneAbove(props) {
25562
25544
  ref: forwardedRef
25563
25545
  }));
25564
25546
  };
25565
- ChoiceNoneAbove.defaultProps = {
25566
- showContent: true
25567
- };
25568
25547
  var ChoiceNoneAbove$1 = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(ChoiceNoneAbove, _extends({}, props, {
25569
25548
  forwardedRef: ref
25570
25549
  })));
@@ -25586,20 +25565,20 @@ function getInstructionsText(multipleSelect, countChoices, numCorrect, strings)
25586
25565
  }
25587
25566
  return strings.chooseOneAnswer;
25588
25567
  }
25589
- const BaseRadio = function BaseRadio(props) {
25590
- const {
25591
- apiOptions,
25592
- reviewModeRubric,
25593
- reviewMode,
25594
- choices,
25595
- editMode,
25596
- multipleSelect,
25597
- labelWrap,
25598
- countChoices,
25599
- numCorrect,
25600
- isLastUsedWidget,
25601
- registerFocusFunction
25602
- } = props;
25568
+ const BaseRadio = function BaseRadio({
25569
+ apiOptions,
25570
+ reviewModeRubric,
25571
+ reviewMode,
25572
+ choices,
25573
+ editMode = false,
25574
+ multipleSelect = false,
25575
+ labelWrap,
25576
+ countChoices,
25577
+ numCorrect,
25578
+ isLastUsedWidget,
25579
+ onChange,
25580
+ registerFocusFunction
25581
+ }) {
25603
25582
  const {
25604
25583
  strings
25605
25584
  } = usePerseusI18n();
@@ -25656,12 +25635,6 @@ const BaseRadio = function BaseRadio(props) {
25656
25635
  // contains a boolean value specifying the new checked and crossed-out
25657
25636
  // value of this choice.
25658
25637
  function updateChoice(choiceIndex, newValues) {
25659
- const {
25660
- multipleSelect,
25661
- choices,
25662
- onChange
25663
- } = props;
25664
-
25665
25638
  // Get the baseline `checked` values. If we're checking a new answer
25666
25639
  // and multiple-select is not on, we should clear all choices to be
25667
25640
  // unchecked. Otherwise, we should copy the old checked values.
@@ -25828,10 +25801,6 @@ const BaseRadio = function BaseRadio(props) {
25828
25801
  className: css(styles$p.responsiveContainer)
25829
25802
  }, fieldset);
25830
25803
  };
25831
- BaseRadio.defaultProps = {
25832
- editMode: false,
25833
- multipleSelect: false
25834
- };
25835
25804
  const styles$p = StyleSheet.create({
25836
25805
  instructions: {
25837
25806
  display: "block",
@@ -25930,7 +25899,7 @@ function radioValidator(userInput, rubric, strings) {
25930
25899
  };
25931
25900
  }
25932
25901
 
25933
- // TODO: should numCorrect actually be on the rubric
25902
+ // TODO(LEMS-2541): should numCorrect actually be on the rubric
25934
25903
  // instead of the userInput?
25935
25904
  if (userInput.numCorrect && userInput.numCorrect > 1 && numSelected !== userInput.numCorrect) {
25936
25905
  return {
@@ -25940,7 +25909,7 @@ function radioValidator(userInput, rubric, strings) {
25940
25909
  // If NOTA and some other answer are checked, ...
25941
25910
  }
25942
25911
 
25943
- // TODO: should noneOfTheAboveSelected be replaced with a
25912
+ // TODO(LEMS-2541): should noneOfTheAboveSelected be replaced with a
25944
25913
  // combination of choicesSelected and noneOfTheAboveIndex?
25945
25914
  if (userInput.noneOfTheAboveSelected && numSelected > 1) {
25946
25915
  return {
@@ -25950,7 +25919,7 @@ function radioValidator(userInput, rubric, strings) {
25950
25919
  }
25951
25920
  const correct = userInput.choicesSelected.every((selected, i) => {
25952
25921
  let isCorrect;
25953
- // TODO: should noneOfTheAboveIndex actually be on the rubric
25922
+ // TODO(LEMS-2541): should noneOfTheAboveIndex actually be on the rubric
25954
25923
  // instead of the userInput?
25955
25924
  if (userInput.noneOfTheAboveIndex === i) {
25956
25925
  isCorrect = rubric.choices.every((choice, j) => {
@@ -26131,7 +26100,6 @@ class Radio$1 extends React.Component {
26131
26100
  let noneOfTheAboveSelected = false;
26132
26101
  const choiceStates = props.choiceStates;
26133
26102
  const choicesSelected = choiceStates.map(() => false);
26134
- const countChoices = props.countChoices;
26135
26103
  const numCorrect = props.numCorrect;
26136
26104
  for (let i = 0; i < choicesSelected.length; i++) {
26137
26105
  const index = props.choices[i].originalIndex;
@@ -26145,7 +26113,6 @@ class Radio$1 extends React.Component {
26145
26113
  }
26146
26114
  }
26147
26115
  return {
26148
- countChoices,
26149
26116
  choicesSelected,
26150
26117
  numCorrect,
26151
26118
  noneOfTheAboveIndex,
@@ -26161,7 +26128,6 @@ class Radio$1 extends React.Component {
26161
26128
  let noneOfTheAboveIndex = null;
26162
26129
  let noneOfTheAboveSelected = false;
26163
26130
  const choicesSelected = [...values];
26164
- const countChoices = props.countChoices;
26165
26131
  const numCorrect = props.numCorrect;
26166
26132
  const valuesLength = values.length;
26167
26133
  for (let i = 0; i < valuesLength; i++) {
@@ -26179,7 +26145,6 @@ class Radio$1 extends React.Component {
26179
26145
  choicesSelected,
26180
26146
  noneOfTheAboveIndex,
26181
26147
  noneOfTheAboveSelected,
26182
- countChoices,
26183
26148
  numCorrect
26184
26149
  };
26185
26150
  }
@@ -29084,23 +29049,23 @@ var Group$1 = {
29084
29049
  isLintable: true
29085
29050
  };
29086
29051
 
29087
- function iframeValidator(state) {
29052
+ function iframeValidator(userInput) {
29088
29053
  // The iframe can tell us whether it's correct or incorrect,
29089
29054
  // and pass an optional message
29090
- if (state.status === "correct") {
29055
+ if (userInput.status === "correct") {
29091
29056
  return {
29092
29057
  type: "points",
29093
29058
  earned: 1,
29094
29059
  total: 1,
29095
- message: state.message || null
29060
+ message: userInput.message || null
29096
29061
  };
29097
29062
  }
29098
- if (state.status === "incorrect") {
29063
+ if (userInput.status === "incorrect") {
29099
29064
  return {
29100
29065
  type: "points",
29101
29066
  earned: 0,
29102
29067
  total: 1,
29103
- message: state.message || null
29068
+ message: userInput.message || null
29104
29069
  };
29105
29070
  }
29106
29071
  return {
@@ -40400,9 +40365,9 @@ var Matcher$1 = {
40400
40365
  validator: matcherValidator
40401
40366
  };
40402
40367
 
40403
- function matrixValidator(state, rubric, strings) {
40368
+ function matrixValidator(userInput, rubric, strings) {
40404
40369
  const solution = rubric.answers;
40405
- const supplied = state.answers;
40370
+ const supplied = userInput.answers;
40406
40371
  const solutionSize = getMatrixSize(solution);
40407
40372
  const suppliedSize = getMatrixSize(supplied);
40408
40373
  const incorrectSize = solutionSize[0] !== suppliedSize[0] || solutionSize[1] !== suppliedSize[1];
@@ -44752,7 +44717,7 @@ const init = function init(options) {
44752
44717
 
44753
44718
  // This file is processed by a Rollup plugin (replace) to inject the production
44754
44719
  const libName = "@khanacademy/perseus";
44755
- const libVersion = "39.0.0";
44720
+ const libVersion = "39.0.1";
44756
44721
  addLibraryVersionToPerseusDebug(libName, libVersion);
44757
44722
 
44758
44723
  const apiVersion = {