@pie-lib/math-input 6.11.5-next.0 → 6.12.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +64 -181
  2. package/NEXT.CHANGELOG.json +1 -0
  3. package/package.json +5 -2
  4. package/src/__tests__/__snapshots__/math-input-test.jsx.snap +152 -0
  5. package/src/__tests__/math-input-test.jsx +85 -0
  6. package/src/horizontal-keypad.jsx +14 -1
  7. package/src/index.jsx +1 -10
  8. package/src/keypad/__tests__/__snapshots__/index.test.jsx.snap +193 -0
  9. package/src/keypad/__tests__/index.test.jsx +24 -0
  10. package/src/keypad/__tests__/keys-layout.test.js +15 -0
  11. package/src/keypad/index.jsx +99 -15
  12. package/src/keys/__tests__/utils.test.js +57 -0
  13. package/src/keys/geometry.js +6 -2
  14. package/src/keys/grades.js +11 -0
  15. package/src/keys/log.js +1 -1
  16. package/src/mq/__tests__/__snapshots__/input.test.jsx.snap +9 -0
  17. package/src/mq/__tests__/input.test.jsx +92 -0
  18. package/src/mq/__tests__/static.test.jsx +57 -0
  19. package/src/mq/common-mq-styles.js +105 -0
  20. package/src/mq/index.js +2 -1
  21. package/src/mq/input.jsx +22 -9
  22. package/src/mq/static.jsx +142 -13
  23. package/src/updateSpans.js +15 -0
  24. package/README.md +0 -27
  25. package/lib/horizontal-keypad.js +0 -118
  26. package/lib/horizontal-keypad.js.map +0 -1
  27. package/lib/index.js +0 -80
  28. package/lib/index.js.map +0 -1
  29. package/lib/keypad/index.js +0 -441
  30. package/lib/keypad/index.js.map +0 -1
  31. package/lib/keypad/keys-layout.js +0 -34
  32. package/lib/keypad/keys-layout.js.map +0 -1
  33. package/lib/keys/basic-operators.js +0 -41
  34. package/lib/keys/basic-operators.js.map +0 -1
  35. package/lib/keys/chars.js +0 -17
  36. package/lib/keys/chars.js.map +0 -1
  37. package/lib/keys/comparison.js +0 -49
  38. package/lib/keys/comparison.js.map +0 -1
  39. package/lib/keys/constants.js +0 -43
  40. package/lib/keys/constants.js.map +0 -1
  41. package/lib/keys/digits.js +0 -53
  42. package/lib/keys/digits.js.map +0 -1
  43. package/lib/keys/edit.js +0 -17
  44. package/lib/keys/edit.js.map +0 -1
  45. package/lib/keys/exponent.js +0 -36
  46. package/lib/keys/exponent.js.map +0 -1
  47. package/lib/keys/fractions.js +0 -34
  48. package/lib/keys/fractions.js.map +0 -1
  49. package/lib/keys/geometry.js +0 -167
  50. package/lib/keys/geometry.js.map +0 -1
  51. package/lib/keys/grades.js +0 -283
  52. package/lib/keys/grades.js.map +0 -1
  53. package/lib/keys/index.js +0 -54
  54. package/lib/keys/index.js.map +0 -1
  55. package/lib/keys/log.js +0 -32
  56. package/lib/keys/log.js.map +0 -1
  57. package/lib/keys/logic.js +0 -23
  58. package/lib/keys/logic.js.map +0 -1
  59. package/lib/keys/matrices.js +0 -23
  60. package/lib/keys/matrices.js.map +0 -1
  61. package/lib/keys/misc.js +0 -74
  62. package/lib/keys/misc.js.map +0 -1
  63. package/lib/keys/navigation.js +0 -25
  64. package/lib/keys/navigation.js.map +0 -1
  65. package/lib/keys/operators.js +0 -18
  66. package/lib/keys/operators.js.map +0 -1
  67. package/lib/keys/statistics.js +0 -47
  68. package/lib/keys/statistics.js.map +0 -1
  69. package/lib/keys/sub-sup.js +0 -23
  70. package/lib/keys/sub-sup.js.map +0 -1
  71. package/lib/keys/trigonometry.js +0 -53
  72. package/lib/keys/trigonometry.js.map +0 -1
  73. package/lib/keys/utils.js +0 -120
  74. package/lib/keys/utils.js.map +0 -1
  75. package/lib/keys/vars.js +0 -29
  76. package/lib/keys/vars.js.map +0 -1
  77. package/lib/math-input.js +0 -192
  78. package/lib/math-input.js.map +0 -1
  79. package/lib/mq/custom-elements.js +0 -23
  80. package/lib/mq/custom-elements.js.map +0 -1
  81. package/lib/mq/index.js +0 -24
  82. package/lib/mq/index.js.map +0 -1
  83. package/lib/mq/input.js +0 -245
  84. package/lib/mq/input.js.map +0 -1
  85. package/lib/mq/static.js +0 -233
  86. package/lib/mq/static.js.map +0 -1
