@khanacademy/math-input 16.5.0 → 17.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.
@@ -1,82 +1,82 @@
1
1
  import MathQuill from "mathquill";
2
2
 
3
- import type {MathQuillInterface, MathFieldConfig} from "./mathquill-types";
3
+ import type {
4
+ MathQuillInterface,
5
+ MathFieldConfig,
6
+ MathFieldInterface,
7
+ } from "./mathquill-types";
4
8
 
5
9
  // We only need one MathQuill instance (referred to as MQ in the docs)
6
10
  // and that contains some MQ constants and the MathField constructor
7
- export const mathQuillInstance = MathQuill.getInterface(
8
- 2,
9
- ) as MathQuillInterface;
11
+ export const mathQuillInstance: MathQuillInterface = MathQuill.getInterface(3);
10
12
 
11
- function createBaseConfig(): MathFieldConfig {
12
- return {
13
- // LaTeX commands that, when typed, are immediately replaced by the
14
- // appropriate symbol. This does not include ln, log, or any of the
15
- // trig functions; those are always interpreted as commands.
16
- autoCommands: "pi theta phi sqrt nthroot",
17
- // Most of these autoOperatorNames are simply the MathQuill defaults.
18
- // We have to list them all in order to add the `sen` operator (see
19
- // comment below).
20
- autoOperatorNames: [
21
- "arccos",
22
- "arcsin",
23
- "arctan",
24
- "arg",
25
- "cos",
26
- "cosh",
27
- "cot",
28
- "coth",
29
- "csc",
30
- "deg",
31
- "det",
32
- "dim",
33
- "exp",
34
- "gcd",
35
- "hom",
36
- "inf",
37
- "ker",
38
- "lg",
39
- "lim",
40
- "liminf",
41
- "limsup",
42
- "ln",
43
- "log",
44
- "max",
45
- "min",
46
- "Pr",
47
- "projlim",
48
- "sec",
49
- // sen is used instead of sin in e.g. Portuguese
50
- "sen",
51
- "sin",
52
- "sinh",
53
- "sup",
54
- "tan",
55
- "tanh",
56
- ].join(" "),
13
+ const createBaseConfig = (): MathFieldConfig => ({
14
+ // LaTeX commands that, when typed, are immediately replaced by the
15
+ // appropriate symbol. This does not include ln, log, or any of the
16
+ // trig functions; those are always interpreted as commands.
17
+ autoCommands: "pi theta phi sqrt nthroot",
18
+ // Most of these autoOperatorNames are simply the MathQuill defaults.
19
+ // We have to list them all in order to add the `sen` operator (see
20
+ // comment below).
21
+ autoOperatorNames: [
22
+ "arccos",
23
+ "arcsin",
24
+ "arctan",
25
+ "arg",
26
+ "cos",
27
+ "cosh",
28
+ "cot",
29
+ "coth",
30
+ "csc",
31
+ "deg",
32
+ "det",
33
+ "dim",
34
+ "exp",
35
+ "gcd",
36
+ "hom",
37
+ "inf",
38
+ "ker",
39
+ "lg",
40
+ "lim",
41
+ "liminf",
42
+ "limsup",
43
+ "ln",
44
+ "log",
45
+ "max",
46
+ "min",
47
+ "Pr",
48
+ "projlim",
49
+ "sec",
50
+ // sen is used instead of sin in e.g. Portuguese
51
+ "sen",
52
+ "sin",
53
+ "sinh",
54
+ "sup",
55
+ "tan",
56
+ "tanh",
57
+ ].join(" "),
57
58
 
58
- // Pop the cursor out of super/subscripts on arithmetic operators
59
- // or (in)equalities.
60
- charsThatBreakOutOfSupSub: "+-*/=<>≠≤≥",
59
+ // Pop the cursor out of super/subscripts on arithmetic operators
60
+ // or (in)equalities.
61
+ charsThatBreakOutOfSupSub: "+-*/=<>≠≤≥",
61
62
 
62
- // Prevent excessive super/subscripts or fractions from being
63
- // created without operands, e.g. when somebody holds down a key
64
- supSubsRequireOperand: true,
63
+ // Prevent excessive super/subscripts or fractions from being
64
+ // created without operands, e.g. when somebody holds down a key
65
+ supSubsRequireOperand: true,
65
66
 
66
- // The name of this option is somewhat misleading, as tabbing in
67
- // MathQuill breaks you out of a nested context (fraction/script)
68
- // if you're in one, but moves focus to the next input if you're
69
- // not. Spaces (with this option enabled) are just ignored in the
70
- // latter case.
71
- //
72
- // TODO(alex): In order to allow inputting mixed numbers, we will
73
- // have to accept spaces in certain cases. The desired behavior is
74
- // still to escape nested contexts if currently in one, but to
75
- // insert a space if not (we don't expect mixed numbers in nested
76
- // contexts). We should also limit to one consecutive space.
77
- spaceBehavesLikeTab: true,
78
- };
79
- }
67
+ // The name of this option is somewhat misleading, as tabbing in
68
+ // MathQuill breaks you out of a nested context (fraction/script)
69
+ // if you're in one, but moves focus to the next input if you're
70
+ // not. Spaces (with this option enabled) are just ignored in the
71
+ // latter case.
72
+ //
73
+ // TODO(alex): In order to allow inputting mixed numbers, we will
74
+ // have to accept spaces in certain cases. The desired behavior is
75
+ // still to escape nested contexts if currently in one, but to
76
+ // insert a space if not (we don't expect mixed numbers in nested
77
+ // contexts). We should also limit to one consecutive space.
78
+ spaceBehavesLikeTab: true,
79
+ });
80
80
 
