@pie-lib/math-input 8.1.2-next.88 → 9.0.0-next.7

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 (183) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +11 -0
  2. package/dist/horizontal-keypad.d.ts +30 -0
  3. package/dist/horizontal-keypad.js +55 -0
  4. package/dist/index.d.ts +17 -0
  5. package/dist/index.js +10 -0
  6. package/dist/keypad/index.d.ts +37 -0
  7. package/dist/keypad/index.js +277 -0
  8. package/dist/keypad/keys-layout.d.ts +15 -0
  9. package/dist/keypad/keys-layout.js +5 -0
  10. package/dist/keys/basic-operators.d.ts +13 -0
  11. package/dist/keys/basic-operators.js +30 -0
  12. package/dist/keys/chars.d.ts +13 -0
  13. package/dist/keys/comparison.d.ts +12 -0
  14. package/dist/keys/comparison.js +32 -0
  15. package/dist/keys/constants.d.ts +12 -0
  16. package/dist/keys/constants.js +35 -0
  17. package/dist/keys/digits.d.ts +23 -0
  18. package/dist/keys/digits.js +34 -0
  19. package/dist/keys/edit.d.ts +14 -0
  20. package/dist/keys/edit.js +9 -0
  21. package/dist/keys/exponent.d.ts +12 -0
  22. package/dist/keys/exponent.js +28 -0
  23. package/dist/keys/fractions.d.ts +11 -0
  24. package/dist/keys/fractions.js +27 -0
  25. package/dist/keys/geometry.d.ts +31 -0
  26. package/dist/keys/geometry.js +127 -0
  27. package/dist/keys/grades.d.ts +17 -0
  28. package/dist/keys/grades.js +414 -0
  29. package/dist/keys/index.d.ts +14 -0
  30. package/dist/keys/index.js +50 -0
  31. package/dist/keys/log.d.ts +11 -0
  32. package/dist/keys/log.js +25 -0
  33. package/dist/keys/logic.d.ts +10 -0
  34. package/dist/keys/logic.js +13 -0
  35. package/dist/keys/matrices.d.ts +10 -0
  36. package/dist/keys/matrices.js +17 -0
  37. package/dist/keys/misc.d.ts +18 -0
  38. package/dist/keys/misc.js +60 -0
  39. package/dist/keys/navigation.d.ts +10 -0
  40. package/dist/keys/navigation.js +13 -0
  41. package/dist/keys/operators.d.ts +9 -0
  42. package/dist/keys/operators.js +11 -0
  43. package/dist/keys/statistics.d.ts +13 -0
  44. package/dist/keys/statistics.js +38 -0
  45. package/dist/keys/sub-sup.d.ts +10 -0
  46. package/dist/keys/sub-sup.js +17 -0
  47. package/dist/keys/trigonometry.d.ts +14 -0
  48. package/dist/keys/trigonometry.js +43 -0
  49. package/dist/keys/utils.d.ts +13 -0
  50. package/dist/keys/utils.js +24 -0
  51. package/dist/keys/vars.d.ts +11 -0
  52. package/dist/keys/vars.js +22 -0
  53. package/dist/math-input.d.ts +30 -0
  54. package/dist/mq/common-mq-styles.d.ts +231 -0
  55. package/dist/mq/common-mq-styles.js +55 -0
  56. package/dist/mq/custom-elements.d.ts +10 -0
  57. package/dist/mq/custom-elements.js +10 -0
  58. package/dist/mq/index.d.ts +12 -0
  59. package/dist/mq/index.js +12 -0
  60. package/dist/mq/input.d.ts +39 -0
  61. package/dist/mq/input.js +83 -0
  62. package/{src/mq/mathquill-instance.js → dist/mq/mathquill-instance.d.ts} +11 -28
  63. package/dist/mq/mathquill-instance.js +13 -0
  64. package/dist/mq/static.d.ts +47 -0
  65. package/dist/mq/static.js +151 -0
  66. package/dist/updateSpans.d.ts +10 -0
  67. package/dist/updateSpans.js +8 -0
  68. package/package.json +29 -15
  69. package/CHANGELOG.json +0 -17
  70. package/CHANGELOG.md +0 -1178
  71. package/LICENSE.md +0 -5
  72. package/lib/horizontal-keypad.js +0 -96
  73. package/lib/horizontal-keypad.js.map +0 -1
  74. package/lib/index.js +0 -69
  75. package/lib/index.js.map +0 -1
  76. package/lib/keypad/index.js +0 -413
  77. package/lib/keypad/index.js.map +0 -1
  78. package/lib/keypad/keys-layout.js +0 -22
  79. package/lib/keypad/keys-layout.js.map +0 -1
  80. package/lib/keys/basic-operators.js +0 -33
  81. package/lib/keys/basic-operators.js.map +0 -1
  82. package/lib/keys/chars.js +0 -12
  83. package/lib/keys/chars.js.map +0 -1
  84. package/lib/keys/comparison.js +0 -39
  85. package/lib/keys/comparison.js.map +0 -1
  86. package/lib/keys/constants.js +0 -37
  87. package/lib/keys/constants.js.map +0 -1
  88. package/lib/keys/digits.js +0 -46
  89. package/lib/keys/digits.js.map +0 -1
  90. package/lib/keys/edit.js +0 -14
  91. package/lib/keys/edit.js.map +0 -1
  92. package/lib/keys/exponent.js +0 -30
  93. package/lib/keys/exponent.js.map +0 -1
  94. package/lib/keys/fractions.js +0 -29
  95. package/lib/keys/fractions.js.map +0 -1
  96. package/lib/keys/geometry.js +0 -140
  97. package/lib/keys/geometry.js.map +0 -1
  98. package/lib/keys/grades.js +0 -259
  99. package/lib/keys/grades.js.map +0 -1
  100. package/lib/keys/index.js +0 -35
  101. package/lib/keys/index.js.map +0 -1
  102. package/lib/keys/log.js +0 -27
  103. package/lib/keys/log.js.map +0 -1
  104. package/lib/keys/logic.js +0 -19
  105. package/lib/keys/logic.js.map +0 -1
  106. package/lib/keys/matrices.js +0 -19
  107. package/lib/keys/matrices.js.map +0 -1
  108. package/lib/keys/misc.js +0 -62
  109. package/lib/keys/misc.js.map +0 -1
  110. package/lib/keys/navigation.js +0 -20
  111. package/lib/keys/navigation.js.map +0 -1
  112. package/lib/keys/operators.js +0 -15
  113. package/lib/keys/operators.js.map +0 -1
  114. package/lib/keys/statistics.js +0 -40
  115. package/lib/keys/statistics.js.map +0 -1
  116. package/lib/keys/sub-sup.js +0 -19
  117. package/lib/keys/sub-sup.js.map +0 -1
  118. package/lib/keys/trigonometry.js +0 -45
  119. package/lib/keys/trigonometry.js.map +0 -1
  120. package/lib/keys/utils.js +0 -87
  121. package/lib/keys/utils.js.map +0 -1
  122. package/lib/keys/vars.js +0 -24
  123. package/lib/keys/vars.js.map +0 -1
  124. package/lib/math-input.js +0 -141
  125. package/lib/math-input.js.map +0 -1
  126. package/lib/mq/common-mq-styles.js +0 -102
  127. package/lib/mq/common-mq-styles.js.map +0 -1
  128. package/lib/mq/custom-elements.js +0 -20
  129. package/lib/mq/custom-elements.js.map +0 -1
  130. package/lib/mq/index.js +0 -28
  131. package/lib/mq/index.js.map +0 -1
  132. package/lib/mq/input.js +0 -186
  133. package/lib/mq/input.js.map +0 -1
  134. package/lib/mq/mathquill-instance.js +0 -52
  135. package/lib/mq/mathquill-instance.js.map +0 -1
  136. package/lib/mq/static.js +0 -301
  137. package/lib/mq/static.js.map +0 -1
  138. package/lib/updateSpans.js +0 -19
  139. package/lib/updateSpans.js.map +0 -1
  140. package/src/__tests__/horizontal-keypad.test.jsx +0 -463
  141. package/src/__tests__/index.test.js +0 -247
  142. package/src/__tests__/math-input-test.jsx +0 -45
  143. package/src/__tests__/updateSpans.test.js +0 -297
  144. package/src/horizontal-keypad.jsx +0 -69
  145. package/src/index.jsx +0 -28
  146. package/src/keypad/__tests__/index.test.jsx +0 -25
  147. package/src/keypad/__tests__/keys-layout.test.js +0 -14
  148. package/src/keypad/index.jsx +0 -439
  149. package/src/keypad/keys-layout.js +0 -16
  150. package/src/keys/__tests__/utils.test.js +0 -57
  151. package/src/keys/basic-operators.js +0 -32
  152. package/src/keys/chars.js +0 -5
  153. package/src/keys/comparison.js +0 -28
  154. package/src/keys/constants.js +0 -35
  155. package/src/keys/digits.js +0 -40
  156. package/src/keys/edit.js +0 -3
  157. package/src/keys/exponent.js +0 -28
  158. package/src/keys/fractions.js +0 -26
  159. package/src/keys/geometry.js +0 -144
  160. package/src/keys/grades.js +0 -367
  161. package/src/keys/index.js +0 -20
  162. package/src/keys/log.js +0 -22
  163. package/src/keys/logic.js +0 -15
  164. package/src/keys/matrices.js +0 -15
  165. package/src/keys/misc.js +0 -65
  166. package/src/keys/navigation.js +0 -8
  167. package/src/keys/operators.js +0 -10
  168. package/src/keys/statistics.js +0 -38
  169. package/src/keys/sub-sup.js +0 -15
  170. package/src/keys/trigonometry.js +0 -15
  171. package/src/keys/utils.js +0 -66
  172. package/src/keys/vars.js +0 -19
  173. package/src/math-input.jsx +0 -119
  174. package/src/mq/__tests__/custom-elements.test.js +0 -342
  175. package/src/mq/__tests__/input.test.jsx +0 -40
  176. package/src/mq/__tests__/mathquill-instance.test.js +0 -67
  177. package/src/mq/__tests__/static.test.jsx +0 -33
  178. package/src/mq/common-mq-styles.js +0 -109
  179. package/src/mq/custom-elements.js +0 -11
  180. package/src/mq/index.js +0 -5
  181. package/src/mq/input.jsx +0 -166
  182. package/src/mq/static.jsx +0 -290
  183. package/src/updateSpans.js +0 -15
