@khanacademy/math-input 3.0.0 → 4.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 +35 -0
- package/dist/components/input/__tests__/test-math-wrapper.d.ts +1 -1
- package/dist/components/input/__tests__/test-math-wrapper.js.flow +1 -1
- package/dist/components/input/key-handlers/handle-arrow.d.ts +3 -0
- package/dist/components/input/key-handlers/handle-arrow.js.flow +12 -0
- package/dist/components/input/key-handlers/handle-backspace.d.ts +7 -0
- package/dist/components/input/key-handlers/handle-backspace.js.flow +14 -0
- package/dist/components/input/key-handlers/handle-exponent.d.ts +3 -0
- package/dist/components/input/key-handlers/handle-exponent.js.flow +12 -0
- package/dist/components/input/key-handlers/handle-jump-out.d.ts +7 -0
- package/dist/components/input/key-handlers/handle-jump-out.js.flow +14 -0
- package/dist/components/input/math-wrapper.d.ts +7 -78
- package/dist/components/input/math-wrapper.js.flow +16 -78
- package/dist/components/input/mathquill-helpers.d.ts +46 -0
- package/dist/components/input/mathquill-helpers.js.flow +56 -0
- package/dist/components/input/mathquill-instance.d.ts +3 -0
- package/dist/components/input/mathquill-instance.js.flow +9 -0
- package/dist/components/input/mathquill-types.d.ts +25 -0
- package/dist/components/input/mathquill-types.js.flow +34 -0
- package/dist/components/key-translator.d.ts +4 -0
- package/dist/components/key-translator.js.flow +10 -0
- package/dist/components/keypad/button-assets.d.ts +2 -2
- package/dist/components/keypad/button-assets.js.flow +2 -2
- package/dist/components/keypad/keypad-page-items.d.ts +1 -1
- package/dist/components/keypad/keypad-page-items.js.flow +1 -1
- package/dist/components/keypad-legacy/gesture-manager.d.ts +21 -9
- package/dist/components/keypad-legacy/gesture-manager.js.flow +27 -12
- package/dist/components/keypad-legacy/gesture-state-machine.d.ts +9 -9
- package/dist/components/keypad-legacy/gesture-state-machine.js.flow +10 -10
- package/dist/components/keypad-legacy/keypad-button.d.ts +2 -2
- package/dist/components/keypad-legacy/keypad-button.js.flow +3 -3
- package/dist/components/keypad-legacy/store/actions.d.ts +4 -14
- package/dist/components/keypad-legacy/store/actions.js.flow +3 -15
- package/dist/components/keypad-legacy/store/types.d.ts +2 -2
- package/dist/components/keypad-legacy/store/types.js.flow +2 -2
- package/dist/components/keypad-legacy/touchable-keypad-button.d.ts +6 -6
- package/dist/components/keypad-legacy/touchable-keypad-button.js.flow +9 -14
- package/dist/data/key-configs.d.ts +3 -6
- package/dist/data/key-configs.js.flow +3 -8
- package/dist/data/keys.d.ts +2 -54
- package/dist/data/keys.js.flow +116 -55
- package/dist/enums.d.ts +2 -9
- package/dist/enums.js.flow +2 -11
- package/dist/es/index.js +1781 -1196
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2069 -1242
- package/dist/index.js.flow +4 -2
- package/dist/index.js.map +1 -1
- package/dist/strings.js +26 -10
- package/dist/types.d.ts +10 -12
- package/dist/types.js.flow +13 -12
- package/package.json +1 -1
- package/src/components/input/__tests__/context-tracking.test.ts +43 -44
- package/src/components/input/__tests__/mathquill.test.ts +133 -135
- package/src/components/input/key-handlers/handle-arrow.ts +70 -0
- package/src/components/input/key-handlers/handle-backspace.ts +275 -0
- package/src/components/input/key-handlers/handle-exponent.ts +52 -0
- package/src/components/input/key-handlers/handle-jump-out.ts +103 -0
- package/src/components/input/math-input.tsx +11 -12
- package/src/components/input/math-wrapper.ts +88 -837
- package/src/components/input/mathquill-helpers.ts +268 -0
- package/src/components/input/mathquill-instance.ts +5 -0
- package/src/components/input/mathquill-types.ts +55 -0
- package/src/components/key-translator.ts +209 -0
- package/src/components/keypad/button-assets.tsx +411 -100
- package/src/components/keypad/geometry-page/index.tsx +1 -1
- package/src/components/keypad/keypad-mathquill.stories.tsx +69 -0
- package/src/components/keypad/keypad-page-items.tsx +2 -1
- package/src/components/keypad/operators-page/index.tsx +1 -1
- package/src/components/keypad-legacy/echo-manager.tsx +4 -4
- package/src/components/keypad-legacy/empty-keypad-button.tsx +6 -4
- package/src/components/keypad-legacy/gesture-manager.ts +32 -9
- package/src/components/keypad-legacy/gesture-state-machine.ts +14 -14
- package/src/components/keypad-legacy/keypad-button.tsx +15 -18
- package/src/components/keypad-legacy/many-keypad-button.tsx +9 -2
- package/src/components/keypad-legacy/store/actions.ts +3 -29
- package/src/components/keypad-legacy/store/echo-reducer.ts +2 -5
- package/src/components/keypad-legacy/store/index.ts +4 -10
- package/src/components/keypad-legacy/store/input-reducer.ts +1 -2
- package/src/components/keypad-legacy/store/keypad-reducer.ts +2 -3
- package/src/components/keypad-legacy/store/types.ts +2 -2
- package/src/components/keypad-legacy/touchable-keypad-button.tsx +8 -13
- package/src/components/tabbar/icons.tsx +0 -2
- package/src/data/key-configs.ts +751 -304
- package/src/data/keys.ts +118 -65
- package/src/enums.ts +10 -9
- package/src/index.ts +3 -2
- package/src/math-input.stories.tsx +1 -1
- package/src/types.ts +10 -12
- package/tsconfig-build.tsbuildinfo +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import MathQuill from "mathquill";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import Key from "../../data/keys";
|
|
5
|
+
import keyTranslator from "../key-translator";
|
|
6
|
+
|
|
7
|
+
import Keypad from "./index";
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
title: "v2 Keypad With Mathquill",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const mathQuillConfig = {
|
|
14
|
+
autoCommands: "pi theta phi sqrt nthroot",
|
|
15
|
+
charsThatBreakOutOfSupSub: "+-*/=<>≠≤≥",
|
|
16
|
+
supSubsRequireOperand: true,
|
|
17
|
+
spaceBehavesLikeTab: true,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function V2KeypadWithMathquill() {
|
|
21
|
+
const mathquillWrapperRef = React.useRef<HTMLDivElement>(null);
|
|
22
|
+
const [mathQuill, setMathQuill] = React.useState<MathQuill>();
|
|
23
|
+
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
if (!mathQuill && mathquillWrapperRef.current) {
|
|
26
|
+
const MQ = MathQuill.getInterface(2);
|
|
27
|
+
const mathQuillInstance = MQ.MathField(
|
|
28
|
+
mathquillWrapperRef.current,
|
|
29
|
+
mathQuillConfig,
|
|
30
|
+
);
|
|
31
|
+
setMathQuill(mathQuillInstance);
|
|
32
|
+
}
|
|
33
|
+
}, [mathQuill]);
|
|
34
|
+
|
|
35
|
+
function handleClickKey(key: Key) {
|
|
36
|
+
if (!mathQuill) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const mathQuillCallback = keyTranslator[key];
|
|
41
|
+
if (mathQuillCallback) {
|
|
42
|
+
mathQuillCallback(mathQuill, key);
|
|
43
|
+
} else {
|
|
44
|
+
// eslint-disable-next-line no-console
|
|
45
|
+
console.warn(`No translation to Mathquill for: ${key}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div style={{maxWidth: "400px", margin: "2em"}}>
|
|
51
|
+
<div
|
|
52
|
+
ref={mathquillWrapperRef}
|
|
53
|
+
style={{width: "100%", marginBottom: "1em"}}
|
|
54
|
+
/>
|
|
55
|
+
<div>
|
|
56
|
+
<Keypad
|
|
57
|
+
onClickKey={handleClickKey}
|
|
58
|
+
advancedRelations
|
|
59
|
+
basicRelations
|
|
60
|
+
divisionKey
|
|
61
|
+
logarithms
|
|
62
|
+
multiplicationDot
|
|
63
|
+
preAlgebra
|
|
64
|
+
trigonometry
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {View} from "@khanacademy/wonder-blocks-core";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
|
|
4
|
+
import {KeyConfig} from "../../types";
|
|
5
|
+
|
|
4
6
|
import Button from "./button";
|
|
5
7
|
import ButtonAsset from "./button-assets";
|
|
6
8
|
|
|
7
|
-
import type {KeyConfig} from "../../data/key-configs";
|
|
8
9
|
import type {StyleType} from "@khanacademy/wonder-blocks-core";
|
|
9
10
|
|
|
10
11
|
type KeypadPageContainerProps = {
|
|
@@ -6,8 +6,8 @@ import * as React from "react";
|
|
|
6
6
|
import {TransitionGroup, CSSTransition} from "react-transition-group";
|
|
7
7
|
|
|
8
8
|
import KeyConfigs from "../../data/key-configs";
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
9
|
+
import Key from "../../data/keys";
|
|
10
|
+
import {EchoAnimationType} from "../../enums";
|
|
11
11
|
|
|
12
12
|
import KeypadButton from "./keypad-button";
|
|
13
13
|
import * as zIndexes from "./z-indexes";
|
|
@@ -16,7 +16,7 @@ import type {Bound, Echo as EchoType} from "../../types";
|
|
|
16
16
|
|
|
17
17
|
type EchoProps = {
|
|
18
18
|
animationDurationMs: number;
|
|
19
|
-
id:
|
|
19
|
+
id: Key;
|
|
20
20
|
initialBounds: Bound;
|
|
21
21
|
onAnimationFinish: () => void;
|
|
22
22
|
};
|
|
@@ -50,7 +50,7 @@ class Echo extends React.Component<EchoProps> {
|
|
|
50
50
|
// applied via StyleSheet, will override our inlines.
|
|
51
51
|
return (
|
|
52
52
|
<div style={containerStyle}>
|
|
53
|
-
<KeypadButton icon={icon} type={
|
|
53
|
+
<KeypadButton icon={icon} type={"ECHO"} />
|
|
54
54
|
</div>
|
|
55
55
|
);
|
|
56
56
|
}
|
|
@@ -27,14 +27,16 @@ class EmptyKeypadButton extends React.Component<ReduxProps> {
|
|
|
27
27
|
// to focus them or trigger presses.
|
|
28
28
|
return (
|
|
29
29
|
<KeypadButton
|
|
30
|
-
onTouchStart={(evt: TouchEvent) =>
|
|
30
|
+
onTouchStart={(evt: React.TouchEvent<HTMLDivElement>) =>
|
|
31
31
|
gestureManager.onTouchStart(evt)
|
|
32
32
|
}
|
|
33
|
-
onTouchEnd={(evt: TouchEvent) =>
|
|
34
|
-
|
|
33
|
+
onTouchEnd={(evt: React.TouchEvent<HTMLDivElement>) =>
|
|
34
|
+
gestureManager.onTouchEnd(evt)
|
|
35
|
+
}
|
|
36
|
+
onTouchMove={(evt: React.TouchEvent<HTMLDivElement>) =>
|
|
35
37
|
gestureManager.onTouchMove(evt)
|
|
36
38
|
}
|
|
37
|
-
onTouchCancel={(evt: TouchEvent) =>
|
|
39
|
+
onTouchCancel={(evt: React.TouchEvent<HTMLDivElement>) =>
|
|
38
40
|
gestureManager.onTouchCancel(evt)
|
|
39
41
|
}
|
|
40
42
|
{...KeyConfigs.NOOP}
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* connects our various bits of logic for managing gestures and interactions,
|
|
4
4
|
* and links them together.
|
|
5
5
|
*/
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
|
|
8
|
+
import Key from "../../data/keys";
|
|
9
|
+
import {ActiveNodesObj, LayoutProps} from "../../types";
|
|
6
10
|
|
|
7
11
|
import GestureStateMachine from "./gesture-state-machine";
|
|
8
12
|
import NodeManager from "./node-manager";
|
|
@@ -12,6 +16,17 @@ const coordsForEvent = (evt) => {
|
|
|
12
16
|
return [evt.changedTouches[0].clientX, evt.changedTouches[0].clientY];
|
|
13
17
|
};
|
|
14
18
|
|
|
19
|
+
type Options = {
|
|
20
|
+
swipeEnabled: boolean;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type Handlers = {
|
|
24
|
+
onSwipeChange?: (dx: number) => void;
|
|
25
|
+
onSwipeEnd?: (dx: number) => void;
|
|
26
|
+
onActiveNodesChanged: (activeNodes: ActiveNodesObj) => void;
|
|
27
|
+
onClick: (key: Key, layoutProps: LayoutProps, inPopover: boolean) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
15
30
|
class GestureManager {
|
|
16
31
|
swipeEnabled: boolean;
|
|
17
32
|
trackEvents: boolean;
|
|
@@ -19,7 +34,12 @@ class GestureManager {
|
|
|
19
34
|
popoverStateMachine: PopoverStateMachine;
|
|
20
35
|
gestureStateMachine: GestureStateMachine;
|
|
21
36
|
|
|
22
|
-
constructor(
|
|
37
|
+
constructor(
|
|
38
|
+
options: Options,
|
|
39
|
+
handlers: Handlers,
|
|
40
|
+
disabledSwipeKeys: ReadonlyArray<Key>,
|
|
41
|
+
multiPressableKeys: ReadonlyArray<Key>,
|
|
42
|
+
) {
|
|
23
43
|
const {swipeEnabled} = options;
|
|
24
44
|
|
|
25
45
|
this.swipeEnabled = swipeEnabled;
|
|
@@ -96,11 +116,14 @@ class GestureManager {
|
|
|
96
116
|
* Handle a touch-start event that originated in a node registered with the
|
|
97
117
|
* gesture system.
|
|
98
118
|
*
|
|
99
|
-
* @param {TouchEvent} evt - the raw touch event from the browser
|
|
119
|
+
* @param {React.TouchEvent<HTMLDivElement>} evt - the raw touch event from the browser
|
|
100
120
|
* @param {string} id - the identifier of the DOM node in which the touch
|
|
101
121
|
* occurred
|
|
102
122
|
*/
|
|
103
|
-
onTouchStart(
|
|
123
|
+
onTouchStart(
|
|
124
|
+
evt: React.TouchEvent<HTMLDivElement>,
|
|
125
|
+
id?: string | undefined,
|
|
126
|
+
) {
|
|
104
127
|
if (!this.trackEvents) {
|
|
105
128
|
return;
|
|
106
129
|
}
|
|
@@ -128,9 +151,9 @@ class GestureManager {
|
|
|
128
151
|
* Handle a touch-move event that originated in a node registered with the
|
|
129
152
|
* gesture system.
|
|
130
153
|
*
|
|
131
|
-
* @param {TouchEvent} evt - the raw touch event from the browser
|
|
154
|
+
* @param {React.TouchEvent<HTMLDivElement>} evt - the raw touch event from the browser
|
|
132
155
|
*/
|
|
133
|
-
onTouchMove(evt: TouchEvent) {
|
|
156
|
+
onTouchMove(evt: React.TouchEvent<HTMLDivElement>) {
|
|
134
157
|
if (!this.trackEvents) {
|
|
135
158
|
return;
|
|
136
159
|
}
|
|
@@ -152,9 +175,9 @@ class GestureManager {
|
|
|
152
175
|
* Handle a touch-end event that originated in a node registered with the
|
|
153
176
|
* gesture system.
|
|
154
177
|
*
|
|
155
|
-
* @param {TouchEvent} evt - the raw touch event from the browser
|
|
178
|
+
* @param {React.TouchEvent<HTMLDivElement>} evt - the raw touch event from the browser
|
|
156
179
|
*/
|
|
157
|
-
onTouchEnd(evt: TouchEvent) {
|
|
180
|
+
onTouchEnd(evt: React.TouchEvent<HTMLDivElement>) {
|
|
158
181
|
if (!this.trackEvents) {
|
|
159
182
|
return;
|
|
160
183
|
}
|
|
@@ -173,9 +196,9 @@ class GestureManager {
|
|
|
173
196
|
* Handle a touch-cancel event that originated in a node registered with the
|
|
174
197
|
* gesture system.
|
|
175
198
|
*
|
|
176
|
-
* @param {TouchEvent} evt - the raw touch event from the browser
|
|
199
|
+
* @param {React.TouchEvent<HTMLDivElement>} evt - the raw touch event from the browser
|
|
177
200
|
*/
|
|
178
|
-
onTouchCancel(evt: TouchEvent) {
|
|
201
|
+
onTouchCancel(evt: React.TouchEvent<HTMLDivElement>) {
|
|
179
202
|
if (!this.trackEvents) {
|
|
180
203
|
return;
|
|
181
204
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Key from "../../data/keys";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The state machine that backs our gesture system. In particular, this state
|
|
@@ -14,8 +14,8 @@ export type Handlers = {
|
|
|
14
14
|
onBlur: () => void;
|
|
15
15
|
onTrigger: (id: string) => void;
|
|
16
16
|
onLongPress: (id: string) => void;
|
|
17
|
-
onSwipeChange
|
|
18
|
-
onSwipeEnd
|
|
17
|
+
onSwipeChange?: (x: number) => void;
|
|
18
|
+
onSwipeEnd?: (x: number) => void;
|
|
19
19
|
onTouchEnd: (id: string) => void;
|
|
20
20
|
};
|
|
21
21
|
|
|
@@ -26,17 +26,17 @@ type Options = {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
type TouchState = {
|
|
29
|
-
activeNodeId:
|
|
29
|
+
activeNodeId: Key;
|
|
30
30
|
pressAndHoldIntervalId: number | null;
|
|
31
31
|
longPressTimeoutId: number | null;
|
|
32
32
|
swipeLocked: boolean;
|
|
33
33
|
startX: number;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
type TouchStateMap = Record<
|
|
36
|
+
type TouchStateMap = Record<Key, TouchState>;
|
|
37
37
|
|
|
38
38
|
type SwipeState = {
|
|
39
|
-
touchId:
|
|
39
|
+
touchId: Key;
|
|
40
40
|
startX: number;
|
|
41
41
|
};
|
|
42
42
|
|
|
@@ -49,16 +49,16 @@ const defaultOptions: Options = {
|
|
|
49
49
|
class GestureStateMachine {
|
|
50
50
|
handlers: Handlers;
|
|
51
51
|
options: Options;
|
|
52
|
-
swipeDisabledNodeIds:
|
|
53
|
-
multiPressableKeys:
|
|
52
|
+
swipeDisabledNodeIds: ReadonlyArray<Key>;
|
|
53
|
+
multiPressableKeys: ReadonlyArray<Key>;
|
|
54
54
|
touchState: Partial<TouchStateMap>;
|
|
55
55
|
swipeState: SwipeState | null;
|
|
56
56
|
|
|
57
57
|
constructor(
|
|
58
58
|
handlers: Handlers,
|
|
59
59
|
options: Partial<Options>,
|
|
60
|
-
swipeDisabledNodeIds?:
|
|
61
|
-
multiPressableKeys?:
|
|
60
|
+
swipeDisabledNodeIds?: ReadonlyArray<Key>,
|
|
61
|
+
multiPressableKeys?: ReadonlyArray<Key>,
|
|
62
62
|
) {
|
|
63
63
|
this.handlers = handlers;
|
|
64
64
|
this.options = {
|
|
@@ -234,7 +234,7 @@ class GestureStateMachine {
|
|
|
234
234
|
// Only respect the finger that started a swipe. Any other lingering
|
|
235
235
|
// gestures are ignored.
|
|
236
236
|
if (this.swipeState.touchId === touchId) {
|
|
237
|
-
this.handlers.onSwipeChange(pageX - this.swipeState.startX);
|
|
237
|
+
this.handlers.onSwipeChange?.(pageX - this.swipeState.startX);
|
|
238
238
|
}
|
|
239
239
|
} else if (this.touchState[touchId]) {
|
|
240
240
|
// It could be touch events started outside the keypad and
|
|
@@ -256,7 +256,7 @@ class GestureStateMachine {
|
|
|
256
256
|
touchId,
|
|
257
257
|
startX,
|
|
258
258
|
};
|
|
259
|
-
this.handlers.onSwipeChange(pageX - this.swipeState.startX);
|
|
259
|
+
this.handlers.onSwipeChange?.(pageX - this.swipeState.startX);
|
|
260
260
|
} else {
|
|
261
261
|
const id = getId();
|
|
262
262
|
if (id !== activeNodeId) {
|
|
@@ -279,7 +279,7 @@ class GestureStateMachine {
|
|
|
279
279
|
// Only respect the finger that started a swipe. Any other lingering
|
|
280
280
|
// gestures are ignored.
|
|
281
281
|
if (this.swipeState.touchId === touchId) {
|
|
282
|
-
this.handlers.onSwipeEnd(pageX - this.swipeState.startX);
|
|
282
|
+
this.handlers.onSwipeEnd?.(pageX - this.swipeState.startX);
|
|
283
283
|
this.swipeState = null;
|
|
284
284
|
}
|
|
285
285
|
} else if (this.touchState[touchId]) {
|
|
@@ -313,7 +313,7 @@ class GestureStateMachine {
|
|
|
313
313
|
// displacement.
|
|
314
314
|
if (this.swipeState) {
|
|
315
315
|
if (this.swipeState.touchId === touchId) {
|
|
316
|
-
this.handlers.onSwipeEnd(0);
|
|
316
|
+
this.handlers.onSwipeEnd?.(0);
|
|
317
317
|
this.swipeState = null;
|
|
318
318
|
}
|
|
319
319
|
} else if (this.touchState[touchId]) {
|
|
@@ -6,7 +6,7 @@ import {StyleSheet, css} from "aphrodite";
|
|
|
6
6
|
import * as React from "react";
|
|
7
7
|
import {connect} from "react-redux";
|
|
8
8
|
|
|
9
|
-
import {BorderDirection, BorderStyles, KeyType} from "../../enums";
|
|
9
|
+
import {BorderDirection, BorderStyles, KeyType, KeyTypes} from "../../enums";
|
|
10
10
|
import {View} from "../../fake-react-native-web/index";
|
|
11
11
|
import {
|
|
12
12
|
wonderBlocksBlue,
|
|
@@ -40,7 +40,7 @@ interface Props extends ReduxProps {
|
|
|
40
40
|
focused: boolean;
|
|
41
41
|
popoverEnabled: boolean;
|
|
42
42
|
type: KeyType;
|
|
43
|
-
icon
|
|
43
|
+
icon?: IconConfig;
|
|
44
44
|
style?: StyleType;
|
|
45
45
|
onTouchCancel?: (evt: React.TouchEvent<HTMLDivElement>) => void;
|
|
46
46
|
onTouchEnd?: (evt: React.TouchEvent<HTMLDivElement>) => void;
|
|
@@ -101,7 +101,7 @@ class KeypadButton extends React.PureComponent<Props> {
|
|
|
101
101
|
// object. This method must be called whenever a property that
|
|
102
102
|
// influences the possible outcomes of `this._getFocusStyle` and
|
|
103
103
|
// `this._getButtonStyle` changes (such as `this.buttonSizeStyle`).
|
|
104
|
-
for (const type of
|
|
104
|
+
for (const type of KeyTypes) {
|
|
105
105
|
css(View.styles.initial, ...this._getFocusStyle(type));
|
|
106
106
|
|
|
107
107
|
for (const borders of Object.values(BorderStyles)) {
|
|
@@ -115,10 +115,7 @@ class KeypadButton extends React.PureComponent<Props> {
|
|
|
115
115
|
|
|
116
116
|
_getFocusStyle = (type: KeyType) => {
|
|
117
117
|
let focusBackgroundStyle;
|
|
118
|
-
if (
|
|
119
|
-
type === KeyType.INPUT_NAVIGATION ||
|
|
120
|
-
type === KeyType.KEYPAD_NAVIGATION
|
|
121
|
-
) {
|
|
118
|
+
if (type === "INPUT_NAVIGATION" || type === "KEYPAD_NAVIGATION") {
|
|
122
119
|
focusBackgroundStyle = styles.light;
|
|
123
120
|
} else {
|
|
124
121
|
focusBackgroundStyle = styles.bright;
|
|
@@ -131,25 +128,25 @@ class KeypadButton extends React.PureComponent<Props> {
|
|
|
131
128
|
// Select the appropriate style for the button.
|
|
132
129
|
let backgroundStyle;
|
|
133
130
|
switch (type) {
|
|
134
|
-
case
|
|
131
|
+
case "EMPTY":
|
|
135
132
|
backgroundStyle = styles.empty;
|
|
136
133
|
break;
|
|
137
134
|
|
|
138
|
-
case
|
|
139
|
-
case
|
|
135
|
+
case "MANY":
|
|
136
|
+
case "VALUE":
|
|
140
137
|
backgroundStyle = styles.value;
|
|
141
138
|
break;
|
|
142
139
|
|
|
143
|
-
case
|
|
140
|
+
case "OPERATOR":
|
|
144
141
|
backgroundStyle = styles.operator;
|
|
145
142
|
break;
|
|
146
143
|
|
|
147
|
-
case
|
|
148
|
-
case
|
|
144
|
+
case "INPUT_NAVIGATION":
|
|
145
|
+
case "KEYPAD_NAVIGATION":
|
|
149
146
|
backgroundStyle = styles.control;
|
|
150
147
|
break;
|
|
151
148
|
|
|
152
|
-
case
|
|
149
|
+
case "ECHO":
|
|
153
150
|
backgroundStyle = null;
|
|
154
151
|
break;
|
|
155
152
|
}
|
|
@@ -168,7 +165,7 @@ class KeypadButton extends React.PureComponent<Props> {
|
|
|
168
165
|
styles.buttonBase,
|
|
169
166
|
backgroundStyle,
|
|
170
167
|
...borderStyle,
|
|
171
|
-
type ===
|
|
168
|
+
type === "ECHO" && styles.echo,
|
|
172
169
|
this.buttonSizeStyle,
|
|
173
170
|
// React Native allows you to set the 'style' props on user defined
|
|
174
171
|
// components.
|
|
@@ -197,7 +194,7 @@ class KeypadButton extends React.PureComponent<Props> {
|
|
|
197
194
|
// We render in the focus state if the key is focused, or if it's an
|
|
198
195
|
// echo.
|
|
199
196
|
const renderFocused =
|
|
200
|
-
(!disabled && focused) || popoverEnabled || type ===
|
|
197
|
+
(!disabled && focused) || popoverEnabled || type === "ECHO";
|
|
201
198
|
const buttonStyle = this._getButtonStyle(type, borders, style);
|
|
202
199
|
const focusStyle = this._getFocusStyle(type);
|
|
203
200
|
const iconWrapperStyle = [
|
|
@@ -218,9 +215,9 @@ class KeypadButton extends React.PureComponent<Props> {
|
|
|
218
215
|
childKeys &&
|
|
219
216
|
childKeys.length > 0 && <CornerDecal style={styles.decalInset} />;
|
|
220
217
|
|
|
221
|
-
if (type ===
|
|
218
|
+
if (type === "EMPTY") {
|
|
222
219
|
return <View style={buttonStyle} {...eventHandlers} />;
|
|
223
|
-
} else if (type ===
|
|
220
|
+
} else if (type === "MANY") {
|
|
224
221
|
// TODO(charlie): Make the long-press interaction accessible. See
|
|
225
222
|
// the TODO in key-configs.js for more.
|
|
226
223
|
const manyButtonA11yMarkup = {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import * as React from "react";
|
|
7
7
|
|
|
8
8
|
import KeyConfigs from "../../data/key-configs";
|
|
9
|
-
import {
|
|
9
|
+
import {IconType} from "../../enums";
|
|
10
10
|
import {KeyConfig} from "../../types";
|
|
11
11
|
|
|
12
12
|
import EmptyKeypadButton from "./empty-keypad-button";
|
|
@@ -35,8 +35,15 @@ class ManyKeypadButton extends React.Component<Props> {
|
|
|
35
35
|
} else {
|
|
36
36
|
const keyConfig: KeyConfig = {
|
|
37
37
|
id: "MANY",
|
|
38
|
-
type:
|
|
38
|
+
type: "MANY",
|
|
39
39
|
childKeyIds: keys,
|
|
40
|
+
ariaLabel: keys
|
|
41
|
+
.map((key) => KeyConfigs[key].ariaLabel)
|
|
42
|
+
.join(", "),
|
|
43
|
+
icon: {
|
|
44
|
+
type: IconType.SVG,
|
|
45
|
+
data: "many",
|
|
46
|
+
},
|
|
40
47
|
};
|
|
41
48
|
return <TouchableKeypadButton keyConfig={keyConfig} {...rest} />;
|
|
42
49
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Key from "../../../data/keys";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
4
|
Bound,
|
|
@@ -104,30 +104,6 @@ export const setCursor = (cursor: Cursor): SetCursorAction => {
|
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
// Gesture actions
|
|
107
|
-
type OnSwipeChangeAction = {
|
|
108
|
-
type: "OnSwipeChange";
|
|
109
|
-
dx: number;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
export const onSwipeChange = (dx: number): OnSwipeChangeAction => {
|
|
113
|
-
return {
|
|
114
|
-
type: "OnSwipeChange",
|
|
115
|
-
dx,
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
type OnSwipeEndAction = {
|
|
120
|
-
type: "OnSwipeEnd";
|
|
121
|
-
dx: number;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
export const onSwipeEnd = (dx: number): OnSwipeEndAction => {
|
|
125
|
-
return {
|
|
126
|
-
type: "OnSwipeEnd",
|
|
127
|
-
dx,
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
|
|
131
107
|
type SetActiveNodesAction = {
|
|
132
108
|
type: "SetActiveNodes";
|
|
133
109
|
activeNodes: any;
|
|
@@ -144,13 +120,13 @@ export const setActiveNodes = (
|
|
|
144
120
|
|
|
145
121
|
type PressKeyAction = {
|
|
146
122
|
type: "PressKey";
|
|
147
|
-
key:
|
|
123
|
+
key: Key;
|
|
148
124
|
initialBounds: Bound;
|
|
149
125
|
inPopover: boolean;
|
|
150
126
|
};
|
|
151
127
|
|
|
152
128
|
export const pressKey = (
|
|
153
|
-
key:
|
|
129
|
+
key: Key,
|
|
154
130
|
initialBounds: Bound,
|
|
155
131
|
inPopover: any,
|
|
156
132
|
): PressKeyAction => {
|
|
@@ -170,7 +146,5 @@ export type Action =
|
|
|
170
146
|
| RemoveEchoAction
|
|
171
147
|
| SetKeyHandlerAction
|
|
172
148
|
| SetCursorAction
|
|
173
|
-
| OnSwipeChangeAction
|
|
174
|
-
| OnSwipeEndAction
|
|
175
149
|
| SetActiveNodesAction
|
|
176
150
|
| PressKeyAction;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import KeyConfigs from "../../../data/key-configs";
|
|
2
|
-
import {EchoAnimationType
|
|
2
|
+
import {EchoAnimationType} from "../../../enums";
|
|
3
3
|
|
|
4
4
|
import type {Action} from "./actions";
|
|
5
5
|
import type {EchoState} from "./types";
|
|
@@ -22,10 +22,7 @@ const echoReducer = function (
|
|
|
22
22
|
|
|
23
23
|
// Add in the echo animation if the user performs a math
|
|
24
24
|
// operation.
|
|
25
|
-
if (
|
|
26
|
-
keyConfig.type === KeyType.VALUE ||
|
|
27
|
-
keyConfig.type === KeyType.OPERATOR
|
|
28
|
-
) {
|
|
25
|
+
if (keyConfig.type === "VALUE" || keyConfig.type === "OPERATOR") {
|
|
29
26
|
return {
|
|
30
27
|
...state,
|
|
31
28
|
echoes: [
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as Redux from "redux";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import Key from "../../../data/keys";
|
|
4
4
|
import GestureManager from "../gesture-manager";
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {setActiveNodes, pressKey} from "./actions";
|
|
7
7
|
import echoReducer from "./echo-reducer";
|
|
8
8
|
import inputReducer from "./input-reducer";
|
|
9
9
|
import keypadReducer from "./keypad-reducer";
|
|
@@ -23,17 +23,11 @@ export const createStore = () => {
|
|
|
23
23
|
swipeEnabled,
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
onSwipeChange: (dx: number) => {
|
|
27
|
-
store.dispatch(onSwipeChange(dx));
|
|
28
|
-
},
|
|
29
|
-
onSwipeEnd: (dx: number) => {
|
|
30
|
-
store.dispatch(onSwipeEnd(dx));
|
|
31
|
-
},
|
|
32
26
|
onActiveNodesChanged: (activeNodes: ActiveNodesObj) => {
|
|
33
27
|
store.dispatch(setActiveNodes(activeNodes));
|
|
34
28
|
},
|
|
35
29
|
onClick: (
|
|
36
|
-
key:
|
|
30
|
+
key: Key,
|
|
37
31
|
layoutProps: LayoutProps,
|
|
38
32
|
inPopover: boolean,
|
|
39
33
|
) => {
|
|
@@ -43,7 +37,7 @@ export const createStore = () => {
|
|
|
43
37
|
},
|
|
44
38
|
},
|
|
45
39
|
[],
|
|
46
|
-
[
|
|
40
|
+
["BACKSPACE", "UP", "RIGHT", "DOWN", "LEFT"],
|
|
47
41
|
);
|
|
48
42
|
};
|
|
49
43
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import KeyConfigs from "../../../data/key-configs";
|
|
2
|
-
import {KeyType} from "../../../enums";
|
|
3
2
|
import {CursorContext} from "../../input/cursor-contexts";
|
|
4
3
|
|
|
5
4
|
import type {Cursor, KeyHandler} from "../../../types";
|
|
@@ -29,7 +28,7 @@ const inputReducer = function (
|
|
|
29
28
|
|
|
30
29
|
case "PressKey":
|
|
31
30
|
const keyConfig = KeyConfigs[action.key];
|
|
32
|
-
if (keyConfig.type !==
|
|
31
|
+
if (keyConfig.type !== "KEYPAD_NAVIGATION") {
|
|
33
32
|
// This is probably an anti-pattern but it works for the
|
|
34
33
|
// case where we don't actually control the state but we
|
|
35
34
|
// still want to communicate with the other object
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import KeyConfigs from "../../../data/key-configs";
|
|
2
|
-
import Keys from "../../../data/keys";
|
|
3
2
|
|
|
4
3
|
import {defaultKeypadType} from "./shared";
|
|
5
4
|
|
|
@@ -7,7 +6,7 @@ import type {Action} from "./actions";
|
|
|
7
6
|
import type {KeypadState} from "./types";
|
|
8
7
|
|
|
9
8
|
const initialKeypadState = {
|
|
10
|
-
extraKeys: ["x", "y",
|
|
9
|
+
extraKeys: ["x", "y", "THETA", "PI"] as const,
|
|
11
10
|
keypadType: defaultKeypadType,
|
|
12
11
|
active: false,
|
|
13
12
|
} as const;
|
|
@@ -46,7 +45,7 @@ const keypadReducer = function (
|
|
|
46
45
|
// right actions when they occur. Hence, we figure off a
|
|
47
46
|
// dismissal here rather than dispatching a dismiss action in
|
|
48
47
|
// the first place.
|
|
49
|
-
if (keyConfig.id ===
|
|
48
|
+
if (keyConfig.id === "DISMISS") {
|
|
50
49
|
return keypadReducer(state, {type: "DismissKeypad"});
|
|
51
50
|
}
|
|
52
51
|
return state;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Key from "../../../data/keys";
|
|
2
2
|
import {LayoutMode, KeypadType} from "../../../enums";
|
|
3
3
|
import GestureManager from "../gesture-manager";
|
|
4
4
|
|
|
@@ -36,7 +36,7 @@ export interface GestureState {
|
|
|
36
36
|
// The current multikey popover?
|
|
37
37
|
popover: Popover | null;
|
|
38
38
|
// ?? Maybe which key is currently focused?
|
|
39
|
-
focus:
|
|
39
|
+
focus: Key | null;
|
|
40
40
|
// Complex object that interprets touches as actions
|
|
41
41
|
gestureManager: GestureManager;
|
|
42
42
|
}
|