81
81
  /**
82
82
  * Creates a new [MathField](http://docs.mathquill.com/en/latest/Api_Methods/#mqmathfieldhtml_element-config)
@@ -92,7 +92,7 @@ function createBaseConfig(): MathFieldConfig {
92
92
  export function createMathField(
93
93
  container: HTMLDivElement | HTMLSpanElement,
94
94
  configCallback?: (baseConfig: MathFieldConfig) => MathFieldConfig,
95
- ) {
95
+ ): MathFieldInterface {
96
96
  const baseConfig = createBaseConfig();
97
97
  const config = configCallback ? configCallback(baseConfig) : baseConfig;
98
98
 
@@ -1,346 +1,16 @@
1
1
  import type Key from "../../data/keys";
2
+ import type MathQuill from "mathquill";
2
3
 
3
- export interface MathQuillInterface {
4
- L: -1;
5
- R: 1;
4
+ export type MathQuillInterface = MathQuill.v3.API;
6
5
 
7
- /**
8
- * Creates an editable MathQuill initialized with the contents of the HTML
9
- * element and returns a MathField object.
10
- *
11
- * If the given element is already an editable math field, this will return
12
- * a new editable MathField object with the same `.id`. If the element is a
13
- * different type of MathQuill, this will return `null`.
14
- */
15
- MathField: (
16
- mount: HTMLDivElement | HTMLSpanElement,
17
- config: MathFieldConfig,
18
- ) => MathFieldInterface;
19
- }
20
-
21
- type MathQuillDirection = MathQuillInterface["L"] | MathQuillInterface["R"];
22
-
23
- export type MathFieldConfig = {
24
- /**
25
- * If spaceBehavesLikeTab is true the keystrokes {Shift-,}Spacebar will
26
- * behave like {Shift-,}Tab escaping from the current block (as opposed
27
- * to the default behavior of inserting a Space character).
28
- */
29
- spaceBehavesLikeTab?: boolean;
30
-
31
- /**
32
- * This allows you to change the way the left and right keys move the
33
- * cursor when there are items of different height, like fractions.
34
- *
35
- * By default, the Left and Right keys move the cursor through all
36
- * possible cursor positions in a particular order: right into a
37
- * fraction puts the cursor at the left end of the numerator, right out
38
- * of the numerator puts the cursor at the left end of the denominator,
39
- * and right out of the denominator puts the cursor to the right of the
40
- * fraction. Symmetrically, left into a fraction puts the cursor at the
41
- * right end of the denominator, etc.
42
- *
43
- * If instead you want right to always visually go right, and left to always go
44
- * visually left, you can set leftRightIntoCmdGoes to 'up' or 'down' so that
45
- * left and right go up or down (respectively) into commands. For example, 'up'
46
- * means that left into a fraction goes up into the numerator and right out of
47
- * the numerator skips the denominator and puts the cursor to the right of the
48
- * fraction. This behavior can be seen in the Desmos calculator. If this
49
- * property is set to 'down' instead, the numerator is harder to navigate to,
50
- * like in the Mac OS X built-in app Grapher.
51
- */
52
- leftRightIntoCmdGoes?: "up" | "down";
53
-
54
- /**
55
- * If restrictMismatchedBrackets is true then you can type [a,b) and
56
- * (a,b], but if you try typing [x} or \langle x|, you'll get [{x}] or
57
- * \langle|x|\rangle instead. This lets you type (|x|+1) normally;
58
- * otherwise, you'd get \left( \right| x \left| + 1 \right).
59
- */
60
- restrictMismatchedBrackets?: boolean;
61
-
62
- /**
63
- * If sumStartsWithNEquals is true then when you type \sum, \prod, or
64
- * \coprod, the lower limit starts out with n=, e.g. you get the LaTeX
65
- * \sum_{n=}^{ }, rather than empty by default.
66
- */
67
- sumStartsWithNEquals?: boolean;
68
-
69
- /**
70
- * supSubsRequireOperand disables typing of superscripts and subscripts
71
- * when there's nothing to the left of the cursor to be exponentiated
72
- * or subscripted. Prevents the especially confusing typo x^^2, which
73
- * looks much like x^2.
74
- */
75
- supSubsRequireOperand?: boolean;
76
-
77
- /**
78
- * charsThatBreakOutOfSupSub takes a string of the chars that when
79
- * typed, "break out" of superscripts and subscripts.
80
- *
81
- * Normally, to get out of a superscript or subscript, a user has to
82
- * navigate out of it with the directional keys, a mouse click, tab, or
83
- * Space if spaceBehavesLikeTab is true. For example, typing x^2n+y
84
- * normally results in the LaTeX x^{2n+y}. If you wanted to get the
85
- * LaTeX x^{2n}+y, the user would have to manually move the cursor out
86
- * of the exponent.
87
- *
88
- * If this option was set to '+-', + and - would "break out" of the
89
- * exponent. This doesn't apply to the first character in a superscript
90
- * or subscript, so typing x^-6 still results in x^{-6}. The downside
91
- * to setting this option is that in order to type x^{n+m}, a
92
- * workaround like typing x^(n+m and then deleting the ( is required.
93
- */
94
- charsThatBreakOutOfSupSub?: string;
95
-
96
- /**
97
- * :shrug: Undocumented except for being shown in an example for
98
- * configuration options.
99
- */
100
- autoSubscriptNumerals?: boolean;
101
-
102
- /**
103
- * autoCommands defines the set of commands automatically rendered by
104
- * just typing the letters without typing a backslash first.
105
- *
106
- * This takes a string formatted as a space-delimited list of LaTeX
107
- * commands. Each LaTeX command must be at least letters only with a
108
- * minimum length of 2 characters.
109
- *
110
- * For example, with autoCommands set to 'pi theta', the word 'pi'
111
- * automatically converts to the pi symbol and the word 'theta'
112
- * automatically converts to the theta symbol.
113
- */
114
- autoCommands?: string;
115
-
116
- /**
117
- * autoOperatorNames overrides the set of operator names that
118
- * automatically become non-italicized when typing the letters without
119
- * typing a backslash first, like sin, log, etc.
120
- *
121
- * This defaults to the LaTeX built-in operator names (Section 3.17 of
122
- * the Short Math Guide) with additional trig operators like sech,
123
- * arcsec, arsinh, etc. If you want some of these italicized after
124
- * setting this property, you will have to add them to the list.
125
- *
126
- * Just like autoCommands above, this takes a string formatted as a
127
- * space-delimited list of LaTeX commands.
128
- */
129
- autoOperatorNames?: string;
130
-
131
- /**
132
- * maxDepth specifies the maximum number of nested MathBlocks. When
133
- * maxDepth is set to 1, the user can type simple math symbols directly
134
- * into the editor but not into nested MathBlocks, e.g. the numerator
135
- * and denominator of a fraction.
136
- *
137
- * Nested content in latex rendered during initialization or pasted
138
- * into mathquill is truncated to avoid violating maxDepth. When
139
- * maxDepth is not set, no depth limit is applied by default.
140
- */
141
- maxDepth?: number;
142
-
143
- /**
144
- * substituteTextarea is a function that creates a focusable DOM
145
- * element that is called when setting up a math field. Overwriting
146
- * this may be useful for hacks like suppressing built-in virtual
147
- * keyboards. It defaults to <textarea autocorrect=off .../>.
148
- *
149
- * For example, Desmos substitutes <span tabindex=0></span> on iOS to
150
- * suppress the built-in virtual keyboard in favor of a custom math
151
- * keypad that calls the MathQuill API. Unfortunately there's no
152
- * universal check for a virtual keyboard or way to detect a
153
- * touchscreen, and even if you could, a touchscreen ≠ virtual keyboard
154
- * (Windows 8 and ChromeOS devices have both physical keyboards and
155
- * touchscreens and iOS and Android devices can have Bluetooth
156
- * keyboards). Desmos currently sniffs the user agent for iOS, so
157
- * Bluetooth keyboards just don't work in Desmos on iOS. The tradeoffs
158
- * are up to you.
159
- */
160
- substituteTextarea?: () => HTMLElement | undefined;
161
-
162
- /**
163
- * Handlers are called after a specified event. They are called
164
- * directly on the handlers object passed in, preserving the this value
165
- */
166
- handlers?: {
167
- edit?: (mathField: MathFieldInterface) => void;
168
- enter?: (mathField: MathFieldInterface) => void;
169
-
170
- moveOutOf?: (
171
- direction: MathQuillDirection,
172
- mathField: MathFieldInterface,
173
- ) => void;
174
- upOutOf?: (mathField: MathFieldInterface) => void;
175
- downOutOf?: (mathField: MathFieldInterface) => void;
176
-
177
- deleteOutOf?: (
178
- direction: MathQuillDirection,
179
- mathField: MathFieldInterface,
180
- ) => void;
181
- selectOutOf?: (
182
- direction: MathQuillDirection,
183
- mathField: MathFieldInterface,
184
- ) => void;
185
- };
186
- };
6
+ export type MathFieldConfig = MathQuill.v3.Config;
187
7
 
