@khanacademy/math-input 17.4.1 → 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/es/index.js CHANGED
@@ -1,11 +1,9 @@
1
1
  import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-core';
2
- import * as i18n from '@khanacademy/wonder-blocks-i18n';
3
- import { getDecimalSeparator, getLocale } from '@khanacademy/wonder-blocks-i18n';
4
2
  import { color } from '@khanacademy/wonder-blocks-tokens';
5
3
  import { entries } from '@khanacademy/wonder-stuff-core';
6
4
  import { StyleSheet, css } from 'aphrodite';
7
5
  import * as React from 'react';
8
- import { useState, useMemo, useEffect } from 'react';
6
+ import { useContext, useState, useMemo, useEffect } from 'react';
9
7
  import ReactDOM from 'react-dom';
10
8
  import { SpeechRuleEngine } from '@khanacademy/mathjax-renderer';
11
9
  import MathQuill from 'mathquill';
@@ -17,21 +15,19 @@ import PropTypes from 'prop-types';
17
15
 
18
16
  // This file is processed by a Rollup plugin (replace) to inject the production
19
17
  const libName = "@khanacademy/math-input";
20
- const libVersion = "17.4.1";
18
+ const libVersion = "18.0.0";
21
19
  addLibraryVersionToPerseusDebug(libName, libVersion);
22
20
 
23
21
  function _extends() {
24
22
  _extends = Object.assign ? Object.assign.bind() : function (target) {
25
23
  for (var i = 1; i < arguments.length; i++) {
26
24
  var source = arguments[i];
27
-
28
25
  for (var key in source) {
29
26
  if (Object.prototype.hasOwnProperty.call(source, key)) {
30
27
  target[key] = source[key];
31
28
  }
32
29
  }
33
30
  }
34
-
35
31
  return target;
36
32
  };
37
33
  return _extends.apply(this, arguments);
@@ -102,6 +98,117 @@ View.styles = StyleSheet.create({
102
98
  }
103
99
  });
104
100
 
101
+ /**
102
+ * The translated strings that are used to render the Math Input.
103
+ */
104
+
105
+ /**
106
+ * Mock strings for the Math Input package, to be used for tests and Storybook.
107
+ */
108
+ const mockStrings = {
109
+ mathInputBox: "Math input box",
110
+ fingerTap: "Tap with one or two fingers to open keyboard",
111
+ before: ({
112
+ obj
113
+ }) => `before ${obj}`,
114
+ after: ({
115
+ obj
116
+ }) => `after ${obj}`,
117
+ "beginning of": ({
118
+ obj
119
+ }) => `beginning of ${obj}`,
120
+ "end of": ({
121
+ obj
122
+ }) => `end of ${obj}`,
123
+ Baseline: "Baseline",
124
+ Superscript: "Superscript",
125
+ selected: ({
126
+ obj
127
+ }) => `${obj} selected`,
128
+ "no answer": "no answer",
129
+ "nothing selected": "nothing selected",
130
+ "nothing to the right": "nothing to the right",
131
+ "nothing to the left": "nothing to the left",
132
+ "block is empty": "block is empty",
133
+ "nothing above": "nothing above",
134
+ labelValue: ({
135
+ label,
136
+ value
137
+ }) => `${label}: ${value}`,
138
+ plus: "Plus",
139
+ minus: "Minus",
140
+ negative: "Negative",
141
+ times: "Multiply",
142
+ divide: "Divide",
143
+ decimal: "Decimal",
144
+ percent: "Percent",
145
+ cdot: "Multiply",
146
+ equalsSign: "Equals sign",
147
+ notEqualsSign: "Not-equals sign",
148
+ greaterThanSign: "Greater than sign",
149
+ lessThanSign: "Less than sign",
150
+ greaterThanOrEqualToSign: "Greater than or equal to sign",
151
+ lessThanOrEqualSign: "Less than or equal to sign",
152
+ fractionExpressionInNumerator: "Fraction, with current expression in numerator",
153
+ fractionExcludingExpression: "Fraction, excluding the current expression",
154
+ customExponent: "Custom exponent",
155
+ square: "Square",
156
+ cube: "Cube",
157
+ squareRoot: "Square root",
158
+ cubeRoot: "Cube root",
159
+ radicalWithCustomRoot: "Radical with custom root",
160
+ leftParenthesis: "Left parenthesis",
161
+ rightParenthesis: "Right parenthesis",
162
+ naturalLog: "Natural logarithm",
163
+ logBase10: "Logarithm with base 10",
164
+ logCustomBase: "Logarithm with custom base",
165
+ sine: "Sine",
166
+ cosine: "Cosine",
167
+ tangent: "Tangent",
168
+ pi: "Pi",
169
+ theta: "Theta",
170
+ upArrow: "Up arrow",
171
+ rightArrow: "Right arrow",
172
+ downArrow: "Down arrow",
173
+ leftArrow: "Left arrow",
174
+ navOutOfParentheses: "Navigate right out of a set of parentheses",
175
+ navOutOfExponent: "Navigate right out of an exponent",
176
+ navOutOfBase: "Navigate right out of a base",
177
+ navIntoNumerator: "Navigate right into the numerator of a fraction",
178
+ navOutOfNumeratorIntoDenominator: "Navigate right out of the numerator and into the denominator",
179
+ navOutOfDenominator: "Navigate right out of the denominator of a fraction",
180
+ delete: "Delete",
181
+ dismiss: "Dismiss"
182
+ };
183
+
184
+ /**
185
+ * MathInputI18nContext provides a way to set the strings and locale that are
186
+ * used inside the Math Input package.
187
+ *
188
+ */
189
+ // @ts-expect-error - TS2322 - Type 'Context<{ strings: {}; locale: string; }>' is not assignable to type 'Context<I18nContextType>'.
190
+ const MathInputI18nContext = /*#__PURE__*/React.createContext(process.env.NODE_ENV === "test" || process.env.STORYBOOK ? {
191
+ strings: mockStrings,
192
+ locale: "en"
193
+ } :
194
+ // We want to return null here, not an empty object, so that we
195
+ // are will throw an error when attempting to access the
196
+ // undefined locale or strings, making it easier to debug.
197
+ null);
198
+ function MathInputI18nContextProvider({
199
+ children,
200
+ strings,
201
+ locale
202
+ }) {
203
+ return /*#__PURE__*/React.createElement(MathInputI18nContext.Provider, {
204
+ value: {
205
+ strings,
206
+ locale
207
+ }
208
+ }, children);
209
+ }
210
+ const useMathInputI18n = () => useContext(MathInputI18nContext);
211
+
105
212
  /**
106
213
  * KeypadContext provides a way to the Keypad and Perseus Renderers to
107
214
  * communicate.
@@ -347,13 +454,34 @@ const DecimalSeparator = {
347
454
  PERIOD: "."
348
455
  };
349
456
 
350
- // NOTES(kevinb):
351
- // - In order to get the correct decimal separator for the current locale,
352
- // the locale must bet set using `setLocale(kaLocale)` which can be
353
- // imported from wonder-blocks-i18n.
354
- // - Some languages/locales use different decimal separators than the ones
355
- // listed here. Much of the Arab world uses U+066C.
356
- const decimalSeparator = getDecimalSeparator() === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
457
+ /**
458
+ * Get the character used for separating decimals.
459
+ */
460
+ const getDecimalSeparator = locale => {
461
+ var _match$;
462
+ let separator = DecimalSeparator.PERIOD;
463
+ switch (locale) {
464
+ // TODO(somewhatabstract): Remove this when Chrome supports the `ka`
465
+ // locale properly.
466
+ // https://github.com/formatjs/formatjs/issues/1526#issuecomment-559891201
467
+ //
468
+ // Supported locales in Chrome:
469
+ // https://source.chromium.org/chromium/chromium/src/+/master:third_party/icu/scripts/chrome_ui_languages.list
470
+ case "ka":
471
+ separator = ",";
472
+ break;
473
+ default:
474
+ const numberWithDecimalSeparator = 1.1;
475
+ // TODO(FEI-3647): Update to use .formatToParts() once we no longer have to
476
+ // support Safari 12.
477
+ const match = new Intl.NumberFormat(locale).format(numberWithDecimalSeparator)
478
+ // 0x661 is ARABIC-INDIC DIGIT ONE
479
+ // 0x6F1 is EXTENDED ARABIC-INDIC DIGIT ONE
480
+ .match(/[^\d\u0661\u06F1]/);
481
+ separator = (_match$ = match == null ? void 0 : match[0]) != null ? _match$ : ".";
482
+ }
483
+ return separator === "," ? DecimalSeparator.COMMA : DecimalSeparator.PERIOD;
484
+ };
357
485
  const CDOT_ONLY = ["az", "cs", "da", "de", "hu", "hy", "kk", "ky", "lt", "lv", "nb", "sk", "sr", "sv", "uz"];