@@ -0,0 +1,85 @@
1
+ import { shallow } from 'enzyme';
2
+ import React from 'react';
3
+ import { MathInput } from '../math-input';
4
+
5
+ describe('MathInput', () => {
6
+ let w;
7
+ let onChange;
8
+
9
+ beforeEach(() => {
10
+ onChange = jest.fn();
11
+ });
12
+ const wrapper = (extras) => {
13
+ const defaults = {
14
+ classes: {},
15
+ className: 'className',
16
+ onChange,
17
+ };
18
+ const props = { ...defaults, ...extras };
19
+ return shallow(<MathInput {...props} />);
20
+ };
21
+ describe('snapshot', () => {
22
+ it('renders', () => {
23
+ w = wrapper();
24
+ expect(w).toMatchSnapshot();
25
+ });
26
+ });
27
+ describe('logic', () => {
28
+ beforeEach(() => {
29
+ w = wrapper();
30
+ w.instance().input = {
31
+ write: jest.fn(),
32
+ command: jest.fn(),
33
+ keystroke: jest.fn(),
34
+ };
35
+ });
36
+ describe('keypadPress', () => {
37
+ it('calls input.write for latex', () => {
38
+ w.instance().keypadPress({ latex: 'latex' });
39
+ expect(w.instance().input.write).toHaveBeenLastCalledWith('latex');
40
+ });
41
+ it('calls input.write for write', () => {
42
+ w.instance().keypadPress({ write: 'write' });
43
+ expect(w.instance().input.write).toHaveBeenLastCalledWith('write');
44
+ });
45
+ it('calls input.command for command', () => {
46
+ w.instance().keypadPress({ command: 'cmd' });
47
+ expect(w.instance().input.command).toHaveBeenLastCalledWith('cmd');
48
+ });
49
+ it('calls input.keystroke for keystroke', () => {
50
+ w.instance().keypadPress({ keystroke: 'k' });
51
+ expect(w.instance().input.keystroke).toHaveBeenLastCalledWith('k');
52
+ });
53
+ });
54
+ });
55
+
56
+ describe('changeLatex', () => {
57
+ it('calls onChange', () => {
58
+ w = wrapper();
59
+ w.instance().changeLatex('new-latex');
60
+ expect(onChange).toHaveBeenCalledWith('new-latex');
61
+ });
62
+ it('does not call onChange if it is the same as the existing latex', () => {
63
+ w = wrapper();
64
+ w.setProps({ latex: 'new-latex' });
65
+ w.instance().changeLatex('new-latex');
66
+ expect(onChange).not.toHaveBeenCalledWith('new-latex');
67
+ });
68
+ });
69
+
70
+ describe('inputFocus', () => {
71
+ it('sets state', () => {
72
+ w = wrapper();
73
+ w.instance().inputFocus();
74
+ expect(w.state().focused).toBe(true);
75
+ });
76
+ });
77
+ describe('inputBlur', () => {
78
+ it('sets state', () => {
79
+ w = wrapper();
80
+ w.instance().inputFocus();
81
+ w.instance().inputBlur();
82
+ expect(w.state().focused).toBe(false);
83
+ });
84
+ });
85
+ });
@@ -17,12 +17,14 @@ const toOldModel = (d) => {
17
17
  export default class HorizontalKeypad extends React.Component {
18
18
  static propTypes = {
19
19
  className: PropTypes.string,
20
+ controlledKeypadMode: PropTypes.bool,
20
21
  mode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
21
22
  layoutForKeyPad: PropTypes.object,
22
23
  onClick: PropTypes.func.isRequired,
23
24
  onFocus: PropTypes.func,
24
25
  noDecimal: PropTypes.bool,
25
26
  additionalKeys: PropTypes.array,
27
+ setKeypadInteraction: PropTypes.func,
26
28
  };
27
29
 
28
30
  static defaultProps = {
@@ -38,18 +40,29 @@ export default class HorizontalKeypad extends React.Component {
38
40
  };
39
41
 
40
42
  render() {
41
- const { mode, onFocus, noDecimal, className, additionalKeys, layoutForKeyPad } = this.props;
43
+ const {
44
+ mode,
45
+ onFocus,
46
+ controlledKeypadMode,
47
+ noDecimal,
48
+ className,
49
+ additionalKeys,
50
+ layoutForKeyPad,
51
+ setKeypadInteraction,
52
+ } = this.props;
42
53
  const normalizedKeys = normalizeAdditionalKeys(additionalKeys);
43
54
 
44
55
  return (
45
56
  <Keypad
46
57
  className={className}
58
+ controlledKeypadMode={controlledKeypadMode}
47
59
  onFocus={onFocus}
48
60
  noDecimal={noDecimal}
49
61
  layoutForKeyPad={layoutForKeyPad}
50
62
  additionalKeys={extendKeySet(keysForGrade(mode), normalizedKeys)}
51
63
  onPress={this.keypadPress}
52
64
  mode={mode}
65
+ setKeypadInteraction={setKeypadInteraction}
53
66
  />
54
67
  );
55
68
  }
package/src/index.jsx CHANGED
@@ -1,4 +1,5 @@
1
1
  import { keysForGrade } from './keys/grades';
2
+ import { updateSpans } from './updateSpans';
2
3
 
3
4
  const addLeftBracket = (s) => (s.indexOf('\\(') === 0 ? s : `\\(${s}`);
4
5
  const addRightBracket = (s) => (s.indexOf('\\)') === s.length - 2 ? s : `${s}\\)`);
@@ -8,16 +9,6 @@ const rmRightBracket = (s) => (s.indexOf('\\)') === s.length - 2 ? s.substring(0
8
9
  const addBrackets = (s) => addRightBracket(addLeftBracket(s));
9
10
  const removeBrackets = (s) => rmRightBracket(rmLeftBracket(s));
10
11
 
11
- // increase the font of parallel notation
12
- const updateSpans = () => {
13
- const spans = Array.from(document.querySelectorAll('span[mathquill-command-id]'));
14
- (spans || []).forEach((span) => {
15
- if (span && span.innerText === '∥' && span.className !== 'mq-editable-field') {
16
- span.style.fontSize = '32px';
17
- }
18
- });
19
- };
20
-
21
12
  import * as keys from './keys';
22
13
 
23
14
  import HorizontalKeypad from './horizontal-keypad';
@@ -0,0 +1,193 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Keypad snapshot renders 1`] = `
4
+ <div
5
+ className="className"
6
+ style={
7
+ Object {
8
+ "gridTemplateColumns": "repeat(4, minmax(min-content, 150px))",
9
+ }
10
+ }
11
+ >
12
+ <WithStyles(Button)
13
+ aria-label="seven"
14
+ className=""
15
+ disabled={false}
16
+ key="7-0"
17
+ onClick={[Function]}
18
+ >
19
+ 7
20
+ </WithStyles(Button)>
21
+ <WithStyles(Button)
22
+ aria-label="four"
23
+ className=""
24
+ disabled={false}
25
+ key="4-1"
26
+ onClick={[Function]}
27
+ >
28
+ 4
29
+ </WithStyles(Button)>
30
+ <WithStyles(Button)
31
+ aria-label="one"
32
+ className=""
33
+ disabled={false}
34
+ key="1-2"
35
+ onClick={[Function]}
36
+ >
37
+ 1
38
+ </WithStyles(Button)>
39
+ <WithStyles(Button)
40
+ aria-label="zero"
41
+ className=""
42
+ disabled={false}
43
+ key="0-3"
44
+ onClick={[Function]}
45
+ >
46
+ 0
47
+ </WithStyles(Button)>
48
+ <WithStyles(Button)
49
+ aria-label="Move cursor left"
50
+ className=""
51
+ disabled={false}
52
+ key="◀-4"
53
+ onClick={[Function]}
54
+ >
55
+
56
+ </WithStyles(Button)>
57
+ <WithStyles(Button)
58
+ aria-label="eight"
59
+ className=""
60
+ disabled={false}
61
+ key="8-5"
62
+ onClick={[Function]}
63
+ >
64
+ 8
65
+ </WithStyles(Button)>
66
+ <WithStyles(Button)
67
+ aria-label="five"
68
+ className=""
69
+ disabled={false}
70
+ key="5-6"
71
+ onClick={[Function]}
72
+ >
73
+ 5
74
+ </WithStyles(Button)>
75
+ <WithStyles(Button)
76
+ aria-label="two"
77
+ className=""
78
+ disabled={false}
79
+ key="2-7"
80
+ onClick={[Function]}
81
+ >
82
+ 2
83
+ </WithStyles(Button)>
84
+ <WithStyles(Button)
85
+ aria-label="decimal-point"
86
+ className=""
87
+ disabled={false}
88
+ key=".-8"
89
+ onClick={[Function]}
90
+ >
91
+ .
92
+ </WithStyles(Button)>
93
+ <WithStyles(Button)
94
+ aria-label="Move cursor right"
95
+ className=""
96
+ disabled={false}
97
+ key="▶-9"
98
+ onClick={[Function]}
99
+ >
100
+
101
+ </WithStyles(Button)>
102
+ <WithStyles(Button)
103
+ aria-label="nine"
104
+ className=""
105
+ disabled={false}
106
+ key="9-10"
107
+ onClick={[Function]}
108
+ >
109
+ 9
110
+ </WithStyles(Button)>
111
+ <WithStyles(Button)
112
+ aria-label="six"
113
+ className=""
114
+ disabled={false}
115
+ key="6-11"
116
+ onClick={[Function]}
117
+ >
118
+ 6
119
+ </WithStyles(Button)>
120
+ <WithStyles(Button)
121
+ aria-label="three"
122
+ className=""
123
+ disabled={false}
124
+ key="3-12"
125
+ onClick={[Function]}
126
+ >
127
+ 3
128
+ </WithStyles(Button)>
129
+ <WithStyles(Button)
130
+ aria-label="comma"
131
+ className=""
132
+ disabled={false}
133
+ key=",-13"
134
+ onClick={[Function]}
135
+ >
136
+ ,
137
+ </WithStyles(Button)>
138
+ <WithStyles(Button)
139
+ aria-label="Delete"
140
+ className="undefined"
141
+ disabled={false}
142
+ key="⌫-14"
143
+ onClick={[Function]}
144
+ >
145
+
146
+ </WithStyles(Button)>
147
+ <WithStyles(Button)
148
+ aria-label="divide"
149
+ className=""
150
+ disabled={false}
151
+ key="÷-15"
152
+ onClick={[Function]}
153
+ >
154
+ ÷
155
+ </WithStyles(Button)>
156
+ <WithStyles(Button)
157
+ aria-label="multiply"
158
+ className=""
159
+ disabled={false}
160
+ key="×-16"
161
+ onClick={[Function]}
162
+ >
163
+ ×
164
+ </WithStyles(Button)>
165
+ <WithStyles(Button)
166
+ aria-label="−"
167
+ className=""
168
+ disabled={false}
169
+ key="−-17"
170
+ onClick={[Function]}
171
+ >
172
+
173
+ </WithStyles(Button)>
174
+ <WithStyles(Button)
175
+ aria-label="+"
176
+ className=""
177
+ disabled={false}
178
+ key="+-18"
179
+ onClick={[Function]}
180
+ >
181
+ +
182
+ </WithStyles(Button)>
183
+ <WithStyles(Button)
184
+ aria-label="="
185
+ className=""
186
+ disabled={false}
187
+ key="=-19"
188
+ onClick={[Function]}
189
+ >
190
+ =
191
+ </WithStyles(Button)>
192
+ </div>
193
+ `;
@@ -0,0 +1,24 @@
1
+ import { shallow } from 'enzyme';
2
+ import React from 'react';
3
+ import { KeyPad } from '../index';
4
+
5
+ describe('Keypad', () => {
6
+ let w;
7
+ let onChange = jest.fn();
8
+ const wrapper = (extras) => {
9
+ const defaults = {
10
+ classes: {},
11
+ className: 'className',
12
+ onChange,
13
+ onPress: jest.fn(),
14
+ };
15
+ const props = { ...defaults, ...extras };
16
+ return shallow(<KeyPad {...props} />);
17
+ };
18
+ describe('snapshot', () => {
19
+ it('renders', () => {
20
+ w = wrapper();
21
+ expect(w).toMatchSnapshot();
22
+ });
23
+ });
24
+ });
@@ -0,0 +1,15 @@
1
+ import { sortKeys } from '../keys-layout';
2
+ import { baseSet, comparison } from '../../keys';
3
+
4
+ describe('keys-layout', () => {
5
+ describe('sortKeys', () => {
6
+ it('pads the rows', () => {
7
+ const result = sortKeys([[1, 2, 3]]);
8
+ expect(result).toEqual([
9
+ [1, undefined, undefined, undefined, undefined],
10
+ [2, undefined, undefined, undefined, undefined],
11
+ [3, undefined, undefined, undefined, undefined],
12
+ ]);
13
+ });
14
+ });
15
+ });
@@ -6,13 +6,16 @@ import { withStyles } from '@material-ui/core/styles';
6
6
  import classNames from 'classnames';
7
7
  import { lighten, fade } from '@material-ui/core/styles/colorManipulator';
8
8
  import green from '@material-ui/core/colors/green';
9
- import { sortKeys } from './keys-layout';
10
- import * as mq from '../mq';
11
- import { baseSet } from '../keys';
12
9
  import debug from 'debug';
13
10
  import _ from 'lodash';
14
11
  import MathQuill from '@pie-framework/mathquill';
15
12
 
13
+ import * as mq from '../mq';
14
+ import { baseSet } from '../keys';
15
+ import { constants } from '@pie-lib/editable-html';
16
+ import { commonMqKeyboardStyles } from '../mq/common-mq-styles';
17
+ import { sortKeys } from './keys-layout';
18
+
16
19
  const log = debug('pie-lib:math-inline:keypad');
17
20
 
18
21
  const LatexButton = withStyles((theme) => ({
@@ -37,6 +40,9 @@ const LatexButton = withStyles((theme) => ({
37
40
  '& .mq-overline .mq-overline-inner': {
38
41
  borderTop: '2px solid black',
39
42
  },
43
+ '& .mq-non-leaf.mq-overline': {
44
+ borderTop: 'none !important', // fixing PD-4873 - in OT, it has border-top 1px and adds extra line
45
+ },
40
46
  '& .mq-overarrow': {
41
47
  width: '30px',
42
48
  marginTop: '0 !important',
@@ -47,11 +53,12 @@ const LatexButton = withStyles((theme) => ({
47
53
  top: '0px !important',
48
54
  '& *': {
49
55
  lineHeight: '1 !important',
56
+ borderTop: 'none !important', // fixing PD-4873 - in OT, it has border-top 1px and adds extra line,
50
57
  },
51
58
  '&:before': {
52
59
  fontSize: '80%',
53
- left: 'calc(-13%)',
54
- top: '-0.31em',
60
+ left: 'calc(-13%) !important',
61
+ top: '-0.31em !important',
55
62
  },
56
63
  '&:after': {
57
64
  fontSize: '80% !important',
@@ -74,8 +81,8 @@ const LatexButton = withStyles((theme) => ({
74
81
  },
75
82
  '&.mq-arrow-right:before': {
76
83
  fontSize: '80%',
77
- right: 'calc(-13%)',
78
- top: '-0.26em',
84
+ right: 'calc(-13%) !important',
85
+ top: '-0.26em !important',
79
86
  },
80
87
  '& .mq-overarrow-inner': {
81
88
  border: 'none !important',
@@ -111,6 +118,9 @@ const LatexButton = withStyles((theme) => ({
111
118
  },
112
119
  '& .mq-overarc': {
113
120
  borderTop: '2px solid black !important',
121
+ '& .mq-overline': {
122
+ borderTop: 'none !important', // fixing PD-4873 - in OT, it has border-top 1px and adds extra line
123
+ },
114
124
  '& .mq-overline-inner': {
115
125
  borderTop: 'none !important',
116
126
  paddingTop: '0 !important',
@@ -118,7 +128,7 @@ const LatexButton = withStyles((theme) => ({
118
128
  },
119
129
  },
120
130
  parallelButton: {
121
- fontStyle: 'italic',
131
+ fontStyle: 'italic !important',
122
132
  },
123
133
  leftRightArrowButton: {
124
134
  '& .mq-overarrow.mq-arrow-both': {
@@ -183,22 +193,83 @@ export class KeyPad extends React.Component {
183
193
  static propTypes = {
184
194
  classes: PropTypes.object.isRequired,
185
195
  className: PropTypes.string,
196
+ controlledKeypadMode: PropTypes.bool,
186
197
  baseSet: PropTypes.array,
187
198
  additionalKeys: PropTypes.array,
188
199
  layoutForKeyPad: PropTypes.object,
189
200
  onPress: PropTypes.func.isRequired,
190
201
  onFocus: PropTypes.func,
191
202
  noDecimal: PropTypes.bool,
192
- mode: PropTypes.string,
203
+ setKeypadInteraction: PropTypes.func,
204
+ mode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
193
205
  };
194
206
  static defaultProps = {
195
207
  baseSet: baseSet,
196
208
  noDecimal: false,
197
209
  };
198
210
 
211
+ constructor(props) {
212
+ super(props);
213
+ this.keypadRef = React.createRef();
214
+ }
215
+
216
+ componentDidMount() {
217
+ const keyPadElement = this.keypadRef?.current;
218
+ const mainContainer = keyPadElement?.closest(`.${constants.MAIN_CONTAINER_CLASS}`);
219
+ const currentToolbar = keyPadElement?.closest('.pie-toolbar');
220
+
221
+ // need only for math keyboard so we need also controlledKeypadMode
222
+ if (this.props.controlledKeypadMode && mainContainer && currentToolbar) {
223
+ const mainContainerPosition = mainContainer.getBoundingClientRect();
224
+ const currentToolbarPosition = currentToolbar.getBoundingClientRect();
225
+ const difference =
226
+ mainContainerPosition.top +
227
+ mainContainerPosition.height -
228
+ (currentToolbarPosition.top + currentToolbarPosition.height);
229
+ if (difference < 0) {
230
+ const totalHeight = mainContainerPosition.height + mainContainerPosition.top - difference;
231
+ // increase the height of the main container if keyboard needs it
232
+ if (mainContainer) {
233
+ mainContainer.style.height = `${totalHeight}px`;
234
+ }
235
+ }
236
+ }
237
+
238
+ if (keyPadElement) {
239
+ keyPadElement.addEventListener('touchstart', this.handleKeypadInteraction, true);
240
+ keyPadElement.addEventListener('mousedown', this.handleKeypadInteraction, true);
241
+ }
242
+ }
243
+
244
+ componentWillUnmount() {
245
+ const keyPadElement = this.keypadRef?.current;
246
+ // need only for math keyboard
247
+ if (this.props.controlledKeypadMode && keyPadElement) {
248
+ const mainContainer = keyPadElement.closest(`.${constants.MAIN_CONTAINER_CLASS}`);
249
+
250
+ if (mainContainer) {
251
+ mainContainer.style.height = 'unset';
252
+ }
253
+ }
254
+
255
+ if (keyPadElement) {
256
+ keyPadElement.removeEventListener('touchstart', this.handleKeypadInteraction, true);
257
+ keyPadElement.removeEventListener('mousedown', this.handleKeypadInteraction, true);
258
+ }
259
+ }
260
+
261
+ handleKeypadInteraction = () => {
262
+ // Check if the setKeypadInteraction prop is available, which is used for both
263
+ // the language keypad and the special characters keypad
264
+ if (this.props.setKeypadInteraction) {
265
+ this.props.setKeypadInteraction(true);
266
+ }
267
+ };
268
+
199
269
  buttonClick = (key) => {
200
270
  log('[buttonClick]', key);
201
271
  const { onPress } = this.props;
272
+
202
273
  onPress(key);
203
274
  };
204
275
 
@@ -234,7 +305,12 @@ export class KeyPad extends React.Component {
234
305
  };
235
306
 
236
307
  return (
237
- <div className={classNames(classes.keys, className, classes[mode])} style={style} onFocus={onFocus}>
308
+ <div
309
+ ref={this.keypadRef}
310
+ className={classNames(classes.keys, className, classes[mode])}
311
+ style={style}
312
+ onFocus={onFocus}
313
+ >
238
314
  {allKeys.map((k, index) => {
239
315
  const onClick = this.buttonClick.bind(this, k);
240
316
 
@@ -271,7 +347,12 @@ export class KeyPad extends React.Component {
271
347
 
272
348
  if (k.label) {
273
349
  return (
274
- <Button key={index} {...common} aria-label={k.ariaLabel ? k.ariaLabel : k.name || k.label}>
350
+ <Button
351
+ key={index}
352
+ {...common}
353
+ className={classNames(common.className, { [classes.deleteButton]: k.label === '⌫' })}
354
+ aria-label={k.ariaLabel ? k.ariaLabel : k.name || k.label}
355
+ >
275
356
  {k.label}
276
357
  </Button>
277
358
  );
@@ -292,9 +373,7 @@ export class KeyPad extends React.Component {
292
373
 
293
374
  const styles = (theme) => ({
294
375
  keys: {
295
- '& *': {
296
- fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important',
297
- },
376
+ ...commonMqKeyboardStyles,
298
377
  width: '100%',
299
378
  display: 'grid',
300
379
  gridTemplateRows: 'repeat(5, minmax(40px, 60px))',
@@ -307,7 +386,7 @@ const styles = (theme) => ({
307
386
  gridTemplateRows: 'repeat(5, minmax(40px, 50px)) !important',
308
387
  },
309
388
  language: {
310
- gridTemplateRows: 'repeat(5, minmax(40px, 50px)) !important',
389
+ gridTemplateRows: 'repeat(4, minmax(40px, 50px)) !important',
311
390
  '& *': {
312
391
  fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important',
313
392
  },
@@ -337,6 +416,11 @@ const styles = (theme) => ({
337
416
  backgroundColor: lighten(theme.palette.primary.light, 0.7),
338
417
  },
339
418
  },
419
+ deleteButton: {
420
+ '& > span': {
421
+ fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important',
422
+ },
423
+ },
340
424
  base: {},
341
425
  operators: {
342
426
  backgroundColor: lighten(theme.palette.secondary.light, 0.5),
@@ -0,0 +1,57 @@
1
+ import { extendKeySet } from '../utils';
2
+ import { keysForGrade, gradeSets } from '../grades';
3
+ import * as comparison from '../../keys/comparison';
4
+
5
+ describe('utils', () => {
6
+ const base = [[comparison.lessThan]];
7
+ describe('extendKeySet', () => {
8
+ it('removes duplicates by latex key', () => {
9
+ const extras = [{ name: 'foo', latex: '<', write: '<', label: 'less than' }];
10
+ const result = extendKeySet(base, extras);
11
+ const resultTwo = extendKeySet(base, []);
12
+ expect(result).toEqual(resultTwo);
13
+ });
14
+
15
+ it('removes duplicates by name key', () => {
16
+ const extras = [{ name: 'Less than', latex: 'this is latex', write: '<', label: '<' }];
17
+ const result = extendKeySet(base, extras);
18
+ const resultTwo = extendKeySet(base, []);
19
+ expect(result).toEqual(resultTwo);
20
+ });
21
+ });
22
+
23
+ describe('keysForGrade', () => {
24
+ it.each`
25
+ key | expected
26
+ ${'1'} | ${[]}
27
+ ${'2'} | ${[]}
28
+ ${'3'} | ${gradeSets[0].set}
29
+ ${'4'} | ${gradeSets[0].set}
30
+ ${'5'} | ${gradeSets[0].set}
31
+ ${'6'} | ${gradeSets[1].set}
32
+ ${'7'} | ${gradeSets[1].set}
33
+ ${'8'} | ${gradeSets[2].set}
34
+ ${'9'} | ${gradeSets[2].set}
35
+ ${'HS'} | ${gradeSets[2].set}
36
+ ${'non-negative-integers'} | ${gradeSets[3].set}
37
+ ${'integers'} | ${gradeSets[4].set}
38
+ ${'decimals'} | ${gradeSets[5].set}
39
+ ${'fractions'} | ${gradeSets[6].set}
40
+ ${'geometry'} | ${gradeSets[7].set}
41
+ ${'advanced-algebra'} | ${gradeSets[8].set}
42
+ ${'statistics'} | ${gradeSets[9].set}
43
+ ${'something else'} | ${gradeSets[2].set}
44
+ ${undefined} | ${[]}
45
+ ${null} | ${[]}
46
+ ${0} | ${[]}
47
+ ${'0'} | ${[]}
48
+ `('$key => $expected', ({ key, expected }) => {
49
+ expect(keysForGrade(key)).toEqual(expected);
50
+
51
+ const n = parseInt(key, 10);
52
+ if (!isNaN(n)) {
53
+ expect(keysForGrade(n)).toEqual(expected);
54
+ }
55
+ });
56
+ });
57
+ });
@@ -101,6 +101,7 @@ export const congruentTo = set({
101
101
  command: '\\cong',
102
102
  latex: '\\cong',
103
103
  });
104
+
104
105
  export const notCongruentTo = set({
105
106
  name: 'Not Congruent To',
106
107
  command: '\\ncong',
@@ -115,10 +116,13 @@ export const primeArcminute = set({
115
116
  // eslint-disable-next-line
116
117
  write: "'",
117
118
  });
119
+
118
120
  export const doublePrimeArcSecond = set({
119
121
  name: 'Double Prime',
120
- latex: '"',
121
- write: '"',
122
+ // eslint-disable-next-line
123
+ latex: "''",
124
+ // eslint-disable-next-line
125
+ write: "''",
122
126
  });
123
127
 
124
128
  export const leftArrow = set({