@khanacademy/math-input 17.0.4 → 17.0.6
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/dist/components/input/math-wrapper.d.ts +2 -2
- package/dist/components/input/mathquill-types.d.ts +49 -6
- package/dist/es/index.js +8 -6
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/.eslintrc.js +0 -18
- package/CHANGELOG.md +0 -660
- package/less/main.less +0 -2
- package/less/overrides.less +0 -122
- package/src/components/__tests__/integration.test.tsx +0 -300
- package/src/components/aphrodite-css-transition-group/index.tsx +0 -78
- package/src/components/aphrodite-css-transition-group/transition-child.tsx +0 -192
- package/src/components/aphrodite-css-transition-group/types.ts +0 -20
- package/src/components/aphrodite-css-transition-group/util.ts +0 -97
- package/src/components/input/__tests__/context-tracking.test.ts +0 -176
- package/src/components/input/__tests__/mathquill-helpers.test.ts +0 -105
- package/src/components/input/__tests__/mathquill.test.ts +0 -747
- package/src/components/input/__tests__/test-math-wrapper.ts +0 -29
- package/src/components/input/cursor-contexts.ts +0 -37
- package/src/components/input/cursor-handle.tsx +0 -137
- package/src/components/input/cursor-styles.ts +0 -10
- package/src/components/input/drag-listener.ts +0 -79
- package/src/components/input/math-input.tsx +0 -1036
- package/src/components/input/math-wrapper.ts +0 -189
- package/src/components/input/mathquill-helpers.ts +0 -262
- package/src/components/input/mathquill-instance.ts +0 -106
- package/src/components/input/mathquill-types.ts +0 -32
- package/src/components/input/scroll-into-view.ts +0 -65
- package/src/components/key-handlers/__tests__/handle-jump-out.test.ts +0 -94
- package/src/components/key-handlers/handle-arrow.ts +0 -70
- package/src/components/key-handlers/handle-backspace.ts +0 -277
- package/src/components/key-handlers/handle-exponent.ts +0 -53
- package/src/components/key-handlers/handle-jump-out.ts +0 -107
- package/src/components/key-handlers/key-translator.ts +0 -222
- package/src/components/keypad/__tests__/__snapshots__/keypad.test.tsx.snap +0 -1913
- package/src/components/keypad/__tests__/__snapshots__/mobile-keypad.test.tsx.snap +0 -600
- package/src/components/keypad/__tests__/keypad-button.test.tsx +0 -84
- package/src/components/keypad/__tests__/keypad-v2-mathquill.test.tsx +0 -304
- package/src/components/keypad/__tests__/keypad-v2.cypress.ts +0 -16
- package/src/components/keypad/__tests__/keypad.test.tsx +0 -321
- package/src/components/keypad/__tests__/mobile-keypad.test.tsx +0 -115
- package/src/components/keypad/__tests__/test-data-tabs.ts +0 -21
- package/src/components/keypad/button-assets.tsx +0 -1880
- package/src/components/keypad/index.tsx +0 -2
- package/src/components/keypad/keypad-button.stories.tsx +0 -81
- package/src/components/keypad/keypad-button.tsx +0 -124
- package/src/components/keypad/keypad-mathquill.stories.tsx +0 -109
- package/src/components/keypad/keypad-pages/extras-page.tsx +0 -35
- package/src/components/keypad/keypad-pages/fractions-page.tsx +0 -125
- package/src/components/keypad/keypad-pages/geometry-page.tsx +0 -34
- package/src/components/keypad/keypad-pages/keypad-pages.stories.tsx +0 -37
- package/src/components/keypad/keypad-pages/numbers-page.tsx +0 -94
- package/src/components/keypad/keypad-pages/operators-page.tsx +0 -117
- package/src/components/keypad/keypad.tsx +0 -233
- package/src/components/keypad/mobile-keypad-internals.tsx +0 -240
- package/src/components/keypad/mobile-keypad.tsx +0 -24
- package/src/components/keypad/navigation-button.tsx +0 -127
- package/src/components/keypad/navigation-pad.stories.tsx +0 -26
- package/src/components/keypad/navigation-pad.tsx +0 -67
- package/src/components/keypad/shared-keys.tsx +0 -109
- package/src/components/keypad/utils.ts +0 -34
- package/src/components/keypad-context.tsx +0 -70
- package/src/components/prop-types.ts +0 -16
- package/src/components/tabbar/__tests__/tabbar.test.tsx +0 -105
- package/src/components/tabbar/icons.tsx +0 -122
- package/src/components/tabbar/index.ts +0 -1
- package/src/components/tabbar/item.tsx +0 -146
- package/src/components/tabbar/tabbar.stories.tsx +0 -83
- package/src/components/tabbar/tabbar.tsx +0 -65
- package/src/data/key-configs.ts +0 -770
- package/src/data/keys.ts +0 -123
- package/src/enums.ts +0 -27
- package/src/fake-react-native-web/index.ts +0 -11
- package/src/fake-react-native-web/text.tsx +0 -55
- package/src/fake-react-native-web/view.tsx +0 -91
- package/src/full-keypad.stories.tsx +0 -142
- package/src/full-mobile-input.stories.tsx +0 -115
- package/src/index.ts +0 -52
- package/src/types.ts +0 -70
- package/src/utils.test.ts +0 -33
- package/src/utils.ts +0 -61
- package/src/version.ts +0 -10
- package/tsconfig-build.json +0 -11
- package/tsconfig-build.tsbuildinfo +0 -1
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import Clickable from "@khanacademy/wonder-blocks-clickable";
|
|
2
|
-
import Color from "@khanacademy/wonder-blocks-color";
|
|
3
|
-
import {View} from "@khanacademy/wonder-blocks-core";
|
|
4
|
-
import {StyleSheet} from "aphrodite";
|
|
5
|
-
import * as React from "react";
|
|
6
|
-
|
|
7
|
-
import ButtonAsset from "./button-assets";
|
|
8
|
-
|
|
9
|
-
import type Key from "../../data/keys";
|
|
10
|
-
import type {KeyConfig, ClickKeyCallback} from "../../types";
|
|
11
|
-
|
|
12
|
-
export type KeypadButtonProps = {
|
|
13
|
-
// 0 indexed [x, y] position in keypad CSS grid
|
|
14
|
-
coord: readonly [number, number];
|
|
15
|
-
keyConfig: KeyConfig;
|
|
16
|
-
onClickKey: ClickKeyCallback;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function getStyles(key: Key) {
|
|
20
|
-
switch (key) {
|
|
21
|
-
case "UP":
|
|
22
|
-
return styles.up;
|
|
23
|
-
case "RIGHT":
|
|
24
|
-
return styles.right;
|
|
25
|
-
case "DOWN":
|
|
26
|
-
return styles.down;
|
|
27
|
-
case "LEFT":
|
|
28
|
-
return styles.left;
|
|
29
|
-
default:
|
|
30
|
-
throw new Error(`Invalid key: ${key}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default function NavigationButton({
|
|
35
|
-
coord,
|
|
36
|
-
keyConfig,
|
|
37
|
-
onClickKey,
|
|
38
|
-
}: KeypadButtonProps) {
|
|
39
|
-
const key = keyConfig.id;
|
|
40
|
-
const directionalStyles = getStyles(key);
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<View
|
|
44
|
-
style={{
|
|
45
|
-
gridColumn: coord[0] + 1,
|
|
46
|
-
gridRow: coord[1] + 1,
|
|
47
|
-
}}
|
|
48
|
-
>
|
|
49
|
-
<Clickable
|
|
50
|
-
onClick={(e) => onClickKey(keyConfig.id, e)}
|
|
51
|
-
style={styles.clickable}
|
|
52
|
-
aria-label={keyConfig.ariaLabel}
|
|
53
|
-
>
|
|
54
|
-
{({hovered, focused, pressed}) => (
|
|
55
|
-
<View style={styles.outerBoxBase}>
|
|
56
|
-
<View
|
|
57
|
-
style={[
|
|
58
|
-
styles.base,
|
|
59
|
-
directionalStyles,
|
|
60
|
-
hovered && styles.hovered,
|
|
61
|
-
focused && styles.focused,
|
|
62
|
-
pressed && styles.pressed,
|
|
63
|
-
]}
|
|
64
|
-
>
|
|
65
|
-
<ButtonAsset id={keyConfig.id} />
|
|
66
|
-
</View>
|
|
67
|
-
</View>
|
|
68
|
-
)}
|
|
69
|
-
</Clickable>
|
|
70
|
-
</View>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const borderRadiusPx = 4;
|
|
75
|
-
|
|
76
|
-
const styles = StyleSheet.create({
|
|
77
|
-
clickable: {
|
|
78
|
-
width: "100%",
|
|
79
|
-
height: "100%",
|
|
80
|
-
|
|
81
|
-
":focus": {
|
|
82
|
-
outline: `none`,
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
outerBoxBase: {
|
|
86
|
-
height: "100%",
|
|
87
|
-
width: "100%",
|
|
88
|
-
},
|
|
89
|
-
base: {
|
|
90
|
-
boxShadow: `0px 1px 0px ${Color.offBlack32}`,
|
|
91
|
-
display: "flex",
|
|
92
|
-
justifyContent: "center",
|
|
93
|
-
alignItems: "center",
|
|
94
|
-
background: Color.white,
|
|
95
|
-
borderWidth: 2,
|
|
96
|
-
borderColor: Color.white,
|
|
97
|
-
},
|
|
98
|
-
up: {
|
|
99
|
-
borderTopLeftRadius: borderRadiusPx,
|
|
100
|
-
borderTopRightRadius: borderRadiusPx,
|
|
101
|
-
},
|
|
102
|
-
right: {
|
|
103
|
-
borderTopRightRadius: borderRadiusPx,
|
|
104
|
-
borderBottomRightRadius: borderRadiusPx,
|
|
105
|
-
},
|
|
106
|
-
down: {
|
|
107
|
-
borderBottomLeftRadius: borderRadiusPx,
|
|
108
|
-
borderBottomRightRadius: borderRadiusPx,
|
|
109
|
-
},
|
|
110
|
-
left: {
|
|
111
|
-
borderTopLeftRadius: borderRadiusPx,
|
|
112
|
-
borderBottomLeftRadius: borderRadiusPx,
|
|
113
|
-
},
|
|
114
|
-
hovered: {
|
|
115
|
-
borderColor: Color.blue,
|
|
116
|
-
boxShadow: "none",
|
|
117
|
-
},
|
|
118
|
-
focused: {
|
|
119
|
-
borderColor: Color.blue,
|
|
120
|
-
boxShadow: "none",
|
|
121
|
-
},
|
|
122
|
-
pressed: {
|
|
123
|
-
border: "2px solid #1B50B3",
|
|
124
|
-
background: `linear-gradient(0deg, rgba(24, 101, 242, 0.32), rgba(24, 101, 242, 0.32)), ${Color.white}`,
|
|
125
|
-
boxShadow: "none",
|
|
126
|
-
},
|
|
127
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import {action} from "@storybook/addon-actions";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
|
|
4
|
-
import NavigationPad from "./navigation-pad";
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
title: "math-input/components/MathInput v2 Navigation Pad",
|
|
8
|
-
parameters: {
|
|
9
|
-
backgrounds: {
|
|
10
|
-
default: "light background",
|
|
11
|
-
values: [
|
|
12
|
-
// We want a slightly darker default bg so that we can
|
|
13
|
-
// see the top of the keypad when it is open
|
|
14
|
-
{name: "light background", value: "lightgrey", default: true},
|
|
15
|
-
],
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export function basic() {
|
|
21
|
-
return (
|
|
22
|
-
<div style={{padding: 50}}>
|
|
23
|
-
<NavigationPad onClickKey={action("onClickKey")} />
|
|
24
|
-
</div>
|
|
25
|
-
);
|
|
26
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
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
|
-
|
|
6
|
-
import Keys from "../../data/key-configs";
|
|
7
|
-
|
|
8
|
-
import NavigationButton from "./navigation-button";
|
|
9
|
-
|
|
10
|
-
import type {ClickKeyCallback} from "../../types";
|
|
11
|
-
|
|
12
|
-
export type Props = {
|
|
13
|
-
onClickKey: ClickKeyCallback;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default function NavigationPad(props: Props) {
|
|
17
|
-
const {onClickKey} = props;
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<View style={styles.container}>
|
|
21
|
-
<View style={styles.grid}>
|
|
22
|
-
<NavigationButton
|
|
23
|
-
keyConfig={Keys.UP}
|
|
24
|
-
onClickKey={onClickKey}
|
|
25
|
-
coord={[1, 0]}
|
|
26
|
-
/>
|
|
27
|
-
<NavigationButton
|
|
28
|
-
keyConfig={Keys.RIGHT}
|
|
29
|
-
onClickKey={onClickKey}
|
|
30
|
-
coord={[2, 1]}
|
|
31
|
-
/>
|
|
32
|
-
<NavigationButton
|
|
33
|
-
keyConfig={Keys.DOWN}
|
|
34
|
-
onClickKey={onClickKey}
|
|
35
|
-
coord={[1, 2]}
|
|
36
|
-
/>
|
|
37
|
-
<NavigationButton
|
|
38
|
-
keyConfig={Keys.LEFT}
|
|
39
|
-
onClickKey={onClickKey}
|
|
40
|
-
coord={[0, 1]}
|
|
41
|
-
/>
|
|
42
|
-
<View style={styles.spacer} />
|
|
43
|
-
</View>
|
|
44
|
-
</View>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const styles = StyleSheet.create({
|
|
49
|
-
container: {
|
|
50
|
-
display: "flex",
|
|
51
|
-
alignItems: "center",
|
|
52
|
-
justifyContent: "center",
|
|
53
|
-
padding: "0 1.5rem",
|
|
54
|
-
},
|
|
55
|
-
grid: {
|
|
56
|
-
width: 140,
|
|
57
|
-
height: 140,
|
|
58
|
-
display: "grid",
|
|
59
|
-
gridTemplateColumns: "repeat(3, 1fr)",
|
|
60
|
-
gridTemplateRows: "repeat(3, 1fr)",
|
|
61
|
-
},
|
|
62
|
-
spacer: {
|
|
63
|
-
gridColumn: 2,
|
|
64
|
-
gridRow: 2,
|
|
65
|
-
background: Color.white,
|
|
66
|
-
},
|
|
67
|
-
});
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
import Keys from "../../data/key-configs";
|
|
4
|
-
import {convertDotToTimesByLocale} from "../../utils";
|
|
5
|
-
|
|
6
|
-
import {KeypadButton} from "./keypad-button";
|
|
7
|
-
import {getCursorContextConfig} from "./utils";
|
|
8
|
-
|
|
9
|
-
import type {ClickKeyCallback, KeypadPageType} from "../../types";
|
|
10
|
-
import type {CursorContext} from "../input/cursor-contexts";
|
|
11
|
-
|
|
12
|
-
type Props = {
|
|
13
|
-
onClickKey: ClickKeyCallback;
|
|
14
|
-
selectedPage: KeypadPageType;
|
|
15
|
-
cursorContext?: typeof CursorContext[keyof typeof CursorContext];
|
|
16
|
-
convertDotToTimes?: boolean;
|
|
17
|
-
divisionKey?: boolean;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default function SharedKeys(props: Props) {
|
|
21
|
-
const {
|
|
22
|
-
onClickKey,
|
|
23
|
-
cursorContext,
|
|
24
|
-
divisionKey,
|
|
25
|
-
convertDotToTimes,
|
|
26
|
-
selectedPage,
|
|
27
|
-
} = props;
|
|
28
|
-
|
|
29
|
-
const cursorKeyConfig = getCursorContextConfig(cursorContext);
|
|
30
|
-
|
|
31
|
-
// Fraction position depends on the page
|
|
32
|
-
const fractionCoord: readonly [number, number] =
|
|
33
|
-
selectedPage === "Numbers" || selectedPage === "Operators"
|
|
34
|
-
? [3, 1]
|
|
35
|
-
: [3, 0];
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<>
|
|
39
|
-
<KeypadButton
|
|
40
|
-
keyConfig={Keys.FRAC}
|
|
41
|
-
onClickKey={onClickKey}
|
|
42
|
-
coord={fractionCoord}
|
|
43
|
-
secondary
|
|
44
|
-
/>
|
|
45
|
-
<KeypadButton
|
|
46
|
-
keyConfig={Keys.PLUS}
|
|
47
|
-
onClickKey={onClickKey}
|
|
48
|
-
coord={[4, 0]}
|
|
49
|
-
secondary
|
|
50
|
-
/>
|
|
51
|
-
<KeypadButton
|
|
52
|
-
keyConfig={Keys.MINUS}
|
|
53
|
-
onClickKey={onClickKey}
|
|
54
|
-
coord={[5, 0]}
|
|
55
|
-
secondary
|
|
56
|
-
/>
|
|
57
|
-
|
|
58
|
-
{/* Row 2 */}
|
|
59
|
-
<KeypadButton
|
|
60
|
-
keyConfig={
|
|
61
|
-
convertDotToTimesByLocale(!!convertDotToTimes)
|
|
62
|
-
? Keys.TIMES
|
|
63
|
-
: Keys.CDOT
|
|
64
|
-
}
|
|
65
|
-
onClickKey={onClickKey}
|
|
66
|
-
coord={[4, 1]}
|
|
67
|
-
secondary
|
|
68
|
-
/>
|
|
69
|
-
{divisionKey && (
|
|
70
|
-
<KeypadButton
|
|
71
|
-
keyConfig={Keys.DIVIDE}
|
|
72
|
-
onClickKey={onClickKey}
|
|
73
|
-
coord={[5, 1]}
|
|
74
|
-
secondary
|
|
75
|
-
/>
|
|
76
|
-
)}
|
|
77
|
-
|
|
78
|
-
{/* Row 3 */}
|
|
79
|
-
<KeypadButton
|
|
80
|
-
keyConfig={Keys.LEFT_PAREN}
|
|
81
|
-
onClickKey={onClickKey}
|
|
82
|
-
coord={[4, 2]}
|
|
83
|
-
secondary
|
|
84
|
-
/>
|
|
85
|
-
<KeypadButton
|
|
86
|
-
keyConfig={Keys.RIGHT_PAREN}
|
|
87
|
-
onClickKey={onClickKey}
|
|
88
|
-
coord={[5, 2]}
|
|
89
|
-
secondary
|
|
90
|
-
/>
|
|
91
|
-
|
|
92
|
-
{/* Row 4 */}
|
|
93
|
-
{cursorKeyConfig && (
|
|
94
|
-
<KeypadButton
|
|
95
|
-
keyConfig={cursorKeyConfig}
|
|
96
|
-
onClickKey={onClickKey}
|
|
97
|
-
coord={[4, 3]}
|
|
98
|
-
secondary
|
|
99
|
-
/>
|
|
100
|
-
)}
|
|
101
|
-
<KeypadButton
|
|
102
|
-
keyConfig={Keys.BACKSPACE}
|
|
103
|
-
onClickKey={onClickKey}
|
|
104
|
-
coord={[5, 3]}
|
|
105
|
-
action
|
|
106
|
-
/>
|
|
107
|
-
</>
|
|
108
|
-
);
|
|
109
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import Keys from "../../data/key-configs";
|
|
2
|
-
import {CursorContext} from "../input/cursor-contexts";
|
|
3
|
-
|
|
4
|
-
// This is just a magic number, I just played around with it
|
|
5
|
-
// until the transition from expanded -> regular -> expanded felt natural
|
|
6
|
-
export const expandedViewThreshold = 500;
|
|
7
|
-
|
|
8
|
-
// This is a helper function that returns the correct context for the cursor
|
|
9
|
-
// based on the cursorContext prop. It is used in the keypad to determine
|
|
10
|
-
// which key to render as the "jump out" key.
|
|
11
|
-
export function getCursorContextConfig(
|
|
12
|
-
cursorContext?: typeof CursorContext[keyof typeof CursorContext],
|
|
13
|
-
) {
|
|
14
|
-
if (!cursorContext) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
switch (cursorContext) {
|
|
19
|
-
case CursorContext.NONE:
|
|
20
|
-
return null;
|
|
21
|
-
case CursorContext.IN_PARENS:
|
|
22
|
-
return Keys.JUMP_OUT_PARENTHESES;
|
|
23
|
-
case CursorContext.IN_SUPER_SCRIPT:
|
|
24
|
-
return Keys.JUMP_OUT_EXPONENT;
|
|
25
|
-
case CursorContext.IN_SUB_SCRIPT:
|
|
26
|
-
return Keys.JUMP_OUT_BASE;
|
|
27
|
-
case CursorContext.IN_NUMERATOR:
|
|
28
|
-
return Keys.JUMP_OUT_NUMERATOR;
|
|
29
|
-
case CursorContext.IN_DENOMINATOR:
|
|
30
|
-
return Keys.JUMP_OUT_DENOMINATOR;
|
|
31
|
-
case CursorContext.BEFORE_FRACTION:
|
|
32
|
-
return Keys.JUMP_INTO_NUMERATOR;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* KeypadContext provides a way to the Keypad and Perseus Renderers to
|
|
3
|
-
* communicate.
|
|
4
|
-
*
|
|
5
|
-
* The StatefulKeypadContextProvider wraps the application
|
|
6
|
-
* while KeypadContext.Consumer wraps things that need this state:
|
|
7
|
-
* - mobile keypad usages
|
|
8
|
-
* - Perseus Renderers (Server/Item/Article)
|
|
9
|
-
*/
|
|
10
|
-
import * as React from "react";
|
|
11
|
-
import {useState, useMemo} from "react";
|
|
12
|
-
|
|
13
|
-
import type {KeypadAPI, KeypadContextType} from "../types";
|
|
14
|
-
import type {KeypadContextRendererInterface} from "@khanacademy/perseus-core";
|
|
15
|
-
|
|
16
|
-
// @ts-expect-error - TS2322 - Type 'Context<{ setKeypadElement: (keypadElement: HTMLElement | null | undefined) => void; keypadElement: null; setRenderer: (renderer: RendererInterface | null | undefined) => void; renderer: null; setScrollableElement: (scrollableElement: HTMLElement | ... 1 more ... | undefined) => void; scrollableElement: null; }>' is not assignable to type 'Context<KeypadContext>'.
|
|
17
|
-
export const KeypadContext: React.Context<KeypadContextType> =
|
|
18
|
-
React.createContext({
|
|
19
|
-
setKeypadActive: (keypadActive) => {},
|
|
20
|
-
keypadActive: false,
|
|
21
|
-
setKeypadElement: (keypadElement) => {},
|
|
22
|
-
keypadElement: null,
|
|
23
|
-
setRenderer: (renderer) => {},
|
|
24
|
-
renderer: null,
|
|
25
|
-
setScrollableElement: (scrollableElement) => {},
|
|
26
|
-
scrollableElement: null,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
type Props = React.PropsWithChildren<unknown>;
|
|
30
|
-
|
|
31
|
-
export function StatefulKeypadContextProvider(props: Props) {
|
|
32
|
-
// whether or not to display the keypad
|
|
33
|
-
const [keypadActive, setKeypadActive] = useState<boolean>(false);
|
|
34
|
-
// used to communicate between the keypad and the Renderer
|
|
35
|
-
const [keypadElement, setKeypadElement] = useState<KeypadAPI | null>();
|
|
36
|
-
// this is a KeypadContextRendererInterface from Perseus
|
|
37
|
-
const [renderer, setRenderer] =
|
|
38
|
-
useState<KeypadContextRendererInterface | null>();
|
|
39
|
-
const [scrollableElement, setScrollableElement] =
|
|
40
|
-
useState<HTMLElement | null>();
|
|
41
|
-
|
|
42
|
-
const memoizedValue = useMemo(
|
|
43
|
-
() => ({
|
|
44
|
-
keypadActive,
|
|
45
|
-
setKeypadActive,
|
|
46
|
-
keypadElement,
|
|
47
|
-
setKeypadElement,
|
|
48
|
-
renderer,
|
|
49
|
-
setRenderer,
|
|
50
|
-
scrollableElement,
|
|
51
|
-
setScrollableElement,
|
|
52
|
-
}),
|
|
53
|
-
[
|
|
54
|
-
keypadActive,
|
|
55
|
-
setKeypadActive,
|
|
56
|
-
keypadElement,
|
|
57
|
-
setKeypadElement,
|
|
58
|
-
renderer,
|
|
59
|
-
setRenderer,
|
|
60
|
-
scrollableElement,
|
|
61
|
-
setScrollableElement,
|
|
62
|
-
],
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<KeypadContext.Provider value={memoizedValue}>
|
|
67
|
-
{props.children}
|
|
68
|
-
</KeypadContext.Provider>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React PropTypes that may be shared between components.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import PropTypes from "prop-types";
|
|
6
|
-
|
|
7
|
-
// NOTE(jared): This is no longer guaranteed to be React element
|
|
8
|
-
// @deprecated Use `KeypadAPI` Typescript interface instead.
|
|
9
|
-
export const keypadElementPropType = PropTypes.shape({
|
|
10
|
-
activate: PropTypes.func.isRequired,
|
|
11
|
-
dismiss: PropTypes.func.isRequired,
|
|
12
|
-
configure: PropTypes.func.isRequired,
|
|
13
|
-
setCursor: PropTypes.func.isRequired,
|
|
14
|
-
setKeyHandler: PropTypes.func.isRequired,
|
|
15
|
-
getDOMNode: PropTypes.func.isRequired,
|
|
16
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import {render, screen} from "@testing-library/react";
|
|
2
|
-
import userEvent from "@testing-library/user-event";
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import "@testing-library/jest-dom";
|
|
5
|
-
|
|
6
|
-
import Tabbar from "../tabbar";
|
|
7
|
-
|
|
8
|
-
describe("<Tabbar />", () => {
|
|
9
|
-
it("renders one tab", () => {
|
|
10
|
-
// Arrange
|
|
11
|
-
render(
|
|
12
|
-
<Tabbar
|
|
13
|
-
items={["Numbers"]}
|
|
14
|
-
selectedItem={"Numbers"}
|
|
15
|
-
onSelectItem={() => {}}
|
|
16
|
-
/>,
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
// Assert
|
|
20
|
-
expect(screen.getByRole("tab", {name: "Numbers"})).toBeInTheDocument();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("renders many tabs", () => {
|
|
24
|
-
// Arrange
|
|
25
|
-
render(
|
|
26
|
-
<Tabbar
|
|
27
|
-
items={["Numbers", "Extras", "Geometry", "Operators"]}
|
|
28
|
-
selectedItem={"Numbers"}
|
|
29
|
-
onSelectItem={() => {}}
|
|
30
|
-
/>,
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
// Assert
|
|
34
|
-
expect(screen.getByRole("tab", {name: "Numbers"})).toBeInTheDocument();
|
|
35
|
-
expect(screen.getByRole("tab", {name: "Extras"})).toBeInTheDocument();
|
|
36
|
-
expect(screen.getByRole("tab", {name: "Geometry"})).toBeInTheDocument();
|
|
37
|
-
expect(
|
|
38
|
-
screen.getByRole("tab", {name: "Operators"}),
|
|
39
|
-
).toBeInTheDocument();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("handles callback", () => {
|
|
43
|
-
// Arrange
|
|
44
|
-
const mockSelectCallback = jest.fn();
|
|
45
|
-
render(
|
|
46
|
-
<Tabbar
|
|
47
|
-
items={["Numbers", "Geometry"]}
|
|
48
|
-
selectedItem={"Numbers"}
|
|
49
|
-
onSelectItem={mockSelectCallback}
|
|
50
|
-
/>,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
// Assert
|
|
54
|
-
userEvent.click(screen.getByRole("tab", {name: "Geometry"}));
|
|
55
|
-
expect(mockSelectCallback).toHaveBeenCalledWith("Geometry");
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("shows dismiss button with a onClickClose callback", () => {
|
|
59
|
-
// Arrange
|
|
60
|
-
render(
|
|
61
|
-
<Tabbar
|
|
62
|
-
items={["Numbers"]}
|
|
63
|
-
selectedItem={"Numbers"}
|
|
64
|
-
onSelectItem={() => {}}
|
|
65
|
-
onClickClose={() => {}}
|
|
66
|
-
/>,
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
// Assert
|
|
70
|
-
expect(screen.getByRole("tab", {name: "Dismiss"})).toBeInTheDocument();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it("does not show dismiss button without onClickClose callback", () => {
|
|
74
|
-
// Arrange
|
|
75
|
-
render(
|
|
76
|
-
<Tabbar
|
|
77
|
-
items={["Numbers"]}
|
|
78
|
-
selectedItem={"Numbers"}
|
|
79
|
-
onSelectItem={() => {}}
|
|
80
|
-
/>,
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
// Assert
|
|
84
|
-
expect(
|
|
85
|
-
screen.queryByRole("tab", {name: "Dismiss"}),
|
|
86
|
-
).not.toBeInTheDocument();
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("handles onClickClose callback", () => {
|
|
90
|
-
// Arrange
|
|
91
|
-
const mockClickCloseCallback = jest.fn();
|
|
92
|
-
render(
|
|
93
|
-
<Tabbar
|
|
94
|
-
items={["Numbers", "Geometry"]}
|
|
95
|
-
selectedItem={"Numbers"}
|
|
96
|
-
onSelectItem={() => {}}
|
|
97
|
-
onClickClose={mockClickCloseCallback}
|
|
98
|
-
/>,
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
// Assert
|
|
102
|
-
userEvent.click(screen.getByRole("tab", {name: "Dismiss"}));
|
|
103
|
-
expect(mockClickCloseCallback).toHaveBeenCalled();
|
|
104
|
-
});
|
|
105
|
-
});
|