@khanacademy/math-input 4.3.0 → 5.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 (43) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/components/input/math-wrapper.d.ts +2 -2
  3. package/dist/components/input/math-wrapper.js.flow +2 -4
  4. package/dist/components/input/mathquill-helpers.d.ts +1 -1
  5. package/dist/components/input/mathquill-helpers.js.flow +2 -2
  6. package/dist/components/input/mathquill-types.d.ts +270 -10
  7. package/dist/components/input/mathquill-types.js.flow +312 -10
  8. package/dist/components/keypad/index.d.ts +11 -1
  9. package/dist/components/keypad/index.js.flow +14 -1
  10. package/dist/components/keypad/shared-keys.d.ts +4 -0
  11. package/dist/components/keypad/shared-keys.js.flow +4 -0
  12. package/dist/components/tabbar/tabbar.d.ts +1 -0
  13. package/dist/components/tabbar/tabbar.js.flow +1 -0
  14. package/dist/components/tabbar/types.d.ts +1 -1
  15. package/dist/components/tabbar/types.js.flow +6 -1
  16. package/dist/es/index.js +607 -409
  17. package/dist/es/index.js.map +1 -1
  18. package/dist/index.js +607 -409
  19. package/dist/index.js.map +1 -1
  20. package/package.json +2 -1
  21. package/src/components/input/__tests__/mathquill-helpers.test.ts +105 -0
  22. package/src/components/input/math-input.tsx +1 -1
  23. package/src/components/input/math-wrapper.ts +6 -10
  24. package/src/components/input/mathquill-helpers.ts +8 -1
  25. package/src/components/input/mathquill-types.ts +308 -40
  26. package/src/components/key-handlers/__tests__/handle-jump-out.test.ts +94 -0
  27. package/src/components/key-handlers/handle-jump-out.ts +3 -2
  28. package/src/components/keypad/__tests__/keypad-v2-mathquill.test.tsx +42 -39
  29. package/src/components/keypad/__tests__/keypad.test.tsx +42 -0
  30. package/src/components/keypad/button-assets.tsx +540 -316
  31. package/src/components/keypad/index.tsx +25 -2
  32. package/src/components/keypad/keypad-mathquill.stories.tsx +20 -1
  33. package/src/components/keypad/keypad-pages/extras-page.tsx +1 -1
  34. package/src/components/keypad/keypad-pages/numbers-page.tsx +25 -16
  35. package/src/components/keypad/keypad.stories.tsx +11 -0
  36. package/src/components/keypad/shared-keys.tsx +56 -8
  37. package/src/components/tabbar/__tests__/tabbar.test.tsx +54 -14
  38. package/src/components/tabbar/icons.tsx +48 -8
  39. package/src/components/tabbar/item.tsx +2 -0
  40. package/src/components/tabbar/tabbar.tsx +32 -12
  41. package/src/components/tabbar/types.ts +6 -1
  42. package/tsconfig-build.json +3 -1
  43. package/tsconfig-build.tsbuildinfo +1 -1
@@ -8,43 +8,339 @@ import Key from "../../data/keys";
8
8
  export interface MathQuillInterface {
9
9
  L: "L";
10
10
  R: "R";
11
+
12
+ /**
13
+ * Creates an editable MathQuill initialized with the contents of the HTML
14
+ * element and returns a MathField object.
15
+ *
16
+ * If the given element is already an editable math field, this will return
17
+ * a new editable MathField object with the same `.id`. If the element is a
18
+ * different type of MathQuill, this will return `null`.
19
+ */
11
20
  MathField: (
12
21
  mount: HTMLDivElement | HTMLSpanElement,
13
22
  config: MathFieldConfig
14
23
  ) => MathFieldInterface;
15
24
  }
