@khanacademy/math-input 14.2.2 → 15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @khanacademy/math-input
2
2
 
3
+ ## 15.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#786](https://github.com/Khan/perseus/pull/786) [`af4ebf37`](https://github.com/Khan/perseus/commit/af4ebf37dfed15ffd93a8cf2a20d0be464120dd7) Thanks [@handeyeco](https://github.com/handeyeco)! - Added a new required dep in Perseus and MathInput (required by WB)
8
+
9
+ ### Patch Changes
10
+
11
+ - [#791](https://github.com/Khan/perseus/pull/791) [`3eb0e158`](https://github.com/Khan/perseus/commit/3eb0e15860224cc595d5b7e78d2a5d60e808561c) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Minor fix to ensure that the keypadElement is always provided to mobile keypad consumers
12
+
3
13
  ## 14.2.2
4
14
 
5
15
  ### Patch Changes
package/dist/es/index.js CHANGED
@@ -20,7 +20,7 @@ import * as Redux from 'redux';
20
20
 
21
21
  // This file is processed by a Rollup plugin (replace) to inject the production
22
22
  const libName = "@khanacademy/math-input";
23
- const libVersion = "14.2.2";
23
+ const libVersion = "15.0.0";
24
24
  addLibraryVersionToPerseusDebug(libName, libVersion);
25
25
 
26
26
  function _extends() {
@@ -1279,10 +1279,9 @@ const mobileKeyTranslator = _extends({}, keyToMathquillMap, {
1279
1279
  * from MathQuill changes.
1280
1280
  */
1281
1281
  class MathWrapper {
1282
- // MathQuill MathField input
1283
-
1284
1282
  constructor(element, callbacks = {}) {
1285
1283
  this.mathField = void 0;
1284
+ // MathQuill MathField input
1286
1285
  this.callbacks = void 0;
1287
1286
  this.mathField = createMathField(element, () => {
1288
1287
  return {
@@ -1471,14 +1470,18 @@ class MathInput extends React.Component {
1471
1470
  this.didTouchOutside = void 0;
1472
1471
  this.didScroll = void 0;
1473
1472
  this.mathField = void 0;
1473
+ // @ts-expect-error - TS2564 - Property 'recordTouchStartOutside' has no initializer and is not definitely assigned in the constructor.
1474
1474
  this.recordTouchStartOutside = void 0;
1475
+ // @ts-expect-error - TS2564 - Property 'blurOnTouchEndOutside' has no initializer and is not definitely assigned in the constructor.
1475
1476
  this.blurOnTouchEndOutside = void 0;
1476
1477
  this.dragListener = void 0;
1477
1478
  this.inputRef = void 0;
1478
1479
  this._isMounted = void 0;
1479
1480
  this._mathContainer = void 0;
1481
+ // @ts-expect-error - TS2564 - Property '_container' has no initializer and is not definitely assigned in the constructor.
1480
1482
  this._container = void 0;
1481
1483
  this._root = void 0;
1484
+ // @ts-expect-error - TS2564 - Property '_containerBounds' has no initializer and is not definitely assigned in the constructor.
1482
1485
  this._containerBounds = void 0;
1483
1486
  this._keypadBounds = void 0;
1484
1487
  this.state = {
@@ -1504,6 +1507,7 @@ class MathInput extends React.Component {
1504
1507
  this._root.style.padding = `${padding.paddingTop}px ${padding.paddingRight}px` + ` ${padding.paddingBottom}px ${padding.paddingLeft}px`;
1505
1508
  this._root.style.fontSize = `${fontSizePt}pt`;
1506
1509
  };
1510
+ /** Gets and cache they bounds of the keypadElement */
1507
1511
  this._getKeypadBounds = () => {
1508
1512
  if (!this._keypadBounds) {
1509
1513
  var _this$props$keypadEle;
@@ -1574,7 +1578,7 @@ class MathInput extends React.Component {
1574
1578
  var _this$props$keypadEle2, _this$props;
1575
1579
  // Pass this component's handleKey method to the keypad so it can call
1576
1580
  // it whenever it needs to trigger a keypress action.
1577
- (_this$props$keypadEle2 = this.props.keypadElement) == null ? void 0 : _this$props$keypadEle2.setKeyHandler(key => {
1581
+ (_this$props$keypadEle2 = this.props.keypadElement) == null || _this$props$keypadEle2.setKeyHandler(key => {
1578
1582
  const cursor = this.mathField.pressKey(key);
1579
1583
 
1580
1584
  // Trigger an `onChange` if the value in the input changed, and hide
@@ -1597,7 +1601,7 @@ class MathInput extends React.Component {
1597
1601
  return cursor;
1598
1602
  });
1599
1603
  this.mathField.focus();
1600
- (_this$props = this.props) == null ? void 0 : _this$props.onFocus();
1604
+ (_this$props = this.props) == null || _this$props.onFocus();
1601
1605
  this.setState({
1602
1606
  focused: true
1603
1607
  }, () => {
@@ -1620,6 +1624,30 @@ class MathInput extends React.Component {
1620
1624
  });
1621
1625
  });
1622
1626
  };
1627
+ /**
1628
+ * Tries to determine which DOM node to place the cursor next to based on
1629
+ * where the user drags the cursor handle. If it finds a node it will
1630
+ * place the cursor next to it, update the handle to be under the cursor,
1631
+ * and return true. If it doesn't find a node, it returns false.
1632
+ *
1633
+ * It searches for nodes by doing it tests at the following points:
1634
+ *
1635
+ * (x - dx, y), (x, y), (x + dx, y)
1636
+ *
1637
+ * If it doesn't find any nodes from the rendered math it will update y
1638
+ * by adding dy.
1639
+ *
1640
+ * The algorithm ends its search when y goes outside the bounds of
1641
+ * containerBounds.
1642
+ *
1643
+ * @param {DOMRect} containerBounds - bounds of the container node
1644
+ * @param {number} x - the initial x coordinate in the viewport
1645
+ * @param {number} y - the initial y coordinate in the viewport
1646
+ * @param {number} dx - horizontal spacing between elementFromPoint calls
1647
+ * @param {number} dy - vertical spacing between elementFromPoint calls,
1648
+ * sign determines direction.
1649
+ * @returns {boolean} - true if a node was hit, false otherwise.
1650
+ */
1623
1651
  this._findHitNode = (containerBounds, x, y, dx, dy) => {
1624
1652
  while (y >= containerBounds.top && y <= containerBounds.bottom) {
1625
1653
  y += dy;
@@ -1691,6 +1719,13 @@ class MathInput extends React.Component {
1691
1719
  }
1692
1720
  return false;
1693
1721
  };
1722
+ /**
1723
+ * Inserts the cursor at the DOM node closest to the given coordinates,
1724
+ * based on hit-tests conducted using #_findHitNode.
1725
+ *
1726
+ * @param {number} x - the x coordinate in the viewport
1727
+ * @param {number} y - the y coordinate in the viewport
1728
+ */
1694
1729
  this._insertCursorAtClosestNode = (x, y) => {
1695
1730
  const cursor = this.mathField.getCursor();
1696
1731
 
@@ -1804,6 +1839,12 @@ class MathInput extends React.Component {
1804
1839
  this._updateCursorHandle();
1805
1840
  }
1806
1841
  };
1842
+ /**
1843
+ * When a touch starts in the cursor handle, we track it so as to avoid
1844
+ * handling any touch events ourself.
1845
+ *
1846
+ * @param {TouchEvent} e - the raw touch event from the browser
1847
+ */
1807
1848
  this.onCursorHandleTouchStart = e => {
1808
1849
  // NOTE(charlie): The cursor handle is a child of this view, so whenever
1809
1850
  // it receives a touch event, that event would also typically be bubbled
@@ -1827,6 +1868,12 @@ class MathInput extends React.Component {
1827
1868
  return value;
1828
1869
  }
1829
1870
  };
1871
+ /**
1872
+ * When the user moves the cursor handle update the position of the cursor
1873
+ * and the handle.
1874
+ *
1875
+ * @param {TouchEvent} e - the raw touch event from the browser
1876
+ */
1830
1877
  this.onCursorHandleTouchMove = e => {
1831
1878
  e.stopPropagation();
1832
1879
  const x = e.changedTouches[0].clientX;
@@ -1859,10 +1906,20 @@ class MathInput extends React.Component {
1859
1906
  const adjustedY = y - distanceAboveFingerToTrySelecting;
1860
1907
  this._insertCursorAtClosestNode(x, adjustedY);
1861
1908
  };
1909
+ /**
1910
+ * When the user releases the cursor handle, animate it back into place.
1911
+ *
1912
+ * @param {TouchEvent} e - the raw touch event from the browser
1913
+ */
1862
1914
  this.onCursorHandleTouchEnd = e => {
1863
1915
  e.stopPropagation();
1864
1916
  this._updateCursorHandle(true);
1865
1917
  };
1918
+ /**
1919
+ * If the gesture is cancelled mid-drag, simply hide it.
1920
+ *
1921
+ * @param {TouchEvent} e - the raw touch event from the browser
1922
+ */
1866
1923
  this.onCursorHandleTouchCancel = e => {
1867
1924
  e.stopPropagation();
1868
1925
  this._updateCursorHandle(true);
@@ -1921,6 +1978,10 @@ class MathInput extends React.Component {
1921
1978
  const focusedBorderWidthPx = 2;
1922
1979
  return this.state.focused ? focusedBorderWidthPx : normalBorderWidthPx;
1923
1980
  };
1981
+ // Calculate the appropriate padding based on the border width (which is
1982
+ // considered 'padding', since we're using 'border-box') and the fact
1983
+ // that MathQuill automatically applies 2px of padding to the inner
1984
+ // input.
1924
1985
  this.getInputInnerPadding = () => {
1925
1986
  const paddingInset = totalDesiredPadding - this.getBorderWidthPx();
1926
1987
 
@@ -5160,13 +5221,6 @@ function processStyleType(style) {
5160
5221
  }
5161
5222
 
5162
5223
  class TransitionChild extends React.Component {
5163
- // Each 2-tuple in the queue represents two classnames: one to remove and
5164
- // one to add (in that order).
5165
-
5166
- // We keep track of all of the current applied classes so that we can remove
5167
- // them before a new transition starts in the case of the current transition
5168
- // being interrupted.
5169
-
5170
5224
  // The use of getDerivedStateFromProps here is to avoid an extra call to
5171
5225
  // setState if the component re-enters. This can happen if TransitionGroup
5172
5226
  // sets `in` from `false` to `true`.
@@ -5183,7 +5237,12 @@ class TransitionChild extends React.Component {
5183
5237
  }
5184
5238
  constructor(props) {
5185
5239
  super(props);
5240
+ // Each 2-tuple in the queue represents two classnames: one to remove and
5241
+ // one to add (in that order).
5186
5242
  this.classNameQueue = void 0;
5243
+ // We keep track of all of the current applied classes so that we can remove
5244
+ // them before a new transition starts in the case of the current transition
5245
+ // being interrupted.
5187
5246
  this.appliedClassNames = void 0;
5188
5247
  this._isMounted = false;
5189
5248
  this.addClass = (elem, className) => {
@@ -5412,7 +5471,7 @@ class MobileKeypad extends React.Component {
5412
5471
  this.dismiss = () => {
5413
5472
  var _this$props$onDismiss, _this$props;
5414
5473
  this.props.setKeypadActive(false);
5415
- (_this$props$onDismiss = (_this$props = this.props).onDismiss) == null ? void 0 : _this$props$onDismiss.call(_this$props);
5474
+ (_this$props$onDismiss = (_this$props = this.props).onDismiss) == null || _this$props$onDismiss.call(_this$props);
5416
5475
  };
5417
5476
  this.configure = (configuration, cb) => {
5418
5477
  this.setState({
@@ -5458,7 +5517,7 @@ class MobileKeypad extends React.Component {
5458
5517
  this._containerResizeObserver.observe(this._containerRef.current);
5459
5518
  }
5460
5519
  }
5461
- (_this$props$onElement = (_this$props2 = this.props).onElementMounted) == null ? void 0 : _this$props$onElement.call(_this$props2, {
5520
+ (_this$props$onElement = (_this$props2 = this.props).onElementMounted) == null || _this$props$onElement.call(_this$props2, {
5462
5521
  activate: this.activate,
5463
5522
  dismiss: this.dismiss,
5464
5523
  configure: this.configure,
@@ -5471,7 +5530,7 @@ class MobileKeypad extends React.Component {
5471
5530
  var _this$_containerResiz;
5472
5531
  window.removeEventListener("resize", this._throttleResizeHandler);
5473
5532
  window.removeEventListener("orientationchange", this._throttleResizeHandler);
5474
- (_this$_containerResiz = this._containerResizeObserver) == null ? void 0 : _this$_containerResiz.disconnect();
5533
+ (_this$_containerResiz = this._containerResizeObserver) == null || _this$_containerResiz.disconnect();
5475
5534
  }
5476
5535
  _handleClickKey(key) {
5477
5536
  var _this$state$keyHandle, _this$state;
@@ -5499,7 +5558,10 @@ class MobileKeypad extends React.Component {
5499
5558
  ...(Array.isArray(style) ? style : [style])];
5500
5559
  const isExpression = (keypadConfig == null ? void 0 : keypadConfig.keypadType) === "EXPRESSION";
5501
5560
  const convertDotToTimes = keypadConfig == null ? void 0 : keypadConfig.times;
5502
- return /*#__PURE__*/React.createElement(AphroditeCSSTransitionGroup, {
5561
+ return /*#__PURE__*/React.createElement(View, {
5562
+ style: containerStyle,
5563
+ forwardRef: this._containerRef
5564
+ }, /*#__PURE__*/React.createElement(AphroditeCSSTransitionGroup, {
5503
5565
  transitionEnterTimeout: AnimationDurationInMS,
5504
5566
  transitionLeaveTimeout: AnimationDurationInMS,
5505
5567
  transitionStyle: {
@@ -5518,10 +5580,7 @@ class MobileKeypad extends React.Component {
5518
5580
  transform: "translate3d(0, 100%, 0)"
5519
5581
  }
5520
5582
  }
5521
- }, keypadActive ? /*#__PURE__*/React.createElement(View, {
5522
- style: containerStyle,
5523
- forwardRef: this._containerRef
5524
- }, /*#__PURE__*/React.createElement(Keypad$2, {
5583
+ }, keypadActive ? /*#__PURE__*/React.createElement(Keypad$2, {
5525
5584
  onAnalyticsEvent: this.props.onAnalyticsEvent,
5526
5585
  extraKeys: keypadConfig == null ? void 0 : keypadConfig.extraKeys,
5527
5586
  onClickKey: key => this._handleClickKey(key),
@@ -5536,7 +5595,7 @@ class MobileKeypad extends React.Component {
5536
5595
  advancedRelations: isExpression,
5537
5596
  expandedView: containerWidth > expandedViewThreshold$1,
5538
5597
  showDismiss: true
5539
- })) : null);
5598
+ }) : null));
5540
5599
  }
5541
5600
  }
5542
5601
  const styles$c = StyleSheet.create({
@@ -7840,7 +7899,6 @@ class PopoverManager extends React.Component {
7840
7899
  // naming convention: verb + noun
7841
7900
  // the noun should be one of the other properties in the object that's
7842
7901
  // being dispatched
7843
-
7844
7902
  const dismissKeypad = () => {
7845
7903
  return {
7846
7904
  type: "DismissKeypad"
@@ -8622,7 +8680,7 @@ class KeypadContainer extends React.Component {
8622
8680
  });
8623
8681
  const containerWidth = ((_this$_containerRef$c = this._containerRef.current) == null ? void 0 : _this$_containerRef$c.clientWidth) || 0;
8624
8682
  const containerHeight = ((_this$_containerRef$c2 = this._containerRef.current) == null ? void 0 : _this$_containerRef$c2.clientHeight) || 0;
8625
- (_this$props$onPageSiz = (_this$props = this.props).onPageSizeChange) == null ? void 0 : _this$props$onPageSiz.call(_this$props, window.innerWidth, window.innerHeight, containerWidth, containerHeight);
8683
+ (_this$props$onPageSiz = (_this$props = this.props).onPageSizeChange) == null || _this$props$onPageSiz.call(_this$props, window.innerWidth, window.innerHeight, containerWidth, containerHeight);
8626
8684
  };
8627
8685
  this.renderKeypad = () => {
8628
8686
  const {
@@ -8698,7 +8756,7 @@ class KeypadContainer extends React.Component {
8698
8756
  var _this$_containerResiz;
8699
8757
  window.removeEventListener("resize", this._throttleResizeHandler);
8700
8758
  window.removeEventListener("orientationchange", this._throttleResizeHandler);
8701
- (_this$_containerResiz = this._containerResizeObserver) == null ? void 0 : _this$_containerResiz.disconnect();
8759
+ (_this$_containerResiz = this._containerResizeObserver) == null || _this$_containerResiz.disconnect();
8702
8760
  }
8703
8761
  render() {
8704
8762
  const {
@@ -8830,10 +8888,7 @@ var KeypadContainer$1 = connect(mapStateToProps, mapDispatchToProps, null, {
8830
8888
  * It is entirely ignorant of the existence of popovers and the positions of
8831
8889
  * DOM nodes, operating solely on IDs. The state machine does accommodate for
8832
8890
  * multi-touch interactions, tracking gesture state on a per-touch basis.
8833
- */
8834
-
8835
- // exported for tests
8836
-
8891
+ */ // exported for tests
8837
8892
  const defaultOptions = {
8838
8893
  longPressWaitTimeMs: 50,
8839
8894
  swipeThresholdPx: 20,
@@ -9010,7 +9065,7 @@ class GestureStateMachine {
9010
9065
  // gestures are ignored.
9011
9066
  if (this.swipeState.touchId === touchId) {
9012
9067
  var _this$handlers$onSwip, _this$handlers;
9013
- (_this$handlers$onSwip = (_this$handlers = this.handlers).onSwipeChange) == null ? void 0 : _this$handlers$onSwip.call(_this$handlers, pageX - this.swipeState.startX);
9068
+ (_this$handlers$onSwip = (_this$handlers = this.handlers).onSwipeChange) == null || _this$handlers$onSwip.call(_this$handlers, pageX - this.swipeState.startX);
9014
9069
  }
9015
9070
  } else if (this.touchState[touchId]) {
9016
9071
  // It could be touch events started outside the keypad and
@@ -9031,7 +9086,7 @@ class GestureStateMachine {
9031
9086
  touchId,
9032
9087
  startX
9033
9088
  };
9034
- (_this$handlers$onSwip2 = (_this$handlers2 = this.handlers).onSwipeChange) == null ? void 0 : _this$handlers$onSwip2.call(_this$handlers2, pageX - this.swipeState.startX);
9089
+ (_this$handlers$onSwip2 = (_this$handlers2 = this.handlers).onSwipeChange) == null || _this$handlers$onSwip2.call(_this$handlers2, pageX - this.swipeState.startX);
9035
9090
  } else {
9036
9091
  const id = getId();
9037
9092
  if (id !== activeNodeId) {
@@ -9055,7 +9110,7 @@ class GestureStateMachine {
9055
9110
  // gestures are ignored.
9056
9111
  if (this.swipeState.touchId === touchId) {
9057
9112
  var _this$handlers$onSwip3, _this$handlers3;
9058
- (_this$handlers$onSwip3 = (_this$handlers3 = this.handlers).onSwipeEnd) == null ? void 0 : _this$handlers$onSwip3.call(_this$handlers3, pageX - this.swipeState.startX);
9113
+ (_this$handlers$onSwip3 = (_this$handlers3 = this.handlers).onSwipeEnd) == null || _this$handlers$onSwip3.call(_this$handlers3, pageX - this.swipeState.startX);
9059
9114
  this.swipeState = null;
9060
9115
  }
9061
9116
  } else if (this.touchState[touchId]) {
@@ -9090,7 +9145,7 @@ class GestureStateMachine {
9090
9145
  if (this.swipeState) {
9091
9146
  if (this.swipeState.touchId === touchId) {
9092
9147
  var _this$handlers$onSwip4, _this$handlers4;
9093
- (_this$handlers$onSwip4 = (_this$handlers4 = this.handlers).onSwipeEnd) == null ? void 0 : _this$handlers$onSwip4.call(_this$handlers4, 0);
9148
+ (_this$handlers$onSwip4 = (_this$handlers4 = this.handlers).onSwipeEnd) == null || _this$handlers$onSwip4.call(_this$handlers4, 0);
9094
9149
  this.swipeState = null;
9095
9150
  }
9096
9151
  } else if (this.touchState[touchId]) {
@@ -10034,7 +10089,7 @@ class ProvidedKeypad extends React.Component {
10034
10089
  setKeyHandler: this.setKeyHandler,
10035
10090
  getDOMNode: this.getDOMNode
10036
10091
  });
10037
- (_this$props$onElement = (_this$props = this.props).onElementMounted) == null ? void 0 : _this$props$onElement.call(_this$props, elementWithDispatchMethods);
10092
+ (_this$props$onElement = (_this$props = this.props).onElementMounted) == null || _this$props$onElement.call(_this$props, elementWithDispatchMethods);
10038
10093
  };
10039
10094
  this.onDismiss = () => {
10040
10095
  var _this$props$onDismiss, _this$props2;
@@ -10044,7 +10099,7 @@ class ProvidedKeypad extends React.Component {
10044
10099
  virtualKeypadVersion: "MATH_INPUT_KEYPAD_V1"
10045
10100
  }
10046
10101
  });
10047
- (_this$props$onDismiss = (_this$props2 = this.props).onDismiss) == null ? void 0 : _this$props$onDismiss.call(_this$props2);
10102
+ (_this$props$onDismiss = (_this$props2 = this.props).onDismiss) == null || _this$props$onDismiss.call(_this$props2);
10048
10103
  };
10049
10104
  this.store = createStore();
10050
10105
  }