@khanacademy/perseus 11.6.1 → 12.0.1

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
@@ -5,30 +5,30 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var KAS = require('@khanacademy/kas');
6
6
  var mathInput = require('@khanacademy/math-input');
7
7
  var PerseusLinter = require('@khanacademy/perseus-linter');
8
+ var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
8
9
  var i18n = require('@khanacademy/wonder-blocks-i18n');
10
+ var Tooltip$1 = require('@khanacademy/wonder-blocks-tooltip');
9
11
  var classNames = require('classnames');
10
12
  var React = require('react');
11
13
  var _ = require('underscore');
14
+ var Clickable = require('@khanacademy/wonder-blocks-clickable');
15
+ var Color = require('@khanacademy/wonder-blocks-color');
16
+ var wonderBlocksPopover = require('@khanacademy/wonder-blocks-popover');
17
+ var Spacing = require('@khanacademy/wonder-blocks-spacing');
18
+ var aphrodite = require('aphrodite');
12
19
  var $ = require('jquery');
13
- var ReactDOM = require('react-dom');
14
20
  var PropTypes = require('prop-types');
21
+ var ReactDOM = require('react-dom');
15
22
  var kmath = require('@khanacademy/kmath');
16
- var Spacing = require('@khanacademy/wonder-blocks-spacing');
17
- var aphrodite = require('aphrodite');
18
23
  var wonderBlocksProgressSpinner = require('@khanacademy/wonder-blocks-progress-spinner');
19
- var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
20
24
  var SimpleMarkdown = require('@khanacademy/simple-markdown');
21
25
  var pureMarkdown = require('@khanacademy/pure-markdown');
22
26
  var wonderBlocksForm = require('@khanacademy/wonder-blocks-form');
23
27
  var Button = require('@khanacademy/wonder-blocks-button');
24
- var Clickable = require('@khanacademy/wonder-blocks-clickable');
25
- var Color = require('@khanacademy/wonder-blocks-color');
26
28
  var wonderBlocksLayout = require('@khanacademy/wonder-blocks-layout');
27
- var wonderBlocksPopover = require('@khanacademy/wonder-blocks-popover');
28
29
  var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
29
30
  var debounce = require('lodash.debounce');
30
31
  var createReactClass = require('create-react-class');
31
- var Tooltip$1 = require('@khanacademy/wonder-blocks-tooltip');
32
32
  var Link = require('@khanacademy/wonder-blocks-link');
33
33
  var perseusCore = require('@khanacademy/perseus-core');
34
34
 
@@ -55,21 +55,21 @@ function _interopNamespace(e) {
55
55
  var KAS__namespace = /*#__PURE__*/_interopNamespace(KAS);
56
56
  var PerseusLinter__namespace = /*#__PURE__*/_interopNamespace(PerseusLinter);
57
57
  var i18n__namespace = /*#__PURE__*/_interopNamespace(i18n);
58
+ var Tooltip__default = /*#__PURE__*/_interopDefaultLegacy(Tooltip$1);
58
59
  var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
59
60
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
60
61
  var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
62
+ var Clickable__default = /*#__PURE__*/_interopDefaultLegacy(Clickable);
63
+ var Color__default = /*#__PURE__*/_interopDefaultLegacy(Color);
64
+ var Spacing__default = /*#__PURE__*/_interopDefaultLegacy(Spacing);
61
65
  var $__default = /*#__PURE__*/_interopDefaultLegacy($);
66
+ var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
62
67
  var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
63
68
  var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
64
- var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
65
- var Spacing__default = /*#__PURE__*/_interopDefaultLegacy(Spacing);
66
69
  var SimpleMarkdown__default = /*#__PURE__*/_interopDefaultLegacy(SimpleMarkdown);
67
70
  var Button__default = /*#__PURE__*/_interopDefaultLegacy(Button);
68
- var Clickable__default = /*#__PURE__*/_interopDefaultLegacy(Clickable);
69
- var Color__default = /*#__PURE__*/_interopDefaultLegacy(Color);
70
71
  var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
71
72
  var createReactClass__default = /*#__PURE__*/_interopDefaultLegacy(createReactClass);
72
- var Tooltip__default = /*#__PURE__*/_interopDefaultLegacy(Tooltip$1);
73
73
  var Link__default = /*#__PURE__*/_interopDefaultLegacy(Link);
74
74
 
75
75
  function _defineProperty(obj, key, value) {
@@ -115,320 +115,6 @@ function _toPropertyKey(arg) {
115
115
  return typeof key === "symbol" ? key : String(key);
116
116
  }
117
117
 
118
- /**
119
- * A stripped version of Icon.jsx from webapp. Takes an SVG icon and renders it
120
- * inline like Font Awesome did.
121
- *
122
- * If you are looking for an icon that we've used before you should look in
123
- * webapp's `icon-paths.js` which is a reference file for all the SVG paths
124
- * that we've used. You'll need to copy the object from that file into
125
- * whichever file you're using the icon and explicitly pass it in to the
126
- * <InlineIcon/> React component.
127
- *
128
- * We assume that the viewBox is cropped and aligned to (0, 0), but icons can
129
- * be defined differently. At some point we might want to add these attributes
130
- * to `icon-paths.js`, but for now this is a fairly safe assumption.
131
- *
132
- * Sample usage:
133
- *
134
- * const editIcon = {
135
- * path: "M41.209 53.753l5.39 0l0 5.39l3.136 0l6.468-6.517-8.477-8.526-6.517 6.517l0 3.136zm33.173-34.937q-.882-.882-1.862.049l-19.6 19.6q-.931.98-.049 1.862t1.862-.049l19.6-19.6q.931-.98.049-1.862zm-38.563 45.668l0-16.121l37.632-37.632 16.17 16.121-37.632 37.632l-16.17 0zm43.022-12.397l0 10.633q-.049 6.713-4.753 11.417t-11.368 4.704l-46.599 0q-6.713 0-11.417-4.753t-4.704-11.368l0-46.599q0-6.664 4.753-11.417t11.368-4.704l46.599 0q3.528 0 6.566 1.372.833.392.98 1.323t-.49 1.617l-2.744 2.744q-.784.784-1.96.441t-2.352-.343l-46.599 0q-3.675 0-6.321 2.646t-2.646 6.321l0 46.599q0 3.675 2.646 6.321t6.321 2.646l46.599 0q3.675 0 6.321-2.646t2.646-6.321l0-7.056q0-.735.49-1.225l3.577-3.577q.833-.833 1.96-.392t1.127 1.617zm7.203-51.646q2.254 0 3.773 1.568l8.526 8.526q1.568 1.568 1.568 3.822t-1.568 3.773l-5.145 5.145-16.121-16.121 5.145-5.145q1.568-1.568 3.822-1.568z",
136
- * width: 100,
137
- * height: 78.912,
138
- * };
139
- * <InlineIcon {...editIcon} />
140
- *
141
- */
142
- const InlineIcon = _ref => {
143
- let {
144
- path,
145
- width,
146
- height,
147
- style = {},
148
- title
149
- } = _ref;
150
- return /*#__PURE__*/React__namespace.createElement("svg", {
151
- role: "img",
152
- "aria-hidden": !title,
153
- style: {
154
- verticalAlign: "middle",
155
- ...style
156
- },
157
- width: "".concat(width / height, "em"),
158
- height: "1em",
159
- viewBox: "0 0 ".concat(width, " ").concat(height)
160
- }, !!title && /*#__PURE__*/React__namespace.createElement("title", null, title), /*#__PURE__*/React__namespace.createElement("path", {
161
- d: path,
162
- fill: "currentColor"
163
- }));
164
- };
165
-
166
- let _dependencies = null;
167
- const setDependencies = dependencies => {
168
- _dependencies = dependencies;
169
- };
170
- const getDependencies = () => {
171
- if (_dependencies) {
172
- return _dependencies;
173
- }
174
- throw new Error(["Perseus has not been provided required dependencies.", "setDependencies(dependencies) must be called first.", "Make sure Perseus is being imported from javascript/perseus/perseus.js."].join("\n"));
175
- };
176
- const DependenciesContext = /*#__PURE__*/React__namespace.createContext({
177
- analytics: {
178
- onAnalyticsEvent: async () => {}
179
- }
180
- });
181
-
182
- /**
183
- * useDependencies provides easy access to the current Perseus dependencies.
184
- */
185
- const useDependencies = () => {
186
- const deps = React__namespace.useContext(DependenciesContext);
187
- return deps;
188
- };
189
-
190
- var dependencies = /*#__PURE__*/Object.freeze({
191
- __proto__: null,
192
- setDependencies: setDependencies,
193
- getDependencies: getDependencies,
194
- DependenciesContext: DependenciesContext,
195
- useDependencies: useDependencies
196
- });
197
-
198
- const prettyBig = {
199
- fontSize: "150%"
200
- };
201
- const slightlyBig = {
202
- fontSize: "120%"
203
- };
204
- const symbStyle = {
205
- fontSize: "130%"
206
- };
207
- // These are functions because we want to generate a new component for each use
208
- // on the page rather than reusing an instance (which will cause an error).
209
- // Also, it's useful for things which might look different depending on the
210
- // props.
211
-
212
- const basic = [() => [/*#__PURE__*/React__namespace.createElement("span", {
213
- key: "plus",
214
- style: slightlyBig
215
- }, "+"), "PLUS", i18n__namespace._("Plus")], () => [/*#__PURE__*/React__namespace.createElement("span", {
216
- key: "minus",
217
- style: prettyBig
218
- }, "-"), "MINUS", i18n__namespace._("Minus")],
219
- // TODO(joel) - display as \cdot when appropriate
220
- props => {
221
- const {
222
- TeX
223
- } = getDependencies();
224
- if (props.convertDotToTimes) {
225
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
226
- key: "times",
227
- style: prettyBig
228
- }, i18n__namespace.doNotTranslate("\\times")), "TIMES", i18n__namespace._("Multiply")];
229
- }
230
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
231
- key: "times",
232
- style: prettyBig
233
- }, i18n__namespace.doNotTranslate("\\cdot")), "CDOT", i18n__namespace._("Multiply")];
234
- }, () => {
235
- const {
236
- TeX
237
- } = getDependencies();
238
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
239
- key: "frac",
240
- style: prettyBig
241
- }, i18n__namespace.doNotTranslate("\\frac{x}{y}")), "FRAC", i18n__namespace._("Fraction, excluding the current expression")];
242
- }];
243
- const buttonSets = {
244
- basic,
245
- "basic+div": basic.concat([() => {
246
- const {
247
- TeX
248
- } = getDependencies();
249
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
250
- key: "div"
251
- }, i18n__namespace.doNotTranslate("\\div")), "DIVIDE", i18n__namespace._("Divide")];
252
- }]),
253
- trig: [() => {
254
- const {
255
- TeX
256
- } = getDependencies();
257
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
258
- key: "sin"
259
- }, i18n__namespace.doNotTranslate("\\sin")), "SIN", i18n__namespace._("Sine")];
260
- }, () => {
261
- const {
262
- TeX
263
- } = getDependencies();
264
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
265
- key: "cos"
266
- }, i18n__namespace.doNotTranslate("\\cos")), "COS", i18n__namespace._("Cosine")];
267
- }, () => {
268
- const {
269
- TeX
270
- } = getDependencies();
271
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
272
- key: "tan"
273
- }, i18n__namespace.doNotTranslate("\\tan")), "TAN", i18n__namespace._("Tangent")];
274
- }, () => {
275
- const {
276
- TeX
277
- } = getDependencies();
278
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
279
- key: "theta",
280
- style: symbStyle
281
- }, i18n__namespace.doNotTranslate("\\theta")), "THETA", i18n__namespace._("Theta")];
282
- }, () => {
283
- const {
284
- TeX
285
- } = getDependencies();
286
- return [/*#__PURE__*/React__namespace.createElement("span", {
287
- key: "phi"
288
- }, /*#__PURE__*/React__namespace.createElement("span", {
289
- className: "perseus-sr-only"
290
- }, i18n__namespace.doNotTranslate("phi")), /*#__PURE__*/React__namespace.createElement(TeX, {
291
- key: "pi",
292
- style: symbStyle
293
- }, i18n__namespace.doNotTranslate("\\phi"))), "PHI", i18n__namespace._("Phi")];
294
- }],
295
- prealgebra: [() => {
296
- const {
297
- TeX
298
- } = getDependencies();
299
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
300
- key: "sqrt"
301
- }, i18n__namespace.doNotTranslate("\\sqrt{x}")), "SQRT", i18n__namespace._("Square root")];
302
- },
303
- // TODO(joel) - how does desmos do this?
304
- () => {
305
- const {
306
- TeX
307
- } = getDependencies();
308
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
309
- key: "nthroot"
310
- }, i18n__namespace.doNotTranslate("\\sqrt[3]{x}")), "NTHROOT3", i18n__namespace._("Cube root")];
311
- }, () => {
312
- const {
313
- TeX
314
- } = getDependencies();
315
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
316
- key: "pow",
317
- style: slightlyBig
318
- }, i18n__namespace.doNotTranslate("a^b")), "POW", i18n__namespace._("Exponent")];
319
- }, () => {
320
- const {
321
- TeX
322
- } = getDependencies();
323
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
324
- key: "pi",
325
- style: slightlyBig
326
- }, i18n__namespace.doNotTranslate("\\pi")), "PI", i18n__namespace._("Pi")];
327
- }],
328
- logarithms: [() => {
329
- const {
330
- TeX
331
- } = getDependencies();
332
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
333
- key: "log"
334
- }, i18n__namespace.doNotTranslate("\\log")), "LOG", i18n__namespace._("Logarithm with base 10")];
335
- }, () => {
336
- const {
337
- TeX
338
- } = getDependencies();
339
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
340
- key: "ln"
341
- }, i18n__namespace.doNotTranslate("\\ln")), "LN", i18n__namespace._("Natural logarithm")];
342
- }, () => {
343
- const {
344
- TeX
345
- } = getDependencies();
346
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
347
- key: "log_b"
348
- }, i18n__namespace.doNotTranslate("\\log_b")), "LOG_B", i18n__namespace._("Logarithm with custom base")];
349
- }],
350
- "basic relations": [() => {
351
- const {
352
- TeX
353
- } = getDependencies();
354
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
355
- key: "eq"
356
- }, "="), "EQUAL", i18n__namespace._("Equals sign")];
357
- }, () => {
358
- const {
359
- TeX
360
- } = getDependencies();
361
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
362
- key: "lt"
363
- }, i18n__namespace.doNotTranslate("\\lt")), "LT", i18n__namespace._("Less than sign")];
364
- }, () => {
365
- const {
366
- TeX
367
- } = getDependencies();
368
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
369
- key: "gt"
370
- }, i18n__namespace.doNotTranslate("\\gt")), "GT", i18n__namespace._("Greater than sign")];
371
- }],
372
- "advanced relations": [() => {
373
- const {
374
- TeX
375
- } = getDependencies();
376
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
377
- key: "neq"
378
- }, i18n__namespace.doNotTranslate("\\neq")), "NEQ", i18n__namespace._("Not-equals sign")];
379
- }, () => {
380
- const {
381
- TeX
382
- } = getDependencies();
383
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
384
- key: "leq"
385
- }, i18n__namespace.doNotTranslate("\\leq")), "LEQ", i18n__namespace._("Less than or equal to sign")];
386
- }, () => {
387
- const {
388
- TeX
389
- } = getDependencies();
390
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
391
- key: "geq"
392
- }, i18n__namespace.doNotTranslate("\\geq")), "GEQ", i18n__namespace._("Greater than or equal to sign")];
393
- }]
394
- };
395
- const buttonSetsPropType = PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOf(___default["default"](buttonSets).keys()));
396
- class TexButtons extends React__namespace.Component {
397
- render() {
398
- // Always show buttonSets in the same order. Note: Technically it's ok
399
- // for _.keys() to return the keys in an arbitrary order, but in
400
- // practice, they will be ordered as listed above.
401
- const sortedButtonSets = ___default["default"].sortBy(this.props.sets, setName =>
402
- // @ts-expect-error - TS2345 - Argument of type 'string | number' is not assignable to parameter of type 'string'.
403
- ___default["default"].keys(buttonSets).indexOf(setName));
404
- const buttons = ___default["default"](sortedButtonSets).map(setName => buttonSets[setName]);
405
- const buttonRows = ___default["default"](buttons).map(row => row.map(symbGen => {
406
- // create a (component, thing we should send to mathquill) pair
407
- const symbol = symbGen(this.props);
408
- return /*#__PURE__*/React__namespace.createElement("button", {
409
- onClick: () => this.props.onInsert(symbol[1]),
410
- className: "tex-button"
411
- // @ts-expect-error - TS2533 - Object is possibly 'null' or 'undefined'. | TS2339 - Property 'key' does not exist on type 'boolean | ReactChild | ReactFragment | ReactPortal'.
412
- ,
413
- key: symbol[0].key,
414
- type: "button",
415
- "aria-label": symbol[2]
416
- }, symbol[0]);
417
- }));
418
- const buttonPopup = ___default["default"](buttonRows).map((row, i) => {
419
- return /*#__PURE__*/React__namespace.createElement("div", {
420
- className: "clearfix tex-button-row",
421
- key: this.props.sets[i]
422
- }, row);
423
- });
424
- return /*#__PURE__*/React__namespace.createElement("div", {
425
- className: "".concat(this.props.className || "", " preview-measure")
426
- }, buttonPopup);
427
- }
428
- }
429
- _defineProperty(TexButtons, "buttonSets", buttonSets);
430
- _defineProperty(TexButtons, "buttonSetsType", buttonSetsPropType);
431
-
432
118
  const customKeyTranslator = {
433
119
  ...mathInput.keyTranslator,
434
120
  // If there's something in the input that can become part of a
@@ -451,57 +137,9 @@ class MathInput extends React__namespace.Component {
451
137
  _defineProperty(this, "__mathFieldWrapperRef", null);
452
138
  _defineProperty(this, "__mathField", null);
453
139
  _defineProperty(this, "state", {
454
- focused: false
455
- });
456
- _defineProperty(this, "handleFocus", () => {
457
- this.setState({
458
- focused: true
459
- });
460
- // TODO(joel) fix properly - we should probably allow onFocus handlers
461
- // to this property, but we need to work correctly with them.
462
- // if (this.props.onFocus) {
463
- // this.props.onFocus();
464
- // }
465
- });
466
- _defineProperty(this, "handleMouseDown", event => {
467
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2345 - Argument of type 'EventTarget | null' is not assignable to parameter of type 'Node | null'.
468
- const focused = ReactDOM__default["default"].findDOMNode(this).contains(event.target);
469
- this.mouseDown = focused;
470
- if (!focused) {
471
- this.setState({
472
- focused: false
473
- });
474
- }
475
- });
476
- _defineProperty(this, "handleMouseUp", () => {
477
- // this mouse click started in the buttons div so we should focus the
478
- // input
479
- if (this.mouseDown) {
480
- this.focus();
481
- }
482
- this.mouseDown = false;
483
- });
484
- _defineProperty(this, "handleBlur", e => {
485
- // TODO(michaelpolyak): Consider trapping focus within the button group.
486
- // Focusing back on the input when TAB out of the last button in the
487
- // group. This will probably require ESCAPE key handling to enable to
488
- // close (blur) the button group in order to focus on next page element.
489
- if (!this.mouseDown &&
490
- // @ts-expect-error - TS2531 - Object is possibly 'null'.
491
- !ReactDOM__default["default"].findDOMNode(this).contains(e.relatedTarget)) {
492
- this.setState({
493
- focused: false
494
- });
495
- }
496
- });
497
- _defineProperty(this, "_shouldShowButtons", () => {
498
- if (this.props.buttonsVisible === "always") {
499
- return true;
500
- }
501
- if (this.props.buttonsVisible === "never") {
502
- return false;
503
- }
504
- return this.state.focused;
140
+ focused: false,
141
+ keypadOpen: this.props.buttonsVisible === "always" ? true : false,
142
+ cursorContext: mathInput.CursorContext.NONE
505
143
  });
506
144
  _defineProperty(this, "insert", value => {
507
145
  const input = this.mathField();
@@ -564,6 +202,9 @@ class MathInput extends React__namespace.Component {
564
202
  if (this.props.value !== value) {
565
203
  this.props.onChange(value);
566
204
  }
205
+ this.setState({
206
+ cursorContext: mathInput.getCursorContext(mathField)
207
+ });
567
208
  },
568
209
  enter: () => {
569
210
  // NOTE(kevinb): This isn't how answers to exercises are
@@ -596,34 +237,50 @@ class MathInput extends React__namespace.Component {
596
237
  focused: true
597
238
  });
598
239
  });
599
- _defineProperty(this, "blur", () => {
600
- var _this$mathField2;
601
- (_this$mathField2 = this.mathField()) === null || _this$mathField2 === void 0 ? void 0 : _this$mathField2.blur();
602
- this.setState({
603
- focused: false
604
- });
240
+ _defineProperty(this, "blur", () => this.setState({
241
+ focused: false
242
+ }));
243
+ _defineProperty(this, "handleKeypadPress", (key, e) => {
244
+ const translator = mathInput.keyTranslator[key];
245
+ const mathField = this.mathField();
246
+ if (mathField) {
247
+ if (translator) {
248
+ translator(mathField, key);
249
+ }
250
+ this.setState({
251
+ cursorContext: mathInput.getCursorContext(mathField)
252
+ });
253
+ }
254
+
255
+ // We want to prevent taking focus from input when clicking on keypad
256
+ // Clickable handles "onClick" differently than react;
257
+ // a keyboard event is "keydown" type.
258
+ // In react without WonderBlocks, "enter" or "space" keydown events
259
+ // are also "click" events, differentiated by "detail".
260
+ if (e.type === "click") {
261
+ this.focus();
262
+ }
605
263
  });
606
264
  }
607
265
  componentDidMount() {
608
- var _this$mathField3;
609
- window.addEventListener("mousedown", this.handleMouseDown);
610
- window.addEventListener("mouseup", this.handleMouseUp);
611
-
266
+ var _this$mathField2;
612
267
  // Ideally, we would be able to pass an initial value directly into
613
268
  // the constructor
614
- (_this$mathField3 = this.mathField()) === null || _this$mathField3 === void 0 ? void 0 : _this$mathField3.latex(this.props.value);
269
+ (_this$mathField2 = this.mathField()) === null || _this$mathField2 === void 0 ? void 0 : _this$mathField2.latex(this.props.value);
615
270
  }
616
- componentWillUnmount() {
617
- window.removeEventListener("mousedown", this.handleMouseDown);
618
- window.removeEventListener("mouseup", this.handleMouseUp);
271
+ openKeypad() {
272
+ if (this.props.buttonsVisible === "never") {
273
+ return;
274
+ }
275
+ this.setState({
276
+ keypadOpen: true
277
+ });
278
+ }
279
+ closeKeypad() {
280
+ this.setState({
281
+ keypadOpen: false
282
+ });
619
283
  }
620
-
621
- // handlers:
622
- // keep track of two related bits of state:
623
- // * this.state.focused - whether the buttons are currently shown
624
- // * this.mouseDown - whether a mouse click is active that started in the
625
- // buttons div
626
-
627
284
  render() {
628
285
  let className = classNames__default["default"]({
629
286
  "perseus-math-input": true,
@@ -635,439 +292,196 @@ class MathInput extends React__namespace.Component {
635
292
  if (this.props.className) {
636
293
  className = className + " " + this.props.className;
637
294
  }
638
- let buttons = null;
639
- if (this._shouldShowButtons()) {
640
- // @ts-expect-error - TS2322 - Type 'Element' is not assignable to type 'null'.
641
- buttons = /*#__PURE__*/React__namespace.createElement(TexButtons, {
642
- sets: this.props.buttonSets,
643
- className: "math-input-buttons absolute",
644
- convertDotToTimes: this.props.convertDotToTimes,
645
- onInsert: this.insert
646
- });
647
- }
648
- return /*#__PURE__*/React__namespace.createElement("div", {
649
- style: {
650
- display: "inline-block"
651
- }
295
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
296
+ style: [styles$A.outerWrapper, this.state.focused && styles$A.wrapperFocused, this.props.hasError && styles$A.wrapperError]
652
297
  }, /*#__PURE__*/React__namespace.createElement("div", {
653
298
  style: {
654
- display: "inline-block"
299
+ display: "flex",
300
+ padding: 1
301
+ },
302
+ onClick: () => {
303
+ const mathField = this.mathField();
304
+ if (!mathField) {
305
+ return;
306
+ }
307
+ this.setState({
308
+ cursorContext: mathInput.getCursorContext(mathField)
309
+ });
655
310
  }
656
311
  }, /*#__PURE__*/React__namespace.createElement("span", {
657
312
  className: className,
658
313
  ref: ref => this.__mathFieldWrapperRef = ref,
659
314
  "aria-label": this.props.labelText,
660
- onFocus: this.handleFocus,
661
- onBlur: this.handleBlur
662
- })), /*#__PURE__*/React__namespace.createElement("div", {
663
- style: {
664
- position: "relative"
665
- },
666
- onBlur: this.handleBlur
667
- }, buttons));
315
+ onFocus: () => this.focus(),
316
+ onBlur: () => this.blur()
317
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.Popover, {
318
+ opened: this.state.keypadOpen,
319
+ onClose: () => this.closeKeypad(),
320
+ dismissEnabled: true,
321
+ content: () => {
322
+ var _this$props$keypadBut, _this$props;
323
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
324
+ closeButtonVisible: true,
325
+ style: styles$A.popoverContent
326
+ }, /*#__PURE__*/React__namespace.createElement(mathInput.DesktopKeypad, _extends({
327
+ onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
328
+ extraKeys: this.props.extraKeys,
329
+ onClickKey: this.handleKeypadPress,
330
+ cursorContext: this.state.cursorContext,
331
+ convertDotToTimes: this.props.convertDotToTimes
332
+ }, (_this$props$keypadBut = this.props.keypadButtonSets) !== null && _this$props$keypadBut !== void 0 ? _this$props$keypadBut : mapButtonSets((_this$props = this.props) === null || _this$props === void 0 ? void 0 : _this$props.buttonSets))));
333
+ }
334
+ }, this.props.buttonsVisible === "never" ? /*#__PURE__*/React__namespace.createElement(MathInputIcon, {
335
+ hovered: false,
336
+ focused: false,
337
+ active: false
338
+ }) : /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
339
+ "aria-label": this.state.keypadOpen ? i18n__namespace._("close math keypad") : i18n__namespace._("open math keypad"),
340
+ "aria-checked": this.state.keypadOpen,
341
+ role: "switch",
342
+ onClick: () => this.state.keypadOpen ? this.closeKeypad() : this.openKeypad()
343
+ }, props => /*#__PURE__*/React__namespace.createElement(MathInputIcon, _extends({
344
+ active: this.state.keypadOpen
345
+ }, props))))));
668
346
  }
