@pie-lib/math-input-mathlive 1.0.9-next.6637 → 1.0.10
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/README.md +14 -5
- package/lib/__tests__/composites.test.js +255 -0
- package/lib/__tests__/composites.test.js.map +1 -0
- package/lib/__tests__/drop-in-compat.test.js +133 -0
- package/lib/__tests__/drop-in-compat.test.js.map +1 -0
- package/lib/__tests__/index.test.js +118 -0
- package/lib/__tests__/index.test.js.map +1 -0
- package/lib/__tests__/input-imperative.test.js +155 -0
- package/lib/__tests__/input-imperative.test.js.map +1 -0
- package/lib/__tests__/keypad-label.test.js +118 -0
- package/lib/__tests__/keypad-label.test.js.map +1 -0
- package/lib/__tests__/keypad-render.test.js +206 -0
- package/lib/__tests__/keypad-render.test.js.map +1 -0
- package/lib/__tests__/latex-bridge.test.js +280 -0
- package/lib/__tests__/latex-bridge.test.js.map +1 -0
- package/lib/__tests__/mathlive-instance.test.js +279 -0
- package/lib/__tests__/mathlive-instance.test.js.map +1 -0
- package/lib/__tests__/mount-race.test.js +195 -0
- package/lib/__tests__/mount-race.test.js.map +1 -0
- package/lib/__tests__/static-prompts.test.js +282 -0
- package/lib/__tests__/static-prompts.test.js.map +1 -0
- package/lib/keypad/index.js +11 -13
- package/lib/keypad/index.js.map +1 -1
- package/lib/keys/geometry.js +7 -4
- package/lib/keys/geometry.js.map +1 -1
- package/lib/latex-bridge.js +18 -3
- package/lib/latex-bridge.js.map +1 -1
- package/lib/mathlive-instance.js +103 -11
- package/lib/mathlive-instance.js.map +1 -1
- package/lib/mf/common-styles.js +33 -4
- package/lib/mf/common-styles.js.map +1 -1
- package/lib/mf/input.js +22 -5
- package/lib/mf/input.js.map +1 -1
- package/lib/mf/static.js +21 -4
- package/lib/mf/static.js.map +1 -1
- package/package.json +3 -4
- package/src/__tests__/composites.test.jsx +220 -0
- package/src/__tests__/keypad-label.test.jsx +81 -14
- package/src/__tests__/keypad-render.test.jsx +123 -0
- package/src/__tests__/latex-bridge.test.js +21 -0
- package/src/__tests__/mathlive-instance.test.js +87 -0
- package/src/__tests__/mount-race.test.jsx +130 -0
- package/src/__tests__/static-prompts.test.jsx +251 -0
- package/src/keypad/index.jsx +11 -13
- package/src/keys/geometry.js +7 -2
- package/src/latex-bridge.js +18 -3
- package/src/mathlive-instance.js +111 -11
- package/src/mf/common-styles.js +33 -4
- package/src/mf/input.jsx +23 -5
- package/src/mf/static.jsx +24 -4
- package/LICENSE.md +0 -5
package/src/mf/input.jsx
CHANGED
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { styled } from '@mui/material/styles';
|
|
4
4
|
import debug from 'debug';
|
|
5
|
-
import { loadMathLive, getMacros } from '../mathlive-instance';
|
|
5
|
+
import { loadMathLive, getMacros, MATH_MODE_SPACE, applyShadowStyles } from '../mathlive-instance';
|
|
6
6
|
import { toMathLive, fromMathLive, keyToAction, KEYSTROKES } from '../latex-bridge';
|
|
7
7
|
|
|
8
8
|
const log = debug('pie-lib:math-input-mathlive:input');
|
|
@@ -49,9 +49,16 @@ export class Input extends React.Component {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async componentDidMount() {
|
|
52
|
+
// MathLive loads asynchronously, so this method resumes after an await and
|
|
53
|
+
// has to know whether it is still the current mount. React StrictMode calls
|
|
54
|
+
// mount -> unmount -> mount on the SAME instance in dev, so a boolean
|
|
55
|
+
// "unmounted" flag would latch and block the remount from ever creating a
|
|
56
|
+
// field. A generation counter identifies the live mount instead: only the
|
|
57
|
+
// newest one proceeds, and a real unmount invalidates all pending ones.
|
|
58
|
+
const generation = (this.mountGeneration = (this.mountGeneration || 0) + 1);
|
|
52
59
|
const ml = await loadMathLive();
|
|
53
60
|
|
|
54
|
-
if (!ml || !this.holderRef.current) {
|
|
61
|
+
if (generation !== this.mountGeneration || !ml || !this.holderRef.current || this.mathField) {
|
|
55
62
|
return;
|
|
56
63
|
}
|
|
57
64
|
|
|
@@ -64,15 +71,22 @@ export class Input extends React.Component {
|
|
|
64
71
|
|
|
65
72
|
// pie drives input through its own keypad, so suppress MathLive's.
|
|
66
73
|
this.mathField.mathVirtualKeyboardPolicy = 'manual';
|
|
74
|
+
// Without this the spacebar does nothing: MathLive's mathModeSpace
|
|
75
|
+
// defaults to an empty string.
|
|
76
|
+
this.mathField.mathModeSpace = MATH_MODE_SPACE;
|
|
77
|
+
|
|
78
|
+
// The mathfield renders in shadow DOM, so page CSS cannot reach it - the
|
|
79
|
+
// stretchy-accent fix has to be injected there directly.
|
|
80
|
+
applyShadowStyles(this.mathField);
|
|
67
81
|
|
|
68
82
|
this.mathField.addEventListener('input', this.onInputEdit);
|
|
69
|
-
|
|
83
|
+
|
|
84
|
+
// Belt and braces: drop anything a previous mount may have left behind.
|
|
85
|
+
this.holderRef.current.replaceChildren(this.mathField);
|
|
70
86
|
|
|
71
87
|
if (this.props.innerRef) {
|
|
72
88
|
this.props.innerRef(this);
|
|
73
89
|
}
|
|
74
|
-
|
|
75
|
-
this.setState?.({});
|
|
76
90
|
}
|
|
77
91
|
|
|
78
92
|
componentDidUpdate(prevProps) {
|
|
@@ -99,6 +113,10 @@ export class Input extends React.Component {
|
|
|
99
113
|
}
|
|
100
114
|
|
|
101
115
|
componentWillUnmount() {
|
|
116
|
+
// Invalidate any mount still awaiting the MathLive load, so it does not
|
|
117
|
+
// append a field into a holder that is going away.
|
|
118
|
+
this.mountGeneration = (this.mountGeneration || 0) + 1;
|
|
119
|
+
|
|
102
120
|
if (this.mathField) {
|
|
103
121
|
this.mathField.removeEventListener('input', this.onInputEdit);
|
|
104
122
|
this.mathField.remove();
|
package/src/mf/static.jsx
CHANGED
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { styled } from '@mui/material/styles';
|
|
4
4
|
import debug from 'debug';
|
|
5
|
-
import { loadMathLive, getMacros, latexToMarkup } from '../mathlive-instance';
|
|
5
|
+
import { loadMathLive, getMacros, latexToMarkup, MATH_MODE_SPACE, applyShadowStyles } from '../mathlive-instance';
|
|
6
6
|
import { toMathLive, fromMathLive, fieldIds } from '../latex-bridge';
|
|
7
7
|
import { placeholderStyles } from './common-styles';
|
|
8
8
|
|
|
@@ -64,28 +64,45 @@ export default class Static extends React.Component {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
async componentDidMount() {
|
|
67
|
+
// See the note in mf/input.jsx: a generation counter, not a boolean, so a
|
|
68
|
+
// StrictMode mount -> unmount -> mount on the same instance still ends up
|
|
69
|
+
// with exactly one field.
|
|
70
|
+
const generation = (this.mountGeneration = (this.mountGeneration || 0) + 1);
|
|
71
|
+
|
|
67
72
|
if (!this.isInteractive()) {
|
|
68
73
|
await loadMathLive();
|
|
69
|
-
|
|
74
|
+
|
|
75
|
+
if (generation === this.mountGeneration) {
|
|
76
|
+
this.renderMarkup();
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
return;
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
const ml = await loadMathLive();
|
|
74
83
|
|
|
75
|
-
if (!ml || !this.holderRef.current) {
|
|
84
|
+
if (generation !== this.mountGeneration || !ml || !this.holderRef.current || this.mathField) {
|
|
76
85
|
return;
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
this.mathField = new ml.MathfieldElement({ macros: getMacros() });
|
|
80
89
|
this.mathField.readOnly = true;
|
|
81
90
|
this.mathField.mathVirtualKeyboardPolicy = 'manual';
|
|
91
|
+
// Without this the spacebar does nothing: MathLive's mathModeSpace
|
|
92
|
+
// defaults to an empty string.
|
|
93
|
+
this.mathField.mathModeSpace = MATH_MODE_SPACE;
|
|
82
94
|
this.mathField.value = toMathLive(this.props.latex);
|
|
83
95
|
|
|
96
|
+
// The mathfield renders in shadow DOM, so page CSS cannot reach it - the
|
|
97
|
+
// stretchy-accent fix has to be injected there directly.
|
|
98
|
+
applyShadowStyles(this.mathField);
|
|
99
|
+
|
|
84
100
|
this.mathField.addEventListener('input', this.onPromptInput);
|
|
85
101
|
this.mathField.addEventListener('focusin', this.onPromptFocus);
|
|
86
102
|
this.mathField.addEventListener('keydown', this.onKeyDown);
|
|
87
103
|
|
|
88
|
-
|
|
104
|
+
// Belt and braces: drop anything a previous mount may have left behind.
|
|
105
|
+
this.holderRef.current.replaceChildren(this.mathField);
|
|
89
106
|
|
|
90
107
|
this.createLiveRegion();
|
|
91
108
|
}
|
|
@@ -103,6 +120,9 @@ export default class Static extends React.Component {
|
|
|
103
120
|
}
|
|
104
121
|
|
|
105
122
|
componentWillUnmount() {
|
|
123
|
+
// Invalidate any mount still awaiting the MathLive load.
|
|
124
|
+
this.mountGeneration = (this.mountGeneration || 0) + 1;
|
|
125
|
+
|
|
106
126
|
if (this.mathField) {
|
|
107
127
|
this.mathField.removeEventListener('input', this.onPromptInput);
|
|
108
128
|
this.mathField.removeEventListener('focusin', this.onPromptFocus);
|
package/LICENSE.md
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
Copyright 2019 CoreSpring Inc
|
|
2
|
-
|
|
3
|
-
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
4
|
-
|
|
5
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|