@khanacademy/math-input 6.0.2 → 7.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/components/input/math-input.d.ts +2 -2
  3. package/dist/components/input/math-input.js.flow +2 -2
  4. package/dist/components/keypad/index.d.ts +2 -26
  5. package/dist/components/keypad/index.js.flow +2 -31
  6. package/dist/components/keypad/keypad.d.ts +26 -0
  7. package/dist/components/keypad/keypad.js.flow +37 -0
  8. package/dist/components/keypad/mobile-keypad.d.ts +39 -0
  9. package/dist/components/keypad/mobile-keypad.js.flow +57 -0
  10. package/dist/components/keypad/shared-keys.d.ts +1 -1
  11. package/dist/components/keypad/shared-keys.js.flow +1 -1
  12. package/dist/components/keypad-legacy/index.d.ts +1 -0
  13. package/dist/components/keypad-legacy/index.js.flow +7 -0
  14. package/dist/components/keypad-legacy/provided-keypad.d.ts +2 -2
  15. package/dist/components/keypad-legacy/provided-keypad.js.flow +10 -2
  16. package/dist/components/keypad-legacy/touchable-keypad-button.d.ts +1 -1
  17. package/dist/components/keypad-legacy/touchable-keypad-button.js.flow +1 -1
  18. package/dist/components/keypad-legacy/two-page-keypad.d.ts +1 -1
  19. package/dist/components/keypad-legacy/two-page-keypad.js.flow +1 -1
  20. package/dist/components/tabbar/index.d.ts +2 -0
  21. package/dist/components/tabbar/index.js.flow +8 -0
  22. package/dist/es/index.js +306 -173
  23. package/dist/es/index.js.map +1 -1
  24. package/dist/index.d.ts +6 -6
  25. package/dist/index.js +322 -187
  26. package/dist/index.js.flow +9 -9
  27. package/dist/index.js.map +1 -1
  28. package/dist/types.d.ts +9 -0
  29. package/dist/types.js.flow +12 -0
  30. package/package.json +2 -2
  31. package/src/components/input/math-input.tsx +4 -5
  32. package/src/components/keypad/index.tsx +2 -173
  33. package/src/components/keypad/keypad.stories.tsx +2 -1
  34. package/src/components/keypad/keypad.tsx +171 -0
  35. package/src/components/keypad/mobile-keypad.tsx +165 -0
  36. package/src/components/keypad/shared-keys.tsx +1 -1
  37. package/src/components/keypad-legacy/index.ts +1 -0
  38. package/src/components/keypad-legacy/provided-keypad.tsx +7 -2
  39. package/src/components/keypad-legacy/two-page-keypad.tsx +3 -2
  40. package/src/components/prop-types.js +0 -1
  41. package/src/components/tabbar/index.ts +2 -0
  42. package/src/full-math-input.stories.tsx +78 -0
  43. package/src/index.ts +28 -9
  44. package/src/types.ts +11 -0
  45. package/tsconfig-build.tsbuildinfo +1 -1
  46. package/src/math-input.stories.tsx +0 -67
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import ReactDOM from "react-dom";
1
2
  import { CursorContext } from "./components/input/cursor-contexts";
2
3
  import Key from "./data/keys";
3
4
  import { BorderDirection, EchoAnimationType, IconType, KeyType, KeypadType } from "./enums";
@@ -62,4 +63,12 @@ export type LayoutProps = {
62
63
  initialBounds: Bound;
63
64
  };
64
65
  export type ClickKeyCallback = (key: Key) => void;
66
+ export interface KeypadAPI {
67
+ activate: () => void;
68
+ dismiss: () => void;
69
+ configure: (configuration: KeypadConfiguration, cb: () => void) => void;
70
+ setCursor: (cursor: Cursor) => void;
71
+ setKeyHandler: (keyHandler: KeyHandler) => void;
72
+ getDOMNode: () => ReturnType<typeof ReactDOM.findDOMNode>;
73
+ }
65
74
  export {};
@@ -4,6 +4,7 @@
4
4
  * Flowgen v1.21.0
5
5
  * @flow
6
6
  */
