@khanacademy/perseus 31.1.0 → 32.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) 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 +570 -562
  8. package/dist/es/index.js.map +1 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +1370 -1370
  11. package/dist/index.js.map +1 -1
  12. package/dist/perseus-types.d.ts +1 -10
  13. package/dist/util.d.ts +0 -1
  14. package/dist/widget-container.d.ts +1 -1
  15. package/dist/widgets/__shared__/test-keypad-context-wrapper.d.ts +6 -0
  16. package/dist/widgets/{categorizer.d.ts → categorizer/categorizer.d.ts} +14 -14
  17. package/dist/widgets/categorizer/index.d.ts +1 -0
  18. package/dist/widgets/{cs-program.d.ts → cs-program/cs-program.d.ts} +7 -7
  19. package/dist/widgets/cs-program/index.d.ts +1 -0
  20. package/dist/widgets/{definition.d.ts → definition/definition.d.ts} +11 -11
  21. package/dist/widgets/definition/index.d.ts +1 -0
  22. package/dist/widgets/{dropdown.d.ts → dropdown/dropdown.d.ts} +9 -9
  23. package/dist/widgets/dropdown/index.d.ts +1 -0
  24. package/dist/widgets/{explanation.d.ts → explanation/explanation.d.ts} +14 -14
  25. package/dist/widgets/explanation/index.d.ts +1 -0
  26. package/dist/widgets/{expression.d.ts → expression/expression.d.ts} +66 -66
  27. package/dist/widgets/expression/index.d.ts +1 -0
  28. package/dist/widgets/{graded-group-answer-bar.d.ts → graded-group/graded-group-answer-bar.d.ts} +3 -3
  29. package/dist/widgets/{graded-group.d.ts → graded-group/graded-group.d.ts} +11 -11
  30. package/dist/widgets/graded-group/index.d.ts +1 -0
  31. package/dist/widgets/{graded-group-set.d.ts → graded-group-set/graded-group-set.d.ts} +11 -11
  32. package/dist/widgets/graded-group-set/index.d.ts +1 -0
  33. package/dist/widgets/{grapher.d.ts → grapher/grapher.d.ts} +15 -15
  34. package/dist/widgets/grapher/index.d.ts +1 -0
  35. package/dist/widgets/{group.d.ts → group/group.d.ts} +12 -12
  36. package/dist/widgets/group/index.d.ts +1 -0
  37. package/dist/widgets/{iframe.d.ts → iframe/iframe.d.ts} +10 -10
  38. package/dist/widgets/iframe/index.d.ts +1 -0
  39. package/dist/widgets/{image.d.ts → image/image.d.ts} +12 -12
  40. package/dist/widgets/image/index.d.ts +1 -0
  41. package/dist/widgets/input-number/index.d.ts +1 -0
  42. package/dist/widgets/{input-number.d.ts → input-number/input-number.d.ts} +19 -19
  43. package/dist/widgets/interaction/index.d.ts +1 -0
  44. package/dist/widgets/{interaction.d.ts → interaction/interaction.d.ts} +12 -12
  45. package/dist/widgets/interactive-graph.d.ts +0 -2
  46. package/dist/widgets/interactive-graphs/reducer/interactive-graph-action.d.ts +22 -1
  47. package/dist/widgets/interactive-graphs/types.d.ts +1 -0
  48. package/dist/widgets/label-image/index.d.ts +1 -0
  49. package/dist/widgets/{label-image.d.ts → label-image/label-image.d.ts} +24 -24
  50. package/dist/widgets/matcher/index.d.ts +1 -0
  51. package/dist/widgets/{matcher.d.ts → matcher/matcher.d.ts} +11 -11
  52. package/dist/widgets/matrix/index.d.ts +1 -0
  53. package/dist/widgets/{matrix.d.ts → matrix/matrix.d.ts} +12 -12
  54. package/dist/widgets/measurer/index.d.ts +1 -0
  55. package/dist/widgets/measurer/measurer.d.ts +21 -0
  56. package/dist/widgets/molecule/index.d.ts +1 -0
  57. package/dist/widgets/{molecule.d.ts → molecule/molecule.d.ts} +10 -10
  58. package/dist/widgets/number-line/index.d.ts +1 -0
  59. package/dist/widgets/{number-line.d.ts → number-line/number-line.d.ts} +11 -11
  60. package/dist/widgets/numeric-input/index.d.ts +1 -0
  61. package/dist/widgets/{numeric-input.d.ts → numeric-input/numeric-input.d.ts} +13 -13
  62. package/dist/widgets/orderer/index.d.ts +1 -0
  63. package/dist/widgets/{orderer.d.ts → orderer/orderer.d.ts} +10 -10
  64. package/dist/widgets/passage/index.d.ts +2 -0
  65. package/dist/widgets/{passage.d.ts → passage/passage.d.ts} +15 -15
  66. package/dist/widgets/passage-ref/index.d.ts +1 -0
  67. package/dist/widgets/{passage-ref.d.ts → passage-ref/passage-ref.d.ts} +16 -16
  68. package/dist/widgets/passage-ref-target/index.d.ts +1 -0
  69. package/dist/widgets/{passage-ref-target.d.ts → passage-ref-target/passage-ref-target.d.ts} +12 -12
  70. package/dist/widgets/phet-simulation/index.d.ts +1 -0
  71. package/dist/widgets/{phet-simulation.d.ts → phet-simulation/phet-simulation.d.ts} +11 -13
  72. package/dist/widgets/plotter/index.d.ts +1 -0
  73. package/dist/widgets/{plotter.d.ts → plotter/plotter.d.ts} +11 -11
  74. package/dist/widgets/python-program/index.d.ts +1 -0
  75. package/dist/widgets/{python-program.d.ts → python-program/python-program.d.ts} +7 -7
  76. package/dist/widgets/radio/index.d.ts +2 -0
  77. package/dist/widgets/radio/radio-component.d.ts +66 -0
  78. package/dist/widgets/radio/radio.d.ts +22 -66
  79. package/dist/widgets/sorter/index.d.ts +1 -0
  80. package/dist/widgets/{sorter.d.ts → sorter/sorter.d.ts} +8 -8
  81. package/dist/widgets/table/index.d.ts +1 -0
  82. package/dist/widgets/{table.d.ts → table/table.d.ts} +10 -10
  83. package/dist/widgets/video/index.d.ts +1 -0
  84. package/dist/widgets/{video.d.ts → video/video.d.ts} +11 -11
  85. package/package.json +1 -1
  86. package/dist/widgets/measurer.d.ts +0 -21
  87. package/dist/widgets/radio.d.ts +0 -22
  88. /package/dist/widgets/{video-transcript-link.d.ts → video/video-transcript-link.d.ts} +0 -0
package/dist/es/index.js CHANGED
@@ -3161,45 +3161,6 @@ function constrainedTickStepsFromTickSteps(tickSteps, ranges) {
3161
3161
  return [constrainTickStep(tickSteps[0], ranges[0]), constrainTickStep(tickSteps[1], ranges[1])];
3162
3162
  }
3163
3163
 
3164
- /**
3165
- * Transparently update deprecated props so that the code to deal
3166
- * with them only lives in one place: (Widget).deprecatedProps
3167
- *
3168
- * For example, if a boolean `foo` was deprecated in favor of a
3169
- * number 'bar':
3170
- * deprecatedProps: {
3171
- * foo: function(props) {
3172
- * return {bar: props.foo ? 1 : 0};
3173
- * }
3174
- * }
3175
- */
3176
- const DeprecationMixin$1 = {
3177
- // This lifecycle stage is only called before first render
3178
- // TODO(jangmi, CP-3288): Remove usage of `UNSAFE_componentWillMount`
3179
- UNSAFE_componentWillMount: function () {
3180
- const newProps = {};
3181
- _.each(this.deprecatedProps, function (func, prop) {
3182
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
3183
- if (_.has(this.props, prop)) {
3184
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
3185
- _.extend(newProps, func(this.props));
3186
- }
3187
- }, this);
3188
- if (!_.isEmpty(newProps)) {
3189
- // Set new props directly so that widget renders correctly
3190
- // when it first mounts, even though these will be overwritten
3191
- // almost immediately afterwards...
3192
- _.extend(this.props, newProps);
3193
-
3194
- // ...when we propagate the new props upwards and they come
3195
- // back down again.
3196
- // TODO(jeff, CP-3128): Use Wonder Blocks Timing API
3197
- // eslint-disable-next-line no-restricted-syntax
3198
- setTimeout(this.props.onChange, 0, newProps);
3199
- }
3200
- }
3201
- };
3202
-
3203
3164
  /**
3204
3165
  * Approximate equality on numbers and primitives.
3205
3166
  */
@@ -3547,7 +3508,6 @@ const Util = {
3547
3508
  gridStepFromTickStep,
3548
3509
  tickStepFromNumTicks,
3549
3510
  constrainedTickStepsFromTickSteps,
3550
- DeprecationMixin: DeprecationMixin$1,
3551
3511
  eq: eq$3,
3552
3512
  deepEq: deepEq$5,
3553
3513
  parseQueryString,
@@ -19467,6 +19427,14 @@ class WidgetContainer extends React.Component {
19467
19427
  }
19468
19428
  }
19469
19429
 
