@khanacademy/perseus-editor 17.8.1 → 17.9.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
@@ -145,7 +145,7 @@ const addLibraryVersionToPerseusDebug = (libraryName, libraryVersion) => {
145
145
 
146
146
  // This file is processed by a Rollup plugin (replace) to inject the production
147
147
  const libName = "@khanacademy/perseus-editor";
148
- const libVersion = "17.8.1";
148
+ const libVersion = "17.9.1";
149
149
  addLibraryVersionToPerseusDebug(libName, libVersion);
150
150
 
151
151
  const devices = {
@@ -20885,12 +20885,13 @@ class WidgetSelect extends React__namespace.Component {
20885
20885
  const addWidgetString = "Add a widget\u2026";
20886
20886
  return /*#__PURE__*/React__namespace.createElement("select", {
20887
20887
  value: "",
20888
- onChange: this.handleChange
20888
+ onChange: this.handleChange,
20889
+ "data-testid": "editor__widget-select"
20889
20890
  }, /*#__PURE__*/React__namespace.createElement("option", {
20890
20891
  value: ""
20891
20892
  }, addWidgetString), /*#__PURE__*/React__namespace.createElement("option", {
20892
20893
  disabled: true
20893
- }, "--"), ___default["default"].map(orderedWidgetNames, name => {
20894
+ }, "--"), orderedWidgetNames.map(name => {
20894
20895
  return /*#__PURE__*/React__namespace.createElement("option", {
20895
20896
  key: name,
20896
20897
  value: name
@@ -25250,17 +25251,25 @@ class ExpressionEditor extends React__namespace.Component {
25250
25251
  return perseus.Changeable.change.apply(_this, args);
25251
25252
  };
25252
25253
  })();
25253
- serialize = () => {
25254
- const formSerializables = ["value", "form", "simplify", "considered",
25255
- // it's a little weird to serialize the react key, but saves some
25256
- // effort reconstructing them when this item is loaded later.
25257
- "key"];
25258
- const serializables = ["answerForms", "buttonSets", "functions", "times", "visibleLabel", "ariaLabel"];
25259
- const answerForms = this.props.answerForms.map(form => {
25260
- return ___default["default"](form).pick(formSerializables);
25261
- });
25262
- return lens(this.props).set(["answerForms"], answerForms).mod([], props => ___default["default"](props).pick(serializables)).freeze();
25263
- };
25254
+ serialize() {
25255
+ const {
25256
+ answerForms,
25257
+ buttonSets,
25258
+ functions,
25259
+ times,
25260
+ visibleLabel,
25261
+ ariaLabel
25262
+ } = this.props;
25263
+ return {
25264
+ answerForms,
25265
+ buttonSets,
25266
+ functions,
25267
+ times,
25268
+ visibleLabel,
25269
+ ariaLabel,
25270
+ extraKeys: perseusCore.deriveExtraKeys(this.props)
25271
+ };
25272
+ }
25264
25273
  getSaveWarnings = () => {
25265
25274
  const issues = [];
25266
25275
  if (this.props.answerForms.length === 0) {
@@ -25329,12 +25338,27 @@ class ExpressionEditor extends React__namespace.Component {
25329
25338
 
25330
25339
  // This function is designed to update the answerForm property
25331
25340
  // with new data. This function should not be used to update any
25332
- // other properties within ExpressionEditor.
25341
+ // other properties within ExpressionEditor except extraKeys
25342
+ // which is derived from answerForms
25333
25343
  updateAnswerForm(i, props) {
25334
25344
  const answerForms = lens(this.props.answerForms).merge([i], props).freeze();
25335
- this.change({
25345
+
25346
+ // deriveExtraKeys defaults to using the `extraKeys` it was given
25347
+ // which in most case is what we want, but is not what we want
25348
+ // in the editing experience because we should recalculate them
25349
+ // when answers change
25350
+ const {
25351
+ extraKeys: _,
25352
+ ...restProps
25353
+ } = this.props;
25354
+ const extraKeys = perseusCore.deriveExtraKeys({
25355
+ ...restProps,
25336
25356
  answerForms
25337
25357
  });
25358
+ this.change({
25359
+ answerForms,
25360
+ extraKeys
25361
+ });
25338
25362
  }
25339
25363
  handleReorder = components => {
25340
25364
  const answerForms = components.map(component => {
@@ -32737,6 +32761,7 @@ class InteractiveGraphEditor extends React__namespace.Component {
32737
32761
  const updates = {
32738
32762
  numSides: parsePointCount(newValue),
32739
32763
  coords: null,
32764
+ startCoords: undefined,
32740
32765
  // reset the snap for UNLIMITED, which
32741
32766
  // only supports "grid"
32742
32767
  // From: D6578
@@ -36402,19 +36427,11 @@ class PythonProgramEditor extends React__namespace.Component {
36402
36427
  }
36403
36428
  }
36404
36429
 
36405
- /* eslint-disable jsx-a11y/anchor-is-valid, react/forbid-prop-types */
36430
+ /* eslint-disable jsx-a11y/anchor-is-valid */
36406
36431
  const {
36407
36432
  InlineIcon
36408
36433
  } = perseus.components;
36409
36434
  class ChoiceEditor extends React__namespace.Component {
36410
- static propTypes = {
36411
- apiOptions: perseus.ApiOptions.propTypes,
36412
- choice: PropTypes__default["default"].object,
36413
- showDelete: PropTypes__default["default"].bool,
36414
- onClueChange: PropTypes__default["default"].func,
36415
- onContentChange: PropTypes__default["default"].func,
36416
- onDelete: PropTypes__default["default"].func
36417
- };
36418
36435
  render() {
36419
36436
  const checkedClass = this.props.choice.correct ? "correct" : "incorrect";
36420
36437
  let placeholder = "Type a choice here...";
@@ -36462,25 +36479,6 @@ class ChoiceEditor extends React__namespace.Component {
36462
36479
  }
36463
36480
  }
36464
36481
  class RadioEditor extends React__namespace.Component {
36465
- static propTypes = {
36466
- ...perseus.Changeable.propTypes,
36467
- apiOptions: perseus.ApiOptions.propTypes,
36468
- choices: PropTypes__default["default"].arrayOf(PropTypes__default["default"].shape({
36469
- content: PropTypes__default["default"].string,
36470
- clue: PropTypes__default["default"].string,
36471
- correct: PropTypes__default["default"].bool
36472
- })),
36473
- displayCount: PropTypes__default["default"].number,
36474
- randomize: PropTypes__default["default"].bool,
36475
- hasNoneOfTheAbove: PropTypes__default["default"].bool,
36476
- multipleSelect: PropTypes__default["default"].bool,
36477
- countChoices: PropTypes__default["default"].bool,
36478
- // TODO(kevinb): DEPRECATED: This is be used to force deselectEnabled
36479
- // behavior on mobile but not on desktop. When enabled, the user can
36480
- // deselect a radio input by tapping on it again.
36481
- deselectEnabled: PropTypes__default["default"].bool,
36482
- static: PropTypes__default["default"].bool
36483
- };
36484
36482
  static widgetName = "radio";
36485
36483
  static defaultProps = perseusCore.radioLogic.defaultWidgetOptions;
36486
36484
  change = (() => {
@@ -36524,14 +36522,19 @@ class RadioEditor extends React__namespace.Component {
36524
36522
  let {
36525
36523
  checked
36526
36524
  } = _ref;
36527
- const choices = ___default["default"].map(this.props.choices, (choice, i) => {
36528
- return ___default["default"].extend({}, choice, {
36525
+ const choices = this.props.choices.map((choice, i) => {
36526
+ return {
36527
+ ...choice,
36529
36528
  correct: checked[i],
36530
36529
  content: choice.isNoneOfTheAbove && !checked[i] ? "" : choice.content
36531
- });
36530
+ };
36532
36531
  });
36533
36532
  this.props.onChange({
36534
- choices: choices
36533
+ choices: choices,
36534
+ numCorrect: perseusCore.deriveNumCorrect({
36535
+ ...this.props,
36536
+ choices
36537
+ })
36535
36538
  });
36536
36539
  };
36537
36540
  onContentChange = (choiceIndex, newContent) => {
@@ -36543,7 +36546,7 @@ class RadioEditor extends React__namespace.Component {
36543
36546
  choices: choices
36544
36547
  });
36545
36548
  };
36546
- onClueChange = (choiceIndex, newClue) => {
36549
+ onClueChange(choiceIndex, newClue) {
36547
36550
  const choices = this.props.choices.slice();
36548
36551
  choices[choiceIndex] = ___default["default"].extend({}, choices[choiceIndex], {
36549
36552
  clue: newClue
@@ -36554,7 +36557,7 @@ class RadioEditor extends React__namespace.Component {
36554
36557
  this.props.onChange({
36555
36558
  choices: choices
36556
36559
  });
36557
- };
36560
+ }
36558
36561
  onDelete = choiceIndex => {
36559
36562
  const choices = this.props.choices.slice();
36560
36563
  const deleted = choices[choiceIndex];
@@ -36568,7 +36571,8 @@ class RadioEditor extends React__namespace.Component {
36568
36571
  e.preventDefault();
36569
36572
  const choices = this.props.choices.slice();
36570
36573
  const newChoice = {
36571
- isNoneOfTheAbove: noneOfTheAbove
36574
+ isNoneOfTheAbove: noneOfTheAbove,
36575
+ content: ""
36572
36576
  };
36573
36577
  const addIndex = choices.length - (this.props.hasNoneOfTheAbove ? 1 : 0);
36574
36578
  choices.splice(addIndex, 0, newChoice);
@@ -36598,9 +36602,27 @@ class RadioEditor extends React__namespace.Component {
36598
36602
  }
36599
36603
  return [];
36600
36604
  };
36601
- serialize = () => {
36602
- return ___default["default"].pick(this.props, "choices", "randomize", "multipleSelect", "countChoices", "displayCount", "hasNoneOfTheAbove", "deselectEnabled");
36603
- };
36605
+ serialize() {
36606
+ const {
36607
+ choices,
36608
+ randomize,
36609
+ multipleSelect,
36610
+ countChoices,
36611
+ displayCount,
36612
+ hasNoneOfTheAbove,
36613
+ deselectEnabled
36614
+ } = this.props;
36615
+ return {
36616
+ choices,
36617
+ randomize,
36618
+ multipleSelect,
36619
+ countChoices,
36620
+ displayCount,
36621
+ hasNoneOfTheAbove,
36622
+ deselectEnabled,
36623
+ numCorrect: perseusCore.deriveNumCorrect(this.props)
36624
+ };
36625
+ }
36604
36626
  render() {
36605
36627
  const numCorrect = ___default["default"].reduce(this.props.choices, function (memo, choice) {
36606
36628
  return choice.correct ? memo + 1 : memo;
@@ -36658,12 +36680,12 @@ class RadioEditor extends React__namespace.Component {
36658
36680
  apiOptions: this.props.apiOptions,
36659
36681
  choice: choice,
36660
36682
  onContentChange: newProps => {
36661
- if ("content" in newProps) {
36683
+ if (newProps.content != null) {
36662
36684
  this.onContentChange(i, newProps.content);
36663
36685
  }
36664
36686
  },
36665
36687
  onClueChange: newProps => {
36666
- if ("content" in newProps) {
36688
+ if (newProps.content != null) {
36667
36689
  this.onClueChange(i, newProps.content);
36668
36690
  }
36669
36691
  },