@khanacademy/math-input 17.5.0 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var perseusCore = require('@khanacademy/perseus-core');
6
- var i18n = require('@khanacademy/wonder-blocks-i18n');
7
6
  var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
8
7
  var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
9
8
  var aphrodite = require('aphrodite');
@@ -37,7 +36,6 @@ function _interopNamespace(e) {
37
36
  return Object.freeze(n);
38
37
  }
39
38
 
40
- var i18n__namespace = /*#__PURE__*/_interopNamespace(i18n);
41
39
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
42
40
  var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
43
41
  var MathQuill__default = /*#__PURE__*/_interopDefaultLegacy(MathQuill);
@@ -46,7 +44,7 @@ var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
46
44
 
47
45
  // This file is processed by a Rollup plugin (replace) to inject the production
48
46
  const libName = "@khanacademy/math-input";
49
- const libVersion = "17.5.0";
47
+ const libVersion = "18.0.0";
50
48
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
51
49
 
52
50
  function _extends() {
@@ -129,6 +127,136 @@ class View extends React__namespace.Component {
129
127
  }
130
128
  }
131
129
 
130
+ /**
131
+ * The translated strings that are used to render the Math Input.
132
+ */
133
+
134
+ /**
135
+ * Mock strings for the Math Input package, to be used for tests and Storybook.
136
+ */
137
+ const mockStrings = {
138
+ mathInputBox: "Math input box",
139
+ fingerTap: "Tap with one or two fingers to open keyboard",
140
+ before: _ref => {
141
+ let {
142
+ obj
143
+ } = _ref;
144
+ return `before ${obj}`;
145
+ },
146
+ after: _ref2 => {
147
+ let {
148
+ obj
149
+ } = _ref2;
150
+ return `after ${obj}`;
151
+ },
152
+ "beginning of": _ref3 => {
153
+ let {
154
+ obj
155
+ } = _ref3;
156
+ return `beginning of ${obj}`;
157
+ },
158
+ "end of": _ref4 => {
159
+ let {
160
+ obj
161
+ } = _ref4;
162
+ return `end of ${obj}`;
163
+ },
164
+ Baseline: "Baseline",
165
+ Superscript: "Superscript",
166
+ selected: _ref5 => {
167
+ let {
168
+ obj
169
+ } = _ref5;
170
+ return `${obj} selected`;
171
+ },
172
+ "no answer": "no answer",
173
+ "nothing selected": "nothing selected",
174
+ "nothing to the right": "nothing to the right",
175
+ "nothing to the left": "nothing to the left",
176
+ "block is empty": "block is empty",
177
+ "nothing above": "nothing above",
178
+ labelValue: _ref6 => {
179
+ let {
180
+ label,
181
+ value
182
+ } = _ref6;
183
+ return `${label}: ${value}`;
184
+ },
185
+ plus: "Plus",
186
+ minus: "Minus",
187
+ negative: "Negative",
188
+ times: "Multiply",
189
+ divide: "Divide",
190
+ decimal: "Decimal",
191
+ percent: "Percent",
192
+ cdot: "Multiply",
193
+ equalsSign: "Equals sign",
194
+ notEqualsSign: "Not-equals sign",
195
+ greaterThanSign: "Greater than sign",
196
+ lessThanSign: "Less than sign",
197
+ greaterThanOrEqualToSign: "Greater than or equal to sign",
198
+ lessThanOrEqualSign: "Less than or equal to sign",
199
+ fractionExpressionInNumerator: "Fraction, with current expression in numerator",
200
+ fractionExcludingExpression: "Fraction, excluding the current expression",
201
+ customExponent: "Custom exponent",
202
+ square: "Square",
203
+ cube: "Cube",
204
+ squareRoot: "Square root",
205
+ cubeRoot: "Cube root",
206
+ radicalWithCustomRoot: "Radical with custom root",
207
+ leftParenthesis: "Left parenthesis",
208
+ rightParenthesis: "Right parenthesis",
209
+ naturalLog: "Natural logarithm",
210
+ logBase10: "Logarithm with base 10",
211
+ logCustomBase: "Logarithm with custom base",
212
+ sine: "Sine",
213
+ cosine: "Cosine",
214
+ tangent: "Tangent",
215
+ pi: "Pi",
216
+ theta: "Theta",
217
+ upArrow: "Up arrow",
218
+ rightArrow: "Right arrow",
219
+ downArrow: "Down arrow",
220
+ leftArrow: "Left arrow",
221
+ navOutOfParentheses: "Navigate right out of a set of parentheses",
222
+ navOutOfExponent: "Navigate right out of an exponent",
223
+ navOutOfBase: "Navigate right out of a base",
224
+ navIntoNumerator: "Navigate right into the numerator of a fraction",
225
+ navOutOfNumeratorIntoDenominator: "Navigate right out of the numerator and into the denominator",
226
+ navOutOfDenominator: "Navigate right out of the denominator of a fraction",
227
+ delete: "Delete",
228
+ dismiss: "Dismiss"
229
+ };
230
+
231
+ /**
232
+ * MathInputI18nContext provides a way to set the strings and locale that are
233
+ * used inside the Math Input package.
234
+ *
235
+ */
236
+ // @ts-expect-error - TS2322 - Type 'Context<{ strings: {}; locale: string; }>' is not assignable to type 'Context<I18nContextType>'.
237
+ const MathInputI18nContext = /*#__PURE__*/React__namespace.createContext(process.env.NODE_ENV === "test" || process.env.STORYBOOK ? {
238
+ strings: mockStrings,
239
+ locale: "en"
240
+ } :
241
+ // We want to return null here, not an empty object, so that we
242
+ // are will throw an error when attempting to access the
243
+ // undefined locale or strings, making it easier to debug.
244
+ null);
245
+ function MathInputI18nContextProvider(_ref) {
246
+ let {
247
+ children,
248
+ strings,
249
+ locale
250
+ } = _ref;
251
+ return /*#__PURE__*/React__namespace.createElement(MathInputI18nContext.Provider, {
252
+ value: {
253
+ strings,
254
+ locale
255
+ }
256
+ }, children);
257
+ }
258
+ const useMathInputI18n = () => React.useContext(MathInputI18nContext);
259
+
132
260
  /**
133
261
  * KeypadContext provides a way to the Keypad and Perseus Renderers to
134
262
  * communicate.
@@ -292,6 +420,9 @@ class CursorHandle extends React__namespace.Component {
292
420
  // but it should be good enough for our purposes.
293
421
  const touchSlopPx = 8;
294
422
  class DragListener {
423
+ _scrollListener;
424
+ _moveListener;
425
+ _endAndCancelListener;
295
426
  constructor(onDrag, initialEvent) {
296
427
  // We detect drags in two ways. First, by listening for the window
297
428
  // scroll event (we consider any legitimate scroll to be a drag).
@@ -374,13 +505,33 @@ const DecimalSeparator = {
374
505
  PERIOD: "."
375
506
  };
376
507
 
377
- // NOTES(kevinb):
378
- // - In order to get the correct decimal separator for the current locale,
379
- // the locale must bet set using `setLocale(kaLocale)` which can be
380
- // imported from wonder-blocks-i18n.
381
- // - Some languages/locales use different decimal separators than the ones
382
- // listed here. Much of the Arab world uses U+066C.
383
- const decimalSeparator = i18n.getDecimalSeparator() === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
508
+ /**
509
+ * Get the character used for separating decimals.
510
+ */
511
+ const getDecimalSeparator = locale => {
512
+ let separator = DecimalSeparator.PERIOD;
513
+ switch (locale) {
514
+ // TODO(somewhatabstract): Remove this when Chrome supports the `ka`
515
+ // locale properly.
516
+ // https://github.com/formatjs/formatjs/issues/1526#issuecomment-559891201
517
+ //
518
+ // Supported locales in Chrome:
519
+ // https://source.chromium.org/chromium/chromium/src/+/master:third_party/icu/scripts/chrome_ui_languages.list
520
+ case "ka":
521
+ separator = ",";
522
+ break;
523
+ default:
524
+ const numberWithDecimalSeparator = 1.1;
525
+ // TODO(FEI-3647): Update to use .formatToParts() once we no longer have to
526
+ // support Safari 12.
527
+ const match = new Intl.NumberFormat(locale).format(numberWithDecimalSeparator)
528
+ // 0x661 is ARABIC-INDIC DIGIT ONE
529
+ // 0x6F1 is EXTENDED ARABIC-INDIC DIGIT ONE
530
+ .match(/[^\d\u0661\u06F1]/);
531
+ separator = match?.[0] ?? ".";
532
+ }
533
+ return separator === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
534
+ };
384
535
  const CDOT_ONLY = ["az", "cs", "da", "de", "hu", "hy", "kk", "ky", "lt", "lv", "nb", "sk", "sr", "sv", "uz"];
