@pie-lib/math-input 6.11.5-next.0 → 6.12.1-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.
- package/CHANGELOG.md +54 -187
- package/NEXT.CHANGELOG.json +1 -0
- package/package.json +6 -2
- package/src/__tests__/__snapshots__/math-input-test.jsx.snap +152 -0
- package/src/__tests__/math-input-test.jsx +85 -0
- package/src/horizontal-keypad.jsx +14 -1
- package/src/index.jsx +1 -10
- package/src/keypad/__tests__/__snapshots__/index.test.jsx.snap +193 -0
- package/src/keypad/__tests__/index.test.jsx +24 -0
- package/src/keypad/__tests__/keys-layout.test.js +15 -0
- package/src/keypad/index.jsx +99 -15
- package/src/keys/__tests__/utils.test.js +57 -0
- package/src/keys/geometry.js +6 -2
- package/src/keys/grades.js +11 -0
- package/src/keys/log.js +1 -1
- package/src/mq/__tests__/__snapshots__/input.test.jsx.snap +9 -0
- package/src/mq/__tests__/input.test.jsx +92 -0
- package/src/mq/__tests__/static.test.jsx +57 -0
- package/src/mq/common-mq-styles.js +105 -0
- package/src/mq/index.js +2 -1
- package/src/mq/input.jsx +22 -9
- package/src/mq/static.jsx +142 -13
- package/src/updateSpans.js +15 -0
- package/README.md +0 -27
- package/lib/horizontal-keypad.js +0 -118
- package/lib/horizontal-keypad.js.map +0 -1
- package/lib/index.js +0 -80
- package/lib/index.js.map +0 -1
- package/lib/keypad/index.js +0 -441
- package/lib/keypad/index.js.map +0 -1
- package/lib/keypad/keys-layout.js +0 -34
- package/lib/keypad/keys-layout.js.map +0 -1
- package/lib/keys/basic-operators.js +0 -41
- package/lib/keys/basic-operators.js.map +0 -1
- package/lib/keys/chars.js +0 -17
- package/lib/keys/chars.js.map +0 -1
- package/lib/keys/comparison.js +0 -49
- package/lib/keys/comparison.js.map +0 -1
- package/lib/keys/constants.js +0 -43
- package/lib/keys/constants.js.map +0 -1
- package/lib/keys/digits.js +0 -53
- package/lib/keys/digits.js.map +0 -1
- package/lib/keys/edit.js +0 -17
- package/lib/keys/edit.js.map +0 -1
- package/lib/keys/exponent.js +0 -36
- package/lib/keys/exponent.js.map +0 -1
- package/lib/keys/fractions.js +0 -34
- package/lib/keys/fractions.js.map +0 -1
- package/lib/keys/geometry.js +0 -167
- package/lib/keys/geometry.js.map +0 -1
- package/lib/keys/grades.js +0 -283
- package/lib/keys/grades.js.map +0 -1
- package/lib/keys/index.js +0 -54
- package/lib/keys/index.js.map +0 -1
- package/lib/keys/log.js +0 -32
- package/lib/keys/log.js.map +0 -1
- package/lib/keys/logic.js +0 -23
- package/lib/keys/logic.js.map +0 -1
- package/lib/keys/matrices.js +0 -23
- package/lib/keys/matrices.js.map +0 -1
- package/lib/keys/misc.js +0 -74
- package/lib/keys/misc.js.map +0 -1
- package/lib/keys/navigation.js +0 -25
- package/lib/keys/navigation.js.map +0 -1
- package/lib/keys/operators.js +0 -18
- package/lib/keys/operators.js.map +0 -1
- package/lib/keys/statistics.js +0 -47
- package/lib/keys/statistics.js.map +0 -1
- package/lib/keys/sub-sup.js +0 -23
- package/lib/keys/sub-sup.js.map +0 -1
- package/lib/keys/trigonometry.js +0 -53
- package/lib/keys/trigonometry.js.map +0 -1
- package/lib/keys/utils.js +0 -120
- package/lib/keys/utils.js.map +0 -1
- package/lib/keys/vars.js +0 -29
- package/lib/keys/vars.js.map +0 -1
- package/lib/math-input.js +0 -192
- package/lib/math-input.js.map +0 -1
- package/lib/mq/custom-elements.js +0 -23
- package/lib/mq/custom-elements.js.map +0 -1
- package/lib/mq/index.js +0 -24
- package/lib/mq/index.js.map +0 -1
- package/lib/mq/input.js +0 -245
- package/lib/mq/input.js.map +0 -1
- package/lib/mq/static.js +0 -233
- package/lib/mq/static.js.map +0 -1
package/src/keys/grades.js
CHANGED
|
@@ -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
|
@@ -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
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
|
-
|
|
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
|
-
|
|
132
|
-
|
|
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 {
|
|
159
|
+
const { onFocus, onBlur, classes, className } = this.props;
|
|
147
160
|
|
|
148
161
|
return (
|
|
149
162
|
<span
|
|
150
163
|
className={classNames(classes.input, className)}
|
|
151
|
-
|
|
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 '../
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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={
|
|
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.
|