@khanacademy/perseus 19.2.1 → 19.3.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.
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import type { Coord } from "../interactive2/types";
3
- import type { PerseusImageBackground } from "../perseus-types";
3
+ import type { PerseusImageBackground, LockedFigure } from "../perseus-types";
4
4
  import type { GridDimensions } from "../util";
5
5
  type Props = {
6
6
  box: [number, number];
@@ -17,6 +17,7 @@ type Props = {
17
17
  rulerTicks: number;
18
18
  instructions?: string;
19
19
  isMobile: boolean;
20
+ lockedFigures?: ReadonlyArray<LockedFigure>;
20
21
  onGraphieUpdated?: (graphie: any) => void;
21
22
  onClick?: (Coord: any) => void;
22
23
  onMouseDown?: (Coord: any) => void;
package/dist/es/index.js CHANGED
@@ -1904,11 +1904,25 @@ const KhanAnswerTypes = {
1904
1904
  const _excluded$4 = ["scoring"];
1905
1905
  const ERROR_TITLE = i18n._("Oops!");
1906
1906
  const ERROR_MESSAGE = i18n._("Sorry, I don't understand that!");
1907
+
1908
+ // Map of international operator names to their English equivalents
1909
+ const englishOperators = {
1910
+ arctg: "arctan",
1911
+ cosec: "csc",
1912
+ cossec: "csc",
1913
+ cotg: "cot",
1914
+ ctg: "cot",
1915
+ sen: "sin",
1916
+ tg: "tan"
1917
+ };
1907
1918
  const anglicizeOperators = tex => {
1908
1919
  // sen is used instead of sin in some languages, e.g. Portuguese.
1909
1920
  // To ensure that answers in various languages are graded correctly, we
1910
1921
  // convert operators to their Englishy forms.
1911
- return tex.replace(/\\operatorname{sen}/g, "\\sin ");
1922
+ return tex.replace(/\\operatorname{([a-z]+)}/g, (_, op) => {
1923
+ var _englishOperators$op;
1924
+ return `\\${(_englishOperators$op = englishOperators[op]) != null ? _englishOperators$op : op} `;
1925
+ });
1912
1926
  };
1913
1927
  const normalizeTex = tex => {
1914
1928
  return anglicizeOperators(tex);
@@ -21521,15 +21535,6 @@ class InputNumber extends React.Component {
21521
21535
  };
21522
21536
  this._handleFocus = () => {
21523
21537
  this.props.onFocus([]);
21524
- // HACK(kevinb): We want to dismiss the feedback popover that webapp
21525
- // displays as soon as a user clicks in in the input field so we call
21526
- // interactionCallback directly.
21527
- const {
21528
- interactionCallback
21529
- } = this.props.apiOptions;
21530
- if (interactionCallback) {
21531
- interactionCallback();
21532
- }
21533
21538
  };
21534
21539
  this._handleBlur = () => {
21535
21540
  this.props.onBlur([]);
@@ -21863,15 +21868,6 @@ class NumericInput extends React.Component {
21863
21868
  };
21864
21869
  this._handleFocus = () => {
21865
21870
  this.props.onFocus([]);
21866
- // HACK(kevinb): We want to dismiss the feedback popover that webapp
21867
- // displays as soon as a user clicks in in the input field so we call
21868
- // interactionCallback directly.
21869
- const {
21870
- interactionCallback
21871
- } = this.props.apiOptions;
21872
- if (interactionCallback) {
21873
- interactionCallback();
21874
- }
21875
21871
  };
21876
21872
  this._handleBlur = () => {
21877
21873
  this.props.onBlur([]);
@@ -28046,6 +28042,33 @@ class Graph extends React.Component {
28046
28042
  allowScratchpad: true,
28047
28043
  setDrawingAreaAvailable: this.props.setDrawingAreaAvailable
28048
28044
  });
28045
+
28046
+ // Maybe move this out later
28047
+ if (this.props.lockedFigures) {
28048
+ for (const lockedFigure of this.props.lockedFigures) {
28049
+ switch (lockedFigure.type) {
28050
+ case "point":
28051
+ graphie.circle(
28052
+ // center
28053
+ lockedFigure.coord,
28054
+ // radius
28055
+ 0.2,
28056
+ // style
28057
+ lockedFigure.style);
28058
+ break;
28059
+ default:
28060
+ /**
28061
+ * Devlopment-time future-proofing: This `never` should
28062
+ * fail during type-checking if we add a new locked
28063
+ * shape type and forget to handle it in any other
28064
+ * switch case here.
28065
+ */
28066
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
28067
+ lockedFigure.type;
28068
+ throw new Error(`Unknown locked shape type: ${lockedFigure.type}`);
28069
+ }
28070
+ }
28071
+ }
28049
28072
  this._updateProtractor();
28050
28073
  this._updateRuler();
28051
28074
 
@@ -29426,7 +29449,8 @@ class InteractiveGraph extends React.Component {
29426
29449
  onMouseDown: onMouseDown,
29427
29450
  onGraphieUpdated: this.setGraphie,
29428
29451
  setDrawingAreaAvailable: this.props.apiOptions.setDrawingAreaAvailable,
29429
- isMobile: isMobile
29452
+ isMobile: isMobile,
29453
+ lockedFigures: this.props.lockedFigures
29430
29454
  }));
29431
29455
  }
29432
29456
  static getQuadraticCoefficients(coords) {
@@ -41556,7 +41580,7 @@ const init = function init(options) {
41556
41580
 
41557
41581
  // This file is processed by a Rollup plugin (replace) to inject the production
41558
41582
  const libName = "@khanacademy/perseus";
41559
- const libVersion = "19.2.1";
41583
+ const libVersion = "19.3.1";
41560
41584
  addLibraryVersionToPerseusDebug(libName, libVersion);
41561
41585
 
41562
41586
  const apiVersion = {
@@ -42101,20 +42125,25 @@ class ServerItemRenderer extends React.Component {
42101
42125
  this.blurTimeoutID = void 0;
42102
42126
  this._handleFocusChange = (newFocus, oldFocus) => {
42103
42127
  if (newFocus != null) {
42128
+ var _this$props$apiOption;
42104
42129
  this._setCurrentFocus(newFocus);
42130
+
42131
+ // Call the interactionCallback, if it exists, with the current user input data
42132
+ (_this$props$apiOption = this.props.apiOptions) == null || _this$props$apiOption.interactionCallback == null || _this$props$apiOption.interactionCallback(this.questionRenderer.getUserInputForWidgets());
42105
42133
  } else {
42106
42134
  this._onRendererBlur(oldFocus);
42107
42135
  }
42108
42136
  };
42109
42137
  this.handleInteractWithWidget = widgetId => {
42138
+ var _this$props$apiOption2;
42110
42139
  const withRemoved = _.difference(this.state.questionHighlightedWidgets, [widgetId]);
42111
42140
  this.setState({
42112
42141
  questionCompleted: false,
42113
42142
  questionHighlightedWidgets: withRemoved
42114
42143
  });
42115
- if (this.props.apiOptions.interactionCallback) {
42116
- this.props.apiOptions.interactionCallback();
42117
- }
42144
+
42145
+ // Call the interactionCallback, if it exists, with the current user input data
42146
+ (_this$props$apiOption2 = this.props.apiOptions) == null || _this$props$apiOption2.interactionCallback == null || _this$props$apiOption2.interactionCallback(this.questionRenderer.getUserInputForWidgets());
42118
42147
  };
42119
42148
  // This must be pre-bound otherwise SvgImage's shouldComponentUpdate
42120
42149
  // won't behave correctly and we'll get an infinite loop.