19430
+ UNSAFE_componentWillReceiveProps(nextProps) {
19431
+ if (this.props.type !== nextProps.type) {
19432
+ throw new Error("WidgetContainer can't change widget type; set a different " + "key instead to recreate the container.");
19433
+ }
19434
+ }
19435
+ shouldComponentUpdate(nextProps, nextState) {
19436
+ return this.props.shouldHighlight !== nextProps.shouldHighlight || this.props.type !== nextProps.type || this.state.widgetProps !== nextState.widgetProps || this.state.sizeClass !== nextState.sizeClass;
19437
+ }
19470
19438
  render() {
19471
19439
  let className = classNames({
19472
19440
  "perseus-widget-container": true,
@@ -19557,14 +19525,6 @@ class WidgetContainer extends React.Component {
19557
19525
  style: staticOverlayStyles
19558
19526
  }))));
19559
19527
  }
19560
- UNSAFE_componentWillReceiveProps(nextProps) {
19561
- if (this.props.type !== nextProps.type) {
19562
- throw new Error("WidgetContainer can't change widget type; set a different " + "key instead to recreate the container.");
19563
- }
19564
- }
19565
- shouldComponentUpdate(nextProps, nextState) {
19566
- return this.props.shouldHighlight !== nextProps.shouldHighlight || this.props.type !== nextProps.type || this.state.widgetProps !== nextState.widgetProps || this.state.sizeClass !== nextState.sizeClass;
19567
- }
19568
19528
  }