188
8
  /**
189
9
  * Editable math fields have all of the above methods in addition to
190
10
  * the ones listed here.
191
11
  * https://docs.mathquill.com/en/latest/Api_Methods/
192
12
  */
193
- export interface MathFieldInterface {
194
- /**
195
- * Any element that has been turned into a MathQuill instance can be
196
- * reverted.
197
- */
198
- revert: () => void;
199
-
200
- /**
201
- * MathQuill uses computed dimensions, so if they change (because an
202
- * element was mathquill-ified before it was in the visible HTML DOM, or
203
- * the font size changed), then you'll need to tell MathQuill to recomput
204
- */
205
- reflow: () => void;
206
-
207
- /** Returns the root HTML element. */
208
- el: () => HTMLElement;
209
-
210
- /**
211
- * Puts the focus on the editable field.
212
- * http://docs.mathquill.com/en/latest/Api_Methods/#focus
213
- */
214
- focus: () => MathFieldInterface;
215
-
216
- /**
217
- * Removes focus from the editable field.
218
- * http://docs.mathquill.com/en/latest/Api_Methods/#blur
219
- */
220
- blur: () => MathFieldInterface;
221
-
222
- /**
223
- * Write the given LaTeX at the current cursor position. If the
224
- * cursor does not have focus, writes to last position the cursor
225
- * occupied in the editable field.
226
- *
227
- * ```
228
- * // writes ' - 1' to mathField at the cursor position
229
- * mathField.write(' - 1');
230
- * ```
231
- *
232
- * https://docs.mathquill.com/en/latest/Api_Methods/#writelatex_string
233
- */
234
- write: (latex_string: string) => MathFieldInterface;
235
-
236
- /**
237
- * Enter a LaTeX command at the current cursor position or with the
238
- * current selection. If the cursor does not have focus, it writes it
239
- * to last position the cursor occupied in the editable field.
240
- *
241
- * ```
242
- * // writes a square root command at the cursor position
243
- * mathField.cmd('\\sqrt');
244
- * ```
245
- *
246
- * https://docs.mathquill.com/en/latest/Api_Methods/#cmdlatex_string
247
- */
248
- cmd: (latex_string: string) => MathFieldInterface;
249
-
250
- /**
251
- * Selects the contents (just like on textareas and on inputs).
252
- *
253
- * https://docs.mathquill.com/en/latest/Api_Methods/#select
254
- */
255
- select: () => void;
256
-
257
- /**
258
- * Clears the selection.
259
- *
260
- * https://docs.mathquill.com/en/latest/Api_Methods/#clearselection
261
- */
262
- clearSelection: () => void;
263
-
264
- /**
265
- * Move the cursor to the left end of the editable field. horthand
266
- * for .moveToDirEnd(L)
267
- */
268
- moveToLeftEnd: () => void;
269
-
270
- /**
271
- * Move the cursor to the right end of the editable field. horthand
272
- * for .moveToDirEnd(R)
273
- */
274
- moveToRightEnd: () => void;
275
-
276
- /**
277
- * Moves the cursor to the end of the mathfield in the direction
278
- * specified. The direction can be one of MQ.L or MQ.R. These are
279
- * constants, where MQ.L === -MQ.R and vice versa. This function
280
- * may be easier to use than moveToLeftEnd or moveToRightEnd if
281
- * used in the moveOutOf handler.
282
- *
283
- * https://docs.mathquill.com/en/latest/Api_Methods/#movetodirenddirection
284
- */
285
- moveToDirEnd: (direction: MathQuillDirection) => void;
286
-
287
- /**
288
- * Simulates keystrokes given a string like "Ctrl-Home Del", a
289
- * whitespace-delimited list of key inputs with optional prefixes.
290
- *
291
- * ```
292
- * mathField.keystroke('Shift-Left'); // Selects character before the current cursor position
293
- * ```
294
- *
295
- * https://docs.mathquill.com/en/latest/Api_Methods/#keystrokekeys
296
- */
297
- keystroke: (keys: string) => MathFieldInterface;
298
-
299
- /**
300
- * Simulates typing text, one character at a time from where the
301
- * cursor currently is. This is supposed to be identical to what
302
- * would happen if a user were typing the text in.
303
- *
304
- * Types part of the demo from mathquill.com without delays between keystrokes
305
- * ```
306
- * mathField.typedText('x=-b\\pm \\sqrt b^2 -4ac');
307
- * ```
308
- *
309
- * https://docs.mathquill.com/en/latest/Api_Methods/#typedtexttext
310
- */
311
- typedText: (text: string) => MathFieldInterface;
312
-
313
- /**
314
- * When called withot any pramaters, gets the contents as LaTeX
315
- * When passed a string, sets the contents as LaTeX
316
- *
317
- * https://docs.mathquill.com/en/latest/Api_Methods/#latex
318
- */
319
- latex: (input?: string) => string;
320
-
321
- /** Changes the configuration of just this math field. */
322
- config: (new_config: MathFieldConfig) => void;
323
-
324
- /**
325
- * KA Custom helper in our MathQuill fork check to see if cursor is on
326
- * right end
327
- */
328
- cursorAtRightEnd: () => boolean;
329
-
330
- /**
331
- * KA Custom helper in our MathQuill fork check to see if cursor is on left
332
- * end
333
- */
334
- cursorAtLeftEnd: () => boolean;
335
-
336
- /**
337
- * This isn't part of the MathQuill public API
338
- * I don't know what it is and it feels wrong using it
339
- *
340
- * @deprecated This is internal and shouldn't be used.
341
- */
342
- __controller: any;
343
- }
13
+ export type MathFieldInterface = MathQuill.v3.EditableMathQuill;
344
14
 
