@khanacademy/perseus 19.1.3 → 19.1.5

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/es/index.js CHANGED
@@ -3975,18 +3975,20 @@ FixedToResponsive.defaultProps = {
3975
3975
 
3976
3976
  /* Local helper methods. */
3977
3977
 
3978
- function getKey(eventName, id) {
3978
+ function getKey$1(eventName, id) {
3979
3979
  return eventName + ":" + id;
3980
3980
  }
3981
- function getEventName(key) {
3981
+ function getEventName$1(key) {
3982
3982
  return key.split(":")[0];
3983
3983
  }
3984
3984
  const MovableHelperMethods = {
3985
3985
  /**
3986
3986
  * Fire an onSomething type event to all functions in listeners
3987
3987
  */
3988
- _fireEvent: function (listeners, currentValue, previousValue) {
3989
- _.invoke(listeners, "call", this, currentValue, previousValue);
3988
+ _fireEvent: function (listeners, ...args) {
3989
+ for (const listener of listeners) {
3990
+ listener.call(this, ...args);
3991
+ }
3990
3992
  },
3991
3993
  /**
3992
3994
  * Combine the array of constraints functions
@@ -4053,7 +4055,7 @@ const MovableHelperMethods = {
4053
4055
 
4054
4056
  // If there's an existing handler, replace it by using its index in
4055
4057
  // `this.state[eventName]`; otherwise, add this handler to the end
4056
- const key = getKey(eventName, id);
4058
+ const key = getKey$1(eventName, id);
4057
4059
  const index = this._listenerMap[key] = this._listenerMap[key] || this.state[eventName].length;
4058
4060
  this.state[eventName][index] = func;
4059
4061
  },
@@ -4065,7 +4067,7 @@ const MovableHelperMethods = {
4065
4067
  */
4066
4068
  unlisten: function (eventName, id) {
4067
4069
  this._listenerMap = this._listenerMap || {};
4068
- const key = getKey(eventName, id);
4070
+ const key = getKey$1(eventName, id);
4069
4071
  const index = this._listenerMap[key];
4070
4072
  if (index !== undefined) {
4071
4073
  // Remove handler from list of event handlers and listenerMap
@@ -4075,7 +4077,7 @@ const MovableHelperMethods = {
4075
4077
  // Re-index existing events: if they occur after `index`, decrement
4076
4078
  const keys = _.keys(this._listenerMap);
4077
4079
  _.each(keys, function (key) {
4078
- if (getEventName(key) === eventName &&
4080
+ if (getEventName$1(key) === eventName &&
4079
4081
  // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
4080
4082
  this._listenerMap[key] > index) {
4081
4083
  // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
@@ -4086,10 +4088,6 @@ const MovableHelperMethods = {
4086
4088
  }
4087
4089
  };
4088
4090
 
4089
- /**
4090
- * Utility functions for writing Interactive2 movablethings
4091
- */
4092
-
4093
4091
  /**
4094
4092
  * Compute the correct vendor-prefixed `transform`.
4095
4093
  */
@@ -4123,6 +4121,7 @@ function computeCanUse3dTransform() {
4123
4121
  // @ts-expect-error - TS2538 - Type 'null' cannot be used as an index type. | TS2538 - Type 'undefined' cannot be used as an index type.
4124
4122
  return !!el.style[prefix];
4125
4123
  }
4124
+ const FUNCTION_ARRAY_OPTIONS = ["add", "modify", "draw", "remove", "constraints", "onMoveStart", "onMove", "onMoveEnd", "onClick"];
4126
4125
  const InteractiveUtil = {
4127
4126
  assert: function (isTrue, message) {
4128
4127
  if (!isTrue) {
@@ -4166,21 +4165,14 @@ const InteractiveUtil = {
4166
4165
  /**
4167
4166
  * Convert all function-or-array arguments to arrays of functions
4168
4167
  */
4169
- normalizeOptions: function (arrayOptionNames, options) {
4170
- // TODO(jack): Having to clone here is annoying; this
4171
- // function should really just modify this.state in place
4172
- // (and maybe be a function on MovableHelperMethods to get access
4173
- // to this.state), which would also be nicer because we could
4174
- // normalizeOptions once in this.modify
4175
- const result = _.clone(options);
4176
- _.each(arrayOptionNames, function (eventName) {
4177
- const funcOrArray = options[eventName];
4168
+ normalizeOptions: function (options) {
4169
+ const result = _extends({}, options);
4170
+ FUNCTION_ARRAY_OPTIONS.forEach(function (eventName) {
4178
4171
  // Only propagate values which were set; not present values
4179
4172
  // shouldn't be added to options because we'd like them to
4180
4173
  // fall through to defaults
4181
- if (funcOrArray !== undefined) {
4182
- const funcArray = InteractiveUtil.arrayify(funcOrArray);
4183
- result[eventName] = funcArray;
4174
+ if (options[eventName] !== undefined) {
4175
+ result[eventName] = InteractiveUtil.arrayify(options[eventName]);
4184
4176
  }
4185
4177
  });
4186
4178
  return result;
@@ -8713,6 +8705,10 @@ class Graphie$1 {
8713
8705
  // Refactor to accessor methods that look at this.dimensions.
8714
8706
  this.xpixels = void 0;
8715
8707
  this.ypixels = void 0;
8708
+ // set by Movables
8709
+ // TODO(benchristel): consider putting this state on the Movable instead of
8710
+ // on the Graphie
8711
+ this.isDragging = void 0;
8716
8712
  this.label = (point, text, direction, arg4, arg5) => {
8717
8713
  const style = typeof arg4 === "object" ? arg4 : arg5;
8718
8714
  const latex = typeof arg4 === "boolean" ? arg4 : true;
@@ -8873,6 +8869,9 @@ class Graphie$1 {
8873
8869
  var _options$isMobile;
8874
8870
  let scale = options.scale || [40, 40];
8875
8871
  scale = typeof scale === "number" ? [scale, scale] : scale;
8872
+
8873
+ // TODO(jeremy): This can be removed once we're confident that callers
8874
+ // obey the Typescript types.
8876
8875
  if (options.range == null) {
8877
8876
  throw new PerseusError("range should be specified in graph init", Errors.Internal);
8878
8877
  }
@@ -9531,6 +9530,11 @@ class Graphie$1 {
9531
9530
  });
9532
9531
  return processed;
9533
9532
  }
9533
+
9534
+ // This is a stub that's overridden in interactive.ts
9535
+ getMouseCoord(event) {
9536
+ throw new Error("getMouseCoord is a stub, and is not implemented");
9537
+ }
9534
9538
  }
9535
9539
  const labelDirections = {
9536
9540
  center: [-0.5, -0.5],
@@ -13724,26 +13728,10 @@ var GraphieClasses = {
13724
13728
  createSimpleClass: createSimpleClass
13725
13729
  };
13726
13730
 
13727
- /**
13728
- * Movable
13729
- *
13730
- * A Movable Something, that sends onMove events based on the
13731
- * mouse coordinate (graphie unscaled, non-pixel-value) of the
13732
- * move.
13733
- *
13734
- * Other MovableThings should generally have a Movable field, and
13735
- * let this class handle all of the virtual mouse events, and then
13736
- * take appropriate action in onMoveStart, onMove, onMoveEnd
13737
- */
13738
13731
  const normalizeOptions$3 = InteractiveUtil.normalizeOptions;
13739
13732
  const assert$8 = InteractiveUtil.assert;
13740
13733
 
13741
- // state parameters that should be converted into an array of
13742
- // functions
13743
- const FUNCTION_ARRAY_OPTIONS$3 = ["add", "modify", "draw", "remove", "onMoveStart", "onMove", "onMoveEnd", "onClick"];
13744
-
13745
- // Default "props" and "state". Both are added to this.state and
13746
- // receive magic getter methods (this.isHovering() etc).
13734
+ // Default "props" and "state". Both are added to this.state.
13747
13735
  // However, properties in DEFAULT_PROPS are updated on `modify()`,
13748
13736
  // while those in DEFAULT_STATE persist and are not updated.
13749
13737
  // Things that the user might want to change should be on "props",
@@ -13758,28 +13746,24 @@ const DEFAULT_STATE$3 = {
13758
13746
  isDragging: false,
13759
13747
  mouseTarget: null
13760
13748
  };
13761
- const Movable = function Movable(graphie, options) {
13762
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
13763
- _.extend(this, {
13764
- graphie: graphie,
13765
- state: {
13766
- // Set here because this must be unique for each instance
13749
+ class Movable {
13750
+ constructor(graphie, options) {
13751
+ this.graphie = void 0;
13752
+ this.state = void 0;
13753
+ this.prevState = void 0;
13754
+ // TODO(benchristel): delete _listenerMap; it's unused
13755
+ this._listenerMap = {};
13756
+ this.graphie = graphie;
13757
+ this.state = {
13767
13758
  id: _.uniqueId("movable")
13768
- }
13769
- });
13770
-
13771
- // We only set DEFAULT_STATE once, here
13772
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
13773
- this.modify(_.extend({}, DEFAULT_STATE$3, options));
13774
- };
13775
- InteractiveUtil.createGettersFor(Movable, _.extend({}, DEFAULT_PROPS$3, DEFAULT_STATE$3));
13776
- InteractiveUtil.addMovableHelperMethodsTo(Movable);
13777
- _.extend(Movable.prototype, {
13778
- cloneState: function () {
13779
- return _.clone(this.state);
13780
- },
13781
- _createDefaultState: function () {
13782
- return _.extend({
13759
+ };
13760
+ this.modify(_extends({}, DEFAULT_STATE$3, options));
13761
+ }
13762
+ modify(options) {
13763
+ this.update(_extends({}, this._createDefaultState(), options));
13764
+ }
13765
+ _createDefaultState() {
13766
+ return _extends({
13783
13767
  id: this.state.id,
13784
13768
  add: [],
13785
13769
  modify: [],
@@ -13789,67 +13773,12 @@ _.extend(Movable.prototype, {
13789
13773
  onMove: [],
13790
13774
  onMoveEnd: [],
13791
13775
  onClick: []
13792
-
13793
- // We only update props here, because we want things on state to
13794
- // be persistent, and updated appropriately in modify()
13795
13776
  }, DEFAULT_PROPS$3);
13796
- },
13797
- /**
13798
- * Resets the object to its state as if it were constructed with
13799
- * `options` originally. The only state maintained is `state.id`
13800
- *
13801
- * Analogous to React.js's replaceProps
13802
- */
13803
- modify: function (options) {
13804
- this.update(_.extend({}, this._createDefaultState(), options));
13805
- },
13806
- /**
13807
- * Simulates a mouse grab event on the movable object.
13808
- */
13809
- grab: function (coord) {
13810
- assert$8(point.is(coord));
13811
- const self = this;
13812
- const graphie = self.graphie;
13813
- const state = self.state;
13814
- state.isHovering = true;
13815
- state.isDragging = true;
13816
- graphie.isDragging = true;
13817
- const startMouseCoord = coord;
13818
- let prevMouseCoord = startMouseCoord;
13819
- self._fireEvent(state.onMoveStart, startMouseCoord, startMouseCoord);
13820
- const moveHandler = function moveHandler(e) {
13821
- e.preventDefault();
13822
- const mouseCoord = graphie.getMouseCoord(e);
13823
- self._fireEvent(state.onMove, mouseCoord, prevMouseCoord);
13824
- self.draw();
13825
- prevMouseCoord = mouseCoord;
13826
- };
13827
- const upHandler = function upHandler(e) {
13828
- $(document).unbind("vmousemove", moveHandler);
13829
- $(document).unbind("vmouseup", upHandler);
13830
- if (state.isHovering) {
13831
- self._fireEvent(state.onClick, prevMouseCoord, startMouseCoord);
13832
- }
13833
- state.isHovering = self.state.isMouseOver;
13834
- state.isDragging = false;
13835
- graphie.isDragging = false;
13836
- self._fireEvent(state.onMoveEnd, prevMouseCoord, startMouseCoord);
13837
- self.draw();
13838
- };
13839
- $(document).bind("vmousemove", moveHandler);
13840
- $(document).bind("vmouseup", upHandler);
13841
- },
13842
- /**
13843
- * Adjusts constructor parameters without changing previous settings
13844
- * for any option not specified
13845
- *
13846
- * Analogous to React.js's setProps
13847
- */
13848
- update: function (options) {
13849
- const self = this;
13850
- const graphie = self.graphie;
13851
- const prevState = self.cloneState();
13852
- const state = _.extend(self.state, normalizeOptions$3(FUNCTION_ARRAY_OPTIONS$3, options));
13777
+ }
13778
+ update(options) {
13779
+ const graphie = this.graphie;
13780
+ const prevState = this.cloneState();
13781
+ const state = Object.assign(this.state, normalizeOptions$3(options));
13853
13782
 
13854
13783
  // the invisible shape in front of the point that gets mouse events
13855
13784
  if (state.mouseTarget && !prevState.mouseTarget) {
@@ -13861,24 +13790,24 @@ _.extend(Movable.prototype, {
13861
13790
  }
13862
13791
  const isMouse = !("ontouchstart" in window);
13863
13792
  if (isMouse) {
13864
- $mouseTarget.on("vmouseover", function () {
13793
+ $mouseTarget.on("vmouseover", () => {
13865
13794
  state.isMouseOver = true;
13866
13795
  if (!graphie.isDragging) {
13867
13796
  state.isHovering = true;
13868
13797
  }
13869
- if (self.state.added) {
13798
+ if (this.state.added) {
13870
13799
  // Avoid drawing if the point has been removed
13871
- self.draw();
13800
+ this.draw();
13872
13801
  }
13873
13802
  });
13874
- $mouseTarget.on("vmouseout", function () {
13803
+ $mouseTarget.on("vmouseout", () => {
13875
13804
  state.isMouseOver = false;
13876
13805
  if (!state.isDragging) {
13877
13806
  state.isHovering = false;
13878
13807
  }
13879
- if (self.state.added) {
13808
+ if (this.state.added) {
13880
13809
  // Avoid drawing if the point has been removed
13881
- self.draw();
13810
+ this.draw();
13882
13811
  }
13883
13812
  });
13884
13813
  }
@@ -13890,13 +13819,13 @@ _.extend(Movable.prototype, {
13890
13819
  }, {
13891
13820
  passive: false
13892
13821
  });
13893
- $mouseTarget.on("vmousedown", function (e) {
13822
+ $mouseTarget.on("vmousedown", e => {
13894
13823
  if (e.which !== 0 && e.which !== 1) {
13895
13824
  return;
13896
13825
  }
13897
13826
  e.preventDefault();
13898
13827
  const mouseCoord = graphie.getMouseCoord(e);
13899
- self.grab(mouseCoord);
13828
+ this.grab(mouseCoord);
13900
13829
  });
13901
13830
  }
13902
13831
  if (state.mouseTarget && state.cursor !== undefined) {
@@ -13913,39 +13842,212 @@ _.extend(Movable.prototype, {
13913
13842
 
13914
13843
  // Trigger an add event if this hasn't been added before
13915
13844
  if (!state.added) {
13916
- self._fireEvent(state.modify, self.cloneState(), {});
13845
+ // TODO(benchristel): No one seems to handle the modify event. Can
13846
+ // we delete this?
13847
+ // @ts-expect-error - TS2345: Argument of type '{}' is not assignable to parameter of type 'State'.
13848
+ this._fireEvent(state.modify, this.cloneState(), {});
13917
13849
  state.added = true;
13918
13850
 
13919
13851
  // Update the state for `added` and in case the add event
13920
13852
  // changed it
13921
- self.prevState = self.cloneState();
13853
+ this.prevState = this.cloneState();
13922
13854
  }
13923
13855
 
13924
13856
  // Trigger a modify event
13925
- self._fireEvent(state.modify, self.cloneState(), self.prevState);
13926
- },
13927
- remove: function () {
13928
- this.state.added = false;
13929
- this._fireEvent(this.state.remove);
13930
- if (this.state.mouseTarget) {
13931
- $(this.state.mouseTarget).off();
13932
- this.state.mouseTarget.remove();
13933
- this.state.mouseTarget = null;
13857
+ this._fireEvent(state.modify, this.cloneState(), this.prevState);
13858
+ }
13859
+ cloneState() {
13860
+ return _extends({}, this.state);
13861
+ }
13862
+
13863
+ /**
13864
+ * Fire an onSomething type event to all functions in listeners
13865
+ */
13866
+ _fireEvent(listeners, ...args) {
13867
+ if (listeners == null) {
13868
+ return;
13934
13869
  }
13935
- },
13870
+ for (const listener of listeners) {
13871
+ listener.call(this, ...args);
13872
+ }
13873
+ }
13874
+
13875
+ /**
13876
+ * Call all draw functions, and update our prevState for the next
13877
+ * draw function
13878
+ */
13879
+ draw() {
13880
+ const currState = this.cloneState();
13881
+ this._fireEvent(this.state.draw, currState, this.prevState);
13882
+ this.prevState = currState;
13883
+ }
13884
+
13885
+ /**
13886
+ * Simulates a mouse grab event on the movable object.
13887
+ */
13888
+ grab(coord) {
13889
+ assert$8(point.is(coord));
13890
+ const graphie = this.graphie;
13891
+ const state = this.state;
13892
+ state.isHovering = true;
13893
+ state.isDragging = true;
13894
+ graphie.isDragging = true;
13895
+ const startMouseCoord = coord;
13896
+ let prevMouseCoord = startMouseCoord;
13897
+ this._fireEvent(state.onMoveStart, startMouseCoord, startMouseCoord);
13898
+ const moveHandler = e => {
13899
+ e.preventDefault();
13900
+ const mouseCoord = graphie.getMouseCoord(e);
13901
+ this._fireEvent(state.onMove, mouseCoord, prevMouseCoord);
13902
+ this.draw();
13903
+ prevMouseCoord = mouseCoord;
13904
+ };
13905
+ const upHandler = () => {
13906
+ $(document).unbind("vmousemove", moveHandler);
13907
+ $(document).unbind("vmouseup", upHandler);
13908
+ if (state.isHovering) {
13909
+ this._fireEvent(state.onClick, prevMouseCoord, startMouseCoord);
13910
+ }
13911
+ state.isHovering = this.state.isMouseOver;
13912
+ state.isDragging = false;
13913
+ graphie.isDragging = false;
13914
+ this._fireEvent(state.onMoveEnd, prevMouseCoord, startMouseCoord);
13915
+ this.draw();
13916
+ };
13917
+ $(document).bind("vmousemove", moveHandler);
13918
+ $(document).bind("vmouseup", upHandler);
13919
+ }
13920
+ _applyConstraints(current, previous, extraOptions) {
13921
+ var _this$state$constrain;
13922
+ let skipRemaining = false;
13923
+ return ((_this$state$constrain = this.state.constraints) != null ? _this$state$constrain : []).reduce((memo, constraint) => {
13924
+ // A move that has been cancelled won't be propagated to later
13925
+ // constraints calls
13926
+ if (memo === false) {
13927
+ return false;
13928
+ }
13929
+ if (skipRemaining) {
13930
+ return memo;
13931
+ }
13932
+ const result = constraint.call(this, memo, previous, _extends({
13933
+ onSkipRemaining: () => {
13934
+ skipRemaining = true;
13935
+ }
13936
+ }, extraOptions));
13937
+ if (result === false) {
13938
+ // Returning false cancels the move
13939
+ return false;
13940
+ }
13941
+ if (point.is(result, 2)) {
13942
+ // Returning a coord from constraints overrides the move
13943
+ return result;
13944
+ }
13945
+ if (result === true || result == null) {
13946
+ // Returning true or undefined allow the move to occur
13947
+ return memo;
13948
+ }
13949
+ // Anything else is an error
13950
+ throw new PerseusError("Constraint returned invalid result: " + result, Errors.Internal);
13951
+ }, current);
13952
+ }
13953
+
13936
13954
  // Change z-order to back
13937
- toBack: function () {
13955
+ toBack() {
13938
13956
  if (this.state.mouseTarget) {
13939
13957
  this.state.mouseTarget.toBack();
13940
13958
  }
13941
- },
13959
+ }
13960
+
13942
13961
  // Change z-order to front
13943
- toFront: function () {
13962
+ toFront() {
13944
13963
  if (this.state.mouseTarget) {
13945
13964
  this.state.mouseTarget.toFront();
13946
13965
  }
13947
13966
  }
13948
- });
13967
+
13968
+ /**
13969
+ * Add a listener to any event: startMove, constraints, onMove, onMoveEnd,
13970
+ * etc. If a listener is already bound to the given eventName and id, then
13971
+ * it is overwritten by func.
13972
+ *
13973
+ * eventName: the string name of the event to listen to. one of:
13974
+ * "onMoveStart", "onMove", "onMoveEnd", "draw", "remove"
13975
+ *
13976
+ * id: a string id that can be used to remove this event at a later time
13977
+ * note: adding multiple listeners with the same id is undefined behavior
13978
+ *
13979
+ * func: the function to call when the event happens, which is called
13980
+ * with the event's standard parameters [usually (coord, prevCoord) or
13981
+ * (state, prevState)]
13982
+ */
13983
+ listen(eventName, id, func) {
13984
+ this._listenerMap = this._listenerMap || {};
13985
+
13986
+ // If there's an existing handler, replace it by using its index in
13987
+ // `this.state[eventName]`; otherwise, add this handler to the end
13988
+ const key = getKey(eventName, id);
13989
+ const index = this._listenerMap[key] = this._listenerMap[key] || this.state[eventName].length;
13990
+ this.state[eventName][index] = func;
13991
+ }
13992
+
13993
+ /**
13994
+ * Remove a previously added listener, by the id specified in the
13995
+ * corresponding listen() call
13996
+ *
13997
+ * If the given id has not been registered already, this is a no-op
13998
+ */
13999
+ unlisten(eventName, id) {
14000
+ this._listenerMap = this._listenerMap || {};
14001
+ const key = getKey(eventName, id);
14002
+ const index = this._listenerMap[key];
14003
+ if (index !== undefined) {
14004
+ // Remove handler from list of event handlers and listenerMap
14005
+ this.state[eventName].splice(index, 1);
14006
+ delete this._listenerMap[key];
14007
+
14008
+ // Re-index existing events: if they occur after `index`, decrement
14009
+ const keys = _.keys(this._listenerMap);
14010
+ keys.forEach(key => {
14011
+ if (getEventName(key) === eventName && this._listenerMap[key] > index) {
14012
+ this._listenerMap[key]--;
14013
+ }
14014
+ });
14015
+ }
14016
+ }
14017
+ remove() {
14018
+ this.state.added = false;
14019
+ this._fireEvent(this.state.remove);
14020
+ if (this.state.mouseTarget) {
14021
+ $(this.state.mouseTarget).off();
14022
+ this.state.mouseTarget.remove();
14023
+ this.state.mouseTarget = null;
14024
+ }
14025
+ }
14026
+ cursor() {
14027
+ return this.state.cursor;
14028
+ }
14029
+ added() {
14030
+ return this.state.added;
14031
+ }
14032
+ isHovering() {
14033
+ return this.state.isHovering;
14034
+ }
14035
+ isMouseOver() {
14036
+ return this.state.isMouseOver;
14037
+ }
14038
+ isDragging() {
14039
+ return this.state.isDragging;
14040
+ }
14041
+ mouseTarget() {
14042
+ return this.state.mouseTarget;
14043
+ }
14044
+ }
14045
+ function getKey(eventName, id) {
14046
+ return eventName + ":" + id;
14047
+ }
14048
+ function getEventName(key) {
14049
+ return key.split(":")[0];
14050
+ }
13949
14051
 
13950
14052
  /* eslint-disable @babel/no-invalid-this */
13951
14053
  /**
@@ -14275,7 +14377,6 @@ var MovableLineOptions = {
14275
14377
  */
14276
14378
  const assert$7 = InteractiveUtil.assert;
14277
14379
  const normalizeOptions$2 = InteractiveUtil.normalizeOptions;
14278
- const FUNCTION_ARRAY_OPTIONS$2 = ["add", "draw", "remove", "onMoveStart", "constraints", "onMove", "onMoveEnd"];
14279
14380
 
14280
14381
  // Default "props" and "state". Both are added to this.state and
14281
14382
  // receive magic getter methods (this.cursor() etc).
@@ -14328,7 +14429,7 @@ _.extend(MovableLine$4.prototype, {
14328
14429
  _createDefaultState: function () {
14329
14430
  return _.extend({
14330
14431
  id: this.state.id
14331
- }, normalizeOptions$2(FUNCTION_ARRAY_OPTIONS$2,
14432
+ }, normalizeOptions$2(
14332
14433
  // Defaults are copied from MovableLineOptions.*.standard
14333
14434
  // These defaults are set here instead of DEFAULT_PROPS/STATE
14334
14435
  // because they:
@@ -14355,7 +14456,7 @@ _.extend(MovableLine$4.prototype, {
14355
14456
  update: function (options) {
14356
14457
  const self = this;
14357
14458
  const graphie = this.graphie;
14358
- const state = self.state = _.extend(self.state, normalizeOptions$2(FUNCTION_ARRAY_OPTIONS$2, options));
14459
+ const state = self.state = _.extend(self.state, normalizeOptions$2(options));
14359
14460
 
14360
14461
  // Default things inside the state.normalStyle object, because
14361
14462
  // _.extend is not deep.
@@ -14788,31 +14889,39 @@ const constraints$1 = {
14788
14889
  snap: function (snap) {
14789
14890
  return function (coord) {
14790
14891
  if (snap === null) {
14791
- // NOTE(kevinb): this should probably return the original point
14892
+ // TODO(benchristel), NOTE(kevinb): this should probably return
14893
+ // the original point
14792
14894
  return true;
14793
14895
  }
14794
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
14795
- snap = snap || this.graphie.snap;
14796
- return point.roundTo(coord, snap);
14896
+ // @ts-expect-error - TS2339: Property 'snap' does not exist on type 'Graphie'.
14897
+ return point.roundTo(coord, snap || this.graphie.snap);
14797
14898
  };
14798
14899
  },
14799
- bound: function (range, snap, paddingPx) {
14800
- if (paddingPx === undefined) {
14801
- if (range === undefined) {
14802
- paddingPx = 10;
14900
+ bound: function (range, snap, optionalPaddingPx) {
14901
+ const paddingPx = (() => {
14902
+ if (optionalPaddingPx === undefined) {
14903
+ if (range === undefined) {
14904
+ return 10;
14905
+ } else {
14906
+ return 0;
14907
+ }
14803
14908
  } else {
14804
- paddingPx = 0;
14909
+ return optionalPaddingPx;
14805
14910
  }
14806
- }
14911
+ })();
14807
14912
  return function (coord, prev, options) {
14808
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
14809
14913
  const graphie = this.graphie;
14810
14914
  range = range || graphie.range;
14811
14915
  if (snap === undefined) {
14916
+ // @ts-expect-error - Property 'snap' does not exist on type 'Graphie'.
14812
14917
  snap = graphie.snap;
14813
14918
  }
14814
- let lower = graphie.unscalePoint([paddingPx, graphie.ypixels - paddingPx]);
14815
- let upper = graphie.unscalePoint([graphie.xpixels - paddingPx, paddingPx]);
14919
+ let lower = graphie.unscalePoint([paddingPx,
14920
+ // @ts-expect-error - 'graphie.ypixels' is possibly 'undefined'.
14921
+ graphie.ypixels - paddingPx]);
14922
+ let upper = graphie.unscalePoint([
14923
+ // @ts-expect-error - 'graphie.ypixels' is possibly 'undefined'.
14924
+ graphie.xpixels - paddingPx, paddingPx]);
14816
14925
  if (snap) {
14817
14926
  lower = point.ceilTo(lower, snap);
14818
14927
  upper = point.floorTo(upper, snap);
@@ -14859,10 +14968,6 @@ const {
14859
14968
  processMath
14860
14969
  } = Tex$1;
14861
14970
 
14862
- // State parameters that should be converted into an array of
14863
- // functions
14864
- const FUNCTION_ARRAY_OPTIONS$1 = _.keys(MovablePointOptions);
14865
-
14866
14971
  // Default "props" and "state". Both are added to this.state and
14867
14972
  // receive magic getter methods (this.coord() etc).
14868
14973
  // However, properties in DEFAULT_PROPS are updated on `modify()`,
@@ -14915,7 +15020,7 @@ _.extend(MovablePoint$5.prototype, {
14915
15020
  _createDefaultState: function () {
14916
15021
  return _.extend({
14917
15022
  id: this.state.id
14918
- }, normalizeOptions$1(FUNCTION_ARRAY_OPTIONS$1,
15023
+ }, normalizeOptions$1(
14919
15024
  // Defaults are copied from MovablePointOptions.*.standard
14920
15025
  // These defaults are set here instead of DEFAULT_PROPS/STATE
14921
15026
  // because they:
@@ -14988,7 +15093,7 @@ _.extend(MovablePoint$5.prototype, {
14988
15093
  update: function (options) {
14989
15094
  const self = this;
14990
15095
  const graphie = self.graphie;
14991
- const state = _.extend(self.state, normalizeOptions$1(FUNCTION_ARRAY_OPTIONS$1, options));
15096
+ const state = _.extend(self.state, normalizeOptions$1(options));
14992
15097
  assert$6(point.is(state.coord));
14993
15098
 
14994
15099
  // Default things inside the state.normalStyle object, because
@@ -15595,10 +15700,6 @@ var MovablePolygonOptions = {
15595
15700
  const assert$5 = InteractiveUtil.assert;
15596
15701
  const normalizeOptions = InteractiveUtil.normalizeOptions;
15597
15702
 
15598
- // State parameters that should be converted into an array of
15599
- // functions
15600
- const FUNCTION_ARRAY_OPTIONS = _.keys(MovablePolygonOptions);
15601
-
15602
15703
  // Default "props" and "state". Both are added to this.state and
15603
15704
  // receive magic getter methods (this.points() etc).
15604
15705
  // However, properties in DEFAULT_PROPS are updated on `modify()`,
@@ -15658,7 +15759,7 @@ _.extend(MovablePolygon.prototype, {
15658
15759
  _createDefaultState: function () {
15659
15760
  return _.extend({
15660
15761
  id: this.state.id
15661
- }, normalizeOptions(FUNCTION_ARRAY_OPTIONS,
15762
+ }, normalizeOptions(
15662
15763
  // Defaults are copied from MovablePolygonOptions.*.standard
15663
15764
  // These defaults are set here instead of DEFAULT_PROPS/STATE
15664
15765
  // because they:
@@ -15689,7 +15790,7 @@ _.extend(MovablePolygon.prototype, {
15689
15790
  update: function (options) {
15690
15791
  const self = this;
15691
15792
  const graphie = self.graphie;
15692
- const state = _.extend(self.state, normalizeOptions(FUNCTION_ARRAY_OPTIONS, options));
15793
+ const state = _.extend(self.state, normalizeOptions(options));
15693
15794
 
15694
15795
  // Default things inside the state.normalStyle object, because
15695
15796
  // _.extend is not deep.
@@ -41499,7 +41600,7 @@ const init = function init(options) {
41499
41600
 
41500
41601
  // This file is processed by a Rollup plugin (replace) to inject the production
41501
41602
  const libName = "@khanacademy/perseus";
41502
- const libVersion = "19.1.3";
41603
+ const libVersion = "19.1.5";
41503
41604
  addLibraryVersionToPerseusDebug(libName, libVersion);
41504
41605
 
41505
41606
  const apiVersion = {