669
347
  }
670
348
  _defineProperty(MathInput, "defaultProps", {
671
349
  value: "",
672
- convertDotToTimes: false,
673
- buttonsVisible: "focused"
350
+ convertDotToTimes: false
674
351
  });
675
-
676
- const zIndex = 10;
677
- let HorizontalDirection = /*#__PURE__*/function (HorizontalDirection) {
678
- HorizontalDirection["Left"] = "left";
679
- HorizontalDirection["Right"] = "right";
680
- return HorizontalDirection;
681
- }({});
682
- let VerticalDirection = /*#__PURE__*/function (VerticalDirection) {
683
- VerticalDirection["Top"] = "top";
684
- VerticalDirection["Bottom"] = "bottom";
685
- return VerticalDirection;
686
- }({});
687
- const Triangle = props => {
688
- let borderLeft;
689
- let borderRight;
690
- let borderTop;
691
- let borderBottom;
692
- const hBorder = "".concat(props.width, "px solid transparent");
693
- if (props.horizontalDirection === "right") {
694
- borderLeft = hBorder;
695
- } else {
696
- borderRight = hBorder;
697
- }
698
- const vBorder = "".concat(props.height, "px solid ").concat(props.color);
699
- if (props.verticalDirection === "top") {
700
- borderTop = vBorder;
701
- } else {
702
- borderBottom = vBorder;
352
+ const MathInputIcon = _ref => {
353
+ let {
354
+ hovered,
355
+ focused,
356
+ active
357
+ } = _ref;
358
+ let color;
359
+ switch (true) {
360
+ case focused || active:
361
+ color = Color__default["default"].white;
362
+ break;
363
+ case hovered:
364
+ color = Color__default["default"].blue;
365
+ break;
366
+ default:
367
+ color = Color__default["default"].offBlack;
368
+ break;
369
+ }
370
+ const dynamicClass = active || focused ? styles$A.iconActive : styles$A.iconInactive;
371
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
372
+ style: [styles$A.iconContainer, dynamicClass]
373
+ }, /*#__PURE__*/React__namespace.createElement("svg", {
374
+ xmlns: "http://www.w3.org/2000/svg",
375
+ width: "16",
376
+ height: "16",
377
+ fill: color,
378
+ viewBox: "0 0 256 256"
379
+ }, /*#__PURE__*/React__namespace.createElement("path", {
380
+ d: "M112,72a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16h64A8,8,0,0,1,112,72Zm-8,104H80V152a8,8,0,0,0-16,0v24H40a8,8,0,0,0,0,16H64v24a8,8,0,0,0,16,0V192h24a8,8,0,0,0,0-16Zm48,0h64a8,8,0,0,0,0-16H152a8,8,0,0,0,0,16Zm64,16H152a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm-61.66-90.34a8,8,0,0,0,11.32,0L184,83.31l18.34,18.35a8,8,0,0,0,11.32-11.32L195.31,72l18.35-18.34a8,8,0,0,0-11.32-11.32L184,60.69,165.66,42.34a8,8,0,0,0-11.32,11.32L172.69,72,154.34,90.34A8,8,0,0,0,154.34,101.66Z"
381
+ })));
382
+ };
383
+ const mapButtonSets = buttonSets => {
384
+ const keypadButtonSets = {};
385
+ if (!buttonSets) {
386
+ return keypadButtonSets;
703
387
  }
704
- return /*#__PURE__*/React__namespace.createElement("div", {
705
- style: {
706
- display: "block",
707
- height: 0,
708
- width: 0,
709
- position: "absolute",
710
- left: props.left,
711
- top: props["top"],
712
- borderLeft: borderLeft,
713
- borderRight: borderRight,
714
- borderTop: borderTop,
715
- borderBottom: borderBottom
388
+ buttonSets.forEach(buttonSet => {
389
+ switch (buttonSet) {
390
+ case "advanced relations":
391
+ keypadButtonSets.advancedRelations = true;
392
+ break;
393
+ case "basic relations":
394
+ keypadButtonSets.basicRelations = true;
395
+ break;
396
+ case "basic+div":
397
+ keypadButtonSets.divisionKey = true;
398
+ break;
399
+ case "logarithms":
400
+ keypadButtonSets.logarithms = true;
401
+ break;
402
+ case "prealgebra":
403
+ keypadButtonSets.preAlgebra = true;
404
+ break;
405
+ case "trig":
406
+ keypadButtonSets.trigonometry = true;
407
+ break;
716
408
  }
717
409
  });
410
+ return keypadButtonSets;
718
411
  };
719
- const TooltipArrow = props => {
720
- // TODO(aria): Think about adding a box-shadow to the triangle here
721
- // See http://css-tricks.com/triangle-with-shadow/
722
-
723
- //const isRight = (this.props.horizontalDirection === "right");
724
- const isTop = props.verticalDirection === "top";
725
- const frontTopOffset = isTop ? 0 : 1;
726
- const borderTopOffset = isTop ? 0 : -1;
727
- return /*#__PURE__*/React__namespace.createElement("div", {
728
- style: {
729
- display: "block",
730
- position: props.position,
731
- visibility: props.visibility,
732
- left: props.left,
733
- top: props["top"],
734
- width: props.width + 2,
735
- height: props.height + 1,
736
- marginTop: -1,
737
- marginBottom: -2,
738
- zIndex: zIndex
739
- }
740
- }, /*#__PURE__*/React__namespace.createElement(Triangle, {
741
- horizontalDirection: props.horizontalDirection,
742
- verticalDirection: props.verticalDirection,
743
- color: props.border,
744
- left: 0,
745
- top: borderTopOffset,
746
- width: props.width + 2 // one extra for the diagonal
747
- ,
748
- height: props.height + 2
749
- }), /*#__PURE__*/React__namespace.createElement(Triangle, {
750
- horizontalDirection: props.horizontalDirection,
751
- verticalDirection: props.verticalDirection,
752
- color: props.color,
753
- left: 1,
754
- top: frontTopOffset,
755
- width: props.width,
756
- height: props.height
757
- }));
758
- };
759
- TooltipArrow.defaultProps = {
760
- position: "relative",
761
- visibility: "visible",
762
- left: 0,
763
- top: 0
412
+ const inputFocused = {
413
+ borderWidth: 2,
414
+ borderColor: Color__default["default"].blue,
415
+ margin: -1
764
416
  };
765
- const VERTICAL_CORNERS = {
766
- top: {
767
- top: "-100%"
417
+ const styles$A = aphrodite.StyleSheet.create({
418
+ iconContainer: {
419
+ display: "flex",
420
+ justifyContent: "center",
421
+ height: "100%",
422
+ padding: Spacing__default["default"].xxxSmall_4,
423
+ borderRadius: 1
768
424
  },
769
- bottom: {
770
- top: 0
771
- }
772
- };
773
- const HORIZONTAL_CORNERS = {
774
- left: {
775
- targetLeft: 0
425
+ iconInactive: {
426
+ backgroundColor: Color__default["default"].offBlack8
776
427
  },
777
- right: {
778
- targetLeft: "100%"
779
- }
780
- };
781
- const HORIZONTAL_ALIGNMNENTS = {
782
- left: {
783
- tooltipLeft: 0,
784
- arrowLeft: arrowSize => 0
428
+ iconActive: {
429
+ backgroundColor: Color__default["default"].offBlack64
785
430
  },
786
- right: {
787
- tooltipLeft: "-100%",
788
- arrowLeft: arrowSize => -arrowSize - 2
789
- }
790
- };
791
- class Tooltip extends React__namespace.Component {
792
- constructor() {
793
- super(...arguments);
794
- _defineProperty(this, "state", {
795
- height: null // used for offsetting "top" positioned tooltips
796
- });
797
- }
798
-
799
- componentDidMount() {
800
- this._updateHeight();
801
- }
802
- UNSAFE_componentWillReceiveProps() {
803
- // If the contents have changed, reset our measure of the height
804
- this.setState({
805
- height: null
806
- });
807
- }
808
- componentDidUpdate() {
809
- this._updateHeight();
810
- }
811
- _renderToolTipDiv(isTooltipAbove) {
812
- const settings = Object.assign({}, HORIZONTAL_CORNERS[this.props.horizontalPosition], HORIZONTAL_ALIGNMNENTS[this.props.horizontalAlign], VERTICAL_CORNERS[this.props.verticalPosition]);
813
- let arrowAbove;
814
- let arrowBelow;
815
- if (isTooltipAbove) {
816
- // We put an absolutely positioned arrow in the correct place
817
- arrowAbove = /*#__PURE__*/React__namespace.createElement(TooltipArrow, {
818
- verticalDirection: VerticalDirection.Top,
819
- horizontalDirection: this.props.horizontalAlign,
820
- position: "absolute",
821
- color: "white",
822
- border: this.props.borderColor,
823
- left: settings.arrowLeft(this.props.arrowSize),
824
- top: -this.props.arrowSize + 2,
825
- width: this.props.arrowSize,
826
- height: this.props.arrowSize,
827
- zIndex: zIndex
828
- });
829
-
830
- // And we use a visibility: hidden arrow below to shift up the
831
- // content by the correct amount
832
- arrowBelow = /*#__PURE__*/React__namespace.createElement(TooltipArrow, {
833
- verticalDirection: VerticalDirection.Top,
834
- horizontalDirection: this.props.horizontalAlign,
835
- visibility: "hidden",
836
- color: "white",
837
- border: this.props.borderColor,
838
- left: settings.arrowLeft(this.props.arrowSize),
839
- top: -1,
840
- width: this.props.arrowSize,
841
- height: this.props.arrowSize,
842
- zIndex: zIndex
843
- });
844
- } else {
845
- arrowAbove = /*#__PURE__*/React__namespace.createElement(TooltipArrow, {
846
- verticalDirection: VerticalDirection.Bottom,
847
- horizontalDirection: this.props.horizontalAlign,
848
- color: "white",
849
- border: this.props.borderColor,
850
- left: settings.arrowLeft(this.props.arrowSize),
851
- top: -1,
852
- width: this.props.arrowSize,
853
- height: this.props.arrowSize,
854
- zIndex: zIndex
855
- });
856
- arrowBelow = null;
857
- }
858
-
859
- /* A positioned div below the input to be the parent for our
860
- tooltip */
861
- return /*#__PURE__*/React__namespace.createElement("div", {
862
- style: {
863
- position: "relative",
864
- height: 0,
865
- display: this.props.show ? "block" : "none"
866
- }
867
- }, /*#__PURE__*/React__namespace.createElement("div", {
868
- // eslint-disable-next-line react/no-string-refs
869
- ref: "tooltipContainer",
870
- className: "tooltipContainer",
871
- style: {
872
- position: "absolute",
873
- // height must start out undefined, not null, so that
874
- // we can measure the actual height with jquery.
875
- // This is used to position the tooltip with top: -100%
876
- // when in verticalPosition: "top" mode
877
- height: this.state.height || undefined,
878
- left: settings.targetLeft
879
- }
880
- }, arrowAbove, /*#__PURE__*/React__namespace.createElement("div", {
881
- className: this.props.className
882
- // eslint-disable-next-line react/no-string-refs
883
- ,
884
- ref: "tooltipContent",
885
- style: {
886
- position: "relative",
887
- top: settings["top"],
888
- left: settings.tooltipLeft,
889
- border: "1px solid " + this.props.borderColor,
890
- boxShadow: "0 1px 3px " + this.props.borderColor,
891
- zIndex: zIndex - 1
892
- }
893
- }, this.props.children.slice(1)), arrowBelow));
894
- }
895
- _updateHeight() {
896
- const tooltipContainer = ReactDOM__default["default"].findDOMNode(
897
- // eslint-disable-next-line react/no-string-refs
898
- this.refs.tooltipContainer);
899
- const height = tooltipContainer.offsetHeight;
900
- if (height !== this.state.height) {
901
- this.setState({
902
- height
903
- });
431
+ outerWrapper: {
432
+ display: "inline-block",
433
+ borderStyle: "solid",
434
+ borderWidth: 1,
435
+ borderColor: Color__default["default"].offBlack50,
436
+ borderRadius: 3,
437
+ background: Color__default["default"].white,
438
+ ":hover": inputFocused
439
+ },
440
+ wrapperFocused: inputFocused,
441
+ wrapperError: {
442
+ borderColor: Color__default["default"].red,
443
+ background: Color.fade(Color__default["default"].red, 0.08),
444
+ ":hover": {
445
+ borderColor: Color__default["default"].red
904
446
  }
447
+ },
448
+ popoverContent: {
449
+ padding: 0,
450
+ paddingBottom: Spacing__default["default"].xxSmall_6,
451
+ maxWidth: "initial"
905
452
  }
906
- render() {
907
- const isTooltipAbove = this.props.verticalPosition === "top";
453
+ });
908
454
 
909
- /* We wrap the entire output in a span so that it displays inline */
910
- return /*#__PURE__*/React__namespace.createElement("span", null, isTooltipAbove && this._renderToolTipDiv(isTooltipAbove), /*#__PURE__*/React__namespace.createElement("div", {
911
- style: this.props.targetContainerStyle
912
- }, this.props.children[0]), !isTooltipAbove && this._renderToolTipDiv());
455
+ let _dependencies = null;
456
+ const setDependencies = dependencies => {
457
+ _dependencies = dependencies;
458
+ };
459
+ const getDependencies = () => {
460
+ if (_dependencies) {
461
+ return _dependencies;
462
+ }
463
+ throw new Error(["Perseus has not been provided required dependencies.", "setDependencies(dependencies) must be called first.", "Make sure Perseus is being imported from javascript/perseus/perseus.js."].join("\n"));
464
+ };
465
+ const DependenciesContext = /*#__PURE__*/React__namespace.createContext({
466
+ analytics: {
467
+ onAnalyticsEvent: async () => {}
913
468
  }
914
- }
915
-
916
- // Sorry. // Apology-Oriented-Programming
917
- _defineProperty(Tooltip, "defaultProps", {
918
- className: "",
919
- arrowSize: 10,
920
- borderColor: "#ccc",
921
- verticalPosition: VerticalDirection.Bottom,
922
- horizontalPosition: HorizontalDirection.Left,
923
- horizontalAlign: HorizontalDirection.Left,
924
- targetContainerStyle: {}
925
469
  });
926
470
 
927
471
  /**
928
- * Icon paths to be used with `inline-icon.jsx`.
929
- *
930
- * These paths are taken directly from webapp's `icon-paths.js`. Unlike the
931
- * webapp equivalent, these can be directly required within Perseus files since
932
- * this is all bundled together anyway.
472
+ * useDependencies provides easy access to the current Perseus dependencies.
933
473
  */
934
-
935
- const iconCheck = {
936
- path: "M8.70710678,12.2928932 C8.31658249,11.9023689 7.68341751,11.9023689 7.29289322,12.2928932 C6.90236893,12.6834175 6.90236893,13.3165825 7.29289322,13.7071068 L9.82842712,16.2426407 C10.2207367,16.6349502 10.8574274,16.6328935 11.2471942,16.2380576 L16.7116603,10.7025237 C17.0996535,10.3094846 17.0955629,9.67633279 16.7025237,9.28833966 C16.3094846,8.90034653 15.6763328,8.90443714 15.2883397,9.29747629 L10.5309507,14.1167372 L8.70710678,12.2928932 Z",
937
- width: 24,
938
- height: 24
939
- };
940
- const iconCheckMedium = {
941
- path: "M6.072 10.4l6.175-7.058a1 1 0 1 1 1.506 1.317L6.769 12.64a1 1 0 0 1-1.55-.054L2.203 8.604a1 1 0 1 1 1.594-1.208L6.072 10.4z",
942
- width: 16,
943
- height: 16
944
- };
945
- const iconChevronDown = {
946
- path: "M99.669 13.048q0 3.36-2.352 5.712l-41.664 41.664q-2.408 2.408-5.88 2.408t-5.712-2.408l-41.664-41.664q-2.408-2.24-2.408-5.712t2.408-5.88l4.76-4.816q2.52-2.352 5.88-2.352t5.656 2.352l31.136 31.136 31.08-31.136q2.352-2.352 5.712-2.352t5.88 2.352l4.816 4.816q2.352 2.52 2.352 5.88z",
947
- width: 100,
948
- height: 63.034
949
- };
950
- const iconChevronRight = {
951
- path: "M62.808 49.728q0 3.36-2.352 5.88l-41.72 41.664q-2.352 2.408-5.768 2.408t-5.768-2.408l-4.872-4.76q-2.352-2.52-2.352-5.88t2.352-5.712l31.08-31.136-31.08-31.024q-2.352-2.52-2.352-5.88t2.352-5.712l4.872-4.76q2.296-2.408 5.768-2.408t5.768 2.408l41.72 41.664q2.352 2.296 2.352 5.656z",
952
- width: 63.034,
953
- height: 100
954
- };
955
- const iconCircle = {
956
- path: "M100.035 50.046q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
957
- width: 100,
958
- height: 100
959
- };
960
- const iconCircleArrowDown = {
961
- path: "M50.046 83.676q1.767 0 2.907-1.14l29.526-29.526q1.197-1.197 1.197-2.907t-1.197-2.964l-5.928-5.928q-1.197-1.14-2.964-1.14t-2.907 1.14l-12.312 12.312l0-32.661q0-1.71-1.254-2.964t-2.907-1.254l-8.322 0q-1.71 0-2.964 1.254t-1.254 2.964l0 32.661l-12.312-12.312q-1.197-1.254-2.907-1.254t-2.907 1.254l-5.928 5.928q-1.197 1.197-1.197 2.964t1.197 2.907l29.469 29.526q1.197 1.14 2.964 1.14zm49.989-33.63q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
962
- width: 100,
963
- height: 100
964
- };
965
- const iconCircleArrowUp = {
966
- path: "M54.207 83.391q1.653 0 2.907-1.254t1.254-2.907l0-32.718l12.312 12.312q1.254 1.254 2.964 1.254t2.907-1.254l5.928-5.928q1.197-1.197 1.14-2.964 0-1.767-1.14-2.907l-29.526-29.526q-1.197-1.14-2.907-1.14t-2.964 1.14l-29.469 29.526q-1.197 1.254-1.197 2.964t1.197 2.907l5.928 5.928q1.197 1.197 2.907 1.197t2.907-1.197l12.312-12.312l0 32.718q0 1.653 1.254 2.907t2.964 1.254l8.322 0zm45.828-33.345q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
967
- width: 100,
968
- height: 100
969
- };
970
- const iconCircleThin = {
971
- path: "M50.046 8.322q-8.493 0-16.188 3.306-15.561 6.669-22.173 22.23-3.363 7.695-3.363 16.188t3.306 16.188 8.949 13.281q5.586 5.586 13.281 8.892t16.188 3.306 16.188-3.306 13.281-8.892 8.892-13.281 3.306-16.188-3.306-16.188-8.892-13.281-13.281-8.949q-7.695-3.306-16.188-3.306zm0 91.713q-13.623 0-25.137-6.726t-18.183-18.183q-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.726 25.137-6.726 25.137-18.24 18.126q-11.514 6.726-25.08 6.726z",
972
- width: 100,
973
- height: 99.944
974
- };
975
- const iconDesktop = {
976
- path: "M94.208 52.119l0-43.746q0-.69-.506-1.15t-1.196-.506l-84.088 0q-.69 0-1.196.506t-.506 1.15l0 43.746q0 .69.506 1.196t1.196.506l84.088 0q.69 0 1.196-.506t.506-1.196zm6.716-43.746l0 57.224q0 3.45-2.484 5.934t-5.934 2.484l-28.566 0q0 3.128 2.53 7.774.828 1.61.828 2.622t-1.012 2.07q-1.012 1.012-2.346.966l-26.91 0q-1.38 0-2.392-1.012t-1.012-2.024q0-1.058 1.656-4.14t1.748-6.256l-28.612 0q-3.45 0-5.934-2.484t-2.484-5.934l0-57.224q0-3.45 2.484-5.934t5.934-2.438l84.088 0q3.45 0 5.98 2.438 2.438 2.484 2.438 5.934z",
977
- width: 100,
978
- height: 86.648
979
- };
980
- const iconDropdownArrow = {
981
- path: "M9 9.8c0 .5.7 1.7 1.5 2.8 1.5 1.9 1.5 1.9 3 0C15.7 9.7 15.4 9 12 9c-1.6 0-3 .4-3 .8z",
982
- width: 24,
983
- height: 24
984
- };
985
- const iconExclamationSign = {
986
- path: "M58.368 81.225l0-12.369q0-.912-.57-1.539t-1.425-.627l-12.54 0q-.855-.057-1.482.627t-.684 1.539l0 12.369q-.057.855.627 1.482t1.539.684l12.54 0q.855 0 1.425-.627t.57-1.539zm1.026-62.871q0-1.596-2.223-1.71l-14.307 0q-2.109 0-2.223 1.71l1.14 40.47q0 .627.627 1.14t1.539.456l12.084 0q.912-.057 1.539-.513t.684-1.083zm-9.348-18.354q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.726 25.137-6.726 25.137-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669z",
987
- width: 100,
988
- height: 99.944
989
- };
990
- // Grabbed from https://github.com/encharm/Font-Awesome-SVG-PNG
991
- const iconGear = {
992
- path: "M1152 896q0-106-75-181t-181-75-181 75-75 181 75 181 181 75 181-75 75-181zm512-109v222q0 12-8 23t-20 13l-185 28q-19 54-39 91 35 50 107 138 10 12 10 25t-9 23q-27 37-99 108t-94 71q-12 0-26-9l-138-108q-44 23-91 38-16 136-29 186-7 28-36 28h-222q-14 0-24.5-8.5t-11.5-21.5l-28-184q-49-16-90-37l-141 107q-10 9-25 9-14 0-25-11-126-114-165-168-7-10-7-23 0-12 8-23 15-21 51-66.5t54-70.5q-27-50-41-99l-183-27q-13-2-21-12.5t-8-23.5v-222q0-12 8-23t19-13l186-28q14-46 39-92-40-57-107-138-10-12-10-24 0-10 9-23 26-36 98.5-107.5t94.5-71.5q13 0 26 10l138 107q44-23 91-38 16-136 29-186 7-28 36-28h222q14 0 24.5 8.5t11.5 21.5l28 184q49 16 90 37l142-107q9-9 24-9 13 0 25 10 129 119 165 170 7 8 7 22 0 12-8 23-15 21-51 66.5t-54 70.5q26 50 41 98l183 28q13 2 21 12.5t8 23.5z",
993
- width: 1792,
994
- height: 1792
995
- };
996
- const iconMobilePhone = {
997
- path: "M36.04 89.557q0-2.584-1.836-4.42t-4.42-1.836-4.352 1.836q-1.836 1.836-1.836 4.42t1.836 4.352 4.42 1.836q2.652-.068 4.42-1.836t1.768-4.352zm16.184-12.444l0-54.74q0-1.088-.748-1.768t-1.768-.68l-39.78 0q-1.088 0-1.768.748t-.68 1.7l0 54.74q0 1.02.748 1.768t1.7.68l39.78 0q1.02-.068 1.768-.748t.748-1.7zm-14.892-65.892q0-1.224-1.292-1.292l-12.444 0q-1.224.068-1.224 1.292t1.224 1.224l12.444 0q1.292 0 1.292-1.224zm22.372-1.292l0 79.628q0 3.944-2.992 6.936t-7.004 2.992l-39.78 0q-4.012 0-7.004-2.924-2.924-2.924-2.924-7.004l0-79.628q0-4.012 2.924-6.936t7.004-2.992l39.78 0q4.012-.068 7.004 2.924t2.992 7.004z",
998
- width: 60.013,
999
- height: 100
1000
- };
1001
- const iconOk = {
1002
- path: "M37.964 76.048q-2.576 0-4.368-1.792l-31.864-31.864q-1.792-1.792-1.792-4.368t1.792-4.368l8.736-8.68q1.792-1.792 4.368-1.792t4.312 1.792l18.816 18.872 42-42.056q1.792-1.792 4.368-1.792t4.312 1.792l8.736 8.736q1.792 1.792 1.792 4.368t-1.792 4.312l-55.048 55.048q-1.792 1.792-4.368 1.792z",
1003
- width: 100,
1004
- height: 76.637
1005
- };
1006
- const iconPlus = {
1007
- path: "M99.758 43.09l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-29.45 0l0 29.45q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-29.45l-29.45 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l29.45 0l0-29.45q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836l0 29.45l29.45 0q2.852 0 4.836 1.984t1.984 4.836z",
1008
- width: 100,
1009
- height: 100
1010
- };
1011
- const iconRemove = {
1012
- path: "M100.464 80.808q0 3.404-2.368 5.772l-11.47 11.544q-2.368 2.368-5.772 2.368t-5.698-2.368l-24.864-24.864-24.864 24.864q-2.368 2.368-5.772 2.368t-5.772-2.368l-11.47-11.544q-2.368-2.368-2.368-5.772t2.368-5.698l24.864-24.864-24.864-24.864q-2.368-2.368-2.368-5.772t2.368-5.772l11.47-11.47q2.368-2.368 5.772-2.368t5.772 2.368l24.864 24.864 24.864-24.864q2.294-2.368 5.698-2.368t5.772 2.368l11.47 11.47q2.368 2.368 2.368 5.772t-2.368 5.772l-24.864 24.864 24.864 24.864q2.368 2.294 2.368 5.698z",
1013
- width: 100,
1014
- height: 100
1015
- };
1016
- const iconStar = {
1017
- path: "M15.1052249,9.55978547 L22.0028147,9.55978545 C23.6568673,9.55978545 23.9349557,10.3753626 22.6181351,11.3858845 L16.9943688,15.7015366 L19.2518801,22.8294455 C19.7526645,24.4106317 19.0984455,24.8825885 17.769353,23.8673293 L12.0490577,19.4977438 L6.5116497,23.8422153 C5.20921411,24.8640642 4.53299569,24.4067544 5.00266927,22.8160582 L7.10332364,15.7015366 L1.42794544,11.3634306 C0.110226041,10.3562014 0.383967283,9.54239221 2.0409646,9.54574013 L8.9924676,9.55978547 L11.1485117,2.72669438 C11.6458693,1.15043244 12.4548928,1.15900049 12.9494787,2.72669438 L15.1052249,9.55978547 Z",
1018
- width: 24,
1019
- height: 24
1020
- };
1021
- const iconTryAgain = {
1022
- path: "M3.74890556,17.9799506 C2.19251241,16.1970909 1.10103636,13.4971457 1.13090903,11.1491783 C1.17160478,7.95052637 4.01704076,0.865059407 11.7028044,0.865059407 C19.388568,0.865059407 22.3026521,7.35203035 22.3026521,11.5879453 C22.3026521,15.8238603 19.386629,20.5574509 13.6832464,21.7131548 L13.6757539,17.3722171 C17.0812986,16.2190517 18.331158,14.1944123 18.3311578,11.5879451 C18.3311574,8.16554692 15.6664205,5.03476549 11.7028048,5.20494205 C7.73918903,5.37511861 5.59244567,8.66930079 5.59244567,11.1491783 C5.59244567,12.9090077 6.11128139,14.1753512 6.93640437,15.3053215 L8.14052356,14.2949456 C8.98559348,13.5858477 9.6994861,13.9070448 9.73489556,15.0076413 L9.91284941,20.5388014 C9.94832683,21.6415103 9.09967118,22.3514475 8.02194403,22.1254594 L2.60571602,20.9897332 C1.5259204,20.7633114 1.34338662,19.9984207 2.18070755,19.295825 L3.74890556,17.9799506 Z",
1023
- width: 23,
1024
- height: 23
1025
- };
1026
- const iconTablet = {
1027
- path: "M45.322 90.706q0-1.86-1.302-3.224-1.364-1.364-3.224-1.364t-3.224 1.364-1.302 3.224q0 1.86 1.364 3.224 1.302 1.364 3.162 1.302 1.86.062 3.224-1.302t1.302-3.224zm27.218-11.346l0-68.014q0-.93-.682-1.612t-1.55-.682l-58.962 0q-.93 0-1.612.682t-.682 1.612l0 68.014q0 .93.682 1.612t1.612.62l58.962 0q.992-.062 1.612-.682t.62-1.55zm9.114-68.014l0 77.066q0 4.65-3.348 7.998t-7.998 3.348l-58.962 0q-4.65 0-7.998-3.348t-3.348-7.998l0-77.066q0-4.65 3.348-7.998t7.998-3.348l58.962 0q4.65 0 7.998 3.348t3.348 7.998z",
1028
- width: 81.852,
1029
- height: 100
1030
- };
1031
- const iconTrash = {
1032
- path: "M31.293 37.506q2.052 0 2.052 2.109l0 37.506q0 1.995-2.052 2.109l-4.218 0q-.912-.057-1.482-.627t-.57-1.482l0-37.506q0-2.109 2.052-2.109l4.218 0zm18.753 2.109l0 37.506q0 .912-.57 1.482t-1.539.627l-4.161 0q-1.995 0-2.109-2.109l0-37.506q.057-.912.627-1.482t1.482-.627l4.161 0q.969.057 1.539.627t.57 1.482zm14.592-2.109q2.052 0 2.052 2.109l0 37.506q0 1.995-2.052 2.109l-4.161 0q-.969-.057-1.539-.627t-.57-1.482l0-37.506q0-2.109 2.109-2.109l4.161 0zm10.431 49.248l0-61.731l-58.368 0l0 61.731q.057 2.679.969 3.819t1.083 1.14l54.207 0q.171 0 1.14-1.083t.969-3.876zm-43.776-70.11l29.184 0l-3.135-7.581q-.456-.57-1.14-.741l-20.634 0q-.627.114-1.083.741zm-31.293 2.109q0-1.995 2.109-2.109l20.121 0l4.56-10.83q.969-2.394 3.477-4.104 2.565-1.71 5.187-1.71l20.805 0q2.622 0 5.187 1.71t3.477 4.104l4.56 10.83l20.178 0q.912.057 1.482.627t.57 1.482l0 4.161q0 1.995-2.052 2.109l-6.27 0l0 61.731q0 5.415-3.078 9.348t-7.353 3.933l-54.207 0q-4.275 0-7.353-3.819t-3.078-9.177l0-62.016l-6.213 0q-.969 0-1.539-.57t-.57-1.539l0-4.161z",
1033
- width: 91.681,
1034
- height: 100
1035
- };
1036
- const iconUndo = {
1037
- path: "M10,6.6C10,7.2,9.8,8,9.3,9.1c0,0,0,0.1-0.1,0.1S9.2,9.3,9.2,9.4c0,0,0,0.1-0.1,0.1C9,9.6,9,9.6,8.9,9.6 c-0.1,0-0.1,0-0.1-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1s0-0.1,0-0.1c0-0.3,0-0.5,0-0.7c0-0.4,0-0.7-0.1-1C8.6,7.1,8.5,6.9,8.4,6.7S8.2,6.3,8,6.1C7.8,5.9,7.6,5.8,7.4,5.7S6.9,5.5,6.7,5.5S6.1,5.4,5.8,5.4c-0.3,0-0.6,0-1,0H3.6v1.4c0,0.1,0,0.2-0.1,0.3C3.4,7.1,3.3,7.1,3.2,7.1C3.1,7.1,3,7.1,3,7L0.1,4.1C0,4.1,0,4,0,3.9s0-0.2,0.1-0.3L3,0.8C3,0.7,3.1,0.7,3.2,0.7c0.1,0,0.2,0,0.3,0.1C3.5,0.9,3.6,0.9,3.6,1v1.4h1.2c2.6,0,4.3,0.7,4.9,2.2C9.9,5.2,10,5.8,10,6.6z",
1038
- width: 10,
1039
- height: 10
1040
- };
1041
- const iconMinus = {
1042
- path: "M8,13 L16,13 C16.5522847,13 17,12.5522847 17,12 C17,11.4477153 16.5522847,11 16,11 L8,11 C7.44771525,11 7,11.4477153 7,12 C7,12.5522847 7.44771525,13 8,13 Z",
1043
- width: 24,
1044
- height: 24
474
+ const useDependencies = () => {
475
+ const deps = React__namespace.useContext(DependenciesContext);
476
+ return deps;
1045
477
  };
1046
478
 
1047
- var iconPaths = /*#__PURE__*/Object.freeze({
479
+ var dependencies = /*#__PURE__*/Object.freeze({
1048
480
  __proto__: null,
1049
- iconCheck: iconCheck,
1050
- iconCheckMedium: iconCheckMedium,
1051
- iconChevronDown: iconChevronDown,
1052
- iconChevronRight: iconChevronRight,
1053
- iconCircle: iconCircle,
1054
- iconCircleArrowDown: iconCircleArrowDown,
1055
- iconCircleArrowUp: iconCircleArrowUp,
1056
- iconCircleThin: iconCircleThin,
1057
- iconDesktop: iconDesktop,
1058
- iconDropdownArrow: iconDropdownArrow,
1059
- iconExclamationSign: iconExclamationSign,
1060
- iconGear: iconGear,
1061
- iconMobilePhone: iconMobilePhone,
1062
- iconOk: iconOk,
1063
- iconPlus: iconPlus,
1064
- iconRemove: iconRemove,
1065
- iconStar: iconStar,
1066
- iconTryAgain: iconTryAgain,
1067
- iconTablet: iconTablet,
1068
- iconTrash: iconTrash,
1069
- iconUndo: iconUndo,
1070
- iconMinus: iconMinus
481
+ setDependencies: setDependencies,
482
+ getDependencies: getDependencies,
483
+ DependenciesContext: DependenciesContext,
484
+ useDependencies: useDependencies
1071
485
  });
1072
486
 
1073
487
  // TODO(LP-11481): Change the primary API we use for logging in Perseus to use
@@ -1579,6 +993,26 @@ const ClassNames = {
1579
993
  MOBILE: "perseus-mobile"
1580
994
  };
1581
995
 
996
+ /*
997
+ * A11y (Accessibility) style rules
998
+ * These are used to mark up areas on the site that should only be readable
999
+ * when using a screen reader.
1000
+ */
1001
+ var a11y = aphrodite.StyleSheet.create({
1002
+ // Make content only visible to screen readers.
1003
+ // Both collegeboard.org and Bootstrap 3 use this exact implementation.
1004
+ srOnly: {
1005
+ border: 0,
1006
+ clip: "rect(0,0,0,0)",
1007
+ height: 1,
1008
+ margin: -1,
1009
+ overflow: "hidden",
1010
+ padding: 0,
1011
+ position: "absolute",
1012
+ width: 1
1013
+ }
1014
+ });
1015
+
1582
1016
  const KhanMath = {
1583
1017
  // Simplify formulas before display
1584
1018
  cleanMath: function (expr) {
@@ -2494,6 +1928,7 @@ const KhanAnswerTypes = {
2494
1928
  }
2495
1929
  };
2496
1930
 
1931
+ const ERROR_TITLE = i18n__namespace._("Oops!");
2497
1932
  const ERROR_MESSAGE = i18n__namespace._("Sorry, I don't understand that!");
2498
1933
  const insertBraces = value => {
2499
1934
  // HACK(alex): Make sure that all LaTeX super/subscripts are wrapped
@@ -2530,53 +1965,48 @@ class Expression extends React__namespace.Component {
2530
1965
  super(...arguments);
2531
1966
  _this = this;
2532
1967
  _defineProperty(this, "_isMounted", false);
2533
- _defineProperty(this, "errorTimeout", null);
2534
1968
  _defineProperty(this, "displayName", "Expression");
2535
1969
  _defineProperty(this, "state", {
1970
+ invalid: false,
2536
1971
  showErrorTooltip: false,
2537
- showErrorText: false
1972
+ showErrorStyle: false
2538
1973
  });
2539
1974
  _defineProperty(this, "componentDidMount", () => {
1975
+ document.addEventListener("mousedown", this._handleMouseDown);
1976
+
2540
1977
  // TODO(scottgrant): This is a hack to remove the deprecated call to
2541
1978
  // this.isMounted() but is still considered an anti-pattern.
2542
1979
  this._isMounted = true;
2543
1980
  });
2544
1981
  _defineProperty(this, "componentDidUpdate", prevProps => {
2545
1982
  if (!___default["default"].isEqual(this.props.value, prevProps.value) || !___default["default"].isEqual(this.props.functions, prevProps.functions)) {
2546
- // TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
2547
- // eslint-disable-next-line no-restricted-syntax
2548
- // @ts-expect-error - TS2769 - No overload matches this call.
2549
- clearTimeout(this.errorTimeout);
2550
- if (this.parse(this.props.value, this.props).parsed) {
2551
- // eslint-disable-next-line react/no-did-update-set-state
2552
- this.setState({
2553
- showErrorTooltip: false
2554
- });
2555
- } else {
2556
- // Store timeout ID so that we can clear it above
2557
- // TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
2558
- // eslint-disable-next-line no-restricted-syntax
2559
- // @ts-expect-error - TS2322 - Type 'Timeout' is not assignable to type 'number'.
2560
- this.errorTimeout = setTimeout(() => {
2561
- const apiResult = this.props.apiOptions.onInputError(null,
2562
- // reserved for some widget identifier
2563
- this.props.value, ERROR_MESSAGE);
2564
- if (apiResult !== false) {
2565
- this.setState({
2566
- showErrorTooltip: true
2567
- });
2568
- }
2569
- }, 2000);
1983
+ this.setState({
1984
+ invalid: false,
1985
+ showErrorTooltip: false,
1986
+ showErrorStyle: false
1987
+ });
1988
+ if (!this.parse(this.props.value, this.props).parsed) {
1989
+ const apiResult = this.props.apiOptions.onInputError(null,
1990
+ // reserved for some widget identifier
1991
+ this.props.value, ERROR_MESSAGE);
1992
+ if (apiResult !== false) {
1993
+ this.setState({
1994
+ invalid: true
1995
+ });
1996
+ }
2570
1997
  }
2571
1998
  }
2572
1999
  });
2573
2000
  _defineProperty(this, "componentWillUnmount", () => {
2574
- // TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
2575
- // eslint-disable-next-line no-restricted-syntax
2576
- // @ts-expect-error - TS2769 - No overload matches this call.
2577
- clearTimeout(this.errorTimeout);
2578
2001
  this._isMounted = false;
2579
2002
  });
2003
+ _defineProperty(this, "_handleMouseDown", () => {
2004
+ if (this._isMounted && this.state.showErrorTooltip) {
2005
+ this.setState({
2006
+ showErrorTooltip: false
2007
+ });
2008
+ }
2009
+ });
2580
2010
  _defineProperty(this, "simpleValidate", (rubric, onInputError) => {
2581
2011
  onInputError = onInputError || function () {};
2582
2012
  const result = Expression.validate(this.getUserInput(), rubric, onInputError);
@@ -2606,7 +2036,8 @@ class Expression extends React__namespace.Component {
2606
2036
  this.props.trackInteraction();
2607
2037
  });
2608
2038
  _defineProperty(this, "_handleFocus", () => {
2609
- this.props.analytics.onAnalyticsEvent({
2039
+ var _this$props$analytics;
2040
+ (_this$props$analytics = this.props.analytics) === null || _this$props$analytics === void 0 ? void 0 : _this$props$analytics.onAnalyticsEvent({
2610
2041
  type: "perseus:expression-focused",
2611
2042
  payload: null
2612
2043
  });
@@ -2814,7 +2245,8 @@ class Expression extends React__namespace.Component {
2814
2245
  this.refs.input.insert(keyPressed);
2815
2246
  }
2816
2247
  sendExpressionEvaluatedEvent(result) {
2817
- this.props.analytics.onAnalyticsEvent({
2248
+ var _this$props$analytics2;
2249
+ (_this$props$analytics2 = this.props.analytics) === null || _this$props$analytics2 === void 0 ? void 0 : _this$props$analytics2.onAnalyticsEvent({
2818
2250
  type: "perseus:expression-evaluated",
2819
2251
  payload: {
2820
2252
  result,
@@ -2823,6 +2255,7 @@ class Expression extends React__namespace.Component {
2823
2255
  });
2824
2256
  }
2825
2257
  render() {
2258
+ var _this$props$keypadCon, _this$props$analytics3;
2826
2259
  if (this.props.apiOptions.customKeypad) {
2827
2260
  return /*#__PURE__*/React__namespace.createElement(mathInput.KeypadInput
2828
2261
  // eslint-disable-next-line react/no-string-refs
@@ -2845,47 +2278,27 @@ class Expression extends React__namespace.Component {
2845
2278
  onBlur: this._handleBlur
2846
2279
  });
2847
2280
  }
2848
- // TODO(alex): Style this tooltip to be more consistent with other
2849
- // tooltips on the site; align to left middle (once possible)
2850
- const errorTooltip = /*#__PURE__*/React__namespace.createElement("span", {
2851
- className: "error-tooltip",
2852
- role: "tooltip"
2853
- }, /*#__PURE__*/React__namespace.createElement(Tooltip, {
2854
- className: "error-text-container",
2855
- horizontalPosition: HorizontalDirection.Right,
2856
- horizontalAlign: HorizontalDirection.Left,
2857
- verticalPosition: VerticalDirection.Top,
2858
- arrowSize: 10,
2859
- borderColor: "#fcc335",
2860
- show: this.state.showErrorText
2861
- }, /*#__PURE__*/React__namespace.createElement("span", {
2862
- className: "error-icon",
2863
- "data-test-id": "test-error-icon",
2864
- onMouseEnter: () => {
2865
- this.setState({
2866
- showErrorText: true
2867
- });
2868
- },
2869
- onMouseLeave: () => {
2870
- this.setState({
2871
- showErrorText: false
2872
- });
2873
- },
2874
- onClick: () => {
2875
- // TODO(alex): Better error feedback for mobile
2876
- this.setState({
2877
- showErrorText: !this.state.showErrorText
2878
- });
2879
- }
2880
- }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconExclamationSign)), /*#__PURE__*/React__namespace.createElement("div", {
2881
- className: "error-text"
2882
- }, ERROR_MESSAGE)));
2883
2281
  const className = classNames__default["default"]({
2884
2282
  "perseus-widget-expression": true,
2885
2283
  "show-error-tooltip": this.state.showErrorTooltip
2886
2284
  });
2887
2285
  return /*#__PURE__*/React__namespace.createElement("div", {
2888
- className: className
2286
+ className: className,
2287
+ onBlur: () => this.state.invalid && this.setState({
2288
+ showErrorTooltip: true,
2289
+ showErrorStyle: true
2290
+ }),
2291
+ onFocus: () => this.setState({
2292
+ showErrorTooltip: false
2293
+ })
2294
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
2295
+ style: a11y.srOnly,
2296
+ role: "alert"
2297
+ }, this.state.showErrorTooltip && ERROR_TITLE + " " + ERROR_MESSAGE), /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
2298
+ forceAnchorFocusivity: false,
2299
+ opened: this.state.showErrorTooltip,
2300
+ title: ERROR_TITLE,
2301
+ content: ERROR_MESSAGE
2889
2302
  }, /*#__PURE__*/React__namespace.createElement(MathInput
2890
2303
  // eslint-disable-next-line react/no-string-refs
2891
2304
  , {
@@ -2894,11 +2307,15 @@ class Expression extends React__namespace.Component {
2894
2307
  value: this.props.value,
2895
2308
  onChange: this.changeAndTrack,
2896
2309
  convertDotToTimes: this.props.times,
2897
- buttonsVisible: this.props.buttonsVisible || "focused",
2898
2310
  buttonSets: this.props.buttonSets,
2899
2311
  onFocus: this._handleFocus,
2900
- onBlur: this._handleBlur
2901
- }), this.state.showErrorTooltip && errorTooltip);
2312
+ onBlur: this._handleBlur,
2313
+ hasError: this.state.showErrorStyle,
2314
+ extraKeys: (_this$props$keypadCon = this.props.keypadConfiguration) === null || _this$props$keypadCon === void 0 ? void 0 : _this$props$keypadCon.extraKeys,
2315
+ analytics: (_this$props$analytics3 = this.props.analytics) !== null && _this$props$analytics3 !== void 0 ? _this$props$analytics3 : {
2316
+ onAnalyticsEvent: async () => {}
2317
+ }
2318
+ })));
2902
2319
  }
2903
2320
  }
2904
2321
 
@@ -2941,11 +2358,18 @@ const keypadConfigurationForProps = widgetOptions => {
2941
2358
  // and Theta, so we special-case.
2942
2359
  const isGreek = symbol => symbol === "pi" || symbol === "theta";
2943
2360
  const toKey = symbol => isGreek(symbol) ? symbol.toUpperCase() : symbol;
2361
+ const isKey = key => mathInput.KeyArray.includes(key);
2944
2362
  for (const variable of expr.getVars()) {
2945
- uniqueExtraVariables[toKey(variable)] = true;
2363
+ const maybeKey = toKey(variable);
2364
+ if (isKey(maybeKey)) {
2365
+ uniqueExtraVariables[maybeKey] = true;
2366
+ }
2946
2367
  }
2947
2368
  for (const constant of expr.getConsts()) {
2948
- uniqueExtraConstants[toKey(constant)] = true;
2369
+ const maybeKey = toKey(constant);
2370
+ if (isKey(maybeKey)) {
2371
+ uniqueExtraConstants[maybeKey] = true;
2372
+ }
2949
2373
  }
2950
2374
  }
2951
2375
  }
@@ -15008,6 +14432,200 @@ ___default["default"].extend(MovableLine$4.prototype, {
15008
14432
  }
15009
14433
  });
15010
14434
 
14435
+ /**
14436
+ * A stripped version of Icon.jsx from webapp. Takes an SVG icon and renders it
14437
+ * inline like Font Awesome did.
14438
+ *
14439
+ * If you are looking for an icon that we've used before you should look in
14440
+ * webapp's `icon-paths.js` which is a reference file for all the SVG paths
14441
+ * that we've used. You'll need to copy the object from that file into
14442
+ * whichever file you're using the icon and explicitly pass it in to the
14443
+ * <InlineIcon/> React component.
14444
+ *
14445
+ * We assume that the viewBox is cropped and aligned to (0, 0), but icons can
14446
+ * be defined differently. At some point we might want to add these attributes
14447
+ * to `icon-paths.js`, but for now this is a fairly safe assumption.
14448
+ *
14449
+ * Sample usage:
14450
+ *
14451
+ * const editIcon = {
14452
+ * path: "M41.209 53.753l5.39 0l0 5.39l3.136 0l6.468-6.517-8.477-8.526-6.517 6.517l0 3.136zm33.173-34.937q-.882-.882-1.862.049l-19.6 19.6q-.931.98-.049 1.862t1.862-.049l19.6-19.6q.931-.98.049-1.862zm-38.563 45.668l0-16.121l37.632-37.632 16.17 16.121-37.632 37.632l-16.17 0zm43.022-12.397l0 10.633q-.049 6.713-4.753 11.417t-11.368 4.704l-46.599 0q-6.713 0-11.417-4.753t-4.704-11.368l0-46.599q0-6.664 4.753-11.417t11.368-4.704l46.599 0q3.528 0 6.566 1.372.833.392.98 1.323t-.49 1.617l-2.744 2.744q-.784.784-1.96.441t-2.352-.343l-46.599 0q-3.675 0-6.321 2.646t-2.646 6.321l0 46.599q0 3.675 2.646 6.321t6.321 2.646l46.599 0q3.675 0 6.321-2.646t2.646-6.321l0-7.056q0-.735.49-1.225l3.577-3.577q.833-.833 1.96-.392t1.127 1.617zm7.203-51.646q2.254 0 3.773 1.568l8.526 8.526q1.568 1.568 1.568 3.822t-1.568 3.773l-5.145 5.145-16.121-16.121 5.145-5.145q1.568-1.568 3.822-1.568z",
14453
+ * width: 100,
14454
+ * height: 78.912,
14455
+ * };
14456
+ * <InlineIcon {...editIcon} />
14457
+ *
14458
+ */
14459
+ const InlineIcon = _ref => {
14460
+ let {
14461
+ path,
14462
+ width,
14463
+ height,
14464
+ style = {},
14465
+ title
14466
+ } = _ref;
14467
+ return /*#__PURE__*/React__namespace.createElement("svg", {
14468
+ role: "img",
14469
+ "aria-hidden": !title,
14470
+ style: {
14471
+ verticalAlign: "middle",
14472
+ ...style
14473
+ },
14474
+ width: "".concat(width / height, "em"),
14475
+ height: "1em",
14476
+ viewBox: "0 0 ".concat(width, " ").concat(height)
14477
+ }, !!title && /*#__PURE__*/React__namespace.createElement("title", null, title), /*#__PURE__*/React__namespace.createElement("path", {
14478
+ d: path,
14479
+ fill: "currentColor"
14480
+ }));
14481
+ };
14482
+
14483
+ /**
14484
+ * Icon paths to be used with `inline-icon.jsx`.
14485
+ *
14486
+ * These paths are taken directly from webapp's `icon-paths.js`. Unlike the
14487
+ * webapp equivalent, these can be directly required within Perseus files since
14488
+ * this is all bundled together anyway.
14489
+ */
14490
+
14491
+ const iconCheck = {
14492
+ path: "M8.70710678,12.2928932 C8.31658249,11.9023689 7.68341751,11.9023689 7.29289322,12.2928932 C6.90236893,12.6834175 6.90236893,13.3165825 7.29289322,13.7071068 L9.82842712,16.2426407 C10.2207367,16.6349502 10.8574274,16.6328935 11.2471942,16.2380576 L16.7116603,10.7025237 C17.0996535,10.3094846 17.0955629,9.67633279 16.7025237,9.28833966 C16.3094846,8.90034653 15.6763328,8.90443714 15.2883397,9.29747629 L10.5309507,14.1167372 L8.70710678,12.2928932 Z",
14493
+ width: 24,
14494
+ height: 24
14495
+ };
14496
+ const iconCheckMedium = {
14497
+ path: "M6.072 10.4l6.175-7.058a1 1 0 1 1 1.506 1.317L6.769 12.64a1 1 0 0 1-1.55-.054L2.203 8.604a1 1 0 1 1 1.594-1.208L6.072 10.4z",
14498
+ width: 16,
14499
+ height: 16
14500
+ };
14501
+ const iconChevronDown = {
14502
+ path: "M99.669 13.048q0 3.36-2.352 5.712l-41.664 41.664q-2.408 2.408-5.88 2.408t-5.712-2.408l-41.664-41.664q-2.408-2.24-2.408-5.712t2.408-5.88l4.76-4.816q2.52-2.352 5.88-2.352t5.656 2.352l31.136 31.136 31.08-31.136q2.352-2.352 5.712-2.352t5.88 2.352l4.816 4.816q2.352 2.52 2.352 5.88z",
14503
+ width: 100,
14504
+ height: 63.034
14505
+ };
14506
+ const iconChevronRight = {
14507
+ path: "M62.808 49.728q0 3.36-2.352 5.88l-41.72 41.664q-2.352 2.408-5.768 2.408t-5.768-2.408l-4.872-4.76q-2.352-2.52-2.352-5.88t2.352-5.712l31.08-31.136-31.08-31.024q-2.352-2.52-2.352-5.88t2.352-5.712l4.872-4.76q2.296-2.408 5.768-2.408t5.768 2.408l41.72 41.664q2.352 2.296 2.352 5.656z",
14508
+ width: 63.034,
14509
+ height: 100
14510
+ };
14511
+ const iconCircle = {
14512
+ path: "M100.035 50.046q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
14513
+ width: 100,
14514
+ height: 100
14515
+ };
14516
+ const iconCircleArrowDown = {
14517
+ path: "M50.046 83.676q1.767 0 2.907-1.14l29.526-29.526q1.197-1.197 1.197-2.907t-1.197-2.964l-5.928-5.928q-1.197-1.14-2.964-1.14t-2.907 1.14l-12.312 12.312l0-32.661q0-1.71-1.254-2.964t-2.907-1.254l-8.322 0q-1.71 0-2.964 1.254t-1.254 2.964l0 32.661l-12.312-12.312q-1.197-1.254-2.907-1.254t-2.907 1.254l-5.928 5.928q-1.197 1.197-1.197 2.964t1.197 2.907l29.469 29.526q1.197 1.14 2.964 1.14zm49.989-33.63q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
14518
+ width: 100,
14519
+ height: 100
14520
+ };
14521
+ const iconCircleArrowUp = {
14522
+ path: "M54.207 83.391q1.653 0 2.907-1.254t1.254-2.907l0-32.718l12.312 12.312q1.254 1.254 2.964 1.254t2.907-1.254l5.928-5.928q1.197-1.197 1.14-2.964 0-1.767-1.14-2.907l-29.526-29.526q-1.197-1.14-2.907-1.14t-2.964 1.14l-29.469 29.526q-1.197 1.254-1.197 2.964t1.197 2.907l5.928 5.928q1.197 1.197 2.907 1.197t2.907-1.197l12.312-12.312l0 32.718q0 1.653 1.254 2.907t2.964 1.254l8.322 0zm45.828-33.345q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
14523
+ width: 100,
14524
+ height: 100
14525
+ };
14526
+ const iconCircleThin = {
14527
+ path: "M50.046 8.322q-8.493 0-16.188 3.306-15.561 6.669-22.173 22.23-3.363 7.695-3.363 16.188t3.306 16.188 8.949 13.281q5.586 5.586 13.281 8.892t16.188 3.306 16.188-3.306 13.281-8.892 8.892-13.281 3.306-16.188-3.306-16.188-8.892-13.281-13.281-8.949q-7.695-3.306-16.188-3.306zm0 91.713q-13.623 0-25.137-6.726t-18.183-18.183q-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.726 25.137-6.726 25.137-18.24 18.126q-11.514 6.726-25.08 6.726z",
14528
+ width: 100,
14529
+ height: 99.944
14530
+ };
14531
+ const iconDesktop = {
14532
+ path: "M94.208 52.119l0-43.746q0-.69-.506-1.15t-1.196-.506l-84.088 0q-.69 0-1.196.506t-.506 1.15l0 43.746q0 .69.506 1.196t1.196.506l84.088 0q.69 0 1.196-.506t.506-1.196zm6.716-43.746l0 57.224q0 3.45-2.484 5.934t-5.934 2.484l-28.566 0q0 3.128 2.53 7.774.828 1.61.828 2.622t-1.012 2.07q-1.012 1.012-2.346.966l-26.91 0q-1.38 0-2.392-1.012t-1.012-2.024q0-1.058 1.656-4.14t1.748-6.256l-28.612 0q-3.45 0-5.934-2.484t-2.484-5.934l0-57.224q0-3.45 2.484-5.934t5.934-2.438l84.088 0q3.45 0 5.98 2.438 2.438 2.484 2.438 5.934z",
14533
+ width: 100,
14534
+ height: 86.648
14535
+ };
14536
+ const iconDropdownArrow = {
14537
+ path: "M9 9.8c0 .5.7 1.7 1.5 2.8 1.5 1.9 1.5 1.9 3 0C15.7 9.7 15.4 9 12 9c-1.6 0-3 .4-3 .8z",
14538
+ width: 24,
14539
+ height: 24
14540
+ };
14541
+ const iconExclamationSign = {
14542
+ path: "M58.368 81.225l0-12.369q0-.912-.57-1.539t-1.425-.627l-12.54 0q-.855-.057-1.482.627t-.684 1.539l0 12.369q-.057.855.627 1.482t1.539.684l12.54 0q.855 0 1.425-.627t.57-1.539zm1.026-62.871q0-1.596-2.223-1.71l-14.307 0q-2.109 0-2.223 1.71l1.14 40.47q0 .627.627 1.14t1.539.456l12.084 0q.912-.057 1.539-.513t.684-1.083zm-9.348-18.354q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.726 25.137-6.726 25.137-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669z",
14543
+ width: 100,
14544
+ height: 99.944
14545
+ };
14546
+ // Grabbed from https://github.com/encharm/Font-Awesome-SVG-PNG
14547
+ const iconGear = {
14548
+ path: "M1152 896q0-106-75-181t-181-75-181 75-75 181 75 181 181 75 181-75 75-181zm512-109v222q0 12-8 23t-20 13l-185 28q-19 54-39 91 35 50 107 138 10 12 10 25t-9 23q-27 37-99 108t-94 71q-12 0-26-9l-138-108q-44 23-91 38-16 136-29 186-7 28-36 28h-222q-14 0-24.5-8.5t-11.5-21.5l-28-184q-49-16-90-37l-141 107q-10 9-25 9-14 0-25-11-126-114-165-168-7-10-7-23 0-12 8-23 15-21 51-66.5t54-70.5q-27-50-41-99l-183-27q-13-2-21-12.5t-8-23.5v-222q0-12 8-23t19-13l186-28q14-46 39-92-40-57-107-138-10-12-10-24 0-10 9-23 26-36 98.5-107.5t94.5-71.5q13 0 26 10l138 107q44-23 91-38 16-136 29-186 7-28 36-28h222q14 0 24.5 8.5t11.5 21.5l28 184q49 16 90 37l142-107q9-9 24-9 13 0 25 10 129 119 165 170 7 8 7 22 0 12-8 23-15 21-51 66.5t-54 70.5q26 50 41 98l183 28q13 2 21 12.5t8 23.5z",
14549
+ width: 1792,
14550
+ height: 1792
14551
+ };
14552
+ const iconMobilePhone = {
14553
+ path: "M36.04 89.557q0-2.584-1.836-4.42t-4.42-1.836-4.352 1.836q-1.836 1.836-1.836 4.42t1.836 4.352 4.42 1.836q2.652-.068 4.42-1.836t1.768-4.352zm16.184-12.444l0-54.74q0-1.088-.748-1.768t-1.768-.68l-39.78 0q-1.088 0-1.768.748t-.68 1.7l0 54.74q0 1.02.748 1.768t1.7.68l39.78 0q1.02-.068 1.768-.748t.748-1.7zm-14.892-65.892q0-1.224-1.292-1.292l-12.444 0q-1.224.068-1.224 1.292t1.224 1.224l12.444 0q1.292 0 1.292-1.224zm22.372-1.292l0 79.628q0 3.944-2.992 6.936t-7.004 2.992l-39.78 0q-4.012 0-7.004-2.924-2.924-2.924-2.924-7.004l0-79.628q0-4.012 2.924-6.936t7.004-2.992l39.78 0q4.012-.068 7.004 2.924t2.992 7.004z",
14554
+ width: 60.013,
14555
+ height: 100
14556
+ };
14557
+ const iconOk = {
14558
+ path: "M37.964 76.048q-2.576 0-4.368-1.792l-31.864-31.864q-1.792-1.792-1.792-4.368t1.792-4.368l8.736-8.68q1.792-1.792 4.368-1.792t4.312 1.792l18.816 18.872 42-42.056q1.792-1.792 4.368-1.792t4.312 1.792l8.736 8.736q1.792 1.792 1.792 4.368t-1.792 4.312l-55.048 55.048q-1.792 1.792-4.368 1.792z",
14559
+ width: 100,
14560
+ height: 76.637
14561
+ };
14562
+ const iconPlus = {
14563
+ path: "M99.758 43.09l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-29.45 0l0 29.45q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-29.45l-29.45 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l29.45 0l0-29.45q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836l0 29.45l29.45 0q2.852 0 4.836 1.984t1.984 4.836z",
14564
+ width: 100,
14565
+ height: 100
14566
+ };
14567
+ const iconRemove = {
14568
+ path: "M100.464 80.808q0 3.404-2.368 5.772l-11.47 11.544q-2.368 2.368-5.772 2.368t-5.698-2.368l-24.864-24.864-24.864 24.864q-2.368 2.368-5.772 2.368t-5.772-2.368l-11.47-11.544q-2.368-2.368-2.368-5.772t2.368-5.698l24.864-24.864-24.864-24.864q-2.368-2.368-2.368-5.772t2.368-5.772l11.47-11.47q2.368-2.368 5.772-2.368t5.772 2.368l24.864 24.864 24.864-24.864q2.294-2.368 5.698-2.368t5.772 2.368l11.47 11.47q2.368 2.368 2.368 5.772t-2.368 5.772l-24.864 24.864 24.864 24.864q2.368 2.294 2.368 5.698z",
14569
+ width: 100,
14570
+ height: 100
14571
+ };
14572
+ const iconStar = {
14573
+ path: "M15.1052249,9.55978547 L22.0028147,9.55978545 C23.6568673,9.55978545 23.9349557,10.3753626 22.6181351,11.3858845 L16.9943688,15.7015366 L19.2518801,22.8294455 C19.7526645,24.4106317 19.0984455,24.8825885 17.769353,23.8673293 L12.0490577,19.4977438 L6.5116497,23.8422153 C5.20921411,24.8640642 4.53299569,24.4067544 5.00266927,22.8160582 L7.10332364,15.7015366 L1.42794544,11.3634306 C0.110226041,10.3562014 0.383967283,9.54239221 2.0409646,9.54574013 L8.9924676,9.55978547 L11.1485117,2.72669438 C11.6458693,1.15043244 12.4548928,1.15900049 12.9494787,2.72669438 L15.1052249,9.55978547 Z",
14574
+ width: 24,
14575
+ height: 24
14576
+ };
14577
+ const iconTryAgain = {
14578
+ path: "M3.74890556,17.9799506 C2.19251241,16.1970909 1.10103636,13.4971457 1.13090903,11.1491783 C1.17160478,7.95052637 4.01704076,0.865059407 11.7028044,0.865059407 C19.388568,0.865059407 22.3026521,7.35203035 22.3026521,11.5879453 C22.3026521,15.8238603 19.386629,20.5574509 13.6832464,21.7131548 L13.6757539,17.3722171 C17.0812986,16.2190517 18.331158,14.1944123 18.3311578,11.5879451 C18.3311574,8.16554692 15.6664205,5.03476549 11.7028048,5.20494205 C7.73918903,5.37511861 5.59244567,8.66930079 5.59244567,11.1491783 C5.59244567,12.9090077 6.11128139,14.1753512 6.93640437,15.3053215 L8.14052356,14.2949456 C8.98559348,13.5858477 9.6994861,13.9070448 9.73489556,15.0076413 L9.91284941,20.5388014 C9.94832683,21.6415103 9.09967118,22.3514475 8.02194403,22.1254594 L2.60571602,20.9897332 C1.5259204,20.7633114 1.34338662,19.9984207 2.18070755,19.295825 L3.74890556,17.9799506 Z",
14579
+ width: 23,
14580
+ height: 23
14581
+ };
14582
+ const iconTablet = {
14583
+ path: "M45.322 90.706q0-1.86-1.302-3.224-1.364-1.364-3.224-1.364t-3.224 1.364-1.302 3.224q0 1.86 1.364 3.224 1.302 1.364 3.162 1.302 1.86.062 3.224-1.302t1.302-3.224zm27.218-11.346l0-68.014q0-.93-.682-1.612t-1.55-.682l-58.962 0q-.93 0-1.612.682t-.682 1.612l0 68.014q0 .93.682 1.612t1.612.62l58.962 0q.992-.062 1.612-.682t.62-1.55zm9.114-68.014l0 77.066q0 4.65-3.348 7.998t-7.998 3.348l-58.962 0q-4.65 0-7.998-3.348t-3.348-7.998l0-77.066q0-4.65 3.348-7.998t7.998-3.348l58.962 0q4.65 0 7.998 3.348t3.348 7.998z",
14584
+ width: 81.852,
14585
+ height: 100
14586
+ };
14587
+ const iconTrash = {
14588
+ path: "M31.293 37.506q2.052 0 2.052 2.109l0 37.506q0 1.995-2.052 2.109l-4.218 0q-.912-.057-1.482-.627t-.57-1.482l0-37.506q0-2.109 2.052-2.109l4.218 0zm18.753 2.109l0 37.506q0 .912-.57 1.482t-1.539.627l-4.161 0q-1.995 0-2.109-2.109l0-37.506q.057-.912.627-1.482t1.482-.627l4.161 0q.969.057 1.539.627t.57 1.482zm14.592-2.109q2.052 0 2.052 2.109l0 37.506q0 1.995-2.052 2.109l-4.161 0q-.969-.057-1.539-.627t-.57-1.482l0-37.506q0-2.109 2.109-2.109l4.161 0zm10.431 49.248l0-61.731l-58.368 0l0 61.731q.057 2.679.969 3.819t1.083 1.14l54.207 0q.171 0 1.14-1.083t.969-3.876zm-43.776-70.11l29.184 0l-3.135-7.581q-.456-.57-1.14-.741l-20.634 0q-.627.114-1.083.741zm-31.293 2.109q0-1.995 2.109-2.109l20.121 0l4.56-10.83q.969-2.394 3.477-4.104 2.565-1.71 5.187-1.71l20.805 0q2.622 0 5.187 1.71t3.477 4.104l4.56 10.83l20.178 0q.912.057 1.482.627t.57 1.482l0 4.161q0 1.995-2.052 2.109l-6.27 0l0 61.731q0 5.415-3.078 9.348t-7.353 3.933l-54.207 0q-4.275 0-7.353-3.819t-3.078-9.177l0-62.016l-6.213 0q-.969 0-1.539-.57t-.57-1.539l0-4.161z",
14589
+ width: 91.681,
14590
+ height: 100
14591
+ };
14592
+ const iconUndo = {
14593
+ path: "M10,6.6C10,7.2,9.8,8,9.3,9.1c0,0,0,0.1-0.1,0.1S9.2,9.3,9.2,9.4c0,0,0,0.1-0.1,0.1C9,9.6,9,9.6,8.9,9.6 c-0.1,0-0.1,0-0.1-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1s0-0.1,0-0.1c0-0.3,0-0.5,0-0.7c0-0.4,0-0.7-0.1-1C8.6,7.1,8.5,6.9,8.4,6.7S8.2,6.3,8,6.1C7.8,5.9,7.6,5.8,7.4,5.7S6.9,5.5,6.7,5.5S6.1,5.4,5.8,5.4c-0.3,0-0.6,0-1,0H3.6v1.4c0,0.1,0,0.2-0.1,0.3C3.4,7.1,3.3,7.1,3.2,7.1C3.1,7.1,3,7.1,3,7L0.1,4.1C0,4.1,0,4,0,3.9s0-0.2,0.1-0.3L3,0.8C3,0.7,3.1,0.7,3.2,0.7c0.1,0,0.2,0,0.3,0.1C3.5,0.9,3.6,0.9,3.6,1v1.4h1.2c2.6,0,4.3,0.7,4.9,2.2C9.9,5.2,10,5.8,10,6.6z",
14594
+ width: 10,
14595
+ height: 10
14596
+ };
14597
+ const iconMinus = {
14598
+ path: "M8,13 L16,13 C16.5522847,13 17,12.5522847 17,12 C17,11.4477153 16.5522847,11 16,11 L8,11 C7.44771525,11 7,11.4477153 7,12 C7,12.5522847 7.44771525,13 8,13 Z",
14599
+ width: 24,
14600
+ height: 24
14601
+ };
14602
+
14603
+ var iconPaths = /*#__PURE__*/Object.freeze({
14604
+ __proto__: null,
14605
+ iconCheck: iconCheck,
14606
+ iconCheckMedium: iconCheckMedium,
14607
+ iconChevronDown: iconChevronDown,
14608
+ iconChevronRight: iconChevronRight,
14609
+ iconCircle: iconCircle,
14610
+ iconCircleArrowDown: iconCircleArrowDown,
14611
+ iconCircleArrowUp: iconCircleArrowUp,
14612
+ iconCircleThin: iconCircleThin,
14613
+ iconDesktop: iconDesktop,
14614
+ iconDropdownArrow: iconDropdownArrow,
14615
+ iconExclamationSign: iconExclamationSign,
14616
+ iconGear: iconGear,
14617
+ iconMobilePhone: iconMobilePhone,
14618
+ iconOk: iconOk,
14619
+ iconPlus: iconPlus,
14620
+ iconRemove: iconRemove,
14621
+ iconStar: iconStar,
14622
+ iconTryAgain: iconTryAgain,
14623
+ iconTablet: iconTablet,
14624
+ iconTrash: iconTrash,
14625
+ iconUndo: iconUndo,
14626
+ iconMinus: iconMinus
14627
+ });
14628
+
15011
14629
  /* eslint-disable @babel/no-invalid-this */
15012
14630
  const add$1 = {
15013
14631
  constrain: function () {
@@ -20939,6 +20557,257 @@ _defineProperty(TextInput, "defaultProps", {
20939
20557
  disabled: false
20940
20558
  });
20941
20559
 
20560
+ const zIndex = 10;
20561
+ let HorizontalDirection = /*#__PURE__*/function (HorizontalDirection) {
20562
+ HorizontalDirection["Left"] = "left";
20563
+ HorizontalDirection["Right"] = "right";
20564
+ return HorizontalDirection;
20565
+ }({});
20566
+ let VerticalDirection = /*#__PURE__*/function (VerticalDirection) {
20567
+ VerticalDirection["Top"] = "top";
20568
+ VerticalDirection["Bottom"] = "bottom";
20569
+ return VerticalDirection;
20570
+ }({});
20571
+ const Triangle = props => {
20572
+ let borderLeft;
20573
+ let borderRight;
20574
+ let borderTop;
20575
+ let borderBottom;
20576
+ const hBorder = "".concat(props.width, "px solid transparent");
20577
+ if (props.horizontalDirection === "right") {
20578
+ borderLeft = hBorder;
20579
+ } else {
20580
+ borderRight = hBorder;
20581
+ }
20582
+ const vBorder = "".concat(props.height, "px solid ").concat(props.color);
20583
+ if (props.verticalDirection === "top") {
20584
+ borderTop = vBorder;
20585
+ } else {
20586
+ borderBottom = vBorder;
20587
+ }
20588
+ return /*#__PURE__*/React__namespace.createElement("div", {
20589
+ style: {
20590
+ display: "block",
20591
+ height: 0,
20592
+ width: 0,
20593
+ position: "absolute",
20594
+ left: props.left,
20595
+ top: props["top"],
20596
+ borderLeft: borderLeft,
20597
+ borderRight: borderRight,
20598
+ borderTop: borderTop,
20599
+ borderBottom: borderBottom
20600
+ }
20601
+ });
20602
+ };
20603
+ const TooltipArrow = props => {
20604
+ // TODO(aria): Think about adding a box-shadow to the triangle here
20605
+ // See http://css-tricks.com/triangle-with-shadow/
20606
+
20607
+ //const isRight = (this.props.horizontalDirection === "right");
20608
+ const isTop = props.verticalDirection === "top";
20609
+ const frontTopOffset = isTop ? 0 : 1;
20610
+ const borderTopOffset = isTop ? 0 : -1;
20611
+ return /*#__PURE__*/React__namespace.createElement("div", {
20612
+ style: {
20613
+ display: "block",
20614
+ position: props.position,
20615
+ visibility: props.visibility,
20616
+ left: props.left,
20617
+ top: props["top"],
20618
+ width: props.width + 2,
20619
+ height: props.height + 1,
20620
+ marginTop: -1,
20621
+ marginBottom: -2,
20622
+ zIndex: zIndex
20623
+ }
20624
+ }, /*#__PURE__*/React__namespace.createElement(Triangle, {
20625
+ horizontalDirection: props.horizontalDirection,
20626
+ verticalDirection: props.verticalDirection,
20627
+ color: props.border,
20628
+ left: 0,
20629
+ top: borderTopOffset,
20630
+ width: props.width + 2 // one extra for the diagonal
20631
+ ,
20632
+ height: props.height + 2
20633
+ }), /*#__PURE__*/React__namespace.createElement(Triangle, {
20634
+ horizontalDirection: props.horizontalDirection,
20635
+ verticalDirection: props.verticalDirection,
20636
+ color: props.color,
20637
+ left: 1,
20638
+ top: frontTopOffset,
20639
+ width: props.width,
20640
+ height: props.height
20641
+ }));
20642
+ };
20643
+ TooltipArrow.defaultProps = {
20644
+ position: "relative",
20645
+ visibility: "visible",
20646
+ left: 0,
20647
+ top: 0
20648
+ };
20649
+ const VERTICAL_CORNERS = {
20650
+ top: {
20651
+ top: "-100%"
20652
+ },
20653
+ bottom: {
20654
+ top: 0
20655
+ }
20656
+ };
20657
+ const HORIZONTAL_CORNERS = {
20658
+ left: {
20659
+ targetLeft: 0
20660
+ },
20661
+ right: {
20662
+ targetLeft: "100%"
20663
+ }
20664
+ };
20665
+ const HORIZONTAL_ALIGNMNENTS = {
20666
+ left: {
20667
+ tooltipLeft: 0,
20668
+ arrowLeft: arrowSize => 0
20669
+ },
20670
+ right: {
20671
+ tooltipLeft: "-100%",
20672
+ arrowLeft: arrowSize => -arrowSize - 2
20673
+ }
20674
+ };
20675
+ class Tooltip extends React__namespace.Component {
20676
+ constructor() {
20677
+ super(...arguments);
20678
+ _defineProperty(this, "state", {
20679
+ height: null // used for offsetting "top" positioned tooltips
20680
+ });
20681
+ }
20682
+
20683
+ componentDidMount() {
20684
+ this._updateHeight();
20685
+ }
20686
+ UNSAFE_componentWillReceiveProps() {
20687
+ // If the contents have changed, reset our measure of the height
20688
+ this.setState({
20689
+ height: null
20690
+ });
20691
+ }
20692
+ componentDidUpdate() {
20693
+ this._updateHeight();
20694
+ }
20695
+ _renderToolTipDiv(isTooltipAbove) {
20696
+ const settings = Object.assign({}, HORIZONTAL_CORNERS[this.props.horizontalPosition], HORIZONTAL_ALIGNMNENTS[this.props.horizontalAlign], VERTICAL_CORNERS[this.props.verticalPosition]);
20697
+ let arrowAbove;
20698
+ let arrowBelow;
20699
+ if (isTooltipAbove) {
20700
+ // We put an absolutely positioned arrow in the correct place
20701
+ arrowAbove = /*#__PURE__*/React__namespace.createElement(TooltipArrow, {
20702
+ verticalDirection: VerticalDirection.Top,
20703
+ horizontalDirection: this.props.horizontalAlign,
20704
+ position: "absolute",
20705
+ color: "white",
20706
+ border: this.props.borderColor,
20707
+ left: settings.arrowLeft(this.props.arrowSize),
20708
+ top: -this.props.arrowSize + 2,
20709
+ width: this.props.arrowSize,
20710
+ height: this.props.arrowSize,
20711
+ zIndex: zIndex
20712
+ });
20713
+
20714
+ // And we use a visibility: hidden arrow below to shift up the
20715
+ // content by the correct amount
20716
+ arrowBelow = /*#__PURE__*/React__namespace.createElement(TooltipArrow, {
20717
+ verticalDirection: VerticalDirection.Top,
20718
+ horizontalDirection: this.props.horizontalAlign,
20719
+ visibility: "hidden",
20720
+ color: "white",
20721
+ border: this.props.borderColor,
20722
+ left: settings.arrowLeft(this.props.arrowSize),
20723
+ top: -1,
20724
+ width: this.props.arrowSize,
20725
+ height: this.props.arrowSize,
20726
+ zIndex: zIndex
20727
+ });
20728
+ } else {
20729
+ arrowAbove = /*#__PURE__*/React__namespace.createElement(TooltipArrow, {
20730
+ verticalDirection: VerticalDirection.Bottom,
20731
+ horizontalDirection: this.props.horizontalAlign,
20732
+ color: "white",
20733
+ border: this.props.borderColor,
20734
+ left: settings.arrowLeft(this.props.arrowSize),
20735
+ top: -1,
20736
+ width: this.props.arrowSize,
20737
+ height: this.props.arrowSize,
20738
+ zIndex: zIndex
20739
+ });
20740
+ arrowBelow = null;
20741
+ }
20742
+
20743
+ /* A positioned div below the input to be the parent for our
20744
+ tooltip */
20745
+ return /*#__PURE__*/React__namespace.createElement("div", {
20746
+ style: {
20747
+ position: "relative",
20748
+ height: 0,
20749
+ display: this.props.show ? "block" : "none"
20750
+ }
20751
+ }, /*#__PURE__*/React__namespace.createElement("div", {
20752
+ // eslint-disable-next-line react/no-string-refs
20753
+ ref: "tooltipContainer",
20754
+ className: "tooltipContainer",
20755
+ style: {
20756
+ position: "absolute",
20757
+ // height must start out undefined, not null, so that
20758
+ // we can measure the actual height with jquery.
20759
+ // This is used to position the tooltip with top: -100%
20760
+ // when in verticalPosition: "top" mode
20761
+ height: this.state.height || undefined,
20762
+ left: settings.targetLeft
20763
+ }
20764
+ }, arrowAbove, /*#__PURE__*/React__namespace.createElement("div", {
20765
+ className: this.props.className
20766
+ // eslint-disable-next-line react/no-string-refs
20767
+ ,
20768
+ ref: "tooltipContent",
20769
+ style: {
20770
+ position: "relative",
20771
+ top: settings["top"],
20772
+ left: settings.tooltipLeft,
20773
+ border: "1px solid " + this.props.borderColor,
20774
+ boxShadow: "0 1px 3px " + this.props.borderColor,
20775
+ zIndex: zIndex - 1
20776
+ }
20777
+ }, this.props.children.slice(1)), arrowBelow));
20778
+ }
20779
+ _updateHeight() {
20780
+ const tooltipContainer = ReactDOM__default["default"].findDOMNode(
20781
+ // eslint-disable-next-line react/no-string-refs
20782
+ this.refs.tooltipContainer);
20783
+ const height = tooltipContainer.offsetHeight;
20784
+ if (height !== this.state.height) {
20785
+ this.setState({
20786
+ height
20787
+ });
20788
+ }
20789
+ }
20790
+ render() {
20791
+ const isTooltipAbove = this.props.verticalPosition === "top";
20792
+
20793
+ /* We wrap the entire output in a span so that it displays inline */
20794
+ return /*#__PURE__*/React__namespace.createElement("span", null, isTooltipAbove && this._renderToolTipDiv(isTooltipAbove), /*#__PURE__*/React__namespace.createElement("div", {
20795
+ style: this.props.targetContainerStyle
20796
+ }, this.props.children[0]), !isTooltipAbove && this._renderToolTipDiv());
20797
+ }
20798
+ }
20799
+
20800
+ // Sorry. // Apology-Oriented-Programming
20801
+ _defineProperty(Tooltip, "defaultProps", {
20802
+ className: "",
20803
+ arrowSize: 10,
20804
+ borderColor: "#ccc",
20805
+ verticalPosition: VerticalDirection.Bottom,
20806
+ horizontalPosition: HorizontalDirection.Left,
20807
+ horizontalAlign: HorizontalDirection.Left,
20808
+ targetContainerStyle: {}
20809
+ });
20810
+
20942
20811
  const {
20943
20812
  captureScratchpadTouchStart: captureScratchpadTouchStart$3
20944
20813
  } = Util;
@@ -24751,26 +24620,6 @@ var Explanation$1 = {
24751
24620
  isLintable: true
24752
24621
  };
24753
24622
 
24754
- /*
24755
- * A11y (Accessibility) style rules
24756
- * These are used to mark up areas on the site that should only be readable
24757
- * when using a screen reader.
24758
- */
24759
- var a11y = aphrodite.StyleSheet.create({
24760
- // Make content only visible to screen readers.
24761
- // Both collegeboard.org and Bootstrap 3 use this exact implementation.
24762
- srOnly: {
24763
- border: 0,
24764
- clip: "rect(0,0,0,0)",
24765
- height: 1,
24766
- margin: -1,
24767
- overflow: "hidden",
24768
- padding: 0,
24769
- position: "absolute",
24770
- width: 1
24771
- }
24772
- });
24773
-
24774
24623
  class GradedGroupAnswerBar extends React__namespace.Component {
24775
24624
  render() {
24776
24625
  const {
@@ -44160,7 +44009,7 @@ const init = function (options) {
44160
44009
 
44161
44010
  // This file is processed by a Rollup plugin (replace) to inject the production
44162
44011
  const libName = "@khanacademy/perseus";
44163
- const libVersion = "11.6.1";
44012
+ const libVersion = "12.0.1";
44164
44013
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
44165
44014
 
44166
44015
  const apiVersion = {
@@ -45893,6 +45742,238 @@ _defineProperty(RangeInput, "defaultProps", {
45893
45742
  placeholder: [null, null]
45894
45743
  });
45895
45744
 
45745
+ const prettyBig = {
45746
+ fontSize: "150%"
45747
+ };
45748
+ const slightlyBig = {
45749
+ fontSize: "120%"
45750
+ };
45751
+ const symbStyle = {
45752
+ fontSize: "130%"
45753
+ };
45754
+ // These are functions because we want to generate a new component for each use
45755
+ // on the page rather than reusing an instance (which will cause an error).
45756
+ // Also, it's useful for things which might look different depending on the
45757
+ // props.
45758
+
45759
+ const basic = [() => [/*#__PURE__*/React__namespace.createElement("span", {
45760
+ key: "plus",
45761
+ style: slightlyBig
45762
+ }, "+"), "PLUS", i18n__namespace._("Plus")], () => [/*#__PURE__*/React__namespace.createElement("span", {
45763
+ key: "minus",
45764
+ style: prettyBig
45765
+ }, "-"), "MINUS", i18n__namespace._("Minus")],
45766
+ // TODO(joel) - display as \cdot when appropriate
45767
+ props => {
45768
+ const {
45769
+ TeX
45770
+ } = getDependencies();
45771
+ if (props.convertDotToTimes) {
45772
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45773
+ key: "times",
45774
+ style: prettyBig
45775
+ }, i18n__namespace.doNotTranslate("\\times")), "TIMES", i18n__namespace._("Multiply")];
45776
+ }
45777
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45778
+ key: "times",
45779
+ style: prettyBig
45780
+ }, i18n__namespace.doNotTranslate("\\cdot")), "CDOT", i18n__namespace._("Multiply")];
45781
+ }, () => {
45782
+ const {
45783
+ TeX
45784
+ } = getDependencies();
45785
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45786
+ key: "frac",
45787
+ style: prettyBig
45788
+ }, i18n__namespace.doNotTranslate("\\frac{x}{y}")), "FRAC", i18n__namespace._("Fraction, excluding the current expression")];
45789
+ }];
45790
+ const buttonSets = {
45791
+ basic,
45792
+ "basic+div": basic.concat([() => {
45793
+ const {
45794
+ TeX
45795
+ } = getDependencies();
45796
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45797
+ key: "div"
45798
+ }, i18n__namespace.doNotTranslate("\\div")), "DIVIDE", i18n__namespace._("Divide")];
45799
+ }]),
45800
+ trig: [() => {
45801
+ const {
45802
+ TeX
45803
+ } = getDependencies();
45804
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45805
+ key: "sin"
45806
+ }, i18n__namespace.doNotTranslate("\\sin")), "SIN", i18n__namespace._("Sine")];
45807
+ }, () => {
45808
+ const {
45809
+ TeX
45810
+ } = getDependencies();
45811
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45812
+ key: "cos"
45813
+ }, i18n__namespace.doNotTranslate("\\cos")), "COS", i18n__namespace._("Cosine")];
45814
+ }, () => {
45815
+ const {
45816
+ TeX
45817
+ } = getDependencies();
45818
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45819
+ key: "tan"
45820
+ }, i18n__namespace.doNotTranslate("\\tan")), "TAN", i18n__namespace._("Tangent")];
45821
+ }, () => {
45822
+ const {
45823
+ TeX
45824
+ } = getDependencies();
45825
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45826
+ key: "theta",
45827
+ style: symbStyle
45828
+ }, i18n__namespace.doNotTranslate("\\theta")), "THETA", i18n__namespace._("Theta")];
45829
+ }, () => {
45830
+ const {
45831
+ TeX
45832
+ } = getDependencies();
45833
+ return [/*#__PURE__*/React__namespace.createElement("span", {
45834
+ key: "phi"
45835
+ }, /*#__PURE__*/React__namespace.createElement("span", {
45836
+ className: "perseus-sr-only"
45837
+ }, i18n__namespace.doNotTranslate("phi")), /*#__PURE__*/React__namespace.createElement(TeX, {
45838
+ key: "pi",
45839
+ style: symbStyle
45840
+ }, i18n__namespace.doNotTranslate("\\phi"))), "PHI", i18n__namespace._("Phi")];
45841
+ }],
45842
+ prealgebra: [() => {
45843
+ const {
45844
+ TeX
45845
+ } = getDependencies();
45846
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45847
+ key: "sqrt"
45848
+ }, i18n__namespace.doNotTranslate("\\sqrt{x}")), "SQRT", i18n__namespace._("Square root")];
45849
+ },
45850
+ // TODO(joel) - how does desmos do this?
45851
+ () => {
45852
+ const {
45853
+ TeX
45854
+ } = getDependencies();
45855
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45856
+ key: "nthroot"
45857
+ }, i18n__namespace.doNotTranslate("\\sqrt[3]{x}")), "NTHROOT3", i18n__namespace._("Cube root")];
45858
+ }, () => {
45859
+ const {
45860
+ TeX
45861
+ } = getDependencies();
45862
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45863
+ key: "pow",
45864
+ style: slightlyBig
45865
+ }, i18n__namespace.doNotTranslate("a^b")), "POW", i18n__namespace._("Exponent")];
45866
+ }, () => {
45867
+ const {
45868
+ TeX
45869
+ } = getDependencies();
45870
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45871
+ key: "pi",
45872
+ style: slightlyBig
45873
+ }, i18n__namespace.doNotTranslate("\\pi")), "PI", i18n__namespace._("Pi")];
45874
+ }],
45875
+ logarithms: [() => {
45876
+ const {
45877
+ TeX
45878
+ } = getDependencies();
45879
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45880
+ key: "log"
45881
+ }, i18n__namespace.doNotTranslate("\\log")), "LOG", i18n__namespace._("Logarithm with base 10")];
45882
+ }, () => {
45883
+ const {
45884
+ TeX
45885
+ } = getDependencies();
45886
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45887
+ key: "ln"
45888
+ }, i18n__namespace.doNotTranslate("\\ln")), "LN", i18n__namespace._("Natural logarithm")];
45889
+ }, () => {
45890
+ const {
45891
+ TeX
45892
+ } = getDependencies();
45893
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45894
+ key: "log_b"
45895
+ }, i18n__namespace.doNotTranslate("\\log_b")), "LOG_B", i18n__namespace._("Logarithm with custom base")];
45896
+ }],
45897
+ "basic relations": [() => {
45898
+ const {
45899
+ TeX
45900
+ } = getDependencies();
45901
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45902
+ key: "eq"
45903
+ }, "="), "EQUAL", i18n__namespace._("Equals sign")];
45904
+ }, () => {
45905
+ const {
45906
+ TeX
45907
+ } = getDependencies();
45908
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45909
+ key: "lt"
45910
+ }, i18n__namespace.doNotTranslate("\\lt")), "LT", i18n__namespace._("Less than sign")];
45911
+ }, () => {
45912
+ const {
45913
+ TeX
45914
+ } = getDependencies();
45915
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45916
+ key: "gt"
45917
+ }, i18n__namespace.doNotTranslate("\\gt")), "GT", i18n__namespace._("Greater than sign")];
45918
+ }],
45919
+ "advanced relations": [() => {
45920
+ const {
45921
+ TeX
45922
+ } = getDependencies();
45923
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45924
+ key: "neq"
45925
+ }, i18n__namespace.doNotTranslate("\\neq")), "NEQ", i18n__namespace._("Not-equals sign")];
45926
+ }, () => {
45927
+ const {
45928
+ TeX
45929
+ } = getDependencies();
45930
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45931
+ key: "leq"
45932
+ }, i18n__namespace.doNotTranslate("\\leq")), "LEQ", i18n__namespace._("Less than or equal to sign")];
45933
+ }, () => {
45934
+ const {
45935
+ TeX
45936
+ } = getDependencies();
45937
+ return [/*#__PURE__*/React__namespace.createElement(TeX, {
45938
+ key: "geq"
45939
+ }, i18n__namespace.doNotTranslate("\\geq")), "GEQ", i18n__namespace._("Greater than or equal to sign")];
45940
+ }]
45941
+ };
45942
+ const buttonSetsPropType = PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOf(___default["default"](buttonSets).keys()));
45943
+ class TexButtons extends React__namespace.Component {
45944
+ render() {
45945
+ // Always show buttonSets in the same order. Note: Technically it's ok
45946
+ // for _.keys() to return the keys in an arbitrary order, but in
45947
+ // practice, they will be ordered as listed above.
45948
+ const sortedButtonSets = ___default["default"].sortBy(this.props.sets, setName => ___default["default"].keys(buttonSets).indexOf(setName));
45949
+ const buttons = ___default["default"](sortedButtonSets).map(setName => buttonSets[setName]);
45950
+ const buttonRows = ___default["default"](buttons).map(row => row.map(symbGen => {
45951
+ // create a (component, thing we should send to mathquill) pair
45952
+ const symbol = symbGen(this.props);
45953
+ return /*#__PURE__*/React__namespace.createElement("button", {
45954
+ onClick: () => this.props.onInsert(symbol[1]),
45955
+ className: "tex-button"
45956
+ // @ts-expect-error - TS2533 - Object is possibly 'null' or 'undefined'. | TS2339 - Property 'key' does not exist on type 'boolean | ReactChild | ReactFragment | ReactPortal'.
45957
+ ,
45958
+ key: symbol[0].key,
45959
+ type: "button",
45960
+ "aria-label": symbol[2]
45961
+ }, symbol[0]);
45962
+ }));
45963
+ const buttonPopup = ___default["default"](buttonRows).map((row, i) => {
45964
+ return /*#__PURE__*/React__namespace.createElement("div", {
45965
+ className: "clearfix tex-button-row",
45966
+ key: this.props.sets[i]
45967
+ }, row);
45968
+ });
45969
+ return /*#__PURE__*/React__namespace.createElement("div", {
45970
+ className: "".concat(this.props.className || "", " preview-measure")
45971
+ }, buttonPopup);
45972
+ }
45973
+ }
45974
+ _defineProperty(TexButtons, "buttonSets", buttonSets);
45975
+ _defineProperty(TexButtons, "buttonSetsType", buttonSetsPropType);
45976
+
45896
45977
  var components = /*#__PURE__*/Object.freeze({
45897
45978
  __proto__: null,
45898
45979
  ButtonGroup: ButtonGroup,