@khanacademy/math-input 17.0.4 → 17.0.5

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 (82) hide show
  1. package/dist/es/index.js +1 -1
  2. package/dist/index.js +1 -1
  3. package/package.json +5 -2
  4. package/.eslintrc.js +0 -18
  5. package/CHANGELOG.md +0 -660
  6. package/less/main.less +0 -2
  7. package/less/overrides.less +0 -122
  8. package/src/components/__tests__/integration.test.tsx +0 -300
  9. package/src/components/aphrodite-css-transition-group/index.tsx +0 -78
  10. package/src/components/aphrodite-css-transition-group/transition-child.tsx +0 -192
  11. package/src/components/aphrodite-css-transition-group/types.ts +0 -20
  12. package/src/components/aphrodite-css-transition-group/util.ts +0 -97
  13. package/src/components/input/__tests__/context-tracking.test.ts +0 -176
  14. package/src/components/input/__tests__/mathquill-helpers.test.ts +0 -105
  15. package/src/components/input/__tests__/mathquill.test.ts +0 -747
  16. package/src/components/input/__tests__/test-math-wrapper.ts +0 -29
  17. package/src/components/input/cursor-contexts.ts +0 -37
  18. package/src/components/input/cursor-handle.tsx +0 -137
  19. package/src/components/input/cursor-styles.ts +0 -10
  20. package/src/components/input/drag-listener.ts +0 -79
  21. package/src/components/input/math-input.tsx +0 -1036
  22. package/src/components/input/math-wrapper.ts +0 -189
  23. package/src/components/input/mathquill-helpers.ts +0 -262
  24. package/src/components/input/mathquill-instance.ts +0 -106
  25. package/src/components/input/mathquill-types.ts +0 -32
  26. package/src/components/input/scroll-into-view.ts +0 -65
  27. package/src/components/key-handlers/__tests__/handle-jump-out.test.ts +0 -94
  28. package/src/components/key-handlers/handle-arrow.ts +0 -70
  29. package/src/components/key-handlers/handle-backspace.ts +0 -277
  30. package/src/components/key-handlers/handle-exponent.ts +0 -53
  31. package/src/components/key-handlers/handle-jump-out.ts +0 -107
  32. package/src/components/key-handlers/key-translator.ts +0 -222
  33. package/src/components/keypad/__tests__/__snapshots__/keypad.test.tsx.snap +0 -1913
  34. package/src/components/keypad/__tests__/__snapshots__/mobile-keypad.test.tsx.snap +0 -600
  35. package/src/components/keypad/__tests__/keypad-button.test.tsx +0 -84
  36. package/src/components/keypad/__tests__/keypad-v2-mathquill.test.tsx +0 -304
  37. package/src/components/keypad/__tests__/keypad-v2.cypress.ts +0 -16
  38. package/src/components/keypad/__tests__/keypad.test.tsx +0 -321
  39. package/src/components/keypad/__tests__/mobile-keypad.test.tsx +0 -115
  40. package/src/components/keypad/__tests__/test-data-tabs.ts +0 -21
  41. package/src/components/keypad/button-assets.tsx +0 -1880
  42. package/src/components/keypad/index.tsx +0 -2
  43. package/src/components/keypad/keypad-button.stories.tsx +0 -81
  44. package/src/components/keypad/keypad-button.tsx +0 -124
  45. package/src/components/keypad/keypad-mathquill.stories.tsx +0 -109
  46. package/src/components/keypad/keypad-pages/extras-page.tsx +0 -35
  47. package/src/components/keypad/keypad-pages/fractions-page.tsx +0 -125
  48. package/src/components/keypad/keypad-pages/geometry-page.tsx +0 -34
  49. package/src/components/keypad/keypad-pages/keypad-pages.stories.tsx +0 -37
  50. package/src/components/keypad/keypad-pages/numbers-page.tsx +0 -94
  51. package/src/components/keypad/keypad-pages/operators-page.tsx +0 -117
  52. package/src/components/keypad/keypad.tsx +0 -233
  53. package/src/components/keypad/mobile-keypad-internals.tsx +0 -240
  54. package/src/components/keypad/mobile-keypad.tsx +0 -24
  55. package/src/components/keypad/navigation-button.tsx +0 -127
  56. package/src/components/keypad/navigation-pad.stories.tsx +0 -26
  57. package/src/components/keypad/navigation-pad.tsx +0 -67
  58. package/src/components/keypad/shared-keys.tsx +0 -109
  59. package/src/components/keypad/utils.ts +0 -34
  60. package/src/components/keypad-context.tsx +0 -70
  61. package/src/components/prop-types.ts +0 -16
  62. package/src/components/tabbar/__tests__/tabbar.test.tsx +0 -105
  63. package/src/components/tabbar/icons.tsx +0 -122
  64. package/src/components/tabbar/index.ts +0 -1
  65. package/src/components/tabbar/item.tsx +0 -146
  66. package/src/components/tabbar/tabbar.stories.tsx +0 -83
  67. package/src/components/tabbar/tabbar.tsx +0 -65
  68. package/src/data/key-configs.ts +0 -770
  69. package/src/data/keys.ts +0 -123
  70. package/src/enums.ts +0 -27
  71. package/src/fake-react-native-web/index.ts +0 -11
  72. package/src/fake-react-native-web/text.tsx +0 -55
  73. package/src/fake-react-native-web/view.tsx +0 -91
  74. package/src/full-keypad.stories.tsx +0 -142
  75. package/src/full-mobile-input.stories.tsx +0 -115
  76. package/src/index.ts +0 -52
  77. package/src/types.ts +0 -70
  78. package/src/utils.test.ts +0 -33
  79. package/src/utils.ts +0 -61
  80. package/src/version.ts +0 -10
  81. package/tsconfig-build.json +0 -11
  82. 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
- });