@@ -1,67 +0,0 @@
1
- const mockRegisterEmbed = jest.fn();
2
- const mockStaticMath = jest.fn().mockReturnValue({ mockInstance: true });
3
-
4
- jest.mock('@pie-framework/mathquill', () => ({
5
- __esModule: true,
6
- default: {
7
- getInterface: jest.fn(() => ({
8
- registerEmbed: mockRegisterEmbed,
9
- StaticMath: mockStaticMath,
10
- })),
11
- },
12
- }));
13
-
14
- jest.mock('../custom-elements', () => ({
15
- registerLineBreak: jest.fn(),
16
- }));
17
-
18
- describe('mathquill-instance', () => {
19
- let registerEmbed;
20
- let applyStaticMath;
21
-
22
- beforeEach(() => {
23
- jest.resetModules();
24
- mockRegisterEmbed.mockClear();
25
- mockStaticMath.mockClear();
26
- ({ registerEmbed, applyStaticMath } = require('../mathquill-instance'));
27
- });
28
-
29
- describe('registerEmbed', () => {
30
- it('delegates to MQ.registerEmbed when available', () => {
31
- const factory = () => ({});
32
- registerEmbed('answerBlock', factory);
33
-
34
- expect(mockRegisterEmbed).toHaveBeenCalledTimes(1);
35
- expect(mockRegisterEmbed).toHaveBeenCalledWith('answerBlock', factory);
36
- });
37
- });
38
-
39
- describe('applyStaticMath', () => {
40
- it('returns undefined when element is missing', () => {
41
- expect(applyStaticMath(null, 'x')).toBeUndefined();
42
- expect(mockStaticMath).not.toHaveBeenCalled();
43
- });
44
-
45
- it('sets textContent when latex is provided and calls StaticMath', () => {
46
- const el = document.createElement('span');
47
- const handlers = { edit: jest.fn() };
48
-
49
- const result = applyStaticMath(el, '\\frac{1}{2}', { handlers });
50
-
51
- expect(el.textContent).toBe('\\frac{1}{2}');
52
- expect(mockStaticMath).toHaveBeenCalledTimes(1);
53
- expect(mockStaticMath).toHaveBeenCalledWith(el, { handlers });
54
- expect(result).toEqual({ mockInstance: true });
55
- });
56
-
57
- it('omits textContent when latex is undefined but still calls StaticMath', () => {
58
- const el = document.createElement('span');
59
- el.textContent = 'preset';
60
-
61
- applyStaticMath(el, undefined);
62
-
63
- expect(el.textContent).toBe('preset');
64
- expect(mockStaticMath).toHaveBeenCalledWith(el, undefined);
65
- });
66
- });
67
- });
@@ -1,33 +0,0 @@
1
- import * as React from 'react';
2
- import { render } from '@testing-library/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
- describe('rendering', () => {
17
- it('renders with latex prop', () => {
18
- const { container } = render(<Static latex="foo" />);
19
- expect(container.firstChild).toBeInTheDocument();
20
- });
21
-
22
- it('renders with empty latex', () => {
23
- const { container } = render(<Static latex="" />);
24
- expect(container.firstChild).toBeInTheDocument();
25
- });
26
- });
27
-
28
- // Note: Tests for internal methods like componentDidMount, shouldComponentUpdate
29
- // are implementation details and cannot be directly tested with RTL.
30
- // These components are wrappers around MathQuill library and the original tests
31
- // focused on testing internal implementation rather than user-facing behavior.
32
- // The actual MathQuill integration is tested through integration/e2e tests.
33
- });
@@ -1,109 +0,0 @@
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-longdiv-inner .mq-empty': {
78
- padding: '0 !important',
79
- },
80
-
81
- '& .mq-math-mode .mq-supsub': {
82
- fontSize: '70.7% !important',
83
- },
84
-
85
- '& .mq-math-mode .mq-sqrt-stem': {
86
- marginTop: '-5px',
87
- paddingTop: '4px',
88
- },
89
-
90
- '& .mq-math-mode .mq-paren': {
91
- verticalAlign: 'middle !important',
92
- },
93
-
94
- '& .mq-math-mode .mq-overarrow .mq-overarrow-inner .mq-empty': {
95
- padding: '0 !important',
96
- },
97
-
98
- '& .mq-math-mode .mq-overline .mq-overline-inner .mq-empty ': {
99
- padding: '0 !important',
100
- },
101
- },
102
- };
103
-
104
- export default {
105
- commonMqFontStyles,
106
- longdivStyles,
107
- supsubStyles,
108
- commonMqKeyboardStyles,
109
- };
@@ -1,11 +0,0 @@
1
- const registerLineBreak = function(MQ) {
2
- MQ.registerEmbed('newLine', () => {
3
- return {
4
- htmlString: '<div class="newLine"></div>',
5
- text: () => 'testText',
6
- latex: () => '\\embed{newLine}[]',
7
- };
8
- });
9
- };
10
-
11
- export { registerLineBreak };
package/src/mq/index.js DELETED
@@ -1,5 +0,0 @@
1
- import Input from './input';
2
- import Static from './static';
3
- import CommonMqStyles from './common-mq-styles';
4
-
5
- export { Input, Static, CommonMqStyles };
package/src/mq/input.jsx DELETED
@@ -1,166 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { styled } from '@mui/material/styles';
4
- import debug from 'debug';
5
- import { MQ } from './mathquill-instance';
6
-
7
- const log = debug('math-input:mq:input');
8
-
9
- const StyledSpan = styled('span')({
10
- // No specific styles needed, but component is available for future styling
11
- });
12
-
13
- /**
14
- * Wrapper for MathQuill MQ.MathField.
15
- */
16
- export class Input extends React.Component {
17
- static propTypes = {
18
- className: PropTypes.string,
19
- onClick: PropTypes.func,
20
- onChange: PropTypes.func,
21
- latex: PropTypes.string,
22
- onFocus: PropTypes.func,
23
- onBlur: PropTypes.func,
24
- };
25
-
26
- componentDidMount() {
27
- if (!MQ) {
28
- throw new Error('MQ is not defined - but component has mounted?');
29
- }
30
-
31
- this.mathField = MQ.MathField(this.input, {
32
- handlers: {
33
- edit: this.onInputEdit.bind(this),
34
- },
35
- });
36
-
37
- this.updateLatex();
38
- }
39
-
40
- componentDidUpdate() {
41
- this.updateLatex();
42
- }
43
-
44
- updateLatex() {
45
- if (!this.mathField) {
46
- return;
47
- }
48
-
49
- const { latex } = this.props;
50
-
51
- if (latex !== undefined && latex !== null) {
52
- this.mathField.latex(latex);
53
- }
54
- }
55
-
56
- clear() {
57
- this.mathField.latex('');
58
-
59
- return '';
60
- }
61
-
62
- blur() {
63
- log('blur mathfield');
64
- this.mathField.blur();
65
- }
66
-
67
- focus() {
68
- log('focus mathfield...');
69
- this.mathField.focus();
70
- }
71
-
72
- command(v) {
73
- log('command: ', v);
74
- if (Array.isArray(v)) {
75
- v.forEach((vv) => {
76
- this.mathField.cmd(vv);
77
- });
78
- } else {
79
- this.mathField.cmd(v);
80
- }
81
-
82
- this.mathField.focus();
83
-
84
- return this.mathField.latex();
85
- }
86
-
87
- keystroke(v) {
88
- this.mathField.keystroke(v);
89
- this.mathField.focus();
90
-
91
- return this.mathField.latex();
92
- }
93
-
94
- write(v) {
95
- log('write: ', v);
96
- this.mathField.write(v);
97
- this.mathField.focus();
98
-
99
- return this.mathField.latex();
100
- }
101
-
102
- onInputEdit = () => {
103
- log('[onInputEdit] ...');
104
- const { onChange } = this.props;
105
-
106
- if (!this.mathField) {
107
- return;
108
- }
109
-
110
- if (onChange) {
111
- onChange(this.mathField.latex());
112
- }
113
- };
114
-
115
- refresh = () => {
116
- this.blur();
117
- this.focus();
118
- };
119
-
120
- onKeyPress = (event) => {
121
- const keys = Object.keys(this.mathField.__controller.options);
122
-
123
- if (keys.indexOf('ignoreNextMousedown') < 0) {
124
- // It seems like the controller has the above handler as an option
125
- // when all the right events are set and everything works fine
126
- // this seems to work in all cases
127
- this.refresh();
128
- }
129
-
130
- if (event.charCode === 13) {
131
- event.preventDefault();
132
- return;
133
- }
134
- };
135
-
136
- onClick = (event) => {
137
- const { onClick } = this.props;
138
-
139
- this.refresh();
140
- onClick && onClick(event);
141
- };
142
-
143
- shouldComponentUpdate(nextProps) {
144
- log('next: ', nextProps.latex);
145
- log('current: ', this.mathField.latex());
146
-
147
- return nextProps.latex !== this.mathField.latex();
148
- }
149
-
150
- render() {
151
- const { onFocus, onBlur, className } = this.props;
152
-
153
- return (
154
- <StyledSpan
155
- className={className}
156
- onKeyDown={this.onKeyPress}
157
- onClick={this.onClick}
158
- onFocus={onFocus}
159
- onBlur={onBlur}
160
- ref={(r) => (this.input = r)}
161
- />
162
- );
163
- }
164
- }
165
-
166
- export default Input;
package/src/mq/static.jsx DELETED
@@ -1,290 +0,0 @@
1
- import PropTypes from 'prop-types';
2
- import React from 'react';
3
- import debug from 'debug';
4
- import { updateSpans } from '../updateSpans';
5
- import { MQ } from './mathquill-instance';
6
-
7
- const log = debug('pie-lib:math-input:mq:static');
8
- const REGEX = /\\MathQuillMathField\[r\d*\]\{(.*?)\}/g;
9
- const WHITESPACE_REGEX = / /g;
10
-
11
- function stripSpaces(string = '') {
12
- return string.replace(WHITESPACE_REGEX, '');
13
- }
14
-
15
- function countBraces(latex) {
16
- let count = 0;
17
-
18
- for (let i = 0; i < (latex || '').length; i++) {
19
- if (latex[i] === '{') {
20
- count++;
21
- }
22
- }
23
-
24
- return count;
25
- }
26
-
27
- /**
28
- * Wrapper for MathQuill MQ.MathField.
29
- */
30
- export default class Static extends React.Component {
31
- static propTypes = {
32
- latex: PropTypes.string.isRequired,
33
- onFocus: PropTypes.func,
34
- onBlur: PropTypes.func,
35
- className: PropTypes.string,
36
- getFieldName: PropTypes.func,
37
- onSubFieldChange: PropTypes.func,
38
- onSubFieldFocus: PropTypes.func,
39
- setInput: PropTypes.func,
40
- };
41
-
42
- static defaultProps = {
43
- getFieldName: () => {},
44
- };
45
-
46
- constructor(props) {
47
- super(props);
48
- this.state = {
49
- announcement: '',
50
- previousLatex: '',
51
- inputSource: null,
52
- isDeleteKeyPressed: false,
53
- };
54
-
55
- this.inputRef = React.createRef();
56
- }
57
-
58
- componentDidMount() {
59
- this.update();
60
- updateSpans();
61
-
62
- this.createLiveRegion();
63
- this.addEventListeners();
64
- }
65
-
66
- componentDidUpdate() {
67
- this.update();
68
- updateSpans();
69
- }
70
-
71
- componentWillUnmount() {
72
- this.removeLiveRegion();
73
- this.removeEventListeners();
74
- }
75
-
76
- createLiveRegion = () => {
77
- this.liveRegion = document.createElement('div');
78
- this.liveRegion.style.position = 'absolute';
79
- this.liveRegion.style.width = '1px';
80
- this.liveRegion.style.height = '1px';
81
- this.liveRegion.style.marginTop = '-1px';
82
- this.liveRegion.style.clip = 'rect(1px, 1px, 1px, 1px)';
83
- this.liveRegion.style.overflow = 'hidden';
84
- this.liveRegion.setAttribute('aria-live', 'polite');
85
- this.liveRegion.setAttribute('aria-atomic', 'true');
86
-
87
- document.body.appendChild(this.liveRegion);
88
- };
89
-
90
- addEventListeners = () => {
91
- const input = this.inputRef.current;
92
-
93
- if (input) {
94
- input.addEventListener('keydown', this.handleKeyDown);
95
- input.addEventListener('click', this.handleMathKeyboardClick);
96
- }
97
- };
98
-
99
- removeEventListeners = () => {
100
- const input = this.inputRef.current;
101
-
102
- if (input) {
103
- input.removeEventListener('keydown', this.handleKeyDown);
104
- input.removeEventListener('click', this.handleMathKeyboardClick);
105
- }
106
- };
107
-
108
- removeLiveRegion = () => {
109
- if (this.liveRegion) {
110
- document.body.removeChild(this.liveRegion);
111
- this.liveRegion = null;
112
- }
113
- };
114
-
115
- handleKeyDown = (event) => {
116
- if (event?.key === 'Backspace' || event?.key === 'Delete') {
117
- this.setState({ isDeleteKeyPressed: true });
118
- }
119
- this.setState({ inputSource: 'keyboard' });
120
- };
121
-
122
- handleMathKeyboardClick = () => {
123
- this.setState({ inputSource: 'mathKeyboard' });
124
- };
125
-
126
- onInputEdit = (field) => {
127
- if (!this.mathField || this._isProgrammaticUpdate) {
128
- return;
129
- }
130
- const name = this.props.getFieldName(field, this.mathField.innerFields);
131
-
132
- if (this.props.onSubFieldChange) {
133
- // eslint-disable-next-line no-useless-escape
134
- const regexMatch = field.latex().match(/[0-9]\\ \\frac\{[^\{]*\}\{ \}/);
135
-
136
- if (this.inputRef?.current && regexMatch && regexMatch?.length) {
137
- try {
138
- field.__controller.cursor.insLeftOf(field.__controller.cursor.parent[-1].parent);
139
- field.el().dispatchEvent(new KeyboardEvent('keydown', { keyCode: 8 }));
140
- } catch (e) {
141
- // eslint-disable-next-line no-console
142
- console.error(e.toString());
143
- }
144
- } else {
145
- this.props.onSubFieldChange(name, field.latex());
146
- }
147
- }
148
-
149
- this.announceLatexConversion(field.latex());
150
- };
151
-
152
- announceLatexConversion = (newLatex) => {
153
- if (!this.state) {
154
- // eslint-disable-next-line no-console
155
- console.error('State is not initialized');
156
- return;
157
- }
158
-
159
- const { previousLatex, inputSource, isDeleteKeyPressed } = this.state;
160
- const announcement = 'Converted to math symbol';
161
-
162
- if (inputSource === 'keyboard' && !isDeleteKeyPressed) {
163
- const newBraces = countBraces(newLatex);
164
- const oldBraces = countBraces(previousLatex);
165
-
166
- if (newBraces > oldBraces) {
167
- this.announceMessage(announcement);
168
- } else {
169
- try {
170
- this.mathField.parseLatex(previousLatex);
171
- this.mathField.parseLatex(newLatex);
172
-
173
- if (newLatex == previousLatex) {
174
- this.announceMessage(announcement);
175
- }
176
- } catch (e) {
177
- // eslint-disable-next-line no-console
178
- console.warn('Error parsing latex:', e.message);
179
- // eslint-disable-next-line no-console
180
- console.warn(e);
181
- }
182
- }
183
- }
184
-
185
- // Only setState when values change to avoid "Maximum update depth exceeded"
186
- if (this.state.previousLatex !== newLatex || this.state.isDeleteKeyPressed) {
187
- this.setState({ previousLatex: newLatex, isDeleteKeyPressed: false });
188
- }
189
- };
190
-
191
- announceMessage = (message) => {
192
- this.setState({ previousLatex: '' });
193
-
194
- if (this.liveRegion) {
195
- this.liveRegion.textContent = message;
196
-
197
- // Clear the message after it is announced
198
- setTimeout(() => {
199
- this.liveRegion.textContent = '';
200
- }, 500);
201
- }
202
- };
203
-
204
- update = () => {
205
- if (!MQ) {
206
- throw new Error('MQ is not defined - but component has mounted?');
207
- }
208
- if (!this.mathField) {
209
- this.mathField = MQ.StaticMath(this.inputRef?.current, {
210
- handlers: {
211
- edit: this.onInputEdit.bind(this),
212
- },
213
- });
214
- }
215
-
216
- try {
217
- this._isProgrammaticUpdate = true;
218
- this.mathField.parseLatex(this.props.latex);
219
- this.mathField.latex(this.props.latex);
220
- } catch (e) {
221
- // default latex if received has errors
222
- this.mathField.latex('\\MathQuillMathField[r1]{}');
223
- } finally {
224
- this._isProgrammaticUpdate = false;
225
- }
226
- };
227
-
228
-
229
- blur = () => {
230
- log('blur mathfield');
231
- this.mathField.blur();
232
- };
233
-
234
- focus = () => {
235
- log('focus mathfield...');
236
- this.mathField.focus();
237
- };
238
-
239
- shouldComponentUpdate(nextProps) {
240
- try {
241
- const parsedLatex = this.mathField.parseLatex(nextProps.latex);
242
- const stripped = stripSpaces(parsedLatex);
243
- const newFieldCount = (nextProps.latex.match(REGEX) || []).length;
244
-
245
- const out =
246
- stripped !== stripSpaces(this.mathField.latex().trim()) ||
247
- newFieldCount !== Object.keys(this.mathField.innerFields).length / 2;
248
-
249
- log('[shouldComponentUpdate] ', out);
250
- return out;
251
- } catch (e) {
252
- // eslint-disable-next-line no-console
253
- console.warn('Error parsing latex:', e.message, 'skip update');
254
- // eslint-disable-next-line no-console
255
- console.warn(e);
256
- return false;
257
- }
258
- }
259
-
260
- onFocus = (e) => {
261
- try {
262
- let rootBlock = e.target.parentElement.nextSibling;
263
- let id = parseInt(rootBlock.getAttribute('mathquill-block-id'), 10);
264
-
265
- if (!id) {
266
- rootBlock = rootBlock.parentElement;
267
- id = parseInt(rootBlock.getAttribute('mathquill-block-id'), 10);
268
- }
269
-
270
- const innerField = this.mathField.innerFields.find((f) => f.id === id);
271
-
272
- if (innerField) {
273
- const name = this.props.getFieldName(innerField, this.mathField.innerFields);
274
- if (this.props.setInput) {
275
- this.props.setInput(innerField);
276
- }
277
- this.props.onSubFieldFocus(name, innerField);
278
- }
279
- } catch (err) {
280
- // eslint-disable-next-line no-console
281
- console.error('error finding root block', err.message);
282
- }
283
- };
284
-
285
- render() {
286
- const { onBlur, className } = this.props;
287
-
288
- return <span className={className} onFocus={this.onFocus} onBlur={onBlur} ref={this.inputRef} />;
289
- }
290
- }
@@ -1,15 +0,0 @@
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 };