7
+ import ReactDOM from "react-dom";
7
8
  import { CursorContext } from "./components/input/cursor-contexts";
8
9
  import Key from "./data/keys";
9
10
  import {
@@ -77,3 +78,14 @@ export type LayoutProps = {|
77
78
  initialBounds: Bound,
78
79
  |};
79
80
  export type ClickKeyCallback = (key: Key) => void;
81
+ export interface KeypadAPI {
82
+ activate: () => void;
83
+ dismiss: () => void;
84
+ configure: (configuration: KeypadConfiguration, cb: () => void) => void;
85
+ setCursor: (cursor: Cursor) => void;
86
+ setKeyHandler: (keyHandler: KeyHandler) => void;
87
+ getDOMNode: () => $Call<
88
+ <R>((...args: any[]) => R) => R,
89
+ typeof ReactDOM.findDOMNode
90
+ >;
91
+ }
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": "6.0.2",
6
+ "version": "7.0.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -20,7 +20,7 @@
20
20
  "scripts": {},
21
21
  "dependencies": {
22
22
  "@khanacademy/perseus-core": "0.0.2",
23
- "mathquill": "git+https://git@github.com/Khan/mathquill.git#a9ae54e057c5c1acc8244a5627acbff29901d992",
23
+ "mathquill": "git+https://git@github.com/Khan/mathquill.git#32d9f351aaa68537170b3120a52e99b8def3a2c3",
24
24
  "performance-now": "^0.2.0"
25
25
  },
26
26
  "devDependencies": {
@@ -12,19 +12,18 @@ import {
12
12
  wonderBlocksBlue,
13
13
  offBlack,
14
14
  } from "../common-style";
15
- import ProvidedKeypad from "../keypad-legacy/provided-keypad";
16
15
 
17
16
  import CursorHandle from "./cursor-handle";
18
17
  import DragListener from "./drag-listener";
19
18
  import MathWrapper from "./math-wrapper";
20
19
  import {scrollIntoView} from "./scroll-into-view";
21
20
 
22
- import type {Cursor} from "../../types";
21
+ import type {Cursor, KeypadAPI} from "../../types";
23
22
 
24
23
  const constrainingFrictionFactor = 0.8;
25
24
 
26
25
  type Props = {
27
- keypadElement: ProvidedKeypad;
26
+ keypadElement?: KeypadAPI;
28
27
  onBlur: () => void;
29
28
  onChange: (value: string, callback: any) => void;
30
29
  onFocus: () => void;
@@ -267,7 +266,7 @@ class MathInput extends React.Component<Props, State> {
267
266
  /** Gets and cache they bounds of the keypadElement */
268
267
  _getKeypadBounds: () => any = () => {
269
268
  if (!this._keypadBounds) {
270
- const node = this.props.keypadElement.getDOMNode();
269
+ const node = this.props.keypadElement?.getDOMNode();
271
270
  this._cacheKeypadBounds(node);
272
271
  }
273
272
  return this._keypadBounds;
@@ -341,7 +340,7 @@ class MathInput extends React.Component<Props, State> {
341
340
  focus: () => void = () => {
342
341
  // Pass this component's handleKey method to the keypad so it can call
343
342
  // it whenever it needs to trigger a keypress action.
344
- this.props.keypadElement.setKeyHandler((key) => {
343
+ this.props.keypadElement?.setKeyHandler((key) => {
345
344
  const cursor = this.mathField.pressKey(key);
346
345
 
347
346
  // Trigger an `onChange` if the value in the input changed, and hide
@@ -1,173 +1,2 @@
1
- import Color from "@khanacademy/wonder-blocks-color";
2
- import {View} from "@khanacademy/wonder-blocks-core";
3
- import {StyleSheet} from "aphrodite";
4
- import * as React from "react";
5
- import {useEffect} from "react";
6
-
7
- import Key from "../../data/keys";
8
- import {ClickKeyCallback} from "../../types";
9
- import {CursorContext} from "../input/cursor-contexts";
10
- import Tabbar from "../tabbar/tabbar";
11
- import {TabbarItemType} from "../tabbar/types";
12
-
13
- import ExtrasPage from "./keypad-pages/extras-page";
14
- import GeometryPage from "./keypad-pages/geometry-page";
15
- import NumbersPage from "./keypad-pages/numbers-page";
16
- import OperatorsPage from "./keypad-pages/operators-page";
17
- import SharedKeys from "./shared-keys";
18
-
19
- import type {SendEventFn} from "@khanacademy/perseus-core";
20
-
21
- export type Props = {
22
- extraKeys: ReadonlyArray<Key>;
23
- cursorContext?: typeof CursorContext[keyof typeof CursorContext];
24
- showDismiss?: boolean;
25
-
26
- multiplicationDot?: boolean;
27
- divisionKey?: boolean;
28
-
29
- trigonometry?: boolean;
30
- preAlgebra?: boolean;
31
- logarithms?: boolean;
32
- basicRelations?: boolean;
33
- advancedRelations?: boolean;
34
-
35
- onClickKey: ClickKeyCallback;
36
- sendEvent: SendEventFn;
37
- };
38
-
39
- const defaultProps = {
40
- extraKeys: [],
41
- };
42
-
43
- function allPages(props: Props): ReadonlyArray<TabbarItemType> {
44
- const pages: Array<TabbarItemType> = ["Numbers"];
45
-
46
- if (
47
- // OperatorsButtonSets
48
- props.preAlgebra ||
49
- props.logarithms ||
50
- props.basicRelations ||
51
- props.advancedRelations
52
- ) {
53
- pages.push("Operators");
54
- }
55
-
56
- if (props.trigonometry) {
57
- pages.push("Geometry");
58
- }
59
-
60
- if (props.extraKeys?.length) {
61
- pages.push("Extras");
62
- }
63
-
64
- return pages;
65
- }
66
-
67
- // The main (v2) Keypad. Use this component to present an accessible, onscreen
68
- // keypad to learners for entering math expressions.
69
- export default function Keypad(props: Props) {
70
- const [selectedPage, setSelectedPage] =
71
- React.useState<TabbarItemType>("Numbers");
72
- const [isMounted, setIsMounted] = React.useState<boolean>(false);
73
-
74
- const availablePages = allPages(props);
75
-
76
- const {
77
- onClickKey,
78
- cursorContext,
79
- extraKeys,
80
- multiplicationDot,
81
- divisionKey,
82
- preAlgebra,
83
- logarithms,
84
- basicRelations,
85
- advancedRelations,
86
- showDismiss,
87
- sendEvent,
88
- } = props;
89
-
90
- useEffect(() => {
91
- if (!isMounted) {
92
- sendEvent({
93
- type: "math-input:keypad-opened",
94
- payload: {virtualKeypadVersion: "MATH_INPUT_KEYPAD_V2"},
95
- });
96
- setIsMounted(true);
97
- }
98
- return () => {
99
- if (isMounted) {
100
- sendEvent({
101
- type: "math-input:keypad-closed",
102
- payload: {virtualKeypadVersion: "MATH_INPUT_KEYPAD_V2"},
103
- });
104
- setIsMounted(false);
105
- }
106
- };
107
- }, [sendEvent, isMounted]);
108
-
109
- return (
110
- <View>
111
- <Tabbar
112
- items={availablePages}
113
- selectedItem={selectedPage}
114
- onSelectItem={(tabbarItem: TabbarItemType) => {
115
- setSelectedPage(tabbarItem);
116
- }}
117
- style={styles.tabbar}
118
- onClickClose={
119
- showDismiss ? () => onClickKey("DISMISS") : undefined
120
- }
121
- />
122
-
123
- <View
124
- style={styles.grid}
125
- role="grid"
126
- tabIndex={0}
127
- aria-label="Keypad"
128
- >
129
- {selectedPage === "Numbers" && (
130
- <NumbersPage onClickKey={onClickKey} />
131
- )}
132
- {selectedPage === "Extras" && (
133
- <ExtrasPage onClickKey={onClickKey} extraKeys={extraKeys} />
134
- )}
135
- {selectedPage === "Operators" && (
136
- <OperatorsPage
137
- onClickKey={onClickKey}
138
- preAlgebra={preAlgebra}
139
- logarithms={logarithms}
140
- basicRelations={basicRelations}
141
- advancedRelations={advancedRelations}
142
- />
143
- )}
144
- {selectedPage === "Geometry" && (
145
- <GeometryPage onClickKey={onClickKey} />
146
- )}
147
- <SharedKeys
148
- onClickKey={onClickKey}
149
- cursorContext={cursorContext}
150
- multiplicationDot={multiplicationDot}
151
- divisionKey={divisionKey}
152
- selectedPage={selectedPage}
153
- />
154
- </View>
155
- </View>
156
- );
157
- }
158
-
159
- Keypad.defaultProps = defaultProps;
160
-
161
- const styles = StyleSheet.create({
162
- tabbar: {
163
- background: Color.white,
164
- },
165
- grid: {
166
- display: "grid",
167
- gridTemplateColumns: "repeat(6, 1fr)",
168
- gridTemplateRows: "repeat(4, 1fr)",
169
- backgroundColor: "#DBDCDD",
170
- maxHeight: 200,
171
- maxWidth: 300,
172
- },
173
- });
1
+ export {default} from "./keypad";
2
+ export {default as MobileKeypad} from "./mobile-keypad";
@@ -3,7 +3,7 @@ import {INITIAL_VIEWPORTS} from "@storybook/addon-viewport";
3
3
  import {ComponentStory} from "@storybook/react";
4
4
  import * as React from "react";
5
5
 
6
- import Keypad, {Props as KeypadProps} from "./index";
6
+ import Keypad, {Props as KeypadProps} from "./keypad";
7
7
 
8
8
  const opsPage = "Operators Page";
9
9
  const numsPage = "Numbers Page";
@@ -26,6 +26,7 @@ export default {
26
26
  multiplicationDot: false,
27
27
  preAlgebra: false,
28
28
  trigonometry: false,
29
+ sendEvent: () => {},
29
30
  },
30
31
  argTypes: {
31
32
  advancedRelations: {
@@ -0,0 +1,171 @@
1
+ import Color from "@khanacademy/wonder-blocks-color";
2
+ import {View} from "@khanacademy/wonder-blocks-core";
3
+ import {StyleSheet} from "aphrodite";
4
+ import * as React from "react";
5
+ import {useEffect} from "react";
6
+
7
+ import Key from "../../data/keys";
8
+ import {ClickKeyCallback} from "../../types";
9
+ import {CursorContext} from "../input/cursor-contexts";
10
+ import Tabbar from "../tabbar";
11
+
12
+ import ExtrasPage from "./keypad-pages/extras-page";
13
+ import GeometryPage from "./keypad-pages/geometry-page";
14
+ import NumbersPage from "./keypad-pages/numbers-page";
15
+ import OperatorsPage from "./keypad-pages/operators-page";
16
+ import SharedKeys from "./shared-keys";
17
+
18
+ import type {TabbarItemType} from "../tabbar";
19
+ import type {SendEventFn} from "@khanacademy/perseus-core";
20
+
21
+ export type Props = {
22
+ extraKeys: ReadonlyArray<Key>;
23
+ cursorContext?: typeof CursorContext[keyof typeof CursorContext];
24
+ showDismiss?: boolean;
25
+
26
+ multiplicationDot?: boolean;
27
+ divisionKey?: boolean;
28
+
29
+ trigonometry?: boolean;
30
+ preAlgebra?: boolean;
31
+ logarithms?: boolean;
32
+ basicRelations?: boolean;
33
+ advancedRelations?: boolean;
34
+
35
+ onClickKey: ClickKeyCallback;
36
+ sendEvent: SendEventFn;
37
+ };
38
+
39
+ const defaultProps = {
40
+ extraKeys: [],
41
+ };
42
+
43
+ function allPages(props: Props): ReadonlyArray<TabbarItemType> {
44
+ const pages: Array<TabbarItemType> = ["Numbers"];
45
+
46
+ if (
47
+ // OperatorsButtonSets
48
+ props.preAlgebra ||
49
+ props.logarithms ||
50
+ props.basicRelations ||
51
+ props.advancedRelations
52
+ ) {
53
+ pages.push("Operators");
54
+ }
55
+
56
+ if (props.trigonometry) {
57
+ pages.push("Geometry");
58
+ }
59
+
60
+ if (props.extraKeys?.length) {
61
+ pages.push("Extras");
62
+ }
63
+
64
+ return pages;
65
+ }
66
+
67
+ // The main (v2) Keypad. Use this component to present an accessible, onscreen
68
+ // keypad to learners for entering math expressions.
69
+ export default function Keypad(props: Props) {
70
+ const [selectedPage, setSelectedPage] =
71
+ React.useState<TabbarItemType>("Numbers");
72
+ const [isMounted, setIsMounted] = React.useState<boolean>(false);
73
+
74
+ const availablePages = allPages(props);
75
+
76
+ const {
77
+ onClickKey,
78
+ cursorContext,
79
+ extraKeys,
80
+ multiplicationDot,
81
+ divisionKey,
82
+ preAlgebra,
83
+ logarithms,
84
+ basicRelations,
85
+ advancedRelations,
86
+ showDismiss,
87
+ sendEvent,
88
+ } = props;
89
+
90
+ useEffect(() => {
91
+ if (!isMounted) {
92
+ sendEvent({
93
+ type: "math-input:keypad-opened",
94
+ payload: {virtualKeypadVersion: "MATH_INPUT_KEYPAD_V2"},
95
+ });
96
+ setIsMounted(true);
97
+ }
98
+ return () => {
99
+ if (isMounted) {
100
+ sendEvent({
101
+ type: "math-input:keypad-closed",
102
+ payload: {virtualKeypadVersion: "MATH_INPUT_KEYPAD_V2"},
103
+ });
104
+ setIsMounted(false);
105
+ }
106
+ };
107
+ }, [sendEvent, isMounted]);
108
+
109
+ return (
110
+ <View>
111
+ <Tabbar
112
+ items={availablePages}
113
+ selectedItem={selectedPage}
114
+ onSelectItem={(tabbarItem: TabbarItemType) => {
115
+ setSelectedPage(tabbarItem);
116
+ }}
117
+ style={styles.tabbar}
118
+ onClickClose={
119
+ showDismiss ? () => onClickKey("DISMISS") : undefined
120
+ }
121
+ />
122
+
123
+ <View
124
+ style={styles.grid}
125
+ role="grid"
126
+ tabIndex={0}
127
+ aria-label="Keypad"
128
+ >
129
+ {selectedPage === "Numbers" && (
130
+ <NumbersPage onClickKey={onClickKey} />
131
+ )}
132
+ {selectedPage === "Extras" && (
133
+ <ExtrasPage onClickKey={onClickKey} extraKeys={extraKeys} />
134
+ )}
135
+ {selectedPage === "Operators" && (
136
+ <OperatorsPage
137
+ onClickKey={onClickKey}
138
+ preAlgebra={preAlgebra}
139
+ logarithms={logarithms}
140
+ basicRelations={basicRelations}
141
+ advancedRelations={advancedRelations}
142
+ />
143
+ )}
144
+ {selectedPage === "Geometry" && (
145
+ <GeometryPage onClickKey={onClickKey} />
146
+ )}
147
+ <SharedKeys
148
+ onClickKey={onClickKey}
149
+ cursorContext={cursorContext}
150
+ multiplicationDot={multiplicationDot}
151
+ divisionKey={divisionKey}
152
+ selectedPage={selectedPage}
153
+ />
154
+ </View>
155
+ </View>
156
+ );
157
+ }
158
+
159
+ Keypad.defaultProps = defaultProps;
160
+
161
+ const styles = StyleSheet.create({
162
+ tabbar: {
163
+ background: Color.white,
164
+ },
165
+ grid: {
166
+ display: "grid",
167
+ gridTemplateColumns: "repeat(6, 1fr)",
168
+ gridTemplateRows: "repeat(4, 1fr)",
169
+ backgroundColor: "#DBDCDD",
170
+ },
171
+ });
@@ -0,0 +1,165 @@
1
+ import {StyleType} from "@khanacademy/wonder-blocks-core";
2
+ import {StyleSheet} from "aphrodite";
3
+ import * as React from "react";
4
+ import ReactDOM from "react-dom";
5
+
6
+ import Key from "../../data/keys";
7
+ import {View} from "../../fake-react-native-web/index";
8
+ import {Cursor, KeypadConfiguration, KeyHandler, KeypadAPI} from "../../types";
9
+
10
+ import Keypad from "./index";
11
+
12
+ /**
13
+ * This is the v2 equivalent of v1's ProvidedKeypad. It follows the same
14
+ * external API so that it can be hot-swapped with the v1 keypad and
15
+ * is responsible for connecting the keypad with MathInput and the Renderer.
16
+ *
17
+ * Ideally this strategy of attaching methods on the class component for
18
+ * other components to call will be replaced props/callbacks since React
19
+ * doesn't support this type of code anymore (functional components
20
+ * can't have methods attached to them).
21
+ */
22
+
23
+ type Props = {
24
+ onElementMounted?: (arg1: any) => void;
25
+ onDismiss?: () => void;
26
+ style?: StyleType;
27
+ };
28
+
29
+ type State = {
30
+ active: boolean;
31
+ keypadConfig?: KeypadConfiguration;
32
+ keyHandler?: KeyHandler;
33
+ cursor?: Cursor;
34
+ };
35
+
36
+ class MobileKeypad extends React.Component<Props, State> implements KeypadAPI {
37
+ hasMounted = false;
38
+
39
+ state: State = {
40
+ active: false,
41
+ };
42
+
43
+ activate: () => void = () => {
44
+ this.setState({active: true});
45
+ };
46
+
47
+ dismiss: () => void = () => {
48
+ this.setState({active: false}, () => {
49
+ this.props.onDismiss?.();
50
+ });
51
+ };
52
+
53
+ configure: (configuration: KeypadConfiguration, cb: () => void) => void = (
54
+ configuration,
55
+ cb,
56
+ ) => {
57
+ this.setState({keypadConfig: configuration});
58
+
59
+ // TODO(matthewc)[LC-1080]: this was brought in from v1's ProvidedKeypad.
60
+ // We need to investigate whether we still need this.
61
+ // HACK(charlie): In Perseus, triggering a focus causes the keypad to
62
+ // animate into view and re-configure. We'd like to provide the option
63
+ // to re-render the re-configured keypad before animating it into view,
64
+ // to avoid jank in the animation. As such, we support passing a
65
+ // callback into `configureKeypad`. However, implementing this properly
66
+ // would require middleware, etc., so we just hack it on with
67
+ // `setTimeout` for now.
68
+ setTimeout(() => cb && cb());
69
+ };
70
+
71
+ setCursor: (cursor: Cursor) => void = (cursor) => {
72
+ this.setState({cursor});
73
+ };
74
+
75
+ setKeyHandler: (keyHandler: KeyHandler) => void = (keyHandler) => {
76
+ this.setState({keyHandler});
77
+ };
78
+
79
+ getDOMNode: () => ReturnType<typeof ReactDOM.findDOMNode> = () => {
80
+ return ReactDOM.findDOMNode(this);
81
+ };
82
+
83
+ _handleClickKey(key: Key) {
84
+ if (key === "DISMISS") {
85
+ this.dismiss();
86
+ return;
87
+ }
88
+
89
+ const cursor = this.state.keyHandler?.(key);
90
+ this.setState({cursor});
91
+ }
92
+
93
+ render(): React.ReactNode {
94
+ const {active, cursor, keypadConfig} = this.state;
95
+
96
+ const containerStyle = [
97
+ styles.keypadContainer,
98
+ active ? styles.activeKeypadContainer : null,
99
+ ];
100
+
101
+ const isExpression = keypadConfig?.keypadType === "EXPRESSION";
102
+
103
+ return (
104
+ <View
105
+ style={containerStyle}
106
+ ref={(element) => {
107
+ if (!this.hasMounted && element) {
108
+ // TODO(matthewc)[LC-1081]: clean up this weird
109
+ // object and type the onElementMounted callback
110
+ // Append the dispatch methods that we want to expose
111
+ // externally to the returned React element.
112
+ const elementWithDispatchMethods = {
113
+ ...element,
114
+ activate: this.activate,
115
+ dismiss: this.dismiss,
116
+ configure: this.configure,
117
+ setCursor: this.setCursor,
118
+ setKeyHandler: this.setKeyHandler,
119
+ getDOMNode: this.getDOMNode,
120
+ } as const;
121
+
122
+ this.hasMounted = true;
123
+ this.props.onElementMounted?.(
124
+ elementWithDispatchMethods,
125
+ );
126
+ }
127
+ }}
128
+ >
129
+ <Keypad
130
+ // TODO(jeremy)
131
+ sendEvent={async () => {}}
132
+ extraKeys={keypadConfig?.extraKeys}
133
+ onClickKey={(key) => this._handleClickKey(key)}
134
+ cursorContext={cursor?.context}
135
+ multiplicationDot={isExpression}
136
+ divisionKey={isExpression}
137
+ trigonometry={isExpression}
138
+ preAlgebra={isExpression}
139
+ logarithms={isExpression}
140
+ basicRelations={isExpression}
141
+ advancedRelations={isExpression}
142
+ showDismiss
143
+ />
144
+ </View>
145
+ );
146
+ }
147
+ }
148
+
149
+ const styles = StyleSheet.create({
150
+ keypadContainer: {
151
+ bottom: 0,
152
+ left: 0,
153
+ right: 0,
154
+ position: "fixed",
155
+ transition: `200ms ease-out`,
156
+ transitionProperty: "transform",
157
+ transform: "translate3d(0, 100%, 0)",
158
+ },
159
+
160
+ activeKeypadContainer: {
161
+ transform: "translate3d(0, 0, 0)",
162
+ },
163
+ });
164
+
165
+ export default MobileKeypad;
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  import Keys from "../../data/key-configs";
4
4
  import {ClickKeyCallback} from "../../types";
5
5
  import {CursorContext} from "../input/cursor-contexts";
6
- import {TabbarItemType} from "../tabbar/types";
6
+ import {TabbarItemType} from "../tabbar";
7
7
 
8
8
  import {KeypadButton} from "./keypad-button";
9
9
 
@@ -0,0 +1 @@
1
+ export {default} from "./provided-keypad";
@@ -12,7 +12,12 @@ import {
12
12
  } from "./store/actions";
13
13
  import {createStore} from "./store/index";
14
14
 
15
- import type {Cursor, KeypadConfiguration, KeyHandler} from "../../types";
15
+ import type {
16
+ Cursor,
17
+ KeypadConfiguration,
18
+ KeyHandler,
19
+ KeypadAPI,
20
+ } from "../../types";
16
21
  import type {StyleType} from "@khanacademy/wonder-blocks-core";
17
22
 
18
23
  type Props = {
@@ -21,7 +26,7 @@ type Props = {
21
26
  style?: StyleType;
22
27
  };
23
28
 
24
- class ProvidedKeypad extends React.Component<Props> {
29
+ class ProvidedKeypad extends React.Component<Props> implements KeypadAPI {
25
30
  store: any;
26
31
 
27
32
  constructor(props) {
@@ -14,13 +14,14 @@ import {
14
14
  innerBorderWidthPx,
15
15
  offBlack16,
16
16
  } from "../common-style";
17
- import Tabbar from "../tabbar/tabbar";
18
- import {TabbarItemType} from "../tabbar/types";
17
+ import Tabbar from "../tabbar";
19
18
 
20
19
  import Keypad from "./keypad";
21
20
  import {State as ReduxState} from "./store/types";
22
21
  import Styles from "./styles";
23
22
 
23
+ import type {TabbarItemType} from "../tabbar";
24
+
24
25
  const {column, row, fullWidth} = Styles;
25
26
 
26
27
  interface ReduxProps {
@@ -5,7 +5,6 @@
5
5
  import PropTypes from "prop-types";
6
6
 
7
7
  // NOTE(jared): This is no longer guaranteed to be React element
8
- // NOTE(matthewc): only seems to be used in Perseus
9
8
  export const keypadElementPropType = PropTypes.shape({
10
9
  activate: PropTypes.func.isRequired,
11
10
  dismiss: PropTypes.func.isRequired,