358
486
  const TIMES_ONLY = ["fr", "tr", "pt-pt"];
359
487
 
@@ -368,8 +496,7 @@ const TIMES_ONLY = ["fr", "tr", "pt-pt"];
368
496
  * @param {boolean} convertDotToTimes - the setting set by content creators
369
497
  * @returns {boolean} - true to convert to × (TIMES), false to use · (CDOT)
370
498
  */
371
- function convertDotToTimesByLocale(convertDotToTimes) {
372
- const locale = getLocale();
499
+ function convertDotToTimesByLocale(locale, convertDotToTimes) {
373
500
  if (CDOT_ONLY.includes(locale)) {
374
501
  return false;
375
502
  }
@@ -385,39 +512,6 @@ function convertDotToTimesByLocale(convertDotToTimes) {
385
512
  const inJest = typeof process !== "undefined" && !!((_process = process) != null && (_process = _process.env) != null && _process.JEST_WORKER_ID);
386
513
  // Explicitly checking for undefined because Cypress throws an error
387
514
 
388
- const mathQuillStrings = {
389
- mathInputBox: i18n._("Math input box"),
390
- ariaStaticStringsMap: {
391
- before: obj => i18n._("before %(obj)s", {
392
- obj
393
- }),
394
- after: obj => i18n._("after %(obj)s", {
395
- obj
396
- }),
397
- "beginning of": obj => i18n._("beginning of %(obj)s", {
398
- obj
399
- }),
400
- "end of": obj => i18n._("end of %(obj)s", {
401
- obj
402
- }),
403
- Baseline: i18n._("Baseline"),
404
- Superscript: i18n._("Superscript"),
405
- selected: obj => i18n._("%(obj)s selected", {
406
- obj
407
- }),
408
- "no answer": i18n._("no answer"),
409
- "nothing selected": i18n._("nothing selected"),
410
- "nothing to the right": i18n._("nothing to the right"),
411
- "nothing to the left": i18n._("nothing to the left"),
412
- "block is empty": i18n._("block is empty"),
413
- "nothing above": i18n._("nothing above"),
414
- labelValue: (label, value) => i18n._("%(label)s: %(value)s", {
415
- label,
416
- value
417
- })
418
- }
419
- };
420
-
421
515
  // We only need one MathQuill instance (referred to as MQ in the docs)
422
516
  // and that contains some MQ constants and the MathField constructor
423
517
  const mathQuillInstance = MathQuill.getInterface(3);
@@ -463,10 +557,38 @@ const createBaseConfig = () => ({
463
557
  * This allows callers to do minimal configuration as only configs
464
558
  * that vary from the default need to be provided.
465
559
  */
466
- function createMathField(container, configCallback) {
560
+ function createMathField(container, strings, configCallback) {
467
561
  const baseConfig = createBaseConfig();
468
562
  const config = configCallback ? configCallback(baseConfig) : baseConfig;
469
- const mathField = mathQuillInstance.MathField(container, config).setAriaLabel(mathQuillStrings.mathInputBox).setAriaStringsOverrideMap(mathQuillStrings.ariaStaticStringsMap);
563
+ const mathField = mathQuillInstance.MathField(container, config).setAriaLabel(strings.mathInputBox).setAriaStringsOverrideMap({
564
+ before: obj => strings.before({
565
+ obj
566
+ }),
567
+ after: obj => strings.after({
568
+ obj
569
+ }),
570
+ "beginning of": obj => strings["beginning of"]({
571
+ obj
572
+ }),
573
+ "end of": obj => strings["end of"]({
574
+ obj
575
+ }),
576
+ Baseline: strings.Baseline,
577
+ Superscript: strings.Superscript,
578
+ selected: obj => strings.selected({
579
+ obj
580
+ }),
581
+ "no answer": strings["no answer"],
582
+ "nothing selected": strings["nothing selected"],
583
+ "nothing to the right": strings["nothing to the right"],
584
+ "nothing to the left": strings["nothing to the left"],
585
+ "block is empty": strings["block is empty"],
586
+ "nothing above": strings["nothing above"],
587
+ labelValue: (label, value) => strings.labelValue({
588
+ label,
589
+ value
590
+ })
591
+ });
470
592
 
471
593
  // We should avoid running SpeechRuleEngine.setup() in Jest. It makes an
472
594
  // HTTP request to fetch non-english speech rules, and cannot be easily
@@ -1115,7 +1237,7 @@ function buildNormalFunctionCallback(command) {
1115
1237
  mathField.keystroke("Left");
1116
1238
  };
1117
1239
  }
1118
- const keyToMathquillMap = {
1240
+ const getKeyTranslator = locale => ({
1119
1241
  EXP: handleExponent,
1120
1242
  EXP_2: handleExponent,
1121
1243
  EXP_3: handleExponent,
@@ -1133,7 +1255,7 @@ const keyToMathquillMap = {
1133
1255
  COS: buildNormalFunctionCallback("cos"),
1134
1256
  TAN: buildNormalFunctionCallback("tan"),
1135
1257
  CDOT: buildGenericCallback("\\cdot"),
1136
- DECIMAL: buildGenericCallback(decimalSeparator),
1258
+ DECIMAL: buildGenericCallback(getDecimalSeparator(locale)),
1137
1259
  DIVIDE: buildGenericCallback("\\div"),
1138
1260
  EQUAL: buildGenericCallback("="),
1139
1261
  GEQ: buildGenericCallback("\\geq"),
@@ -1272,16 +1394,6 @@ const keyToMathquillMap = {
1272
1394
  X: buildGenericCallback("X"),
1273
1395
  Y: buildGenericCallback("Y"),
1274
1396
  Z: buildGenericCallback("Z")
1275
- };
1276
-
1277
- const mobileKeyTranslator = _extends({}, keyToMathquillMap, {
1278
- // note(Matthew): our mobile backspace logic is really complicated
1279
- // and for some reason doesn't really work in the desktop experience.
1280
- // So we default to the basic backspace functionality in the
1281
- // key translator and overwrite it with the complicated logic here
1282
- // until we can unify the experiences (if we even want to).
1283
- // https://khanacademy.atlassian.net/browse/LC-906
1284
- BACKSPACE: handleBackspace
1285
1397
  });
1286
1398
 
1287
1399
  /**
@@ -1290,11 +1402,12 @@ const mobileKeyTranslator = _extends({}, keyToMathquillMap, {
1290
1402
  * from MathQuill changes.
1291
1403
  */
1292
1404
  class MathWrapper {
1293
- constructor(element, callbacks = {}) {
1405
+ constructor(element, strings, locale, callbacks = {}) {
1294
1406
  this.mathField = void 0;
1295
1407
  // MathQuill MathField input
1296
1408
  this.callbacks = void 0;
1297
- this.mathField = createMathField(element, () => {
1409
+ this.mobileKeyTranslator = void 0;
1410
+ this.mathField = createMathField(element, strings, () => {
1298
1411
  return {
1299
1412
  // use a span instead of a textarea so that we don't bring up the
1300
1413
  // native keyboard on mobile when selecting the input
@@ -1304,6 +1417,15 @@ class MathWrapper {
1304
1417
  };
1305
1418
  });
1306
1419
  this.callbacks = callbacks;
1420
+ this.mobileKeyTranslator = _extends({}, getKeyTranslator(locale), {
1421
+ // note(Matthew): our mobile backspace logic is really complicated
1422
+ // and for some reason doesn't really work in the desktop experience.
1423
+ // So we default to the basic backspace functionality in the
1424
+ // key translator and overwrite it with the complicated logic here
1425
+ // until we can unify the experiences (if we even want to).
1426
+ // https://khanacademy.atlassian.net/browse/LC-906
1427
+ BACKSPACE: handleBackspace
1428
+ });
1307
1429
  }
1308
1430
  focus() {
1309
1431
  // HACK(charlie): We shouldn't reaching into MathQuill internals like
@@ -1329,7 +1451,7 @@ class MathWrapper {
1329
1451
  */
1330
1452
  pressKey(key) {
1331
1453
  const cursor = this.getCursor();
1332
- const translator = mobileKeyTranslator[key];
1454
+ const translator = this.mobileKeyTranslator[key];
1333
1455
  if (translator) {
1334
1456
  translator(this.mathField, key);
1335
1457
  }
@@ -2057,7 +2179,7 @@ class MathInput extends React.Component {
2057
2179
  }
2058
2180
  componentDidMount() {
2059
2181
  this._isMounted = true;
2060
- this.mathField = new MathWrapper(this._mathContainer, {
2182
+ this.mathField = new MathWrapper(this._mathContainer, this.context.strings, this.context.locale, {
2061
2183
  onCursorMove: cursor => {
2062
2184
  // TODO(charlie): It's not great that there is so much coupling
2063
2185
  // between this keypad and the input behavior. We should wrap
@@ -2215,7 +2337,7 @@ class MathInput extends React.Component {
2215
2337
  // keyboard appear. It should only require one finger, which is how iOS works.
2216
2338
  // TODO(diedra): Fix the bug that is causing Android to require a two finger tap
2217
2339
  // to the open the keyboard, and then remove the second half of this label.
2218
- const ariaLabel = mathQuillStrings.mathInputBox + " " + i18n._("Tap with one or two fingers to open keyboard");
2340
+ const ariaLabel = this.context.strings.mathInputBox + " " + this.context.strings.fingerTap;
2219
2341
  return /*#__PURE__*/React.createElement(KeypadContext.Consumer, null, ({
2220
2342
  keypadActive,
2221
2343
  setKeypadActive
@@ -2257,10 +2379,12 @@ class MathInput extends React.Component {
2257
2379
  }))));
2258
2380
  }
2259
2381
  }
2382
+ MathInput.contextType = MathInputI18nContext;
2260
2383
  MathInput.defaultProps = {
2261
2384
  style: {},
2262
2385
  value: ""
2263
2386
  };
2387
+ MathInput.contextType = MathInputI18nContext;
2264
2388
  const fontSizePt = 18;
2265
2389
  const inputMaxWidth = 128;
2266
2390
 
@@ -2551,6 +2675,10 @@ function Tabbar(props) {
2551
2675
  })));
2552
2676
  }
2553
2677
 
2678
+ /**
2679
+ * This file contains configuration settings for the buttons in the keypad.
2680
+ */
2681
+
2554
2682
  const getDefaultOperatorFields = ({
2555
2683
  key,
2556
2684
  keyType: _keyType = "OPERATOR",
@@ -2590,38 +2718,32 @@ const getDefaultNumberFields = ({
2590
2718
  data: _data3
2591
2719
  }
2592
2720
  });
2593
- const KeyConfigs = {
2721
+ const KeyConfigs = strings => ({
2594
2722
  // Basic math
2595
2723
  PLUS: _extends({}, getDefaultOperatorFields({
2596
2724
  key: "PLUS",
2597
- // I18N: A label for a 'plus' sign.
2598
- ariaLabel: i18n._("Plus")
2725
+ ariaLabel: strings.plus
2599
2726
  })),
2600
2727
  MINUS: _extends({}, getDefaultOperatorFields({
2601
2728
  key: "MINUS",
2602
- // I18N: A label for a 'minus' sign.
2603
- ariaLabel: i18n._("Minus")
2729
+ ariaLabel: strings.minus
2604
2730
  })),
2605
2731
  NEGATIVE: _extends({}, getDefaultOperatorFields({
2606
2732
  key: "NEGATIVE",
2607
- // I18N: A label for a 'negative' sign.
2608
- ariaLabel: i18n._("Negative")
2733
+ ariaLabel: strings.negative
2609
2734
  })),
2610
2735
  TIMES: _extends({}, getDefaultOperatorFields({
2611
2736
  key: "TIMES",
2612
- // I18N: A label for a 'multiply' sign.
2613
- ariaLabel: i18n._("Multiply")
2737
+ ariaLabel: strings.times
2614
2738
  })),
2615
2739
  DIVIDE: _extends({}, getDefaultOperatorFields({
2616
2740
  key: "DIVIDE",
2617
- // I18N: A label for a 'divide' sign.
2618
- ariaLabel: i18n._("Divide")
2741
+ ariaLabel: strings.divide
2619
2742
  })),
2620
2743
  DECIMAL: _extends({}, getDefaultOperatorFields({
2621
2744
  key: "DECIMAL",
2622
2745
  keyType: "VALUE",
2623
- // I18N: A label for a 'decimal' sign (represented as '.' or ',').
2624
- ariaLabel: i18n._("Decimal")
2746
+ ariaLabel: strings.decimal
2625
2747
  })),
2626
2748
  PERIOD: _extends({}, getDefaultOperatorFields({
2627
2749
  key: "PERIOD",
@@ -2630,162 +2752,116 @@ const KeyConfigs = {
2630
2752
  })),
2631
2753
  PERCENT: _extends({}, getDefaultOperatorFields({
2632
2754
  key: "PERCENT",
2633
- // I18N: A label for a 'percent' sign (represented as '%').
2634
- ariaLabel: i18n._("Percent")
2755
+ ariaLabel: strings.percent
2635
2756
  })),
2636
2757
  CDOT: _extends({}, getDefaultOperatorFields({
2637
2758
  key: "CDOT",
2638
- // I18N: A label for a 'centered dot' multiplication sign (represented as '⋅').
2639
- ariaLabel: i18n._("Multiply")
2759
+ ariaLabel: strings.cdot
2640
2760
  })),
2641
2761
  EQUAL: _extends({}, getDefaultOperatorFields({
2642
2762
  key: "EQUAL",
2643
- // I18N: A label for an 'equals' sign (represented as '=').
2644
- ariaLabel: i18n._("Equals sign")
2763
+ ariaLabel: strings.equalsSign
2645
2764
  })),
2646
2765
  NEQ: _extends({}, getDefaultOperatorFields({
2647
2766
  key: "NEQ",
2648
- // I18N: A label for a 'not-equals' sign (represented as '≠').
2649
- ariaLabel: i18n._("Not-equals sign")
2767
+ ariaLabel: strings.notEqualsSign
2650
2768
  })),
2651
2769
  GT: _extends({}, getDefaultOperatorFields({
2652
2770
  key: "GT",
2653
- // I18N: A label for a 'greater than' sign (represented as '>').
2654
- ariaLabel: i18n._("Greater than sign")
2771
+ ariaLabel: strings.greaterThanSign
2655
2772
  })),
2656
2773
  LT: _extends({}, getDefaultOperatorFields({
2657
2774
  key: "LT",
2658
- // I18N: A label for a 'less than' sign (represented as '<').
2659
- ariaLabel: i18n._("Less than sign")
2775
+ ariaLabel: strings.lessThanSign
2660
2776
  })),
2661
2777
  GEQ: _extends({}, getDefaultOperatorFields({
2662
2778
  key: "GEQ",
2663
- // I18N: A label for a 'greater than or equal to' sign (represented as '≥').
2664
- ariaLabel: i18n._("Greater than or equal to sign")
2779
+ ariaLabel: strings.greaterThanOrEqualToSign
2665
2780
  })),
2666
2781
  LEQ: _extends({}, getDefaultOperatorFields({
2667
2782
  key: "LEQ",
2668
- // I18N: A label for a 'less than or equal to' sign (represented as '≤').
2669
- ariaLabel: i18n._("Less than or equal to sign")
2783
+ ariaLabel: strings.lessThanOrEqualSign
2670
2784
  })),
2671
2785
  // mobile native
2672
2786
  FRAC_INCLUSIVE: _extends({}, getDefaultOperatorFields({
2673
2787
  key: "FRAC_INCLUSIVE",
2674
- // I18N: A label for a button that creates a new fraction and puts the
2675
- // current expression in the numerator of that fraction.
2676
- ariaLabel: i18n._("Fraction, with current expression in numerator")
2788
+ ariaLabel: strings.fractionExpressionInNumerator
2677
2789
  })),
2678
2790
  // mobile native
2679
2791
  FRAC_EXCLUSIVE: _extends({}, getDefaultOperatorFields({
2680
2792
  key: "FRAC_EXCLUSIVE",
2681
- // I18N: A label for a button that creates a new fraction next to the
2682
- // cursor.
2683
- ariaLabel: i18n._("Fraction, excluding the current expression")
2793
+ ariaLabel: strings.fractionExcludingExpression
2684
2794
  })),
2685
2795
  // mobile web
2686
2796
  FRAC: _extends({}, getDefaultOperatorFields({
2687
2797
  key: "FRAC",
2688
- // I18N: A label for a button that creates a new fraction next to the
2689
- // cursor.
2690
- ariaLabel: i18n._("Fraction, excluding the current expression")
2798
+ ariaLabel: strings.fractionExcludingExpression
2691
2799
  })),
2692
2800
  EXP: _extends({}, getDefaultOperatorFields({
2693
2801
  key: "EXP",
2694
- // I18N: A label for a button that will allow the user to input a
2695
- // custom exponent.
2696
- ariaLabel: i18n._("Custom exponent")
2802
+ ariaLabel: strings.customExponent
2697
2803
  })),
2698
2804
  EXP_2: _extends({}, getDefaultOperatorFields({
2699
2805
  key: "EXP_2",
2700
- // I18N: A label for a button that will square (take to the second
2701
- // power) some math.
2702
- ariaLabel: i18n._("Square")
2806
+ ariaLabel: strings.square
2703
2807
  })),
2704
2808
  EXP_3: _extends({}, getDefaultOperatorFields({
2705
2809
  key: "EXP_3",
2706
- // I18N: A label for a button that will cube (take to the third power)
2707
- // some math.
2708
- ariaLabel: i18n._("Cube")
2810
+ ariaLabel: strings.cube
2709
2811
  })),
2710
2812
  SQRT: _extends({}, getDefaultOperatorFields({
2711
2813
  key: "SQRT",
2712
- // I18N: A label for a button that will allow the user to input a
2713
- // square root.
2714
- ariaLabel: i18n._("Square root")
2814
+ ariaLabel: strings.squareRoot
2715
2815
  })),
2716
2816
  CUBE_ROOT: _extends({}, getDefaultOperatorFields({
2717
2817
  key: "CUBE_ROOT",
2718
- // I18N: A label for a button that will allow the user to input a
2719
- // cube root.
2720
- ariaLabel: i18n._("Cube root")
2818
+ ariaLabel: strings.cubeRoot
2721
2819
  })),
2722
2820
  RADICAL: _extends({}, getDefaultOperatorFields({
2723
2821
  key: "RADICAL",
2724
- // I18N: A label for a button that will allow the user to input a
2725
- // radical with a custom root.
2726
- ariaLabel: i18n._("Radical with custom root")
2822
+ ariaLabel: strings.radicalWithCustomRoot
2727
2823
  })),
2728
2824
  LEFT_PAREN: _extends({}, getDefaultOperatorFields({
2729
2825
  key: "LEFT_PAREN",
2730
- // I18N: A label for a button that will allow the user to input a
2731
- // left parenthesis (i.e. '(')
2732
- ariaLabel: i18n._("Left parenthesis")
2826
+ ariaLabel: strings.leftParenthesis
2733
2827
  })),
2734
2828
  RIGHT_PAREN: _extends({}, getDefaultOperatorFields({
2735
2829
  key: "RIGHT_PAREN",
2736
- // I18N: A label for a button that will allow the user to input a
2737
- // right parenthesis (i.e. ')')
2738
- ariaLabel: i18n._("Right parenthesis")
2830
+ ariaLabel: strings.rightParenthesis
2739
2831
  })),
2740
2832
  LN: _extends({}, getDefaultOperatorFields({
2741
2833
  key: "LN",
2742
- // I18N: A label for a button that will allow the user to input a
2743
- // natural logarithm.
2744
- ariaLabel: i18n._("Natural logarithm")
2834
+ ariaLabel: strings.naturalLog
2745
2835
  })),
2746
2836
  LOG: _extends({}, getDefaultOperatorFields({
2747
2837
  key: "LOG",
2748
- // I18N: A label for a button that will allow the user to input a
2749
- // logarithm with base 10.
2750
- ariaLabel: i18n._("Logarithm with base 10")
2838
+ ariaLabel: strings.logBase10
2751
2839
  })),
2752
2840
  LOG_N: _extends({}, getDefaultOperatorFields({
2753
2841
  key: "LOG_N",
2754
- // I18N: A label for a button that will allow the user to input a
2755
- // logarithm with a custom base.
2756
- ariaLabel: i18n._("Logarithm with custom base")
2842
+ ariaLabel: strings.logCustomBase
2757
2843
  })),
2758
2844
  SIN: _extends({}, getDefaultOperatorFields({
2759
2845
  key: "SIN",
2760
- // I18N: A label for a button that will allow the user to input a
2761
- // sine function.
2762
- ariaLabel: i18n._("Sine")
2846
+ ariaLabel: strings.sine
2763
2847
  })),
2764
2848
  COS: _extends({}, getDefaultOperatorFields({
2765
2849
  key: "COS",
2766
- // I18N: A label for a button that will allow the user to input a
2767
- // cosine function.
2768
- ariaLabel: i18n._("Cosine")
2850
+ ariaLabel: strings.cosine
2769
2851
  })),
2770
2852
  TAN: _extends({}, getDefaultOperatorFields({
2771
2853
  key: "TAN",
2772
- // I18N: A label for a button that will allow the user to input a
2773
- // tangent function.
2774
- ariaLabel: i18n._("Tangent")
2854
+ ariaLabel: strings.tangent
2775
2855
  })),
2776
2856
  PI: _extends({}, getDefaultValueFields({
2777
2857
  key: "PI",
2778
2858
  data: "\\pi",
2779
- // I18N: A label for a button that will allow the user to input the
2780
- // mathematical constant pi (i.e., π)
2781
- ariaLabel: i18n._("Pi")
2859
+ ariaLabel: strings.pi
2782
2860
  })),
2783
2861
  THETA: _extends({}, getDefaultValueFields({
2784
2862
  key: "THETA",
2785
2863
  data: "\\theta",
2786
- // I18N: A label for a button that will allow the user to input the
2787
- // mathematical constant theta (i.e., θ)
2788
- ariaLabel: i18n._("Theta")
2864
+ ariaLabel: strings.theta
2789
2865
  })),
2790
2866
  NOOP: _extends({}, getDefaultOperatorFields({
2791
2867
  key: "NOOP",
@@ -2795,64 +2871,63 @@ const KeyConfigs = {
2795
2871
  UP: _extends({}, getDefaultOperatorFields({
2796
2872
  key: "UP",
2797
2873
  keyType: "INPUT_NAVIGATION",
2798
- ariaLabel: i18n._("Up arrow")
2874
+ ariaLabel: strings.upArrow
2799
2875
  })),
2800
2876
  RIGHT: _extends({}, getDefaultOperatorFields({
2801
2877
  key: "RIGHT",
2802
2878
  keyType: "INPUT_NAVIGATION",
2803
- ariaLabel: i18n._("Right arrow")
2879
+ ariaLabel: strings.rightArrow
2804
2880
  })),
2805
2881
  DOWN: _extends({}, getDefaultOperatorFields({
2806
2882
  key: "DOWN",
2807
2883
  keyType: "INPUT_NAVIGATION",
2808
- ariaLabel: i18n._("Down arrow")
2884
+ ariaLabel: strings.downArrow
2809
2885
  })),
2810
2886
  LEFT: _extends({}, getDefaultOperatorFields({
2811
2887
  key: "LEFT",
2812
2888
  keyType: "INPUT_NAVIGATION",
2813
- ariaLabel: i18n._("Left arrow")
2889
+ ariaLabel: strings.leftArrow
2814
2890
  })),
2815
2891
  JUMP_OUT_PARENTHESES: _extends({}, getDefaultOperatorFields({
2816
2892
  key: "JUMP_OUT_PARENTHESES",
2817
2893
  keyType: "INPUT_NAVIGATION",
2818
- ariaLabel: i18n._("Navigate right out of a set of parentheses")
2894
+ ariaLabel: strings.navOutOfParentheses
2819
2895
  })),
2820
2896
  JUMP_OUT_EXPONENT: _extends({}, getDefaultOperatorFields({
2821
2897
  key: "JUMP_OUT_EXPONENT",
2822
2898
  keyType: "INPUT_NAVIGATION",
2823
- ariaLabel: i18n._("Navigate right out of an exponent")
2899
+ ariaLabel: strings.navOutOfExponent
2824
2900
  })),
2825
2901
  JUMP_OUT_BASE: _extends({}, getDefaultOperatorFields({
2826
2902
  key: "JUMP_OUT_BASE",
2827
2903
  keyType: "INPUT_NAVIGATION",
2828
- ariaLabel: i18n._("Navigate right out of a base")
2904
+ ariaLabel: strings.navOutOfBase
2829
2905
  })),
2830
2906
  JUMP_INTO_NUMERATOR: _extends({}, getDefaultOperatorFields({
2831
2907
  key: "JUMP_INTO_NUMERATOR",
2832
2908
  keyType: "INPUT_NAVIGATION",
2833
- ariaLabel: i18n._("Navigate right into the numerator of a fraction")
2909
+ ariaLabel: strings.navIntoNumerator
2834
2910
  })),
2835
2911
  JUMP_OUT_NUMERATOR: _extends({}, getDefaultOperatorFields({
2836
2912
  key: "JUMP_OUT_NUMERATOR",
2837
2913
  keyType: "INPUT_NAVIGATION",
2838
- ariaLabel: i18n._("Navigate right out of the numerator and into the denominator")
2914
+ ariaLabel: strings.navOutOfNumeratorIntoDenominator
2839
2915
  })),
2840
2916
  JUMP_OUT_DENOMINATOR: _extends({}, getDefaultOperatorFields({
2841
2917
  key: "JUMP_OUT_DENOMINATOR",
2842
2918
  keyType: "INPUT_NAVIGATION",
2843
- ariaLabel: i18n._("Navigate right out of the denominator of a fraction")
2919
+ ariaLabel: strings.navOutOfDenominator
2844
2920
  })),
2845
2921
  BACKSPACE: _extends({}, getDefaultOperatorFields({
2846
2922
  key: "BACKSPACE",
2847
2923
  keyType: "INPUT_NAVIGATION",
2848
- ariaLabel: i18n._("Delete")
2924
+ ariaLabel: strings.delete
2849
2925
  })),
2850
2926
  // Keypad navigation
2851
2927
  DISMISS: _extends({}, getDefaultOperatorFields({
2852
2928
  key: "DISMISS",
2853
2929
  keyType: "KEYPAD_NAVIGATION",
2854
- // I18N: A label for a button that will dismiss/hide a keypad.
2855
- ariaLabel: i18n._("Dismiss")
2930
+ ariaLabel: strings.dismiss
2856
2931
  })),
2857
2932
  // TODO(charlie): Use the numeral color for the 'Many' key.
2858
2933
  MANY: _extends({}, getDefaultOperatorFields({
@@ -3059,7 +3134,7 @@ const KeyConfigs = {
3059
3134
  LOG_B: _extends({}, getDefaultValueFields({
3060
3135
  key: "LOG_B"
3061
3136
  }))
3062
- };
3137
+ });
3063
3138
 
3064
3139
  /*
3065
3140
  The SVGs in this file should be treated as binary assets. If, in the future,
@@ -3076,6 +3151,9 @@ no copying and pasting is necessary.
3076
3151
  function ButtonAsset({
3077
3152
  id
3078
3153
  }) {
3154
+ const {
3155
+ locale
3156
+ } = useMathInputI18n();
3079
3157
  switch (id) {
3080
3158
  case "NUM_0":
3081
3159
  return /*#__PURE__*/React.createElement("svg", {
@@ -3191,7 +3269,7 @@ function ButtonAsset({
3191
3269
  case "PERIOD":
3192
3270
  // Different locales use different symbols for the decimal separator
3193
3271
  // (, vs .)
3194
- if (id === "DECIMAL" && decimalSeparator === DecimalSeparator.COMMA) {
3272
+ if (id === "DECIMAL" && getDecimalSeparator(locale) === DecimalSeparator.COMMA) {
3195
3273
  // comma decimal separator
3196
3274
  return /*#__PURE__*/React.createElement("svg", {
3197
3275
  width: "40",
@@ -3199,7 +3277,7 @@ function ButtonAsset({
3199
3277
  viewBox: "0 0 32 32",
3200
3278
  fill: "none",
3201
3279
  xmlns: "http://www.w3.org/2000/svg",
3202
- "data-test-id": "comma-decimal"
3280
+ "data-testid": "comma-decimal"
3203
3281
  }, /*#__PURE__*/React.createElement("path", {
3204
3282
  d: "M11.5559 25.3544C11.8679 24.661 12.1799 23.933 12.4919 23.1704C12.8039 22.425 13.0986 21.6884 13.3759 20.9604C13.6706 20.2324 13.9219 19.5737 14.1299 18.9844H16.6259L16.7299 19.2704C16.4526 19.877 16.1232 20.5357 15.7419 21.2464C15.3606 21.9397 14.9619 22.633 14.5459 23.3264C14.1299 24.037 13.7139 24.713 13.2979 25.3544H11.5559Z",
3205
3283
  fill: "#21242C"
@@ -3212,7 +3290,7 @@ function ButtonAsset({
3212
3290
  viewBox: "0 0 40 40",
3213
3291
  fill: "none",
3214
3292
  xmlns: "http://www.w3.org/2000/svg",
3215
- "data-test-id": "period-decimal"
3293
+ "data-testid": "period-decimal"
3216
3294
  }, /*#__PURE__*/React.createElement("path", {
3217
3295
  d: "M18.3401 27.512c0-.232.04-.448.12-.648.088-.208.204-.388.348-.54.152-.152.328-.272.528-.36.208-.088.428-.132.66-.132.232 0 .448.044.648.132.208.088.388.208.54.36.152.152.272.332.36.54.088.2.132.416.132.648 0 .24-.044.46-.132.66-.088.2-.208.376-.36.528-.152.152-.332.268-.54.348-.2.088-.416.132-.648.132-.232 0-.452-.044-.66-.132-.2-.08-.376-.196-.528-.348-.144-.152-.26-.328-.348-.528-.08-.2-.12-.42-.12-.66z",
3218
3296
  fill: "#21242C"
@@ -4604,13 +4682,17 @@ function ExtrasPage(props) {
4604
4682
  extraKeys,
4605
4683
  onClickKey
4606
4684
  } = props;
4685
+ const {
4686
+ strings
4687
+ } = useMathInputI18n();
4688
+ const Keys = KeyConfigs(strings);
4607
4689
  return /*#__PURE__*/React.createElement(React.Fragment, null, extraKeys.map((key, i) => {
4608
4690
  // Map 1D array to Cartesian coordinates
4609
4691
  const coordX = i % columns;
4610
4692
  const coordY = i / columns;
4611
4693
  return /*#__PURE__*/React.createElement(KeypadButton, {
4612
4694
  key: key,
4613
- keyConfig: KeyConfigs[key],
4695
+ keyConfig: Keys[key],
4614
4696
  onClickKey: onClickKey,
4615
4697
  coord: [coordX, coordY]
4616
4698
  });
@@ -4624,7 +4706,7 @@ const expandedViewThreshold = 500;
4624
4706
  // This is a helper function that returns the correct context for the cursor
4625
4707
  // based on the cursorContext prop. It is used in the keypad to determine
4626
4708
  // which key to render as the "jump out" key.
4627
- function getCursorContextConfig(cursorContext) {
4709
+ function getCursorContextConfig(strings, cursorContext) {
4628
4710
  if (!cursorContext) {
4629
4711
  return null;
4630
4712
  }
@@ -4632,17 +4714,17 @@ function getCursorContextConfig(cursorContext) {
4632
4714
  case CursorContext.NONE:
4633
4715
  return null;
4634
4716
  case CursorContext.IN_PARENS:
4635
- return KeyConfigs.JUMP_OUT_PARENTHESES;
4717
+ return KeyConfigs(strings).JUMP_OUT_PARENTHESES;
4636
4718
  case CursorContext.IN_SUPER_SCRIPT:
4637
- return KeyConfigs.JUMP_OUT_EXPONENT;
4719
+ return KeyConfigs(strings).JUMP_OUT_EXPONENT;
4638
4720
  case CursorContext.IN_SUB_SCRIPT:
4639
- return KeyConfigs.JUMP_OUT_BASE;
4721
+ return KeyConfigs(strings).JUMP_OUT_BASE;
4640
4722
  case CursorContext.IN_NUMERATOR:
4641
- return KeyConfigs.JUMP_OUT_NUMERATOR;
4723
+ return KeyConfigs(strings).JUMP_OUT_NUMERATOR;
4642
4724
  case CursorContext.IN_DENOMINATOR:
4643
- return KeyConfigs.JUMP_OUT_DENOMINATOR;
4725
+ return KeyConfigs(strings).JUMP_OUT_DENOMINATOR;
4644
4726
  case CursorContext.BEFORE_FRACTION:
4645
- return KeyConfigs.JUMP_INTO_NUMERATOR;
4727
+ return KeyConfigs(strings).JUMP_INTO_NUMERATOR;
4646
4728
  }
4647
4729
  }
4648
4730
 
@@ -4651,70 +4733,74 @@ function FractionsPage(props) {
4651
4733
  onClickKey,
4652
4734
  cursorContext
4653
4735
  } = props;
4654
- const cursorKeyConfig = getCursorContextConfig(cursorContext);
4736
+ const {
4737
+ strings
4738
+ } = useMathInputI18n();
4739
+ const cursorKeyConfig = getCursorContextConfig(strings, cursorContext);
4655
4740
  // These keys are arranged sequentially so that tabbing follows numerical order. This
4656
4741
  // allows us to visually mimic a keypad without affecting a11y. The visual order of the
4657
4742
  // keys in the keypad is determined by their coordinates, not their order in the DOM.
4743
+ const Keys = KeyConfigs(strings);
4658
4744
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
4659
- keyConfig: KeyConfigs.NUM_1,
4745
+ keyConfig: Keys.NUM_1,
4660
4746
  onClickKey: onClickKey,
4661
4747
  coord: [0, 2]
4662
4748
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4663
- keyConfig: KeyConfigs.NUM_2,
4749
+ keyConfig: Keys.NUM_2,
4664
4750
  onClickKey: onClickKey,
4665
4751
  coord: [1, 2]
4666
4752
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4667
- keyConfig: KeyConfigs.NUM_3,
4753
+ keyConfig: Keys.NUM_3,
4668
4754
  onClickKey: onClickKey,
4669
4755
  coord: [2, 2]
4670
4756
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4671
- keyConfig: KeyConfigs.NUM_4,
4757
+ keyConfig: Keys.NUM_4,
4672
4758
  onClickKey: onClickKey,
4673
4759
  coord: [0, 1]
4674
4760
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4675
- keyConfig: KeyConfigs.NUM_5,
4761
+ keyConfig: Keys.NUM_5,
4676
4762
  onClickKey: onClickKey,
4677
4763
  coord: [1, 1]
4678
4764
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4679
- keyConfig: KeyConfigs.NUM_6,
4765
+ keyConfig: Keys.NUM_6,
4680
4766
  onClickKey: onClickKey,
4681
4767
  coord: [2, 1]
4682
4768
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4683
- keyConfig: KeyConfigs.NUM_7,
4769
+ keyConfig: Keys.NUM_7,
4684
4770
  onClickKey: onClickKey,
4685
4771
  coord: [0, 0]
4686
4772
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4687
- keyConfig: KeyConfigs.NUM_8,
4773
+ keyConfig: Keys.NUM_8,
4688
4774
  onClickKey: onClickKey,
4689
4775
  coord: [1, 0]
4690
4776
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4691
- keyConfig: KeyConfigs.NUM_9,
4777
+ keyConfig: Keys.NUM_9,
4692
4778
  onClickKey: onClickKey,
4693
4779
  coord: [2, 0]
4694
4780
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4695
- keyConfig: KeyConfigs.NUM_0,
4781
+ keyConfig: Keys.NUM_0,
4696
4782
  onClickKey: onClickKey,
4697
4783
  coord: [0, 3]
4698
4784
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4699
- keyConfig: KeyConfigs.DECIMAL,
4785
+ keyConfig: Keys.DECIMAL,
4700
4786
  onClickKey: onClickKey,
4701
4787
  coord: [1, 3]
4702
4788
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4703
- keyConfig: KeyConfigs.NEGATIVE,
4789
+ keyConfig: Keys.NEGATIVE,
4704
4790
  onClickKey: onClickKey,
4705
4791
  coord: [2, 3]
4706
4792
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4707
- keyConfig: KeyConfigs.PERCENT,
4793
+ keyConfig: Keys.PERCENT,
4708
4794
  onClickKey: onClickKey,
4709
4795
  coord: [3, 0],
4710
4796
  secondary: true
4711
4797
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4712
- keyConfig: KeyConfigs.PI,
4798
+ keyConfig: Keys.PI,
4713
4799
  onClickKey: onClickKey,
4714
4800
  coord: [3, 1],
4715
4801
  secondary: true
4716
4802
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4717
- keyConfig: KeyConfigs.FRAC,
4803
+ keyConfig: Keys.FRAC,
4718
4804
  onClickKey: onClickKey,
4719
4805
  coord: [3, 2],
4720
4806
  secondary: true
@@ -4724,7 +4810,7 @@ function FractionsPage(props) {
4724
4810
  coord: [3, 3],
4725
4811
  secondary: true
4726
4812
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4727
- keyConfig: KeyConfigs.BACKSPACE,
4813
+ keyConfig: Keys.BACKSPACE,
4728
4814
  onClickKey: onClickKey,
4729
4815
  coord: [4, 3],
4730
4816
  action: true
@@ -4735,16 +4821,20 @@ function GeometryPage(props) {
4735
4821
  const {
4736
4822
  onClickKey
4737
4823
  } = props;
4824
+ const {
4825
+ strings
4826
+ } = useMathInputI18n();
4827
+ const Keys = KeyConfigs(strings);
4738
4828
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
4739
- keyConfig: KeyConfigs.SIN,
4829
+ keyConfig: Keys.SIN,
4740
4830
  onClickKey: onClickKey,
4741
4831
  coord: [0, 0]
4742
4832
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4743
- keyConfig: KeyConfigs.COS,
4833
+ keyConfig: Keys.COS,
4744
4834
  onClickKey: onClickKey,
4745
4835
  coord: [1, 0]
4746
4836
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4747
- keyConfig: KeyConfigs.TAN,
4837
+ keyConfig: Keys.TAN,
4748
4838
  onClickKey: onClickKey,
4749
4839
  coord: [2, 0]
4750
4840
  }));
@@ -4754,59 +4844,63 @@ function NumbersPage(props) {
4754
4844
  const {
4755
4845
  onClickKey
4756
4846
  } = props;
4847
+ const {
4848
+ strings
4849
+ } = useMathInputI18n();
4850
+ const Keys = KeyConfigs(strings);
4757
4851
  // These keys are arranged sequentially so that tabbing follows numerical order. This
4758
4852
  // allows us to visually mimic a keypad without affecting a11y. The visual order of the
4759
4853
  // keys in the keypad is determined by their coordinates, not their order in the DOM.
4760
4854
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
4761
- keyConfig: KeyConfigs.NUM_1,
4855
+ keyConfig: Keys.NUM_1,
4762
4856
  onClickKey: onClickKey,
4763
4857
  coord: [0, 2]
4764
4858
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4765
- keyConfig: KeyConfigs.NUM_2,
4859
+ keyConfig: Keys.NUM_2,
4766
4860
  onClickKey: onClickKey,
4767
4861
  coord: [1, 2]
4768
4862
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4769
- keyConfig: KeyConfigs.NUM_3,
4863
+ keyConfig: Keys.NUM_3,
4770
4864
  onClickKey: onClickKey,
4771
4865
  coord: [2, 2]
4772
4866
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4773
- keyConfig: KeyConfigs.NUM_4,
4867
+ keyConfig: Keys.NUM_4,
4774
4868
  onClickKey: onClickKey,
4775
4869
  coord: [0, 1]
4776
4870
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4777
- keyConfig: KeyConfigs.NUM_5,
4871
+ keyConfig: Keys.NUM_5,
4778
4872
  onClickKey: onClickKey,
4779
4873
  coord: [1, 1]
4780
4874
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4781
- keyConfig: KeyConfigs.NUM_6,
4875
+ keyConfig: Keys.NUM_6,
4782
4876
  onClickKey: onClickKey,
4783
4877
  coord: [2, 1]
4784
4878
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4785
- keyConfig: KeyConfigs.NUM_7,
4879
+ keyConfig: Keys.NUM_7,
4786
4880
  onClickKey: onClickKey,
4787
4881
  coord: [0, 0]
4788
4882
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4789
- keyConfig: KeyConfigs.NUM_8,
4883
+ keyConfig: Keys.NUM_8,
4790
4884
  onClickKey: onClickKey,
4791
4885
  coord: [1, 0]
4792
4886
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4793
- keyConfig: KeyConfigs.NUM_9,
4887
+ keyConfig: Keys.NUM_9,
4794
4888
  onClickKey: onClickKey,
4795
4889
  coord: [2, 0]
4796
4890
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4797
- keyConfig: KeyConfigs.NUM_0,
4891
+ keyConfig: Keys.NUM_0,
4798
4892
  onClickKey: onClickKey,
4799
4893
  coord: [0, 3]
4800
4894
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4801
- keyConfig: KeyConfigs.DECIMAL,
4895
+ keyConfig: Keys.DECIMAL,
4802
4896
  onClickKey: onClickKey,
4803
4897
  coord: [1, 3]
4804
4898
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4805
- keyConfig: KeyConfigs.NEGATIVE,
4899
+ keyConfig: Keys.NEGATIVE,
4806
4900
  onClickKey: onClickKey,
4807
4901
  coord: [2, 3]
4808
4902
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4809
- keyConfig: KeyConfigs.PERCENT,
4903
+ keyConfig: Keys.PERCENT,
4810
4904
  onClickKey: onClickKey,
4811
4905
  coord: [3, 0],
4812
4906
  secondary: true
@@ -4821,56 +4915,60 @@ function OperatorsPage(props) {
4821
4915
  basicRelations,
4822
4916
  advancedRelations
4823
4917
  } = props;
4918
+ const {
4919
+ strings
4920
+ } = useMathInputI18n();
4921
+ const Keys = KeyConfigs(strings);
4824
4922
  return /*#__PURE__*/React.createElement(React.Fragment, null, preAlgebra && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
4825
- keyConfig: KeyConfigs.EXP_2,
4923
+ keyConfig: Keys.EXP_2,
4826
4924
  onClickKey: onClickKey,
4827
4925
  coord: [0, 0]
4828
4926
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4829
- keyConfig: KeyConfigs.EXP,
4927
+ keyConfig: Keys.EXP,
4830
4928
  onClickKey: onClickKey,
4831
4929
  coord: [1, 0]
4832
4930
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4833
- keyConfig: KeyConfigs.SQRT,
4931
+ keyConfig: Keys.SQRT,
4834
4932
  onClickKey: onClickKey,
4835
4933
  coord: [2, 0]
4836
4934
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4837
- keyConfig: KeyConfigs.RADICAL,
4935
+ keyConfig: Keys.RADICAL,
4838
4936
  onClickKey: onClickKey,
4839
4937
  coord: [3, 0]
4840
4938
  })), logarithms && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
4841
- keyConfig: KeyConfigs.LOG,
4939
+ keyConfig: Keys.LOG,
4842
4940
  onClickKey: onClickKey,
4843
4941
  coord: [0, 1]
4844
4942
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4845
- keyConfig: KeyConfigs.LOG_N,
4943
+ keyConfig: Keys.LOG_N,
4846
4944
  onClickKey: onClickKey,
4847
4945
  coord: [1, 1]
4848
4946
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4849
- keyConfig: KeyConfigs.LN,
4947
+ keyConfig: Keys.LN,
4850
4948
  onClickKey: onClickKey,
4851
4949
  coord: [2, 1]
4852
4950
  })), basicRelations && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
4853
- keyConfig: KeyConfigs.EQUAL,
4951
+ keyConfig: Keys.EQUAL,
4854
4952
  onClickKey: onClickKey,
4855
4953
  coord: [0, 2]
4856
4954
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4857
- keyConfig: KeyConfigs.LT,
4955
+ keyConfig: Keys.LT,
4858
4956
  onClickKey: onClickKey,
4859
4957
  coord: [1, 2]
4860
4958
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4861
- keyConfig: KeyConfigs.GT,
4959
+ keyConfig: Keys.GT,
4862
4960
  onClickKey: onClickKey,
4863
4961
  coord: [2, 2]
4864
4962
  })), advancedRelations && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
4865
- keyConfig: KeyConfigs.NEQ,
4963
+ keyConfig: Keys.NEQ,
4866
4964
  onClickKey: onClickKey,
4867
4965
  coord: [0, 3]
4868
4966
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4869
- keyConfig: KeyConfigs.LEQ,
4967
+ keyConfig: Keys.LEQ,
4870
4968
  onClickKey: onClickKey,
4871
4969
  coord: [1, 3]
4872
4970
  }), /*#__PURE__*/React.createElement(KeypadButton, {
4873
- keyConfig: KeyConfigs.GEQ,
4971
+ keyConfig: Keys.GEQ,
4874
4972
  onClickKey: onClickKey,
4875
4973
  coord: [2, 3]
4876
4974
  })));
@@ -4975,24 +5073,28 @@ function NavigationPad(props) {
4975
5073
  const {
4976
5074
  onClickKey
4977
5075
  } = props;
5076
+ const {
5077
+ strings
5078
+ } = useMathInputI18n();
5079
+ const Keys = KeyConfigs(strings);
4978
5080
  return /*#__PURE__*/React.createElement(View$1, {
4979
5081
  style: styles$2.container
4980
5082
  }, /*#__PURE__*/React.createElement(View$1, {
4981
5083
  style: styles$2.grid
4982
5084
  }, /*#__PURE__*/React.createElement(NavigationButton, {
4983
- keyConfig: KeyConfigs.UP,
5085
+ keyConfig: Keys.UP,
4984
5086
  onClickKey: onClickKey,
4985
5087
  coord: [1, 0]
4986
5088
  }), /*#__PURE__*/React.createElement(NavigationButton, {
4987
- keyConfig: KeyConfigs.RIGHT,
5089
+ keyConfig: Keys.RIGHT,
4988
5090
  onClickKey: onClickKey,
4989
5091
  coord: [2, 1]
4990
5092
  }), /*#__PURE__*/React.createElement(NavigationButton, {
4991
- keyConfig: KeyConfigs.DOWN,
5093
+ keyConfig: Keys.DOWN,
4992
5094
  onClickKey: onClickKey,
4993
5095
  coord: [1, 2]
4994
5096
  }), /*#__PURE__*/React.createElement(NavigationButton, {
4995
- keyConfig: KeyConfigs.LEFT,
5097
+ keyConfig: Keys.LEFT,
4996
5098
  onClickKey: onClickKey,
4997
5099
  coord: [0, 1]
4998
5100
  }), /*#__PURE__*/React.createElement(View$1, {
@@ -5028,42 +5130,47 @@ function SharedKeys(props) {
5028
5130
  convertDotToTimes,
5029
5131
  selectedPage
5030
5132
  } = props;
5031
- const cursorKeyConfig = getCursorContextConfig(cursorContext);
5133
+ const {
5134
+ strings,
5135
+ locale
5136
+ } = useMathInputI18n();
5137
+ const cursorKeyConfig = getCursorContextConfig(strings, cursorContext);
5138
+ const Keys = KeyConfigs(strings);
5032
5139
 
5033
5140
  // Fraction position depends on the page
5034
5141
  const fractionCoord = selectedPage === "Numbers" || selectedPage === "Operators" ? [3, 1] : [3, 0];
5035
5142
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(KeypadButton, {
5036
- keyConfig: KeyConfigs.FRAC,
5143
+ keyConfig: Keys.FRAC,
5037
5144
  onClickKey: onClickKey,
5038
5145
  coord: fractionCoord,
5039
5146
  secondary: true
5040
5147
  }), /*#__PURE__*/React.createElement(KeypadButton, {
5041
- keyConfig: KeyConfigs.PLUS,
5148
+ keyConfig: Keys.PLUS,
5042
5149
  onClickKey: onClickKey,
5043
5150
  coord: [4, 0],
5044
5151
  secondary: true
5045
5152
  }), /*#__PURE__*/React.createElement(KeypadButton, {
5046
- keyConfig: KeyConfigs.MINUS,
5153
+ keyConfig: Keys.MINUS,
5047
5154
  onClickKey: onClickKey,
5048
5155
  coord: [5, 0],
5049
5156
  secondary: true
5050
5157
  }), /*#__PURE__*/React.createElement(KeypadButton, {
5051
- keyConfig: convertDotToTimesByLocale(!!convertDotToTimes) ? KeyConfigs.TIMES : KeyConfigs.CDOT,
5158
+ keyConfig: convertDotToTimesByLocale(locale, !!convertDotToTimes) ? Keys.TIMES : Keys.CDOT,
5052
5159
  onClickKey: onClickKey,
5053
5160
  coord: [4, 1],
5054
5161
  secondary: true
5055
5162
  }), divisionKey && /*#__PURE__*/React.createElement(KeypadButton, {
5056
- keyConfig: KeyConfigs.DIVIDE,
5163
+ keyConfig: Keys.DIVIDE,
5057
5164
  onClickKey: onClickKey,
5058
5165
  coord: [5, 1],
5059
5166
  secondary: true
5060
5167
  }), /*#__PURE__*/React.createElement(KeypadButton, {
5061
- keyConfig: KeyConfigs.LEFT_PAREN,
5168
+ keyConfig: Keys.LEFT_PAREN,
5062
5169
  onClickKey: onClickKey,
5063
5170
  coord: [4, 2],
5064
5171
  secondary: true
5065
5172
  }), /*#__PURE__*/React.createElement(KeypadButton, {
5066
- keyConfig: KeyConfigs.RIGHT_PAREN,
5173
+ keyConfig: Keys.RIGHT_PAREN,
5067
5174
  onClickKey: onClickKey,
5068
5175
  coord: [5, 2],
5069
5176
  secondary: true
@@ -5073,7 +5180,7 @@ function SharedKeys(props) {
5073
5180
  coord: [4, 3],
5074
5181
  secondary: true
5075
5182
  }), /*#__PURE__*/React.createElement(KeypadButton, {
5076
- keyConfig: KeyConfigs.BACKSPACE,
5183
+ keyConfig: Keys.BACKSPACE,
5077
5184
  onClickKey: onClickKey,
5078
5185
  coord: [5, 3],
5079
5186
  action: true
@@ -5745,5 +5852,5 @@ let KeypadType = /*#__PURE__*/function (KeypadType) {
5745
5852
  return KeypadType;
5746
5853
  }({});
5747
5854
 
5748
- export { CursorContext, Keypad as DesktopKeypad, KeyArray, KeyConfigs, KeypadContext, MathInput as KeypadInput, KeypadType, MobileKeypad, StatefulKeypadContextProvider, convertDotToTimesByLocale, createMathField, getCursorContext, keyToMathquillMap as keyTranslator, keypadElementPropType, libVersion, mathQuillInstance };
5855
+ export { CursorContext, Keypad as DesktopKeypad, KeyArray, KeyConfigs, KeypadContext, MathInput as KeypadInput, KeypadType, MathInputI18nContext, MathInputI18nContextProvider, MobileKeypad, StatefulKeypadContextProvider, convertDotToTimesByLocale, createMathField, getCursorContext, getKeyTranslator, keypadElementPropType, libVersion, mathQuillInstance, useMathInputI18n };
5749
5856
  //# sourceMappingURL=index.js.map