19569
19529
  WidgetContainer.defaultProps = {
19570
19530
  linterContext: linterContextDefault
@@ -21325,7 +21285,6 @@ Tooltip.defaultProps = {
21325
21285
  targetContainerStyle: {}
21326
21286
  };
21327
21287
 
21328
- /* eslint-disable react/sort-comp */
21329
21288
  const {
21330
21289
  captureScratchpadTouchStart: captureScratchpadTouchStart$2
21331
21290
  } = Util;
@@ -21681,7 +21640,6 @@ var TexWrangler = {
21681
21640
  modifyTex
21682
21641
  };
21683
21642
 
21684
- /* eslint-disable react/sort-comp */
21685
21643
  const ParseTex$1 = TexWrangler.parseTex;
21686
21644
  const answerTypes = {
21687
21645
  number: {
@@ -21819,55 +21777,6 @@ class InputNumber extends React.Component {
21819
21777
  return [strings.yourAnswer].concat(examples);
21820
21778
  };
21821
21779
  }
21822
- render() {
21823
- if (this.props.apiOptions.customKeypad) {
21824
- // TODO(charlie): Support "Review Mode".
21825
- const input = /*#__PURE__*/React.createElement(SimpleKeypadInput
21826
- // eslint-disable-next-line react/no-string-refs
21827
- , {
21828
- ref: "input",
21829
- value: this.props.currentValue,
21830
- keypadElement: this.props.keypadElement,
21831
- onChange: this.handleChange,
21832
- onFocus: this._handleFocus,
21833
- onBlur: this._handleBlur
21834
- });
21835
- if (this.props.rightAlign) {
21836
- return /*#__PURE__*/React.createElement("div", {
21837
- className: "perseus-input-right-align"
21838
- }, input);
21839
- }
21840
- return input;
21841
- }
21842
- // HACK(johnsullivan): Create a function with shared logic between
21843
- // this and NumericInput.
21844
- // TODO(jeremy): Deprecate this widget and prefer numeric-input.
21845
- const rubric = this.props.reviewModeRubric;
21846
-
21847
- // Note: This is _very_ similar to what `numeric-input.jsx` does. If
21848
- // you modify this, double-check if you also need to modify that
21849
- // component.
21850
- const inputStyles = [styles$A.default, this.props.size === "small" ? styles$A.small : null, this.props.rightAlign ? styles$A.rightAlign : styles$A.leftAlign];
21851
- // Unanswered
21852
- if (rubric && !this.props.currentValue) {
21853
- inputStyles.push(styles$A.answerStateUnanswered);
21854
- }
21855
- return /*#__PURE__*/React.createElement(InputWithExamples
21856
- // eslint-disable-next-line react/no-string-refs
21857
- , {
21858
- ref: "input",
21859
- value: this.props.currentValue,
21860
- onChange: this.handleChange,
21861
- style: inputStyles,
21862
- examples: this.examples(),
21863
- shouldShowExamples: this.shouldShowExamples(),
21864
- onFocus: this._handleFocus,
21865
- onBlur: this._handleBlur,
21866
- id: this.props.widgetId,
21867
- disabled: this.props.apiOptions.readOnly,
21868
- linterContext: this.props.linterContext
21869
- });
21870
- }
21871
21780
  static validate(state, rubric, strings, onInputError = () => {}) {
21872
21781
  if (rubric.answerType == null) {
21873
21782
  rubric.answerType = "number";
@@ -21923,6 +21832,55 @@ class InputNumber extends React.Component {
21923
21832
  }
21924
21833
  return answerString;
21925
21834
  }
21835
+ render() {
21836
+ if (this.props.apiOptions.customKeypad) {
21837
+ // TODO(charlie): Support "Review Mode".
21838
+ const input = /*#__PURE__*/React.createElement(SimpleKeypadInput
21839
+ // eslint-disable-next-line react/no-string-refs
21840
+ , {
21841
+ ref: "input",
21842
+ value: this.props.currentValue,
21843
+ keypadElement: this.props.keypadElement,
21844
+ onChange: this.handleChange,
21845
+ onFocus: this._handleFocus,
21846
+ onBlur: this._handleBlur
21847
+ });
21848
+ if (this.props.rightAlign) {
21849
+ return /*#__PURE__*/React.createElement("div", {
21850
+ className: "perseus-input-right-align"
21851
+ }, input);
21852
+ }
21853
+ return input;
21854
+ }
21855
+ // HACK(johnsullivan): Create a function with shared logic between
21856
+ // this and NumericInput.
21857
+ // TODO(jeremy): Deprecate this widget and prefer numeric-input.
21858
+ const rubric = this.props.reviewModeRubric;
21859
+
21860
+ // Note: This is _very_ similar to what `numeric-input.jsx` does. If
21861
+ // you modify this, double-check if you also need to modify that
21862
+ // component.
21863
+ const inputStyles = [styles$A.default, this.props.size === "small" ? styles$A.small : null, this.props.rightAlign ? styles$A.rightAlign : styles$A.leftAlign];
21864
+ // Unanswered
21865
+ if (rubric && !this.props.currentValue) {
21866
+ inputStyles.push(styles$A.answerStateUnanswered);
21867
+ }
21868
+ return /*#__PURE__*/React.createElement(InputWithExamples
21869
+ // eslint-disable-next-line react/no-string-refs
21870
+ , {
21871
+ ref: "input",
21872
+ value: this.props.currentValue,
21873
+ onChange: this.handleChange,
21874
+ style: inputStyles,
21875
+ examples: this.examples(),
21876
+ shouldShowExamples: this.shouldShowExamples(),
21877
+ onFocus: this._handleFocus,
21878
+ onBlur: this._handleBlur,
21879
+ id: this.props.widgetId,
21880
+ disabled: this.props.apiOptions.readOnly,
21881
+ linterContext: this.props.linterContext
21882
+ });
21883
+ }
21926
21884
  }
21927
21885
  InputNumber.contextType = PerseusI18nContext;
21928
21886
  InputNumber.defaultProps = {
@@ -22384,7 +22342,6 @@ var NumericInput$1 = {
22384
22342
  isLintable: true
22385
22343
  };
22386
22344
 
22387
- /* eslint-disable react/sort-comp */
22388
22345
  const EN_DASH$1 = "\u2013";
22389
22346
  class PassageRef extends React.Component {
22390
22347
  constructor(..._args) {
@@ -22436,9 +22393,32 @@ class PassageRef extends React.Component {
22436
22393
  return PassageRef.validate(this.getUserInput(), rubric);
22437
22394
  };
22438
22395
  }
22396
+ static validate(userInput, rubric) {
22397
+ return {
22398
+ type: "points",
22399
+ earned: 0,
22400
+ total: 0,
22401
+ message: null
22402
+ };
22403
+ }
22404
+ componentDidMount() {
22405
+ // TODO(scottgrant): This is a hack to remove the deprecated call to
22406
+ // this.isMounted() but is still considered an anti-pattern.
22407
+ this._isMounted = true;
22408
+ this._deferredUpdateRange();
22409
+ this._throttledUpdateRange = _.throttle(this._deferredUpdateRange, 500);
22410
+ window.addEventListener("resize", this._throttledUpdateRange);
22411
+ }
22439
22412
  shouldComponentUpdate(nextProps, nextState) {
22440
22413
  return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
22441
22414
  }
22415
+ componentDidUpdate() {
22416
+ this._deferredUpdateRange();
22417
+ }
22418
+ componentWillUnmount() {
22419
+ window.removeEventListener("resize", this._throttledUpdateRange);
22420
+ this._isMounted = false;
22421
+ }
22442
22422
  render() {
22443
22423
  const {
22444
22424
  strings
@@ -22472,29 +22452,6 @@ class PassageRef extends React.Component {
22472
22452
  className: "perseus-sr-only"
22473
22453
  }, this.state.content));
22474
22454
  }
22475
- componentDidMount() {
22476
- // TODO(scottgrant): This is a hack to remove the deprecated call to
22477
- // this.isMounted() but is still considered an anti-pattern.
22478
- this._isMounted = true;
22479
- this._deferredUpdateRange();
22480
- this._throttledUpdateRange = _.throttle(this._deferredUpdateRange, 500);
22481
- window.addEventListener("resize", this._throttledUpdateRange);
22482
- }
22483
- componentDidUpdate() {
22484
- this._deferredUpdateRange();
22485
- }
22486
- componentWillUnmount() {
22487
- window.removeEventListener("resize", this._throttledUpdateRange);
22488
- this._isMounted = false;
22489
- }
22490
- static validate(userInput, rubric) {
22491
- return {
22492
- type: "points",
22493
- earned: 0,
22494
- total: 0,
22495
- message: null
22496
- };
22497
- }
22498
22455
  }
22499
22456
  PassageRef.contextType = PerseusI18nContext;
22500
22457
  PassageRef.defaultProps = {
@@ -24434,89 +24391,6 @@ class Categorizer extends React.Component {
24434
24391
  return Categorizer.validate(this.getUserInput(), rubric, this.context.strings);
24435
24392
  };
24436
24393
  }
24437
- render() {
24438
- const self = this;
24439
-
24440
- // In this context, isMobile is used to differentiate mobile from
24441
- // desktop.
24442
- const isMobile = this.props.apiOptions.isMobile;
24443
- let indexedItems = this.props.items.map((item, n) => [item, n]);
24444
- if (this.props.randomizeItems) {
24445
- // @ts-expect-error - TS4104 - The type 'readonly (string | number)[][]' is 'readonly' and cannot be assigned to the mutable type '(string | number)[][]'. | TS2345 - Argument of type 'number | null | undefined' is not assignable to parameter of type 'number | RNG'.
24446
- indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
24447
- }
24448
- const table = /*#__PURE__*/React.createElement("table", {
24449
- className: "categorizer-table " + css(styles$s.mobileTable)
24450
- }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
24451
- className: css(styles$s.emptyHeaderCell)
24452
- }), this.props.categories.map((category, i) => {
24453
- // Array index is the correct key here, as that's
24454
- // how category grading actually works -- no way
24455
- // to add or remove categories or items in the
24456
- // middle. (If we later add that, this should be
24457
- // fixed.)
24458
- return /*#__PURE__*/React.createElement("th", {
24459
- className: css(styles$s.header),
24460
- key: i
24461
- }, /*#__PURE__*/React.createElement(Renderer, {
24462
- content: category,
24463
- linterContext: this.props.linterContext,
24464
- strings: this.context.strings
24465
- }));
24466
- }))), /*#__PURE__*/React.createElement("tbody", null, indexedItems.map(indexedItem => {
24467
- const item = indexedItem[0];
24468
- const itemNum = indexedItem[1];
24469
- const uniqueId = self.state.uniqueId + "_" + itemNum;
24470
- return /*#__PURE__*/React.createElement("tr", {
24471
- key: itemNum
24472
- }, /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Renderer
24473
- // @ts-expect-error - TS2322 - Type 'string | number' is not assignable to type 'string | undefined'.
24474
- , {
24475
- content: item,
24476
- linterContext: this.props.linterContext,
24477
- strings: this.context.strings
24478
- })), self.props.categories.map((catName, catNum) => {
24479
- const selected = self.props.values[itemNum] === catNum;
24480
- return /*#__PURE__*/React.createElement("td", {
24481
- className: "category " + css(styles$s.cell),
24482
- key: catNum
24483
- }, /*#__PURE__*/React.createElement("div", {
24484
- className: ClassNames.INTERACTIVE,
24485
- role: "button",
24486
- "aria-label": catName,
24487
- onClick: () => this.onChange(itemNum, catNum)
24488
- }, isMobile && /*#__PURE__*/React.createElement("input", {
24489
- type: "radio",
24490
- name: uniqueId,
24491
- className: css(sharedStyles.responsiveInput, sharedStyles.responsiveRadioInput),
24492
- checked: selected,
24493
- onChange: () => this.onChange(itemNum, catNum),
24494
- onClick: e => e.stopPropagation()
24495
- }), !isMobile && /*#__PURE__*/React.createElement("span", {
24496
- className: css(styles$s.radioSpan, selected && styles$s.checkedRadioSpan, this.props.static && selected && styles$s.staticCheckedRadioSpan)
24497
- }, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
24498
- }));
24499
- /* eslint-enable max-len */
24500
- })));
24501
-
24502
- // TODO(benkomalo): kill CSS-based styling and move everything to
24503
- // aphrodite.
24504
- const extraClassNames = classNames({
24505
- "categorizer-container": true,
24506
- "static-mode": this.props.static
24507
- });
24508
- const inlineStyles = this.props.apiOptions.isMobile ? [styles$s.fullBleedContainer] : [];
24509
- return /*#__PURE__*/React.createElement("div", {
24510
- className: extraClassNames + " " + css(...inlineStyles)
24511
- }, table);
24512
- }
24513
- onChange(itemNum, catNum) {
24514
- const values = [...this.props.values];
24515
- // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'.
24516
- values[itemNum] = catNum;
24517
- this.change("values", values);
24518
- this.props.trackInteraction();
24519
- }
24520
24394
  static validate(userInput, rubric, strings) {
24521
24395
  let completed = true;
24522
24396
  let allCorrect = true;
@@ -24544,6 +24418,89 @@ class Categorizer extends React.Component {
24544
24418
  static getUserInputFromProps(props) {
24545
24419
  return WidgetJsonifyDeprecated.getUserInputFromProps(props);
24546
24420
  }
24421
+ onChange(itemNum, catNum) {
24422
+ const values = [...this.props.values];
24423
+ // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'.
24424
+ values[itemNum] = catNum;
24425
+ this.change("values", values);
24426
+ this.props.trackInteraction();
24427
+ }
24428
+ render() {
24429
+ const self = this;
24430
+
24431
+ // In this context, isMobile is used to differentiate mobile from
24432
+ // desktop.
24433
+ const isMobile = this.props.apiOptions.isMobile;
24434
+ let indexedItems = this.props.items.map((item, n) => [item, n]);
24435
+ if (this.props.randomizeItems) {
24436
+ // @ts-expect-error - TS4104 - The type 'readonly (string | number)[][]' is 'readonly' and cannot be assigned to the mutable type '(string | number)[][]'. | TS2345 - Argument of type 'number | null | undefined' is not assignable to parameter of type 'number | RNG'.
24437
+ indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
24438
+ }
24439
+ const table = /*#__PURE__*/React.createElement("table", {
24440
+ className: "categorizer-table " + css(styles$s.mobileTable)
24441
+ }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
24442
+ className: css(styles$s.emptyHeaderCell)
24443
+ }), this.props.categories.map((category, i) => {
24444
+ // Array index is the correct key here, as that's
24445
+ // how category grading actually works -- no way
24446
+ // to add or remove categories or items in the
24447
+ // middle. (If we later add that, this should be
24448
+ // fixed.)
24449
+ return /*#__PURE__*/React.createElement("th", {
24450
+ className: css(styles$s.header),
24451
+ key: i
24452
+ }, /*#__PURE__*/React.createElement(Renderer, {
24453
+ content: category,
24454
+ linterContext: this.props.linterContext,
24455
+ strings: this.context.strings
24456
+ }));
24457
+ }))), /*#__PURE__*/React.createElement("tbody", null, indexedItems.map(indexedItem => {
24458
+ const item = indexedItem[0];
24459
+ const itemNum = indexedItem[1];
24460
+ const uniqueId = self.state.uniqueId + "_" + itemNum;
24461
+ return /*#__PURE__*/React.createElement("tr", {
24462
+ key: itemNum
24463
+ }, /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Renderer
24464
+ // @ts-expect-error - TS2322 - Type 'string | number' is not assignable to type 'string | undefined'.
24465
+ , {
24466
+ content: item,
24467
+ linterContext: this.props.linterContext,
24468
+ strings: this.context.strings
24469
+ })), self.props.categories.map((catName, catNum) => {
24470
+ const selected = self.props.values[itemNum] === catNum;
24471
+ return /*#__PURE__*/React.createElement("td", {
24472
+ className: "category " + css(styles$s.cell),
24473
+ key: catNum
24474
+ }, /*#__PURE__*/React.createElement("div", {
24475
+ className: ClassNames.INTERACTIVE,
24476
+ role: "button",
24477
+ "aria-label": catName,
24478
+ onClick: () => this.onChange(itemNum, catNum)
24479
+ }, isMobile && /*#__PURE__*/React.createElement("input", {
24480
+ type: "radio",
24481
+ name: uniqueId,
24482
+ className: css(sharedStyles.responsiveInput, sharedStyles.responsiveRadioInput),
24483
+ checked: selected,
24484
+ onChange: () => this.onChange(itemNum, catNum),
24485
+ onClick: e => e.stopPropagation()
24486
+ }), !isMobile && /*#__PURE__*/React.createElement("span", {
24487
+ className: css(styles$s.radioSpan, selected && styles$s.checkedRadioSpan, this.props.static && selected && styles$s.staticCheckedRadioSpan)
24488
+ }, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
24489
+ }));
24490
+ /* eslint-enable max-len */
24491
+ })));
24492
+
24493
+ // TODO(benkomalo): kill CSS-based styling and move everything to
24494
+ // aphrodite.
24495
+ const extraClassNames = classNames({
24496
+ "categorizer-container": true,
24497
+ "static-mode": this.props.static
24498
+ });
24499
+ const inlineStyles = this.props.apiOptions.isMobile ? [styles$s.fullBleedContainer] : [];
24500
+ return /*#__PURE__*/React.createElement("div", {
24501
+ className: extraClassNames + " " + css(...inlineStyles)
24502
+ }, table);
24503
+ }
24547
24504
  }