16
- declare type MathQuillDir = "L" | "R";
25
+ declare type MathQuillDirection =
26
+ | $PropertyType<MathQuillInterface, "L">
27
+ | $PropertyType<MathQuillInterface, "R">;
17
28
  export type MathFieldConfig = {|
29
+ /**
30
+ * If spaceBehavesLikeTab is true the keystrokes {Shift-,}Spacebar will
31
+ * behave like {Shift-,}Tab escaping from the current block (as opposed
32
+ * to the default behavior of inserting a Space character).
33
+ */
18
34
  spaceBehavesLikeTab?: boolean,
19
- leftRightIntoCmdGoes?: string,
35
+
36
+ /**
37
+ * This allows you to change the way the left and right keys move the
38
+ * cursor when there are items of different height, like fractions.
39
+ *
40
+ * By default, the Left and Right keys move the cursor through all
41
+ * possible cursor positions in a particular order: right into a
42
+ * fraction puts the cursor at the left end of the numerator, right out
43
+ * of the numerator puts the cursor at the left end of the denominator,
44
+ * and right out of the denominator puts the cursor to the right of the
45
+ * fraction. Symmetrically, left into a fraction puts the cursor at the
46
+ * right end of the denominator, etc.
47
+ *
48
+ * If instead you want right to always visually go right, and left to always go
49
+ * visually left, you can set leftRightIntoCmdGoes to 'up' or 'down' so that
50
+ * left and right go up or down (respectively) into commands. For example, 'up'
51
+ * means that left into a fraction goes up into the numerator and right out of
52
+ * the numerator skips the denominator and puts the cursor to the right of the
53
+ * fraction. This behavior can be seen in the Desmos calculator. If this
54
+ * property is set to 'down' instead, the numerator is harder to navigate to,
55
+ * like in the Mac OS X built-in app Grapher.
56
+ */
57
+ leftRightIntoCmdGoes?: "up" | "down",
58
+
59
+ /**
60
+ * If restrictMismatchedBrackets is true then you can type [a,b) and
61
+ * (a,b], but if you try typing [x} or \langle x|, you'll get [{x}] or
62
+ * \langle|x|\rangle instead. This lets you type (|x|+1) normally;
63
+ * otherwise, you'd get \left( \right| x \left| + 1 \right).
64
+ */
20
65
  restrictMismatchedBrackets?: boolean,
66
+
67
+ /**
68
+ * If sumStartsWithNEquals is true then when you type \sum, \prod, or
69
+ * \coprod, the lower limit starts out with n=, e.g. you get the LaTeX
70
+ * \sum_{n=}^{ }, rather than empty by default.
71
+ */
21
72
  sumStartsWithNEquals?: boolean,
73
+
74
+ /**
75
+ * supSubsRequireOperand disables typing of superscripts and subscripts
76
+ * when there's nothing to the left of the cursor to be exponentiated
77
+ * or subscripted. Prevents the especially confusing typo x^^2, which
78
+ * looks much like x^2.
79
+ */
22
80
  supSubsRequireOperand?: boolean,
81
+
82
+ /**
83
+ * charsThatBreakOutOfSupSub takes a string of the chars that when
84
+ * typed, "break out" of superscripts and subscripts.
85
+ *
86
+ * Normally, to get out of a superscript or subscript, a user has to
87
+ * navigate out of it with the directional keys, a mouse click, tab, or
88
+ * Space if spaceBehavesLikeTab is true. For example, typing x^2n+y
89
+ * normally results in the LaTeX x^{2n+y}. If you wanted to get the
90
+ * LaTeX x^{2n}+y, the user would have to manually move the cursor out
91
+ * of the exponent.
92
+ *
93
+ * If this option was set to '+-', + and - would "break out" of the
94
+ * exponent. This doesn't apply to the first character in a superscript
95
+ * or subscript, so typing x^-6 still results in x^{-6}. The downside
96
+ * to setting this option is that in order to type x^{n+m}, a
97
+ * workaround like typing x^(n+m and then deleting the ( is required.
98
+ */
23
99
  charsThatBreakOutOfSupSub?: string,
100
+
101
+ /**
102
+ * :shrug: Undocumented except for being shown in an example for
103
+ * configuration options.
104
+ */
24
105
  autoSubscriptNumerals?: boolean,
106
+
107
+ /**
108
+ * autoCommands defines the set of commands automatically rendered by
109
+ * just typing the letters without typing a backslash first.
110
+ *
111
+ * This takes a string formatted as a space-delimited list of LaTeX
112
+ * commands. Each LaTeX command must be at least letters only with a
113
+ * minimum length of 2 characters.
114
+ *
115
+ * For example, with autoCommands set to 'pi theta', the word 'pi'
116
+ * automatically converts to the pi symbol and the word 'theta'
117
+ * automatically converts to the theta symbol.
118
+ */
25
119
  autoCommands?: string,
120
+
121
+ /**
122
+ * autoOperatorNames overrides the set of operator names that
123
+ * automatically become non-italicized when typing the letters without
124
+ * typing a backslash first, like sin, log, etc.
125
+ *
126
+ * This defaults to the LaTeX built-in operator names (Section 3.17 of
127
+ * the Short Math Guide) with additional trig operators like sech,
128
+ * arcsec, arsinh, etc. If you want some of these italicized after
129
+ * setting this property, you will have to add them to the list.
130
+ *
131
+ * Just like autoCommands above, this takes a string formatted as a
132
+ * space-delimited list of LaTeX commands.
133
+ */
26
134
  autoOperatorNames?: string,
135
+
136
+ /**
137
+ * maxDepth specifies the maximum number of nested MathBlocks. When
138
+ * maxDepth is set to 1, the user can type simple math symbols directly
139
+ * into the editor but not into nested MathBlocks, e.g. the numerator
140
+ * and denominator of a fraction.
141
+ *
142
+ * Nested content in latex rendered during initialization or pasted
143
+ * into mathquill is truncated to avoid violating maxDepth. When
144
+ * maxDepth is not set, no depth limit is applied by default.
145
+ */
27
146
  maxDepth?: number,
28
- substituteTextarea?: () => HTMLElement,
147
+
148
+ /**
149
+ * substituteTextarea is a function that creates a focusable DOM
150
+ * element that is called when setting up a math field. Overwriting
151
+ * this may be useful for hacks like suppressing built-in virtual
152
+ * keyboards. It defaults to <textarea autocorrect=off .../>.
153
+ *
154
+ * For example, Desmos substitutes <span tabindex=0></span> on iOS to
155
+ * suppress the built-in virtual keyboard in favor of a custom math
156
+ * keypad that calls the MathQuill API. Unfortunately there's no
157
+ * universal check for a virtual keyboard or way to detect a
158
+ * touchscreen, and even if you could, a touchscreen ≠ virtual keyboard
159
+ * (Windows 8 and ChromeOS devices have both physical keyboards and
160
+ * touchscreens and iOS and Android devices can have Bluetooth
161
+ * keyboards). Desmos currently sniffs the user agent for iOS, so
162
+ * Bluetooth keyboards just don't work in Desmos on iOS. The tradeoffs
163
+ * are up to you.
164
+ */
165
+ substituteTextarea?: () => HTMLElement | void,
166
+
167
+ /**
168
+ * Handlers are called after a specified event. They are called
169
+ * directly on the handlers object passed in, preserving the this value
170
+ */
29
171
  handlers?: {|
30
172
  edit?: (mathField: MathFieldInterface) => void,
173
+ enter?: (mathField: MathFieldInterface) => void,
174
+ moveOutOf?: (mathField: MathFieldInterface) => void,
31
175
  upOutOf?: (mathField: MathFieldInterface) => void,
32
- moveOutOf?: (dir: MathQuillDir, mathField: MathFieldInterface) => void,
176
+ downOutOf?: (mathField: MathFieldInterface) => void,
177
+ deleteOutOf?: (
178
+ direction: MathQuillDirection,
179
+ mathField: MathFieldInterface
180
+ ) => void,
181
+ selectOutOf?: (
182
+ direction: MathQuillDirection,
183
+ mathField: MathFieldInterface
184
+ ) => void,
33
185
  |},
34
186
  |};
