@pie-lib/math-input 6.11.4 → 6.13.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/NEXT.CHANGELOG.json +1 -0
  3. package/lib/__tests__/math-input-test.js +109 -0
  4. package/lib/horizontal-keypad.js +10 -4
  5. package/lib/index.js +11 -15
  6. package/lib/keypad/__tests__/index.test.js +41 -0
  7. package/lib/keypad/__tests__/keys-layout.test.js +15 -0
  8. package/lib/keypad/index.js +96 -25
  9. package/lib/keypad/keys-layout.js +1 -1
  10. package/lib/keys/__tests__/utils.test.js +60 -0
  11. package/lib/keys/basic-operators.js +1 -1
  12. package/lib/keys/chars.js +1 -1
  13. package/lib/keys/comparison.js +1 -1
  14. package/lib/keys/constants.js +1 -1
  15. package/lib/keys/digits.js +1 -1
  16. package/lib/keys/edit.js +1 -1
  17. package/lib/keys/exponent.js +1 -1
  18. package/lib/keys/fractions.js +1 -1
  19. package/lib/keys/geometry.js +5 -3
  20. package/lib/keys/grades.js +13 -1
  21. package/lib/keys/index.js +1 -1
  22. package/lib/keys/log.js +2 -2
  23. package/lib/keys/logic.js +1 -1
  24. package/lib/keys/matrices.js +1 -1
  25. package/lib/keys/misc.js +1 -1
  26. package/lib/keys/navigation.js +1 -1
  27. package/lib/keys/operators.js +1 -1
  28. package/lib/keys/statistics.js +1 -1
  29. package/lib/keys/sub-sup.js +1 -1
  30. package/lib/keys/trigonometry.js +1 -1
  31. package/lib/keys/utils.js +1 -1
  32. package/lib/keys/vars.js +1 -1
  33. package/lib/math-input.js +1 -1
  34. package/lib/mq/__tests__/input.test.js +119 -0
  35. package/lib/mq/__tests__/static.test.js +74 -0
  36. package/lib/mq/common-mq-styles.js +110 -0
  37. package/lib/mq/custom-elements.js +1 -1
  38. package/lib/mq/index.js +9 -1
  39. package/lib/mq/input.js +13 -11
  40. package/lib/mq/static.js +199 -76
  41. package/lib/updateSpans.js +23 -0
  42. package/package.json +2 -2
  43. package/src/__tests__/__snapshots__/math-input-test.jsx.snap +152 -0
  44. package/src/__tests__/math-input-test.jsx +85 -0
  45. package/src/horizontal-keypad.jsx +14 -1
  46. package/src/index.jsx +1 -10
  47. package/src/keypad/__tests__/__snapshots__/index.test.jsx.snap +193 -0
  48. package/src/keypad/__tests__/index.test.jsx +24 -0
  49. package/src/keypad/__tests__/keys-layout.test.js +15 -0
  50. package/src/keypad/index.jsx +99 -15
  51. package/src/keys/__tests__/utils.test.js +57 -0
  52. package/src/keys/geometry.js +6 -2
  53. package/src/keys/grades.js +11 -0
  54. package/src/keys/log.js +1 -1
  55. package/src/mq/__tests__/__snapshots__/input.test.jsx.snap +9 -0
  56. package/src/mq/__tests__/input.test.jsx +92 -0
  57. package/src/mq/__tests__/static.test.jsx +57 -0
  58. package/src/mq/common-mq-styles.js +105 -0
  59. package/src/mq/index.js +2 -1
  60. package/src/mq/input.jsx +22 -9
  61. package/src/mq/static.jsx +142 -13
  62. package/src/updateSpans.js +15 -0
  63. package/README.md +0 -27
  64. package/lib/horizontal-keypad.js.map +0 -1
  65. package/lib/index.js.map +0 -1
  66. package/lib/keypad/index.js.map +0 -1
  67. package/lib/keypad/keys-layout.js.map +0 -1
  68. package/lib/keys/basic-operators.js.map +0 -1
  69. package/lib/keys/chars.js.map +0 -1
  70. package/lib/keys/comparison.js.map +0 -1
  71. package/lib/keys/constants.js.map +0 -1
  72. package/lib/keys/digits.js.map +0 -1
  73. package/lib/keys/edit.js.map +0 -1
  74. package/lib/keys/exponent.js.map +0 -1
  75. package/lib/keys/fractions.js.map +0 -1
  76. package/lib/keys/geometry.js.map +0 -1
  77. package/lib/keys/grades.js.map +0 -1
  78. package/lib/keys/index.js.map +0 -1
  79. package/lib/keys/log.js.map +0 -1
  80. package/lib/keys/logic.js.map +0 -1
  81. package/lib/keys/matrices.js.map +0 -1
  82. package/lib/keys/misc.js.map +0 -1
  83. package/lib/keys/navigation.js.map +0 -1
  84. package/lib/keys/operators.js.map +0 -1
  85. package/lib/keys/statistics.js.map +0 -1
  86. package/lib/keys/sub-sup.js.map +0 -1
  87. package/lib/keys/trigonometry.js.map +0 -1
  88. package/lib/keys/utils.js.map +0 -1
  89. package/lib/keys/vars.js.map +0 -1
  90. package/lib/math-input.js.map +0 -1
  91. package/lib/mq/custom-elements.js.map +0 -1
  92. package/lib/mq/index.js.map +0 -1
  93. package/lib/mq/input.js.map +0 -1
  94. package/lib/mq/static.js.map +0 -1
