@khanacademy/perseus 18.0.0 → 19.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.
package/dist/index.js CHANGED
@@ -2776,7 +2776,7 @@ function gridDimensionConfig(absTickStep, extent, dimensionConstraint, gridStep)
2776
2776
  *
2777
2777
  * TODO(somewhatabstract, FEI-3464): Consolidate query string parsing functions.
2778
2778
  */
2779
- function getGridStep$1(range, step, boxSize) {
2779
+ function getGridStep(range, step, boxSize) {
2780
2780
  // @ts-expect-error - TS2322 - Type '(number | null | undefined)[]' is not assignable to type 'Coordinates'.
2781
2781
  return ___default["default"](2).times(function (i) {
2782
2782
  const scale = scaleFromExtent(range[i], boxSize);
@@ -2958,13 +2958,13 @@ function eq$2(x, y) {
2958
2958
  * Deep approximate equality on primitives, numbers, arrays, and objects.
2959
2959
  * Recursive.
2960
2960
  */
2961
- function deepEq$6(x, y) {
2961
+ function deepEq$5(x, y) {
2962
2962
  if (Array.isArray(x) && Array.isArray(y)) {
2963
2963
  if (x.length !== y.length) {
2964
2964
  return false;
2965
2965
  }
2966
2966
  for (let i = 0; i < x.length; i++) {
2967
- if (!deepEq$6(x[i], y[i])) {
2967
+ if (!deepEq$5(x[i], y[i])) {
2968
2968
  return false;
2969
2969
  }
2970
2970
  }
@@ -2982,10 +2982,10 @@ function deepEq$6(x, y) {
2982
2982
  if (typeof x === "object" && typeof y === "object" && !!x && !!y) {
2983
2983
  return x === y || ___default["default"].all(x, function (v, k) {
2984
2984
  // @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
2985
- return deepEq$6(y[k], v);
2985
+ return deepEq$5(y[k], v);
2986
2986
  }) && ___default["default"].all(y, function (v, k) {
2987
2987
  // @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
2988
- return deepEq$6(x[k], v);
2988
+ return deepEq$5(x[k], v);
2989
2989
  });
2990
2990
  }
2991
2991
  if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
@@ -3185,7 +3185,7 @@ const supportsPassiveEvents = () => {
3185
3185
  * Pass this function as the touchstart for an element to
3186
3186
  * avoid sending the touch to the mobile scratchpad
3187
3187
  */
3188
- function captureScratchpadTouchStart$4(e) {
3188
+ function captureScratchpadTouchStart$3(e) {
3189
3189
  e.stopPropagation();
3190
3190
  }
3191
3191
  function getImageSize(url, callback) {
@@ -3273,7 +3273,7 @@ const Util = {
3273
3273
  firstNumericalParse: firstNumericalParse$1,
3274
3274
  stringArrayOfSize: stringArrayOfSize$1,
3275
3275
  gridDimensionConfig,
3276
- getGridStep: getGridStep$1,
3276
+ getGridStep,
3277
3277
  snapStepFromGridStep,
3278
3278
  scaleFromExtent,
3279
3279
  tickStepFromExtent,
@@ -3282,7 +3282,7 @@ const Util = {
3282
3282
  constrainedTickStepsFromTickSteps,
3283
3283
  DeprecationMixin: DeprecationMixin$1,
3284
3284
  eq: eq$2,
3285
- deepEq: deepEq$6,
3285
+ deepEq: deepEq$5,
3286
3286
  parseQueryString,
3287
3287
  updateQueryString: updateQueryString$2,
3288
3288
  strongEncodeURIComponent,
@@ -3292,7 +3292,7 @@ const Util = {
3292
3292
  resetTouchHandlers,
3293
3293
  extractPointerLocation,
3294
3294
  supportsPassiveEvents,
3295
- captureScratchpadTouchStart: captureScratchpadTouchStart$4,
3295
+ captureScratchpadTouchStart: captureScratchpadTouchStart$3,
3296
3296
  getImageSize,
3297
3297
  getImageSizeModern: getImageSizeModern,
3298
3298
  getRealImageUrl: getRealImageUrl,
@@ -13479,7 +13479,7 @@ ___default["default"].extend(MovableAngle.prototype, {
13479
13479
 
13480
13480
  /* eslint-disable @babel/no-invalid-this */
13481
13481
  const nestedMap$1 = Util.nestedMap;
13482
- const deepEq$5 = Util.deepEq;
13482
+ const deepEq$4 = Util.deepEq;
13483
13483
 
13484
13484
  /**
13485
13485
  * A base class for all Graphie Movables
@@ -13576,7 +13576,7 @@ const createSimpleClass = function (addFunction) {
13576
13576
  this._prevProps = this.props;
13577
13577
  },
13578
13578
  modify: function (graphie) {
13579
- if (!deepEq$5(this.props, this._prevProps)) {
13579
+ if (!deepEq$4(this.props, this._prevProps)) {
13580
13580
  this.remove();
13581
13581
  this.add(graphie);
13582
13582
  this._prevProps = this.props;
@@ -13621,7 +13621,7 @@ var GraphieClasses = {
13621
13621
  * take appropriate action in onMoveStart, onMove, onMoveEnd
13622
13622
  */
13623
13623
  const normalizeOptions$3 = InteractiveUtil.normalizeOptions;
13624
- const assert$9 = InteractiveUtil.assert;
13624
+ const assert$8 = InteractiveUtil.assert;
13625
13625
 
13626
13626
  // state parameters that should be converted into an array of
13627
13627
  // functions
@@ -13692,7 +13692,7 @@ ___default["default"].extend(Movable.prototype, {
13692
13692
  * Simulates a mouse grab event on the movable object.
13693
13693
  */
13694
13694
  grab: function (coord) {
13695
- assert$9(kmath.point.is(coord));
13695
+ assert$8(kmath.point.is(coord));
13696
13696
  const self = this;
13697
13697
  const graphie = self.graphie;
13698
13698
  const state = self.state;
@@ -14158,7 +14158,7 @@ var MovableLineOptions = {
14158
14158
  /**
14159
14159
  * MovableLine
14160
14160
  */
14161
- const assert$8 = InteractiveUtil.assert;
14161
+ const assert$7 = InteractiveUtil.assert;
14162
14162
  const normalizeOptions$2 = InteractiveUtil.normalizeOptions;
14163
14163
  const FUNCTION_ARRAY_OPTIONS$2 = ["add", "draw", "remove", "onMoveStart", "constraints", "onMove", "onMoveEnd"];
14164
14164
 
@@ -14184,8 +14184,8 @@ const DEFAULT_STATE$2 = {
14184
14184
  mouseTarget: null
14185
14185
  };
14186
14186
  const MovableLine$4 = function (graphie, movable, options) {
14187
- assert$8(graphie != null);
14188
- assert$8(options != null);
14187
+ assert$7(graphie != null);
14188
+ assert$7(options != null);
14189
14189
 
14190
14190
  // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
14191
14191
  ___default["default"].extend(this, {
@@ -14742,7 +14742,7 @@ var MovablePointOptions = {
14742
14742
  }
14743
14743
  };
14744
14744
 
14745
- const assert$7 = InteractiveUtil.assert;
14745
+ const assert$6 = InteractiveUtil.assert;
14746
14746
  const normalizeOptions$1 = InteractiveUtil.normalizeOptions;
14747
14747
  const {
14748
14748
  processMath
@@ -14878,7 +14878,7 @@ ___default["default"].extend(MovablePoint$5.prototype, {
14878
14878
  const self = this;
14879
14879
  const graphie = self.graphie;
14880
14880
  const state = ___default["default"].extend(self.state, normalizeOptions$1(FUNCTION_ARRAY_OPTIONS$1, options));
14881
- assert$7(kmath.point.is(state.coord));
14881
+ assert$6(kmath.point.is(state.coord));
14882
14882
 
14883
14883
  // Default things inside the state.normalStyle object, because
14884
14884
  // _.extend is not deep.
@@ -15080,12 +15080,12 @@ ___default["default"].extend(MovablePoint$5.prototype, {
15080
15080
  return result !== false;
15081
15081
  },
15082
15082
  setCoord: function (coord) {
15083
- assert$7(kmath.point.is(coord, 2));
15083
+ assert$6(kmath.point.is(coord, 2));
15084
15084
  this.state.coord = ___default["default"].clone(coord);
15085
15085
  this.draw();
15086
15086
  },
15087
15087
  setCoordConstrained: function (coord) {
15088
- assert$7(kmath.point.is(coord, 2));
15088
+ assert$6(kmath.point.is(coord, 2));
15089
15089
  const result = this._applyConstraints(coord, this.coord());
15090
15090
  if (result !== false) {
15091
15091
  this.state.coord = ___default["default"].clone(result);
@@ -15481,7 +15481,7 @@ var MovablePolygonOptions = {
15481
15481
  * Creates and adds a polygon to the graph that can be dragged around.
15482
15482
  * It allows constraints on its movement and draws when moves happen.
15483
15483
  */
15484
- const assert$6 = InteractiveUtil.assert;
15484
+ const assert$5 = InteractiveUtil.assert;
15485
15485
  const normalizeOptions = InteractiveUtil.normalizeOptions;
15486
15486
 
15487
15487
  // State parameters that should be converted into an array of
@@ -15520,8 +15520,8 @@ const DEFAULT_STATE = {
15520
15520
  mouseTarget: null
15521
15521
  };
15522
15522
  const MovablePolygon = function (graphie, movable, options) {
15523
- assert$6(graphie != null);
15524
- assert$6(options != null);
15523
+ assert$5(graphie != null);
15524
+ assert$5(options != null);
15525
15525
 
15526
15526
  // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
15527
15527
  ___default["default"].extend(this, {
@@ -16039,11 +16039,11 @@ var Movables = {
16039
16039
  const GraphieMovable = GraphieClasses.GraphieMovable;
16040
16040
  const createGraphie = GraphUtils.createGraphie;
16041
16041
  const {
16042
- deepEq: deepEq$4,
16042
+ deepEq: deepEq$3,
16043
16043
  nestedMap
16044
16044
  } = Util;
16045
16045
  const {
16046
- assert: assert$5
16046
+ assert: assert$4
16047
16047
  } = InteractiveUtil;
16048
16048
  class Graphie extends React__namespace.Component {
16049
16049
  graphieDivRef = /*#__PURE__*/React__namespace.createRef();
@@ -16074,7 +16074,7 @@ class Graphie extends React__namespace.Component {
16074
16074
  if (this.props.setup !== prevProps.setup) {
16075
16075
  Log.error("<Graphie> was given a new setup function. " + "This is a bad idea; please refactor your code to give " + "the same setup function reference to <Graphie> on " + "every render.", Errors.Internal);
16076
16076
  }
16077
- if (!deepEq$4(this.props.options, prevProps.options) || !deepEq$4(this.props.box, prevProps.box) || !deepEq$4(this.props.range, prevProps.range)) {
16077
+ if (!deepEq$3(this.props.options, prevProps.options) || !deepEq$3(this.props.box, prevProps.box) || !deepEq$3(this.props.range, prevProps.range)) {
16078
16078
  this._setupGraphie();
16079
16079
  }
16080
16080
  this._updateMovables();
@@ -16218,7 +16218,7 @@ class Graphie extends React__namespace.Component {
16218
16218
 
16219
16219
  // Instantiate the descriptor to turn it into a real Movable
16220
16220
  const child = new childDescriptor.type(childDescriptor.props);
16221
- assert$5(child instanceof GraphieMovable, "All children of a Graphie component must be Graphie " + "movables");
16221
+ assert$4(child instanceof GraphieMovable, "All children of a Graphie component must be Graphie " + "movables");
16222
16222
 
16223
16223
  // Give each child a key
16224
16224
  const keyProp = childDescriptor.key;
@@ -18405,7 +18405,7 @@ const registerWidgets = widgets => {
18405
18405
  * @param name - the widget that you are trying to replace
18406
18406
  * @param replacementName - the name of the widget that takes its place
18407
18407
  *
18408
- * e.g. replaceWidget("transformer", "always-correct") will make it so the
18408
+ * e.g. replaceWidget("transformer", "deprecated-standin") will make it so the
18409
18409
  * transformer widget is replaced by the always correct widget
18410
18410
  */
18411
18411
  const replaceWidget = (name, replacementName) => {
@@ -18416,9 +18416,6 @@ const replaceWidget = (name, replacementName) => {
18416
18416
  return;
18417
18417
  }
18418
18418
  registerWidget(name, substituteWidget);
18419
- if (Log) {
18420
- Log.log(`INFO: Replacing widget ${name} with ${replacementName}`);
18421
- }
18422
18419
  };
18423
18420
  const registerEditors = editorsToRegister => {
18424
18421
  editorsToRegister.forEach(editor => {
@@ -18445,9 +18442,6 @@ const replaceEditor = (name, replacementName) => {
18445
18442
  return;
18446
18443
  }
18447
18444
  editors[name] = substituteEditor;
18448
- if (Log) {
18449
- Log.log(`INFO: Replacing editor ${name} with ${replacementName}`);
18450
- }
18451
18445
  };
18452
18446
  const getWidget = name => {
18453
18447
  // TODO(alex): Consider referring to these as renderers to avoid
@@ -20958,7 +20952,7 @@ class Tooltip extends React__namespace.Component {
20958
20952
 
20959
20953
  /* eslint-disable react/sort-comp */
20960
20954
  const {
20961
- captureScratchpadTouchStart: captureScratchpadTouchStart$3
20955
+ captureScratchpadTouchStart: captureScratchpadTouchStart$2
20962
20956
  } = Util;
20963
20957
  class InputWithExamples extends React__namespace.Component {
20964
20958
  static defaultProps = {
@@ -21016,7 +21010,7 @@ class InputWithExamples extends React__namespace.Component {
21016
21010
  // Add useful props required for MATH and TEXT modes
21017
21011
  ___default["default"].extend(inputProps, {
21018
21012
  onChange: this.props.onChange,
21019
- onTouchStart: captureScratchpadTouchStart$3
21013
+ onTouchStart: captureScratchpadTouchStart$2
21020
21014
  });
21021
21015
 
21022
21016
  // And add final props that are MATH- and TEXT-specific
@@ -23044,7 +23038,7 @@ var ChoiceNoneAbove$1 = /*#__PURE__*/React__namespace.forwardRef((props, ref) =>
23044
23038
  })));
23045
23039
 
23046
23040
  const {
23047
- captureScratchpadTouchStart: captureScratchpadTouchStart$2
23041
+ captureScratchpadTouchStart: captureScratchpadTouchStart$1
23048
23042
  } = Util;
23049
23043
 
23050
23044
  // exported for tests
@@ -23296,7 +23290,7 @@ const BaseRadio = function (props) {
23296
23290
  onClick: clickHandler
23297
23291
  // @ts-expect-error - TS2322 - Type '((e: TouchEvent) => void) | null' is not assignable to type 'TouchEventHandler<HTMLLIElement> | undefined'.
23298
23292
  ,
23299
- onTouchStart: !labelWrap ? null : captureScratchpadTouchStart$2
23293
+ onTouchStart: !labelWrap ? null : captureScratchpadTouchStart$1
23300
23294
  }, /*#__PURE__*/React__namespace.createElement(Element, _extends({}, elementProps, {
23301
23295
  ref: ref
23302
23296
  })));
@@ -26841,9 +26835,9 @@ var Iframe$1 = {
26841
26835
  };
26842
26836
 
26843
26837
  /* eslint-disable react/sort-comp */
26844
- const defaultBoxSize$2 = 400;
26838
+ const defaultBoxSize$1 = 400;
26845
26839
  const defaultRange = [0, 10];
26846
- const defaultBackgroundImage$3 = {
26840
+ const defaultBackgroundImage$2 = {
26847
26841
  url: null,
26848
26842
  width: 0,
26849
26843
  height: 0
@@ -26858,8 +26852,8 @@ class ImageWidget extends React__namespace.Component {
26858
26852
  alignment: DEFAULT_ALIGNMENT,
26859
26853
  title: "",
26860
26854
  range: [defaultRange, defaultRange],
26861
- box: [defaultBoxSize$2, defaultBoxSize$2],
26862
- backgroundImage: defaultBackgroundImage$3,
26855
+ box: [defaultBoxSize$1, defaultBoxSize$1],
26856
+ backgroundImage: defaultBackgroundImage$2,
26863
26857
  labels: [],
26864
26858
  alt: "",
26865
26859
  caption: "",
@@ -27677,7 +27671,7 @@ var Interactive = {
27677
27671
  };
27678
27672
 
27679
27673
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
27680
- const defaultBackgroundImage$2 = {
27674
+ const defaultBackgroundImage$1 = {
27681
27675
  url: null
27682
27676
  };
27683
27677
 
@@ -27713,7 +27707,7 @@ class Graph extends React__namespace.Component {
27713
27707
  gridStep: [1, 1],
27714
27708
  snapStep: [0.5, 0.5],
27715
27709
  markings: "graph",
27716
- backgroundImage: defaultBackgroundImage$2,
27710
+ backgroundImage: defaultBackgroundImage$1,
27717
27711
  showProtractor: false,
27718
27712
  showRuler: false,
27719
27713
  rulerLabel: "",
@@ -27981,7 +27975,7 @@ class Graph extends React__namespace.Component {
27981
27975
  */
27982
27976
  const {
27983
27977
  eq: eq$1,
27984
- deepEq: deepEq$3
27978
+ deepEq: deepEq$2
27985
27979
  } = Util;
27986
27980
 
27987
27981
  // This should really be a readonly tuple of [number, number]
@@ -28094,7 +28088,7 @@ function similar(coords1, coords2, tolerance) {
28094
28088
  angles = rotate(angles, i);
28095
28089
  // @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
28096
28090
  sides = rotate(sides, i);
28097
- if (deepEq$3(angles1, angles)) {
28091
+ if (deepEq$2(angles1, angles)) {
28098
28092
  const sidePairs = ___default["default"].zip(sides1, sides);
28099
28093
  const factors = ___default["default"].map(sidePairs, function (pair) {
28100
28094
  return pair[0] / pair[1];
@@ -28188,11 +28182,11 @@ const {
28188
28182
  DeprecationMixin
28189
28183
  } = Util;
28190
28184
  const TRASH_ICON_URI = "https://ka-perseus-graphie.s3.amazonaws.com/b1452c0d79fd0f7ff4c3af9488474a0a0decb361.png";
28191
- const defaultBackgroundImage$1 = {
28185
+ const defaultBackgroundImage = {
28192
28186
  url: null
28193
28187
  };
28194
28188
  const eq = Util.eq;
28195
- const deepEq$2 = Util.deepEq;
28189
+ const deepEq$1 = Util.deepEq;
28196
28190
  const UNLIMITED = "unlimited";
28197
28191
 
28198
28192
  // Sample background image:
@@ -28249,7 +28243,7 @@ class InteractiveGraph extends React__namespace.Component {
28249
28243
  labels: ["x", "y"],
28250
28244
  range: [[-10, 10], [-10, 10]],
28251
28245
  step: [1, 1],
28252
- backgroundImage: defaultBackgroundImage$1,
28246
+ backgroundImage: defaultBackgroundImage,
28253
28247
  markings: "graph",
28254
28248
  showTooltips: false,
28255
28249
  showProtractor: false,
@@ -29842,7 +29836,7 @@ class InteractiveGraph extends React__namespace.Component {
29842
29836
  const correctCoeffs = this.getQuadraticCoefficients(
29843
29837
  // @ts-expect-error - TS2345 - Argument of type 'readonly Coord[] | undefined' is not assignable to parameter of type 'readonly Coord[]'.
29844
29838
  rubric.correct.coords);
29845
- if (deepEq$2(guessCoeffs, correctCoeffs)) {
29839
+ if (deepEq$1(guessCoeffs, correctCoeffs)) {
29846
29840
  return {
29847
29841
  type: "points",
29848
29842
  earned: 1,
@@ -29858,7 +29852,7 @@ class InteractiveGraph extends React__namespace.Component {
29858
29852
  const canonicalGuessCoeffs = canonicalSineCoefficients(guessCoeffs);
29859
29853
  const canonicalCorrectCoeffs = canonicalSineCoefficients(correctCoeffs);
29860
29854
  // If the canonical coefficients match, it's correct.
29861
- if (deepEq$2(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
29855
+ if (deepEq$1(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
29862
29856
  return {
29863
29857
  type: "points",
29864
29858
  earned: 1,
@@ -29867,7 +29861,7 @@ class InteractiveGraph extends React__namespace.Component {
29867
29861
  };
29868
29862
  }
29869
29863
  } else if (state.type === "circle" && rubric.correct.type === "circle") {
29870
- if (deepEq$2(state.center, rubric.correct.center) && eq(state.radius, rubric.correct.radius)) {
29864
+ if (deepEq$1(state.center, rubric.correct.center) && eq(state.radius, rubric.correct.radius)) {
29871
29865
  return {
29872
29866
  type: "points",
29873
29867
  earned: 1,
@@ -29886,7 +29880,7 @@ class InteractiveGraph extends React__namespace.Component {
29886
29880
  guess?.sort();
29887
29881
  // @ts-expect-error - TS2339 - Property 'sort' does not exist on type 'readonly Coord[]'.
29888
29882
  correct.sort();
29889
- if (deepEq$2(guess, correct)) {
29883
+ if (deepEq$1(guess, correct)) {
29890
29884
  return {
29891
29885
  type: "points",
29892
29886
  earned: 1,
@@ -29909,7 +29903,7 @@ class InteractiveGraph extends React__namespace.Component {
29909
29903
  /* exact */
29910
29904
  guess.sort();
29911
29905
  correct.sort();
29912
- match = deepEq$2(guess, correct);
29906
+ match = deepEq$1(guess, correct);
29913
29907
  }
29914
29908
  if (match) {
29915
29909
  return {
@@ -29925,7 +29919,7 @@ class InteractiveGraph extends React__namespace.Component {
29925
29919
  guess = ___default["default"].invoke(guess, "sort").sort();
29926
29920
  // @ts-expect-error - TS2345 - Argument of type '(readonly Coord[])[] | undefined' is not assignable to parameter of type 'Collection<any>'.
29927
29921
  correct = ___default["default"].invoke(correct, "sort").sort();
29928
- if (deepEq$2(guess, correct)) {
29922
+ if (deepEq$1(guess, correct)) {
29929
29923
  return {
29930
29924
  type: "points",
29931
29925
  earned: 1,
@@ -29938,7 +29932,7 @@ class InteractiveGraph extends React__namespace.Component {
29938
29932
  const correct = rubric.correct.coords;
29939
29933
  if (
29940
29934
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'.
29941
- deepEq$2(guess[0], correct[0]) &&
29935
+ deepEq$1(guess[0], correct[0]) &&
29942
29936
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
29943
29937
  collinear(correct[0], correct[1], guess[1])) {
29944
29938
  return {
@@ -29969,7 +29963,7 @@ class InteractiveGraph extends React__namespace.Component {
29969
29963
  /* exact */
29970
29964
  match =
29971
29965
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
29972
- deepEq$2(guess[1], correct[1]) &&
29966
+ deepEq$1(guess[1], correct[1]) &&
29973
29967
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
29974
29968
  collinear(correct[1], correct[0], guess[0]) &&
29975
29969
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
@@ -31108,7 +31102,7 @@ const AnswerPill = props => {
31108
31102
  id: idFactory.get("perseus-label-image-widget-answer-pill"),
31109
31103
  onClick: correct ? undefined : onClick,
31110
31104
  ref: ref,
31111
- style: [style, popperStyle, styles$h.relative, correct && styles$h.correct, incorrect && styles$h.incorrect, (focused || hovered) && BringToFront]
31105
+ style: [style, popperStyle, styles$h.pill, correct && styles$h.correct, incorrect && styles$h.incorrect, (focused || hovered) && BringToFront]
31112
31106
  }, /*#__PURE__*/React__namespace.createElement(Renderer, {
31113
31107
  content: answerString,
31114
31108
  inline: true
@@ -31122,6 +31116,11 @@ const styles$h = aphrodite.StyleSheet.create({
31122
31116
  },
31123
31117
  incorrect: {
31124
31118
  backgroundColor: Color__default["default"].offBlack64
31119
+ },
31120
+ pill: {
31121
+ // Reset the Pill's default height in order to account
31122
+ // for multi-line pills.
31123
+ height: "auto"
31125
31124
  }
31126
31125
  });
31127
31126
 
@@ -33127,7 +33126,7 @@ var Matcher$1 = {
33127
33126
 
33128
33127
  const {
33129
33128
  firstNumericalParse,
33130
- captureScratchpadTouchStart: captureScratchpadTouchStart$1
33129
+ captureScratchpadTouchStart
33131
33130
  } = Util;
33132
33131
  const toNumericString = KhanMath.toNumericString;
33133
33132
  const getNumericFormat = KhanMath.getNumericFormat;
@@ -33200,7 +33199,7 @@ class NumberInput extends React__namespace.Component {
33200
33199
  onKeyDown: this._onKeyDown
33201
33200
  // @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
33202
33201
  ,
33203
- onTouchStart: captureScratchpadTouchStart$1,
33202
+ onTouchStart: captureScratchpadTouchStart,
33204
33203
  defaultValue: toNumericString(this.props.value, this.state.format),
33205
33204
  value: undefined
33206
33205
  }));
@@ -33326,7 +33325,7 @@ class NumberInput extends React__namespace.Component {
33326
33325
  // Type imports
33327
33326
 
33328
33327
  const {
33329
- assert: assert$4
33328
+ assert: assert$3
33330
33329
  } = InteractiveUtil;
33331
33330
  const {
33332
33331
  stringArrayOfSize
@@ -33360,12 +33359,12 @@ const getDefaultPath$1 = function () {
33360
33359
  };
33361
33360
  const getRowFromPath$1 = function (path) {
33362
33361
  // 'path' should be a (row, column) pair
33363
- assert$4(___default["default"].isArray(path) && path.length === 2);
33362
+ assert$3(___default["default"].isArray(path) && path.length === 2);
33364
33363
  return +path[0];
33365
33364
  };
33366
33365
  const getColumnFromPath$1 = function (path) {
33367
33366
  // 'path' should be a (row, column) pair
33368
- assert$4(___default["default"].isArray(path) && path.length === 2);
33367
+ assert$3(___default["default"].isArray(path) && path.length === 2);
33369
33368
  return +path[1];
33370
33369
  };
33371
33370
  const getRefForPath$1 = function (path) {
@@ -34866,7 +34865,7 @@ const MovablePoint$1 = Graphie.MovablePoint;
34866
34865
  // @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
34867
34866
  const Line$1 = Graphie.Line;
34868
34867
  const {
34869
- assert: assert$3
34868
+ assert: assert$2
34870
34869
  } = InteractiveUtil;
34871
34870
  const bound = (x, gt, lt) => Math.min(Math.max(x, gt), lt);
34872
34871
  const EN_DASH = "\u2013";
@@ -35142,7 +35141,7 @@ class NumberLine extends React__namespace.Component {
35142
35141
  const snapX = props.tickStep / props.snapDivisions;
35143
35142
  let x = bound(numLinePosition, left, right);
35144
35143
  x = left + kmath.number.roundTo(x - left, snapX);
35145
- assert$3(___default["default"].isFinite(x));
35144
+ assert$2(___default["default"].isFinite(x));
35146
35145
  return x;
35147
35146
  };
35148
35147
 
@@ -38249,7 +38248,7 @@ var PassageRefTarget$1 = {
38249
38248
 
38250
38249
  /* eslint-disable react/no-unsafe */
38251
38250
  const {
38252
- deepEq: deepEq$1
38251
+ deepEq
38253
38252
  } = Util;
38254
38253
  class Plotter extends React__namespace.Component {
38255
38254
  // @ts-expect-error - TS2564 - Property 'shouldSetupGraphie' has no initializer and is not definitely assigned in the constructor.
@@ -39042,7 +39041,7 @@ class Plotter extends React__namespace.Component {
39042
39041
  }
39043
39042
  ___default["default"].extend(Plotter, {
39044
39043
  validate: function (guess, rubric) {
39045
- if (deepEq$1(guess, rubric.starting)) {
39044
+ if (deepEq(guess, rubric.starting)) {
39046
39045
  return {
39047
39046
  type: "invalid",
39048
39047
  message: null
@@ -39050,7 +39049,7 @@ ___default["default"].extend(Plotter, {
39050
39049
  }
39051
39050
  return {
39052
39051
  type: "points",
39053
- earned: deepEq$1(guess, rubric.correct) ? 1 : 0,
39052
+ earned: deepEq(guess, rubric.correct) ? 1 : 0,
39054
39053
  total: 1,
39055
39054
  message: null
39056
39055
  };
@@ -39412,7 +39411,7 @@ class InfoTip extends React__namespace.Component {
39412
39411
 
39413
39412
  /* eslint-disable @typescript-eslint/no-unused-vars, react/no-unsafe, react/sort-comp */
39414
39413
  const {
39415
- assert: assert$2
39414
+ assert: assert$1
39416
39415
  } = InteractiveUtil;
39417
39416
  // @ts-expect-error - TS2339 - Property 'Path' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Arc' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Circle' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Label' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Line' does not exist on type 'typeof Graphie'. | TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'. | TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
39418
39417
  const {
@@ -39424,7 +39423,7 @@ const {
39424
39423
  MovablePoint,
39425
39424
  MovableLine
39426
39425
  } = Graphie;
39427
- const defaultBoxSize$1 = 400;
39426
+ const defaultBoxSize = 400;
39428
39427
  const maxSampleSize = 1000;
39429
39428
  class Histogram extends React__namespace.Component {
39430
39429
  static propTypes = {
@@ -39437,7 +39436,7 @@ class Histogram extends React__namespace.Component {
39437
39436
  data: null,
39438
39437
  xAxisLabel: "Proportion (%)",
39439
39438
  yAxisLabel: "Number of times seen",
39440
- box: [defaultBoxSize$1, defaultBoxSize$1]
39439
+ box: [defaultBoxSize, defaultBoxSize]
39441
39440
  };
39442
39441
  UNSAFE_componentWillReceiveProps(nextProps) {
39443
39442
  // Reset the threshold if the range has changed
@@ -39940,7 +39939,7 @@ class Simulator extends React__namespace.Component {
39940
39939
  return true;
39941
39940
  };
39942
39941
  focusInputPath = path => {
39943
- assert$2(path.length > 0);
39942
+ assert$1(path.length > 0);
39944
39943
  const inputID = ___default["default"].head(path);
39945
39944
  // eslint-disable-next-line react/no-string-refs
39946
39945
  const inputComponent = this.refs[inputID];
@@ -39948,7 +39947,7 @@ class Simulator extends React__namespace.Component {
39948
39947
  inputComponent.focus();
39949
39948
  };
39950
39949
  blurInputPath = path => {
39951
- assert$2(path.length > 0);
39950
+ assert$1(path.length > 0);
39952
39951
  const inputID = ___default["default"].head(path);
39953
39952
  // eslint-disable-next-line react/no-string-refs
39954
39953
  const inputComponent = this.refs[inputID];
@@ -39956,17 +39955,17 @@ class Simulator extends React__namespace.Component {
39956
39955
  inputComponent.blur();
39957
39956
  };
39958
39957
  getDOMNodeForPath = path => {
39959
- assert$2(path.length > 0);
39958
+ assert$1(path.length > 0);
39960
39959
  const inputID = ___default["default"].head(path);
39961
39960
  // eslint-disable-next-line react/no-string-refs
39962
39961
  return ReactDOM__default["default"].findDOMNode(this.refs[inputID]);
39963
39962
  };
39964
39963
  getGrammarTypeForPath = path => {
39965
- assert$2(path.length > 0);
39964
+ assert$1(path.length > 0);
39966
39965
  return "number";
39967
39966
  };
39968
39967
  setInputValue = (path, newValue, cb) => {
39969
- assert$2(path.length > 0);
39968
+ assert$1(path.length > 0);
39970
39969
  const inputID = ___default["default"].head(path);
39971
39970
  const capitalizedID = inputID.charAt(0).toUpperCase() + inputID.slice(1);
39972
39971
  const functionName = "handle" + capitalizedID + "Change";
@@ -40126,7 +40125,7 @@ var Sorter$1 = {
40126
40125
  };
40127
40126
 
40128
40127
  const {
40129
- assert: assert$1
40128
+ assert
40130
40129
  } = InteractiveUtil;
40131
40130
 
40132
40131
  /* Input handling: Maps a (row, column) pair to a unique ref used by React,
@@ -40140,12 +40139,12 @@ const getDefaultPath = function () {
40140
40139
  };
40141
40140
  const getRowFromPath = function (path) {
40142
40141
  // 'path' should be a (row, column) pair
40143
- assert$1(___default["default"].isArray(path) && path.length === 2);
40142
+ assert(___default["default"].isArray(path) && path.length === 2);
40144
40143
  return +path[0];
40145
40144
  };
40146
40145
  const getColumnFromPath = function (path) {
40147
40146
  // 'path' should be a (row, column) pair
40148
- assert$1(___default["default"].isArray(path) && path.length === 2);
40147
+ assert(___default["default"].isArray(path) && path.length === 2);
40149
40148
  return +path[1];
40150
40149
  };
40151
40150
  const getRefForPath = function (path) {
@@ -40419,2415 +40418,6 @@ var Table$1 = {
40419
40418
  isLintable: true
40420
40419
  };
40421
40420
 
40422
- const {
40423
- deepEq,
40424
- getGridStep,
40425
- captureScratchpadTouchStart
40426
- } = Util;
40427
- const {
40428
- assert
40429
- } = InteractiveUtil;
40430
- const ROTATE_SNAP_DEGREES = 15;
40431
- const DEGREE_SIGN = "\u00B0";
40432
- const RENDER_TRANSFORM_DELAY_IN_MS = 300;
40433
- const ROTATE_HANDLE_DIST = 1.5;
40434
- const REFLECT_ROTATE_HANDLE_DIST = 2;
40435
- const REFLECT_BUTTON_SIZE = 1;
40436
- const defaultBoxSize = 400;
40437
- const defaultBackgroundImage = {
40438
- url: null
40439
- };
40440
-
40441
- /* Does a pluck on keys inside objects in an object
40442
- *
40443
- * Ex:
40444
- * tools = {
40445
- * translation: {
40446
- * enabled: true
40447
- * },
40448
- * rotation: {
40449
- * enabled: false
40450
- * }
40451
- * };
40452
- * pluckObject(tools, "enabled") returns {
40453
- * translation: true
40454
- * rotation: false
40455
- * }
40456
- */
40457
- function pluckObject(object, subKey) {
40458
- return ___default["default"].object(___default["default"].map(object, function (value, key) {
40459
- return [key, value[subKey]];
40460
- }));
40461
- }
40462
- const defaultGraphProps = function (setProps, boxSize) {
40463
- setProps = setProps || {};
40464
- const labels = setProps.labels || ["x", "y"];
40465
- const range = setProps.range || [[-10, 10], [-10, 10]];
40466
- const step = setProps.step || [1, 1];
40467
- const gridStep = setProps.gridStep || getGridStep(range, step, boxSize);
40468
- return {
40469
- box: [boxSize, boxSize],
40470
- labels: labels,
40471
- range: range,
40472
- step: step,
40473
- gridStep: gridStep,
40474
- valid: true,
40475
- backgroundImage: defaultBackgroundImage,
40476
- markings: "grid",
40477
- showProtractor: false
40478
- };
40479
- };
40480
- const defaultTransformerProps = {
40481
- apiOptions: ApiOptions.defaults,
40482
- gradeEmpty: false,
40483
- graphMode: "interactive",
40484
- listMode: "dynamic",
40485
- graph: {},
40486
- tools: {
40487
- translation: {
40488
- enabled: true,
40489
- required: false,
40490
- constraints: {}
40491
- },
40492
- rotation: {
40493
- enabled: true,
40494
- required: false,
40495
- constraints: {
40496
- fixed: false
40497
- },
40498
- coord: [1, 6]
40499
- },
40500
- reflection: {
40501
- enabled: true,
40502
- required: false,
40503
- constraints: {
40504
- fixed: false
40505
- },
40506
- coords: [[2, -4], [2, 2]]
40507
- },
40508
- dilation: {
40509
- enabled: true,
40510
- required: false,
40511
- constraints: {
40512
- fixed: false
40513
- },
40514
- coord: [6, 6]
40515
- }
40516
- },
40517
- drawSolutionShape: true,
40518
- starting: {
40519
- shape: {
40520
- type: "polygon-3",
40521
- coords: [[2, 2], [2, 6], [7, 2]]
40522
- },
40523
- transformations: []
40524
- },
40525
- correct: {
40526
- shape: {
40527
- type: "polygon-3",
40528
- coords: [[2, 2], [2, 6], [7, 2]]
40529
- },
40530
- transformations: []
40531
- }
40532
- };
40533
- function colorForTool(tool) {
40534
- return tool.constraints.fixed ? KhanColors.DYNAMIC : KhanColors.INTERACTIVE;
40535
- }
40536
-
40537
- /* Scales a distance from the default range of
40538
- * [-10, 10] to a given props.range pair
40539
- *
40540
- * Used for sizing various transformation tools
40541
- * (rotation handle, dilation circle)
40542
- */
40543
- function scaleToRange(dist, range) {
40544
- const spreadX = range[0][1] - range[0][0];
40545
- const spreadY = range[1][1] - range[1][0];
40546
- return dist * Math.max(spreadX, spreadY) / 20;
40547
- }
40548
- function dilatePointFromCenter(point, dilationCenter, scale) {
40549
- const pv = kmath.vector.subtract(point, dilationCenter);
40550
- const pvScaled = kmath.vector.scale(pv, scale);
40551
- const transformedPoint = kmath.vector.add(dilationCenter, pvScaled);
40552
- return transformedPoint;
40553
- }
40554
-
40555
- // TODO(jack): i18nize this
40556
- function stringFromDecimal(number) {
40557
- return String(KhanMath.roundTo(9, number));
40558
- }
40559
- function stringFromFraction(number) {
40560
- const frac = KhanMath.toFraction(number, kmath.number.DEFAULT_TOLERANCE);
40561
- if (frac[1] === 1) {
40562
- return stringFromDecimal(number);
40563
- }
40564
- return stringFromDecimal(frac[0]) + "/" + stringFromDecimal(frac[1]);
40565
- }
40566
- function texFromPoint(point) {
40567
- const {
40568
- TeX
40569
- } = getDependencies();
40570
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
40571
- key: "("
40572
- }, "("), stringFromDecimal(point[0]), /*#__PURE__*/React__namespace.createElement(TeX, {
40573
- key: ","
40574
- }, ", {}"), stringFromDecimal(point[1]), /*#__PURE__*/React__namespace.createElement(TeX, {
40575
- key: ")"
40576
- }, ")")];
40577
- }
40578
- function texFromVector(vector) {
40579
- const {
40580
- TeX
40581
- } = getDependencies();
40582
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
40583
- key: "<"
40584
- }, i18n__namespace.doNotTranslate("\\langle")), stringFromDecimal(vector[0]), /*#__PURE__*/React__namespace.createElement(TeX, {
40585
- key: ","
40586
- }, ", {}"), stringFromDecimal(vector[1]), /*#__PURE__*/React__namespace.createElement(TeX, {
40587
- key: ">"
40588
- }, i18n__namespace.doNotTranslate("\\rangle"))];
40589
- }
40590
- function texFromAngleDeg(angleDeg) {
40591
- return stringFromDecimal(angleDeg) + DEGREE_SIGN;
40592
- }
40593
- function orderInsensitiveCoordsEqual(coords1, coords2) {
40594
- coords1 = ___default["default"].clone(coords1).sort(kmath.point.compare);
40595
- coords2 = ___default["default"].clone(coords2).sort(kmath.point.compare);
40596
- return ___default["default"].all(___default["default"].map(coords1, function (coord1, i) {
40597
- const coord2 = coords2[i];
40598
- return kmath.point.equal(coord1, coord2);
40599
- }));
40600
- }
40601
- const inputComponentForApiOptions = apiOptions => {
40602
- if (apiOptions.customKeypad) {
40603
- return SimpleKeypadInput;
40604
- }
40605
- return NumberInput;
40606
- };
40607
-
40608
- /* Perform operations on raw transform objects */
40609
- const TransformOps = {
40610
- apply: function (transform) {
40611
- // Any transformation with empty text boxes is a no-op until
40612
- // filled out (these show up as nulls in transform.vector/line/etc).
40613
- // TODO (jack): Merge this just into reflections now that other
40614
- // transforms are always valid (after merging transformation
40615
- // collapsing, which may use isValid)
40616
- // @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
40617
- if (!Transformations[transform.type].isValid(transform)) {
40618
- return ___default["default"].identity; // do not transform the coord
40619
- }
40620
- // @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
40621
- return Transformations[transform.type].apply(transform);
40622
- },
40623
- append: function (transformList, newTransform) {
40624
- // Append newTransform to transformList, and collapse the last
40625
- // two transforms if they are collapsable
40626
- const results = TransformOps._appendAndCollapseLastTwo(transformList, newTransform);
40627
- // Collapse any no-ops at the end of the transformation list
40628
- return TransformOps._collapseFinalNoOps(results);
40629
- },
40630
- _collapseFinalNoOps: function (transforms) {
40631
- // Collapse no-op transformations at the end of the list
40632
- if (transforms.length && TransformOps.isNoOp(___default["default"].last(transforms))) {
40633
- return ___default["default"].initial(transforms);
40634
- }
40635
- return transforms;
40636
- },
40637
- _appendAndCollapseLastTwo: function (transformList, newTransform) {
40638
- if (!transformList.length) {
40639
- return [newTransform];
40640
- }
40641
- const collapsed = TransformOps.collapse(___default["default"].last(transformList), newTransform);
40642
- return ___default["default"].initial(transformList).concat(collapsed);
40643
- },
40644
- isNoOp: function (transform) {
40645
- return Transformations[transform.type].isNoOp(transform);
40646
- },
40647
- collapse: function (transform1, transform2) {
40648
- // We can only collapse transforms that have the same type
40649
- if (transform1.type !== transform2.type) {
40650
- return [transform1, transform2];
40651
- }
40652
-
40653
- // Clicking the button again removes empty transformations
40654
- if (TransformOps.isEmpty(transform1) && TransformOps.isEmpty(transform2)) {
40655
- return [];
40656
- }
40657
-
40658
- // Don't collapse invalid transformations otherwise
40659
- if (!TransformOps.isValid(transform1) || !TransformOps.isValid(transform2)) {
40660
- return [transform1, transform2];
40661
- }
40662
- return TransformOps._collapseValidMonotypedTransforms(transform1, transform2);
40663
- },
40664
- isValid: function (transform) {
40665
- // @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
40666
- return Transformations[transform.type].isValid(transform);
40667
- },
40668
- isEmpty: function (transform) {
40669
- // @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
40670
- return Transformations[transform.type].isEmpty(transform);
40671
- },
40672
- _collapseValidMonotypedTransforms: function (transform1, transform2) {
40673
- let collapsed = Transformations[transform1.type].collapse(transform1, transform2);
40674
- if (collapsed) {
40675
- // Force all answers into an array
40676
- if (!___default["default"].isArray(collapsed)) {
40677
- collapsed = [collapsed];
40678
- }
40679
- // Add types to all transforms in the answer
40680
- ___default["default"].each(collapsed, function (transform) {
40681
- transform.type = transform1.type;
40682
- });
40683
- return collapsed;
40684
- }
40685
- // These transforms can't be collapsed together
40686
- return [transform1, transform2];
40687
- },
40688
- toTeX: function (transform) {
40689
- return Transformations[transform.type].toTeX(transform);
40690
- },
40691
- /* A react representation of this transform object */
40692
- ListItem: createReactClass__default["default"]({
40693
- displayName: "ListItem",
40694
- render: function () {
40695
- if (this.props.mode === "dynamic") {
40696
- return /*#__PURE__*/React__namespace.createElement("div", null, TransformOps.toTeX(this.props.transform));
40697
- }
40698
- if (this.props.mode === "interactive") {
40699
- const TransformClass = Transformations[this.props.transform.type].Input;
40700
- return /*#__PURE__*/React__namespace.createElement(TransformClass
40701
- // eslint-disable-next-line react/no-string-refs
40702
- , _extends({
40703
- ref: "transform",
40704
- onChange: this.handleChange,
40705
- onFocus: this.props.onFocus,
40706
- onBlur: this.props.onBlur,
40707
- keypadElement: this.props.keypadElement,
40708
- apiOptions: this.props.apiOptions
40709
- }, this.props.transform));
40710
- }
40711
- throw new PerseusError("Invalid mode: " + this.props.mode, Errors.InvalidInput);
40712
- },
40713
- value: function () {
40714
- if (this.props.mode === "interactive") {
40715
- return ___default["default"].extend({
40716
- type: this.props.transform.type
40717
- },
40718
- // eslint-disable-next-line react/no-string-refs
40719
- this.refs.transform.value());
40720
- }
40721
- return this.props.transform;
40722
- },
40723
- handleChange: ___default["default"].debounce(function (callback) {
40724
- // @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.
40725
- this.props.onChange(this.value(), callback);
40726
- }, RENDER_TRANSFORM_DELAY_IN_MS),
40727
- /* InputPath API: depending on the API call, this could involve simply
40728
- * navigating to the right ref and calling the function on that
40729
- * component, or threading the call down and returning the result. */
40730
- _getComponentAtPath: function (path) {
40731
- // eslint-disable-next-line react/no-string-refs
40732
- const transform = this.refs.transform;
40733
- const ref = ___default["default"].head(path);
40734
- return transform.refs[ref];
40735
- },
40736
- focus: function () {
40737
- // eslint-disable-next-line react/no-string-refs
40738
- const transform = this.refs.transform;
40739
- const path = ___default["default"].head(transform.getInputPaths());
40740
- if (path) {
40741
- this.focusInputPath(path);
40742
- }
40743
- },
40744
- focusInputPath: function (path) {
40745
- this._getComponentAtPath(path).focus();
40746
- },
40747
- blurInputPath: function (path) {
40748
- this._getComponentAtPath(path).blur();
40749
- },
40750
- getDOMNodeForPath: function (path) {
40751
- return ReactDOM__default["default"].findDOMNode(this._getComponentAtPath(path));
40752
- },
40753
- getGrammarTypeForPath: function (path) {
40754
- return "number";
40755
- },
40756
- setInputValue: function (path, value, cb) {
40757
- // `value` comes in as a string on mobile, but we need a number
40758
- // We let through the empty string so that "Clear" works -- in
40759
- // that case, the transformer widget will just act as if there is
40760
- // no input, which is what we want.
40761
- // @ts-expect-error - TS2339 - Property 'length' does not exist on type 'string | number'.
40762
- if (value.length) {
40763
- // @ts-expect-error - TS2345 - Argument of type 'string | number' is not assignable to parameter of type 'string'.
40764
- value = parseFloat(value);
40765
- if (isNaN(value)) {
40766
- return;
40767
- }
40768
- }
40769
- // eslint-disable-next-line react/no-string-refs
40770
- this.refs.transform.setInputValue(path, value, cb);
40771
- },
40772
- getInputPaths: function () {
40773
- // If we're in dynamic mode, then the list items are made up of
40774
- // static text.
40775
- if (this.props.mode === "dynamic") {
40776
- return [];
40777
- }
40778
- // eslint-disable-next-line react/no-string-refs
40779
- return this.refs.transform.getInputPaths();
40780
- }
40781
- })
40782
- };
40783
- const Transformations = {
40784
- translation: {
40785
- // I18N: As in the command, "Translate the polygon"
40786
- verbName: i18n__namespace._("Translate"),
40787
- nounName: i18n__namespace._("Translation"),
40788
- lowerNounName: i18n__namespace._("translation"),
40789
- apply: function (transform) {
40790
- return function (coord) {
40791
- return kmath.vector.add(coord, transform.vector);
40792
- };
40793
- },
40794
- isValid: function (transform) {
40795
- return ___default["default"].isFinite(transform.vector[0]) && ___default["default"].isFinite(transform.vector[1]);
40796
- },
40797
- isEmpty: function (transform) {
40798
- return transform.vector[0] === null && transform.vector[1] === null;
40799
- },
40800
- isNoOp: function (transform) {
40801
- return kmath.vector.equal(transform.vector, [0, 0]);
40802
- },
40803
- collapse: function (transform1, transform2) {
40804
- return {
40805
- vector: kmath.vector.add(transform1.vector, transform2.vector)
40806
- };
40807
- },
40808
- toTeX: function (transform) {
40809
- // I18N: As in the command, "Translation by <3, 1>"
40810
- return i18n__namespace.$_("Translation by %(vector)s", {
40811
- vector: texFromVector(transform.vector)
40812
- });
40813
- },
40814
- Input: class extends React__namespace.Component {
40815
- state = {
40816
- vector: this.props.vector || [null, null]
40817
- };
40818
- componentDidUpdate(prevProps) {
40819
- if (!deepEq(this.props, prevProps)) {
40820
- this.setState({
40821
- vector: this.props.vector
40822
- });
40823
- }
40824
- }
40825
- render() {
40826
- const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
40827
- const {
40828
- TeX
40829
- } = getDependencies();
40830
- const vector = [/*#__PURE__*/React__namespace.createElement(TeX, {
40831
- key: "<"
40832
- }, i18n__namespace.doNotTranslate("\\langle")), /*#__PURE__*/React__namespace.createElement(InputComponent, {
40833
- key: "vec_x"
40834
- // eslint-disable-next-line react/no-string-refs
40835
- ,
40836
- ref: "x",
40837
- placeholder: 0,
40838
- value: this.state.vector[0],
40839
- useArrowKeys: true,
40840
- onChange: val0 => {
40841
- const val1 = this.state.vector[1];
40842
- this.setState({
40843
- vector: [val0, val1]
40844
- }, () => {
40845
- this.props.onChange();
40846
- });
40847
- },
40848
- onFocus: ___default["default"].partial(this.props.onFocus, "x"),
40849
- onBlur: ___default["default"].partial(this.props.onBlur, "x"),
40850
- keypadElement: this.props.keypadElement
40851
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
40852
- key: ","
40853
- }, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
40854
- key: "vec_y"
40855
- // eslint-disable-next-line react/no-string-refs
40856
- ,
40857
- ref: "y",
40858
- placeholder: 0,
40859
- value: this.state.vector[1],
40860
- useArrowKeys: true,
40861
- onChange: val1 => {
40862
- const val0 = this.state.vector[0];
40863
- this.setState({
40864
- vector: [val0, val1]
40865
- }, () => {
40866
- this.props.onChange();
40867
- });
40868
- },
40869
- onFocus: ___default["default"].partial(this.props.onFocus, "y"),
40870
- onBlur: ___default["default"].partial(this.props.onBlur, "y"),
40871
- keypadElement: this.props.keypadElement
40872
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
40873
- key: ">"
40874
- }, i18n__namespace.doNotTranslate("\\rangle"))];
40875
- return /*#__PURE__*/React__namespace.createElement("div", null, i18n__namespace.$_("Translation by %(vector)s", {
40876
- vector: vector
40877
- }));
40878
- }
40879
- value = () => {
40880
- // eslint-disable-next-line react/no-string-refs
40881
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
40882
- const x = this.refs.x.getValue();
40883
- // eslint-disable-next-line react/no-string-refs
40884
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
40885
- const y = this.refs.y.getValue();
40886
- return {
40887
- vector: [x, y]
40888
- };
40889
- };
40890
-
40891
- /* InputPath API */
40892
- setInputValue = (path, value, cb) => {
40893
- const id = ___default["default"].first(path);
40894
- const vector = ___default["default"].clone(this.state.vector);
40895
- if (id === "x") {
40896
- vector[0] = value;
40897
- } else if (id === "y") {
40898
- vector[1] = value;
40899
- }
40900
- this.setState({
40901
- vector: vector
40902
- }, () => {
40903
- this.props.onChange(cb);
40904
- });
40905
- };
40906
- getInputPaths = () => {
40907
- return [["x"], ["y"]];
40908
- };
40909
- }
40910
- },
40911
- rotation: {
40912
- // I18N: As in the command, "Rotate the polygon"
40913
- verbName: i18n__namespace._("Rotate"),
40914
- nounName: i18n__namespace._("Rotation"),
40915
- lowerNounName: i18n__namespace._("rotation"),
40916
- apply: function (transform) {
40917
- return function (coord) {
40918
- return kmath.point.rotateDeg(coord, transform.angleDeg, transform.center);
40919
- };
40920
- },
40921
- isValid: function (transform) {
40922
- return ___default["default"].isFinite(transform.angleDeg) && ___default["default"].isFinite(transform.center[0]) && ___default["default"].isFinite(transform.center[1]);
40923
- },
40924
- isEmpty: function (transform) {
40925
- return transform.angleDeg === null && transform.center[0] === null && transform.center[1] === null;
40926
- },
40927
- isNoOp: function (transform) {
40928
- return kmath.number.equal(transform.angleDeg, 0);
40929
- },
40930
- collapse: function (transform1, transform2) {
40931
- if (!kmath.point.equal(transform1.center, transform2.center)) {
40932
- return false;
40933
- }
40934
- return {
40935
- center: transform1.center,
40936
- angleDeg: transform1.angleDeg + transform2.angleDeg
40937
- };
40938
- },
40939
- toTeX: function (transform) {
40940
- return i18n__namespace.$_("Rotation by %(degrees)s about %(point)s", {
40941
- degrees: texFromAngleDeg(transform.angleDeg),
40942
- point: texFromPoint(transform.center)
40943
- });
40944
- },
40945
- Input: class extends React__namespace.Component {
40946
- state = {
40947
- center: this.props.center || [null, null],
40948
- angleDeg: this.props.angleDeg || null
40949
- };
40950
- componentDidUpdate(prevProps) {
40951
- if (!deepEq(this.props, prevProps)) {
40952
- this.setState({
40953
- center: this.props.center,
40954
- angleDeg: this.props.angleDeg
40955
- });
40956
- }
40957
- }
40958
- render() {
40959
- const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
40960
- const {
40961
- TeX
40962
- } = getDependencies();
40963
- const point = [/*#__PURE__*/React__namespace.createElement(TeX, {
40964
- key: "("
40965
- }, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
40966
- key: "X"
40967
- // eslint-disable-next-line react/no-string-refs
40968
- ,
40969
- ref: "centerX",
40970
- placeholder: 0,
40971
- value: this.state.center[0],
40972
- useArrowKeys: true,
40973
- onChange: val0 => {
40974
- const val1 = this.state.center[1];
40975
- this.setState({
40976
- center: [val0, val1]
40977
- }, () => {
40978
- this.props.onChange();
40979
- });
40980
- },
40981
- onFocus: ___default["default"].partial(this.props.onFocus, "centerX"),
40982
- onBlur: ___default["default"].partial(this.props.onBlur, "centerX"),
40983
- keypadElement: this.props.keypadElement
40984
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
40985
- key: ","
40986
- }, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
40987
- key: "Y"
40988
- // eslint-disable-next-line react/no-string-refs
40989
- ,
40990
- ref: "centerY",
40991
- placeholder: 0,
40992
- value: this.state.center[1],
40993
- useArrowKeys: true,
40994
- onChange: val1 => {
40995
- const val0 = this.state.center[0];
40996
- this.setState({
40997
- center: [val0, val1]
40998
- }, () => {
40999
- this.props.onChange();
41000
- });
41001
- },
41002
- onFocus: ___default["default"].partial(this.props.onFocus, "centerY"),
41003
- onBlur: ___default["default"].partial(this.props.onBlur, "centerY"),
41004
- keypadElement: this.props.keypadElement
41005
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
41006
- key: ")"
41007
- }, ")")];
41008
- const degrees = [/*#__PURE__*/React__namespace.createElement(InputComponent, {
41009
- key: "deg"
41010
- // eslint-disable-next-line react/no-string-refs
41011
- ,
41012
- ref: "angleDeg",
41013
- placeholder: 0,
41014
- value: this.state.angleDeg,
41015
- useArrowKeys: true,
41016
- onChange: val => {
41017
- this.setState({
41018
- angleDeg: val
41019
- }, () => {
41020
- this.props.onChange();
41021
- });
41022
- },
41023
- onFocus: ___default["default"].partial(this.props.onFocus, "angleDeg"),
41024
- onBlur: ___default["default"].partial(this.props.onBlur, "angleDeg"),
41025
- keypadElement: this.props.keypadElement
41026
- }), DEGREE_SIGN];
41027
- // I18N: %(point)s must come before %(degrees)s in this phrase
41028
- const text = i18n__namespace.$_("Rotation about %(point)s by %(degrees)s", {
41029
- point,
41030
- degrees
41031
- });
41032
- return /*#__PURE__*/React__namespace.createElement("div", null, text);
41033
- }
41034
- value = () => {
41035
- // eslint-disable-next-line react/no-string-refs
41036
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41037
- const angleDeg = this.refs.angleDeg.getValue();
41038
- // eslint-disable-next-line react/no-string-refs
41039
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41040
- const centerX = this.refs.centerX.getValue();
41041
- // eslint-disable-next-line react/no-string-refs
41042
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41043
- const centerY = this.refs.centerY.getValue();
41044
- return {
41045
- angleDeg: angleDeg,
41046
- center: [centerX, centerY]
41047
- };
41048
- };
41049
-
41050
- /* InputPath API */
41051
- setInputValue = (path, value, cb) => {
41052
- const id = ___default["default"].first(path);
41053
- let angleDeg = ___default["default"].clone(this.state.angleDeg);
41054
- const center = ___default["default"].clone(this.state.center);
41055
- if (id === "angleDeg") {
41056
- angleDeg = value;
41057
- } else if (id === "centerX") {
41058
- center[0] = value;
41059
- } else if (id === "centerY") {
41060
- center[1] = value;
41061
- }
41062
- this.setState({
41063
- angleDeg: angleDeg,
41064
- center: center
41065
- }, () => {
41066
- this.props.onChange(cb);
41067
- });
41068
- };
41069
- getInputPaths = () => {
41070
- return [["centerX"], ["centerY"], ["angleDeg"]];
41071
- };
41072
- }
41073
- },
41074
- reflection: {
41075
- // I18N: As in the command, "Reflect the polygon"
41076
- verbName: i18n__namespace._("Reflect"),
41077
- nounName: i18n__namespace._("Reflection"),
41078
- lowerNounName: i18n__namespace._("reflection"),
41079
- apply: function (transform) {
41080
- return function (coord) {
41081
- return kmath.point.reflectOverLine(coord, transform.line);
41082
- };
41083
- },
41084
- isValid: function (transform) {
41085
- // A bit hacky, but we'll also define reflecting over a
41086
- // single point as a no-op, to avoid NaN fun.
41087
- return ___default["default"].all(___default["default"].flatten(transform.line), ___default["default"].isFinite) && !kmath.point.equal(transform.line[0], transform.line[1]);
41088
- },
41089
- isEmpty: function (transform) {
41090
- return ___default["default"].all(___default["default"].flatten(transform.line), ___default["default"].isNull);
41091
- },
41092
- isNoOp: function (transform) {
41093
- // Invalid transforms are implicitly no-ops, so we don't
41094
- // have to catch that case here.
41095
- return false;
41096
- },
41097
- collapse: function (transform1, transform2) {
41098
- if (!kmath.line.equal(transform1.line, transform2.line)) {
41099
- return false;
41100
- }
41101
- return [];
41102
- },
41103
- toTeX: function (transform) {
41104
- const point1 = transform.line[0];
41105
- const point2 = transform.line[1];
41106
- return i18n__namespace.$_("Reflection over the line from %(point1)s to %(point2)s", {
41107
- point1: texFromPoint(point1),
41108
- point2: texFromPoint(point2)
41109
- });
41110
- },
41111
- Input: class extends React__namespace.Component {
41112
- state = {
41113
- line: this.props.line || [[null, null], [null, null]]
41114
- };
41115
- componentDidUpdate(prevProps) {
41116
- if (!deepEq(this.props, prevProps)) {
41117
- this.setState({
41118
- line: this.props.line
41119
- });
41120
- }
41121
- }
41122
- render() {
41123
- const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
41124
- const {
41125
- TeX
41126
- } = getDependencies();
41127
- const point1 = [/*#__PURE__*/React__namespace.createElement(TeX, {
41128
- key: "("
41129
- }, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
41130
- key: "x1"
41131
- // eslint-disable-next-line react/no-string-refs
41132
- ,
41133
- ref: "x1",
41134
- value: this.state.line[0][0],
41135
- useArrowKeys: true
41136
- // eslint-disable-next-line react/jsx-no-bind
41137
- ,
41138
- onChange: this.changePoint.bind(this, 0, 0),
41139
- onFocus: ___default["default"].partial(this.props.onFocus, "x1"),
41140
- onBlur: ___default["default"].partial(this.props.onBlur, "x1"),
41141
- keypadElement: this.props.keypadElement
41142
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
41143
- key: ","
41144
- }, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
41145
- key: "y1"
41146
- // eslint-disable-next-line react/no-string-refs
41147
- ,
41148
- ref: "y1",
41149
- value: this.state.line[0][1],
41150
- useArrowKeys: true
41151
- // eslint-disable-next-line react/jsx-no-bind
41152
- ,
41153
- onChange: this.changePoint.bind(this, 0, 1),
41154
- onFocus: ___default["default"].partial(this.props.onFocus, "y1"),
41155
- onBlur: ___default["default"].partial(this.props.onBlur, "y1"),
41156
- keypadElement: this.props.keypadElement
41157
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
41158
- key: ")"
41159
- }, ")")];
41160
- const point2 = [/*#__PURE__*/React__namespace.createElement(TeX, {
41161
- key: "("
41162
- }, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
41163
- key: "x2"
41164
- // eslint-disable-next-line react/no-string-refs
41165
- ,
41166
- ref: "x2",
41167
- value: this.state.line[1][0],
41168
- useArrowKeys: true
41169
- // eslint-disable-next-line react/jsx-no-bind
41170
- ,
41171
- onChange: this.changePoint.bind(this, 1, 0),
41172
- onFocus: ___default["default"].partial(this.props.onFocus, "x2"),
41173
- onBlur: ___default["default"].partial(this.props.onBlur, "x2"),
41174
- keypadElement: this.props.keypadElement
41175
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
41176
- key: ","
41177
- }, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
41178
- key: "y2"
41179
- // eslint-disable-next-line react/no-string-refs
41180
- ,
41181
- ref: "y2",
41182
- value: this.state.line[1][1],
41183
- useArrowKeys: true
41184
- // eslint-disable-next-line react/jsx-no-bind
41185
- ,
41186
- onChange: this.changePoint.bind(this, 1, 1),
41187
- onFocus: ___default["default"].partial(this.props.onFocus, "y2"),
41188
- onBlur: ___default["default"].partial(this.props.onBlur, "y2"),
41189
- keypadElement: this.props.keypadElement
41190
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
41191
- key: ")"
41192
- }, ")")];
41193
- return /*#__PURE__*/React__namespace.createElement("div", null, i18n__namespace.$_("Reflection over the line from " + "%(point1)s to %(point2)s", {
41194
- point1,
41195
- point2
41196
- }));
41197
- }
41198
- changePoint = (i, j, val, cb) => {
41199
- const line = ___default["default"].map(this.state.line, ___default["default"].clone);
41200
- // @ts-expect-error - TS2538 - Type 'undefined' cannot be used as an index type.
41201
- line[i][j] = val;
41202
- this.setState({
41203
- line: line
41204
- }, () => {
41205
- this.props.onChange(cb);
41206
- });
41207
- };
41208
- value = () => {
41209
- // eslint-disable-next-line react/no-string-refs
41210
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41211
- const x1 = this.refs.x1.getValue();
41212
- // eslint-disable-next-line react/no-string-refs
41213
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41214
- const y1 = this.refs.y1.getValue();
41215
- // eslint-disable-next-line react/no-string-refs
41216
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41217
- const x2 = this.refs.x2.getValue();
41218
- // eslint-disable-next-line react/no-string-refs
41219
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41220
- const y2 = this.refs.y2.getValue();
41221
- return {
41222
- line: [[x1, y1], [x2, y2]]
41223
- };
41224
- };
41225
-
41226
- /* InputPath API */
41227
- setInputValue = (path, value, cb) => {
41228
- const id = ___default["default"].first(path);
41229
- let j;
41230
- if (id[0] === "x") {
41231
- j = 0;
41232
- } else if (id[0] === "y") {
41233
- j = 1;
41234
- }
41235
- let i;
41236
- if (id[1] === "1") {
41237
- i = 0;
41238
- } else if (id[1] === "2") {
41239
- i = 1;
41240
- }
41241
- this.changePoint(i, j, value, cb);
41242
- };
41243
- getInputPaths = () => {
41244
- return [["x1"], ["y1"], ["x2"], ["y2"]];
41245
- };
41246
- }
41247
- },
41248
- dilation: {
41249
- // I18N: As in the command, "Dilate the polygon"
41250
- verbName: i18n__namespace._("Dilate"),
41251
- nounName: i18n__namespace._("Dilation"),
41252
- lowerNounName: i18n__namespace._("dilation"),
41253
- apply: function (transform) {
41254
- return function (coord) {
41255
- return dilatePointFromCenter(coord, transform.center, transform.scale);
41256
- };
41257
- },
41258
- isValid: function (transform) {
41259
- return ___default["default"].isFinite(transform.scale) && ___default["default"].isFinite(transform.center[0]) && ___default["default"].isFinite(transform.center[1]);
41260
- },
41261
- isEmpty: function (transform) {
41262
- return transform.scale === null && transform.center[0] === null && transform.center[1] === null;
41263
- },
41264
- isNoOp: function (transform) {
41265
- return kmath.number.equal(transform.scale, 1);
41266
- },
41267
- collapse: function (transform1, transform2) {
41268
- if (!kmath.point.equal(transform1.center, transform2.center)) {
41269
- return false;
41270
- }
41271
- return {
41272
- center: transform1.center,
41273
- scale: transform1.scale * transform2.scale
41274
- };
41275
- },
41276
- toTeX: function (transform) {
41277
- const scaleString = stringFromFraction(transform.scale);
41278
- return i18n__namespace.$_("Dilation of scale %(scale)s about %(point)s", {
41279
- scale: scaleString,
41280
- point: texFromPoint(transform.center)
41281
- });
41282
- },
41283
- Input: class extends React__namespace.Component {
41284
- state = {
41285
- center: this.props.center || [null, null],
41286
- scale: this.props.scale || null
41287
- };
41288
- componentDidUpdate(prevProps) {
41289
- if (!deepEq(this.props, prevProps)) {
41290
- this.setState({
41291
- center: this.props.center,
41292
- scale: this.props.scale
41293
- });
41294
- }
41295
- }
41296
- render() {
41297
- const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
41298
- const {
41299
- TeX
41300
- } = getDependencies();
41301
- const point = [/*#__PURE__*/React__namespace.createElement(TeX, {
41302
- key: "("
41303
- }, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
41304
- key: "point_x"
41305
- // eslint-disable-next-line react/no-string-refs
41306
- ,
41307
- ref: "x",
41308
- placeholder: 0,
41309
- value: this.state.center[0],
41310
- useArrowKeys: true,
41311
- onChange: val0 => {
41312
- const val1 = this.state.center[1];
41313
- this.setState({
41314
- center: [val0, val1]
41315
- }, () => {
41316
- this.props.onChange();
41317
- });
41318
- },
41319
- onFocus: ___default["default"].partial(this.props.onFocus, "x"),
41320
- onBlur: ___default["default"].partial(this.props.onBlur, "x"),
41321
- keypadElement: this.props.keypadElement
41322
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
41323
- key: ","
41324
- }, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
41325
- key: "point_y"
41326
- // eslint-disable-next-line react/no-string-refs
41327
- ,
41328
- ref: "y",
41329
- placeholder: 0,
41330
- value: this.state.center[1],
41331
- useArrowKeys: true,
41332
- onChange: val1 => {
41333
- const val0 = this.state.center[0];
41334
- this.setState({
41335
- center: [val0, val1]
41336
- }, () => {
41337
- this.props.onChange();
41338
- });
41339
- },
41340
- onFocus: ___default["default"].partial(this.props.onFocus, "y"),
41341
- onBlur: ___default["default"].partial(this.props.onBlur, "y"),
41342
- keypadElement: this.props.keypadElement
41343
- }), /*#__PURE__*/React__namespace.createElement(TeX, {
41344
- key: ")"
41345
- }, ")")];
41346
- const scale = /*#__PURE__*/React__namespace.createElement(InputComponent
41347
- // eslint-disable-next-line react/no-string-refs
41348
- , {
41349
- ref: "scale",
41350
- placeholder: 1,
41351
- value: this.state.scale,
41352
- useArrowKeys: true,
41353
- onChange: val => {
41354
- this.setState({
41355
- scale: val
41356
- }, () => {
41357
- this.props.onChange();
41358
- });
41359
- },
41360
- onFocus: ___default["default"].partial(this.props.onFocus, "scale"),
41361
- onBlur: ___default["default"].partial(this.props.onBlur, "scale"),
41362
- keypadElement: this.props.keypadElement
41363
- });
41364
- return /*#__PURE__*/React__namespace.createElement("div", null, i18n__namespace.$_("Dilation about %(point)s by %(scale)s", {
41365
- point,
41366
- scale
41367
- }));
41368
- }
41369
- value = () => {
41370
- // eslint-disable-next-line react/no-string-refs
41371
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41372
- const scale = this.refs.scale.getValue();
41373
- // eslint-disable-next-line react/no-string-refs
41374
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41375
- const x = this.refs.x.getValue();
41376
- // eslint-disable-next-line react/no-string-refs
41377
- // @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
41378
- const y = this.refs.y.getValue();
41379
- return {
41380
- scale: scale,
41381
- center: [x, y]
41382
- };
41383
- };
41384
-
41385
- /* InputPath API */
41386
- setInputValue = (path, value, cb) => {
41387
- const id = ___default["default"].first(path);
41388
- let scale = this.state.scale;
41389
- const center = ___default["default"].clone(this.state.center);
41390
- if (id === "x") {
41391
- center[0] = value;
41392
- } else if (id === "y") {
41393
- center[1] = value;
41394
- } else if (id === "scale") {
41395
- scale = value;
41396
- }
41397
- this.setState({
41398
- scale: scale,
41399
- center: center
41400
- }, () => {
41401
- this.props.onChange(cb);
41402
- });
41403
- };
41404
- getInputPaths = () => {
41405
- return [["x"], ["y"], ["scale"]];
41406
- };
41407
- }
41408
- }
41409
- };
41410
-
41411
- /* Various functions to deal with different shape types */
41412
- const ShapeTypes = {
41413
- getPointCountForType: function (type) {
41414
- const splitType = type.split("-");
41415
- if (splitType[0] === "polygon") {
41416
- return splitType[1] || 3;
41417
- }
41418
- if (splitType[0] === "line" || splitType[0] === "lineSegment") {
41419
- return 2;
41420
- }
41421
- if (splitType[0] === "angle") {
41422
- return 3;
41423
- }
41424
- if (splitType[0] === "circle") {
41425
- return 2;
41426
- }
41427
- if (splitType[0] === "point") {
41428
- return 1;
41429
- }
41430
- },
41431
- addMovableShape: function (graphie, options) {
41432
- if (options.editable && options.translatable) {
41433
- throw new PerseusError("It doesn't make sense to have a movable shape " + "where you can stretch the points and translate them " + "simultaneously. options: " + JSON.stringify(options), Errors.InvalidInput);
41434
- }
41435
- const points = ___default["default"].map(options.shape.coords, function (coord) {
41436
- let isMoving = false;
41437
- let previousCoord = coord;
41438
- const onMove = function (x, y) {
41439
- if (!isMoving) {
41440
- previousCoord = currentPoint.coord;
41441
- isMoving = true;
41442
- }
41443
- let moveVector = kmath.vector.subtract([x, y], currentPoint.coord);
41444
-
41445
- // Translate from (x, y) semantics to (dX, dY) semantics
41446
- // This is more useful for translations on multiple points,
41447
- // where we care about how the points moved, not where any
41448
- // individual point ended up
41449
- if (options.onMove) {
41450
- moveVector = options.onMove(moveVector[0], moveVector[1]);
41451
- }
41452
-
41453
- // Perform a translation on all points in this shape when
41454
- // any point moves
41455
- if (options.translatable) {
41456
- ___default["default"].each(points, function (point) {
41457
- // The point itself will be updated by the
41458
- // movablePoint class, so only translate the other
41459
- // points
41460
- if (point !== currentPoint) {
41461
- point.setCoord(kmath.vector.add(point.coord, moveVector));
41462
- }
41463
- });
41464
- }
41465
-
41466
- // Update our shape and our currentPoint
41467
- // Without this, some shapes (circles, angles) appear
41468
- // "bouncy" as they are updated with currentPoint at the
41469
- // current mouse coordinate (oldCoord), rather than newCoord
41470
- const oldCoord = currentPoint.coord;
41471
- const newCoord = kmath.vector.add(currentPoint.coord, moveVector);
41472
- // Temporarily change our coordinate so that
41473
- // shape.update() sees the new coordinate
41474
- currentPoint.coord = newCoord;
41475
- shape.update();
41476
- // ...But don't break onMove, which assumes it
41477
- // is the only thing changing our coord
41478
- currentPoint.coord = oldCoord;
41479
- return newCoord;
41480
- };
41481
- const onMoveEnd = function () {
41482
- // onMove isn't guaranteed to be called before onMoveEnd, so
41483
- // we have to take into account that we may not have moved and
41484
- // set previousCoord.
41485
- if (options.onMoveEnd && isMoving) {
41486
- isMoving = false;
41487
- // We don't use the supplied x and y parameters here
41488
- // because MovablePoint's onMoveEnd semantics suck.
41489
- // It returns the mouseX, mouseY without processing them
41490
- // through onMove, leaving us with weird fractional moves
41491
- const change = kmath.vector.subtract(currentPoint.coord, previousCoord);
41492
- options.onMoveEnd(change[0], change[1]);
41493
- }
41494
- shape.update();
41495
- };
41496
- const currentPoint = graphie.addMovablePoint({
41497
- coord: coord,
41498
- normalStyle: options.normalPointStyle,
41499
- highlightStyle: options.highlightPointStyle,
41500
- constraints: {
41501
- fixed: !options.translatable && !options.editable
41502
- },
41503
- visible: options.showPoints,
41504
- snapX: options.snap && options.snap[0] || 0,
41505
- snapY: options.snap && options.snap[1] || 0,
41506
- bounded: false,
41507
- // Don't bound it when placing it on the graph
41508
- onMove: onMove,
41509
- onMoveEnd: onMoveEnd
41510
- });
41511
-
41512
- // Bound it when moving
41513
- // We can't set this earlier, because doing so would mean any
41514
- // points outside of the graph would be moved into a moved into
41515
- // a position that doesn't preserve the shape
41516
- currentPoint.bounded = true;
41517
- return currentPoint;
41518
- });
41519
- const shape = ShapeTypes.addShape(graphie, options, points);
41520
- const removeShapeWithoutPoints = shape.remove;
41521
- shape.remove = function () {
41522
- removeShapeWithoutPoints.apply(shape);
41523
- ___default["default"].invoke(points, "remove");
41524
- };
41525
- return shape;
41526
- },
41527
- addShape: function (graphie, options, points) {
41528
- points = points || options.shape.coords;
41529
- const types = ShapeTypes._typesOf(options.shape);
41530
- const typeOptions = options.shape.options || ShapeTypes.defaultOptions(types);
41531
-
41532
- // @ts-expect-error - TS2554 - Expected 4 arguments, but got 3.
41533
- const shapes = ShapeTypes._mapTypes(types, points, function (type, points, i) {
41534
- const shapeOptions = ___default["default"].extend({}, options, typeOptions[i]);
41535
- return ShapeTypes._addType(graphie, type, points, shapeOptions);
41536
- });
41537
- const updateFuncs = ___default["default"].filter(___default["default"].pluck(shapes, "update"), ___default["default"].identity);
41538
- const update = function () {
41539
- ___default["default"].invoke(updateFuncs, "call");
41540
- };
41541
- const removeFuncs = ___default["default"].filter(___default["default"].pluck(shapes, "remove"), ___default["default"].identity);
41542
- const remove = function () {
41543
- ___default["default"].invoke(removeFuncs, "call");
41544
- };
41545
- const getOptions = function () {
41546
- return ___default["default"].map(shapes, function (shape) {
41547
- if (shape.getOptions) {
41548
- return shape.getOptions();
41549
- }
41550
- return {};
41551
- });
41552
- };
41553
- const toJSON = function () {
41554
- const coords = ___default["default"].map(points, function (pt) {
41555
- if (___default["default"].isArray(pt)) {
41556
- return pt;
41557
- }
41558
- return pt.coord;
41559
- });
41560
- return {
41561
- type: types,
41562
- coords: coords,
41563
- options: getOptions()
41564
- };
41565
- };
41566
- return {
41567
- type: types,
41568
- points: points,
41569
- update: update,
41570
- remove: remove,
41571
- toJSON: toJSON,
41572
- getOptions: getOptions
41573
- };
41574
- },
41575
- equal: function (shape1, shape2) {
41576
- const types1 = ShapeTypes._typesOf(shape1);
41577
- const types2 = ShapeTypes._typesOf(shape2);
41578
- if (types1.length !== types2.length) {
41579
- return false;
41580
- }
41581
- // @ts-expect-error - TS2554 - Expected 4 arguments, but got 3.
41582
- const shapes1 = ShapeTypes._mapTypes(types1, shape1.coords, ShapeTypes._combine);
41583
- // @ts-expect-error - TS2554 - Expected 4 arguments, but got 3.
41584
- const shapes2 = ShapeTypes._mapTypes(types2, shape2.coords, ShapeTypes._combine);
41585
- return ___default["default"].all(___default["default"].map(shapes1, function (partialShape1, i) {
41586
- const partialShape2 = shapes2[i];
41587
- if (partialShape1.type !== partialShape2.type) {
41588
- return false;
41589
- }
41590
- return ShapeTypes._forType(partialShape1.type).equal(partialShape1.coords, partialShape2.coords);
41591
- }));
41592
- },
41593
- _typesOf: function (shape) {
41594
- let types = shape.type;
41595
- if (!___default["default"].isArray(types)) {
41596
- types = [types];
41597
- }
41598
- return ___default["default"].map(types, function (type) {
41599
- if (type === "polygon") {
41600
- return "polygon-3";
41601
- }
41602
- return type;
41603
- });
41604
- },
41605
- defaultOptions: function (types) {
41606
- return ___default["default"].map(types, function (type) {
41607
- const typeDefaultOptions = ShapeTypes._forType(type).defaultOptions;
41608
- return ___default["default"].extend({}, typeDefaultOptions);
41609
- });
41610
- },
41611
- _forType: function (type) {
41612
- const baseType = type.split("-")[0];
41613
- return ShapeTypes[baseType];
41614
- },
41615
- _mapTypes: function (types, points, func, context) {
41616
- return ___default["default"].map(types, function (type, i) {
41617
- const pointCount = ShapeTypes.getPointCountForType(type);
41618
- const currentPoints = ___default["default"].first(points, pointCount);
41619
- points = ___default["default"].rest(points, pointCount);
41620
- return func.call(context, type, currentPoints, i);
41621
- });
41622
- },
41623
- _addType: function (graphie, type, points, options) {
41624
- const lineCoords = ___default["default"].isArray(points[0]) ? {
41625
- coordA: points[0],
41626
- coordZ: points[1]
41627
- } : {
41628
- pointA: points[0],
41629
- pointZ: points[1]
41630
- };
41631
- type = type.split("-")[0];
41632
- if (type === "polygon") {
41633
- const polygon = graphie.addMovablePolygon(___default["default"].extend({}, options, {
41634
- fixed: !options.editable,
41635
- snapX: options.snap && options.snap[0] || 0,
41636
- snapY: options.snap && options.snap[1] || 0,
41637
- points: points,
41638
- constrainToGraph: false
41639
- }));
41640
- return {
41641
- update: polygon.transform.bind(polygon),
41642
- remove: polygon.remove.bind(polygon)
41643
- };
41644
- }
41645
- if (type === "line" || type === "lineSegment") {
41646
- const line = graphie.addMovableLineSegment(___default["default"].extend({}, options, lineCoords, {
41647
- movePointsWithLine: true,
41648
- fixed: true,
41649
- constraints: {
41650
- fixed: true
41651
- },
41652
- extendLine: type === "line"
41653
- }));
41654
-
41655
- // TODO(jack): Hide points on uneditable lines when translation
41656
- // is a vector.
41657
- // We can't just remove the points yet, because they are the
41658
- // translation handle for the line.
41659
- return {
41660
- update: line.transform.bind(line, true),
41661
- remove: line.remove.bind(line)
41662
- };
41663
- }
41664
- if (type === "angle") {
41665
- // If this angle is editable, we want to be able to make angles
41666
- // both larger and smaller than 180 degrees.
41667
- // If this angle is not editable, it should always maintain
41668
- // it's angle measure, even if it is reflected (causing the
41669
- // clockwise-ness of the points to change)
41670
- const shouldChangeReflexivity = options.editable ? null : false;
41671
- const angle = graphie.addMovableAngle({
41672
- angleLabel: "$deg0",
41673
- fixed: true,
41674
- points: points,
41675
- normalStyle: options.normalStyle,
41676
- reflex: options.reflex
41677
- });
41678
-
41679
- // Hide non-vertex points on uneditable angles
41680
- if (!___default["default"].isArray(points[0]) && !options.editable) {
41681
- points[0].remove();
41682
- points[2].remove();
41683
- }
41684
- return {
41685
- update: angle.update.bind(angle, shouldChangeReflexivity),
41686
- remove: angle.remove.bind(angle),
41687
- getOptions: function () {
41688
- return {
41689
- reflex: angle.isReflex()
41690
- };
41691
- }
41692
- };
41693
- }
41694
- if (type === "circle") {
41695
- let perimeter = {
41696
- // temporary object for the first removal
41697
- remove: ___default["default"].identity
41698
- };
41699
- const redrawPerim = function () {
41700
- const coord0 = points[0].coord || points[0];
41701
- const coord1 = points[1].coord || points[1];
41702
- const radius = kmath.point.distanceToPoint(coord0, coord1);
41703
- // @ts-expect-error - TS2554 - Expected 1 arguments, but got 0.
41704
- perimeter.remove();
41705
- perimeter = graphie.circle(coord0, radius, ___default["default"].extend({
41706
- stroke: KhanColors.DYNAMIC,
41707
- "stroke-width": 2
41708
- }, options.normalStyle));
41709
- };
41710
- redrawPerim();
41711
- if (points[1].remove && !options.editable) {
41712
- points[1].remove();
41713
- }
41714
- return {
41715
- update: redrawPerim,
41716
- remove: function () {
41717
- // Not _.bind because the remove function changes
41718
- // when the perimeter is redrawn
41719
- // @ts-expect-error - TS2554 - Expected 1 arguments, but got 0.
41720
- perimeter.remove();
41721
- }
41722
- };
41723
- }
41724
- if (type === "point") {
41725
- // do nothing
41726
- return {
41727
- update: null,
41728
- remove: null
41729
- };
41730
- }
41731
- throw new PerseusError("Invalid shape type " + type, Errors.InvalidInput);
41732
- },
41733
- _combine: function (type, coords) {
41734
- return {
41735
- type: type,
41736
- coords: coords
41737
- };
41738
- },
41739
- polygon: {
41740
- equal: orderInsensitiveCoordsEqual
41741
- },
41742
- line: {
41743
- equal: kmath.line.equal
41744
- },
41745
- lineSegment: {
41746
- equal: orderInsensitiveCoordsEqual
41747
- },
41748
- angle: {
41749
- equal: function (points1, points2) {
41750
- if (!kmath.point.equal(points1[1], points2[1])) {
41751
- return false;
41752
- }
41753
- const line1_0 = [points1[1], points1[0]];
41754
- const line1_2 = [points1[1], points1[2]];
41755
- const line2_0 = [points2[1], points2[0]];
41756
- const line2_2 = [points2[1], points2[2]];
41757
- const equalUnflipped =
41758
- // @ts-expect-error - TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'. | TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'.
41759
- kmath.ray.equal(line1_0, line2_0) && kmath.ray.equal(line1_2, line2_2);
41760
- const equalFlipped =
41761
- // @ts-expect-error - TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'. | TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'.
41762
- kmath.ray.equal(line1_0, line2_2) && kmath.ray.equal(line1_2, line2_0);
41763
- return equalUnflipped || equalFlipped;
41764
- },
41765
- defaultOptions: {
41766
- reflex: false
41767
- }
41768
- },
41769
- circle: {
41770
- equal: function (points1, points2) {
41771
- const radius1 = kmath.point.distanceToPoint(points1[0], points1[1]);
41772
- const radius2 = kmath.point.distanceToPoint(points2[0], points2[1]);
41773
- return kmath.point.equal(points1[0], points2[0]) && kmath.number.equal(radius1, radius2);
41774
- }
41775
- },
41776
- point: {
41777
- equal: kmath.point.equal
41778
- }
41779
- };
41780
- const TransformationListItem = TransformOps.ListItem;
41781
- class TransformationList extends React__namespace.Component {
41782
- render() {
41783
- if (this.props.mode === "static") {
41784
- return /*#__PURE__*/React__namespace.createElement("span", null); // don't render anything
41785
- }
41786
-
41787
- const transformationList = ___default["default"].map(this.props.transformations, function (transform, i) {
41788
- return /*#__PURE__*/React__namespace.createElement(TransformationListItem, {
41789
- ref: "transformation" + i,
41790
- key: "transformation" + i,
41791
- transform: transform
41792
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41793
- ,
41794
- mode: this.props.mode
41795
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41796
- ,
41797
- onChange: this.handleChange
41798
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41799
- ,
41800
- onFocus: ___default["default"].partial(this.props.onFocus, "" + i)
41801
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41802
- ,
41803
- onBlur: ___default["default"].partial(this.props.onBlur, "" + i)
41804
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41805
- ,
41806
- keypadElement: this.props.keypadElement
41807
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41808
- ,
41809
- apiOptions: this.props.apiOptions
41810
- });
41811
- }, this);
41812
- return /*#__PURE__*/React__namespace.createElement("div", {
41813
- className: "perseus-transformation-list"
41814
- }, transformationList);
41815
- }
41816
- _transformationRefs = () => {
41817
- return ___default["default"].times(this.props.transformations.length, i => {
41818
- // eslint-disable-next-line react/no-string-refs
41819
- return this.refs["transformation" + i];
41820
- });
41821
- };
41822
- value = () => {
41823
- return ___default["default"].invoke(this._transformationRefs(), "value");
41824
- };
41825
- handleChange = (changed, callback) => {
41826
- this.props.onChange(this.value(), callback);
41827
- };
41828
- focusLast = () => {
41829
- const transformationRefs = this._transformationRefs();
41830
- if (transformationRefs.length !== 0) {
41831
- // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
41832
- ___default["default"].last(transformationRefs).focus();
41833
- }
41834
- };
41835
- }
41836
- class ToolButton extends React__namespace.Component {
41837
- render() {
41838
- const classes = this.props.toggled ? "simple-button exercise-orange toggled highlighted-tool-button" : "simple-button";
41839
- return /*#__PURE__*/React__namespace.createElement("button", {
41840
- type: "button",
41841
- className: classes,
41842
- disabled: this.props.disabled,
41843
- onClick: this.props.onClick
41844
- // @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLButtonElement>'.
41845
- ,
41846
- onTouchStart: captureScratchpadTouchStart
41847
- }, this.props.children);
41848
- }
41849
- }
41850
- class ToolsBar extends React__namespace.Component {
41851
- state = {
41852
- selected: null
41853
- };
41854
- render() {
41855
- const tools = ___default["default"].map(Transformations, function (tool, type) {
41856
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41857
- if (this.props.enabled[type]) {
41858
- return /*#__PURE__*/React__namespace.createElement(ToolButton, {
41859
- key: type
41860
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41861
- ,
41862
- disabled: this.props.apiOptions.readOnly
41863
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41864
- ,
41865
- toggled: this.state.selected === type
41866
- // eslint-disable-next-line react/jsx-no-bind
41867
- // @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.
41868
- ,
41869
- onClick: this.changeSelected.bind(this, type)
41870
- }, tool.verbName);
41871
- }
41872
- }, this);
41873
- return /*#__PURE__*/React__namespace.createElement("div", {
41874
- className: "transformer-tools-bar"
41875
- }, /*#__PURE__*/React__namespace.createElement("span", {
41876
- className: "simple-button-group"
41877
- }, tools), /*#__PURE__*/React__namespace.createElement("button", {
41878
- className: "transformer-undo-button simple-button",
41879
- type: "button",
41880
- disabled: this.props.apiOptions.readOnly,
41881
- onClick: this.props.onUndoClick
41882
- // @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLButtonElement>'.
41883
- ,
41884
- onTouchStart: captureScratchpadTouchStart
41885
- }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconUndo), " " + i18n__namespace._("Undo")), /*#__PURE__*/React__namespace.createElement("div", {
41886
- className: "clear"
41887
- }));
41888
- }
41889
- changeSelected = tool => {
41890
- this.props.removeTool(this.state.selected);
41891
- if (!tool || tool === this.state.selected) {
41892
- this.setState({
41893
- selected: null
41894
- });
41895
- } else {
41896
- this.props.addTool(tool);
41897
- this.setState({
41898
- selected: tool
41899
- });
41900
- }
41901
- };
41902
- }
41903
- class AddTransformBar extends React__namespace.Component {
41904
- render() {
41905
- const tools = ___default["default"].map(Transformations, function (tool, type) {
41906
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41907
- if (this.props.enabled[type]) {
41908
- return /*#__PURE__*/React__namespace.createElement(ToolButton, {
41909
- key: type,
41910
- toggled: false
41911
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
41912
- ,
41913
- disabled: this.props.apiOptions.readOnly
41914
- // eslint-disable-next-line react/jsx-no-bind
41915
- // @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.
41916
- ,
41917
- onClick: this.changeSelected.bind(this, type)
41918
- }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconPlus), " ", tool.nounName);
41919
- }
41920
- }, this);
41921
- return /*#__PURE__*/React__namespace.createElement("div", {
41922
- className: "transformer-tools-bar"
41923
- }, tools, /*#__PURE__*/React__namespace.createElement("button", {
41924
- className: "transformer-undo-button simple-button",
41925
- type: "button",
41926
- onClick: this.props.onUndoClick,
41927
- disabled: this.props.apiOptions.readOnly
41928
- // @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLButtonElement>'.
41929
- ,
41930
- onTouchStart: captureScratchpadTouchStart
41931
- }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconUndo), " " + i18n__namespace._("Undo")), /*#__PURE__*/React__namespace.createElement("div", {
41932
- className: "clear"
41933
- }));
41934
- }
41935
- changeSelected = tool => {
41936
- if (tool) {
41937
- this.props.addTool(tool);
41938
- }
41939
- };
41940
- }
41941
-
41942
- // there's no transform in the exports
41943
-
41944
- class Transformer extends React__namespace.Component {
41945
- // @ts-expect-error - TS2564 - Property 'tools' has no initializer and is not definitely assigned in the constructor.
41946
-
41947
- // @ts-expect-error - TS2564 - Property 'transformations' has no initializer and is not definitely assigned in the constructor.
41948
-
41949
- // This is not the same as TransformerShape
41950
-
41951
- static defaultProps = ___default["default"].defaults({
41952
- transformations: []
41953
- }, defaultTransformerProps);
41954
- render() {
41955
- // Fill in any missing value in this.props.graph
41956
- // this can happen because the graph json doesn't include
41957
- // box, for example
41958
- const graph = ___default["default"].extend(defaultGraphProps(this.props.graph, defaultBoxSize), this.props.graph);
41959
- const interactiveToolsMode = this.props.graphMode === "interactive";
41960
- const ToolsBarClass = interactiveToolsMode ? ToolsBar : AddTransformBar;
41961
-
41962
- // This style is applied inline because it is dependent on the
41963
- // size of the graph as set by the graph.box prop, and this also
41964
- // lets us specify it in the same place the graph's width is
41965
- // specified.
41966
- const toolsBar = /*#__PURE__*/React__namespace.createElement("div", {
41967
- style: {
41968
- width: graph.box[0]
41969
- }
41970
- }, /*#__PURE__*/React__namespace.createElement(ToolsBarClass
41971
- // eslint-disable-next-line react/no-string-refs
41972
- , {
41973
- ref: "toolsBar",
41974
- enabled: pluckObject(this.props.tools, "enabled"),
41975
- apiOptions: this.props.apiOptions,
41976
- addTool: this.addTool,
41977
- removeTool: this.removeTool,
41978
- onUndoClick: this.handleUndoClick
41979
- }));
41980
- return /*#__PURE__*/React__namespace.createElement("div", {
41981
- className: "perseus-widget " + "perseus-widget-transformer"
41982
- }, /*#__PURE__*/React__namespace.createElement(Graph
41983
- // eslint-disable-next-line react/no-string-refs
41984
- , {
41985
- ref: "graph",
41986
- box: graph.box,
41987
- range: graph.range,
41988
- labels: graph.labels,
41989
- step: graph.step,
41990
- gridStep: graph.gridStep,
41991
- markings: graph.markings,
41992
- backgroundImage: graph.backgroundImage,
41993
- showProtractor: graph.showProtractor,
41994
- onGraphieUpdated: this.setupGraphie,
41995
- setDrawingAreaAvailable: this.props.apiOptions.setDrawingAreaAvailable
41996
- }), !interactiveToolsMode && i18n__namespace._("Add transformations below:"), this.props.graphMode === "static" && [/*#__PURE__*/React__namespace.createElement("br", {
41997
- key: "static-br"
41998
- }), /*#__PURE__*/React__namespace.createElement("em", {
41999
- key: "static-nomove"
42000
- }, " ", i18n__namespace._("Note: For this question, the shape will not move."), " ")], interactiveToolsMode && toolsBar, /*#__PURE__*/React__namespace.createElement(TransformationList
42001
- // eslint-disable-next-line react/no-string-refs
42002
- , {
42003
- ref: "transformationList",
42004
- mode: this.props.listMode,
42005
- transformations: this.props.transformations,
42006
- onChange: this.setTransformationProps,
42007
- onFocus: this._handleFocus,
42008
- onBlur: this._handleBlur,
42009
- keypadElement: this.props.keypadElement,
42010
- apiOptions: this.props.apiOptions
42011
- }), !interactiveToolsMode && toolsBar);
42012
- }
42013
- componentDidMount() {
42014
- this.setupGraphie(this.graphie());
42015
- }
42016
- componentDidUpdate(prevProps) {
42017
- if (this.shouldSetupGraphie(this.props, prevProps)) {
42018
- // eslint-disable-next-line react/no-string-refs
42019
- // @ts-expect-error - TS2339 - Property 'reset' does not exist on type 'ReactInstance'.
42020
- this.refs.graph.reset();
42021
- } else if (!deepEq(this.props.transformations, this.transformations)) {
42022
- this.setTransformations(this.props.transformations);
42023
- }
42024
- }
42025
- shouldSetupGraphie = (nextProps, prevProps) => {
42026
- if (!deepEq(prevProps.starting, nextProps.starting)) {
42027
- return true;
42028
- }
42029
- if (prevProps.graphMode !== nextProps.graphMode) {
42030
- return true;
42031
- }
42032
- if (prevProps.listMode !== nextProps.listMode) {
42033
- return true;
42034
- }
42035
- if (prevProps.drawSolutionShape !== nextProps.drawSolutionShape) {
42036
- return true;
42037
- }
42038
- if (nextProps.drawSolutionShape && !deepEq(prevProps.correct.shape, nextProps.correct.shape)) {
42039
- return true;
42040
- }
42041
- if (!deepEq(this.tools, nextProps.tools)) {
42042
- return true;
42043
- }
42044
- return false;
42045
- };
42046
- graphie = () => {
42047
- // eslint-disable-next-line react/no-string-refs
42048
- // @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
42049
- return this.refs.graph.graphie();
42050
- };
42051
- setupGraphie = graphie => {
42052
- // A background image of our solution:
42053
- if (this.props.drawSolutionShape && this.props.correct.shape && this.props.correct.shape.coords) {
42054
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 2.
42055
- ShapeTypes.addShape(graphie, {
42056
- fixed: true,
42057
- shape: this.props.correct.shape,
42058
- normalStyle: {
42059
- stroke: KhanColors.GRAY,
42060
- "stroke-dasharray": "",
42061
- "stroke-width": 2
42062
- }
42063
- });
42064
- }
42065
- this.currentTool = null;
42066
- // eslint-disable-next-line react/no-string-refs
42067
- // @ts-expect-error - TS2339 - Property 'changeSelected' does not exist on type 'ReactInstance'.
42068
- this.refs.toolsBar.changeSelected(null);
42069
- this.addTransformerShape(this.props.starting.shape, /* translatable */false);
42070
- this.setTransformations(this.props.transformations);
42071
-
42072
- // Save a copy of our tools so that we can check future
42073
- // this.props.tools changes against them
42074
- // This seems weird, but gives us an easy way to tell whether
42075
- // props changes were self-inflicted (for which a graphie reset
42076
- // is not required, and is in fact a bad idea right now because
42077
- // of resetting the size of the dilation tool).
42078
- // TODO (jack): A deepClone method would be nice here
42079
- this.tools = {
42080
- translation: ___default["default"].clone(this.props.tools.translation),
42081
- rotation: ___default["default"].clone(this.props.tools.rotation),
42082
- reflection: ___default["default"].clone(this.props.tools.reflection),
42083
- dilation: ___default["default"].clone(this.props.tools.dilation)
42084
- };
42085
- };
42086
-
42087
- /* Applies all transformations in `transformations`
42088
- * to the starting shape, and updates this.transformations
42089
- * to reflect this
42090
- *
42091
- * Usually called with this.props.transformations
42092
- */
42093
- setTransformations = transformations => {
42094
- this.resetCoords();
42095
- this.transformations = ___default["default"].clone(transformations);
42096
- ___default["default"].each(this.transformations, this.applyTransform);
42097
- };
42098
-
42099
- // the polygon that we transform
42100
- addTransformerShape = (shape, translatable) => {
42101
- const self = this;
42102
- const graphie = this.graphie();
42103
- this.shape = ShapeTypes.addMovableShape(graphie, {
42104
- shape: shape,
42105
- editable: false,
42106
- showPoints: this.props.graphMode !== "static",
42107
- translatable: translatable,
42108
- onMove: function (dX, dY) {
42109
- dX = KhanMath.roundToNearest(graphie.snap[0], dX);
42110
- dY = KhanMath.roundToNearest(graphie.snap[1], dY);
42111
- // NOTE(kevinb): object is missing .constraints property
42112
- // @ts-expect-error - TS2345 - Argument of type '{ type: "translation"; vector: [any, any]; }' is not assignable to parameter of type 'PerseusTransformerTransformation'.
42113
- self.addTransform({
42114
- type: "translation",
42115
- vector: [dX, dY]
42116
- });
42117
- return [dX, dY];
42118
- },
42119
- normalPointStyle: {
42120
- fill: translatable ? KhanColors.INTERACTIVE : KhanColors.DYNAMIC,
42121
- stroke: translatable ? KhanColors.INTERACTIVE : KhanColors.DYNAMIC
42122
- },
42123
- highlightPointStyle: {
42124
- fill: KhanColors.INTERACTING,
42125
- stroke: KhanColors.INTERACTING
42126
- }
42127
- });
42128
- };
42129
- addTool = toolId => {
42130
- const self = this;
42131
- if (this.props.graphMode === "interactive") {
42132
- if (toolId === "translation") {
42133
- this.currentTool = this.addTranslationTool();
42134
- } else if (toolId === "rotation") {
42135
- this.currentTool = this.addRotationTool();
42136
- } else if (toolId === "reflection") {
42137
- this.currentTool = this.addReflectionTool();
42138
- } else if (toolId === "dilation") {
42139
- this.currentTool = this.addDilationTool();
42140
- } else {
42141
- throw new PerseusError("Invalid tool id: " + toolId, Errors.InvalidInput);
42142
- }
42143
- } else {
42144
- let transform;
42145
- if (toolId === "translation") {
42146
- // NOTE(kevinb): object is missing .constraints property
42147
- transform = {
42148
- type: "translation",
42149
- // NOTE(kevib): these should be numbers
42150
- // @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
42151
- vector: [null, null]
42152
- };
42153
- } else if (toolId === "rotation") {
42154
- // NOTE(kevinb): object is missing .constraints property
42155
- transform = {
42156
- type: "rotation",
42157
- // NOTE(kevib): these should be numbers
42158
- // @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
42159
- center: [null, null],
42160
- // NOTE(kevib): this should be a number
42161
- // @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'.
42162
- angleDeg: null
42163
- };
42164
- } else if (toolId === "reflection") {
42165
- // Reflections with nulls in them won't be applied until
42166
- // fills in the blanks
42167
- transform = {
42168
- type: "reflection",
42169
- line: [
42170
- // NOTE(kevib): these should be numbers
42171
- // @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
42172
- [null, null],
42173
- // NOTE(kevib): these should be numbers
42174
- // @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
42175
- [null, null]]
42176
- };
42177
- } else if (toolId === "dilation") {
42178
- // NOTE(kevinb): object is missing .constraints property
42179
- transform = {
42180
- type: "dilation",
42181
- // NOTE(kevib): these should be numbers
42182
- // @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
42183
- center: [null, null],
42184
- // NOTE(kevib): this should be a number
42185
- // @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'.
42186
- scale: null
42187
- };
42188
- } else {
42189
- throw new PerseusError("Invalid tool id: " + toolId, Errors.InvalidInput);
42190
- }
42191
- this.doTransform(transform, function () {
42192
- // @ts-expect-error - TS2339 - Property 'focusLast' does not exist on type 'ReactInstance'.
42193
- self.refs.transformationList.focusLast();
42194
- });
42195
- }
42196
- };
42197
- removeTool = toolId => {
42198
- if (this.currentTool) {
42199
- this.currentTool.remove();
42200
- }
42201
- this.currentTool = null;
42202
- };
42203
- addTranslationTool = () => {
42204
- const self = this;
42205
- this.shape?.remove();
42206
- this.addTransformerShape(this.shape?.toJSON(), /* translatable */true);
42207
- return {
42208
- remove: function () {
42209
- self.shape?.remove();
42210
- self.addTransformerShape(self.shape?.toJSON(), /* translatable */false);
42211
- }
42212
- };
42213
- };
42214
-
42215
- // Snaps a coord to this.graphie()'s snap
42216
- // @ts-expect-error - TS2322 - Type '(coord: Coord) => number[]' is not assignable to type '(arg1: Coord) => Coord'.
42217
- snapCoord = coord => {
42218
- const graphie = this.graphie();
42219
- return ___default["default"].map(coord, function (val, dim) {
42220
- return KhanMath.roundToNearest(graphie.snap[dim], val);
42221
- });
42222
- };
42223
-
42224
- // Normalize the coords into something that fits the new 45 degree
42225
- // reflection line.
42226
- // @ts-expect-error - TS2322 - Type '(messyCoords: [Coord, Coord]) => any[]' is not assignable to type '(arg1: [Coord, Coord]) => [Coord, Coord]'.
42227
- normalizeReflectionCoords = messyCoords => {
42228
- // @ts-expect-error - TS2345 - Argument of type 'Point' is not assignable to parameter of type 'Coord'.
42229
- const midpoint = this.snapCoord(kmath.line.midpoint(messyCoords));
42230
- const origDirectionPolar = kmath.vector.polarDegFromCart(kmath.vector.subtract(messyCoords[0], messyCoords[1]));
42231
- const direction = kmath.vector.cartFromPolarDeg(1, KhanMath.roundToNearest(45, origDirectionPolar[1]));
42232
- const coords = ___default["default"].map([-1, 1], function (directionCoefficient) {
42233
- const coord = kmath.vector.add(midpoint, kmath.vector.scale(direction, directionCoefficient *
42234
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
42235
- this.scaleToCurrentRange(REFLECT_ROTATE_HANDLE_DIST)));
42236
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
42237
- return this.snapCoord(coord);
42238
- }, this);
42239
- return coords;
42240
- };
42241
- addReflectionTool = () => {
42242
- const options = this.props.tools.reflection;
42243
- if (!options.enabled) {
42244
- return;
42245
- }
42246
- const self = this;
42247
- // eslint-disable-next-line react/no-string-refs
42248
- // @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
42249
- const graphie = this.refs.graph.graphie();
42250
- const updateReflectionTool = function () {
42251
- self.changeTool("reflection", {
42252
- coords: ___default["default"].pluck(reflectPoints, "coord")
42253
- });
42254
- };
42255
- const coords = this.normalizeReflectionCoords(options.coords);
42256
-
42257
- // The points defining the line of reflection; hidden from the
42258
- // user.
42259
- const reflectPoints = ___default["default"].map(coords, function (coord) {
42260
- return graphie.addMovablePoint({
42261
- coord: coord,
42262
- visible: false
42263
- });
42264
- }, this);
42265
-
42266
- // the line of reflection
42267
- // TODO(jack): graphie.style here is a hack to prevent the dashed
42268
- // style from leaking into the rest of the shapes. Remove when
42269
- // graphie.addMovableLineSegment doesn't leak styles anymore.
42270
- let reflectLine;
42271
- const normalColor = colorForTool(options);
42272
- graphie.style({}, function () {
42273
- reflectLine = graphie.addMovableLineSegment({
42274
- fixed: options.constraints.fixed,
42275
- constraints: options.constraints,
42276
- pointA: reflectPoints[0],
42277
- pointZ: reflectPoints[1],
42278
- snapX: graphie.snap[0],
42279
- snapY: graphie.snap[1],
42280
- extendLine: true,
42281
- normalStyle: {
42282
- stroke: normalColor,
42283
- "stroke-width": 2,
42284
- "stroke-dasharray": "- "
42285
- },
42286
- highlightStyle: {
42287
- stroke: KhanColors.INTERACTING,
42288
- "stroke-width": 2,
42289
- "stroke-dasharray": "- " // TODO(jack) solid doesn't
42290
- // work here, but would be
42291
- // nicer
42292
- },
42293
-
42294
- movePointsWithLine: true,
42295
- onMoveEnd: updateReflectionTool
42296
- });
42297
- });
42298
-
42299
- // the "button" point in the center of the line of reflection
42300
- const reflectButton = graphie.addReflectButton({
42301
- fixed: options.constraints.fixed,
42302
- line: reflectLine,
42303
- size: this.scaleToCurrentRange(REFLECT_BUTTON_SIZE),
42304
- onClick: function () {
42305
- self.doTransform({
42306
- type: "reflection",
42307
- // @ts-expect-error - TS2322 - Type 'any[]' is not assignable to type '[Coord, Coord]'.
42308
- line: ___default["default"].pluck(reflectPoints, "coord")
42309
- });
42310
- if (reflectRotateHandle) {
42311
- // flip the rotation handle
42312
- // @ts-expect-error - TS2339 - Property 'setCoord' does not exist on type 'never'.
42313
- reflectRotateHandle.setCoord(kmath.vector.add(reflectButton.coord, kmath.vector.subtract(reflectButton.coord,
42314
- // @ts-expect-error - TS2339 - Property 'coord' does not exist on type 'never'.
42315
- reflectRotateHandle.coord)));
42316
- // @ts-expect-error - TS2339 - Property 'update' does not exist on type 'never'.
42317
- reflectRotateHandle.update();
42318
- }
42319
- },
42320
- normalStyle: {
42321
- stroke: normalColor,
42322
- "stroke-width": 2,
42323
- fill: normalColor
42324
- },
42325
- highlightStyle: {
42326
- stroke: KhanColors.INTERACTING,
42327
- "stroke-width": 3,
42328
- fill: KhanColors.INTERACTING
42329
- },
42330
- onMoveEnd: updateReflectionTool
42331
- });
42332
- let reflectRotateHandle = null;
42333
- if (!options.constraints.fixed) {
42334
- // The rotation handle for rotating the line of reflection
42335
- const initRotateHandleAngle = kmath.vector.polarDegFromCart(kmath.vector.subtract(reflectPoints[1].coord, reflectPoints[0].coord))[1] + 90; // 90 degrees off of the line
42336
- reflectRotateHandle = graphie.addRotateHandle({
42337
- center: reflectButton,
42338
- radius: this.scaleToCurrentRange(REFLECT_ROTATE_HANDLE_DIST),
42339
- angleDeg: initRotateHandleAngle,
42340
- width: this.scaleToCurrentRange(0.24),
42341
- hoverWidth: this.scaleToCurrentRange(0.4),
42342
- lengthAngle: 17,
42343
- onMove: function (newAngle) {
42344
- return KhanMath.roundToNearest(45, newAngle);
42345
- },
42346
- onMoveEnd: updateReflectionTool
42347
- });
42348
- }
42349
-
42350
- // Move the reflectButton and reflectRotateHandle with the line
42351
- $__default["default"](reflectLine).on("move", function () {
42352
- reflectButton.update();
42353
- $__default["default"](reflectButton).trigger("move"); // update the rotation handle,
42354
- // which watches for this in util/interactive.js.
42355
- });
42356
-
42357
- // Update the line and reflect button when the reflectRotateHandle is
42358
- // rotated
42359
- if (reflectRotateHandle) {
42360
- $__default["default"](reflectRotateHandle).on("move", function () {
42361
- const rotateHandleApprox = self.snapCoord(
42362
- // @ts-expect-error - TS2531 - Object is possibly 'null'.
42363
- reflectRotateHandle.coord);
42364
- const rotateVector = kmath.vector.subtract(rotateHandleApprox, reflectButton.coord);
42365
- const flipped = reflectButton.isFlipped() ? 1 : 0;
42366
- reflectPoints[flipped].setCoord(kmath.vector.add(reflectButton.coord, kmath.vector.rotateDeg(rotateVector, 90)));
42367
- reflectPoints[1 - flipped].setCoord(kmath.vector.add(reflectButton.coord, kmath.vector.rotateDeg(rotateVector, -90)));
42368
- reflectLine.transform(true);
42369
- reflectButton.update();
42370
- });
42371
- }
42372
- return {
42373
- remove: function () {
42374
- reflectButton.remove();
42375
- if (reflectRotateHandle) {
42376
- // @ts-expect-error - TS2339 - Property 'remove' does not exist on type 'never'.
42377
- reflectRotateHandle.remove();
42378
- }
42379
- reflectLine.remove();
42380
- reflectPoints[0].remove();
42381
- reflectPoints[1].remove();
42382
- }
42383
- };
42384
- };
42385
-
42386
- /* Scales a distance from the default range of
42387
- * [-10, 10] to the current this.props.graph.range
42388
- *
42389
- * Used for sizing various transformation tools
42390
- * (rotation handle, dilation circle)
42391
- */
42392
- scaleToCurrentRange = dist => {
42393
- // eslint-disable-next-line react/no-string-refs
42394
- // @ts-expect-error - TS2339 - Property 'props' does not exist on type 'ReactInstance'.
42395
- return scaleToRange(dist, this.refs.graph.props.range);
42396
- };
42397
- addRotationTool = () => {
42398
- const options = this.props.tools.rotation;
42399
- if (!options.enabled) {
42400
- return;
42401
- }
42402
- const self = this;
42403
- // eslint-disable-next-line react/no-string-refs
42404
- // @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
42405
- const graphie = this.refs.graph.graphie();
42406
- const pointColor = colorForTool(options);
42407
- // The center of our rotation, which can be moved to change the
42408
- // center of rotation
42409
- this.rotatePoint = graphie.addMovablePoint({
42410
- constraints: options.constraints,
42411
- coord: options.coord,
42412
- snapX: graphie.snap[0],
42413
- snapY: graphie.snap[1],
42414
- normalStyle: {
42415
- // ugh, this seems to be a global and
42416
- "stroke-dasharray": "",
42417
- // is set to dash above
42418
- stroke: pointColor,
42419
- fill: pointColor
42420
- },
42421
- highlightStyle: {
42422
- "stroke-dasharray": "",
42423
- stroke: KhanColors.INTERACTING,
42424
- fill: KhanColors.INTERACTING
42425
- }
42426
- });
42427
-
42428
- // The point that we move around the center of rotation to actually
42429
- // cause rotations
42430
- this.rotateHandle = graphie.addRotateHandle({
42431
- center: this.rotatePoint,
42432
- radius: this.scaleToCurrentRange(ROTATE_HANDLE_DIST),
42433
- width: this.scaleToCurrentRange(0.24),
42434
- hoverWidth: this.scaleToCurrentRange(0.4),
42435
- onMove: function (newAngle, oldAngle) {
42436
- const transform = self.getRotationTransformFromAngle(self.rotatePoint.coord, newAngle - oldAngle);
42437
-
42438
- // Rotate polygon with rotateHandle
42439
- self.doTransform(transform);
42440
-
42441
- // @ts-expect-error - TS2339 - Property 'angleDeg' does not exist on type 'PerseusTransformerTransformation'.
42442
- return oldAngle + transform.angleDeg;
42443
- }
42444
- });
42445
-
42446
- // Update tools.rotation.coord
42447
- this.rotatePoint.onMoveEnd = (x, y) => {
42448
- self.changeTool("rotation", {
42449
- coord: [x, y]
42450
- });
42451
- };
42452
- return {
42453
- remove: function () {
42454
- self.rotateHandle?.remove();
42455
- self.rotatePoint?.remove();
42456
- }
42457
- };
42458
- };
42459
- addDilationTool = () => {
42460
- const options = this.props.tools.dilation;
42461
- if (!options.enabled) {
42462
- return;
42463
- }
42464
- const self = this;
42465
- // eslint-disable-next-line react/no-string-refs
42466
- // @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
42467
- const graphie = this.refs.graph.graphie();
42468
- const pointColor = colorForTool(options);
42469
- // the circle for causing dilation transforms
42470
- self.dilationCircle = graphie.addCircleGraph({
42471
- centerConstraints: options.constraints,
42472
- center: options.coord,
42473
- radius: self.scaleToCurrentRange(2),
42474
- snapX: graphie.snap[0],
42475
- snapY: graphie.snap[1],
42476
- minRadius: self.scaleToCurrentRange(1),
42477
- snapRadius: self.scaleToCurrentRange(0.5),
42478
- onResize: function (newRadius, oldRadius) {
42479
- // NOTE(kevinb): object is missing .constraints property
42480
- // @ts-expect-error - TS2345 - Argument of type '{ type: "dilation"; center: any; scale: number; }' is not assignable to parameter of type 'PerseusTransformerTransformation'.
42481
- self.doTransform({
42482
- type: "dilation",
42483
- center: self.dilationCircle.centerPoint.coord,
42484
- scale: newRadius / oldRadius
42485
- });
42486
- },
42487
- circleNormalStyle: {
42488
- stroke: pointColor,
42489
- "stroke-width": 2,
42490
- "stroke-dasharray": "- ",
42491
- "fill-opacity": 0
42492
- },
42493
- circleHighlightStyle: {
42494
- stroke: KhanColors.INTERACTING,
42495
- "stroke-width": 2,
42496
- "stroke-dasharray": "",
42497
- fill: KhanColors.INTERACTING,
42498
- "fill-opacity": 0.05
42499
- },
42500
- centerNormalStyle: {
42501
- stroke: pointColor,
42502
- fill: pointColor,
42503
- "stroke-width": 2,
42504
- "stroke-dasharray": ""
42505
- },
42506
- centerHighlightStyle: {
42507
- stroke: pointColor,
42508
- fill: pointColor,
42509
- "stroke-width": 2,
42510
- "stroke-dasharray": ""
42511
- }
42512
- });
42513
- const origOnMoveEnd = this.dilationCircle.centerPoint.onMoveEnd;
42514
- this.dilationCircle.centerPoint.onMoveEnd = function () {
42515
- if (origOnMoveEnd) {
42516
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
42517
- args[_key] = arguments[_key];
42518
- }
42519
- origOnMoveEnd(args);
42520
- }
42521
- self.changeTool("dilation", {
42522
- coord: self.dilationCircle.centerPoint.coord
42523
- });
42524
- };
42525
- return {
42526
- remove: function () {
42527
- self.dilationCircle?.remove();
42528
- }
42529
- };
42530
- };
42531
-
42532
- // returns a transformation object representing a rotation
42533
- // rounds the angle to the nearest 15 degrees
42534
- // @ts-expect-error - TS2322 - Type '(center: Coord, angleChanged: number) => { type: "rotation"; center: Coord; angleDeg: number; }' is not assignable to type '(arg1: Coord, arg2: number) => PerseusTransformerTransformation'.
42535
- getRotationTransformFromAngle = (center, angleChanged) => {
42536
- angleChanged = (angleChanged + 360) % 360;
42537
- if (angleChanged > 180) {
42538
- angleChanged -= 360;
42539
- }
42540
- const roundedAngle = Math.round(angleChanged / ROTATE_SNAP_DEGREES) * ROTATE_SNAP_DEGREES;
42541
-
42542
- // NOTE(kevinb): return object is missing .constraints property
42543
- return {
42544
- type: "rotation",
42545
- center: center,
42546
- angleDeg: roundedAngle
42547
- };
42548
- };
42549
-
42550
- // apply and save a transform
42551
- doTransform = (transform, callback) => {
42552
- this.applyTransform(transform);
42553
- this.addTransform(transform, callback);
42554
- };
42555
-
42556
- // apply a transform to our polygon (without modifying our transformation
42557
- // list)
42558
- applyTransform = transform => {
42559
- if (this.props.graphMode !== "static") {
42560
- const transformFunc = TransformOps.apply(transform);
42561
- // @ts-expect-error - TS2345 - Argument of type '(coord: any) => any' is not assignable to parameter of type 'PerseusTransformerTransformation'.
42562
- this.applyCoordTransformation(transformFunc);
42563
- }
42564
- };
42565
-
42566
- // transform our polygon by transforming each point using a given function
42567
- applyCoordTransformation = pointTransform => {
42568
- ___default["default"].each(this.shape.points, function (point) {
42569
- // @ts-expect-error - TS2349 - This expression is not callable.
42570
- const newCoord = pointTransform(point.coord);
42571
- point.setCoord(newCoord);
42572
- });
42573
- this.shape?.update();
42574
- };
42575
- resetCoords = () => {
42576
- const startCoords = this.props.starting.shape.coords;
42577
- ___default["default"].each(this.shape.points, function (point, i) {
42578
- point.setCoord(startCoords[i]);
42579
- });
42580
- this.shape?.update();
42581
- };
42582
-
42583
- // Remove the last transformation
42584
- handleUndoClick = () => {
42585
- // eslint-disable-next-line react/no-string-refs
42586
- // @ts-expect-error - TS2339 - Property 'changeSelected' does not exist on type 'ReactInstance'.
42587
- this.refs.toolsBar.changeSelected(null);
42588
- if (this.props.transformations.length) {
42589
- this.props.onChange({
42590
- transformations: ___default["default"].initial(this.props.transformations)
42591
- });
42592
- }
42593
- };
42594
- setTransformationProps = (newTransfomationList, callback) => {
42595
- this.props.onChange({
42596
- transformations: newTransfomationList
42597
- },
42598
- // @ts-expect-error - TS2345 - Argument of type '(arg1: any) => unknown' is not assignable to parameter of type '() => unknown'.
42599
- callback);
42600
- };
42601
-
42602
- // add a transformation to our props list of transformation
42603
- addTransform = (transform, callback) => {
42604
- this.transformations = TransformOps.append(this.transformations, transform);
42605
- this.props.onChange({
42606
- transformations: ___default["default"].clone(this.transformations)
42607
- },
42608
- // @ts-expect-error - TS2345 - Argument of type '((arg1: any) => unknown) | undefined' is not assignable to parameter of type '(() => unknown) | undefined'.
42609
- callback);
42610
- };
42611
- changeTool = (tool, changes) => {
42612
- const newTools = ___default["default"].clone(this.props.tools);
42613
- newTools[tool] = ___default["default"].extend({}, this.props.tools[tool], changes);
42614
- this.tools[tool] = ___default["default"].clone(newTools[tool]);
42615
- this.props.onChange({
42616
- // @ts-expect-error - TS2740 - Type '{ dilation: DilationTool; reflection: ReflectionTool; rotation: RotationTool; translation: TranslationTool; }' is missing the following properties from type 'readonly any[]': length, concat, join, slice, and 18 more.
42617
- tools: newTools
42618
- });
42619
- this.props.trackInteraction();
42620
- };
42621
- simpleValidate = rubric => {
42622
- return Transformer.validate(this.getUserInput(), rubric);
42623
- };
42624
-
42625
- /**
42626
- * Calculate where the coordinates would be if they were
42627
- * moved, even if we're in formal mode with no movement
42628
- * (and thus the actual movablepoints may not have moved
42629
- */
42630
- // @ts-expect-error - TS2322 - Type '() => [Coord, Coord] | readonly Coord[] | [Coord, Coord, Coord]' is not assignable to type '() => Coord'.
42631
- getCoords = () => {
42632
- const startCoords = this.props.starting.shape.coords;
42633
- const transforms = this.props.transformations;
42634
- return ___default["default"].reduce(transforms, function (coords, transform) {
42635
- return ___default["default"].map(coords, TransformOps.apply(transform));
42636
- }, startCoords);
42637
- };
42638
- getEditorJSON = () => {
42639
- const json = ___default["default"].pick(this.props, "grading", "starting", "graphMode", "listMode", "tools", "drawSolutionShape", "gradeEmpty");
42640
- // eslint-disable-next-line react/no-string-refs
42641
- // @ts-expect-error - TS2339 - Property 'graph' does not exist on type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "tools" | "starting" | "drawSolutionShape" | "gradeEmpty" | "graphMode" | "listMode">'. | TS2339 - Property 'toJSON' does not exist on type 'ReactInstance'.
42642
- json.graph = this.refs.graph.toJSON();
42643
- // @ts-expect-error - TS2339 - Property 'version' does not exist on type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "tools" | "starting" | "drawSolutionShape" | "gradeEmpty" | "graphMode" | "listMode">'.
42644
- json.version = 1.2; // Give us some safety to change the format
42645
- // when we realize that I wrote
42646
- // a horrible json spec for this widget
42647
-
42648
- // @ts-expect-error - TS2339 - Property 'answer' does not exist on type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "tools" | "starting" | "drawSolutionShape" | "gradeEmpty" | "graphMode" | "listMode">'.
42649
- json.answer = this.getUserInput();
42650
- return json;
42651
- };
42652
- getUserInput = () => {
42653
- return {
42654
- transformations: this.props.transformations,
42655
- // This doesn't call this.shape.toJSON() because that doesn't
42656
- // handle coordinates in formal mode without movement, since
42657
- // the movablepoints never move
42658
- shape: {
42659
- type: this.shape.type,
42660
- coords: this.getCoords(),
42661
- options: this.shape?.getOptions()
42662
- }
42663
- };
42664
- };
42665
-
42666
- /* InputPath API */
42667
-
42668
- _handleFocus = (() => {
42669
- var _this = this;
42670
- return function () {
42671
- for (var _len2 = arguments.length, path = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
42672
- path[_key2] = arguments[_key2];
42673
- }
42674
- _this.props.onFocus(path);
42675
- };
42676
- })();
42677
- _handleBlur = (() => {
42678
- var _this2 = this;
42679
- return function () {
42680
- for (var _len3 = arguments.length, path = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
42681
- path[_key3] = arguments[_key3];
42682
- }
42683
- _this2.props.onBlur(path);
42684
- };
42685
- })();
42686
- _getTransformationForID = transformationID => {
42687
- // Returns the 'transformation' component corresponding to a given ID
42688
- const refPath = ["transformationList", "transformation" + transformationID];
42689
-
42690
- // Follow the path of references
42691
- let component = this;
42692
- ___default["default"].each(refPath, ref => {
42693
- // @ts-expect-error - TS2322 - Type 'ReactInstance' is not assignable to type 'this'.
42694
- component = component.refs[ref];
42695
- });
42696
- return component;
42697
- };
42698
- getInputPaths = () => {
42699
- // If we're in static mode, then there is no transformation list, and,
42700
- // as a result, no input paths.
42701
- if (this.props.listMode === "static") {
42702
- return [];
42703
- }
42704
- let inputPaths = [];
42705
- ___default["default"].each(this.props.transformations, (transformation, i) => {
42706
- // @ts-expect-error - TS2345 - Argument of type 'number' is not assignable to parameter of type 'string'.
42707
- transformation = this._getTransformationForID(i);
42708
- // @ts-expect-error - TS2339 - Property 'getInputPaths' does not exist on type 'PerseusTransformerTransformation'.
42709
- const innerPaths = transformation.getInputPaths();
42710
- const fullPaths = ___default["default"].map(innerPaths, innerPath => {
42711
- return ["" + i].concat(innerPath);
42712
- });
42713
- // @ts-expect-error - TS2345 - Argument of type 'string[][]' is not assignable to parameter of type 'ConcatArray<never>'.
42714
- inputPaths = inputPaths.concat(fullPaths);
42715
- });
42716
- return inputPaths;
42717
- };
42718
- _passToInner = function (functionName, path) {
42719
- if (!path || !path.length) {
42720
- return;
42721
- }
42722
-
42723
- // First argument tells us which transformation will receive the call;
42724
- // remaining arguments are used within that transformation to identify
42725
- // a specific input.
42726
- const innerPath = ___default["default"].rest(path);
42727
-
42728
- // Pass arguments down to appropriate 'transformation' component
42729
- const transformationID = ___default["default"].head(path);
42730
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
42731
- const caller = this._getTransformationForID(transformationID);
42732
- for (var _len4 = arguments.length, args = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) {
42733
- args[_key4 - 2] = arguments[_key4];
42734
- }
42735
- return caller[functionName](innerPath, ...args);
42736
- };
42737
- focus = () => {
42738
- // Just focus the first showing input
42739
- const inputs = this.getInputPaths();
42740
- if (inputs.length > 0) {
42741
- this.focusInputPath(inputs[0]);
42742
- return true;
42743
- }
42744
- return false;
42745
- };
42746
- focusInputPath = path => {
42747
- // Since the transformer exposes the input API, it needs to be robust
42748
- // to empty paths. We don't expect this to happen, as entire-widget
42749
- // focusing is typically done through the focus() method, which already
42750
- // handles the empty path case properly, but it's better to be safe
42751
- // here.
42752
- if (path.length === 0) {
42753
- return false;
42754
- }
42755
- assert(path.length >= 2);
42756
- return this._passToInner("focusInputPath", path);
42757
- };
42758
- blurInputPath = path => {
42759
- // Since the transformer exposes the input API, it needs to be robust
42760
- // to empty paths (which indicate a blurring of the entire widget,
42761
- // e.g., when switching from interacting with the transformer to
42762
- // interacting with some other widget).
42763
- if (path.length === 0) {
42764
- return false;
42765
- }
42766
- assert(path.length >= 2);
42767
- return this._passToInner("blurInputPath", path);
42768
- };
42769
- setInputValue = (path, value, cb) => {
42770
- assert(path.length >= 2);
42771
- return this._passToInner("setInputValue", path, value, cb);
42772
- };
42773
- getDOMNodeForPath = path => {
42774
- assert(path.length >= 2);
42775
- return this._passToInner("getDOMNodeForPath", path);
42776
- };
42777
- getGrammarTypeForPath = path => {
42778
- assert(path.length >= 2);
42779
- return this._passToInner("getGrammarTypeForPath", path);
42780
- };
42781
- static validate(guess, rubric) {
42782
- // Check for any required transformations
42783
- for (const type in Transformations) {
42784
- if (rubric.tools[type].required) {
42785
- const isUsed = ___default["default"].any(___default["default"].map(guess.transformations, function (transform) {
42786
- // Required transformations must appear in the
42787
- // transformation list, and must not be no-ops
42788
- return transform.type === type && !TransformOps.isEmpty(transform) && !TransformOps.isNoOp(transform);
42789
- }));
42790
- if (!isUsed) {
42791
- return {
42792
- type: "invalid",
42793
- message: i18n__namespace._("Your transformation must use a " + "%(type)s.", {
42794
- type: Transformations[type].lowerNounName
42795
- })
42796
- };
42797
- }
42798
- }
42799
- }
42800
-
42801
- // Compare shapes
42802
- if (ShapeTypes.equal(guess.shape, rubric.correct.shape)) {
42803
- return {
42804
- type: "points",
42805
- earned: 1,
42806
- total: 1,
42807
- message: null
42808
- };
42809
- }
42810
- if (!rubric.gradeEmpty && deepEq(guess.shape.coords, rubric.starting.shape.coords)) {
42811
- return {
42812
- type: "invalid",
42813
- message: i18n__namespace._("Use the interactive graph to define a " + "correct transformation.")
42814
- };
42815
- }
42816
- return {
42817
- type: "points",
42818
- earned: 0,
42819
- total: 1,
42820
- message: null
42821
- };
42822
- }
42823
- }
42824
- var Transformer$1 = {
42825
- name: "transformer",
42826
- displayName: "Transformer (deprecated)",
42827
- hidden: true,
42828
- widget: Transformer
42829
- };
42830
-
42831
40421
  var hubble = {exports: {}};
42832
40422
 
42833
40423
  (function (module, exports) {
@@ -44053,7 +41643,7 @@ var Video$1 = {
44053
41643
  };
44054
41644
 
44055
41645
  /* eslint-disable import/no-named-as-default */
44056
- var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1, Transformer$1, Unit, Video$1, DeprecatedStandin$1];
41646
+ var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1, Unit, Video$1, DeprecatedStandin$1];
44057
41647
 
44058
41648
  /**
44059
41649
  * This should be called by all clients, specifying whether extra widgets are
@@ -44097,7 +41687,7 @@ const init = function (options) {
44097
41687
 
44098
41688
  // This file is processed by a Rollup plugin (replace) to inject the production
44099
41689
  const libName = "@khanacademy/perseus";
44100
- const libVersion = "18.0.0";
41690
+ const libVersion = "19.0.0";
44101
41691
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
44102
41692
 
44103
41693
  const apiVersion = {
@@ -45542,8 +43132,6 @@ const ItemExtras = [
45542
43132
 
45543
43133
  // prettier-ignore
45544
43134
 
45545
- // prettier-ignore
45546
-
45547
43135
  //prettier-ignore
45548
43136
 
45549
43137
  // A background image applied to various widgets.
@@ -46668,10 +44256,7 @@ function violatingWidgets(itemData) {
46668
44256
  */
46669
44257
  const registerAllWidgetsForTesting = () => {
46670
44258
  registerWidgets(allWidgets);
46671
-
46672
- // When it's time to replace the transformer widget
46673
- // uncomment this line
46674
- // Widgets.replaceWidget("transformer", "deprecated-standin");
44259
+ replaceWidget("transformer", "deprecated-standin");
46675
44260
  };
46676
44261
 
46677
44262
  /**
@@ -47131,7 +44716,6 @@ exports.Renderer = Renderer;
47131
44716
  exports.ServerItemRenderer = ref;
47132
44717
  exports.SizingUtils = sizingUtils;
47133
44718
  exports.TableWidget = Table$1;
47134
- exports.TransformerWidget = Transformer$1;
47135
44719
  exports.Util = Util;
47136
44720
  exports.WIDGET_PROP_DENYLIST = denylist;
47137
44721
  exports.WidgetJsonifyDeprecated = WidgetJsonifyDeprecated;