@khanacademy/perseus 31.1.0 → 32.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.
Files changed (86) hide show
  1. package/dist/components/input-with-examples.d.ts +1 -1
  2. package/dist/components/number-input.d.ts +1 -1
  3. package/dist/components/range-input.d.ts +1 -1
  4. package/dist/components/sortable.d.ts +5 -5
  5. package/dist/components/text-input.d.ts +1 -1
  6. package/dist/components/text-list-editor.d.ts +1 -1
  7. package/dist/es/index.js +529 -479
  8. package/dist/es/index.js.map +1 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +1348 -1305
  11. package/dist/index.js.map +1 -1
  12. package/dist/perseus-types.d.ts +1 -10
  13. package/dist/widget-container.d.ts +1 -1
  14. package/dist/widgets/__shared__/test-keypad-context-wrapper.d.ts +6 -0
  15. package/dist/widgets/{categorizer.d.ts → categorizer/categorizer.d.ts} +14 -14
  16. package/dist/widgets/categorizer/index.d.ts +1 -0
  17. package/dist/widgets/{cs-program.d.ts → cs-program/cs-program.d.ts} +7 -7
  18. package/dist/widgets/cs-program/index.d.ts +1 -0
  19. package/dist/widgets/{definition.d.ts → definition/definition.d.ts} +11 -11
  20. package/dist/widgets/definition/index.d.ts +1 -0
  21. package/dist/widgets/{dropdown.d.ts → dropdown/dropdown.d.ts} +9 -9
  22. package/dist/widgets/dropdown/index.d.ts +1 -0
  23. package/dist/widgets/{explanation.d.ts → explanation/explanation.d.ts} +14 -14
  24. package/dist/widgets/explanation/index.d.ts +1 -0
  25. package/dist/widgets/{expression.d.ts → expression/expression.d.ts} +66 -66
  26. package/dist/widgets/expression/index.d.ts +1 -0
  27. package/dist/widgets/{graded-group-answer-bar.d.ts → graded-group/graded-group-answer-bar.d.ts} +3 -3
  28. package/dist/widgets/{graded-group.d.ts → graded-group/graded-group.d.ts} +11 -11
  29. package/dist/widgets/graded-group/index.d.ts +1 -0
  30. package/dist/widgets/{graded-group-set.d.ts → graded-group-set/graded-group-set.d.ts} +11 -11
  31. package/dist/widgets/graded-group-set/index.d.ts +1 -0
  32. package/dist/widgets/{grapher.d.ts → grapher/grapher.d.ts} +15 -15
  33. package/dist/widgets/grapher/index.d.ts +1 -0
  34. package/dist/widgets/{group.d.ts → group/group.d.ts} +12 -12
  35. package/dist/widgets/group/index.d.ts +1 -0
  36. package/dist/widgets/{iframe.d.ts → iframe/iframe.d.ts} +10 -10
  37. package/dist/widgets/iframe/index.d.ts +1 -0
  38. package/dist/widgets/{image.d.ts → image/image.d.ts} +12 -12
  39. package/dist/widgets/image/index.d.ts +1 -0
  40. package/dist/widgets/input-number/index.d.ts +1 -0
  41. package/dist/widgets/{input-number.d.ts → input-number/input-number.d.ts} +19 -19
  42. package/dist/widgets/interaction/index.d.ts +1 -0
  43. package/dist/widgets/{interaction.d.ts → interaction/interaction.d.ts} +12 -12
  44. package/dist/widgets/interactive-graphs/reducer/interactive-graph-action.d.ts +22 -1
  45. package/dist/widgets/interactive-graphs/types.d.ts +1 -0
  46. package/dist/widgets/label-image/index.d.ts +1 -0
  47. package/dist/widgets/{label-image.d.ts → label-image/label-image.d.ts} +24 -24
  48. package/dist/widgets/matcher/index.d.ts +1 -0
  49. package/dist/widgets/{matcher.d.ts → matcher/matcher.d.ts} +11 -11
  50. package/dist/widgets/matrix/index.d.ts +1 -0
  51. package/dist/widgets/{matrix.d.ts → matrix/matrix.d.ts} +12 -12
  52. package/dist/widgets/measurer/index.d.ts +1 -0
  53. package/dist/widgets/measurer/measurer.d.ts +21 -0
  54. package/dist/widgets/molecule/index.d.ts +1 -0
  55. package/dist/widgets/{molecule.d.ts → molecule/molecule.d.ts} +10 -10
  56. package/dist/widgets/number-line/index.d.ts +1 -0
  57. package/dist/widgets/{number-line.d.ts → number-line/number-line.d.ts} +11 -11
  58. package/dist/widgets/numeric-input/index.d.ts +1 -0
  59. package/dist/widgets/{numeric-input.d.ts → numeric-input/numeric-input.d.ts} +13 -13
  60. package/dist/widgets/orderer/index.d.ts +1 -0
  61. package/dist/widgets/{orderer.d.ts → orderer/orderer.d.ts} +10 -10
  62. package/dist/widgets/passage/index.d.ts +2 -0
  63. package/dist/widgets/{passage.d.ts → passage/passage.d.ts} +15 -15
  64. package/dist/widgets/passage-ref/index.d.ts +1 -0
  65. package/dist/widgets/{passage-ref.d.ts → passage-ref/passage-ref.d.ts} +16 -16
  66. package/dist/widgets/passage-ref-target/index.d.ts +1 -0
  67. package/dist/widgets/{passage-ref-target.d.ts → passage-ref-target/passage-ref-target.d.ts} +12 -12
  68. package/dist/widgets/phet-simulation/index.d.ts +1 -0
  69. package/dist/widgets/{phet-simulation.d.ts → phet-simulation/phet-simulation.d.ts} +11 -13
  70. package/dist/widgets/plotter/index.d.ts +1 -0
  71. package/dist/widgets/{plotter.d.ts → plotter/plotter.d.ts} +11 -11
  72. package/dist/widgets/python-program/index.d.ts +1 -0
  73. package/dist/widgets/{python-program.d.ts → python-program/python-program.d.ts} +7 -7
  74. package/dist/widgets/radio/index.d.ts +2 -0
  75. package/dist/widgets/radio/radio-component.d.ts +66 -0
  76. package/dist/widgets/radio/radio.d.ts +22 -66
  77. package/dist/widgets/sorter/index.d.ts +1 -0
  78. package/dist/widgets/{sorter.d.ts → sorter/sorter.d.ts} +8 -8
  79. package/dist/widgets/table/index.d.ts +1 -0
  80. package/dist/widgets/{table.d.ts → table/table.d.ts} +10 -10
  81. package/dist/widgets/video/index.d.ts +1 -0
  82. package/dist/widgets/{video.d.ts → video/video.d.ts} +11 -11
  83. package/package.json +1 -1
  84. package/dist/widgets/measurer.d.ts +0 -21
  85. package/dist/widgets/radio.d.ts +0 -22
  86. /package/dist/widgets/{video-transcript-link.d.ts → video/video-transcript-link.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -1009,32 +1009,6 @@ class TextListEditor extends React__namespace.Component {
1009
1009
  items: nextProps.options.concat("")
1010
1010
  });
1011
1011
  }
1012
- render() {
1013
- const className = ["perseus-text-list-editor", "perseus-clearfix", "layout-" + this.props.layout].join(" ");
1014
- const inputs = ___default["default"].map(this.state.items, function (item, i) {
1015
- return /*#__PURE__*/React__namespace.createElement("li", {
1016
- key: i
1017
- }, /*#__PURE__*/React__namespace.createElement("input", {
1018
- ref: "input_" + i,
1019
- type: "text",
1020
- value: item
1021
- // eslint-disable-next-line react/jsx-no-bind
1022
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
1023
- ,
1024
- onChange: this.onChange.bind(this, i)
1025
- // eslint-disable-next-line react/jsx-no-bind
1026
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
1027
- ,
1028
- onKeyDown: this.onKeyDown.bind(this, i),
1029
- style: {
1030
- width: getTextWidth(item)
1031
- }
1032
- }));
1033
- }, this);
1034
- return /*#__PURE__*/React__namespace.createElement("ul", {
1035
- className: className
1036
- }, inputs);
1037
- }
1038
1012
  onChange = (index, event) => {
1039
1013
  let items = ___default["default"].clone(this.state.items);
1040
1014
  items[index] = event.target.value;
@@ -1110,6 +1084,32 @@ class TextListEditor extends React__namespace.Component {
1110
1084
  }
1111
1085
  }
1112
1086
  };
1087
+ render() {
1088
+ const className = ["perseus-text-list-editor", "perseus-clearfix", "layout-" + this.props.layout].join(" ");
1089
+ const inputs = ___default["default"].map(this.state.items, function (item, i) {
1090
+ return /*#__PURE__*/React__namespace.createElement("li", {
1091
+ key: i
1092
+ }, /*#__PURE__*/React__namespace.createElement("input", {
1093
+ ref: "input_" + i,
1094
+ type: "text",
1095
+ value: item
1096
+ // eslint-disable-next-line react/jsx-no-bind
1097
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
1098
+ ,
1099
+ onChange: this.onChange.bind(this, i)
1100
+ // eslint-disable-next-line react/jsx-no-bind
1101
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
1102
+ ,
1103
+ onKeyDown: this.onKeyDown.bind(this, i),
1104
+ style: {
1105
+ width: getTextWidth(item)
1106
+ }
1107
+ }));
1108
+ }, this);
1109
+ return /*#__PURE__*/React__namespace.createElement("ul", {
1110
+ className: className
1111
+ }, inputs);
1112
+ }
1113
1113
  }
1114
1114
 
1115
1115
  /**
@@ -19651,6 +19651,22 @@ class WidgetContainer extends React__namespace.Component {
19651
19651
  }
19652
19652
  }
19653
19653
 
19654
+ UNSAFE_componentWillReceiveProps(nextProps) {
19655
+ if (this.props.type !== nextProps.type) {
19656
+ throw new Error("WidgetContainer can't change widget type; set a different " + "key instead to recreate the container.");
19657
+ }
19658
+ }
19659
+ shouldComponentUpdate(nextProps, nextState) {
19660
+ return this.props.shouldHighlight !== nextProps.shouldHighlight || this.props.type !== nextProps.type || this.state.widgetProps !== nextState.widgetProps || this.state.sizeClass !== nextState.sizeClass;
19661
+ }
19662
+ getWidget = () => {
19663
+ return this.widgetRef.current;
19664
+ };
19665
+ replaceWidgetProps = newWidgetProps => {
19666
+ this.setState({
19667
+ widgetProps: newWidgetProps
19668
+ });
19669
+ };
19654
19670
  render() {
19655
19671
  let className = classNames__default["default"]({
19656
19672
  "perseus-widget-container": true,
@@ -19745,22 +19761,6 @@ class WidgetContainer extends React__namespace.Component {
19745
19761
  }));
19746
19762
  }));
19747
19763
  }
19748
- UNSAFE_componentWillReceiveProps(nextProps) {
19749
- if (this.props.type !== nextProps.type) {
19750
- throw new Error("WidgetContainer can't change widget type; set a different " + "key instead to recreate the container.");
19751
- }
19752
- }
19753
- shouldComponentUpdate(nextProps, nextState) {
19754
- return this.props.shouldHighlight !== nextProps.shouldHighlight || this.props.type !== nextProps.type || this.state.widgetProps !== nextState.widgetProps || this.state.sizeClass !== nextState.sizeClass;
19755
- }
19756
- getWidget = () => {
19757
- return this.widgetRef.current;
19758
- };
19759
- replaceWidgetProps = newWidgetProps => {
19760
- this.setState({
19761
- widgetProps: newWidgetProps
19762
- });
19763
- };
19764
19764
  }
19765
19765
 
19766
19766
  const {
@@ -21261,6 +21261,34 @@ class TextInput extends React__namespace.Component {
21261
21261
  this.id = uniqueIdForInput();
21262
21262
  }
21263
21263
  }
21264
+ focus = () => {
21265
+ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
21266
+ ReactDOM__default["default"].findDOMNode(this).focus();
21267
+ };
21268
+ blur = () => {
21269
+ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
21270
+ ReactDOM__default["default"].findDOMNode(this).blur();
21271
+ };
21272
+ getValue = () => {
21273
+ // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'Element | Text'.
21274
+ return ReactDOM__default["default"].findDOMNode(this)?.value;
21275
+ };
21276
+ getStringValue = () => {
21277
+ // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'Element | Text'.
21278
+ return ReactDOM__default["default"].findDOMNode(this)?.value.toString();
21279
+ };
21280
+ setSelectionRange = (selectionStart, selectionEnd) => {
21281
+ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
21282
+ ReactDOM__default["default"].findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
21283
+ };
21284
+ getSelectionStart = () => {
21285
+ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
21286
+ return ReactDOM__default["default"].findDOMNode(this).selectionStart;
21287
+ };
21288
+ getSelectionEnd = () => {
21289
+ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
21290
+ return ReactDOM__default["default"].findDOMNode(this).selectionEnd;
21291
+ };
21264
21292
  render() {
21265
21293
  const {
21266
21294
  labelText,
@@ -21292,34 +21320,6 @@ class TextInput extends React__namespace.Component {
21292
21320
  autoComplete: "off"
21293
21321
  });
21294
21322
  }
21295
- focus = () => {
21296
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
21297
- ReactDOM__default["default"].findDOMNode(this).focus();
21298
- };
21299
- blur = () => {
21300
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
21301
- ReactDOM__default["default"].findDOMNode(this).blur();
21302
- };
21303
- getValue = () => {
21304
- // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'Element | Text'.
21305
- return ReactDOM__default["default"].findDOMNode(this)?.value;
21306
- };
21307
- getStringValue = () => {
21308
- // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'Element | Text'.
21309
- return ReactDOM__default["default"].findDOMNode(this)?.value.toString();
21310
- };
21311
- setSelectionRange = (selectionStart, selectionEnd) => {
21312
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
21313
- ReactDOM__default["default"].findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
21314
- };
21315
- getSelectionStart = () => {
21316
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
21317
- return ReactDOM__default["default"].findDOMNode(this).selectionStart;
21318
- };
21319
- getSelectionEnd = () => {
21320
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
21321
- return ReactDOM__default["default"].findDOMNode(this).selectionEnd;
21322
- };
21323
21323
  }
21324
21324
 
21325
21325
  /* eslint-disable react/no-unsafe */
@@ -21569,7 +21569,6 @@ class Tooltip extends React__namespace.Component {
21569
21569
  }
21570
21570
  }
21571
21571
 
21572
- /* eslint-disable react/sort-comp */
21573
21572
  const {
21574
21573
  captureScratchpadTouchStart: captureScratchpadTouchStart$2
21575
21574
  } = Util;
@@ -21623,31 +21622,6 @@ class InputWithExamples extends React__namespace.Component {
21623
21622
  };
21624
21623
  return /*#__PURE__*/React__namespace.createElement(TextInput, inputProps);
21625
21624
  };