187
+ /**
188
+ * Editable math fields have all of the above methods in addition to
189
+ * the ones listed here.
190
+ * https://docs.mathquill.com/en/latest/Api_Methods/
191
+ */
35
192
  export interface MathFieldInterface {
193
+ /**
194
+ * Any element that has been turned into a MathQuill instance can be
195
+ * reverted.
196
+ */
197
+ revert: () => void;
198
+
199
+ /**
200
+ * MathQuill uses computed dimensions, so if they change (because an
201
+ * element was mathquill-ified before it was in the visible HTML DOM, or
202
+ * the font size changed), then you'll need to tell MathQuill to recomput
203
+ */
204
+ reflow: () => void;
205
+
206
+ /**
207
+ * Returns the root HTML element.
208
+ */
209
+ el: () => HTMLElement;
210
+
211
+ /**
212
+ * Puts the focus on the editable field.
213
+ * http://docs.mathquill.com/en/latest/Api_Methods/#focus
214
+ */
36
215
  focus: () => MathFieldInterface;
216
+
217
+ /**
218
+ * Removes focus from the editable field.
219
+ * http://docs.mathquill.com/en/latest/Api_Methods/#blur
220
+ */
37
221
  blur: () => MathFieldInterface;
38
- write: (input: string) => MathFieldInterface;
39
- cmd: (input: string) => MathFieldInterface;
40
- keystroke: (input: string) => MathFieldInterface;
41
- typedText: (input: string) => MathFieldInterface;
42
- latex: (input?: string) => string;
43
- moveToDirEnd: (direction: "L" | "R") => void;
222
+
223
+ /**
224
+ * Write the given LaTeX at the current cursor position. If the
225
+ * cursor does not have focus, writes to last position the cursor
226
+ * occupied in the editable field.
227
+ *
228
+ * ```
229
+ * // writes ' - 1' to mathField at the cursor position
230
+ * mathField.write(' - 1');
231
+ * ```
232
+ *
233
+ * https://docs.mathquill.com/en/latest/Api_Methods/#writelatex_string
234
+ */
235
+ write: (latex_string: string) => MathFieldInterface;
236
+
237
+ /**
238
+ * Enter a LaTeX command at the current cursor position or with the
239
+ * current selection. If the cursor does not have focus, it writes it
240
+ * to last position the cursor occupied in the editable field.
241
+ *
242
+ * ```
243
+ * // writes a square root command at the cursor position
244
+ * mathField.cmd('\\sqrt');
245
+ * ```
246
+ *
247
+ * https://docs.mathquill.com/en/latest/Api_Methods/#cmdlatex_string
248
+ */
249
+ cmd: (latex_string: string) => MathFieldInterface;
250
+
251
+ /**
252
+ * Selects the contents (just like on textareas and on inputs).
253
+ *
254
+ * https://docs.mathquill.com/en/latest/Api_Methods/#select
255
+ */
44
256
  select: () => void;
257
+
258
+ /**
259
+ * Clears the selection.
260
+ *
261
+ * https://docs.mathquill.com/en/latest/Api_Methods/#clearselection
262
+ */
45
263
  clearSelection: () => void;
264
+
265
+ /**
266
+ * Move the cursor to the left end of the editable field. horthand
267
+ * for .moveToDirEnd(L)
268
+ */
269
+ moveToLeftEnd: () => void;
270
+
271
+ /**
272
+ * Move the cursor to the right end of the editable field. horthand
273
+ * for .moveToDirEnd(R)
274
+ */
275
+ moveToRightEnd: () => void;
276
+
277
+ /**
278
+ * Moves the cursor to the end of the mathfield in the direction
279
+ * specified. The direction can be one of MQ.L or MQ.R. These are
280
+ * constants, where MQ.L === -MQ.R and vice versa. This function
281
+ * may be easier to use than moveToLeftEnd or moveToRightEnd if
282
+ * used in the moveOutOf handler.
283
+ *
284
+ * https://docs.mathquill.com/en/latest/Api_Methods/#movetodirenddirection
285
+ */
286
+ moveToDirEnd: (direction: MathQuillDirection) => void;
287
+
288
+ /**
289
+ * Simulates keystrokes given a string like "Ctrl-Home Del", a
290
+ * whitespace-delimited list of key inputs with optional prefixes.
291
+ *
292
+ * ```
293
+ * mathField.keystroke('Shift-Left'); // Selects character before the current cursor position
294
+ * ```
295
+ *
296
+ * https://docs.mathquill.com/en/latest/Api_Methods/#keystrokekeys
297
+ */
298
+ keystroke: (keys: string) => MathFieldInterface;
299
+
300
+ /**
301
+ * Simulates typing text, one character at a time from where the
302
+ * cursor currently is. This is supposed to be identical to what
303
+ * would happen if a user were typing the text in.
304
+ *
305
+ * Types part of the demo from mathquill.com without delays between keystrokes
306
+ * ```
307
+ * mathField.typedText('x=-b\\pm \\sqrt b^2 -4ac');
308
+ * ```
309
+ *
310
+ * https://docs.mathquill.com/en/latest/Api_Methods/#typedtexttext
311
+ */
312
+ typedText: (text: string) => MathFieldInterface;
313
+
314
+ /**
315
+ * When called withot any pramaters, gets the contents as LaTeX
316
+ * When passed a string, sets the contents as LaTeX
317
+ *
318
+ * https://docs.mathquill.com/en/latest/Api_Methods/#latex
319
+ */
320
+ latex: (input?: string) => string;
321
+
322
+ /**
323
+ * Changes the configuration of just this math field.
324
+ */
325
+ config: (new_config: MathFieldConfig) => void;
326
+
327
+ /**
328
+ * KA Custom helper in our MathQuill fork check to see if cursor is on
329
+ * right end
330
+ */
46
331
  cursorAtRightEnd: () => boolean;
332
+
333
+ /**
334
+ * KA Custom helper in our MathQuill fork check to see if cursor is on left
335
+ * end
336
+ */
47
337
  cursorAtLeftEnd: () => boolean;
338
+
339
+ /**
340
+ * This isn't part of the MathQuill public API
341
+ * I don't know what it is and it feels wrong using it
342
+ * @deprecated This is internal and shouldn't be used.
343
+ */
48
344
  __controller: any;
49
345
  }
