@pie-lib/math-input-mathlive 1.1.5-beta.9 → 2.0.1-next.20261107131445

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 (195) hide show
  1. package/README.md +84 -109
  2. package/dist/_virtual/_rolldown/runtime.js +11 -0
  3. package/dist/horizontal-keypad.d.ts +22 -0
  4. package/dist/horizontal-keypad.js +54 -0
  5. package/dist/index.d.ts +20 -0
  6. package/dist/index.js +12 -0
  7. package/dist/keypad/index.d.ts +40 -0
  8. package/dist/keypad/index.js +245 -0
  9. package/dist/keypad/keys-layout.d.ts +7 -0
  10. package/dist/keypad/keys-layout.js +5 -0
  11. package/dist/keys/basic-operators.d.ts +5 -0
  12. package/dist/keys/basic-operators.js +30 -0
  13. package/dist/keys/chars.d.ts +5 -0
  14. package/dist/keys/comparison.d.ts +4 -0
  15. package/dist/keys/comparison.js +32 -0
  16. package/dist/keys/constants.d.ts +4 -0
  17. package/dist/keys/constants.js +35 -0
  18. package/dist/keys/digits.d.ts +15 -0
  19. package/dist/keys/digits.js +34 -0
  20. package/dist/keys/edit.d.ts +6 -0
  21. package/dist/keys/edit.js +9 -0
  22. package/dist/keys/exponent.d.ts +4 -0
  23. package/dist/keys/exponent.js +28 -0
  24. package/dist/keys/fractions.d.ts +3 -0
  25. package/dist/keys/fractions.js +27 -0
  26. package/dist/keys/geometry.d.ts +23 -0
  27. package/dist/keys/geometry.js +127 -0
  28. package/dist/keys/grades.d.ts +9 -0
  29. package/dist/keys/grades.js +414 -0
  30. package/dist/keys/index.d.ts +6 -0
  31. package/dist/keys/index.js +50 -0
  32. package/dist/keys/log.d.ts +3 -0
  33. package/dist/keys/log.js +25 -0
  34. package/dist/keys/logic.d.ts +2 -0
  35. package/dist/keys/logic.js +13 -0
  36. package/dist/keys/matrices.d.ts +2 -0
  37. package/dist/keys/matrices.js +17 -0
  38. package/dist/keys/misc.d.ts +10 -0
  39. package/dist/keys/misc.js +60 -0
  40. package/dist/keys/navigation.d.ts +2 -0
  41. package/dist/keys/navigation.js +13 -0
  42. package/dist/keys/operators.d.ts +1 -0
  43. package/dist/keys/operators.js +11 -0
  44. package/dist/keys/statistics.d.ts +5 -0
  45. package/dist/keys/statistics.js +38 -0
  46. package/dist/keys/sub-sup.d.ts +2 -0
  47. package/dist/keys/sub-sup.js +17 -0
  48. package/dist/keys/trigonometry.d.ts +6 -0
  49. package/dist/keys/trigonometry.js +43 -0
  50. package/dist/keys/utils.d.ts +5 -0
  51. package/dist/keys/utils.js +24 -0
  52. package/dist/keys/vars.d.ts +3 -0
  53. package/dist/keys/vars.js +22 -0
  54. package/dist/latex-bridge.d.ts +197 -0
  55. package/dist/latex-bridge.js +210 -0
  56. package/dist/longdiv.d.ts +24 -0
  57. package/dist/longdiv.js +43 -0
  58. package/dist/math-input.d.ts +26 -0
  59. package/dist/math-input.js +74 -0
  60. package/dist/mathlive-instance.d.ts +221 -0
  61. package/dist/mathlive-instance.js +159 -0
  62. package/dist/mf/common-styles.d.ts +594 -0
  63. package/dist/mf/common-styles.js +80 -0
  64. package/dist/mf/field-label.d.ts +16 -0
  65. package/dist/mf/field-label.js +13 -0
  66. package/dist/mf/index.d.ts +4 -0
  67. package/dist/mf/index.js +21 -0
  68. package/dist/mf/input.d.ts +94 -0
  69. package/dist/mf/input.js +127 -0
  70. package/dist/mf/static.d.ts +143 -0
  71. package/dist/mf/static.js +230 -0
  72. package/dist/selection.d.ts +43 -0
  73. package/dist/selection.js +39 -0
  74. package/package.json +32 -18
  75. package/lib/__tests__/composites.test.js +0 -255
  76. package/lib/__tests__/drop-in-compat.test.js +0 -133
  77. package/lib/__tests__/embedded-fonts.test.js +0 -121
  78. package/lib/__tests__/index.test.js +0 -118
  79. package/lib/__tests__/input-imperative.test.js +0 -155
  80. package/lib/__tests__/keypad-label.test.js +0 -231
  81. package/lib/__tests__/keypad-render.test.js +0 -206
  82. package/lib/__tests__/latex-bridge.test.js +0 -386
  83. package/lib/__tests__/mathlive-instance.test.js +0 -419
  84. package/lib/__tests__/mount-race.test.js +0 -218
  85. package/lib/__tests__/static-prompts.test.js +0 -405
  86. package/lib/__tests__/tmp-markup.test.js +0 -26
  87. package/lib/horizontal-keypad.js +0 -101
  88. package/lib/horizontal-keypad.js.map +0 -1
  89. package/lib/index.js +0 -143
  90. package/lib/index.js.map +0 -1
  91. package/lib/keypad/index.js +0 -431
  92. package/lib/keypad/index.js.map +0 -1
  93. package/lib/keypad/keys-layout.js +0 -22
  94. package/lib/keypad/keys-layout.js.map +0 -1
  95. package/lib/keys/basic-operators.js +0 -33
  96. package/lib/keys/basic-operators.js.map +0 -1
  97. package/lib/keys/chars.js +0 -12
  98. package/lib/keys/chars.js.map +0 -1
  99. package/lib/keys/comparison.js +0 -39
  100. package/lib/keys/comparison.js.map +0 -1
  101. package/lib/keys/constants.js +0 -37
  102. package/lib/keys/constants.js.map +0 -1
  103. package/lib/keys/digits.js +0 -46
  104. package/lib/keys/digits.js.map +0 -1
  105. package/lib/keys/edit.js +0 -14
  106. package/lib/keys/edit.js.map +0 -1
  107. package/lib/keys/exponent.js +0 -30
  108. package/lib/keys/exponent.js.map +0 -1
  109. package/lib/keys/fractions.js +0 -29
  110. package/lib/keys/fractions.js.map +0 -1
  111. package/lib/keys/geometry.js +0 -143
  112. package/lib/keys/geometry.js.map +0 -1
  113. package/lib/keys/grades.js +0 -259
  114. package/lib/keys/grades.js.map +0 -1
  115. package/lib/keys/index.js +0 -35
  116. package/lib/keys/index.js.map +0 -1
  117. package/lib/keys/log.js +0 -27
  118. package/lib/keys/log.js.map +0 -1
  119. package/lib/keys/logic.js +0 -19
  120. package/lib/keys/logic.js.map +0 -1
  121. package/lib/keys/matrices.js +0 -19
  122. package/lib/keys/matrices.js.map +0 -1
  123. package/lib/keys/misc.js +0 -69
  124. package/lib/keys/misc.js.map +0 -1
  125. package/lib/keys/navigation.js +0 -20
  126. package/lib/keys/navigation.js.map +0 -1
  127. package/lib/keys/operators.js +0 -15
  128. package/lib/keys/operators.js.map +0 -1
  129. package/lib/keys/statistics.js +0 -40
  130. package/lib/keys/statistics.js.map +0 -1
  131. package/lib/keys/sub-sup.js +0 -19
  132. package/lib/keys/sub-sup.js.map +0 -1
  133. package/lib/keys/trigonometry.js +0 -45
  134. package/lib/keys/trigonometry.js.map +0 -1
  135. package/lib/keys/utils.js +0 -87
  136. package/lib/keys/utils.js.map +0 -1
  137. package/lib/keys/vars.js +0 -24
  138. package/lib/keys/vars.js.map +0 -1
  139. package/lib/latex-bridge.js +0 -508
  140. package/lib/latex-bridge.js.map +0 -1
  141. package/lib/math-input.js +0 -143
  142. package/lib/math-input.js.map +0 -1
  143. package/lib/mathlive-instance.js +0 -585
  144. package/lib/mathlive-instance.js.map +0 -1
  145. package/lib/mf/common-styles.js +0 -203
  146. package/lib/mf/common-styles.js.map +0 -1
  147. package/lib/mf/index.js +0 -84
  148. package/lib/mf/index.js.map +0 -1
  149. package/lib/mf/input.js +0 -364
  150. package/lib/mf/input.js.map +0 -1
  151. package/lib/mf/static.js +0 -500
  152. package/lib/mf/static.js.map +0 -1
  153. package/src/__tests__/composites.test.jsx +0 -220
  154. package/src/__tests__/drop-in-compat.test.jsx +0 -112
  155. package/src/__tests__/index.test.jsx +0 -109
  156. package/src/__tests__/input-imperative.test.jsx +0 -144
  157. package/src/__tests__/keypad-label.test.jsx +0 -283
  158. package/src/__tests__/keypad-render.test.jsx +0 -123
  159. package/src/__tests__/latex-bridge.test.js +0 -389
  160. package/src/__tests__/mathlive-instance.test.js +0 -418
  161. package/src/__tests__/mount-race.test.jsx +0 -142
  162. package/src/__tests__/static-prompts.test.jsx +0 -364
  163. package/src/horizontal-keypad.jsx +0 -73
  164. package/src/index.jsx +0 -63
  165. package/src/keypad/index.jsx +0 -386
  166. package/src/keypad/keys-layout.js +0 -16
  167. package/src/keys/basic-operators.js +0 -32
  168. package/src/keys/chars.js +0 -5
  169. package/src/keys/comparison.js +0 -28
  170. package/src/keys/constants.js +0 -35
  171. package/src/keys/digits.js +0 -40
  172. package/src/keys/edit.js +0 -3
  173. package/src/keys/exponent.js +0 -28
  174. package/src/keys/fractions.js +0 -26
  175. package/src/keys/geometry.js +0 -149
  176. package/src/keys/grades.js +0 -367
  177. package/src/keys/index.js +0 -20
  178. package/src/keys/log.js +0 -22
  179. package/src/keys/logic.js +0 -15
  180. package/src/keys/matrices.js +0 -15
  181. package/src/keys/misc.js +0 -71
  182. package/src/keys/navigation.js +0 -8
  183. package/src/keys/operators.js +0 -10
  184. package/src/keys/statistics.js +0 -38
  185. package/src/keys/sub-sup.js +0 -15
  186. package/src/keys/trigonometry.js +0 -15
  187. package/src/keys/utils.js +0 -66
  188. package/src/keys/vars.js +0 -19
  189. package/src/latex-bridge.js +0 -524
  190. package/src/math-input.jsx +0 -115
  191. package/src/mathlive-instance.js +0 -582
  192. package/src/mf/common-styles.js +0 -210
  193. package/src/mf/index.js +0 -30
  194. package/src/mf/input.jsx +0 -319
  195. package/src/mf/static.jsx +0 -479
