@khanacademy/math-input 4.1.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/components/input/math-wrapper.d.ts +1 -1
  3. package/dist/components/input/math-wrapper.js.flow +1 -1
  4. package/dist/components/input/mathquill-instance.d.ts +14 -3
  5. package/dist/components/input/mathquill-instance.js.flow +18 -3
  6. package/dist/components/input/mathquill-types.d.ts +30 -6
  7. package/dist/components/input/mathquill-types.js.flow +33 -7
  8. package/dist/components/key-handlers/handle-arrow.d.ts +3 -0
  9. package/dist/components/{input/key-handlers → key-handlers}/handle-arrow.js.flow +2 -2
  10. package/dist/components/{input/key-handlers → key-handlers}/handle-backspace.d.ts +1 -1
  11. package/dist/components/{input/key-handlers → key-handlers}/handle-backspace.js.flow +1 -1
  12. package/dist/components/key-handlers/handle-exponent.d.ts +3 -0
  13. package/dist/components/{input/key-handlers → key-handlers}/handle-exponent.js.flow +2 -2
  14. package/dist/components/{input/key-handlers → key-handlers}/handle-jump-out.d.ts +2 -2
  15. package/dist/components/{input/key-handlers → key-handlers}/handle-jump-out.js.flow +2 -2
  16. package/dist/components/key-handlers/key-translator.d.ts +4 -0
  17. package/dist/components/{key-translator.js.flow → key-handlers/key-translator.js.flow} +3 -3
  18. package/dist/components/keypad/index.d.ts +8 -16
  19. package/dist/components/keypad/index.js.flow +10 -22
  20. package/dist/components/keypad/keypad-button.d.ts +12 -0
  21. package/dist/components/keypad/keypad-button.js.flow +18 -0
  22. package/dist/components/keypad/keypad-pages/extras-page.d.ts +9 -0
  23. package/dist/components/keypad/{operators-page/basic-relations-buttons.js.flow → keypad-pages/extras-page.js.flow} +3 -3
  24. package/dist/components/keypad/keypad-pages/geometry-page.d.ts +7 -0
  25. package/dist/components/keypad/{operators-page/logarithms-buttons.js.flow → keypad-pages/geometry-page.js.flow} +1 -3
  26. package/dist/components/keypad/keypad-pages/numbers-page.d.ts +7 -0
  27. package/dist/components/keypad/{operators-page/pre-algebra-buttons.js.flow → keypad-pages/numbers-page.js.flow} +1 -3
  28. package/dist/components/keypad/keypad-pages/operators-page.d.ts +11 -0
  29. package/dist/components/keypad/{geometry-page/index.js.flow → keypad-pages/operators-page.js.flow} +5 -4
  30. package/dist/components/keypad/shared-keys.d.ts +9 -0
  31. package/dist/components/keypad/{numbers-page/types.js.flow → shared-keys.js.flow} +4 -1
  32. package/dist/es/index.js +763 -878
  33. package/dist/es/index.js.map +1 -1
  34. package/dist/index.d.ts +3 -1
  35. package/dist/index.js +740 -878
  36. package/dist/index.js.flow +6 -1
  37. package/dist/index.js.map +1 -1
  38. package/package.json +2 -3
  39. package/src/components/input/__tests__/test-math-wrapper.ts +2 -5
  40. package/src/components/input/math-input.tsx +10 -14
  41. package/src/components/input/math-wrapper.ts +23 -49
  42. package/src/components/input/mathquill-helpers.ts +11 -11
  43. package/src/components/input/mathquill-instance.ts +57 -2
  44. package/src/components/input/mathquill-types.ts +43 -7
  45. package/src/components/{input/key-handlers → key-handlers}/handle-arrow.ts +6 -6
  46. package/src/components/{input/key-handlers → key-handlers}/handle-backspace.ts +19 -17
  47. package/src/components/{input/key-handlers → key-handlers}/handle-exponent.ts +8 -5
  48. package/src/components/{input/key-handlers → key-handlers}/handle-jump-out.ts +15 -10
  49. package/src/components/{key-translator.ts → key-handlers/key-translator.ts} +43 -28
  50. package/src/components/keypad/__tests__/{KeypadButton.test.tsx → keypad-button.test.tsx} +7 -5
  51. package/src/components/keypad/__tests__/keypad-v2-mathquill.test.tsx +231 -0
  52. package/src/components/keypad/__tests__/keypad-v2.cypress.ts +19 -6
  53. package/src/components/keypad/index.tsx +73 -49
  54. package/src/components/keypad/{button.stories.tsx → keypad-button.stories.tsx} +2 -1
  55. package/src/components/keypad/keypad-button.tsx +128 -0
  56. package/src/components/keypad/keypad-mathquill.stories.tsx +24 -26
  57. package/src/components/keypad/keypad-pages/extras-page.tsx +34 -0
  58. package/src/components/keypad/keypad-pages/geometry-page.tsx +33 -0
  59. package/src/components/keypad/keypad-pages/numbers-page.tsx +84 -0
  60. package/src/components/keypad/keypad-pages/operators-page.tsx +116 -0
  61. package/src/components/keypad/shared-keys.tsx +78 -0
  62. package/src/index.ts +6 -1
  63. package/tsconfig-build.tsbuildinfo +1 -1
  64. package/dist/components/input/key-handlers/handle-arrow.d.ts +0 -3
  65. package/dist/components/input/key-handlers/handle-exponent.d.ts +0 -3
  66. package/dist/components/key-translator.d.ts +0 -4
  67. package/dist/components/keypad/button.d.ts +0 -12
  68. package/dist/components/keypad/button.js.flow +0 -18
  69. package/dist/components/keypad/extras-page/index.d.ts +0 -10
  70. package/dist/components/keypad/extras-page/index.js.flow +0 -15
  71. package/dist/components/keypad/geometry-page/index.d.ts +0 -9
  72. package/dist/components/keypad/keypad-page-items.d.ts +0 -26
  73. package/dist/components/keypad/keypad-page-items.js.flow +0 -40
  74. package/dist/components/keypad/numbers-page/index.d.ts +0 -10
  75. package/dist/components/keypad/numbers-page/index.js.flow +0 -18
  76. package/dist/components/keypad/numbers-page/types.d.ts +0 -4
  77. package/dist/components/keypad/operators-page/advanced-relations-buttons.d.ts +0 -8
  78. package/dist/components/keypad/operators-page/advanced-relations-buttons.js.flow +0 -13
  79. package/dist/components/keypad/operators-page/basic-relations-buttons.d.ts +0 -8
  80. package/dist/components/keypad/operators-page/index.d.ts +0 -10
  81. package/dist/components/keypad/operators-page/index.js.flow +0 -18
  82. package/dist/components/keypad/operators-page/logarithms-buttons.d.ts +0 -8
  83. package/dist/components/keypad/operators-page/pre-algebra-buttons.d.ts +0 -8
  84. package/dist/components/keypad/operators-page/types.d.ts +0 -6
  85. package/dist/components/keypad/operators-page/types.js.flow +0 -12
  86. package/src/components/keypad/__tests__/Button.test.tsx +0 -51
  87. package/src/components/keypad/button.tsx +0 -108
  88. package/src/components/keypad/extras-page/index.tsx +0 -27
  89. package/src/components/keypad/geometry-page/index.tsx +0 -89
  90. package/src/components/keypad/keypad-page-items.tsx +0 -118
  91. package/src/components/keypad/numbers-page/index.tsx +0 -136
  92. package/src/components/keypad/numbers-page/types.ts +0 -4
  93. package/src/components/keypad/operators-page/advanced-relations-buttons.tsx +0 -33
  94. package/src/components/keypad/operators-page/basic-relations-buttons.tsx +0 -33
  95. package/src/components/keypad/operators-page/index.tsx +0 -94
  96. package/src/components/keypad/operators-page/logarithms-buttons.tsx +0 -33
  97. package/src/components/keypad/operators-page/pre-algebra-buttons.tsx +0 -37
  98. package/src/components/keypad/operators-page/types.ts +0 -6
  99. /package/src/components/keypad/{keypad-pages.stories.tsx → keypad-pages/keypad-pages.stories.tsx} +0 -0
package/dist/es/index.js CHANGED
@@ -4,7 +4,6 @@ import { getDecimalSeparator } from '@khanacademy/wonder-blocks-i18n';
4
4
  import { entries } from '@khanacademy/wonder-stuff-core';
5
5
  import { StyleSheet, css } from 'aphrodite';
6
6
  import * as React from 'react';
7
- import React__default from 'react';
8
7
  import ReactDOM from 'react-dom';
9
8
  import $ from 'jquery';
10
9
  import MathQuill from 'mathquill';
@@ -341,273 +340,52 @@ class DragListener {
341
340
  }
342
341
  }
343
342
 
344
- /**
345
- * Constants that are shared between multiple files.
346
- */
347
-
348
- let KeypadType = /*#__PURE__*/function (KeypadType) {
349
- KeypadType["FRACTION"] = "FRACTION";
350
- KeypadType["EXPRESSION"] = "EXPRESSION";
351
- return KeypadType;
352
- }({});
353
- const KeyTypes = ["EMPTY",
354
- // For numerals, variables, and any other characters that themselves
355
- // compose 'values'.
356
- "VALUE",
357
- // For buttons that insert or adjust math in an input.
358
- "OPERATOR",
359
- // For buttons that move the cursor in an input (including via
360
- // deletion).
361
- "INPUT_NAVIGATION",
362
- // For buttons that modify the broader keypad state (e.g., by changing
363
- // the visible pane).
364
- "KEYPAD_NAVIGATION",
365
- // For buttons that house multiple buttons and have no action
366
- // themselves.
367
- "MANY",
368
- // For the echo animation that appears on press.
369
- "ECHO"];
370
- let DeviceOrientation = /*#__PURE__*/function (DeviceOrientation) {
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
- }
343
+ // We only need one MathQuill instance (referred to as MQ in the docs)
344
+ // and that contains some MQ constants and the MathField constructor
345
+ const mathQuillInstance = MathQuill.getInterface(2);
346
+ function createBaseConfig() {
347
+ return {
348
+ // LaTeX commands that, when typed, are immediately replaced by the
349
+ // appropriate symbol. This does not include ln, log, or any of the
350
+ // trig functions; those are always interpreted as commands.
351
+ autoCommands: "pi theta phi sqrt nthroot",
352
+ // Pop the cursor out of super/subscripts on arithmetic operators
353
+ // or (in)equalities.
354
+ charsThatBreakOutOfSupSub: "+-*/=<>≠≤≥",
355
+ // Prevent excessive super/subscripts or fractions from being
356
+ // created without operands, e.g. when somebody holds down a key
357
+ supSubsRequireOperand: true,
358
+ // The name of this option is somewhat misleading, as tabbing in
359
+ // MathQuill breaks you out of a nested context (fraction/script)
360
+ // if you're in one, but moves focus to the next input if you're
361
+ // not. Spaces (with this option enabled) are just ignored in the
362
+ // latter case.
363
+ //
364
+ // TODO(alex): In order to allow inputting mixed numbers, we will
365
+ // have to accept spaces in certain cases. The desired behavior is
366
+ // still to escape nested contexts if currently in one, but to
367
+ // insert a space if not (we don't expect mixed numbers in nested
368
+ // contexts). We should also limit to one consecutive space.
369
+ spaceBehavesLikeTab: true
451
370
  };
452
371
  }
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
372
 
