@khanacademy/math-input 0.6.6 → 0.6.8
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 +12 -0
- package/dist/es/index.js +1601 -1609
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +1205 -1213
- package/dist/index.js.map +1 -1
- package/package.json +12 -10
- package/src/components/input/__tests__/context-tracking_test.js +2 -2
- package/src/components/input/__tests__/mathquill_test.js +2 -2
- package/src/components/input/cursor-handle.js +21 -20
- package/src/components/input/math-input.js +108 -58
- package/src/components/keypad/pre-algebra-page.js +1 -1
- package/src/components/keypad-container.js +0 -4
- package/src/fake-react-native-web/view.js +5 -5
- /package/src/components/input/__tests__/{math-wrapper.jsx → test-math-wrapper.jsx} +0 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Khan Academy's new expression editor for the mobile web.",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.6.
|
|
6
|
+
"version": "0.6.8",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -22,10 +22,11 @@
|
|
|
22
22
|
"performance-now": "^0.2.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@khanacademy/wonder-blocks-clickable": "^
|
|
26
|
-
"@khanacademy/wonder-blocks-color": "^
|
|
27
|
-
"@khanacademy/wonder-blocks-core": "^
|
|
28
|
-
"@khanacademy/wonder-blocks-i18n": "^
|
|
25
|
+
"@khanacademy/wonder-blocks-clickable": "^3.0.8",
|
|
26
|
+
"@khanacademy/wonder-blocks-color": "^2.0.1",
|
|
27
|
+
"@khanacademy/wonder-blocks-core": "^5.0.4",
|
|
28
|
+
"@khanacademy/wonder-blocks-i18n": "^2.0.2",
|
|
29
|
+
"@khanacademy/wonder-stuff-core": "^1.2.2",
|
|
29
30
|
"aphrodite": "^1.1.0",
|
|
30
31
|
"jquery": "^2.1.1",
|
|
31
32
|
"katex": "^0.11.1",
|
|
@@ -41,10 +42,11 @@
|
|
|
41
42
|
"redux": "^4.0.0"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
|
-
"@khanacademy/wonder-blocks-clickable": "^
|
|
45
|
-
"@khanacademy/wonder-blocks-color": "^
|
|
46
|
-
"@khanacademy/wonder-blocks-core": "^
|
|
47
|
-
"@khanacademy/wonder-blocks-i18n": "^
|
|
45
|
+
"@khanacademy/wonder-blocks-clickable": "^3.0.8",
|
|
46
|
+
"@khanacademy/wonder-blocks-color": "^2.0.1",
|
|
47
|
+
"@khanacademy/wonder-blocks-core": "^5.0.4",
|
|
48
|
+
"@khanacademy/wonder-blocks-i18n": "^2.0.2",
|
|
49
|
+
"@khanacademy/wonder-stuff-core": "^1.2.2",
|
|
48
50
|
"aphrodite": "^1.1.0",
|
|
49
51
|
"jquery": "^2.1.1",
|
|
50
52
|
"katex": "^0.11.1",
|
|
@@ -59,4 +61,4 @@
|
|
|
59
61
|
"redux": "^4.0.0"
|
|
60
62
|
},
|
|
61
63
|
"keywords": []
|
|
62
|
-
}
|
|
64
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Keys from "../../../data/keys.js";
|
|
2
2
|
import * as CursorContexts from "../cursor-contexts.js";
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import TestMathWrapper from "./test-math-wrapper.jsx";
|
|
5
5
|
|
|
6
6
|
describe("Cursor context", () => {
|
|
7
7
|
let mathField;
|
|
@@ -11,7 +11,7 @@ describe("Cursor context", () => {
|
|
|
11
11
|
span = document.createElement("span");
|
|
12
12
|
document.body.appendChild(span);
|
|
13
13
|
|
|
14
|
-
mathField = new
|
|
14
|
+
mathField = new TestMathWrapper(span);
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
afterEach(() => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Keys from "../../../data/keys.js";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import TestMathWrapper from "./test-math-wrapper.jsx";
|
|
4
4
|
|
|
5
5
|
const MQ = {L: "-1", R: "1"};
|
|
6
6
|
const END_OF_EXPR = 0;
|
|
@@ -21,7 +21,7 @@ describe("MathQuill", () => {
|
|
|
21
21
|
span = document.createElement("span");
|
|
22
22
|
document.body.appendChild(span);
|
|
23
23
|
|
|
24
|
-
mathField = new
|
|
24
|
+
mathField = new TestMathWrapper(span);
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
afterEach(() => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
// @flow
|
|
1
2
|
/**
|
|
2
3
|
* Renders the green tear-shaped handle under the cursor.
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
|
-
import PropTypes from "prop-types";
|
|
6
6
|
import * as React from "react";
|
|
7
7
|
|
|
8
8
|
import {
|
|
@@ -18,35 +18,38 @@ const cursorRadiusPx = cursorHandleRadiusPx;
|
|
|
18
18
|
const cursorHeightPx = cursorHandleDistanceMultiplier * (cursorRadiusPx * 4);
|
|
19
19
|
const cursorWidthPx = 4 * cursorRadiusPx;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
type Props = {|
|
|
22
|
+
animateIntoPosition: ?boolean,
|
|
23
|
+
onTouchCancel: (SyntheticTouchEvent<HTMLSpanElement>) => void,
|
|
24
|
+
onTouchEnd: (SyntheticTouchEvent<HTMLSpanElement>) => void,
|
|
25
|
+
onTouchMove: (SyntheticTouchEvent<HTMLSpanElement>) => void,
|
|
26
|
+
onTouchStart: (SyntheticTouchEvent<HTMLSpanElement>) => void,
|
|
27
|
+
visible: boolean,
|
|
28
|
+
x: number,
|
|
29
|
+
y: number,
|
|
30
|
+
|};
|
|
31
|
+
|
|
32
|
+
type DefaultProps = {|
|
|
33
|
+
animateIntoPosition: Props["animateIntoPosition"],
|
|
34
|
+
visible: Props["visible"],
|
|
35
|
+
x: Props["x"],
|
|
36
|
+
y: Props["y"],
|
|
37
|
+
|};
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
class CursorHandle extends React.Component<Props> {
|
|
40
|
+
static defaultProps: DefaultProps = {
|
|
34
41
|
animateIntoPosition: false,
|
|
35
42
|
visible: false,
|
|
36
43
|
x: 0,
|
|
37
44
|
y: 0,
|
|
38
45
|
};
|
|
39
46
|
|
|
40
|
-
render() {
|
|
47
|
+
render(): React.Node {
|
|
41
48
|
const {x, y, animateIntoPosition} = this.props;
|
|
42
49
|
|
|
43
50
|
const animationStyle = animateIntoPosition
|
|
44
51
|
? {
|
|
45
|
-
msTransitionDuration: "100ms",
|
|
46
|
-
WebkitTransitionDuration: "100ms",
|
|
47
52
|
transitionDuration: "100ms",
|
|
48
|
-
msTransitionProperty: "transform",
|
|
49
|
-
WebkitTransitionProperty: "transform",
|
|
50
53
|
transitionProperty: "transform",
|
|
51
54
|
}
|
|
52
55
|
: {};
|
|
@@ -59,8 +62,6 @@ class CursorHandle extends React.Component {
|
|
|
59
62
|
zIndex: 4,
|
|
60
63
|
left: -touchTargetWidthPx / 2,
|
|
61
64
|
top: 0,
|
|
62
|
-
msTransform: transformString,
|
|
63
|
-
WebkitTransform: transformString,
|
|
64
65
|
transform: transformString,
|
|
65
66
|
width: touchTargetWidthPx,
|
|
66
67
|
height: touchTargetHeightPx,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
// @flow
|
|
1
2
|
import Color from "@khanacademy/wonder-blocks-color";
|
|
2
3
|
import * as i18n from "@khanacademy/wonder-blocks-i18n";
|
|
4
|
+
import {entries} from "@khanacademy/wonder-stuff-core";
|
|
3
5
|
import {StyleSheet} from "aphrodite";
|
|
4
|
-
import PropTypes from "prop-types";
|
|
5
6
|
import * as React from "react";
|
|
6
7
|
import ReactDOM from "react-dom";
|
|
7
8
|
|
|
@@ -13,7 +14,6 @@ import {
|
|
|
13
14
|
wonderBlocksBlue,
|
|
14
15
|
offBlack,
|
|
15
16
|
} from "../common-style.js";
|
|
16
|
-
import {keypadElementPropType} from "../prop-types.js";
|
|
17
17
|
|
|
18
18
|
import CursorHandle from "./cursor-handle.js";
|
|
19
19
|
import DragListener from "./drag-listener.js";
|
|
@@ -22,29 +22,54 @@ import {scrollIntoView} from "./scroll-into-view.js";
|
|
|
22
22
|
|
|
23
23
|
const constrainingFrictionFactor = 0.8;
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
25
|
+
type Props = {|
|
|
26
|
+
keypadElement: $FlowFixMe,
|
|
27
|
+
onBlur: () => void,
|
|
28
|
+
onChange: $FlowFixMe,
|
|
29
|
+
onFocus: () => void,
|
|
30
|
+
style: $FlowFixMe,
|
|
31
|
+
value: string,
|
|
32
|
+
|};
|
|
33
|
+
|
|
34
|
+
type DefaultProps = {|
|
|
35
|
+
style: Props["style"],
|
|
36
|
+
value: Props["value"],
|
|
37
|
+
|};
|
|
38
|
+
|
|
39
|
+
type HandleState = {|
|
|
40
|
+
animateIntoPosition?: ?boolean,
|
|
41
|
+
visible: boolean,
|
|
42
|
+
x?: number,
|
|
43
|
+
y?: number,
|
|
44
|
+
|};
|
|
45
|
+
|
|
46
|
+
type State = {|
|
|
47
|
+
focused: boolean,
|
|
48
|
+
handle: HandleState,
|
|
49
|
+
|};
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
// eslint-disable-next-line react/no-unsafe
|
|
52
|
+
class MathInput extends React.Component<Props, State> {
|
|
53
|
+
didTouchOutside: ?boolean;
|
|
54
|
+
didScroll: ?boolean;
|
|
55
|
+
mathField: $FlowFixMe;
|
|
56
|
+
recordTouchStartOutside: ($FlowFixMe) => void;
|
|
57
|
+
blurOnTouchEndOutside: ($FlowFixMe) => void;
|
|
58
|
+
dragListener: $FlowFixMe;
|
|
59
|
+
inputRef: ?HTMLDivElement;
|
|
60
|
+
_isMounted: ?boolean;
|
|
61
|
+
_mathContainer: $FlowFixMe;
|
|
62
|
+
_container: HTMLDivElement;
|
|
63
|
+
_root: $FlowFixMe;
|
|
64
|
+
_containerBounds: ClientRect;
|
|
65
|
+
_keypadBounds: ?ClientRect;
|
|
66
|
+
|
|
67
|
+
static defaultProps: DefaultProps = {
|
|
43
68
|
style: {},
|
|
44
69
|
value: "",
|
|
45
70
|
};
|
|
46
71
|
|
|
47
|
-
state = {
|
|
72
|
+
state: State = {
|
|
48
73
|
focused: false,
|
|
49
74
|
handle: {
|
|
50
75
|
animateIntoPosition: false,
|
|
@@ -92,15 +117,16 @@ class MathInput extends React.Component {
|
|
|
92
117
|
|
|
93
118
|
this._updateInputPadding();
|
|
94
119
|
|
|
95
|
-
this._container = ReactDOM.findDOMNode(this);
|
|
120
|
+
this._container = ((ReactDOM.findDOMNode(this): any): HTMLDivElement);
|
|
96
121
|
this._root = this._container.querySelector(".mq-root-block");
|
|
122
|
+
// $FlowFixMe[incompatible-use]
|
|
123
|
+
// $FlowFixMe[prop-missing]
|
|
97
124
|
this._root.addEventListener("scroll", this._handleScroll);
|
|
98
125
|
|
|
99
126
|
// Record the initial scroll displacement on touch start. This allows
|
|
100
127
|
// us to detect whether a touch event was a scroll and only blur the
|
|
101
128
|
// input on non-scrolls--blurring the input on scroll makes for a
|
|
102
129
|
// frustrating user experience.
|
|
103
|
-
this.touchStartInitialScroll = null;
|
|
104
130
|
this.recordTouchStartOutside = (evt) => {
|
|
105
131
|
if (this.state.focused) {
|
|
106
132
|
// Only blur if the touch is both outside of the input, and
|
|
@@ -168,7 +194,6 @@ class MathInput extends React.Component {
|
|
|
168
194
|
|
|
169
195
|
if (this.dragListener) {
|
|
170
196
|
this.dragListener.detach();
|
|
171
|
-
this.removeListeners = null;
|
|
172
197
|
}
|
|
173
198
|
};
|
|
174
199
|
|
|
@@ -189,13 +214,13 @@ class MathInput extends React.Component {
|
|
|
189
214
|
);
|
|
190
215
|
}
|
|
191
216
|
|
|
192
|
-
UNSAFE_componentWillReceiveProps(props) {
|
|
217
|
+
UNSAFE_componentWillReceiveProps(props: Props) {
|
|
193
218
|
if (this.props.keypadElement !== props.keypadElement) {
|
|
194
219
|
this._clearKeypadBoundsCache();
|
|
195
220
|
}
|
|
196
221
|
}
|
|
197
222
|
|
|
198
|
-
componentDidUpdate(prevProps, prevState) {
|
|
223
|
+
componentDidUpdate(prevProps: Props, prevState: State) {
|
|
199
224
|
if (this.mathField.getContent() !== this.props.value) {
|
|
200
225
|
this.mathField.setContent(this.props.value);
|
|
201
226
|
}
|
|
@@ -218,16 +243,16 @@ class MathInput extends React.Component {
|
|
|
218
243
|
);
|
|
219
244
|
}
|
|
220
245
|
|
|
221
|
-
_clearKeypadBoundsCache = (
|
|
246
|
+
_clearKeypadBoundsCache: () => void = () => {
|
|
222
247
|
this._keypadBounds = null;
|
|
223
248
|
};
|
|
224
249
|
|
|
225
|
-
_cacheKeypadBounds = (keypadNode) => {
|
|
250
|
+
_cacheKeypadBounds: ($FlowFixMe) => void = (keypadNode) => {
|
|
226
251
|
this._keypadBounds = keypadNode.getBoundingClientRect();
|
|
227
252
|
};
|
|
228
253
|
|
|
229
|
-
_updateInputPadding = () => {
|
|
230
|
-
this._container = ReactDOM.findDOMNode(this);
|
|
254
|
+
_updateInputPadding: () => void = () => {
|
|
255
|
+
this._container = ((ReactDOM.findDOMNode(this): any): HTMLDivElement);
|
|
231
256
|
this._root = this._container.querySelector(".mq-root-block");
|
|
232
257
|
|
|
233
258
|
const padding = this.getInputInnerPadding();
|
|
@@ -239,7 +264,7 @@ class MathInput extends React.Component {
|
|
|
239
264
|
};
|
|
240
265
|
|
|
241
266
|
/** Gets and cache they bounds of the keypadElement */
|
|
242
|
-
_getKeypadBounds = () => {
|
|
267
|
+
_getKeypadBounds: () => $FlowFixMe = () => {
|
|
243
268
|
if (!this._keypadBounds) {
|
|
244
269
|
const node = this.props.keypadElement.getDOMNode();
|
|
245
270
|
this._cacheKeypadBounds(node);
|
|
@@ -247,9 +272,9 @@ class MathInput extends React.Component {
|
|
|
247
272
|
return this._keypadBounds;
|
|
248
273
|
};
|
|
249
274
|
|
|
250
|
-
_updateCursorHandle = (animateIntoPosition) => {
|
|
275
|
+
_updateCursorHandle: (?boolean) => void = (animateIntoPosition) => {
|
|
251
276
|
const containerBounds = this._container.getBoundingClientRect();
|
|
252
|
-
const cursor = this._container.querySelector(".mq-cursor");
|
|
277
|
+
const cursor: $FlowFixMe = this._container.querySelector(".mq-cursor");
|
|
253
278
|
const cursorBounds = cursor.getBoundingClientRect();
|
|
254
279
|
|
|
255
280
|
const cursorWidth = cursorBounds.width;
|
|
@@ -285,7 +310,7 @@ class MathInput extends React.Component {
|
|
|
285
310
|
});
|
|
286
311
|
};
|
|
287
312
|
|
|
288
|
-
_hideCursorHandle = () => {
|
|
313
|
+
_hideCursorHandle: () => void = () => {
|
|
289
314
|
this.setState({
|
|
290
315
|
handle: {
|
|
291
316
|
visible: false,
|
|
@@ -295,7 +320,7 @@ class MathInput extends React.Component {
|
|
|
295
320
|
});
|
|
296
321
|
};
|
|
297
322
|
|
|
298
|
-
_handleScroll = () => {
|
|
323
|
+
_handleScroll: () => void = () => {
|
|
299
324
|
// If animateIntoPosition is false, the user is currently manually positioning
|
|
300
325
|
// the cursor. This is important because the user can scroll the input field
|
|
301
326
|
// with the curor handle, and we don't want to override that ability.
|
|
@@ -306,13 +331,13 @@ class MathInput extends React.Component {
|
|
|
306
331
|
}
|
|
307
332
|
};
|
|
308
333
|
|
|
309
|
-
blur = () => {
|
|
334
|
+
blur: () => void = () => {
|
|
310
335
|
this.mathField.blur();
|
|
311
336
|
this.props.onBlur && this.props.onBlur();
|
|
312
337
|
this.setState({focused: false, handle: {visible: false}});
|
|
313
338
|
};
|
|
314
339
|
|
|
315
|
-
focus = () => {
|
|
340
|
+
focus: () => void = () => {
|
|
316
341
|
// Pass this component's handleKey method to the keypad so it can call
|
|
317
342
|
// it whenever it needs to trigger a keypress action.
|
|
318
343
|
this.props.keypadElement.setKeyHandler((key) => {
|
|
@@ -379,7 +404,7 @@ class MathInput extends React.Component {
|
|
|
379
404
|
* The algorithm ends its search when y goes outside the bounds of
|
|
380
405
|
* containerBounds.
|
|
381
406
|
*
|
|
382
|
-
* @param {
|
|
407
|
+
* @param {DOMRect} containerBounds - bounds of the container node
|
|
383
408
|
* @param {number} x - the initial x coordinate in the viewport
|
|
384
409
|
* @param {number} y - the initial y coordinate in the viewport
|
|
385
410
|
* @param {number} dx - horizontal spacing between elementFromPoint calls
|
|
@@ -387,7 +412,13 @@ class MathInput extends React.Component {
|
|
|
387
412
|
* sign determines direction.
|
|
388
413
|
* @returns {boolean} - true if a node was hit, false otherwise.
|
|
389
414
|
*/
|
|
390
|
-
_findHitNode
|
|
415
|
+
_findHitNode: (ClientRect, number, number, number, number) => boolean = (
|
|
416
|
+
containerBounds,
|
|
417
|
+
x,
|
|
418
|
+
y,
|
|
419
|
+
dx,
|
|
420
|
+
dy,
|
|
421
|
+
) => {
|
|
391
422
|
while (y >= containerBounds.top && y <= containerBounds.bottom) {
|
|
392
423
|
y += dy;
|
|
393
424
|
|
|
@@ -428,11 +459,13 @@ class MathInput extends React.Component {
|
|
|
428
459
|
// Contains only DOMNodes with child elements.
|
|
429
460
|
const nonLeafElements = [];
|
|
430
461
|
|
|
431
|
-
let max = 0;
|
|
432
|
-
const counts = {};
|
|
462
|
+
let max: number = 0;
|
|
463
|
+
const counts: {[string]: number} = {};
|
|
433
464
|
const elementsById = {};
|
|
434
465
|
|
|
435
466
|
for (const element of elements) {
|
|
467
|
+
// $FlowFixMe[incompatible-use]
|
|
468
|
+
// $FlowFixMe[prop-missing]
|
|
436
469
|
const id = element.getAttribute("mathquill-command-id");
|
|
437
470
|
if (id != null) {
|
|
438
471
|
leafElements.push(element);
|
|
@@ -455,7 +488,7 @@ class MathInput extends React.Component {
|
|
|
455
488
|
// we hit multiple leaf nodes at the same time. In this case we
|
|
456
489
|
// we prefer the DOMNode with the most hits.
|
|
457
490
|
// TODO(kevinb) consider preferring nodes hit by [x, y].
|
|
458
|
-
for (const [id, count] of
|
|
491
|
+
for (const [id, count] of entries(counts)) {
|
|
459
492
|
if (count > max) {
|
|
460
493
|
max = count;
|
|
461
494
|
hitNode = elementsById[id];
|
|
@@ -487,7 +520,7 @@ class MathInput extends React.Component {
|
|
|
487
520
|
* @param {number} x - the x coordinate in the viewport
|
|
488
521
|
* @param {number} y - the y coordinate in the viewport
|
|
489
522
|
*/
|
|
490
|
-
_insertCursorAtClosestNode = (x, y) => {
|
|
523
|
+
_insertCursorAtClosestNode: (number, number) => void = (x, y) => {
|
|
491
524
|
const cursor = this.mathField.getCursor();
|
|
492
525
|
|
|
493
526
|
// Pre-emptively check if the input has any child nodes; if not, the
|
|
@@ -557,7 +590,7 @@ class MathInput extends React.Component {
|
|
|
557
590
|
});
|
|
558
591
|
};
|
|
559
592
|
|
|
560
|
-
handleTouchStart = (e) => {
|
|
593
|
+
handleTouchStart: (SyntheticTouchEvent<HTMLDivElement>) => void = (e) => {
|
|
561
594
|
e.stopPropagation();
|
|
562
595
|
|
|
563
596
|
// Hide the cursor handle on touch start, if the handle itself isn't
|
|
@@ -582,7 +615,7 @@ class MathInput extends React.Component {
|
|
|
582
615
|
}
|
|
583
616
|
};
|
|
584
617
|
|
|
585
|
-
handleTouchMove = (e) => {
|
|
618
|
+
handleTouchMove: (SyntheticTouchEvent<HTMLDivElement>) => void = (e) => {
|
|
586
619
|
e.stopPropagation();
|
|
587
620
|
|
|
588
621
|
// Update the handle-less cursor's location on move, if there's any
|
|
@@ -597,7 +630,7 @@ class MathInput extends React.Component {
|
|
|
597
630
|
}
|
|
598
631
|
};
|
|
599
632
|
|
|
600
|
-
handleTouchEnd = (e) => {
|
|
633
|
+
handleTouchEnd: (SyntheticTouchEvent<HTMLDivElement>) => void = (e) => {
|
|
601
634
|
e.stopPropagation();
|
|
602
635
|
|
|
603
636
|
// And on touch-end, reveal the cursor, unless the input is empty. Note
|
|
@@ -616,7 +649,9 @@ class MathInput extends React.Component {
|
|
|
616
649
|
*
|
|
617
650
|
* @param {TouchEvent} e - the raw touch event from the browser
|
|
618
651
|
*/
|
|
619
|
-
onCursorHandleTouchStart
|
|
652
|
+
onCursorHandleTouchStart: (SyntheticTouchEvent<HTMLSpanElement>) => void = (
|
|
653
|
+
e,
|
|
654
|
+
) => {
|
|
620
655
|
// NOTE(charlie): The cursor handle is a child of this view, so whenever
|
|
621
656
|
// it receives a touch event, that event would also typically be bubbled
|
|
622
657
|
// up to our own handlers. However, we want the cursor to handle its own
|
|
@@ -632,7 +667,12 @@ class MathInput extends React.Component {
|
|
|
632
667
|
this._containerBounds = this._container.getBoundingClientRect();
|
|
633
668
|
};
|
|
634
669
|
|
|
635
|
-
_constrainToBound
|
|
670
|
+
_constrainToBound: (number, number, number, number) => number = (
|
|
671
|
+
value,
|
|
672
|
+
min,
|
|
673
|
+
max,
|
|
674
|
+
friction,
|
|
675
|
+
) => {
|
|
636
676
|
if (value < min) {
|
|
637
677
|
return min + (value - min) * friction;
|
|
638
678
|
} else if (value > max) {
|
|
@@ -648,7 +688,9 @@ class MathInput extends React.Component {
|
|
|
648
688
|
*
|
|
649
689
|
* @param {TouchEvent} e - the raw touch event from the browser
|
|
650
690
|
*/
|
|
651
|
-
onCursorHandleTouchMove
|
|
691
|
+
onCursorHandleTouchMove: (SyntheticTouchEvent<HTMLSpanElement>) => void = (
|
|
692
|
+
e,
|
|
693
|
+
) => {
|
|
652
694
|
e.stopPropagation();
|
|
653
695
|
|
|
654
696
|
const x = e.changedTouches[0].clientX;
|
|
@@ -702,7 +744,9 @@ class MathInput extends React.Component {
|
|
|
702
744
|
*
|
|
703
745
|
* @param {TouchEvent} e - the raw touch event from the browser
|
|
704
746
|
*/
|
|
705
|
-
onCursorHandleTouchEnd
|
|
747
|
+
onCursorHandleTouchEnd: (SyntheticTouchEvent<HTMLSpanElement>) => void = (
|
|
748
|
+
e,
|
|
749
|
+
) => {
|
|
706
750
|
e.stopPropagation();
|
|
707
751
|
|
|
708
752
|
this._updateCursorHandle(true);
|
|
@@ -713,13 +757,14 @@ class MathInput extends React.Component {
|
|
|
713
757
|
*
|
|
714
758
|
* @param {TouchEvent} e - the raw touch event from the browser
|
|
715
759
|
*/
|
|
716
|
-
onCursorHandleTouchCancel
|
|
717
|
-
e
|
|
760
|
+
onCursorHandleTouchCancel: (SyntheticTouchEvent<HTMLSpanElement>) => void =
|
|
761
|
+
(e) => {
|
|
762
|
+
e.stopPropagation();
|
|
718
763
|
|
|
719
|
-
|
|
720
|
-
|
|
764
|
+
this._updateCursorHandle(true);
|
|
765
|
+
};
|
|
721
766
|
|
|
722
|
-
domKeyToMathQuillKey = (key) => {
|
|
767
|
+
domKeyToMathQuillKey: (string) => ?string = (key) => {
|
|
723
768
|
const keyMap = {
|
|
724
769
|
"+": Keys.PLUS,
|
|
725
770
|
"-": Keys.MINUS,
|
|
@@ -752,7 +797,7 @@ class MathInput extends React.Component {
|
|
|
752
797
|
return null;
|
|
753
798
|
};
|
|
754
799
|
|
|
755
|
-
handleKeyUp = (event) => {
|
|
800
|
+
handleKeyUp: (SyntheticKeyboardEvent<HTMLDivElement>) => void = (event) => {
|
|
756
801
|
const mathQuillKey = this.domKeyToMathQuillKey(event.key);
|
|
757
802
|
|
|
758
803
|
if (mathQuillKey) {
|
|
@@ -770,7 +815,7 @@ class MathInput extends React.Component {
|
|
|
770
815
|
}
|
|
771
816
|
};
|
|
772
817
|
|
|
773
|
-
getBorderWidthPx = () => {
|
|
818
|
+
getBorderWidthPx: () => number = () => {
|
|
774
819
|
// TODO(diedra): Move these to the common style package.
|
|
775
820
|
const normalBorderWidthPx = 1;
|
|
776
821
|
const focusedBorderWidthPx = 2;
|
|
@@ -782,7 +827,12 @@ class MathInput extends React.Component {
|
|
|
782
827
|
// considered 'padding', since we're using 'border-box') and the fact
|
|
783
828
|
// that MathQuill automatically applies 2px of padding to the inner
|
|
784
829
|
// input.
|
|
785
|
-
getInputInnerPadding
|
|
830
|
+
getInputInnerPadding: () => {|
|
|
831
|
+
paddingTop: number,
|
|
832
|
+
paddingRight: number,
|
|
833
|
+
paddingBottom: number,
|
|
834
|
+
paddingLeft: number,
|
|
835
|
+
|} = () => {
|
|
786
836
|
const paddingInset = totalDesiredPadding - this.getBorderWidthPx();
|
|
787
837
|
|
|
788
838
|
// Now, translate that to the appropriate padding for each direction.
|
|
@@ -803,7 +853,7 @@ class MathInput extends React.Component {
|
|
|
803
853
|
return padding;
|
|
804
854
|
};
|
|
805
855
|
|
|
806
|
-
render() {
|
|
856
|
+
render(): React.Node {
|
|
807
857
|
const {focused, handle} = this.state;
|
|
808
858
|
const {style} = this.props;
|
|
809
859
|
|
|
@@ -14,7 +14,7 @@ type Props = {|
|
|
|
14
14
|
onClickKey: (keyConfig: string) => void,
|
|
15
15
|
|};
|
|
16
16
|
|
|
17
|
-
export default class
|
|
17
|
+
export default class PreAlgebraPage extends React.Component<Props> {
|
|
18
18
|
render(): React.Node {
|
|
19
19
|
const {onClickKey} = this.props;
|
|
20
20
|
return (
|
|
@@ -270,14 +270,10 @@ const inlineStyles = {
|
|
|
270
270
|
},
|
|
271
271
|
|
|
272
272
|
hidden: {
|
|
273
|
-
msTransform: "translate3d(0, 100%, 0)",
|
|
274
|
-
WebkitTransform: "translate3d(0, 100%, 0)",
|
|
275
273
|
transform: "translate3d(0, 100%, 0)",
|
|
276
274
|
},
|
|
277
275
|
|
|
278
276
|
active: {
|
|
279
|
-
msTransform: "translate3d(0, 0, 0)",
|
|
280
|
-
WebkitTransform: "translate3d(0, 0, 0)",
|
|
281
277
|
transform: "translate3d(0, 0, 0)",
|
|
282
278
|
},
|
|
283
279
|
};
|
|
@@ -20,11 +20,11 @@ type Props = {|
|
|
|
20
20
|
// difficult to override with inline styles.)
|
|
21
21
|
extraClassName?: string,
|
|
22
22
|
numberOfLines?: number,
|
|
23
|
-
onClick?: () => void,
|
|
24
|
-
onTouchCancel?: () => void,
|
|
25
|
-
onTouchEnd?: () => void,
|
|
26
|
-
onTouchMove?: () => void,
|
|
27
|
-
onTouchStart?: () => void,
|
|
23
|
+
onClick?: (SyntheticEvent<HTMLDivElement>) => void,
|
|
24
|
+
onTouchCancel?: (SyntheticTouchEvent<HTMLDivElement>) => void,
|
|
25
|
+
onTouchEnd?: (SyntheticTouchEvent<HTMLDivElement>) => void,
|
|
26
|
+
onTouchMove?: (SyntheticTouchEvent<HTMLDivElement>) => void,
|
|
27
|
+
onTouchStart?: (SyntheticTouchEvent<HTMLDivElement>) => void,
|
|
28
28
|
role?: string,
|
|
29
29
|
style?: CSSProperties,
|
|
30
30
|
|};
|
|
File without changes
|