@khanacademy/math-input 4.1.0 → 4.2.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 +18 -0
- package/dist/components/input/math-wrapper.d.ts +1 -1
- package/dist/components/input/math-wrapper.js.flow +1 -1
- package/dist/components/input/mathquill-instance.d.ts +14 -3
- package/dist/components/input/mathquill-instance.js.flow +18 -3
- package/dist/components/input/mathquill-types.d.ts +28 -6
- package/dist/components/input/mathquill-types.js.flow +31 -7
- package/dist/components/key-handlers/handle-arrow.d.ts +3 -0
- package/dist/components/{input/key-handlers → key-handlers}/handle-arrow.js.flow +2 -2
- package/dist/components/{input/key-handlers → key-handlers}/handle-backspace.d.ts +1 -1
- package/dist/components/{input/key-handlers → key-handlers}/handle-backspace.js.flow +1 -1
- package/dist/components/key-handlers/handle-exponent.d.ts +3 -0
- package/dist/components/{input/key-handlers → key-handlers}/handle-exponent.js.flow +2 -2
- package/dist/components/{input/key-handlers → key-handlers}/handle-jump-out.d.ts +2 -2
- package/dist/components/{input/key-handlers → key-handlers}/handle-jump-out.js.flow +2 -2
- package/dist/components/key-handlers/key-translator.d.ts +4 -0
- package/dist/components/{key-translator.js.flow → key-handlers/key-translator.js.flow} +3 -3
- package/dist/components/keypad/geometry-page/index.d.ts +2 -1
- package/dist/components/keypad/geometry-page/index.js.flow +2 -1
- package/dist/components/keypad/index.d.ts +2 -1
- package/dist/components/keypad/index.js.flow +2 -1
- package/dist/components/keypad/keypad-page-items.d.ts +8 -16
- package/dist/components/keypad/keypad-page-items.js.flow +11 -16
- package/dist/components/keypad/numbers-page/index.d.ts +2 -1
- package/dist/components/keypad/numbers-page/index.js.flow +2 -1
- package/dist/components/keypad/operators-page/advanced-relations-buttons.d.ts +2 -1
- package/dist/components/keypad/operators-page/advanced-relations-buttons.js.flow +2 -1
- package/dist/components/keypad/operators-page/basic-relations-buttons.d.ts +2 -1
- package/dist/components/keypad/operators-page/basic-relations-buttons.js.flow +2 -1
- package/dist/components/keypad/operators-page/index.d.ts +2 -1
- package/dist/components/keypad/operators-page/index.js.flow +2 -1
- package/dist/components/keypad/operators-page/logarithms-buttons.d.ts +2 -1
- package/dist/components/keypad/operators-page/logarithms-buttons.js.flow +2 -1
- package/dist/components/keypad/operators-page/pre-algebra-buttons.d.ts +2 -1
- package/dist/components/keypad/operators-page/pre-algebra-buttons.js.flow +2 -1
- package/dist/es/index.js +395 -366
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +398 -367
- package/dist/index.js.flow +6 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.js.flow +1 -0
- package/package.json +1 -1
- package/src/components/input/math-input.tsx +10 -14
- package/src/components/input/math-wrapper.ts +23 -49
- package/src/components/input/mathquill-helpers.ts +11 -11
- package/src/components/input/mathquill-instance.ts +57 -2
- package/src/components/input/mathquill-types.ts +37 -7
- package/src/components/{input/key-handlers → key-handlers}/handle-arrow.ts +6 -6
- package/src/components/{input/key-handlers → key-handlers}/handle-backspace.ts +19 -17
- package/src/components/{input/key-handlers → key-handlers}/handle-exponent.ts +8 -5
- package/src/components/{input/key-handlers → key-handlers}/handle-jump-out.ts +15 -10
- package/src/components/{key-translator.ts → key-handlers/key-translator.ts} +43 -28
- package/src/components/keypad/__tests__/Button.test.tsx +51 -0
- package/src/components/keypad/__tests__/keypad-button.test.tsx +41 -0
- package/src/components/keypad/__tests__/keypad-v2-mathquill.test.tsx +231 -0
- package/src/components/keypad/__tests__/keypad-v2.cypress.ts +46 -0
- package/src/components/keypad/geometry-page/index.tsx +2 -1
- package/src/components/keypad/index.tsx +2 -1
- package/src/components/keypad/keypad-mathquill.stories.tsx +15 -23
- package/src/components/keypad/keypad-page-items.tsx +10 -19
- package/src/components/keypad/numbers-page/index.tsx +2 -1
- package/src/components/keypad/operators-page/advanced-relations-buttons.tsx +2 -1
- package/src/components/keypad/operators-page/basic-relations-buttons.tsx +2 -1
- package/src/components/keypad/operators-page/index.tsx +2 -1
- package/src/components/keypad/operators-page/logarithms-buttons.tsx +2 -1
- package/src/components/keypad/operators-page/pre-algebra-buttons.tsx +2 -1
- package/src/index.ts +6 -1
- package/src/types.ts +2 -0
- package/tsconfig-build.json +1 -2
- package/tsconfig-build.tsbuildinfo +1 -1
- package/dist/components/input/__tests__/test-math-wrapper.d.ts +0 -8
- package/dist/components/input/__tests__/test-math-wrapper.js.flow +0 -14
- package/dist/components/input/key-handlers/handle-arrow.d.ts +0 -3
- package/dist/components/input/key-handlers/handle-exponent.d.ts +0 -3
- package/dist/components/key-translator.d.ts +0 -4
package/dist/types.d.ts
CHANGED
package/dist/types.js.flow
CHANGED
package/package.json
CHANGED
|
@@ -87,21 +87,17 @@ class MathInput extends React.Component<Props, State> {
|
|
|
87
87
|
componentDidMount() {
|
|
88
88
|
this._isMounted = true;
|
|
89
89
|
|
|
90
|
-
this.mathField = new MathWrapper(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// to make this input keypad-agnostic.
|
|
100
|
-
this.props.keypadElement &&
|
|
101
|
-
this.props.keypadElement.setCursor(cursor);
|
|
102
|
-
},
|
|
90
|
+
this.mathField = new MathWrapper(this._mathContainer, {
|
|
91
|
+
onCursorMove: (cursor: Cursor) => {
|
|
92
|
+
// TODO(charlie): It's not great that there is so much coupling
|
|
93
|
+
// between this keypad and the input behavior. We should wrap
|
|
94
|
+
// this `MathInput` component in an intermediary component
|
|
95
|
+
// that translates accesses on the keypad into vanilla props,
|
|
96
|
+
// to make this input keypad-agnostic.
|
|
97
|
+
this.props.keypadElement &&
|
|
98
|
+
this.props.keypadElement.setCursor(cursor);
|
|
103
99
|
},
|
|
104
|
-
);
|
|
100
|
+
});
|
|
105
101
|
|
|
106
102
|
// NOTE(charlie): MathQuill binds this handler to manage its
|
|
107
103
|
// drag-to-select behavior. For reasons that I can't explain, the event
|
|
@@ -18,58 +18,30 @@ import $ from "jquery";
|
|
|
18
18
|
|
|
19
19
|
import Key from "../../data/keys";
|
|
20
20
|
import {Cursor} from "../../types";
|
|
21
|
-
import
|
|
21
|
+
import handleBackspace from "../key-handlers/handle-backspace";
|
|
22
|
+
import keyTranslator from "../key-handlers/key-translator";
|
|
22
23
|
|
|
23
|
-
import handleArrow from "./key-handlers/handle-arrow";
|
|
24
|
-
import handleBackspace from "./key-handlers/handle-backspace";
|
|
25
|
-
import handleExponent from "./key-handlers/handle-exponent";
|
|
26
|
-
import handleJumpOut from "./key-handlers/handle-jump-out";
|
|
27
24
|
import {
|
|
28
25
|
getCursor,
|
|
29
26
|
contextForCursor,
|
|
30
27
|
maybeFindCommand,
|
|
31
28
|
} from "./mathquill-helpers";
|
|
32
|
-
import
|
|
29
|
+
import {createMathField, mathQuillInstance} from "./mathquill-instance";
|
|
33
30
|
import {
|
|
34
31
|
MathFieldInterface,
|
|
35
32
|
MathFieldCursor,
|
|
36
|
-
|
|
33
|
+
MathFieldUpdaterCallback,
|
|
37
34
|
} from "./mathquill-types";
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
return function (mathField: MathFieldInterface) {
|
|
41
|
-
mathField.write(`\\${command}\\left(\\right)`);
|
|
42
|
-
mathField.keystroke("Left");
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const customKeyTranslator: Record<Key, MathQuillUpdaterCallback> = {
|
|
36
|
+
const mobileKeyTranslator: Record<Key, MathFieldUpdaterCallback> = {
|
|
47
37
|
...keyTranslator,
|
|
48
|
-
// note(Matthew):
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
38
|
+
// note(Matthew): our mobile backspace logic is really complicated
|
|
39
|
+
// and for some reason doesn't really work in the desktop experience.
|
|
40
|
+
// So we default to the basic backspace functionality in the
|
|
41
|
+
// key translator and overwrite it with the complicated logic here
|
|
42
|
+
// until we can unify the experiences (if we even want to).
|
|
43
|
+
// https://khanacademy.atlassian.net/browse/LC-906
|
|
53
44
|
BACKSPACE: handleBackspace,
|
|
54
|
-
EXP: handleExponent,
|
|
55
|
-
EXP_2: handleExponent,
|
|
56
|
-
EXP_3: handleExponent,
|
|
57
|
-
FRAC: (mathQuill) => {
|
|
58
|
-
mathQuill.cmd("\\frac");
|
|
59
|
-
},
|
|
60
|
-
JUMP_OUT_PARENTHESES: handleJumpOut,
|
|
61
|
-
JUMP_OUT_EXPONENT: handleJumpOut,
|
|
62
|
-
JUMP_OUT_BASE: handleJumpOut,
|
|
63
|
-
JUMP_INTO_NUMERATOR: handleJumpOut,
|
|
64
|
-
JUMP_OUT_NUMERATOR: handleJumpOut,
|
|
65
|
-
JUMP_OUT_DENOMINATOR: handleJumpOut,
|
|
66
|
-
LEFT: handleArrow,
|
|
67
|
-
RIGHT: handleArrow,
|
|
68
|
-
LOG: buildNormalFunctionCallback("log"),
|
|
69
|
-
LN: buildNormalFunctionCallback("ln"),
|
|
70
|
-
SIN: buildNormalFunctionCallback("sin"),
|
|
71
|
-
COS: buildNormalFunctionCallback("cos"),
|
|
72
|
-
TAN: buildNormalFunctionCallback("tan"),
|
|
73
45
|
};
|
|
74
46
|
|
|
75
47
|
/**
|
|
@@ -78,16 +50,18 @@ const customKeyTranslator: Record<Key, MathQuillUpdaterCallback> = {
|
|
|
78
50
|
* from MathQuill changes.
|
|
79
51
|
*/
|
|
80
52
|
class MathWrapper {
|
|
81
|
-
mathField: MathFieldInterface; // MathQuill input
|
|
53
|
+
mathField: MathFieldInterface; // MathQuill MathField input
|
|
82
54
|
callbacks: any;
|
|
83
55
|
|
|
84
|
-
constructor(element,
|
|
85
|
-
this.mathField =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
56
|
+
constructor(element, callbacks = {}) {
|
|
57
|
+
this.mathField = createMathField(element, () => {
|
|
58
|
+
return {
|
|
59
|
+
// use a span instead of a textarea so that we don't bring up the
|
|
60
|
+
// native keyboard on mobile when selecting the input
|
|
61
|
+
substituteTextarea: function () {
|
|
62
|
+
return document.createElement("span");
|
|
63
|
+
},
|
|
64
|
+
};
|
|
91
65
|
});
|
|
92
66
|
this.callbacks = callbacks;
|
|
93
67
|
}
|
|
@@ -119,7 +93,7 @@ class MathWrapper {
|
|
|
119
93
|
*/
|
|
120
94
|
pressKey(key: Key): Cursor {
|
|
121
95
|
const cursor = this.getCursor();
|
|
122
|
-
const translator =
|
|
96
|
+
const translator = mobileKeyTranslator[key];
|
|
123
97
|
|
|
124
98
|
if (translator) {
|
|
125
99
|
translator(this.mathField, key);
|
|
@@ -173,7 +147,7 @@ class MathWrapper {
|
|
|
173
147
|
// Unless that would leave us mid-command, in which case, we
|
|
174
148
|
// need to adjust and place the cursor inside the parens
|
|
175
149
|
// following the command.
|
|
176
|
-
const command = maybeFindCommand(cursor[
|
|
150
|
+
const command = maybeFindCommand(cursor[mathQuillInstance.L]);
|
|
177
151
|
if (command && command.endNode) {
|
|
178
152
|
// NOTE(charlie): endNode should definitely be \left(.
|
|
179
153
|
cursor.insLeftOf(command.endNode);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {CursorContext} from "./cursor-contexts";
|
|
2
|
-
import
|
|
2
|
+
import {mathQuillInstance} from "./mathquill-instance";
|
|
3
3
|
import {
|
|
4
4
|
MathFieldActionType,
|
|
5
5
|
MathFieldCursor,
|
|
@@ -126,8 +126,8 @@ export function isInsideLogIndex(cursor: MathFieldCursor): boolean {
|
|
|
126
126
|
|
|
127
127
|
export function isInsideEmptyNode(cursor: MathFieldCursor): boolean {
|
|
128
128
|
return (
|
|
129
|
-
cursor[
|
|
130
|
-
cursor[
|
|
129
|
+
cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END &&
|
|
130
|
+
cursor[mathQuillInstance.R] === MathFieldActionType.MQ_END
|
|
131
131
|
);
|
|
132
132
|
}
|
|
133
133
|
|
|
@@ -191,7 +191,7 @@ export function maybeFindCommand(initialNode) {
|
|
|
191
191
|
break;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
node = node[
|
|
194
|
+
node = node[mathQuillInstance.L];
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
// If we hit the start of a command, then grab the rest of it by
|
|
@@ -199,7 +199,7 @@ export function maybeFindCommand(initialNode) {
|
|
|
199
199
|
// with its terminal node.
|
|
200
200
|
if (startNode) {
|
|
201
201
|
// Next, iterate from the start to the right.
|
|
202
|
-
node = initialNode[
|
|
202
|
+
node = initialNode[mathQuillInstance.R];
|
|
203
203
|
while (node !== 0) {
|
|
204
204
|
const ctrlSeq = node.ctrlSeq.trim();
|
|
205
205
|
if (commandCharRegex.test(ctrlSeq)) {
|
|
@@ -213,7 +213,7 @@ export function maybeFindCommand(initialNode) {
|
|
|
213
213
|
break;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
node = node[
|
|
216
|
+
node = node[mathQuillInstance.R];
|
|
217
217
|
}
|
|
218
218
|
if (validCommands.includes(name)) {
|
|
219
219
|
return {name, startNode, endNode};
|
|
@@ -235,19 +235,19 @@ export function maybeFindCommand(initialNode) {
|
|
|
235
235
|
* name (`name`) of the command
|
|
236
236
|
*/
|
|
237
237
|
export function maybeFindCommandBeforeParens(leftParenNode) {
|
|
238
|
-
return maybeFindCommand(leftParenNode[
|
|
238
|
+
return maybeFindCommand(leftParenNode[mathQuillInstance.L]);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
export function contextForCursor(cursor: MathFieldCursor): CursorContext {
|
|
242
242
|
// First, try to find any fraction to the right, unimpeded.
|
|
243
243
|
let visitor = cursor;
|
|
244
|
-
while (visitor[
|
|
245
|
-
if (isFraction(visitor[
|
|
244
|
+
while (visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
245
|
+
if (isFraction(visitor[mathQuillInstance.R])) {
|
|
246
246
|
return CursorContext.BEFORE_FRACTION;
|
|
247
|
-
} else if (!isLeaf(visitor[
|
|
247
|
+
} else if (!isLeaf(visitor[mathQuillInstance.R])) {
|
|
248
248
|
break;
|
|
249
249
|
}
|
|
250
|
-
visitor = visitor[
|
|
250
|
+
visitor = visitor[mathQuillInstance.R];
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
// If that didn't work, check if the parent or grandparent is a special
|
|
@@ -1,5 +1,60 @@
|
|
|
1
1
|
import MathQuill from "mathquill";
|
|
2
2
|
|
|
3
|
-
import {MathQuillInterface} from "./mathquill-types";
|
|
3
|
+
import {MathQuillInterface, MathFieldConfig} from "./mathquill-types";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// We only need one MathQuill instance (referred to as MQ in the docs)
|
|
6
|
+
// and that contains some MQ constants and the MathField constructor
|
|
7
|
+
export const mathQuillInstance = MathQuill.getInterface(
|
|
8
|
+
2,
|
|
9
|
+
) as MathQuillInterface;
|
|
10
|
+
|
|
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
|
+
|
|
18
|
+
// Pop the cursor out of super/subscripts on arithmetic operators
|
|
19
|
+
// or (in)equalities.
|
|
20
|
+
charsThatBreakOutOfSupSub: "+-*/=<>≠≤≥",
|
|
21
|
+
|
|
22
|
+
// Prevent excessive super/subscripts or fractions from being
|
|
23
|
+
// created without operands, e.g. when somebody holds down a key
|
|
24
|
+
supSubsRequireOperand: true,
|
|
25
|
+
|
|
26
|
+
// The name of this option is somewhat misleading, as tabbing in
|
|
27
|
+
// MathQuill breaks you out of a nested context (fraction/script)
|
|
28
|
+
// if you're in one, but moves focus to the next input if you're
|
|
29
|
+
// not. Spaces (with this option enabled) are just ignored in the
|
|
30
|
+
// latter case.
|
|
31
|
+
//
|
|
32
|
+
// TODO(alex): In order to allow inputting mixed numbers, we will
|
|
33
|
+
// have to accept spaces in certain cases. The desired behavior is
|
|
34
|
+
// still to escape nested contexts if currently in one, but to
|
|
35
|
+
// insert a space if not (we don't expect mixed numbers in nested
|
|
36
|
+
// contexts). We should also limit to one consecutive space.
|
|
37
|
+
spaceBehavesLikeTab: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new [MathField](http://docs.mathquill.com/en/latest/Api_Methods/#mqmathfieldhtml_element-config)
|
|
43
|
+
* instance within the given `container`.
|
|
44
|
+
*
|
|
45
|
+
* An optional configuration callback can be provided to customize
|
|
46
|
+
* the created MathField. A default configuration is passed to this
|
|
47
|
+
* callback which can then be adjusted as needed. The configuration
|
|
48
|
+
* returned from this callback is used to create the MathField.
|
|
49
|
+
* This allows callers to do minimal configuration as only configs
|
|
50
|
+
* that vary from the default need to be provided.
|
|
51
|
+
*/
|
|
52
|
+
export function createMathField(
|
|
53
|
+
container: HTMLDivElement | HTMLSpanElement,
|
|
54
|
+
configCallback?: (baseConfig: MathFieldConfig) => MathFieldConfig,
|
|
55
|
+
) {
|
|
56
|
+
const baseConfig = createBaseConfig();
|
|
57
|
+
const config = configCallback ? configCallback(baseConfig) : baseConfig;
|
|
58
|
+
|
|
59
|
+
return mathQuillInstance.MathField(container, config);
|
|
60
|
+
}
|
|
@@ -3,22 +3,52 @@ import Key from "../../data/keys";
|
|
|
3
3
|
export interface MathQuillInterface {
|
|
4
4
|
L: "L";
|
|
5
5
|
R: "R";
|
|
6
|
-
MathField: (
|
|
6
|
+
MathField: (
|
|
7
|
+
mount: HTMLDivElement | HTMLSpanElement,
|
|
8
|
+
config: MathFieldConfig,
|
|
9
|
+
) => MathFieldInterface;
|
|
7
10
|
}
|
|
8
11
|
|
|
12
|
+
type MathQuillDir = "L" | "R";
|
|
13
|
+
|
|
14
|
+
export type MathFieldConfig = {
|
|
15
|
+
spaceBehavesLikeTab?: boolean;
|
|
16
|
+
leftRightIntoCmdGoes?: string;
|
|
17
|
+
restrictMismatchedBrackets?: boolean;
|
|
18
|
+
sumStartsWithNEquals?: boolean;
|
|
19
|
+
supSubsRequireOperand?: boolean;
|
|
20
|
+
charsThatBreakOutOfSupSub?: string;
|
|
21
|
+
autoSubscriptNumerals?: boolean;
|
|
22
|
+
autoCommands?: string;
|
|
23
|
+
autoOperatorNames?: string;
|
|
24
|
+
maxDepth?: number;
|
|
25
|
+
substituteTextarea?: () => HTMLElement;
|
|
26
|
+
handlers?: {
|
|
27
|
+
edit?: (mathField: MathFieldInterface) => void;
|
|
28
|
+
upOutOf?: (mathField: MathFieldInterface) => void;
|
|
29
|
+
moveOutOf?: (dir: MathQuillDir, mathField: MathFieldInterface) => void;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
9
33
|
export interface MathFieldInterface {
|
|
34
|
+
// Puts the focus on the editable field.
|
|
35
|
+
// http://docs.mathquill.com/en/latest/Api_Methods/#focus
|
|
36
|
+
focus: () => MathFieldInterface;
|
|
37
|
+
// Removes focus from the editable field.
|
|
38
|
+
// http://docs.mathquill.com/en/latest/Api_Methods/#blur
|
|
39
|
+
blur: () => MathFieldInterface;
|
|
10
40
|
// Write LaTeX
|
|
11
41
|
// https://docs.mathquill.com/en/latest/Api_Methods/#writelatex_string
|
|
12
|
-
write: (input: string) =>
|
|
42
|
+
write: (input: string) => MathFieldInterface;
|
|
13
43
|
// Enter a LaTeX command
|
|
14
44
|
// https://docs.mathquill.com/en/latest/Api_Methods/#cmdlatex_string
|
|
15
|
-
cmd: (input: string) =>
|
|
45
|
+
cmd: (input: string) => MathFieldInterface;
|
|
16
46
|
// Simulates keystrokes given a string like "Ctrl-Home Del"
|
|
17
47
|
// https://docs.mathquill.com/en/latest/Api_Methods/#keystrokekeys
|
|
18
|
-
keystroke: (input: string) =>
|
|
48
|
+
keystroke: (input: string) => MathFieldInterface;
|
|
19
49
|
// Simulates typing text, one character at a time
|
|
20
50
|
// https://docs.mathquill.com/en/latest/Api_Methods/#typedtexttext
|
|
21
|
-
typedText: (input: string) =>
|
|
51
|
+
typedText: (input: string) => MathFieldInterface;
|
|
22
52
|
// () => {}: Gets the contents as LaTeX
|
|
23
53
|
// (string) => {}: Sets the contents as LaTeX
|
|
24
54
|
// https://docs.mathquill.com/en/latest/Api_Methods/#latex
|
|
@@ -49,7 +79,7 @@ export enum MathFieldActionType {
|
|
|
49
79
|
// we reach into the internals to get it
|
|
50
80
|
export type MathFieldCursor = any;
|
|
51
81
|
|
|
52
|
-
export type
|
|
53
|
-
|
|
82
|
+
export type MathFieldUpdaterCallback = (
|
|
83
|
+
mathField: MathFieldInterface,
|
|
54
84
|
key: Key,
|
|
55
85
|
) => void;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import Key from "
|
|
1
|
+
import Key from "../../data/keys";
|
|
2
2
|
import {
|
|
3
3
|
maybeFindCommand,
|
|
4
4
|
maybeFindCommandBeforeParens,
|
|
5
5
|
getCursor,
|
|
6
|
-
} from "../mathquill-helpers";
|
|
7
|
-
import
|
|
6
|
+
} from "../input/mathquill-helpers";
|
|
7
|
+
import {mathQuillInstance} from "../input/mathquill-instance";
|
|
8
8
|
import {
|
|
9
9
|
MathFieldInterface,
|
|
10
10
|
MathFieldActionType,
|
|
11
11
|
MathFieldCursor,
|
|
12
|
-
} from "../mathquill-types";
|
|
12
|
+
} from "../input/mathquill-types";
|
|
13
13
|
|
|
14
14
|
function handleLeftArrow(
|
|
15
15
|
mathField: MathFieldInterface,
|
|
@@ -25,7 +25,7 @@ function handleLeftArrow(
|
|
|
25
25
|
// the ActionType.MQ_END node, that our grandparent is the left parenthesis, and
|
|
26
26
|
// the nodes to the left of our grandparent comprise a valid function
|
|
27
27
|
// name.
|
|
28
|
-
if (cursor[
|
|
28
|
+
if (cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END) {
|
|
29
29
|
const parent = cursor.parent;
|
|
30
30
|
const grandparent = parent.parent;
|
|
31
31
|
if (grandparent.ctrlSeq === "\\left(") {
|
|
@@ -45,7 +45,7 @@ function handleRightArrow(
|
|
|
45
45
|
mathField: MathFieldInterface,
|
|
46
46
|
cursor: MathFieldCursor,
|
|
47
47
|
) {
|
|
48
|
-
const command = maybeFindCommand(cursor[
|
|
48
|
+
const command = maybeFindCommand(cursor[mathQuillInstance.R]);
|
|
49
49
|
if (command) {
|
|
50
50
|
// Similarly, if a function is to our right, then we need to place
|
|
51
51
|
// the cursor at the start of its parenthetical content, which is
|
|
@@ -8,19 +8,20 @@ import {
|
|
|
8
8
|
selectNode,
|
|
9
9
|
getCursor,
|
|
10
10
|
maybeFindCommandBeforeParens,
|
|
11
|
-
} from "../mathquill-helpers";
|
|
12
|
-
import
|
|
11
|
+
} from "../input/mathquill-helpers";
|
|
12
|
+
import {mathQuillInstance} from "../input/mathquill-instance";
|
|
13
13
|
import {
|
|
14
14
|
MathFieldActionType,
|
|
15
15
|
MathFieldInterface,
|
|
16
16
|
MathFieldCursor,
|
|
17
|
-
} from "../mathquill-types";
|
|
17
|
+
} from "../input/mathquill-types";
|
|
18
18
|
|
|
19
19
|
function handleBackspaceInNthRoot(
|
|
20
20
|
mathField: MathFieldInterface,
|
|
21
21
|
cursor: MathFieldCursor,
|
|
22
22
|
) {
|
|
23
|
-
const isAtLeftEnd =
|
|
23
|
+
const isAtLeftEnd =
|
|
24
|
+
cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END;
|
|
24
25
|
|
|
25
26
|
const isRootEmpty = isInsideEmptyNode(cursor.parent.parent.blocks[0].ends);
|
|
26
27
|
|
|
@@ -46,7 +47,7 @@ function handleBackspaceInRootIndex(
|
|
|
46
47
|
|
|
47
48
|
const grandparent = cursor.parent.parent;
|
|
48
49
|
const latex = grandparent.latex();
|
|
49
|
-
const reinsertionPoint = grandparent[
|
|
50
|
+
const reinsertionPoint = grandparent[mathQuillInstance.L];
|
|
50
51
|
|
|
51
52
|
selectNode(grandparent, cursor);
|
|
52
53
|
|
|
@@ -68,13 +69,13 @@ function handleBackspaceInRootIndex(
|
|
|
68
69
|
|
|
69
70
|
// Adjust the cursor to be to the left the sqrt.
|
|
70
71
|
if (reinsertionPoint === MathFieldActionType.MQ_END) {
|
|
71
|
-
mathField.moveToDirEnd(
|
|
72
|
+
mathField.moveToDirEnd(mathQuillInstance.L);
|
|
72
73
|
} else {
|
|
73
74
|
cursor.insRightOf(reinsertionPoint);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
} else {
|
|
77
|
-
if (cursor[
|
|
78
|
+
if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
|
|
78
79
|
// If the cursor is not at the leftmost position inside the
|
|
79
80
|
// root's index, delete a character.
|
|
80
81
|
mathField.keystroke("Backspace");
|
|
@@ -97,8 +98,8 @@ function handleBackspaceInLogIndex(
|
|
|
97
98
|
cursor.insLeftOf(command?.startNode);
|
|
98
99
|
cursor.startSelection();
|
|
99
100
|
|
|
100
|
-
if (grandparent[
|
|
101
|
-
cursor.insRightOf(grandparent[
|
|
101
|
+
if (grandparent[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
102
|
+
cursor.insRightOf(grandparent[mathQuillInstance.R]);
|
|
102
103
|
} else {
|
|
103
104
|
cursor.insRightOf(grandparent);
|
|
104
105
|
}
|
|
@@ -106,7 +107,8 @@ function handleBackspaceInLogIndex(
|
|
|
106
107
|
cursor.select();
|
|
107
108
|
cursor.endSelection();
|
|
108
109
|
|
|
109
|
-
const isLogBodyEmpty =
|
|
110
|
+
const isLogBodyEmpty =
|
|
111
|
+
grandparent[mathQuillInstance.R].contentjQ.text() === "";
|
|
110
112
|
|
|
111
113
|
if (isLogBodyEmpty) {
|
|
112
114
|
// If there's no content inside the log's parens then delete the
|
|
@@ -127,8 +129,8 @@ function handleBackspaceOutsideParens(cursor: MathFieldCursor) {
|
|
|
127
129
|
// (x+1)| => |(x+1)|
|
|
128
130
|
// \log(x+1)| => |\log(x+1)|
|
|
129
131
|
|
|
130
|
-
const leftNode = cursor[
|
|
131
|
-
const rightNode = cursor[
|
|
132
|
+
const leftNode = cursor[mathQuillInstance.L];
|
|
133
|
+
const rightNode = cursor[mathQuillInstance.R];
|
|
132
134
|
const command = maybeFindCommandBeforeParens(leftNode);
|
|
133
135
|
|
|
134
136
|
if (command && command.startNode) {
|
|
@@ -179,7 +181,7 @@ function handleBackspaceInsideParens(
|
|
|
179
181
|
// - \log(|x+1) => |\log(x+1)|
|
|
180
182
|
// - \log(|) => |
|
|
181
183
|
|
|
182
|
-
if (cursor[
|
|
184
|
+
if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
|
|
183
185
|
// This command contains math and there's some math to
|
|
184
186
|
// the left of the cursor that we should delete normally
|
|
185
187
|
// before doing anything special.
|
|
@@ -193,12 +195,12 @@ function handleBackspaceInsideParens(
|
|
|
193
195
|
// has a subscript as is the case in log_n then move the cursor into
|
|
194
196
|
// the subscript, e.g. \log_{5}(|x+1) => \log_{5|}(x+1)
|
|
195
197
|
|
|
196
|
-
if (grandparent[
|
|
198
|
+
if (grandparent[mathQuillInstance.L].sub) {
|
|
197
199
|
// if there is a subscript
|
|
198
|
-
if (grandparent[
|
|
200
|
+
if (grandparent[mathQuillInstance.L].sub.jQ.text()) {
|
|
199
201
|
// and it contains text
|
|
200
202
|
// move the cursor to the right end of the subscript
|
|
201
|
-
cursor.insAtRightEnd(grandparent[
|
|
203
|
+
cursor.insAtRightEnd(grandparent[mathQuillInstance.L].sub);
|
|
202
204
|
return;
|
|
203
205
|
}
|
|
204
206
|
}
|
|
@@ -238,7 +240,7 @@ function handleBackspace(mathField: MathFieldInterface) {
|
|
|
238
240
|
if (!cursor.selection) {
|
|
239
241
|
const parent = cursor.parent;
|
|
240
242
|
const grandparent = parent.parent;
|
|
241
|
-
const leftNode = cursor[
|
|
243
|
+
const leftNode = cursor[mathQuillInstance.L];
|
|
242
244
|
|
|
243
245
|
if (isFraction(leftNode)) {
|
|
244
246
|
selectNode(leftNode, cursor);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import Key from "
|
|
2
|
-
import {getCursor} from "../mathquill-helpers";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
1
|
+
import Key from "../../data/keys";
|
|
2
|
+
import {getCursor} from "../input/mathquill-helpers";
|
|
3
|
+
import {mathQuillInstance} from "../input/mathquill-instance";
|
|
4
|
+
import {
|
|
5
|
+
MathFieldInterface,
|
|
6
|
+
MathFieldActionType,
|
|
7
|
+
} from "../input/mathquill-types";
|
|
5
8
|
|
|
6
9
|
const ArithmeticOperators = ["+", "-", "\\cdot", "\\times", "\\div"];
|
|
7
10
|
const EqualityOperators = ["=", "\\neq", "<", "\\leq", ">", "\\geq"];
|
|
@@ -16,7 +19,7 @@ export default function handleExponent(
|
|
|
16
19
|
// parentheses and apply the exponent to that.
|
|
17
20
|
const invalidPrefixes = [...ArithmeticOperators, ...EqualityOperators];
|
|
18
21
|
|
|
19
|
-
const precedingNode = cursor[
|
|
22
|
+
const precedingNode = cursor[mathQuillInstance.L];
|
|
20
23
|
const shouldPrefixWithParens =
|
|
21
24
|
precedingNode === MathFieldActionType.MQ_END ||
|
|
22
25
|
invalidPrefixes.includes(precedingNode.ctrlSeq.trim());
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import Key from "
|
|
2
|
-
import {CursorContext} from "../cursor-contexts";
|
|
1
|
+
import Key from "../../data/keys";
|
|
2
|
+
import {CursorContext} from "../input/cursor-contexts";
|
|
3
3
|
import {
|
|
4
4
|
isFraction,
|
|
5
5
|
isParens,
|
|
6
6
|
contextForCursor,
|
|
7
7
|
getCursor,
|
|
8
|
-
} from "../mathquill-helpers";
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
8
|
+
} from "../input/mathquill-helpers";
|
|
9
|
+
import {mathQuillInstance} from "../input/mathquill-instance";
|
|
10
|
+
import {
|
|
11
|
+
MathFieldInterface,
|
|
12
|
+
MathFieldActionType,
|
|
13
|
+
} from "../input/mathquill-types";
|
|
11
14
|
|
|
12
15
|
const KeysForJumpContext = {
|
|
13
16
|
[CursorContext.IN_PARENS]: "JUMP_OUT_PARENTHESES",
|
|
@@ -46,11 +49,13 @@ function handleJumpOut(mathField: MathFieldInterface, key: Key): void {
|
|
|
46
49
|
// Find the nearest fraction to the right of the cursor.
|
|
47
50
|
let fractionNode;
|
|
48
51
|
let visitor = cursor;
|
|
49
|
-
while (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
while (
|
|
53
|
+
visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END
|
|
54
|
+
) {
|
|
55
|
+
if (isFraction(visitor[mathQuillInstance.R])) {
|
|
56
|
+
fractionNode = visitor[mathQuillInstance.R];
|
|
52
57
|
}
|
|
53
|
-
visitor = visitor[
|
|
58
|
+
visitor = visitor[mathQuillInstance.R];
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
// Jump into it!
|
|
@@ -82,7 +87,7 @@ function handleJumpOut(mathField: MathFieldInterface, key: Key): void {
|
|
|
82
87
|
// Navigate right once more, if we're right before parens. This
|
|
83
88
|
// is to handle the standard case in which the subscript is the
|
|
84
89
|
// base of a custom log.
|
|
85
|
-
if (isParens(cursor[
|
|
90
|
+
if (isParens(cursor[mathQuillInstance.R])) {
|
|
86
91
|
mathField.keystroke("Right");
|
|
87
92
|
}
|
|
88
93
|
break;
|