526
- // If the input hasn't changed (for example, if we're
527
- // attempting to add an exponent on an empty input or an empty
528
- // denominator), insert our own "a^b"
529
- if (mathQuill.latex() === contents) {
530
- mathQuill.typedText("a^b");
531
- }
532
- },
533
- // These need to be overwritten by the consumer
534
- // if they're going to be used
535
- FRAC: () => {},
536
- RIGHT: () => {},
537
- LEFT: () => {},
538
- BACKSPACE: () => {},
539
- DISMISS: () => {},
540
- JUMP_OUT_PARENTHESES: () => {},
541
- JUMP_OUT_EXPONENT: () => {},
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
- };
373
+ /**
374
+ * Creates a new [MathField](http://docs.mathquill.com/en/latest/Api_Methods/#mqmathfieldhtml_element-config)
375
+ * instance within the given `container`.
376
+ *
377
+ * An optional configuration callback can be provided to customize
378
+ * the created MathField. A default configuration is passed to this
379
+ * callback which can then be adjusted as needed. The configuration
380
+ * returned from this callback is used to create the MathField.
381
+ * This allows callers to do minimal configuration as only configs
382
+ * that vary from the default need to be provided.
383
+ */
384
+ function createMathField(container, configCallback) {
385
+ const baseConfig = createBaseConfig();
386
+ const config = configCallback ? configCallback(baseConfig) : baseConfig;
387
+ return mathQuillInstance.MathField(container, config);
388
+ }
611
389
 