21626
- render() {
21627
- const input = this._renderInput();
21628
- const examplesContent = ___default["default"].map(this.props.examples, example => {
21629
- return "- " + example;
21630
- }).join("\n");
21631
- const showExamples = this.props.shouldShowExamples && this.state.showExamples;
21632
- return /*#__PURE__*/React__namespace.createElement(Tooltip
21633
- // eslint-disable-next-line react/no-string-refs
21634
- , {
21635
- ref: "tooltip",
21636
- className: "perseus-formats-tooltip preview-measure",
21637
- horizontalPosition: HorizontalDirection.Left,
21638
- horizontalAlign: HorizontalDirection.Left,
21639
- verticalPosition: VerticalDirection.Bottom,
21640
- arrowSize: 10,
21641
- borderColor: "#ccc",
21642
- show: showExamples
21643
- }, input, /*#__PURE__*/React__namespace.createElement("div", {
21644
- id: this._getUniqueId()
21645
- }, /*#__PURE__*/React__namespace.createElement(Renderer, {
21646
- content: examplesContent,
21647
- linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "input-with-examples"),
21648
- strings: this.context.strings
21649
- })));
21650
- }
21651
21625
  _handleFocus = () => {
21652
21626
  this.props.onFocus();
21653
21627
  this.setState({
@@ -21685,6 +21659,31 @@ class InputWithExamples extends React__namespace.Component {
21685
21659
  handleChange = e => {
21686
21660
  this.props.onChange(e.target.value);
21687
21661
  };
21662
+ render() {
21663
+ const input = this._renderInput();
21664
+ const examplesContent = ___default["default"].map(this.props.examples, example => {
21665
+ return "- " + example;
21666
+ }).join("\n");
21667
+ const showExamples = this.props.shouldShowExamples && this.state.showExamples;
21668
+ return /*#__PURE__*/React__namespace.createElement(Tooltip
21669
+ // eslint-disable-next-line react/no-string-refs
21670
+ , {
21671
+ ref: "tooltip",
21672
+ className: "perseus-formats-tooltip preview-measure",
21673
+ horizontalPosition: HorizontalDirection.Left,
21674
+ horizontalAlign: HorizontalDirection.Left,
21675
+ verticalPosition: VerticalDirection.Bottom,
21676
+ arrowSize: 10,
21677
+ borderColor: "#ccc",
21678
+ show: showExamples
21679
+ }, input, /*#__PURE__*/React__namespace.createElement("div", {
21680
+ id: this._getUniqueId()
21681
+ }, /*#__PURE__*/React__namespace.createElement(Renderer, {
21682
+ content: examplesContent,
21683
+ linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "input-with-examples"),
21684
+ strings: this.context.strings
21685
+ })));
21686
+ }
21688
21687
  }
21689
21688
 
21690
21689
  class SimpleKeypadInput extends React__namespace.Component {
@@ -21915,7 +21914,6 @@ var TexWrangler = {
21915
21914
  modifyTex
21916
21915
  };
21917
21916
 
21918
- /* eslint-disable react/sort-comp */
21919
21917
  const ParseTex$1 = TexWrangler.parseTex;
21920
21918
  const answerTypes = {
21921
21919
  number: {
@@ -21992,58 +21990,65 @@ class InputNumber extends React__namespace.Component {
21992
21990
  apiOptions: ApiOptions.defaults,
21993
21991
  linterContext: PerseusLinter.linterContextDefault
21994
21992
  };
21995
- shouldShowExamples = () => {
21996
- return this.props.answerType !== "number";
21997
- };
21998
- render() {
21999
- if (this.props.apiOptions.customKeypad) {
22000
- // TODO(charlie): Support "Review Mode".
22001
- const input = /*#__PURE__*/React__namespace.createElement(SimpleKeypadInput
22002
- // eslint-disable-next-line react/no-string-refs
22003
- , {
22004
- ref: "input",
22005
- value: this.props.currentValue,
22006
- keypadElement: this.props.keypadElement,
22007
- onChange: this.handleChange,
22008
- onFocus: this._handleFocus,
22009
- onBlur: this._handleBlur
22010
- });
22011
- if (this.props.rightAlign) {
22012
- return /*#__PURE__*/React__namespace.createElement("div", {
22013
- className: "perseus-input-right-align"
22014
- }, input);
22015
- }
22016
- return input;
21993
+ static validate(state, rubric, strings) {
21994
+ let onInputError = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : () => {};
21995
+ if (rubric.answerType == null) {
21996
+ rubric.answerType = "number";
22017
21997
  }
22018
- // HACK(johnsullivan): Create a function with shared logic between
22019
- // this and NumericInput.
22020
- // TODO(jeremy): Deprecate this widget and prefer numeric-input.
22021
- const rubric = this.props.reviewModeRubric;
22022
21998
 
22023
- // Note: This is _very_ similar to what `numeric-input.jsx` does. If
22024
- // you modify this, double-check if you also need to modify that
22025
- // component.
22026
- const inputStyles = [styles$A.default, this.props.size === "small" ? styles$A.small : null, this.props.rightAlign ? styles$A.rightAlign : styles$A.leftAlign];
22027
- // Unanswered
22028
- if (rubric && !this.props.currentValue) {
22029
- inputStyles.push(styles$A.answerStateUnanswered);
21999
+ // note(matthewc): this will get immediately parsed again by
22000
+ // `KhanAnswerTypes.number.convertToPredicate`, but a string is
22001
+ // expected here
22002
+ const stringValue = `${rubric.value}`;
22003
+ const val = KhanAnswerTypes.number.createValidatorFunctional(stringValue, {
22004
+ simplify: rubric.simplify,
22005
+ inexact: rubric.inexact || undefined,
22006
+ maxError: rubric.maxError,
22007
+ forms: answerTypes[rubric.answerType].forms
22008
+ }, strings);
22009
+
22010
+ // We may have received TeX; try to parse it before grading.
22011
+ // If `currentValue` is not TeX, this should be a no-op.
22012
+ const currentValue = ParseTex$1(state.currentValue);
22013
+ const result = val(currentValue);
22014
+
22015
+ // TODO(eater): Seems silly to translate result to this invalid/points
22016
+ // thing and immediately translate it back in ItemRenderer.scoreInput()
22017
+ if (result.empty) {
22018
+ // TODO(FEI-3867): remove null-check once we have APIOptionsInternal
22019
+ const apiResult = onInputError?.(null,
22020
+ // reserved for some widget identifier
22021
+ state.currentValue, result.message);
22022
+ return {
22023
+ type: "invalid",
22024
+ message: apiResult === false ? null : result.message
22025
+ };
22030
22026
  }
22031
- return /*#__PURE__*/React__namespace.createElement(InputWithExamples
22032
- // eslint-disable-next-line react/no-string-refs
22033
- , {
22034
- ref: "input",
22035
- value: this.props.currentValue,
22036
- onChange: this.handleChange,
22037
- style: inputStyles,
22038
- examples: this.examples(),
22039
- shouldShowExamples: this.shouldShowExamples(),
22040
- onFocus: this._handleFocus,
22041
- onBlur: this._handleBlur,
22042
- id: this.props.widgetId,
22043
- disabled: this.props.apiOptions.readOnly,
22044
- linterContext: this.props.linterContext
22045
- });
22027
+ return {
22028
+ type: "points",
22029
+ earned: result.correct ? 1 : 0,
22030
+ total: 1,
22031
+ message: result.message
22032
+ };
22046
22033
  }
22034
+ static getUserInputFromProps(props) {
22035
+ return {
22036
+ currentValue: props.currentValue
22037
+ };
22038
+ }
22039
+ static getOneCorrectAnswerFromRubric(rubric) {
22040
+ if (rubric.value == null) {
22041
+ return;
22042
+ }
22043
+ let answerString = String(rubric.value);
22044
+ if (rubric.inexact && rubric.maxError) {
22045
+ answerString += " \u00B1 " + rubric.maxError;
22046
+ }
22047
+ return answerString;
22048
+ }
22049
+ shouldShowExamples = () => {
22050
+ return this.props.answerType !== "number";
22051
+ };
22047
22052
  handleChange = (newValue, cb) => {
22048
22053
  this.props.onChange({
22049
22054
  currentValue: newValue
@@ -22109,61 +22114,54 @@ class InputNumber extends React__namespace.Component {
22109
22114
  const examples = ___default["default"].map(forms, form => formExamples$1[form](this.props, strings));
22110
22115
  return [strings.yourAnswer].concat(examples);
22111
22116
  };
22112
- static validate(state, rubric, strings) {
22113
- let onInputError = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : () => {};
22114
- if (rubric.answerType == null) {
22115
- rubric.answerType = "number";
22117
+ render() {
22118
+ if (this.props.apiOptions.customKeypad) {
22119
+ // TODO(charlie): Support "Review Mode".
22120
+ const input = /*#__PURE__*/React__namespace.createElement(SimpleKeypadInput
22121
+ // eslint-disable-next-line react/no-string-refs
22122
+ , {
22123
+ ref: "input",
22124
+ value: this.props.currentValue,
22125
+ keypadElement: this.props.keypadElement,
22126
+ onChange: this.handleChange,
22127
+ onFocus: this._handleFocus,
22128
+ onBlur: this._handleBlur
22129
+ });
22130
+ if (this.props.rightAlign) {
22131
+ return /*#__PURE__*/React__namespace.createElement("div", {
22132
+ className: "perseus-input-right-align"
22133
+ }, input);
22134
+ }
22135
+ return input;
22116
22136
  }
22137
+ // HACK(johnsullivan): Create a function with shared logic between
22138
+ // this and NumericInput.
22139
+ // TODO(jeremy): Deprecate this widget and prefer numeric-input.
22140
+ const rubric = this.props.reviewModeRubric;
22117
22141
 
22118
- // note(matthewc): this will get immediately parsed again by
22119
- // `KhanAnswerTypes.number.convertToPredicate`, but a string is
22120
- // expected here
22121
- const stringValue = `${rubric.value}`;
22122
- const val = KhanAnswerTypes.number.createValidatorFunctional(stringValue, {
22123
- simplify: rubric.simplify,
22124
- inexact: rubric.inexact || undefined,
22125
- maxError: rubric.maxError,
22126
- forms: answerTypes[rubric.answerType].forms
22127
- }, strings);
22128
-
22129
- // We may have received TeX; try to parse it before grading.
22130
- // If `currentValue` is not TeX, this should be a no-op.
22131
- const currentValue = ParseTex$1(state.currentValue);
22132
- const result = val(currentValue);
22133
-
22134
- // TODO(eater): Seems silly to translate result to this invalid/points
22135
- // thing and immediately translate it back in ItemRenderer.scoreInput()
22136
- if (result.empty) {
22137
- // TODO(FEI-3867): remove null-check once we have APIOptionsInternal
22138
- const apiResult = onInputError?.(null,
22139
- // reserved for some widget identifier
22140
- state.currentValue, result.message);
22141
- return {
22142
- type: "invalid",
22143
- message: apiResult === false ? null : result.message
22144
- };
22145
- }
22146
- return {
22147
- type: "points",
22148
- earned: result.correct ? 1 : 0,
22149
- total: 1,
22150
- message: result.message
22151
- };
22152
- }
22153
- static getUserInputFromProps(props) {
22154
- return {
22155
- currentValue: props.currentValue
22156
- };
22157
- }
22158
- static getOneCorrectAnswerFromRubric(rubric) {
22159
- if (rubric.value == null) {
22160
- return;
22161
- }
22162
- let answerString = String(rubric.value);
22163
- if (rubric.inexact && rubric.maxError) {
22164
- answerString += " \u00B1 " + rubric.maxError;
22142
+ // Note: This is _very_ similar to what `numeric-input.jsx` does. If
22143
+ // you modify this, double-check if you also need to modify that
22144
+ // component.
22145
+ const inputStyles = [styles$A.default, this.props.size === "small" ? styles$A.small : null, this.props.rightAlign ? styles$A.rightAlign : styles$A.leftAlign];
22146
+ // Unanswered
22147
+ if (rubric && !this.props.currentValue) {
22148
+ inputStyles.push(styles$A.answerStateUnanswered);
22165
22149
  }
22166
- return answerString;
22150
+ return /*#__PURE__*/React__namespace.createElement(InputWithExamples
22151
+ // eslint-disable-next-line react/no-string-refs
22152
+ , {
22153
+ ref: "input",
22154
+ value: this.props.currentValue,
22155
+ onChange: this.handleChange,
22156
+ style: inputStyles,
22157
+ examples: this.examples(),
22158
+ shouldShowExamples: this.shouldShowExamples(),
22159
+ onFocus: this._handleFocus,
22160
+ onBlur: this._handleBlur,
22161
+ id: this.props.widgetId,
22162
+ disabled: this.props.apiOptions.readOnly,
22163
+ linterContext: this.props.linterContext
22164
+ });
22167
22165
  }
22168
22166
  }
22169
22167
  const styles$A = aphrodite.StyleSheet.create({
@@ -22607,7 +22605,6 @@ var NumericInput$1 = {
22607
22605
  isLintable: true
22608
22606
  };
22609
22607
 
22610
- /* eslint-disable react/sort-comp */
22611
22608
  const EN_DASH$1 = "\u2013";
22612
22609
  class PassageRef extends React__namespace.Component {
22613
22610
  static contextType = PerseusI18nContext;
@@ -22625,48 +22622,38 @@ class PassageRef extends React__namespace.Component {
22625
22622
  lineRange: null,
22626
22623
  content: null
22627
22624
  };
22625
+ static validate(userInput, rubric) {
22626
+ return {
22627
+ type: "points",
22628
+ earned: 0,
22629
+ total: 0,
22630
+ message: null
22631
+ };
22632
+ }
22633
+ componentDidMount() {
22634
+ // TODO(scottgrant): This is a hack to remove the deprecated call to
22635
+ // this.isMounted() but is still considered an anti-pattern.
22636
+ this._isMounted = true;
22637
+ this._deferredUpdateRange();
22638
+ this._throttledUpdateRange = ___default["default"].throttle(this._deferredUpdateRange, 500);
22639
+ window.addEventListener("resize", this._throttledUpdateRange);
22640
+ }
22628
22641
  shouldComponentUpdate(nextProps, nextState) {
22629
22642
  return !___default["default"].isEqual(this.props, nextProps) || !___default["default"].isEqual(this.state, nextState);
22630
22643
  }
22644
+ componentDidUpdate() {
22645
+ this._deferredUpdateRange();
22646
+ }
22647
+ componentWillUnmount() {
22648
+ window.removeEventListener("resize", this._throttledUpdateRange);
22649
+ this._isMounted = false;
22650
+ }
22631
22651
 
22632
22652
  // TODO(tamarab): getUserInput needs to be updated to only return
22633
22653
  // props input by the user. Currently returns all the widget's props.
22634
22654
  getUserInput = () => {
22635
22655
  return removeDenylistProps(this.props);
22636
22656
  };
22637
- render() {
22638
- const {
22639
- strings
22640
- } = this.context;
22641
- const lineRange = this.state.lineRange;
22642
- let lineRangeOutput;
22643
- if (!lineRange) {
22644
- lineRangeOutput = strings.lineRange({
22645
- lineRange: `?${EN_DASH$1}?`
22646
- });
22647
- } else if (lineRange[0] === lineRange[1]) {
22648
- lineRangeOutput = strings.lineNumber({
22649
- lineNumber: String(lineRange[0])
22650
- });
22651
- } else {
22652
- lineRangeOutput = strings.lineRange({
22653
- lineRange: lineRange[0] + EN_DASH$1 + lineRange[1]
22654
- });
22655
- }
22656
- let summaryOutput;
22657
- if (this.props.summaryText) {
22658
- // @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
22659
- const summaryTree = PerseusMarkdown.parseInline(this.props.summaryText);
22660
- summaryOutput = /*#__PURE__*/React__namespace.createElement("span", {
22661
- "aria-hidden": true
22662
- }, " ", "(\u201C", PerseusMarkdown.basicOutput(summaryTree), "\u201D)");
22663
- } else {
22664
- summaryOutput = null;
22665
- }
22666
- return /*#__PURE__*/React__namespace.createElement("span", null, lineRangeOutput, summaryOutput, lineRange && /*#__PURE__*/React__namespace.createElement("div", {
22667
- className: "perseus-sr-only"
22668
- }, this.state.content));
22669
- }
22670
22657
  change = (() => {
22671
22658
  var _this = this;
22672
22659
  return function () {
@@ -22676,21 +22663,6 @@ class PassageRef extends React__namespace.Component {
22676
22663
  return change.apply(_this, args);
22677
22664
  };
22678
22665
  })();
22679
- componentDidMount() {
22680
- // TODO(scottgrant): This is a hack to remove the deprecated call to
22681
- // this.isMounted() but is still considered an anti-pattern.
22682
- this._isMounted = true;
22683
- this._deferredUpdateRange();
22684
- this._throttledUpdateRange = ___default["default"].throttle(this._deferredUpdateRange, 500);
22685
- window.addEventListener("resize", this._throttledUpdateRange);
22686
- }
22687
- componentDidUpdate() {
22688
- this._deferredUpdateRange();
22689
- }
22690
- componentWillUnmount() {
22691
- window.removeEventListener("resize", this._throttledUpdateRange);
22692
- this._isMounted = false;
22693
- }
22694
22666
  _deferredUpdateRange = () => {
22695
22667
  ___default["default"].defer(this._updateRange);
22696
22668
  };
@@ -22720,13 +22692,38 @@ class PassageRef extends React__namespace.Component {
22720
22692
  simpleValidate = rubric => {
22721
22693
  return PassageRef.validate(this.getUserInput(), rubric);
22722
22694
  };
22723
- static validate(userInput, rubric) {
22724
- return {
22725
- type: "points",
22726
- earned: 0,
22727
- total: 0,
22728
- message: null
22729
- };
22695
+ render() {
22696
+ const {
22697
+ strings
22698
+ } = this.context;
22699
+ const lineRange = this.state.lineRange;
22700
+ let lineRangeOutput;
22701
+ if (!lineRange) {
22702
+ lineRangeOutput = strings.lineRange({
22703
+ lineRange: `?${EN_DASH$1}?`
22704
+ });
22705
+ } else if (lineRange[0] === lineRange[1]) {
22706
+ lineRangeOutput = strings.lineNumber({
22707
+ lineNumber: String(lineRange[0])
22708
+ });
22709
+ } else {
22710
+ lineRangeOutput = strings.lineRange({
22711
+ lineRange: lineRange[0] + EN_DASH$1 + lineRange[1]
22712
+ });
22713
+ }
22714
+ let summaryOutput;
22715
+ if (this.props.summaryText) {
22716
+ // @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
22717
+ const summaryTree = PerseusMarkdown.parseInline(this.props.summaryText);
22718
+ summaryOutput = /*#__PURE__*/React__namespace.createElement("span", {
22719
+ "aria-hidden": true
22720
+ }, " ", "(\u201C", PerseusMarkdown.basicOutput(summaryTree), "\u201D)");
22721
+ } else {
22722
+ summaryOutput = null;
22723
+ }
22724
+ return /*#__PURE__*/React__namespace.createElement("span", null, lineRangeOutput, summaryOutput, lineRange && /*#__PURE__*/React__namespace.createElement("div", {
22725
+ className: "perseus-sr-only"
22726
+ }, this.state.content));
22730
22727
  }
22731
22728
  }
22732
22729
  var PassageRef$1 = {
@@ -24678,6 +24675,33 @@ class Categorizer extends React__namespace.Component {
24678
24675
  state = {
24679
24676
  uniqueId: ___default["default"].uniqueId("perseus_radio_")
24680
24677
  };
24678
+ static validate(userInput, rubric, strings) {
24679
+ let completed = true;
24680
+ let allCorrect = true;
24681
+ rubric.values.forEach((value, i) => {
24682
+ if (userInput.values[i] == null) {
24683
+ completed = false;
24684
+ }
24685
+ if (userInput.values[i] !== value) {
24686
+ allCorrect = false;
24687
+ }
24688
+ });
24689
+ if (!completed) {
24690
+ return {
24691
+ type: "invalid",
24692
+ message: strings.invalidSelection
24693
+ };
24694
+ }
24695
+ return {
24696
+ type: "points",
24697
+ earned: allCorrect ? 1 : 0,
24698
+ total: 1,
24699
+ message: null
24700
+ };
24701
+ }
24702
+ static getUserInputFromProps(props) {
24703
+ return WidgetJsonifyDeprecated.getUserInputFromProps(props);
24704
+ }
24681
24705
  change = (() => {
24682
24706
  var _this = this;
24683
24707
  return function () {
@@ -24691,6 +24715,16 @@ class Categorizer extends React__namespace.Component {
24691
24715
  getUserInput = () => {
24692
24716
  return Categorizer.getUserInputFromProps(this.props);
24693
24717
  };
24718
+ onChange(itemNum, catNum) {
24719
+ const values = [...this.props.values];
24720
+ // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'.
24721
+ values[itemNum] = catNum;
24722
+ this.change("values", values);
24723
+ this.props.trackInteraction();
24724
+ }
24725
+ simpleValidate = rubric => {
24726
+ return Categorizer.validate(this.getUserInput(), rubric, this.context.strings);
24727
+ };
24694
24728
  render() {
24695
24729
  const self = this;
24696
24730
 
@@ -24767,43 +24801,6 @@ class Categorizer extends React__namespace.Component {
24767
24801
  className: extraClassNames + " " + aphrodite.css(...inlineStyles)
24768
24802
  }, table);
24769
24803
  }
24770
- onChange(itemNum, catNum) {
24771
- const values = [...this.props.values];
24772
- // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'.
24773
- values[itemNum] = catNum;
24774
- this.change("values", values);
24775
- this.props.trackInteraction();
24776
- }
24777
- simpleValidate = rubric => {
24778
- return Categorizer.validate(this.getUserInput(), rubric, this.context.strings);
24779
- };
24780
- static validate(userInput, rubric, strings) {
24781
- let completed = true;
24782
- let allCorrect = true;
24783
- rubric.values.forEach((value, i) => {
24784
- if (userInput.values[i] == null) {
24785
- completed = false;
24786
- }
24787
- if (userInput.values[i] !== value) {
24788
- allCorrect = false;
24789
- }
24790
- });
24791
- if (!completed) {
24792
- return {
24793
- type: "invalid",
24794
- message: strings.invalidSelection
24795
- };
24796
- }
24797
- return {
24798
- type: "points",
24799
- earned: allCorrect ? 1 : 0,
24800
- total: 1,
24801
- message: null
24802
- };
24803
- }
24804
- static getUserInputFromProps(props) {
24805
- return WidgetJsonifyDeprecated.getUserInputFromProps(props);
24806
- }
24807
24804
  }
24808
24805
 
24809
24806
  // TODO(benkomalo): inject page-margin into Perseus instead of hardcoding.
@@ -25311,8 +25308,6 @@ var Dropdown$1 = {
25311
25308
  transform: optionsTransform
25312
25309
  };
25313
25310
 
25314
- /* eslint-disable react/sort-comp */
25315
-
25316
25311
  // transform = _.identity
25317
25312
 
25318
25313
  function mediaQueryIsMatched(mediaQuery) {
@@ -25323,6 +25318,10 @@ function mediaQueryIsMatched(mediaQuery) {
25323
25318
  }
25324
25319
  class Explanation extends React__namespace.Component {
25325
25320
  static contextType = PerseusI18nContext;
25321
+ state = {
25322
+ expanded: false
25323
+ };
25324
+ _mounted = false;
25326
25325
  static defaultProps = {
25327
25326
  showPrompt: "Explain",
25328
25327
  hidePrompt: "Hide explanation",
@@ -25338,10 +25337,6 @@ class Explanation extends React__namespace.Component {
25338
25337
  message: null
25339
25338
  };
25340
25339
  }
25341
- state = {
25342
- expanded: false
25343
- };
25344
- _mounted = false;
25345
25340
  componentDidMount() {
25346
25341
  this._mounted = true;
25347
25342
  }
@@ -25363,6 +25358,12 @@ class Explanation extends React__namespace.Component {
25363
25358
  });
25364
25359
  this.props.trackInteraction();
25365
25360
  };
25361
+ getUserInput = () => {
25362
+ return {};
25363
+ };
25364
+ simpleValidate = rubric => {
25365
+ return Explanation.validate(this.getUserInput(), rubric);
25366
+ };
25366
25367
  render() {
25367
25368
  const promptText = this.state.expanded ? this.props.hidePrompt : this.props.showPrompt;
25368
25369
  const caretIcon = this.state.expanded ? caretUp__default["default"] : caretDown__default["default"];
@@ -25418,12 +25419,6 @@ class Explanation extends React__namespace.Component {
25418
25419
  strings: this.context.strings
25419
25420
  })))));
25420
25421
  }
25421
- getUserInput = () => {
25422
- return {};
25423
- };
25424
- simpleValidate = rubric => {
25425
- return Explanation.validate(this.getUserInput(), rubric);
25426
- };
25427
25422
  }
25428
25423
  const leftBorderSpacing = 23;
25429
25424
  const verticalContentPadding = 10;
@@ -26847,6 +26842,70 @@ class FunctionGrapher extends React__namespace.Component {
26847
26842
  return change.apply(_this, args);
26848
26843
  };
26849
26844
  })();
26845
+ renderPlot = () => {
26846
+ const model = this.props.model;
26847
+ const xRange = this.props.graph.range[0];
26848
+ const style = {
26849
+ stroke: this.props.isMobile ? KhanColors.BLUE_C : KhanColors.DYNAMIC,
26850
+ ...(this.props.isMobile ? {
26851
+ "stroke-width": 3
26852
+ } : {})
26853
+ };
26854
+ const coeffs = model.getCoefficients(this._coords(), this._asymptote());
26855
+ if (!coeffs) {
26856
+ return;
26857
+ }
26858
+ const functionProps = model.getPropsForCoeffs(coeffs, xRange);
26859
+ return /*#__PURE__*/React__namespace.createElement(model.Movable, _extends({}, functionProps, {
26860
+ key: this.props.model.url,
26861
+ range: xRange,
26862
+ style: style
26863
+ }));
26864
+ };
26865
+ renderAsymptote = () => {
26866
+ const model = this.props.model;
26867
+ const graph = this.props.graph;
26868
+ const asymptote = this._asymptote();
26869
+ const dashed = {
26870
+ strokeDasharray: "- "
26871
+ };
26872
+ return asymptote && /*#__PURE__*/React__namespace.createElement(MovableLine$2, {
26873
+ onMove: (newCoord, oldCoord) => {
26874
+ // Calculate and apply displacement
26875
+ const delta = kmath.vector.subtract(newCoord, oldCoord);
26876
+ const newAsymptote = ___default["default"].map(this._asymptote(), coord => kmath.vector.add(coord, delta));
26877
+ this.props.onChange({
26878
+ asymptote: newAsymptote
26879
+ });
26880
+ },
26881
+ constraints: [
26882
+ // @ts-expect-error - TS2339 - Property 'constraints' does not exist on type '(graphie: any, movable: any, options: any) => void'.
26883
+ Interactive2.MovableLine.constraints.bound(),
26884
+ // @ts-expect-error - TS2339 - Property 'constraints' does not exist on type '(graphie: any, movable: any, options: any) => void'.
26885
+ Interactive2.MovableLine.constraints.snap(), (newCoord, oldCoord) => {
26886
+ // Calculate and apply proposed displacement
26887
+ const delta = kmath.vector.subtract(newCoord, oldCoord);
26888
+ const proposedAsymptote = ___default["default"].map(this._asymptote(), coord => kmath.vector.add(coord, delta));
26889
+ // Verify that resulting asymptote is valid for graph
26890
+ if (model.extraAsymptoteConstraint) {
26891
+ return model.extraAsymptoteConstraint(newCoord, oldCoord, this._coords(), proposedAsymptote, graph);
26892
+ }
26893
+ return true;
26894
+ }],
26895
+ normalStyle: dashed,
26896
+ highlightStyle: dashed
26897
+ }, ___default["default"].map(asymptote, (coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$3, {
26898
+ key: `asymptoteCoord-${i}`,
26899
+ coord: coord,
26900
+ static: true,
26901
+ draw: null,
26902
+ extendLine: true,
26903
+ showHairlines: this.props.showHairlines,
26904
+ hideHairlines: this.props.hideHairlines,
26905
+ showTooltips: this.props.showTooltips,
26906
+ isMobile: this.props.isMobile
26907
+ })));
26908
+ };
26850
26909
  render() {
26851
26910
  const pointForCoord = (coord, i) => {
26852
26911
  return /*#__PURE__*/React__namespace.createElement(MovablePoint$3, {
@@ -26934,70 +26993,6 @@ class FunctionGrapher extends React__namespace.Component {
26934
26993
  setDrawingAreaAvailable: this.props.setDrawingAreaAvailable
26935
26994
  }), this.props.model && this.renderPlot(), this.props.model && this.renderAsymptote(), this.props.model && points)));
26936
26995
  }
26937
- renderPlot = () => {
26938
- const model = this.props.model;
26939
- const xRange = this.props.graph.range[0];
26940
- const style = {
26941
- stroke: this.props.isMobile ? KhanColors.BLUE_C : KhanColors.DYNAMIC,
26942
- ...(this.props.isMobile ? {
26943
- "stroke-width": 3
26944
- } : {})
26945
- };
26946
- const coeffs = model.getCoefficients(this._coords(), this._asymptote());
26947
- if (!coeffs) {
26948
- return;
26949
- }
26950
- const functionProps = model.getPropsForCoeffs(coeffs, xRange);
26951
- return /*#__PURE__*/React__namespace.createElement(model.Movable, _extends({}, functionProps, {
26952
- key: this.props.model.url,
26953
- range: xRange,
26954
- style: style
26955
- }));
26956
- };
26957
- renderAsymptote = () => {
26958
- const model = this.props.model;
26959
- const graph = this.props.graph;
26960
- const asymptote = this._asymptote();
26961
- const dashed = {
26962
- strokeDasharray: "- "
26963
- };
26964
- return asymptote && /*#__PURE__*/React__namespace.createElement(MovableLine$2, {
26965
- onMove: (newCoord, oldCoord) => {
26966
- // Calculate and apply displacement
26967
- const delta = kmath.vector.subtract(newCoord, oldCoord);
26968
- const newAsymptote = ___default["default"].map(this._asymptote(), coord => kmath.vector.add(coord, delta));
26969
- this.props.onChange({
26970
- asymptote: newAsymptote
26971
- });
26972
- },
26973
- constraints: [
26974
- // @ts-expect-error - TS2339 - Property 'constraints' does not exist on type '(graphie: any, movable: any, options: any) => void'.
26975
- Interactive2.MovableLine.constraints.bound(),
26976
- // @ts-expect-error - TS2339 - Property 'constraints' does not exist on type '(graphie: any, movable: any, options: any) => void'.
26977
- Interactive2.MovableLine.constraints.snap(), (newCoord, oldCoord) => {
26978
- // Calculate and apply proposed displacement
26979
- const delta = kmath.vector.subtract(newCoord, oldCoord);
26980
- const proposedAsymptote = ___default["default"].map(this._asymptote(), coord => kmath.vector.add(coord, delta));
26981
- // Verify that resulting asymptote is valid for graph
26982
- if (model.extraAsymptoteConstraint) {
26983
- return model.extraAsymptoteConstraint(newCoord, oldCoord, this._coords(), proposedAsymptote, graph);
26984
- }
26985
- return true;
26986
- }],
26987
- normalStyle: dashed,
26988
- highlightStyle: dashed
26989
- }, ___default["default"].map(asymptote, (coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$3, {
26990
- key: `asymptoteCoord-${i}`,
26991
- coord: coord,
26992
- static: true,
26993
- draw: null,
26994
- extendLine: true,
26995
- showHairlines: this.props.showHairlines,
26996
- hideHairlines: this.props.hideHairlines,
26997
- showTooltips: this.props.showTooltips,
26998
- isMobile: this.props.isMobile
26999
- })));
27000
- };
27001
26996
  }
27002
26997
 
27003
26998
  // Really this is props.plot, I think
@@ -27007,6 +27002,118 @@ class Grapher extends React__namespace.Component {
27007
27002
  horizHairline;
27008
27003
  vertHairline;
27009
27004
  static defaultProps = DEFAULT_GRAPHER_PROPS;
27005
+ static validate(state, rubric) {
27006
+ return validate$1(state, rubric);
27007
+ }
27008
+ static getUserInputFromProps(props) {
27009
+ return props.plot;
27010
+ }
27011
+ handlePlotChanges = newPlot => {
27012
+ const plot = ___default["default"].extend({}, this.props.plot, newPlot);
27013
+ this.props.onChange({
27014
+ plot: plot
27015
+ });
27016
+ this.props.trackInteraction();
27017
+ };
27018
+ handleActiveTypeChange = newType => {
27019
+ const graph = this.props.graph;
27020
+ const plot = ___default["default"].extend({}, this.props.plot, defaultPlotProps(newType, graph));
27021
+ this.props.onChange({
27022
+ plot: plot
27023
+ });
27024
+ };
27025
+ _getGridConfig(options) {
27026
+ return options.step.map((step, i) => {
27027
+ return Util.gridDimensionConfig(step, options.range[i], options.box[i], options.gridStep[i]);
27028
+ });
27029
+ }
27030
+ _calculateMobileTickStep(gridStep, step, ranges) {
27031
+ const tickStep = Util.constrainedTickStepsFromTickSteps(step, ranges);
27032
+
27033
+ // According to the graphInit documentation in graphie.js, tickStep is
27034
+ // relative to the grid units so we need to adjust all values by the
27035
+ // grid step.
27036
+ tickStep[0] = tickStep[0] / gridStep[0];
27037
+ tickStep[1] = tickStep[1] / gridStep[1];
27038
+ return tickStep;
27039
+ }
27040
+ _setupGraphie = (graphie, options) => {
27041
+ const isMobile = this.props.apiOptions.isMobile;
27042
+ if (options.markings === "graph") {
27043
+ graphie.graphInit({
27044
+ range: options.range,
27045
+ scale: ___default["default"].pluck(options.gridConfig, "scale"),
27046
+ axisArrows: "<->",
27047
+ labelFormat: function (s) {
27048
+ return "\\small{" + s + "}";
27049
+ },
27050
+ gridStep: options.gridStep,
27051
+ snapStep: options.snapStep,
27052
+ tickStep: isMobile ? this._calculateMobileTickStep(options.gridStep, options.step, options.range) : ___default["default"].pluck(options.gridConfig, "tickStep"),
27053
+ labelStep: 1,
27054
+ unityLabels: ___default["default"].pluck(options.gridConfig, "unityLabel"),
27055
+ isMobile: isMobile
27056
+ });
27057
+ graphie.label([0, options.range[1][1]], options.labels[1], isMobile ? "below right" : "above");
27058
+ graphie.label([options.range[0][1], 0], options.labels[0], isMobile ? "above left" : "right");
27059
+ } else if (options.markings === "grid") {
27060
+ graphie.graphInit({
27061
+ range: options.range,
27062
+ scale: ___default["default"].pluck(options.gridConfig, "scale"),
27063
+ gridStep: options.gridStep,
27064
+ axes: false,
27065
+ ticks: false,
27066
+ labels: false,
27067
+ isMobile: isMobile
27068
+ });
27069
+ } else if (options.markings === "none") {
27070
+ graphie.init({
27071
+ range: options.range,
27072
+ scale: ___default["default"].pluck(options.gridConfig, "scale")
27073
+ });
27074
+ }
27075
+ if (this.props.apiOptions.isMobile) {
27076
+ const hairlineStyle = {
27077
+ normalStyle: {
27078
+ strokeWidth: 1
27079
+ }
27080
+ };
27081
+ this.horizHairline = new WrappedLine(graphie, [0, 0], [0, 0], hairlineStyle);
27082
+ this.horizHairline.attr({
27083
+ stroke: KhanColors.INTERACTIVE
27084
+ });
27085
+ this.horizHairline.hide();
27086
+ this.vertHairline = new WrappedLine(graphie, [0, 0], [0, 0], hairlineStyle);
27087
+ this.vertHairline.attr({
27088
+ stroke: KhanColors.INTERACTIVE
27089
+ });
27090
+ this.vertHairline.hide();
27091
+ }
27092
+ };
27093
+ showHairlines = point => {
27094
+ if (this.props.apiOptions.isMobile && this.props.markings !== "none") {
27095
+ // Hairlines are already initialized when the graph is loaded, so
27096
+ // here we just move them to the updated location and make them
27097
+ // visible.
27098
+ this.horizHairline.moveTo([this.props.graph.range[0][0], point[1]], [this.props.graph.range[0][1], point[1]]);
27099
+ this.horizHairline.show();
27100
+ this.vertHairline.moveTo([point[0], this.props.graph.range[1][0]], [point[0], this.props.graph.range[1][1]]);
27101
+ this.vertHairline.show();
27102
+ }
27103
+ };
27104
+ hideHairlines = () => {
27105
+ if (this.props.apiOptions.isMobile) {
27106
+ this.horizHairline.hide();
27107
+ this.vertHairline.hide();
27108
+ }
27109
+ };
27110
+ simpleValidate(rubric) {
27111
+ return validate$1(this.getUserInput(), rubric);
27112
+ }
27113
+ getUserInput() {
27114
+ return Grapher.getUserInputFromProps(this.props);
27115
+ }
27116
+ focus() {}
27010
27117
  render() {
27011
27118
  const type = this.props.plot.type;
27012
27119
  const coords = this.props.plot.coords;
@@ -27061,118 +27168,6 @@ class Grapher extends React__namespace.Component {
27061
27168
  };
27062
27169
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(FunctionGrapher, grapherProps), this.props.availableTypes.length > 1 && typeSelector);
27063
27170
  }
27064
- handlePlotChanges = newPlot => {
27065
- const plot = ___default["default"].extend({}, this.props.plot, newPlot);
27066
- this.props.onChange({
27067
- plot: plot
27068
- });
27069
- this.props.trackInteraction();
27070
- };
27071
- handleActiveTypeChange = newType => {
27072
- const graph = this.props.graph;
27073
- const plot = ___default["default"].extend({}, this.props.plot, defaultPlotProps(newType, graph));
27074
- this.props.onChange({
27075
- plot: plot
27076
- });
27077
- };
27078
- _getGridConfig(options) {
27079
- return options.step.map((step, i) => {
27080
- return Util.gridDimensionConfig(step, options.range[i], options.box[i], options.gridStep[i]);
27081
- });
27082
- }
27083
- _calculateMobileTickStep(gridStep, step, ranges) {
27084
- const tickStep = Util.constrainedTickStepsFromTickSteps(step, ranges);
27085
-
27086
- // According to the graphInit documentation in graphie.js, tickStep is
27087
- // relative to the grid units so we need to adjust all values by the
27088
- // grid step.
27089
- tickStep[0] = tickStep[0] / gridStep[0];
27090
- tickStep[1] = tickStep[1] / gridStep[1];
27091
- return tickStep;
27092
- }
27093
- _setupGraphie = (graphie, options) => {
27094
- const isMobile = this.props.apiOptions.isMobile;
27095
- if (options.markings === "graph") {
27096
- graphie.graphInit({
27097
- range: options.range,
27098
- scale: ___default["default"].pluck(options.gridConfig, "scale"),
27099
- axisArrows: "<->",
27100
- labelFormat: function (s) {
27101
- return "\\small{" + s + "}";
27102
- },
27103
- gridStep: options.gridStep,
27104
- snapStep: options.snapStep,
27105
- tickStep: isMobile ? this._calculateMobileTickStep(options.gridStep, options.step, options.range) : ___default["default"].pluck(options.gridConfig, "tickStep"),
27106
- labelStep: 1,
27107
- unityLabels: ___default["default"].pluck(options.gridConfig, "unityLabel"),
27108
- isMobile: isMobile
27109
- });
27110
- graphie.label([0, options.range[1][1]], options.labels[1], isMobile ? "below right" : "above");
27111
- graphie.label([options.range[0][1], 0], options.labels[0], isMobile ? "above left" : "right");
27112
- } else if (options.markings === "grid") {
27113
- graphie.graphInit({
27114
- range: options.range,
27115
- scale: ___default["default"].pluck(options.gridConfig, "scale"),
27116
- gridStep: options.gridStep,
27117
- axes: false,
27118
- ticks: false,
27119
- labels: false,
27120
- isMobile: isMobile
27121
- });
27122
- } else if (options.markings === "none") {
27123
- graphie.init({
27124
- range: options.range,
27125
- scale: ___default["default"].pluck(options.gridConfig, "scale")
27126
- });
27127
- }
27128
- if (this.props.apiOptions.isMobile) {
27129
- const hairlineStyle = {
27130
- normalStyle: {
27131
- strokeWidth: 1
27132
- }
27133
- };
27134
- this.horizHairline = new WrappedLine(graphie, [0, 0], [0, 0], hairlineStyle);
27135
- this.horizHairline.attr({
27136
- stroke: KhanColors.INTERACTIVE
27137
- });
27138
- this.horizHairline.hide();
27139
- this.vertHairline = new WrappedLine(graphie, [0, 0], [0, 0], hairlineStyle);
27140
- this.vertHairline.attr({
27141
- stroke: KhanColors.INTERACTIVE
27142
- });
27143
- this.vertHairline.hide();
27144
- }
27145
- };
27146
- showHairlines = point => {
27147
- if (this.props.apiOptions.isMobile && this.props.markings !== "none") {
27148
- // Hairlines are already initialized when the graph is loaded, so
27149
- // here we just move them to the updated location and make them
27150
- // visible.
27151
- this.horizHairline.moveTo([this.props.graph.range[0][0], point[1]], [this.props.graph.range[0][1], point[1]]);
27152
- this.horizHairline.show();
27153
- this.vertHairline.moveTo([point[0], this.props.graph.range[1][0]], [point[0], this.props.graph.range[1][1]]);
27154
- this.vertHairline.show();
27155
- }
27156
- };
27157
- hideHairlines = () => {
27158
- if (this.props.apiOptions.isMobile) {
27159
- this.horizHairline.hide();
27160
- this.vertHairline.hide();
27161
- }
27162
- };
27163
- simpleValidate(rubric) {
27164
- return validate$1(this.getUserInput(), rubric);
27165
- }
27166
- getUserInput() {
27167
- return Grapher.getUserInputFromProps(this.props);
27168
- }
27169
- focus() {}
27170
- static validate(state, rubric) {
27171
- return validate$1(state, rubric);
27172
- }
27173
- static getUserInputFromProps(props) {
27174
- return props.plot;
27175
- }
27176
27171
  }
27177
27172
  const propTransform$2 = editorProps => {
27178
27173
  const widgetProps = {
@@ -27355,7 +27350,7 @@ var Group$1 = {
27355
27350
  isLintable: true
27356
27351
  };
27357
27352
 
27358
- /* eslint-disable react/forbid-prop-types, react/sort-comp */
27353
+ /* eslint-disable react/forbid-prop-types */
27359
27354
  const {
27360
27355
  updateQueryString
27361
27356
  } = Util;
@@ -27380,6 +27375,12 @@ class Iframe extends React__namespace.Component {
27380
27375
  allowFullScreen: false,
27381
27376
  allowTopNavigation: false
27382
27377
  };
27378
+ componentDidMount() {
27379
+ $__default["default"](window).on("message", this.handleMessageEvent);
27380
+ }
27381
+ componentWillUnmount() {
27382
+ $__default["default"](window).off("message", this.handleMessageEvent);
27383
+ }
27383
27384
  getUserInput = () => {
27384
27385
  return WidgetJsonifyDeprecated.getUserInput.call(this);
27385
27386
  };
@@ -27402,12 +27403,20 @@ class Iframe extends React__namespace.Component {
27402
27403
  message: data.message
27403
27404
  });
27404
27405
  };
27405
- componentDidMount() {
27406
- $__default["default"](window).on("message", this.handleMessageEvent);
27407
- }
27408
- componentWillUnmount() {
27409
- $__default["default"](window).off("message", this.handleMessageEvent);
27410
- }
27406
+ change = (() => {
27407
+ var _this = this;
27408
+ return function () {
27409
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
27410
+ args[_key] = arguments[_key];
27411
+ }
27412
+ // @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
27413
+ return change.apply(_this, args);
27414
+ };
27415
+ })();
27416
+ simpleValidate = rubric => {
27417
+ // @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Iframe'.
27418
+ return Iframe.validate(this.getUserInput(), rubric);
27419
+ };
27411
27420
  render() {
27412
27421
  const style = {
27413
27422
  width: String(this.props.width),
@@ -27469,20 +27478,6 @@ class Iframe extends React__namespace.Component {
27469
27478
  allowFullScreen: this.props.allowFullScreen
27470
27479
  });
27471
27480
  }
27472
- change = (() => {
27473
- var _this = this;
27474
- return function () {
27475
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
27476
- args[_key] = arguments[_key];
27477
- }
27478
- // @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
27479
- return change.apply(_this, args);
27480
- };
27481
- })();
27482
- simpleValidate = rubric => {
27483
- // @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Iframe'.
27484
- return Iframe.validate(this.getUserInput(), rubric);
27485
- };
27486
27481
  }
27487
27482
 
27488
27483
  /**
@@ -27522,7 +27517,6 @@ var Iframe$1 = {
27522
27517
  hidden: true
27523
27518
  };
27524
27519
 
27525
- /* eslint-disable react/sort-comp */
27526
27520
  const defaultBoxSize = 400;
27527
27521
  const defaultRange = [0, 10];
27528
27522
  const defaultBackgroundImage$2 = {
@@ -27548,6 +27542,14 @@ class ImageWidget extends React__namespace.Component {
27548
27542
  caption: "",
27549
27543
  linterContext: PerseusLinter.linterContextDefault
27550
27544
  };
27545
+ static validate(userInput, rubric) {
27546
+ return {
27547
+ type: "points",
27548
+ earned: 0,
27549
+ total: 0,
27550
+ message: null
27551
+ };
27552
+ }
27551
27553
  change = (() => {
27552
27554
  var _this = this;
27553
27555
  return function () {
@@ -27697,14 +27699,6 @@ class ImageWidget extends React__namespace.Component {
27697
27699
  }
27698
27700
  }, title, image, caption);
27699
27701
  }
27700
- static validate(userInput, rubric) {
27701
- return {
27702
- type: "points",
27703
- earned: 0,
27704
- total: 0,
27705
- message: null
27706
- };
27707
- }
27708
27702
  }
27709
27703
  var Image$1 = {
27710
27704
  name: "image",
@@ -27796,6 +27790,14 @@ class Interaction extends React__namespace.Component {
27796
27790
  },
27797
27791
  elements: []
27798
27792
  };
27793
+ static validate(state, rubric) {
27794
+ return {
27795
+ type: "points",
27796
+ earned: 0,
27797
+ total: 0,
27798
+ message: null
27799
+ };
27800
+ }
27799
27801
  state = {
27800
27802
  variables: _getInitialVariables(this.props.elements),
27801
27803
  functions: _getInitialFunctions(this.props.elements)
@@ -27903,6 +27905,16 @@ class Interaction extends React__namespace.Component {
27903
27905
  return change.apply(_this, args);
27904
27906
  };
27905
27907
  })();
27908
+ getUserInput = () => {
27909
+ // TODO(eater): Perhaps we want to be able to record the state of the
27910
+ // user's interaction. Unfortunately sending all the props will
27911
+ // probably make the attempt payload too large. So for now, don't send
27912
+ // anything.
27913
+ return {};
27914
+ };
27915
+ simpleValidate = rubric => {
27916
+ return Interaction.validate(this.getUserInput(), rubric);
27917
+ };
27906
27918
  render() {
27907
27919
  const range = this.props.graph.range;
27908
27920
  let labels = this.props.graph.labels;
@@ -28230,24 +28242,6 @@ class Interaction extends React__namespace.Component {
28230
28242
  }
28231
28243
  }, this));
28232
28244
  }
28233
- getUserInput = () => {
28234
- // TODO(eater): Perhaps we want to be able to record the state of the
28235
- // user's interaction. Unfortunately sending all the props will
28236
- // probably make the attempt payload too large. So for now, don't send
28237
- // anything.
28238
- return {};
28239
- };
28240
- simpleValidate = rubric => {
28241
- return Interaction.validate(this.getUserInput(), rubric);
28242
- };
28243
- static validate(state, rubric) {
28244
- return {
28245
- type: "points",
28246
- earned: 0,
28247
- total: 0,
28248
- message: null
28249
- };
28250
- }
28251
28245
  }
28252
28246
  const _getInitialVariables = elements => {
28253
28247
  const variables = {};
@@ -29756,44 +29750,6 @@ class NumberInput extends React__namespace.Component {
29756
29750
  state = {
29757
29751
  format: this.props.format
29758
29752
  };
29759
- render() {
29760
- let classes = classNames__default["default"]({
29761
- "number-input": true,
29762
- "invalid-input": !this._checkValidity(this.props.value),
29763
- mini: this.props.size === "mini",
29764
- small: this.props.size === "small",
29765
- normal: this.props.size === "normal"
29766
- });
29767
- if (this.props.className != null) {
29768
- classes = classes + " " + this.props.className;
29769
- }
29770
- const {
29771
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
29772
- onFormatChange,
29773
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
29774
- checkValidity,
29775
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
29776
- useArrowKeys,
29777
- ...restProps
29778
- } = this.props;
29779
- return /*#__PURE__*/React__namespace.createElement("input", _extends({}, restProps, {
29780
- className: classes,
29781
- type: "text"
29782
- // eslint-disable-next-line react/no-string-refs
29783
- ,
29784
- ref: "input",
29785
- onChange: this._handleChange,
29786
- onFocus: this._handleFocus,
29787
- onBlur: this._handleBlur,
29788
- onKeyPress: this._handleBlur,
29789
- onKeyDown: this._onKeyDown
29790
- // @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
29791
- ,
29792
- onTouchStart: captureScratchpadTouchStart,
29793
- defaultValue: toNumericString(this.props.value, this.state.format),
29794
- value: undefined
29795
- }));
29796
- }
29797
29753
  componentDidUpdate(prevProps) {
29798
29754
  if (!kmath.number.equal(this.getValue(), this.props.value)) {
29799
29755
  this._setValue(this.props.value, this.state.format);
@@ -29910,6 +29866,44 @@ class NumberInput extends React__namespace.Component {
29910
29866
  // @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
29911
29867
  $__default["default"](ReactDOM__default["default"].findDOMNode(this.refs.input)).val(toNumericString(val, format));
29912
29868
  };
29869
+ render() {
29870
+ let classes = classNames__default["default"]({
29871
+ "number-input": true,
29872
+ "invalid-input": !this._checkValidity(this.props.value),
29873
+ mini: this.props.size === "mini",
29874
+ small: this.props.size === "small",
29875
+ normal: this.props.size === "normal"
29876
+ });
29877
+ if (this.props.className != null) {
29878
+ classes = classes + " " + this.props.className;
29879
+ }
29880
+ const {
29881
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
29882
+ onFormatChange,
29883
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
29884
+ checkValidity,
29885
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
29886
+ useArrowKeys,
29887
+ ...restProps
29888
+ } = this.props;
29889
+ return /*#__PURE__*/React__namespace.createElement("input", _extends({}, restProps, {
29890
+ className: classes,
29891
+ type: "text"
29892
+ // eslint-disable-next-line react/no-string-refs
29893
+ ,
29894
+ ref: "input",
29895
+ onChange: this._handleChange,
29896
+ onFocus: this._handleFocus,
29897
+ onBlur: this._handleBlur,
29898
+ onKeyPress: this._handleBlur,
29899
+ onKeyDown: this._onKeyDown
29900
+ // @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
29901
+ ,
29902
+ onTouchStart: captureScratchpadTouchStart,
29903
+ defaultValue: toNumericString(this.props.value, this.state.format),
29904
+ value: undefined
29905
+ }));
29906
+ }
29913
29907
  }
29914
29908
 
29915
29909
  const truth = () => true;
@@ -29927,6 +29921,14 @@ class RangeInput extends React__namespace.Component {
29927
29921
  static defaultProps = {
29928
29922
  placeholder: [null, null]
29929
29923
  };
29924
+ onChange = (i, newVal) => {
29925
+ const value = this.props.value;
29926
+ if (i === 0) {
29927
+ this.props.onChange([newVal, value[1]]);
29928
+ } else {
29929
+ this.props.onChange([value[0], newVal]);
29930
+ }
29931
+ };
29930
29932
  render() {
29931
29933
  const value = this.props.value;
29932
29934
  const checkValidity = this.props.checkValidity || truth;
@@ -29948,14 +29950,6 @@ class RangeInput extends React__namespace.Component {
29948
29950
  placeholder: this.props.placeholder[1]
29949
29951
  })));
29950
29952
  }
29951
- onChange = (i, newVal) => {
29952
- const value = this.props.value;
29953
- if (i === 0) {
29954
- this.props.onChange([newVal, value[1]]);
29955
- } else {
29956
- this.props.onChange([value[0], newVal]);
29957
- }
29958
- };
29959
29953
  }
29960
29954
 
29961
29955
  var components = /*#__PURE__*/Object.freeze({
@@ -30119,12 +30113,6 @@ const ItemExtras = [
30119
30113
 
30120
30114
  // prettier-ignore
30121
30115
 
30122
- // prettier-ignore
30123
-
30124
- // prettier-ignore
30125
-
30126
- // prettier-ignore
30127
-
30128
30116
  //prettier-ignore
30129
30117
 
30130
30118
  // A background image applied to various widgets.
@@ -30525,6 +30513,9 @@ const GraphLockedLayer = props => {
30525
30513
  };
30526
30514
 
30527
30515
  const actions = {
30516
+ global: {
30517
+ deleteIntent
30518
+ },
30528
30519
  angle: {
30529
30520
  movePoint
30530
30521
  },
@@ -30543,7 +30534,9 @@ const actions = {
30543
30534
  pointGraph: {
30544
30535
  movePoint,
30545
30536
  addPoint,
30546
- removePoint
30537
+ removePoint,
30538
+ focusPoint,
30539
+ blurPoint
30547
30540
  },
30548
30541
  polygon: {
30549
30542
  movePoint,
@@ -30564,6 +30557,12 @@ const actions = {
30564
30557
  movePoint
30565
30558
  }
30566
30559
  };
30560
+ const DELETE_INTENT = "delete-intent";
30561
+ function deleteIntent() {
30562
+ return {
30563
+ type: DELETE_INTENT
30564
+ };
30565
+ }
30567
30566
  const MOVE_LINE = "move-line";
30568
30567
  function moveLine(itemIndex, delta) {
30569
30568
  return {
@@ -30586,6 +30585,19 @@ function removePoint(index) {
30586
30585
  index
30587
30586
  };
30588
30587
  }
30588
+ const FOCUS_POINT = "focus-point";
30589
+ function focusPoint(index) {
30590
+ return {
30591
+ type: FOCUS_POINT,
30592
+ index
30593
+ };
30594
+ }
30595
+ const BLUR_POINT = "blur-point";
30596
+ function blurPoint() {
30597
+ return {
30598
+ type: BLUR_POINT
30599
+ };
30600
+ }
30589
30601
  const MOVE_ALL = "move-all";
30590
30602
  function moveAll(delta) {
30591
30603
  return {
@@ -32199,7 +32211,14 @@ function UnlimitedPointGraph(props) {
32199
32211
  }), props.graphState.coords.map((point, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
32200
32212
  key: i,
32201
32213
  point: point,
32202
- onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
32214
+ onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination)),
32215
+ onFocusChange: isFocused => {
32216
+ if (isFocused) {
32217
+ dispatch(actions.pointGraph.focusPoint(i));
32218
+ } else {
32219
+ dispatch(actions.pointGraph.blurPoint());
32220
+ }
32221
+ }
32203
32222
  })));
32204
32223
  }
32205
32224
  function PointGraph(props) {
@@ -32355,6 +32374,7 @@ const MafsGraph = props => {
32355
32374
  } = props;
32356
32375
  const [width, height] = props.box;
32357
32376
  const tickStep = props.step;
32377
+ const graphRef = React__namespace.useRef(null);
32358
32378
  return /*#__PURE__*/React__namespace.createElement(GraphConfigContext.Provider, {
32359
32379
  value: {
32360
32380
  range: state.range,
@@ -32372,16 +32392,24 @@ const MafsGraph = props => {
32372
32392
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
32373
32393
  className: "mafs-graph",
32374
32394
  style: {
32375
- height,
32376
- width: "intrinsic",
32377
32395
  position: "relative",
32378
32396
  padding: "25px 25px 0 0",
32379
32397
  boxSizing: "content-box",
32380
32398
  marginLeft: "20px",
32381
32399
  marginBottom: "20px",
32382
32400
  pointerEvents: props.static ? "none" : "auto",
32383
- userSelect: "none"
32384
- }
32401
+ userSelect: "none",
32402
+ width,
32403
+ height
32404
+ },
32405
+ onKeyUp: event => {
32406
+ if (event.key === "Backspace") {
32407
+ dispatch(actions.global.deleteIntent());
32408
+ graphRef.current?.focus();
32409
+ }
32410
+ },
32411
+ ref: graphRef,
32412
+ tabIndex: 0
32385
32413
  }, /*#__PURE__*/React__namespace.createElement(LegacyGrid, {
32386
32414
  box: props.box,
32387
32415
  backgroundImage: props.backgroundImage
@@ -32567,7 +32595,8 @@ function initializeGraphState(params) {
32567
32595
  ...shared,
32568
32596
  type: graph.type,
32569
32597
  coords: getPointCoords(graph, range, step),
32570
- numPoints: graph.numPoints || 0
32598
+ numPoints: graph.numPoints || 0,
32599
+ focusedPointIndex: null
32571
32600
  };
32572
32601
  case "circle":
32573
32602
  return {
@@ -32827,10 +32856,49 @@ function interactiveGraphReducer(state, action) {
32827
32856
  return doAddPoint(state, action);
32828
32857
  case REMOVE_POINT:
32829
32858
  return doRemovePoint(state, action);
32859
+ case FOCUS_POINT:
32860
+ return doFocusPoint(state, action);
32861
+ case BLUR_POINT:
32862
+ return doBlurPoint(state);
32863
+ case DELETE_INTENT:
32864
+ return doDeleteIntent(state);
32830
32865
  default:
32831
32866
  throw new wonderStuffCore.UnreachableCaseError(action);
32832
32867
  }
32833
32868
  }
32869
+ function doDeleteIntent(state, action) {
32870
+ // For unlimited point graphs
32871
+ if (state.type === "point" && state.numPoints === "unlimited") {
32872
+ // if there's a focused point
32873
+ if (state.focusedPointIndex !== null) {
32874
+ // Remove the focused focus
32875
+ return doRemovePoint(state, actions.pointGraph.removePoint(state.focusedPointIndex));
32876
+ }
32877
+ }
32878
+ return state;
32879
+ }
32880
+ function doFocusPoint(state, action) {
32881
+ switch (state.type) {
32882
+ case "point":
32883
+ return {
32884
+ ...state,
32885
+ focusedPointIndex: action.index
32886
+ };
32887
+ default:
32888
+ return state;
32889
+ }
32890
+ }
32891
+ function doBlurPoint(state, action) {
32892
+ switch (state.type) {
32893
+ case "point":
32894
+ return {
32895
+ ...state,
32896
+ focusedPointIndex: null
32897
+ };
32898
+ default:
32899
+ return state;
32900
+ }
32901
+ }
32834
32902
  function doMovePointInFigure(state, action) {
32835
32903
  switch (state.type) {
32836
32904
  case "segment":
@@ -33196,7 +33264,8 @@ function doRemovePoint(state, action) {
33196
33264
  }
33197
33265
  return {
33198
33266
  ...state,
33199
- coords: state.coords.filter((_, i) => i !== action.index)
33267
+ coords: state.coords.filter((_, i) => i !== action.index),
33268
+ focusedPointIndex: null
33200
33269
  };
33201
33270
  }
33202
33271
  const getDeltaVertex = (maxMoves, minMoves, delta) => {
@@ -37552,73 +37621,6 @@ class Draggable extends React__namespace.Component {
37552
37621
  passive: false
37553
37622
  } : false);
37554
37623
  }
37555
- componentWillUnmount() {
37556
- this._mounted = false;
37557
- // Event handlers should be unbound before component unmounting, but
37558
- // just in case...
37559
- if (this.isMouseMoveUpBound) {
37560
- this.unbindMouseMoveUp();
37561
- }
37562
- if (this.animationFrameRequest) {
37563
- // TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
37564
- // eslint-disable-next-line no-restricted-syntax
37565
- cancelAnimationFrame(this.animationFrameRequest);
37566
- }
37567
- document.removeEventListener("touchmove", this.onMouseMove);
37568
- }
37569
- getCurrentPosition = () => {
37570
- return {
37571
- left: this.state.startPosition.left + this.state.mouse.left - this.state.startMouse.left,
37572
- top: this.state.startPosition.top + this.state.mouse.top - this.state.startMouse.top
37573
- };
37574
- };
37575
- render() {
37576
- const {
37577
- includePadding,
37578
- layout,
37579
- state: type
37580
- } = this.props;
37581
-
37582
- // We need to keep backwards compatbility with rules specified directly
37583
- // in CSS. Hence the hacky tacking on of manual classNames.
37584
- // See sortable.less for details.
37585
- let className = aphrodite.css(styles$d.card, styles$d.draggable, layout === Layout.HORIZONTAL && styles$d.horizontalCard, layout === Layout.VERTICAL && styles$d.verticalCard, type === ItemState.DRAGGING && styles$d.dragging, type === ItemState.DISABLED && styles$d.disabled, !includePadding && styles$d.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
37586
- if (!includePadding) {
37587
- className += " perseus-sortable-draggable-unpadded";
37588
- }
37589
- const style = {
37590
- position: "static"
37591
- };
37592
- if (this.props.state === ItemState.DRAGGING || this.props.state === ItemState.ANIMATING) {
37593
- ___default["default"].extend(style, {
37594
- position: "absolute"
37595
- }, this.getCurrentPosition());
37596
- }
37597
- if (this.props.width) {
37598
- style.width = this.props.width + 1; // Fix for non-integer widths
37599
- }
37600
-
37601
- if (this.props.height) {
37602
- style.height = this.props.height;
37603
- }
37604
- if (this.props.margin != null) {
37605
- style.margin = this.props.margin;
37606
- }
37607
- return /*#__PURE__*/React__namespace.createElement("li", {
37608
- className: className,
37609
- style: style,
37610
- onMouseDown: this.onMouseDown,
37611
- onTouchStart: this.onMouseDown,
37612
- onTouchMove: this.onMouseMove,
37613
- onTouchEnd: this.onMouseUp,
37614
- onTouchCancel: this.onMouseUp
37615
- }, /*#__PURE__*/React__namespace.createElement(Renderer, {
37616
- content: this.props.content,
37617
- linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "draggable"),
37618
- onRender: this.props.onRender,
37619
- strings: this.context.strings
37620
- }));
37621
- }
37622
37624
  componentDidUpdate(prevProps) {
37623
37625
  if (this.props.state === prevProps.state) {
37624
37626
  return;
@@ -37640,6 +37642,26 @@ class Draggable extends React__namespace.Component {
37640
37642
  $__default["default"](ReactDOM__default["default"].findDOMNode(this)).finish();
37641
37643
  }
37642
37644
  }
37645
+ componentWillUnmount() {
37646
+ this._mounted = false;
37647
+ // Event handlers should be unbound before component unmounting, but
37648
+ // just in case...
37649
+ if (this.isMouseMoveUpBound) {
37650
+ this.unbindMouseMoveUp();
37651
+ }
37652
+ if (this.animationFrameRequest) {
37653
+ // TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
37654
+ // eslint-disable-next-line no-restricted-syntax
37655
+ cancelAnimationFrame(this.animationFrameRequest);
37656
+ }
37657
+ document.removeEventListener("touchmove", this.onMouseMove);
37658
+ }
37659
+ getCurrentPosition = () => {
37660
+ return {
37661
+ left: this.state.startPosition.left + this.state.mouse.left - this.state.startMouse.left,
37662
+ top: this.state.startPosition.top + this.state.mouse.top - this.state.startMouse.top
37663
+ };
37664
+ };
37643
37665
  bindMouseMoveUp = () => {
37644
37666
  this.isMouseMoveUpBound = true;
37645
37667
  $__default["default"](document).on("mousemove", this.onMouseMove);
@@ -37727,6 +37749,53 @@ class Draggable extends React__namespace.Component {
37727
37749
  this.props.onMouseUp();
37728
37750
  }
37729
37751
  };
37752
+ render() {
37753
+ const {
37754
+ includePadding,
37755
+ layout,
37756
+ state: type
37757
+ } = this.props;
37758
+
37759
+ // We need to keep backwards compatbility with rules specified directly
37760
+ // in CSS. Hence the hacky tacking on of manual classNames.
37761
+ // See sortable.less for details.
37762
+ let className = aphrodite.css(styles$d.card, styles$d.draggable, layout === Layout.HORIZONTAL && styles$d.horizontalCard, layout === Layout.VERTICAL && styles$d.verticalCard, type === ItemState.DRAGGING && styles$d.dragging, type === ItemState.DISABLED && styles$d.disabled, !includePadding && styles$d.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
37763
+ if (!includePadding) {
37764
+ className += " perseus-sortable-draggable-unpadded";
37765
+ }
37766
+ const style = {
37767
+ position: "static"
37768
+ };
37769
+ if (this.props.state === ItemState.DRAGGING || this.props.state === ItemState.ANIMATING) {
37770
+ ___default["default"].extend(style, {
37771
+ position: "absolute"
37772
+ }, this.getCurrentPosition());
37773
+ }
37774
+ if (this.props.width) {
37775
+ style.width = this.props.width + 1; // Fix for non-integer widths
37776
+ }
37777
+
37778
+ if (this.props.height) {
37779
+ style.height = this.props.height;
37780
+ }
37781
+ if (this.props.margin != null) {
37782
+ style.margin = this.props.margin;
37783
+ }
37784
+ return /*#__PURE__*/React__namespace.createElement("li", {
37785
+ className: className,
37786
+ style: style,
37787
+ onMouseDown: this.onMouseDown,
37788
+ onTouchStart: this.onMouseDown,
37789
+ onTouchMove: this.onMouseMove,
37790
+ onTouchEnd: this.onMouseUp,
37791
+ onTouchCancel: this.onMouseUp
37792
+ }, /*#__PURE__*/React__namespace.createElement(Renderer, {
37793
+ content: this.props.content,
37794
+ linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "draggable"),
37795
+ onRender: this.props.onRender,
37796
+ strings: this.context.strings
37797
+ }));
37798
+ }
37730
37799
  }
37731
37800
  class Sortable extends React__namespace.Component {
37732
37801
  static defaultProps = {
@@ -37740,6 +37809,33 @@ class Sortable extends React__namespace.Component {
37740
37809
  linterContext: PerseusLinter__namespace.linterContextDefault,
37741
37810
  waitForTexRendererToLoad: true
37742
37811
  };
37812
+ remeasureItems = ___default["default"].debounce(() => {
37813
+ this.setState({
37814
+ // Clear item measurements
37815
+ items: Sortable.clearItemMeasurements(this.state.items)
37816
+ });
37817
+ }, 20);
37818
+ static itemsFromProps(props) {
37819
+ const state = props.disabled ? ItemState.DISABLED : ItemState.STATIC;
37820
+ return props.options.map((option, i) => {
37821
+ return {
37822
+ option: option,
37823
+ key: i,
37824
+ state,
37825
+ width: 0,
37826
+ height: 0
37827
+ };
37828
+ });
37829
+ }
37830
+ static clearItemMeasurements(items) {
37831
+ return items.map(item => {
37832
+ return {
37833
+ ...item,
37834
+ width: 0,
37835
+ height: 0
37836
+ };
37837
+ });
37838
+ }
37743
37839
  constructor(props) {
37744
37840
  super(props);
37745
37841
  // Don't call this.setState() here!
@@ -37773,27 +37869,6 @@ class Sortable extends React__namespace.Component {
37773
37869
  }, 0);
37774
37870
  }
37775
37871
  }
37776
- static itemsFromProps(props) {
37777
- const state = props.disabled ? ItemState.DISABLED : ItemState.STATIC;
37778
- return props.options.map((option, i) => {
37779
- return {
37780
- option: option,
37781
- key: i,
37782
- state,
37783
- width: 0,
37784
- height: 0
37785
- };
37786
- });
37787
- }
37788
- static clearItemMeasurements(items) {
37789
- return items.map(item => {
37790
- return {
37791
- ...item,
37792
- width: 0,
37793
- height: 0
37794
- };
37795
- });
37796
- }
37797
37872
  measureItems() {
37798
37873
  // Measure all items and cache what their dimensions should be, taking
37799
37874
  // into account constraints and the current layout. This allows syncing
@@ -37845,129 +37920,6 @@ class Sortable extends React__namespace.Component {
37845
37920
  });
37846
37921
  });
37847
37922
  }
37848
- remeasureItems = ___default["default"].debounce(() => {
37849
- this.setState({
37850
- // Clear item measurements
37851
- items: Sortable.clearItemMeasurements(this.state.items)
37852
- });
37853
- }, 20);
37854
- render() {
37855
- // To minimize layout shift, we display a spinner until our math
37856
- // renderer is ready to render the math inside the sortable. To
37857
- // do this, we:
37858
- // - render a dummy TeX component to force the math renderer to load
37859
- // - display a spinner until the TeX component calls its onRender
37860
- // callback, signifying that the math is rendered (from which we can
37861
- // infer that the math renderer has loaded)
37862
- //
37863
- // If we didn't do this, the user might see a sortable with empty
37864
- // cells on first render, and then the math would pop in a few moments
37865
- // later once the rendering library loaded.
37866
- if (this.props.waitForTexRendererToLoad && !this.state.texRendererLoaded) {
37867
- const {
37868
- TeX
37869
- } = getDependencies();
37870
- return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksProgressSpinner.CircularSpinner, null), /*#__PURE__*/React__namespace.createElement("div", {
37871
- style: {
37872
- display: "none"
37873
- }
37874
- }, /*#__PURE__*/React__namespace.createElement(TeX, {
37875
- onRender: () => this.setState({
37876
- texRendererLoaded: true
37877
- })
37878
- }, "1")));
37879
- }
37880
- const cards = [];
37881
- const {
37882
- layout
37883
- } = this.props;
37884
- // We need to keep backwards compatbility with rules specified directly
37885
- // in CSS. See sortable.less for details.
37886
- const className = aphrodite.css(styles$d.sortable) + " perseus-sortable";
37887
- const syncWidth = this.props.constraints?.width || layout === Layout.VERTICAL;
37888
- const syncHeight = this.props.constraints?.height || layout === Layout.HORIZONTAL;
37889
- ___default["default"].each(this.state.items, function (item, i, items) {
37890
- const isLast = i === items.length - 1;
37891
- const isStatic = item.state === ItemState.STATIC || item.state === ItemState.DISABLED;
37892
- let margin;
37893
-
37894
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37895
- if (this.props.layout === Layout.HORIZONTAL) {
37896
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37897
- margin = "0 " + this.props.margin + "px 0 0"; // right
37898
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37899
- } else if (this.props.layout === Layout.VERTICAL) {
37900
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37901
- margin = "0 0 " + this.props.margin + "px 0"; // bottom
37902
- }
37903
-
37904
- cards.push( /*#__PURE__*/React__namespace.createElement(Draggable, {
37905
- content: item.option,
37906
- key: item.key,
37907
- state: item.state
37908
- // @ts-expect-error - TS2769 - No overload matches this call.
37909
- ,
37910
- ref: item.key,
37911
- width: syncWidth ? item.width : undefined,
37912
- height: syncHeight ? item.height : undefined,
37913
- layout: layout
37914
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37915
- ,
37916
- includePadding: this.props.padding,
37917
- margin: isLast && isStatic ? 0 : margin,
37918
- endPosition: item.endPosition,
37919
- linterContext: PerseusLinter__namespace.pushContextStack(
37920
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37921
- this.props.linterContext, "sortable")
37922
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37923
- ,
37924
- onRender: this.remeasureItems
37925
- // eslint-disable-next-line react/jsx-no-bind
37926
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37927
- ,
37928
- onMouseDown: this.onMouseDown.bind(this, item.key)
37929
- // eslint-disable-next-line react/jsx-no-bind
37930
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37931
- ,
37932
- onMouseMove: this.onMouseMove.bind(this, item.key)
37933
- // eslint-disable-next-line react/jsx-no-bind
37934
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37935
- ,
37936
- onMouseUp: this.onMouseUp.bind(this, item.key)
37937
- // eslint-disable-next-line react/jsx-no-bind
37938
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37939
- ,
37940
- onTouchMove: this.onMouseMove.bind(this, item.key)
37941
- // eslint-disable-next-line react/jsx-no-bind
37942
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37943
- ,
37944
- onTouchEnd: this.onMouseUp.bind(this, item.key)
37945
- // eslint-disable-next-line react/jsx-no-bind
37946
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37947
- ,
37948
- onTouchCancel: this.onMouseUp.bind(this, item.key)
37949
- // eslint-disable-next-line react/jsx-no-bind
37950
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37951
- ,
37952
- onAnimationEnd: this.onAnimationEnd.bind(
37953
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37954
- this, item.key)
37955
- }));
37956
- if (item.state === ItemState.DRAGGING || item.state === ItemState.ANIMATING) {
37957
- cards.push( /*#__PURE__*/React__namespace.createElement(Placeholder, {
37958
- key: "placeholder_" + item.key,
37959
- ref: "placeholder_" + item.key,
37960
- width: item.width,
37961
- height: item.height,
37962
- layout: layout,
37963
- margin: isLast ? 0 : margin
37964
- }));
37965
- }
37966
- }, this);
37967
- return /*#__PURE__*/React__namespace.createElement("ul", {
37968
- className: className
37969
- }, cards);
37970
- }
37971
37923
  onMouseDown(key) {
37972
37924
  // Static -> Dragging
37973
37925
  const items = ___default["default"].map(this.state.items, function (item) {
@@ -38113,6 +38065,123 @@ class Sortable extends React__namespace.Component {
38113
38065
  getOptions() {
38114
38066
  return ___default["default"].pluck(this.state.items, "option");
38115
38067
  }
38068
+ render() {
38069
+ // To minimize layout shift, we display a spinner until our math
38070
+ // renderer is ready to render the math inside the sortable. To
38071
+ // do this, we:
38072
+ // - render a dummy TeX component to force the math renderer to load
38073
+ // - display a spinner until the TeX component calls its onRender
38074
+ // callback, signifying that the math is rendered (from which we can
38075
+ // infer that the math renderer has loaded)
38076
+ //
38077
+ // If we didn't do this, the user might see a sortable with empty
38078
+ // cells on first render, and then the math would pop in a few moments
38079
+ // later once the rendering library loaded.
38080
+ if (this.props.waitForTexRendererToLoad && !this.state.texRendererLoaded) {
38081
+ const {
38082
+ TeX
38083
+ } = getDependencies();
38084
+ return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksProgressSpinner.CircularSpinner, null), /*#__PURE__*/React__namespace.createElement("div", {
38085
+ style: {
38086
+ display: "none"
38087
+ }
38088
+ }, /*#__PURE__*/React__namespace.createElement(TeX, {
38089
+ onRender: () => this.setState({
38090
+ texRendererLoaded: true
38091
+ })
38092
+ }, "1")));
38093
+ }
38094
+ const cards = [];
38095
+ const {
38096
+ layout
38097
+ } = this.props;
38098
+ // We need to keep backwards compatbility with rules specified directly
38099
+ // in CSS. See sortable.less for details.
38100
+ const className = aphrodite.css(styles$d.sortable) + " perseus-sortable";
38101
+ const syncWidth = this.props.constraints?.width || layout === Layout.VERTICAL;
38102
+ const syncHeight = this.props.constraints?.height || layout === Layout.HORIZONTAL;
38103
+ ___default["default"].each(this.state.items, function (item, i, items) {
38104
+ const isLast = i === items.length - 1;
38105
+ const isStatic = item.state === ItemState.STATIC || item.state === ItemState.DISABLED;
38106
+ let margin;
38107
+
38108
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38109
+ if (this.props.layout === Layout.HORIZONTAL) {
38110
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38111
+ margin = "0 " + this.props.margin + "px 0 0"; // right
38112
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38113
+ } else if (this.props.layout === Layout.VERTICAL) {
38114
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38115
+ margin = "0 0 " + this.props.margin + "px 0"; // bottom
38116
+ }
38117
+
38118
+ cards.push( /*#__PURE__*/React__namespace.createElement(Draggable, {
38119
+ content: item.option,
38120
+ key: item.key,
38121
+ state: item.state
38122
+ // @ts-expect-error - TS2769 - No overload matches this call.
38123
+ ,
38124
+ ref: item.key,
38125
+ width: syncWidth ? item.width : undefined,
38126
+ height: syncHeight ? item.height : undefined,
38127
+ layout: layout
38128
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38129
+ ,
38130
+ includePadding: this.props.padding,
38131
+ margin: isLast && isStatic ? 0 : margin,
38132
+ endPosition: item.endPosition,
38133
+ linterContext: PerseusLinter__namespace.pushContextStack(
38134
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38135
+ this.props.linterContext, "sortable")
38136
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38137
+ ,
38138
+ onRender: this.remeasureItems
38139
+ // eslint-disable-next-line react/jsx-no-bind
38140
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38141
+ ,
38142
+ onMouseDown: this.onMouseDown.bind(this, item.key)
38143
+ // eslint-disable-next-line react/jsx-no-bind
38144
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38145
+ ,
38146
+ onMouseMove: this.onMouseMove.bind(this, item.key)
38147
+ // eslint-disable-next-line react/jsx-no-bind
38148
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38149
+ ,
38150
+ onMouseUp: this.onMouseUp.bind(this, item.key)
38151
+ // eslint-disable-next-line react/jsx-no-bind
38152
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38153
+ ,
38154
+ onTouchMove: this.onMouseMove.bind(this, item.key)
38155
+ // eslint-disable-next-line react/jsx-no-bind
38156
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38157
+ ,
38158
+ onTouchEnd: this.onMouseUp.bind(this, item.key)
38159
+ // eslint-disable-next-line react/jsx-no-bind
38160
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38161
+ ,
38162
+ onTouchCancel: this.onMouseUp.bind(this, item.key)
38163
+ // eslint-disable-next-line react/jsx-no-bind
38164
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38165
+ ,
38166
+ onAnimationEnd: this.onAnimationEnd.bind(
38167
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38168
+ this, item.key)
38169
+ }));
38170
+ if (item.state === ItemState.DRAGGING || item.state === ItemState.ANIMATING) {
38171
+ cards.push( /*#__PURE__*/React__namespace.createElement(Placeholder, {
38172
+ key: "placeholder_" + item.key,
38173
+ ref: "placeholder_" + item.key,
38174
+ width: item.width,
38175
+ height: item.height,
38176
+ layout: layout,
38177
+ margin: isLast ? 0 : margin
38178
+ }));
38179
+ }
38180
+ }, this);
38181
+ return /*#__PURE__*/React__namespace.createElement("ul", {
38182
+ className: className
38183
+ }, cards);
38184
+ }
38116
38185
  }
38117
38186
  const styles$d = aphrodite.StyleSheet.create({
38118
38187
  sortable: {
@@ -38198,6 +38267,61 @@ class Matcher extends React__namespace.Component {
38198
38267
  rightHeight: 0,
38199
38268
  texRendererLoaded: false
38200
38269
  };
38270
+ changeAndTrack = e => {
38271
+ this.props.onChange(e);
38272
+ this.props.trackInteraction();
38273
+ };
38274
+ onMeasureLeft = dimensions => {
38275
+ const height = ___default["default"].max(dimensions.heights);
38276
+ this.setState({
38277
+ leftHeight: height
38278
+ });
38279
+ };
38280
+ onMeasureRight = dimensions => {
38281
+ const height = ___default["default"].max(dimensions.heights);
38282
+ this.setState({
38283
+ rightHeight: height
38284
+ });
38285
+ };
38286
+ getUserInput = () => {
38287
+ // If the math renderer hasn't loaded then we won't be able to get the
38288
+ // contents of the sortables on the left and right, so we just return
38289
+ // empty arrays until we render for the first time.
38290
+ if (!this.state.texRendererLoaded) {
38291
+ return {
38292
+ left: [],
38293
+ right: []
38294
+ };
38295
+ }
38296
+ return {
38297
+ // eslint-disable-next-line react/no-string-refs
38298
+ // @ts-expect-error - TS2339 - Property 'getOptions' does not exist on type 'ReactInstance'.
38299
+ left: this.refs.left.getOptions(),
38300
+ // eslint-disable-next-line react/no-string-refs
38301
+ // @ts-expect-error - TS2339 - Property 'getOptions' does not exist on type 'ReactInstance'.
38302
+ right: this.refs.right.getOptions()
38303
+ };
38304
+ };
38305
+
38306
+ // Programatic API for moving options
38307
+ // This is used by testing
38308
+ moveLeftOptionToIndex = (option, index) => {
38309
+ // eslint-disable-next-line react/no-string-refs
38310
+ // @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
38311
+ this.refs.left.moveOptionToIndex(option, index);
38312
+ };
38313
+
38314
+ // Programatic API for moving options
38315
+ // This is used by testing
38316
+ moveRightOptionToIndex = (option, index) => {
38317
+ // eslint-disable-next-line react/no-string-refs
38318
+ // @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
38319
+ this.refs.right.moveOptionToIndex(option, index);
38320
+ };
38321
+ simpleValidate = rubric => {
38322
+ // @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Matcher'.
38323
+ return Matcher.validate(this.getUserInput(), rubric);
38324
+ };
38201
38325
  render() {
38202
38326
  // To minimize layout shift, we display a spinner until our math
38203
38327
  // renderer is ready to render the math inside the matcher. To
@@ -38293,61 +38417,6 @@ class Matcher extends React__namespace.Component {
38293
38417
  ref: "right"
38294
38418
  })))));
38295
38419
  }
38296
- changeAndTrack = e => {
38297
- this.props.onChange(e);
38298
- this.props.trackInteraction();
38299
- };
38300
- onMeasureLeft = dimensions => {
38301
- const height = ___default["default"].max(dimensions.heights);
38302
- this.setState({
38303
- leftHeight: height
38304
- });
38305
- };
38306
- onMeasureRight = dimensions => {
38307
- const height = ___default["default"].max(dimensions.heights);
38308
- this.setState({
38309
- rightHeight: height
38310
- });
38311
- };
38312
- getUserInput = () => {
38313
- // If the math renderer hasn't loaded then we won't be able to get the
38314
- // contents of the sortables on the left and right, so we just return
38315
- // empty arrays until we render for the first time.
38316
- if (!this.state.texRendererLoaded) {
38317
- return {
38318
- left: [],
38319
- right: []
38320
- };
38321
- }
38322
- return {
38323
- // eslint-disable-next-line react/no-string-refs
38324
- // @ts-expect-error - TS2339 - Property 'getOptions' does not exist on type 'ReactInstance'.
38325
- left: this.refs.left.getOptions(),
38326
- // eslint-disable-next-line react/no-string-refs
38327
- // @ts-expect-error - TS2339 - Property 'getOptions' does not exist on type 'ReactInstance'.
38328
- right: this.refs.right.getOptions()
38329
- };
38330
- };
38331
-
38332
- // Programatic API for moving options
38333
- // This is used by testing
38334
- moveLeftOptionToIndex = (option, index) => {
38335
- // eslint-disable-next-line react/no-string-refs
38336
- // @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
38337
- this.refs.left.moveOptionToIndex(option, index);
38338
- };
38339
-
38340
- // Programatic API for moving options
38341
- // This is used by testing
38342
- moveRightOptionToIndex = (option, index) => {
38343
- // eslint-disable-next-line react/no-string-refs
38344
- // @ts-expect-error - TS2339 - Property 'moveOptionToIndex' does not exist on type 'ReactInstance'.
38345
- this.refs.right.moveOptionToIndex(option, index);
38346
- };
38347
- simpleValidate = rubric => {
38348
- // @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Matcher'.
38349
- return Matcher.validate(this.getUserInput(), rubric);
38350
- };
38351
38420
  }
38352
38421
  ___default["default"].extend(Matcher, {
38353
38422
  validate: function (state, rubric) {
@@ -38539,6 +38608,144 @@ class Matrix extends React__namespace.Component {
38539
38608
  // Used in the `onBlur` and `onFocus` handlers
38540
38609
  this.cursorPosition = [0, 0];
38541
38610
  }
38611
+ getInputPaths = () => {
38612
+ const inputPaths = [];
38613
+ const maxRows = this.props.matrixBoardSize[0];
38614
+ const maxCols = this.props.matrixBoardSize[1];
38615
+ ___default["default"](maxRows).times(row => {
38616
+ ___default["default"](maxCols).times(col => {
38617
+ const inputPath = getInputPath$1(row, col);
38618
+ inputPaths.push(inputPath);
38619
+ });
38620
+ });
38621
+ return inputPaths;
38622
+ };
38623
+ getGrammarTypeForPath = inputPath => {
38624
+ return "number";
38625
+ };
38626
+ _handleFocus = (row, col) => {
38627
+ this.props.onFocus(getInputPath$1(row, col));
38628
+ };
38629
+ _handleBlur = (row, col) => {
38630
+ this.props.onBlur(getInputPath$1(row, col));
38631
+ };
38632
+ focus = () => {
38633
+ this.focusInputPath(getDefaultPath$1());
38634
+ return true;
38635
+ };
38636
+ focusInputPath = path => {
38637
+ const inputID = getRefForPath$1(path);
38638
+ // eslint-disable-next-line react/no-string-refs
38639
+ // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
38640
+ this.refs[inputID].focus();
38641
+ };
38642
+ blurInputPath = path => {
38643
+ if (path.length === 0) {
38644
+ path = getDefaultPath$1();
38645
+ }
38646
+ const inputID = getRefForPath$1(path);
38647
+ // eslint-disable-next-line react/no-string-refs
38648
+ // @ts-expect-error - TS2339 - Property 'blur' does not exist on type 'ReactInstance'.
38649
+ this.refs[inputID].blur();
38650
+ };
38651
+ getDOMNodeForPath = inputPath => {
38652
+ const inputID = getRefForPath$1(inputPath);
38653
+ // eslint-disable-next-line react/no-string-refs
38654
+ return ReactDOM__default["default"].findDOMNode(this.refs[inputID]);
38655
+ };
38656
+ setInputValue = (inputPath, value, callback) => {
38657
+ const row = getRowFromPath$1(inputPath);
38658
+ const col = getColumnFromPath$1(inputPath);
38659
+ this.onValueChange(row, col, value, callback);
38660
+ };
38661
+ handleKeyDown = (row, col, e) => {
38662
+ const maxRow = this.props.matrixBoardSize[0];
38663
+ const maxCol = this.props.matrixBoardSize[1];
38664
+ let enterTheMatrix = null;
38665
+
38666
+ // eslint-disable-next-line react/no-string-refs
38667
+ const curInput = this.refs[getRefForPath$1(getInputPath$1(row, col))];
38668
+ // @ts-expect-error - TS2339 - Property 'getStringValue' does not exist on type 'ReactInstance'.
38669
+ const curValueString = curInput.getStringValue();
38670
+ // @ts-expect-error - TS2339 - Property 'getSelectionStart' does not exist on type 'ReactInstance'.
38671
+ const cursorStartPosition = curInput.getSelectionStart();
38672
+ // @ts-expect-error - TS2339 - Property 'getSelectionEnd' does not exist on type 'ReactInstance'.
38673
+ const cursorEndPosition = curInput.getSelectionEnd();
38674
+ let nextPath = null;
38675
+ if (e.key === "ArrowUp" && row > 0) {
38676
+ // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38677
+ nextPath = getInputPath$1(row - 1, col);
38678
+ } else if (e.key === "ArrowDown" && row + 1 < maxRow) {
38679
+ // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38680
+ nextPath = getInputPath$1(row + 1, col);
38681
+ } else if (e.key === "ArrowLeft" && col > 0) {
38682
+ if (cursorStartPosition === 0 && cursorEndPosition === 0) {
38683
+ // Only go to next input if we're at the *start* of the content
38684
+ // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38685
+ nextPath = getInputPath$1(row, col - 1);
38686
+ }
38687
+ } else if (e.key === "ArrowRight" && col + 1 < maxCol) {
38688
+ if (cursorStartPosition === curValueString.length) {
38689
+ // Only go to next input if we're at the *end* of the content
38690
+ // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38691
+ nextPath = getInputPath$1(row, col + 1);
38692
+ }
38693
+ } else if (e.key === "Enter") {
38694
+ // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'null'.
38695
+ enterTheMatrix = this.state.enterTheMatrix + 1;
38696
+ } else if (e.key === "Escape") {
38697
+ // @ts-expect-error - TS2322 - Type '0' is not assignable to type 'null'.
38698
+ enterTheMatrix = 0;
38699
+ }
38700
+ if (nextPath) {
38701
+ // Prevent the cursor from jumping again inside the next input
38702
+ e.preventDefault();
38703
+
38704
+ // Focus the input and move the cursor to the end of it.
38705
+ // eslint-disable-next-line react/no-string-refs
38706
+ const input = this.refs[getRefForPath$1(nextPath)];
38707
+
38708
+ // Multiply by 2 to ensure the cursor always ends up at the end;
38709
+ // Opera sometimes sees a carriage return as 2 characters.
38710
+ // @ts-expect-error - TS2339 - Property 'getStringValue' does not exist on type 'ReactInstance'.
38711
+ const inputValString = input.getStringValue();
38712
+ const valueLength = inputValString.length * 2;
38713
+
38714
+ // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
38715
+ input.focus();
38716
+ if (e.key === "ArrowRight") {
38717
+ // @ts-expect-error - TS2339 - Property 'setSelectionRange' does not exist on type 'ReactInstance'.
38718
+ input.setSelectionRange(0, 0);
38719
+ } else {
38720
+ // @ts-expect-error - TS2339 - Property 'setSelectionRange' does not exist on type 'ReactInstance'.
38721
+ input.setSelectionRange(valueLength, valueLength);
38722
+ }
38723
+ }
38724
+ if (enterTheMatrix != null) {
38725
+ this.setState({
38726
+ enterTheMatrix: enterTheMatrix
38727
+ });
38728
+ }
38729
+ };
38730
+ onValueChange = (row, column, value, cb) => {
38731
+ const answers = this.props.answers.map(answer => [...answer]);
38732
+ if (!answers[row]) {
38733
+ answers[row] = [];
38734
+ }
38735
+ answers[row][column] = value;
38736
+ this.props.onChange({
38737
+ answers
38738
+ }, cb);
38739
+ this.props.trackInteraction();
38740
+ };
38741
+ getUserInput = () => {
38742
+ return {
38743
+ answers: this.props.answers
38744
+ };
38745
+ };
38746
+ simpleValidate = rubric => {
38747
+ return Matrix.validate(this.getUserInput(), rubric, this.context.strings);
38748
+ };
38542
38749
  render() {
38543
38750
  // Set the input sizes through JS so we can control the size of the
38544
38751
  // brackets. (If we set them in CSS we won't know values until the
@@ -38694,144 +38901,6 @@ class Matrix extends React__namespace.Component {
38694
38901
  strings: this.context.strings
38695
38902
  })));
38696
38903
  }
38697
- getInputPaths = () => {
38698
- const inputPaths = [];
38699
- const maxRows = this.props.matrixBoardSize[0];
38700
- const maxCols = this.props.matrixBoardSize[1];
38701
- ___default["default"](maxRows).times(row => {
38702
- ___default["default"](maxCols).times(col => {
38703
- const inputPath = getInputPath$1(row, col);
38704
- inputPaths.push(inputPath);
38705
- });
38706
- });
38707
- return inputPaths;
38708
- };
38709
- getGrammarTypeForPath = inputPath => {
38710
- return "number";
38711
- };
38712
- _handleFocus = (row, col) => {
38713
- this.props.onFocus(getInputPath$1(row, col));
38714
- };
38715
- _handleBlur = (row, col) => {
38716
- this.props.onBlur(getInputPath$1(row, col));
38717
- };
38718
- focus = () => {
38719
- this.focusInputPath(getDefaultPath$1());
38720
- return true;
38721
- };
38722
- focusInputPath = path => {
38723
- const inputID = getRefForPath$1(path);
38724
- // eslint-disable-next-line react/no-string-refs
38725
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
38726
- this.refs[inputID].focus();
38727
- };
38728
- blurInputPath = path => {
38729
- if (path.length === 0) {
38730
- path = getDefaultPath$1();
38731
- }
38732
- const inputID = getRefForPath$1(path);
38733
- // eslint-disable-next-line react/no-string-refs
38734
- // @ts-expect-error - TS2339 - Property 'blur' does not exist on type 'ReactInstance'.
38735
- this.refs[inputID].blur();
38736
- };
38737
- getDOMNodeForPath = inputPath => {
38738
- const inputID = getRefForPath$1(inputPath);
38739
- // eslint-disable-next-line react/no-string-refs
38740
- return ReactDOM__default["default"].findDOMNode(this.refs[inputID]);
38741
- };
38742
- setInputValue = (inputPath, value, callback) => {
38743
- const row = getRowFromPath$1(inputPath);
38744
- const col = getColumnFromPath$1(inputPath);
38745
- this.onValueChange(row, col, value, callback);
38746
- };
38747
- handleKeyDown = (row, col, e) => {
38748
- const maxRow = this.props.matrixBoardSize[0];
38749
- const maxCol = this.props.matrixBoardSize[1];
38750
- let enterTheMatrix = null;
38751
-
38752
- // eslint-disable-next-line react/no-string-refs
38753
- const curInput = this.refs[getRefForPath$1(getInputPath$1(row, col))];
38754
- // @ts-expect-error - TS2339 - Property 'getStringValue' does not exist on type 'ReactInstance'.
38755
- const curValueString = curInput.getStringValue();
38756
- // @ts-expect-error - TS2339 - Property 'getSelectionStart' does not exist on type 'ReactInstance'.
38757
- const cursorStartPosition = curInput.getSelectionStart();
38758
- // @ts-expect-error - TS2339 - Property 'getSelectionEnd' does not exist on type 'ReactInstance'.
38759
- const cursorEndPosition = curInput.getSelectionEnd();
38760
- let nextPath = null;
38761
- if (e.key === "ArrowUp" && row > 0) {
38762
- // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38763
- nextPath = getInputPath$1(row - 1, col);
38764
- } else if (e.key === "ArrowDown" && row + 1 < maxRow) {
38765
- // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38766
- nextPath = getInputPath$1(row + 1, col);
38767
- } else if (e.key === "ArrowLeft" && col > 0) {
38768
- if (cursorStartPosition === 0 && cursorEndPosition === 0) {
38769
- // Only go to next input if we're at the *start* of the content
38770
- // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38771
- nextPath = getInputPath$1(row, col - 1);
38772
- }
38773
- } else if (e.key === "ArrowRight" && col + 1 < maxCol) {
38774
- if (cursorStartPosition === curValueString.length) {
38775
- // Only go to next input if we're at the *end* of the content
38776
- // @ts-expect-error - TS2322 - Type 'readonly string[]' is not assignable to type 'null'.
38777
- nextPath = getInputPath$1(row, col + 1);
38778
- }
38779
- } else if (e.key === "Enter") {
38780
- // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'null'.
38781
- enterTheMatrix = this.state.enterTheMatrix + 1;
38782
- } else if (e.key === "Escape") {
38783
- // @ts-expect-error - TS2322 - Type '0' is not assignable to type 'null'.
38784
- enterTheMatrix = 0;
38785
- }
38786
- if (nextPath) {
38787
- // Prevent the cursor from jumping again inside the next input
38788
- e.preventDefault();
38789
-
38790
- // Focus the input and move the cursor to the end of it.
38791
- // eslint-disable-next-line react/no-string-refs
38792
- const input = this.refs[getRefForPath$1(nextPath)];
38793
-
38794
- // Multiply by 2 to ensure the cursor always ends up at the end;
38795
- // Opera sometimes sees a carriage return as 2 characters.
38796
- // @ts-expect-error - TS2339 - Property 'getStringValue' does not exist on type 'ReactInstance'.
38797
- const inputValString = input.getStringValue();
38798
- const valueLength = inputValString.length * 2;
38799
-
38800
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
38801
- input.focus();
38802
- if (e.key === "ArrowRight") {
38803
- // @ts-expect-error - TS2339 - Property 'setSelectionRange' does not exist on type 'ReactInstance'.
38804
- input.setSelectionRange(0, 0);
38805
- } else {
38806
- // @ts-expect-error - TS2339 - Property 'setSelectionRange' does not exist on type 'ReactInstance'.
38807
- input.setSelectionRange(valueLength, valueLength);
38808
- }
38809
- }
38810
- if (enterTheMatrix != null) {
38811
- this.setState({
38812
- enterTheMatrix: enterTheMatrix
38813
- });
38814
- }
38815
- };
38816
- onValueChange = (row, column, value, cb) => {
38817
- const answers = this.props.answers.map(answer => [...answer]);
38818
- if (!answers[row]) {
38819
- answers[row] = [];
38820
- }
38821
- answers[row][column] = value;
38822
- this.props.onChange({
38823
- answers
38824
- }, cb);
38825
- this.props.trackInteraction();
38826
- };
38827
- getUserInput = () => {
38828
- return {
38829
- answers: this.props.answers
38830
- };
38831
- };
38832
- simpleValidate = rubric => {
38833
- return Matrix.validate(this.getUserInput(), rubric, this.context.strings);
38834
- };
38835
38904
  }
38836
38905
  const propTransform$1 = editorProps => {
38837
38906
  // Remove answers before passing to widget
@@ -38863,7 +38932,7 @@ var Matrix$1 = {
38863
38932
  isLintable: true
38864
38933
  };
38865
38934
 
38866
- /* eslint-disable @babel/no-invalid-this, react/sort-comp */
38935
+ /* eslint-disable @babel/no-invalid-this */
38867
38936
  const defaultImage = {
38868
38937
  url: null,
38869
38938
  top: 0,
@@ -38905,6 +38974,64 @@ const Measurer = createReactClass__default["default"]({
38905
38974
  getInitialState: function () {
38906
38975
  return {};
38907
38976
  },
38977
+ componentDidMount: function () {
38978
+ this.setupGraphie();
38979
+ },
38980
+ componentDidUpdate: function (prevProps) {
38981
+ const shouldSetupGraphie = ___default["default"].any(["box", "showProtractor", "showRuler", "rulerLabel", "rulerTicks", "rulerPixels", "rulerLength"], function (prop) {
38982
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38983
+ return prevProps[prop] !== this.props[prop];
38984
+ }, this);
38985
+ if (shouldSetupGraphie) {
38986
+ this.setupGraphie();
38987
+ }
38988
+ },
38989
+ setupGraphie: function () {
38990
+ // eslint-disable-next-line react/no-string-refs
38991
+ const graphieDiv = ReactDOM__default["default"].findDOMNode(this.refs.graphieDiv);
38992
+ // @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'empty' does not exist on type 'JQueryStatic'.
38993
+ $__default["default"](graphieDiv).empty();
38994
+ // @ts-expect-error - Argument of type 'Element | Text | null' is not assignable to parameter of type 'HTMLElement'.
38995
+ const graphie = this.graphie = GraphUtils.createGraphie(graphieDiv);
38996
+ const scale = [40, 40];
38997
+ const range = [[0, this.props.box[0] / scale[0]], [0, this.props.box[1] / scale[1]]];
38998
+ graphie.init({
38999
+ range: range,
39000
+ scale: scale
39001
+ });
39002
+ graphie.addMouseLayer({
39003
+ allowScratchpad: true,
39004
+ setDrawingAreaAvailable: this.props.apiOptions.setDrawingAreaAvailable
39005
+ });
39006
+ if (this.protractor) {
39007
+ this.protractor.remove();
39008
+ }
39009
+ if (this.props.showProtractor) {
39010
+ // @ts-expect-error - Property 'protractor' does not exist on type 'Graphie'.
39011
+ this.protractor = graphie.protractor([this.props.protractorX, this.props.protractorY]);
39012
+ }
39013
+ if (this.ruler) {
39014
+ this.ruler.remove();
39015
+ }
39016
+ if (this.props.showRuler) {
39017
+ // @ts-expect-error - Property 'ruler' does not exist on type 'Graphie'.
39018
+ this.ruler = graphie.ruler({
39019
+ center: [(range[0][0] + range[0][1]) / 2, (range[1][0] + range[1][1]) / 2],
39020
+ label: this.props.rulerLabel,
39021
+ pixelsPerUnit: this.props.rulerPixels,
39022
+ ticksPerUnit: this.props.rulerTicks,
39023
+ units: this.props.rulerLength
39024
+ });
39025
+ }
39026
+ },
39027
+ getUserInput: function () {
39028
+ return {};
39029
+ },
39030
+ simpleValidate: function (rubric) {
39031
+ // TODO(joel) - I don't understand how this is useful!
39032
+ return Measurer.validate(this.getUserInput(), rubric);
39033
+ },
39034
+ focus: $__default["default"].noop,
38908
39035
  render: function () {
38909
39036
  const image = ___default["default"].extend({}, defaultImage, this.props.image);
38910
39037
 
@@ -38928,65 +39055,7 @@ const Measurer = createReactClass__default["default"]({
38928
39055
  className: "graphie",
38929
39056
  ref: "graphieDiv"
38930
39057
  }));
38931
- },
38932
- componentDidMount: function () {
38933
- this.setupGraphie();
38934
- },
38935
- componentDidUpdate: function (prevProps) {
38936
- const shouldSetupGraphie = ___default["default"].any(["box", "showProtractor", "showRuler", "rulerLabel", "rulerTicks", "rulerPixels", "rulerLength"], function (prop) {
38937
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
38938
- return prevProps[prop] !== this.props[prop];
38939
- }, this);
38940
- if (shouldSetupGraphie) {
38941
- this.setupGraphie();
38942
- }
38943
- },
38944
- setupGraphie: function () {
38945
- // eslint-disable-next-line react/no-string-refs
38946
- const graphieDiv = ReactDOM__default["default"].findDOMNode(this.refs.graphieDiv);
38947
- // @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'empty' does not exist on type 'JQueryStatic'.
38948
- $__default["default"](graphieDiv).empty();
38949
- // @ts-expect-error - Argument of type 'Element | Text | null' is not assignable to parameter of type 'HTMLElement'.
38950
- const graphie = this.graphie = GraphUtils.createGraphie(graphieDiv);
38951
- const scale = [40, 40];
38952
- const range = [[0, this.props.box[0] / scale[0]], [0, this.props.box[1] / scale[1]]];
38953
- graphie.init({
38954
- range: range,
38955
- scale: scale
38956
- });
38957
- graphie.addMouseLayer({
38958
- allowScratchpad: true,
38959
- setDrawingAreaAvailable: this.props.apiOptions.setDrawingAreaAvailable
38960
- });
38961
- if (this.protractor) {
38962
- this.protractor.remove();
38963
- }
38964
- if (this.props.showProtractor) {
38965
- // @ts-expect-error - Property 'protractor' does not exist on type 'Graphie'.
38966
- this.protractor = graphie.protractor([this.props.protractorX, this.props.protractorY]);
38967
- }
38968
- if (this.ruler) {
38969
- this.ruler.remove();
38970
- }
38971
- if (this.props.showRuler) {
38972
- // @ts-expect-error - Property 'ruler' does not exist on type 'Graphie'.
38973
- this.ruler = graphie.ruler({
38974
- center: [(range[0][0] + range[0][1]) / 2, (range[1][0] + range[1][1]) / 2],
38975
- label: this.props.rulerLabel,
38976
- pixelsPerUnit: this.props.rulerPixels,
38977
- ticksPerUnit: this.props.rulerTicks,
38978
- units: this.props.rulerLength
38979
- });
38980
- }
38981
- },
38982
- getUserInput: function () {
38983
- return {};
38984
- },
38985
- simpleValidate: function (rubric) {
38986
- // TODO(joel) - I don't understand how this is useful!
38987
- return Measurer.validate(this.getUserInput(), rubric);
38988
- },
38989
- focus: $__default["default"].noop
39058
+ }
38990
39059
  });
38991
39060
  ___default["default"].extend(Measurer, {
38992
39061
  validate: function (state, rubric) {
@@ -40568,55 +40637,6 @@ class Card extends React__namespace.Component {
40568
40637
  state = {
40569
40638
  dragging: false
40570
40639
  };
40571
- render() {
40572
- let style = {};
40573
- if (this.props.floating) {
40574
- style = {
40575
- position: "absolute",
40576
- left: this.props.startOffset.left,
40577
- top: this.props.startOffset.top
40578
- };
40579
- }
40580
- if (this.props.width) {
40581
- style.width = this.props.width;
40582
- }
40583
- const className = ["card"];
40584
- if (this.props.stack) {
40585
- className.push("stack");
40586
- }
40587
- if (this.props.floating && !this.props.animating) {
40588
- className.push("dragging");
40589
- style.left += this.props.mouse.left - this.props.startMouse.left;
40590
- style.top += this.props.mouse.top - this.props.startMouse.top;
40591
- }
40592
-
40593
- // Pull out the content to get rendered
40594
- const rendererProps = ___default["default"].pick(this.props, "content");
40595
- const onMouseDown = this.props.animating ? $__default["default"].noop : this.onMouseDown;
40596
- return /*#__PURE__*/React__namespace.createElement("div", {
40597
- className: "card-wrap " + ClassNames.INTERACTIVE,
40598
- style: style,
40599
- onMouseDown: onMouseDown,
40600
- onTouchStart: onMouseDown,
40601
- onTouchEnd: this.onMouseUp,
40602
- onTouchCancel: this.onMouseUp
40603
- }, /*#__PURE__*/React__namespace.createElement("div", {
40604
- className: className.join(" ")
40605
- }, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, rendererProps, {
40606
- linterContext: this.props.linterContext,
40607
- strings: this.context.strings
40608
- }))));
40609
- }
40610
- shouldComponentUpdate(nextProps, nextState) {
40611
- // Cards in the bank or drag list don't usually change -- they only
40612
- // reorder themselves -- so we want to skip the update to things a
40613
- // little faster. We also need to re-render if the content changes,
40614
- // which happens only in the editor. (We do want to update the floating
40615
- // card on mouse move to update its position.)
40616
- return this.props.floating || nextProps.floating || this.props.content !== nextProps.content ||
40617
- // TODO(alpert): Remove ref here after fixing facebook/react#1392.
40618
- this.props.fakeRef !== nextProps.fakeRef;
40619
- }
40620
40640
  componentDidMount() {
40621
40641
  this.mouseMoveUpBound = false;
40622
40642
 
@@ -40635,6 +40655,16 @@ class Card extends React__namespace.Component {
40635
40655
  passive: false
40636
40656
  } : false);
40637
40657
  }
40658
+ shouldComponentUpdate(nextProps, nextState) {
40659
+ // Cards in the bank or drag list don't usually change -- they only
40660
+ // reorder themselves -- so we want to skip the update to things a
40661
+ // little faster. We also need to re-render if the content changes,
40662
+ // which happens only in the editor. (We do want to update the floating
40663
+ // card on mouse move to update its position.)
40664
+ return this.props.floating || nextProps.floating || this.props.content !== nextProps.content ||
40665
+ // TODO(alpert): Remove ref here after fixing facebook/react#1392.
40666
+ this.props.fakeRef !== nextProps.fakeRef;
40667
+ }
40638
40668
  componentDidUpdate(prevProps, prevState) {
40639
40669
  if (this.props.animating && !prevProps.animating) {
40640
40670
  // If we just were changed into animating, start the animation.
@@ -40698,6 +40728,45 @@ class Card extends React__namespace.Component {
40698
40728
  this.props.onMouseUp && this.props.onMouseUp(loc);
40699
40729
  }
40700
40730
  };
40731
+ render() {
40732
+ let style = {};
40733
+ if (this.props.floating) {
40734
+ style = {
40735
+ position: "absolute",
40736
+ left: this.props.startOffset.left,
40737
+ top: this.props.startOffset.top
40738
+ };
40739
+ }
40740
+ if (this.props.width) {
40741
+ style.width = this.props.width;
40742
+ }
40743
+ const className = ["card"];
40744
+ if (this.props.stack) {
40745
+ className.push("stack");
40746
+ }
40747
+ if (this.props.floating && !this.props.animating) {
40748
+ className.push("dragging");
40749
+ style.left += this.props.mouse.left - this.props.startMouse.left;
40750
+ style.top += this.props.mouse.top - this.props.startMouse.top;
40751
+ }
40752
+
40753
+ // Pull out the content to get rendered
40754
+ const rendererProps = ___default["default"].pick(this.props, "content");
40755
+ const onMouseDown = this.props.animating ? $__default["default"].noop : this.onMouseDown;
40756
+ return /*#__PURE__*/React__namespace.createElement("div", {
40757
+ className: "card-wrap " + ClassNames.INTERACTIVE,
40758
+ style: style,
40759
+ onMouseDown: onMouseDown,
40760
+ onTouchStart: onMouseDown,
40761
+ onTouchEnd: this.onMouseUp,
40762
+ onTouchCancel: this.onMouseUp
40763
+ }, /*#__PURE__*/React__namespace.createElement("div", {
40764
+ className: className.join(" ")
40765
+ }, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, rendererProps, {
40766
+ linterContext: this.props.linterContext,
40767
+ strings: this.context.strings
40768
+ }))));
40769
+ }
40701
40770
  }
40702
40771
  const NORMAL = "normal",
40703
40772
  HORIZONTAL$1 = "horizontal";
@@ -40730,109 +40799,6 @@ class Orderer extends React__namespace.Component {
40730
40799
  });