@@ -1,220 +0,0 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
-
4
- import MathInput from '../math-input';
5
- import HorizontalKeypad from '../horizontal-keypad';
6
- import Input from '../mf/input';
7
-
8
- /**
9
- * The pieces that sit between the keypad and the field: how a pressed key is
10
- * routed into the field, and the legacy `{value,type}` shape math-toolbar
11
- * consumes.
12
- */
13
- describe('MathInput.keypadPress routing', () => {
14
- const withInput = () => {
15
- const mi = new MathInput({});
16
- const calls = { write: [], keystroke: [] };
17
-
18
- mi.input = {
19
- write: (v) => calls.write.push(v),
20
- keystroke: (v) => calls.keystroke.push(v),
21
- };
22
-
23
- return { mi, calls };
24
- };
25
-
26
- it('routes an insert action to write()', () => {
27
- const { mi, calls } = withInput();
28
-
29
- mi.keypadPress({ latex: '\\pi' });
30
-
31
- expect(calls.write).toEqual(['\\pi']);
32
- expect(calls.keystroke).toEqual([]);
33
- });
34
-
35
- it('expands an argument-taking command before writing', () => {
36
- const { mi, calls } = withInput();
37
-
38
- mi.keypadPress({ command: '\\frac' });
39
-
40
- expect(calls.write).toEqual(['\\frac{#?}{#?}']);
41
- });
42
-
43
- it('routes a cursor keystroke to keystroke()', () => {
44
- const { mi, calls } = withInput();
45
-
46
- mi.keypadPress({ keystroke: 'Left' });
47
-
48
- expect(calls.keystroke).toEqual(['moveToPreviousChar']);
49
- expect(calls.write).toEqual([]);
50
- });
51
-
52
- it('ignores keys with no action', () => {
53
- const { mi, calls } = withInput();
54
-
55
- mi.keypadPress({});
56
- mi.keypadPress({ keystroke: 'Nonsense' });
57
-
58
- expect(calls.write).toEqual([]);
59
- expect(calls.keystroke).toEqual([]);
60
- });
61
-
62
- it('is a no-op before the field ref exists', () => {
63
- const mi = new MathInput({});
64
-
65
- expect(() => mi.keypadPress({ latex: '\\pi' })).not.toThrow();
66
- });
67
-
68
- it('changeLatex only fires onChange when the value differs', () => {
69
- const onChange = jest.fn();
70
- const mi = new MathInput({ latex: 'x', onChange });
71
-
72
- mi.changeLatex('x');
73
- expect(onChange).not.toHaveBeenCalled();
74
-
75
- mi.changeLatex('y');
76
- expect(onChange).toHaveBeenCalledWith('y');
77
- });
78
-
79
- it('tracks focus state', () => {
80
- const mi = new MathInput({});
81
-
82
- mi.setState = (s) => Object.assign(mi.state, s);
83
- mi.inputFocus();
84
- expect(mi.state.focused).toBe(true);
85
-
86
- mi.inputBlur();
87
- expect(mi.state.focused).toBe(false);
88
- });
89
- });
90
-
91
- describe('HorizontalKeypad legacy {value,type} model', () => {
92
- const pressed = (key) => {
93
- const onClick = jest.fn();
94
- const hk = new HorizontalKeypad({ onClick });
95
-
96
- hk.keypadPress(key);
97
-
98
- return onClick.mock.calls[0][0];
99
- };
100
-
101
- it('maps a command to {value, type: command}', () => {
102
- expect(pressed({ command: '\\frac' })).toEqual({ value: '\\frac', type: 'command' });
103
- });
104
-
105
- it('maps a write to {value}', () => {
106
- expect(pressed({ write: 'x' })).toEqual({ value: 'x' });
107
- });
108
-
109
- it('maps a keystroke to {type: cursor}', () => {
110
- expect(pressed({ keystroke: 'Left' })).toEqual({ type: 'cursor', value: 'Left' });
111
- });
112
-
113
- it('renders without throwing', () => {
114
- expect(() => render(<HorizontalKeypad onClick={() => {}} />)).not.toThrow();
115
- });
116
- });
117
-
118
- describe('Input: controlled-value sync and events', () => {
119
- const withField = () => {
120
- const input = new Input({});
121
-
122
- input.mathField = {
123
- value: '',
124
- getValue: () => input.mathField.value,
125
- insert(v) {
126
- input.mathField.value += v;
127
- },
128
- executeCommand() {},
129
- focus() {},
130
- blur() {},
131
- addEventListener() {},
132
- removeEventListener() {},
133
- remove() {},
134
- };
135
-
136
- return input;
137
- };
138
-
139
- it('emits stored-form latex on edit', () => {
140
- const onChange = jest.fn();
141
- const input = withField();
142
-
143
- input.props = { onChange };
144
- input.mathField.value = '\\longdiv{\\placeholder{}}';
145
- input.onInputEdit();
146
-
147
- // \placeholder is MathLive-internal and must not reach the model
148
- expect(onChange).toHaveBeenCalledWith('\\longdiv{}');
149
- expect(input.lastEmitted).toEqual('\\longdiv{}');
150
- });
151
-
152
- it('does not push a prop echo back into the field', () => {
153
- const input = withField();
154
-
155
- input.mathField.value = 'x';
156
- input.lastEmitted = 'x';
157
- input.props = { latex: 'x' };
158
-
159
- input.componentDidUpdate({ latex: '' });
160
-
161
- expect(input.mathField.value).toEqual('x');
162
- });
163
-
164
- it('pushes a genuinely new latex prop into the field', () => {
165
- const input = withField();
166
-
167
- input.mathField.value = 'x';
168
- input.lastEmitted = 'x';
169
- input.props = { latex: 'y' };
170
-
171
- input.componentDidUpdate({ latex: 'x' });
172
-
173
- expect(input.mathField.value).toEqual('y');
174
- });
175
-
176
- it('bridges stored latex on the way in', () => {
177
- const input = withField();
178
-
179
- input.props = { latex: '\\longdiv{5}' };
180
- input.componentDidUpdate({ latex: '' });
181
-
182
- // must become native \enclose so the content stays editable
183
- expect(input.mathField.value).toEqual('\\enclose{longdiv}{5}');
184
- });
185
-
186
- it('toggles readOnly', () => {
187
- const input = withField();
188
-
189
- input.props = { readOnly: true };
190
- input.componentDidUpdate({ readOnly: false });
191
-
192
- expect(input.mathField.readOnly).toBe(true);
193
- });
194
-
195
- it('clear() empties the field', () => {
196
- const input = withField();
197
-
198
- input.mathField.value = 'abc';
199
- expect(input.clear()).toEqual('');
200
- expect(input.mathField.value).toEqual('');
201
- });
202
-
203
- it('suppresses Enter so it cannot insert a line break', () => {
204
- const input = withField();
205
- const preventDefault = jest.fn();
206
-
207
- input.onKeyDown({ key: 'Enter', preventDefault });
208
- expect(preventDefault).toHaveBeenCalled();
209
-
210
- preventDefault.mockClear();
211
- input.onKeyDown({ key: 'a', preventDefault });
212
- expect(preventDefault).not.toHaveBeenCalled();
213
- });
214
-
215
- it('componentDidUpdate is safe before the field exists', () => {
216
- const input = new Input({ latex: 'x' });
217
-
218
- expect(() => input.componentDidUpdate({ latex: '' })).not.toThrow();
219
- });
220
- });
@@ -1,112 +0,0 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
- import { styled } from '@mui/material/styles';
4
-
5
- import { mq } from '../index';
6
-
7
- /**
8
- * Exercises the exact call patterns real consumers use against
9
- * @pie-lib/math-input, to catch drop-in incompatibilities.
10
- *
11
- * Sources:
12
- * - packages/math-toolbar/src/editor-and-pad.jsx:16,185
13
- * - packages/math-toolbar/src/math-preview.jsx:8,156
14
- * - packages/editable-html/src/plugins/respArea/math-templated/index.jsx:92
15
- * - packages/editable-html-tip-tap/src/components/respArea/MathTemplated.jsx:111
16
- */
17
- describe('drop-in compatibility with @pie-lib/math-input consumers', () => {
18
- describe('mq.CommonMqStyles destructuring', () => {
19
- it('math-preview.jsx: { commonMqFontStyles, longdivStyles, supsubStyles }', () => {
20
- const { commonMqFontStyles, longdivStyles, supsubStyles } = mq.CommonMqStyles;
21
-
22
- expect(commonMqFontStyles).toBeDefined();
23
- expect(longdivStyles).toBeDefined();
24
- expect(supsubStyles).toBeDefined();
25
- });
26
-
27
- it('editor-and-pad.jsx: also { commonMqKeyboardStyles }', () => {
28
- const { commonMqFontStyles, commonMqKeyboardStyles, longdivStyles, supsubStyles } = mq.CommonMqStyles;
29
-
30
- expect(commonMqKeyboardStyles).toBeDefined();
31
- // All four must be spreadable into an emotion style object.
32
- expect(() => ({
33
- ...commonMqFontStyles,
34
- ...commonMqKeyboardStyles,
35
- ...longdivStyles,
36
- ...supsubStyles,
37
- })).not.toThrow();
38
- });
39
-
40
- it('the destructured groups survive being spread into a styled component', () => {
41
- const { commonMqFontStyles, longdivStyles, supsubStyles } = mq.CommonMqStyles;
42
- const Styled = styled('div')({ ...commonMqFontStyles, ...longdivStyles, ...supsubStyles });
43
-
44
- expect(() => render(<Styled />)).not.toThrow();
45
- });
46
- });
47
-
48
- describe('mq.Input', () => {
49
- it('editor-and-pad.jsx: styled(mq.Input) renders', () => {
50
- const MathEditor = styled(mq.Input)(() => ({ width: '100%' }));
51
-
52
- expect(() => render(<MathEditor latex="\\frac{1}{2}" onChange={() => {}} />)).not.toThrow();
53
- });
54
-
55
- it('accepts the className that styled() injects', () => {
56
- const Styled = styled(mq.Input)({ padding: 4 });
57
- const { container } = render(<Styled latex="x" onChange={() => {}} />);
58
-
59
- expect(container.firstChild).toBeTruthy();
60
- expect(container.firstChild.className).toBeTruthy();
61
- });
62
- });
63
-
64
- describe('mq.Static', () => {
65
- it('math-preview.jsx: <mq.Static latex onFocus onBlur />', () => {
66
- expect(() => render(<mq.Static latex={'\\frac{1}{2}'} onFocus={() => {}} onBlur={() => {}} />)).not.toThrow();
67
- });
68
-
69
- it('math-templated respArea: <mq.Static latex={value} />', () => {
70
- expect(() => render(<mq.Static latex={'x=1'} />)).not.toThrow();
71
- });
72
-
73
- it('renders answer-block latex (the templated-math case) without throwing', () => {
74
- expect(() =>
75
- render(<mq.Static latex={'x=\\MathQuillMathField[r1]{}'} onSubFieldChange={() => {}} />),
76
- ).not.toThrow();
77
- });
78
-
79
- it('is styleable, as keypad labels were in math-input', () => {
80
- const Styled = styled(mq.Static)({ pointerEvents: 'none' });
81
-
82
- expect(() => render(<Styled latex={'\\pi'} />)).not.toThrow();
83
- });
84
- });
85
-
86
- describe('surface parity', () => {
87
- it('exposes exactly the names math-input exported', () => {
88
- // eslint-disable-next-line global-require
89
- const pkg = require('../index');
90
-
91
- [
92
- 'keysForGrade',
93
- 'addBrackets',
94
- 'removeBrackets',
95
- 'keys',
96
- 'HorizontalKeypad',
97
- 'mq',
98
- 'updateSpans',
99
- 'registerEmbed',
100
- 'applyStaticMath',
101
- ].forEach((name) => {
102
- expect(pkg[name]).toBeDefined();
103
- });
104
- });
105
-
106
- it('mq exposes Input, Static and CommonMqStyles', () => {
107
- ['Input', 'Static', 'CommonMqStyles'].forEach((name) => {
108
- expect(mq[name]).toBeDefined();
109
- });
110
- });
111
- });
112
- });
@@ -1,109 +0,0 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
-
4
- import {
5
- keys,
6
- keysForGrade,
7
- addBrackets,
8
- removeBrackets,
9
- registerEmbed,
10
- applyStaticMath,
11
- updateSpans,
12
- mf,
13
- mq,
14
- MathInput,
15
- HorizontalKeypad,
16
- KeyPad,
17
- } from '../index';
18
-
19
- describe('math-input-mathlive public API', () => {
20
- it('mirrors the @pie-lib/math-input export surface', () => {
21
- expect(typeof keysForGrade).toBe('function');
22
- expect(typeof addBrackets).toBe('function');
23
- expect(typeof removeBrackets).toBe('function');
24
- expect(typeof registerEmbed).toBe('function');
25
- expect(typeof applyStaticMath).toBe('function');
26
- expect(typeof updateSpans).toBe('function');
27
- expect(keys).toBeDefined();
28
- expect(keys.baseSet).toBeDefined();
29
- });
30
-
31
- it('exports the field wrappers under both mf and mq', () => {
32
- expect(mf.Input).toBeDefined();
33
- expect(mf.Static).toBeDefined();
34
- // `mq` alias lets a consumer swap packages by changing only the import.
35
- expect(mq).toBe(mf);
36
- });
37
-
38
- it('updateSpans is a safe no-op', () => {
39
- expect(() => updateSpans()).not.toThrow();
40
- });
41
-
42
- it('CommonMqStyles keeps the shape consumers destructure', () => {
43
- // math-toolbar does:
44
- // const { commonMqFontStyles, commonMqKeyboardStyles, longdivStyles, supsubStyles }
45
- // = mq.CommonMqStyles;
46
- const { commonMqFontStyles, commonMqKeyboardStyles, longdivStyles, supsubStyles } = mf.CommonMqStyles;
47
-
48
- [commonMqFontStyles, commonMqKeyboardStyles, longdivStyles, supsubStyles].forEach((s) => {
49
- expect(s).toBeDefined();
50
- expect(typeof s).toBe('object');
51
- });
52
- });
53
-
54
- it('bracket helpers round-trip', () => {
55
- expect(addBrackets('x')).toEqual('\\(x\\)');
56
- expect(removeBrackets('\\(x\\)')).toEqual('x');
57
- expect(removeBrackets(addBrackets('\\frac{1}{2}'))).toEqual('\\frac{1}{2}');
58
- });
59
-
60
- it('keysForGrade returns a 5-row keyset', () => {
61
- const set = keysForGrade('geometry');
62
-
63
- expect(Array.isArray(set)).toBe(true);
64
- expect(set.length).toBe(5);
65
- });
66
- });
67
-
68
- describe('rendering', () => {
69
- // MathLive is a browser-only custom element; loadMathLive() resolves async and
70
- // is a no-op-ish under jsdom. These assert the components mount without
71
- // throwing, which is what regressed most often in the MathQuill version.
72
- it('KeyPad renders without a live MathLive instance', () => {
73
- const { container } = render(<KeyPad onPress={() => {}} />);
74
-
75
- expect(container.querySelectorAll('button').length).toBeGreaterThan(0);
76
- });
77
-
78
- it('KeyPad falls back to raw latex for labels before MathLive loads', () => {
79
- const { container } = render(
80
- <KeyPad onPress={() => {}} baseSet={[[{ name: 'pi', latex: '\\pi', category: 'constants' }]]} />,
81
- );
82
-
83
- expect(container.textContent).toContain('\\pi');
84
- });
85
-
86
- it('KeyPad fires onPress with the key definition', () => {
87
- const onPress = jest.fn();
88
- const key = { name: 'x', label: 'x', write: 'x', category: 'vars' };
89
- const { container } = render(<KeyPad onPress={onPress} baseSet={[[key]]} />);
90
-
91
- container.querySelector('button').click();
92
-
93
- expect(onPress).toHaveBeenCalledWith(key);
94
- });
95
-
96
- it('MathInput mounts', () => {
97
- expect(() => render(<MathInput latex="\\frac{1}{2}" onChange={() => {}} />)).not.toThrow();
98
- });
99
-
100
- it('HorizontalKeypad mounts and reports the legacy {value,type} model', () => {
101
- const onClick = jest.fn();
102
-
103
- expect(() => render(<HorizontalKeypad onClick={onClick} />)).not.toThrow();
104
- });
105
-
106
- it('Static renders display-mode latex without a mathfield', () => {
107
- expect(() => render(<mf.Static latex="\\frac{1}{2}" />)).not.toThrow();
108
- });
109
- });
@@ -1,144 +0,0 @@
1
- import { KEYSTROKES, keyToAction } from '../latex-bridge';
2
- import Input from '../mf/input';
3
-
4
- /**
5
- * The imperative surface that @pie-lib/math-toolbar drives
6
- * (editor-and-pad.jsx: clear/command/keystroke/write/latex).
7
- *
8
- * These call the methods against a stub mathfield, because a real
9
- * <math-field> needs a browser. What matters here is the *translation*:
10
- * MathQuill-era arguments must become valid MathLive operations.
11
- */
12
- const stubField = () => {
13
- const calls = { insert: [], executeCommand: [], focus: 0 };
14
-
15
- return {
16
- calls,
17
- value: '',
18
- getValue: () => '',
19
- insert(v) {
20
- calls.insert.push(v);
21
- },
22
- executeCommand(v) {
23
- calls.executeCommand.push(v);
24
- },
25
- focus() {
26
- calls.focus++;
27
- },
28
- blur() {},
29
- };
30
- };
31
-
32
- const withField = () => {
33
- const input = new Input({});
34
- const f = stubField();
35
-
36
- input.mathField = f;
37
-
38
- return { input, f };
39
- };
40
-
41
- describe('Input imperative API (drives math-toolbar)', () => {
42
- describe('keystroke', () => {
43
- it('maps MathQuill keystroke names to MathLive selectors', () => {
44
- const { input, f } = withField();
45
-
46
- input.keystroke('Left');
47
- input.keystroke('Right');
48
- input.keystroke('Backspace');
49
-
50
- expect(f.calls.executeCommand).toEqual(['moveToPreviousChar', 'moveToNextChar', 'deleteBackward']);
51
- });
52
-
53
- it('passes an unknown value through as a selector', () => {
54
- const { input, f } = withField();
55
-
56
- input.keystroke('deleteForward');
57
-
58
- expect(f.calls.executeCommand).toEqual(['deleteForward']);
59
- });
60
-
61
- it('does not throw when the engine rejects the selector', () => {
62
- const { input } = withField();
63
-
64
- input.mathField.executeCommand = () => {
65
- throw new Error('unknown command');
66
- };
67
-
68
- expect(() => input.keystroke('Nonsense')).not.toThrow();
69
- });
70
-
71
- it('covers every keystroke the keypad emits', () => {
72
- // navigation.js / edit.js only produce these three
73
- ['Left', 'Right', 'Backspace'].forEach((k) => expect(KEYSTROKES[k]).toBeDefined());
74
- });
75
- });
76
-
77
- describe('command', () => {
78
- it('expands argument-taking commands into placeholders', () => {
79
- const { input, f } = withField();
80
-
81
- input.command('\\frac');
82
-
83
- // a bare \frac would give no editable slots
84
- expect(f.calls.insert).toEqual(['\\frac{#?}{#?}']);
85
- });
86
-
87
- it('handles array commands', () => {
88
- const { input, f } = withField();
89
-
90
- input.command(['\\log', '_']);
91
-
92
- expect(f.calls.insert).toEqual(['\\log_{#?}']);
93
- });
94
-
95
- it('passes argument-less commands through', () => {
96
- const { input, f } = withField();
97
-
98
- input.command('\\pi');
99
-
100
- expect(f.calls.insert).toEqual(['\\pi']);
101
- });
102
-
103
- it('agrees with keyToAction', () => {
104
- expect(keyToAction({ command: '\\sqrt' }).value).toEqual('\\sqrt{#?}');
105
- });
106
- });
107
-
108
- describe('safety before MathLive loads', () => {
109
- it('every method is a no-op rather than a crash', () => {
110
- const input = new Input({});
111
-
112
- // mathField is undefined until loadMathLive() resolves
113
- expect(input.latex()).toEqual('');
114
- expect(input.clear()).toEqual('');
115
- expect(input.command('\\frac')).toEqual('');
116
- expect(input.keystroke('Left')).toEqual('');
117
- expect(input.write('x')).toEqual('');
118
- expect(() => input.focus()).not.toThrow();
119
- expect(() => input.blur()).not.toThrow();
120
- expect(() => input.setLatex('x')).not.toThrow();
121
- expect(input.element).toBeUndefined();
122
- });
123
- });
124
-
125
- describe('mqCompat facade', () => {
126
- // math-toolbar used to call this.input.mathField.latex(); external
127
- // consumers may still do the same.
128
- it('exposes latex() as a getter', () => {
129
- const { input } = withField();
130
-
131
- input.mathField.getValue = () => '\\frac{1}{2}';
132
-
133
- expect(input.mqCompat.latex()).toEqual('\\frac{1}{2}');
134
- });
135
-
136
- it('exposes latex(v) as a setter and el()', () => {
137
- const { input, f } = withField();
138
-
139
- input.mqCompat.latex('x+1');
140
- expect(f.value).toEqual('x+1');
141
- expect(input.mqCompat.el()).toBe(f);
142
- });
143
- });
144
- });