@khanacademy/math-input 0.4.1 → 0.5.2

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.
Files changed (176) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/{build/math-input.css → dist/es/index.css} +0 -150
  4. package/dist/es/index.js +7798 -0
  5. package/dist/es/index.js.map +1 -0
  6. package/dist/index.css +586 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +7768 -0
  9. package/dist/index.js.flow +2 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/strings.js +71 -0
  12. package/index.html +20 -0
  13. package/less/echo.less +56 -0
  14. package/less/main.less +5 -0
  15. package/less/overrides.less +129 -0
  16. package/less/popover.less +22 -0
  17. package/less/tabbar.less +6 -0
  18. package/package.json +60 -89
  19. package/src/actions/index.js +57 -0
  20. package/src/components/__tests__/gesture-state-machine_test.js +437 -0
  21. package/src/components/__tests__/node-manager_test.js +89 -0
  22. package/src/components/__tests__/two-page-keypad_test.js +42 -0
  23. package/src/components/app.js +73 -0
  24. package/src/components/common-style.js +47 -0
  25. package/src/components/compute-layout-parameters.js +157 -0
  26. package/src/components/corner-decal.js +56 -0
  27. package/src/components/echo-manager.js +160 -0
  28. package/src/components/empty-keypad-button.js +49 -0
  29. package/src/components/expression-keypad.js +323 -0
  30. package/src/components/fraction-keypad.js +176 -0
  31. package/src/components/gesture-manager.js +226 -0
  32. package/src/components/gesture-state-machine.js +283 -0
  33. package/src/components/icon.js +74 -0
  34. package/src/components/iconography/arrow.js +22 -0
  35. package/src/components/iconography/backspace.js +29 -0
  36. package/src/components/iconography/cdot.js +29 -0
  37. package/src/components/iconography/cos.js +30 -0
  38. package/src/components/iconography/cube-root.js +36 -0
  39. package/src/components/iconography/dismiss.js +25 -0
  40. package/src/components/iconography/divide.js +34 -0
  41. package/src/components/iconography/down.js +16 -0
  42. package/src/components/iconography/equal.js +33 -0
  43. package/src/components/iconography/exp-2.js +29 -0
  44. package/src/components/iconography/exp-3.js +29 -0
  45. package/src/components/iconography/exp.js +29 -0
  46. package/src/components/iconography/frac.js +44 -0
  47. package/src/components/iconography/geq.js +33 -0
  48. package/src/components/iconography/gt.js +33 -0
  49. package/src/components/iconography/index.js +45 -0
  50. package/src/components/iconography/jump-into-numerator.js +41 -0
  51. package/src/components/iconography/jump-out-base.js +30 -0
  52. package/src/components/iconography/jump-out-denominator.js +41 -0
  53. package/src/components/iconography/jump-out-exponent.js +30 -0
  54. package/src/components/iconography/jump-out-numerator.js +41 -0
  55. package/src/components/iconography/jump-out-parentheses.js +33 -0
  56. package/src/components/iconography/left-paren.js +33 -0
  57. package/src/components/iconography/left.js +16 -0
  58. package/src/components/iconography/leq.js +33 -0
  59. package/src/components/iconography/ln.js +29 -0
  60. package/src/components/iconography/log-n.js +29 -0
  61. package/src/components/iconography/log.js +29 -0
  62. package/src/components/iconography/lt.js +33 -0
  63. package/src/components/iconography/minus.js +32 -0
  64. package/src/components/iconography/neq.js +33 -0
  65. package/src/components/iconography/parens.js +33 -0
  66. package/src/components/iconography/percent.js +49 -0
  67. package/src/components/iconography/period.js +26 -0
  68. package/src/components/iconography/plus.js +32 -0
  69. package/src/components/iconography/radical.js +36 -0
  70. package/src/components/iconography/right-paren.js +33 -0
  71. package/src/components/iconography/right.js +16 -0
  72. package/src/components/iconography/sin.js +30 -0
  73. package/src/components/iconography/sqrt.js +32 -0
  74. package/src/components/iconography/tan.js +30 -0
  75. package/src/components/iconography/times.js +33 -0
  76. package/src/components/iconography/up.js +16 -0
  77. package/src/components/input/__tests__/context-tracking_test.js +177 -0
  78. package/src/components/input/__tests__/math-wrapper.jsx +33 -0
  79. package/src/components/input/__tests__/mathquill_test.js +747 -0
  80. package/src/components/input/cursor-contexts.js +29 -0
  81. package/src/components/input/cursor-handle.js +137 -0
  82. package/src/components/input/drag-listener.js +75 -0
  83. package/src/components/input/math-input.js +924 -0
  84. package/src/components/input/math-wrapper.js +959 -0
  85. package/src/components/input/scroll-into-view.js +72 -0
  86. package/src/components/keypad/button-assets.js +492 -0
  87. package/src/components/keypad/button.js +106 -0
  88. package/src/components/keypad/button.stories.js +29 -0
  89. package/src/components/keypad/index.js +64 -0
  90. package/src/components/keypad/keypad-page-items.js +106 -0
  91. package/src/components/keypad/keypad-pages.stories.js +32 -0
  92. package/src/components/keypad/keypad.stories.js +35 -0
  93. package/src/components/keypad/numeric-input-page.js +100 -0
  94. package/src/components/keypad/pre-algebra-page.js +98 -0
  95. package/src/components/keypad/trigonometry-page.js +90 -0
  96. package/src/components/keypad-button.js +366 -0
  97. package/src/components/keypad-container.js +303 -0
  98. package/src/components/keypad.js +154 -0
  99. package/src/components/many-keypad-button.js +44 -0
  100. package/src/components/math-icon.js +65 -0
  101. package/src/components/multi-symbol-grid.js +182 -0
  102. package/src/components/multi-symbol-popover.js +59 -0
  103. package/src/components/navigation-pad.js +139 -0
  104. package/src/components/node-manager.js +129 -0
  105. package/src/components/popover-manager.js +76 -0
  106. package/src/components/popover-state-machine.js +173 -0
  107. package/src/components/prop-types.js +82 -0
  108. package/src/components/provided-keypad.js +103 -0
  109. package/src/components/styles.js +38 -0
  110. package/src/components/svg-icon.js +25 -0
  111. package/src/components/tabbar/__tests__/tabbar_test.js +65 -0
  112. package/src/components/tabbar/icons.js +69 -0
  113. package/src/components/tabbar/item.js +138 -0
  114. package/src/components/tabbar/tabbar.js +61 -0
  115. package/src/components/tabbar/tabbar.stories.js +60 -0
  116. package/src/components/tabbar/types.js +3 -0
  117. package/src/components/text-icon.js +52 -0
  118. package/src/components/touchable-keypad-button.js +146 -0
  119. package/src/components/two-page-keypad.js +99 -0
  120. package/src/components/velocity-tracker.js +76 -0
  121. package/src/components/z-indexes.js +9 -0
  122. package/src/consts.js +74 -0
  123. package/src/data/key-configs.js +349 -0
  124. package/src/data/keys.js +72 -0
  125. package/src/demo.js +8 -0
  126. package/src/fake-react-native-web/index.js +12 -0
  127. package/src/fake-react-native-web/text.js +56 -0
  128. package/src/fake-react-native-web/view.js +91 -0
  129. package/src/index.js +14 -0
  130. package/src/native-app.js +84 -0
  131. package/src/store/index.js +505 -0
  132. package/src/utils.js +18 -0
  133. package/tools/svg-to-react/convert.py +111 -0
  134. package/tools/svg-to-react/icons/math-keypad-icon-0.svg +32 -0
  135. package/tools/svg-to-react/icons/math-keypad-icon-1.svg +32 -0
  136. package/tools/svg-to-react/icons/math-keypad-icon-2.svg +32 -0
  137. package/tools/svg-to-react/icons/math-keypad-icon-3.svg +32 -0
  138. package/tools/svg-to-react/icons/math-keypad-icon-4.svg +32 -0
  139. package/tools/svg-to-react/icons/math-keypad-icon-5.svg +32 -0
  140. package/tools/svg-to-react/icons/math-keypad-icon-6.svg +32 -0
  141. package/tools/svg-to-react/icons/math-keypad-icon-7.svg +32 -0
  142. package/tools/svg-to-react/icons/math-keypad-icon-8.svg +32 -0
  143. package/tools/svg-to-react/icons/math-keypad-icon-9.svg +32 -0
  144. package/tools/svg-to-react/icons/math-keypad-icon-addition.svg +34 -0
  145. package/tools/svg-to-react/icons/math-keypad-icon-cos.svg +38 -0
  146. package/tools/svg-to-react/icons/math-keypad-icon-delete.svg +36 -0
  147. package/tools/svg-to-react/icons/math-keypad-icon-dismiss.svg +36 -0
  148. package/tools/svg-to-react/icons/math-keypad-icon-division.svg +36 -0
  149. package/tools/svg-to-react/icons/math-keypad-icon-equals-not.svg +50 -0
  150. package/tools/svg-to-react/icons/math-keypad-icon-equals.svg +48 -0
  151. package/tools/svg-to-react/icons/math-keypad-icon-exponent-2.svg +38 -0
  152. package/tools/svg-to-react/icons/math-keypad-icon-exponent-3.svg +38 -0
  153. package/tools/svg-to-react/icons/math-keypad-icon-exponent.svg +38 -0
  154. package/tools/svg-to-react/icons/math-keypad-icon-fraction.svg +42 -0
  155. package/tools/svg-to-react/icons/math-keypad-icon-greater-than.svg +46 -0
  156. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-base.svg +44 -0
  157. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-denominator.svg +48 -0
  158. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-exponent.svg +44 -0
  159. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-parentheses.svg +44 -0
  160. package/tools/svg-to-react/icons/math-keypad-icon-less-than.svg +46 -0
  161. package/tools/svg-to-react/icons/math-keypad-icon-log-10.svg +36 -0
  162. package/tools/svg-to-react/icons/math-keypad-icon-log-e.svg +36 -0
  163. package/tools/svg-to-react/icons/math-keypad-icon-log.svg +38 -0
  164. package/tools/svg-to-react/icons/math-keypad-icon-multiplication-cross.svg +40 -0
  165. package/tools/svg-to-react/icons/math-keypad-icon-multiplication-dot.svg +38 -0
  166. package/tools/svg-to-react/icons/math-keypad-icon-percent.svg +42 -0
  167. package/tools/svg-to-react/icons/math-keypad-icon-radical-2.svg +36 -0
  168. package/tools/svg-to-react/icons/math-keypad-icon-radical-3.svg +38 -0
  169. package/tools/svg-to-react/icons/math-keypad-icon-radical.svg +38 -0
  170. package/tools/svg-to-react/icons/math-keypad-icon-radix-character.svg +32 -0
  171. package/tools/svg-to-react/icons/math-keypad-icon-sin.svg +38 -0
  172. package/tools/svg-to-react/icons/math-keypad-icon-subtraction.svg +32 -0
  173. package/tools/svg-to-react/icons/math-keypad-icon-tan.svg +38 -0
  174. package/tools/svg-to-react/symbol_map.py +41 -0
  175. package/LICENSE.txt +0 -21
  176. package/build/math-input.js +0 -1
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Constants that define the various contexts in which a cursor can exist. The
3
+ * active context is determined first by looking at the cursor's siblings (e.g.,
4
+ * for the `BEFORE_FRACTION` context), and then at its direct parent. Though a
5
+ * cursor could in theory be nested in multiple contexts, we only care about the
6
+ * immediate context.
7
+ *
8
+ * TODO(charlie): Add a context to represent being inside of a radical. Right
9
+ * now, we show the dismiss button rather than allowing the user to jump out of
10
+ * the radical.
11
+ */
12
+
13
+ // The cursor is not in any of the other viable contexts.
14
+ export const NONE = "NONE";
15
+ // The cursor is within a set of parentheses.
16
+ export const IN_PARENS = "IN_PARENS";
17
+ // The cursor is within a superscript (e.g., an exponent).
18
+ export const IN_SUPER_SCRIPT = "IN_SUPER_SCRIPT";
19
+ // The cursor is within a subscript (e.g., the base of a custom logarithm).
20
+ export const IN_SUB_SCRIPT = "IN_SUB_SCRIPT";
21
+ // The cursor is in the numerator of a fraction.
22
+ export const IN_NUMERATOR = "IN_NUMERATOR";
23
+ // The cursor is in the denominator of a fraction.
24
+ export const IN_DENOMINATOR = "IN_DENOMINATOR";
25
+ // The cursor is sitting before a fraction; that is, the cursor is within
26
+ // what looks to be a mixed number preceding a fraction. This will only be
27
+ // the case when the only math between the cursor and the fraction to its
28
+ // write is non-leaf math (numbers and variables).
29
+ export const BEFORE_FRACTION = "BEFORE_FRACTION";
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Renders the green tear-shaped handle under the cursor.
3
+ */
4
+
5
+ import PropTypes from "prop-types";
6
+ import * as React from "react";
7
+
8
+ import {
9
+ cursorHandleRadiusPx,
10
+ cursorHandleDistanceMultiplier,
11
+ } from "../common-style.js";
12
+
13
+ const touchTargetRadiusPx = 2 * cursorHandleRadiusPx;
14
+ const touchTargetHeightPx = 2 * touchTargetRadiusPx;
15
+ const touchTargetWidthPx = 2 * touchTargetRadiusPx;
16
+
17
+ const cursorRadiusPx = cursorHandleRadiusPx;
18
+ const cursorHeightPx = cursorHandleDistanceMultiplier * (cursorRadiusPx * 4);
19
+ const cursorWidthPx = 4 * cursorRadiusPx;
20
+
21
+ class CursorHandle extends React.Component {
22
+ static propTypes = {
23
+ animateIntoPosition: PropTypes.bool,
24
+ onTouchCancel: PropTypes.func.isRequired,
25
+ onTouchEnd: PropTypes.func.isRequired,
26
+ onTouchMove: PropTypes.func.isRequired,
27
+ onTouchStart: PropTypes.func.isRequired,
28
+ visible: PropTypes.bool.isRequired,
29
+ x: PropTypes.number.isRequired,
30
+ y: PropTypes.number.isRequired,
31
+ };
32
+
33
+ static defaultProps = {
34
+ animateIntoPosition: false,
35
+ visible: false,
36
+ x: 0,
37
+ y: 0,
38
+ };
39
+
40
+ render() {
41
+ const {x, y, animateIntoPosition} = this.props;
42
+
43
+ const animationStyle = animateIntoPosition
44
+ ? {
45
+ msTransitionDuration: "100ms",
46
+ WebkitTransitionDuration: "100ms",
47
+ transitionDuration: "100ms",
48
+ msTransitionProperty: "transform",
49
+ WebkitTransitionProperty: "transform",
50
+ transitionProperty: "transform",
51
+ }
52
+ : {};
53
+ const transformString = `translate(${x}px, ${y}px)`;
54
+
55
+ const outerStyle = {
56
+ position: "absolute",
57
+ // This is essentially webapp's interactiveComponent + 1.
58
+ // TODO(charlie): Pull in those styles somehow to avoid breakages.
59
+ zIndex: 4,
60
+ left: -touchTargetWidthPx / 2,
61
+ top: 0,
62
+ msTransform: transformString,
63
+ WebkitTransform: transformString,
64
+ transform: transformString,
65
+ width: touchTargetWidthPx,
66
+ height: touchTargetHeightPx,
67
+ // Touch events that start on the cursor shouldn't be allowed to
68
+ // produce page scrolls.
69
+ touchAction: "none",
70
+ ...animationStyle,
71
+ };
72
+
73
+ return (
74
+ <span
75
+ style={outerStyle}
76
+ onTouchStart={this.props.onTouchStart}
77
+ onTouchMove={this.props.onTouchMove}
78
+ onTouchEnd={this.props.onTouchEnd}
79
+ onTouchCancel={this.props.onTouchCancel}
80
+ >
81
+ <svg
82
+ fill="none"
83
+ width={cursorWidthPx}
84
+ height={cursorHeightPx}
85
+ viewBox={`0 0 ${cursorWidthPx} ${cursorHeightPx}`}
86
+ >
87
+ <filter
88
+ id="math-input_cursor"
89
+ colorInterpolationFilters="sRGB"
90
+ filterUnits="userSpaceOnUse"
91
+ height={cursorHeightPx * 0.87} // ~40
92
+ width={cursorWidthPx * 0.82} // ~36
93
+ x="4"
94
+ y="0"
95
+ >
96
+ <feFlood floodOpacity="0" result="BackgroundImageFix" />
97
+ <feColorMatrix
98
+ in="SourceAlpha"
99
+ type="matrix"
100
+ values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
101
+ />
102
+ <feOffset dy="4" />
103
+ <feGaussianBlur stdDeviation="4" />
104
+ <feColorMatrix
105
+ type="matrix"
106
+ values="0 0 0 0 0.129412 0 0 0 0 0.141176 0 0 0 0 0.172549 0 0 0 0.08 0"
107
+ />
108
+ <feBlend
109
+ in2="BackgroundImageFix"
110
+ mode="normal"
111
+ result="effect1_dropShadow"
112
+ />
113
+ <feBlend
114
+ in="SourceGraphic"
115
+ in2="effect1_dropShadow"
116
+ mode="normal"
117
+ result="shape"
118
+ />
119
+ </filter>
120
+ <g filter="url(#math-input_cursor)">
121
+ <path
122
+ d="m22 4-7.07 7.0284c-1.3988 1.3901-2.3515 3.1615-2.7376 5.09-.3861 1.9284-.1883 3.9274.5685 5.7441s2.0385 3.3694 3.6831 4.4619c1.6445 1.0925 3.5781 1.6756 5.556 1.6756s3.9115-.5831 5.556-1.6756c1.6446-1.0925 2.9263-2.6452 3.6831-4.4619s.9546-3.8157.5685-5.7441c-.3861-1.9285-1.3388-3.6999-2.7376-5.09z"
123
+ fill="#1865f2"
124
+ />
125
+ </g>
126
+ <path
127
+ d="m14.9301 10.4841 7.0699-7.06989 7.0699 7.06989.0001.0001c1.3988 1.3984 2.3515 3.1802 2.7376 5.1201s.1883 3.9507-.5685 5.7782c-.7568 1.8274-2.0385 3.3894-3.6831 4.4883-1.6445 1.099-3.5781 1.6855-5.556 1.6855s-3.9115-.5865-5.556-1.6855c-1.6446-1.0989-2.9263-2.6609-3.6831-4.4883-.7568-1.8275-.9546-3.8383-.5685-5.7782s1.3388-3.7217 2.7376-5.1201z"
128
+ stroke="#fff"
129
+ strokeWidth="2"
130
+ />
131
+ </svg>
132
+ </span>
133
+ );
134
+ }
135
+ }
136
+
137
+ export default CursorHandle;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * A gesture recognizer that detects 'drags', crudely defined as either scrolls
3
+ * or touches that move a sufficient distance.
4
+ */
5
+
6
+ // The 'slop' factor, after which we consider the use to be dragging. The value
7
+ // is taken from the Android SDK. It won't be robust to page zoom and the like,
8
+ // but it should be good enough for our purposes.
9
+ const touchSlopPx = 8;
10
+
11
+ class DragListener {
12
+ constructor(onDrag, initialEvent) {
13
+ // We detect drags in two ways. First, by listening for the window
14
+ // scroll event (we consider any legitimate scroll to be a drag).
15
+ this._scrollListener = () => {
16
+ onDrag();
17
+ };
18
+
19
+ // And second, by listening for touch moves and tracking the each
20
+ // finger's displacement. This allows us to track, e.g., when the user
21
+ // scrolls within an individual view.
22
+ const touchLocationsById = {};
23
+ for (let i = 0; i < initialEvent.changedTouches.length; i++) {
24
+ const touch = initialEvent.changedTouches[i];
25
+ touchLocationsById[touch.identifier] = [
26
+ touch.clientX,
27
+ touch.clientY,
28
+ ];
29
+ }
30
+
31
+ this._moveListener = (evt) => {
32
+ for (let i = 0; i < evt.changedTouches.length; i++) {
33
+ const touch = evt.changedTouches[i];
34
+ const initialTouchLocation =
35
+ touchLocationsById[touch.identifier];
36
+ if (initialTouchLocation) {
37
+ const touchLocation = [touch.clientX, touch.clientY];
38
+ const dx = touchLocation[0] - initialTouchLocation[0];
39
+ const dy = touchLocation[1] - initialTouchLocation[1];
40
+
41
+ const squaredDist = dx * dx + dy * dy;
42
+ const squaredTouchSlop = touchSlopPx * touchSlopPx;
43
+
44
+ if (squaredDist > squaredTouchSlop) {
45
+ onDrag();
46
+ }
47
+ }
48
+ }
49
+ };
50
+
51
+ // Clean-up any terminated gestures, since some browsers reuse
52
+ // identifiers.
53
+ this._endAndCancelListener = (evt) => {
54
+ for (let i = 0; i < evt.changedTouches.length; i++) {
55
+ delete touchLocationsById[evt.changedTouches[i].identifier];
56
+ }
57
+ };
58
+ }
59
+
60
+ attach() {
61
+ window.addEventListener("scroll", this._scrollListener);
62
+ window.addEventListener("touchmove", this._moveListener);
63
+ window.addEventListener("touchend", this._endAndCancelListener);
64
+ window.addEventListener("touchcancel", this._endAndCancelListener);
65
+ }
66
+
67
+ detach() {
68
+ window.removeEventListener("scroll", this._scrollListener);
69
+ window.removeEventListener("touchmove", this._moveListener);
70
+ window.removeEventListener("touchend", this._endAndCancelListener);
71
+ window.removeEventListener("touchcancel", this._endAndCancelListener);
72
+ }
73
+ }
74
+
75
+ export default DragListener;