385
536
  const TIMES_ONLY = ["fr", "tr", "pt-pt"];
386
537
 
@@ -395,8 +546,7 @@ const TIMES_ONLY = ["fr", "tr", "pt-pt"];
395
546
  * @param {boolean} convertDotToTimes - the setting set by content creators
396
547
  * @returns {boolean} - true to convert to × (TIMES), false to use · (CDOT)
397
548
  */
398
- function convertDotToTimesByLocale(convertDotToTimes) {
399
- const locale = i18n.getLocale();
549
+ function convertDotToTimesByLocale(locale, convertDotToTimes) {
400
550
  if (CDOT_ONLY.includes(locale)) {
401
551
  return false;
402
552
  }
@@ -412,39 +562,6 @@ function convertDotToTimesByLocale(convertDotToTimes) {
412
562
  const inJest = typeof process !== "undefined" && !!process?.env?.JEST_WORKER_ID;
413
563
  // Explicitly checking for undefined because Cypress throws an error
414
564
 
415
- const mathQuillStrings = {
416
- mathInputBox: i18n__namespace._("Math input box"),
417
- ariaStaticStringsMap: {
418
- before: obj => i18n__namespace._("before %(obj)s", {
419
- obj
420
- }),
421
- after: obj => i18n__namespace._("after %(obj)s", {
422
- obj
423
- }),
424
- "beginning of": obj => i18n__namespace._("beginning of %(obj)s", {
425
- obj
426
- }),
427
- "end of": obj => i18n__namespace._("end of %(obj)s", {
428
- obj
429
- }),
430
- Baseline: i18n__namespace._("Baseline"),
431
- Superscript: i18n__namespace._("Superscript"),
432
- selected: obj => i18n__namespace._("%(obj)s selected", {
433
- obj
434
- }),
435
- "no answer": i18n__namespace._("no answer"),
436
- "nothing selected": i18n__namespace._("nothing selected"),
437
- "nothing to the right": i18n__namespace._("nothing to the right"),
438
- "nothing to the left": i18n__namespace._("nothing to the left"),
439
- "block is empty": i18n__namespace._("block is empty"),
440
- "nothing above": i18n__namespace._("nothing above"),
441
- labelValue: (label, value) => i18n__namespace._("%(label)s: %(value)s", {
442
- label,
443
- value
444
- })
445
- }
446
- };
447
-
448
565
  // We only need one MathQuill instance (referred to as MQ in the docs)
449
566
  // and that contains some MQ constants and the MathField constructor
450
567
  const mathQuillInstance = MathQuill__default["default"].getInterface(3);
@@ -490,10 +607,38 @@ const createBaseConfig = () => ({
490
607
  * This allows callers to do minimal configuration as only configs
491
608
  * that vary from the default need to be provided.
492
609
  */
493
- function createMathField(container, configCallback) {
610
+ function createMathField(container, strings, configCallback) {
494
611
  const baseConfig = createBaseConfig();
495
612
  const config = configCallback ? configCallback(baseConfig) : baseConfig;
496
- const mathField = mathQuillInstance.MathField(container, config).setAriaLabel(mathQuillStrings.mathInputBox).setAriaStringsOverrideMap(mathQuillStrings.ariaStaticStringsMap);
613
+ const mathField = mathQuillInstance.MathField(container, config).setAriaLabel(strings.mathInputBox).setAriaStringsOverrideMap({
614
+ before: obj => strings.before({
615
+ obj
616
+ }),
617
+ after: obj => strings.after({
618
+ obj
619
+ }),
620
+ "beginning of": obj => strings["beginning of"]({
621
+ obj
622
+ }),
623
+ "end of": obj => strings["end of"]({
624
+ obj
625
+ }),
626
+ Baseline: strings.Baseline,
627
+ Superscript: strings.Superscript,
628
+ selected: obj => strings.selected({
629
+ obj
630
+ }),
631
+ "no answer": strings["no answer"],
632
+ "nothing selected": strings["nothing selected"],
633
+ "nothing to the right": strings["nothing to the right"],
634
+ "nothing to the left": strings["nothing to the left"],
635
+ "block is empty": strings["block is empty"],
636
+ "nothing above": strings["nothing above"],
637
+ labelValue: (label, value) => strings.labelValue({
638
+ label,
639
+ value
640
+ })
641
+ });
497
642
 
498
643
  // We should avoid running SpeechRuleEngine.setup() in Jest. It makes an
499
644
  // HTTP request to fetch non-english speech rules, and cannot be easily
@@ -1143,7 +1288,7 @@ function buildNormalFunctionCallback(command) {
1143
1288
  mathField.keystroke("Left");
1144
1289
  };
1145
1290
  }
1146
- const keyToMathquillMap = {
1291
+ const getKeyTranslator = locale => ({
1147
1292
  EXP: handleExponent,
1148
1293
  EXP_2: handleExponent,
1149
1294
  EXP_3: handleExponent,
@@ -1161,7 +1306,7 @@ const keyToMathquillMap = {
1161
1306
  COS: buildNormalFunctionCallback("cos"),
1162
1307
  TAN: buildNormalFunctionCallback("tan"),
1163
1308
  CDOT: buildGenericCallback("\\cdot"),
1164
- DECIMAL: buildGenericCallback(decimalSeparator),
1309
+ DECIMAL: buildGenericCallback(getDecimalSeparator(locale)),
1165
1310
  DIVIDE: buildGenericCallback("\\div"),
1166
1311
  EQUAL: buildGenericCallback("="),
1167
1312
  GEQ: buildGenericCallback("\\geq"),
@@ -1300,31 +1445,21 @@ const keyToMathquillMap = {
1300
1445
  X: buildGenericCallback("X"),
1301
1446
  Y: buildGenericCallback("Y"),
1302
1447
  Z: buildGenericCallback("Z")
1303
- };
1448
+ });
1304
1449
 
1305
1450
  // Notes about MathQuill
1306
- const mobileKeyTranslator = {
1307
- ...keyToMathquillMap,
1308
- // note(Matthew): our mobile backspace logic is really complicated
1309
- // and for some reason doesn't really work in the desktop experience.
1310
- // So we default to the basic backspace functionality in the
1311
- // key translator and overwrite it with the complicated logic here
1312
- // until we can unify the experiences (if we even want to).
1313
- // https://khanacademy.atlassian.net/browse/LC-906
1314
- BACKSPACE: handleBackspace
1315
- };
1316
-
1317
1451
  /**
1318
1452
  * This file contains a wrapper around MathQuill so that we can provide a
1319
1453
  * more regular interface for the functionality we need while insulating us
1320
1454
  * from MathQuill changes.
1321
1455
  */
1322
1456
  class MathWrapper {
1323
- // MathQuill MathField input
1324
-
1325
- constructor(element) {
1326
- let callbacks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1327
- this.mathField = createMathField(element, () => {
1457
+ mathField; // MathQuill MathField input
1458
+ callbacks;
1459
+ mobileKeyTranslator;
1460
+ constructor(element, strings, locale) {
1461
+ let callbacks = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1462
+ this.mathField = createMathField(element, strings, () => {
1328
1463
  return {
1329
1464
  // use a span instead of a textarea so that we don't bring up the
1330
1465
  // native keyboard on mobile when selecting the input
@@ -1334,6 +1469,16 @@ class MathWrapper {
1334
1469
  };
1335
1470
  });
1336
1471
  this.callbacks = callbacks;
1472
+ this.mobileKeyTranslator = {
1473
+ ...getKeyTranslator(locale),
1474
+ // note(Matthew): our mobile backspace logic is really complicated
1475
+ // and for some reason doesn't really work in the desktop experience.
1476
+ // So we default to the basic backspace functionality in the
1477
+ // key translator and overwrite it with the complicated logic here
1478
+ // until we can unify the experiences (if we even want to).
1479
+ // https://khanacademy.atlassian.net/browse/LC-906
1480
+ BACKSPACE: handleBackspace
1481
+ };
1337
1482
  }
1338
1483
  focus() {
1339
1484
  // HACK(charlie): We shouldn't reaching into MathQuill internals like
@@ -1359,7 +1504,7 @@ class MathWrapper {
1359
1504
  */
1360
1505
  pressKey(key) {
1361
1506
  const cursor = this.getCursor();
1362
- const translator = mobileKeyTranslator[key];
1507
+ const translator = this.mobileKeyTranslator[key];
1363
1508
  if (translator) {
1364
1509
  translator(this.mathField, key);
1365
1510
  }
@@ -1509,16 +1654,25 @@ const scrollIntoView = (containerNode, keypadNode) => {
1509
1654
  const constrainingFrictionFactor = 0.8;
1510
1655
  // eslint-disable-next-line react/no-unsafe
1511
1656
  class MathInput extends React__namespace.Component {
1657
+ static contextType = MathInputI18nContext;
1658
+ didTouchOutside;
1659
+ didScroll;
1660
+ mathField;
1512
1661
  // @ts-expect-error - TS2564 - Property 'recordTouchStartOutside' has no initializer and is not definitely assigned in the constructor.
1513
-
1662
+ recordTouchStartOutside;
1514
1663
  // @ts-expect-error - TS2564 - Property 'blurOnTouchEndOutside' has no initializer and is not definitely assigned in the constructor.
1515
-
1664
+ blurOnTouchEndOutside;
1516
1665
  // @ts-expect-error - TS2564 - Property 'blurOnClickOutside' has no initializer and is not definitely assigned in the constructor.
1517
-
1666
+ blurOnClickOutside;
1667
+ dragListener;
1668
+ inputRef;
1669
+ _isMounted;
1670
+ _mathContainer;
1518
1671
  // @ts-expect-error - TS2564 - Property '_container' has no initializer and is not definitely assigned in the constructor.
1519
-
1672
+ _container;
1673
+ _root;
1520
1674
  // @ts-expect-error - TS2564 - Property '_containerBounds' has no initializer and is not definitely assigned in the constructor.
1521
-
1675
+ _containerBounds;
1522
1676
  static defaultProps = {
1523
1677
  style: {},
1524
1678
  value: ""
@@ -1535,7 +1689,7 @@ class MathInput extends React__namespace.Component {
1535
1689
  };
1536
1690
  componentDidMount() {
1537
1691
  this._isMounted = true;
1538
- this.mathField = new MathWrapper(this._mathContainer, {
1692
+ this.mathField = new MathWrapper(this._mathContainer, this.context.strings, this.context.locale, {
1539
1693
  onCursorMove: cursor => {
1540
1694
  // TODO(charlie): It's not great that there is so much coupling
1541
1695
  // between this keypad and the input behavior. We should wrap
@@ -2244,7 +2398,7 @@ class MathInput extends React__namespace.Component {
2244
2398
  // keyboard appear. It should only require one finger, which is how iOS works.
2245
2399
  // TODO(diedra): Fix the bug that is causing Android to require a two finger tap
2246
2400
  // to the open the keyboard, and then remove the second half of this label.
2247
- const ariaLabel = mathQuillStrings.mathInputBox + " " + i18n__namespace._("Tap with one or two fingers to open keyboard");
2401
+ const ariaLabel = this.context.strings.mathInputBox + " " + this.context.strings.fingerTap;
2248
2402
  return /*#__PURE__*/React__namespace.createElement(KeypadContext.Consumer, null, _ref => {
2249
2403
  let {
2250
2404
  keypadActive,
@@ -2289,6 +2443,7 @@ class MathInput extends React__namespace.Component {
2289
2443
  });
2290
2444
  }
2291
2445
  }
2446
+ MathInput.contextType = MathInputI18nContext;
2292
2447
  const fontSizePt = 18;
2293
2448
  const inputMaxWidth = 128;
2294
2449
 
@@ -2584,6 +2739,7 @@ function Tabbar(props) {
2584
2739
  /**
2585
2740
  * This file contains configuration settings for the buttons in the keypad.
2586
2741
  */
2742
+
2587
2743
  const getDefaultOperatorFields = _ref => {
2588
2744
  let {
2589
2745
  key,
@@ -2632,49 +2788,43 @@ const getDefaultNumberFields = _ref3 => {
2632
2788
  }
2633
2789
  };
2634
2790
  };
2635
- const KeyConfigs = {
2791
+ const KeyConfigs = strings => ({
2636
2792
  // Basic math
2637
2793
  PLUS: {
2638
2794
  ...getDefaultOperatorFields({
2639
2795
  key: "PLUS",
2640
- // I18N: A label for a 'plus' sign.
2641
- ariaLabel: i18n__namespace._("Plus")
2796
+ ariaLabel: strings.plus
2642
2797
  })
2643
2798
  },
2644
2799
  MINUS: {
2645
2800
  ...getDefaultOperatorFields({
2646
2801
  key: "MINUS",
2647
- // I18N: A label for a 'minus' sign.
2648
- ariaLabel: i18n__namespace._("Minus")
2802
+ ariaLabel: strings.minus
2649
2803
  })
2650
2804
  },
2651
2805
  NEGATIVE: {
2652
2806
  ...getDefaultOperatorFields({
2653
2807
  key: "NEGATIVE",
2654
- // I18N: A label for a 'negative' sign.
2655
- ariaLabel: i18n__namespace._("Negative")
2808
+ ariaLabel: strings.negative
2656
2809
  })
2657
2810
  },
2658
2811
  TIMES: {
2659
2812
  ...getDefaultOperatorFields({
2660
2813
  key: "TIMES",
2661
- // I18N: A label for a 'multiply' sign.
2662
- ariaLabel: i18n__namespace._("Multiply")
2814
+ ariaLabel: strings.times
2663
2815
  })
2664
2816
  },
2665
2817
  DIVIDE: {
2666
2818
  ...getDefaultOperatorFields({
2667
2819
  key: "DIVIDE",
2668
- // I18N: A label for a 'divide' sign.
2669
- ariaLabel: i18n__namespace._("Divide")
2820
+ ariaLabel: strings.divide
2670
2821
  })
2671
2822
  },
2672
2823
  DECIMAL: {
2673
2824
  ...getDefaultOperatorFields({
2674
2825
  key: "DECIMAL",
2675
2826
  keyType: "VALUE",
2676
- // I18N: A label for a 'decimal' sign (represented as '.' or ',').
2677
- ariaLabel: i18n__namespace._("Decimal")
2827
+ ariaLabel: strings.decimal
2678
2828
  })
2679
2829
  },
2680
2830
  PERIOD: {
@@ -2687,214 +2837,168 @@ const KeyConfigs = {
2687
2837
  PERCENT: {
2688
2838
  ...getDefaultOperatorFields({
2689
2839
  key: "PERCENT",
2690
- // I18N: A label for a 'percent' sign (represented as '%').
2691
- ariaLabel: i18n__namespace._("Percent")
2840
+ ariaLabel: strings.percent
2692
2841
  })
2693
2842
  },
2694
2843
  CDOT: {
2695
2844
  ...getDefaultOperatorFields({
2696
2845
  key: "CDOT",
2697
- // I18N: A label for a 'centered dot' multiplication sign (represented as '⋅').
2698
- ariaLabel: i18n__namespace._("Multiply")
2846
+ ariaLabel: strings.cdot
2699
2847
  })
2700
2848
  },
2701
2849
  EQUAL: {
2702
2850
  ...getDefaultOperatorFields({
2703
2851
  key: "EQUAL",
2704
- // I18N: A label for an 'equals' sign (represented as '=').
2705
- ariaLabel: i18n__namespace._("Equals sign")
2852
+ ariaLabel: strings.equalsSign
2706
2853
  })
2707
2854
  },
2708
2855
  NEQ: {
2709
2856
  ...getDefaultOperatorFields({
2710
2857
  key: "NEQ",
2711
- // I18N: A label for a 'not-equals' sign (represented as '≠').
2712
- ariaLabel: i18n__namespace._("Not-equals sign")
2858
+ ariaLabel: strings.notEqualsSign
2713
2859
  })
2714
2860
  },
2715
2861
  GT: {
2716
2862
  ...getDefaultOperatorFields({
2717
2863
  key: "GT",
2718
- // I18N: A label for a 'greater than' sign (represented as '>').
2719
- ariaLabel: i18n__namespace._("Greater than sign")
2864
+ ariaLabel: strings.greaterThanSign
2720
2865
  })
2721
2866
  },
2722
2867
  LT: {
2723
2868
  ...getDefaultOperatorFields({
2724
2869
  key: "LT",
2725
- // I18N: A label for a 'less than' sign (represented as '<').
2726
- ariaLabel: i18n__namespace._("Less than sign")
2870
+ ariaLabel: strings.lessThanSign
2727
2871
  })
2728
2872
  },
2729
2873
  GEQ: {
2730
2874
  ...getDefaultOperatorFields({
2731
2875
  key: "GEQ",
2732
- // I18N: A label for a 'greater than or equal to' sign (represented as '≥').
2733
- ariaLabel: i18n__namespace._("Greater than or equal to sign")
2876
+ ariaLabel: strings.greaterThanOrEqualToSign
2734
2877
  })
2735
2878
  },
2736
2879
  LEQ: {
2737
2880
  ...getDefaultOperatorFields({
2738
2881
  key: "LEQ",
2739
- // I18N: A label for a 'less than or equal to' sign (represented as '≤').
2740
- ariaLabel: i18n__namespace._("Less than or equal to sign")
2882
+ ariaLabel: strings.lessThanOrEqualSign
2741
2883
  })
2742
2884
  },
2743
2885
  // mobile native
2744
2886
  FRAC_INCLUSIVE: {
2745
2887
  ...getDefaultOperatorFields({
2746
2888
  key: "FRAC_INCLUSIVE",
2747
- // I18N: A label for a button that creates a new fraction and puts the
2748
- // current expression in the numerator of that fraction.
2749
- ariaLabel: i18n__namespace._("Fraction, with current expression in numerator")
2889
+ ariaLabel: strings.fractionExpressionInNumerator
2750
2890
  })
2751
2891
  },
2752
2892
  // mobile native
2753
2893
  FRAC_EXCLUSIVE: {
2754
2894
  ...getDefaultOperatorFields({
2755
2895
  key: "FRAC_EXCLUSIVE",
2756
- // I18N: A label for a button that creates a new fraction next to the
2757
- // cursor.
2758
- ariaLabel: i18n__namespace._("Fraction, excluding the current expression")
2896
+ ariaLabel: strings.fractionExcludingExpression
2759
2897
  })
2760
2898
  },
2761
2899
  // mobile web
2762
2900
  FRAC: {
2763
2901
  ...getDefaultOperatorFields({
2764
2902
  key: "FRAC",
2765
- // I18N: A label for a button that creates a new fraction next to the
2766
- // cursor.
2767
- ariaLabel: i18n__namespace._("Fraction, excluding the current expression")
2903
+ ariaLabel: strings.fractionExcludingExpression
2768
2904
  })
2769
2905
  },
2770
2906
  EXP: {
2771
2907
  ...getDefaultOperatorFields({
2772
2908
  key: "EXP",
2773
- // I18N: A label for a button that will allow the user to input a
2774
- // custom exponent.
2775
- ariaLabel: i18n__namespace._("Custom exponent")
2909
+ ariaLabel: strings.customExponent
2776
2910
  })
2777
2911
  },
2778
2912
  EXP_2: {
2779
2913
  ...getDefaultOperatorFields({
2780
2914
  key: "EXP_2",
2781
- // I18N: A label for a button that will square (take to the second
2782
- // power) some math.
2783
- ariaLabel: i18n__namespace._("Square")
2915
+ ariaLabel: strings.square
2784
2916
  })
2785
2917
  },
2786
2918
  EXP_3: {
2787
2919
  ...getDefaultOperatorFields({
2788
2920
  key: "EXP_3",
2789
- // I18N: A label for a button that will cube (take to the third power)
2790
- // some math.
2791
- ariaLabel: i18n__namespace._("Cube")
2921
+ ariaLabel: strings.cube
2792
2922
  })
2793
2923
  },
2794
2924
  SQRT: {
2795
2925
  ...getDefaultOperatorFields({
2796
2926
  key: "SQRT",
2797
- // I18N: A label for a button that will allow the user to input a
2798
- // square root.
2799
- ariaLabel: i18n__namespace._("Square root")
2927
+ ariaLabel: strings.squareRoot
2800
2928
  })
2801
2929
  },
2802
2930
  CUBE_ROOT: {
2803
2931
  ...getDefaultOperatorFields({
2804
2932
  key: "CUBE_ROOT",
2805
- // I18N: A label for a button that will allow the user to input a
2806
- // cube root.
2807
- ariaLabel: i18n__namespace._("Cube root")
2933
+ ariaLabel: strings.cubeRoot
2808
2934
  })
2809
2935
  },
2810
2936
  RADICAL: {
2811
2937
  ...getDefaultOperatorFields({
2812
2938
  key: "RADICAL",
2813
- // I18N: A label for a button that will allow the user to input a
2814
- // radical with a custom root.
2815
- ariaLabel: i18n__namespace._("Radical with custom root")
2939
+ ariaLabel: strings.radicalWithCustomRoot
2816
2940
  })
2817
2941
  },
2818
2942
  LEFT_PAREN: {
2819
2943
  ...getDefaultOperatorFields({
2820
2944
  key: "LEFT_PAREN",
2821
- // I18N: A label for a button that will allow the user to input a
2822
- // left parenthesis (i.e. '(')
2823
- ariaLabel: i18n__namespace._("Left parenthesis")
2945
+ ariaLabel: strings.leftParenthesis
2824
2946
  })
2825
2947
  },
2826
2948
  RIGHT_PAREN: {
2827
2949
  ...getDefaultOperatorFields({
2828
2950
  key: "RIGHT_PAREN",
2829
- // I18N: A label for a button that will allow the user to input a
2830
- // right parenthesis (i.e. ')')
2831
- ariaLabel: i18n__namespace._("Right parenthesis")
2951
+ ariaLabel: strings.rightParenthesis
2832
2952
  })
2833
2953
  },
2834
2954
  LN: {
2835
2955
  ...getDefaultOperatorFields({
2836
2956
  key: "LN",
2837
- // I18N: A label for a button that will allow the user to input a
2838
- // natural logarithm.
2839
- ariaLabel: i18n__namespace._("Natural logarithm")
2957
+ ariaLabel: strings.naturalLog
2840
2958
  })
2841
2959
  },
2842
2960
  LOG: {
2843
2961
  ...getDefaultOperatorFields({
2844
2962
  key: "LOG",
2845
- // I18N: A label for a button that will allow the user to input a
2846
- // logarithm with base 10.
2847
- ariaLabel: i18n__namespace._("Logarithm with base 10")
2963
+ ariaLabel: strings.logBase10
2848
2964
  })
2849
2965
  },
2850
2966
  LOG_N: {
2851
2967
  ...getDefaultOperatorFields({
2852
2968
  key: "LOG_N",
2853
- // I18N: A label for a button that will allow the user to input a
2854
- // logarithm with a custom base.
2855
- ariaLabel: i18n__namespace._("Logarithm with custom base")
2969
+ ariaLabel: strings.logCustomBase
2856
2970
  })
2857
2971
  },
2858
2972
  SIN: {
2859
2973
  ...getDefaultOperatorFields({
2860
2974
  key: "SIN",
2861
- // I18N: A label for a button that will allow the user to input a
2862
- // sine function.
2863
- ariaLabel: i18n__namespace._("Sine")
2975
+ ariaLabel: strings.sine
2864
2976
  })
2865
2977
  },
2866
2978
  COS: {
2867
2979
  ...getDefaultOperatorFields({
2868
2980
  key: "COS",
2869
- // I18N: A label for a button that will allow the user to input a
2870
- // cosine function.
2871
- ariaLabel: i18n__namespace._("Cosine")
2981
+ ariaLabel: strings.cosine
2872
2982
  })
2873
2983
  },
2874
2984
  TAN: {
2875
2985
  ...getDefaultOperatorFields({
2876
2986
  key: "TAN",
2877
- // I18N: A label for a button that will allow the user to input a
2878
- // tangent function.
2879
- ariaLabel: i18n__namespace._("Tangent")
2987
+ ariaLabel: strings.tangent
2880
2988
  })
2881
2989
  },
2882
2990
  PI: {
2883
2991
  ...getDefaultValueFields({
2884
2992
  key: "PI",
2885
2993
  data: "\\pi",
2886
- // I18N: A label for a button that will allow the user to input the
2887
- // mathematical constant pi (i.e., π)
2888
- ariaLabel: i18n__namespace._("Pi")
2994
+ ariaLabel: strings.pi
2889
2995
  })
2890
2996
  },
2891
2997
  THETA: {
2892
2998
  ...getDefaultValueFields({
2893
2999
  key: "THETA",
2894
3000
  data: "\\theta",
2895
- // I18N: A label for a button that will allow the user to input the
2896
- // mathematical constant theta (i.e., θ)
2897
- ariaLabel: i18n__namespace._("Theta")
3001
+ ariaLabel: strings.theta
2898
3002
  })
2899
3003
  },
2900
3004
  NOOP: {
@@ -2908,77 +3012,77 @@ const KeyConfigs = {
2908
3012
  ...getDefaultOperatorFields({
2909
3013
  key: "UP",
2910
3014
  keyType: "INPUT_NAVIGATION",
2911
- ariaLabel: i18n__namespace._("Up arrow")
3015
+ ariaLabel: strings.upArrow
2912
3016
  })
2913
3017
  },
2914
3018
  RIGHT: {
2915
3019
  ...getDefaultOperatorFields({
2916
3020
  key: "RIGHT",
2917
3021
  keyType: "INPUT_NAVIGATION",
2918
- ariaLabel: i18n__namespace._("Right arrow")
3022
+ ariaLabel: strings.rightArrow
2919
3023
  })
2920
3024
  },
2921
3025
  DOWN: {
2922
3026
  ...getDefaultOperatorFields({
2923
3027
  key: "DOWN",
2924
3028
  keyType: "INPUT_NAVIGATION",
2925
- ariaLabel: i18n__namespace._("Down arrow")
3029
+ ariaLabel: strings.downArrow
2926
3030
  })
2927
3031
  },
2928
3032
  LEFT: {
2929
3033
  ...getDefaultOperatorFields({
2930
3034
  key: "LEFT",
2931
3035
  keyType: "INPUT_NAVIGATION",
2932
- ariaLabel: i18n__namespace._("Left arrow")
3036
+ ariaLabel: strings.leftArrow
2933
3037
  })
2934
3038
  },
2935
3039
  JUMP_OUT_PARENTHESES: {
2936
3040
  ...getDefaultOperatorFields({
2937
3041
  key: "JUMP_OUT_PARENTHESES",
2938
3042
  keyType: "INPUT_NAVIGATION",
2939
- ariaLabel: i18n__namespace._("Navigate right out of a set of parentheses")
3043
+ ariaLabel: strings.navOutOfParentheses
2940
3044
  })
2941
3045
  },
2942
3046
  JUMP_OUT_EXPONENT: {
2943
3047
  ...getDefaultOperatorFields({
2944
3048
  key: "JUMP_OUT_EXPONENT",
2945
3049
  keyType: "INPUT_NAVIGATION",
2946
- ariaLabel: i18n__namespace._("Navigate right out of an exponent")
3050
+ ariaLabel: strings.navOutOfExponent
2947
3051
  })
2948
3052
  },
2949
3053
  JUMP_OUT_BASE: {
2950
3054
  ...getDefaultOperatorFields({
2951
3055
  key: "JUMP_OUT_BASE",
2952
3056
  keyType: "INPUT_NAVIGATION",
2953
- ariaLabel: i18n__namespace._("Navigate right out of a base")
3057
+ ariaLabel: strings.navOutOfBase
2954
3058
  })
2955
3059
  },
2956
3060
  JUMP_INTO_NUMERATOR: {
2957
3061
  ...getDefaultOperatorFields({
2958
3062
  key: "JUMP_INTO_NUMERATOR",
2959
3063
  keyType: "INPUT_NAVIGATION",
2960
- ariaLabel: i18n__namespace._("Navigate right into the numerator of a fraction")
3064
+ ariaLabel: strings.navIntoNumerator
2961
3065
  })
2962
3066
  },
2963
3067
  JUMP_OUT_NUMERATOR: {
2964
3068
  ...getDefaultOperatorFields({
2965
3069
  key: "JUMP_OUT_NUMERATOR",
2966
3070
  keyType: "INPUT_NAVIGATION",
2967
- ariaLabel: i18n__namespace._("Navigate right out of the numerator and into the denominator")
3071
+ ariaLabel: strings.navOutOfNumeratorIntoDenominator
2968
3072
  })
2969
3073
  },
2970
3074
  JUMP_OUT_DENOMINATOR: {
2971
3075
  ...getDefaultOperatorFields({
2972
3076
  key: "JUMP_OUT_DENOMINATOR",
2973
3077
  keyType: "INPUT_NAVIGATION",
2974
- ariaLabel: i18n__namespace._("Navigate right out of the denominator of a fraction")
3078
+ ariaLabel: strings.navOutOfDenominator
2975
3079
  })
2976
3080
  },
2977
3081
  BACKSPACE: {
2978
3082
  ...getDefaultOperatorFields({
2979
3083
  key: "BACKSPACE",
2980
3084
  keyType: "INPUT_NAVIGATION",
2981
- ariaLabel: i18n__namespace._("Delete")
3085
+ ariaLabel: strings.delete
2982
3086
  })
2983
3087
  },
2984
3088
  // Keypad navigation
@@ -2986,8 +3090,7 @@ const KeyConfigs = {
2986
3090
  ...getDefaultOperatorFields({
2987
3091
  key: "DISMISS",
2988
3092
  keyType: "KEYPAD_NAVIGATION",
2989
- // I18N: A label for a button that will dismiss/hide a keypad.
2990
- ariaLabel: i18n__namespace._("Dismiss")
3093
+ ariaLabel: strings.dismiss
2991
3094
  })
2992
3095
  },
2993
3096
  // TODO(charlie): Use the numeral color for the 'Many' key.
@@ -3329,7 +3432,7 @@ const KeyConfigs = {
3329
3432
  key: "LOG_B"
3330
3433
  })
3331
3434
  }
3332
- };
3435
+ });
3333
3436
 
3334
3437
  /*
3335
3438
  The SVGs in this file should be treated as binary assets. If, in the future,
@@ -3347,6 +3450,9 @@ function ButtonAsset(_ref) {
3347
3450
  let {
3348
3451
  id
3349
3452
  } = _ref;
3453
+ const {
3454
+ locale
3455
+ } = useMathInputI18n();
3350
3456
  switch (id) {
3351
3457
  case "NUM_0":
3352
3458
  return /*#__PURE__*/React__namespace.createElement("svg", {
@@ -3462,7 +3568,7 @@ function ButtonAsset(_ref) {
3462
3568
  case "PERIOD":
3463
3569
  // Different locales use different symbols for the decimal separator
3464
3570
  // (, vs .)
3465
- if (id === "DECIMAL" && decimalSeparator === DecimalSeparator.COMMA) {
3571
+ if (id === "DECIMAL" && getDecimalSeparator(locale) === DecimalSeparator.COMMA) {
3466
3572
  // comma decimal separator
3467
3573
  return /*#__PURE__*/React__namespace.createElement("svg", {
3468
3574
  width: "40",
@@ -4878,13 +4984,17 @@ function ExtrasPage(props) {
4878
4984
  extraKeys,
4879
4985
  onClickKey
4880
4986
  } = props;
4987
+ const {
4988
+ strings
4989
+ } = useMathInputI18n();
4990
+ const Keys = KeyConfigs(strings);
4881
4991
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, extraKeys.map((key, i) => {
4882
4992
  // Map 1D array to Cartesian coordinates
4883
4993
  const coordX = i % columns;
4884
4994
  const coordY = i / columns;
4885
4995
  return /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4886
4996
  key: key,
4887
- keyConfig: KeyConfigs[key],
4997
+ keyConfig: Keys[key],
4888
4998
  onClickKey: onClickKey,
4889
4999
  coord: [coordX, coordY]
4890
5000
  });
@@ -4898,7 +5008,7 @@ const expandedViewThreshold = 500;
4898
5008
  // This is a helper function that returns the correct context for the cursor
4899
5009
  // based on the cursorContext prop. It is used in the keypad to determine
4900
5010
  // which key to render as the "jump out" key.
4901
- function getCursorContextConfig(cursorContext) {
5011
+ function getCursorContextConfig(strings, cursorContext) {
4902
5012
  if (!cursorContext) {
4903
5013
  return null;
4904
5014
  }
@@ -4906,17 +5016,17 @@ function getCursorContextConfig(cursorContext) {
4906
5016
  case CursorContext.NONE:
4907
5017
  return null;
4908
5018
  case CursorContext.IN_PARENS:
4909
- return KeyConfigs.JUMP_OUT_PARENTHESES;
5019
+ return KeyConfigs(strings).JUMP_OUT_PARENTHESES;
4910
5020
  case CursorContext.IN_SUPER_SCRIPT:
4911
- return KeyConfigs.JUMP_OUT_EXPONENT;
5021
+ return KeyConfigs(strings).JUMP_OUT_EXPONENT;
4912
5022
  case CursorContext.IN_SUB_SCRIPT:
4913
- return KeyConfigs.JUMP_OUT_BASE;
5023
+ return KeyConfigs(strings).JUMP_OUT_BASE;
4914
5024
  case CursorContext.IN_NUMERATOR:
4915
- return KeyConfigs.JUMP_OUT_NUMERATOR;
5025
+ return KeyConfigs(strings).JUMP_OUT_NUMERATOR;
4916
5026
  case CursorContext.IN_DENOMINATOR:
4917
- return KeyConfigs.JUMP_OUT_DENOMINATOR;
5027
+ return KeyConfigs(strings).JUMP_OUT_DENOMINATOR;
4918
5028
  case CursorContext.BEFORE_FRACTION:
4919
- return KeyConfigs.JUMP_INTO_NUMERATOR;
5029
+ return KeyConfigs(strings).JUMP_INTO_NUMERATOR;
4920
5030
  }
4921
5031
  }
4922
5032
 
@@ -4925,70 +5035,74 @@ function FractionsPage(props) {
4925
5035
  onClickKey,
4926
5036
  cursorContext
4927
5037
  } = props;
4928
- const cursorKeyConfig = getCursorContextConfig(cursorContext);
5038
+ const {
5039
+ strings
5040
+ } = useMathInputI18n();
5041
+ const cursorKeyConfig = getCursorContextConfig(strings, cursorContext);
4929
5042
  // These keys are arranged sequentially so that tabbing follows numerical order. This
4930
5043
  // allows us to visually mimic a keypad without affecting a11y. The visual order of the
4931
5044
  // keys in the keypad is determined by their coordinates, not their order in the DOM.
5045
+ const Keys = KeyConfigs(strings);
4932
5046
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4933
- keyConfig: KeyConfigs.NUM_1,
5047
+ keyConfig: Keys.NUM_1,
4934
5048
  onClickKey: onClickKey,
4935
5049
  coord: [0, 2]
4936
5050
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4937
- keyConfig: KeyConfigs.NUM_2,
5051
+ keyConfig: Keys.NUM_2,
4938
5052
  onClickKey: onClickKey,
4939
5053
  coord: [1, 2]
4940
5054
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4941
- keyConfig: KeyConfigs.NUM_3,
5055
+ keyConfig: Keys.NUM_3,
4942
5056
  onClickKey: onClickKey,
4943
5057
  coord: [2, 2]
4944
5058
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4945
- keyConfig: KeyConfigs.NUM_4,
5059
+ keyConfig: Keys.NUM_4,
4946
5060
  onClickKey: onClickKey,
4947
5061
  coord: [0, 1]
4948
5062
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4949
- keyConfig: KeyConfigs.NUM_5,
5063
+ keyConfig: Keys.NUM_5,
4950
5064
  onClickKey: onClickKey,
4951
5065
  coord: [1, 1]
4952
5066
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4953
- keyConfig: KeyConfigs.NUM_6,
5067
+ keyConfig: Keys.NUM_6,
4954
5068
  onClickKey: onClickKey,
4955
5069
  coord: [2, 1]
4956
5070
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4957
- keyConfig: KeyConfigs.NUM_7,
5071
+ keyConfig: Keys.NUM_7,
4958
5072
  onClickKey: onClickKey,
4959
5073
  coord: [0, 0]
4960
5074
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4961
- keyConfig: KeyConfigs.NUM_8,
5075
+ keyConfig: Keys.NUM_8,
4962
5076
  onClickKey: onClickKey,
4963
5077
  coord: [1, 0]
4964
5078
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4965
- keyConfig: KeyConfigs.NUM_9,
5079
+ keyConfig: Keys.NUM_9,
4966
5080
  onClickKey: onClickKey,
4967
5081
  coord: [2, 0]
4968
5082
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4969
- keyConfig: KeyConfigs.NUM_0,
5083
+ keyConfig: Keys.NUM_0,
4970
5084
  onClickKey: onClickKey,
4971
5085
  coord: [0, 3]
4972
5086
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4973
- keyConfig: KeyConfigs.DECIMAL,
5087
+ keyConfig: Keys.DECIMAL,
4974
5088
  onClickKey: onClickKey,
4975
5089
  coord: [1, 3]
4976
5090
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4977
- keyConfig: KeyConfigs.NEGATIVE,
5091
+ keyConfig: Keys.NEGATIVE,
4978
5092
  onClickKey: onClickKey,
4979
5093
  coord: [2, 3]
4980
5094
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4981
- keyConfig: KeyConfigs.PERCENT,
5095
+ keyConfig: Keys.PERCENT,
4982
5096
  onClickKey: onClickKey,
4983
5097
  coord: [3, 0],
4984
5098
  secondary: true
4985
5099
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4986
- keyConfig: KeyConfigs.PI,
5100
+ keyConfig: Keys.PI,
4987
5101
  onClickKey: onClickKey,
4988
5102
  coord: [3, 1],
4989
5103
  secondary: true
4990
5104
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
4991
- keyConfig: KeyConfigs.FRAC,
5105
+ keyConfig: Keys.FRAC,
4992
5106
  onClickKey: onClickKey,
4993
5107
  coord: [3, 2],
4994
5108
  secondary: true
@@ -4998,7 +5112,7 @@ function FractionsPage(props) {
4998
5112
  coord: [3, 3],
4999
5113
  secondary: true
5000
5114
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5001
- keyConfig: KeyConfigs.BACKSPACE,
5115
+ keyConfig: Keys.BACKSPACE,
5002
5116
  onClickKey: onClickKey,
5003
5117
  coord: [4, 3],
5004
5118
  action: true
@@ -5009,16 +5123,20 @@ function GeometryPage(props) {
5009
5123
  const {
5010
5124
  onClickKey
5011
5125
  } = props;
5126
+ const {
5127
+ strings
5128
+ } = useMathInputI18n();
5129
+ const Keys = KeyConfigs(strings);
5012
5130
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5013
- keyConfig: KeyConfigs.SIN,
5131
+ keyConfig: Keys.SIN,
5014
5132
  onClickKey: onClickKey,
5015
5133
  coord: [0, 0]
5016
5134
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5017
- keyConfig: KeyConfigs.COS,
5135
+ keyConfig: Keys.COS,
5018
5136
  onClickKey: onClickKey,
5019
5137
  coord: [1, 0]
5020
5138
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5021
- keyConfig: KeyConfigs.TAN,
5139
+ keyConfig: Keys.TAN,
5022
5140
  onClickKey: onClickKey,
5023
5141
  coord: [2, 0]
5024
5142
  }));
@@ -5028,59 +5146,63 @@ function NumbersPage(props) {
5028
5146
  const {
5029
5147
  onClickKey
5030
5148
  } = props;
5149
+ const {
5150
+ strings
5151
+ } = useMathInputI18n();
5152
+ const Keys = KeyConfigs(strings);
5031
5153
  // These keys are arranged sequentially so that tabbing follows numerical order. This
5032
5154
  // allows us to visually mimic a keypad without affecting a11y. The visual order of the
5033
5155
  // keys in the keypad is determined by their coordinates, not their order in the DOM.
5034
5156
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5035
- keyConfig: KeyConfigs.NUM_1,
5157
+ keyConfig: Keys.NUM_1,
5036
5158
  onClickKey: onClickKey,
5037
5159
  coord: [0, 2]
5038
5160
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5039
- keyConfig: KeyConfigs.NUM_2,
5161
+ keyConfig: Keys.NUM_2,
5040
5162
  onClickKey: onClickKey,
5041
5163
  coord: [1, 2]
5042
5164
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5043
- keyConfig: KeyConfigs.NUM_3,
5165
+ keyConfig: Keys.NUM_3,
5044
5166
  onClickKey: onClickKey,
5045
5167
  coord: [2, 2]
5046
5168
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5047
- keyConfig: KeyConfigs.NUM_4,
5169
+ keyConfig: Keys.NUM_4,
5048
5170
  onClickKey: onClickKey,
5049
5171
  coord: [0, 1]
5050
5172
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5051
- keyConfig: KeyConfigs.NUM_5,
5173
+ keyConfig: Keys.NUM_5,
5052
5174
  onClickKey: onClickKey,
5053
5175
  coord: [1, 1]
5054
5176
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5055
- keyConfig: KeyConfigs.NUM_6,
5177
+ keyConfig: Keys.NUM_6,
5056
5178
  onClickKey: onClickKey,
5057
5179
  coord: [2, 1]
5058
5180
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5059
- keyConfig: KeyConfigs.NUM_7,
5181
+ keyConfig: Keys.NUM_7,
5060
5182
  onClickKey: onClickKey,
5061
5183
  coord: [0, 0]
5062
5184
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5063
- keyConfig: KeyConfigs.NUM_8,
5185
+ keyConfig: Keys.NUM_8,
5064
5186
  onClickKey: onClickKey,
5065
5187
  coord: [1, 0]
5066
5188
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5067
- keyConfig: KeyConfigs.NUM_9,
5189
+ keyConfig: Keys.NUM_9,
5068
5190
  onClickKey: onClickKey,
5069
5191
  coord: [2, 0]
5070
5192
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5071
- keyConfig: KeyConfigs.NUM_0,
5193
+ keyConfig: Keys.NUM_0,
5072
5194
  onClickKey: onClickKey,
5073
5195
  coord: [0, 3]
5074
5196
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5075
- keyConfig: KeyConfigs.DECIMAL,
5197
+ keyConfig: Keys.DECIMAL,
5076
5198
  onClickKey: onClickKey,
5077
5199
  coord: [1, 3]
5078
5200
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5079
- keyConfig: KeyConfigs.NEGATIVE,
5201
+ keyConfig: Keys.NEGATIVE,
5080
5202
  onClickKey: onClickKey,
5081
5203
  coord: [2, 3]
5082
5204
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5083
- keyConfig: KeyConfigs.PERCENT,
5205
+ keyConfig: Keys.PERCENT,
5084
5206
  onClickKey: onClickKey,
5085
5207
  coord: [3, 0],
5086
5208
  secondary: true
@@ -5095,56 +5217,60 @@ function OperatorsPage(props) {
5095
5217
  basicRelations,
5096
5218
  advancedRelations
5097
5219
  } = props;
5220
+ const {
5221
+ strings
5222
+ } = useMathInputI18n();
5223
+ const Keys = KeyConfigs(strings);
5098
5224
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, preAlgebra && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5099
- keyConfig: KeyConfigs.EXP_2,
5225
+ keyConfig: Keys.EXP_2,
5100
5226
  onClickKey: onClickKey,
5101
5227
  coord: [0, 0]
5102
5228
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5103
- keyConfig: KeyConfigs.EXP,
5229
+ keyConfig: Keys.EXP,
5104
5230
  onClickKey: onClickKey,
5105
5231
  coord: [1, 0]
5106
5232
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5107
- keyConfig: KeyConfigs.SQRT,
5233
+ keyConfig: Keys.SQRT,
5108
5234
  onClickKey: onClickKey,
5109
5235
  coord: [2, 0]
5110
5236
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5111
- keyConfig: KeyConfigs.RADICAL,
5237
+ keyConfig: Keys.RADICAL,
5112
5238
  onClickKey: onClickKey,
5113
5239
  coord: [3, 0]
5114
5240
  })), logarithms && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5115
- keyConfig: KeyConfigs.LOG,
5241
+ keyConfig: Keys.LOG,
5116
5242
  onClickKey: onClickKey,
5117
5243
  coord: [0, 1]
5118
5244
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5119
- keyConfig: KeyConfigs.LOG_N,
5245
+ keyConfig: Keys.LOG_N,
5120
5246
  onClickKey: onClickKey,
5121
5247
  coord: [1, 1]
5122
5248
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5123
- keyConfig: KeyConfigs.LN,
5249
+ keyConfig: Keys.LN,
5124
5250
  onClickKey: onClickKey,
5125
5251
  coord: [2, 1]
5126
5252
  })), basicRelations && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5127
- keyConfig: KeyConfigs.EQUAL,
5253
+ keyConfig: Keys.EQUAL,
5128
5254
  onClickKey: onClickKey,
5129
5255
  coord: [0, 2]
5130
5256
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5131
- keyConfig: KeyConfigs.LT,
5257
+ keyConfig: Keys.LT,
5132
5258
  onClickKey: onClickKey,
5133
5259
  coord: [1, 2]
5134
5260
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5135
- keyConfig: KeyConfigs.GT,
5261
+ keyConfig: Keys.GT,
5136
5262
  onClickKey: onClickKey,
5137
5263
  coord: [2, 2]
5138
5264
  })), advancedRelations && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5139
- keyConfig: KeyConfigs.NEQ,
5265
+ keyConfig: Keys.NEQ,
5140
5266
  onClickKey: onClickKey,
5141
5267
  coord: [0, 3]
5142
5268
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5143
- keyConfig: KeyConfigs.LEQ,
5269
+ keyConfig: Keys.LEQ,
5144
5270
  onClickKey: onClickKey,
5145
5271
  coord: [1, 3]
5146
5272
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5147
- keyConfig: KeyConfigs.GEQ,
5273
+ keyConfig: Keys.GEQ,
5148
5274
  onClickKey: onClickKey,
5149
5275
  coord: [2, 3]
5150
5276
  })));
@@ -5253,24 +5379,28 @@ function NavigationPad(props) {
5253
5379
  const {
5254
5380
  onClickKey
5255
5381
  } = props;
5382
+ const {
5383
+ strings
5384
+ } = useMathInputI18n();
5385
+ const Keys = KeyConfigs(strings);
5256
5386
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
5257
5387
  style: styles$2.container
5258
5388
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
5259
5389
  style: styles$2.grid
5260
5390
  }, /*#__PURE__*/React__namespace.createElement(NavigationButton, {
5261
- keyConfig: KeyConfigs.UP,
5391
+ keyConfig: Keys.UP,
5262
5392
  onClickKey: onClickKey,
5263
5393
  coord: [1, 0]
5264
5394
  }), /*#__PURE__*/React__namespace.createElement(NavigationButton, {
5265
- keyConfig: KeyConfigs.RIGHT,
5395
+ keyConfig: Keys.RIGHT,
5266
5396
  onClickKey: onClickKey,
5267
5397
  coord: [2, 1]
5268
5398
  }), /*#__PURE__*/React__namespace.createElement(NavigationButton, {
5269
- keyConfig: KeyConfigs.DOWN,
5399
+ keyConfig: Keys.DOWN,
5270
5400
  onClickKey: onClickKey,
5271
5401
  coord: [1, 2]
5272
5402
  }), /*#__PURE__*/React__namespace.createElement(NavigationButton, {
5273
- keyConfig: KeyConfigs.LEFT,
5403
+ keyConfig: Keys.LEFT,
5274
5404
  onClickKey: onClickKey,
5275
5405
  coord: [0, 1]
5276
5406
  }), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
@@ -5306,42 +5436,47 @@ function SharedKeys(props) {
5306
5436
  convertDotToTimes,
5307
5437
  selectedPage
5308
5438
  } = props;
5309
- const cursorKeyConfig = getCursorContextConfig(cursorContext);
5439
+ const {
5440
+ strings,
5441
+ locale
5442
+ } = useMathInputI18n();
5443
+ const cursorKeyConfig = getCursorContextConfig(strings, cursorContext);
5444
+ const Keys = KeyConfigs(strings);
5310
5445
 
5311
5446
  // Fraction position depends on the page
5312
5447
  const fractionCoord = selectedPage === "Numbers" || selectedPage === "Operators" ? [3, 1] : [3, 0];
5313
5448
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5314
- keyConfig: KeyConfigs.FRAC,
5449
+ keyConfig: Keys.FRAC,
5315
5450
  onClickKey: onClickKey,
5316
5451
  coord: fractionCoord,
5317
5452
  secondary: true
5318
5453
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5319
- keyConfig: KeyConfigs.PLUS,
5454
+ keyConfig: Keys.PLUS,
5320
5455
  onClickKey: onClickKey,
5321
5456
  coord: [4, 0],
5322
5457
  secondary: true
5323
5458
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5324
- keyConfig: KeyConfigs.MINUS,
5459
+ keyConfig: Keys.MINUS,
5325
5460
  onClickKey: onClickKey,
5326
5461
  coord: [5, 0],
5327
5462
  secondary: true
5328
5463
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5329
- keyConfig: convertDotToTimesByLocale(!!convertDotToTimes) ? KeyConfigs.TIMES : KeyConfigs.CDOT,
5464
+ keyConfig: convertDotToTimesByLocale(locale, !!convertDotToTimes) ? Keys.TIMES : Keys.CDOT,
5330
5465
  onClickKey: onClickKey,
5331
5466
  coord: [4, 1],
5332
5467
  secondary: true
5333
5468
  }), divisionKey && /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5334
- keyConfig: KeyConfigs.DIVIDE,
5469
+ keyConfig: Keys.DIVIDE,
5335
5470
  onClickKey: onClickKey,
5336
5471
  coord: [5, 1],
5337
5472
  secondary: true
5338
5473
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5339
- keyConfig: KeyConfigs.LEFT_PAREN,
5474
+ keyConfig: Keys.LEFT_PAREN,
5340
5475
  onClickKey: onClickKey,
5341
5476
  coord: [4, 2],
5342
5477
  secondary: true
5343
5478
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5344
- keyConfig: KeyConfigs.RIGHT_PAREN,
5479
+ keyConfig: Keys.RIGHT_PAREN,
5345
5480
  onClickKey: onClickKey,
5346
5481
  coord: [5, 2],
5347
5482
  secondary: true
@@ -5351,7 +5486,7 @@ function SharedKeys(props) {
5351
5486
  coord: [4, 3],
5352
5487
  secondary: true
5353
5488
  }), /*#__PURE__*/React__namespace.createElement(KeypadButton, {
5354
- keyConfig: KeyConfigs.BACKSPACE,
5489
+ keyConfig: Keys.BACKSPACE,
5355
5490
  onClickKey: onClickKey,
5356
5491
  coord: [5, 3],
5357
5492
  action: true
@@ -5584,10 +5719,11 @@ function processStyleType(style) {
5584
5719
  class TransitionChild extends React__namespace.Component {
5585
5720
  // Each 2-tuple in the queue represents two classnames: one to remove and
5586
5721
  // one to add (in that order).
5587
-
5722
+ classNameQueue;
5588
5723
  // We keep track of all of the current applied classes so that we can remove
5589
5724
  // them before a new transition starts in the case of the current transition
5590
5725
  // being interrupted.
5726
+ appliedClassNames;
5591
5727
  _isMounted = false;
5592
5728
 
5593
5729
  // The use of getDerivedStateFromProps here is to avoid an extra call to
@@ -6026,13 +6162,16 @@ exports.KeyConfigs = KeyConfigs;
6026
6162
  exports.KeypadContext = KeypadContext;
6027
6163
  exports.KeypadInput = MathInput;
6028
6164
  exports.KeypadType = KeypadType;
6165
+ exports.MathInputI18nContext = MathInputI18nContext;
6166
+ exports.MathInputI18nContextProvider = MathInputI18nContextProvider;
6029
6167
  exports.MobileKeypad = MobileKeypad;
6030
6168
  exports.StatefulKeypadContextProvider = StatefulKeypadContextProvider;
6031
6169
  exports.convertDotToTimesByLocale = convertDotToTimesByLocale;
6032
6170
  exports.createMathField = createMathField;
6033
6171
  exports.getCursorContext = getCursorContext;
6034
- exports.keyTranslator = keyToMathquillMap;
6172
+ exports.getKeyTranslator = getKeyTranslator;
6035
6173
  exports.keypadElementPropType = keypadElementPropType;
6036
6174
  exports.libVersion = libVersion;
6037
6175
  exports.mathQuillInstance = mathQuillInstance;
6176
+ exports.useMathInputI18n = useMathInputI18n;
6038
6177
  //# sourceMappingURL=index.js.map