40731
40800
  }
40732
40801
  }
40733
- render() {
40734
- // This is the card we are currently dragging
40735
- const dragging = this.state.dragging && /*#__PURE__*/React__namespace.createElement(Card
40736
- // eslint-disable-next-line react/no-string-refs
40737
- , {
40738
- ref: "dragging",
40739
- floating: true,
40740
- content: this.state.dragContent,
40741
- startOffset: this.state.offsetPos,
40742
- startMouse: this.state.grabPos,
40743
- mouse: this.state.mousePos,
40744
- width: this.state.dragWidth,
40745
- onMouseUp: this.onRelease,
40746
- onMouseMove: this.onMouseMove,
40747
- key: this.state.dragKey || "draggingCard",
40748
- linterContext: this.props.linterContext
40749
- });
40750
-
40751
- // This is the card that is currently animating
40752
- const animating = this.state.animating && /*#__PURE__*/React__namespace.createElement(Card, {
40753
- floating: true,
40754
- animating: true,
40755
- content: this.state.dragContent,
40756
- startOffset: this.state.offsetPos,
40757
- width: this.state.dragWidth,
40758
- animateTo: this.state.animateTo,
40759
- onAnimationEnd: this.state.onAnimationEnd,
40760
- key: this.state.dragKey || "draggingCard",
40761
- linterContext: this.props.linterContext
40762
- });
40763
-
40764
- // This is the list of draggable, rearrangable cards
40765
- const sortableCards = ___default["default"].map(this.state.current, function (opt, i) {
40766
- return /*#__PURE__*/React__namespace.createElement(Card, {
40767
- key: `sortableCard${i}`,
40768
- ref: "sortable" + i,
40769
- fakeRef: "sortable" + i,
40770
- floating: false,
40771
- content: opt.content,
40772
- width: opt.width
40773
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
40774
- ,
40775
- linterContext: this.props.linterContext
40776
- // eslint-disable-next-line react/jsx-no-bind
40777
- ,
40778
- onMouseDown:
40779
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
40780
- this.state.animating ? $__default["default"].noop :
40781
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
40782
- this.onClick.bind(null, "current", i)
40783
- });
40784
- }, this);
40785
- if (this.state.placeholderIndex != null) {
40786
- const placeholder = /*#__PURE__*/React__namespace.createElement(PlaceholderCard
40787
- // eslint-disable-next-line react/no-string-refs
40788
- , {
40789
- ref: "placeholder",
40790
- width: this.state.dragWidth,
40791
- height: this.state.dragHeight,
40792
- key: "placeholder"
40793
- });
40794
- sortableCards.splice(this.state.placeholderIndex, 0, placeholder);
40795
- }
40796
- const anySortableCards = sortableCards.length > 0;
40797
- // @ts-expect-error - TS2345 - Argument of type 'false | Element' is not assignable to parameter of type 'Element'.
40798
- sortableCards.push(dragging, animating);
40799
-
40800
- // If there are no cards in the list, then add a "hint" card
40801
- const sortable = /*#__PURE__*/React__namespace.createElement("div", {
40802
- className: "perseus-clearfix draggable-box"
40803
- }, !anySortableCards && /*#__PURE__*/React__namespace.createElement(DragHintCard, null), /*#__PURE__*/React__namespace.createElement("div", {
40804
- ref: "dragList"
40805
- }, sortableCards));
40806
-
40807
- // This is the bank of stacks of cards
40808
- const bank =
40809
- /*#__PURE__*/
40810
- // eslint-disable-next-line react/no-string-refs
40811
- React__namespace.createElement("div", {
40812
- ref: "bank",
40813
- className: "bank perseus-clearfix"
40814
- }, ___default["default"].map(this.props.options, (opt, i) => {
40815
- return /*#__PURE__*/React__namespace.createElement(Card, {
40816
- ref: "bank" + i,
40817
- floating: false,
40818
- content: opt.content,
40819
- stack: true,
40820
- key: i,
40821
- linterContext: this.props.linterContext
40822
- // eslint-disable-next-line react/jsx-no-bind
40823
- ,
40824
- onMouseDown: this.state.animating ? $__default["default"].noop : this.onClick.bind(null, "bank", i),
40825
- onMouseMove: this.onMouseMove,
40826
- onMouseUp: this.onRelease
40827
- });
40828
- }, this));
40829
- return /*#__PURE__*/React__namespace.createElement("div", {
40830
- className: "draggy-boxy-thing orderer " + "height-" + this.props.height + " " + "layout-" + this.props.layout + " " + "above-scratchpad blank-background " + "perseus-clearfix " + ClassNames.INTERACTIVE
40831
- // eslint-disable-next-line react/no-string-refs
40832
- ,
40833
- ref: "orderer"
40834
- }, bank, sortable);
40835
- }
40836
40802
  onClick = (type, index, loc, draggable) => {
40837
40803
  // @ts-expect-error - TS2769 - No overload matches this call.
40838
40804
  const $draggable = $__default["default"](ReactDOM__default["default"].findDOMNode(draggable));
@@ -41069,6 +41035,109 @@ class Orderer extends React__namespace.Component {
41069
41035
  // @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Orderer'.
41070
41036
  return Orderer.validate(this.getUserInput(), rubric);
41071
41037
  };
41038
+ render() {
41039
+ // This is the card we are currently dragging
41040
+ const dragging = this.state.dragging && /*#__PURE__*/React__namespace.createElement(Card
41041
+ // eslint-disable-next-line react/no-string-refs
41042
+ , {
41043
+ ref: "dragging",
41044
+ floating: true,
41045
+ content: this.state.dragContent,
41046
+ startOffset: this.state.offsetPos,
41047
+ startMouse: this.state.grabPos,
41048
+ mouse: this.state.mousePos,
41049
+ width: this.state.dragWidth,
41050
+ onMouseUp: this.onRelease,
41051
+ onMouseMove: this.onMouseMove,
41052
+ key: this.state.dragKey || "draggingCard",
41053
+ linterContext: this.props.linterContext
41054
+ });
41055
+
41056
+ // This is the card that is currently animating
41057
+ const animating = this.state.animating && /*#__PURE__*/React__namespace.createElement(Card, {
41058
+ floating: true,
41059
+ animating: true,
41060
+ content: this.state.dragContent,
41061
+ startOffset: this.state.offsetPos,
41062
+ width: this.state.dragWidth,
41063
+ animateTo: this.state.animateTo,
41064
+ onAnimationEnd: this.state.onAnimationEnd,
41065
+ key: this.state.dragKey || "draggingCard",
41066
+ linterContext: this.props.linterContext
41067
+ });
41068
+
41069
+ // This is the list of draggable, rearrangable cards
41070
+ const sortableCards = ___default["default"].map(this.state.current, function (opt, i) {
41071
+ return /*#__PURE__*/React__namespace.createElement(Card, {
41072
+ key: `sortableCard${i}`,
41073
+ ref: "sortable" + i,
41074
+ fakeRef: "sortable" + i,
41075
+ floating: false,
41076
+ content: opt.content,
41077
+ width: opt.width
41078
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41079
+ ,
41080
+ linterContext: this.props.linterContext
41081
+ // eslint-disable-next-line react/jsx-no-bind
41082
+ ,
41083
+ onMouseDown:
41084
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41085
+ this.state.animating ? $__default["default"].noop :
41086
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41087
+ this.onClick.bind(null, "current", i)
41088
+ });
41089
+ }, this);
41090
+ if (this.state.placeholderIndex != null) {
41091
+ const placeholder = /*#__PURE__*/React__namespace.createElement(PlaceholderCard
41092
+ // eslint-disable-next-line react/no-string-refs
41093
+ , {
41094
+ ref: "placeholder",
41095
+ width: this.state.dragWidth,
41096
+ height: this.state.dragHeight,
41097
+ key: "placeholder"
41098
+ });
41099
+ sortableCards.splice(this.state.placeholderIndex, 0, placeholder);
41100
+ }
41101
+ const anySortableCards = sortableCards.length > 0;
41102
+ // @ts-expect-error - TS2345 - Argument of type 'false | Element' is not assignable to parameter of type 'Element'.
41103
+ sortableCards.push(dragging, animating);
41104
+
41105
+ // If there are no cards in the list, then add a "hint" card
41106
+ const sortable = /*#__PURE__*/React__namespace.createElement("div", {
41107
+ className: "perseus-clearfix draggable-box"
41108
+ }, !anySortableCards && /*#__PURE__*/React__namespace.createElement(DragHintCard, null), /*#__PURE__*/React__namespace.createElement("div", {
41109
+ ref: "dragList"
41110
+ }, sortableCards));
41111
+
41112
+ // This is the bank of stacks of cards
41113
+ const bank =
41114
+ /*#__PURE__*/
41115
+ // eslint-disable-next-line react/no-string-refs
41116
+ React__namespace.createElement("div", {
41117
+ ref: "bank",
41118
+ className: "bank perseus-clearfix"
41119
+ }, ___default["default"].map(this.props.options, (opt, i) => {
41120
+ return /*#__PURE__*/React__namespace.createElement(Card, {
41121
+ ref: "bank" + i,
41122
+ floating: false,
41123
+ content: opt.content,
41124
+ stack: true,
41125
+ key: i,
41126
+ linterContext: this.props.linterContext
41127
+ // eslint-disable-next-line react/jsx-no-bind
41128
+ ,
41129
+ onMouseDown: this.state.animating ? $__default["default"].noop : this.onClick.bind(null, "bank", i),
41130
+ onMouseMove: this.onMouseMove,
41131
+ onMouseUp: this.onRelease
41132
+ });
41133
+ }, this));
41134
+ return /*#__PURE__*/React__namespace.createElement("div", {
41135
+ className: "draggy-boxy-thing orderer " + "height-" + this.props.height + " " + "layout-" + this.props.layout + " " + "above-scratchpad blank-background " + "perseus-clearfix " + ClassNames.INTERACTIVE
41136
+ // eslint-disable-next-line react/no-string-refs
41137
+ ,
41138
+ ref: "orderer"
41139
+ }, bank, sortable);
41140
+ }
41072
41141
  }
