@khanacademy/math-input 12.1.1 → 13.1.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 +22 -0
- package/dist/components/keypad/keypad.d.ts +1 -1
- package/dist/components/keypad/mobile-keypad.d.ts +2 -1
- package/dist/components/keypad/shared-keys.d.ts +1 -1
- package/dist/es/index.js +30 -10
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -10
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/__tests__/integration.test.tsx +287 -0
- package/src/components/keypad/__tests__/__snapshots__/keypad.test.tsx.snap +84 -26
- package/src/components/keypad/__tests__/keypad-v2-mathquill.test.tsx +1 -1
- package/src/components/keypad/__tests__/keypad.test.tsx +30 -0
- package/src/components/keypad/keypad-button.stories.tsx +2 -1
- package/src/components/keypad/keypad-button.tsx +3 -0
- package/src/components/keypad/keypad-mathquill.stories.tsx +2 -2
- package/src/components/keypad/keypad-pages/fractions-page.tsx +1 -1
- package/src/components/keypad/keypad-pages/keypad-pages.stories.tsx +1 -1
- package/src/components/keypad/keypad.tsx +3 -3
- package/src/components/keypad/mobile-keypad.tsx +21 -4
- package/src/components/keypad/navigation-pad.stories.tsx +1 -1
- package/src/components/keypad/shared-keys.tsx +4 -4
- package/src/components/tabbar/tabbar.stories.tsx +4 -1
- package/src/{components/keypad/keypad.stories.tsx → full-keypad.stories.tsx} +6 -6
- package/src/{full-math-input.stories.tsx → full-mobile-input.stories.tsx} +15 -3
- package/src/index.ts +1 -1
- package/src/types.ts +1 -0
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import {
|
|
3
|
+
screen,
|
|
4
|
+
render,
|
|
5
|
+
fireEvent,
|
|
6
|
+
within,
|
|
7
|
+
waitFor,
|
|
8
|
+
} from "@testing-library/react";
|
|
9
|
+
import userEvent from "@testing-library/user-event";
|
|
10
|
+
import MathQuill from "mathquill";
|
|
11
|
+
import React, {useState} from "react";
|
|
12
|
+
|
|
13
|
+
import {KeypadType} from "../../enums";
|
|
14
|
+
import MathInput from "../input/math-input";
|
|
15
|
+
import KeypadContext from "../keypad-context";
|
|
16
|
+
import KeypadSwitch from "../keypad-switch";
|
|
17
|
+
|
|
18
|
+
import type {KeypadAPI, KeypadConfiguration} from "../../types";
|
|
19
|
+
|
|
20
|
+
const MQ = MathQuill.getInterface(2);
|
|
21
|
+
|
|
22
|
+
const defaultConfiguration: KeypadConfiguration = {
|
|
23
|
+
keypadType: KeypadType.FRACTION,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function InputWithContext({keypadConfiguration}) {
|
|
27
|
+
const [value, setValue] = useState<string>("");
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<KeypadContext.Consumer>
|
|
31
|
+
{({keypadElement}) => {
|
|
32
|
+
return (
|
|
33
|
+
<MathInput
|
|
34
|
+
keypadElement={keypadElement as any}
|
|
35
|
+
value={value}
|
|
36
|
+
onChange={(nextValue, cb) => {
|
|
37
|
+
setValue(nextValue);
|
|
38
|
+
cb();
|
|
39
|
+
}}
|
|
40
|
+
onFocus={() => {
|
|
41
|
+
keypadElement?.configure(
|
|
42
|
+
keypadConfiguration,
|
|
43
|
+
() => {
|
|
44
|
+
keypadElement?.activate();
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
}}
|
|
48
|
+
onBlur={() => {
|
|
49
|
+
keypadElement?.dismiss();
|
|
50
|
+
}}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}}
|
|
54
|
+
</KeypadContext.Consumer>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function KeypadWithContext() {
|
|
59
|
+
return (
|
|
60
|
+
<KeypadContext.Consumer>
|
|
61
|
+
{({setKeypadElement}) => {
|
|
62
|
+
return (
|
|
63
|
+
<KeypadSwitch
|
|
64
|
+
onElementMounted={setKeypadElement}
|
|
65
|
+
onDismiss={() => {}}
|
|
66
|
+
onAnalyticsEvent={async () => {}}
|
|
67
|
+
useV2Keypad
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}}
|
|
71
|
+
</KeypadContext.Consumer>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function ConnectedMathInput({keypadConfiguration = defaultConfiguration}) {
|
|
76
|
+
const [keypadElement, setKeypadElement] = useState<KeypadAPI | null>();
|
|
77
|
+
const [renderer, setRenderer] = useState<any>(null);
|
|
78
|
+
const [scrollableElement, setScrollableElement] =
|
|
79
|
+
useState<HTMLElement | null>();
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<KeypadContext.Provider
|
|
83
|
+
value={{
|
|
84
|
+
setKeypadElement,
|
|
85
|
+
keypadElement,
|
|
86
|
+
setRenderer,
|
|
87
|
+
renderer,
|
|
88
|
+
setScrollableElement,
|
|
89
|
+
scrollableElement,
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<InputWithContext keypadConfiguration={keypadConfiguration} />
|
|
93
|
+
<KeypadWithContext />
|
|
94
|
+
</KeypadContext.Provider>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
describe("math input integration", () => {
|
|
99
|
+
it("renders", () => {
|
|
100
|
+
render(<ConnectedMathInput />);
|
|
101
|
+
|
|
102
|
+
expect(
|
|
103
|
+
screen.getByLabelText(
|
|
104
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
105
|
+
),
|
|
106
|
+
).toBeInTheDocument();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("doesn't show the keypad initially", () => {
|
|
110
|
+
render(<ConnectedMathInput />);
|
|
111
|
+
|
|
112
|
+
expect(
|
|
113
|
+
screen.queryByRole("button", {name: "1"}),
|
|
114
|
+
).not.toBeInTheDocument();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("shows the keypad after input interaction", async () => {
|
|
118
|
+
render(<ConnectedMathInput />);
|
|
119
|
+
|
|
120
|
+
const input = screen.getByLabelText(
|
|
121
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
fireEvent.touchStart(input);
|
|
125
|
+
|
|
126
|
+
await waitFor(() => {
|
|
127
|
+
expect(screen.getByRole("button", {name: "4"})).toBeVisible();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(screen.getByRole("button", {name: "1"})).toBeVisible();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("updates input when using keypad", async () => {
|
|
134
|
+
render(<ConnectedMathInput />);
|
|
135
|
+
|
|
136
|
+
const input = screen.getByLabelText(
|
|
137
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
fireEvent.touchStart(input);
|
|
141
|
+
|
|
142
|
+
await waitFor(() => {
|
|
143
|
+
expect(screen.getByRole("button", {name: "4"})).toBeVisible();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
userEvent.click(screen.getByRole("button", {name: "1"}));
|
|
147
|
+
|
|
148
|
+
// MathQuill is problematic,
|
|
149
|
+
// this is the only way I know how to test the "input"
|
|
150
|
+
const mathquillInput =
|
|
151
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
152
|
+
document.getElementsByClassName("mq-root-block")[0] as HTMLElement;
|
|
153
|
+
const span1 = within(mathquillInput).getByText("1");
|
|
154
|
+
|
|
155
|
+
expect(span1).toBeVisible();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("updates input when pressing many numbers", async () => {
|
|
159
|
+
render(<ConnectedMathInput />);
|
|
160
|
+
|
|
161
|
+
const input = screen.getByLabelText(
|
|
162
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
fireEvent.touchStart(input);
|
|
166
|
+
|
|
167
|
+
await waitFor(() => {
|
|
168
|
+
expect(screen.getByRole("button", {name: "4"})).toBeVisible();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const testNumbers = [8, 6, 7, 5, 3, 0, 9];
|
|
172
|
+
testNumbers.forEach((num) => {
|
|
173
|
+
userEvent.click(screen.getByRole("button", {name: `${num}`}));
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// MathQuill is problematic,
|
|
177
|
+
// this is how to get the value of the input directly from MQ
|
|
178
|
+
const mathquillInstance =
|
|
179
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
180
|
+
MQ(document.getElementsByClassName("mq-editable-field")[0]);
|
|
181
|
+
|
|
182
|
+
expect(mathquillInstance.latex()).toBe("8675309");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("can handle symbols", async () => {
|
|
186
|
+
render(<ConnectedMathInput />);
|
|
187
|
+
|
|
188
|
+
const input = screen.getByLabelText(
|
|
189
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
fireEvent.touchStart(input);
|
|
193
|
+
|
|
194
|
+
await waitFor(() => {
|
|
195
|
+
expect(screen.getByRole("button", {name: "4"})).toBeVisible();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
userEvent.click(screen.getByRole("button", {name: "4"}));
|
|
199
|
+
userEvent.click(screen.getByRole("button", {name: "2"}));
|
|
200
|
+
userEvent.click(screen.getByRole("button", {name: "Percent"}));
|
|
201
|
+
|
|
202
|
+
// MathQuill is problematic,
|
|
203
|
+
// this is how to get the value of the input directly from MQ
|
|
204
|
+
const mathquillInstance =
|
|
205
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
206
|
+
MQ(document.getElementsByClassName("mq-editable-field")[0]);
|
|
207
|
+
|
|
208
|
+
expect(mathquillInstance.latex()).toBe("42\\%");
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("handles fractions correctly in expression", async () => {
|
|
212
|
+
const keypadConfiguration = {
|
|
213
|
+
keypadType: KeypadType.EXPRESSION,
|
|
214
|
+
};
|
|
215
|
+
render(
|
|
216
|
+
<ConnectedMathInput keypadConfiguration={keypadConfiguration} />,
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
const input = screen.getByLabelText(
|
|
220
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
fireEvent.touchStart(input);
|
|
224
|
+
|
|
225
|
+
await waitFor(() => {
|
|
226
|
+
expect(screen.getByRole("button", {name: "4"})).toBeVisible();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
userEvent.click(screen.getByRole("button", {name: "1"}));
|
|
230
|
+
userEvent.click(
|
|
231
|
+
screen.getByRole("button", {
|
|
232
|
+
name: "Fraction, excluding the current expression",
|
|
233
|
+
}),
|
|
234
|
+
);
|
|
235
|
+
userEvent.click(screen.getByRole("button", {name: "4"}));
|
|
236
|
+
userEvent.click(
|
|
237
|
+
screen.getByRole("button", {
|
|
238
|
+
name: "Navigate right out of the numerator and into the denominator",
|
|
239
|
+
}),
|
|
240
|
+
);
|
|
241
|
+
userEvent.click(screen.getByRole("button", {name: "2"}));
|
|
242
|
+
|
|
243
|
+
// MathQuill is problematic,
|
|
244
|
+
// this is how to get the value of the input directly from MQ
|
|
245
|
+
const mathquillInstance =
|
|
246
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
247
|
+
MQ(document.getElementsByClassName("mq-editable-field")[0]);
|
|
248
|
+
|
|
249
|
+
expect(mathquillInstance.latex()).toBe("1\\frac{4}{2}");
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("handles fractions correctly in fraction", async () => {
|
|
253
|
+
render(<ConnectedMathInput />);
|
|
254
|
+
|
|
255
|
+
const input = screen.getByLabelText(
|
|
256
|
+
"Math input box Tap with one or two fingers to open keyboard",
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
fireEvent.touchStart(input);
|
|
260
|
+
|
|
261
|
+
await waitFor(() => {
|
|
262
|
+
expect(screen.getByRole("button", {name: "4"})).toBeVisible();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
userEvent.click(screen.getByRole("button", {name: "1"}));
|
|
266
|
+
userEvent.click(
|
|
267
|
+
screen.getByRole("button", {
|
|
268
|
+
name: "Fraction, excluding the current expression",
|
|
269
|
+
}),
|
|
270
|
+
);
|
|
271
|
+
userEvent.click(screen.getByRole("button", {name: "4"}));
|
|
272
|
+
userEvent.click(
|
|
273
|
+
screen.getByRole("button", {
|
|
274
|
+
name: "Navigate right out of the numerator and into the denominator",
|
|
275
|
+
}),
|
|
276
|
+
);
|
|
277
|
+
userEvent.click(screen.getByRole("button", {name: "2"}));
|
|
278
|
+
|
|
279
|
+
// MathQuill is problematic,
|
|
280
|
+
// this is how to get the value of the input directly from MQ
|
|
281
|
+
const mathquillInstance =
|
|
282
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
283
|
+
MQ(document.getElementsByClassName("mq-editable-field")[0]);
|
|
284
|
+
|
|
285
|
+
expect(mathquillInstance.latex()).toBe("1\\frac{4}{2}");
|
|
286
|
+
});
|
|
287
|
+
});
|