345
15
  export enum MathFieldActionType {
346
16
  WRITE = "write",
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  maybeFindCommand,
3
3
  maybeFindCommandBeforeParens,
4
- getCursor,
5
4
  } from "../input/mathquill-helpers";
6
5
  import {mathQuillInstance} from "../input/mathquill-instance";
7
6
  import {MathFieldActionType} from "../input/mathquill-types";
@@ -61,7 +60,7 @@ function handleRightArrow(
61
60
  }
62
61
 
63
62
  export default function handleArrow(mathField: MathFieldInterface, key: Key) {
64
- const cursor = getCursor(mathField);
63
+ const cursor = mathField.cursor();
65
64
 
66
65
  if (key === "LEFT") {
67
66
  handleLeftArrow(mathField, cursor);
@@ -6,7 +6,6 @@ import {
6
6
  isInsideLogIndex,
7
7
  isInsideEmptyNode,
8
8
  selectNode,
9
- getCursor,
10
9
  maybeFindCommandBeforeParens,
11
10
  } from "../input/mathquill-helpers";
12
11
  import {mathQuillInstance} from "../input/mathquill-instance";
@@ -52,7 +51,8 @@ function handleBackspaceInRootIndex(
52
51
 
53
52
  selectNode(grandparent, cursor);
54
53
 
55
- const rootIsEmpty = grandparent.blocks[1].jQ.text() === "";
54
+ const rootIsEmpty =
55
+ (grandparent.blocks[1]._el as HTMLElement).textContent === "";
56
56
 
57
57
  if (rootIsEmpty) {
58
58
  // If there is not content under the root then simply delete
@@ -70,7 +70,7 @@ function handleBackspaceInRootIndex(
70
70
 
71
71
  // Adjust the cursor to be to the left the sqrt.
72
72
  if (reinsertionPoint === MathFieldActionType.MQ_END) {
73
- mathField.moveToDirEnd(mathQuillInstance.L);
73
+ mathField.moveToLeftEnd();
74
74
  } else {
75
75
  cursor.insRightOf(reinsertionPoint);
76
76
  }
@@ -107,9 +107,8 @@ function handleBackspaceInLogIndex(
107
107
 
108
108
  cursor.select();
109
109
  cursor.endSelection();
110
-
111
110
  const isLogBodyEmpty =
112
- grandparent[mathQuillInstance.R].contentjQ.text() === "";
111
+ grandparent[mathQuillInstance.R]._el.textContent === "";
113
112
 
114
113
  if (isLogBodyEmpty) {
115
114
  // If there's no content inside the log's parens then delete the
@@ -198,7 +197,7 @@ function handleBackspaceInsideParens(
198
197
 
199
198
  if (grandparent[mathQuillInstance.L].sub) {
200
199
  // if there is a subscript
201
- if (grandparent[mathQuillInstance.L].sub.jQ.text()) {
200
+ if (grandparent[mathQuillInstance.L].sub._el.textContent) {
202
201
  // and it contains text
203
202
  // move the cursor to the right end of the subscript
204
203
  cursor.insAtRightEnd(grandparent[mathQuillInstance.L].sub);
@@ -237,7 +236,7 @@ function handleBackspaceAfterLigaturedSymbol(mathField: MathFieldInterface) {
237
236
  * See inline comments for precise behavior of different cases.
238
237
  */
239
238
  function handleBackspace(mathField: MathFieldInterface) {
240
- const cursor = getCursor(mathField);
239
+ const cursor = mathField.cursor();
241
240
  if (!cursor.selection) {
242
241
  const parent = cursor.parent;
243
242
  const grandparent = parent.parent;
@@ -1,4 +1,3 @@
1
- import {getCursor} from "../input/mathquill-helpers";
2
1
  import {mathQuillInstance} from "../input/mathquill-instance";
3
2
  import {MathFieldActionType} from "../input/mathquill-types";
4
3
 
@@ -12,7 +11,7 @@ export default function handleExponent(
12
11
  mathField: MathFieldInterface,
13
12
  key: Key,
14
13
  ) {
15
- const cursor = getCursor(mathField);
14
+ const cursor = mathField.cursor();
16
15
  // If there's an invalid operator preceding the cursor (anything that
17
16
  // knowingly cannot be raised to a power), add an empty set of
18
17
  // parentheses and apply the exponent to that.
@@ -3,7 +3,6 @@ import {
3
3
  isFraction,
4
4
  isParens,
5
5
  getCursorContext,
6
- getCursor,
7
6
  } from "../input/mathquill-helpers";
8
7
  import {mathQuillInstance} from "../input/mathquill-instance";
9
8
  import {MathFieldActionType} from "../input/mathquill-types";
@@ -24,7 +23,7 @@ const KeysForJumpContext = {
24
23
  * Advances the cursor to the next logical position.
25
24
  */
26
25
  function handleJumpOut(mathField: MathFieldInterface, key: Key): void {
27
- const cursor = getCursor(mathField);
26
+ const cursor = mathField.cursor();
28
27
  const context = getCursorContext(mathField);
29
28
 
30
29
  // Validate that the current cursor context matches the key's intent.
@@ -106,7 +106,7 @@ const keyToMathquillMap: Record<Key, MathFieldUpdaterCallback> = {
106
106
  },
107
107
 
108
108
  FRAC_EXCLUSIVE: (mathQuill) => {
109
- const cursor = mathQuill.__controller.cursor;
109
+ const cursor = mathQuill.cursor();
110
110
  // If there's nothing to the left of the cursor, then we want to
111
111
  // leave the cursor to the left of the fraction after creating it.
112
112
  const shouldNavigateLeft =
@@ -140,7 +140,9 @@ describe("Keypad v2 with MathQuill", () => {
140
140
  userEvent.click(screen.getByRole("button", {name: "Square"}));
141
141
 
142
142
  // Assert
143
- expect(mockMathInputCallback).toHaveBeenLastCalledWith("a^2+b^2=c^2");
143
+ expect(mockMathInputCallback).toHaveBeenLastCalledWith(
144
+ "a^{2}+b^{2}=c^{2}",
145
+ );
144
146
  });
145
147
 
146
148
  it("can write the Pythagorean theorem (complex)", () => {
@@ -177,7 +179,7 @@ describe("Keypad v2 with MathQuill", () => {
177
179
 
178
180
  // Assert
179
181
  expect(mockMathInputCallback).toHaveBeenLastCalledWith(
180
- "c=\\sqrt{a^2+b^2}",
182
+ "c=\\sqrt{a^{2}+b^{2}}",
181
183
  );
182
184
  });
183
185
 
@@ -202,10 +204,12 @@ describe("Keypad v2 with MathQuill", () => {
202
204
  userEvent.click(screen.getByRole("button", {name: "b"}));
203
205
  userEvent.click(screen.getByRole("tab", {name: "Operators"}));
204
206
  userEvent.click(screen.getByRole("button", {name: "Square"}));
205
- userEvent.type(screen.getByRole("textbox"), "=c^2");
207
+ userEvent.type(screen.getByRole("textbox"), "=c^{2}");
206
208
 
207
209
  // Assert
208
- expect(mockMathInputCallback).toHaveBeenLastCalledWith("a^2+b^2=c^2");
210
+ expect(mockMathInputCallback).toHaveBeenLastCalledWith(
211
+ "a^{2}+b^{2}=c^{2}",
212
+ );
209
213
  });
210
214
 
211
215
  it("deletes from the input using the backspace button", () => {
@@ -242,7 +246,9 @@ describe("Keypad v2 with MathQuill", () => {
242
246
 
243
247
  // Assert
244
248
  // make sure the formula was typed correctly
245
- expect(mockMathInputCallback).toHaveBeenLastCalledWith("a^2+b^2=c^2");
249
+ expect(mockMathInputCallback).toHaveBeenLastCalledWith(
250
+ "a^{2}+b^{2}=c^{2}",
251
+ );
246
252
 
247
253
  userEvent.click(screen.getByRole("tab", {name: "Numbers"}));
248
254
  // delete: need 14 backspaces in MathQuill to delete `a^2+b^2=c^2`