612
390
  let MathFieldActionType = /*#__PURE__*/function (MathFieldActionType) {
613
391
  MathFieldActionType["WRITE"] = "write";
@@ -678,7 +456,7 @@ function isInsideLogIndex(cursor) {
678
456
  return false;
679
457
  }
680
458
  function isInsideEmptyNode(cursor) {
681
- return cursor[MQ.L] === MathFieldActionType.MQ_END && cursor[MQ.R] === MathFieldActionType.MQ_END;
459
+ return cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END && cursor[mathQuillInstance.R] === MathFieldActionType.MQ_END;
682
460
  }
683
461
  function selectNode(node, cursor) {
684
462
  cursor.insLeftOf(node);
@@ -738,7 +516,7 @@ function maybeFindCommand(initialNode) {
738
516
  } else {
739
517
  break;
740
518
  }
741
- node = node[MQ.L];
519
+ node = node[mathQuillInstance.L];
742
520
  }
743
521
 
744
522
  // If we hit the start of a command, then grab the rest of it by
@@ -746,7 +524,7 @@ function maybeFindCommand(initialNode) {
746
524
  // with its terminal node.
747
525
  if (startNode) {
748
526
  // Next, iterate from the start to the right.
749
- node = initialNode[MQ.R];
527
+ node = initialNode[mathQuillInstance.R];
750
528
  while (node !== 0) {
751
529
  const ctrlSeq = node.ctrlSeq.trim();
752
530
  if (commandCharRegex.test(ctrlSeq)) {
@@ -759,7 +537,7 @@ function maybeFindCommand(initialNode) {
759
537
  endNode = node;
760
538
  break;
761
539
  }
762
- node = node[MQ.R];
540
+ node = node[mathQuillInstance.R];
763
541
  }
764
542
  if (validCommands.includes(name)) {
765
543
  return {
@@ -785,18 +563,18 @@ function maybeFindCommand(initialNode) {
785
563
  * name (`name`) of the command
786
564
  */
787
565
  function maybeFindCommandBeforeParens(leftParenNode) {
788
- return maybeFindCommand(leftParenNode[MQ.L]);
566
+ return maybeFindCommand(leftParenNode[mathQuillInstance.L]);
789
567
  }
790
568
  function contextForCursor(cursor) {
791
569
  // First, try to find any fraction to the right, unimpeded.
792
570
  let visitor = cursor;
793
- while (visitor[MQ.R] !== MathFieldActionType.MQ_END) {
794
- if (isFraction(visitor[MQ.R])) {
571
+ while (visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
572
+ if (isFraction(visitor[mathQuillInstance.R])) {
795
573
  return CursorContext.BEFORE_FRACTION;
796
- } else if (!isLeaf(visitor[MQ.R])) {
574
+ } else if (!isLeaf(visitor[mathQuillInstance.R])) {
797
575
  break;
798
576
  }
799
- visitor = visitor[MQ.R];
577
+ visitor = visitor[mathQuillInstance.R];
800
578
  }
801
579
 
802
580
  // If that didn't work, check if the parent or grandparent is a special
@@ -816,57 +594,8 @@ function contextForCursor(cursor) {
816
594
  }
817
595
  }
818
596
 
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
597
  function handleBackspaceInNthRoot(mathField, cursor) {
869
- const isAtLeftEnd = cursor[MQ.L] === MathFieldActionType.MQ_END;
598
+ const isAtLeftEnd = cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END;
870
599
  const isRootEmpty = isInsideEmptyNode(cursor.parent.parent.blocks[0].ends);
871
600
  if (isAtLeftEnd) {
872
601
  selectNode(cursor.parent.parent, cursor);
@@ -885,7 +614,7 @@ function handleBackspaceInRootIndex(mathField, cursor) {
885
614
 
886
615
  const grandparent = cursor.parent.parent;
887
616
  const latex = grandparent.latex();
888
- const reinsertionPoint = grandparent[MQ.L];
617
+ const reinsertionPoint = grandparent[mathQuillInstance.L];
889
618
  selectNode(grandparent, cursor);
890
619
  const rootIsEmpty = grandparent.blocks[1].jQ.text() === "";
891
620
  if (rootIsEmpty) {
@@ -904,13 +633,13 @@ function handleBackspaceInRootIndex(mathField, cursor) {
904
633
 
905
634
  // Adjust the cursor to be to the left the sqrt.
906
635
  if (reinsertionPoint === MathFieldActionType.MQ_END) {
907
- mathField.moveToDirEnd(MQ.L);
636
+ mathField.moveToDirEnd(mathQuillInstance.L);
908
637
  } else {
909
638
  cursor.insRightOf(reinsertionPoint);
910
639
  }
911
640
  }
912
641
  } else {
913
- if (cursor[MQ.L] !== MathFieldActionType.MQ_END) {
642
+ if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
914
643
  // If the cursor is not at the leftmost position inside the
915
644
  // root's index, delete a character.
916
645
  mathField.keystroke("Backspace");
@@ -923,14 +652,14 @@ function handleBackspaceInLogIndex(mathField, cursor) {
923
652
  const command = maybeFindCommandBeforeParens(grandparent);
924
653
  cursor.insLeftOf(command == null ? void 0 : command.startNode);
925
654
  cursor.startSelection();
926
- if (grandparent[MQ.R] !== MathFieldActionType.MQ_END) {
927
- cursor.insRightOf(grandparent[MQ.R]);
655
+ if (grandparent[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
656
+ cursor.insRightOf(grandparent[mathQuillInstance.R]);
928
657
  } else {
929
658
  cursor.insRightOf(grandparent);
930
659
  }
931
660
  cursor.select();
932
661
  cursor.endSelection();
933
- const isLogBodyEmpty = grandparent[MQ.R].contentjQ.text() === "";
662
+ const isLogBodyEmpty = grandparent[mathQuillInstance.R].contentjQ.text() === "";
934
663
  if (isLogBodyEmpty) {
935
664
  // If there's no content inside the log's parens then delete the
936
665
  // whole thing.
@@ -949,8 +678,8 @@ function handleBackspaceOutsideParens(cursor) {
949
678
  // (x+1)| => |(x+1)|
950
679
  // \log(x+1)| => |\log(x+1)|
951
680
 
952
- const leftNode = cursor[MQ.L];
953
- const rightNode = cursor[MQ.R];
681
+ const leftNode = cursor[mathQuillInstance.L];
682
+ const rightNode = cursor[mathQuillInstance.R];
954
683
  const command = maybeFindCommandBeforeParens(leftNode);
955
684
  if (command && command.startNode) {
956
685
  // There's a command before the parens so we select it as well as
@@ -996,7 +725,7 @@ function handleBackspaceInsideParens(mathField, cursor) {
996
725
  // - \log(|x+1) => |\log(x+1)|
997
726
  // - \log(|) => |
998
727
 
999
- if (cursor[MQ.L] !== MathFieldActionType.MQ_END) {
728
+ if (cursor[mathQuillInstance.L] !== MathFieldActionType.MQ_END) {
1000
729
  // This command contains math and there's some math to
1001
730
  // the left of the cursor that we should delete normally
1002
731
  // before doing anything special.
@@ -1009,12 +738,12 @@ function handleBackspaceInsideParens(mathField, cursor) {
1009
738
  // has a subscript as is the case in log_n then move the cursor into
1010
739
  // the subscript, e.g. \log_{5}(|x+1) => \log_{5|}(x+1)
1011
740
 
1012
- if (grandparent[MQ.L].sub) {
741
+ if (grandparent[mathQuillInstance.L].sub) {
1013
742
  // if there is a subscript
1014
- if (grandparent[MQ.L].sub.jQ.text()) {
743
+ if (grandparent[mathQuillInstance.L].sub.jQ.text()) {
1015
744
  // and it contains text
1016
745
  // move the cursor to the right end of the subscript
1017
- cursor.insAtRightEnd(grandparent[MQ.L].sub);
746
+ cursor.insAtRightEnd(grandparent[mathQuillInstance.L].sub);
1018
747
  return;
1019
748
  }
1020
749
  }
@@ -1052,7 +781,7 @@ function handleBackspace(mathField) {
1052
781
  if (!cursor.selection) {
1053
782
  const parent = cursor.parent;
1054
783
  const grandparent = parent.parent;
1055
- const leftNode = cursor[MQ.L];
784
+ const leftNode = cursor[mathQuillInstance.L];
1056
785
  if (isFraction(leftNode)) {
1057
786
  selectNode(leftNode, cursor);
1058
787
  } else if (isSquareRoot(leftNode)) {
@@ -1079,6 +808,133 @@ function handleBackspace(mathField) {
1079
808
  }
1080
809
  }
1081
810
 
811
+ /**
812
+ * Constants that are shared between multiple files.
813
+ */
814
+
815
+ let KeypadType = /*#__PURE__*/function (KeypadType) {
816
+ KeypadType["FRACTION"] = "FRACTION";
817
+ KeypadType["EXPRESSION"] = "EXPRESSION";
818
+ return KeypadType;
819
+ }({});
820
+ const KeyTypes = ["EMPTY",
821
+ // For numerals, variables, and any other characters that themselves
822
+ // compose 'values'.
823
+ "VALUE",
824
+ // For buttons that insert or adjust math in an input.
825
+ "OPERATOR",
826
+ // For buttons that move the cursor in an input (including via
827
+ // deletion).
828
+ "INPUT_NAVIGATION",
829
+ // For buttons that modify the broader keypad state (e.g., by changing
830
+ // the visible pane).
831
+ "KEYPAD_NAVIGATION",
832
+ // For buttons that house multiple buttons and have no action
833
+ // themselves.
834
+ "MANY",
835
+ // For the echo animation that appears on press.
836
+ "ECHO"];
837
+ let DeviceOrientation = /*#__PURE__*/function (DeviceOrientation) {
838
+ DeviceOrientation["LANDSCAPE"] = "LANDSCAPE";
839
+ DeviceOrientation["PORTRAIT"] = "PORTRAIT";
840
+ return DeviceOrientation;
841
+ }({});
842
+ let DeviceType = /*#__PURE__*/function (DeviceType) {
843
+ DeviceType["PHONE"] = "PHONE";
844
+ DeviceType["TABLET"] = "TABLET";
845
+ return DeviceType;
846
+ }({});
847
+ let LayoutMode = /*#__PURE__*/function (LayoutMode) {
848
+ LayoutMode["FULLSCREEN"] = "FULLSCREEN";
849
+ LayoutMode["COMPACT"] = "COMPACT";
850
+ return LayoutMode;
851
+ }({});
852
+ let BorderDirection = /*#__PURE__*/function (BorderDirection) {
853
+ BorderDirection["LEFT"] = "LEFT";
854
+ BorderDirection["BOTTOM"] = "BOTTOM";
855
+ return BorderDirection;
856
+ }({});
857
+ const BorderStyles = {
858
+ LEFT: [BorderDirection.LEFT],
859
+ BOTTOM: [BorderDirection.BOTTOM],
860
+ ALL: [BorderDirection.LEFT, BorderDirection.BOTTOM],
861
+ NONE: []
862
+ };
863
+ let IconType = /*#__PURE__*/function (IconType) {
864
+ IconType["MATH"] = "MATH";
865
+ IconType["SVG"] = "SVG";
866
+ IconType["TEXT"] = "TEXT";
867
+ return IconType;
868
+ }({});
869
+ let DecimalSeparator = /*#__PURE__*/function (DecimalSeparator) {
870
+ DecimalSeparator["COMMA"] = "COMMA";
871
+ DecimalSeparator["PERIOD"] = "PERIOD";
872
+ return DecimalSeparator;
873
+ }({});
874
+ let EchoAnimationType = /*#__PURE__*/function (EchoAnimationType) {
875
+ EchoAnimationType["SLIDE_AND_FADE"] = "SLIDE_AND_FADE";
876
+ EchoAnimationType["FADE_ONLY"] = "FADE_ONLY";
877
+ EchoAnimationType["LONG_FADE_ONLY"] = "LONG_FADE_ONLY";
878
+ return EchoAnimationType;
879
+ }({});
880
+
881
+ // NOTES(kevinb):
882
+ // - In order to get the correct decimal separator for the current locale,
883
+ // the locale must bet set using `setLocale(kaLocale)` which can be
884
+ // imported from wonder-blocks-i18n.
885
+ // - Some languages/locales use different decimal separators than the ones
886
+ // listed here. Much of the Arab world uses U+066C.
887
+ const decimalSeparator = getDecimalSeparator() === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
888
+
889
+ function handleLeftArrow(mathField, cursor) {
890
+ // If we're inside a function, and just after the left parentheses, we
891
+ // need to skip the entire function name, rather than move the cursor
892
+ // inside of it. For example, when hitting left from within the
893
+ // parentheses in `cos()`, we want to place the cursor to the left of
894
+ // the entire expression, rather than between the `s` and the left
895
+ // parenthesis.
896
+ // From the cursor's perspective, this requires that our left node is
897
+ // the ActionType.MQ_END node, that our grandparent is the left parenthesis, and
898
+ // the nodes to the left of our grandparent comprise a valid function
899
+ // name.
900
+ if (cursor[mathQuillInstance.L] === MathFieldActionType.MQ_END) {
901
+ const parent = cursor.parent;
902
+ const grandparent = parent.parent;
903
+ if (grandparent.ctrlSeq === "\\left(") {
904
+ const command = maybeFindCommandBeforeParens(grandparent);
905
+ if (command) {
906
+ cursor.insLeftOf(command.startNode);
907
+ return;
908
+ }
909
+ }
910
+ }
911
+
912
+ // Otherwise, we default to the standard MathQull left behavior.
913
+ mathField.keystroke("Left");
914
+ }
915
+ function handleRightArrow(mathField, cursor) {
916
+ const command = maybeFindCommand(cursor[mathQuillInstance.R]);
917
+ if (command) {
918
+ // Similarly, if a function is to our right, then we need to place
919
+ // the cursor at the start of its parenthetical content, which is
920
+ // done by putting it to the left of ites parentheses and then
921
+ // moving right once.
922
+ cursor.insLeftOf(command.endNode);
923
+ mathField.keystroke("Right");
924
+ } else {
925
+ // Otherwise, we default to the standard MathQull right behavior.
926
+ mathField.keystroke("Right");
927
+ }
928
+ }
929
+ function handleArrow(mathField, key) {
930
+ const cursor = getCursor(mathField);
931
+ if (key === "LEFT") {
932
+ handleLeftArrow(mathField, cursor);
933
+ } else if (key === "RIGHT") {
934
+ handleRightArrow(mathField, cursor);
935
+ }
936
+ }
937
+
1082
938
  const ArithmeticOperators = ["+", "-", "\\cdot", "\\times", "\\div"];
1083
939
  const EqualityOperators = ["=", "\\neq", "<", "\\leq", ">", "\\geq"];
1084
940
  function handleExponent(mathField, key) {
@@ -1087,7 +943,7 @@ function handleExponent(mathField, key) {
1087
943
  // knowingly cannot be raised to a power), add an empty set of
1088
944
  // parentheses and apply the exponent to that.
1089
945
  const invalidPrefixes = [...ArithmeticOperators, ...EqualityOperators];
1090
- const precedingNode = cursor[MQ.L];
946
+ const precedingNode = cursor[mathQuillInstance.L];
1091
947
  const shouldPrefixWithParens = precedingNode === MathFieldActionType.MQ_END || invalidPrefixes.includes(precedingNode.ctrlSeq.trim());
1092
948
  if (shouldPrefixWithParens) {
1093
949
  mathField.write("\\left(\\right)");
@@ -1153,11 +1009,11 @@ function handleJumpOut(mathField, key) {
1153
1009
  // Find the nearest fraction to the right of the cursor.
1154
1010
  let fractionNode;
1155
1011
  let visitor = cursor;
1156
- while (visitor[MQ.R] !== MathFieldActionType.MQ_END) {
1157
- if (isFraction(visitor[MQ.R])) {
1158
- fractionNode = visitor[MQ.R];
1012
+ while (visitor[mathQuillInstance.R] !== MathFieldActionType.MQ_END) {
1013
+ if (isFraction(visitor[mathQuillInstance.R])) {
1014
+ fractionNode = visitor[mathQuillInstance.R];
1159
1015
  }
1160
- visitor = visitor[MQ.R];
1016
+ visitor = visitor[mathQuillInstance.R];
1161
1017
  }
1162
1018
 
1163
1019
  // Jump into it!
@@ -1186,7 +1042,7 @@ function handleJumpOut(mathField, key) {
1186
1042
  // Navigate right once more, if we're right before parens. This
1187
1043
  // is to handle the standard case in which the subscript is the
1188
1044
  // base of a custom log.
1189
- if (isParens(cursor[MQ.R])) {
1045
+ if (isParens(cursor[mathQuillInstance.R])) {
1190
1046
  mathField.keystroke("Right");
1191
1047
  }
1192
1048
  break;
@@ -1198,26 +1054,46 @@ function handleJumpOut(mathField, key) {
1198
1054
  throw new Error(`Attempted to 'Jump Out' from node, but found no ` + `appropriate cursor context: ${context}`);
1199
1055
  }
1200
1056
  }
1201
-
1057
+
1058
+ var ActionType = /*#__PURE__*/function (ActionType) {
1059
+ ActionType["WRITE"] = "write";
1060
+ ActionType["CMD"] = "cmd";
1061
+ ActionType["KEYSTROKE"] = "keystroke";
1062
+ ActionType[ActionType["MQ_END"] = 0] = "MQ_END";
1063
+ return ActionType;
1064
+ }(ActionType || {});
1065
+ const decimalSymbol = decimalSeparator === DecimalSeparator.COMMA ? "," : ".";
1066
+ function buildGenericCallback(str, type = ActionType.WRITE) {
1067
+ return function (mathQuill) {
1068
+ switch (type) {
1069
+ case ActionType.WRITE:
1070
+ {
1071
+ mathQuill.write(str);
1072
+ return;
1073
+ }
1074
+ case ActionType.CMD:
1075
+ {
1076
+ mathQuill.cmd(str);
1077
+ return;
1078
+ }
1079
+ case ActionType.KEYSTROKE:
1080
+ {
1081
+ mathQuill.keystroke(str);
1082
+ return;
1083
+ }
1084
+ }
1085
+ };
1086
+ }
1202
1087
  function buildNormalFunctionCallback(command) {
1203
1088
  return function (mathField) {
1204
1089
  mathField.write(`\\${command}\\left(\\right)`);
1205
1090
  mathField.keystroke("Left");
1206
1091
  };
1207
1092
  }
1208
- const customKeyTranslator = _extends({}, keyToMathquillMap, {
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,
1093
+ const keyToMathquillMap = {
1215
1094
  EXP: handleExponent,
1216
1095
  EXP_2: handleExponent,
1217
1096
  EXP_3: handleExponent,
1218
- FRAC: mathQuill => {
1219
- mathQuill.cmd("\\frac");
1220
- },
1221
1097
  JUMP_OUT_PARENTHESES: handleJumpOut,
1222
1098
  JUMP_OUT_EXPONENT: handleJumpOut,
1223
1099
  JUMP_OUT_BASE: handleJumpOut,
@@ -1230,7 +1106,157 @@ const customKeyTranslator = _extends({}, keyToMathquillMap, {
1230
1106
  LN: buildNormalFunctionCallback("ln"),
1231
1107
  SIN: buildNormalFunctionCallback("sin"),
1232
1108
  COS: buildNormalFunctionCallback("cos"),
1233
- TAN: buildNormalFunctionCallback("tan")
1109
+ TAN: buildNormalFunctionCallback("tan"),
1110
+ CDOT: buildGenericCallback("\\cdot"),
1111
+ DECIMAL: buildGenericCallback(decimalSymbol),
1112
+ DIVIDE: buildGenericCallback("\\div"),
1113
+ EQUAL: buildGenericCallback("="),
1114
+ GEQ: buildGenericCallback("\\geq"),
1115
+ GT: buildGenericCallback(">"),
1116
+ LEQ: buildGenericCallback("\\leq"),
1117
+ LT: buildGenericCallback("<"),
1118
+ MINUS: buildGenericCallback("-"),
1119
+ NEGATIVE: buildGenericCallback("-"),
1120
+ NEQ: buildGenericCallback("\\neq"),
1121
+ PERCENT: buildGenericCallback("%"),
1122
+ PERIOD: buildGenericCallback("."),
1123
+ PLUS: buildGenericCallback("+"),
1124
+ TIMES: buildGenericCallback("\\times"),
1125
+ // The `FRAC_EXCLUSIVE` variant is handled manually, since we may need to do
1126
+ // some additional navigation depending on the cursor position.
1127
+ FRAC_INCLUSIVE: buildGenericCallback("/", ActionType.CMD),
1128
+ FRAC: buildGenericCallback("\\frac", ActionType.CMD),
1129
+ LEFT_PAREN: buildGenericCallback("(", ActionType.CMD),
1130
+ RIGHT_PAREN: buildGenericCallback(")", ActionType.CMD),
1131
+ SQRT: buildGenericCallback("sqrt", ActionType.CMD),
1132
+ PHI: buildGenericCallback("\\phi", ActionType.CMD),
1133
+ PI: buildGenericCallback("pi", ActionType.CMD),
1134
+ THETA: buildGenericCallback("theta", ActionType.CMD),
1135
+ RADICAL: buildGenericCallback("nthroot", ActionType.CMD),
1136
+ BACKSPACE: buildGenericCallback("Backspace", ActionType.KEYSTROKE),
1137
+ UP: buildGenericCallback("Up", ActionType.KEYSTROKE),
1138
+ DOWN: buildGenericCallback("Down", ActionType.KEYSTROKE),
1139
+ CUBE_ROOT: mathQuill => {
1140
+ mathQuill.write("\\sqrt[3]{}");
1141
+ mathQuill.keystroke("Left"); // under the root
1142
+ },
1143
+
1144
+ FRAC_EXCLUSIVE: mathQuill => {
1145
+ const cursor = mathQuill.__controller.cursor;
1146
+ // If there's nothing to the left of the cursor, then we want to
1147
+ // leave the cursor to the left of the fraction after creating it.
1148
+ const shouldNavigateLeft = cursor[mathQuillInstance.L] === ActionType.MQ_END;
1149
+ mathQuill.cmd("\\frac");
1150
+ if (shouldNavigateLeft) {
1151
+ mathQuill.keystroke("Left");
1152
+ }
1153
+ },
1154
+ LOG_B: mathQuill => {
1155
+ mathQuill.typedText("log_");
1156
+ mathQuill.keystroke("Right");
1157
+ mathQuill.typedText("(");
1158
+ mathQuill.keystroke("Left");
1159
+ mathQuill.keystroke("Left");
1160
+ },
1161
+ LOG_N: mathQuill => {
1162
+ mathQuill.write("log_{ }\\left(\\right)");
1163
+ mathQuill.keystroke("Left"); // into parentheses
1164
+ mathQuill.keystroke("Left"); // out of parentheses
1165
+ mathQuill.keystroke("Left"); // into index
1166
+ },
1167
+
1168
+ NTHROOT3: mathQuill => {
1169
+ mathQuill.typedText("nthroot3");
1170
+ mathQuill.keystroke("Right");
1171
+ },
1172
+ POW: mathQuill => {
1173
+ const contents = mathQuill.latex();
1174
+ mathQuill.typedText("^");
1175
+
1176
+ // If the input hasn't changed (for example, if we're
1177
+ // attempting to add an exponent on an empty input or an empty
1178
+ // denominator), insert our own "a^b"
1179
+ if (mathQuill.latex() === contents) {
1180
+ mathQuill.typedText("a^b");
1181
+ }
1182
+ },
1183
+ // These need to be overwritten by the consumer
1184
+ // if they're going to be used
1185
+ DISMISS: () => {},
1186
+ NOOP: () => {},
1187
+ MANY: () => {},
1188
+ NUM_0: buildGenericCallback("0"),
1189
+ NUM_1: buildGenericCallback("1"),
1190
+ NUM_2: buildGenericCallback("2"),
1191
+ NUM_3: buildGenericCallback("3"),
1192
+ NUM_4: buildGenericCallback("4"),
1193
+ NUM_5: buildGenericCallback("5"),
1194
+ NUM_6: buildGenericCallback("6"),
1195
+ NUM_7: buildGenericCallback("7"),
1196
+ NUM_8: buildGenericCallback("8"),
1197
+ NUM_9: buildGenericCallback("9"),
1198
+ a: buildGenericCallback("a"),
1199
+ b: buildGenericCallback("b"),
1200
+ c: buildGenericCallback("c"),
1201
+ d: buildGenericCallback("d"),
1202
+ e: buildGenericCallback("e"),
1203
+ f: buildGenericCallback("f"),
1204
+ g: buildGenericCallback("g"),
1205
+ h: buildGenericCallback("h"),
1206
+ i: buildGenericCallback("i"),
1207
+ j: buildGenericCallback("j"),
1208
+ k: buildGenericCallback("k"),
1209
+ l: buildGenericCallback("l"),
1210
+ m: buildGenericCallback("m"),
1211
+ n: buildGenericCallback("n"),
1212
+ o: buildGenericCallback("o"),
1213
+ p: buildGenericCallback("p"),
1214
+ q: buildGenericCallback("q"),
1215
+ r: buildGenericCallback("r"),
1216
+ s: buildGenericCallback("s"),
1217
+ t: buildGenericCallback("t"),
1218
+ u: buildGenericCallback("u"),
1219
+ v: buildGenericCallback("v"),
1220
+ w: buildGenericCallback("w"),
1221
+ x: buildGenericCallback("x"),
1222
+ y: buildGenericCallback("y"),
1223
+ z: buildGenericCallback("z"),
1224
+ A: buildGenericCallback("A"),
1225
+ B: buildGenericCallback("B"),
1226
+ C: buildGenericCallback("C"),
1227
+ D: buildGenericCallback("D"),
1228
+ E: buildGenericCallback("E"),
1229
+ F: buildGenericCallback("F"),
1230
+ G: buildGenericCallback("G"),
1231
+ H: buildGenericCallback("H"),
1232
+ I: buildGenericCallback("I"),
1233
+ J: buildGenericCallback("J"),
1234
+ K: buildGenericCallback("K"),
1235
+ L: buildGenericCallback("L"),
1236
+ M: buildGenericCallback("M"),
1237
+ N: buildGenericCallback("N"),
1238
+ O: buildGenericCallback("O"),
1239
+ P: buildGenericCallback("P"),
1240
+ Q: buildGenericCallback("Q"),
1241
+ R: buildGenericCallback("R"),
1242
+ S: buildGenericCallback("S"),
1243
+ T: buildGenericCallback("T"),
1244
+ U: buildGenericCallback("U"),
1245
+ V: buildGenericCallback("V"),
1246
+ W: buildGenericCallback("W"),
1247
+ X: buildGenericCallback("X"),
1248
+ Y: buildGenericCallback("Y"),
1249
+ Z: buildGenericCallback("Z")
1250
+ };
1251
+
1252
+ const mobileKeyTranslator = _extends({}, keyToMathquillMap, {
1253
+ // note(Matthew): our mobile backspace logic is really complicated
1254
+ // and for some reason doesn't really work in the desktop experience.
1255
+ // So we default to the basic backspace functionality in the
1256
+ // key translator and overwrite it with the complicated logic here
1257
+ // until we can unify the experiences (if we even want to).
1258
+ // https://khanacademy.atlassian.net/browse/LC-906
1259
+ BACKSPACE: handleBackspace
1234
1260
  });
1235
1261
 
1236
1262
  /**
@@ -1239,17 +1265,19 @@ const customKeyTranslator = _extends({}, keyToMathquillMap, {
1239
1265
  * from MathQuill changes.
1240
1266
  */
1241
1267
  class MathWrapper {
1242
- // MathQuill input
1268
+ // MathQuill MathField input
1243
1269
 
1244
- constructor(element, options = {}, callbacks = {}) {
1270
+ constructor(element, callbacks = {}) {
1245
1271
  this.mathField = void 0;
1246
1272
  this.callbacks = void 0;
1247
- this.mathField = MQ.MathField(element, {
1248
- // use a span instead of a textarea so that we don't bring up the
1249
- // native keyboard on mobile when selecting the input
1250
- substituteTextarea: function () {
1251
- return document.createElement("span");
1252
- }
1273
+ this.mathField = createMathField(element, () => {
1274
+ return {
1275
+ // use a span instead of a textarea so that we don't bring up the
1276
+ // native keyboard on mobile when selecting the input
1277
+ substituteTextarea: function () {
1278
+ return document.createElement("span");
1279
+ }
1280
+ };
1253
1281
  });
1254
1282
  this.callbacks = callbacks;
1255
1283
  }
@@ -1279,7 +1307,7 @@ class MathWrapper {
1279
1307
  */
1280
1308
  pressKey(key) {
1281
1309
  const cursor = this.getCursor();
1282
- const translator = customKeyTranslator[key];
1310
+ const translator = mobileKeyTranslator[key];
1283
1311
  if (translator) {
1284
1312
  translator(this.mathField, key);
1285
1313
  }
@@ -1327,7 +1355,7 @@ class MathWrapper {
1327
1355
  // Unless that would leave us mid-command, in which case, we
1328
1356
  // need to adjust and place the cursor inside the parens
1329
1357
  // following the command.
1330
- const command = maybeFindCommand(cursor[MQ.L]);
1358
+ const command = maybeFindCommand(cursor[mathQuillInstance.L]);
1331
1359
  if (command && command.endNode) {
1332
1360
  // NOTE(charlie): endNode should definitely be \left(.
1333
1361
  cursor.insLeftOf(command.endNode);
@@ -1898,7 +1926,7 @@ class MathInput extends React.Component {
1898
1926
  }
1899
1927
  componentDidMount() {
1900
1928
  this._isMounted = true;
1901
- this.mathField = new MathWrapper(this._mathContainer, {}, {
1929
+ this.mathField = new MathWrapper(this._mathContainer, {
1902
1930
  onCursorMove: cursor => {
1903
1931
  // TODO(charlie): It's not great that there is so much coupling
1904
1932
  // between this keypad and the input behavior. We should wrap
@@ -7244,140 +7272,58 @@ class ProvidedKeypad extends React.Component {
7244
7272
  super(props);
7245
7273
  this.store = void 0;
7246
7274
  this.activate = () => {
7247
- this.store.dispatch(activateKeypad());
7248
- };
7249
- this.dismiss = () => {
7250
- this.store.dispatch(dismissKeypad());
7251
- };
7252
- this.configure = (configuration, cb) => {
7253
- this.store.dispatch(configureKeypad(configuration));
7254
-
7255
- // HACK(charlie): In Perseus, triggering a focus causes the keypad to
7256
- // animate into view and re-configure. We'd like to provide the option
7257
- // to re-render the re-configured keypad before animating it into view,
7258
- // to avoid jank in the animation. As such, we support passing a
7259
- // callback into `configureKeypad`. However, implementing this properly
7260
- // would require middleware, etc., so we just hack it on with
7261
- // `setTimeout` for now.
7262
- setTimeout(() => cb && cb());
7263
- };
7264
- this.setCursor = cursor => {
7265
- this.store.dispatch(setCursor(cursor));
7266
- };
7267
- this.setKeyHandler = keyHandler => {
7268
- this.store.dispatch(setKeyHandler(keyHandler));
7269
- };
7270
- this.getDOMNode = () => {
7271
- return ReactDOM.findDOMNode(this);
7272
- };
7273
- this.store = createStore();
7274
- }
7275
- render() {
7276
- const {
7277
- onElementMounted,
7278
- onDismiss,
7279
- style
7280
- } = this.props;
7281
- return /*#__PURE__*/React.createElement(Provider, {
7282
- store: this.store
7283
- }, /*#__PURE__*/React.createElement(KeypadContainer$1, {
7284
- onElementMounted: element => {
7285
- // Append the dispatch methods that we want to expose
7286
- // externally to the returned React element.
7287
- const elementWithDispatchMethods = _extends({}, element, {
7288
- activate: this.activate,
7289
- dismiss: this.dismiss,
7290
- configure: this.configure,
7291
- setCursor: this.setCursor,
7292
- setKeyHandler: this.setKeyHandler,
7293
- getDOMNode: this.getDOMNode
7294
- });
7295
- onElementMounted && onElementMounted(elementWithDispatchMethods);
7296
- },
7297
- onDismiss: onDismiss,
7298
- style: style
7299
- }));
7300
- }
7301
- }
7302
-
7303
- const styles$1 = StyleSheet.create({
7304
- base: {
7305
- display: "flex",
7306
- justifyContent: "center",
7307
- alignItems: "center",
7308
- boxShadow: "0px 1px 0px rgba(33, 36, 44, 0.32)",
7309
- boxSizing: "border-box",
7310
- background: Color.white,
7311
- borderRadius: 4,
7312
- border: `1px solid transparent`,
7313
- flex: 1,
7314
- minHeight: 42,
7315
- minWidth: 42,
7316
- padding: 1
7317
- },
7318
- hovered: {
7319
- border: `1px solid ${Color.blue}`,
7320
- padding: 1,
7321
- boxShadow: "none"
7322
- },
7323
- focused: {
7324
- border: `2px solid ${Color.blue}`,
7325
- padding: 0,
7326
- boxShadow: "none"
7327
- },
7328
- pressed: {
7329
- border: "2px solid #1B50B3",
7330
- padding: 0,
7331
- background: `linear-gradient(0deg, rgba(24, 101, 242, 0.32), rgba(24, 101, 242, 0.32)), ${Color.white}`,
7332
- boxShadow: "none"
7333
- },
7334
- outerBoxBase: {
7335
- padding: 1,
7336
- height: "100%",
7337
- width: "100%",
7338
- boxSizing: "border-box",
7339
- borderRadius: 7,
7340
- border: "2px solid transparent"
7341
- },
7342
- outerBoxHover: {
7343
- border: `2px solid ${Color.blue}`
7344
- },
7345
- outerBoxPressed: {
7346
- border: "2px solid #1B50B3"
7347
- },
7348
- clickable: {
7349
- width: "100%",
7350
- height: "100%",
7351
- boxSizing: "border-box"
7275
+ this.store.dispatch(activateKeypad());
7276
+ };
7277
+ this.dismiss = () => {
7278
+ this.store.dispatch(dismissKeypad());
7279
+ };
7280
+ this.configure = (configuration, cb) => {
7281
+ this.store.dispatch(configureKeypad(configuration));
7282
+
7283
+ // HACK(charlie): In Perseus, triggering a focus causes the keypad to
7284
+ // animate into view and re-configure. We'd like to provide the option
7285
+ // to re-render the re-configured keypad before animating it into view,
7286
+ // to avoid jank in the animation. As such, we support passing a
7287
+ // callback into `configureKeypad`. However, implementing this properly
7288
+ // would require middleware, etc., so we just hack it on with
7289
+ // `setTimeout` for now.
7290
+ setTimeout(() => cb && cb());
7291
+ };
7292
+ this.setCursor = cursor => {
7293
+ this.store.dispatch(setCursor(cursor));
7294
+ };
7295
+ this.setKeyHandler = keyHandler => {
7296
+ this.store.dispatch(setKeyHandler(keyHandler));
7297
+ };
7298
+ this.getDOMNode = () => {
7299
+ return ReactDOM.findDOMNode(this);
7300
+ };
7301
+ this.store = createStore();
7352
7302
  }
7353
- });
7354
- class Button extends React.Component {
7355
7303
  render() {
7356
7304
  const {
7357
- onPress,
7358
- ariaLabel,
7359
- children,
7360
- style,
7361
- tintColor
7305
+ onElementMounted,
7306
+ onDismiss,
7307
+ style
7362
7308
  } = this.props;
7363
- return /*#__PURE__*/React.createElement(View$1, {
7309
+ return /*#__PURE__*/React.createElement(Provider, {
7310
+ store: this.store
7311
+ }, /*#__PURE__*/React.createElement(KeypadContainer$1, {
7312
+ onElementMounted: element => {
7313
+ // Append the dispatch methods that we want to expose
7314
+ // externally to the returned React element.
7315
+ const elementWithDispatchMethods = _extends({}, element, {
7316
+ activate: this.activate,
7317
+ dismiss: this.dismiss,
7318
+ configure: this.configure,
7319
+ setCursor: this.setCursor,
7320
+ setKeyHandler: this.setKeyHandler,
7321
+ getDOMNode: this.getDOMNode
7322
+ });
7323
+ onElementMounted && onElementMounted(elementWithDispatchMethods);
7324
+ },
7325
+ onDismiss: onDismiss,
7364
7326
  style: style
7365
- }, /*#__PURE__*/React.createElement(Clickable, {
7366
- onClick: onPress,
7367
- style: styles$1.clickable,
7368
- "aria-label": ariaLabel
7369
- }, ({
7370
- hovered,
7371
- focused,
7372
- pressed
7373
- }) => {
7374
- return /*#__PURE__*/React.createElement(View$1, {
7375
- style: [styles$1.outerBoxBase, hovered && styles$1.outerBoxHover, pressed && styles$1.outerBoxPressed]
7376
- }, /*#__PURE__*/React.createElement(View$1, {
7377
- style: [styles$1.base, tintColor != null ? {
7378
- background: tintColor
7379
- } : undefined, hovered && styles$1.hovered, focused && styles$1.focused, pressed && styles$1.pressed]
7380
- }, children));
7381
7327
  }));
7382
7328
  }
7383
7329
  }
@@ -8140,386 +8086,300 @@ function ButtonAsset({
8140
8086
  }
8141
8087
  }
8142
8088
 
8143
- const KeypadPageContainer = ({
8144
- children
8145
- }) => /*#__PURE__*/React.createElement(View$1, {
8146
- style: {
8147
- backgroundColor: "#DBDCDD",
8148
- width: "100%",
8149
- height: 192,
8150
- display: "grid",
8151
- gridTemplateColumns: "repeat(6, 1fr)",
8152
- gridTemplateRows: "repeat(4, 1fr)"
8153
- }
8154
- }, children);
8155
8089
  const KeypadButton = ({
8090
+ coord,
8156
8091
  keyConfig,
8157
8092
  onClickKey,
8158
- tintColor,
8159
- style
8160
- }) => /*#__PURE__*/React.createElement(Button, {
8161
- onPress: () => onClickKey(keyConfig.id),
8162
- tintColor: tintColor,
8163
- style: style,
8164
- ariaLabel: keyConfig.id
8165
- }, /*#__PURE__*/React.createElement(ButtonAsset, {
8166
- id: keyConfig.id
8167
- }));
8168
- const SecondaryKeypadButton = ({
8169
- keyConfig,
8170
- onClickKey,
8171
- style
8172
- }) => /*#__PURE__*/React.createElement(KeypadButton, {
8173
- keyConfig: keyConfig,
8174
- onClickKey: onClickKey,
8175
- style: style,
8176
- tintColor: "#F6F6F7"
8177
- });
8178
- const KeypadActionButton = ({
8179
- keyConfig,
8180
- onClickKey,
8181
- style
8182
- }) => /*#__PURE__*/React.createElement(KeypadButton, {
8183
- keyConfig: keyConfig,
8184
- onClickKey: onClickKey,
8185
- style: style,
8186
- tintColor: "#DBDCDD"
8187
- });
8188
-
8189
- /**
8190
- * A placeholder button for the keypad. Optional count prop to render multiple
8191
- * buttons. Defaults to 1.
8192
- */
8193
- const PlaceHolderButtons = ({
8194
- count: _count = 1
8195
- }) => /*#__PURE__*/React.createElement(React.Fragment, null, Array.from({
8196
- length: _count
8197
- }).map((_, index) => /*#__PURE__*/React.createElement(View$1, {
8198
- key: index,
8199
- style: {
8093
+ style,
8094
+ secondary,
8095
+ action
8096
+ }) => {
8097
+ const tintColor = secondary ? "#F6F6F7" : action ? "#DBDCDD" : undefined;
8098
+ return /*#__PURE__*/React.createElement(View$1, {
8099
+ style: _extends({
8100
+ gridColumn: coord[0] + 1,
8101
+ gridRow: coord[1] + 1
8102
+ }, style)
8103
+ }, /*#__PURE__*/React.createElement(Clickable, {
8104
+ onClick: () => onClickKey(keyConfig.id),
8105
+ style: styles$1.clickable,
8106
+ "aria-label": keyConfig.ariaLabel
8107
+ }, ({
8108
+ hovered,
8109
+ focused,
8110
+ pressed
8111
+ }) => {
8112
+ return /*#__PURE__*/React.createElement(View$1, {
8113
+ style: [styles$1.outerBoxBase, hovered && styles$1.outerBoxHover, pressed && styles$1.outerBoxPressed]
8114
+ }, /*#__PURE__*/React.createElement(View$1, {
8115
+ style: [styles$1.base, tintColor != null ? {
8116
+ background: tintColor
8117
+ } : undefined, hovered && styles$1.hovered, focused && styles$1.focused, pressed && styles$1.pressed]
8118
+ }, /*#__PURE__*/React.createElement(ButtonAsset, {
8119
+ id: keyConfig.id
8120
+ })));
8121
+ }));
8122
+ };
8123
+ const styles$1 = StyleSheet.create({
8124
+ base: {
8125
+ display: "flex",
8126
+ justifyContent: "center",
8127
+ alignItems: "center",
8128
+ boxShadow: "0px 1px 0px rgba(33, 36, 44, 0.32)",
8129
+ boxSizing: "border-box",
8130
+ background: Color.white,
8131
+ borderRadius: 4,
8132
+ border: `1px solid transparent`,
8133
+ flex: 1,
8134
+ minHeight: 42,
8135
+ minWidth: 42,
8136
+ padding: 1
8137
+ },
8138
+ hovered: {
8139
+ border: `1px solid ${Color.blue}`,
8140
+ padding: 1,
8141
+ boxShadow: "none"
8142
+ },
8143
+ focused: {
8144
+ border: `2px solid ${Color.blue}`,
8145
+ padding: 0,
8146
+ boxShadow: "none"
8147
+ },
8148
+ pressed: {
8149
+ border: "2px solid #1B50B3",
8150
+ padding: 0,
8151
+ background: `linear-gradient(0deg, rgba(24, 101, 242, 0.32), rgba(24, 101, 242, 0.32)), ${Color.white}`,
8152
+ boxShadow: "none"
8153
+ },
8154
+ outerBoxBase: {
8155
+ padding: 1,
8200
8156
  height: "100%",
8201
8157
  width: "100%",
8202
8158
  boxSizing: "border-box",
8203
8159
  borderRadius: 7,
8204
- border: "4px solid transparent"
8205
- }
8206
- }, /*#__PURE__*/React.createElement(View$1, {
8207
- style: {
8208
- background: "rgba(33, 36, 44, 0.04)",
8160
+ border: "2px solid transparent"
8161
+ },
8162
+ outerBoxHover: {
8163
+ border: `2px solid ${Color.blue}`
8164
+ },
8165
+ outerBoxPressed: {
8166
+ border: "2px solid #1B50B3"
8167
+ },
8168
+ clickable: {
8209
8169
  width: "100%",
8210
8170
  height: "100%",
8211
- borderRadius: 4,
8212
- border: `1px solid transparent`
8171
+ boxSizing: "border-box"
8213
8172
  }
8214
- }))));
8173
+ });
8215
8174
 
8216
- class ExtrasPage extends React.Component {
8217
- render() {
8218
- const {
8219
- extraKeys,
8220
- onClickKey
8221
- } = this.props;
8222
- return /*#__PURE__*/React.createElement(KeypadPageContainer, null, extraKeys.map(key => /*#__PURE__*/React.createElement(KeypadButton, {
8175
+ const columns = 4;
8176
+ function ExtrasPage(props) {
8177
+ const {
8178
+ extraKeys,
8179
+ onClickKey
8180
+ } = props;
8181
+ return /*#__PURE__*/React.createElement(React.Fragment, null, extraKeys.map((key, i) => {
8182
+ // Map 1D array to Cartesian coordinates
8183
+ const coordX = i % columns;
8184
+ const coordY = i / columns;
8185
+ return /*#__PURE__*/React.createElement(KeypadButton, {
8223
8186
  key: key,
8224
8187
  keyConfig: KeyConfigs[key],
8225
- onClickKey: onClickKey
8226
- })));
8227
- }
8188
+ onClickKey: onClickKey,
8189
+ coord: [coordX, coordY]
8190
+ });
8191
+ }));
8228
8192
  }
8229
8193
 
8230
- class GeometryPage extends React.Component {
8231
- render() {
8232
- const {
8233
- onClickKey
8234
- } = this.props;
8235
- return /*#__PURE__*/React.createElement(KeypadPageContainer, null, /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8236
- keyConfig: KeyConfigs.SIN,
8237
- onClickKey: onClickKey
8238
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8239
- keyConfig: KeyConfigs.COS,
8240
- onClickKey: onClickKey
8241
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8242
- keyConfig: KeyConfigs.TAN,
8243
- onClickKey: onClickKey
8244
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8245
- keyConfig: KeyConfigs.LEFT_PAREN,
8246
- onClickKey: onClickKey,
8247
- style: {
8248
- gridColumn: 5
8249
- }
8250
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8251
- keyConfig: KeyConfigs.RIGHT_PAREN,
8252
- onClickKey: onClickKey,
8253
- style: {
8254
- gridColumn: 6
8255
- }
8256
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8257
- keyConfig: KeyConfigs.x,
8258
- onClickKey: onClickKey,
8259
- style: {
8260
- gridColumn: 5
8261
- }
8262
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8263
- keyConfig: KeyConfigs.FRAC_INCLUSIVE,
8264
- onClickKey: onClickKey,
8265
- style: {
8266
- gridColumn: 6
8267
- }
8268
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8269
- keyConfig: KeyConfigs.PI,
8270
- onClickKey: onClickKey,
8271
- style: {
8272
- gridColumn: 5
8273
- }
8274
- }), /*#__PURE__*/React.createElement(KeypadActionButton, {
8275
- keyConfig: KeyConfigs.BACKSPACE,
8276
- style: {
8277
- gridColumn: "6"
8278
- },
8279
- onClickKey: onClickKey
8280
- }), /*#__PURE__*/React.createElement(KeypadActionButton, {
8281
- keyConfig: KeyConfigs.DISMISS,
8282
- style: {
8283
- gridColumn: "6"
8284
- },
8285
- onClickKey: onClickKey
8286
- }));
8287
- }
8194
+ function GeometryPage(props) {
8195
+ const {
8196
+ onClickKey
8197
+ } = props;
8198
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
8199
+ keyConfig: KeyConfigs.SIN,
8200
+ onClickKey: onClickKey,
8201
+ coord: [0, 0]
8202
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8203
+ keyConfig: KeyConfigs.COS,
8204
+ onClickKey: onClickKey,
8205
+ coord: [1, 0]
8206
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8207
+ keyConfig: KeyConfigs.TAN,
8208
+ onClickKey: onClickKey,
8209
+ coord: [2, 0]
8210
+ }));
8288
8211
  }
8289
8212
 
8290
- class NumbersPage extends React.Component {
8291
- render() {
8292
- const {
8293
- onClickKey
8294
- } = this.props;
8295
- return /*#__PURE__*/React.createElement(KeypadPageContainer, null, /*#__PURE__*/React.createElement(KeypadButton, {
8296
- keyConfig: KeyConfigs.NUM_7,
8297
- onClickKey: onClickKey
8298
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8299
- keyConfig: KeyConfigs.NUM_8,
8300
- onClickKey: onClickKey
8301
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8302
- keyConfig: KeyConfigs.NUM_9,
8303
- onClickKey: onClickKey
8304
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8305
- keyConfig: KeyConfigs.DIVIDE,
8306
- style: this.props.divisionKey ? {
8307
- gridColumn: "4",
8308
- gridRow: "1"
8309
- } : {
8310
- display: "none"
8311
- },
8312
- onClickKey: onClickKey
8313
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8314
- keyConfig: this.props.multiplicationDot ? KeyConfigs.CDOT : KeyConfigs.TIMES,
8315
- style: this.props.divisionKey && {
8316
- gridColumn: "4",
8317
- gridRow: "2"
8318
- },
8319
- onClickKey: onClickKey
8320
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8321
- keyConfig: KeyConfigs.LEFT_PAREN,
8322
- onClickKey: onClickKey
8323
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8324
- keyConfig: KeyConfigs.RIGHT_PAREN,
8325
- onClickKey: onClickKey
8326
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8327
- keyConfig: KeyConfigs.NUM_4,
8328
- onClickKey: onClickKey
8329
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8330
- keyConfig: KeyConfigs.NUM_5,
8331
- onClickKey: onClickKey
8332
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8333
- keyConfig: KeyConfigs.NUM_6,
8334
- onClickKey: onClickKey
8335
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8336
- keyConfig: KeyConfigs.MINUS,
8337
- style: this.props.divisionKey && {
8338
- gridColumn: "4",
8339
- gridRow: "3"
8340
- },
8341
- onClickKey: onClickKey
8342
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8343
- keyConfig: KeyConfigs.FRAC_INCLUSIVE,
8344
- onClickKey: onClickKey,
8345
- style: {
8346
- gridColumn: "5 / 7"
8347
- }
8348
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8349
- keyConfig: KeyConfigs.NUM_1,
8350
- onClickKey: onClickKey
8351
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8352
- keyConfig: KeyConfigs.NUM_2,
8353
- onClickKey: onClickKey
8354
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8355
- keyConfig: KeyConfigs.NUM_3,
8356
- onClickKey: onClickKey
8357
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8358
- keyConfig: KeyConfigs.PLUS,
8359
- style: this.props.divisionKey ? {
8360
- gridColumn: "4",
8361
- gridRow: "4"
8362
- } : {
8363
- gridColumn: "4",
8364
- gridRowStart: "3",
8365
- gridRowEnd: "5"
8366
- },
8367
- onClickKey: onClickKey
8368
- }), /*#__PURE__*/React.createElement(KeypadActionButton, {
8369
- keyConfig: KeyConfigs.BACKSPACE,
8370
- style: {
8371
- gridColumn: "6"
8372
- },
8373
- onClickKey: onClickKey
8374
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8375
- keyConfig: KeyConfigs.NUM_0,
8376
- onClickKey: onClickKey
8377
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8378
- keyConfig: KeyConfigs.DECIMAL,
8379
- onClickKey: onClickKey
8380
- }), /*#__PURE__*/React.createElement(KeypadButton, {
8381
- keyConfig: KeyConfigs.NEGATIVE,
8382
- onClickKey: onClickKey
8383
- }), /*#__PURE__*/React.createElement(KeypadActionButton, {
8384
- keyConfig: KeyConfigs.DISMISS,
8385
- style: {
8386
- gridColumn: "6"
8387
- },
8388
- onClickKey: onClickKey
8389
- }));
8390
- }
8213
+ function NumbersPage(props) {
8214
+ const {
8215
+ onClickKey
8216
+ } = props;
8217
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
8218
+ keyConfig: KeyConfigs.NUM_7,
8219
+ onClickKey: onClickKey,
8220
+ coord: [0, 0]
8221
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8222
+ keyConfig: KeyConfigs.NUM_8,
8223
+ onClickKey: onClickKey,
8224
+ coord: [1, 0]
8225
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8226
+ keyConfig: KeyConfigs.NUM_9,
8227
+ onClickKey: onClickKey,
8228
+ coord: [2, 0]
8229
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8230
+ keyConfig: KeyConfigs.NUM_4,
8231
+ onClickKey: onClickKey,
8232
+ coord: [0, 1]
8233
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8234
+ keyConfig: KeyConfigs.NUM_5,
8235
+ onClickKey: onClickKey,
8236
+ coord: [1, 1]
8237
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8238
+ keyConfig: KeyConfigs.NUM_6,
8239
+ onClickKey: onClickKey,
8240
+ coord: [2, 1]
8241
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8242
+ keyConfig: KeyConfigs.NUM_1,
8243
+ onClickKey: onClickKey,
8244
+ coord: [0, 2]
8245
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8246
+ keyConfig: KeyConfigs.NUM_2,
8247
+ onClickKey: onClickKey,
8248
+ coord: [1, 2]
8249
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8250
+ keyConfig: KeyConfigs.NUM_3,
8251
+ onClickKey: onClickKey,
8252
+ coord: [2, 2]
8253
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8254
+ keyConfig: KeyConfigs.NUM_0,
8255
+ onClickKey: onClickKey,
8256
+ coord: [0, 3]
8257
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8258
+ keyConfig: KeyConfigs.DECIMAL,
8259
+ onClickKey: onClickKey,
8260
+ coord: [1, 3]
8261
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8262
+ keyConfig: KeyConfigs.NEGATIVE,
8263
+ onClickKey: onClickKey,
8264
+ coord: [2, 3]
8265
+ }));
8391
8266
  }
8392
8267
 
8393
- const AdvancedRelations = ({
8394
- onClickKey,
8395
- placeholder
8396
- }) => placeholder ? /*#__PURE__*/React__default.createElement(PlaceHolderButtons, {
8397
- count: 3
8398
- }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8399
- keyConfig: KeyConfigs.NEQ,
8400
- onClickKey: onClickKey
8401
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8402
- keyConfig: KeyConfigs.LEQ,
8403
- onClickKey: onClickKey
8404
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8405
- keyConfig: KeyConfigs.GEQ,
8406
- onClickKey: onClickKey
8407
- }));
8408
-
8409
- const BasicRelations = ({
8410
- onClickKey,
8411
- placeholder
8412
- }) => placeholder ? /*#__PURE__*/React__default.createElement(PlaceHolderButtons, {
8413
- count: 3
8414
- }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8415
- keyConfig: KeyConfigs.EQUAL,
8416
- onClickKey: onClickKey
8417
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8418
- keyConfig: KeyConfigs.LT,
8419
- onClickKey: onClickKey
8420
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8421
- keyConfig: KeyConfigs.GT,
8422
- onClickKey: onClickKey
8423
- }));
8424
-
8425
- const Logarithms = ({
8426
- onClickKey,
8427
- placeholder
8428
- }) => placeholder ? /*#__PURE__*/React__default.createElement(PlaceHolderButtons, {
8429
- count: 3
8430
- }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8431
- keyConfig: KeyConfigs.LOG,
8432
- onClickKey: onClickKey
8433
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8434
- keyConfig: KeyConfigs.LOG_N,
8435
- onClickKey: onClickKey
8436
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8437
- keyConfig: KeyConfigs.LN,
8438
- onClickKey: onClickKey
8439
- }));
8440
-
8441
- const PreAlgebra = ({
8442
- onClickKey,
8443
- placeholder
8444
- }) => placeholder ? /*#__PURE__*/React__default.createElement(PlaceHolderButtons, {
8445
- count: 4
8446
- }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8447
- keyConfig: KeyConfigs.EXP_2,
8448
- onClickKey: onClickKey
8449
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8450
- keyConfig: KeyConfigs.EXP,
8451
- onClickKey: onClickKey
8452
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8453
- keyConfig: KeyConfigs.SQRT,
8454
- onClickKey: onClickKey
8455
- }), /*#__PURE__*/React__default.createElement(SecondaryKeypadButton, {
8456
- keyConfig: KeyConfigs.RADICAL,
8457
- onClickKey: onClickKey
8458
- }));
8459
-
8460
- class OperatorsPage extends React.Component {
8461
- render() {
8462
- const {
8463
- onClickKey
8464
- } = this.props;
8465
- return /*#__PURE__*/React.createElement(KeypadPageContainer, null, /*#__PURE__*/React.createElement(PreAlgebra, {
8466
- onClickKey: onClickKey,
8467
- placeholder: !this.props.preAlgebra
8468
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8469
- keyConfig: KeyConfigs.LEFT_PAREN,
8470
- onClickKey: onClickKey
8471
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8472
- keyConfig: KeyConfigs.RIGHT_PAREN,
8473
- onClickKey: onClickKey
8474
- }), /*#__PURE__*/React.createElement(Logarithms, {
8475
- onClickKey: onClickKey,
8476
- placeholder: !this.props.logarithms
8477
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8478
- keyConfig: KeyConfigs.x,
8479
- onClickKey: onClickKey,
8480
- style: {
8481
- gridColumn: 5
8482
- }
8483
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8484
- keyConfig: KeyConfigs.FRAC_INCLUSIVE,
8485
- onClickKey: onClickKey,
8486
- style: {
8487
- gridColumn: 6
8488
- }
8489
- }), /*#__PURE__*/React.createElement(BasicRelations, {
8490
- onClickKey: onClickKey,
8491
- placeholder: !this.props.basicRelations
8492
- }), /*#__PURE__*/React.createElement(SecondaryKeypadButton, {
8493
- keyConfig: KeyConfigs.PI,
8494
- onClickKey: onClickKey,
8495
- style: {
8496
- gridColumn: 5
8497
- }
8498
- }), /*#__PURE__*/React.createElement(KeypadActionButton, {
8499
- keyConfig: KeyConfigs.BACKSPACE,
8500
- style: {
8501
- gridColumn: 6
8502
- },
8503
- onClickKey: onClickKey
8504
- }), /*#__PURE__*/React.createElement(AdvancedRelations, {
8505
- onClickKey: onClickKey,
8506
- placeholder: !this.props.advancedRelations
8507
- }), /*#__PURE__*/React.createElement(KeypadActionButton, {
8508
- keyConfig: KeyConfigs.DISMISS,
8509
- style: {
8510
- gridColumn: "6"
8511
- },
8512
- onClickKey: onClickKey
8513
- }));
8514
- }
8268
+ function OperatorsPage(props) {
8269
+ const {
8270
+ onClickKey,
8271
+ preAlgebra,
8272
+ logarithms,
8273
+ basicRelations,
8274
+ advancedRelations
8275
+ } = props;
8276
+ return /*#__PURE__*/React.createElement(React.Fragment, null, preAlgebra && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
8277
+ keyConfig: KeyConfigs.EXP_2,
8278
+ onClickKey: onClickKey,
8279
+ coord: [0, 0]
8280
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8281
+ keyConfig: KeyConfigs.EXP,
8282
+ onClickKey: onClickKey,
8283
+ coord: [1, 0]
8284
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8285
+ keyConfig: KeyConfigs.SQRT,
8286
+ onClickKey: onClickKey,
8287
+ coord: [2, 0]
8288
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8289
+ keyConfig: KeyConfigs.RADICAL,
8290
+ onClickKey: onClickKey,
8291
+ coord: [3, 0]
8292
+ })), logarithms && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
8293
+ keyConfig: KeyConfigs.LOG,
8294
+ onClickKey: onClickKey,
8295
+ coord: [0, 1]
8296
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8297
+ keyConfig: KeyConfigs.LOG_N,
8298
+ onClickKey: onClickKey,
8299
+ coord: [1, 1]
8300
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8301
+ keyConfig: KeyConfigs.LN,
8302
+ onClickKey: onClickKey,
8303
+ coord: [2, 1]
8304
+ })), basicRelations && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
8305
+ keyConfig: KeyConfigs.EQUAL,
8306
+ onClickKey: onClickKey,
8307
+ coord: [0, 2]
8308
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8309
+ keyConfig: KeyConfigs.LT,
8310
+ onClickKey: onClickKey,
8311
+ coord: [1, 2]
8312
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8313
+ keyConfig: KeyConfigs.GT,
8314
+ onClickKey: onClickKey,
8315
+ coord: [2, 2]
8316
+ })), advancedRelations && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
8317
+ keyConfig: KeyConfigs.NEQ,
8318
+ onClickKey: onClickKey,
8319
+ coord: [0, 3]
8320
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8321
+ keyConfig: KeyConfigs.LEQ,
8322
+ onClickKey: onClickKey,
8323
+ coord: [1, 3]
8324
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8325
+ keyConfig: KeyConfigs.GEQ,
8326
+ onClickKey: onClickKey,
8327
+ coord: [2, 3]
8328
+ })));
8329
+ }
8330
+
8331
+ function SharedKeys(props) {
8332
+ const {
8333
+ onClickKey,
8334
+ divisionKey,
8335
+ multiplicationDot
8336
+ } = props;
8337
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
8338
+ keyConfig: KeyConfigs.PLUS,
8339
+ onClickKey: onClickKey,
8340
+ coord: [4, 0],
8341
+ secondary: true
8342
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8343
+ keyConfig: KeyConfigs.MINUS,
8344
+ onClickKey: onClickKey,
8345
+ coord: [5, 0],
8346
+ secondary: true
8347
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8348
+ keyConfig: multiplicationDot ? KeyConfigs.CDOT : KeyConfigs.TIMES,
8349
+ onClickKey: onClickKey,
8350
+ coord: [4, 1],
8351
+ secondary: true
8352
+ }), divisionKey && /*#__PURE__*/React.createElement(KeypadButton, {
8353
+ keyConfig: KeyConfigs.DIVIDE,
8354
+ onClickKey: onClickKey,
8355
+ coord: [5, 1],
8356
+ secondary: true
8357
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8358
+ keyConfig: KeyConfigs.LEFT_PAREN,
8359
+ onClickKey: onClickKey,
8360
+ coord: [4, 2],
8361
+ secondary: true
8362
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8363
+ keyConfig: KeyConfigs.RIGHT_PAREN,
8364
+ onClickKey: onClickKey,
8365
+ coord: [5, 2],
8366
+ secondary: true
8367
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8368
+ keyConfig: KeyConfigs.FRAC_INCLUSIVE,
8369
+ onClickKey: onClickKey,
8370
+ coord: [4, 3],
8371
+ secondary: true
8372
+ }), /*#__PURE__*/React.createElement(KeypadButton, {
8373
+ keyConfig: KeyConfigs.BACKSPACE,
8374
+ onClickKey: onClickKey,
8375
+ coord: [5, 3],
8376
+ action: true
8377
+ }));
8515
8378
  }
8516
8379
 
8517
8380
  function allPages(props) {
8518
8381
  var _props$extraKeys;
8519
8382
  const pages = ["Numbers"];
8520
- if ((_props$extraKeys = props.extraKeys) != null && _props$extraKeys.length) {
8521
- pages.push("Extras");
8522
- }
8523
8383
  if (
8524
8384
  // OperatorsButtonSets
8525
8385
  props.preAlgebra || props.logarithms || props.basicRelations || props.advancedRelations) {
@@ -8528,40 +8388,65 @@ function allPages(props) {
8528
8388
  if (props.trigonometry) {
8529
8389
  pages.push("Geometry");
8530
8390
  }
8391
+ if ((_props$extraKeys = props.extraKeys) != null && _props$extraKeys.length) {
8392
+ pages.push("Extras");
8393
+ }
8531
8394
  return pages;
8532
8395
  }
8533
- class Keypad extends React.Component {
8534
- constructor(...args) {
8535
- super(...args);
8536
- this.state = {
8537
- selectedPage: "Numbers"
8538
- };
8539
- }
8540
- render() {
8541
- const {
8542
- selectedPage
8543
- } = this.state;
8544
- const availablePages = allPages(this.props);
8545
- return /*#__PURE__*/React.createElement(View$1, null, /*#__PURE__*/React.createElement(Tabbar, {
8546
- items: availablePages,
8547
- selectedItem: selectedPage,
8548
- onSelectItem: tabbarItem => {
8549
- this.setState({
8550
- selectedPage: tabbarItem
8551
- });
8552
- },
8553
- style: styles.tabbar
8554
- }), selectedPage === "Numbers" && /*#__PURE__*/React.createElement(NumbersPage, this.props), selectedPage === "Extras" && /*#__PURE__*/React.createElement(ExtrasPage, this.props), selectedPage === "Operators" && /*#__PURE__*/React.createElement(OperatorsPage, this.props), selectedPage === "Geometry" && /*#__PURE__*/React.createElement(GeometryPage, this.props));
8555
- }
8396
+ function Keypad(props) {
8397
+ const [selectedPage, setSelectedPage] = React.useState("Numbers");
8398
+ const availablePages = allPages(props);
8399
+ const {
8400
+ onClickKey,
8401
+ extraKeys = [],
8402
+ multiplicationDot,
8403
+ divisionKey,
8404
+ preAlgebra,
8405
+ logarithms,
8406
+ basicRelations,
8407
+ advancedRelations
8408
+ } = props;
8409
+ return /*#__PURE__*/React.createElement(View$1, null, /*#__PURE__*/React.createElement(Tabbar, {
8410
+ items: availablePages,
8411
+ selectedItem: selectedPage,
8412
+ onSelectItem: tabbarItem => {
8413
+ setSelectedPage(tabbarItem);
8414
+ },
8415
+ style: styles.tabbar
8416
+ }), /*#__PURE__*/React.createElement(View$1, {
8417
+ style: styles.grid
8418
+ }, selectedPage === "Numbers" && /*#__PURE__*/React.createElement(NumbersPage, {
8419
+ onClickKey: onClickKey
8420
+ }), selectedPage === "Extras" && /*#__PURE__*/React.createElement(ExtrasPage, {
8421
+ onClickKey: onClickKey,
8422
+ extraKeys: extraKeys
8423
+ }), selectedPage === "Operators" && /*#__PURE__*/React.createElement(OperatorsPage, {
8424
+ onClickKey: onClickKey,
8425
+ preAlgebra: preAlgebra,
8426
+ logarithms: logarithms,
8427
+ basicRelations: basicRelations,
8428
+ advancedRelations: advancedRelations
8429
+ }), selectedPage === "Geometry" && /*#__PURE__*/React.createElement(GeometryPage, {
8430
+ onClickKey: onClickKey
8431
+ }), /*#__PURE__*/React.createElement(SharedKeys, {
8432
+ onClickKey: onClickKey,
8433
+ multiplicationDot: multiplicationDot,
8434
+ divisionKey: divisionKey
8435
+ })));
8556
8436
  }
8557
- Keypad.defaultProps = {
8558
- extraKeys: []
8559
- };
8560
8437
  const styles = StyleSheet.create({
8561
8438
  tabbar: {
8562
8439
  background: Color.white
8440
+ },
8441
+ grid: {
8442
+ display: "grid",
8443
+ gridTemplateColumns: "repeat(6, 1fr)",
8444
+ gridTemplateRows: "repeat(4, 1fr)",
8445
+ backgroundColor: "#DBDCDD",
8446
+ maxHeight: 200,
8447
+ maxWidth: 300
8563
8448
  }
8564
8449
  });
8565
8450
 
8566
- export { CursorContext, KeyConfigs, Keypad, MathInput as KeypadInput, KeypadType, ProvidedKeypad as LegacyKeypad, keyToMathquillMap as keyTranslator, keypadElementPropType };
8451
+ export { CursorContext, KeyConfigs, Keypad, MathInput as KeypadInput, KeypadType, ProvidedKeypad as LegacyKeypad, createMathField, keyToMathquillMap as keyTranslator, keypadElementPropType, mathQuillInstance };
8567
8452
  //# sourceMappingURL=index.js.map