@@ -304,6 +304,12 @@ export const gradeSets = [
304
304
  ],
305
305
  ],
306
306
  },
307
+ // for grade 1-2, we want to display the base set only
308
+ // we need it here because we don't want to display the default set (grade 8)
309
+ {
310
+ predicate: (n) => n >= 1 && n <= 2,
311
+ set: [],
312
+ },
307
313
  ];
308
314
 
309
315
  export const keysForGrade = (n) => {
@@ -324,6 +330,11 @@ export const keysForGrade = (n) => {
324
330
  if (match) {
325
331
  return match.set || [];
326
332
  }
333
+
334
+ // if the grade is not found, return the default set which is grade 8 (as per PD-3549), for mode language it is not the default
335
+ if (n !== 'language') {
336
+ return gradeSets[2].set;
337
+ }
327
338
  };
328
339
 
329
340
  const ALL_KEYS = [
package/src/keys/log.js CHANGED
@@ -12,7 +12,7 @@ export const logSubscript = set({
12
12
  name: 'log base n',
13
13
  label: 'log s',
14
14
  latex: '\\log_{}',
15
- command: ['\\log', '_', ' '],
15
+ command: ['\\log', '_'],
16
16
  });
17
17
  export const ln = set({
18
18
  name: 'natural log',
@@ -0,0 +1,9 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Input snapshot renders 1`] = `
4
+ <span
5
+ className="className"
6
+ onClick={[Function]}
7
+ onKeyDown={[Function]}
8
+ />
9
+ `;
@@ -0,0 +1,92 @@
1
+ import { shallow } from 'enzyme';
2
+ import React from 'react';
3
+ import { Input } from '../input';
4
+
5
+ describe('Input', () => {
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
+ const out = shallow(<Input {...props} />);
20
+
21
+ out.mathField = () => out.instance().mathField;
22
+ return out;
23
+ };
24
+
25
+ describe('snapshot', () => {
26
+ it('renders', () => {
27
+ w = wrapper();
28
+ expect(w).toMatchSnapshot();
29
+ });
30
+ });
31
+ describe('logic', () => {
32
+ beforeEach(() => {
33
+ w = wrapper();
34
+ });
35
+ describe('clear', () => {
36
+ it('calls latex', () => {
37
+ w.instance().clear();
38
+ expect(w.mathField().latex).toHaveBeenCalledWith('');
39
+ });
40
+ });
41
+ describe('blur', () => {
42
+ it('calls blur', () => {
43
+ w.instance().blur();
44
+ expect(w.mathField().blur).toHaveBeenCalled();
45
+ });
46
+ });
47
+ describe('focus', () => {
48
+ it('calls focus', () => {
49
+ w.instance().focus();
50
+ expect(w.mathField().focus).toHaveBeenCalled();
51
+ });
52
+ });
53
+ describe('command', () => {
54
+ it('calls cmd', () => {
55
+ w.instance().command('foo');
56
+ expect(w.mathField().cmd).toHaveBeenCalledWith('foo');
57
+ });
58
+ it('calls cmd if passed an array', () => {
59
+ w.instance().command(['foo', 'bar']);
60
+ expect(w.mathField().cmd).toHaveBeenCalledWith('foo');
61
+ expect(w.mathField().cmd).toHaveBeenCalledWith('bar');
62
+ });
63
+ });
64
+
65
+ describe('keystroke', () => {
66
+ beforeEach(() => {
67
+ w.instance().keystroke('9');
68
+ });
69
+ it('calls keystroke', () => expect(w.mathField().keystroke).toHaveBeenCalledWith('9'));
70
+ it('calls focus', () => expect(w.mathField().focus).toHaveBeenCalled());
71
+ it('calls latex', () => expect(w.mathField().latex).toHaveBeenCalled());
72
+ });
73
+
74
+ describe('write', () => {
75
+ beforeEach(() => {
76
+ w.instance().write('hi');
77
+ });
78
+ it('calls write', () => expect(w.mathField().write).toHaveBeenCalledWith('hi'));
79
+ it('calls focus', () => expect(w.mathField().focus).toHaveBeenCalled());
80
+ it('calls latex', () => expect(w.mathField().latex).toHaveBeenCalled());
81
+ });
82
+
83
+ describe('onInputEdit', () => {
84
+ it('calls onChange', () => {
85
+ w = wrapper();
86
+ w.mathField().latex.mockReturnValue('foo');
87
+ w.instance().onInputEdit();
88
+ expect(onChange).toHaveBeenCalledWith('foo');
89
+ });
90
+ });
91
+ });
92
+ });
@@ -0,0 +1,57 @@
1
+ import { shallow } from 'enzyme';
2
+ import React from 'react';
3
+ import Static from '../static';
4
+
5
+ const Mathquill = require('@pie-framework/mathquill');
6
+
7
+ jest.mock('@pie-framework/mathquill', () => ({
8
+ StaticMath: jest.fn().mockReturnValue({
9
+ latex: jest.fn(),
10
+ parseLatex: jest.fn(),
11
+ }),
12
+ getInterface: jest.fn().mockReturnThis(),
13
+ }));
14
+
15
+ describe('static', () => {
16
+ let w;
17
+ describe('mount', () => {
18
+ beforeEach(() => {
19
+ w = shallow(<Static latex="foo" />, {
20
+ disableLifecycleMethods: true,
21
+ });
22
+
23
+ w.instance().input = {};
24
+ w.instance().componentDidMount();
25
+ });
26
+
27
+ it('set the html', () => {
28
+ expect(Mathquill.getInterface().StaticMath().latex).toBeCalledWith('foo');
29
+ });
30
+
31
+ it('calls MQ.StaticMath', () => {
32
+ expect(Mathquill.getInterface().StaticMath).toHaveBeenCalled();
33
+ });
34
+ });
35
+
36
+ describe('shouldComponentUpdate', () => {
37
+ it('returns false if there is an error', () => {
38
+ w = shallow(<Static latex="foo" />, { disableLifecycleMethods: true });
39
+ w.instance().mathField = {
40
+ parseLatex: jest.fn((e) => {
41
+ throw new Error('boom');
42
+ }),
43
+ };
44
+ expect(w.instance().shouldComponentUpdate({ latex: '\\abs{}' })).toEqual(false);
45
+ });
46
+
47
+ it('returns true if ??', () => {
48
+ w = shallow(<Static latex="foo" />, { disableLifecycleMethods: true });
49
+ w.instance().mathField = {
50
+ latex: jest.fn().mockReturnValue('foo'),
51
+ parseLatex: jest.fn().mockReturnValue('foo'),
52
+ innerFields: ['field1', 'field2'],
53
+ };
54
+ expect(w.instance().shouldComponentUpdate({ latex: '\\abs{}' })).toEqual(true);
55
+ });
56
+ });
57
+ });
@@ -0,0 +1,105 @@
1
+ export const commonMqFontStyles = {
2
+ fontFamily: 'MJXZERO, MJXTEX !important',
3
+ '-webkit-font-smoothing': 'antialiased !important',
4
+
5
+ '& .mq-math-mode > span > var': {
6
+ fontFamily: 'MJXZERO, MJXTEX-I !important',
7
+ },
8
+ '& .mq-math-mode span var': {
9
+ fontFamily: 'MJXZERO, MJXTEX-I !important',
10
+ },
11
+ '& .mq-math-mode .mq-nonSymbola': {
12
+ fontFamily: 'MJXZERO, MJXTEX-I !important',
13
+ },
14
+ '& .mq-math-mode > span > var.mq-operator-name': {
15
+ fontFamily: 'MJXZERO, MJXTEX !important',
16
+ },
17
+ };
18
+
19
+ export const longdivStyles = {
20
+ '& .mq-longdiv-inner': {
21
+ marginTop: '-1px',
22
+ marginLeft: '5px !important;',
23
+
24
+ '& > .mq-empty': {
25
+ padding: '0 !important',
26
+ marginLeft: '0px !important',
27
+ marginTop: '2px',
28
+ },
29
+ },
30
+
31
+ '& .mq-math-mode .mq-longdiv': {
32
+ display: 'inline-flex !important',
33
+ },
34
+ };
35
+
36
+ export const supsubStyles = {
37
+ '& .mq-math-mode sup.mq-nthroot': {
38
+ fontSize: '70% !important',
39
+ verticalAlign: '0.5em !important',
40
+ paddingRight: '0.15em',
41
+ },
42
+ '& .mq-math-mode .mq-supsub': {
43
+ fontSize: '70.7% !important',
44
+ },
45
+ '& .mq-supsub ': {
46
+ fontSize: '70.7%',
47
+ },
48
+ '& .mq-math-mode .mq-supsub.mq-sup-only': {
49
+ verticalAlign: '-0.1em !important',
50
+
51
+ '& .mq-sup': {
52
+ marginBottom: '0px !important',
53
+ },
54
+ },
55
+ /* But when the base is a fraction, move it higher */
56
+ '& .mq-math-mode .mq-fraction + .mq-supsub.mq-sup-only': {
57
+ verticalAlign: '0.4em !important',
58
+ },
59
+
60
+ '& .mq-math-mode .mq-supsub.mq-sup-only.mq-after-fraction-group': {
61
+ verticalAlign: '0.4em !important',
62
+ },
63
+ };
64
+
65
+ export const commonMqKeyboardStyles = {
66
+ '& *': {
67
+ ...commonMqFontStyles,
68
+ ...longdivStyles,
69
+ '& .mq-math-mode .mq-sqrt-prefix': {
70
+ top: '0 !important',
71
+ },
72
+
73
+ '& .mq-math-mode .mq-empty': {
74
+ padding: '9px 1px !important',
75
+ },
76
+
77
+ '& .mq-math-mode .mq-supsub': {
78
+ fontSize: '70.7% !important',
79
+ },
80
+
81
+ '& .mq-math-mode .mq-sqrt-stem': {
82
+ marginTop: '-5px',
83
+ paddingTop: '4px',
84
+ },
85
+
86
+ '& .mq-math-mode .mq-paren': {
87
+ verticalAlign: 'middle !important',
88
+ },
89
+
90
+ '& .mq-math-mode .mq-overarrow .mq-overarrow-inner .mq-empty': {
91
+ padding: '0 !important',
92
+ },
93
+
94
+ '& .mq-math-mode .mq-overline .mq-overline-inner .mq-empty ': {
95
+ padding: '0 !important',
96
+ },
97
+ },
98
+ };
99
+
100
+ export default {
101
+ commonMqFontStyles,
102
+ longdivStyles,
103
+ supsubStyles,
104
+ commonMqKeyboardStyles,
105
+ };
package/src/mq/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import Input from './input';
2
2
  import Static from './static';
3
+ import CommonMqStyles from './common-mq-styles';
3
4
 
4
- export { Input, Static };
5
+ export { Input, Static, CommonMqStyles };
package/src/mq/input.jsx CHANGED
@@ -53,14 +53,17 @@ export class Input extends React.Component {
53
53
  if (!this.mathField) {
54
54
  return;
55
55
  }
56
+
56
57
  const { latex } = this.props;
57
- if (latex) {
58
+
59
+ if (latex !== undefined && latex !== null) {
58
60
  this.mathField.latex(latex);
59
61
  }
60
62
  }
61
63
 
62
64
  clear() {
63
65
  this.mathField.latex('');
66
+
64
67
  return '';
65
68
  }
66
69
 
@@ -83,13 +86,16 @@ export class Input extends React.Component {
83
86
  } else {
84
87
  this.mathField.cmd(v);
85
88
  }
89
+
86
90
  this.mathField.focus();
91
+
87
92
  return this.mathField.latex();
88
93
  }
89
94
 
90
95
  keystroke(v) {
91
96
  this.mathField.keystroke(v);
92
97
  this.mathField.focus();
98
+
93
99
  return this.mathField.latex();
94
100
  }
95
101
 
@@ -97,12 +103,14 @@ export class Input extends React.Component {
97
103
  log('write: ', v);
98
104
  this.mathField.write(v);
99
105
  this.mathField.focus();
106
+
100
107
  return this.mathField.latex();
101
108
  }
102
109
 
103
110
  onInputEdit = () => {
104
111
  log('[onInputEdit] ...');
105
112
  const { onChange } = this.props;
113
+
106
114
  if (!this.mathField) {
107
115
  return;
108
116
  }
@@ -128,28 +136,33 @@ export class Input extends React.Component {
128
136
  }
129
137
 
130
138
  if (event.charCode === 13) {
131
- // if enter's pressed, we're going for a custom embedded element that'll
132
- // have a block display (empty div) - for a hacked line break using ccs
133
- // all because mathquill doesn't support a line break
134
- this.write('\\embed{newLine}[]');
135
- this.onInputEdit();
139
+ event.preventDefault();
140
+ return;
136
141
  }
137
142
  };
138
143
 
144
+ onClick = (event) => {
145
+ const { onClick } = this.props;
146
+
147
+ this.refresh();
148
+ onClick && onClick(event);
149
+ };
150
+
139
151
  shouldComponentUpdate(nextProps) {
140
152
  log('next: ', nextProps.latex);
141
153
  log('current: ', this.mathField.latex());
154
+
142
155
  return nextProps.latex !== this.mathField.latex();
143
156
  }
144
157
 
145
158
  render() {
146
- const { onClick, onFocus, onBlur, classes, className } = this.props;
159
+ const { onFocus, onBlur, classes, className } = this.props;
147
160
 
148
161
  return (
149
162
  <span
150
163
  className={classNames(classes.input, className)}
151
- onKeyPress={this.onKeyPress}
152
- onClick={onClick}
164
+ onKeyDown={this.onKeyPress}
165
+ onClick={this.onClick}
153
166
  onFocus={onFocus}
154
167
  onBlur={onBlur}
155
168
  ref={(r) => (this.input = r)}
package/src/mq/static.jsx CHANGED
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import debug from 'debug';
4
4
  import MathQuill from '@pie-framework/mathquill';
5
- import { updateSpans } from '../index';
5
+ import { updateSpans } from '../updateSpans';
6
6
 
7
7
  let MQ;
8
8
  if (typeof window !== 'undefined') {
@@ -17,6 +17,18 @@ function stripSpaces(string = '') {
17
17
  return string.replace(WHITESPACE_REGEX, '');
18
18
  }
19
19
 
20
+ function countBraces(latex) {
21
+ let count = 0;
22
+
23
+ for (let i = 0; i < (latex || '').length; i++) {
24
+ if (latex[i] === '{') {
25
+ count++;
26
+ }
27
+ }
28
+
29
+ return count;
30
+ }
31
+
20
32
  /**
21
33
  * Wrapper for MathQuill MQ.MathField.
22
34
  */
@@ -36,9 +48,24 @@ export default class Static extends React.Component {
36
48
  getFieldName: () => {},
37
49
  };
38
50
 
51
+ constructor(props) {
52
+ super(props);
53
+ this.state = {
54
+ announcement: '',
55
+ previousLatex: '',
56
+ inputSource: null,
57
+ isDeleteKeyPressed: false,
58
+ };
59
+
60
+ this.inputRef = React.createRef();
61
+ }
62
+
39
63
  componentDidMount() {
40
64
  this.update();
41
65
  updateSpans();
66
+
67
+ this.createLiveRegion();
68
+ this.addEventListeners();
42
69
  }
43
70
 
44
71
  componentDidUpdate() {
@@ -46,7 +73,62 @@ export default class Static extends React.Component {
46
73
  updateSpans();
47
74
  }
48
75
 
49
- onInputEdit(field) {
76
+ componentWillUnmount() {
77
+ this.removeLiveRegion();
78
+ this.removeEventListeners();
79
+ }
80
+
81
+ createLiveRegion = () => {
82
+ this.liveRegion = document.createElement('div');
83
+ this.liveRegion.style.position = 'absolute';
84
+ this.liveRegion.style.width = '1px';
85
+ this.liveRegion.style.height = '1px';
86
+ this.liveRegion.style.marginTop = '-1px';
87
+ this.liveRegion.style.clip = 'rect(1px, 1px, 1px, 1px)';
88
+ this.liveRegion.style.overflow = 'hidden';
89
+ this.liveRegion.setAttribute('aria-live', 'polite');
90
+ this.liveRegion.setAttribute('aria-atomic', 'true');
91
+
92
+ document.body.appendChild(this.liveRegion);
93
+ };
94
+
95
+ addEventListeners = () => {
96
+ const input = this.inputRef.current;
97
+
98
+ if (input) {
99
+ input.addEventListener('keydown', this.handleKeyDown);
100
+ input.addEventListener('click', this.handleMathKeyboardClick);
101
+ }
102
+ };
103
+
104
+ removeEventListeners = () => {
105
+ const input = this.inputRef.current;
106
+
107
+ if (input) {
108
+ input.removeEventListener('keydown', this.handleKeyDown);
109
+ input.removeEventListener('click', this.handleMathKeyboardClick);
110
+ }
111
+ };
112
+
113
+ removeLiveRegion = () => {
114
+ if (this.liveRegion) {
115
+ document.body.removeChild(this.liveRegion);
116
+ this.liveRegion = null;
117
+ }
118
+ };
119
+
120
+ handleKeyDown = (event) => {
121
+ if (event?.key === 'Backspace' || event?.key === 'Delete') {
122
+ this.setState({ isDeleteKeyPressed: true });
123
+ }
124
+ this.setState({ inputSource: 'keyboard' });
125
+ };
126
+
127
+ handleMathKeyboardClick = () => {
128
+ this.setState({ inputSource: 'mathKeyboard' });
129
+ };
130
+
131
+ onInputEdit = (field) => {
50
132
  if (!this.mathField) {
51
133
  return;
52
134
  }
@@ -56,7 +138,7 @@ export default class Static extends React.Component {
56
138
  // eslint-disable-next-line no-useless-escape
57
139
  const regexMatch = field.latex().match(/[0-9]\\ \\frac\{[^\{]*\}\{ \}/);
58
140
 
59
- if (this.input && regexMatch && regexMatch?.length) {
141
+ if (this.inputRef?.current && regexMatch && regexMatch?.length) {
60
142
  try {
61
143
  field.__controller.cursor.insLeftOf(field.__controller.cursor.parent[-1].parent);
62
144
  field.el().dispatchEvent(new KeyboardEvent('keydown', { keyCode: 8 }));
@@ -68,15 +150,62 @@ export default class Static extends React.Component {
68
150
  this.props.onSubFieldChange(name, field.latex());
69
151
  }
70
152
  }
71
- }
72
153
 
73
- update() {
154
+ this.announceLatexConversion(field.latex());
155
+ };
156
+
157
+ announceLatexConversion = (newLatex) => {
158
+ if (!this.state) {
159
+ console.error('State is not initialized');
160
+ return;
161
+ }
162
+
163
+ const { previousLatex, inputSource, isDeleteKeyPressed } = this.state;
164
+ const announcement = 'Converted to math symbol';
165
+
166
+ if (inputSource === 'keyboard' && !isDeleteKeyPressed) {
167
+ const newBraces = countBraces(newLatex);
168
+ const oldBraces = countBraces(previousLatex);
169
+
170
+ if (newBraces > oldBraces) {
171
+ this.announceMessage(announcement);
172
+ } else {
173
+ try {
174
+ this.mathField.parseLatex(previousLatex);
175
+ this.mathField.parseLatex(newLatex);
176
+
177
+ if (newLatex == previousLatex) {
178
+ this.announceMessage(announcement);
179
+ }
180
+ } catch (e) {
181
+ console.warn('Error parsing latex:', e.message);
182
+ console.warn(e);
183
+ }
184
+ }
185
+ }
186
+
187
+ this.setState({ previousLatex: newLatex, isDeleteKeyPressed: false });
188
+ };
189
+
190
+ announceMessage = (message) => {
191
+ this.setState({ previousLatex: '' });
192
+
193
+ if (this.liveRegion) {
194
+ this.liveRegion.textContent = message;
195
+
196
+ // Clear the message after it is announced
197
+ setTimeout(() => {
198
+ this.liveRegion.textContent = '';
199
+ }, 500);
200
+ }
201
+ };
202
+
203
+ update = () => {
74
204
  if (!MQ) {
75
205
  throw new Error('MQ is not defined - but component has mounted?');
76
206
  }
77
- // this.input.innerHTML = this.props.latex;
78
207
  if (!this.mathField) {
79
- this.mathField = MQ.StaticMath(this.input, {
208
+ this.mathField = MQ.StaticMath(this.inputRef?.current, {
80
209
  handlers: {
81
210
  edit: this.onInputEdit.bind(this),
82
211
  },
@@ -90,17 +219,17 @@ export default class Static extends React.Component {
90
219
  // default latex if received has errors
91
220
  this.mathField.latex('\\MathQuillMathField[r1]{}');
92
221
  }
93
- }
222
+ };
94
223
 
95
- blur() {
224
+ blur = () => {
96
225
  log('blur mathfield');
97
226
  this.mathField.blur();
98
- }
227
+ };
99
228
 
100
- focus() {
229
+ focus = () => {
101
230
  log('focus mathfield...');
102
231
  this.mathField.focus();
103
- }
232
+ };
104
233
 
105
234
  shouldComponentUpdate(nextProps) {
106
235
  try {
@@ -151,6 +280,6 @@ export default class Static extends React.Component {
151
280
  render() {
152
281
  const { onBlur, className } = this.props;
153
282
 
154
- return <span className={className} onFocus={this.onFocus} onBlur={onBlur} ref={(r) => (this.input = r)} />;
283
+ return <span className={className} onFocus={this.onFocus} onBlur={onBlur} ref={this.inputRef} />;
155
284
  }
156
285
  }
@@ -0,0 +1,15 @@
1
+ // increase the font of parallel notation
2
+ const updateSpans = () => {
3
+ const spans = Array.from(document.querySelectorAll('span[mathquill-command-id]'));
4
+ (spans || []).forEach((span) => {
5
+ if (span && span.innerText === '∥' && span.className !== 'mq-editable-field') {
6
+ span.style.fontSize = '32px';
7
+ }
8
+
9
+ if ((span.innerText === '′' || span.innerText === '′′') && !span.hasAttribute('data-prime')) {
10
+ span.setAttribute('data-prime', 'true');
11
+ }
12
+ });
13
+ };
14
+
15
+ export { updateSpans };
package/README.md DELETED
@@ -1,27 +0,0 @@
1
- # math-input
2
-
3
- A [React](http://github.com/facebook/react) math input field, with a material design feel. Uses [Mathquill](http://mathquill.com/).
4
-
5
- ## install
6
-
7
- ```bash
8
- npm|yarn install
9
- ```
10
-
11
- ## demo
12
- ```bash
13
-
14
- cd demo
15
- ../node_modules/.bin/webpack-dev-server --hot --inline
16
- ```
17
-
18
- ## test
19
-
20
- ```bash
21
- npm|yarn test
22
- ```
23
-
24
-
25
- ## Using in another app
26
-
27
- We expose the jsx directly, so you'll need to update your build pipeline to build from src.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/horizontal-keypad.jsx"],"names":["toOldModel","d","command","value","type","write","keystroke","HorizontalKeypad","data","onClick","props","mode","onFocus","noDecimal","className","additionalKeys","layoutForKeyPad","normalizedKeys","keypadPress","React","Component","PropTypes","string","oneOfType","number","object","func","isRequired","bool","array"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AACA;;;;;;AAEA,IAAMA,UAAU,GAAG,SAAbA,UAAa,CAACC,CAAD,EAAO;AACxB,MAAIA,CAAC,CAACC,OAAN,EAAe;AACb,WAAO;AAAEC,MAAAA,KAAK,EAAEF,CAAC,CAACC,OAAX;AAAoBE,MAAAA,IAAI,EAAE;AAA1B,KAAP;AACD,GAFD,MAEO,IAAIH,CAAC,CAACI,KAAN,EAAa;AAClB,WAAO;AAAEF,MAAAA,KAAK,EAAEF,CAAC,CAACI;AAAX,KAAP;AACD,GAFM,MAEA,IAAIJ,CAAC,CAACK,SAAN,EAAiB;AACtB,WAAO;AAAEF,MAAAA,IAAI,EAAE,QAAR;AAAkBD,MAAAA,KAAK,EAAEF,CAAC,CAACK;AAA3B,KAAP;AACD;AACF,CARD;;IAUqBC,gB;;;;;;;;;;;;;;;oGAiBL,UAACC,IAAD,EAAU;AACtB,UAAQC,OAAR,GAAoB,MAAKC,KAAzB,CAAQD,OAAR;AAEAA,MAAAA,OAAO,CAACT,UAAU,CAACQ,IAAD,CAAX,CAAP;AACD,K;;;;;;WAED,kBAAS;AACP,wBAAiF,KAAKE,KAAtF;AAAA,UAAQC,IAAR,eAAQA,IAAR;AAAA,UAAcC,OAAd,eAAcA,OAAd;AAAA,UAAuBC,SAAvB,eAAuBA,SAAvB;AAAA,UAAkCC,SAAlC,eAAkCA,SAAlC;AAAA,UAA6CC,cAA7C,eAA6CA,cAA7C;AAAA,UAA6DC,eAA7D,eAA6DA,eAA7D;AACA,UAAMC,cAAc,GAAG,qCAAwBF,cAAxB,CAAvB;AAEA,0BACE,gCAAC,kBAAD;AACE,QAAA,SAAS,EAAED,SADb;AAEE,QAAA,OAAO,EAAEF,OAFX;AAGE,QAAA,SAAS,EAAEC,SAHb;AAIE,QAAA,eAAe,EAAEG,eAJnB;AAKE,QAAA,cAAc,EAAE,yBAAa,0BAAaL,IAAb,CAAb,EAAiCM,cAAjC,CALlB;AAME,QAAA,OAAO,EAAE,KAAKC,WANhB;AAOE,QAAA,IAAI,EAAEP;AAPR,QADF;AAWD;;;EAtC2CQ,kBAAMC,S;;;iCAA/Bb,gB,eACA;AACjBO,EAAAA,SAAS,EAAEO,sBAAUC,MADJ;AAEjBX,EAAAA,IAAI,EAAEU,sBAAUE,SAAV,CAAoB,CAACF,sBAAUC,MAAX,EAAmBD,sBAAUG,MAA7B,CAApB,CAFW;AAGjBR,EAAAA,eAAe,EAAEK,sBAAUI,MAHV;AAIjBhB,EAAAA,OAAO,EAAEY,sBAAUK,IAAV,CAAeC,UAJP;AAKjBf,EAAAA,OAAO,EAAES,sBAAUK,IALF;AAMjBb,EAAAA,SAAS,EAAEQ,sBAAUO,IANJ;AAOjBb,EAAAA,cAAc,EAAEM,sBAAUQ;AAPT,C;iCADAtB,gB,kBAWG;AACpBI,EAAAA,IAAI,EAAE,YADc;AAEpBE,EAAAA,SAAS,EAAE,KAFS;AAGpBE,EAAAA,cAAc,EAAE;AAHI,C","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { keysForGrade, normalizeAdditionalKeys } from './keys/grades';\nimport { extendKeySet } from './keys/utils';\nimport Keypad from './keypad';\n\nconst toOldModel = (d) => {\n if (d.command) {\n return { value: d.command, type: 'command' };\n } else if (d.write) {\n return { value: d.write };\n } else if (d.keystroke) {\n return { type: 'cursor', value: d.keystroke };\n }\n};\n\nexport default class HorizontalKeypad extends React.Component {\n static propTypes = {\n className: PropTypes.string,\n mode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n layoutForKeyPad: PropTypes.object,\n onClick: PropTypes.func.isRequired,\n onFocus: PropTypes.func,\n noDecimal: PropTypes.bool,\n additionalKeys: PropTypes.array,\n };\n\n static defaultProps = {\n mode: 'scientific',\n noDecimal: false,\n additionalKeys: [],\n };\n\n keypadPress = (data) => {\n const { onClick } = this.props;\n\n onClick(toOldModel(data));\n };\n\n render() {\n const { mode, onFocus, noDecimal, className, additionalKeys, layoutForKeyPad } = this.props;\n const normalizedKeys = normalizeAdditionalKeys(additionalKeys);\n\n return (\n <Keypad\n className={className}\n onFocus={onFocus}\n noDecimal={noDecimal}\n layoutForKeyPad={layoutForKeyPad}\n additionalKeys={extendKeySet(keysForGrade(mode), normalizedKeys)}\n onPress={this.keypadPress}\n mode={mode}\n />\n );\n }\n}\n"],"file":"horizontal-keypad.js"}
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.jsx"],"names":["addLeftBracket","s","indexOf","addRightBracket","length","rmLeftBracket","substring","rmRightBracket","addBrackets","removeBrackets","updateSpans","spans","Array","from","document","querySelectorAll","forEach","span","innerText","className","style","fontSize"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAoBA;;;;AAEA;;AAEA;;;;;;;;AAtBA,IAAMA,cAAc,GAAG,SAAjBA,cAAiB,CAACC,CAAD;AAAA,SAAQA,CAAC,CAACC,OAAF,CAAU,KAAV,MAAqB,CAArB,GAAyBD,CAAzB,gBAAmCA,CAAnC,CAAR;AAAA,CAAvB;;AACA,IAAME,eAAe,GAAG,SAAlBA,eAAkB,CAACF,CAAD;AAAA,SAAQA,CAAC,CAACC,OAAF,CAAU,KAAV,MAAqBD,CAAC,CAACG,MAAF,GAAW,CAAhC,GAAoCH,CAApC,aAA2CA,CAA3C,QAAR;AAAA,CAAxB;;AACA,IAAMI,aAAa,GAAG,SAAhBA,aAAgB,CAACJ,CAAD;AAAA,SAAQA,CAAC,CAACC,OAAF,CAAU,KAAV,MAAqB,CAArB,GAAyBD,CAAC,CAACK,SAAF,CAAY,CAAZ,CAAzB,GAA0CL,CAAlD;AAAA,CAAtB;;AACA,IAAMM,cAAc,GAAG,SAAjBA,cAAiB,CAACN,CAAD;AAAA,SAAQA,CAAC,CAACC,OAAF,CAAU,KAAV,MAAqBD,CAAC,CAACG,MAAF,GAAW,CAAhC,GAAoCH,CAAC,CAACK,SAAF,CAAY,CAAZ,EAAeL,CAAC,CAACG,MAAF,GAAW,CAA1B,CAApC,GAAmEH,CAA3E;AAAA,CAAvB;;AAEA,IAAMO,WAAW,GAAG,SAAdA,WAAc,CAACP,CAAD;AAAA,SAAOE,eAAe,CAACH,cAAc,CAACC,CAAD,CAAf,CAAtB;AAAA,CAApB;;;;AACA,IAAMQ,cAAc,GAAG,SAAjBA,cAAiB,CAACR,CAAD;AAAA,SAAOM,cAAc,CAACF,aAAa,CAACJ,CAAD,CAAd,CAArB;AAAA,CAAvB,C,CAEA;;;;;AACA,IAAMS,WAAW,GAAG,SAAdA,WAAc,GAAM;AACxB,MAAMC,KAAK,GAAGC,KAAK,CAACC,IAAN,CAAWC,QAAQ,CAACC,gBAAT,CAA0B,4BAA1B,CAAX,CAAd;AACA,GAACJ,KAAK,IAAI,EAAV,EAAcK,OAAd,CAAsB,UAACC,IAAD,EAAU;AAC9B,QAAIA,IAAI,IAAIA,IAAI,CAACC,SAAL,KAAmB,GAA3B,IAAkCD,IAAI,CAACE,SAAL,KAAmB,mBAAzD,EAA8E;AAC5EF,MAAAA,IAAI,CAACG,KAAL,CAAWC,QAAX,GAAsB,MAAtB;AACD;AACF,GAJD;AAKD,CAPD","sourcesContent":["import { keysForGrade } from './keys/grades';\n\nconst addLeftBracket = (s) => (s.indexOf('\\\\(') === 0 ? s : `\\\\(${s}`);\nconst addRightBracket = (s) => (s.indexOf('\\\\)') === s.length - 2 ? s : `${s}\\\\)`);\nconst rmLeftBracket = (s) => (s.indexOf('\\\\(') === 0 ? s.substring(2) : s);\nconst rmRightBracket = (s) => (s.indexOf('\\\\)') === s.length - 2 ? s.substring(0, s.length - 2) : s);\n\nconst addBrackets = (s) => addRightBracket(addLeftBracket(s));\nconst removeBrackets = (s) => rmRightBracket(rmLeftBracket(s));\n\n// increase the font of parallel notation\nconst updateSpans = () => {\n const spans = Array.from(document.querySelectorAll('span[mathquill-command-id]'));\n (spans || []).forEach((span) => {\n if (span && span.innerText === '∥' && span.className !== 'mq-editable-field') {\n span.style.fontSize = '32px';\n }\n });\n};\n\nimport * as keys from './keys';\n\nimport HorizontalKeypad from './horizontal-keypad';\n\nimport * as mq from './mq';\n\nexport { keysForGrade, addBrackets, removeBrackets, keys, HorizontalKeypad, mq, updateSpans };\n"],"file":"index.js"}