@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/index.js CHANGED
@@ -21260,7 +21260,14 @@ const Triangle = props => {
21260
21260
  }
21261
21261
  });
21262
21262
  };
21263
- const TooltipArrow = props => {
21263
+ const TooltipArrow = _ref => {
21264
+ let {
21265
+ position = "relative",
21266
+ visibility = "visible",
21267
+ left = 100,
21268
+ top = 0,
21269
+ ...props
21270
+ } = _ref;
21264
21271
  // TODO(aria): Think about adding a box-shadow to the triangle here
21265
21272
  // See http://css-tricks.com/triangle-with-shadow/
21266
21273
 
@@ -21271,10 +21278,10 @@ const TooltipArrow = props => {
21271
21278
  return /*#__PURE__*/React__namespace.createElement("div", {
21272
21279
  style: {
21273
21280
  display: "block",
21274
- position: props.position,
21275
- visibility: props.visibility,
21276
- left: props.left,
21277
- top: props["top"],
21281
+ position: position,
21282
+ visibility: visibility,
21283
+ left: left,
21284
+ top: top,
21278
21285
  width: props.width + 2,
21279
21286
  height: props.height + 1,
21280
21287
  marginTop: -1,
@@ -21300,12 +21307,6 @@ const TooltipArrow = props => {
21300
21307
  height: props.height
21301
21308
  }));
21302
21309
  };
21303
- TooltipArrow.defaultProps = {
21304
- position: "relative",
21305
- visibility: "visible",
21306
- left: 0,
21307
- top: 0
21308
- };
21309
21310
  const VERTICAL_CORNERS = {
21310
21311
  top: {
21311
21312
  top: "-100%"
@@ -22176,48 +22177,35 @@ function numericInputValidator(userInput, rubric, strings) {
22176
22177
  // We may have received TeX; try to parse it before grading.
22177
22178
  // If `currentValue` is not TeX, this should be a no-op.
22178
22179
  const currentValue = ParseTex(userInput.currentValue);
22179
- const correctAnswers = rubric.answers.filter(answer => answer.status === "correct");
22180
- const normalizedAnswerExpected = correctAnswers.every(answer => Math.abs(answer.value) <= 1);
22181
-
22182
- // Look through all correct answers for one that matches either
22183
- // precisely or approximately and return the appropriate message:
22184
- // - if precise, return the message that the answer came with
22185
- // - if it needs to be simplified, etc., show that message
22186
- let result = correctAnswers.map(answer => {
22187
- // The coefficient is an attribute of the widget
22188
- let localValue = currentValue;
22189
- if (rubric.coefficient) {
22190
- if (!localValue) {
22191
- localValue = 1;
22192
- } else if (localValue === "-") {
22193
- localValue = -1;
22194
- }
22195
- }
22196
- const validate = createValidator(answer);
22197
- return validate(maybeParsePercentInput(localValue, normalizedAnswerExpected));
22198
- }).find(match => match.correct || match.empty);
22199
- if (!result) {
22200
- // Otherwise, if the guess is not correct
22201
- const otherAnswers = [].concat(
22202
- // @ts-expect-error - TS2769 - No overload matches this call.
22203
- rubric.answers.filter(answer => answer.status === "ungraded"), rubric.answers.filter(answer => answer.status === "wrong"));
22180
+ const normalizedAnswerExpected = rubric.answers.filter(answer => answer.status === "correct").every(answer => Math.abs(answer.value) <= 1);
22204
22181
 
22205
- // Look through all other answers and if one matches either
22206
- // precisely or approximately return the answer's message
22207
- const match = otherAnswers.find(answer => {
22208
- const validate = createValidator(answer);
22209
- return validate(maybeParsePercentInput(currentValue, normalizedAnswerExpected)).correct;
22210
- });
22211
- result = {
22212
- // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'never'.
22213
- empty: match ? match.status === "ungraded" : false,
22214
- // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'never'.
22215
- correct: match ? match.status === "correct" : false,
22216
- // @ts-expect-error - TS2339 - Property 'message' does not exist on type 'never'.
22217
- message: match ? match.message : null,
22218
- guess: currentValue
22219
- };
22182
+ // The coefficient is an attribute of the widget
22183
+ let localValue = currentValue;
22184
+ if (rubric.coefficient) {
22185
+ if (!localValue) {
22186
+ localValue = 1;
22187
+ } else if (localValue === "-") {
22188
+ localValue = -1;
22189
+ }
22220
22190
  }
22191
+ const matchedAnswer = rubric.answers.map(answer => {
22192
+ const validateFn = createValidator(answer);
22193
+ const score = validateFn(maybeParsePercentInput(localValue, normalizedAnswerExpected));
22194
+ return {
22195
+ ...answer,
22196
+ score
22197
+ };
22198
+ }).find(answer => {
22199
+ // NOTE: "answer.score.correct" indicates a match via the validate function.
22200
+ // It does NOT indicate that the answer itself is correct.
22201
+ return answer.score.correct || answer.status === "correct" && answer.score.empty;
22202
+ });
22203
+ const result = matchedAnswer?.status === "correct" ? matchedAnswer.score : {
22204
+ empty: matchedAnswer?.status === "ungraded",
22205
+ correct: matchedAnswer?.status === "correct",
22206
+ message: matchedAnswer?.message ?? null,
22207
+ guess: localValue
22208
+ };
22221
22209
 
22222
22210
  // TODO(eater): Seems silly to translate result to this
22223
22211
  // invalid/points thing and immediately translate it
@@ -25191,13 +25179,13 @@ function getA11yText(letter, checked, correct, crossedOut, showCorrectness, stri
25191
25179
  /**
25192
25180
  * Renders a circular selection ring around the child.
25193
25181
  */
25194
- const FocusRing = function (props) {
25195
- const {
25196
- visible,
25197
- color,
25198
- children,
25199
- multipleSelect
25200
- } = props;
25182
+ const FocusRing = function (_ref) {
25183
+ let {
25184
+ visible = true,
25185
+ color = kaGreen$1,
25186
+ multipleSelect = false,
25187
+ children
25188
+ } = _ref;
25201
25189
  const borderColor = visible ? color : "transparent";
25202
25190
  const borderRadius = multipleSelect ? 5 : "50%";
25203
25191
  const style = {
@@ -25210,11 +25198,6 @@ const FocusRing = function (props) {
25210
25198
  style: style
25211
25199
  }, children);
25212
25200
  };
25213
- FocusRing.defaultProps = {
25214
- visible: true,
25215
- color: kaGreen$1,
25216
- multipleSelect: false
25217
- };
25218
25201
  const styles$v = aphrodite.StyleSheet.create({
25219
25202
  ring: {
25220
25203
  margin: "auto",
@@ -25753,13 +25736,13 @@ var Choice$1 = /*#__PURE__*/React__namespace.forwardRef((props, ref) => /*#__PUR
25753
25736
  forwardedRef: ref
25754
25737
  })));
25755
25738
 
25756
- const ChoiceNoneAbove = function (props) {
25757
- const {
25758
- showContent,
25739
+ const ChoiceNoneAbove = function (_ref) {
25740
+ let {
25759
25741
  content,
25760
25742
  forwardedRef,
25743
+ showContent = true,
25761
25744
  ...rest
25762
- } = props;
25745
+ } = _ref;
25763
25746
  const {
25764
25747
  strings
25765
25748
  } = usePerseusI18n();
@@ -25787,9 +25770,6 @@ const ChoiceNoneAbove = function (props) {
25787
25770
  ref: forwardedRef
25788
25771
  }));
25789
25772
  };
25790
- ChoiceNoneAbove.defaultProps = {
25791
- showContent: true
25792
- };
25793
25773
  var ChoiceNoneAbove$1 = /*#__PURE__*/React__namespace.forwardRef((props, ref) => /*#__PURE__*/React__namespace.createElement(ChoiceNoneAbove, _extends({}, props, {
25794
25774
  forwardedRef: ref
25795
25775
  })));
@@ -25811,20 +25791,21 @@ function getInstructionsText(multipleSelect, countChoices, numCorrect, strings)
25811
25791
  }
25812
25792
  return strings.chooseOneAnswer;
25813
25793
  }
25814
- const BaseRadio = function (props) {
25815
- const {
25794
+ const BaseRadio = function (_ref) {
25795
+ let {
25816
25796
  apiOptions,
25817
25797
  reviewModeRubric,
25818
25798
  reviewMode,
25819
25799
  choices,
25820
- editMode,
25821
- multipleSelect,
25800
+ editMode = false,
25801
+ multipleSelect = false,
25822
25802
  labelWrap,
25823
25803
  countChoices,
25824
25804
  numCorrect,
25825
25805
  isLastUsedWidget,
25806
+ onChange,
25826
25807
  registerFocusFunction
25827
- } = props;
25808
+ } = _ref;
25828
25809
  const {
25829
25810
  strings
25830
25811
  } = usePerseusI18n();
@@ -25881,12 +25862,6 @@ const BaseRadio = function (props) {
25881
25862
  // contains a boolean value specifying the new checked and crossed-out
25882
25863
  // value of this choice.
25883
25864
  function updateChoice(choiceIndex, newValues) {
25884
- const {
25885
- multipleSelect,
25886
- choices,
25887
- onChange
25888
- } = props;
25889
-
25890
25865
  // Get the baseline `checked` values. If we're checking a new answer
25891
25866
  // and multiple-select is not on, we should clear all choices to be
25892
25867
  // unchecked. Otherwise, we should copy the old checked values.
@@ -26053,10 +26028,6 @@ const BaseRadio = function (props) {
26053
26028
  className: aphrodite.css(styles$p.responsiveContainer)
26054
26029
  }, fieldset);
26055
26030
  };
26056
- BaseRadio.defaultProps = {
26057
- editMode: false,
26058
- multipleSelect: false
26059
- };
26060
26031
  const styles$p = aphrodite.StyleSheet.create({
26061
26032
  instructions: {
26062
26033
  display: "block",
@@ -26155,7 +26126,7 @@ function radioValidator(userInput, rubric, strings) {
26155
26126
  };
26156
26127
  }
26157
26128
 
26158
- // TODO: should numCorrect actually be on the rubric
26129
+ // TODO(LEMS-2541): should numCorrect actually be on the rubric
26159
26130
  // instead of the userInput?
26160
26131
  if (userInput.numCorrect && userInput.numCorrect > 1 && numSelected !== userInput.numCorrect) {
26161
26132
  return {
@@ -26165,7 +26136,7 @@ function radioValidator(userInput, rubric, strings) {
26165
26136
  // If NOTA and some other answer are checked, ...
26166
26137
  }
26167
26138
 
26168
- // TODO: should noneOfTheAboveSelected be replaced with a
26139
+ // TODO(LEMS-2541): should noneOfTheAboveSelected be replaced with a
26169
26140
  // combination of choicesSelected and noneOfTheAboveIndex?
26170
26141
  if (userInput.noneOfTheAboveSelected && numSelected > 1) {
26171
26142
  return {
@@ -26175,7 +26146,7 @@ function radioValidator(userInput, rubric, strings) {
26175
26146
  }
26176
26147
  const correct = userInput.choicesSelected.every((selected, i) => {
26177
26148
  let isCorrect;
26178
- // TODO: should noneOfTheAboveIndex actually be on the rubric
26149
+ // TODO(LEMS-2541): should noneOfTheAboveIndex actually be on the rubric
26179
26150
  // instead of the userInput?
26180
26151
  if (userInput.noneOfTheAboveIndex === i) {
26181
26152
  isCorrect = rubric.choices.every((choice, j) => {
@@ -26217,7 +26188,6 @@ class Radio$1 extends React__namespace.Component {
26217
26188
  let noneOfTheAboveSelected = false;
26218
26189
  const choiceStates = props.choiceStates;
26219
26190
  const choicesSelected = choiceStates.map(() => false);
26220
- const countChoices = props.countChoices;
26221
26191
  const numCorrect = props.numCorrect;
26222
26192
  for (let i = 0; i < choicesSelected.length; i++) {
26223
26193
  const index = props.choices[i].originalIndex;
@@ -26231,7 +26201,6 @@ class Radio$1 extends React__namespace.Component {
26231
26201
  }
26232
26202
  }
26233
26203
  return {
26234
- countChoices,
26235
26204
  choicesSelected,
26236
26205
  numCorrect,
26237
26206
  noneOfTheAboveIndex,
@@ -26247,7 +26216,6 @@ class Radio$1 extends React__namespace.Component {
26247
26216
  let noneOfTheAboveIndex = null;
26248
26217
  let noneOfTheAboveSelected = false;
26249
26218
  const choicesSelected = [...values];
26250
- const countChoices = props.countChoices;
26251
26219
  const numCorrect = props.numCorrect;
26252
26220
  const valuesLength = values.length;
26253
26221
  for (let i = 0; i < valuesLength; i++) {
@@ -26265,7 +26233,6 @@ class Radio$1 extends React__namespace.Component {
26265
26233
  choicesSelected,
26266
26234
  noneOfTheAboveIndex,
26267
26235
  noneOfTheAboveSelected,
26268
- countChoices,
26269
26236
  numCorrect
26270
26237
  };
26271
26238
  }
@@ -29349,23 +29316,23 @@ var Group$1 = {
29349
29316
  isLintable: true
29350
29317
  };
29351
29318
 
29352
- function iframeValidator(state) {
29319
+ function iframeValidator(userInput) {
29353
29320
  // The iframe can tell us whether it's correct or incorrect,
29354
29321
  // and pass an optional message
29355
- if (state.status === "correct") {
29322
+ if (userInput.status === "correct") {
29356
29323
  return {
29357
29324
  type: "points",
29358
29325
  earned: 1,
29359
29326
  total: 1,
29360
- message: state.message || null
29327
+ message: userInput.message || null
29361
29328
  };
29362
29329
  }
29363
- if (state.status === "incorrect") {
29330
+ if (userInput.status === "incorrect") {
29364
29331
  return {
29365
29332
  type: "points",
29366
29333
  earned: 0,
29367
29334
  total: 1,
29368
- message: state.message || null
29335
+ message: userInput.message || null
29369
29336
  };
29370
29337
  }
29371
29338
  return {
@@ -40749,9 +40716,9 @@ var Matcher$1 = {
40749
40716
  validator: matcherValidator
40750
40717
  };
40751
40718
 
40752
- function matrixValidator(state, rubric, strings) {
40719
+ function matrixValidator(userInput, rubric, strings) {
40753
40720
  const solution = rubric.answers;
40754
- const supplied = state.answers;
40721
+ const supplied = userInput.answers;
40755
40722
  const solutionSize = getMatrixSize(solution);
40756
40723
  const suppliedSize = getMatrixSize(supplied);
40757
40724
  const incorrectSize = solutionSize[0] !== suppliedSize[0] || solutionSize[1] !== suppliedSize[1];
@@ -45101,7 +45068,7 @@ const init = function (options) {
45101
45068
 
45102
45069
  // This file is processed by a Rollup plugin (replace) to inject the production
45103
45070
  const libName = "@khanacademy/perseus";
45104
- const libVersion = "39.0.0";
45071
+ const libVersion = "39.0.1";
45105
45072
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
45106
45073
 
45107
45074
  const apiVersion = {