@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/index.js
CHANGED
|
@@ -401,274 +401,52 @@ class DragListener {
|
|
|
401
401
|
}
|
|
402
402
|
}
|
|
403
403
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
//
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
//
|
|
420
|
-
//
|
|
421
|
-
|
|
422
|
-
//
|
|
423
|
-
//
|
|
424
|
-
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
|
|
428
|
-
//
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
DeviceOrientation["LANDSCAPE"] = "LANDSCAPE";
|
|
432
|
-
DeviceOrientation["PORTRAIT"] = "PORTRAIT";
|
|
433
|
-
return DeviceOrientation;
|
|
434
|
-
}({});
|
|
435
|
-
let DeviceType = /*#__PURE__*/function (DeviceType) {
|
|
436
|
-
DeviceType["PHONE"] = "PHONE";
|
|
437
|
-
DeviceType["TABLET"] = "TABLET";
|
|
438
|
-
return DeviceType;
|
|
439
|
-
}({});
|
|
440
|
-
let LayoutMode = /*#__PURE__*/function (LayoutMode) {
|
|
441
|
-
LayoutMode["FULLSCREEN"] = "FULLSCREEN";
|
|
442
|
-
LayoutMode["COMPACT"] = "COMPACT";
|
|
443
|
-
return LayoutMode;
|
|
444
|
-
}({});
|
|
445
|
-
let BorderDirection = /*#__PURE__*/function (BorderDirection) {
|
|
446
|
-
BorderDirection["LEFT"] = "LEFT";
|
|
447
|
-
BorderDirection["BOTTOM"] = "BOTTOM";
|
|
448
|
-
return BorderDirection;
|
|
449
|
-
}({});
|
|
450
|
-
const BorderStyles = {
|
|
451
|
-
LEFT: [BorderDirection.LEFT],
|
|
452
|
-
BOTTOM: [BorderDirection.BOTTOM],
|
|
453
|
-
ALL: [BorderDirection.LEFT, BorderDirection.BOTTOM],
|
|
454
|
-
NONE: []
|
|
455
|
-
};
|
|
456
|
-
let IconType = /*#__PURE__*/function (IconType) {
|
|
457
|
-
IconType["MATH"] = "MATH";
|
|
458
|
-
IconType["SVG"] = "SVG";
|
|
459
|
-
IconType["TEXT"] = "TEXT";
|
|
460
|
-
return IconType;
|
|
461
|
-
}({});
|
|
462
|
-
let DecimalSeparator = /*#__PURE__*/function (DecimalSeparator) {
|
|
463
|
-
DecimalSeparator["COMMA"] = "COMMA";
|
|
464
|
-
DecimalSeparator["PERIOD"] = "PERIOD";
|
|
465
|
-
return DecimalSeparator;
|
|
466
|
-
}({});
|
|
467
|
-
let EchoAnimationType = /*#__PURE__*/function (EchoAnimationType) {
|
|
468
|
-
EchoAnimationType["SLIDE_AND_FADE"] = "SLIDE_AND_FADE";
|
|
469
|
-
EchoAnimationType["FADE_ONLY"] = "FADE_ONLY";
|
|
470
|
-
EchoAnimationType["LONG_FADE_ONLY"] = "LONG_FADE_ONLY";
|
|
471
|
-
return EchoAnimationType;
|
|
472
|
-
}({});
|
|
473
|
-
|
|
474
|
-
// NOTES(kevinb):
|
|
475
|
-
// - In order to get the correct decimal separator for the current locale,
|
|
476
|
-
// the locale must bet set using `setLocale(kaLocale)` which can be
|
|
477
|
-
// imported from wonder-blocks-i18n.
|
|
478
|
-
// - Some languages/locales use different decimal separators than the ones
|
|
479
|
-
// listed here. Much of the Arab world uses U+066C.
|
|
480
|
-
const decimalSeparator = i18n.getDecimalSeparator() === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
|
|
481
|
-
|
|
482
|
-
var MQ = MathQuill__default["default"].getInterface(2);
|
|
483
|
-
|
|
484
|
-
var ActionType = /*#__PURE__*/function (ActionType) {
|
|
485
|
-
ActionType["WRITE"] = "write";
|
|
486
|
-
ActionType["CMD"] = "cmd";
|
|
487
|
-
ActionType["KEYSTROKE"] = "keystroke";
|
|
488
|
-
ActionType[ActionType["MQ_END"] = 0] = "MQ_END";
|
|
489
|
-
return ActionType;
|
|
490
|
-
}(ActionType || {});
|
|
491
|
-
const decimalSymbol = decimalSeparator === DecimalSeparator.COMMA ? "," : ".";
|
|
492
|
-
function buildGenericCallback(str) {
|
|
493
|
-
let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ActionType.WRITE;
|
|
494
|
-
return function (mathQuill) {
|
|
495
|
-
switch (type) {
|
|
496
|
-
case ActionType.WRITE:
|
|
497
|
-
{
|
|
498
|
-
mathQuill.write(str);
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
501
|
-
case ActionType.CMD:
|
|
502
|
-
{
|
|
503
|
-
mathQuill.cmd(str);
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
case ActionType.KEYSTROKE:
|
|
507
|
-
{
|
|
508
|
-
mathQuill.keystroke(str);
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
404
|
+
// We only need one MathQuill instance (referred to as MQ in the docs)
|
|
405
|
+
// and that contains some MQ constants and the MathField constructor
|
|
406
|
+
const mathQuillInstance = MathQuill__default["default"].getInterface(2);
|
|
407
|
+
function createBaseConfig() {
|
|
408
|
+
return {
|
|
409
|
+
// LaTeX commands that, when typed, are immediately replaced by the
|
|
410
|
+
// appropriate symbol. This does not include ln, log, or any of the
|
|
411
|
+
// trig functions; those are always interpreted as commands.
|
|
412
|
+
autoCommands: "pi theta phi sqrt nthroot",
|
|
413
|
+
// Pop the cursor out of super/subscripts on arithmetic operators
|
|
414
|
+
// or (in)equalities.
|
|
415
|
+
charsThatBreakOutOfSupSub: "+-*/=<>≠≤≥",
|
|
416
|
+
// Prevent excessive super/subscripts or fractions from being
|
|
417
|
+
// created without operands, e.g. when somebody holds down a key
|
|
418
|
+
supSubsRequireOperand: true,
|
|
419
|
+
// The name of this option is somewhat misleading, as tabbing in
|
|
420
|
+
// MathQuill breaks you out of a nested context (fraction/script)
|
|
421
|
+
// if you're in one, but moves focus to the next input if you're
|
|
422
|
+
// not. Spaces (with this option enabled) are just ignored in the
|
|
423
|
+
// latter case.
|
|
424
|
+
//
|
|
425
|
+
// TODO(alex): In order to allow inputting mixed numbers, we will
|
|
426
|
+
// have to accept spaces in certain cases. The desired behavior is
|
|
427
|
+
// still to escape nested contexts if currently in one, but to
|
|
428
|
+
// insert a space if not (we don't expect mixed numbers in nested
|
|
429
|
+
// contexts). We should also limit to one consecutive space.
|
|
430
|
+
spaceBehavesLikeTab: true
|
|
512
431
|
};
|
|
513
432
|
}
|
|
514
|
-
const keyToMathquillMap = {
|
|
515
|
-
CDOT: buildGenericCallback("\\cdot"),
|
|
516
|
-
COS: buildGenericCallback("cos"),
|
|
517
|
-
DECIMAL: buildGenericCallback(decimalSymbol),
|
|
518
|
-
DIVIDE: buildGenericCallback("\\div"),
|
|
519
|
-
EQUAL: buildGenericCallback("="),
|
|
520
|
-
EXP: buildGenericCallback("^"),
|
|
521
|
-
EXP_2: buildGenericCallback("^2"),
|
|
522
|
-
EXP_3: buildGenericCallback("^3"),
|
|
523
|
-
GEQ: buildGenericCallback("\\geq"),
|
|
524
|
-
GT: buildGenericCallback(">"),
|
|
525
|
-
LEQ: buildGenericCallback("\\leq"),
|
|
526
|
-
LN: buildGenericCallback("\\ln"),
|
|
527
|
-
LOG: buildGenericCallback("\\log"),
|
|
528
|
-
LT: buildGenericCallback("<"),
|
|
529
|
-
MINUS: buildGenericCallback("-"),
|
|
530
|
-
NEGATIVE: buildGenericCallback("-"),
|
|
531
|
-
NEQ: buildGenericCallback("\\neq"),
|
|
532
|
-
PERCENT: buildGenericCallback("%"),
|
|
533
|
-
PERIOD: buildGenericCallback("."),
|
|
534
|
-
PLUS: buildGenericCallback("+"),
|
|
535
|
-
SIN: buildGenericCallback("sin"),
|
|
536
|
-
TAN: buildGenericCallback("tan"),
|
|
537
|
-
TIMES: buildGenericCallback("\\times"),
|
|
538
|
-
// The `FRAC_EXCLUSIVE` variant is handled manually, since we may need to do
|
|
539
|
-
// some additional navigation depending on the cursor position.
|
|
540
|
-
FRAC_INCLUSIVE: buildGenericCallback("/", ActionType.CMD),
|
|
541
|
-
LEFT_PAREN: buildGenericCallback("(", ActionType.CMD),
|
|
542
|
-
RIGHT_PAREN: buildGenericCallback(")", ActionType.CMD),
|
|
543
|
-
SQRT: buildGenericCallback("sqrt", ActionType.CMD),
|
|
544
|
-
PHI: buildGenericCallback("\\phi", ActionType.CMD),
|
|
545
|
-
PI: buildGenericCallback("pi", ActionType.CMD),
|
|
546
|
-
THETA: buildGenericCallback("theta", ActionType.CMD),
|
|
547
|
-
RADICAL: buildGenericCallback("nthroot", ActionType.CMD),
|
|
548
|
-
UP: buildGenericCallback("Up", ActionType.KEYSTROKE),
|
|
549
|
-
DOWN: buildGenericCallback("Down", ActionType.KEYSTROKE),
|
|
550
|
-
CUBE_ROOT: mathQuill => {
|
|
551
|
-
mathQuill.write("\\sqrt[3]{}");
|
|
552
|
-
mathQuill.keystroke("Left"); // under the root
|
|
553
|
-
},
|
|
554
|
-
|
|
555
|
-
FRAC_EXCLUSIVE: mathQuill => {
|
|
556
|
-
const cursor = mathQuill.__controller.cursor;
|
|
557
|
-
// If there's nothing to the left of the cursor, then we want to
|
|
558
|
-
// leave the cursor to the left of the fraction after creating it.
|
|
559
|
-
const shouldNavigateLeft = cursor[MQ.L] === ActionType.MQ_END;
|
|
560
|
-
mathQuill.cmd("\\frac");
|
|
561
|
-
if (shouldNavigateLeft) {
|
|
562
|
-
mathQuill.keystroke("Left");
|
|
563
|
-
}
|
|
564
|
-
},
|
|
565
|
-
LOG_B: mathQuill => {
|
|
566
|
-
mathQuill.typedText("log_");
|
|
567
|
-
mathQuill.keystroke("Right");
|
|
568
|
-
mathQuill.typedText("(");
|
|
569
|
-
mathQuill.keystroke("Left");
|
|
570
|
-
mathQuill.keystroke("Left");
|
|
571
|
-
},
|
|
572
|
-
LOG_N: mathQuill => {
|
|
573
|
-
mathQuill.write("log_{ }\\left(\\right)");
|
|
574
|
-
mathQuill.keystroke("Left"); // into parentheses
|
|
575
|
-
mathQuill.keystroke("Left"); // out of parentheses
|
|
576
|
-
mathQuill.keystroke("Left"); // into index
|
|
577
|
-
},
|
|
578
|
-
|
|
579
|
-
NTHROOT3: mathQuill => {
|
|
580
|
-
mathQuill.typedText("nthroot3");
|
|
581
|
-
mathQuill.keystroke("Right");
|
|
582
|
-
},
|
|
583
|
-
POW: mathQuill => {
|
|
584
|
-
const contents = mathQuill.latex();
|
|
585
|
-
mathQuill.typedText("^");
|
|
586
433
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
JUMP_OUT_BASE: () => {},
|
|
604
|
-
JUMP_INTO_NUMERATOR: () => {},
|
|
605
|
-
JUMP_OUT_NUMERATOR: () => {},
|
|
606
|
-
JUMP_OUT_DENOMINATOR: () => {},
|
|
607
|
-
NOOP: () => {},
|
|
608
|
-
MANY: () => {},
|
|
609
|
-
NUM_0: buildGenericCallback("0"),
|
|
610
|
-
NUM_1: buildGenericCallback("1"),
|
|
611
|
-
NUM_2: buildGenericCallback("2"),
|
|
612
|
-
NUM_3: buildGenericCallback("3"),
|
|
613
|
-
NUM_4: buildGenericCallback("4"),
|
|
614
|
-
NUM_5: buildGenericCallback("5"),
|
|
615
|
-
NUM_6: buildGenericCallback("6"),
|
|
616
|
-
NUM_7: buildGenericCallback("7"),
|
|
617
|
-
NUM_8: buildGenericCallback("8"),
|
|
618
|
-
NUM_9: buildGenericCallback("9"),
|
|
619
|
-
a: buildGenericCallback("a"),
|
|
620
|
-
b: buildGenericCallback("b"),
|
|
621
|
-
c: buildGenericCallback("c"),
|
|
622
|
-
d: buildGenericCallback("d"),
|
|
623
|
-
e: buildGenericCallback("e"),
|
|
624
|
-
f: buildGenericCallback("f"),
|
|
625
|
-
g: buildGenericCallback("g"),
|
|
626
|
-
h: buildGenericCallback("h"),
|
|
627
|
-
i: buildGenericCallback("i"),
|
|
628
|
-
j: buildGenericCallback("j"),
|
|
629
|
-
k: buildGenericCallback("k"),
|
|
630
|
-
l: buildGenericCallback("l"),
|
|
631
|
-
m: buildGenericCallback("m"),
|
|
632
|
-
n: buildGenericCallback("n"),
|
|
633
|
-
o: buildGenericCallback("o"),
|
|
634
|
-
p: buildGenericCallback("p"),
|
|
635
|
-
q: buildGenericCallback("q"),
|
|
636
|
-
r: buildGenericCallback("r"),
|
|
637
|
-
s: buildGenericCallback("s"),
|
|
638
|
-
t: buildGenericCallback("t"),
|
|
639
|
-
u: buildGenericCallback("u"),
|
|
640
|
-
v: buildGenericCallback("v"),
|
|
641
|
-
w: buildGenericCallback("w"),
|
|
642
|
-
x: buildGenericCallback("x"),
|
|
643
|
-
y: buildGenericCallback("y"),
|
|
644
|
-
z: buildGenericCallback("z"),
|
|
645
|
-
A: buildGenericCallback("A"),
|
|
646
|
-
B: buildGenericCallback("B"),
|
|
647
|
-
C: buildGenericCallback("C"),
|
|
648
|
-
D: buildGenericCallback("D"),
|
|
649
|
-
E: buildGenericCallback("E"),
|
|
650
|
-
F: buildGenericCallback("F"),
|
|
651
|
-
G: buildGenericCallback("G"),
|
|
652
|
-
H: buildGenericCallback("H"),
|
|
653
|
-
I: buildGenericCallback("I"),
|
|
654
|
-
J: buildGenericCallback("J"),
|
|
655
|
-
K: buildGenericCallback("K"),
|
|
656
|
-
L: buildGenericCallback("L"),
|
|
657
|
-
M: buildGenericCallback("M"),
|
|
658
|
-
N: buildGenericCallback("N"),
|
|
659
|
-
O: buildGenericCallback("O"),
|
|
660
|
-
P: buildGenericCallback("P"),
|
|
661
|
-
Q: buildGenericCallback("Q"),
|
|
662
|
-
R: buildGenericCallback("R"),
|
|
663
|
-
S: buildGenericCallback("S"),
|
|
664
|
-
T: buildGenericCallback("T"),
|
|
665
|
-
U: buildGenericCallback("U"),
|
|
666
|
-
V: buildGenericCallback("V"),
|
|
667
|
-
W: buildGenericCallback("W"),
|
|
668
|
-
X: buildGenericCallback("X"),
|
|
669
|
-
Y: buildGenericCallback("Y"),
|
|
670
|
-
Z: buildGenericCallback("Z")
|
|
671
|
-
};
|
|
434
|
+
/**
|
|
435
|
+
* Creates a new [MathField](http://docs.mathquill.com/en/latest/Api_Methods/#mqmathfieldhtml_element-config)
|
|
436
|
+
* instance within the given `container`.
|
|
437
|
+
*
|
|
438
|
+
* An optional configuration callback can be provided to customize
|
|
439
|
+
* the created MathField. A default configuration is passed to this
|
|
440
|
+
* callback which can then be adjusted as needed. The configuration
|
|
441
|
+
* returned from this callback is used to create the MathField.
|
|
442
|
+
* This allows callers to do minimal configuration as only configs
|
|
443
|
+
* that vary from the default need to be provided.
|
|
444
|
+
*/
|
|
445
|
+
function createMathField(container, configCallback) {
|
|
446
|
+
const baseConfig = createBaseConfig();
|
|
447
|
+
const config = configCallback ? configCallback(baseConfig) : baseConfig;
|
|
448
|
+
return mathQuillInstance.MathField(container, config);
|
|
449
|
+
}
|
|
672
450
|
|
|
673
451
|
let MathFieldActionType = /*#__PURE__*/function (MathFieldActionType) {
|
|
674
452
|
MathFieldActionType["WRITE"] = "write";
|
|
@@ -739,7 +517,7 @@ function isInsideLogIndex(cursor) {
|
|
|
739
517
|
return false;
|
|
740
518
|
}
|
|
741
519
|
function isInsideEmptyNode(cursor) {
|
|
742
|
-
return cursor[
|
|
520
|
+
return cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END && cursor[mathQuillInstance.R] === MathFieldActionType.MQ_END;
|
|
743
521
|
}
|
|
744
522
|
function selectNode(node, cursor) {
|
|
745
523
|
cursor.insLeftOf(node);
|
|
@@ -799,7 +577,7 @@ function maybeFindCommand(initialNode) {
|
|
|
799
577
|
} else {
|
|
800
578
|
break;
|
|
801
579
|
}
|
|
802
|
-
node = node[
|
|
580
|
+
node = node[mathQuillInstance.L];
|
|
803
581
|
}
|
|
804
582
|
|
|
805
583
|
// If we hit the start of a command, then grab the rest of it by
|
|
@@ -807,7 +585,7 @@ function maybeFindCommand(initialNode) {
|
|
|
807
585
|
// with its terminal node.
|
|
808
586
|
if (startNode) {
|
|
809
587
|
// Next, iterate from the start to the right.
|
|
810
|
-
node = initialNode[
|
|
588
|
+
node = initialNode[mathQuillInstance.R];
|
|
811
589
|
while (node !== 0) {
|
|
812
590
|
const ctrlSeq = node.ctrlSeq.trim();
|
|
813
591
|
if (commandCharRegex.test(ctrlSeq)) {
|
|
@@ -820,7 +598,7 @@ function maybeFindCommand(initialNode) {
|
|
|
820
598
|
endNode = node;
|
|
821
599
|
break;
|
|
822
600
|
}
|
|
823
|
-
node = node[
|
|
601
|
+
node = node[mathQuillInstance.R];
|
|
824
602
|
}
|
|
825
603
|
if (validCommands.includes(name)) {
|
|
826
604
|
return {
|
|
@@ -846,18 +624,18 @@ function maybeFindCommand(initialNode) {
|
|
|
846
624
|
* name (`name`) of the command
|
|
847
625
|
*/
|
|
848
626
|
function maybeFindCommandBeforeParens(leftParenNode) {
|
|
849
|
-
return maybeFindCommand(leftParenNode[
|
|
627
|
+
return maybeFindCommand(leftParenNode[mathQuillInstance.L]);
|
|
850
628
|
}
|
|
851
629
|
function contextForCursor(cursor) {
|
|
852
630
|
// First, try to find any fraction to the right, unimpeded.
|
|
853
631
|
let visitor = cursor;
|
|
854
|
-
while (visitor[
|
|
855
|
-
if (isFraction(visitor[
|
|
632
|
+
while (visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
633
|
+
if (isFraction(visitor[mathQuillInstance.R])) {
|
|
856
634
|
return CursorContext.BEFORE_FRACTION;
|
|
857
|
-
} else if (!isLeaf(visitor[
|
|
635
|
+
} else if (!isLeaf(visitor[mathQuillInstance.R])) {
|
|
858
636
|
break;
|
|
859
637
|
}
|
|
860
|
-
visitor = visitor[
|
|
638
|
+
visitor = visitor[mathQuillInstance.R];
|
|
861
639
|
}
|
|
862
640
|
|
|
863
641
|
// If that didn't work, check if the parent or grandparent is a special
|
|
@@ -877,57 +655,8 @@ function contextForCursor(cursor) {
|
|
|
877
655
|
}
|
|
878
656
|
}
|
|
879
657
|
|
|
880
|
-
function handleLeftArrow(mathField, cursor) {
|
|
881
|
-
// If we're inside a function, and just after the left parentheses, we
|
|
882
|
-
// need to skip the entire function name, rather than move the cursor
|
|
883
|
-
// inside of it. For example, when hitting left from within the
|
|
884
|
-
// parentheses in `cos()`, we want to place the cursor to the left of
|
|
885
|
-
// the entire expression, rather than between the `s` and the left
|
|
886
|
-
// parenthesis.
|
|
887
|
-
// From the cursor's perspective, this requires that our left node is
|
|
888
|
-
// the ActionType.MQ_END node, that our grandparent is the left parenthesis, and
|
|
889
|
-
// the nodes to the left of our grandparent comprise a valid function
|
|
890
|
-
// name.
|
|
891
|
-
if (cursor[MQ.L] === MathFieldActionType.MQ_END) {
|
|
892
|
-
const parent = cursor.parent;
|
|
893
|
-
const grandparent = parent.parent;
|
|
894
|
-
if (grandparent.ctrlSeq === "\\left(") {
|
|
895
|
-
const command = maybeFindCommandBeforeParens(grandparent);
|
|
896
|
-
if (command) {
|
|
897
|
-
cursor.insLeftOf(command.startNode);
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
// Otherwise, we default to the standard MathQull left behavior.
|
|
904
|
-
mathField.keystroke("Left");
|
|
905
|
-
}
|
|
906
|
-
function handleRightArrow(mathField, cursor) {
|
|
907
|
-
const command = maybeFindCommand(cursor[MQ.R]);
|
|
908
|
-
if (command) {
|
|
909
|
-
// Similarly, if a function is to our right, then we need to place
|
|
910
|
-
// the cursor at the start of its parenthetical content, which is
|
|
911
|
-
// done by putting it to the left of ites parentheses and then
|
|
912
|
-
// moving right once.
|
|
913
|
-
cursor.insLeftOf(command.endNode);
|
|
914
|
-
mathField.keystroke("Right");
|
|
915
|
-
} else {
|
|
916
|
-
// Otherwise, we default to the standard MathQull right behavior.
|
|
917
|
-
mathField.keystroke("Right");
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
function handleArrow(mathField, key) {
|
|
921
|
-
const cursor = getCursor(mathField);
|
|
922
|
-
if (key === "LEFT") {
|
|
923
|
-
handleLeftArrow(mathField, cursor);
|
|
924
|
-
} else if (key === "RIGHT") {
|
|
925
|
-
handleRightArrow(mathField, cursor);
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
658
|
function handleBackspaceInNthRoot(mathField, cursor) {
|
|
930
|
-
const isAtLeftEnd = cursor[
|
|
659
|
+
const isAtLeftEnd = cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END;
|
|
931
660
|
const isRootEmpty = isInsideEmptyNode(cursor.parent.parent.blocks[0].ends);
|
|
932
661
|
if (isAtLeftEnd) {
|
|
933
662
|
selectNode(cursor.parent.parent, cursor);
|
|
@@ -946,7 +675,7 @@ function handleBackspaceInRootIndex(mathField, cursor) {
|
|
|
946
675
|
|
|
947
676
|
const grandparent = cursor.parent.parent;
|
|
948
677
|
const latex = grandparent.latex();
|
|
949
|
-
const reinsertionPoint = grandparent[
|
|
678
|
+
const reinsertionPoint = grandparent[mathQuillInstance.L];
|
|
950
679
|
selectNode(grandparent, cursor);
|
|
951
680
|
const rootIsEmpty = grandparent.blocks[1].jQ.text() === "";
|
|
952
681
|
if (rootIsEmpty) {
|
|
@@ -965,13 +694,13 @@ function handleBackspaceInRootIndex(mathField, cursor) {
|
|
|
965
694
|
|
|
966
695
|
// Adjust the cursor to be to the left the sqrt.
|
|
967
696
|
if (reinsertionPoint === MathFieldActionType.MQ_END) {
|
|
968
|
-
mathField.moveToDirEnd(
|
|
697
|
+
mathField.moveToDirEnd(mathQuillInstance.L);
|
|
969
698
|
} else {
|
|
970
699
|
cursor.insRightOf(reinsertionPoint);
|
|
971
700
|
}
|
|
972
701
|
}
|
|
973
702
|
} else {
|
|
974
|
-
if (cursor[
|
|
703
|
+
if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
|
|
975
704
|
// If the cursor is not at the leftmost position inside the
|
|
976
705
|
// root's index, delete a character.
|
|
977
706
|
mathField.keystroke("Backspace");
|
|
@@ -984,14 +713,14 @@ function handleBackspaceInLogIndex(mathField, cursor) {
|
|
|
984
713
|
const command = maybeFindCommandBeforeParens(grandparent);
|
|
985
714
|
cursor.insLeftOf(command === null || command === void 0 ? void 0 : command.startNode);
|
|
986
715
|
cursor.startSelection();
|
|
987
|
-
if (grandparent[
|
|
988
|
-
cursor.insRightOf(grandparent[
|
|
716
|
+
if (grandparent[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
717
|
+
cursor.insRightOf(grandparent[mathQuillInstance.R]);
|
|
989
718
|
} else {
|
|
990
719
|
cursor.insRightOf(grandparent);
|
|
991
720
|
}
|
|
992
721
|
cursor.select();
|
|
993
722
|
cursor.endSelection();
|
|
994
|
-
const isLogBodyEmpty = grandparent[
|
|
723
|
+
const isLogBodyEmpty = grandparent[mathQuillInstance.R].contentjQ.text() === "";
|
|
995
724
|
if (isLogBodyEmpty) {
|
|
996
725
|
// If there's no content inside the log's parens then delete the
|
|
997
726
|
// whole thing.
|
|
@@ -1010,8 +739,8 @@ function handleBackspaceOutsideParens(cursor) {
|
|
|
1010
739
|
// (x+1)| => |(x+1)|
|
|
1011
740
|
// \log(x+1)| => |\log(x+1)|
|
|
1012
741
|
|
|
1013
|
-
const leftNode = cursor[
|
|
1014
|
-
const rightNode = cursor[
|
|
742
|
+
const leftNode = cursor[mathQuillInstance.L];
|
|
743
|
+
const rightNode = cursor[mathQuillInstance.R];
|
|
1015
744
|
const command = maybeFindCommandBeforeParens(leftNode);
|
|
1016
745
|
if (command && command.startNode) {
|
|
1017
746
|
// There's a command before the parens so we select it as well as
|
|
@@ -1057,7 +786,7 @@ function handleBackspaceInsideParens(mathField, cursor) {
|
|
|
1057
786
|
// - \log(|x+1) => |\log(x+1)|
|
|
1058
787
|
// - \log(|) => |
|
|
1059
788
|
|
|
1060
|
-
if (cursor[
|
|
789
|
+
if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
|
|
1061
790
|
// This command contains math and there's some math to
|
|
1062
791
|
// the left of the cursor that we should delete normally
|
|
1063
792
|
// before doing anything special.
|
|
@@ -1070,12 +799,12 @@ function handleBackspaceInsideParens(mathField, cursor) {
|
|
|
1070
799
|
// has a subscript as is the case in log_n then move the cursor into
|
|
1071
800
|
// the subscript, e.g. \log_{5}(|x+1) => \log_{5|}(x+1)
|
|
1072
801
|
|
|
1073
|
-
if (grandparent[
|
|
802
|
+
if (grandparent[mathQuillInstance.L].sub) {
|
|
1074
803
|
// if there is a subscript
|
|
1075
|
-
if (grandparent[
|
|
804
|
+
if (grandparent[mathQuillInstance.L].sub.jQ.text()) {
|
|
1076
805
|
// and it contains text
|
|
1077
806
|
// move the cursor to the right end of the subscript
|
|
1078
|
-
cursor.insAtRightEnd(grandparent[
|
|
807
|
+
cursor.insAtRightEnd(grandparent[mathQuillInstance.L].sub);
|
|
1079
808
|
return;
|
|
1080
809
|
}
|
|
1081
810
|
}
|
|
@@ -1113,7 +842,7 @@ function handleBackspace(mathField) {
|
|
|
1113
842
|
if (!cursor.selection) {
|
|
1114
843
|
const parent = cursor.parent;
|
|
1115
844
|
const grandparent = parent.parent;
|
|
1116
|
-
const leftNode = cursor[
|
|
845
|
+
const leftNode = cursor[mathQuillInstance.L];
|
|
1117
846
|
if (isFraction(leftNode)) {
|
|
1118
847
|
selectNode(leftNode, cursor);
|
|
1119
848
|
} else if (isSquareRoot(leftNode)) {
|
|
@@ -1140,6 +869,133 @@ function handleBackspace(mathField) {
|
|
|
1140
869
|
}
|
|
1141
870
|
}
|
|
1142
871
|
|
|
872
|
+
/**
|
|
873
|
+
* Constants that are shared between multiple files.
|
|
874
|
+
*/
|
|
875
|
+
|
|
876
|
+
let KeypadType = /*#__PURE__*/function (KeypadType) {
|
|
877
|
+
KeypadType["FRACTION"] = "FRACTION";
|
|
878
|
+
KeypadType["EXPRESSION"] = "EXPRESSION";
|
|
879
|
+
return KeypadType;
|
|
880
|
+
}({});
|
|
881
|
+
const KeyTypes = ["EMPTY",
|
|
882
|
+
// For numerals, variables, and any other characters that themselves
|
|
883
|
+
// compose 'values'.
|
|
884
|
+
"VALUE",
|
|
885
|
+
// For buttons that insert or adjust math in an input.
|
|
886
|
+
"OPERATOR",
|
|
887
|
+
// For buttons that move the cursor in an input (including via
|
|
888
|
+
// deletion).
|
|
889
|
+
"INPUT_NAVIGATION",
|
|
890
|
+
// For buttons that modify the broader keypad state (e.g., by changing
|
|
891
|
+
// the visible pane).
|
|
892
|
+
"KEYPAD_NAVIGATION",
|
|
893
|
+
// For buttons that house multiple buttons and have no action
|
|
894
|
+
// themselves.
|
|
895
|
+
"MANY",
|
|
896
|
+
// For the echo animation that appears on press.
|
|
897
|
+
"ECHO"];
|
|
898
|
+
let DeviceOrientation = /*#__PURE__*/function (DeviceOrientation) {
|
|
899
|
+
DeviceOrientation["LANDSCAPE"] = "LANDSCAPE";
|
|
900
|
+
DeviceOrientation["PORTRAIT"] = "PORTRAIT";
|
|
901
|
+
return DeviceOrientation;
|
|
902
|
+
}({});
|
|
903
|
+
let DeviceType = /*#__PURE__*/function (DeviceType) {
|
|
904
|
+
DeviceType["PHONE"] = "PHONE";
|
|
905
|
+
DeviceType["TABLET"] = "TABLET";
|
|
906
|
+
return DeviceType;
|
|
907
|
+
}({});
|
|
908
|
+
let LayoutMode = /*#__PURE__*/function (LayoutMode) {
|
|
909
|
+
LayoutMode["FULLSCREEN"] = "FULLSCREEN";
|
|
910
|
+
LayoutMode["COMPACT"] = "COMPACT";
|
|
911
|
+
return LayoutMode;
|
|
912
|
+
}({});
|
|
913
|
+
let BorderDirection = /*#__PURE__*/function (BorderDirection) {
|
|
914
|
+
BorderDirection["LEFT"] = "LEFT";
|
|
915
|
+
BorderDirection["BOTTOM"] = "BOTTOM";
|
|
916
|
+
return BorderDirection;
|
|
917
|
+
}({});
|
|
918
|
+
const BorderStyles = {
|
|
919
|
+
LEFT: [BorderDirection.LEFT],
|
|
920
|
+
BOTTOM: [BorderDirection.BOTTOM],
|
|
921
|
+
ALL: [BorderDirection.LEFT, BorderDirection.BOTTOM],
|
|
922
|
+
NONE: []
|
|
923
|
+
};
|
|
924
|
+
let IconType = /*#__PURE__*/function (IconType) {
|
|
925
|
+
IconType["MATH"] = "MATH";
|
|
926
|
+
IconType["SVG"] = "SVG";
|
|
927
|
+
IconType["TEXT"] = "TEXT";
|
|
928
|
+
return IconType;
|
|
929
|
+
}({});
|
|
930
|
+
let DecimalSeparator = /*#__PURE__*/function (DecimalSeparator) {
|
|
931
|
+
DecimalSeparator["COMMA"] = "COMMA";
|
|
932
|
+
DecimalSeparator["PERIOD"] = "PERIOD";
|
|
933
|
+
return DecimalSeparator;
|
|
934
|
+
}({});
|
|
935
|
+
let EchoAnimationType = /*#__PURE__*/function (EchoAnimationType) {
|
|
936
|
+
EchoAnimationType["SLIDE_AND_FADE"] = "SLIDE_AND_FADE";
|
|
937
|
+
EchoAnimationType["FADE_ONLY"] = "FADE_ONLY";
|
|
938
|
+
EchoAnimationType["LONG_FADE_ONLY"] = "LONG_FADE_ONLY";
|
|
939
|
+
return EchoAnimationType;
|
|
940
|
+
}({});
|
|
941
|
+
|
|
942
|
+
// NOTES(kevinb):
|
|
943
|
+
// - In order to get the correct decimal separator for the current locale,
|
|
944
|
+
// the locale must bet set using `setLocale(kaLocale)` which can be
|
|
945
|
+
// imported from wonder-blocks-i18n.
|
|
946
|
+
// - Some languages/locales use different decimal separators than the ones
|
|
947
|
+
// listed here. Much of the Arab world uses U+066C.
|
|
948
|
+
const decimalSeparator = i18n.getDecimalSeparator() === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
|
|
949
|
+
|
|
950
|
+
function handleLeftArrow(mathField, cursor) {
|
|
951
|
+
// If we're inside a function, and just after the left parentheses, we
|
|
952
|
+
// need to skip the entire function name, rather than move the cursor
|
|
953
|
+
// inside of it. For example, when hitting left from within the
|
|
954
|
+
// parentheses in `cos()`, we want to place the cursor to the left of
|
|
955
|
+
// the entire expression, rather than between the `s` and the left
|
|
956
|
+
// parenthesis.
|
|
957
|
+
// From the cursor's perspective, this requires that our left node is
|
|
958
|
+
// the ActionType.MQ_END node, that our grandparent is the left parenthesis, and
|
|
959
|
+
// the nodes to the left of our grandparent comprise a valid function
|
|
960
|
+
// name.
|
|
961
|
+
if (cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END) {
|
|
962
|
+
const parent = cursor.parent;
|
|
963
|
+
const grandparent = parent.parent;
|
|
964
|
+
if (grandparent.ctrlSeq === "\\left(") {
|
|
965
|
+
const command = maybeFindCommandBeforeParens(grandparent);
|
|
966
|
+
if (command) {
|
|
967
|
+
cursor.insLeftOf(command.startNode);
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// Otherwise, we default to the standard MathQull left behavior.
|
|
974
|
+
mathField.keystroke("Left");
|
|
975
|
+
}
|
|
976
|
+
function handleRightArrow(mathField, cursor) {
|
|
977
|
+
const command = maybeFindCommand(cursor[mathQuillInstance.R]);
|
|
978
|
+
if (command) {
|
|
979
|
+
// Similarly, if a function is to our right, then we need to place
|
|
980
|
+
// the cursor at the start of its parenthetical content, which is
|
|
981
|
+
// done by putting it to the left of ites parentheses and then
|
|
982
|
+
// moving right once.
|
|
983
|
+
cursor.insLeftOf(command.endNode);
|
|
984
|
+
mathField.keystroke("Right");
|
|
985
|
+
} else {
|
|
986
|
+
// Otherwise, we default to the standard MathQull right behavior.
|
|
987
|
+
mathField.keystroke("Right");
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function handleArrow(mathField, key) {
|
|
991
|
+
const cursor = getCursor(mathField);
|
|
992
|
+
if (key === "LEFT") {
|
|
993
|
+
handleLeftArrow(mathField, cursor);
|
|
994
|
+
} else if (key === "RIGHT") {
|
|
995
|
+
handleRightArrow(mathField, cursor);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
1143
999
|
const ArithmeticOperators = ["+", "-", "\\cdot", "\\times", "\\div"];
|
|
1144
1000
|
const EqualityOperators = ["=", "\\neq", "<", "\\leq", ">", "\\geq"];
|
|
1145
1001
|
function handleExponent(mathField, key) {
|
|
@@ -1148,7 +1004,7 @@ function handleExponent(mathField, key) {
|
|
|
1148
1004
|
// knowingly cannot be raised to a power), add an empty set of
|
|
1149
1005
|
// parentheses and apply the exponent to that.
|
|
1150
1006
|
const invalidPrefixes = [...ArithmeticOperators, ...EqualityOperators];
|
|
1151
|
-
const precedingNode = cursor[
|
|
1007
|
+
const precedingNode = cursor[mathQuillInstance.L];
|
|
1152
1008
|
const shouldPrefixWithParens = precedingNode === MathFieldActionType.MQ_END || invalidPrefixes.includes(precedingNode.ctrlSeq.trim());
|
|
1153
1009
|
if (shouldPrefixWithParens) {
|
|
1154
1010
|
mathField.write("\\left(\\right)");
|
|
@@ -1214,11 +1070,11 @@ function handleJumpOut(mathField, key) {
|
|
|
1214
1070
|
// Find the nearest fraction to the right of the cursor.
|
|
1215
1071
|
let fractionNode;
|
|
1216
1072
|
let visitor = cursor;
|
|
1217
|
-
while (visitor[
|
|
1218
|
-
if (isFraction(visitor[
|
|
1219
|
-
fractionNode = visitor[
|
|
1073
|
+
while (visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
|
|
1074
|
+
if (isFraction(visitor[mathQuillInstance.R])) {
|
|
1075
|
+
fractionNode = visitor[mathQuillInstance.R];
|
|
1220
1076
|
}
|
|
1221
|
-
visitor = visitor[
|
|
1077
|
+
visitor = visitor[mathQuillInstance.R];
|
|
1222
1078
|
}
|
|
1223
1079
|
|
|
1224
1080
|
// Jump into it!
|
|
@@ -1247,7 +1103,7 @@ function handleJumpOut(mathField, key) {
|
|
|
1247
1103
|
// Navigate right once more, if we're right before parens. This
|
|
1248
1104
|
// is to handle the standard case in which the subscript is the
|
|
1249
1105
|
// base of a custom log.
|
|
1250
|
-
if (isParens(cursor[
|
|
1106
|
+
if (isParens(cursor[mathQuillInstance.R])) {
|
|
1251
1107
|
mathField.keystroke("Right");
|
|
1252
1108
|
}
|
|
1253
1109
|
break;
|
|
@@ -1260,26 +1116,46 @@ function handleJumpOut(mathField, key) {
|
|
|
1260
1116
|
}
|
|
1261
1117
|
}
|
|
1262
1118
|
|
|
1119
|
+
var ActionType = /*#__PURE__*/function (ActionType) {
|
|
1120
|
+
ActionType["WRITE"] = "write";
|
|
1121
|
+
ActionType["CMD"] = "cmd";
|
|
1122
|
+
ActionType["KEYSTROKE"] = "keystroke";
|
|
1123
|
+
ActionType[ActionType["MQ_END"] = 0] = "MQ_END";
|
|
1124
|
+
return ActionType;
|
|
1125
|
+
}(ActionType || {});
|
|
1126
|
+
const decimalSymbol = decimalSeparator === DecimalSeparator.COMMA ? "," : ".";
|
|
1127
|
+
function buildGenericCallback(str) {
|
|
1128
|
+
let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ActionType.WRITE;
|
|
1129
|
+
return function (mathQuill) {
|
|
1130
|
+
switch (type) {
|
|
1131
|
+
case ActionType.WRITE:
|
|
1132
|
+
{
|
|
1133
|
+
mathQuill.write(str);
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
case ActionType.CMD:
|
|
1137
|
+
{
|
|
1138
|
+
mathQuill.cmd(str);
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
case ActionType.KEYSTROKE:
|
|
1142
|
+
{
|
|
1143
|
+
mathQuill.keystroke(str);
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1263
1149
|
function buildNormalFunctionCallback(command) {
|
|
1264
1150
|
return function (mathField) {
|
|
1265
1151
|
mathField.write("\\".concat(command, "\\left(\\right)"));
|
|
1266
1152
|
mathField.keystroke("Left");
|
|
1267
1153
|
};
|
|
1268
1154
|
}
|
|
1269
|
-
const
|
|
1270
|
-
...keyToMathquillMap,
|
|
1271
|
-
// note(Matthew): in all likelihood, this should be moved
|
|
1272
|
-
// to the shared key2MathQuill translator. During this refactor
|
|
1273
|
-
// I tried to keep logic the same while deduplicating code.
|
|
1274
|
-
// Perseus' Expression MathInput treats this stuff differently
|
|
1275
|
-
// (or doesn't do anything with them at all), so I kept it that way
|
|
1276
|
-
BACKSPACE: handleBackspace,
|
|
1155
|
+
const keyToMathquillMap = {
|
|
1277
1156
|
EXP: handleExponent,
|
|
1278
1157
|
EXP_2: handleExponent,
|
|
1279
1158
|
EXP_3: handleExponent,
|
|
1280
|
-
FRAC: mathQuill => {
|
|
1281
|
-
mathQuill.cmd("\\frac");
|
|
1282
|
-
},
|
|
1283
1159
|
JUMP_OUT_PARENTHESES: handleJumpOut,
|
|
1284
1160
|
JUMP_OUT_EXPONENT: handleJumpOut,
|
|
1285
1161
|
JUMP_OUT_BASE: handleJumpOut,
|
|
@@ -1292,7 +1168,158 @@ const customKeyTranslator = {
|
|
|
1292
1168
|
LN: buildNormalFunctionCallback("ln"),
|
|
1293
1169
|
SIN: buildNormalFunctionCallback("sin"),
|
|
1294
1170
|
COS: buildNormalFunctionCallback("cos"),
|
|
1295
|
-
TAN: buildNormalFunctionCallback("tan")
|
|
1171
|
+
TAN: buildNormalFunctionCallback("tan"),
|
|
1172
|
+
CDOT: buildGenericCallback("\\cdot"),
|
|
1173
|
+
DECIMAL: buildGenericCallback(decimalSymbol),
|
|
1174
|
+
DIVIDE: buildGenericCallback("\\div"),
|
|
1175
|
+
EQUAL: buildGenericCallback("="),
|
|
1176
|
+
GEQ: buildGenericCallback("\\geq"),
|
|
1177
|
+
GT: buildGenericCallback(">"),
|
|
1178
|
+
LEQ: buildGenericCallback("\\leq"),
|
|
1179
|
+
LT: buildGenericCallback("<"),
|
|
1180
|
+
MINUS: buildGenericCallback("-"),
|
|
1181
|
+
NEGATIVE: buildGenericCallback("-"),
|
|
1182
|
+
NEQ: buildGenericCallback("\\neq"),
|
|
1183
|
+
PERCENT: buildGenericCallback("%"),
|
|
1184
|
+
PERIOD: buildGenericCallback("."),
|
|
1185
|
+
PLUS: buildGenericCallback("+"),
|
|
1186
|
+
TIMES: buildGenericCallback("\\times"),
|
|
1187
|
+
// The `FRAC_EXCLUSIVE` variant is handled manually, since we may need to do
|
|
1188
|
+
// some additional navigation depending on the cursor position.
|
|
1189
|
+
FRAC_INCLUSIVE: buildGenericCallback("/", ActionType.CMD),
|
|
1190
|
+
FRAC: buildGenericCallback("\\frac", ActionType.CMD),
|
|
1191
|
+
LEFT_PAREN: buildGenericCallback("(", ActionType.CMD),
|
|
1192
|
+
RIGHT_PAREN: buildGenericCallback(")", ActionType.CMD),
|
|
1193
|
+
SQRT: buildGenericCallback("sqrt", ActionType.CMD),
|
|
1194
|
+
PHI: buildGenericCallback("\\phi", ActionType.CMD),
|
|
1195
|
+
PI: buildGenericCallback("pi", ActionType.CMD),
|
|
1196
|
+
THETA: buildGenericCallback("theta", ActionType.CMD),
|
|
1197
|
+
RADICAL: buildGenericCallback("nthroot", ActionType.CMD),
|
|
1198
|
+
BACKSPACE: buildGenericCallback("Backspace", ActionType.KEYSTROKE),
|
|
1199
|
+
UP: buildGenericCallback("Up", ActionType.KEYSTROKE),
|
|
1200
|
+
DOWN: buildGenericCallback("Down", ActionType.KEYSTROKE),
|
|
1201
|
+
CUBE_ROOT: mathQuill => {
|
|
1202
|
+
mathQuill.write("\\sqrt[3]{}");
|
|
1203
|
+
mathQuill.keystroke("Left"); // under the root
|
|
1204
|
+
},
|
|
1205
|
+
|
|
1206
|
+
FRAC_EXCLUSIVE: mathQuill => {
|
|
1207
|
+
const cursor = mathQuill.__controller.cursor;
|
|
1208
|
+
// If there's nothing to the left of the cursor, then we want to
|
|
1209
|
+
// leave the cursor to the left of the fraction after creating it.
|
|
1210
|
+
const shouldNavigateLeft = cursor[mathQuillInstance.L] === ActionType.MQ_END;
|
|
1211
|
+
mathQuill.cmd("\\frac");
|
|
1212
|
+
if (shouldNavigateLeft) {
|
|
1213
|
+
mathQuill.keystroke("Left");
|
|
1214
|
+
}
|
|
1215
|
+
},
|
|
1216
|
+
LOG_B: mathQuill => {
|
|
1217
|
+
mathQuill.typedText("log_");
|
|
1218
|
+
mathQuill.keystroke("Right");
|
|
1219
|
+
mathQuill.typedText("(");
|
|
1220
|
+
mathQuill.keystroke("Left");
|
|
1221
|
+
mathQuill.keystroke("Left");
|
|
1222
|
+
},
|
|
1223
|
+
LOG_N: mathQuill => {
|
|
1224
|
+
mathQuill.write("log_{ }\\left(\\right)");
|
|
1225
|
+
mathQuill.keystroke("Left"); // into parentheses
|
|
1226
|
+
mathQuill.keystroke("Left"); // out of parentheses
|
|
1227
|
+
mathQuill.keystroke("Left"); // into index
|
|
1228
|
+
},
|
|
1229
|
+
|
|
1230
|
+
NTHROOT3: mathQuill => {
|
|
1231
|
+
mathQuill.typedText("nthroot3");
|
|
1232
|
+
mathQuill.keystroke("Right");
|
|
1233
|
+
},
|
|
1234
|
+
POW: mathQuill => {
|
|
1235
|
+
const contents = mathQuill.latex();
|
|
1236
|
+
mathQuill.typedText("^");
|
|
1237
|
+
|
|
1238
|
+
// If the input hasn't changed (for example, if we're
|
|
1239
|
+
// attempting to add an exponent on an empty input or an empty
|
|
1240
|
+
// denominator), insert our own "a^b"
|
|
1241
|
+
if (mathQuill.latex() === contents) {
|
|
1242
|
+
mathQuill.typedText("a^b");
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
1245
|
+
// These need to be overwritten by the consumer
|
|
1246
|
+
// if they're going to be used
|
|
1247
|
+
DISMISS: () => {},
|
|
1248
|
+
NOOP: () => {},
|
|
1249
|
+
MANY: () => {},
|
|
1250
|
+
NUM_0: buildGenericCallback("0"),
|
|
1251
|
+
NUM_1: buildGenericCallback("1"),
|
|
1252
|
+
NUM_2: buildGenericCallback("2"),
|
|
1253
|
+
NUM_3: buildGenericCallback("3"),
|
|
1254
|
+
NUM_4: buildGenericCallback("4"),
|
|
1255
|
+
NUM_5: buildGenericCallback("5"),
|
|
1256
|
+
NUM_6: buildGenericCallback("6"),
|
|
1257
|
+
NUM_7: buildGenericCallback("7"),
|
|
1258
|
+
NUM_8: buildGenericCallback("8"),
|
|
1259
|
+
NUM_9: buildGenericCallback("9"),
|
|
1260
|
+
a: buildGenericCallback("a"),
|
|
1261
|
+
b: buildGenericCallback("b"),
|
|
1262
|
+
c: buildGenericCallback("c"),
|
|
1263
|
+
d: buildGenericCallback("d"),
|
|
1264
|
+
e: buildGenericCallback("e"),
|
|
1265
|
+
f: buildGenericCallback("f"),
|
|
1266
|
+
g: buildGenericCallback("g"),
|
|
1267
|
+
h: buildGenericCallback("h"),
|
|
1268
|
+
i: buildGenericCallback("i"),
|
|
1269
|
+
j: buildGenericCallback("j"),
|
|
1270
|
+
k: buildGenericCallback("k"),
|
|
1271
|
+
l: buildGenericCallback("l"),
|
|
1272
|
+
m: buildGenericCallback("m"),
|
|
1273
|
+
n: buildGenericCallback("n"),
|
|
1274
|
+
o: buildGenericCallback("o"),
|
|
1275
|
+
p: buildGenericCallback("p"),
|
|
1276
|
+
q: buildGenericCallback("q"),
|
|
1277
|
+
r: buildGenericCallback("r"),
|
|
1278
|
+
s: buildGenericCallback("s"),
|
|
1279
|
+
t: buildGenericCallback("t"),
|
|
1280
|
+
u: buildGenericCallback("u"),
|
|
1281
|
+
v: buildGenericCallback("v"),
|
|
1282
|
+
w: buildGenericCallback("w"),
|
|
1283
|
+
x: buildGenericCallback("x"),
|
|
1284
|
+
y: buildGenericCallback("y"),
|
|
1285
|
+
z: buildGenericCallback("z"),
|
|
1286
|
+
A: buildGenericCallback("A"),
|
|
1287
|
+
B: buildGenericCallback("B"),
|
|
1288
|
+
C: buildGenericCallback("C"),
|
|
1289
|
+
D: buildGenericCallback("D"),
|
|
1290
|
+
E: buildGenericCallback("E"),
|
|
1291
|
+
F: buildGenericCallback("F"),
|
|
1292
|
+
G: buildGenericCallback("G"),
|
|
1293
|
+
H: buildGenericCallback("H"),
|
|
1294
|
+
I: buildGenericCallback("I"),
|
|
1295
|
+
J: buildGenericCallback("J"),
|
|
1296
|
+
K: buildGenericCallback("K"),
|
|
1297
|
+
L: buildGenericCallback("L"),
|
|
1298
|
+
M: buildGenericCallback("M"),
|
|
1299
|
+
N: buildGenericCallback("N"),
|
|
1300
|
+
O: buildGenericCallback("O"),
|
|
1301
|
+
P: buildGenericCallback("P"),
|
|
1302
|
+
Q: buildGenericCallback("Q"),
|
|
1303
|
+
R: buildGenericCallback("R"),
|
|
1304
|
+
S: buildGenericCallback("S"),
|
|
1305
|
+
T: buildGenericCallback("T"),
|
|
1306
|
+
U: buildGenericCallback("U"),
|
|
1307
|
+
V: buildGenericCallback("V"),
|
|
1308
|
+
W: buildGenericCallback("W"),
|
|
1309
|
+
X: buildGenericCallback("X"),
|
|
1310
|
+
Y: buildGenericCallback("Y"),
|
|
1311
|
+
Z: buildGenericCallback("Z")
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1314
|
+
const mobileKeyTranslator = {
|
|
1315
|
+
...keyToMathquillMap,
|
|
1316
|
+
// note(Matthew): our mobile backspace logic is really complicated
|
|
1317
|
+
// and for some reason doesn't really work in the desktop experience.
|
|
1318
|
+
// So we default to the basic backspace functionality in the
|
|
1319
|
+
// key translator and overwrite it with the complicated logic here
|
|
1320
|
+
// until we can unify the experiences (if we even want to).
|
|
1321
|
+
// https://khanacademy.atlassian.net/browse/LC-906
|
|
1322
|
+
BACKSPACE: handleBackspace
|
|
1296
1323
|
};
|
|
1297
1324
|
|
|
1298
1325
|
/**
|
|
@@ -1301,18 +1328,20 @@ const customKeyTranslator = {
|
|
|
1301
1328
|
* from MathQuill changes.
|
|
1302
1329
|
*/
|
|
1303
1330
|
class MathWrapper {
|
|
1304
|
-
// MathQuill input
|
|
1331
|
+
// MathQuill MathField input
|
|
1305
1332
|
|
|
1306
1333
|
constructor(element) {
|
|
1307
|
-
let callbacks = arguments.length >
|
|
1334
|
+
let callbacks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1308
1335
|
_defineProperty(this, "mathField", void 0);
|
|
1309
1336
|
_defineProperty(this, "callbacks", void 0);
|
|
1310
|
-
this.mathField =
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1337
|
+
this.mathField = createMathField(element, () => {
|
|
1338
|
+
return {
|
|
1339
|
+
// use a span instead of a textarea so that we don't bring up the
|
|
1340
|
+
// native keyboard on mobile when selecting the input
|
|
1341
|
+
substituteTextarea: function () {
|
|
1342
|
+
return document.createElement("span");
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1316
1345
|
});
|
|
1317
1346
|
this.callbacks = callbacks;
|
|
1318
1347
|
}
|
|
@@ -1342,7 +1371,7 @@ class MathWrapper {
|
|
|
1342
1371
|
*/
|
|
1343
1372
|
pressKey(key) {
|
|
1344
1373
|
const cursor = this.getCursor();
|
|
1345
|
-
const translator =
|
|
1374
|
+
const translator = mobileKeyTranslator[key];
|
|
1346
1375
|
if (translator) {
|
|
1347
1376
|
translator(this.mathField, key);
|
|
1348
1377
|
}
|
|
@@ -1390,7 +1419,7 @@ class MathWrapper {
|
|
|
1390
1419
|
// Unless that would leave us mid-command, in which case, we
|
|
1391
1420
|
// need to adjust and place the cursor inside the parens
|
|
1392
1421
|
// following the command.
|
|
1393
|
-
const command = maybeFindCommand(cursor[
|
|
1422
|
+
const command = maybeFindCommand(cursor[mathQuillInstance.L]);
|
|
1394
1423
|
if (command && command.endNode) {
|
|
1395
1424
|
// NOTE(charlie): endNode should definitely be \left(.
|
|
1396
1425
|
cursor.insLeftOf(command.endNode);
|
|
@@ -1961,7 +1990,7 @@ class MathInput extends React__namespace.Component {
|
|
|
1961
1990
|
}
|
|
1962
1991
|
componentDidMount() {
|
|
1963
1992
|
this._isMounted = true;
|
|
1964
|
-
this.mathField = new MathWrapper(this._mathContainer, {
|
|
1993
|
+
this.mathField = new MathWrapper(this._mathContainer, {
|
|
1965
1994
|
onCursorMove: cursor => {
|
|
1966
1995
|
// TODO(charlie): It's not great that there is so much coupling
|
|
1967
1996
|
// between this keypad and the input behavior. We should wrap
|
|
@@ -8363,7 +8392,7 @@ const KeypadButton = _ref2 => {
|
|
|
8363
8392
|
onPress: () => onClickKey(keyConfig.id),
|
|
8364
8393
|
tintColor: tintColor,
|
|
8365
8394
|
style: style,
|
|
8366
|
-
ariaLabel: keyConfig.
|
|
8395
|
+
ariaLabel: keyConfig.ariaLabel
|
|
8367
8396
|
}, /*#__PURE__*/React__namespace.createElement(ButtonAsset, {
|
|
8368
8397
|
id: keyConfig.id
|
|
8369
8398
|
}));
|
|
@@ -8793,6 +8822,8 @@ exports.Keypad = Keypad;
|
|
|
8793
8822
|
exports.KeypadInput = MathInput;
|
|
8794
8823
|
exports.KeypadType = KeypadType;
|
|
8795
8824
|
exports.LegacyKeypad = ProvidedKeypad;
|
|
8825
|
+
exports.createMathField = createMathField;
|
|
8796
8826
|
exports.keyTranslator = keyToMathquillMap;
|
|
8797
8827
|
exports.keypadElementPropType = keypadElementPropType;
|
|
8828
|
+
exports.mathQuillInstance = mathQuillInstance;
|
|
8798
8829
|
//# sourceMappingURL=index.js.map
|