24548
24505
 
24549
24506
  // TODO(benkomalo): inject page-margin into Perseus instead of hardcoding.
@@ -25053,8 +25010,6 @@ var Dropdown$1 = {
25053
25010
  transform: optionsTransform
25054
25011
  };
25055
25012
 
25056
- /* eslint-disable react/sort-comp */
25057
-
25058
25013
  // transform = _.identity
25059
25014
 
25060
25015
  function mediaQueryIsMatched(mediaQuery) {
@@ -26811,6 +26766,34 @@ class Grapher extends React.Component {
26811
26766
  }
26812
26767
  };
26813
26768
  }
26769
+ static validate(state, rubric) {
26770
+ return validate$1(state, rubric);
26771
+ }
26772
+ static getUserInputFromProps(props) {
26773
+ return props.plot;
26774
+ }
26775
+ _getGridConfig(options) {
26776
+ return options.step.map((step, i) => {
26777
+ return Util.gridDimensionConfig(step, options.range[i], options.box[i], options.gridStep[i]);
26778
+ });
26779
+ }
26780
+ _calculateMobileTickStep(gridStep, step, ranges) {
26781
+ const tickStep = Util.constrainedTickStepsFromTickSteps(step, ranges);
26782
+
26783
+ // According to the graphInit documentation in graphie.js, tickStep is
26784
+ // relative to the grid units so we need to adjust all values by the
26785
+ // grid step.
26786
+ tickStep[0] = tickStep[0] / gridStep[0];
26787
+ tickStep[1] = tickStep[1] / gridStep[1];
26788
+ return tickStep;
26789
+ }
26790
+ simpleValidate(rubric) {
26791
+ return validate$1(this.getUserInput(), rubric);
26792
+ }
26793
+ getUserInput() {
26794
+ return Grapher.getUserInputFromProps(this.props);
26795
+ }
26796
+ focus() {}
26814
26797
  render() {
26815
26798
  const type = this.props.plot.type;
26816
26799
  const coords = this.props.plot.coords;
@@ -26861,34 +26844,6 @@ class Grapher extends React.Component {
26861
26844
  };
26862
26845
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(FunctionGrapher, grapherProps), this.props.availableTypes.length > 1 && typeSelector);
26863
26846
  }
26864
- _getGridConfig(options) {
26865
- return options.step.map((step, i) => {
26866
- return Util.gridDimensionConfig(step, options.range[i], options.box[i], options.gridStep[i]);
26867
- });
26868
- }
26869
- _calculateMobileTickStep(gridStep, step, ranges) {
26870
- const tickStep = Util.constrainedTickStepsFromTickSteps(step, ranges);
26871
-
26872
- // According to the graphInit documentation in graphie.js, tickStep is
26873
- // relative to the grid units so we need to adjust all values by the
26874
- // grid step.
26875
- tickStep[0] = tickStep[0] / gridStep[0];
26876
- tickStep[1] = tickStep[1] / gridStep[1];
26877
- return tickStep;
26878
- }
26879
- simpleValidate(rubric) {
26880
- return validate$1(this.getUserInput(), rubric);
26881
- }
26882
- getUserInput() {
26883
- return Grapher.getUserInputFromProps(this.props);
26884
- }
26885
- focus() {}
26886
- static validate(state, rubric) {
26887
- return validate$1(state, rubric);
26888
- }
26889
- static getUserInputFromProps(props) {
26890
- return props.plot;
26891
- }
26892
26847
  }
26893
26848
  Grapher.defaultProps = DEFAULT_GRAPHER_PROPS;
26894
26849
  const propTransform$2 = editorProps => {
@@ -27234,7 +27189,6 @@ var Iframe$1 = {
27234
27189
  hidden: true
27235
27190
  };
27236
27191
 
27237
- /* eslint-disable react/sort-comp */
27238
27192
  const defaultBoxSize = 400;
27239
27193
  const defaultRange = [0, 10];
27240
27194
  const defaultBackgroundImage$2 = {
@@ -27261,6 +27215,14 @@ class ImageWidget extends React.Component {
27261
27215
  };
27262
27216
  this.focus = () => {};
27263
27217
  }
27218
+ static validate(userInput, rubric) {
27219
+ return {
27220
+ type: "points",
27221
+ earned: 0,
27222
+ total: 0,
27223
+ message: null
27224
+ };
27225
+ }
27264
27226
  // no-op
27265
27227
 
27266
27228
  render() {
@@ -27392,14 +27354,6 @@ class ImageWidget extends React.Component {
27392
27354
  }
27393
27355
  }, title, image, caption);
27394
27356
  }
27395
- static validate(userInput, rubric) {
27396
- return {
27397
- type: "points",
27398
- earned: 0,
27399
- total: 0,
27400
- message: null
27401
- };
27402
- }
27403
27357
  }
27404
27358
  ImageWidget.contextType = PerseusI18nContext;
27405
27359
  ImageWidget.defaultProps = {
@@ -27587,6 +27541,14 @@ class Interaction extends React.Component {
27587
27541
  return Interaction.validate(this.getUserInput(), rubric);
27588
27542
  };
27589
27543
  }
27544
+ static validate(state, rubric) {
27545
+ return {
27546
+ type: "points",
27547
+ earned: 0,
27548
+ total: 0,
27549
+ message: null
27550
+ };
27551
+ }
27590
27552
  UNSAFE_componentWillReceiveProps(nextProps) {
27591
27553
  // HACK(michaelpolyak): This widget is not wired to use the Perseus
27592
27554
  // `onChange` callback to save user changes. Perseus re-rendering of the
@@ -27932,14 +27894,6 @@ class Interaction extends React.Component {
27932
27894
  }
27933
27895
  }, this));
27934
27896
  }
27935
- static validate(state, rubric) {
27936
- return {
27937
- type: "points",
27938
- earned: 0,
27939
- total: 0,
27940
- message: null
27941
- };
27942
- }
27943
27897
  }
27944
27898
  Interaction.defaultProps = {
27945
27899
  graph: {
@@ -29539,6 +29493,11 @@ class NumberInput extends React.Component {
29539
29493
  $(ReactDOM__default.findDOMNode(this.refs.input)).val(toNumericString(val, format));
29540
29494
  };
29541
29495
  }
29496
+ componentDidUpdate(prevProps) {
29497
+ if (!number.equal(this.getValue(), this.props.value)) {
29498
+ this._setValue(this.props.value, this.state.format);
29499
+ }
29500
+ }
29542
29501
  render() {
29543
29502
  let classes = classNames({
29544
29503
  "number-input": true,
@@ -29570,11 +29529,6 @@ class NumberInput extends React.Component {
29570
29529
  value: undefined
29571
29530
  }));
29572
29531
  }
29573
- componentDidUpdate(prevProps) {
29574
- if (!number.equal(this.getValue(), this.props.value)) {
29575
- this._setValue(this.props.value, this.state.format);
29576
- }
29577
- }
29578
29532
  }
29579
29533
  NumberInput.contextType = PerseusI18nContext;
29580
29534
  NumberInput.propTypes = {
@@ -29802,12 +29756,6 @@ const ItemExtras = [
29802
29756
 
29803
29757
  // prettier-ignore
29804
29758
 
29805
- // prettier-ignore
29806
-
29807
- // prettier-ignore
29808
-
29809
- // prettier-ignore
29810
-
29811
29759
  //prettier-ignore
29812
29760
 
29813
29761
  // A background image applied to various widgets.
@@ -30208,6 +30156,9 @@ const GraphLockedLayer = props => {
30208
30156
  };
30209
30157
 
30210
30158
  const actions = {
30159
+ global: {
30160
+ deleteIntent
30161
+ },
30211
30162
  angle: {
30212
30163
  movePoint
30213
30164
  },
@@ -30226,7 +30177,9 @@ const actions = {
30226
30177
  pointGraph: {
30227
30178
  movePoint,
30228
30179
  addPoint,
30229
- removePoint
30180
+ removePoint,
30181
+ focusPoint,
30182
+ blurPoint
30230
30183
  },
30231
30184
  polygon: {
30232
30185
  movePoint,
@@ -30247,6 +30200,12 @@ const actions = {
30247
30200
  movePoint
30248
30201
  }
30249
30202
  };
30203
+ const DELETE_INTENT = "delete-intent";
30204
+ function deleteIntent() {
30205
+ return {
30206
+ type: DELETE_INTENT
30207
+ };
30208
+ }
30250
30209
  const MOVE_LINE = "move-line";
30251
30210
  function moveLine(itemIndex, delta) {
30252
30211
  return {
@@ -30269,6 +30228,19 @@ function removePoint(index) {
30269
30228
  index
30270
30229
  };
30271
30230
  }
30231
+ const FOCUS_POINT = "focus-point";
30232
+ function focusPoint(index) {
30233
+ return {
30234
+ type: FOCUS_POINT,
30235
+ index
30236
+ };
30237
+ }
30238
+ const BLUR_POINT = "blur-point";
30239
+ function blurPoint() {
30240
+ return {
30241
+ type: BLUR_POINT
30242
+ };
30243
+ }
30272
30244
  const MOVE_ALL = "move-all";
30273
30245
  function moveAll(delta) {
30274
30246
  return {
@@ -31863,7 +31835,14 @@ function UnlimitedPointGraph(props) {
31863
31835
  }), props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
31864
31836
  key: i,
31865
31837
  point: point,
31866
- onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
31838
+ onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination)),
31839
+ onFocusChange: isFocused => {
31840
+ if (isFocused) {
31841
+ dispatch(actions.pointGraph.focusPoint(i));
31842
+ } else {
31843
+ dispatch(actions.pointGraph.blurPoint());
31844
+ }
31845
+ }
31867
31846
  })));
