@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/index.js CHANGED
@@ -3999,18 +3999,23 @@ class FixedToResponsive extends React__namespace.Component {
3999
3999
 
4000
4000
  /* Local helper methods. */
4001
4001
 
4002
- function getKey(eventName, id) {
4002
+ function getKey$1(eventName, id) {
4003
4003
  return eventName + ":" + id;
4004
4004
  }
4005
- function getEventName(key) {
4005
+ function getEventName$1(key) {
4006
4006
  return key.split(":")[0];
4007
4007
  }
4008
4008
  const MovableHelperMethods = {
4009
4009
  /**
4010
4010
  * Fire an onSomething type event to all functions in listeners
4011
4011
  */
4012
- _fireEvent: function (listeners, currentValue, previousValue) {
4013
- ___default["default"].invoke(listeners, "call", this, currentValue, previousValue);
4012
+ _fireEvent: function (listeners) {
4013
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
4014
+ args[_key - 1] = arguments[_key];
4015
+ }
4016
+ for (const listener of listeners) {
4017
+ listener.call(this, ...args);
4018
+ }
4014
4019
  },
4015
4020
  /**
4016
4021
  * Combine the array of constraints functions
@@ -4078,7 +4083,7 @@ const MovableHelperMethods = {
4078
4083
 
4079
4084
  // If there's an existing handler, replace it by using its index in
4080
4085
  // `this.state[eventName]`; otherwise, add this handler to the end
4081
- const key = getKey(eventName, id);
4086
+ const key = getKey$1(eventName, id);
4082
4087
  const index = this._listenerMap[key] = this._listenerMap[key] || this.state[eventName].length;
4083
4088
  this.state[eventName][index] = func;
4084
4089
  },
@@ -4090,7 +4095,7 @@ const MovableHelperMethods = {
4090
4095
  */
4091
4096
  unlisten: function (eventName, id) {
4092
4097
  this._listenerMap = this._listenerMap || {};
4093
- const key = getKey(eventName, id);
4098
+ const key = getKey$1(eventName, id);
4094
4099
  const index = this._listenerMap[key];
4095
4100
  if (index !== undefined) {
4096
4101
  // Remove handler from list of event handlers and listenerMap
@@ -4100,7 +4105,7 @@ const MovableHelperMethods = {
4100
4105
  // Re-index existing events: if they occur after `index`, decrement
4101
4106
  const keys = ___default["default"].keys(this._listenerMap);
4102
4107
  ___default["default"].each(keys, function (key) {
4103
- if (getEventName(key) === eventName &&
4108
+ if (getEventName$1(key) === eventName &&
4104
4109
  // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
4105
4110
  this._listenerMap[key] > index) {
4106
4111
  // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
@@ -4148,6 +4153,7 @@ function computeCanUse3dTransform() {
4148
4153
  // @ts-expect-error - TS2538 - Type 'null' cannot be used as an index type. | TS2538 - Type 'undefined' cannot be used as an index type.
4149
4154
  return !!el.style[prefix];
4150
4155
  }
4156
+ const FUNCTION_ARRAY_OPTIONS = ["add", "modify", "draw", "remove", "constraints", "onMoveStart", "onMove", "onMoveEnd", "onClick"];
4151
4157
  const InteractiveUtil = {
4152
4158
  assert: function (isTrue, message) {
4153
4159
  if (!isTrue) {
@@ -4191,21 +4197,16 @@ const InteractiveUtil = {
4191
4197
  /**
4192
4198
  * Convert all function-or-array arguments to arrays of functions
4193
4199
  */
4194
- normalizeOptions: function (arrayOptionNames, options) {
4195
- // TODO(jack): Having to clone here is annoying; this
4196
- // function should really just modify this.state in place
4197
- // (and maybe be a function on MovableHelperMethods to get access
4198
- // to this.state), which would also be nicer because we could
4199
- // normalizeOptions once in this.modify
4200
- const result = ___default["default"].clone(options);
4201
- ___default["default"].each(arrayOptionNames, function (eventName) {
4202
- const funcOrArray = options[eventName];
4200
+ normalizeOptions: function (options) {
4201
+ const result = {
4202
+ ...options
4203
+ };
4204
+ FUNCTION_ARRAY_OPTIONS.forEach(function (eventName) {
4203
4205
  // Only propagate values which were set; not present values
4204
4206
  // shouldn't be added to options because we'd like them to
4205
4207
  // fall through to defaults
4206
- if (funcOrArray !== undefined) {
4207
- const funcArray = InteractiveUtil.arrayify(funcOrArray);
4208
- result[eventName] = funcArray;
4208
+ if (options[eventName] !== undefined) {
4209
+ result[eventName] = InteractiveUtil.arrayify(options[eventName]);
4209
4210
  }
4210
4211
  });
4211
4212
  return result;
@@ -8706,6 +8707,9 @@ class Graphie$1 {
8706
8707
  // TODO(benchristel): xpixels and ypixels are never used by this class, but
8707
8708
  // other code reaches in to access them :(
8708
8709
  // Refactor to accessor methods that look at this.dimensions.
8710
+ // set by Movables
8711
+ // TODO(benchristel): consider putting this state on the Movable instead of
8712
+ // on the Graphie
8709
8713
  constructor(el) {
8710
8714
  this.el = el;
8711
8715
  $__default["default"](el).css("position", "relative");
@@ -8717,6 +8721,9 @@ class Graphie$1 {
8717
8721
  init(options) {
8718
8722
  let scale = options.scale || [40, 40];
8719
8723
  scale = typeof scale === "number" ? [scale, scale] : scale;
8724
+
8725
+ // TODO(jeremy): This can be removed once we're confident that callers
8726
+ // obey the Typescript types.
8720
8727
  if (options.range == null) {
8721
8728
  throw new PerseusError("range should be specified in graph init", Errors.Internal);
8722
8729
  }
@@ -9534,6 +9541,11 @@ class Graphie$1 {
9534
9541
  });
9535
9542
  return processed;
9536
9543
  }
9544
+
9545
+ // This is a stub that's overridden in interactive.ts
9546
+ getMouseCoord(event) {
9547
+ throw new Error("getMouseCoord is a stub, and is not implemented");
9548
+ }
9537
9549
  }
9538
9550
  const labelDirections = {
9539
9551
  center: [-0.5, -0.5],
@@ -13742,12 +13754,7 @@ var GraphieClasses = {
13742
13754
  const normalizeOptions$3 = InteractiveUtil.normalizeOptions;
13743
13755
  const assert$8 = InteractiveUtil.assert;
13744
13756
 
13745
- // state parameters that should be converted into an array of
13746
- // functions
13747
- const FUNCTION_ARRAY_OPTIONS$3 = ["add", "modify", "draw", "remove", "onMoveStart", "onMove", "onMoveEnd", "onClick"];
13748
-
13749
- // Default "props" and "state". Both are added to this.state and
13750
- // receive magic getter methods (this.isHovering() etc).
13757
+ // Default "props" and "state". Both are added to this.state.
13751
13758
  // However, properties in DEFAULT_PROPS are updated on `modify()`,
13752
13759
  // while those in DEFAULT_STATE persist and are not updated.
13753
13760
  // Things that the user might want to change should be on "props",
@@ -13762,28 +13769,27 @@ const DEFAULT_STATE$3 = {
13762
13769
  isDragging: false,
13763
13770
  mouseTarget: null
13764
13771
  };
13765
- const Movable = function (graphie, options) {
13766
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
13767
- ___default["default"].extend(this, {
13768
- graphie: graphie,
13769
- state: {
13770
- // Set here because this must be unique for each instance
13772
+ class Movable {
13773
+ // TODO(benchristel): delete _listenerMap; it's unused
13774
+ _listenerMap = {};
13775
+ constructor(graphie, options) {
13776
+ this.graphie = graphie;
13777
+ this.state = {
13771
13778
  id: ___default["default"].uniqueId("movable")
13772
- }
13773
- });
13774
-
13775
- // We only set DEFAULT_STATE once, here
13776
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
13777
- this.modify(___default["default"].extend({}, DEFAULT_STATE$3, options));
13778
- };
13779
- InteractiveUtil.createGettersFor(Movable, ___default["default"].extend({}, DEFAULT_PROPS$3, DEFAULT_STATE$3));
13780
- InteractiveUtil.addMovableHelperMethodsTo(Movable);
13781
- ___default["default"].extend(Movable.prototype, {
13782
- cloneState: function () {
13783
- return ___default["default"].clone(this.state);
13784
- },
13785
- _createDefaultState: function () {
13786
- return ___default["default"].extend({
13779
+ };
13780
+ this.modify({
13781
+ ...DEFAULT_STATE$3,
13782
+ ...options
13783
+ });
13784
+ }
13785
+ modify(options) {
13786
+ this.update({
13787
+ ...this._createDefaultState(),
13788
+ ...options
13789
+ });
13790
+ }
13791
+ _createDefaultState() {
13792
+ return {
13787
13793
  id: this.state.id,
13788
13794
  add: [],
13789
13795
  modify: [],
@@ -13792,68 +13798,16 @@ ___default["default"].extend(Movable.prototype, {
13792
13798
  onMoveStart: [],
13793
13799
  onMove: [],
13794
13800
  onMoveEnd: [],
13795
- onClick: []
13796
-
13801
+ onClick: [],
13797
13802
  // We only update props here, because we want things on state to
13798
13803
  // be persistent, and updated appropriately in modify()
13799
- }, DEFAULT_PROPS$3);
13800
- },
13801
- /**
13802
- * Resets the object to its state as if it were constructed with
13803
- * `options` originally. The only state maintained is `state.id`
13804
- *
13805
- * Analogous to React.js's replaceProps
13806
- */
13807
- modify: function (options) {
13808
- this.update(___default["default"].extend({}, this._createDefaultState(), options));
13809
- },
13810
- /**
13811
- * Simulates a mouse grab event on the movable object.
13812
- */
13813
- grab: function (coord) {
13814
- assert$8(kmath.point.is(coord));
13815
- const self = this;
13816
- const graphie = self.graphie;
13817
- const state = self.state;
13818
- state.isHovering = true;
13819
- state.isDragging = true;
13820
- graphie.isDragging = true;
13821
- const startMouseCoord = coord;
13822
- let prevMouseCoord = startMouseCoord;
13823
- self._fireEvent(state.onMoveStart, startMouseCoord, startMouseCoord);
13824
- const moveHandler = function (e) {
13825
- e.preventDefault();
13826
- const mouseCoord = graphie.getMouseCoord(e);
13827
- self._fireEvent(state.onMove, mouseCoord, prevMouseCoord);
13828
- self.draw();
13829
- prevMouseCoord = mouseCoord;
13804
+ ...DEFAULT_PROPS$3
13830
13805
  };
13831
- const upHandler = function (e) {
13832
- $__default["default"](document).unbind("vmousemove", moveHandler);
13833
- $__default["default"](document).unbind("vmouseup", upHandler);
13834
- if (state.isHovering) {
13835
- self._fireEvent(state.onClick, prevMouseCoord, startMouseCoord);
13836
- }
13837
- state.isHovering = self.state.isMouseOver;
13838
- state.isDragging = false;
13839
- graphie.isDragging = false;
13840
- self._fireEvent(state.onMoveEnd, prevMouseCoord, startMouseCoord);
13841
- self.draw();
13842
- };
13843
- $__default["default"](document).bind("vmousemove", moveHandler);
13844
- $__default["default"](document).bind("vmouseup", upHandler);
13845
- },
13846
- /**
13847
- * Adjusts constructor parameters without changing previous settings
13848
- * for any option not specified
13849
- *
13850
- * Analogous to React.js's setProps
13851
- */
13852
- update: function (options) {
13853
- const self = this;
13854
- const graphie = self.graphie;
13855
- const prevState = self.cloneState();
13856
- const state = ___default["default"].extend(self.state, normalizeOptions$3(FUNCTION_ARRAY_OPTIONS$3, options));
13806
+ }
13807
+ update(options) {
13808
+ const graphie = this.graphie;
13809
+ const prevState = this.cloneState();
13810
+ const state = Object.assign(this.state, normalizeOptions$3(options));
13857
13811
 
13858
13812
  // the invisible shape in front of the point that gets mouse events
13859
13813
  if (state.mouseTarget && !prevState.mouseTarget) {
@@ -13865,24 +13819,24 @@ ___default["default"].extend(Movable.prototype, {
13865
13819
  }
13866
13820
  const isMouse = !("ontouchstart" in window);
13867
13821
  if (isMouse) {
13868
- $mouseTarget.on("vmouseover", function () {
13822
+ $mouseTarget.on("vmouseover", () => {
13869
13823
  state.isMouseOver = true;
13870
13824
  if (!graphie.isDragging) {
13871
13825
  state.isHovering = true;
13872
13826
  }
13873
- if (self.state.added) {
13827
+ if (this.state.added) {
13874
13828
  // Avoid drawing if the point has been removed
13875
- self.draw();
13829
+ this.draw();
13876
13830
  }
13877
13831
  });
13878
- $mouseTarget.on("vmouseout", function () {
13832
+ $mouseTarget.on("vmouseout", () => {
13879
13833
  state.isMouseOver = false;
13880
13834
  if (!state.isDragging) {
13881
13835
  state.isHovering = false;
13882
13836
  }
13883
- if (self.state.added) {
13837
+ if (this.state.added) {
13884
13838
  // Avoid drawing if the point has been removed
13885
- self.draw();
13839
+ this.draw();
13886
13840
  }
13887
13841
  });
13888
13842
  }
@@ -13894,13 +13848,13 @@ ___default["default"].extend(Movable.prototype, {
13894
13848
  }, {
13895
13849
  passive: false
13896
13850
  });
13897
- $mouseTarget.on("vmousedown", function (e) {
13851
+ $mouseTarget.on("vmousedown", e => {
13898
13852
  if (e.which !== 0 && e.which !== 1) {
13899
13853
  return;
13900
13854
  }
13901
13855
  e.preventDefault();
13902
13856
  const mouseCoord = graphie.getMouseCoord(e);
13903
- self.grab(mouseCoord);
13857
+ this.grab(mouseCoord);
13904
13858
  });
13905
13859
  }
13906
13860
  if (state.mouseTarget && state.cursor !== undefined) {
@@ -13917,39 +13871,217 @@ ___default["default"].extend(Movable.prototype, {
13917
13871
 
13918
13872
  // Trigger an add event if this hasn't been added before
13919
13873
  if (!state.added) {
13920
- self._fireEvent(state.modify, self.cloneState(), {});
13874
+ // TODO(benchristel): No one seems to handle the modify event. Can
13875
+ // we delete this?
13876
+ // @ts-expect-error - TS2345: Argument of type '{}' is not assignable to parameter of type 'State'.
13877
+ this._fireEvent(state.modify, this.cloneState(), {});
13921
13878
  state.added = true;
13922
13879
 
13923
13880
  // Update the state for `added` and in case the add event
13924
13881
  // changed it
13925
- self.prevState = self.cloneState();
13882
+ this.prevState = this.cloneState();
13926
13883
  }
13927
13884
 
13928
13885
  // Trigger a modify event
13929
- self._fireEvent(state.modify, self.cloneState(), self.prevState);
13930
- },
13931
- remove: function () {
13932
- this.state.added = false;
13933
- this._fireEvent(this.state.remove);
13934
- if (this.state.mouseTarget) {
13935
- $__default["default"](this.state.mouseTarget).off();
13936
- this.state.mouseTarget.remove();
13937
- this.state.mouseTarget = null;
13886
+ this._fireEvent(state.modify, this.cloneState(), this.prevState);
13887
+ }
13888
+ cloneState() {
13889
+ return {
13890
+ ...this.state
13891
+ };
13892
+ }
13893
+
13894
+ /**
13895
+ * Fire an onSomething type event to all functions in listeners
13896
+ */
13897
+ _fireEvent(listeners) {
13898
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
13899
+ args[_key - 1] = arguments[_key];
13938
13900
  }
13939
- },
13901
+ if (listeners == null) {
13902
+ return;
13903
+ }
13904
+ for (const listener of listeners) {
13905
+ listener.call(this, ...args);
13906
+ }
13907
+ }
13908
+
13909
+ /**
13910
+ * Call all draw functions, and update our prevState for the next
13911
+ * draw function
13912
+ */
13913
+ draw() {
13914
+ const currState = this.cloneState();
13915
+ this._fireEvent(this.state.draw, currState, this.prevState);
13916
+ this.prevState = currState;
13917
+ }
13918
+
13919
+ /**
13920
+ * Simulates a mouse grab event on the movable object.
13921
+ */
13922
+ grab(coord) {
13923
+ assert$8(kmath.point.is(coord));
13924
+ const graphie = this.graphie;
13925
+ const state = this.state;
13926
+ state.isHovering = true;
13927
+ state.isDragging = true;
13928
+ graphie.isDragging = true;
13929
+ const startMouseCoord = coord;
13930
+ let prevMouseCoord = startMouseCoord;
13931
+ this._fireEvent(state.onMoveStart, startMouseCoord, startMouseCoord);
13932
+ const moveHandler = e => {
13933
+ e.preventDefault();
13934
+ const mouseCoord = graphie.getMouseCoord(e);
13935
+ this._fireEvent(state.onMove, mouseCoord, prevMouseCoord);
13936
+ this.draw();
13937
+ prevMouseCoord = mouseCoord;
13938
+ };
13939
+ const upHandler = () => {
13940
+ $__default["default"](document).unbind("vmousemove", moveHandler);
13941
+ $__default["default"](document).unbind("vmouseup", upHandler);
13942
+ if (state.isHovering) {
13943
+ this._fireEvent(state.onClick, prevMouseCoord, startMouseCoord);
13944
+ }
13945
+ state.isHovering = this.state.isMouseOver;
13946
+ state.isDragging = false;
13947
+ graphie.isDragging = false;
13948
+ this._fireEvent(state.onMoveEnd, prevMouseCoord, startMouseCoord);
13949
+ this.draw();
13950
+ };
13951
+ $__default["default"](document).bind("vmousemove", moveHandler);
13952
+ $__default["default"](document).bind("vmouseup", upHandler);
13953
+ }
13954
+ _applyConstraints(current, previous, extraOptions) {
13955
+ let skipRemaining = false;
13956
+ return (this.state.constraints ?? []).reduce((memo, constraint) => {
13957
+ // A move that has been cancelled won't be propagated to later
13958
+ // constraints calls
13959
+ if (memo === false) {
13960
+ return false;
13961
+ }
13962
+ if (skipRemaining) {
13963
+ return memo;
13964
+ }
13965
+ const result = constraint.call(this, memo, previous, {
13966
+ onSkipRemaining: () => {
13967
+ skipRemaining = true;
13968
+ },
13969
+ ...extraOptions
13970
+ });
13971
+ if (result === false) {
13972
+ // Returning false cancels the move
13973
+ return false;
13974
+ }
13975
+ if (kmath.point.is(result, 2)) {
13976
+ // Returning a coord from constraints overrides the move
13977
+ return result;
13978
+ }
13979
+ if (result === true || result == null) {
13980
+ // Returning true or undefined allow the move to occur
13981
+ return memo;
13982
+ }
13983
+ // Anything else is an error
13984
+ throw new PerseusError("Constraint returned invalid result: " + result, Errors.Internal);
13985
+ }, current);
13986
+ }
13987
+
13940
13988
  // Change z-order to back
13941
- toBack: function () {
13989
+ toBack() {
13942
13990
  if (this.state.mouseTarget) {
13943
13991
  this.state.mouseTarget.toBack();
13944
13992
  }
13945
- },
13993
+ }
13994
+
13946
13995
  // Change z-order to front
13947
- toFront: function () {
13996
+ toFront() {
13948
13997
  if (this.state.mouseTarget) {
13949
13998
  this.state.mouseTarget.toFront();
13950
13999
  }
13951
14000
  }
13952
- });
14001
+
14002
+ /**
14003
+ * Add a listener to any event: startMove, constraints, onMove, onMoveEnd,
14004
+ * etc. If a listener is already bound to the given eventName and id, then
14005
+ * it is overwritten by func.
14006
+ *
14007
+ * eventName: the string name of the event to listen to. one of:
14008
+ * "onMoveStart", "onMove", "onMoveEnd", "draw", "remove"
14009
+ *
14010
+ * id: a string id that can be used to remove this event at a later time
14011
+ * note: adding multiple listeners with the same id is undefined behavior
14012
+ *
14013
+ * func: the function to call when the event happens, which is called
14014
+ * with the event's standard parameters [usually (coord, prevCoord) or
14015
+ * (state, prevState)]
14016
+ */
14017
+ listen(eventName, id, func) {
14018
+ this._listenerMap = this._listenerMap || {};
14019
+
14020
+ // If there's an existing handler, replace it by using its index in
14021
+ // `this.state[eventName]`; otherwise, add this handler to the end
14022
+ const key = getKey(eventName, id);
14023
+ const index = this._listenerMap[key] = this._listenerMap[key] || this.state[eventName].length;
14024
+ this.state[eventName][index] = func;
14025
+ }
14026
+
14027
+ /**
14028
+ * Remove a previously added listener, by the id specified in the
14029
+ * corresponding listen() call
14030
+ *
14031
+ * If the given id has not been registered already, this is a no-op
14032
+ */
14033
+ unlisten(eventName, id) {
14034
+ this._listenerMap = this._listenerMap || {};
14035
+ const key = getKey(eventName, id);
14036
+ const index = this._listenerMap[key];
14037
+ if (index !== undefined) {
14038
+ // Remove handler from list of event handlers and listenerMap
14039
+ this.state[eventName].splice(index, 1);
14040
+ delete this._listenerMap[key];
14041
+
14042
+ // Re-index existing events: if they occur after `index`, decrement
14043
+ const keys = ___default["default"].keys(this._listenerMap);
14044
+ keys.forEach(key => {
14045
+ if (getEventName(key) === eventName && this._listenerMap[key] > index) {
14046
+ this._listenerMap[key]--;
14047
+ }
14048
+ });
14049
+ }
14050
+ }
14051
+ remove() {
14052
+ this.state.added = false;
14053
+ this._fireEvent(this.state.remove);
14054
+ if (this.state.mouseTarget) {
14055
+ $__default["default"](this.state.mouseTarget).off();
14056
+ this.state.mouseTarget.remove();
14057
+ this.state.mouseTarget = null;
14058
+ }
14059
+ }
14060
+ cursor() {
14061
+ return this.state.cursor;
14062
+ }
14063
+ added() {
14064
+ return this.state.added;
14065
+ }
14066
+ isHovering() {
14067
+ return this.state.isHovering;
14068
+ }
14069
+ isMouseOver() {
14070
+ return this.state.isMouseOver;
14071
+ }
14072
+ isDragging() {
14073
+ return this.state.isDragging;
14074
+ }
14075
+ mouseTarget() {
14076
+ return this.state.mouseTarget;
14077
+ }
14078
+ }
14079
+ function getKey(eventName, id) {
14080
+ return eventName + ":" + id;
14081
+ }
14082
+ function getEventName(key) {
14083
+ return key.split(":")[0];
14084
+ }
13953
14085
 
13954
14086
  /* eslint-disable @babel/no-invalid-this */
13955
14087
  /**
@@ -14279,7 +14411,6 @@ var MovableLineOptions = {
14279
14411
  */
14280
14412
  const assert$7 = InteractiveUtil.assert;
14281
14413
  const normalizeOptions$2 = InteractiveUtil.normalizeOptions;
14282
- const FUNCTION_ARRAY_OPTIONS$2 = ["add", "draw", "remove", "onMoveStart", "constraints", "onMove", "onMoveEnd"];
14283
14414
 
14284
14415
  // Default "props" and "state". Both are added to this.state and
14285
14416
  // receive magic getter methods (this.cursor() etc).
@@ -14332,7 +14463,7 @@ ___default["default"].extend(MovableLine$4.prototype, {
14332
14463
  _createDefaultState: function () {
14333
14464
  return ___default["default"].extend({
14334
14465
  id: this.state.id
14335
- }, normalizeOptions$2(FUNCTION_ARRAY_OPTIONS$2,
14466
+ }, normalizeOptions$2(
14336
14467
  // Defaults are copied from MovableLineOptions.*.standard
14337
14468
  // These defaults are set here instead of DEFAULT_PROPS/STATE
14338
14469
  // because they:
@@ -14359,7 +14490,7 @@ ___default["default"].extend(MovableLine$4.prototype, {
14359
14490
  update: function (options) {
14360
14491
  const self = this;
14361
14492
  const graphie = this.graphie;
14362
- const state = self.state = ___default["default"].extend(self.state, normalizeOptions$2(FUNCTION_ARRAY_OPTIONS$2, options));
14493
+ const state = self.state = ___default["default"].extend(self.state, normalizeOptions$2(options));
14363
14494
 
14364
14495
  // Default things inside the state.normalStyle object, because
14365
14496
  // _.extend is not deep.
@@ -14796,31 +14927,39 @@ const constraints$1 = {
14796
14927
  snap: function (snap) {
14797
14928
  return function (coord) {
14798
14929
  if (snap === null) {
14799
- // NOTE(kevinb): this should probably return the original point
14930
+ // TODO(benchristel), NOTE(kevinb): this should probably return
14931
+ // the original point
14800
14932
  return true;
14801
14933
  }
14802
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
14803
- snap = snap || this.graphie.snap;
14804
- return kmath.point.roundTo(coord, snap);
14934
+ // @ts-expect-error - TS2339: Property 'snap' does not exist on type 'Graphie'.
14935
+ return kmath.point.roundTo(coord, snap || this.graphie.snap);
14805
14936
  };
14806
14937
  },
14807
- bound: function (range, snap, paddingPx) {
14808
- if (paddingPx === undefined) {
14809
- if (range === undefined) {
14810
- paddingPx = 10;
14938
+ bound: function (range, snap, optionalPaddingPx) {
14939
+ const paddingPx = (() => {
14940
+ if (optionalPaddingPx === undefined) {
14941
+ if (range === undefined) {
14942
+ return 10;
14943
+ } else {
14944
+ return 0;
14945
+ }
14811
14946
  } else {
14812
- paddingPx = 0;
14947
+ return optionalPaddingPx;
14813
14948
  }
14814
- }
14949
+ })();
14815
14950
  return function (coord, prev, options) {
14816
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
14817
14951
  const graphie = this.graphie;
14818
14952
  range = range || graphie.range;
14819
14953
  if (snap === undefined) {
14954
+ // @ts-expect-error - Property 'snap' does not exist on type 'Graphie'.
14820
14955
  snap = graphie.snap;
14821
14956
  }
14822
- let lower = graphie.unscalePoint([paddingPx, graphie.ypixels - paddingPx]);
14823
- let upper = graphie.unscalePoint([graphie.xpixels - paddingPx, paddingPx]);
14957
+ let lower = graphie.unscalePoint([paddingPx,
14958
+ // @ts-expect-error - 'graphie.ypixels' is possibly 'undefined'.
14959
+ graphie.ypixels - paddingPx]);
14960
+ let upper = graphie.unscalePoint([
14961
+ // @ts-expect-error - 'graphie.ypixels' is possibly 'undefined'.
14962
+ graphie.xpixels - paddingPx, paddingPx]);
14824
14963
  if (snap) {
14825
14964
  lower = kmath.point.ceilTo(lower, snap);
14826
14965
  upper = kmath.point.floorTo(upper, snap);
@@ -14867,10 +15006,6 @@ const {
14867
15006
  processMath
14868
15007
  } = Tex$1;
14869
15008
 
14870
- // State parameters that should be converted into an array of
14871
- // functions
14872
- const FUNCTION_ARRAY_OPTIONS$1 = ___default["default"].keys(MovablePointOptions);
14873
-
14874
15009
  // Default "props" and "state". Both are added to this.state and
14875
15010
  // receive magic getter methods (this.coord() etc).
14876
15011
  // However, properties in DEFAULT_PROPS are updated on `modify()`,
@@ -14923,7 +15058,7 @@ ___default["default"].extend(MovablePoint$5.prototype, {
14923
15058
  _createDefaultState: function () {
14924
15059
  return ___default["default"].extend({
14925
15060
  id: this.state.id
14926
- }, normalizeOptions$1(FUNCTION_ARRAY_OPTIONS$1,
15061
+ }, normalizeOptions$1(
14927
15062
  // Defaults are copied from MovablePointOptions.*.standard
14928
15063
  // These defaults are set here instead of DEFAULT_PROPS/STATE
14929
15064
  // because they:
@@ -14996,7 +15131,7 @@ ___default["default"].extend(MovablePoint$5.prototype, {
14996
15131
  update: function (options) {
14997
15132
  const self = this;
14998
15133
  const graphie = self.graphie;
14999
- const state = ___default["default"].extend(self.state, normalizeOptions$1(FUNCTION_ARRAY_OPTIONS$1, options));
15134
+ const state = ___default["default"].extend(self.state, normalizeOptions$1(options));
15000
15135
  assert$6(kmath.point.is(state.coord));
15001
15136
 
15002
15137
  // Default things inside the state.normalStyle object, because
@@ -15603,10 +15738,6 @@ var MovablePolygonOptions = {
15603
15738
  const assert$5 = InteractiveUtil.assert;
15604
15739
  const normalizeOptions = InteractiveUtil.normalizeOptions;
15605
15740
 
15606
- // State parameters that should be converted into an array of
15607
- // functions
15608
- const FUNCTION_ARRAY_OPTIONS = ___default["default"].keys(MovablePolygonOptions);
15609
-
15610
15741
  // Default "props" and "state". Both are added to this.state and
15611
15742
  // receive magic getter methods (this.points() etc).
15612
15743
  // However, properties in DEFAULT_PROPS are updated on `modify()`,
@@ -15666,7 +15797,7 @@ ___default["default"].extend(MovablePolygon.prototype, {
15666
15797
  _createDefaultState: function () {
15667
15798
  return ___default["default"].extend({
15668
15799
  id: this.state.id
15669
- }, normalizeOptions(FUNCTION_ARRAY_OPTIONS,
15800
+ }, normalizeOptions(
15670
15801
  // Defaults are copied from MovablePolygonOptions.*.standard
15671
15802
  // These defaults are set here instead of DEFAULT_PROPS/STATE
15672
15803
  // because they:
@@ -15697,7 +15828,7 @@ ___default["default"].extend(MovablePolygon.prototype, {
15697
15828
  update: function (options) {
15698
15829
  const self = this;
15699
15830
  const graphie = self.graphie;
15700
- const state = ___default["default"].extend(self.state, normalizeOptions(FUNCTION_ARRAY_OPTIONS, options));
15831
+ const state = ___default["default"].extend(self.state, normalizeOptions(options));
15701
15832
 
15702
15833
  // Default things inside the state.normalStyle object, because
15703
15834
  // _.extend is not deep.
@@ -41615,7 +41746,7 @@ const init = function (options) {
41615
41746
 
41616
41747
  // This file is processed by a Rollup plugin (replace) to inject the production
41617
41748
  const libName = "@khanacademy/perseus";
41618
- const libVersion = "19.1.3";
41749
+ const libVersion = "19.1.5";
41619
41750
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
41620
41751
 
41621
41752
  const apiVersion = {