50
346
  declare export var MathFieldActionType: {|
@@ -53,6 +349,12 @@ declare export var MathFieldActionType: {|
53
349
  +KEYSTROKE: "keystroke", // "keystroke"
54
350
  +MQ_END: 0, // 0
55
351
  |};
352
+
353
+ /**
354
+ * The MathQuill MathField Cursor
355
+ * it's not part of the public API for MathQuill,
356
+ * we reach into the internals to get it
357
+ */
56
358
  export type MathFieldCursor = any;
57
359
  export type MathFieldUpdaterCallback = (
58
360
  mathField: MathFieldInterface,
@@ -1,8 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import Key from "../../data/keys";
3
3
  import { ClickKeyCallback } from "../../types";
4
+ import { CursorContext } from "../input/cursor-contexts";
5
+ import type { SendEventFn } from "@khanacademy/perseus-core";
4
6
  export type Props = {
5
7
  onClickKey: ClickKeyCallback;
8
+ cursorContext?: CursorContext;
6
9
  trigonometry?: boolean;
7
10
  extraKeys: ReadonlyArray<Key>;
8
11
  multiplicationDot?: boolean;
@@ -11,5 +14,12 @@ export type Props = {
11
14
  logarithms?: boolean;
12
15
  basicRelations?: boolean;
13
16
  advancedRelations?: boolean;
17
+ sendEvent: SendEventFn;
14
18
  };
15
- export default function Keypad(props: Props): JSX.Element;
19
+ declare function Keypad(props: Props): JSX.Element;
20
+ declare namespace Keypad {
21
+ var defaultProps: {
22
+ extraKeys: never[];
23
+ };
24
+ }
25
+ export default Keypad;
@@ -6,8 +6,11 @@
6
6
  */
7
7
  import Key from "../../data/keys";
8
8
  import { ClickKeyCallback } from "../../types";
9
+ import { CursorContext } from "../input/cursor-contexts";
10
+ import type { SendEventFn } from "@khanacademy/perseus-core";
9
11
  export type Props = {|
10
12
  onClickKey: ClickKeyCallback,
13
+ cursorContext?: CursorContext,
11
14
  trigonometry?: boolean,
12
15
  extraKeys: $ReadOnlyArray<Key>,
13
16
  multiplicationDot?: boolean,
@@ -16,5 +19,15 @@ export type Props = {|
16
19
  logarithms?: boolean,
17
20
  basicRelations?: boolean,
18
21
  advancedRelations?: boolean,
22
+ sendEvent: SendEventFn,
19
23
  |};
20
- declare export default function Keypad(props: Props): React$Node;
24
+ declare var Keypad: typeof npm$namespace$Keypad;
25
+
26
+ declare var npm$namespace$Keypad: {|
27
+ (props: Props): React$Node,
28
+ defaultProps: typeof Keypad$defaultProps,
29
+ |};
30
+ declare var Keypad$defaultProps: {|
31
+ extraKeys: empty[],
32
+ |};
33
+ declare export default typeof Keypad;
@@ -1,7 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import { ClickKeyCallback } from "../../types";
3
+ import { CursorContext } from "../input/cursor-contexts";
4
+ import { TabbarItemType } from "../tabbar/types";
3
5
  type Props = {
4
6
  onClickKey: ClickKeyCallback;
7
+ selectedPage: TabbarItemType;
8
+ cursorContext?: CursorContext;
5
9
  multiplicationDot?: boolean;
6
10
  divisionKey?: boolean;
7
11
  };
@@ -5,8 +5,12 @@
5
5
  * @flow
6
6
  */
7
7
  import { ClickKeyCallback } from "../../types";
8
+ import { CursorContext } from "../input/cursor-contexts";
9
+ import { TabbarItemType } from "../tabbar/types";
8
10
  declare type Props = {|
9
11
  onClickKey: ClickKeyCallback,
12
+ selectedPage: TabbarItemType,
13
+ cursorContext?: CursorContext,
10
14
  multiplicationDot?: boolean,
11
15
  divisionKey?: boolean,
12
16
  |};
@@ -4,6 +4,7 @@ import { TabbarItemType } from "./types";
4
4
  type Props = {
5
5
  items: ReadonlyArray<TabbarItemType>;
6
6
  selectedItem: TabbarItemType;
7
+ onClickClose?: () => void;
7
8
  onSelectItem: (item: TabbarItemType) => void;
8
9
  style?: StyleType;
9
10
  };
@@ -10,6 +10,7 @@ import { TabbarItemType } from "./types";
10
10
  declare type Props = {|
11
11
  items: $ReadOnlyArray<TabbarItemType>,
12
12
  selectedItem: TabbarItemType,
13
+ onClickClose?: () => void,
13
14
  onSelectItem: (item: TabbarItemType) => void,
14
15
  style?: StyleType,
15
16
  |};
@@ -1 +1 @@
1
- export type TabbarItemType = "Geometry" | "Operators" | "Numbers" | "Extras";
1
+ export type TabbarItemType = "Geometry" | "Operators" | "Numbers" | "Extras" | "Dismiss";
@@ -4,4 +4,9 @@
4
4
  * Flowgen v1.21.0
5
5
  * @flow
6
6
  */
7
- export type TabbarItemType = "Geometry" | "Operators" | "Numbers" | "Extras";
7
+ export type TabbarItemType =
8
+ | "Geometry"
9
+ | "Operators"
10
+ | "Numbers"
11
+ | "Extras"
12
+ | "Dismiss";