31868
31847
  }
31869
31848
  function PointGraph(props) {
@@ -32019,6 +31998,7 @@ const MafsGraph = props => {
32019
31998
  } = props;
32020
31999
  const [width, height] = props.box;
32021
32000
  const tickStep = props.step;
32001
+ const graphRef = React.useRef(null);
32022
32002
  return /*#__PURE__*/React.createElement(GraphConfigContext.Provider, {
32023
32003
  value: {
32024
32004
  range: state.range,
@@ -32036,16 +32016,25 @@ const MafsGraph = props => {
32036
32016
  }, /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(View, {
32037
32017
  className: "mafs-graph",
32038
32018
  style: {
32039
- height,
32040
- width: "intrinsic",
32041
32019
  position: "relative",
32042
32020
  padding: "25px 25px 0 0",
32043
32021
  boxSizing: "content-box",
32044
32022
  marginLeft: "20px",
32045
32023
  marginBottom: "20px",
32046
32024
  pointerEvents: props.static ? "none" : "auto",
32047
- userSelect: "none"
32048
- }
32025
+ userSelect: "none",
32026
+ width,
32027
+ height
32028
+ },
32029
+ onKeyUp: event => {
32030
+ if (event.key === "Backspace") {
32031
+ var _graphRef$current;
32032
+ dispatch(actions.global.deleteIntent());
32033
+ (_graphRef$current = graphRef.current) == null || _graphRef$current.focus();
32034
+ }
32035
+ },
32036
+ ref: graphRef,
32037
+ tabIndex: 0
32049
32038
  }, /*#__PURE__*/React.createElement(LegacyGrid, {
32050
32039
  box: props.box,
32051
32040
  backgroundImage: props.backgroundImage
@@ -32226,7 +32215,8 @@ function initializeGraphState(params) {
32226
32215
  return _extends({}, shared, {
32227
32216
  type: graph.type,
32228
32217
  coords: getPointCoords(graph, range, step),
32229
- numPoints: graph.numPoints || 0
32218
+ numPoints: graph.numPoints || 0,
32219
+ focusedPointIndex: null
32230
32220
  });
32231
32221
  case "circle":
32232
32222
  return _extends({}, shared, {
@@ -32484,10 +32474,47 @@ function interactiveGraphReducer(state, action) {
32484
32474
  return doAddPoint(state, action);
32485
32475
  case REMOVE_POINT:
32486
32476
  return doRemovePoint(state, action);
32477
+ case FOCUS_POINT:
32478
+ return doFocusPoint(state, action);
32479
+ case BLUR_POINT:
32480
+ return doBlurPoint(state);
32481
+ case DELETE_INTENT:
32482
+ return doDeleteIntent(state);
32487
32483
  default:
32488
32484
  throw new UnreachableCaseError(action);
32489
32485
  }
32490
32486
  }
32487
+ function doDeleteIntent(state, action) {
32488
+ // For unlimited point graphs
32489
+ if (state.type === "point" && state.numPoints === "unlimited") {
32490
+ // if there's a focused point
32491
+ if (state.focusedPointIndex !== null) {
32492
+ // Remove the focused focus
32493
+ return doRemovePoint(state, actions.pointGraph.removePoint(state.focusedPointIndex));
32494
+ }
32495
+ }
32496
+ return state;
32497
+ }
32498
+ function doFocusPoint(state, action) {
32499
+ switch (state.type) {
32500
+ case "point":
32501
+ return _extends({}, state, {
32502
+ focusedPointIndex: action.index
32503
+ });
32504
+ default:
32505
+ return state;
32506
+ }
32507
+ }
32508
+ function doBlurPoint(state, action) {
32509
+ switch (state.type) {
32510
+ case "point":
32511
+ return _extends({}, state, {
32512
+ focusedPointIndex: null
32513
+ });
32514
+ default:
32515
+ return state;
32516
+ }
32517
+ }
32491
32518
  function doMovePointInFigure(state, action) {
32492
32519
  switch (state.type) {
32493
32520
  case "segment":
@@ -32836,7 +32863,8 @@ function doRemovePoint(state, action) {
32836
32863
  return state;
32837
32864
  }
32838
32865
  return _extends({}, state, {
32839
- coords: state.coords.filter((_, i) => i !== action.index)
32866
+ coords: state.coords.filter((_, i) => i !== action.index),
32867
+ focusedPointIndex: null
32840
32868
  });
32841
32869
  }
32842
32870
  const getDeltaVertex = (maxMoves, minMoves, delta) => {
@@ -33248,9 +33276,6 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
33248
33276
  }));
33249
33277
  });
33250
33278
 
33251
- const {
33252
- DeprecationMixin
33253
- } = Util;
33254
33279
  const TRASH_ICON_URI = "https://ka-perseus-graphie.s3.amazonaws.com/b1452c0d79fd0f7ff4c3af9488474a0a0decb361.png";
33255
33280
  const defaultBackgroundImage = {
33256
33281
  url: null
@@ -33279,13 +33304,6 @@ function capitalize(str) {
33279
33304
  function numSteps(range, step) {
33280
33305
  return Math.floor((range[1] - range[0]) / step);
33281
33306
  }
33282
- const deprecatedProps = {
33283
- showGraph: function (props) {
33284
- return {
33285
- markings: props.showGraph ? "graph" : "none"
33286
- };
33287
- }
33288
- };
33289
33307
  const _getShouldShowInstructions = props => {
33290
33308
  return _isClickToAddPoints(props) && (
33291
33309
  // @ts-expect-error - TS2339 - Property 'coords' does not exist on type 'PerseusGraphType'. | TS2339 - Property 'coords' does not exist on type 'PerseusGraphType'.
@@ -33338,7 +33356,6 @@ class LegacyInteractiveGraph extends React.Component {
33338
33356
  // @ts-expect-error - TS2339 - Property 'coords' does not exist on type 'PerseusGraphType'. | TS2339 - Property 'coords' does not exist on type 'PerseusGraphType'.
33339
33357
  props.graph.coords == null || props.graph.coords.length === 0);
33340
33358
  };
33341
- this.deprecatedProps = deprecatedProps;
33342
33359
  this.setGraphie = newGraphie => {
33343
33360
  this.graphie = newGraphie;
33344
33361
  this.setupGraphie();
@@ -34411,10 +34428,6 @@ class LegacyInteractiveGraph extends React.Component {
34411
34428
  };
34412
34429
  this.focus = $.noop;
34413
34430
  }
34414
- // TODO(jangmi, CP-3288): Remove usage of `UNSAFE_componentWillMount`
34415
- UNSAFE_componentWillMount() {
34416
- DeprecationMixin.UNSAFE_componentWillMount.call(this);
34417
- }
34418
34431
  componentDidMount() {
34419
34432
  if (this.refs.graph) {
34420
34433
  // eslint-disable-next-line react/no-string-refs
@@ -37278,6 +37291,27 @@ class Draggable extends React.Component {
37278
37291
  passive: false
37279
37292
  } : false);
37280
37293
  }
37294
+ componentDidUpdate(prevProps) {
37295
+ if (this.props.state === prevProps.state) {
37296
+ return;
37297
+ }
37298
+ if (this.props.state === ItemState.ANIMATING && this.props.endPosition) {
37299
+ // Start animating
37300
+ const current = this.getCurrentPosition();
37301
+ const duration = 15 * Math.sqrt(Math.sqrt(Math.pow(this.props.endPosition.left - current.left, 2) + Math.pow(this.props.endPosition.top - current.top, 2)));
37302
+
37303
+ // @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'animate' does not exist on type 'JQueryStatic'.
37304
+ $(ReactDOM__default.findDOMNode(this)).animate(this.props.endPosition, {
37305
+ duration: Math.max(duration, 1),
37306
+ // Animating -> Static
37307
+ complete: this.props.onAnimationEnd
37308
+ });
37309
+ } else if (this.props.state === ItemState.STATIC) {
37310
+ // Ensure that any animations are done
37311
+ // @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'finish' does not exist on type 'JQueryStatic'.
37312
+ $(ReactDOM__default.findDOMNode(this)).finish();
37313
+ }
37314
+ }
37281
37315
  componentWillUnmount() {
37282
37316
  this._mounted = false;
37283
37317
  // Event handlers should be unbound before component unmounting, but
@@ -37339,27 +37373,6 @@ class Draggable extends React.Component {
37339
37373
  strings: this.context.strings
37340
37374
  }));
37341
37375
  }
37342
- componentDidUpdate(prevProps) {
37343
- if (this.props.state === prevProps.state) {
37344
- return;
37345
- }
37346
- if (this.props.state === ItemState.ANIMATING && this.props.endPosition) {
37347
- // Start animating
37348
- const current = this.getCurrentPosition();
37349
- const duration = 15 * Math.sqrt(Math.sqrt(Math.pow(this.props.endPosition.left - current.left, 2) + Math.pow(this.props.endPosition.top - current.top, 2)));
37350
-
37351
- // @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'animate' does not exist on type 'JQueryStatic'.
37352
- $(ReactDOM__default.findDOMNode(this)).animate(this.props.endPosition, {
37353
- duration: Math.max(duration, 1),
37354
- // Animating -> Static
37355
- complete: this.props.onAnimationEnd
37356
- });
37357
- } else if (this.props.state === ItemState.STATIC) {
37358
- // Ensure that any animations are done
37359
- // @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'finish' does not exist on type 'JQueryStatic'.
37360
- $(ReactDOM__default.findDOMNode(this)).finish();
37361
- }
37362
- }
37363
37376
  }
37364
37377
  Draggable.contextType = PerseusI18nContext;
37365
37378
  Draggable.defaultProps = {
@@ -37368,6 +37381,26 @@ Draggable.defaultProps = {
37368
37381
  linterContext: PerseusLinter.linterContextDefault
37369
37382
  };
37370
37383
  class Sortable extends React.Component {
37384
+ static itemsFromProps(props) {
37385
+ const state = props.disabled ? ItemState.DISABLED : ItemState.STATIC;
37386
+ return props.options.map((option, i) => {
37387
+ return {
37388
+ option: option,
37389
+ key: i,
37390
+ state,
37391
+ width: 0,
37392
+ height: 0
37393
+ };
37394
+ });
37395
+ }
37396
+ static clearItemMeasurements(items) {
37397
+ return items.map(item => {
37398
+ return _extends({}, item, {
37399
+ width: 0,
37400
+ height: 0
37401
+ });
37402
+ });
37403
+ }
37371
37404
  constructor(props) {
37372
37405
  super(props);
37373
37406
  // Don't call this.setState() here!
@@ -37407,26 +37440,6 @@ class Sortable extends React.Component {
37407
37440
  }, 0);
37408
37441
  }
37409
37442
  }
37410
- static itemsFromProps(props) {
37411
- const state = props.disabled ? ItemState.DISABLED : ItemState.STATIC;
37412
- return props.options.map((option, i) => {
37413
- return {
37414
- option: option,
37415
- key: i,
37416
- state,
37417
- width: 0,
37418
- height: 0
37419
- };
37420
- });
37421
- }
37422
- static clearItemMeasurements(items) {
37423
- return items.map(item => {
37424
- return _extends({}, item, {
37425
- width: 0,
37426
- height: 0
37427
- });
37428
- });
37429
- }
37430
37443
  measureItems() {
37431
37444
  // Measure all items and cache what their dimensions should be, taking
37432
37445
  // into account constraints and the current layout. This allows syncing
@@ -37478,124 +37491,6 @@ class Sortable extends React.Component {
37478
37491
  });
37479
37492
  });
37480
37493
  }
37481
- render() {
37482
- var _this$props$constrain, _this$props$constrain2;
37483
- // To minimize layout shift, we display a spinner until our math
37484
- // renderer is ready to render the math inside the sortable. To
37485
- // do this, we:
37486
- // - render a dummy TeX component to force the math renderer to load
37487
- // - display a spinner until the TeX component calls its onRender
37488
- // callback, signifying that the math is rendered (from which we can
37489
- // infer that the math renderer has loaded)
37490
- //
37491
- // If we didn't do this, the user might see a sortable with empty
37492
- // cells on first render, and then the math would pop in a few moments
37493
- // later once the rendering library loaded.
37494
- if (this.props.waitForTexRendererToLoad && !this.state.texRendererLoaded) {
37495
- const {
37496
- TeX
37497
- } = getDependencies();
37498
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(CircularSpinner, null), /*#__PURE__*/React.createElement("div", {
37499
- style: {
37500
- display: "none"
37501
- }
37502
- }, /*#__PURE__*/React.createElement(TeX, {
37503
- onRender: () => this.setState({
37504
- texRendererLoaded: true
37505
- })
37506
- }, "1")));
37507
- }
37508
- const cards = [];
37509
- const {
37510
- layout
37511
- } = this.props;
37512
- // We need to keep backwards compatbility with rules specified directly
37513
- // in CSS. See sortable.less for details.
37514
- const className = css(styles$d.sortable) + " perseus-sortable";
37515
- const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === Layout.VERTICAL;
37516
- const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === Layout.HORIZONTAL;
37517
- _.each(this.state.items, function (item, i, items) {
37518
- const isLast = i === items.length - 1;
37519
- const isStatic = item.state === ItemState.STATIC || item.state === ItemState.DISABLED;
37520
- let margin;
37521
-
37522
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37523
- if (this.props.layout === Layout.HORIZONTAL) {
37524
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37525
- margin = "0 " + this.props.margin + "px 0 0"; // right
37526
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37527
- } else if (this.props.layout === Layout.VERTICAL) {
37528
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37529
- margin = "0 0 " + this.props.margin + "px 0"; // bottom
37530
- }
37531
-
37532
- cards.push( /*#__PURE__*/React.createElement(Draggable, {
37533
- content: item.option,
37534
- key: item.key,
37535
- state: item.state
37536
- // @ts-expect-error - TS2769 - No overload matches this call.
37537
- ,
37538
- ref: item.key,
37539
- width: syncWidth ? item.width : undefined,
37540
- height: syncHeight ? item.height : undefined,
37541
- layout: layout
37542
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37543
- ,
37544
- includePadding: this.props.padding,
37545
- margin: isLast && isStatic ? 0 : margin,
37546
- endPosition: item.endPosition,
37547
- linterContext: PerseusLinter.pushContextStack(
37548
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37549
- this.props.linterContext, "sortable")
37550
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37551
- ,
37552
- onRender: this.remeasureItems
37553
- // eslint-disable-next-line react/jsx-no-bind
37554
- // @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.
37555
- ,
37556
- onMouseDown: this.onMouseDown.bind(this, item.key)
37557
- // eslint-disable-next-line react/jsx-no-bind
37558
- // @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.
37559
- ,
37560
- onMouseMove: this.onMouseMove.bind(this, item.key)
37561
- // eslint-disable-next-line react/jsx-no-bind
37562
- // @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.
37563
- ,
37564
- onMouseUp: this.onMouseUp.bind(this, item.key)
37565
- // eslint-disable-next-line react/jsx-no-bind
37566
- // @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.
37567
- ,
37568
- onTouchMove: this.onMouseMove.bind(this, item.key)
37569
- // eslint-disable-next-line react/jsx-no-bind
37570
- // @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.
37571
- ,
37572
- onTouchEnd: this.onMouseUp.bind(this, item.key)
37573
- // eslint-disable-next-line react/jsx-no-bind
37574
- // @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.
37575
- ,
37576
- onTouchCancel: this.onMouseUp.bind(this, item.key)
37577
- // eslint-disable-next-line react/jsx-no-bind
37578
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37579
- ,
37580
- onAnimationEnd: this.onAnimationEnd.bind(
37581
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37582
- this, item.key)
37583
- }));
37584
- if (item.state === ItemState.DRAGGING || item.state === ItemState.ANIMATING) {
37585
- cards.push( /*#__PURE__*/React.createElement(Placeholder, {
37586
- key: "placeholder_" + item.key,
37587
- ref: "placeholder_" + item.key,
37588
- width: item.width,
37589
- height: item.height,
37590
- layout: layout,
37591
- margin: isLast ? 0 : margin
37592
- }));
37593
- }
37594
- }, this);
37595
- return /*#__PURE__*/React.createElement("ul", {
37596
- className: className
37597
- }, cards);
37598
- }
37599
37494
  onMouseDown(key) {
37600
37495
  // Static -> Dragging
37601
37496
  const items = _.map(this.state.items, function (item) {
@@ -37741,6 +37636,124 @@ class Sortable extends React.Component {
37741
37636
  getOptions() {
37742
37637
  return _.pluck(this.state.items, "option");
37743
37638
  }
37639
+ render() {
37640
+ var _this$props$constrain, _this$props$constrain2;
37641
+ // To minimize layout shift, we display a spinner until our math
37642
+ // renderer is ready to render the math inside the sortable. To
37643
+ // do this, we:
37644
+ // - render a dummy TeX component to force the math renderer to load
37645
+ // - display a spinner until the TeX component calls its onRender
37646
+ // callback, signifying that the math is rendered (from which we can
37647
+ // infer that the math renderer has loaded)
37648
+ //
37649
+ // If we didn't do this, the user might see a sortable with empty
37650
+ // cells on first render, and then the math would pop in a few moments
37651
+ // later once the rendering library loaded.
37652
+ if (this.props.waitForTexRendererToLoad && !this.state.texRendererLoaded) {
37653
+ const {
37654
+ TeX
37655
+ } = getDependencies();
37656
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(CircularSpinner, null), /*#__PURE__*/React.createElement("div", {
37657
+ style: {
37658
+ display: "none"
37659
+ }
37660
+ }, /*#__PURE__*/React.createElement(TeX, {
37661
+ onRender: () => this.setState({
37662
+ texRendererLoaded: true
37663
+ })
37664
+ }, "1")));
37665
+ }
37666
+ const cards = [];
37667
+ const {
37668
+ layout
37669
+ } = this.props;
37670
+ // We need to keep backwards compatbility with rules specified directly
37671
+ // in CSS. See sortable.less for details.
37672
+ const className = css(styles$d.sortable) + " perseus-sortable";
37673
+ const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === Layout.VERTICAL;
37674
+ const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === Layout.HORIZONTAL;
37675
+ _.each(this.state.items, function (item, i, items) {
37676
+ const isLast = i === items.length - 1;
37677
+ const isStatic = item.state === ItemState.STATIC || item.state === ItemState.DISABLED;
37678
+ let margin;
37679
+
37680
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37681
+ if (this.props.layout === Layout.HORIZONTAL) {
37682
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37683
+ margin = "0 " + this.props.margin + "px 0 0"; // right
37684
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37685
+ } else if (this.props.layout === Layout.VERTICAL) {
37686
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37687
+ margin = "0 0 " + this.props.margin + "px 0"; // bottom
37688
+ }
37689
+
37690
+ cards.push( /*#__PURE__*/React.createElement(Draggable, {
37691
+ content: item.option,
37692
+ key: item.key,
37693
+ state: item.state
37694
+ // @ts-expect-error - TS2769 - No overload matches this call.
37695
+ ,
37696
+ ref: item.key,
37697
+ width: syncWidth ? item.width : undefined,
37698
+ height: syncHeight ? item.height : undefined,
37699
+ layout: layout
37700
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37701
+ ,
37702
+ includePadding: this.props.padding,
37703
+ margin: isLast && isStatic ? 0 : margin,
37704
+ endPosition: item.endPosition,
37705
+ linterContext: PerseusLinter.pushContextStack(
37706
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37707
+ this.props.linterContext, "sortable")
37708
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37709
+ ,
37710
+ onRender: this.remeasureItems
37711
+ // eslint-disable-next-line react/jsx-no-bind
37712
+ // @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.
37713
+ ,
37714
+ onMouseDown: this.onMouseDown.bind(this, item.key)
37715
+ // eslint-disable-next-line react/jsx-no-bind
37716
+ // @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.
37717
+ ,
37718
+ onMouseMove: this.onMouseMove.bind(this, item.key)
37719
+ // eslint-disable-next-line react/jsx-no-bind
37720
+ // @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.
37721
+ ,
37722
+ onMouseUp: this.onMouseUp.bind(this, item.key)
37723
+ // eslint-disable-next-line react/jsx-no-bind
37724
+ // @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.
37725
+ ,
37726
+ onTouchMove: this.onMouseMove.bind(this, item.key)
37727
+ // eslint-disable-next-line react/jsx-no-bind
37728
+ // @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.
37729
+ ,
37730
+ onTouchEnd: this.onMouseUp.bind(this, item.key)
37731
+ // eslint-disable-next-line react/jsx-no-bind
37732
+ // @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.
37733
+ ,
37734
+ onTouchCancel: this.onMouseUp.bind(this, item.key)
37735
+ // eslint-disable-next-line react/jsx-no-bind
37736
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37737
+ ,
37738
+ onAnimationEnd: this.onAnimationEnd.bind(
37739
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
37740
+ this, item.key)
37741
+ }));
37742
+ if (item.state === ItemState.DRAGGING || item.state === ItemState.ANIMATING) {
37743
+ cards.push( /*#__PURE__*/React.createElement(Placeholder, {
37744
+ key: "placeholder_" + item.key,
37745
+ ref: "placeholder_" + item.key,
37746
+ width: item.width,
37747
+ height: item.height,
37748
+ layout: layout,
37749
+ margin: isLast ? 0 : margin
37750
+ }));
37751
+ }
37752
+ }, this);
37753
+ return /*#__PURE__*/React.createElement("ul", {
37754
+ className: className
37755
+ }, cards);
37756
+ }
37744
37757
  }
37745
37758
  Sortable.defaultProps = {
37746
37759
  layout: Layout.HORIZONTAL,
@@ -38504,7 +38517,7 @@ var Matrix$1 = {
38504
38517
  isLintable: true
38505
38518
  };
38506
38519
 
38507
- /* eslint-disable @babel/no-invalid-this, react/sort-comp */
38520
+ /* eslint-disable @babel/no-invalid-this */
38508
38521
  const defaultImage = {
38509
38522
  url: null,
38510
38523
  top: 0,
@@ -38546,30 +38559,6 @@ const Measurer = createReactClass({
38546
38559
  getInitialState: function () {
38547
38560
  return {};
38548
38561
  },
38549
- render: function () {
38550
- const image = _.extend({}, defaultImage, this.props.image);
38551
-
38552
- // TODO(scottgrant): This isn't a11y-friendly! We should insist on
38553
- // finding some valid alt text when this widget is used.
38554
- return /*#__PURE__*/React.createElement("div", {
38555
- className: "perseus-widget perseus-widget-measurer " + "graphie-container above-scratchpad",
38556
- style: {
38557
- width: this.props.box[0],
38558
- height: this.props.box[1]
38559
- }
38560
- }, image.url && /*#__PURE__*/React.createElement("div", {
38561
- style: {
38562
- position: "relative",
38563
- top: image.top,
38564
- left: image.left
38565
- }
38566
- }, /*#__PURE__*/React.createElement(SvgImage, {
38567
- src: image.url
38568
- })), /*#__PURE__*/React.createElement("div", {
38569
- className: "graphie",
38570
- ref: "graphieDiv"
38571
- }));
38572
- },
38573
38562
  componentDidMount: function () {
38574
38563
  this.setupGraphie();
38575
38564
  },
@@ -38627,7 +38616,31 @@ const Measurer = createReactClass({
38627
38616
  // TODO(joel) - I don't understand how this is useful!
38628
38617
  return Measurer.validate(this.getUserInput(), rubric);
38629
38618
  },
38630
- focus: $.noop
38619
+ focus: $.noop,
38620
+ render: function () {
38621
+ const image = _.extend({}, defaultImage, this.props.image);
38622
+
38623
+ // TODO(scottgrant): This isn't a11y-friendly! We should insist on
38624
+ // finding some valid alt text when this widget is used.
38625
+ return /*#__PURE__*/React.createElement("div", {
38626
+ className: "perseus-widget perseus-widget-measurer " + "graphie-container above-scratchpad",
38627
+ style: {
38628
+ width: this.props.box[0],
38629
+ height: this.props.box[1]
38630
+ }
38631
+ }, image.url && /*#__PURE__*/React.createElement("div", {
38632
+ style: {
38633
+ position: "relative",
38634
+ top: image.top,
38635
+ left: image.left
38636
+ }
38637
+ }, /*#__PURE__*/React.createElement(SvgImage, {
38638
+ src: image.url
38639
+ })), /*#__PURE__*/React.createElement("div", {
38640
+ className: "graphie",
38641
+ ref: "graphieDiv"
38642
+ }));
38643
+ }
38631
38644
  });
38632
38645
  _.extend(Measurer, {
38633
38646
  validate: function (state, rubric) {
@@ -40228,55 +40241,6 @@ class Card extends React.Component {
40228
40241
  }
40229
40242
  };
40230
40243
  }
40231
- render() {
40232
- let style = {};
40233
- if (this.props.floating) {
40234
- style = {
40235
- position: "absolute",
40236
- left: this.props.startOffset.left,
40237
- top: this.props.startOffset.top
40238
- };
40239
- }
40240
- if (this.props.width) {
40241
- style.width = this.props.width;
40242
- }
40243
- const className = ["card"];
40244
- if (this.props.stack) {
40245
- className.push("stack");
40246
- }
40247
- if (this.props.floating && !this.props.animating) {
40248
- className.push("dragging");
40249
- style.left += this.props.mouse.left - this.props.startMouse.left;
40250
- style.top += this.props.mouse.top - this.props.startMouse.top;
40251
- }
40252
-
40253
- // Pull out the content to get rendered
40254
- const rendererProps = _.pick(this.props, "content");
40255
- const onMouseDown = this.props.animating ? $.noop : this.onMouseDown;
40256
- return /*#__PURE__*/React.createElement("div", {
40257
- className: "card-wrap " + ClassNames.INTERACTIVE,
40258
- style: style,
40259
- onMouseDown: onMouseDown,
40260
- onTouchStart: onMouseDown,
40261
- onTouchEnd: this.onMouseUp,
40262
- onTouchCancel: this.onMouseUp
40263
- }, /*#__PURE__*/React.createElement("div", {
40264
- className: className.join(" ")
40265
- }, /*#__PURE__*/React.createElement(Renderer, _extends({}, rendererProps, {
40266
- linterContext: this.props.linterContext,
40267
- strings: this.context.strings
40268
- }))));
40269
- }
40270
- shouldComponentUpdate(nextProps, nextState) {
40271
- // Cards in the bank or drag list don't usually change -- they only
40272
- // reorder themselves -- so we want to skip the update to things a
40273
- // little faster. We also need to re-render if the content changes,
40274
- // which happens only in the editor. (We do want to update the floating
40275
- // card on mouse move to update its position.)
40276
- return this.props.floating || nextProps.floating || this.props.content !== nextProps.content ||
40277
- // TODO(alpert): Remove ref here after fixing facebook/react#1392.
40278
- this.props.fakeRef !== nextProps.fakeRef;
40279
- }
40280
40244
  componentDidMount() {
40281
40245
  this.mouseMoveUpBound = false;
40282
40246
 
@@ -40295,6 +40259,16 @@ class Card extends React.Component {
40295
40259
  passive: false
40296
40260
  } : false);
40297
40261
  }
40262
+ shouldComponentUpdate(nextProps, nextState) {
40263
+ // Cards in the bank or drag list don't usually change -- they only
40264
+ // reorder themselves -- so we want to skip the update to things a
40265
+ // little faster. We also need to re-render if the content changes,
40266
+ // which happens only in the editor. (We do want to update the floating
40267
+ // card on mouse move to update its position.)
40268
+ return this.props.floating || nextProps.floating || this.props.content !== nextProps.content ||
40269
+ // TODO(alpert): Remove ref here after fixing facebook/react#1392.
40270
+ this.props.fakeRef !== nextProps.fakeRef;
40271
+ }
40298
40272
  componentDidUpdate(prevProps, prevState) {
40299
40273
  if (this.props.animating && !prevProps.animating) {
40300
40274
  // If we just were changed into animating, start the animation.
@@ -40316,6 +40290,45 @@ class Card extends React.Component {
40316
40290
  }
40317
40291
  document.removeEventListener("touchmove", this.onMouseMove);
40318
40292
  }
40293
+ render() {
40294
+ let style = {};
40295
+ if (this.props.floating) {
40296
+ style = {
40297
+ position: "absolute",
40298
+ left: this.props.startOffset.left,
40299
+ top: this.props.startOffset.top
40300
+ };
40301
+ }
40302
+ if (this.props.width) {
40303
+ style.width = this.props.width;
40304
+ }
40305
+ const className = ["card"];
40306
+ if (this.props.stack) {
40307
+ className.push("stack");
40308
+ }
40309
+ if (this.props.floating && !this.props.animating) {
40310
+ className.push("dragging");
40311
+ style.left += this.props.mouse.left - this.props.startMouse.left;
40312
+ style.top += this.props.mouse.top - this.props.startMouse.top;
40313
+ }
40314
+
40315
+ // Pull out the content to get rendered
40316
+ const rendererProps = _.pick(this.props, "content");
40317
+ const onMouseDown = this.props.animating ? $.noop : this.onMouseDown;
40318
+ return /*#__PURE__*/React.createElement("div", {
40319
+ className: "card-wrap " + ClassNames.INTERACTIVE,
40320
+ style: style,
40321
+ onMouseDown: onMouseDown,
40322
+ onTouchStart: onMouseDown,
40323
+ onTouchEnd: this.onMouseUp,
40324
+ onTouchCancel: this.onMouseUp
40325
+ }, /*#__PURE__*/React.createElement("div", {
40326
+ className: className.join(" ")
40327
+ }, /*#__PURE__*/React.createElement(Renderer, _extends({}, rendererProps, {
40328
+ linterContext: this.props.linterContext,
40329
+ strings: this.context.strings
40330
+ }))));
40331
+ }
40319
40332
  }
40320
40333
  Card.contextType = PerseusI18nContext;
40321
40334
  Card.propTypes = {
@@ -41522,7 +41535,6 @@ class HighlightSetRenderer extends React.PureComponent {
41522
41535
  hoveredHighlightKey: null,
41523
41536
  hoveringTooltipFor: null
41524
41537
  };
41525
- // eslint-disable-next-line react/sort-comp
41526
41538
  this._highlightRenderers = {};
41527
41539
  this._handleMouseMove = e => {
41528
41540
  const mouseClientPosition = {
@@ -41866,8 +41878,6 @@ class WordIndexer extends React.PureComponent {
41866
41878
  super(...args);
41867
41879
  this._container = void 0;
41868
41880
  }
41869
- /* eslint-enable react/sort-comp */
41870
-
41871
41881
  componentDidMount() {
41872
41882
  this._sendWordsUpdate();
41873
41883
  }
@@ -42537,6 +42547,14 @@ class Passage extends React.Component {
42537
42547
  });
42538
42548
  };
42539
42549
  }
42550
+ static validate(state, rubric) {
42551
+ return {
42552
+ type: "points",
42553
+ earned: 0,
42554
+ total: 0,
42555
+ message: null
42556
+ };
42557
+ }
42540
42558
  componentDidMount() {
42541
42559
  this._updateState();
42542
42560
 
@@ -42754,17 +42772,6 @@ class Passage extends React.Component {
42754
42772
  return Passage.validate(this.getUserInput(), rubric);
42755
42773
  }
42756
42774
 
42757
- /* eslint-disable react/sort-comp */
42758
- static validate(state, rubric) {
42759
- return {
42760
- type: "points",
42761
- earned: 0,
42762
- total: 0,
42763
- message: null
42764
- };
42765
- }
42766
- /* eslint-enable react/sort-comp */
42767
-
42768
42775
  /**
42769
42776
  * Rendering
42770
42777
  *
@@ -42994,14 +43001,6 @@ class PhetSimulation extends React.Component {
42994
43001
  url: null,
42995
43002
  banner: null
42996
43003
  };
42997
- this.change = (...args) => {
42998
- // @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
42999
- return change.apply(this, args);
43000
- };
43001
- this.simpleValidate = rubric => {
43002
- // @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof PhetSimulation'.
43003
- return PhetSimulation.validate(this.getUserInput(), rubric);
43004
- };
43005
43004
  // kaLocales and PhET locales use different formats and abbreviations.
43006
43005
  // PhET accepts different formats, i.e. kaLocale's hyphens, but it does not accept
43007
43006
  // different abbreviations, so in points of divergence of abbreviations, we need to
@@ -43107,7 +43106,7 @@ class PhetSimulation extends React.Component {
43107
43106
  // http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
43108
43107
  const sandboxProperties = "allow-same-origin allow-scripts";
43109
43108
  return /*#__PURE__*/React.createElement(View, {
43110
- style: styles$6.container
43109
+ style: styles$6.widgetContainer
43111
43110
  }, this.state.banner !== null &&
43112
43111
  /*#__PURE__*/
43113
43112
  // TODO(anna): Make this banner focusable
@@ -43119,19 +43118,16 @@ class PhetSimulation extends React.Component {
43119
43118
  layout: "floating",
43120
43119
  kind: this.state.banner.kind,
43121
43120
  text: this.state.banner.message
43122
- })), /*#__PURE__*/React.createElement("iframe", {
43121
+ })), /*#__PURE__*/React.createElement(View, {
43122
+ style: styles$6.iframeContainer
43123
+ }, /*#__PURE__*/React.createElement("iframe", {
43123
43124
  ref: this.iframeRef,
43124
43125
  title: this.props.description,
43125
43126
  sandbox: sandboxProperties,
43126
- style: {
43127
- minWidth: 400,
43128
- height: 360,
43129
- width: "100%",
43130
- borderWidth: 0
43131
- },
43127
+ className: css(styles$6.iframeResponsive),
43132
43128
  src: (_this$state$url = this.state.url) == null ? void 0 : _this$state$url.toString(),
43133
43129
  allow: "fullscreen"
43134
- }), /*#__PURE__*/React.createElement(IconButton, {
43130
+ })), /*#__PURE__*/React.createElement(IconButton, {
43135
43131
  icon: cornersOutIcon,
43136
43132
  onClick: () => {
43137
43133
  var _this$iframeRef$curre;
@@ -43163,21 +43159,35 @@ const makeSafeUrl = (urlString, locale) => {
43163
43159
  return url;
43164
43160
  };
43165
43161
  const styles$6 = StyleSheet.create({
43166
- container: {
43162
+ widgetContainer: {
43167
43163
  borderRadius: borderRadiusLarge,
43168
43164
  borderWidth: 1,
43169
43165
  borderColor: basicBorderColor,
43170
- padding: phoneMargin,
43171
- paddingBottom: 0,
43172
- width: 650
43166
+ padding: spacing.medium_16,
43167
+ paddingBottom: 0
43168
+ },
43169
+ iframeContainer: {
43170
+ position: "relative",
43171
+ overflow: "hidden",
43172
+ width: "100%",
43173
+ // 16:9 aspect ratio
43174
+ paddingTop: "56.25%"
43175
+ },
43176
+ iframeResponsive: {
43177
+ borderWidth: 0,
43178
+ position: "absolute",
43179
+ top: 0,
43180
+ left: 0,
43181
+ bottom: 0,
43182
+ right: 0,
43183
+ width: "100%",
43184
+ height: "100%"
43173
43185
  }
43174
43186
  });
43175
43187
  var PhetSimulation$1 = {
43176
43188
  name: "phet-simulation",
43177
43189
  displayName: "PhET Simulation",
43178
43190
  widget: PhetSimulation,
43179
- // Hides widget from content creators until full release
43180
- hidden: true,
43181
43191
  isLintable: true
43182
43192
  };
43183
43193
 
@@ -44685,7 +44695,7 @@ const init = function init(options) {
44685
44695
 
44686
44696
  // This file is processed by a Rollup plugin (replace) to inject the production
44687
44697
  const libName = "@khanacademy/perseus";
44688
- const libVersion = "31.1.0";
44698
+ const libVersion = "32.0.1";
44689
44699
  addLibraryVersionToPerseusDebug(libName, libVersion);
44690
44700
 
44691
44701
  const apiVersion = {
@@ -46498,8 +46508,6 @@ class MultiRenderer extends React.Component {
46498
46508
  // Keep state in sync with props.
46499
46509
  this.state = this._tryMakeRendererState(this.props);
46500
46510
  }
46501
- /* eslint-enable react/sort-comp */
46502
-
46503
46511
  UNSAFE_componentWillReceiveProps(nextProps) {
46504
46512
  // Keep state in sync with props.
46505
46513
  if (nextProps.item !== this.props.item) {
@@ -48272,5 +48280,5 @@ const EditorJsonify = {
48272
48280
  }
48273
48281
  };
48274
48282
 
48275
- export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAngleCoords, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getCorrectAnswerForWidgetId, getLineCoords, getLinearSystemCoords, getPointCoords, getPolygonCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
48283
+ export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAngleCoords, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getCorrectAnswerForWidgetId, getLineCoords, getLinearSystemCoords, getPointCoords, getPolygonCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, makeSafeUrl, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
48276
48284
  //# sourceMappingURL=index.js.map