41073
41142
  ___default["default"].extend(Orderer, {
41074
41143
  validate: function (state, rubric) {
@@ -41882,8 +41951,6 @@ class HighlightSetRenderer extends React__namespace.PureComponent {
41882
41951
  hoveredHighlightKey: null,
41883
41952
  hoveringTooltipFor: null
41884
41953
  };
41885
-
41886
- // eslint-disable-next-line react/sort-comp
41887
41954
  _highlightRenderers = {};
41888
41955
  componentDidMount() {
41889
41956
  this._updateEditListeners(false, this.props.editable);
@@ -42219,8 +42286,6 @@ class HighlightingUI extends React__namespace.PureComponent {
42219
42286
  */
42220
42287
  class WordIndexer extends React__namespace.PureComponent {
42221
42288
  _container;
42222
- /* eslint-enable react/sort-comp */
42223
-
42224
42289
  componentDidMount() {
42225
42290
  this._sendWordsUpdate();
42226
42291
  }
@@ -42482,7 +42547,6 @@ const styles$8 = aphrodite.StyleSheet.create({
42482
42547
  }
42483
42548
  });
42484
42549
 
42485
- /* eslint-disable react/sort-comp */
42486
42550
  function getInitialParseState() {
42487
42551
  return {
42488
42552
  currentRef: [],
@@ -42497,16 +42561,15 @@ function getInitialParseState() {
42497
42561
  };
42498
42562
  }
42499
42563
  class RefStart extends React__namespace.Component {
42564
+ // @ts-expect-error - TS2322 - Type '() => React.ReactNode' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>>'.
42565
+ getRefContent = () => {
42566
+ return this.props.refContent;
42567
+ };
42500
42568
  render() {
42501
42569
  return /*#__PURE__*/React__namespace.createElement("span", {
42502
42570
  style: REF_STYLE
42503
42571
  }, "_");
42504
42572
  }
42505
-
42506
- // @ts-expect-error - TS2322 - Type '() => React.ReactNode' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>>'.
42507
- getRefContent = () => {
42508
- return this.props.refContent;
42509
- };
42510
42573
  }
42511
42574
  class RefEnd extends React__namespace.Component {
42512
42575
  render() {
@@ -42905,6 +42968,14 @@ class Passage extends React__namespace.Component {
42905
42968
  startLineNumbersAfter: 0,
42906
42969
  stylesAreApplied: false
42907
42970
  };
42971
+ static validate(state, rubric) {
42972
+ return {
42973
+ type: "points",
42974
+ earned: 0,
42975
+ total: 0,
42976
+ message: null
42977
+ };
42978
+ }
42908
42979
  componentDidMount() {
42909
42980
  this._updateState();
42910
42981
 
@@ -43126,17 +43197,6 @@ class Passage extends React__namespace.Component {
43126
43197
  return Passage.validate(this.getUserInput(), rubric);
43127
43198
  }
43128
43199
 
43129
- /* eslint-disable react/sort-comp */
43130
- static validate(state, rubric) {
43131
- return {
43132
- type: "points",
43133
- earned: 0,
43134
- total: 0,
43135
- message: null
43136
- };
43137
- }
43138
- /* eslint-enable react/sort-comp */
43139
-
43140
43200
  /**
43141
43201
  * Rendering
43142
43202
  *
@@ -43375,20 +43435,6 @@ class PhetSimulation extends React__namespace.Component {
43375
43435
  getUserInput() {
43376
43436
  return null;
43377
43437
  }
43378
- change = (() => {
43379
- var _this = this;
43380
- return function () {
43381
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
43382
- args[_key] = arguments[_key];
43383
- }
43384
- // @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
43385
- return change.apply(_this, args);
43386
- };
43387
- })();
43388
- simpleValidate = rubric => {
43389
- // @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof PhetSimulation'.
43390
- return PhetSimulation.validate(this.getUserInput(), rubric);
43391
- };
43392
43438
 
43393
43439
  // kaLocales and PhET locales use different formats and abbreviations.
43394
43440
  // PhET accepts different formats, i.e. kaLocale's hyphens, but it does not accept
@@ -43497,8 +43543,7 @@ class PhetSimulation extends React__namespace.Component {
43497
43543
  title: this.props.description,
43498
43544
  sandbox: sandboxProperties,
43499
43545
  style: {
43500
- minWidth: 400,
43501
- height: 360,
43546
+ height: 225,
43502
43547
  width: "100%",
43503
43548
  borderWidth: 0
43504
43549
  },
@@ -43538,17 +43583,16 @@ const styles$6 = aphrodite.StyleSheet.create({
43538
43583
  borderRadius: borderRadiusLarge,
43539
43584
  borderWidth: 1,
43540
43585
  borderColor: basicBorderColor,
43541
- padding: phoneMargin,
43586
+ padding: wonderBlocksTokens.spacing.medium_16,
43542
43587
  paddingBottom: 0,
43543
- width: 650
43588
+ // Include space for medium_16 padding on each side
43589
+ width: 400 + wonderBlocksTokens.spacing.xLarge_32
43544
43590
  }
43545
43591
  });
43546
43592
  var PhetSimulation$1 = {
43547
43593
  name: "phet-simulation",
43548
43594
  displayName: "PhET Simulation",
43549
43595
  widget: PhetSimulation,
43550
- // Hides widget from content creators until full release
43551
- hidden: true,
43552
43596
  isLintable: true
43553
43597
  };
43554
43598
 
@@ -44605,65 +44649,6 @@ class Table extends React__namespace.Component {
44605
44649
  _getColumns = () => {
44606
44650
  return this.props.answers[0].length;
44607
44651
  };
44608
- render() {
44609
- const rows = this._getRows();
44610
- const columns = this._getColumns();
44611
- const headers = this.props.headers;
44612
- let InputComponent;
44613
- let inputStyle;
44614
- const extraInputProps = {};
44615
- if (this.props.apiOptions.customKeypad) {
44616
- InputComponent = SimpleKeypadInput;
44617
- // NOTE(charlie): This is intended to match the "width: 80px" in
44618
- // input in table.less. Those values should be kept in-sync.
44619
- inputStyle = {
44620
- width: 80
44621
- };
44622
- extraInputProps.keypadElement = this.props.keypadElement;
44623
- } else {
44624
- InputComponent = "input";
44625
- inputStyle = {};
44626
- }
44627
- return /*#__PURE__*/React__namespace.createElement("table", {
44628
- className: "perseus-widget-table-of-values non-markdown"
44629
- }, /*#__PURE__*/React__namespace.createElement("thead", null, /*#__PURE__*/React__namespace.createElement("tr", null, ___default["default"].map(headers, (header, i) => {
44630
- if (this.props.editableHeaders) {
44631
- return /*#__PURE__*/React__namespace.createElement("th", {
44632
- key: i
44633
- }, /*#__PURE__*/React__namespace.createElement(this.props.Editor, {
44634
- ref: "columnHeader" + i,
44635
- apiOptions: this.props.apiOptions,
44636
- content: header,
44637
- widgetEnabled: false,
44638
- onChange: ___default["default"].partial(this.onHeaderChange, i)
44639
- }));
44640
- }
44641
- return /*#__PURE__*/React__namespace.createElement("th", {
44642
- key: i
44643
- }, /*#__PURE__*/React__namespace.createElement(Renderer, {
44644
- content: header,
44645
- linterContext: this.props.linterContext,
44646
- strings: this.context.strings
44647
- }));
44648
- }))), /*#__PURE__*/React__namespace.createElement("tbody", null, ___default["default"](rows).times(r => {
44649
- return /*#__PURE__*/React__namespace.createElement("tr", {
44650
- key: r
44651
- }, ___default["default"](columns).times(c => {
44652
- return /*#__PURE__*/React__namespace.createElement("td", {
44653
- key: c
44654
- }, /*#__PURE__*/React__namespace.createElement(InputComponent, _extends({
44655
- ref: getRefForPath(getInputPath(r, c)),
44656
- type: "text",
44657
- value: this.props.answers[r][c],
44658
- disabled: this.props.apiOptions.readOnly,
44659
- onFocus: ___default["default"].partial(this._handleFocus, getInputPath(r, c)),
44660
- onBlur: ___default["default"].partial(this._handleBlur, getInputPath(r, c)),
44661
- onChange: ___default["default"].partial(this.onValueChange, r, c),
44662
- style: inputStyle
44663
- }, extraInputProps)));
44664
- }));
44665
- })));
44666
- }
44667
44652
  getUserInput = () => {
44668
44653
  return ___default["default"].map(this.props.answers, ___default["default"].clone);
44669
44654
  };
@@ -44755,6 +44740,65 @@ class Table extends React__namespace.Component {
44755
44740
  answers: answers
44756
44741
  }, cb);
44757
44742
  };
44743
+ render() {
44744
+ const rows = this._getRows();
44745
+ const columns = this._getColumns();
44746
+ const headers = this.props.headers;
44747
+ let InputComponent;
44748
+ let inputStyle;
44749
+ const extraInputProps = {};
44750
+ if (this.props.apiOptions.customKeypad) {
44751
+ InputComponent = SimpleKeypadInput;
44752
+ // NOTE(charlie): This is intended to match the "width: 80px" in
44753
+ // input in table.less. Those values should be kept in-sync.
44754
+ inputStyle = {
44755
+ width: 80
44756
+ };
44757
+ extraInputProps.keypadElement = this.props.keypadElement;
44758
+ } else {
44759
+ InputComponent = "input";
44760
+ inputStyle = {};
44761
+ }
44762
+ return /*#__PURE__*/React__namespace.createElement("table", {
44763
+ className: "perseus-widget-table-of-values non-markdown"
44764
+ }, /*#__PURE__*/React__namespace.createElement("thead", null, /*#__PURE__*/React__namespace.createElement("tr", null, ___default["default"].map(headers, (header, i) => {
44765
+ if (this.props.editableHeaders) {
44766
+ return /*#__PURE__*/React__namespace.createElement("th", {
44767
+ key: i
44768
+ }, /*#__PURE__*/React__namespace.createElement(this.props.Editor, {
44769
+ ref: "columnHeader" + i,
44770
+ apiOptions: this.props.apiOptions,
44771
+ content: header,
44772
+ widgetEnabled: false,
44773
+ onChange: ___default["default"].partial(this.onHeaderChange, i)
44774
+ }));
44775
+ }
44776
+ return /*#__PURE__*/React__namespace.createElement("th", {
44777
+ key: i
44778
+ }, /*#__PURE__*/React__namespace.createElement(Renderer, {
44779
+ content: header,
44780
+ linterContext: this.props.linterContext,
44781
+ strings: this.context.strings
44782
+ }));
44783
+ }))), /*#__PURE__*/React__namespace.createElement("tbody", null, ___default["default"](rows).times(r => {
44784
+ return /*#__PURE__*/React__namespace.createElement("tr", {
44785
+ key: r
44786
+ }, ___default["default"](columns).times(c => {
44787
+ return /*#__PURE__*/React__namespace.createElement("td", {
44788
+ key: c
44789
+ }, /*#__PURE__*/React__namespace.createElement(InputComponent, _extends({
44790
+ ref: getRefForPath(getInputPath(r, c)),
44791
+ type: "text",
44792
+ value: this.props.answers[r][c],
44793
+ disabled: this.props.apiOptions.readOnly,
44794
+ onFocus: ___default["default"].partial(this._handleFocus, getInputPath(r, c)),
44795
+ onBlur: ___default["default"].partial(this._handleBlur, getInputPath(r, c)),
44796
+ onChange: ___default["default"].partial(this.onValueChange, r, c),
44797
+ style: inputStyle
44798
+ }, extraInputProps)));
44799
+ }));
44800
+ })));
44801
+ }
44758
44802
  }
44759
44803
  ___default["default"].extend(Table, {
44760
44804
  validate: function (state, rubric, strings) {
@@ -45053,7 +45097,7 @@ const init = function (options) {
45053
45097
 
45054
45098
  // This file is processed by a Rollup plugin (replace) to inject the production
45055
45099
  const libName = "@khanacademy/perseus";
45056
- const libVersion = "31.1.0";
45100
+ const libVersion = "32.0.0";
45057
45101
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
45058
45102
 
45059
45103
  const apiVersion = {
@@ -46865,8 +46909,6 @@ class MultiRenderer extends React__namespace.Component {
46865
46909
  // Keep state in sync with props.
46866
46910
  this.state = this._tryMakeRendererState(this.props);
46867
46911
  }
46868
- /* eslint-enable react/sort-comp */
46869
-
46870
46912
  UNSAFE_componentWillReceiveProps(nextProps) {
46871
46913
  // Keep state in sync with props.
46872
46914
  if (nextProps.item !== this.props.item) {
@@ -48748,6 +48790,7 @@ exports.itemVersion = ItemVersion;
48748
48790
  exports.libVersion = libVersion;
48749
48791
  exports.lockedFigureColors = lockedFigureColors;
48750
48792
  exports.lockedFigureFillStyles = lockedFigureFillStyles;
48793
+ exports.makeSafeUrl = makeSafeUrl;
48751
48794
  exports.mediaQueries = mediaQueries;
48752
48795
  exports.parsePerseusItem = parsePerseusItem;
48753
48796
  exports.plotterPlotTypes = plotterPlotTypes;