@khanacademy/math-input 0.7.0 → 0.7.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/CHANGELOG.md +6 -0
- package/dist/es/index.js +1045 -952
- package/dist/es/index.js.map +1 -1
- package/package.json +2 -2
- /package/dist/{strings → strings.js} +0 -0
package/dist/es/index.js
CHANGED
|
@@ -16,96 +16,23 @@ import { View as View$1 } from '@khanacademy/wonder-blocks-core';
|
|
|
16
16
|
import Clickable from '@khanacademy/wonder-blocks-clickable';
|
|
17
17
|
import now from 'performance-now';
|
|
18
18
|
|
|
19
|
-
function ownKeys(object, enumerableOnly) {
|
|
20
|
-
var keys = Object.keys(object);
|
|
21
|
-
if (Object.getOwnPropertySymbols) {
|
|
22
|
-
var symbols = Object.getOwnPropertySymbols(object);
|
|
23
|
-
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
|
24
|
-
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
25
|
-
})), keys.push.apply(keys, symbols);
|
|
26
|
-
}
|
|
27
|
-
return keys;
|
|
28
|
-
}
|
|
29
|
-
function _objectSpread2(target) {
|
|
30
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
31
|
-
var source = null != arguments[i] ? arguments[i] : {};
|
|
32
|
-
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
|
|
33
|
-
_defineProperty(target, key, source[key]);
|
|
34
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
|
|
35
|
-
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return target;
|
|
39
|
-
}
|
|
40
|
-
function _defineProperty(obj, key, value) {
|
|
41
|
-
key = _toPropertyKey(key);
|
|
42
|
-
if (key in obj) {
|
|
43
|
-
Object.defineProperty(obj, key, {
|
|
44
|
-
value: value,
|
|
45
|
-
enumerable: true,
|
|
46
|
-
configurable: true,
|
|
47
|
-
writable: true
|
|
48
|
-
});
|
|
49
|
-
} else {
|
|
50
|
-
obj[key] = value;
|
|
51
|
-
}
|
|
52
|
-
return obj;
|
|
53
|
-
}
|
|
54
19
|
function _extends() {
|
|
55
|
-
_extends = Object.assign
|
|
20
|
+
_extends = Object.assign || function (target) {
|
|
56
21
|
for (var i = 1; i < arguments.length; i++) {
|
|
57
22
|
var source = arguments[i];
|
|
23
|
+
|
|
58
24
|
for (var key in source) {
|
|
59
25
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
60
26
|
target[key] = source[key];
|
|
61
27
|
}
|
|
62
28
|
}
|
|
63
29
|
}
|
|
30
|
+
|
|
64
31
|
return target;
|
|
65
32
|
};
|
|
33
|
+
|
|
66
34
|
return _extends.apply(this, arguments);
|
|
67
35
|
}
|
|
68
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
69
|
-
if (source == null) return {};
|
|
70
|
-
var target = {};
|
|
71
|
-
var sourceKeys = Object.keys(source);
|
|
72
|
-
var key, i;
|
|
73
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
74
|
-
key = sourceKeys[i];
|
|
75
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
76
|
-
target[key] = source[key];
|
|
77
|
-
}
|
|
78
|
-
return target;
|
|
79
|
-
}
|
|
80
|
-
function _objectWithoutProperties(source, excluded) {
|
|
81
|
-
if (source == null) return {};
|
|
82
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
83
|
-
var key, i;
|
|
84
|
-
if (Object.getOwnPropertySymbols) {
|
|
85
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
86
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
87
|
-
key = sourceSymbolKeys[i];
|
|
88
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
89
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
90
|
-
target[key] = source[key];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return target;
|
|
94
|
-
}
|
|
95
|
-
function _toPrimitive(input, hint) {
|
|
96
|
-
if (typeof input !== "object" || input === null) return input;
|
|
97
|
-
var prim = input[Symbol.toPrimitive];
|
|
98
|
-
if (prim !== undefined) {
|
|
99
|
-
var res = prim.call(input, hint || "default");
|
|
100
|
-
if (typeof res !== "object") return res;
|
|
101
|
-
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
102
|
-
}
|
|
103
|
-
return (hint === "string" ? String : Number)(input);
|
|
104
|
-
}
|
|
105
|
-
function _toPropertyKey(arg) {
|
|
106
|
-
var key = _toPrimitive(arg, "string");
|
|
107
|
-
return typeof key === "symbol" ? key : String(key);
|
|
108
|
-
}
|
|
109
36
|
|
|
110
37
|
/**
|
|
111
38
|
* This file contains constants for keypad buttons that aren't single
|
|
@@ -115,7 +42,7 @@ function _toPropertyKey(arg) {
|
|
|
115
42
|
// TODO(charlie): There's duplication between this file and key-configs.js.
|
|
116
43
|
// We should clean it up by removing this file and requiring clients to use the
|
|
117
44
|
// `id` field on the key configurations.
|
|
118
|
-
|
|
45
|
+
const Keys = {
|
|
119
46
|
PLUS: "PLUS",
|
|
120
47
|
MINUS: "MINUS",
|
|
121
48
|
NEGATIVE: "NEGATIVE",
|
|
@@ -177,11 +104,11 @@ var Keys = {
|
|
|
177
104
|
|
|
178
105
|
class Text extends React.Component {
|
|
179
106
|
render() {
|
|
180
|
-
|
|
107
|
+
const {
|
|
181
108
|
numberOfLines,
|
|
182
109
|
style
|
|
183
110
|
} = this.props;
|
|
184
|
-
|
|
111
|
+
const className = css(styles$f.initial, ...(Array.isArray(style) ? style : [style]), numberOfLines === 1 && styles$f.singleLineStyle);
|
|
185
112
|
return /*#__PURE__*/React.createElement("span", {
|
|
186
113
|
className: className,
|
|
187
114
|
style: this.props.dynamicStyle
|
|
@@ -190,7 +117,7 @@ class Text extends React.Component {
|
|
|
190
117
|
}
|
|
191
118
|
|
|
192
119
|
// https://github.com/necolas/react-native-web/blob/master/src/components/Text/index.js
|
|
193
|
-
|
|
120
|
+
const styles$f = StyleSheet.create({
|
|
194
121
|
initial: {
|
|
195
122
|
color: "inherit",
|
|
196
123
|
display: "inline",
|
|
@@ -212,7 +139,7 @@ class View extends React.Component {
|
|
|
212
139
|
// $FlowFixMe[signature-verification-failure]
|
|
213
140
|
|
|
214
141
|
render() {
|
|
215
|
-
|
|
142
|
+
const className = css(View.styles.initial, ...(Array.isArray(this.props.style) ? this.props.style : [this.props.style])) + (this.props.extraClassName ? ` ${this.props.extraClassName}` : "");
|
|
216
143
|
return /*#__PURE__*/React.createElement("div", {
|
|
217
144
|
className: className,
|
|
218
145
|
style: this.props.dynamicStyle,
|
|
@@ -226,7 +153,7 @@ class View extends React.Component {
|
|
|
226
153
|
}, this.props.children);
|
|
227
154
|
}
|
|
228
155
|
}
|
|
229
|
-
|
|
156
|
+
View.styles = StyleSheet.create({
|
|
230
157
|
// From: https://github.com/necolas/react-native-web/blob/master/src/components/View/index.js
|
|
231
158
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
232
159
|
initial: {
|
|
@@ -253,71 +180,71 @@ _defineProperty(View, "styles", StyleSheet.create({
|
|
|
253
180
|
minHeight: 0,
|
|
254
181
|
minWidth: 0
|
|
255
182
|
}
|
|
256
|
-
})
|
|
183
|
+
});
|
|
257
184
|
|
|
258
185
|
/**
|
|
259
186
|
* Common parameters used to style components.
|
|
260
187
|
*/
|
|
261
|
-
|
|
262
|
-
|
|
188
|
+
const wonderBlocksBlue = Color.blue;
|
|
189
|
+
const offBlack = Color.offBlack;
|
|
263
190
|
Color.offBlack32;
|
|
264
|
-
|
|
191
|
+
const offBlack16 = Color.offBlack16;
|
|
265
192
|
Color.offBlack8;
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
193
|
+
const iconSizeHeightPx = 48;
|
|
194
|
+
const iconSizeWidthPx = 48;
|
|
195
|
+
const compactKeypadBorderRadiusPx = 4;
|
|
196
|
+
const cursorHandleRadiusPx = 11;
|
|
270
197
|
|
|
271
198
|
// The amount to multiply the radius by to get the distance from the
|
|
272
199
|
// center to the tip of the cursor handle. The cursor is a circle with
|
|
273
200
|
// one quadrant replace with a square. The hypotenuse of the square is
|
|
274
201
|
// 1.045 times the radius of the circle.
|
|
275
|
-
|
|
202
|
+
const cursorHandleDistanceMultiplier = 1.045;
|
|
276
203
|
|
|
277
204
|
// Keypad button colors
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
205
|
+
const valueGrey = "#FFF";
|
|
206
|
+
const operatorGrey = "#FAFAFA";
|
|
207
|
+
const controlGrey = "#F6F7F7";
|
|
208
|
+
const emptyGrey = "#F0F1F2";
|
|
282
209
|
|
|
283
210
|
// Constants defining any borders between elements in the keypad.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
211
|
+
const innerBorderColor = offBlack16;
|
|
212
|
+
const innerBorderStyle = "solid";
|
|
213
|
+
const innerBorderWidthPx = 1;
|
|
287
214
|
|
|
288
215
|
// The width at which a device is classified as a "tablet" for the purposes
|
|
289
216
|
// of the keypad layout.
|
|
290
|
-
|
|
217
|
+
const tabletCutoffPx = 600;
|
|
291
218
|
|
|
292
219
|
// The dimensions that define various components in the tree, which may be
|
|
293
220
|
// needed outside of those components in order to determine various layout
|
|
294
221
|
// parameters.
|
|
295
|
-
|
|
296
|
-
|
|
222
|
+
const pageIndicatorHeightPx = 16;
|
|
223
|
+
const navigationPadWidthPx = 192;
|
|
297
224
|
// HACK(charlie): This should be injected by webapp somehow.
|
|
298
225
|
// TODO(charlie): Add a link to the webapp location as soon as the footer
|
|
299
226
|
// has settled down.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
227
|
+
const toolbarHeightPx = 60;
|
|
228
|
+
|
|
229
|
+
const touchTargetRadiusPx = 2 * cursorHandleRadiusPx;
|
|
230
|
+
const touchTargetHeightPx = 2 * touchTargetRadiusPx;
|
|
231
|
+
const touchTargetWidthPx = 2 * touchTargetRadiusPx;
|
|
232
|
+
const cursorRadiusPx = cursorHandleRadiusPx;
|
|
233
|
+
const cursorHeightPx = cursorHandleDistanceMultiplier * (cursorRadiusPx * 4);
|
|
234
|
+
const cursorWidthPx = 4 * cursorRadiusPx;
|
|
308
235
|
class CursorHandle extends React.Component {
|
|
309
236
|
render() {
|
|
310
|
-
|
|
237
|
+
const {
|
|
311
238
|
x,
|
|
312
239
|
y,
|
|
313
240
|
animateIntoPosition
|
|
314
241
|
} = this.props;
|
|
315
|
-
|
|
242
|
+
const animationStyle = animateIntoPosition ? {
|
|
316
243
|
transitionDuration: "100ms",
|
|
317
244
|
transitionProperty: "transform"
|
|
318
245
|
} : {};
|
|
319
|
-
|
|
320
|
-
|
|
246
|
+
const transformString = `translate(${x}px, ${y}px)`;
|
|
247
|
+
const outerStyle = _extends({
|
|
321
248
|
position: "absolute",
|
|
322
249
|
// This is essentially webapp's interactiveComponent + 1.
|
|
323
250
|
// TODO(charlie): Pull in those styles somehow to avoid breakages.
|
|
@@ -341,7 +268,7 @@ class CursorHandle extends React.Component {
|
|
|
341
268
|
fill: "none",
|
|
342
269
|
width: cursorWidthPx,
|
|
343
270
|
height: cursorHeightPx,
|
|
344
|
-
viewBox:
|
|
271
|
+
viewBox: `0 0 ${cursorWidthPx} ${cursorHeightPx}`
|
|
345
272
|
}, /*#__PURE__*/React.createElement("filter", {
|
|
346
273
|
id: "math-input_cursor",
|
|
347
274
|
colorInterpolationFilters: "sRGB",
|
|
@@ -387,12 +314,12 @@ class CursorHandle extends React.Component {
|
|
|
387
314
|
})));
|
|
388
315
|
}
|
|
389
316
|
}
|
|
390
|
-
|
|
317
|
+
CursorHandle.defaultProps = {
|
|
391
318
|
animateIntoPosition: false,
|
|
392
319
|
visible: false,
|
|
393
320
|
x: 0,
|
|
394
321
|
y: 0
|
|
395
|
-
}
|
|
322
|
+
};
|
|
396
323
|
|
|
397
324
|
/**
|
|
398
325
|
* A gesture recognizer that detects 'drags', crudely defined as either scrolls
|
|
@@ -402,7 +329,7 @@ _defineProperty(CursorHandle, "defaultProps", {
|
|
|
402
329
|
// The 'slop' factor, after which we consider the use to be dragging. The value
|
|
403
330
|
// is taken from the Android SDK. It won't be robust to page zoom and the like,
|
|
404
331
|
// but it should be good enough for our purposes.
|
|
405
|
-
|
|
332
|
+
const touchSlopPx = 8;
|
|
406
333
|
class DragListener {
|
|
407
334
|
constructor(onDrag, initialEvent) {
|
|
408
335
|
// We detect drags in two ways. First, by listening for the window
|
|
@@ -414,21 +341,21 @@ class DragListener {
|
|
|
414
341
|
// And second, by listening for touch moves and tracking the each
|
|
415
342
|
// finger's displacement. This allows us to track, e.g., when the user
|
|
416
343
|
// scrolls within an individual view.
|
|
417
|
-
|
|
418
|
-
for (
|
|
419
|
-
|
|
344
|
+
const touchLocationsById = {};
|
|
345
|
+
for (let i = 0; i < initialEvent.changedTouches.length; i++) {
|
|
346
|
+
const touch = initialEvent.changedTouches[i];
|
|
420
347
|
touchLocationsById[touch.identifier] = [touch.clientX, touch.clientY];
|
|
421
348
|
}
|
|
422
349
|
this._moveListener = evt => {
|
|
423
|
-
for (
|
|
424
|
-
|
|
425
|
-
|
|
350
|
+
for (let i = 0; i < evt.changedTouches.length; i++) {
|
|
351
|
+
const touch = evt.changedTouches[i];
|
|
352
|
+
const initialTouchLocation = touchLocationsById[touch.identifier];
|
|
426
353
|
if (initialTouchLocation) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
354
|
+
const touchLocation = [touch.clientX, touch.clientY];
|
|
355
|
+
const dx = touchLocation[0] - initialTouchLocation[0];
|
|
356
|
+
const dy = touchLocation[1] - initialTouchLocation[1];
|
|
357
|
+
const squaredDist = dx * dx + dy * dy;
|
|
358
|
+
const squaredTouchSlop = touchSlopPx * touchSlopPx;
|
|
432
359
|
if (squaredDist > squaredTouchSlop) {
|
|
433
360
|
onDrag();
|
|
434
361
|
}
|
|
@@ -439,8 +366,8 @@ class DragListener {
|
|
|
439
366
|
// Clean-up any terminated gestures, since some browsers reuse
|
|
440
367
|
// identifiers.
|
|
441
368
|
this._endAndCancelListener = evt => {
|
|
442
|
-
for (
|
|
443
|
-
delete touchLocationsById[evt.changedTouches[
|
|
369
|
+
for (let i = 0; i < evt.changedTouches.length; i++) {
|
|
370
|
+
delete touchLocationsById[evt.changedTouches[i].identifier];
|
|
444
371
|
}
|
|
445
372
|
};
|
|
446
373
|
}
|
|
@@ -463,11 +390,11 @@ class DragListener {
|
|
|
463
390
|
*/
|
|
464
391
|
|
|
465
392
|
// TODO: Retire this in favour of KeypadType (above)
|
|
466
|
-
|
|
393
|
+
const KeypadTypes = {
|
|
467
394
|
FRACTION: "FRACTION",
|
|
468
395
|
EXPRESSION: "EXPRESSION"
|
|
469
396
|
};
|
|
470
|
-
|
|
397
|
+
const KeyTypes = {
|
|
471
398
|
EMPTY: "EMPTY",
|
|
472
399
|
// For numerals, variables, and any other characters that themselves
|
|
473
400
|
// compose 'values'.
|
|
@@ -486,38 +413,38 @@ var KeyTypes = {
|
|
|
486
413
|
// For the echo animation that appears on press.
|
|
487
414
|
ECHO: "ECHO"
|
|
488
415
|
};
|
|
489
|
-
|
|
416
|
+
const DeviceOrientations = {
|
|
490
417
|
LANDSCAPE: "LANDSCAPE",
|
|
491
418
|
PORTRAIT: "PORTRAIT"
|
|
492
419
|
};
|
|
493
|
-
|
|
420
|
+
const DeviceTypes = {
|
|
494
421
|
PHONE: "PHONE",
|
|
495
422
|
TABLET: "TABLET"
|
|
496
423
|
};
|
|
497
|
-
|
|
424
|
+
const LayoutModes = {
|
|
498
425
|
FULLSCREEN: "FULLSCREEN",
|
|
499
426
|
COMPACT: "COMPACT"
|
|
500
427
|
};
|
|
501
|
-
|
|
428
|
+
const BorderDirections = {
|
|
502
429
|
LEFT: "LEFT",
|
|
503
430
|
BOTTOM: "BOTTOM"
|
|
504
431
|
};
|
|
505
|
-
|
|
432
|
+
const BorderStyles = {
|
|
506
433
|
LEFT: ["LEFT"],
|
|
507
434
|
BOTTOM: ["BOTTOM"],
|
|
508
435
|
ALL: ["LEFT", "BOTTOM"],
|
|
509
436
|
NONE: []
|
|
510
437
|
};
|
|
511
|
-
|
|
438
|
+
const IconTypes = {
|
|
512
439
|
MATH: "MATH",
|
|
513
440
|
SVG: "SVG",
|
|
514
441
|
TEXT: "TEXT"
|
|
515
442
|
};
|
|
516
|
-
|
|
443
|
+
const DecimalSeparators = {
|
|
517
444
|
COMMA: "COMMA",
|
|
518
445
|
PERIOD: "PERIOD"
|
|
519
446
|
};
|
|
520
|
-
|
|
447
|
+
const EchoAnimationTypes = {
|
|
521
448
|
SLIDE_AND_FADE: "SLIDE_AND_FADE",
|
|
522
449
|
FADE_ONLY: "FADE_ONLY",
|
|
523
450
|
LONG_FADE_ONLY: "LONG_FADE_ONLY"
|
|
@@ -529,7 +456,7 @@ var EchoAnimationTypes = {
|
|
|
529
456
|
// imported from wonder-blocks-i18n.
|
|
530
457
|
// - Some languages/locales use different decimal separators than the ones
|
|
531
458
|
// listed here. Much of the Arab world uses U+066C.
|
|
532
|
-
|
|
459
|
+
const decimalSeparator = getDecimalSeparator() === "," ? DecimalSeparators.COMMA : DecimalSeparators.PERIOD;
|
|
533
460
|
|
|
534
461
|
/**
|
|
535
462
|
* Constants that define the various contexts in which a cursor can exist. The
|
|
@@ -546,22 +473,22 @@ var decimalSeparator = getDecimalSeparator() === "," ? DecimalSeparators.COMMA :
|
|
|
546
473
|
// TODO: Get rid of these constants in favour of CursorContext type.
|
|
547
474
|
|
|
548
475
|
// The cursor is not in any of the other viable contexts.
|
|
549
|
-
|
|
476
|
+
const NONE = "NONE";
|
|
550
477
|
// The cursor is within a set of parentheses.
|
|
551
|
-
|
|
478
|
+
const IN_PARENS = "IN_PARENS";
|
|
552
479
|
// The cursor is within a superscript (e.g., an exponent).
|
|
553
|
-
|
|
480
|
+
const IN_SUPER_SCRIPT = "IN_SUPER_SCRIPT";
|
|
554
481
|
// The cursor is within a subscript (e.g., the base of a custom logarithm).
|
|
555
|
-
|
|
482
|
+
const IN_SUB_SCRIPT = "IN_SUB_SCRIPT";
|
|
556
483
|
// The cursor is in the numerator of a fraction.
|
|
557
|
-
|
|
484
|
+
const IN_NUMERATOR = "IN_NUMERATOR";
|
|
558
485
|
// The cursor is in the denominator of a fraction.
|
|
559
|
-
|
|
486
|
+
const IN_DENOMINATOR = "IN_DENOMINATOR";
|
|
560
487
|
// The cursor is sitting before a fraction; that is, the cursor is within
|
|
561
488
|
// what looks to be a mixed number preceding a fraction. This will only be
|
|
562
489
|
// the case when the only math between the cursor and the fraction to its
|
|
563
490
|
// write is non-leaf math (numbers and variables).
|
|
564
|
-
|
|
491
|
+
const BEFORE_FRACTION = "BEFORE_FRACTION";
|
|
565
492
|
|
|
566
493
|
var CursorContexts = /*#__PURE__*/Object.freeze({
|
|
567
494
|
__proto__: null,
|
|
@@ -583,17 +510,17 @@ var CursorContexts = /*#__PURE__*/Object.freeze({
|
|
|
583
510
|
// Keeping `window` in place for test suite and GitHub Pages.
|
|
584
511
|
// If it does not exist, fall back to CommonJS require. - jsatk
|
|
585
512
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
513
|
+
const decimalSymbol = decimalSeparator === DecimalSeparators.COMMA ? "," : ".";
|
|
514
|
+
const WRITE = "write";
|
|
515
|
+
const CMD = "cmd";
|
|
516
|
+
const KEYSTROKE = "keystroke";
|
|
517
|
+
const MQ_END = 0;
|
|
591
518
|
|
|
592
519
|
// A mapping from keys that can be pressed on a keypad to the way in which
|
|
593
520
|
// MathQuill should modify its input in response to that key-press. Any keys
|
|
594
521
|
// that do not provide explicit actions (like the numeral keys) will merely
|
|
595
522
|
// write their contents to MathQuill.
|
|
596
|
-
|
|
523
|
+
const KeyActions = {
|
|
597
524
|
[Keys.PLUS]: {
|
|
598
525
|
str: "+",
|
|
599
526
|
fn: WRITE
|
|
@@ -689,23 +616,23 @@ var KeyActions = {
|
|
|
689
616
|
fn: CMD
|
|
690
617
|
}
|
|
691
618
|
};
|
|
692
|
-
|
|
619
|
+
const NormalCommands = {
|
|
693
620
|
[Keys.LOG]: "log",
|
|
694
621
|
[Keys.LN]: "ln",
|
|
695
622
|
[Keys.SIN]: "sin",
|
|
696
623
|
[Keys.COS]: "cos",
|
|
697
624
|
[Keys.TAN]: "tan"
|
|
698
625
|
};
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
626
|
+
const ArithmeticOperators = ["+", "-", "\\cdot", "\\times", "\\div"];
|
|
627
|
+
const EqualityOperators = ["=", "\\neq", "<", "\\leq", ">", "\\geq"];
|
|
628
|
+
const Numerals = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
|
|
629
|
+
const GreekLetters = ["\\theta", "\\pi"];
|
|
630
|
+
const Letters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
|
|
704
631
|
|
|
705
632
|
// We only consider numerals, variables, and Greek Letters to be proper
|
|
706
633
|
// leaf nodes.
|
|
707
|
-
|
|
708
|
-
|
|
634
|
+
const ValidLeaves = [...Numerals, ...GreekLetters, ...Letters.map(letter => letter.toLowerCase()), ...Letters.map(letter => letter.toUpperCase())];
|
|
635
|
+
const KeysForJumpContext = {
|
|
709
636
|
[IN_PARENS]: Keys.JUMP_OUT_PARENTHESES,
|
|
710
637
|
[IN_SUPER_SCRIPT]: Keys.JUMP_OUT_EXPONENT,
|
|
711
638
|
[IN_SUB_SCRIPT]: Keys.JUMP_OUT_BASE,
|
|
@@ -714,13 +641,12 @@ var KeysForJumpContext = {
|
|
|
714
641
|
[IN_DENOMINATOR]: Keys.JUMP_OUT_DENOMINATOR
|
|
715
642
|
};
|
|
716
643
|
class MathWrapper {
|
|
717
|
-
constructor(element) {
|
|
718
|
-
var callbacks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
644
|
+
constructor(element, options = {}, callbacks = {}) {
|
|
719
645
|
this.MQ = MathQuill.getInterface(2);
|
|
720
646
|
this.mathField = this.MQ.MathField(element, {
|
|
721
647
|
// use a span instead of a textarea so that we don't bring up the
|
|
722
648
|
// native keyboard on mobile when selecting the input
|
|
723
|
-
substituteTextarea: function
|
|
649
|
+
substituteTextarea: function () {
|
|
724
650
|
return document.createElement("span");
|
|
725
651
|
}
|
|
726
652
|
});
|
|
@@ -730,7 +656,7 @@ class MathWrapper {
|
|
|
730
656
|
// HACK(charlie): We shouldn't reaching into MathQuill internals like
|
|
731
657
|
// this, but it's the easiest way to allow us to manage the focus state
|
|
732
658
|
// ourselves.
|
|
733
|
-
|
|
659
|
+
const controller = this.mathField.__controller;
|
|
734
660
|
controller.cursor.show();
|
|
735
661
|
|
|
736
662
|
// Set MathQuill's internal state to reflect the focus, otherwise it
|
|
@@ -739,12 +665,12 @@ class MathWrapper {
|
|
|
739
665
|
controller.blurred = false;
|
|
740
666
|
}
|
|
741
667
|
blur() {
|
|
742
|
-
|
|
668
|
+
const controller = this.mathField.__controller;
|
|
743
669
|
controller.cursor.hide();
|
|
744
670
|
controller.blurred = true;
|
|
745
671
|
}
|
|
746
672
|
_writeNormalFunction(name) {
|
|
747
|
-
this.mathField.write(
|
|
673
|
+
this.mathField.write(`\\${name}\\left(\\right)`);
|
|
748
674
|
this.mathField.keystroke("Left");
|
|
749
675
|
}
|
|
750
676
|
|
|
@@ -755,9 +681,9 @@ class MathWrapper {
|
|
|
755
681
|
* @returns {object} a cursor object, consisting of a cursor context
|
|
756
682
|
*/
|
|
757
683
|
pressKey(key) {
|
|
758
|
-
|
|
684
|
+
const cursor = this.mathField.__controller.cursor;
|
|
759
685
|
if (key in KeyActions) {
|
|
760
|
-
|
|
686
|
+
const {
|
|
761
687
|
str,
|
|
762
688
|
fn
|
|
763
689
|
} = KeyActions[key];
|
|
@@ -769,7 +695,7 @@ class MathWrapper {
|
|
|
769
695
|
} else if (key === Keys.FRAC_EXCLUSIVE) {
|
|
770
696
|
// If there's nothing to the left of the cursor, then we want to
|
|
771
697
|
// leave the cursor to the left of the fraction after creating it.
|
|
772
|
-
|
|
698
|
+
const shouldNavigateLeft = cursor[this.MQ.L] === MQ_END;
|
|
773
699
|
this.mathField.cmd("\\frac");
|
|
774
700
|
if (shouldNavigateLeft) {
|
|
775
701
|
this.mathField.keystroke("Left");
|
|
@@ -828,24 +754,24 @@ class MathWrapper {
|
|
|
828
754
|
* should be placed
|
|
829
755
|
*/
|
|
830
756
|
setCursorPosition(x, y, hitNode) {
|
|
831
|
-
|
|
757
|
+
const el = hitNode || document.elementFromPoint(x, y);
|
|
832
758
|
if (el) {
|
|
833
|
-
|
|
759
|
+
const cursor = this.getCursor();
|
|
834
760
|
if (el.hasAttribute("mq-root-block")) {
|
|
835
761
|
// If we're in the empty area place the cursor at the right
|
|
836
762
|
// end of the expression.
|
|
837
763
|
cursor.insAtRightEnd(this.mathField.__controller.root);
|
|
838
764
|
} else {
|
|
839
765
|
// Otherwise place beside the element at x, y.
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
766
|
+
const controller = this.mathField.__controller;
|
|
767
|
+
const pageX = x - document.body.scrollLeft;
|
|
768
|
+
const pageY = y - document.body.scrollTop;
|
|
843
769
|
controller.seek($(el), pageX, pageY).cursor.startSelection();
|
|
844
770
|
|
|
845
771
|
// Unless that would leave us mid-command, in which case, we
|
|
846
772
|
// need to adjust and place the cursor inside the parens
|
|
847
773
|
// following the command.
|
|
848
|
-
|
|
774
|
+
const command = this._maybeFindCommand(cursor[this.MQ.L]);
|
|
849
775
|
if (command && command.endNode) {
|
|
850
776
|
// NOTE(charlie): endNode should definitely be \left(.
|
|
851
777
|
cursor.insLeftOf(command.endNode);
|
|
@@ -872,7 +798,7 @@ class MathWrapper {
|
|
|
872
798
|
this.mathField.latex(latex);
|
|
873
799
|
}
|
|
874
800
|
isEmpty() {
|
|
875
|
-
|
|
801
|
+
const cursor = this.getCursor();
|
|
876
802
|
return cursor.parent.id === 1 && cursor[1] === 0 && cursor[-1] === 0;
|
|
877
803
|
}
|
|
878
804
|
|
|
@@ -893,8 +819,8 @@ class MathWrapper {
|
|
|
893
819
|
// when upgrading MathQuill.
|
|
894
820
|
|
|
895
821
|
_handleBackspaceInNthRoot(cursor) {
|
|
896
|
-
|
|
897
|
-
|
|
822
|
+
const isAtLeftEnd = cursor[this.MQ.L] === MQ_END;
|
|
823
|
+
const isRootEmpty = this._isInsideEmptyNode(cursor.parent.parent.blocks[0].ends);
|
|
898
824
|
if (isAtLeftEnd) {
|
|
899
825
|
this._selectNode(cursor.parent.parent, cursor);
|
|
900
826
|
if (isRootEmpty) {
|
|
@@ -912,7 +838,7 @@ class MathWrapper {
|
|
|
912
838
|
* @private
|
|
913
839
|
*/
|
|
914
840
|
_handleJumpOut(cursor, key) {
|
|
915
|
-
|
|
841
|
+
const context = this.contextForCursor(cursor);
|
|
916
842
|
|
|
917
843
|
// Validate that the current cursor context matches the key's intent.
|
|
918
844
|
if (KeysForJumpContext[context] !== key) {
|
|
@@ -931,8 +857,8 @@ class MathWrapper {
|
|
|
931
857
|
break;
|
|
932
858
|
case BEFORE_FRACTION:
|
|
933
859
|
// Find the nearest fraction to the right of the cursor.
|
|
934
|
-
|
|
935
|
-
|
|
860
|
+
let fractionNode;
|
|
861
|
+
let visitor = cursor;
|
|
936
862
|
while (visitor[this.MQ.R] !== MQ_END) {
|
|
937
863
|
if (this._isFraction(visitor[this.MQ.R])) {
|
|
938
864
|
fractionNode = visitor[this.MQ.R];
|
|
@@ -951,7 +877,7 @@ class MathWrapper {
|
|
|
951
877
|
// continue rightwards until we find ourselves inside of it.
|
|
952
878
|
// It's possible that there are cases in which we don't reach
|
|
953
879
|
// the denominator, though I can't think of any.
|
|
954
|
-
|
|
880
|
+
const siblingDenominator = cursor.parent.parent.blocks[1];
|
|
955
881
|
while (cursor.parent !== siblingDenominator) {
|
|
956
882
|
this.mathField.keystroke("Right");
|
|
957
883
|
}
|
|
@@ -975,7 +901,7 @@ class MathWrapper {
|
|
|
975
901
|
cursor.insRightOf(cursor.parent.parent);
|
|
976
902
|
break;
|
|
977
903
|
default:
|
|
978
|
-
throw new Error(
|
|
904
|
+
throw new Error(`Attempted to 'Jump Out' from node, but found no ` + `appropriate cursor context: ${context}`);
|
|
979
905
|
}
|
|
980
906
|
}
|
|
981
907
|
|
|
@@ -988,9 +914,9 @@ class MathWrapper {
|
|
|
988
914
|
*/
|
|
989
915
|
_handleBackspace(cursor) {
|
|
990
916
|
if (!cursor.selection) {
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
917
|
+
const parent = cursor.parent;
|
|
918
|
+
const grandparent = parent.parent;
|
|
919
|
+
const leftNode = cursor[this.MQ.L];
|
|
994
920
|
if (this._isFraction(leftNode)) {
|
|
995
921
|
this._selectNode(leftNode, cursor);
|
|
996
922
|
} else if (this._isSquareRoot(leftNode)) {
|
|
@@ -1028,10 +954,10 @@ class MathWrapper {
|
|
|
1028
954
|
// the nodes to the left of our grandparent comprise a valid function
|
|
1029
955
|
// name.
|
|
1030
956
|
if (cursor[this.MQ.L] === MQ_END) {
|
|
1031
|
-
|
|
1032
|
-
|
|
957
|
+
const parent = cursor.parent;
|
|
958
|
+
const grandparent = parent.parent;
|
|
1033
959
|
if (grandparent.ctrlSeq === "\\left(") {
|
|
1034
|
-
|
|
960
|
+
const command = this._maybeFindCommandBeforeParens(grandparent);
|
|
1035
961
|
if (command) {
|
|
1036
962
|
cursor.insLeftOf(command.startNode);
|
|
1037
963
|
return;
|
|
@@ -1043,7 +969,7 @@ class MathWrapper {
|
|
|
1043
969
|
this.mathField.keystroke("Left");
|
|
1044
970
|
}
|
|
1045
971
|
_handleRightArrow(cursor) {
|
|
1046
|
-
|
|
972
|
+
const command = this._maybeFindCommand(cursor[this.MQ.R]);
|
|
1047
973
|
if (command) {
|
|
1048
974
|
// Similarly, if a function is to our right, then we need to place
|
|
1049
975
|
// the cursor at the start of its parenthetical content, which is
|
|
@@ -1060,9 +986,9 @@ class MathWrapper {
|
|
|
1060
986
|
// If there's an invalid operator preceding the cursor (anything that
|
|
1061
987
|
// knowingly cannot be raised to a power), add an empty set of
|
|
1062
988
|
// parentheses and apply the exponent to that.
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
989
|
+
const invalidPrefixes = [...ArithmeticOperators, ...EqualityOperators];
|
|
990
|
+
const precedingNode = cursor[this.MQ.L];
|
|
991
|
+
const shouldPrefixWithParens = precedingNode === MQ_END || invalidPrefixes.includes(precedingNode.ctrlSeq.trim());
|
|
1066
992
|
if (shouldPrefixWithParens) {
|
|
1067
993
|
this.mathField.write("\\left(\\right)");
|
|
1068
994
|
}
|
|
@@ -1074,7 +1000,7 @@ class MathWrapper {
|
|
|
1074
1000
|
break;
|
|
1075
1001
|
case Keys.EXP_2:
|
|
1076
1002
|
case Keys.EXP_3:
|
|
1077
|
-
this.mathField.write(
|
|
1003
|
+
this.mathField.write(`^${key === Keys.EXP_2 ? 2 : 3}`);
|
|
1078
1004
|
|
|
1079
1005
|
// If we enter a square or a cube, we should leave the cursor
|
|
1080
1006
|
// within the newly inserted parens, if they exist. This takes
|
|
@@ -1088,7 +1014,7 @@ class MathWrapper {
|
|
|
1088
1014
|
}
|
|
1089
1015
|
break;
|
|
1090
1016
|
default:
|
|
1091
|
-
throw new Error(
|
|
1017
|
+
throw new Error(`Invalid exponent key: ${key}`);
|
|
1092
1018
|
}
|
|
1093
1019
|
}
|
|
1094
1020
|
|
|
@@ -1116,24 +1042,24 @@ class MathWrapper {
|
|
|
1116
1042
|
// command. If we encounter any character that doesn't belong in a
|
|
1117
1043
|
// command, we return null. We match a single character at a time.
|
|
1118
1044
|
// Ex) ['\\l', 'o', 'g ', '\\left(', ...]
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1045
|
+
const commandCharRegex = /^[a-z]$/;
|
|
1046
|
+
const commandStartRegex = /^\\[a-z]$/;
|
|
1047
|
+
const commandEndSeq = "\\left(";
|
|
1122
1048
|
|
|
1123
1049
|
// Note: We allowlist the set of valid commands, since relying solely on
|
|
1124
1050
|
// a command being prefixed with a backslash leads to undesired
|
|
1125
1051
|
// behavior. For example, Greek symbols, left parentheses, and square
|
|
1126
1052
|
// roots all get treated as commands.
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1053
|
+
const validCommands = ["\\log", "\\ln", "\\cos", "\\sin", "\\tan"];
|
|
1054
|
+
let name = "";
|
|
1055
|
+
let startNode;
|
|
1056
|
+
let endNode;
|
|
1131
1057
|
|
|
1132
1058
|
// Collect the portion of the command from the current node, leftwards
|
|
1133
1059
|
// until the start of the command.
|
|
1134
|
-
|
|
1060
|
+
let node = initialNode;
|
|
1135
1061
|
while (node !== 0) {
|
|
1136
|
-
|
|
1062
|
+
const ctrlSeq = node.ctrlSeq.trim();
|
|
1137
1063
|
if (commandCharRegex.test(ctrlSeq)) {
|
|
1138
1064
|
name = ctrlSeq + name;
|
|
1139
1065
|
} else if (commandStartRegex.test(ctrlSeq)) {
|
|
@@ -1153,12 +1079,12 @@ class MathWrapper {
|
|
|
1153
1079
|
// Next, iterate from the start to the right.
|
|
1154
1080
|
node = initialNode[this.MQ.R];
|
|
1155
1081
|
while (node !== 0) {
|
|
1156
|
-
|
|
1157
|
-
if (commandCharRegex.test(
|
|
1082
|
+
const ctrlSeq = node.ctrlSeq.trim();
|
|
1083
|
+
if (commandCharRegex.test(ctrlSeq)) {
|
|
1158
1084
|
// If we have a single character, add it to the command
|
|
1159
1085
|
// name.
|
|
1160
|
-
name = name +
|
|
1161
|
-
} else if (
|
|
1086
|
+
name = name + ctrlSeq;
|
|
1087
|
+
} else if (ctrlSeq === commandEndSeq) {
|
|
1162
1088
|
// If we hit the command end delimiter (the left
|
|
1163
1089
|
// parentheses surrounding its arguments), stop.
|
|
1164
1090
|
endNode = node;
|
|
@@ -1237,9 +1163,9 @@ class MathWrapper {
|
|
|
1237
1163
|
return node.jQ && node.jQ.hasClass("mq-nthroot");
|
|
1238
1164
|
}
|
|
1239
1165
|
_isInsideLogIndex(cursor) {
|
|
1240
|
-
|
|
1166
|
+
const grandparent = cursor.parent.parent;
|
|
1241
1167
|
if (grandparent && grandparent.jQ.hasClass("mq-supsub")) {
|
|
1242
|
-
|
|
1168
|
+
const command = this._maybeFindCommandBeforeParens(grandparent);
|
|
1243
1169
|
if (command && command.name === "\\log") {
|
|
1244
1170
|
return true;
|
|
1245
1171
|
}
|
|
@@ -1255,11 +1181,11 @@ class MathWrapper {
|
|
|
1255
1181
|
// to a sqrt, e.g. \sqrt[|]{35x-5} => |\sqrt{35x-5}. If there's no
|
|
1256
1182
|
// content under the root, then we delete the whole thing.
|
|
1257
1183
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1184
|
+
const grandparent = cursor.parent.parent;
|
|
1185
|
+
const latex = grandparent.latex();
|
|
1186
|
+
const reinsertionPoint = grandparent[this.MQ.L];
|
|
1261
1187
|
this._selectNode(grandparent, cursor);
|
|
1262
|
-
|
|
1188
|
+
const rootIsEmpty = grandparent.blocks[1].jQ.text() === "";
|
|
1263
1189
|
if (rootIsEmpty) {
|
|
1264
1190
|
// If there is not content under the root then simply delete
|
|
1265
1191
|
// the whole thing.
|
|
@@ -1291,8 +1217,8 @@ class MathWrapper {
|
|
|
1291
1217
|
}
|
|
1292
1218
|
_handleBackspaceInLogIndex(cursor) {
|
|
1293
1219
|
if (this._isInsideEmptyNode(cursor)) {
|
|
1294
|
-
|
|
1295
|
-
|
|
1220
|
+
const grandparent = cursor.parent.parent;
|
|
1221
|
+
const command = this._maybeFindCommandBeforeParens(grandparent);
|
|
1296
1222
|
cursor.insLeftOf(command.startNode);
|
|
1297
1223
|
cursor.startSelection();
|
|
1298
1224
|
if (grandparent[this.MQ.R] !== MQ_END) {
|
|
@@ -1302,7 +1228,7 @@ class MathWrapper {
|
|
|
1302
1228
|
}
|
|
1303
1229
|
cursor.select();
|
|
1304
1230
|
cursor.endSelection();
|
|
1305
|
-
|
|
1231
|
+
const isLogBodyEmpty = grandparent[this.MQ.R].contentjQ.text() === "";
|
|
1306
1232
|
if (isLogBodyEmpty) {
|
|
1307
1233
|
// If there's no content inside the log's parens then delete the
|
|
1308
1234
|
// whole thing.
|
|
@@ -1321,9 +1247,9 @@ class MathWrapper {
|
|
|
1321
1247
|
// (x+1)| => |(x+1)|
|
|
1322
1248
|
// \log(x+1)| => |\log(x+1)|
|
|
1323
1249
|
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1250
|
+
const leftNode = cursor[this.MQ.L];
|
|
1251
|
+
const rightNode = cursor[this.MQ.R];
|
|
1252
|
+
const command = this._maybeFindCommandBeforeParens(leftNode);
|
|
1327
1253
|
if (command && command.startNode) {
|
|
1328
1254
|
// There's a command before the parens so we select it as well as
|
|
1329
1255
|
// the parens.
|
|
@@ -1375,7 +1301,7 @@ class MathWrapper {
|
|
|
1375
1301
|
this.mathField.keystroke("Backspace");
|
|
1376
1302
|
return;
|
|
1377
1303
|
}
|
|
1378
|
-
|
|
1304
|
+
const grandparent = cursor.parent.parent;
|
|
1379
1305
|
|
|
1380
1306
|
// If the cursors is inside the parens at the start but the command
|
|
1381
1307
|
// has a subscript as is the case in log_n then move the cursor into
|
|
@@ -1393,11 +1319,11 @@ class MathWrapper {
|
|
|
1393
1319
|
|
|
1394
1320
|
// Determine if the parens are empty before we modify the
|
|
1395
1321
|
// cursor's position.
|
|
1396
|
-
|
|
1322
|
+
const isEmpty = this._isInsideEmptyNode(cursor);
|
|
1397
1323
|
|
|
1398
1324
|
// Insert the cursor to the left of the command if there is one
|
|
1399
1325
|
// or before the '\\left(` if there isn't
|
|
1400
|
-
|
|
1326
|
+
const command = this._maybeFindCommandBeforeParens(grandparent);
|
|
1401
1327
|
cursor.insLeftOf(command && command.startNode || grandparent);
|
|
1402
1328
|
cursor.startSelection();
|
|
1403
1329
|
cursor.insRightOf(grandparent);
|
|
@@ -1416,7 +1342,7 @@ class MathWrapper {
|
|
|
1416
1342
|
}
|
|
1417
1343
|
contextForCursor(cursor) {
|
|
1418
1344
|
// First, try to find any fraction to the right, unimpeded.
|
|
1419
|
-
|
|
1345
|
+
let visitor = cursor;
|
|
1420
1346
|
while (visitor[this.MQ.R] !== MQ_END) {
|
|
1421
1347
|
if (this._isFraction(visitor[this.MQ.R])) {
|
|
1422
1348
|
return BEFORE_FRACTION;
|
|
@@ -1469,17 +1395,17 @@ function bodyOrHtml() {
|
|
|
1469
1395
|
}
|
|
1470
1396
|
return document.documentElement;
|
|
1471
1397
|
}
|
|
1472
|
-
|
|
1398
|
+
const scrollIntoView = (containerNode, keypadNode) => {
|
|
1473
1399
|
// TODO(charlie): There's no need for us to be reading the keypad bounds
|
|
1474
1400
|
// here, since they're pre-determined by logic in the store. We should
|
|
1475
1401
|
// instead pass around an object that knows the bounds.
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1402
|
+
const containerBounds = containerNode.getBoundingClientRect();
|
|
1403
|
+
const containerBottomPx = containerBounds.bottom;
|
|
1404
|
+
const containerTopPx = containerBounds.top;
|
|
1479
1405
|
|
|
1480
1406
|
// Get the element that scrolls the document.
|
|
1481
|
-
|
|
1482
|
-
|
|
1407
|
+
const scrollNode = bodyOrHtml();
|
|
1408
|
+
const desiredMarginPx = 16;
|
|
1483
1409
|
if (keypadNode) {
|
|
1484
1410
|
// NOTE(charlie): We can't use the bounding rect of the keypad,
|
|
1485
1411
|
// as it is likely in the process of animating in. Instead, to
|
|
@@ -1489,14 +1415,14 @@ var scrollIntoView = (containerNode, keypadNode) => {
|
|
|
1489
1415
|
// in the native apps (where the toolbar is rendered natively), this
|
|
1490
1416
|
// will result in us leaving excess space between the input and the
|
|
1491
1417
|
// keypad, but that seems okay.
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1418
|
+
const pageHeightPx = window.innerHeight;
|
|
1419
|
+
const keypadHeightPx = keypadNode.clientHeight;
|
|
1420
|
+
const keypadTopPx = pageHeightPx - (keypadHeightPx + toolbarHeightPx);
|
|
1495
1421
|
if (containerBottomPx > keypadTopPx) {
|
|
1496
1422
|
// If the input would be obscured by the keypad, scroll such that
|
|
1497
1423
|
// the bottom of the input is just above the top of the keypad,
|
|
1498
1424
|
// taking care not to scroll the input out of view.
|
|
1499
|
-
|
|
1425
|
+
const scrollOffset = Math.min(containerBottomPx - keypadTopPx + desiredMarginPx, containerTopPx);
|
|
1500
1426
|
scrollNode.scrollTop += scrollOffset;
|
|
1501
1427
|
return;
|
|
1502
1428
|
}
|
|
@@ -1510,25 +1436,25 @@ var scrollIntoView = (containerNode, keypadNode) => {
|
|
|
1510
1436
|
}
|
|
1511
1437
|
};
|
|
1512
1438
|
|
|
1513
|
-
|
|
1439
|
+
const constrainingFrictionFactor = 0.8;
|
|
1514
1440
|
// eslint-disable-next-line react/no-unsafe
|
|
1515
1441
|
class MathInput extends React.Component {
|
|
1516
|
-
constructor() {
|
|
1517
|
-
super(...
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1442
|
+
constructor(...args) {
|
|
1443
|
+
super(...args);
|
|
1444
|
+
this.didTouchOutside = void 0;
|
|
1445
|
+
this.didScroll = void 0;
|
|
1446
|
+
this.mathField = void 0;
|
|
1447
|
+
this.recordTouchStartOutside = void 0;
|
|
1448
|
+
this.blurOnTouchEndOutside = void 0;
|
|
1449
|
+
this.dragListener = void 0;
|
|
1450
|
+
this.inputRef = void 0;
|
|
1451
|
+
this._isMounted = void 0;
|
|
1452
|
+
this._mathContainer = void 0;
|
|
1453
|
+
this._container = void 0;
|
|
1454
|
+
this._root = void 0;
|
|
1455
|
+
this._containerBounds = void 0;
|
|
1456
|
+
this._keypadBounds = void 0;
|
|
1457
|
+
this.state = {
|
|
1532
1458
|
focused: false,
|
|
1533
1459
|
handle: {
|
|
1534
1460
|
animateIntoPosition: false,
|
|
@@ -1536,41 +1462,41 @@ class MathInput extends React.Component {
|
|
|
1536
1462
|
x: 0,
|
|
1537
1463
|
y: 0
|
|
1538
1464
|
}
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1465
|
+
};
|
|
1466
|
+
this._clearKeypadBoundsCache = () => {
|
|
1541
1467
|
this._keypadBounds = null;
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1468
|
+
};
|
|
1469
|
+
this._cacheKeypadBounds = keypadNode => {
|
|
1544
1470
|
this._keypadBounds = keypadNode.getBoundingClientRect();
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1471
|
+
};
|
|
1472
|
+
this._updateInputPadding = () => {
|
|
1547
1473
|
this._container = ReactDOM.findDOMNode(this);
|
|
1548
1474
|
this._root = this._container.querySelector(".mq-root-block");
|
|
1549
|
-
|
|
1475
|
+
const padding = this.getInputInnerPadding();
|
|
1550
1476
|
// NOTE(diedra): This overrides the default 2px padding from Mathquil.
|
|
1551
|
-
this._root.style.padding =
|
|
1552
|
-
this._root.style.fontSize =
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1477
|
+
this._root.style.padding = `${padding.paddingTop}px ${padding.paddingRight}px` + ` ${padding.paddingBottom}px ${padding.paddingLeft}px`;
|
|
1478
|
+
this._root.style.fontSize = `${fontSizePt}pt`;
|
|
1479
|
+
};
|
|
1480
|
+
this._getKeypadBounds = () => {
|
|
1555
1481
|
if (!this._keypadBounds) {
|
|
1556
|
-
|
|
1482
|
+
const node = this.props.keypadElement.getDOMNode();
|
|
1557
1483
|
this._cacheKeypadBounds(node);
|
|
1558
1484
|
}
|
|
1559
1485
|
return this._keypadBounds;
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1486
|
+
};
|
|
1487
|
+
this._updateCursorHandle = animateIntoPosition => {
|
|
1488
|
+
const containerBounds = this._container.getBoundingClientRect();
|
|
1489
|
+
const cursor = this._container.querySelector(".mq-cursor");
|
|
1490
|
+
const cursorBounds = cursor.getBoundingClientRect();
|
|
1491
|
+
const cursorWidth = cursorBounds.width;
|
|
1492
|
+
const gapBelowCursor = 2;
|
|
1493
|
+
const inputInnerPadding = this.getInputInnerPadding();
|
|
1568
1494
|
|
|
1569
1495
|
// The cursor should never be further right or left than the edge of the
|
|
1570
1496
|
// container's values.
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1497
|
+
const furthestRightCursorBound = containerBounds.right - cursorWidth - inputInnerPadding.paddingRight;
|
|
1498
|
+
const furthestLeftCursorBound = containerBounds.left + cursorWidth + inputInnerPadding.paddingLeft;
|
|
1499
|
+
let cursorBoundsLeft = cursorBounds.left;
|
|
1574
1500
|
if (cursorBounds.left > furthestRightCursorBound) {
|
|
1575
1501
|
cursorBoundsLeft = furthestRightCursorBound;
|
|
1576
1502
|
} else if (cursorBounds.left < furthestLeftCursorBound) {
|
|
@@ -1586,8 +1512,8 @@ class MathInput extends React.Component {
|
|
|
1586
1512
|
y: cursorBounds.bottom + gapBelowCursor - containerBounds.top
|
|
1587
1513
|
}
|
|
1588
1514
|
});
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1515
|
+
};
|
|
1516
|
+
this._hideCursorHandle = () => {
|
|
1591
1517
|
this.setState({
|
|
1592
1518
|
handle: {
|
|
1593
1519
|
visible: false,
|
|
@@ -1595,8 +1521,8 @@ class MathInput extends React.Component {
|
|
|
1595
1521
|
y: 0
|
|
1596
1522
|
}
|
|
1597
1523
|
});
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1524
|
+
};
|
|
1525
|
+
this._handleScroll = () => {
|
|
1600
1526
|
// If animateIntoPosition is false, the user is currently manually positioning
|
|
1601
1527
|
// the cursor. This is important because the user can scroll the input field
|
|
1602
1528
|
// with the curor handle, and we don't want to override that ability.
|
|
@@ -1605,8 +1531,8 @@ class MathInput extends React.Component {
|
|
|
1605
1531
|
if (this.state.handle.animateIntoPosition !== false) {
|
|
1606
1532
|
this._hideCursorHandle();
|
|
1607
1533
|
}
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1534
|
+
};
|
|
1535
|
+
this.blur = () => {
|
|
1610
1536
|
this.mathField.blur();
|
|
1611
1537
|
this.props.onBlur && this.props.onBlur();
|
|
1612
1538
|
this.setState({
|
|
@@ -1615,25 +1541,25 @@ class MathInput extends React.Component {
|
|
|
1615
1541
|
visible: false
|
|
1616
1542
|
}
|
|
1617
1543
|
});
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1544
|
+
};
|
|
1545
|
+
this.focus = () => {
|
|
1620
1546
|
// Pass this component's handleKey method to the keypad so it can call
|
|
1621
1547
|
// it whenever it needs to trigger a keypress action.
|
|
1622
1548
|
this.props.keypadElement.setKeyHandler(key => {
|
|
1623
|
-
|
|
1549
|
+
const cursor = this.mathField.pressKey(key);
|
|
1624
1550
|
|
|
1625
1551
|
// Trigger an `onChange` if the value in the input changed, and hide
|
|
1626
1552
|
// the cursor handle whenever the user types a key. If the value
|
|
1627
1553
|
// changed as a result of a keypress, we need to be careful not to
|
|
1628
1554
|
// call `setState` until after `onChange` has resolved.
|
|
1629
|
-
|
|
1555
|
+
const hideCursor = () => {
|
|
1630
1556
|
this.setState({
|
|
1631
1557
|
handle: {
|
|
1632
1558
|
visible: false
|
|
1633
1559
|
}
|
|
1634
1560
|
});
|
|
1635
1561
|
};
|
|
1636
|
-
|
|
1562
|
+
const value = this.mathField.getContent();
|
|
1637
1563
|
if (this.props.value !== value) {
|
|
1638
1564
|
this.props.onChange(value, hideCursor);
|
|
1639
1565
|
} else {
|
|
@@ -1658,17 +1584,17 @@ class MathInput extends React.Component {
|
|
|
1658
1584
|
// that the higher level controller tells us when the
|
|
1659
1585
|
// keypad is settled (then scrollIntoView wouldn't have
|
|
1660
1586
|
// to make assumptions about that either).
|
|
1661
|
-
|
|
1587
|
+
const maybeKeypadNode = this.props.keypadElement && this.props.keypadElement.getDOMNode();
|
|
1662
1588
|
scrollIntoView(this._container, maybeKeypadNode);
|
|
1663
1589
|
}
|
|
1664
1590
|
});
|
|
1665
1591
|
});
|
|
1666
|
-
}
|
|
1667
|
-
|
|
1592
|
+
};
|
|
1593
|
+
this._findHitNode = (containerBounds, x, y, dx, dy) => {
|
|
1668
1594
|
while (y >= containerBounds.top && y <= containerBounds.bottom) {
|
|
1669
1595
|
y += dy;
|
|
1670
|
-
|
|
1671
|
-
|
|
1596
|
+
const points = [[x - dx, y], [x, y], [x + dx, y]];
|
|
1597
|
+
const elements = points
|
|
1672
1598
|
// @ts-expect-error [FEI-5003] - TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
|
|
1673
1599
|
.map(point => document.elementFromPoint(...point))
|
|
1674
1600
|
// We exclude the root container itself and any nodes marked
|
|
@@ -1682,23 +1608,17 @@ class MathInput extends React.Component {
|
|
|
1682
1608
|
// included, neither mq-numerator nor mq-denominator nodes are
|
|
1683
1609
|
// and neither are subscripts or superscripts.
|
|
1684
1610
|
.filter(element => element && this._root.contains(element) && (!element.classList.contains("mq-root-block") && !element.classList.contains("mq-non-leaf") || element.classList.contains("mq-empty") || element.classList.contains("mq-hasCursor")));
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
// Contains only DOMNodes without child elements. These should
|
|
1688
|
-
// contain some amount of text though.
|
|
1689
|
-
var leafElements = [];
|
|
1611
|
+
let hitNode = null;
|
|
1690
1612
|
|
|
1691
1613
|
// Contains only DOMNodes with child elements.
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
for (
|
|
1614
|
+
const nonLeafElements = [];
|
|
1615
|
+
let max = 0;
|
|
1616
|
+
const counts = {};
|
|
1617
|
+
const elementsById = {};
|
|
1618
|
+
for (const element of elements) {
|
|
1697
1619
|
// @ts-expect-error [FEI-5003] - TS2531 - Object is possibly 'null'.
|
|
1698
|
-
|
|
1620
|
+
const id = element.getAttribute("mathquill-command-id");
|
|
1699
1621
|
if (id != null) {
|
|
1700
|
-
// @ts-expect-error [FEI-5003] - TS2345 - Argument of type 'Element | null' is not assignable to parameter of type 'HTMLElement | null'.
|
|
1701
|
-
leafElements.push(element);
|
|
1702
1622
|
counts[id] = (counts[id] || 0) + 1;
|
|
1703
1623
|
elementsById[id] = element;
|
|
1704
1624
|
} else {
|
|
@@ -1718,10 +1638,10 @@ class MathInput extends React.Component {
|
|
|
1718
1638
|
// we hit multiple leaf nodes at the same time. In this case we
|
|
1719
1639
|
// we prefer the DOMNode with the most hits.
|
|
1720
1640
|
// TODO(kevinb) consider preferring nodes hit by [x, y].
|
|
1721
|
-
for (
|
|
1641
|
+
for (const [id, count] of entries(counts)) {
|
|
1722
1642
|
if (count > max) {
|
|
1723
1643
|
max = count;
|
|
1724
|
-
hitNode = elementsById[
|
|
1644
|
+
hitNode = elementsById[id];
|
|
1725
1645
|
}
|
|
1726
1646
|
}
|
|
1727
1647
|
|
|
@@ -1740,9 +1660,9 @@ class MathInput extends React.Component {
|
|
|
1740
1660
|
}
|
|
1741
1661
|
}
|
|
1742
1662
|
return false;
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
|
|
1663
|
+
};
|
|
1664
|
+
this._insertCursorAtClosestNode = (x, y) => {
|
|
1665
|
+
const cursor = this.mathField.getCursor();
|
|
1746
1666
|
|
|
1747
1667
|
// Pre-emptively check if the input has any child nodes; if not, the
|
|
1748
1668
|
// input is empty, so we throw the cursor at the start.
|
|
@@ -1763,7 +1683,7 @@ class MathInput extends React.Component {
|
|
|
1763
1683
|
} else if (x < this._containerBounds.left) {
|
|
1764
1684
|
x = this._containerBounds.left + 15;
|
|
1765
1685
|
}
|
|
1766
|
-
|
|
1686
|
+
let dy;
|
|
1767
1687
|
|
|
1768
1688
|
// Vertical spacing between hit tests
|
|
1769
1689
|
// dy is negative because we're moving upwards.
|
|
@@ -1773,7 +1693,7 @@ class MathInput extends React.Component {
|
|
|
1773
1693
|
// Note: This value depends on the font size. If the gap is too small
|
|
1774
1694
|
// we end up placing the cursor at the end of the expression when we
|
|
1775
1695
|
// shouldn't.
|
|
1776
|
-
|
|
1696
|
+
const dx = 5;
|
|
1777
1697
|
if (this._findHitNode(this._containerBounds, x, y, dx, dy)) {
|
|
1778
1698
|
return;
|
|
1779
1699
|
}
|
|
@@ -1786,10 +1706,10 @@ class MathInput extends React.Component {
|
|
|
1786
1706
|
if (this._findHitNode(this._containerBounds, x, y, dx, dy)) {
|
|
1787
1707
|
return;
|
|
1788
1708
|
}
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1709
|
+
const firstChildBounds = this._root.firstChild.getBoundingClientRect();
|
|
1710
|
+
const lastChildBounds = this._root.lastChild.getBoundingClientRect();
|
|
1711
|
+
const left = firstChildBounds.left;
|
|
1712
|
+
const right = lastChildBounds.right;
|
|
1793
1713
|
|
|
1794
1714
|
// We've exhausted all of the options. We're likely either to the right
|
|
1795
1715
|
// or left of all of the math, so we place the cursor at the end to
|
|
@@ -1803,8 +1723,8 @@ class MathInput extends React.Component {
|
|
|
1803
1723
|
this.props.keypadElement && this.props.keypadElement.setCursor({
|
|
1804
1724
|
context: this.mathField.contextForCursor(cursor)
|
|
1805
1725
|
});
|
|
1806
|
-
}
|
|
1807
|
-
|
|
1726
|
+
};
|
|
1727
|
+
this.handleTouchStart = e => {
|
|
1808
1728
|
e.stopPropagation();
|
|
1809
1729
|
|
|
1810
1730
|
// Hide the cursor handle on touch start, if the handle itself isn't
|
|
@@ -1819,7 +1739,7 @@ class MathInput extends React.Component {
|
|
|
1819
1739
|
|
|
1820
1740
|
// Make the cursor visible and set the handle-less cursor's
|
|
1821
1741
|
// location.
|
|
1822
|
-
|
|
1742
|
+
const touch = e.changedTouches[0];
|
|
1823
1743
|
this._insertCursorAtClosestNode(touch.clientX, touch.clientY);
|
|
1824
1744
|
}
|
|
1825
1745
|
|
|
@@ -1827,8 +1747,8 @@ class MathInput extends React.Component {
|
|
|
1827
1747
|
if (!this.state.focused) {
|
|
1828
1748
|
this.focus();
|
|
1829
1749
|
}
|
|
1830
|
-
}
|
|
1831
|
-
|
|
1750
|
+
};
|
|
1751
|
+
this.handleTouchMove = e => {
|
|
1832
1752
|
e.stopPropagation();
|
|
1833
1753
|
|
|
1834
1754
|
// Update the handle-less cursor's location on move, if there's any
|
|
@@ -1838,11 +1758,11 @@ class MathInput extends React.Component {
|
|
|
1838
1758
|
// the cursor is no longer visible and the input is no longer
|
|
1839
1759
|
// highlighted).
|
|
1840
1760
|
if (this.mathField.getContent() !== "" && this.state.focused) {
|
|
1841
|
-
|
|
1761
|
+
const touch = e.changedTouches[0];
|
|
1842
1762
|
this._insertCursorAtClosestNode(touch.clientX, touch.clientY);
|
|
1843
1763
|
}
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1764
|
+
};
|
|
1765
|
+
this.handleTouchEnd = e => {
|
|
1846
1766
|
e.stopPropagation();
|
|
1847
1767
|
|
|
1848
1768
|
// And on touch-end, reveal the cursor, unless the input is empty. Note
|
|
@@ -1853,8 +1773,8 @@ class MathInput extends React.Component {
|
|
|
1853
1773
|
if (this.mathField.getContent() !== "" && this.state.focused) {
|
|
1854
1774
|
this._updateCursorHandle();
|
|
1855
1775
|
}
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1776
|
+
};
|
|
1777
|
+
this.onCursorHandleTouchStart = e => {
|
|
1858
1778
|
// NOTE(charlie): The cursor handle is a child of this view, so whenever
|
|
1859
1779
|
// it receives a touch event, that event would also typically be bubbled
|
|
1860
1780
|
// up to our own handlers. However, we want the cursor to handle its own
|
|
@@ -1867,8 +1787,8 @@ class MathInput extends React.Component {
|
|
|
1867
1787
|
|
|
1868
1788
|
// Cache the container bounds, so as to avoid re-computing.
|
|
1869
1789
|
this._containerBounds = this._container.getBoundingClientRect();
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1790
|
+
};
|
|
1791
|
+
this._constrainToBound = (value, min, max, friction) => {
|
|
1872
1792
|
if (value < min) {
|
|
1873
1793
|
return min + (value - min) * friction;
|
|
1874
1794
|
} else if (value > max) {
|
|
@@ -1876,13 +1796,13 @@ class MathInput extends React.Component {
|
|
|
1876
1796
|
} else {
|
|
1877
1797
|
return value;
|
|
1878
1798
|
}
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1799
|
+
};
|
|
1800
|
+
this.onCursorHandleTouchMove = e => {
|
|
1881
1801
|
e.stopPropagation();
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1802
|
+
const x = e.changedTouches[0].clientX;
|
|
1803
|
+
const y = e.changedTouches[0].clientY;
|
|
1804
|
+
const relativeX = x - this._containerBounds.left;
|
|
1805
|
+
const relativeY = y - 2 * cursorHandleRadiusPx * cursorHandleDistanceMultiplier - this._containerBounds.top;
|
|
1886
1806
|
|
|
1887
1807
|
// We subtract the containerBounds left/top to correct for the
|
|
1888
1808
|
// MathInput's position on the page. On top of that, we subtract an
|
|
@@ -1905,20 +1825,20 @@ class MathInput extends React.Component {
|
|
|
1905
1825
|
// Use a y-coordinate that's just above where the user is actually
|
|
1906
1826
|
// touching because they're dragging the handle which is a little
|
|
1907
1827
|
// below where the cursor actually is.
|
|
1908
|
-
|
|
1909
|
-
|
|
1828
|
+
const distanceAboveFingerToTrySelecting = 22;
|
|
1829
|
+
const adjustedY = y - distanceAboveFingerToTrySelecting;
|
|
1910
1830
|
this._insertCursorAtClosestNode(x, adjustedY);
|
|
1911
|
-
}
|
|
1912
|
-
|
|
1831
|
+
};
|
|
1832
|
+
this.onCursorHandleTouchEnd = e => {
|
|
1913
1833
|
e.stopPropagation();
|
|
1914
1834
|
this._updateCursorHandle(true);
|
|
1915
|
-
}
|
|
1916
|
-
|
|
1835
|
+
};
|
|
1836
|
+
this.onCursorHandleTouchCancel = e => {
|
|
1917
1837
|
e.stopPropagation();
|
|
1918
1838
|
this._updateCursorHandle(true);
|
|
1919
|
-
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1839
|
+
};
|
|
1840
|
+
this.domKeyToMathQuillKey = key => {
|
|
1841
|
+
const keyMap = {
|
|
1922
1842
|
"+": Keys.PLUS,
|
|
1923
1843
|
"-": Keys.MINUS,
|
|
1924
1844
|
"*": Keys.TIMES,
|
|
@@ -1933,7 +1853,7 @@ class MathInput extends React.Component {
|
|
|
1933
1853
|
|
|
1934
1854
|
// Numbers
|
|
1935
1855
|
if (["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(key)) {
|
|
1936
|
-
return
|
|
1856
|
+
return `NUM_${key}`;
|
|
1937
1857
|
}
|
|
1938
1858
|
|
|
1939
1859
|
// Movement keys
|
|
@@ -1948,31 +1868,31 @@ class MathInput extends React.Component {
|
|
|
1948
1868
|
|
|
1949
1869
|
// The key pressed doesn't map to any of the math input operators
|
|
1950
1870
|
return null;
|
|
1951
|
-
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1871
|
+
};
|
|
1872
|
+
this.handleKeyUp = event => {
|
|
1873
|
+
const mathQuillKey = this.domKeyToMathQuillKey(event.key);
|
|
1954
1874
|
if (mathQuillKey) {
|
|
1955
1875
|
this.mathField.pressKey(mathQuillKey);
|
|
1956
1876
|
|
|
1957
1877
|
// TODO(diedra): If the new value being added is off-screen to the right
|
|
1958
1878
|
// due to the max-width of the text box, scroll the box to show the newest
|
|
1959
1879
|
// value
|
|
1960
|
-
|
|
1880
|
+
const value = this.mathField.getContent();
|
|
1961
1881
|
if (this.props.value !== value) {
|
|
1962
1882
|
this.mathField.setContent(this.props.value);
|
|
1963
1883
|
this.props.onChange(value, false);
|
|
1964
1884
|
this._hideCursorHandle();
|
|
1965
1885
|
}
|
|
1966
1886
|
}
|
|
1967
|
-
}
|
|
1968
|
-
|
|
1887
|
+
};
|
|
1888
|
+
this.getBorderWidthPx = () => {
|
|
1969
1889
|
// TODO(diedra): Move these to the common style package.
|
|
1970
|
-
|
|
1971
|
-
|
|
1890
|
+
const normalBorderWidthPx = 1;
|
|
1891
|
+
const focusedBorderWidthPx = 2;
|
|
1972
1892
|
return this.state.focused ? focusedBorderWidthPx : normalBorderWidthPx;
|
|
1973
|
-
}
|
|
1974
|
-
|
|
1975
|
-
|
|
1893
|
+
};
|
|
1894
|
+
this.getInputInnerPadding = () => {
|
|
1895
|
+
const paddingInset = totalDesiredPadding - this.getBorderWidthPx();
|
|
1976
1896
|
|
|
1977
1897
|
// Now, translate that to the appropriate padding for each direction.
|
|
1978
1898
|
// The complication here is that we want numerals to be centered within
|
|
@@ -1980,16 +1900,16 @@ class MathInput extends React.Component {
|
|
|
1980
1900
|
// numerals with approximately 3px of padding below and 1px of padding
|
|
1981
1901
|
// above (to make room for ascenders and descenders). So we ignore those
|
|
1982
1902
|
// padding values for the vertical directions.
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1903
|
+
const symbolaPaddingBottom = 3;
|
|
1904
|
+
const symbolaPaddingTop = 1;
|
|
1905
|
+
const padding = {
|
|
1986
1906
|
paddingTop: paddingInset - symbolaPaddingTop,
|
|
1987
1907
|
paddingRight: paddingInset,
|
|
1988
1908
|
paddingBottom: paddingInset - symbolaPaddingBottom,
|
|
1989
1909
|
paddingLeft: paddingInset
|
|
1990
1910
|
};
|
|
1991
1911
|
return padding;
|
|
1992
|
-
}
|
|
1912
|
+
};
|
|
1993
1913
|
}
|
|
1994
1914
|
componentDidMount() {
|
|
1995
1915
|
this._isMounted = true;
|
|
@@ -2036,11 +1956,11 @@ class MathInput extends React.Component {
|
|
|
2036
1956
|
// to dismiss the keypad on check.
|
|
2037
1957
|
// TODO(charlie): Inject this logic.
|
|
2038
1958
|
if (!this._container.contains(evt.target)) {
|
|
2039
|
-
|
|
1959
|
+
let touchDidStartInOrBelowKeypad = false;
|
|
2040
1960
|
if (this.props.keypadElement && this.props.keypadElement.getDOMNode()) {
|
|
2041
|
-
|
|
2042
|
-
for (
|
|
2043
|
-
|
|
1961
|
+
const bounds = this._getKeypadBounds();
|
|
1962
|
+
for (let i = 0; i < evt.changedTouches.length; i++) {
|
|
1963
|
+
const [x, y] = [evt.changedTouches[i].clientX, evt.changedTouches[i].clientY];
|
|
2044
1964
|
if (bounds.left <= x && bounds.right >= x && bounds.top <= y && bounds.bottom >= y || bounds.bottom < y) {
|
|
2045
1965
|
touchDidStartInOrBelowKeypad = true;
|
|
2046
1966
|
break;
|
|
@@ -2115,18 +2035,18 @@ class MathInput extends React.Component {
|
|
|
2115
2035
|
this._clearKeypadBoundsCache());
|
|
2116
2036
|
}
|
|
2117
2037
|
render() {
|
|
2118
|
-
|
|
2038
|
+
const {
|
|
2119
2039
|
focused,
|
|
2120
2040
|
handle
|
|
2121
2041
|
} = this.state;
|
|
2122
|
-
|
|
2042
|
+
const {
|
|
2123
2043
|
style
|
|
2124
2044
|
} = this.props;
|
|
2125
|
-
|
|
2045
|
+
const innerStyle = _extends({}, inlineStyles$1.innerContainer, {
|
|
2126
2046
|
borderWidth: this.getBorderWidthPx()
|
|
2127
2047
|
}, focused ? {
|
|
2128
2048
|
borderColor: wonderBlocksBlue
|
|
2129
|
-
} : {}
|
|
2049
|
+
} : {}, style);
|
|
2130
2050
|
|
|
2131
2051
|
// NOTE(diedra): This label explicitly refers to tapping because this field
|
|
2132
2052
|
// is currently only seen if the user is using a mobile device.
|
|
@@ -2135,7 +2055,7 @@ class MathInput extends React.Component {
|
|
|
2135
2055
|
// keyboard appear. It should only require one finger, which is how iOS works.
|
|
2136
2056
|
// TODO(diedra): Fix the bug that is causing Android to require a two finger tap
|
|
2137
2057
|
// to the open the keyboard, and then remove the second half of this label.
|
|
2138
|
-
|
|
2058
|
+
const ariaLabel = i18n._("Math input box") + " " + i18n._("Tap with one or two fingers to open keyboard");
|
|
2139
2059
|
return /*#__PURE__*/React.createElement(View, {
|
|
2140
2060
|
style: styles$e.input,
|
|
2141
2061
|
onTouchStart: this.handleTouchStart,
|
|
@@ -2166,12 +2086,12 @@ class MathInput extends React.Component {
|
|
|
2166
2086
|
})));
|
|
2167
2087
|
}
|
|
2168
2088
|
}
|
|
2169
|
-
|
|
2089
|
+
MathInput.defaultProps = {
|
|
2170
2090
|
style: {},
|
|
2171
2091
|
value: ""
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2092
|
+
};
|
|
2093
|
+
const fontSizePt = 18;
|
|
2094
|
+
const inputMaxWidth = 128;
|
|
2175
2095
|
|
|
2176
2096
|
// The height of numerals in Symbola (rendered at 18pt) is about 20px (though
|
|
2177
2097
|
// they render at 24px due to padding for ascenders and descenders). We want our
|
|
@@ -2179,11 +2099,11 @@ var inputMaxWidth = 128;
|
|
|
2179
2099
|
// edge of the input, so we use this 20px number as our 'base height' and
|
|
2180
2100
|
// account for the ascender and descender padding when computing the additional
|
|
2181
2101
|
// padding in our `render` method.
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2102
|
+
const numeralHeightPx = 20;
|
|
2103
|
+
const totalDesiredPadding = 12;
|
|
2104
|
+
const minHeightPx = numeralHeightPx + totalDesiredPadding * 2;
|
|
2105
|
+
const minWidthPx = 64;
|
|
2106
|
+
const styles$e = StyleSheet.create({
|
|
2187
2107
|
input: {
|
|
2188
2108
|
position: "relative",
|
|
2189
2109
|
display: "inline-block",
|
|
@@ -2191,7 +2111,7 @@ var styles$e = StyleSheet.create({
|
|
|
2191
2111
|
maxWidth: inputMaxWidth
|
|
2192
2112
|
}
|
|
2193
2113
|
});
|
|
2194
|
-
|
|
2114
|
+
const inlineStyles$1 = {
|
|
2195
2115
|
// Styles for the inner, MathQuill-ified input element. It's important that
|
|
2196
2116
|
// these are done with regular inline styles rather than Aphrodite classes
|
|
2197
2117
|
// as MathQuill adds CSS class names to the element outside of the typical
|
|
@@ -2215,7 +2135,7 @@ var inlineStyles$1 = {
|
|
|
2215
2135
|
}
|
|
2216
2136
|
};
|
|
2217
2137
|
|
|
2218
|
-
|
|
2138
|
+
const KeyConfigs = {
|
|
2219
2139
|
// Basic math keys.
|
|
2220
2140
|
[Keys.PLUS]: {
|
|
2221
2141
|
type: KeyTypes.OPERATOR,
|
|
@@ -2465,13 +2385,13 @@ KeyConfigs[Keys.MANY] = {
|
|
|
2465
2385
|
};
|
|
2466
2386
|
|
|
2467
2387
|
// Add in every numeral.
|
|
2468
|
-
|
|
2469
|
-
for (
|
|
2388
|
+
const NUMBERS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
2389
|
+
for (const num of NUMBERS) {
|
|
2470
2390
|
// TODO(charlie): Consider removing the SVG icons that we have for the
|
|
2471
2391
|
// numeral keys. They can be rendered just as easily with text (though that
|
|
2472
2392
|
// would mean that we'd be using text beyond the variable key).
|
|
2473
|
-
|
|
2474
|
-
KeyConfigs[
|
|
2393
|
+
const textRepresentation = `${num}`;
|
|
2394
|
+
KeyConfigs[`NUM_${num}`] = {
|
|
2475
2395
|
type: KeyTypes.VALUE,
|
|
2476
2396
|
ariaLabel: textRepresentation,
|
|
2477
2397
|
icon: {
|
|
@@ -2482,23 +2402,23 @@ for (var num of NUMBERS) {
|
|
|
2482
2402
|
}
|
|
2483
2403
|
|
|
2484
2404
|
// Add in every variable.
|
|
2485
|
-
|
|
2486
|
-
for (
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
for (
|
|
2490
|
-
KeyConfigs[
|
|
2405
|
+
const LETTERS = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
|
|
2406
|
+
for (const letter of LETTERS) {
|
|
2407
|
+
const lowerCaseVariable = letter.toLowerCase();
|
|
2408
|
+
const upperCaseVariable = letter.toUpperCase();
|
|
2409
|
+
for (const textRepresentation of [lowerCaseVariable, upperCaseVariable]) {
|
|
2410
|
+
KeyConfigs[textRepresentation] = {
|
|
2491
2411
|
type: KeyTypes.VALUE,
|
|
2492
|
-
ariaLabel:
|
|
2412
|
+
ariaLabel: textRepresentation,
|
|
2493
2413
|
icon: {
|
|
2494
2414
|
type: IconTypes.MATH,
|
|
2495
|
-
data:
|
|
2415
|
+
data: textRepresentation
|
|
2496
2416
|
}
|
|
2497
2417
|
};
|
|
2498
2418
|
}
|
|
2499
2419
|
}
|
|
2500
|
-
for (
|
|
2501
|
-
KeyConfigs[key] =
|
|
2420
|
+
for (const key of Object.keys(KeyConfigs)) {
|
|
2421
|
+
KeyConfigs[key] = _extends({
|
|
2502
2422
|
id: key,
|
|
2503
2423
|
// Default to an SVG icon indexed by the key name.
|
|
2504
2424
|
icon: {
|
|
@@ -2511,25 +2431,25 @@ for (var key of Object.keys(KeyConfigs)) {
|
|
|
2511
2431
|
/**
|
|
2512
2432
|
* React PropTypes that may be shared between components.
|
|
2513
2433
|
*/
|
|
2514
|
-
|
|
2434
|
+
const iconPropType = PropTypes.shape({
|
|
2515
2435
|
type: PropTypes.oneOf(Object.keys(IconTypes)).isRequired,
|
|
2516
2436
|
data: PropTypes.string.isRequired
|
|
2517
2437
|
});
|
|
2518
|
-
|
|
2519
|
-
|
|
2438
|
+
const keyIdPropType = PropTypes.oneOf(Object.keys(KeyConfigs));
|
|
2439
|
+
const keyConfigPropType = PropTypes.shape({
|
|
2520
2440
|
ariaLabel: PropTypes.string,
|
|
2521
2441
|
id: keyIdPropType.isRequired,
|
|
2522
2442
|
type: PropTypes.oneOf(Object.keys(KeyTypes)).isRequired,
|
|
2523
2443
|
childKeyIds: PropTypes.arrayOf(keyIdPropType),
|
|
2524
2444
|
icon: iconPropType.isRequired
|
|
2525
2445
|
});
|
|
2526
|
-
|
|
2446
|
+
const keypadConfigurationPropType = PropTypes.shape({
|
|
2527
2447
|
keypadType: PropTypes.oneOf(Object.keys(KeypadTypes)).isRequired,
|
|
2528
2448
|
extraKeys: PropTypes.arrayOf(keyIdPropType)
|
|
2529
2449
|
});
|
|
2530
2450
|
|
|
2531
2451
|
// NOTE(jared): This is no longer guaranteed to be React element
|
|
2532
|
-
|
|
2452
|
+
const keypadElementPropType = PropTypes.shape({
|
|
2533
2453
|
activate: PropTypes.func.isRequired,
|
|
2534
2454
|
dismiss: PropTypes.func.isRequired,
|
|
2535
2455
|
configure: PropTypes.func.isRequired,
|
|
@@ -2537,8 +2457,8 @@ var keypadElementPropType = PropTypes.shape({
|
|
|
2537
2457
|
setKeyHandler: PropTypes.func.isRequired,
|
|
2538
2458
|
getDOMNode: PropTypes.func.isRequired
|
|
2539
2459
|
});
|
|
2540
|
-
|
|
2541
|
-
|
|
2460
|
+
const bordersPropType = PropTypes.arrayOf(PropTypes.oneOf(Object.keys(BorderDirections)));
|
|
2461
|
+
const boundingBoxPropType = PropTypes.shape({
|
|
2542
2462
|
height: PropTypes.number,
|
|
2543
2463
|
width: PropTypes.number,
|
|
2544
2464
|
top: PropTypes.number,
|
|
@@ -2546,31 +2466,46 @@ var boundingBoxPropType = PropTypes.shape({
|
|
|
2546
2466
|
bottom: PropTypes.number,
|
|
2547
2467
|
left: PropTypes.number
|
|
2548
2468
|
});
|
|
2549
|
-
|
|
2469
|
+
const echoPropType = PropTypes.shape({
|
|
2550
2470
|
animationId: PropTypes.string.isRequired,
|
|
2551
2471
|
animationType: PropTypes.oneOf(Object.keys(EchoAnimationTypes)).isRequired,
|
|
2552
2472
|
borders: bordersPropType,
|
|
2553
2473
|
id: keyIdPropType.isRequired,
|
|
2554
2474
|
initialBounds: boundingBoxPropType.isRequired
|
|
2555
2475
|
});
|
|
2556
|
-
|
|
2557
|
-
|
|
2476
|
+
const cursorContextPropType = PropTypes.oneOf(Object.keys(CursorContexts));
|
|
2477
|
+
const popoverPropType = PropTypes.shape({
|
|
2558
2478
|
parentId: keyIdPropType.isRequired,
|
|
2559
2479
|
bounds: boundingBoxPropType.isRequired,
|
|
2560
2480
|
childKeyIds: PropTypes.arrayOf(keyIdPropType).isRequired
|
|
2561
2481
|
});
|
|
2562
2482
|
PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]);
|
|
2563
2483
|
|
|
2484
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
2485
|
+
if (source == null) return {};
|
|
2486
|
+
var target = {};
|
|
2487
|
+
var sourceKeys = Object.keys(source);
|
|
2488
|
+
var key, i;
|
|
2489
|
+
|
|
2490
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
2491
|
+
key = sourceKeys[i];
|
|
2492
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
2493
|
+
target[key] = source[key];
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
return target;
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2564
2499
|
// naming convention: verb + noun
|
|
2565
2500
|
// the noun should be one of the other properties in the object that's
|
|
2566
2501
|
// being dispatched
|
|
2567
2502
|
|
|
2568
|
-
|
|
2503
|
+
const dismissKeypad = () => {
|
|
2569
2504
|
return {
|
|
2570
2505
|
type: "DismissKeypad"
|
|
2571
2506
|
};
|
|
2572
2507
|
};
|
|
2573
|
-
|
|
2508
|
+
const activateKeypad = () => {
|
|
2574
2509
|
return {
|
|
2575
2510
|
type: "ActivateKeypad"
|
|
2576
2511
|
};
|
|
@@ -2581,20 +2516,20 @@ var activateKeypad = () => {
|
|
|
2581
2516
|
*
|
|
2582
2517
|
* See: `prop-types.js#keypadConfigurationPropType`.
|
|
2583
2518
|
*/
|
|
2584
|
-
|
|
2519
|
+
const configureKeypad = configuration => {
|
|
2585
2520
|
return {
|
|
2586
2521
|
type: "ConfigureKeypad",
|
|
2587
2522
|
configuration
|
|
2588
2523
|
};
|
|
2589
2524
|
};
|
|
2590
|
-
|
|
2525
|
+
const setPageSize = (pageWidthPx, pageHeightPx) => {
|
|
2591
2526
|
return {
|
|
2592
2527
|
type: "SetPageSize",
|
|
2593
2528
|
pageWidthPx,
|
|
2594
2529
|
pageHeightPx
|
|
2595
2530
|
};
|
|
2596
2531
|
};
|
|
2597
|
-
|
|
2532
|
+
const removeEcho = animationId => {
|
|
2598
2533
|
return {
|
|
2599
2534
|
type: "RemoveEcho",
|
|
2600
2535
|
animationId
|
|
@@ -2602,13 +2537,13 @@ var removeEcho = animationId => {
|
|
|
2602
2537
|
};
|
|
2603
2538
|
|
|
2604
2539
|
// Input-related actions.
|
|
2605
|
-
|
|
2540
|
+
const setKeyHandler = keyHandler => {
|
|
2606
2541
|
return {
|
|
2607
2542
|
type: "SetKeyHandler",
|
|
2608
2543
|
keyHandler
|
|
2609
2544
|
};
|
|
2610
2545
|
};
|
|
2611
|
-
|
|
2546
|
+
const setCursor = cursor => {
|
|
2612
2547
|
return {
|
|
2613
2548
|
type: "SetCursor",
|
|
2614
2549
|
cursor
|
|
@@ -2635,63 +2570,59 @@ var setCursor = cursor => {
|
|
|
2635
2570
|
* to be conservative in our measurements and make things smaller than they
|
|
2636
2571
|
* might need to be.
|
|
2637
2572
|
*/
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2573
|
+
const minButtonHeight = 48;
|
|
2574
|
+
const maxButtonSize = 64;
|
|
2575
|
+
const minSpaceAboveKeypad = 32;
|
|
2641
2576
|
|
|
2642
2577
|
// These values are taken from an iPhone 5, but should be consistent with the
|
|
2643
2578
|
// iPhone 4 as well. Regardless, these are meant to be representative of the
|
|
2644
2579
|
// possible types of browser chrome that could appear in various context, rather
|
|
2645
2580
|
// than pixel-perfect for every device.
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2581
|
+
const safariNavBarWhenShrunk = 44;
|
|
2582
|
+
const safariNavBarWhenExpanded = 64;
|
|
2583
|
+
const safariToolbar = 44;
|
|
2649
2584
|
|
|
2650
2585
|
// In mobile Safari, the browser chrome is completely hidden in landscape,
|
|
2651
2586
|
// though a shrunken navbar and full-sized toolbar on scroll. In portrait, the
|
|
2652
2587
|
// shrunken navbar is always visible, but expands on scroll (and the toolbar
|
|
2653
2588
|
// appears as well).
|
|
2654
|
-
|
|
2655
|
-
|
|
2589
|
+
const maxLandscapeBrowserChrome = safariNavBarWhenShrunk + safariToolbar;
|
|
2590
|
+
const maxPortraitBrowserChrome = safariToolbar + (safariNavBarWhenExpanded - safariNavBarWhenShrunk);
|
|
2656
2591
|
|
|
2657
2592
|
// This represents the 'worst case' aspect ratio that we care about (for
|
|
2658
2593
|
// portrait layouts). It's taken from the iPhone 4. The height is computed by
|
|
2659
2594
|
// taking the height of the device and removing the persistent, shrunken navbar.
|
|
2660
2595
|
// (We don't need to account for the expanded navbar, since we include the
|
|
2661
2596
|
// difference when reserving space above the keypad.)
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
navigationPadEnabled,
|
|
2679
|
-
paginationEnabled,
|
|
2680
|
-
toolbarEnabled
|
|
2681
|
-
} = _ref4;
|
|
2597
|
+
const worstCaseAspectRatio = 320 / (480 - safariNavBarWhenShrunk);
|
|
2598
|
+
const computeLayoutParameters = ({
|
|
2599
|
+
numColumns,
|
|
2600
|
+
numMaxVisibleRows,
|
|
2601
|
+
numPages
|
|
2602
|
+
}, {
|
|
2603
|
+
pageWidthPx,
|
|
2604
|
+
pageHeightPx
|
|
2605
|
+
}, {
|
|
2606
|
+
deviceOrientation,
|
|
2607
|
+
deviceType
|
|
2608
|
+
}, {
|
|
2609
|
+
navigationPadEnabled,
|
|
2610
|
+
paginationEnabled,
|
|
2611
|
+
toolbarEnabled
|
|
2612
|
+
}) => {
|
|
2682
2613
|
// First, compute some values that will be used in multiple computations.
|
|
2683
|
-
|
|
2614
|
+
const effectiveNumColumns = paginationEnabled ? numColumns : numColumns * numPages;
|
|
2684
2615
|
|
|
2685
2616
|
// Then, compute the button dimensions based on the provided parameters.
|
|
2686
|
-
|
|
2617
|
+
let buttonDimensions;
|
|
2687
2618
|
if (deviceType === DeviceTypes.PHONE) {
|
|
2688
|
-
|
|
2619
|
+
const isLandscape = deviceOrientation === DeviceOrientations.LANDSCAPE;
|
|
2689
2620
|
|
|
2690
2621
|
// In many cases, the browser chrome will already have been factored
|
|
2691
2622
|
// into `pageHeightPx`. But we have no way of knowing if that's
|
|
2692
2623
|
// the case or not. As such, we take a conservative approach and
|
|
2693
2624
|
// assume that the chrome is _never_ included in `pageHeightPx`.
|
|
2694
|
-
|
|
2625
|
+
const browserChromeHeight = isLandscape ? maxLandscapeBrowserChrome : maxPortraitBrowserChrome;
|
|
2695
2626
|
|
|
2696
2627
|
// Count up all the space that we need to reserve on the page.
|
|
2697
2628
|
// Namely, we need to account for:
|
|
@@ -2699,7 +2630,7 @@ var computeLayoutParameters = (_ref, _ref2, _ref3, _ref4) => {
|
|
|
2699
2630
|
// 2. The presence of the exercise toolbar.
|
|
2700
2631
|
// 3. The presence of the view pager indicator.
|
|
2701
2632
|
// 4. Any browser chrome that may appear later.
|
|
2702
|
-
|
|
2633
|
+
const reservedSpace = minSpaceAboveKeypad + browserChromeHeight + (toolbarEnabled ? toolbarHeightPx : 0) + (paginationEnabled ? pageIndicatorHeightPx : 0);
|
|
2703
2634
|
|
|
2704
2635
|
// Next, compute the effective width and height. We can use the page
|
|
2705
2636
|
// width as the effective width. For the height, though, we take
|
|
@@ -2708,18 +2639,18 @@ var computeLayoutParameters = (_ref, _ref2, _ref3, _ref4) => {
|
|
|
2708
2639
|
// we ignore the device height in portrait and assume the worst.
|
|
2709
2640
|
// This prevents the keypad from changing size when browser chrome
|
|
2710
2641
|
// appears and disappears.
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2642
|
+
const effectiveWidth = pageWidthPx;
|
|
2643
|
+
const effectiveHeight = isLandscape ? pageHeightPx : pageWidthPx / worstCaseAspectRatio;
|
|
2644
|
+
const maxKeypadHeight = effectiveHeight - reservedSpace;
|
|
2714
2645
|
|
|
2715
2646
|
// Finally, compute the button height and width. In computing the
|
|
2716
2647
|
// height, accommodate for the maximum number of rows that will ever be
|
|
2717
2648
|
// visible (since the toggling of popovers can increase the number of
|
|
2718
2649
|
// visible rows).
|
|
2719
|
-
|
|
2720
|
-
|
|
2650
|
+
const buttonHeightPx = Math.max(Math.min(maxKeypadHeight / numMaxVisibleRows, maxButtonSize), minButtonHeight);
|
|
2651
|
+
let buttonWidthPx;
|
|
2721
2652
|
if (numPages > 1) {
|
|
2722
|
-
|
|
2653
|
+
const _effectiveNumColumns = paginationEnabled ? numColumns : numColumns * numPages;
|
|
2723
2654
|
buttonWidthPx = effectiveWidth / _effectiveNumColumns;
|
|
2724
2655
|
} else {
|
|
2725
2656
|
buttonWidthPx = isLandscape ? maxButtonSize : effectiveWidth / numColumns;
|
|
@@ -2739,8 +2670,8 @@ var computeLayoutParameters = (_ref, _ref2, _ref3, _ref4) => {
|
|
|
2739
2670
|
|
|
2740
2671
|
// Finally, determine whether the keypad should be rendered in the
|
|
2741
2672
|
// fullscreen layout by determining its resultant width.
|
|
2742
|
-
|
|
2743
|
-
|
|
2673
|
+
const numSeparators = (navigationPadEnabled ? 1 : 0) + (!paginationEnabled ? numPages - 1 : 0);
|
|
2674
|
+
const keypadWidth = effectiveNumColumns * buttonDimensions.widthPx + (navigationPadEnabled ? navigationPadWidthPx : 0) + numSeparators * innerBorderWidthPx;
|
|
2744
2675
|
return {
|
|
2745
2676
|
buttonDimensions,
|
|
2746
2677
|
layoutMode: keypadWidth >= pageWidthPx ? LayoutModes.FULLSCREEN : LayoutModes.COMPACT
|
|
@@ -2755,7 +2686,7 @@ var computeLayoutParameters = (_ref, _ref2, _ref3, _ref4) => {
|
|
|
2755
2686
|
* multi-touch interactions, tracking gesture state on a per-touch basis.
|
|
2756
2687
|
*/
|
|
2757
2688
|
|
|
2758
|
-
|
|
2689
|
+
const defaults = {
|
|
2759
2690
|
longPressWaitTimeMs: 50,
|
|
2760
2691
|
swipeThresholdPx: 20,
|
|
2761
2692
|
holdIntervalMs: 250
|
|
@@ -2763,7 +2694,7 @@ var defaults = {
|
|
|
2763
2694
|
class GestureStateMachine {
|
|
2764
2695
|
constructor(handlers, options, swipeDisabledNodeIds, multiPressableKeys) {
|
|
2765
2696
|
this.handlers = handlers;
|
|
2766
|
-
this.options =
|
|
2697
|
+
this.options = _extends({}, defaults, options);
|
|
2767
2698
|
this.swipeDisabledNodeIds = swipeDisabledNodeIds || [];
|
|
2768
2699
|
this.multiPressableKeys = multiPressableKeys || [];
|
|
2769
2700
|
|
|
@@ -2773,24 +2704,24 @@ class GestureStateMachine {
|
|
|
2773
2704
|
this.swipeState = null;
|
|
2774
2705
|
}
|
|
2775
2706
|
_maybeCancelLongPressForTouch(touchId) {
|
|
2776
|
-
|
|
2707
|
+
const {
|
|
2777
2708
|
longPressTimeoutId
|
|
2778
2709
|
} = this.touchState[touchId];
|
|
2779
2710
|
if (longPressTimeoutId) {
|
|
2780
2711
|
clearTimeout(longPressTimeoutId);
|
|
2781
|
-
this.touchState[touchId] =
|
|
2712
|
+
this.touchState[touchId] = _extends({}, this.touchState[touchId], {
|
|
2782
2713
|
longPressTimeoutId: null
|
|
2783
2714
|
});
|
|
2784
2715
|
}
|
|
2785
2716
|
}
|
|
2786
2717
|
_maybeCancelPressAndHoldForTouch(touchId) {
|
|
2787
|
-
|
|
2718
|
+
const {
|
|
2788
2719
|
pressAndHoldIntervalId
|
|
2789
2720
|
} = this.touchState[touchId];
|
|
2790
2721
|
if (pressAndHoldIntervalId) {
|
|
2791
2722
|
// If there was an interval set to detect holds, clear it out.
|
|
2792
2723
|
clearInterval(pressAndHoldIntervalId);
|
|
2793
|
-
this.touchState[touchId] =
|
|
2724
|
+
this.touchState[touchId] = _extends({}, this.touchState[touchId], {
|
|
2794
2725
|
pressAndHoldIntervalId: null
|
|
2795
2726
|
});
|
|
2796
2727
|
}
|
|
@@ -2823,7 +2754,7 @@ class GestureStateMachine {
|
|
|
2823
2754
|
// indicates that a gesture that can focus future nodes is still in
|
|
2824
2755
|
// progress, but that no node is currently focused. The latter
|
|
2825
2756
|
// indicates that the gesture has ended and nothing will be focused.
|
|
2826
|
-
this.touchState[touchId] =
|
|
2757
|
+
this.touchState[touchId] = _extends({}, this.touchState[touchId], {
|
|
2827
2758
|
activeNodeId: id
|
|
2828
2759
|
});
|
|
2829
2760
|
this.handlers.onFocus(id);
|
|
@@ -2834,7 +2765,7 @@ class GestureStateMachine {
|
|
|
2834
2765
|
this.handlers.onTrigger(id);
|
|
2835
2766
|
|
|
2836
2767
|
// Set up a new hold detector for the current button.
|
|
2837
|
-
this.touchState[touchId] =
|
|
2768
|
+
this.touchState[touchId] = _extends({}, this.touchState[touchId], {
|
|
2838
2769
|
pressAndHoldIntervalId: setInterval(() => {
|
|
2839
2770
|
// On every cycle, trigger the click handler.
|
|
2840
2771
|
this.handlers.onTrigger(id);
|
|
@@ -2842,10 +2773,10 @@ class GestureStateMachine {
|
|
|
2842
2773
|
});
|
|
2843
2774
|
} else {
|
|
2844
2775
|
// Set up a new hold detector for the current button.
|
|
2845
|
-
this.touchState[touchId] =
|
|
2776
|
+
this.touchState[touchId] = _extends({}, this.touchState[touchId], {
|
|
2846
2777
|
longPressTimeoutId: setTimeout(() => {
|
|
2847
2778
|
this.handlers.onLongPress(id);
|
|
2848
|
-
this.touchState[touchId] =
|
|
2779
|
+
this.touchState[touchId] = _extends({}, this.touchState[touchId], {
|
|
2849
2780
|
longPressTimeoutId: null
|
|
2850
2781
|
});
|
|
2851
2782
|
}, this.options.longPressWaitTimeMs)
|
|
@@ -2858,7 +2789,7 @@ class GestureStateMachine {
|
|
|
2858
2789
|
* Clear out all active gesture information.
|
|
2859
2790
|
*/
|
|
2860
2791
|
_onSwipeStart() {
|
|
2861
|
-
for (
|
|
2792
|
+
for (const activeTouchId of Object.keys(this.touchState)) {
|
|
2862
2793
|
this._maybeCancelLongPressForTouch(activeTouchId);
|
|
2863
2794
|
this._maybeCancelPressAndHoldForTouch(activeTouchId);
|
|
2864
2795
|
}
|
|
@@ -2901,7 +2832,7 @@ class GestureStateMachine {
|
|
|
2901
2832
|
// here anyways.
|
|
2902
2833
|
return;
|
|
2903
2834
|
}
|
|
2904
|
-
|
|
2835
|
+
const startingNodeId = getId();
|
|
2905
2836
|
this.touchState[touchId] = {
|
|
2906
2837
|
swipeLocked: this.swipeDisabledNodeIds.includes(startingNodeId),
|
|
2907
2838
|
startX: pageX
|
|
@@ -2929,13 +2860,13 @@ class GestureStateMachine {
|
|
|
2929
2860
|
} else if (this.touchState[touchId]) {
|
|
2930
2861
|
// It could be touch events started outside the keypad and
|
|
2931
2862
|
// moved into it; ignore them.
|
|
2932
|
-
|
|
2863
|
+
const {
|
|
2933
2864
|
activeNodeId,
|
|
2934
2865
|
startX,
|
|
2935
2866
|
swipeLocked
|
|
2936
2867
|
} = this.touchState[touchId];
|
|
2937
|
-
|
|
2938
|
-
|
|
2868
|
+
const dx = pageX - startX;
|
|
2869
|
+
const shouldBeginSwiping = swipeEnabled && !swipeLocked && Math.abs(dx) > this.options.swipeThresholdPx;
|
|
2939
2870
|
if (shouldBeginSwiping) {
|
|
2940
2871
|
this._onSwipeStart();
|
|
2941
2872
|
|
|
@@ -2946,7 +2877,7 @@ class GestureStateMachine {
|
|
|
2946
2877
|
};
|
|
2947
2878
|
this.handlers.onSwipeChange(pageX - this.swipeState.startX);
|
|
2948
2879
|
} else {
|
|
2949
|
-
|
|
2880
|
+
const id = getId();
|
|
2950
2881
|
if (id !== activeNodeId) {
|
|
2951
2882
|
this._onFocus(id, touchId);
|
|
2952
2883
|
}
|
|
@@ -2973,12 +2904,12 @@ class GestureStateMachine {
|
|
|
2973
2904
|
} else if (this.touchState[touchId]) {
|
|
2974
2905
|
// It could be touch events started outside the keypad and
|
|
2975
2906
|
// moved into it; ignore them.
|
|
2976
|
-
|
|
2907
|
+
const {
|
|
2977
2908
|
activeNodeId,
|
|
2978
2909
|
pressAndHoldIntervalId
|
|
2979
2910
|
} = this.touchState[touchId];
|
|
2980
2911
|
this._cleanupTouchEvent(touchId);
|
|
2981
|
-
|
|
2912
|
+
const didPressAndHold = !!pressAndHoldIntervalId;
|
|
2982
2913
|
if (didPressAndHold) {
|
|
2983
2914
|
// We don't trigger a touch end if there was a press and hold,
|
|
2984
2915
|
// because the key has been triggered at least once and calling
|
|
@@ -3066,12 +2997,12 @@ class NodeManager {
|
|
|
3066
2997
|
// Make sure that any children appear first.
|
|
3067
2998
|
// TODO(charlie): This is a very simplistic system that wouldn't
|
|
3068
2999
|
// properly handle multiple levels of nesting.
|
|
3069
|
-
|
|
3000
|
+
const allIds = [...(childIds || []), id, ...this._orderedIds];
|
|
3070
3001
|
|
|
3071
3002
|
// De-dupe the list of IDs.
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
for (
|
|
3003
|
+
const orderedIds = [];
|
|
3004
|
+
const seenIds = {};
|
|
3005
|
+
for (const _id of allIds) {
|
|
3075
3006
|
if (!seenIds[_id]) {
|
|
3076
3007
|
orderedIds.push(_id);
|
|
3077
3008
|
seenIds[_id] = true;
|
|
@@ -3099,10 +3030,10 @@ class NodeManager {
|
|
|
3099
3030
|
* the given coordinates
|
|
3100
3031
|
*/
|
|
3101
3032
|
idForCoords(x, y) {
|
|
3102
|
-
for (
|
|
3103
|
-
|
|
3033
|
+
for (const id of this._orderedIds) {
|
|
3034
|
+
const domNode = this._nodesById[id];
|
|
3104
3035
|
if (domNode) {
|
|
3105
|
-
|
|
3036
|
+
const bounds = domNode.getBoundingClientRect();
|
|
3106
3037
|
if (bounds.left <= x && bounds.right > x && bounds.top <= y && bounds.bottom > y) {
|
|
3107
3038
|
this._cachedBoundingBoxesById[id] = bounds;
|
|
3108
3039
|
return id;
|
|
@@ -3122,7 +3053,7 @@ class NodeManager {
|
|
|
3122
3053
|
*/
|
|
3123
3054
|
layoutPropsForId(id) {
|
|
3124
3055
|
if (!this._cachedBoundingBoxesById[id]) {
|
|
3125
|
-
|
|
3056
|
+
const node = this._nodesById[id];
|
|
3126
3057
|
this._cachedBoundingBoxesById[id] = node ? node.getBoundingClientRect() : new DOMRect();
|
|
3127
3058
|
}
|
|
3128
3059
|
return {
|
|
@@ -3261,7 +3192,7 @@ class PopoverStateMachine {
|
|
|
3261
3192
|
* ended
|
|
3262
3193
|
*/
|
|
3263
3194
|
onTouchEnd(id) {
|
|
3264
|
-
|
|
3195
|
+
const inPopover = !!this.activePopover;
|
|
3265
3196
|
if (inPopover) {
|
|
3266
3197
|
// If we have a popover that is currently active, we trigger a
|
|
3267
3198
|
// click on this node if and only if it's in the popover, with the
|
|
@@ -3275,16 +3206,16 @@ class PopoverStateMachine {
|
|
|
3275
3206
|
if (this._isNodeInsidePopover(this.activePopover, id)) {
|
|
3276
3207
|
this.handlers.onClick(id, id, inPopover);
|
|
3277
3208
|
} else if (this.activePopover === id) {
|
|
3278
|
-
|
|
3209
|
+
const keyId = this._defaultNodeForPopover(id);
|
|
3279
3210
|
this.handlers.onClick(keyId, keyId, inPopover);
|
|
3280
3211
|
}
|
|
3281
3212
|
} else if (this.popovers[id]) {
|
|
3282
3213
|
// Otherwise, if the node is itself a popover revealer, trigger the
|
|
3283
3214
|
// clicking of its default node, but pass back the popover node ID
|
|
3284
3215
|
// for layout purposes.
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
this.handlers.onClick(
|
|
3216
|
+
const keyId = this._defaultNodeForPopover(id);
|
|
3217
|
+
const domNodeId = id;
|
|
3218
|
+
this.handlers.onClick(keyId, domNodeId, inPopover);
|
|
3288
3219
|
} else if (id != null) {
|
|
3289
3220
|
// Finally, if we have no active popover, and we touched up over a
|
|
3290
3221
|
// valid key, trigger a click.
|
|
@@ -3300,13 +3231,13 @@ class PopoverStateMachine {
|
|
|
3300
3231
|
}
|
|
3301
3232
|
}
|
|
3302
3233
|
|
|
3303
|
-
|
|
3304
|
-
|
|
3234
|
+
const _excluded$5 = ["popover"];
|
|
3235
|
+
const coordsForEvent = evt => {
|
|
3305
3236
|
return [evt.changedTouches[0].clientX, evt.changedTouches[0].clientY];
|
|
3306
3237
|
};
|
|
3307
3238
|
class GestureManager {
|
|
3308
3239
|
constructor(options, handlers, disabledSwipeKeys, multiPressableKeys) {
|
|
3309
|
-
|
|
3240
|
+
const {
|
|
3310
3241
|
swipeEnabled
|
|
3311
3242
|
} = options;
|
|
3312
3243
|
this.swipeEnabled = swipeEnabled;
|
|
@@ -3316,11 +3247,11 @@ class GestureManager {
|
|
|
3316
3247
|
this.nodeManager = new NodeManager();
|
|
3317
3248
|
this.popoverStateMachine = new PopoverStateMachine({
|
|
3318
3249
|
onActiveNodesChanged: activeNodes => {
|
|
3319
|
-
|
|
3250
|
+
const {
|
|
3320
3251
|
popover
|
|
3321
3252
|
} = activeNodes,
|
|
3322
|
-
rest =
|
|
3323
|
-
handlers.onActiveNodesChanged(
|
|
3253
|
+
rest = _objectWithoutPropertiesLoose(activeNodes, _excluded$5);
|
|
3254
|
+
handlers.onActiveNodesChanged(_extends({
|
|
3324
3255
|
popover: popover && {
|
|
3325
3256
|
parentId: popover.parentId,
|
|
3326
3257
|
bounds: this.nodeManager.layoutPropsForId(popover.parentId).initialBounds,
|
|
@@ -3381,13 +3312,13 @@ class GestureManager {
|
|
|
3381
3312
|
if (!this.trackEvents) {
|
|
3382
3313
|
return;
|
|
3383
3314
|
}
|
|
3384
|
-
|
|
3315
|
+
const [x] = coordsForEvent(evt);
|
|
3385
3316
|
|
|
3386
3317
|
// TODO(charlie): It doesn't seem to be guaranteed that every touch
|
|
3387
3318
|
// event on `changedTouches` originates from the node through which this
|
|
3388
3319
|
// touch event was sent. In that case, we'd be inappropriately reporting
|
|
3389
3320
|
// the starting node ID.
|
|
3390
|
-
for (
|
|
3321
|
+
for (let i = 0; i < evt.changedTouches.length; i++) {
|
|
3391
3322
|
this.gestureStateMachine.onTouchStart(() => id, evt.changedTouches[i].identifier, x);
|
|
3392
3323
|
}
|
|
3393
3324
|
|
|
@@ -3406,10 +3337,10 @@ class GestureManager {
|
|
|
3406
3337
|
if (!this.trackEvents) {
|
|
3407
3338
|
return;
|
|
3408
3339
|
}
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
for (
|
|
3340
|
+
const swipeLocked = this.popoverStateMachine.isPopoverVisible();
|
|
3341
|
+
const swipeEnabled = this.swipeEnabled && !swipeLocked;
|
|
3342
|
+
const [x, y] = coordsForEvent(evt);
|
|
3343
|
+
for (let i = 0; i < evt.changedTouches.length; i++) {
|
|
3413
3344
|
this.gestureStateMachine.onTouchMove(() => this.nodeManager.idForCoords(x, y), evt.changedTouches[i].identifier, x, swipeEnabled);
|
|
3414
3345
|
}
|
|
3415
3346
|
}
|
|
@@ -3424,8 +3355,8 @@ class GestureManager {
|
|
|
3424
3355
|
if (!this.trackEvents) {
|
|
3425
3356
|
return;
|
|
3426
3357
|
}
|
|
3427
|
-
|
|
3428
|
-
for (
|
|
3358
|
+
const [x, y] = coordsForEvent(evt);
|
|
3359
|
+
for (let i = 0; i < evt.changedTouches.length; i++) {
|
|
3429
3360
|
this.gestureStateMachine.onTouchEnd(() => this.nodeManager.idForCoords(x, y), evt.changedTouches[i].identifier, x);
|
|
3430
3361
|
}
|
|
3431
3362
|
}
|
|
@@ -3440,7 +3371,7 @@ class GestureManager {
|
|
|
3440
3371
|
if (!this.trackEvents) {
|
|
3441
3372
|
return;
|
|
3442
3373
|
}
|
|
3443
|
-
for (
|
|
3374
|
+
for (let i = 0; i < evt.changedTouches.length; i++) {
|
|
3444
3375
|
this.gestureStateMachine.onTouchCancel(evt.changedTouches[i].identifier);
|
|
3445
3376
|
}
|
|
3446
3377
|
}
|
|
@@ -3487,12 +3418,15 @@ class GestureManager {
|
|
|
3487
3418
|
}
|
|
3488
3419
|
}
|
|
3489
3420
|
|
|
3421
|
+
/**
|
|
3422
|
+
* A small triangular decal to sit in the corner of a parent component.
|
|
3423
|
+
*/
|
|
3490
3424
|
class CornerDecal extends React.Component {
|
|
3491
3425
|
render() {
|
|
3492
|
-
|
|
3426
|
+
const {
|
|
3493
3427
|
style
|
|
3494
3428
|
} = this.props;
|
|
3495
|
-
|
|
3429
|
+
const containerStyle = [styles$d.container, ...(Array.isArray(style) ? style : [style])];
|
|
3496
3430
|
return /*#__PURE__*/React.createElement(View, {
|
|
3497
3431
|
style: containerStyle
|
|
3498
3432
|
}, /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3506,11 +3440,11 @@ class CornerDecal extends React.Component {
|
|
|
3506
3440
|
})));
|
|
3507
3441
|
}
|
|
3508
3442
|
}
|
|
3509
|
-
|
|
3443
|
+
CornerDecal.propTypes = {
|
|
3510
3444
|
style: PropTypes.any
|
|
3511
|
-
}
|
|
3512
|
-
|
|
3513
|
-
|
|
3445
|
+
};
|
|
3446
|
+
const triangleSizePx = 7;
|
|
3447
|
+
const styles$d = StyleSheet.create({
|
|
3514
3448
|
container: {
|
|
3515
3449
|
position: "absolute",
|
|
3516
3450
|
top: 0,
|
|
@@ -3554,19 +3488,22 @@ var Styles = StyleSheet.create({
|
|
|
3554
3488
|
}
|
|
3555
3489
|
});
|
|
3556
3490
|
|
|
3557
|
-
|
|
3491
|
+
/**
|
|
3492
|
+
* A component that renders an icon with math (via KaTeX).
|
|
3493
|
+
*/
|
|
3494
|
+
const {
|
|
3558
3495
|
row: row$7,
|
|
3559
3496
|
centered: centered$4
|
|
3560
3497
|
} = Styles;
|
|
3561
3498
|
class MathIcon extends React.Component {
|
|
3562
|
-
constructor() {
|
|
3563
|
-
super(...
|
|
3564
|
-
|
|
3565
|
-
|
|
3499
|
+
constructor(...args) {
|
|
3500
|
+
super(...args);
|
|
3501
|
+
this._renderMath = () => {
|
|
3502
|
+
const {
|
|
3566
3503
|
math
|
|
3567
3504
|
} = this.props;
|
|
3568
3505
|
katex.render(math, ReactDOM.findDOMNode(this));
|
|
3569
|
-
}
|
|
3506
|
+
};
|
|
3570
3507
|
}
|
|
3571
3508
|
componentDidMount() {
|
|
3572
3509
|
this._renderMath();
|
|
@@ -3577,20 +3514,20 @@ class MathIcon extends React.Component {
|
|
|
3577
3514
|
}
|
|
3578
3515
|
}
|
|
3579
3516
|
render() {
|
|
3580
|
-
|
|
3517
|
+
const {
|
|
3581
3518
|
style
|
|
3582
3519
|
} = this.props;
|
|
3583
|
-
|
|
3520
|
+
const containerStyle = [row$7, centered$4, styles$c.size, styles$c.base, ...(Array.isArray(style) ? style : [style])];
|
|
3584
3521
|
return /*#__PURE__*/React.createElement(View, {
|
|
3585
3522
|
style: containerStyle
|
|
3586
3523
|
});
|
|
3587
3524
|
}
|
|
3588
3525
|
}
|
|
3589
|
-
|
|
3526
|
+
MathIcon.propTypes = {
|
|
3590
3527
|
math: PropTypes.string.isRequired,
|
|
3591
3528
|
style: PropTypes.any
|
|
3592
|
-
}
|
|
3593
|
-
|
|
3529
|
+
};
|
|
3530
|
+
const styles$c = StyleSheet.create({
|
|
3594
3531
|
size: {
|
|
3595
3532
|
height: iconSizeHeightPx,
|
|
3596
3533
|
width: iconSizeWidthPx
|
|
@@ -3600,6 +3537,11 @@ var styles$c = StyleSheet.create({
|
|
|
3600
3537
|
}
|
|
3601
3538
|
});
|
|
3602
3539
|
|
|
3540
|
+
/**
|
|
3541
|
+
* An autogenerated component that renders the COS iconograpy in SVG.
|
|
3542
|
+
*
|
|
3543
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3544
|
+
*/
|
|
3603
3545
|
class Cos extends React.Component {
|
|
3604
3546
|
render() {
|
|
3605
3547
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3621,10 +3563,15 @@ class Cos extends React.Component {
|
|
|
3621
3563
|
})));
|
|
3622
3564
|
}
|
|
3623
3565
|
}
|
|
3624
|
-
|
|
3566
|
+
Cos.propTypes = {
|
|
3625
3567
|
color: PropTypes.string.isRequired
|
|
3626
|
-
}
|
|
3568
|
+
};
|
|
3627
3569
|
|
|
3570
|
+
/**
|
|
3571
|
+
* An autogenerated component that renders the LOG iconograpy in SVG.
|
|
3572
|
+
*
|
|
3573
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3574
|
+
*/
|
|
3628
3575
|
class Log extends React.Component {
|
|
3629
3576
|
render() {
|
|
3630
3577
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3643,10 +3590,15 @@ class Log extends React.Component {
|
|
|
3643
3590
|
})));
|
|
3644
3591
|
}
|
|
3645
3592
|
}
|
|
3646
|
-
|
|
3593
|
+
Log.propTypes = {
|
|
3647
3594
|
color: PropTypes.string.isRequired
|
|
3648
|
-
}
|
|
3595
|
+
};
|
|
3649
3596
|
|
|
3597
|
+
/**
|
|
3598
|
+
* An autogenerated component that renders the EQUAL iconograpy in SVG.
|
|
3599
|
+
*
|
|
3600
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3601
|
+
*/
|
|
3650
3602
|
class Equal extends React.Component {
|
|
3651
3603
|
render() {
|
|
3652
3604
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3671,16 +3623,16 @@ class Equal extends React.Component {
|
|
|
3671
3623
|
})));
|
|
3672
3624
|
}
|
|
3673
3625
|
}
|
|
3674
|
-
|
|
3626
|
+
Equal.propTypes = {
|
|
3675
3627
|
color: PropTypes.string.isRequired
|
|
3676
|
-
}
|
|
3628
|
+
};
|
|
3677
3629
|
|
|
3678
3630
|
/**
|
|
3679
3631
|
* An autogenerated component that renders the BACKSPACE iconograpy in SVG.
|
|
3680
3632
|
*
|
|
3681
3633
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3682
3634
|
*/
|
|
3683
|
-
|
|
3635
|
+
const Backspace = () => {
|
|
3684
3636
|
return /*#__PURE__*/React.createElement("svg", {
|
|
3685
3637
|
width: "48",
|
|
3686
3638
|
height: "48",
|
|
@@ -3703,6 +3655,11 @@ var Backspace = () => {
|
|
|
3703
3655
|
})));
|
|
3704
3656
|
};
|
|
3705
3657
|
|
|
3658
|
+
/**
|
|
3659
|
+
* An autogenerated component that renders the SQRT iconograpy in SVG.
|
|
3660
|
+
*
|
|
3661
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3662
|
+
*/
|
|
3706
3663
|
class Sqrt extends React.Component {
|
|
3707
3664
|
render() {
|
|
3708
3665
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3724,10 +3681,15 @@ class Sqrt extends React.Component {
|
|
|
3724
3681
|
})));
|
|
3725
3682
|
}
|
|
3726
3683
|
}
|
|
3727
|
-
|
|
3684
|
+
Sqrt.propTypes = {
|
|
3728
3685
|
color: PropTypes.string.isRequired
|
|
3729
|
-
}
|
|
3686
|
+
};
|
|
3730
3687
|
|
|
3688
|
+
/**
|
|
3689
|
+
* An autogenerated component that renders the EXP iconograpy in SVG.
|
|
3690
|
+
*
|
|
3691
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3692
|
+
*/
|
|
3731
3693
|
class Exp extends React.Component {
|
|
3732
3694
|
render() {
|
|
3733
3695
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3746,10 +3708,15 @@ class Exp extends React.Component {
|
|
|
3746
3708
|
})));
|
|
3747
3709
|
}
|
|
3748
3710
|
}
|
|
3749
|
-
|
|
3711
|
+
Exp.propTypes = {
|
|
3750
3712
|
color: PropTypes.string.isRequired
|
|
3751
|
-
}
|
|
3713
|
+
};
|
|
3752
3714
|
|
|
3715
|
+
/**
|
|
3716
|
+
* An autogenerated component that renders the NEQ iconograpy in SVG.
|
|
3717
|
+
*
|
|
3718
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3719
|
+
*/
|
|
3753
3720
|
class Neq extends React.Component {
|
|
3754
3721
|
render() {
|
|
3755
3722
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3774,10 +3741,15 @@ class Neq extends React.Component {
|
|
|
3774
3741
|
})));
|
|
3775
3742
|
}
|
|
3776
3743
|
}
|
|
3777
|
-
|
|
3744
|
+
Neq.propTypes = {
|
|
3778
3745
|
color: PropTypes.string.isRequired
|
|
3779
|
-
}
|
|
3746
|
+
};
|
|
3780
3747
|
|
|
3748
|
+
/**
|
|
3749
|
+
* An autogenerated component that renders the GEQ iconograpy in SVG.
|
|
3750
|
+
*
|
|
3751
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3752
|
+
*/
|
|
3781
3753
|
class Geq extends React.Component {
|
|
3782
3754
|
render() {
|
|
3783
3755
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3802,10 +3774,15 @@ class Geq extends React.Component {
|
|
|
3802
3774
|
})));
|
|
3803
3775
|
}
|
|
3804
3776
|
}
|
|
3805
|
-
|
|
3777
|
+
Geq.propTypes = {
|
|
3806
3778
|
color: PropTypes.string.isRequired
|
|
3807
|
-
}
|
|
3779
|
+
};
|
|
3808
3780
|
|
|
3781
|
+
/**
|
|
3782
|
+
* An autogenerated component that renders the LN iconograpy in SVG.
|
|
3783
|
+
*
|
|
3784
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3785
|
+
*/
|
|
3809
3786
|
class Ln extends React.Component {
|
|
3810
3787
|
render() {
|
|
3811
3788
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3824,16 +3801,16 @@ class Ln extends React.Component {
|
|
|
3824
3801
|
})));
|
|
3825
3802
|
}
|
|
3826
3803
|
}
|
|
3827
|
-
|
|
3804
|
+
Ln.propTypes = {
|
|
3828
3805
|
color: PropTypes.string.isRequired
|
|
3829
|
-
}
|
|
3806
|
+
};
|
|
3830
3807
|
|
|
3831
3808
|
/**
|
|
3832
3809
|
* An autogenerated component that renders the DISMISS iconograpy in SVG.
|
|
3833
3810
|
*
|
|
3834
3811
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3835
3812
|
*/
|
|
3836
|
-
|
|
3813
|
+
const Dismiss = () => {
|
|
3837
3814
|
return /*#__PURE__*/React.createElement("svg", {
|
|
3838
3815
|
width: "48",
|
|
3839
3816
|
height: "48",
|
|
@@ -3853,6 +3830,11 @@ var Dismiss = () => {
|
|
|
3853
3830
|
})));
|
|
3854
3831
|
};
|
|
3855
3832
|
|
|
3833
|
+
/**
|
|
3834
|
+
* An autogenerated component that renders the SIN iconograpy in SVG.
|
|
3835
|
+
*
|
|
3836
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3837
|
+
*/
|
|
3856
3838
|
class Sin extends React.Component {
|
|
3857
3839
|
render() {
|
|
3858
3840
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3874,10 +3856,15 @@ class Sin extends React.Component {
|
|
|
3874
3856
|
})));
|
|
3875
3857
|
}
|
|
3876
3858
|
}
|
|
3877
|
-
|
|
3859
|
+
Sin.propTypes = {
|
|
3878
3860
|
color: PropTypes.string.isRequired
|
|
3879
|
-
}
|
|
3861
|
+
};
|
|
3880
3862
|
|
|
3863
|
+
/**
|
|
3864
|
+
* An autogenerated component that renders the LT iconograpy in SVG.
|
|
3865
|
+
*
|
|
3866
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3867
|
+
*/
|
|
3881
3868
|
class Lt extends React.Component {
|
|
3882
3869
|
render() {
|
|
3883
3870
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3902,10 +3889,15 @@ class Lt extends React.Component {
|
|
|
3902
3889
|
})));
|
|
3903
3890
|
}
|
|
3904
3891
|
}
|
|
3905
|
-
|
|
3892
|
+
Lt.propTypes = {
|
|
3906
3893
|
color: PropTypes.string.isRequired
|
|
3907
|
-
}
|
|
3894
|
+
};
|
|
3908
3895
|
|
|
3896
|
+
/**
|
|
3897
|
+
* An autogenerated component that renders the CUBE_ROOT iconograpy in SVG.
|
|
3898
|
+
*
|
|
3899
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3900
|
+
*/
|
|
3909
3901
|
class CubeRoot extends React.Component {
|
|
3910
3902
|
render() {
|
|
3911
3903
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3930,10 +3922,15 @@ class CubeRoot extends React.Component {
|
|
|
3930
3922
|
})));
|
|
3931
3923
|
}
|
|
3932
3924
|
}
|
|
3933
|
-
|
|
3925
|
+
CubeRoot.propTypes = {
|
|
3934
3926
|
color: PropTypes.string.isRequired
|
|
3935
|
-
}
|
|
3927
|
+
};
|
|
3936
3928
|
|
|
3929
|
+
/**
|
|
3930
|
+
* An autogenerated component that renders the PLUS iconograpy in SVG.
|
|
3931
|
+
*
|
|
3932
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3933
|
+
*/
|
|
3937
3934
|
class Plus extends React.Component {
|
|
3938
3935
|
render() {
|
|
3939
3936
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3955,10 +3952,15 @@ class Plus extends React.Component {
|
|
|
3955
3952
|
})));
|
|
3956
3953
|
}
|
|
3957
3954
|
}
|
|
3958
|
-
|
|
3955
|
+
Plus.propTypes = {
|
|
3959
3956
|
color: PropTypes.string.isRequired
|
|
3960
|
-
}
|
|
3957
|
+
};
|
|
3961
3958
|
|
|
3959
|
+
/**
|
|
3960
|
+
* An autogenerated component that renders the TAN iconograpy in SVG.
|
|
3961
|
+
*
|
|
3962
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
3963
|
+
*/
|
|
3962
3964
|
class Tan extends React.Component {
|
|
3963
3965
|
render() {
|
|
3964
3966
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -3980,11 +3982,11 @@ class Tan extends React.Component {
|
|
|
3980
3982
|
})));
|
|
3981
3983
|
}
|
|
3982
3984
|
}
|
|
3983
|
-
|
|
3985
|
+
Tan.propTypes = {
|
|
3984
3986
|
color: PropTypes.string.isRequired
|
|
3985
|
-
}
|
|
3987
|
+
};
|
|
3986
3988
|
|
|
3987
|
-
|
|
3989
|
+
const Arrow = props => {
|
|
3988
3990
|
return /*#__PURE__*/React.createElement("g", _extends({
|
|
3989
3991
|
fill: "none",
|
|
3990
3992
|
fillRule: "evenodd"
|
|
@@ -4006,7 +4008,7 @@ var Arrow = props => {
|
|
|
4006
4008
|
/**
|
|
4007
4009
|
* An component that renders the LEFT iconograpy in SVG.
|
|
4008
4010
|
*/
|
|
4009
|
-
|
|
4011
|
+
const Left = () => {
|
|
4010
4012
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4011
4013
|
width: "48",
|
|
4012
4014
|
height: "48",
|
|
@@ -4017,7 +4019,7 @@ var Left = () => {
|
|
|
4017
4019
|
/**
|
|
4018
4020
|
* A component that renders the UP iconograpy in SVG.
|
|
4019
4021
|
*/
|
|
4020
|
-
|
|
4022
|
+
const Up = () => {
|
|
4021
4023
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4022
4024
|
width: "48",
|
|
4023
4025
|
height: "48",
|
|
@@ -4030,7 +4032,7 @@ var Up = () => {
|
|
|
4030
4032
|
/**
|
|
4031
4033
|
* A component that renders the DOWN iconograpy in SVG.
|
|
4032
4034
|
*/
|
|
4033
|
-
|
|
4035
|
+
const Down = () => {
|
|
4034
4036
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4035
4037
|
width: "48",
|
|
4036
4038
|
height: "48",
|
|
@@ -4040,6 +4042,11 @@ var Down = () => {
|
|
|
4040
4042
|
}));
|
|
4041
4043
|
};
|
|
4042
4044
|
|
|
4045
|
+
/**
|
|
4046
|
+
* An autogenerated component that renders the LEFT_PAREN iconograpy in SVG.
|
|
4047
|
+
*
|
|
4048
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4049
|
+
*/
|
|
4043
4050
|
class LeftParen extends React.Component {
|
|
4044
4051
|
render() {
|
|
4045
4052
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4064,10 +4071,15 @@ class LeftParen extends React.Component {
|
|
|
4064
4071
|
})));
|
|
4065
4072
|
}
|
|
4066
4073
|
}
|
|
4067
|
-
|
|
4074
|
+
LeftParen.propTypes = {
|
|
4068
4075
|
color: PropTypes.string.isRequired
|
|
4069
|
-
}
|
|
4076
|
+
};
|
|
4070
4077
|
|
|
4078
|
+
/**
|
|
4079
|
+
* An autogenerated component that renders the RIGHT_PAREN iconograpy in SVG.
|
|
4080
|
+
*
|
|
4081
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4082
|
+
*/
|
|
4071
4083
|
class RightParen extends React.Component {
|
|
4072
4084
|
render() {
|
|
4073
4085
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4092,10 +4104,15 @@ class RightParen extends React.Component {
|
|
|
4092
4104
|
})));
|
|
4093
4105
|
}
|
|
4094
4106
|
}
|
|
4095
|
-
|
|
4107
|
+
RightParen.propTypes = {
|
|
4096
4108
|
color: PropTypes.string.isRequired
|
|
4097
|
-
}
|
|
4109
|
+
};
|
|
4098
4110
|
|
|
4111
|
+
/**
|
|
4112
|
+
* An autogenerated component that renders the GT iconograpy in SVG.
|
|
4113
|
+
*
|
|
4114
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4115
|
+
*/
|
|
4099
4116
|
class Gt extends React.Component {
|
|
4100
4117
|
render() {
|
|
4101
4118
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4120,10 +4137,15 @@ class Gt extends React.Component {
|
|
|
4120
4137
|
})));
|
|
4121
4138
|
}
|
|
4122
4139
|
}
|
|
4123
|
-
|
|
4140
|
+
Gt.propTypes = {
|
|
4124
4141
|
color: PropTypes.string.isRequired
|
|
4125
|
-
}
|
|
4142
|
+
};
|
|
4126
4143
|
|
|
4144
|
+
/**
|
|
4145
|
+
* An autogenerated component that renders the DIVIDE iconograpy in SVG.
|
|
4146
|
+
*
|
|
4147
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4148
|
+
*/
|
|
4127
4149
|
class Divide extends React.Component {
|
|
4128
4150
|
render() {
|
|
4129
4151
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4155,10 +4177,15 @@ class Divide extends React.Component {
|
|
|
4155
4177
|
})));
|
|
4156
4178
|
}
|
|
4157
4179
|
}
|
|
4158
|
-
|
|
4180
|
+
Divide.propTypes = {
|
|
4159
4181
|
color: PropTypes.string.isRequired
|
|
4160
|
-
}
|
|
4182
|
+
};
|
|
4161
4183
|
|
|
4184
|
+
/**
|
|
4185
|
+
* An autogenerated component that renders the PERIOD iconograpy in SVG.
|
|
4186
|
+
*
|
|
4187
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4188
|
+
*/
|
|
4162
4189
|
class Period extends React.Component {
|
|
4163
4190
|
render() {
|
|
4164
4191
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4179,10 +4206,15 @@ class Period extends React.Component {
|
|
|
4179
4206
|
})));
|
|
4180
4207
|
}
|
|
4181
4208
|
}
|
|
4182
|
-
|
|
4209
|
+
Period.propTypes = {
|
|
4183
4210
|
color: PropTypes.string.isRequired
|
|
4184
|
-
}
|
|
4211
|
+
};
|
|
4185
4212
|
|
|
4213
|
+
/**
|
|
4214
|
+
* An autogenerated component that renders the PERCENT iconograpy in SVG.
|
|
4215
|
+
*
|
|
4216
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4217
|
+
*/
|
|
4186
4218
|
class Percent extends React.Component {
|
|
4187
4219
|
render() {
|
|
4188
4220
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4221,10 +4253,15 @@ class Percent extends React.Component {
|
|
|
4221
4253
|
}))));
|
|
4222
4254
|
}
|
|
4223
4255
|
}
|
|
4224
|
-
|
|
4256
|
+
Percent.propTypes = {
|
|
4225
4257
|
color: PropTypes.string.isRequired
|
|
4226
|
-
}
|
|
4258
|
+
};
|
|
4227
4259
|
|
|
4260
|
+
/**
|
|
4261
|
+
* An autogenerated component that renders the TIMES iconograpy in SVG.
|
|
4262
|
+
*
|
|
4263
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4264
|
+
*/
|
|
4228
4265
|
class Times extends React.Component {
|
|
4229
4266
|
render() {
|
|
4230
4267
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4249,10 +4286,15 @@ class Times extends React.Component {
|
|
|
4249
4286
|
})));
|
|
4250
4287
|
}
|
|
4251
4288
|
}
|
|
4252
|
-
|
|
4289
|
+
Times.propTypes = {
|
|
4253
4290
|
color: PropTypes.string.isRequired
|
|
4254
|
-
}
|
|
4291
|
+
};
|
|
4255
4292
|
|
|
4293
|
+
/**
|
|
4294
|
+
* An autogenerated component that renders the EXP_3 iconograpy in SVG.
|
|
4295
|
+
*
|
|
4296
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4297
|
+
*/
|
|
4256
4298
|
class Exp3 extends React.Component {
|
|
4257
4299
|
render() {
|
|
4258
4300
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4271,10 +4313,15 @@ class Exp3 extends React.Component {
|
|
|
4271
4313
|
})));
|
|
4272
4314
|
}
|
|
4273
4315
|
}
|
|
4274
|
-
|
|
4316
|
+
Exp3.propTypes = {
|
|
4275
4317
|
color: PropTypes.string.isRequired
|
|
4276
|
-
}
|
|
4318
|
+
};
|
|
4277
4319
|
|
|
4320
|
+
/**
|
|
4321
|
+
* An autogenerated component that renders the EXP_2 iconograpy in SVG.
|
|
4322
|
+
*
|
|
4323
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4324
|
+
*/
|
|
4278
4325
|
class Exp2 extends React.Component {
|
|
4279
4326
|
render() {
|
|
4280
4327
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4293,14 +4340,14 @@ class Exp2 extends React.Component {
|
|
|
4293
4340
|
})));
|
|
4294
4341
|
}
|
|
4295
4342
|
}
|
|
4296
|
-
|
|
4343
|
+
Exp2.propTypes = {
|
|
4297
4344
|
color: PropTypes.string.isRequired
|
|
4298
|
-
}
|
|
4345
|
+
};
|
|
4299
4346
|
|
|
4300
4347
|
/**
|
|
4301
4348
|
* A component that renders the RIGHT iconograpy in SVG.
|
|
4302
4349
|
*/
|
|
4303
|
-
|
|
4350
|
+
const Right = () => {
|
|
4304
4351
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4305
4352
|
width: "48",
|
|
4306
4353
|
height: "48",
|
|
@@ -4310,6 +4357,11 @@ var Right = () => {
|
|
|
4310
4357
|
}));
|
|
4311
4358
|
};
|
|
4312
4359
|
|
|
4360
|
+
/**
|
|
4361
|
+
* An autogenerated component that renders the CDOT iconograpy in SVG.
|
|
4362
|
+
*
|
|
4363
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4364
|
+
*/
|
|
4313
4365
|
class Cdot extends React.Component {
|
|
4314
4366
|
render() {
|
|
4315
4367
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4335,10 +4387,15 @@ class Cdot extends React.Component {
|
|
|
4335
4387
|
}))));
|
|
4336
4388
|
}
|
|
4337
4389
|
}
|
|
4338
|
-
|
|
4390
|
+
Cdot.propTypes = {
|
|
4339
4391
|
color: PropTypes.string.isRequired
|
|
4340
|
-
}
|
|
4392
|
+
};
|
|
4341
4393
|
|
|
4394
|
+
/**
|
|
4395
|
+
* An autogenerated component that renders the LOG_N iconograpy in SVG.
|
|
4396
|
+
*
|
|
4397
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4398
|
+
*/
|
|
4342
4399
|
class LogN extends React.Component {
|
|
4343
4400
|
render() {
|
|
4344
4401
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4357,10 +4414,15 @@ class LogN extends React.Component {
|
|
|
4357
4414
|
})));
|
|
4358
4415
|
}
|
|
4359
4416
|
}
|
|
4360
|
-
|
|
4417
|
+
LogN.propTypes = {
|
|
4361
4418
|
color: PropTypes.string.isRequired
|
|
4362
|
-
}
|
|
4419
|
+
};
|
|
4363
4420
|
|
|
4421
|
+
/**
|
|
4422
|
+
* An autogenerated component that renders the LEQ iconograpy in SVG.
|
|
4423
|
+
*
|
|
4424
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4425
|
+
*/
|
|
4364
4426
|
class Leq extends React.Component {
|
|
4365
4427
|
render() {
|
|
4366
4428
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4385,10 +4447,15 @@ class Leq extends React.Component {
|
|
|
4385
4447
|
})));
|
|
4386
4448
|
}
|
|
4387
4449
|
}
|
|
4388
|
-
|
|
4450
|
+
Leq.propTypes = {
|
|
4389
4451
|
color: PropTypes.string.isRequired
|
|
4390
|
-
}
|
|
4452
|
+
};
|
|
4391
4453
|
|
|
4454
|
+
/**
|
|
4455
|
+
* An autogenerated component that renders the MINUS iconograpy in SVG.
|
|
4456
|
+
*
|
|
4457
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4458
|
+
*/
|
|
4392
4459
|
class Minus extends React.Component {
|
|
4393
4460
|
render() {
|
|
4394
4461
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4410,10 +4477,15 @@ class Minus extends React.Component {
|
|
|
4410
4477
|
})));
|
|
4411
4478
|
}
|
|
4412
4479
|
}
|
|
4413
|
-
|
|
4480
|
+
Minus.propTypes = {
|
|
4414
4481
|
color: PropTypes.string.isRequired
|
|
4415
|
-
}
|
|
4482
|
+
};
|
|
4416
4483
|
|
|
4484
|
+
/**
|
|
4485
|
+
* An autogenerated component that renders the RADICAL iconograpy in SVG.
|
|
4486
|
+
*
|
|
4487
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4488
|
+
*/
|
|
4417
4489
|
class Radical extends React.Component {
|
|
4418
4490
|
render() {
|
|
4419
4491
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4438,10 +4510,15 @@ class Radical extends React.Component {
|
|
|
4438
4510
|
})));
|
|
4439
4511
|
}
|
|
4440
4512
|
}
|
|
4441
|
-
|
|
4513
|
+
Radical.propTypes = {
|
|
4442
4514
|
color: PropTypes.string.isRequired
|
|
4443
|
-
}
|
|
4515
|
+
};
|
|
4444
4516
|
|
|
4517
|
+
/**
|
|
4518
|
+
* An autogenerated component that renders the FRAC iconograpy in SVG.
|
|
4519
|
+
*
|
|
4520
|
+
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4521
|
+
*/
|
|
4445
4522
|
class FracInclusive extends React.Component {
|
|
4446
4523
|
render() {
|
|
4447
4524
|
return /*#__PURE__*/React.createElement("svg", {
|
|
@@ -4475,16 +4552,16 @@ class FracInclusive extends React.Component {
|
|
|
4475
4552
|
}))));
|
|
4476
4553
|
}
|
|
4477
4554
|
}
|
|
4478
|
-
|
|
4555
|
+
FracInclusive.propTypes = {
|
|
4479
4556
|
color: PropTypes.string.isRequired
|
|
4480
|
-
}
|
|
4557
|
+
};
|
|
4481
4558
|
|
|
4482
4559
|
/**
|
|
4483
4560
|
* An autogenerated component that renders the JUMP_OUT_PARENTHESES iconograpy in SVG.
|
|
4484
4561
|
*
|
|
4485
4562
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4486
4563
|
*/
|
|
4487
|
-
|
|
4564
|
+
const JumpOutParentheses = () => {
|
|
4488
4565
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4489
4566
|
width: "48",
|
|
4490
4567
|
height: "48",
|
|
@@ -4518,7 +4595,7 @@ var JumpOutParentheses = () => {
|
|
|
4518
4595
|
*
|
|
4519
4596
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4520
4597
|
*/
|
|
4521
|
-
|
|
4598
|
+
const JumpOutExponent = () => {
|
|
4522
4599
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4523
4600
|
width: "48",
|
|
4524
4601
|
height: "48",
|
|
@@ -4549,7 +4626,7 @@ var JumpOutExponent = () => {
|
|
|
4549
4626
|
*
|
|
4550
4627
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4551
4628
|
*/
|
|
4552
|
-
|
|
4629
|
+
const JumpOutBase = () => {
|
|
4553
4630
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4554
4631
|
width: "48",
|
|
4555
4632
|
height: "48",
|
|
@@ -4580,7 +4657,7 @@ var JumpOutBase = () => {
|
|
|
4580
4657
|
*
|
|
4581
4658
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4582
4659
|
*/
|
|
4583
|
-
|
|
4660
|
+
const JumpIntoNumerator = () => {
|
|
4584
4661
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4585
4662
|
width: "48",
|
|
4586
4663
|
height: "48",
|
|
@@ -4620,7 +4697,7 @@ var JumpIntoNumerator = () => {
|
|
|
4620
4697
|
*
|
|
4621
4698
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4622
4699
|
*/
|
|
4623
|
-
|
|
4700
|
+
const JumpOutNumerator = () => {
|
|
4624
4701
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4625
4702
|
width: "48",
|
|
4626
4703
|
height: "48",
|
|
@@ -4660,7 +4737,7 @@ var JumpOutNumerator = () => {
|
|
|
4660
4737
|
*
|
|
4661
4738
|
* Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.
|
|
4662
4739
|
*/
|
|
4663
|
-
|
|
4740
|
+
const JumpOutDenominator = () => {
|
|
4664
4741
|
return /*#__PURE__*/React.createElement("svg", {
|
|
4665
4742
|
width: "48",
|
|
4666
4743
|
height: "48",
|
|
@@ -4742,46 +4819,52 @@ var Iconography = /*#__PURE__*/Object.freeze({
|
|
|
4742
4819
|
JUMP_OUT_DENOMINATOR: JumpOutDenominator
|
|
4743
4820
|
});
|
|
4744
4821
|
|
|
4822
|
+
/**
|
|
4823
|
+
* A component that renders a single SVG icon.
|
|
4824
|
+
*/
|
|
4745
4825
|
class SvgIcon extends React.Component {
|
|
4746
4826
|
render() {
|
|
4747
|
-
|
|
4827
|
+
const {
|
|
4748
4828
|
color,
|
|
4749
4829
|
name
|
|
4750
4830
|
} = this.props;
|
|
4751
4831
|
|
|
4752
4832
|
// eslint-disable-next-line import/namespace
|
|
4753
|
-
|
|
4833
|
+
const SvgForName = Iconography[name];
|
|
4754
4834
|
return /*#__PURE__*/React.createElement(SvgForName, {
|
|
4755
4835
|
color: color
|
|
4756
4836
|
});
|
|
4757
4837
|
}
|
|
4758
4838
|
}
|
|
4759
|
-
|
|
4839
|
+
SvgIcon.propTypes = {
|
|
4760
4840
|
color: PropTypes.string.isRequired,
|
|
4761
4841
|
name: PropTypes.string.isRequired
|
|
4762
|
-
}
|
|
4842
|
+
};
|
|
4763
4843
|
|
|
4764
|
-
|
|
4844
|
+
/**
|
|
4845
|
+
* A component that renders a text-based icon.
|
|
4846
|
+
*/
|
|
4847
|
+
const {
|
|
4765
4848
|
row: row$6,
|
|
4766
4849
|
centered: centered$3
|
|
4767
4850
|
} = Styles;
|
|
4768
4851
|
class TextIcon extends React.Component {
|
|
4769
4852
|
render() {
|
|
4770
|
-
|
|
4853
|
+
const {
|
|
4771
4854
|
character,
|
|
4772
4855
|
style
|
|
4773
4856
|
} = this.props;
|
|
4774
|
-
|
|
4857
|
+
const containerStyle = [row$6, centered$3, styles$b.size, styles$b.base, ...(Array.isArray(style) ? style : [style])];
|
|
4775
4858
|
return /*#__PURE__*/React.createElement(View, {
|
|
4776
4859
|
style: containerStyle
|
|
4777
4860
|
}, /*#__PURE__*/React.createElement(Text, null, character));
|
|
4778
4861
|
}
|
|
4779
4862
|
}
|
|
4780
|
-
|
|
4863
|
+
TextIcon.propTypes = {
|
|
4781
4864
|
character: PropTypes.string.isRequired,
|
|
4782
4865
|
style: PropTypes.any
|
|
4783
|
-
}
|
|
4784
|
-
|
|
4866
|
+
};
|
|
4867
|
+
const styles$b = StyleSheet.create({
|
|
4785
4868
|
size: {
|
|
4786
4869
|
height: iconSizeHeightPx,
|
|
4787
4870
|
width: iconSizeWidthPx
|
|
@@ -4792,16 +4875,19 @@ var styles$b = StyleSheet.create({
|
|
|
4792
4875
|
}
|
|
4793
4876
|
});
|
|
4794
4877
|
|
|
4795
|
-
|
|
4796
|
-
|
|
4878
|
+
/**
|
|
4879
|
+
* A component that renders an icon for a symbol with the given name.
|
|
4880
|
+
*/
|
|
4881
|
+
const focusedColor = "#FFF";
|
|
4882
|
+
const unfocusedColor = offBlack;
|
|
4797
4883
|
class Icon extends React.PureComponent {
|
|
4798
4884
|
render() {
|
|
4799
|
-
|
|
4885
|
+
const {
|
|
4800
4886
|
focused,
|
|
4801
4887
|
icon,
|
|
4802
4888
|
style
|
|
4803
4889
|
} = this.props;
|
|
4804
|
-
|
|
4890
|
+
const styleWithFocus = [focused ? styles$a.focused : styles$a.unfocused, ...(Array.isArray(style) ? style : [style])];
|
|
4805
4891
|
switch (icon.type) {
|
|
4806
4892
|
case IconTypes.MATH:
|
|
4807
4893
|
return /*#__PURE__*/React.createElement(MathIcon, {
|
|
@@ -4826,15 +4912,15 @@ class Icon extends React.PureComponent {
|
|
|
4826
4912
|
throw new Error("No icon or symbol provided");
|
|
4827
4913
|
}
|
|
4828
4914
|
}
|
|
4829
|
-
|
|
4915
|
+
Icon.propTypes = {
|
|
4830
4916
|
focused: PropTypes.bool,
|
|
4831
4917
|
icon: iconPropType.isRequired,
|
|
4832
4918
|
// An Aphrodite style object, or an array of Aphrodite style objects.
|
|
4833
4919
|
// Note that custom styles will only be applied to text and math icons
|
|
4834
4920
|
// (and not SVG icons).
|
|
4835
4921
|
style: PropTypes.any
|
|
4836
|
-
}
|
|
4837
|
-
|
|
4922
|
+
};
|
|
4923
|
+
const styles$a = StyleSheet.create({
|
|
4838
4924
|
unfocused: {
|
|
4839
4925
|
color: unfocusedColor
|
|
4840
4926
|
},
|
|
@@ -4843,7 +4929,11 @@ var styles$a = StyleSheet.create({
|
|
|
4843
4929
|
}
|
|
4844
4930
|
});
|
|
4845
4931
|
|
|
4846
|
-
|
|
4932
|
+
/**
|
|
4933
|
+
* A grid of symbols, rendered as text and positioned based on the number of
|
|
4934
|
+
* symbols provided. Up to four symbols will be shown.
|
|
4935
|
+
*/
|
|
4936
|
+
const {
|
|
4847
4937
|
row: row$5,
|
|
4848
4938
|
column: column$3,
|
|
4849
4939
|
centered: centered$2,
|
|
@@ -4851,7 +4941,7 @@ var {
|
|
|
4851
4941
|
} = Styles;
|
|
4852
4942
|
class MultiSymbolGrid extends React.Component {
|
|
4853
4943
|
render() {
|
|
4854
|
-
|
|
4944
|
+
const {
|
|
4855
4945
|
focused,
|
|
4856
4946
|
icons
|
|
4857
4947
|
} = this.props;
|
|
@@ -4863,7 +4953,7 @@ class MultiSymbolGrid extends React.Component {
|
|
|
4863
4953
|
// some styles coercion and doesn't seem worthwhile right now.
|
|
4864
4954
|
icons.forEach(icon => {
|
|
4865
4955
|
if (icon.type !== IconTypes.MATH) {
|
|
4866
|
-
throw new Error(
|
|
4956
|
+
throw new Error(`Received invalid icon: type=${icon.type}, ` + `data=${icon.data}`);
|
|
4867
4957
|
}
|
|
4868
4958
|
});
|
|
4869
4959
|
if (icons.length === 1) {
|
|
@@ -4872,8 +4962,8 @@ class MultiSymbolGrid extends React.Component {
|
|
|
4872
4962
|
focused: focused
|
|
4873
4963
|
});
|
|
4874
4964
|
} else {
|
|
4875
|
-
|
|
4876
|
-
|
|
4965
|
+
const primaryIconStyle = styles$9.base;
|
|
4966
|
+
const secondaryIconStyle = [styles$9.base, styles$9.secondary];
|
|
4877
4967
|
if (icons.length === 2) {
|
|
4878
4968
|
return /*#__PURE__*/React.createElement(View, {
|
|
4879
4969
|
style: [row$5, styles$9.size]
|
|
@@ -4927,13 +5017,13 @@ class MultiSymbolGrid extends React.Component {
|
|
|
4927
5017
|
throw new Error("Invalid number of icons:", icons.length);
|
|
4928
5018
|
}
|
|
4929
5019
|
}
|
|
4930
|
-
|
|
5020
|
+
MultiSymbolGrid.propTypes = {
|
|
4931
5021
|
focused: PropTypes.bool,
|
|
4932
5022
|
icons: PropTypes.arrayOf(iconPropType).isRequired
|
|
4933
|
-
}
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
5023
|
+
};
|
|
5024
|
+
const verticalInsetPx = 2;
|
|
5025
|
+
const horizontalInsetPx = 4;
|
|
5026
|
+
const styles$9 = StyleSheet.create({
|
|
4937
5027
|
size: {
|
|
4938
5028
|
height: iconSizeHeightPx,
|
|
4939
5029
|
width: iconSizeWidthPx
|
|
@@ -4972,9 +5062,9 @@ var styles$9 = StyleSheet.create({
|
|
|
4972
5062
|
|
|
4973
5063
|
// eslint-disable-next-line react/no-unsafe
|
|
4974
5064
|
class KeypadButton extends React.PureComponent {
|
|
4975
|
-
constructor() {
|
|
4976
|
-
super(...
|
|
4977
|
-
|
|
5065
|
+
constructor(...args) {
|
|
5066
|
+
super(...args);
|
|
5067
|
+
this._preInjectStyles = () => {
|
|
4978
5068
|
// HACK(charlie): Pre-inject all of the possible styles for the button.
|
|
4979
5069
|
// This avoids a flickering effect in the echo animation whereby the
|
|
4980
5070
|
// echoes vary in size as they animate. Note that we need to account for
|
|
@@ -4983,25 +5073,25 @@ class KeypadButton extends React.PureComponent {
|
|
|
4983
5073
|
// object. This method must be called whenever a property that
|
|
4984
5074
|
// influences the possible outcomes of `this._getFocusStyle` and
|
|
4985
5075
|
// `this._getButtonStyle` changes (such as `this.buttonSizeStyle`).
|
|
4986
|
-
for (
|
|
5076
|
+
for (const type of Object.keys(KeyTypes)) {
|
|
4987
5077
|
css(View.styles.initial, ...this._getFocusStyle(type));
|
|
4988
|
-
for (
|
|
5078
|
+
for (const borders of Object.values(BorderStyles)) {
|
|
4989
5079
|
css(View.styles.initial, ...this._getButtonStyle(type, borders));
|
|
4990
5080
|
}
|
|
4991
5081
|
}
|
|
4992
|
-
}
|
|
4993
|
-
|
|
4994
|
-
|
|
5082
|
+
};
|
|
5083
|
+
this._getFocusStyle = type => {
|
|
5084
|
+
let focusBackgroundStyle;
|
|
4995
5085
|
if (type === KeyTypes.INPUT_NAVIGATION || type === KeyTypes.KEYPAD_NAVIGATION) {
|
|
4996
5086
|
focusBackgroundStyle = styles$8.light;
|
|
4997
5087
|
} else {
|
|
4998
5088
|
focusBackgroundStyle = styles$8.bright;
|
|
4999
5089
|
}
|
|
5000
5090
|
return [styles$8.focusBox, focusBackgroundStyle];
|
|
5001
|
-
}
|
|
5002
|
-
|
|
5091
|
+
};
|
|
5092
|
+
this._getButtonStyle = (type, borders, style) => {
|
|
5003
5093
|
// Select the appropriate style for the button.
|
|
5004
|
-
|
|
5094
|
+
let backgroundStyle;
|
|
5005
5095
|
switch (type) {
|
|
5006
5096
|
case KeyTypes.EMPTY:
|
|
5007
5097
|
backgroundStyle = styles$8.empty;
|
|
@@ -5021,7 +5111,7 @@ class KeypadButton extends React.PureComponent {
|
|
|
5021
5111
|
backgroundStyle = null;
|
|
5022
5112
|
break;
|
|
5023
5113
|
}
|
|
5024
|
-
|
|
5114
|
+
const borderStyle = [];
|
|
5025
5115
|
if (borders.indexOf(BorderDirections.LEFT) !== -1) {
|
|
5026
5116
|
borderStyle.push(styles$8.leftBorder);
|
|
5027
5117
|
}
|
|
@@ -5033,7 +5123,7 @@ class KeypadButton extends React.PureComponent {
|
|
|
5033
5123
|
// components.
|
|
5034
5124
|
// See: https://facebook.github.io/react-native/docs/style.html
|
|
5035
5125
|
...(Array.isArray(style) ? style : [style])];
|
|
5036
|
-
}
|
|
5126
|
+
};
|
|
5037
5127
|
}
|
|
5038
5128
|
UNSAFE_componentWillMount() {
|
|
5039
5129
|
this.buttonSizeStyle = styleForButtonDimensions(this.props.heightPx, this.props.widthPx);
|
|
@@ -5052,7 +5142,7 @@ class KeypadButton extends React.PureComponent {
|
|
|
5052
5142
|
}
|
|
5053
5143
|
}
|
|
5054
5144
|
render() {
|
|
5055
|
-
|
|
5145
|
+
const {
|
|
5056
5146
|
ariaLabel,
|
|
5057
5147
|
borders,
|
|
5058
5148
|
childKeys,
|
|
@@ -5070,20 +5160,20 @@ class KeypadButton extends React.PureComponent {
|
|
|
5070
5160
|
|
|
5071
5161
|
// We render in the focus state if the key is focused, or if it's an
|
|
5072
5162
|
// echo.
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5163
|
+
const renderFocused = !disabled && focused || popoverEnabled || type === KeyTypes.ECHO;
|
|
5164
|
+
const buttonStyle = this._getButtonStyle(type, borders, style);
|
|
5165
|
+
const focusStyle = this._getFocusStyle(type);
|
|
5166
|
+
const iconWrapperStyle = [styles$8.iconWrapper, disabled && styles$8.disabled];
|
|
5167
|
+
const eventHandlers = {
|
|
5078
5168
|
onTouchCancel,
|
|
5079
5169
|
onTouchEnd,
|
|
5080
5170
|
onTouchMove,
|
|
5081
5171
|
onTouchStart
|
|
5082
5172
|
};
|
|
5083
|
-
|
|
5173
|
+
const maybeFocusBox = renderFocused && /*#__PURE__*/React.createElement(View, {
|
|
5084
5174
|
style: focusStyle
|
|
5085
5175
|
});
|
|
5086
|
-
|
|
5176
|
+
const maybeCornerDecal = !renderFocused && !disabled && childKeys && childKeys.length > 0 && /*#__PURE__*/React.createElement(CornerDecal, {
|
|
5087
5177
|
style: styles$8.decalInset
|
|
5088
5178
|
});
|
|
5089
5179
|
if (type === KeyTypes.EMPTY) {
|
|
@@ -5093,11 +5183,11 @@ class KeypadButton extends React.PureComponent {
|
|
|
5093
5183
|
} else if (type === KeyTypes.MANY) {
|
|
5094
5184
|
// TODO(charlie): Make the long-press interaction accessible. See
|
|
5095
5185
|
// the TODO in key-configs.js for more.
|
|
5096
|
-
|
|
5186
|
+
const manyButtonA11yMarkup = {
|
|
5097
5187
|
role: "button",
|
|
5098
5188
|
ariaLabel: childKeys[0].ariaLabel
|
|
5099
5189
|
};
|
|
5100
|
-
|
|
5190
|
+
const icons = childKeys.map(keyConfig => {
|
|
5101
5191
|
return keyConfig.icon;
|
|
5102
5192
|
});
|
|
5103
5193
|
return /*#__PURE__*/React.createElement(View, _extends({
|
|
@@ -5109,7 +5199,7 @@ class KeypadButton extends React.PureComponent {
|
|
|
5109
5199
|
focused: renderFocused
|
|
5110
5200
|
})), maybeCornerDecal);
|
|
5111
5201
|
} else {
|
|
5112
|
-
|
|
5202
|
+
const a11yMarkup = {
|
|
5113
5203
|
role: "button",
|
|
5114
5204
|
ariaLabel: ariaLabel
|
|
5115
5205
|
};
|
|
@@ -5124,7 +5214,7 @@ class KeypadButton extends React.PureComponent {
|
|
|
5124
5214
|
}
|
|
5125
5215
|
}
|
|
5126
5216
|
}
|
|
5127
|
-
|
|
5217
|
+
KeypadButton.propTypes = {
|
|
5128
5218
|
ariaLabel: PropTypes.string,
|
|
5129
5219
|
// The borders to display on the button. Typically, this should be set
|
|
5130
5220
|
// using one of the preset `BorderStyles` options.
|
|
@@ -5149,17 +5239,17 @@ _defineProperty(KeypadButton, "propTypes", {
|
|
|
5149
5239
|
// (and rely on Flexbox instead), since it might not be pixel perfect
|
|
5150
5240
|
// with borders and such.
|
|
5151
5241
|
widthPx: PropTypes.number.isRequired
|
|
5152
|
-
}
|
|
5153
|
-
|
|
5242
|
+
};
|
|
5243
|
+
KeypadButton.defaultProps = {
|
|
5154
5244
|
borders: BorderStyles.ALL,
|
|
5155
5245
|
childKeys: [],
|
|
5156
5246
|
disabled: false,
|
|
5157
5247
|
focused: false,
|
|
5158
5248
|
popoverEnabled: false
|
|
5159
|
-
}
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5249
|
+
};
|
|
5250
|
+
const focusInsetPx = 4;
|
|
5251
|
+
const focusBoxZIndex = 0;
|
|
5252
|
+
const styles$8 = StyleSheet.create({
|
|
5163
5253
|
buttonBase: {
|
|
5164
5254
|
// HACK(benkomalo): support old style flex box in Android browsers
|
|
5165
5255
|
"-webkit-box-flex": "1",
|
|
@@ -5227,7 +5317,7 @@ var styles$8 = StyleSheet.create({
|
|
|
5227
5317
|
borderBottomWidth: innerBorderWidthPx
|
|
5228
5318
|
}
|
|
5229
5319
|
});
|
|
5230
|
-
|
|
5320
|
+
const styleForButtonDimensions = (heightPx, widthPx) => {
|
|
5231
5321
|
return StyleSheet.create({
|
|
5232
5322
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
5233
5323
|
buttonSize: {
|
|
@@ -5237,21 +5327,21 @@ var styleForButtonDimensions = (heightPx, widthPx) => {
|
|
|
5237
5327
|
}
|
|
5238
5328
|
}).buttonSize;
|
|
5239
5329
|
};
|
|
5240
|
-
|
|
5330
|
+
const mapStateToProps$7 = state => {
|
|
5241
5331
|
return state.layout.buttonDimensions;
|
|
5242
5332
|
};
|
|
5243
5333
|
var KeypadButton$1 = connect(mapStateToProps$7, null, null, {
|
|
5244
5334
|
forwardRef: true
|
|
5245
5335
|
})(KeypadButton);
|
|
5246
5336
|
|
|
5247
|
-
|
|
5337
|
+
const _excluded$4 = ["gestureManager"];
|
|
5248
5338
|
class EmptyKeypadButton extends React.Component {
|
|
5249
5339
|
render() {
|
|
5250
|
-
|
|
5340
|
+
const _this$props = this.props,
|
|
5251
5341
|
{
|
|
5252
5342
|
gestureManager
|
|
5253
5343
|
} = _this$props,
|
|
5254
|
-
rest =
|
|
5344
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$4);
|
|
5255
5345
|
|
|
5256
5346
|
// Register touch events on the button, but don't register its DOM node
|
|
5257
5347
|
// or compute focus state or anything like that. We want the gesture
|
|
@@ -5266,11 +5356,11 @@ class EmptyKeypadButton extends React.Component {
|
|
|
5266
5356
|
}, KeyConfigs.NOOP, rest));
|
|
5267
5357
|
}
|
|
5268
5358
|
}
|
|
5269
|
-
|
|
5359
|
+
EmptyKeypadButton.propTypes = {
|
|
5270
5360
|
gestureManager: PropTypes.instanceOf(GestureManager)
|
|
5271
|
-
}
|
|
5272
|
-
|
|
5273
|
-
|
|
5361
|
+
};
|
|
5362
|
+
const mapStateToProps$6 = state => {
|
|
5363
|
+
const {
|
|
5274
5364
|
gestures
|
|
5275
5365
|
} = state;
|
|
5276
5366
|
return {
|
|
@@ -5281,7 +5371,7 @@ var EmptyKeypadButton$1 = connect(mapStateToProps$6, null, null, {
|
|
|
5281
5371
|
forwardRef: true
|
|
5282
5372
|
})(EmptyKeypadButton);
|
|
5283
5373
|
|
|
5284
|
-
|
|
5374
|
+
const _excluded$3 = ["borders", "childKeyIds", "disabled", "gestureManager", "id", "style"],
|
|
5285
5375
|
_excluded2 = ["keyConfig"];
|
|
5286
5376
|
class TouchableKeypadButton extends React.Component {
|
|
5287
5377
|
shouldComponentUpdate(newProps) {
|
|
@@ -5292,14 +5382,14 @@ class TouchableKeypadButton extends React.Component {
|
|
|
5292
5382
|
return newProps.id !== this.props.id || newProps.gestureManager !== this.props.gestureManager || newProps.focused !== this.props.focused || newProps.disabled !== this.props.disabled || newProps.popoverEnabled !== this.props.popoverEnabled || newProps.type !== this.props.type || !!newProps.style;
|
|
5293
5383
|
}
|
|
5294
5384
|
componentWillUnmount() {
|
|
5295
|
-
|
|
5385
|
+
const {
|
|
5296
5386
|
gestureManager,
|
|
5297
5387
|
id
|
|
5298
5388
|
} = this.props;
|
|
5299
5389
|
gestureManager.unregisterDOMNode(id);
|
|
5300
5390
|
}
|
|
5301
5391
|
render() {
|
|
5302
|
-
|
|
5392
|
+
const _this$props = this.props,
|
|
5303
5393
|
{
|
|
5304
5394
|
borders,
|
|
5305
5395
|
childKeyIds,
|
|
@@ -5308,10 +5398,10 @@ class TouchableKeypadButton extends React.Component {
|
|
|
5308
5398
|
id,
|
|
5309
5399
|
style
|
|
5310
5400
|
} = _this$props,
|
|
5311
|
-
rest =
|
|
5401
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
|
|
5312
5402
|
|
|
5313
5403
|
// Only bind the relevant event handlers if the key is enabled.
|
|
5314
|
-
|
|
5404
|
+
const eventHandlers = disabled ? {
|
|
5315
5405
|
onTouchStart: evt => evt.preventDefault()
|
|
5316
5406
|
} : {
|
|
5317
5407
|
onTouchStart: evt => gestureManager.onTouchStart(evt, id),
|
|
@@ -5319,7 +5409,7 @@ class TouchableKeypadButton extends React.Component {
|
|
|
5319
5409
|
onTouchMove: evt => gestureManager.onTouchMove(evt),
|
|
5320
5410
|
onTouchCancel: evt => gestureManager.onTouchCancel(evt)
|
|
5321
5411
|
};
|
|
5322
|
-
|
|
5412
|
+
const styleWithAddons = [...(Array.isArray(style) ? style : [style]), styles$7.preventScrolls];
|
|
5323
5413
|
return /*#__PURE__*/React.createElement(KeypadButton$1, _extends({
|
|
5324
5414
|
ref: node => gestureManager.registerDOMNode(id, ReactDOM.findDOMNode(node), childKeyIds, borders),
|
|
5325
5415
|
borders: borders,
|
|
@@ -5328,7 +5418,7 @@ class TouchableKeypadButton extends React.Component {
|
|
|
5328
5418
|
}, eventHandlers, rest));
|
|
5329
5419
|
}
|
|
5330
5420
|
}
|
|
5331
|
-
|
|
5421
|
+
TouchableKeypadButton.propTypes = {
|
|
5332
5422
|
borders: bordersPropType,
|
|
5333
5423
|
childKeyIds: PropTypes.arrayOf(keyIdPropType),
|
|
5334
5424
|
disabled: PropTypes.bool,
|
|
@@ -5338,9 +5428,9 @@ _defineProperty(TouchableKeypadButton, "propTypes", {
|
|
|
5338
5428
|
popoverEnabled: PropTypes.bool,
|
|
5339
5429
|
style: PropTypes.any,
|
|
5340
5430
|
type: PropTypes.oneOf(Object.keys(KeyTypes)).isRequired
|
|
5341
|
-
}
|
|
5342
|
-
|
|
5343
|
-
|
|
5431
|
+
};
|
|
5432
|
+
const extractProps = keyConfig => {
|
|
5433
|
+
const {
|
|
5344
5434
|
ariaLabel,
|
|
5345
5435
|
icon,
|
|
5346
5436
|
type
|
|
@@ -5351,25 +5441,25 @@ var extractProps = keyConfig => {
|
|
|
5351
5441
|
type
|
|
5352
5442
|
};
|
|
5353
5443
|
};
|
|
5354
|
-
|
|
5355
|
-
|
|
5444
|
+
const mapStateToProps$5 = (state, ownProps) => {
|
|
5445
|
+
const {
|
|
5356
5446
|
gestures
|
|
5357
5447
|
} = state;
|
|
5358
|
-
|
|
5448
|
+
const {
|
|
5359
5449
|
keyConfig
|
|
5360
5450
|
} = ownProps,
|
|
5361
|
-
rest =
|
|
5362
|
-
|
|
5451
|
+
rest = _objectWithoutPropertiesLoose(ownProps, _excluded2);
|
|
5452
|
+
const {
|
|
5363
5453
|
id,
|
|
5364
5454
|
childKeyIds,
|
|
5365
5455
|
type
|
|
5366
5456
|
} = keyConfig;
|
|
5367
|
-
|
|
5457
|
+
const childKeys = childKeyIds && childKeyIds.map(id => KeyConfigs[id]);
|
|
5368
5458
|
|
|
5369
5459
|
// Override with the default child props, if the key is a multi-symbol key
|
|
5370
5460
|
// (but not a many-symbol key, which operates under different rules).
|
|
5371
|
-
|
|
5372
|
-
return
|
|
5461
|
+
const useFirstChildProps = type !== KeyTypes.MANY && childKeys && childKeys.length > 0;
|
|
5462
|
+
return _extends({}, rest, {
|
|
5373
5463
|
childKeyIds: childKeyIds,
|
|
5374
5464
|
gestureManager: gestures.gestureManager,
|
|
5375
5465
|
id: id,
|
|
@@ -5380,7 +5470,7 @@ var mapStateToProps$5 = (state, ownProps) => {
|
|
|
5380
5470
|
childKeys
|
|
5381
5471
|
}, extractProps(useFirstChildProps ? childKeys[0] : keyConfig));
|
|
5382
5472
|
};
|
|
5383
|
-
|
|
5473
|
+
const styles$7 = StyleSheet.create({
|
|
5384
5474
|
preventScrolls: {
|
|
5385
5475
|
// Touch events that start in the touchable buttons shouldn't be
|
|
5386
5476
|
// allowed to produce page scrolls.
|
|
@@ -5391,14 +5481,14 @@ var TouchableKeypadButton$1 = connect(mapStateToProps$5, null, null, {
|
|
|
5391
5481
|
forwardRef: true
|
|
5392
5482
|
})(TouchableKeypadButton);
|
|
5393
5483
|
|
|
5394
|
-
|
|
5484
|
+
const _excluded$2 = ["keys"];
|
|
5395
5485
|
class ManyKeypadButton extends React.Component {
|
|
5396
5486
|
render() {
|
|
5397
|
-
|
|
5487
|
+
const _this$props = this.props,
|
|
5398
5488
|
{
|
|
5399
5489
|
keys
|
|
5400
5490
|
} = _this$props,
|
|
5401
|
-
rest =
|
|
5491
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$2);
|
|
5402
5492
|
|
|
5403
5493
|
// If we have no extra symbols, render an empty button. If we have just
|
|
5404
5494
|
// one, render a standard button. Otherwise, capture them all in a
|
|
@@ -5406,34 +5496,34 @@ class ManyKeypadButton extends React.Component {
|
|
|
5406
5496
|
if (keys.length === 0) {
|
|
5407
5497
|
return /*#__PURE__*/React.createElement(EmptyKeypadButton$1, rest);
|
|
5408
5498
|
} else if (keys.length === 1) {
|
|
5409
|
-
|
|
5499
|
+
const keyConfig = KeyConfigs[keys[0]];
|
|
5410
5500
|
return /*#__PURE__*/React.createElement(TouchableKeypadButton$1, _extends({
|
|
5411
5501
|
keyConfig: keyConfig
|
|
5412
5502
|
}, rest));
|
|
5413
5503
|
} else {
|
|
5414
|
-
|
|
5504
|
+
const keyConfig = {
|
|
5415
5505
|
id: Keys.MANY,
|
|
5416
5506
|
type: KeyTypes.MANY,
|
|
5417
5507
|
childKeyIds: keys
|
|
5418
5508
|
};
|
|
5419
5509
|
return /*#__PURE__*/React.createElement(TouchableKeypadButton$1, _extends({
|
|
5420
|
-
keyConfig:
|
|
5510
|
+
keyConfig: keyConfig
|
|
5421
5511
|
}, rest));
|
|
5422
5512
|
}
|
|
5423
5513
|
}
|
|
5424
5514
|
}
|
|
5425
|
-
|
|
5515
|
+
ManyKeypadButton.propTypes = {
|
|
5426
5516
|
keys: PropTypes.arrayOf(keyIdPropType).isRequired
|
|
5427
|
-
}
|
|
5517
|
+
};
|
|
5428
5518
|
|
|
5429
5519
|
/**
|
|
5430
5520
|
* This file contains all of the z-index values used throughout the math-input
|
|
5431
5521
|
* component and its children.
|
|
5432
5522
|
*/
|
|
5433
5523
|
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5524
|
+
const popover = 1;
|
|
5525
|
+
const echo = 2;
|
|
5526
|
+
const keypad = 1060;
|
|
5437
5527
|
|
|
5438
5528
|
class Echo extends React.Component {
|
|
5439
5529
|
componentDidMount() {
|
|
@@ -5442,22 +5532,22 @@ class Echo extends React.Component {
|
|
|
5442
5532
|
// ignorant. However, there doesn't seem to be a cleaner way to make
|
|
5443
5533
|
// this happen, and at least here, all the animation context is
|
|
5444
5534
|
// colocated in this file.
|
|
5445
|
-
|
|
5535
|
+
const {
|
|
5446
5536
|
animationDurationMs,
|
|
5447
5537
|
onAnimationFinish
|
|
5448
5538
|
} = this.props;
|
|
5449
5539
|
setTimeout(() => onAnimationFinish(), animationDurationMs);
|
|
5450
5540
|
}
|
|
5451
5541
|
render() {
|
|
5452
|
-
|
|
5542
|
+
const {
|
|
5453
5543
|
borders,
|
|
5454
5544
|
id,
|
|
5455
5545
|
initialBounds
|
|
5456
5546
|
} = this.props;
|
|
5457
|
-
|
|
5547
|
+
const {
|
|
5458
5548
|
icon
|
|
5459
5549
|
} = KeyConfigs[id];
|
|
5460
|
-
|
|
5550
|
+
const containerStyle = _extends({
|
|
5461
5551
|
zIndex: echo,
|
|
5462
5552
|
position: "absolute",
|
|
5463
5553
|
pointerEvents: "none"
|
|
@@ -5478,21 +5568,21 @@ class Echo extends React.Component {
|
|
|
5478
5568
|
}));
|
|
5479
5569
|
}
|
|
5480
5570
|
}
|
|
5481
|
-
|
|
5571
|
+
Echo.propTypes = {
|
|
5482
5572
|
animationDurationMs: PropTypes.number.isRequired,
|
|
5483
5573
|
borders: bordersPropType,
|
|
5484
5574
|
id: keyIdPropType.isRequired,
|
|
5485
5575
|
initialBounds: boundingBoxPropType.isRequired,
|
|
5486
5576
|
onAnimationFinish: PropTypes.func.isRequired
|
|
5487
|
-
}
|
|
5577
|
+
};
|
|
5488
5578
|
class EchoManager extends React.Component {
|
|
5489
|
-
constructor() {
|
|
5490
|
-
super(...
|
|
5491
|
-
|
|
5579
|
+
constructor(...args) {
|
|
5580
|
+
super(...args);
|
|
5581
|
+
this._animationConfigForType = animationType => {
|
|
5492
5582
|
// NOTE(charlie): These must be kept in sync with the transition
|
|
5493
5583
|
// durations and classnames specified in echo.css.
|
|
5494
|
-
|
|
5495
|
-
|
|
5584
|
+
let animationDurationMs;
|
|
5585
|
+
let animationTransitionName;
|
|
5496
5586
|
switch (animationType) {
|
|
5497
5587
|
case EchoAnimationTypes.SLIDE_AND_FADE:
|
|
5498
5588
|
animationDurationMs = 400;
|
|
@@ -5513,21 +5603,21 @@ class EchoManager extends React.Component {
|
|
|
5513
5603
|
animationDurationMs,
|
|
5514
5604
|
animationTransitionName
|
|
5515
5605
|
};
|
|
5516
|
-
}
|
|
5606
|
+
};
|
|
5517
5607
|
}
|
|
5518
5608
|
render() {
|
|
5519
|
-
|
|
5609
|
+
const {
|
|
5520
5610
|
echoes,
|
|
5521
|
-
onAnimationFinish
|
|
5611
|
+
onAnimationFinish
|
|
5522
5612
|
} = this.props;
|
|
5523
5613
|
return /*#__PURE__*/React.createElement("span", null, Object.keys(EchoAnimationTypes).map(animationType => {
|
|
5524
5614
|
// Collect the relevant parameters for the animation type, and
|
|
5525
5615
|
// filter for the appropriate echoes.
|
|
5526
|
-
|
|
5616
|
+
const {
|
|
5527
5617
|
animationDurationMs,
|
|
5528
5618
|
animationTransitionName
|
|
5529
5619
|
} = this._animationConfigForType(animationType);
|
|
5530
|
-
|
|
5620
|
+
const echoesForType = echoes.filter(echo => {
|
|
5531
5621
|
return echo.animationType === animationType;
|
|
5532
5622
|
});
|
|
5533
5623
|
|
|
@@ -5539,7 +5629,7 @@ class EchoManager extends React.Component {
|
|
|
5539
5629
|
return /*#__PURE__*/React.createElement(TransitionGroup, {
|
|
5540
5630
|
key: animationType
|
|
5541
5631
|
}, echoesForType.map(echo => {
|
|
5542
|
-
|
|
5632
|
+
const {
|
|
5543
5633
|
animationId
|
|
5544
5634
|
} = echo;
|
|
5545
5635
|
return /*#__PURE__*/React.createElement(CSSTransition, {
|
|
@@ -5552,20 +5642,23 @@ class EchoManager extends React.Component {
|
|
|
5552
5642
|
key: animationId
|
|
5553
5643
|
}, /*#__PURE__*/React.createElement(Echo, _extends({
|
|
5554
5644
|
animationDurationMs: animationDurationMs,
|
|
5555
|
-
onAnimationFinish: () =>
|
|
5645
|
+
onAnimationFinish: () => onAnimationFinish(animationId)
|
|
5556
5646
|
}, echo)));
|
|
5557
5647
|
}));
|
|
5558
5648
|
}));
|
|
5559
5649
|
}
|
|
5560
5650
|
}
|
|
5561
|
-
|
|
5651
|
+
EchoManager.propTypes = {
|
|
5562
5652
|
echoes: PropTypes.arrayOf(echoPropType),
|
|
5563
5653
|
onAnimationFinish: PropTypes.func.isRequired
|
|
5564
|
-
}
|
|
5654
|
+
};
|
|
5565
5655
|
|
|
5656
|
+
/**
|
|
5657
|
+
* A popover that renders a set of keys floating above the page.
|
|
5658
|
+
*/
|
|
5566
5659
|
class MultiSymbolPopover extends React.Component {
|
|
5567
5660
|
render() {
|
|
5568
|
-
|
|
5661
|
+
const {
|
|
5569
5662
|
keys
|
|
5570
5663
|
} = this.props;
|
|
5571
5664
|
|
|
@@ -5582,10 +5675,10 @@ class MultiSymbolPopover extends React.Component {
|
|
|
5582
5675
|
}));
|
|
5583
5676
|
}
|
|
5584
5677
|
}
|
|
5585
|
-
|
|
5678
|
+
MultiSymbolPopover.propTypes = {
|
|
5586
5679
|
keys: PropTypes.arrayOf(keyConfigPropType)
|
|
5587
|
-
}
|
|
5588
|
-
|
|
5680
|
+
};
|
|
5681
|
+
const styles$6 = StyleSheet.create({
|
|
5589
5682
|
container: {
|
|
5590
5683
|
flexDirection: "column-reverse",
|
|
5591
5684
|
position: "relative",
|
|
@@ -5603,18 +5696,18 @@ var styles$6 = StyleSheet.create({
|
|
|
5603
5696
|
|
|
5604
5697
|
// NOTE(charlie): These must be kept in sync with the transition durations and
|
|
5605
5698
|
// classnames specified in popover.less.
|
|
5606
|
-
|
|
5607
|
-
|
|
5699
|
+
const animationTransitionName = "popover";
|
|
5700
|
+
const animationDurationMs = 200;
|
|
5608
5701
|
|
|
5609
5702
|
// A container component used to position a popover absolutely at a specific
|
|
5610
5703
|
// position.
|
|
5611
5704
|
class PopoverContainer extends React.Component {
|
|
5612
5705
|
render() {
|
|
5613
|
-
|
|
5706
|
+
const {
|
|
5614
5707
|
bounds,
|
|
5615
5708
|
childKeys
|
|
5616
5709
|
} = this.props;
|
|
5617
|
-
|
|
5710
|
+
const containerStyle = _extends({
|
|
5618
5711
|
position: "absolute"
|
|
5619
5712
|
}, bounds);
|
|
5620
5713
|
return /*#__PURE__*/React.createElement("div", {
|
|
@@ -5624,13 +5717,13 @@ class PopoverContainer extends React.Component {
|
|
|
5624
5717
|
}));
|
|
5625
5718
|
}
|
|
5626
5719
|
}
|
|
5627
|
-
|
|
5720
|
+
PopoverContainer.propTypes = {
|
|
5628
5721
|
bounds: boundingBoxPropType.isRequired,
|
|
5629
5722
|
childKeys: PropTypes.arrayOf(keyConfigPropType).isRequired
|
|
5630
|
-
}
|
|
5723
|
+
};
|
|
5631
5724
|
class PopoverManager extends React.Component {
|
|
5632
5725
|
render() {
|
|
5633
|
-
|
|
5726
|
+
const {
|
|
5634
5727
|
popover
|
|
5635
5728
|
} = this.props;
|
|
5636
5729
|
return popover ? /*#__PURE__*/React.createElement(CSSTransition, {
|
|
@@ -5648,21 +5741,21 @@ class PopoverManager extends React.Component {
|
|
|
5648
5741
|
})) : null;
|
|
5649
5742
|
}
|
|
5650
5743
|
}
|
|
5651
|
-
|
|
5744
|
+
PopoverManager.propTypes = {
|
|
5652
5745
|
popover: popoverPropType
|
|
5653
|
-
}
|
|
5746
|
+
};
|
|
5654
5747
|
|
|
5655
|
-
|
|
5748
|
+
const _excluded$1 = ["initialBounds"];
|
|
5656
5749
|
|
|
5657
5750
|
// eslint-disable-next-line react/no-unsafe
|
|
5658
5751
|
class Keypad extends React.Component {
|
|
5659
|
-
constructor() {
|
|
5660
|
-
super(...
|
|
5661
|
-
|
|
5662
|
-
|
|
5752
|
+
constructor(...args) {
|
|
5753
|
+
super(...args);
|
|
5754
|
+
this._computeContainer = () => {
|
|
5755
|
+
const domNode = ReactDOM.findDOMNode(this);
|
|
5663
5756
|
this._container = domNode.getBoundingClientRect();
|
|
5664
|
-
}
|
|
5665
|
-
|
|
5757
|
+
};
|
|
5758
|
+
this._updateSizeAndPosition = () => {
|
|
5666
5759
|
// Mark the container for recalculation next time the keypad is
|
|
5667
5760
|
// opened.
|
|
5668
5761
|
// TODO(charlie): Since we're not recalculating the container
|
|
@@ -5671,8 +5764,8 @@ class Keypad extends React.Component {
|
|
|
5671
5764
|
// difficult to do and, as such, incredibly unlikely, but we may
|
|
5672
5765
|
// want to reconsider the caching here.
|
|
5673
5766
|
this._container = null;
|
|
5674
|
-
}
|
|
5675
|
-
|
|
5767
|
+
};
|
|
5768
|
+
this._onResize = () => {
|
|
5676
5769
|
// Whenever the page resizes, we need to recompute the container's
|
|
5677
5770
|
// bounding box. This is the only time that the bounding box can change.
|
|
5678
5771
|
|
|
@@ -5686,7 +5779,7 @@ class Keypad extends React.Component {
|
|
|
5686
5779
|
}
|
|
5687
5780
|
}, 66);
|
|
5688
5781
|
}
|
|
5689
|
-
}
|
|
5782
|
+
};
|
|
5690
5783
|
}
|
|
5691
5784
|
componentDidMount() {
|
|
5692
5785
|
this._isMounted = true;
|
|
@@ -5703,7 +5796,7 @@ class Keypad extends React.Component {
|
|
|
5703
5796
|
window.removeEventListener("resize", this._onResize);
|
|
5704
5797
|
}
|
|
5705
5798
|
render() {
|
|
5706
|
-
|
|
5799
|
+
const {
|
|
5707
5800
|
children,
|
|
5708
5801
|
echoes,
|
|
5709
5802
|
removeEcho,
|
|
@@ -5713,12 +5806,12 @@ class Keypad extends React.Component {
|
|
|
5713
5806
|
|
|
5714
5807
|
// Translate the echo boxes, as they'll be positioned absolutely to
|
|
5715
5808
|
// this relative container.
|
|
5716
|
-
|
|
5717
|
-
|
|
5809
|
+
const relativeEchoes = echoes.map(echo => {
|
|
5810
|
+
const {
|
|
5718
5811
|
initialBounds
|
|
5719
5812
|
} = echo,
|
|
5720
|
-
rest =
|
|
5721
|
-
return
|
|
5813
|
+
rest = _objectWithoutPropertiesLoose(echo, _excluded$1);
|
|
5814
|
+
return _extends({}, rest, {
|
|
5722
5815
|
initialBounds: {
|
|
5723
5816
|
top: initialBounds.top - this._container.top,
|
|
5724
5817
|
right: initialBounds.right - this._container.left,
|
|
@@ -5733,7 +5826,7 @@ class Keypad extends React.Component {
|
|
|
5733
5826
|
// Translate the popover bounds from page-absolute to keypad-relative.
|
|
5734
5827
|
// Note that we only need three bounds, since popovers are anchored to
|
|
5735
5828
|
// the bottom left corners of the keys over which they appear.
|
|
5736
|
-
|
|
5829
|
+
const relativePopover = popover && _extends({}, popover, {
|
|
5737
5830
|
bounds: {
|
|
5738
5831
|
bottom: this._container.height - (popover.bounds.bottom - this._container.top),
|
|
5739
5832
|
left: popover.bounds.left - this._container.left,
|
|
@@ -5750,7 +5843,7 @@ class Keypad extends React.Component {
|
|
|
5750
5843
|
}));
|
|
5751
5844
|
}
|
|
5752
5845
|
}
|
|
5753
|
-
|
|
5846
|
+
Keypad.propTypes = {
|
|
5754
5847
|
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
|
|
5755
5848
|
removeEcho: PropTypes.func.isRequired,
|
|
5756
5849
|
style: PropTypes.any,
|
|
@@ -5761,14 +5854,14 @@ _defineProperty(Keypad, "propTypes", {
|
|
|
5761
5854
|
active: PropTypes.bool,
|
|
5762
5855
|
echoes: PropTypes.arrayOf(echoPropType).isRequired,
|
|
5763
5856
|
popover: popoverPropType
|
|
5764
|
-
}
|
|
5765
|
-
|
|
5766
|
-
return
|
|
5857
|
+
};
|
|
5858
|
+
const mapStateToProps$4 = state => {
|
|
5859
|
+
return _extends({}, state.echoes, {
|
|
5767
5860
|
active: state.keypad.active,
|
|
5768
5861
|
popover: state.gestures.popover
|
|
5769
5862
|
});
|
|
5770
5863
|
};
|
|
5771
|
-
|
|
5864
|
+
const mapDispatchToProps$1 = dispatch => {
|
|
5772
5865
|
return {
|
|
5773
5866
|
removeEcho: animationId => {
|
|
5774
5867
|
dispatch(removeEcho(animationId));
|
|
@@ -5779,11 +5872,10 @@ var Keypad$1 = connect(mapStateToProps$4, mapDispatchToProps$1, null, {
|
|
|
5779
5872
|
forwardRef: true
|
|
5780
5873
|
})(Keypad);
|
|
5781
5874
|
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
} = _ref;
|
|
5875
|
+
const IconAsset = function IconAsset({
|
|
5876
|
+
tintColor,
|
|
5877
|
+
type
|
|
5878
|
+
}) {
|
|
5787
5879
|
if (type === "Geometry") {
|
|
5788
5880
|
return /*#__PURE__*/React.createElement("svg", {
|
|
5789
5881
|
width: "32",
|
|
@@ -5827,19 +5919,19 @@ var IconAsset = function IconAsset(_ref) {
|
|
|
5827
5919
|
throw new Error("Invalid icon type");
|
|
5828
5920
|
};
|
|
5829
5921
|
|
|
5830
|
-
|
|
5922
|
+
const styles$5 = StyleSheet.create({
|
|
5831
5923
|
base: {
|
|
5832
5924
|
display: "flex",
|
|
5833
5925
|
width: 44,
|
|
5834
5926
|
height: 38,
|
|
5835
5927
|
boxSizing: "border-box",
|
|
5836
5928
|
borderRadius: 3,
|
|
5837
|
-
border:
|
|
5929
|
+
border: `1px solid transparent`,
|
|
5838
5930
|
marginRight: 1,
|
|
5839
5931
|
marginLeft: 1
|
|
5840
5932
|
},
|
|
5841
5933
|
hovered: {
|
|
5842
|
-
background:
|
|
5934
|
+
background: `linear-gradient(0deg, rgba(24, 101, 242, 0.32), rgba(24, 101, 242, 0.32)), ${Color.white}`,
|
|
5843
5935
|
border: "1px solid #1865F2"
|
|
5844
5936
|
},
|
|
5845
5937
|
pressed: {
|
|
@@ -5847,11 +5939,11 @@ var styles$5 = StyleSheet.create({
|
|
|
5847
5939
|
},
|
|
5848
5940
|
focused: {
|
|
5849
5941
|
outline: "none",
|
|
5850
|
-
border:
|
|
5942
|
+
border: `2px solid ${Color.blue}`
|
|
5851
5943
|
},
|
|
5852
5944
|
innerBox: {
|
|
5853
5945
|
boxSizing: "border-box",
|
|
5854
|
-
border:
|
|
5946
|
+
border: `1px solid transparent`,
|
|
5855
5947
|
borderRadius: 2,
|
|
5856
5948
|
display: "flex",
|
|
5857
5949
|
flex: 1,
|
|
@@ -5859,7 +5951,7 @@ var styles$5 = StyleSheet.create({
|
|
|
5859
5951
|
alignItems: "center"
|
|
5860
5952
|
},
|
|
5861
5953
|
innerBoxPressed: {
|
|
5862
|
-
border:
|
|
5954
|
+
border: `1px solid ${Color.white}`
|
|
5863
5955
|
},
|
|
5864
5956
|
activeIndicator: {
|
|
5865
5957
|
position: "absolute",
|
|
@@ -5884,7 +5976,7 @@ function imageTintColor(itemState, hovered, focused, pressed) {
|
|
|
5884
5976
|
}
|
|
5885
5977
|
class TabbarItem extends React.Component {
|
|
5886
5978
|
render() {
|
|
5887
|
-
|
|
5979
|
+
const {
|
|
5888
5980
|
onClick,
|
|
5889
5981
|
itemType,
|
|
5890
5982
|
itemState
|
|
@@ -5892,13 +5984,12 @@ class TabbarItem extends React.Component {
|
|
|
5892
5984
|
return /*#__PURE__*/React.createElement(Clickable, {
|
|
5893
5985
|
onClick: onClick,
|
|
5894
5986
|
disabled: itemState === "disabled"
|
|
5895
|
-
},
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
var tintColor = imageTintColor(itemState, hovered, focused, pressed);
|
|
5987
|
+
}, ({
|
|
5988
|
+
hovered,
|
|
5989
|
+
focused,
|
|
5990
|
+
pressed
|
|
5991
|
+
}) => {
|
|
5992
|
+
const tintColor = imageTintColor(itemState, hovered, focused, pressed);
|
|
5902
5993
|
return /*#__PURE__*/React.createElement(View$1, {
|
|
5903
5994
|
style: [styles$5.base, itemState !== "disabled" && hovered && styles$5.hovered, focused && styles$5.focused, pressed && styles$5.pressed]
|
|
5904
5995
|
}, /*#__PURE__*/React.createElement(View$1, {
|
|
@@ -5915,33 +6006,33 @@ class TabbarItem extends React.Component {
|
|
|
5915
6006
|
}
|
|
5916
6007
|
}
|
|
5917
6008
|
|
|
5918
|
-
|
|
6009
|
+
const styles$4 = StyleSheet.create({
|
|
5919
6010
|
tabbar: {
|
|
5920
6011
|
display: "flex",
|
|
5921
6012
|
flexDirection: "row",
|
|
5922
6013
|
background: Color.offWhite,
|
|
5923
6014
|
paddingTop: 2,
|
|
5924
6015
|
paddingBottom: 2,
|
|
5925
|
-
borderTop:
|
|
5926
|
-
borderBottom:
|
|
6016
|
+
borderTop: `1px solid ${Color.offBlack50}`,
|
|
6017
|
+
borderBottom: `1px solid ${Color.offBlack50}`
|
|
5927
6018
|
}
|
|
5928
6019
|
});
|
|
5929
6020
|
class Tabbar extends React.Component {
|
|
5930
|
-
constructor() {
|
|
5931
|
-
super(...
|
|
5932
|
-
|
|
6021
|
+
constructor(...args) {
|
|
6022
|
+
super(...args);
|
|
6023
|
+
this.state = {
|
|
5933
6024
|
selectedItem: 0
|
|
5934
|
-
}
|
|
6025
|
+
};
|
|
5935
6026
|
}
|
|
5936
6027
|
render() {
|
|
5937
|
-
|
|
6028
|
+
const {
|
|
5938
6029
|
items,
|
|
5939
6030
|
onSelect
|
|
5940
6031
|
} = this.props;
|
|
5941
6032
|
return /*#__PURE__*/React.createElement(View$1, {
|
|
5942
6033
|
style: styles$4.tabbar
|
|
5943
6034
|
}, items.map((item, index) => /*#__PURE__*/React.createElement(TabbarItem, {
|
|
5944
|
-
key:
|
|
6035
|
+
key: `tabbar-item-${index}`,
|
|
5945
6036
|
itemState: index === this.state.selectedItem ? "active" : "inactive",
|
|
5946
6037
|
itemType: item,
|
|
5947
6038
|
onClick: () => {
|
|
@@ -5954,25 +6045,28 @@ class Tabbar extends React.Component {
|
|
|
5954
6045
|
}
|
|
5955
6046
|
}
|
|
5956
6047
|
|
|
5957
|
-
|
|
6048
|
+
/**
|
|
6049
|
+
* A keypad with two pages of keys.
|
|
6050
|
+
*/
|
|
6051
|
+
const {
|
|
5958
6052
|
column: column$2,
|
|
5959
6053
|
row: row$4,
|
|
5960
6054
|
fullWidth: fullWidth$2
|
|
5961
6055
|
} = Styles;
|
|
5962
6056
|
class TwoPageKeypad extends React.Component {
|
|
5963
|
-
constructor() {
|
|
5964
|
-
super(...
|
|
5965
|
-
|
|
6057
|
+
constructor(...args) {
|
|
6058
|
+
super(...args);
|
|
6059
|
+
this.state = {
|
|
5966
6060
|
selectedPage: "Numbers"
|
|
5967
|
-
}
|
|
6061
|
+
};
|
|
5968
6062
|
}
|
|
5969
6063
|
render() {
|
|
5970
|
-
|
|
6064
|
+
const {
|
|
5971
6065
|
leftPage,
|
|
5972
6066
|
paginationEnabled,
|
|
5973
6067
|
rightPage
|
|
5974
6068
|
} = this.props;
|
|
5975
|
-
|
|
6069
|
+
const {
|
|
5976
6070
|
selectedPage
|
|
5977
6071
|
} = this.state;
|
|
5978
6072
|
if (paginationEnabled) {
|
|
@@ -6001,27 +6095,27 @@ class TwoPageKeypad extends React.Component {
|
|
|
6001
6095
|
}
|
|
6002
6096
|
}
|
|
6003
6097
|
}
|
|
6004
|
-
|
|
6098
|
+
TwoPageKeypad.propTypes = {
|
|
6005
6099
|
currentPage: PropTypes.oneOf([0, 1]).isRequired,
|
|
6006
6100
|
leftPage: PropTypes.node.isRequired,
|
|
6007
6101
|
paginationEnabled: PropTypes.bool.isRequired,
|
|
6008
6102
|
rightPage: PropTypes.node.isRequired
|
|
6009
|
-
}
|
|
6010
|
-
|
|
6103
|
+
};
|
|
6104
|
+
const styles$3 = StyleSheet.create({
|
|
6011
6105
|
keypad: {
|
|
6012
6106
|
// Set the background to light grey, so that when the user drags the
|
|
6013
6107
|
// keypad pages past the edges, there's a grey backdrop.
|
|
6014
6108
|
backgroundColor: offBlack16
|
|
6015
6109
|
},
|
|
6016
6110
|
borderTop: {
|
|
6017
|
-
borderTop:
|
|
6111
|
+
borderTop: `${innerBorderWidthPx}px ${innerBorderStyle} ` + `${innerBorderColor}`
|
|
6018
6112
|
},
|
|
6019
6113
|
borderLeft: {
|
|
6020
|
-
borderLeft:
|
|
6114
|
+
borderLeft: `${innerBorderWidthPx}px ${innerBorderStyle} ` + `${innerBorderColor}`,
|
|
6021
6115
|
boxSizing: "content-box"
|
|
6022
6116
|
}
|
|
6023
6117
|
});
|
|
6024
|
-
|
|
6118
|
+
const mapStateToProps$3 = state => {
|
|
6025
6119
|
return {
|
|
6026
6120
|
paginationEnabled: state.layout.paginationEnabled
|
|
6027
6121
|
};
|
|
@@ -6030,7 +6124,10 @@ var TwoPageKeypad$1 = connect(mapStateToProps$3, null, null, {
|
|
|
6030
6124
|
forwardRef: true
|
|
6031
6125
|
})(TwoPageKeypad);
|
|
6032
6126
|
|
|
6033
|
-
|
|
6127
|
+
/**
|
|
6128
|
+
* A keypad that includes all of the expression symbols.
|
|
6129
|
+
*/
|
|
6130
|
+
const {
|
|
6034
6131
|
row: row$3,
|
|
6035
6132
|
column: column$1,
|
|
6036
6133
|
oneColumn,
|
|
@@ -6044,7 +6141,7 @@ class ExpressionKeypad extends React.Component {
|
|
|
6044
6141
|
// contains more than four children.
|
|
6045
6142
|
|
|
6046
6143
|
render() {
|
|
6047
|
-
|
|
6144
|
+
const {
|
|
6048
6145
|
currentPage,
|
|
6049
6146
|
cursorContext,
|
|
6050
6147
|
dynamicJumpOut,
|
|
@@ -6052,7 +6149,7 @@ class ExpressionKeypad extends React.Component {
|
|
|
6052
6149
|
roundTopLeft,
|
|
6053
6150
|
roundTopRight
|
|
6054
6151
|
} = this.props;
|
|
6055
|
-
|
|
6152
|
+
let dismissOrJumpOutKey;
|
|
6056
6153
|
if (dynamicJumpOut) {
|
|
6057
6154
|
switch (cursorContext) {
|
|
6058
6155
|
case IN_PARENS:
|
|
@@ -6081,8 +6178,8 @@ class ExpressionKeypad extends React.Component {
|
|
|
6081
6178
|
} else {
|
|
6082
6179
|
dismissOrJumpOutKey = KeyConfigs.DISMISS;
|
|
6083
6180
|
}
|
|
6084
|
-
|
|
6085
|
-
|
|
6181
|
+
const rightPageStyle = [row$3, fullWidth$1, styles$2.rightPage, roundTopRight && roundedTopRight$1];
|
|
6182
|
+
const rightPage = /*#__PURE__*/React.createElement(View, {
|
|
6086
6183
|
style: rightPageStyle
|
|
6087
6184
|
}, /*#__PURE__*/React.createElement(View, {
|
|
6088
6185
|
style: [column$1, oneColumn]
|
|
@@ -6154,8 +6251,8 @@ class ExpressionKeypad extends React.Component {
|
|
|
6154
6251
|
keyConfig: dismissOrJumpOutKey,
|
|
6155
6252
|
borders: BorderStyles.LEFT
|
|
6156
6253
|
})));
|
|
6157
|
-
|
|
6158
|
-
|
|
6254
|
+
const leftPageStyle = [row$3, fullWidth$1, styles$2.leftPage, roundTopLeft && roundedTopLeft$2];
|
|
6255
|
+
const leftPage = /*#__PURE__*/React.createElement(View, {
|
|
6159
6256
|
style: leftPageStyle
|
|
6160
6257
|
}, /*#__PURE__*/React.createElement(View, {
|
|
6161
6258
|
style: [column$1, oneColumn]
|
|
@@ -6235,19 +6332,19 @@ class ExpressionKeypad extends React.Component {
|
|
|
6235
6332
|
});
|
|
6236
6333
|
}
|
|
6237
6334
|
}
|
|
6238
|
-
|
|
6335
|
+
ExpressionKeypad.propTypes = {
|
|
6239
6336
|
currentPage: PropTypes.number.isRequired,
|
|
6240
6337
|
cursorContext: cursorContextPropType.isRequired,
|
|
6241
6338
|
dynamicJumpOut: PropTypes.bool,
|
|
6242
6339
|
extraKeys: PropTypes.arrayOf(keyIdPropType),
|
|
6243
6340
|
roundTopLeft: PropTypes.bool,
|
|
6244
6341
|
roundTopRight: PropTypes.bool
|
|
6245
|
-
}
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6342
|
+
};
|
|
6343
|
+
ExpressionKeypad.rows = 4;
|
|
6344
|
+
ExpressionKeypad.columns = 5;
|
|
6345
|
+
ExpressionKeypad.maxVisibleRows = 4;
|
|
6346
|
+
ExpressionKeypad.numPages = 2;
|
|
6347
|
+
const styles$2 = StyleSheet.create({
|
|
6251
6348
|
// NOTE(charlie): These backgrounds are applied to as to fill in some
|
|
6252
6349
|
// unfortunate 'cracks' in the layout. However, not all keys in the first
|
|
6253
6350
|
// page use this background color (namely, the 'command' keys, backspace and
|
|
@@ -6260,7 +6357,7 @@ var styles$2 = StyleSheet.create({
|
|
|
6260
6357
|
backgroundColor: controlGrey
|
|
6261
6358
|
}
|
|
6262
6359
|
});
|
|
6263
|
-
|
|
6360
|
+
const mapStateToProps$2 = state => {
|
|
6264
6361
|
return {
|
|
6265
6362
|
currentPage: state.pager.currentPage,
|
|
6266
6363
|
cursorContext: state.input.cursor.context,
|
|
@@ -6271,7 +6368,11 @@ var ExpressionKeypad$1 = connect(mapStateToProps$2, null, null, {
|
|
|
6271
6368
|
forwardRef: true
|
|
6272
6369
|
})(ExpressionKeypad);
|
|
6273
6370
|
|
|
6274
|
-
|
|
6371
|
+
/**
|
|
6372
|
+
* A keypad that includes the digits, as well as the symbols required to deal
|
|
6373
|
+
* with fractions, decimals, and percents.
|
|
6374
|
+
*/
|
|
6375
|
+
const {
|
|
6275
6376
|
row: row$2,
|
|
6276
6377
|
roundedTopLeft: roundedTopLeft$1,
|
|
6277
6378
|
roundedTopRight
|
|
@@ -6282,13 +6383,13 @@ class FractionKeypad extends React.Component {
|
|
|
6282
6383
|
// rows vertically.
|
|
6283
6384
|
|
|
6284
6385
|
render() {
|
|
6285
|
-
|
|
6386
|
+
const {
|
|
6286
6387
|
cursorContext,
|
|
6287
6388
|
dynamicJumpOut,
|
|
6288
6389
|
roundTopLeft,
|
|
6289
6390
|
roundTopRight
|
|
6290
6391
|
} = this.props;
|
|
6291
|
-
|
|
6392
|
+
let dismissOrJumpOutKey;
|
|
6292
6393
|
if (dynamicJumpOut) {
|
|
6293
6394
|
switch (cursorContext) {
|
|
6294
6395
|
case IN_PARENS:
|
|
@@ -6384,17 +6485,17 @@ class FractionKeypad extends React.Component {
|
|
|
6384
6485
|
})));
|
|
6385
6486
|
}
|
|
6386
6487
|
}
|
|
6387
|
-
|
|
6488
|
+
FractionKeypad.propTypes = {
|
|
6388
6489
|
cursorContext: cursorContextPropType.isRequired,
|
|
6389
6490
|
dynamicJumpOut: PropTypes.bool,
|
|
6390
6491
|
roundTopLeft: PropTypes.bool,
|
|
6391
6492
|
roundTopRight: PropTypes.bool
|
|
6392
|
-
}
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6493
|
+
};
|
|
6494
|
+
FractionKeypad.rows = 4;
|
|
6495
|
+
FractionKeypad.columns = 4;
|
|
6496
|
+
FractionKeypad.maxVisibleRows = 5;
|
|
6497
|
+
FractionKeypad.numPages = 1;
|
|
6498
|
+
const mapStateToProps$1 = state => {
|
|
6398
6499
|
return {
|
|
6399
6500
|
cursorContext: state.input.cursor.context,
|
|
6400
6501
|
dynamicJumpOut: !state.layout.navigationPadEnabled
|
|
@@ -6406,7 +6507,7 @@ var FractionKeypad$1 = connect(mapStateToProps$1, null, null, {
|
|
|
6406
6507
|
|
|
6407
6508
|
class VelocityTracker {
|
|
6408
6509
|
constructor(options) {
|
|
6409
|
-
this.options =
|
|
6510
|
+
this.options = _extends({
|
|
6410
6511
|
velocityTimeout: 100
|
|
6411
6512
|
}, options);
|
|
6412
6513
|
this._events = [];
|
|
@@ -6439,13 +6540,13 @@ class VelocityTracker {
|
|
|
6439
6540
|
* @returns {number} the velocity associated with the tracker
|
|
6440
6541
|
*/
|
|
6441
6542
|
getVelocity() {
|
|
6442
|
-
|
|
6543
|
+
const events = this._getEvents();
|
|
6443
6544
|
if (events.length < 2) {
|
|
6444
6545
|
return 0;
|
|
6445
6546
|
} else {
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6547
|
+
const current = events[events.length - 1];
|
|
6548
|
+
const first = events[0];
|
|
6549
|
+
const dt = current.t - first.t;
|
|
6449
6550
|
return (current.x - first.x) / dt;
|
|
6450
6551
|
}
|
|
6451
6552
|
}
|
|
@@ -6459,8 +6560,8 @@ class VelocityTracker {
|
|
|
6459
6560
|
* milliseconds
|
|
6460
6561
|
*/
|
|
6461
6562
|
_getEvents() {
|
|
6462
|
-
|
|
6463
|
-
|
|
6563
|
+
const threshold = now() - this.options.velocityTimeout;
|
|
6564
|
+
const recentEvents = this._events.filter(event => {
|
|
6464
6565
|
return event.t > threshold;
|
|
6465
6566
|
});
|
|
6466
6567
|
this._events = [];
|
|
@@ -6468,32 +6569,30 @@ class VelocityTracker {
|
|
|
6468
6569
|
}
|
|
6469
6570
|
}
|
|
6470
6571
|
|
|
6471
|
-
|
|
6572
|
+
const keypadForType = {
|
|
6472
6573
|
[KeypadTypes.FRACTION]: FractionKeypad$1,
|
|
6473
6574
|
[KeypadTypes.EXPRESSION]: ExpressionKeypad$1
|
|
6474
6575
|
};
|
|
6475
|
-
|
|
6476
|
-
|
|
6576
|
+
const createStore = () => {
|
|
6577
|
+
const initialInputState = {
|
|
6477
6578
|
keyHandler: null,
|
|
6478
6579
|
cursor: {
|
|
6479
6580
|
context: NONE
|
|
6480
6581
|
}
|
|
6481
6582
|
};
|
|
6482
|
-
|
|
6483
|
-
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialInputState;
|
|
6484
|
-
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
6583
|
+
const inputReducer = function inputReducer(state = initialInputState, action) {
|
|
6485
6584
|
switch (action.type) {
|
|
6486
6585
|
case "SetKeyHandler":
|
|
6487
|
-
return
|
|
6586
|
+
return _extends({}, state, {
|
|
6488
6587
|
keyHandler: action.keyHandler
|
|
6489
6588
|
});
|
|
6490
6589
|
case "PressKey":
|
|
6491
|
-
|
|
6590
|
+
const keyConfig = KeyConfigs[action.key];
|
|
6492
6591
|
if (keyConfig.type !== KeyTypes.KEYPAD_NAVIGATION) {
|
|
6493
6592
|
// This is probably an anti-pattern but it works for the
|
|
6494
6593
|
// case where we don't actually control the state but we
|
|
6495
6594
|
// still want to communicate with the other object
|
|
6496
|
-
return
|
|
6595
|
+
return _extends({}, state, {
|
|
6497
6596
|
cursor: state.keyHandler(keyConfig.id)
|
|
6498
6597
|
});
|
|
6499
6598
|
}
|
|
@@ -6501,39 +6600,37 @@ var createStore = () => {
|
|
|
6501
6600
|
// TODO(kevinb) get state from MathQuill and store it?
|
|
6502
6601
|
return state;
|
|
6503
6602
|
case "SetCursor":
|
|
6504
|
-
return
|
|
6603
|
+
return _extends({}, state, {
|
|
6505
6604
|
cursor: action.cursor
|
|
6506
6605
|
});
|
|
6507
6606
|
default:
|
|
6508
6607
|
return state;
|
|
6509
6608
|
}
|
|
6510
6609
|
};
|
|
6511
|
-
|
|
6512
|
-
|
|
6610
|
+
const defaultKeypadType = KeypadTypes.EXPRESSION;
|
|
6611
|
+
const initialKeypadState = {
|
|
6513
6612
|
extraKeys: ["x", "y", Keys.THETA, Keys.PI],
|
|
6514
6613
|
keypadType: defaultKeypadType,
|
|
6515
6614
|
active: false
|
|
6516
6615
|
};
|
|
6517
|
-
|
|
6518
|
-
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialKeypadState;
|
|
6519
|
-
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
6616
|
+
const keypadReducer = function keypadReducer(state = initialKeypadState, action) {
|
|
6520
6617
|
switch (action.type) {
|
|
6521
6618
|
case "DismissKeypad":
|
|
6522
|
-
return
|
|
6619
|
+
return _extends({}, state, {
|
|
6523
6620
|
active: false
|
|
6524
6621
|
});
|
|
6525
6622
|
case "ActivateKeypad":
|
|
6526
|
-
return
|
|
6623
|
+
return _extends({}, state, {
|
|
6527
6624
|
active: true
|
|
6528
6625
|
});
|
|
6529
6626
|
case "ConfigureKeypad":
|
|
6530
|
-
return
|
|
6627
|
+
return _extends({}, state, {
|
|
6531
6628
|
// Default `extraKeys` to the empty array.
|
|
6532
6629
|
extraKeys: []
|
|
6533
6630
|
}, action.configuration);
|
|
6534
6631
|
case "PressKey":
|
|
6535
6632
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'key' does not exist on type '{ type: string; }'.
|
|
6536
|
-
|
|
6633
|
+
const keyConfig = KeyConfigs[action.key];
|
|
6537
6634
|
// NOTE(charlie): Our keypad system operates by triggering key
|
|
6538
6635
|
// presses with key IDs in a dumb manner, such that the keys
|
|
6539
6636
|
// don't know what they can do--instead, the store is
|
|
@@ -6555,8 +6652,8 @@ var createStore = () => {
|
|
|
6555
6652
|
// We default to the right-most page. This is done so-as to enforce a
|
|
6556
6653
|
// consistent orientation between the view pager layout and the flattened
|
|
6557
6654
|
// layout, where our default page appears on the far right.
|
|
6558
|
-
|
|
6559
|
-
|
|
6655
|
+
const getDefaultPage = numPages => numPages - 1;
|
|
6656
|
+
const initialPagerState = {
|
|
6560
6657
|
animateToPosition: false,
|
|
6561
6658
|
currentPage: getDefaultPage(keypadForType[defaultKeypadType].numPages),
|
|
6562
6659
|
// The cumulative differential in the horizontal direction for the
|
|
@@ -6566,32 +6663,30 @@ var createStore = () => {
|
|
|
6566
6663
|
pageWidthPx: 0,
|
|
6567
6664
|
velocityTracker: new VelocityTracker()
|
|
6568
6665
|
};
|
|
6569
|
-
|
|
6570
|
-
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialPagerState;
|
|
6571
|
-
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
6666
|
+
const pagerReducer = function pagerReducer(state = initialPagerState, action) {
|
|
6572
6667
|
switch (action.type) {
|
|
6573
6668
|
case "ConfigureKeypad":
|
|
6574
6669
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'configuration' does not exist on type '{ type: string; }'.
|
|
6575
|
-
|
|
6670
|
+
const {
|
|
6576
6671
|
keypadType
|
|
6577
6672
|
} = action.configuration;
|
|
6578
|
-
|
|
6673
|
+
const {
|
|
6579
6674
|
numPages
|
|
6580
6675
|
} = keypadForType[keypadType];
|
|
6581
|
-
return
|
|
6676
|
+
return _extends({}, state, {
|
|
6582
6677
|
numPages,
|
|
6583
6678
|
animateToPosition: false,
|
|
6584
6679
|
currentPage: getDefaultPage(numPages),
|
|
6585
6680
|
dx: 0
|
|
6586
6681
|
});
|
|
6587
6682
|
case "SetPageSize":
|
|
6588
|
-
return
|
|
6683
|
+
return _extends({}, state, {
|
|
6589
6684
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'pageWidthPx' does not exist on type '{ type: string; }'.
|
|
6590
6685
|
pageWidthPx: action.pageWidthPx
|
|
6591
6686
|
});
|
|
6592
6687
|
case "PressKey":
|
|
6593
6688
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'key' does not exist on type '{ type: string; }'.
|
|
6594
|
-
|
|
6689
|
+
const keyConfig = KeyConfigs[action.key];
|
|
6595
6690
|
|
|
6596
6691
|
// Reset the keypad page if the user performs a math operation.
|
|
6597
6692
|
if (keyConfig.type === KeyTypes.VALUE || keyConfig.type === KeyTypes.OPERATOR) {
|
|
@@ -6601,22 +6696,22 @@ var createStore = () => {
|
|
|
6601
6696
|
}
|
|
6602
6697
|
return state;
|
|
6603
6698
|
case "ResetKeypadPage":
|
|
6604
|
-
return
|
|
6699
|
+
return _extends({}, state, {
|
|
6605
6700
|
animateToPosition: true,
|
|
6606
6701
|
// We start at the right-most page.
|
|
6607
6702
|
currentPage: getDefaultPage(state.numPages),
|
|
6608
6703
|
dx: 0
|
|
6609
6704
|
});
|
|
6610
6705
|
case "PageKeypadRight":
|
|
6611
|
-
|
|
6612
|
-
return
|
|
6706
|
+
const nextPage = Math.min(state.currentPage + 1, state.numPages - 1);
|
|
6707
|
+
return _extends({}, state, {
|
|
6613
6708
|
animateToPosition: true,
|
|
6614
6709
|
currentPage: nextPage,
|
|
6615
6710
|
dx: 0
|
|
6616
6711
|
});
|
|
6617
6712
|
case "PageKeypadLeft":
|
|
6618
|
-
|
|
6619
|
-
return
|
|
6713
|
+
const prevPage = Math.max(state.currentPage - 1, 0);
|
|
6714
|
+
return _extends({}, state, {
|
|
6620
6715
|
animateToPosition: true,
|
|
6621
6716
|
currentPage: prevPage,
|
|
6622
6717
|
dx: 0
|
|
@@ -6624,28 +6719,28 @@ var createStore = () => {
|
|
|
6624
6719
|
case "OnSwipeChange":
|
|
6625
6720
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'dx' does not exist on type '{ type: string; }'.
|
|
6626
6721
|
state.velocityTracker.push(action.dx);
|
|
6627
|
-
return
|
|
6722
|
+
return _extends({}, state, {
|
|
6628
6723
|
animateToPosition: false,
|
|
6629
6724
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'dx' does not exist on type '{ type: string; }'.
|
|
6630
6725
|
dx: action.dx
|
|
6631
6726
|
});
|
|
6632
6727
|
case "OnSwipeEnd":
|
|
6633
|
-
|
|
6728
|
+
const {
|
|
6634
6729
|
pageWidthPx,
|
|
6635
6730
|
velocityTracker
|
|
6636
6731
|
} = state;
|
|
6637
6732
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'dx' does not exist on type '{ type: string; }'.
|
|
6638
|
-
|
|
6733
|
+
const {
|
|
6639
6734
|
dx
|
|
6640
6735
|
} = action;
|
|
6641
|
-
|
|
6736
|
+
const velocity = velocityTracker.getVelocity();
|
|
6642
6737
|
|
|
6643
6738
|
// NOTE(charlie): These will need refinement. The velocity comes
|
|
6644
6739
|
// from Framer.
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6740
|
+
const minFlingVelocity = 0.1;
|
|
6741
|
+
const minFlingDistance = 10;
|
|
6742
|
+
const shouldPageRight = dx < -pageWidthPx / 2 || velocity < -minFlingVelocity && dx < -minFlingDistance;
|
|
6743
|
+
const shouldPageLeft = dx > pageWidthPx / 2 || velocity > minFlingVelocity && dx > minFlingDistance;
|
|
6649
6744
|
if (shouldPageRight) {
|
|
6650
6745
|
return pagerReducer(state, {
|
|
6651
6746
|
type: "PageKeypadRight"
|
|
@@ -6655,7 +6750,7 @@ var createStore = () => {
|
|
|
6655
6750
|
type: "PageKeypadLeft"
|
|
6656
6751
|
});
|
|
6657
6752
|
}
|
|
6658
|
-
return
|
|
6753
|
+
return _extends({}, state, {
|
|
6659
6754
|
animateToPosition: true,
|
|
6660
6755
|
dx: 0
|
|
6661
6756
|
});
|
|
@@ -6663,7 +6758,7 @@ var createStore = () => {
|
|
|
6663
6758
|
return state;
|
|
6664
6759
|
}
|
|
6665
6760
|
};
|
|
6666
|
-
|
|
6761
|
+
const createGestureManager = swipeEnabled => {
|
|
6667
6762
|
return new GestureManager({
|
|
6668
6763
|
swipeEnabled
|
|
6669
6764
|
}, {
|
|
@@ -6686,23 +6781,21 @@ var createStore = () => {
|
|
|
6686
6781
|
});
|
|
6687
6782
|
},
|
|
6688
6783
|
onClick: (key, layoutProps, inPopover) => {
|
|
6689
|
-
store.dispatch(
|
|
6784
|
+
store.dispatch(_extends({
|
|
6690
6785
|
type: "PressKey",
|
|
6691
6786
|
key
|
|
6692
|
-
}, layoutProps
|
|
6787
|
+
}, layoutProps, {
|
|
6693
6788
|
inPopover
|
|
6694
6789
|
}));
|
|
6695
6790
|
}
|
|
6696
6791
|
}, [], [Keys.BACKSPACE, Keys.UP, Keys.RIGHT, Keys.DOWN, Keys.LEFT]);
|
|
6697
6792
|
};
|
|
6698
|
-
|
|
6793
|
+
const initialGestureState = {
|
|
6699
6794
|
popover: null,
|
|
6700
6795
|
focus: null,
|
|
6701
6796
|
gestureManager: createGestureManager(keypadForType[defaultKeypadType].numPages > 1)
|
|
6702
6797
|
};
|
|
6703
|
-
|
|
6704
|
-
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialGestureState;
|
|
6705
|
-
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
6798
|
+
const gestureReducer = function gestureReducer(state = initialGestureState, action) {
|
|
6706
6799
|
switch (action.type) {
|
|
6707
6800
|
case "DismissKeypad":
|
|
6708
6801
|
// NOTE(charlie): In the past, we enforced the "gesture manager
|
|
@@ -6720,15 +6813,15 @@ var createStore = () => {
|
|
|
6720
6813
|
state.gestureManager.enableEventTracking();
|
|
6721
6814
|
return state;
|
|
6722
6815
|
case "SetActiveNodes":
|
|
6723
|
-
return
|
|
6816
|
+
return _extends({}, state, action.activeNodes);
|
|
6724
6817
|
case "ConfigureKeypad":
|
|
6725
|
-
|
|
6818
|
+
const {
|
|
6726
6819
|
keypadType
|
|
6727
6820
|
} = action.configuration;
|
|
6728
|
-
|
|
6821
|
+
const {
|
|
6729
6822
|
numPages
|
|
6730
6823
|
} = keypadForType[keypadType];
|
|
6731
|
-
|
|
6824
|
+
const swipeEnabled = numPages > 1;
|
|
6732
6825
|
return {
|
|
6733
6826
|
popover: null,
|
|
6734
6827
|
focus: null,
|
|
@@ -6741,21 +6834,19 @@ var createStore = () => {
|
|
|
6741
6834
|
|
|
6742
6835
|
// Used to generate unique animation IDs for the echo animations. The actual
|
|
6743
6836
|
// values are irrelevant as long as they are unique.
|
|
6744
|
-
|
|
6745
|
-
|
|
6837
|
+
let _lastAnimationId = 0;
|
|
6838
|
+
const initialEchoState = {
|
|
6746
6839
|
echoes: []
|
|
6747
6840
|
};
|
|
6748
|
-
|
|
6749
|
-
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialEchoState;
|
|
6750
|
-
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
6841
|
+
const echoReducer = function echoReducer(state = initialEchoState, action) {
|
|
6751
6842
|
switch (action.type) {
|
|
6752
6843
|
case "PressKey":
|
|
6753
|
-
|
|
6844
|
+
const keyConfig = KeyConfigs[action.key];
|
|
6754
6845
|
|
|
6755
6846
|
// Add in the echo animation if the user performs a math
|
|
6756
6847
|
// operation.
|
|
6757
6848
|
if (keyConfig.type === KeyTypes.VALUE || keyConfig.type === KeyTypes.OPERATOR) {
|
|
6758
|
-
return
|
|
6849
|
+
return _extends({}, state, {
|
|
6759
6850
|
echoes: [...state.echoes, {
|
|
6760
6851
|
animationId: "" + _lastAnimationId++,
|
|
6761
6852
|
animationType: action.inPopover ? EchoAnimationTypes.LONG_FADE_ONLY : EchoAnimationTypes.FADE_ONLY,
|
|
@@ -6767,18 +6858,18 @@ var createStore = () => {
|
|
|
6767
6858
|
}
|
|
6768
6859
|
return state;
|
|
6769
6860
|
case "RemoveEcho":
|
|
6770
|
-
|
|
6861
|
+
const remainingEchoes = state.echoes.filter(echo => {
|
|
6771
6862
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'animationId' does not exist on type 'never'.
|
|
6772
6863
|
return echo.animationId !== action.animationId;
|
|
6773
6864
|
});
|
|
6774
|
-
return
|
|
6865
|
+
return _extends({}, state, {
|
|
6775
6866
|
echoes: remainingEchoes
|
|
6776
6867
|
});
|
|
6777
6868
|
default:
|
|
6778
6869
|
return state;
|
|
6779
6870
|
}
|
|
6780
6871
|
};
|
|
6781
|
-
|
|
6872
|
+
const initialLayoutState = {
|
|
6782
6873
|
gridDimensions: {
|
|
6783
6874
|
numRows: keypadForType[defaultKeypadType].rows,
|
|
6784
6875
|
numColumns: keypadForType[defaultKeypadType].columns,
|
|
@@ -6802,25 +6893,25 @@ var createStore = () => {
|
|
|
6802
6893
|
* Compute the additional layout state based on the provided page and grid
|
|
6803
6894
|
* dimensions.
|
|
6804
6895
|
*/
|
|
6805
|
-
|
|
6806
|
-
|
|
6896
|
+
const layoutParametersForDimensions = (pageDimensions, gridDimensions) => {
|
|
6897
|
+
const {
|
|
6807
6898
|
pageWidthPx,
|
|
6808
6899
|
pageHeightPx
|
|
6809
6900
|
} = pageDimensions;
|
|
6810
6901
|
|
|
6811
6902
|
// Determine the device type and orientation.
|
|
6812
|
-
|
|
6813
|
-
|
|
6903
|
+
const deviceOrientation = pageWidthPx > pageHeightPx ? DeviceOrientations.LANDSCAPE : DeviceOrientations.PORTRAIT;
|
|
6904
|
+
const deviceType = Math.min(pageWidthPx, pageHeightPx) > tabletCutoffPx ? DeviceTypes.TABLET : DeviceTypes.PHONE;
|
|
6814
6905
|
|
|
6815
6906
|
// Using that information, make some decisions (or assumptions)
|
|
6816
6907
|
// about the resulting layout.
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6908
|
+
const navigationPadEnabled = deviceType === DeviceTypes.TABLET;
|
|
6909
|
+
const paginationEnabled = deviceType === DeviceTypes.PHONE && deviceOrientation === DeviceOrientations.PORTRAIT;
|
|
6910
|
+
const deviceInfo = {
|
|
6820
6911
|
deviceOrientation,
|
|
6821
6912
|
deviceType
|
|
6822
6913
|
};
|
|
6823
|
-
|
|
6914
|
+
const layoutOptions = {
|
|
6824
6915
|
navigationPadEnabled,
|
|
6825
6916
|
paginationEnabled,
|
|
6826
6917
|
// HACK(charlie): It's not great that we're making assumptions about
|
|
@@ -6832,47 +6923,45 @@ var createStore = () => {
|
|
|
6832
6923
|
// of error.
|
|
6833
6924
|
toolbarEnabled: true
|
|
6834
6925
|
};
|
|
6835
|
-
return
|
|
6926
|
+
return _extends({}, computeLayoutParameters(gridDimensions, pageDimensions, deviceInfo, layoutOptions), {
|
|
6836
6927
|
// Pass along some of the layout information, so that other
|
|
6837
6928
|
// components in the heirarchy can adapt appropriately.
|
|
6838
6929
|
navigationPadEnabled,
|
|
6839
6930
|
paginationEnabled
|
|
6840
6931
|
});
|
|
6841
6932
|
};
|
|
6842
|
-
|
|
6843
|
-
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialLayoutState;
|
|
6844
|
-
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
6933
|
+
const layoutReducer = function layoutReducer(state = initialLayoutState, action) {
|
|
6845
6934
|
switch (action.type) {
|
|
6846
6935
|
case "ConfigureKeypad":
|
|
6847
|
-
|
|
6936
|
+
const {
|
|
6848
6937
|
keypadType
|
|
6849
6938
|
} = action.configuration;
|
|
6850
|
-
|
|
6939
|
+
const gridDimensions = {
|
|
6851
6940
|
numRows: keypadForType[keypadType].rows,
|
|
6852
6941
|
numColumns: keypadForType[keypadType].columns,
|
|
6853
6942
|
numMaxVisibleRows: keypadForType[keypadType].maxVisibleRows,
|
|
6854
6943
|
numPages: keypadForType[keypadType].numPages
|
|
6855
6944
|
};
|
|
6856
|
-
return
|
|
6945
|
+
return _extends({}, state, layoutParametersForDimensions(state.pageDimensions, gridDimensions), {
|
|
6857
6946
|
gridDimensions
|
|
6858
6947
|
});
|
|
6859
6948
|
case "SetPageSize":
|
|
6860
|
-
|
|
6949
|
+
const {
|
|
6861
6950
|
pageWidthPx,
|
|
6862
6951
|
pageHeightPx
|
|
6863
6952
|
} = action;
|
|
6864
|
-
|
|
6953
|
+
const pageDimensions = {
|
|
6865
6954
|
pageWidthPx,
|
|
6866
6955
|
pageHeightPx
|
|
6867
6956
|
};
|
|
6868
|
-
return
|
|
6957
|
+
return _extends({}, state, layoutParametersForDimensions(pageDimensions, state.gridDimensions), {
|
|
6869
6958
|
pageDimensions
|
|
6870
6959
|
});
|
|
6871
6960
|
default:
|
|
6872
6961
|
return state;
|
|
6873
6962
|
}
|
|
6874
6963
|
};
|
|
6875
|
-
|
|
6964
|
+
const reducer = Redux.combineReducers({
|
|
6876
6965
|
input: inputReducer,
|
|
6877
6966
|
keypad: keypadReducer,
|
|
6878
6967
|
pager: pagerReducer,
|
|
@@ -6885,11 +6974,15 @@ var createStore = () => {
|
|
|
6885
6974
|
// gesture manager to dispatch actions on the store in its callbacks. We
|
|
6886
6975
|
// should come up with a better pattern to remove the two-way dependency.
|
|
6887
6976
|
// eslint-disable-next-line import/no-deprecated
|
|
6888
|
-
|
|
6977
|
+
const store = Redux.createStore(reducer);
|
|
6889
6978
|
return store;
|
|
6890
6979
|
};
|
|
6891
6980
|
|
|
6892
|
-
|
|
6981
|
+
/**
|
|
6982
|
+
* A component that renders a navigation pad, which consists of an arrow for
|
|
6983
|
+
* each possible direction.
|
|
6984
|
+
*/
|
|
6985
|
+
const {
|
|
6893
6986
|
row: row$1,
|
|
6894
6987
|
column,
|
|
6895
6988
|
centered: centered$1,
|
|
@@ -6900,11 +6993,11 @@ class NavigationPad extends React.Component {
|
|
|
6900
6993
|
render() {
|
|
6901
6994
|
// TODO(charlie): Disable the navigational arrows depending on the
|
|
6902
6995
|
// cursor context.
|
|
6903
|
-
|
|
6996
|
+
const {
|
|
6904
6997
|
roundTopLeft,
|
|
6905
6998
|
style
|
|
6906
6999
|
} = this.props;
|
|
6907
|
-
|
|
7000
|
+
const containerStyle = [column, centered$1, styles$1.container, roundTopLeft && roundedTopLeft, ...(Array.isArray(style) ? style : [style])];
|
|
6908
7001
|
return /*#__PURE__*/React.createElement(View, {
|
|
6909
7002
|
style: containerStyle
|
|
6910
7003
|
}, /*#__PURE__*/React.createElement(View, {
|
|
@@ -6934,14 +7027,14 @@ class NavigationPad extends React.Component {
|
|
|
6934
7027
|
})));
|
|
6935
7028
|
}
|
|
6936
7029
|
}
|
|
6937
|
-
|
|
7030
|
+
NavigationPad.propTypes = {
|
|
6938
7031
|
roundTopLeft: PropTypes.bool,
|
|
6939
7032
|
style: PropTypes.any
|
|
6940
|
-
}
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
7033
|
+
};
|
|
7034
|
+
const buttonSizePx = 48;
|
|
7035
|
+
const borderRadiusPx = 4;
|
|
7036
|
+
const borderWidthPx$1 = 1;
|
|
7037
|
+
const styles$1 = StyleSheet.create({
|
|
6945
7038
|
container: {
|
|
6946
7039
|
backgroundColor: controlGrey,
|
|
6947
7040
|
width: navigationPadWidthPx
|
|
@@ -6991,7 +7084,7 @@ var styles$1 = StyleSheet.create({
|
|
|
6991
7084
|
}
|
|
6992
7085
|
});
|
|
6993
7086
|
|
|
6994
|
-
|
|
7087
|
+
const {
|
|
6995
7088
|
row,
|
|
6996
7089
|
centered,
|
|
6997
7090
|
fullWidth
|
|
@@ -6999,13 +7092,13 @@ var {
|
|
|
6999
7092
|
|
|
7000
7093
|
// eslint-disable-next-line react/no-unsafe
|
|
7001
7094
|
class KeypadContainer extends React.Component {
|
|
7002
|
-
constructor() {
|
|
7003
|
-
super(...
|
|
7004
|
-
|
|
7095
|
+
constructor(...args) {
|
|
7096
|
+
super(...args);
|
|
7097
|
+
this.state = {
|
|
7005
7098
|
hasBeenActivated: false,
|
|
7006
7099
|
viewportWidth: "100vw"
|
|
7007
|
-
}
|
|
7008
|
-
|
|
7100
|
+
};
|
|
7101
|
+
this._throttleResizeHandler = () => {
|
|
7009
7102
|
// Throttle the resize callbacks.
|
|
7010
7103
|
// https://developer.mozilla.org/en-US/docs/Web/Events/resize
|
|
7011
7104
|
if (this._resizeTimeout == null) {
|
|
@@ -7014,23 +7107,23 @@ class KeypadContainer extends React.Component {
|
|
|
7014
7107
|
this._onResize();
|
|
7015
7108
|
}, 66);
|
|
7016
7109
|
}
|
|
7017
|
-
}
|
|
7018
|
-
|
|
7110
|
+
};
|
|
7111
|
+
this._onResize = () => {
|
|
7019
7112
|
// Whenever the page resizes, we need to force an update, as the button
|
|
7020
7113
|
// heights and keypad width are computed based on horizontal space.
|
|
7021
7114
|
this.setState({
|
|
7022
7115
|
viewportWidth: window.innerWidth
|
|
7023
7116
|
});
|
|
7024
7117
|
this.props.onPageSizeChange(window.innerWidth, window.innerHeight);
|
|
7025
|
-
}
|
|
7026
|
-
|
|
7027
|
-
|
|
7118
|
+
};
|
|
7119
|
+
this.renderKeypad = () => {
|
|
7120
|
+
const {
|
|
7028
7121
|
extraKeys,
|
|
7029
7122
|
keypadType,
|
|
7030
7123
|
layoutMode,
|
|
7031
7124
|
navigationPadEnabled
|
|
7032
7125
|
} = this.props;
|
|
7033
|
-
|
|
7126
|
+
const keypadProps = {
|
|
7034
7127
|
extraKeys,
|
|
7035
7128
|
// HACK(charlie): In order to properly round the corners of the
|
|
7036
7129
|
// compact keypad, we need to instruct some of our child views to
|
|
@@ -7055,7 +7148,7 @@ class KeypadContainer extends React.Component {
|
|
|
7055
7148
|
default:
|
|
7056
7149
|
throw new Error("Invalid keypad type: " + keypadType);
|
|
7057
7150
|
}
|
|
7058
|
-
}
|
|
7151
|
+
};
|
|
7059
7152
|
}
|
|
7060
7153
|
UNSAFE_componentWillMount() {
|
|
7061
7154
|
if (this.props.active) {
|
|
@@ -7089,23 +7182,23 @@ class KeypadContainer extends React.Component {
|
|
|
7089
7182
|
window.removeEventListener("orientationchange", this._throttleResizeHandler);
|
|
7090
7183
|
}
|
|
7091
7184
|
render() {
|
|
7092
|
-
|
|
7185
|
+
const {
|
|
7093
7186
|
active,
|
|
7094
7187
|
layoutMode,
|
|
7095
7188
|
navigationPadEnabled,
|
|
7096
7189
|
onElementMounted,
|
|
7097
7190
|
style
|
|
7098
7191
|
} = this.props;
|
|
7099
|
-
|
|
7192
|
+
const {
|
|
7100
7193
|
hasBeenActivated
|
|
7101
7194
|
} = this.state;
|
|
7102
7195
|
|
|
7103
7196
|
// NOTE(charlie): We render the transforms as pure inline styles to
|
|
7104
7197
|
// avoid an Aphrodite bug in mobile Safari.
|
|
7105
7198
|
// See: https://github.com/Khan/aphrodite/issues/68.
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7199
|
+
const dynamicStyle = _extends({}, active ? inlineStyles.active : inlineStyles.hidden, !active && !hasBeenActivated ? inlineStyles.invisible : {});
|
|
7200
|
+
const keypadContainerStyle = [row, centered, fullWidth, styles.keypadContainer, ...(Array.isArray(style) ? style : [style])];
|
|
7201
|
+
const keypadStyle = [row, styles.keypadBorder, layoutMode === LayoutModes.FULLSCREEN ? styles.fullscreen : styles.compact];
|
|
7109
7202
|
|
|
7110
7203
|
// TODO(charlie): When the keypad is shorter than the width of the
|
|
7111
7204
|
// screen, add a border on its left and right edges, and round out the
|
|
@@ -7130,7 +7223,7 @@ class KeypadContainer extends React.Component {
|
|
|
7130
7223
|
}, this.renderKeypad())));
|
|
7131
7224
|
}
|
|
7132
7225
|
}
|
|
7133
|
-
|
|
7226
|
+
KeypadContainer.propTypes = {
|
|
7134
7227
|
active: PropTypes.bool,
|
|
7135
7228
|
extraKeys: PropTypes.arrayOf(keyIdPropType),
|
|
7136
7229
|
keypadType: PropTypes.oneOf(Object.keys(KeypadTypes)).isRequired,
|
|
@@ -7142,16 +7235,16 @@ _defineProperty(KeypadContainer, "propTypes", {
|
|
|
7142
7235
|
onElementMounted: PropTypes.func,
|
|
7143
7236
|
onPageSizeChange: PropTypes.func.isRequired,
|
|
7144
7237
|
style: PropTypes.any
|
|
7145
|
-
}
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7238
|
+
};
|
|
7239
|
+
const keypadAnimationDurationMs = 300;
|
|
7240
|
+
const borderWidthPx = 1;
|
|
7241
|
+
const styles = StyleSheet.create({
|
|
7149
7242
|
keypadContainer: {
|
|
7150
7243
|
bottom: 0,
|
|
7151
7244
|
left: 0,
|
|
7152
7245
|
right: 0,
|
|
7153
7246
|
position: "fixed",
|
|
7154
|
-
transition:
|
|
7247
|
+
transition: `${keypadAnimationDurationMs}ms ease-out`,
|
|
7155
7248
|
transitionProperty: "transform",
|
|
7156
7249
|
zIndex: keypad
|
|
7157
7250
|
},
|
|
@@ -7172,7 +7265,7 @@ var styles = StyleSheet.create({
|
|
|
7172
7265
|
},
|
|
7173
7266
|
navigationPadContainer: {
|
|
7174
7267
|
// Add a separator between the navigation pad and the keypad.
|
|
7175
|
-
borderRight:
|
|
7268
|
+
borderRight: `${innerBorderWidthPx}px ${innerBorderStyle} ` + `${innerBorderColor}`,
|
|
7176
7269
|
boxSizing: "content-box"
|
|
7177
7270
|
},
|
|
7178
7271
|
// Defer to the navigation pad, such that the navigation pad is always
|
|
@@ -7187,7 +7280,7 @@ var styles = StyleSheet.create({
|
|
|
7187
7280
|
});
|
|
7188
7281
|
|
|
7189
7282
|
// Note: these don't go through an autoprefixer/aphrodite.
|
|
7190
|
-
|
|
7283
|
+
const inlineStyles = {
|
|
7191
7284
|
// If the keypad is yet to have ever been activated, we keep it invisible
|
|
7192
7285
|
// so as to avoid, e.g., the keypad flashing at the bottom of the page
|
|
7193
7286
|
// during the initial render.
|
|
@@ -7201,13 +7294,13 @@ var inlineStyles = {
|
|
|
7201
7294
|
transform: "translate3d(0, 0, 0)"
|
|
7202
7295
|
}
|
|
7203
7296
|
};
|
|
7204
|
-
|
|
7205
|
-
return
|
|
7297
|
+
const mapStateToProps = state => {
|
|
7298
|
+
return _extends({}, state.keypad, {
|
|
7206
7299
|
layoutMode: state.layout.layoutMode,
|
|
7207
7300
|
navigationPadEnabled: state.layout.navigationPadEnabled
|
|
7208
7301
|
});
|
|
7209
7302
|
};
|
|
7210
|
-
|
|
7303
|
+
const mapDispatchToProps = dispatch => {
|
|
7211
7304
|
return {
|
|
7212
7305
|
onPageSizeChange: (pageWidthPx, pageHeightPx) => {
|
|
7213
7306
|
dispatch(setPageSize(pageWidthPx, pageHeightPx));
|
|
@@ -7218,19 +7311,19 @@ var KeypadContainer$1 = connect(mapStateToProps, mapDispatchToProps, null, {
|
|
|
7218
7311
|
forwardRef: true
|
|
7219
7312
|
})(KeypadContainer);
|
|
7220
7313
|
|
|
7221
|
-
|
|
7314
|
+
const _excluded = ["onElementMounted"];
|
|
7222
7315
|
class ProvidedKeypad extends React.Component {
|
|
7223
|
-
constructor() {
|
|
7224
|
-
super(...
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7316
|
+
constructor(...args) {
|
|
7317
|
+
super(...args);
|
|
7318
|
+
this.mounted = void 0;
|
|
7319
|
+
this.store = void 0;
|
|
7320
|
+
this.activate = () => {
|
|
7228
7321
|
this.store.dispatch(activateKeypad());
|
|
7229
|
-
}
|
|
7230
|
-
|
|
7322
|
+
};
|
|
7323
|
+
this.dismiss = () => {
|
|
7231
7324
|
this.store.dispatch(dismissKeypad());
|
|
7232
|
-
}
|
|
7233
|
-
|
|
7325
|
+
};
|
|
7326
|
+
this.configure = (configuration, cb) => {
|
|
7234
7327
|
this.store.dispatch(configureKeypad(configuration));
|
|
7235
7328
|
|
|
7236
7329
|
// HACK(charlie): In Perseus, triggering a focus causes the keypad to
|
|
@@ -7241,16 +7334,16 @@ class ProvidedKeypad extends React.Component {
|
|
|
7241
7334
|
// would require middleware, etc., so we just hack it on with
|
|
7242
7335
|
// `setTimeout` for now.
|
|
7243
7336
|
setTimeout(() => cb && cb());
|
|
7244
|
-
}
|
|
7245
|
-
|
|
7337
|
+
};
|
|
7338
|
+
this.setCursor = cursor => {
|
|
7246
7339
|
this.store.dispatch(setCursor(cursor));
|
|
7247
|
-
}
|
|
7248
|
-
|
|
7340
|
+
};
|
|
7341
|
+
this.setKeyHandler = keyHandler => {
|
|
7249
7342
|
this.store.dispatch(setKeyHandler(keyHandler));
|
|
7250
|
-
}
|
|
7251
|
-
|
|
7343
|
+
};
|
|
7344
|
+
this.getDOMNode = () => {
|
|
7252
7345
|
return ReactDOM.findDOMNode(this);
|
|
7253
|
-
}
|
|
7346
|
+
};
|
|
7254
7347
|
}
|
|
7255
7348
|
UNSAFE_componentWillMount() {
|
|
7256
7349
|
this.store = createStore();
|
|
@@ -7262,18 +7355,18 @@ class ProvidedKeypad extends React.Component {
|
|
|
7262
7355
|
this.mounted = false;
|
|
7263
7356
|
}
|
|
7264
7357
|
render() {
|
|
7265
|
-
|
|
7358
|
+
const _this$props = this.props,
|
|
7266
7359
|
{
|
|
7267
|
-
onElementMounted
|
|
7360
|
+
onElementMounted
|
|
7268
7361
|
} = _this$props,
|
|
7269
|
-
rest =
|
|
7362
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded);
|
|
7270
7363
|
return /*#__PURE__*/React.createElement(Provider, {
|
|
7271
7364
|
store: this.store
|
|
7272
7365
|
}, /*#__PURE__*/React.createElement(KeypadContainer$1, _extends({
|
|
7273
7366
|
onElementMounted: element => {
|
|
7274
7367
|
// Append the dispatch methods that we want to expose
|
|
7275
7368
|
// externally to the returned React element.
|
|
7276
|
-
|
|
7369
|
+
const elementWithDispatchMethods = _extends({}, element, {
|
|
7277
7370
|
activate: this.activate,
|
|
7278
7371
|
dismiss: this.dismiss,
|
|
7279
7372
|
configure: this.configure,
|
|
@@ -7281,7 +7374,7 @@ class ProvidedKeypad extends React.Component {
|
|
|
7281
7374
|
setKeyHandler: this.setKeyHandler,
|
|
7282
7375
|
getDOMNode: this.getDOMNode
|
|
7283
7376
|
});
|
|
7284
|
-
|
|
7377
|
+
onElementMounted && onElementMounted(elementWithDispatchMethods);
|
|
7285
7378
|
}
|
|
7286
7379
|
}, rest)));
|
|
7287
7380
|
}
|