@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/es/index.js
CHANGED
|
@@ -341,273 +341,52 @@ class DragListener {
|
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
//
|
|
360
|
-
//
|
|
361
|
-
|
|
362
|
-
//
|
|
363
|
-
//
|
|
364
|
-
|
|
365
|
-
//
|
|
366
|
-
//
|
|
367
|
-
|
|
368
|
-
//
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
DeviceOrientation["LANDSCAPE"] = "LANDSCAPE";
|
|
372
|
-
DeviceOrientation["PORTRAIT"] = "PORTRAIT";
|
|
373
|
-
return DeviceOrientation;
|
|
374
|
-
}({});
|
|
375
|
-
let DeviceType = /*#__PURE__*/function (DeviceType) {
|
|
376
|
-
DeviceType["PHONE"] = "PHONE";
|
|
377
|
-
DeviceType["TABLET"] = "TABLET";
|
|
378
|
-
return DeviceType;
|
|
379
|
-
}({});
|
|
380
|
-
let LayoutMode = /*#__PURE__*/function (LayoutMode) {
|
|
381
|
-
LayoutMode["FULLSCREEN"] = "FULLSCREEN";
|
|
382
|
-
LayoutMode["COMPACT"] = "COMPACT";
|
|
383
|
-
return LayoutMode;
|
|
384
|
-
}({});
|
|
385
|
-
let BorderDirection = /*#__PURE__*/function (BorderDirection) {
|
|
386
|
-
BorderDirection["LEFT"] = "LEFT";
|
|
387
|
-
BorderDirection["BOTTOM"] = "BOTTOM";
|
|
388
|
-
return BorderDirection;
|
|
389
|
-
}({});
|
|
390
|
-
const BorderStyles = {
|
|
391
|
-
LEFT: [BorderDirection.LEFT],
|
|
392
|
-
BOTTOM: [BorderDirection.BOTTOM],
|
|
393
|
-
ALL: [BorderDirection.LEFT, BorderDirection.BOTTOM],
|
|
394
|
-
NONE: []
|
|
395
|
-
};
|
|
396
|
-
let IconType = /*#__PURE__*/function (IconType) {
|
|
397
|
-
IconType["MATH"] = "MATH";
|
|
398
|
-
IconType["SVG"] = "SVG";
|
|
399
|
-
IconType["TEXT"] = "TEXT";
|
|
400
|
-
return IconType;
|
|
401
|
-
}({});
|
|
402
|
-
let DecimalSeparator = /*#__PURE__*/function (DecimalSeparator) {
|
|
403
|
-
DecimalSeparator["COMMA"] = "COMMA";
|
|
404
|
-
DecimalSeparator["PERIOD"] = "PERIOD";
|
|
405
|
-
return DecimalSeparator;
|
|
406
|
-
}({});
|
|
407
|
-
let EchoAnimationType = /*#__PURE__*/function (EchoAnimationType) {
|
|
408
|
-
EchoAnimationType["SLIDE_AND_FADE"] = "SLIDE_AND_FADE";
|
|
409
|
-
EchoAnimationType["FADE_ONLY"] = "FADE_ONLY";
|
|
410
|
-
EchoAnimationType["LONG_FADE_ONLY"] = "LONG_FADE_ONLY";
|
|
411
|
-
return EchoAnimationType;
|
|
412
|
-
}({});
|
|
413
|
-
|
|
414
|
-
// NOTES(kevinb):
|
|
415
|
-
// - In order to get the correct decimal separator for the current locale,
|
|
416
|
-
// the locale must bet set using `setLocale(kaLocale)` which can be
|
|
417
|
-
// imported from wonder-blocks-i18n.
|
|
418
|
-
// - Some languages/locales use different decimal separators than the ones
|
|
419
|
-
// listed here. Much of the Arab world uses U+066C.
|
|
420
|
-
const decimalSeparator = getDecimalSeparator() === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
|
|
421
|
-
|
|
422
|
-
var MQ = MathQuill.getInterface(2);
|
|
423
|
-
|
|
424
|
-
var ActionType = /*#__PURE__*/function (ActionType) {
|
|
425
|
-
ActionType["WRITE"] = "write";
|
|
426
|
-
ActionType["CMD"] = "cmd";
|
|
427
|
-
ActionType["KEYSTROKE"] = "keystroke";
|
|
428
|
-
ActionType[ActionType["MQ_END"] = 0] = "MQ_END";
|
|
429
|
-
return ActionType;
|
|
430
|
-
}(ActionType || {});
|
|
431
|
-
const decimalSymbol = decimalSeparator === DecimalSeparator.COMMA ? "," : ".";
|
|
432
|
-
function buildGenericCallback(str, type = ActionType.WRITE) {
|
|
433
|
-
return function (mathQuill) {
|
|
434
|
-
switch (type) {
|
|
435
|
-
case ActionType.WRITE:
|
|
436
|
-
{
|
|
437
|
-
mathQuill.write(str);
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
case ActionType.CMD:
|
|
441
|
-
{
|
|
442
|
-
mathQuill.cmd(str);
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
case ActionType.KEYSTROKE:
|
|
446
|
-
{
|
|
447
|
-
mathQuill.keystroke(str);
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
344
|
+
// We only need one MathQuill instance (referred to as MQ in the docs)
|
|
345
|
+
// and that contains some MQ constants and the MathField constructor
|
|
346
|
+
const mathQuillInstance = MathQuill.getInterface(2);
|
|
347
|
+
function createBaseConfig() {
|
|
348
|
+
return {
|
|
349
|
+
// LaTeX commands that, when typed, are immediately replaced by the
|
|
350
|
+
// appropriate symbol. This does not include ln, log, or any of the
|
|
351
|
+
// trig functions; those are always interpreted as commands.
|
|
352
|
+
autoCommands: "pi theta phi sqrt nthroot",
|
|
353
|
+
// Pop the cursor out of super/subscripts on arithmetic operators
|
|
354
|
+
// or (in)equalities.
|
|
355
|
+
charsThatBreakOutOfSupSub: "+-*/=<>≠≤≥",
|
|
356
|
+
// Prevent excessive super/subscripts or fractions from being
|
|
357
|
+
// created without operands, e.g. when somebody holds down a key
|
|
358
|
+
supSubsRequireOperand: true,
|
|
359
|
+
// The name of this option is somewhat misleading, as tabbing in
|
|
360
|
+
// MathQuill breaks you out of a nested context (fraction/script)
|
|
361
|
+
// if you're in one, but moves focus to the next input if you're
|
|
362
|
+
// not. Spaces (with this option enabled) are just ignored in the
|
|
363
|
+
// latter case.
|
|
364
|
+
//
|
|
365
|
+
// TODO(alex): In order to allow inputting mixed numbers, we will
|
|
366
|
+
// have to accept spaces in certain cases. The desired behavior is
|
|
367
|
+
// still to escape nested contexts if currently in one, but to
|
|
368
|
+
// insert a space if not (we don't expect mixed numbers in nested
|
|
369
|
+
// contexts). We should also limit to one consecutive space.
|
|
370
|
+
spaceBehavesLikeTab: true
|
|
451
371
|
};
|
|
452
372
|
}
|
|
453
|
-
const keyToMathquillMap = {
|
|
454
|
-
CDOT: buildGenericCallback("\\cdot"),
|
|
455
|
-
COS: buildGenericCallback("cos"),
|
|
456
|
-
DECIMAL: buildGenericCallback(decimalSymbol),
|
|
457
|
-
DIVIDE: buildGenericCallback("\\div"),
|
|
458
|
-
EQUAL: buildGenericCallback("="),
|
|
459
|
-
EXP: buildGenericCallback("^"),
|
|
460
|
-
EXP_2: buildGenericCallback("^2"),
|
|
461
|
-
EXP_3: buildGenericCallback("^3"),
|
|
462
|
-
GEQ: buildGenericCallback("\\geq"),
|
|
463
|
-
GT: buildGenericCallback(">"),
|
|
464
|
-
LEQ: buildGenericCallback("\\leq"),
|
|
465
|
-
LN: buildGenericCallback("\\ln"),
|
|
466
|
-
LOG: buildGenericCallback("\\log"),
|
|
467
|
-
LT: buildGenericCallback("<"),
|
|
468
|
-
MINUS: buildGenericCallback("-"),
|
|
469
|
-
NEGATIVE: buildGenericCallback("-"),
|
|
470
|
-
NEQ: buildGenericCallback("\\neq"),
|
|
471
|
-
PERCENT: buildGenericCallback("%"),
|
|
472
|
-
PERIOD: buildGenericCallback("."),
|
|
473
|
-
PLUS: buildGenericCallback("+"),
|
|
474
|
-
SIN: buildGenericCallback("sin"),
|
|
475
|
-
TAN: buildGenericCallback("tan"),
|
|
476
|
-
TIMES: buildGenericCallback("\\times"),
|
|
477
|
-
// The `FRAC_EXCLUSIVE` variant is handled manually, since we may need to do
|
|
478
|
-
// some additional navigation depending on the cursor position.
|
|
479
|
-
FRAC_INCLUSIVE: buildGenericCallback("/", ActionType.CMD),
|
|
480
|
-
LEFT_PAREN: buildGenericCallback("(", ActionType.CMD),
|
|
481
|
-
RIGHT_PAREN: buildGenericCallback(")", ActionType.CMD),
|
|
482
|
-
SQRT: buildGenericCallback("sqrt", ActionType.CMD),
|
|
483
|
-
PHI: buildGenericCallback("\\phi", ActionType.CMD),
|
|
484
|
-
PI: buildGenericCallback("pi", ActionType.CMD),
|
|
485
|
-
THETA: buildGenericCallback("theta", ActionType.CMD),
|
|
486
|
-
RADICAL: buildGenericCallback("nthroot", ActionType.CMD),
|
|
487
|
-
UP: buildGenericCallback("Up", ActionType.KEYSTROKE),
|
|
488
|
-
DOWN: buildGenericCallback("Down", ActionType.KEYSTROKE),
|
|
489
|
-
CUBE_ROOT: mathQuill => {
|
|
490
|
-
mathQuill.write("\\sqrt[3]{}");
|
|
491
|
-
mathQuill.keystroke("Left"); // under the root
|
|
492
|
-
},
|
|
493
|
-
|
|
494
|
-
FRAC_EXCLUSIVE: mathQuill => {
|
|
495
|
-
const cursor = mathQuill.__controller.cursor;
|
|
496
|
-
// If there's nothing to the left of the cursor, then we want to
|
|
497
|
-
// leave the cursor to the left of the fraction after creating it.
|
|
498
|
-
const shouldNavigateLeft = cursor[MQ.L] === ActionType.MQ_END;
|
|
499
|
-
mathQuill.cmd("\\frac");
|
|
500
|
-
if (shouldNavigateLeft) {
|
|
501
|
-
mathQuill.keystroke("Left");
|
|
502
|
-
}
|
|
503
|
-
},
|
|
504
|
-
LOG_B: mathQuill => {
|
|
505
|
-
mathQuill.typedText("log_");
|
|
506
|
-
mathQuill.keystroke("Right");
|
|
507
|
-
mathQuill.typedText("(");
|
|
508
|
-
mathQuill.keystroke("Left");
|
|
509
|
-
mathQuill.keystroke("Left");
|
|
510
|
-
},
|
|
511
|
-
LOG_N: mathQuill => {
|
|
512
|
-
mathQuill.write("log_{ }\\left(\\right)");
|
|
513
|
-
mathQuill.keystroke("Left"); // into parentheses
|
|
514
|
-
mathQuill.keystroke("Left"); // out of parentheses
|
|
515
|
-
mathQuill.keystroke("Left"); // into index
|
|
516
|
-
},
|
|
517
|
-
|
|
518
|
-
NTHROOT3: mathQuill => {
|
|
519
|
-
mathQuill.typedText("nthroot3");
|
|
520
|
-
mathQuill.keystroke("Right");
|
|
521
|
-
},
|
|
522
|
-
POW: mathQuill => {
|
|
523
|
-
const contents = mathQuill.latex();
|
|
524
|
-
mathQuill.typedText("^");
|
|
525
373
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
JUMP_OUT_BASE: () => {},
|
|
543
|
-
JUMP_INTO_NUMERATOR: () => {},
|
|
544
|
-
JUMP_OUT_NUMERATOR: () => {},
|
|
545
|
-
JUMP_OUT_DENOMINATOR: () => {},
|
|
546
|
-
NOOP: () => {},
|
|
547
|
-
MANY: () => {},
|
|
548
|
-
NUM_0: buildGenericCallback("0"),
|
|
549
|
-
NUM_1: buildGenericCallback("1"),
|
|
550
|
-
NUM_2: buildGenericCallback("2"),
|
|
551
|
-
NUM_3: buildGenericCallback("3"),
|
|
552
|
-
NUM_4: buildGenericCallback("4"),
|
|
553
|
-
NUM_5: buildGenericCallback("5"),
|
|
554
|
-
NUM_6: buildGenericCallback("6"),
|
|
555
|
-
NUM_7: buildGenericCallback("7"),
|
|
556
|
-
NUM_8: buildGenericCallback("8"),
|
|
557
|
-
NUM_9: buildGenericCallback("9"),
|
|
558
|
-
a: buildGenericCallback("a"),
|
|
559
|
-
b: buildGenericCallback("b"),
|
|
560
|
-
c: buildGenericCallback("c"),
|
|
561
|
-
d: buildGenericCallback("d"),
|
|
562
|
-
e: buildGenericCallback("e"),
|
|
563
|
-
f: buildGenericCallback("f"),
|
|
564
|
-
g: buildGenericCallback("g"),
|
|
565
|
-
h: buildGenericCallback("h"),
|
|
566
|
-
i: buildGenericCallback("i"),
|
|
567
|
-
j: buildGenericCallback("j"),
|
|
568
|
-
k: buildGenericCallback("k"),
|
|
569
|
-
l: buildGenericCallback("l"),
|
|
570
|
-
m: buildGenericCallback("m"),
|
|
571
|
-
n: buildGenericCallback("n"),
|
|
572
|
-
o: buildGenericCallback("o"),
|
|
573
|
-
p: buildGenericCallback("p"),
|
|
574
|
-
q: buildGenericCallback("q"),
|
|
575
|
-
r: buildGenericCallback("r"),
|
|
576
|
-
s: buildGenericCallback("s"),
|
|
577
|
-
t: buildGenericCallback("t"),
|
|
578
|
-
u: buildGenericCallback("u"),
|
|
579
|
-
v: buildGenericCallback("v"),
|
|
580
|
-
w: buildGenericCallback("w"),
|
|
581
|
-
x: buildGenericCallback("x"),
|
|
582
|
-
y: buildGenericCallback("y"),
|
|
583
|
-
z: buildGenericCallback("z"),
|
|
584
|
-
A: buildGenericCallback("A"),
|
|
585
|
-
B: buildGenericCallback("B"),
|
|
586
|
-
C: buildGenericCallback("C"),
|
|
587
|
-
D: buildGenericCallback("D"),
|
|
588
|
-
E: buildGenericCallback("E"),
|
|
589
|
-
F: buildGenericCallback("F"),
|
|
590
|
-
G: buildGenericCallback("G"),
|
|
591
|
-
H: buildGenericCallback("H"),
|
|
592
|
-
I: buildGenericCallback("I"),
|
|
593
|
-
J: buildGenericCallback("J"),
|
|
594
|
-
K: buildGenericCallback("K"),
|
|
595
|
-
L: buildGenericCallback("L"),
|
|
596
|
-
M: buildGenericCallback("M"),
|
|
597
|
-
N: buildGenericCallback("N"),
|
|
598
|
-
O: buildGenericCallback("O"),
|
|
599
|
-
P: buildGenericCallback("P"),
|
|
600
|
-
Q: buildGenericCallback("Q"),
|
|
601
|
-
R: buildGenericCallback("R"),
|
|
602
|
-
S: buildGenericCallback("S"),
|
|
603
|
-
T: buildGenericCallback("T"),
|
|
604
|
-
U: buildGenericCallback("U"),
|
|
605
|
-
V: buildGenericCallback("V"),
|
|
606
|
-
W: buildGenericCallback("W"),
|
|
607
|
-
X: buildGenericCallback("X"),
|
|
608
|
-
Y: buildGenericCallback("Y"),
|
|
609
|
-
Z: buildGenericCallback("Z")
|
|
610
|
-
};
|
|
374
|
+
/**
|
|
375
|
+
* Creates a new [MathField](http://docs.mathquill.com/en/latest/Api_Methods/#mqmathfieldhtml_element-config)
|
|
376
|
+
* instance within the given `container`.
|
|
377
|
+
*
|
|
378
|
+
* An optional configuration callback can be provided to customize
|
|
379
|
+
* the created MathField. A default configuration is passed to this
|
|
380
|
+
* callback which can then be adjusted as needed. The configuration
|
|
381
|
+
* returned from this callback is used to create the MathField.
|
|
382
|
+
* This allows callers to do minimal configuration as only configs
|
|
383
|
+
* that vary from the default need to be provided.
|
|
384
|
+
*/
|
|
385
|
+
function createMathField(container, configCallback) {
|
|
386
|
+
const baseConfig = createBaseConfig();
|
|
387
|
+
const config = configCallback ? configCallback(baseConfig) : baseConfig;
|
|
388
|
+
return mathQuillInstance.MathField(container, config);
|
|
389
|
+
}
|
|
611
390
|
|
|
612
391
|
let MathFieldActionType = /*#__PURE__*/function (MathFieldActionType) {
|
|
613
392
|
MathFieldActionType["WRITE"] = "write";
|
|
@@ -678,7 +457,7 @@ function isInsideLogIndex(cursor) {
|
|
|
678
457
|
return false;
|
|
679
458
|
}
|
|
680
459
|
function isInsideEmptyNode(cursor) {
|
|
681
|
-
return cursor[
|
|
460
|
+
return cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END && cursor[mathQuillInstance.R] === MathFieldActionType.MQ_END;
|
|
682
461
|
}
|
|
683
462
|
function selectNode(node, cursor) {
|
|
684
463
|
cursor.insLeftOf(node);
|
|
@@ -738,7 +517,7 @@ function maybeFindCommand(initialNode) {
|
|
|
738
517
|
} else {
|
|
739
518
|
break;
|
|
740
519
|
}
|
|
741
|
-
node = node[
|
|
520
|
+
node = node[mathQuillInstance.L];
|
|
742
521
|
}
|
|
743
522
|
|
|
744
523
|
// If we hit the start of a command, then grab the rest of it by
|
|
@@ -746,7 +525,7 @@ function maybeFindCommand(initialNode) {
|
|
|
746
525
|
// with its terminal node.
|
|
747
526
|
if (startNode) {
|
|
748
527
|
// Next, iterate from the start to the right.
|
|
749
|
-
node = initialNode[
|
|
528
|
+
node = initialNode[mathQuillInstance.R];
|
|
750
529
|
while (node !== 0) {
|
|
751
530
|
const ctrlSeq = node.ctrlSeq.trim();
|
|
752
531
|
if (commandCharRegex.test(ctrlSeq)) {
|
|
@@ -759,7 +538,7 @@ function maybeFindCommand(initialNode) {
|
|
|
759
538
|
endNode = node;
|
|
760
539
|
break;
|
|
761
540
|
}
|
|
762
|
-
node = node[
|
|
541
|
+
node = node[mathQuillInstance.R];
|
|
763
542
|
}
|
|
764
543
|
if (validCommands.includes(name)) {
|
|
765
544
|
return {
|
|
@@ -785,18 +564,18 @@ function maybeFindCommand(initialNode) {
|
|
|
785
564
|
* name (`name`) of the command
|
|
786
565
|
*/
|
|
787
566
|
function maybeFindCommandBeforeParens(leftParenNode) {
|
|
788
|
-
return maybeFindCommand(leftParenNode[
|
|
567
|
+
return maybeFindCommand(leftParenNode[mathQuillInstance.L]);
|
|
789
568
|
}
|
|
790
569
|
function contextForCursor(cursor) {
|
|
791
570
|
// First, try to find any fraction to the right, unimpeded.
|
|
792
571
|
let visitor = cursor;
|
|
793
|
-
while (visitor[
|
|
794
|
-
if (isFraction(visitor[
|
|
572
|
+
while (visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
573
|
+
if (isFraction(visitor[mathQuillInstance.R])) {
|
|
795
574
|
return CursorContext.BEFORE_FRACTION;
|
|
796
|
-
} else if (!isLeaf(visitor[
|
|
575
|
+
} else if (!isLeaf(visitor[mathQuillInstance.R])) {
|
|
797
576
|
break;
|
|
798
577
|
}
|
|
799
|
-
visitor = visitor[
|
|
578
|
+
visitor = visitor[mathQuillInstance.R];
|
|
800
579
|
}
|
|
801
580
|
|
|
802
581
|
// If that didn't work, check if the parent or grandparent is a special
|
|
@@ -816,57 +595,8 @@ function contextForCursor(cursor) {
|
|
|
816
595
|
}
|
|
817
596
|
}
|
|
818
597
|
|
|
819
|
-
function handleLeftArrow(mathField, cursor) {
|
|
820
|
-
// If we're inside a function, and just after the left parentheses, we
|
|
821
|
-
// need to skip the entire function name, rather than move the cursor
|
|
822
|
-
// inside of it. For example, when hitting left from within the
|
|
823
|
-
// parentheses in `cos()`, we want to place the cursor to the left of
|
|
824
|
-
// the entire expression, rather than between the `s` and the left
|
|
825
|
-
// parenthesis.
|
|
826
|
-
// From the cursor's perspective, this requires that our left node is
|
|
827
|
-
// the ActionType.MQ_END node, that our grandparent is the left parenthesis, and
|
|
828
|
-
// the nodes to the left of our grandparent comprise a valid function
|
|
829
|
-
// name.
|
|
830
|
-
if (cursor[MQ.L] === MathFieldActionType.MQ_END) {
|
|
831
|
-
const parent = cursor.parent;
|
|
832
|
-
const grandparent = parent.parent;
|
|
833
|
-
if (grandparent.ctrlSeq === "\\left(") {
|
|
834
|
-
const command = maybeFindCommandBeforeParens(grandparent);
|
|
835
|
-
if (command) {
|
|
836
|
-
cursor.insLeftOf(command.startNode);
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
// Otherwise, we default to the standard MathQull left behavior.
|
|
843
|
-
mathField.keystroke("Left");
|
|
844
|
-
}
|
|
845
|
-
function handleRightArrow(mathField, cursor) {
|
|
846
|
-
const command = maybeFindCommand(cursor[MQ.R]);
|
|
847
|
-
if (command) {
|
|
848
|
-
// Similarly, if a function is to our right, then we need to place
|
|
849
|
-
// the cursor at the start of its parenthetical content, which is
|
|
850
|
-
// done by putting it to the left of ites parentheses and then
|
|
851
|
-
// moving right once.
|
|
852
|
-
cursor.insLeftOf(command.endNode);
|
|
853
|
-
mathField.keystroke("Right");
|
|
854
|
-
} else {
|
|
855
|
-
// Otherwise, we default to the standard MathQull right behavior.
|
|
856
|
-
mathField.keystroke("Right");
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
function handleArrow(mathField, key) {
|
|
860
|
-
const cursor = getCursor(mathField);
|
|
861
|
-
if (key === "LEFT") {
|
|
862
|
-
handleLeftArrow(mathField, cursor);
|
|
863
|
-
} else if (key === "RIGHT") {
|
|
864
|
-
handleRightArrow(mathField, cursor);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
598
|
function handleBackspaceInNthRoot(mathField, cursor) {
|
|
869
|
-
const isAtLeftEnd = cursor[
|
|
599
|
+
const isAtLeftEnd = cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END;
|
|
870
600
|
const isRootEmpty = isInsideEmptyNode(cursor.parent.parent.blocks[0].ends);
|
|
871
601
|
if (isAtLeftEnd) {
|
|
872
602
|
selectNode(cursor.parent.parent, cursor);
|
|
@@ -885,7 +615,7 @@ function handleBackspaceInRootIndex(mathField, cursor) {
|
|
|
885
615
|
|
|
886
616
|
const grandparent = cursor.parent.parent;
|
|
887
617
|
const latex = grandparent.latex();
|
|
888
|
-
const reinsertionPoint = grandparent[
|
|
618
|
+
const reinsertionPoint = grandparent[mathQuillInstance.L];
|
|
889
619
|
selectNode(grandparent, cursor);
|
|
890
620
|
const rootIsEmpty = grandparent.blocks[1].jQ.text() === "";
|
|
891
621
|
if (rootIsEmpty) {
|
|
@@ -904,13 +634,13 @@ function handleBackspaceInRootIndex(mathField, cursor) {
|
|
|
904
634
|
|
|
905
635
|
// Adjust the cursor to be to the left the sqrt.
|
|
906
636
|
if (reinsertionPoint === MathFieldActionType.MQ_END) {
|
|
907
|
-
mathField.moveToDirEnd(
|
|
637
|
+
mathField.moveToDirEnd(mathQuillInstance.L);
|
|
908
638
|
} else {
|
|
909
639
|
cursor.insRightOf(reinsertionPoint);
|
|
910
640
|
}
|
|
911
641
|
}
|
|
912
642
|
} else {
|
|
913
|
-
if (cursor[
|
|
643
|
+
if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
|
|
914
644
|
// If the cursor is not at the leftmost position inside the
|
|
915
645
|
// root's index, delete a character.
|
|
916
646
|
mathField.keystroke("Backspace");
|
|
@@ -923,14 +653,14 @@ function handleBackspaceInLogIndex(mathField, cursor) {
|
|
|
923
653
|
const command = maybeFindCommandBeforeParens(grandparent);
|
|
924
654
|
cursor.insLeftOf(command == null ? void 0 : command.startNode);
|
|
925
655
|
cursor.startSelection();
|
|
926
|
-
if (grandparent[
|
|
927
|
-
cursor.insRightOf(grandparent[
|
|
656
|
+
if (grandparent[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
657
|
+
cursor.insRightOf(grandparent[mathQuillInstance.R]);
|
|
928
658
|
} else {
|
|
929
659
|
cursor.insRightOf(grandparent);
|
|
930
660
|
}
|
|
931
661
|
cursor.select();
|
|
932
662
|
cursor.endSelection();
|
|
933
|
-
const isLogBodyEmpty = grandparent[
|
|
663
|
+
const isLogBodyEmpty = grandparent[mathQuillInstance.R].contentjQ.text() === "";
|
|
934
664
|
if (isLogBodyEmpty) {
|
|
935
665
|
// If there's no content inside the log's parens then delete the
|
|
936
666
|
// whole thing.
|
|
@@ -949,8 +679,8 @@ function handleBackspaceOutsideParens(cursor) {
|
|
|
949
679
|
// (x+1)| => |(x+1)|
|
|
950
680
|
// \log(x+1)| => |\log(x+1)|
|
|
951
681
|
|
|
952
|
-
const leftNode = cursor[
|
|
953
|
-
const rightNode = cursor[
|
|
682
|
+
const leftNode = cursor[mathQuillInstance.L];
|
|
683
|
+
const rightNode = cursor[mathQuillInstance.R];
|
|
954
684
|
const command = maybeFindCommandBeforeParens(leftNode);
|
|
955
685
|
if (command && command.startNode) {
|
|
956
686
|
// There's a command before the parens so we select it as well as
|
|
@@ -996,7 +726,7 @@ function handleBackspaceInsideParens(mathField, cursor) {
|
|
|
996
726
|
// - \log(|x+1) => |\log(x+1)|
|
|
997
727
|
// - \log(|) => |
|
|
998
728
|
|
|
999
|
-
if (cursor[
|
|
729
|
+
if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
|
|
1000
730
|
// This command contains math and there's some math to
|
|
1001
731
|
// the left of the cursor that we should delete normally
|
|
1002
732
|
// before doing anything special.
|
|
@@ -1009,12 +739,12 @@ function handleBackspaceInsideParens(mathField, cursor) {
|
|
|
1009
739
|
// has a subscript as is the case in log_n then move the cursor into
|
|
1010
740
|
// the subscript, e.g. \log_{5}(|x+1) => \log_{5|}(x+1)
|
|
1011
741
|
|
|
1012
|
-
if (grandparent[
|
|
742
|
+
if (grandparent[mathQuillInstance.L].sub) {
|
|
1013
743
|
// if there is a subscript
|
|
1014
|
-
if (grandparent[
|
|
744
|
+
if (grandparent[mathQuillInstance.L].sub.jQ.text()) {
|
|
1015
745
|
// and it contains text
|
|
1016
746
|
// move the cursor to the right end of the subscript
|
|
1017
|
-
cursor.insAtRightEnd(grandparent[
|
|
747
|
+
cursor.insAtRightEnd(grandparent[mathQuillInstance.L].sub);
|
|
1018
748
|
return;
|
|
1019
749
|
}
|
|
1020
750
|
}
|
|
@@ -1052,7 +782,7 @@ function handleBackspace(mathField) {
|
|
|
1052
782
|
if (!cursor.selection) {
|
|
1053
783
|
const parent = cursor.parent;
|
|
1054
784
|
const grandparent = parent.parent;
|
|
1055
|
-
const leftNode = cursor[
|
|
785
|
+
const leftNode = cursor[mathQuillInstance.L];
|
|
1056
786
|
if (isFraction(leftNode)) {
|
|
1057
787
|
selectNode(leftNode, cursor);
|
|
1058
788
|
} else if (isSquareRoot(leftNode)) {
|
|
@@ -1079,6 +809,133 @@ function handleBackspace(mathField) {
|
|
|
1079
809
|
}
|
|
1080
810
|
}
|
|
1081
811
|
|
|
812
|
+
/**
|
|
813
|
+
* Constants that are shared between multiple files.
|
|
814
|
+
*/
|
|
815
|
+
|
|
816
|
+
let KeypadType = /*#__PURE__*/function (KeypadType) {
|
|
817
|
+
KeypadType["FRACTION"] = "FRACTION";
|
|
818
|
+
KeypadType["EXPRESSION"] = "EXPRESSION";
|
|
819
|
+
return KeypadType;
|
|
820
|
+
}({});
|
|
821
|
+
const KeyTypes = ["EMPTY",
|
|
822
|
+
// For numerals, variables, and any other characters that themselves
|
|
823
|
+
// compose 'values'.
|
|
824
|
+
"VALUE",
|
|
825
|
+
// For buttons that insert or adjust math in an input.
|
|
826
|
+
"OPERATOR",
|
|
827
|
+
// For buttons that move the cursor in an input (including via
|
|
828
|
+
// deletion).
|
|
829
|
+
"INPUT_NAVIGATION",
|
|
830
|
+
// For buttons that modify the broader keypad state (e.g., by changing
|
|
831
|
+
// the visible pane).
|
|
832
|
+
"KEYPAD_NAVIGATION",
|
|
833
|
+
// For buttons that house multiple buttons and have no action
|
|
834
|
+
// themselves.
|
|
835
|
+
"MANY",
|
|
836
|
+
// For the echo animation that appears on press.
|
|
837
|
+
"ECHO"];
|
|
838
|
+
let DeviceOrientation = /*#__PURE__*/function (DeviceOrientation) {
|
|
839
|
+
DeviceOrientation["LANDSCAPE"] = "LANDSCAPE";
|
|
840
|
+
DeviceOrientation["PORTRAIT"] = "PORTRAIT";
|
|
841
|
+
return DeviceOrientation;
|
|
842
|
+
}({});
|
|
843
|
+
let DeviceType = /*#__PURE__*/function (DeviceType) {
|
|
844
|
+
DeviceType["PHONE"] = "PHONE";
|
|
845
|
+
DeviceType["TABLET"] = "TABLET";
|
|
846
|
+
return DeviceType;
|
|
847
|
+
}({});
|
|
848
|
+
let LayoutMode = /*#__PURE__*/function (LayoutMode) {
|
|
849
|
+
LayoutMode["FULLSCREEN"] = "FULLSCREEN";
|
|
850
|
+
LayoutMode["COMPACT"] = "COMPACT";
|
|
851
|
+
return LayoutMode;
|
|
852
|
+
}({});
|
|
853
|
+
let BorderDirection = /*#__PURE__*/function (BorderDirection) {
|
|
854
|
+
BorderDirection["LEFT"] = "LEFT";
|
|
855
|
+
BorderDirection["BOTTOM"] = "BOTTOM";
|
|
856
|
+
return BorderDirection;
|
|
857
|
+
}({});
|
|
858
|
+
const BorderStyles = {
|
|
859
|
+
LEFT: [BorderDirection.LEFT],
|
|
860
|
+
BOTTOM: [BorderDirection.BOTTOM],
|
|
861
|
+
ALL: [BorderDirection.LEFT, BorderDirection.BOTTOM],
|
|
862
|
+
NONE: []
|
|
863
|
+
};
|
|
864
|
+
let IconType = /*#__PURE__*/function (IconType) {
|
|
865
|
+
IconType["MATH"] = "MATH";
|
|
866
|
+
IconType["SVG"] = "SVG";
|
|
867
|
+
IconType["TEXT"] = "TEXT";
|
|
868
|
+
return IconType;
|
|
869
|
+
}({});
|
|
870
|
+
let DecimalSeparator = /*#__PURE__*/function (DecimalSeparator) {
|
|
871
|
+
DecimalSeparator["COMMA"] = "COMMA";
|
|
872
|
+
DecimalSeparator["PERIOD"] = "PERIOD";
|
|
873
|
+
return DecimalSeparator;
|
|
874
|
+
}({});
|
|
875
|
+
let EchoAnimationType = /*#__PURE__*/function (EchoAnimationType) {
|
|
876
|
+
EchoAnimationType["SLIDE_AND_FADE"] = "SLIDE_AND_FADE";
|
|
877
|
+
EchoAnimationType["FADE_ONLY"] = "FADE_ONLY";
|
|
878
|
+
EchoAnimationType["LONG_FADE_ONLY"] = "LONG_FADE_ONLY";
|
|
879
|
+
return EchoAnimationType;
|
|
880
|
+
}({});
|
|
881
|
+
|
|
882
|
+
// NOTES(kevinb):
|
|
883
|
+
// - In order to get the correct decimal separator for the current locale,
|
|
884
|
+
// the locale must bet set using `setLocale(kaLocale)` which can be
|
|
885
|
+
// imported from wonder-blocks-i18n.
|
|
886
|
+
// - Some languages/locales use different decimal separators than the ones
|
|
887
|
+
// listed here. Much of the Arab world uses U+066C.
|
|
888
|
+
const decimalSeparator = getDecimalSeparator() === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
|
|
889
|
+
|
|
890
|
+
function handleLeftArrow(mathField, cursor) {
|
|
891
|
+
// If we're inside a function, and just after the left parentheses, we
|
|
892
|
+
// need to skip the entire function name, rather than move the cursor
|
|
893
|
+
// inside of it. For example, when hitting left from within the
|
|
894
|
+
// parentheses in `cos()`, we want to place the cursor to the left of
|
|
895
|
+
// the entire expression, rather than between the `s` and the left
|
|
896
|
+
// parenthesis.
|
|
897
|
+
// From the cursor's perspective, this requires that our left node is
|
|
898
|
+
// the ActionType.MQ_END node, that our grandparent is the left parenthesis, and
|
|
899
|
+
// the nodes to the left of our grandparent comprise a valid function
|
|
900
|
+
// name.
|
|
901
|
+
if (cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END) {
|
|
902
|
+
const parent = cursor.parent;
|
|
903
|
+
const grandparent = parent.parent;
|
|
904
|
+
if (grandparent.ctrlSeq === "\\left(") {
|
|
905
|
+
const command = maybeFindCommandBeforeParens(grandparent);
|
|
906
|
+
if (command) {
|
|
907
|
+
cursor.insLeftOf(command.startNode);
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// Otherwise, we default to the standard MathQull left behavior.
|
|
914
|
+
mathField.keystroke("Left");
|
|
915
|
+
}
|
|
916
|
+
function handleRightArrow(mathField, cursor) {
|
|
917
|
+
const command = maybeFindCommand(cursor[mathQuillInstance.R]);
|
|
918
|
+
if (command) {
|
|
919
|
+
// Similarly, if a function is to our right, then we need to place
|
|
920
|
+
// the cursor at the start of its parenthetical content, which is
|
|
921
|
+
// done by putting it to the left of ites parentheses and then
|
|
922
|
+
// moving right once.
|
|
923
|
+
cursor.insLeftOf(command.endNode);
|
|
924
|
+
mathField.keystroke("Right");
|
|
925
|
+
} else {
|
|
926
|
+
// Otherwise, we default to the standard MathQull right behavior.
|
|
927
|
+
mathField.keystroke("Right");
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
function handleArrow(mathField, key) {
|
|
931
|
+
const cursor = getCursor(mathField);
|
|
932
|
+
if (key === "LEFT") {
|
|
933
|
+
handleLeftArrow(mathField, cursor);
|
|
934
|
+
} else if (key === "RIGHT") {
|
|
935
|
+
handleRightArrow(mathField, cursor);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
1082
939
|
const ArithmeticOperators = ["+", "-", "\\cdot", "\\times", "\\div"];
|
|
1083
940
|
const EqualityOperators = ["=", "\\neq", "<", "\\leq", ">", "\\geq"];
|
|
1084
941
|
function handleExponent(mathField, key) {
|
|
@@ -1087,7 +944,7 @@ function handleExponent(mathField, key) {
|
|
|
1087
944
|
// knowingly cannot be raised to a power), add an empty set of
|
|
1088
945
|
// parentheses and apply the exponent to that.
|
|
1089
946
|
const invalidPrefixes = [...ArithmeticOperators, ...EqualityOperators];
|
|
1090
|
-
const precedingNode = cursor[
|
|
947
|
+
const precedingNode = cursor[mathQuillInstance.L];
|
|
1091
948
|
const shouldPrefixWithParens = precedingNode === MathFieldActionType.MQ_END || invalidPrefixes.includes(precedingNode.ctrlSeq.trim());
|
|
1092
949
|
if (shouldPrefixWithParens) {
|
|
1093
950
|
mathField.write("\\left(\\right)");
|
|
@@ -1153,11 +1010,11 @@ function handleJumpOut(mathField, key) {
|
|
|
1153
1010
|
// Find the nearest fraction to the right of the cursor.
|
|
1154
1011
|
let fractionNode;
|
|
1155
1012
|
let visitor = cursor;
|
|
1156
|
-
while (visitor[
|
|
1157
|
-
if (isFraction(visitor[
|
|
1158
|
-
fractionNode = visitor[
|
|
1013
|
+
while (visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
1014
|
+
if (isFraction(visitor[mathQuillInstance.R])) {
|
|
1015
|
+
fractionNode = visitor[mathQuillInstance.R];
|
|
1159
1016
|
}
|
|
1160
|
-
visitor = visitor[
|
|
1017
|
+
visitor = visitor[mathQuillInstance.R];
|
|
1161
1018
|
}
|
|
1162
1019
|
|
|
1163
1020
|
// Jump into it!
|
|
@@ -1186,7 +1043,7 @@ function handleJumpOut(mathField, key) {
|
|
|
1186
1043
|
// Navigate right once more, if we're right before parens. This
|
|
1187
1044
|
// is to handle the standard case in which the subscript is the
|
|
1188
1045
|
// base of a custom log.
|
|
1189
|
-
if (isParens(cursor[
|
|
1046
|
+
if (isParens(cursor[mathQuillInstance.R])) {
|
|
1190
1047
|
mathField.keystroke("Right");
|
|
1191
1048
|
}
|
|
1192
1049
|
break;
|
|
@@ -1199,25 +1056,45 @@ function handleJumpOut(mathField, key) {
|
|
|
1199
1056
|
}
|
|
1200
1057
|
}
|
|
1201
1058
|
|
|
1059
|
+
var ActionType = /*#__PURE__*/function (ActionType) {
|
|
1060
|
+
ActionType["WRITE"] = "write";
|
|
1061
|
+
ActionType["CMD"] = "cmd";
|
|
1062
|
+
ActionType["KEYSTROKE"] = "keystroke";
|
|
1063
|
+
ActionType[ActionType["MQ_END"] = 0] = "MQ_END";
|
|
1064
|
+
return ActionType;
|
|
1065
|
+
}(ActionType || {});
|
|
1066
|
+
const decimalSymbol = decimalSeparator === DecimalSeparator.COMMA ? "," : ".";
|
|
1067
|
+
function buildGenericCallback(str, type = ActionType.WRITE) {
|
|
1068
|
+
return function (mathQuill) {
|
|
1069
|
+
switch (type) {
|
|
1070
|
+
case ActionType.WRITE:
|
|
1071
|
+
{
|
|
1072
|
+
mathQuill.write(str);
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
case ActionType.CMD:
|
|
1076
|
+
{
|
|
1077
|
+
mathQuill.cmd(str);
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
case ActionType.KEYSTROKE:
|
|
1081
|
+
{
|
|
1082
|
+
mathQuill.keystroke(str);
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1202
1088
|
function buildNormalFunctionCallback(command) {
|
|
1203
1089
|
return function (mathField) {
|
|
1204
1090
|
mathField.write(`\\${command}\\left(\\right)`);
|
|
1205
1091
|
mathField.keystroke("Left");
|
|
1206
1092
|
};
|
|
1207
1093
|
}
|
|
1208
|
-
const
|
|
1209
|
-
// note(Matthew): in all likelihood, this should be moved
|
|
1210
|
-
// to the shared key2MathQuill translator. During this refactor
|
|
1211
|
-
// I tried to keep logic the same while deduplicating code.
|
|
1212
|
-
// Perseus' Expression MathInput treats this stuff differently
|
|
1213
|
-
// (or doesn't do anything with them at all), so I kept it that way
|
|
1214
|
-
BACKSPACE: handleBackspace,
|
|
1094
|
+
const keyToMathquillMap = {
|
|
1215
1095
|
EXP: handleExponent,
|
|
1216
1096
|
EXP_2: handleExponent,
|
|
1217
1097
|
EXP_3: handleExponent,
|
|
1218
|
-
FRAC: mathQuill => {
|
|
1219
|
-
mathQuill.cmd("\\frac");
|
|
1220
|
-
},
|
|
1221
1098
|
JUMP_OUT_PARENTHESES: handleJumpOut,
|
|
1222
1099
|
JUMP_OUT_EXPONENT: handleJumpOut,
|
|
1223
1100
|
JUMP_OUT_BASE: handleJumpOut,
|
|
@@ -1230,7 +1107,157 @@ const customKeyTranslator = _extends({}, keyToMathquillMap, {
|
|
|
1230
1107
|
LN: buildNormalFunctionCallback("ln"),
|
|
1231
1108
|
SIN: buildNormalFunctionCallback("sin"),
|
|
1232
1109
|
COS: buildNormalFunctionCallback("cos"),
|
|
1233
|
-
TAN: buildNormalFunctionCallback("tan")
|
|
1110
|
+
TAN: buildNormalFunctionCallback("tan"),
|
|
1111
|
+
CDOT: buildGenericCallback("\\cdot"),
|
|
1112
|
+
DECIMAL: buildGenericCallback(decimalSymbol),
|
|
1113
|
+
DIVIDE: buildGenericCallback("\\div"),
|
|
1114
|
+
EQUAL: buildGenericCallback("="),
|
|
1115
|
+
GEQ: buildGenericCallback("\\geq"),
|
|
1116
|
+
GT: buildGenericCallback(">"),
|
|
1117
|
+
LEQ: buildGenericCallback("\\leq"),
|
|
1118
|
+
LT: buildGenericCallback("<"),
|
|
1119
|
+
MINUS: buildGenericCallback("-"),
|
|
1120
|
+
NEGATIVE: buildGenericCallback("-"),
|
|
1121
|
+
NEQ: buildGenericCallback("\\neq"),
|
|
1122
|
+
PERCENT: buildGenericCallback("%"),
|
|
1123
|
+
PERIOD: buildGenericCallback("."),
|
|
1124
|
+
PLUS: buildGenericCallback("+"),
|
|
1125
|
+
TIMES: buildGenericCallback("\\times"),
|
|
1126
|
+
// The `FRAC_EXCLUSIVE` variant is handled manually, since we may need to do
|
|
1127
|
+
// some additional navigation depending on the cursor position.
|
|
1128
|
+
FRAC_INCLUSIVE: buildGenericCallback("/", ActionType.CMD),
|
|
1129
|
+
FRAC: buildGenericCallback("\\frac", ActionType.CMD),
|
|
1130
|
+
LEFT_PAREN: buildGenericCallback("(", ActionType.CMD),
|
|
1131
|
+
RIGHT_PAREN: buildGenericCallback(")", ActionType.CMD),
|
|
1132
|
+
SQRT: buildGenericCallback("sqrt", ActionType.CMD),
|
|
1133
|
+
PHI: buildGenericCallback("\\phi", ActionType.CMD),
|
|
1134
|
+
PI: buildGenericCallback("pi", ActionType.CMD),
|
|
1135
|
+
THETA: buildGenericCallback("theta", ActionType.CMD),
|
|
1136
|
+
RADICAL: buildGenericCallback("nthroot", ActionType.CMD),
|
|
1137
|
+
BACKSPACE: buildGenericCallback("Backspace", ActionType.KEYSTROKE),
|
|
1138
|
+
UP: buildGenericCallback("Up", ActionType.KEYSTROKE),
|
|
1139
|
+
DOWN: buildGenericCallback("Down", ActionType.KEYSTROKE),
|
|
1140
|
+
CUBE_ROOT: mathQuill => {
|
|
1141
|
+
mathQuill.write("\\sqrt[3]{}");
|
|
1142
|
+
mathQuill.keystroke("Left"); // under the root
|
|
1143
|
+
},
|
|
1144
|
+
|
|
1145
|
+
FRAC_EXCLUSIVE: mathQuill => {
|
|
1146
|
+
const cursor = mathQuill.__controller.cursor;
|
|
1147
|
+
// If there's nothing to the left of the cursor, then we want to
|
|
1148
|
+
// leave the cursor to the left of the fraction after creating it.
|
|
1149
|
+
const shouldNavigateLeft = cursor[mathQuillInstance.L] === ActionType.MQ_END;
|
|
1150
|
+
mathQuill.cmd("\\frac");
|
|
1151
|
+
if (shouldNavigateLeft) {
|
|
1152
|
+
mathQuill.keystroke("Left");
|
|
1153
|
+
}
|
|
1154
|
+
},
|
|
1155
|
+
LOG_B: mathQuill => {
|
|
1156
|
+
mathQuill.typedText("log_");
|
|
1157
|
+
mathQuill.keystroke("Right");
|
|
1158
|
+
mathQuill.typedText("(");
|
|
1159
|
+
mathQuill.keystroke("Left");
|
|
1160
|
+
mathQuill.keystroke("Left");
|
|
1161
|
+
},
|
|
1162
|
+
LOG_N: mathQuill => {
|
|
1163
|
+
mathQuill.write("log_{ }\\left(\\right)");
|
|
1164
|
+
mathQuill.keystroke("Left"); // into parentheses
|
|
1165
|
+
mathQuill.keystroke("Left"); // out of parentheses
|
|
1166
|
+
mathQuill.keystroke("Left"); // into index
|
|
1167
|
+
},
|
|
1168
|
+
|
|
1169
|
+
NTHROOT3: mathQuill => {
|
|
1170
|
+
mathQuill.typedText("nthroot3");
|
|
1171
|
+
mathQuill.keystroke("Right");
|
|
1172
|
+
},
|
|
1173
|
+
POW: mathQuill => {
|
|
1174
|
+
const contents = mathQuill.latex();
|
|
1175
|
+
mathQuill.typedText("^");
|
|
1176
|
+
|
|
1177
|
+
// If the input hasn't changed (for example, if we're
|
|
1178
|
+
// attempting to add an exponent on an empty input or an empty
|
|
1179
|
+
// denominator), insert our own "a^b"
|
|
1180
|
+
if (mathQuill.latex() === contents) {
|
|
1181
|
+
mathQuill.typedText("a^b");
|
|
1182
|
+
}
|
|
1183
|
+
},
|
|
1184
|
+
// These need to be overwritten by the consumer
|
|
1185
|
+
// if they're going to be used
|
|
1186
|
+
DISMISS: () => {},
|
|
1187
|
+
NOOP: () => {},
|
|
1188
|
+
MANY: () => {},
|
|
1189
|
+
NUM_0: buildGenericCallback("0"),
|
|
1190
|
+
NUM_1: buildGenericCallback("1"),
|
|
1191
|
+
NUM_2: buildGenericCallback("2"),
|
|
1192
|
+
NUM_3: buildGenericCallback("3"),
|
|
1193
|
+
NUM_4: buildGenericCallback("4"),
|
|
1194
|
+
NUM_5: buildGenericCallback("5"),
|
|
1195
|
+
NUM_6: buildGenericCallback("6"),
|
|
1196
|
+
NUM_7: buildGenericCallback("7"),
|
|
1197
|
+
NUM_8: buildGenericCallback("8"),
|
|
1198
|
+
NUM_9: buildGenericCallback("9"),
|
|
1199
|
+
a: buildGenericCallback("a"),
|
|
1200
|
+
b: buildGenericCallback("b"),
|
|
1201
|
+
c: buildGenericCallback("c"),
|
|
1202
|
+
d: buildGenericCallback("d"),
|
|
1203
|
+
e: buildGenericCallback("e"),
|
|
1204
|
+
f: buildGenericCallback("f"),
|
|
1205
|
+
g: buildGenericCallback("g"),
|
|
1206
|
+
h: buildGenericCallback("h"),
|
|
1207
|
+
i: buildGenericCallback("i"),
|
|
1208
|
+
j: buildGenericCallback("j"),
|
|
1209
|
+
k: buildGenericCallback("k"),
|
|
1210
|
+
l: buildGenericCallback("l"),
|
|
1211
|
+
m: buildGenericCallback("m"),
|
|
1212
|
+
n: buildGenericCallback("n"),
|
|
1213
|
+
o: buildGenericCallback("o"),
|
|
1214
|
+
p: buildGenericCallback("p"),
|
|
1215
|
+
q: buildGenericCallback("q"),
|
|
1216
|
+
r: buildGenericCallback("r"),
|
|
1217
|
+
s: buildGenericCallback("s"),
|
|
1218
|
+
t: buildGenericCallback("t"),
|
|
1219
|
+
u: buildGenericCallback("u"),
|
|
1220
|
+
v: buildGenericCallback("v"),
|
|
1221
|
+
w: buildGenericCallback("w"),
|
|
1222
|
+
x: buildGenericCallback("x"),
|
|
1223
|
+
y: buildGenericCallback("y"),
|
|
1224
|
+
z: buildGenericCallback("z"),
|
|
1225
|
+
A: buildGenericCallback("A"),
|
|
1226
|
+
B: buildGenericCallback("B"),
|
|
1227
|
+
C: buildGenericCallback("C"),
|
|
1228
|
+
D: buildGenericCallback("D"),
|
|
1229
|
+
E: buildGenericCallback("E"),
|
|
1230
|
+
F: buildGenericCallback("F"),
|
|
1231
|
+
G: buildGenericCallback("G"),
|
|
1232
|
+
H: buildGenericCallback("H"),
|
|
1233
|
+
I: buildGenericCallback("I"),
|
|
1234
|
+
J: buildGenericCallback("J"),
|
|
1235
|
+
K: buildGenericCallback("K"),
|
|
1236
|
+
L: buildGenericCallback("L"),
|
|
1237
|
+
M: buildGenericCallback("M"),
|
|
1238
|
+
N: buildGenericCallback("N"),
|
|
1239
|
+
O: buildGenericCallback("O"),
|
|
1240
|
+
P: buildGenericCallback("P"),
|
|
1241
|
+
Q: buildGenericCallback("Q"),
|
|
1242
|
+
R: buildGenericCallback("R"),
|
|
1243
|
+
S: buildGenericCallback("S"),
|
|
1244
|
+
T: buildGenericCallback("T"),
|
|
1245
|
+
U: buildGenericCallback("U"),
|
|
1246
|
+
V: buildGenericCallback("V"),
|
|
1247
|
+
W: buildGenericCallback("W"),
|
|
1248
|
+
X: buildGenericCallback("X"),
|
|
1249
|
+
Y: buildGenericCallback("Y"),
|
|
1250
|
+
Z: buildGenericCallback("Z")
|
|
1251
|
+
};
|
|
1252
|
+
|
|
1253
|
+
const mobileKeyTranslator = _extends({}, keyToMathquillMap, {
|
|
1254
|
+
// note(Matthew): our mobile backspace logic is really complicated
|
|
1255
|
+
// and for some reason doesn't really work in the desktop experience.
|
|
1256
|
+
// So we default to the basic backspace functionality in the
|
|
1257
|
+
// key translator and overwrite it with the complicated logic here
|
|
1258
|
+
// until we can unify the experiences (if we even want to).
|
|
1259
|
+
// https://khanacademy.atlassian.net/browse/LC-906
|
|
1260
|
+
BACKSPACE: handleBackspace
|
|
1234
1261
|
});
|
|
1235
1262
|
|
|
1236
1263
|
/**
|
|
@@ -1239,17 +1266,19 @@ const customKeyTranslator = _extends({}, keyToMathquillMap, {
|
|
|
1239
1266
|
* from MathQuill changes.
|
|
1240
1267
|
*/
|
|
1241
1268
|
class MathWrapper {
|
|
1242
|
-
// MathQuill input
|
|
1269
|
+
// MathQuill MathField input
|
|
1243
1270
|
|
|
1244
|
-
constructor(element,
|
|
1271
|
+
constructor(element, callbacks = {}) {
|
|
1245
1272
|
this.mathField = void 0;
|
|
1246
1273
|
this.callbacks = void 0;
|
|
1247
|
-
this.mathField =
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1274
|
+
this.mathField = createMathField(element, () => {
|
|
1275
|
+
return {
|
|
1276
|
+
// use a span instead of a textarea so that we don't bring up the
|
|
1277
|
+
// native keyboard on mobile when selecting the input
|
|
1278
|
+
substituteTextarea: function () {
|
|
1279
|
+
return document.createElement("span");
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1253
1282
|
});
|
|
1254
1283
|
this.callbacks = callbacks;
|
|
1255
1284
|
}
|
|
@@ -1279,7 +1308,7 @@ class MathWrapper {
|
|
|
1279
1308
|
*/
|
|
1280
1309
|
pressKey(key) {
|
|
1281
1310
|
const cursor = this.getCursor();
|
|
1282
|
-
const translator =
|
|
1311
|
+
const translator = mobileKeyTranslator[key];
|
|
1283
1312
|
if (translator) {
|
|
1284
1313
|
translator(this.mathField, key);
|
|
1285
1314
|
}
|
|
@@ -1327,7 +1356,7 @@ class MathWrapper {
|
|
|
1327
1356
|
// Unless that would leave us mid-command, in which case, we
|
|
1328
1357
|
// need to adjust and place the cursor inside the parens
|
|
1329
1358
|
// following the command.
|
|
1330
|
-
const command = maybeFindCommand(cursor[
|
|
1359
|
+
const command = maybeFindCommand(cursor[mathQuillInstance.L]);
|
|
1331
1360
|
if (command && command.endNode) {
|
|
1332
1361
|
// NOTE(charlie): endNode should definitely be \left(.
|
|
1333
1362
|
cursor.insLeftOf(command.endNode);
|
|
@@ -1898,7 +1927,7 @@ class MathInput extends React.Component {
|
|
|
1898
1927
|
}
|
|
1899
1928
|
componentDidMount() {
|
|
1900
1929
|
this._isMounted = true;
|
|
1901
|
-
this.mathField = new MathWrapper(this._mathContainer, {
|
|
1930
|
+
this.mathField = new MathWrapper(this._mathContainer, {
|
|
1902
1931
|
onCursorMove: cursor => {
|
|
1903
1932
|
// TODO(charlie): It's not great that there is so much coupling
|
|
1904
1933
|
// between this keypad and the input behavior. We should wrap
|
|
@@ -8161,7 +8190,7 @@ const KeypadButton = ({
|
|
|
8161
8190
|
onPress: () => onClickKey(keyConfig.id),
|
|
8162
8191
|
tintColor: tintColor,
|
|
8163
8192
|
style: style,
|
|
8164
|
-
ariaLabel: keyConfig.
|
|
8193
|
+
ariaLabel: keyConfig.ariaLabel
|
|
8165
8194
|
}, /*#__PURE__*/React.createElement(ButtonAsset, {
|
|
8166
8195
|
id: keyConfig.id
|
|
8167
8196
|
}));
|
|
@@ -8563,5 +8592,5 @@ const styles = StyleSheet.create({
|
|
|
8563
8592
|
}
|
|
8564
8593
|
});
|
|
8565
8594
|
|
|
8566
|
-
export { CursorContext, KeyConfigs, Keypad, MathInput as KeypadInput, KeypadType, ProvidedKeypad as LegacyKeypad, keyToMathquillMap as keyTranslator, keypadElementPropType };
|
|
8595
|
+
export { CursorContext, KeyConfigs, Keypad, MathInput as KeypadInput, KeypadType, ProvidedKeypad as LegacyKeypad, createMathField, keyToMathquillMap as keyTranslator, keypadElementPropType, mathQuillInstance };
|
|
8567
8596
|
//# sourceMappingURL=index.js.map
|