@zzish/math-rich-input 0.1.55 → 0.1.56
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/dist/index.js +30 -4
- package/dist/standalone.js +1 -1
- package/package.json +4 -2
- package/src/MathRichInput.jsx +35 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zzish/math-rich-input",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.56",
|
|
4
4
|
"description": "React component for user to enter rich text with embedded math equations.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"scripts": {
|
|
16
|
+
"test": "playwright test tests/caret-regression.spec.js --workers=1",
|
|
16
17
|
"build": "rollup --config && webpack --config webpack.standalone.config.js",
|
|
17
18
|
"build:legacy": "rollup --config",
|
|
18
19
|
"build:standalone": "webpack --config webpack.standalone.config.js",
|
|
19
|
-
"prepublishOnly": "npm run build"
|
|
20
|
+
"prepublishOnly": "npm test && npm run build"
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
23
|
"katex": "^0.12.0",
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"@babel/preset-env": "^7.24.5",
|
|
37
38
|
"@babel/preset-react": "^7.24.1",
|
|
38
39
|
"@babel/register": "^7.13.8",
|
|
40
|
+
"@playwright/test": "^1.62.1",
|
|
39
41
|
"@rollup/plugin-babel": "^5.3.0",
|
|
40
42
|
"@rollup/plugin-commonjs": "^17.1.0",
|
|
41
43
|
"@rollup/plugin-node-resolve": "^11.2.0",
|
package/src/MathRichInput.jsx
CHANGED
|
@@ -84,6 +84,7 @@ const EMPTY_INLINE_FORMATTING_REG_EXP =
|
|
|
84
84
|
// const LATEX_MARKER_END = "</annotation>"
|
|
85
85
|
|
|
86
86
|
const MAX_HISTORY_LENGTH = 100;
|
|
87
|
+
const CONTROLLED_VALUE_ECHO_TIMEOUT_MS = 50;
|
|
87
88
|
|
|
88
89
|
const DEFAULT_OPTIONS = {
|
|
89
90
|
useExpertMode: false,
|
|
@@ -367,6 +368,21 @@ export default class MathRichInput extends React.Component {
|
|
|
367
368
|
|
|
368
369
|
// Call the parent handler to apply the changes
|
|
369
370
|
this.onChangeCallback({ value, mimeType }, { isExpertMode, selectedTab });
|
|
371
|
+
if (applyOptions.skipControlledRender === true) {
|
|
372
|
+
const pendingNativeValue = value;
|
|
373
|
+
// Give a scheduled controlled echo one short render window. If the host
|
|
374
|
+
// never echoes the value, release the gate rather than preserving a
|
|
375
|
+
// rejected native edit indefinitely.
|
|
376
|
+
setTimeout(() => {
|
|
377
|
+
if (
|
|
378
|
+
this.skipNextControlledValueRender === true &&
|
|
379
|
+
this.skipNextControlledValue === pendingNativeValue
|
|
380
|
+
) {
|
|
381
|
+
this.skipNextControlledValueRender = false;
|
|
382
|
+
this.skipNextControlledValue = null;
|
|
383
|
+
}
|
|
384
|
+
}, CONTROLLED_VALUE_ECHO_TIMEOUT_MS);
|
|
385
|
+
}
|
|
370
386
|
debugMathRichInput("applyChangesToComponent:after-onChange", {
|
|
371
387
|
afterComponentUpdateData: this.afterComponentUpdateData,
|
|
372
388
|
selection: getSelectionSnapshot(this.editableDiv),
|
|
@@ -587,6 +603,9 @@ export default class MathRichInput extends React.Component {
|
|
|
587
603
|
? this.getCurrentRawTextForProps(this.props)
|
|
588
604
|
: null;
|
|
589
605
|
const liveEditableHtml = this.editableDiv ? this.editableDiv.innerHTML : null;
|
|
606
|
+
const pendingNativeInputMatchesLiveDom =
|
|
607
|
+
this.skipNextControlledValueRender === true &&
|
|
608
|
+
currentRawText === this.skipNextControlledValue;
|
|
590
609
|
const canPreserveNativeDom =
|
|
591
610
|
this.state.hasFocus === true &&
|
|
592
611
|
this.editableDiv !== null &&
|
|
@@ -594,7 +613,7 @@ export default class MathRichInput extends React.Component {
|
|
|
594
613
|
(this.afterComponentUpdateData === null ||
|
|
595
614
|
this.afterComponentUpdateData === undefined) &&
|
|
596
615
|
this.lastRenderedEditableHtml !== null &&
|
|
597
|
-
currentRawText === this.props.value;
|
|
616
|
+
(currentRawText === this.props.value || pendingNativeInputMatchesLiveDom);
|
|
598
617
|
const preserveRangeParams = canPreserveNativeDom
|
|
599
618
|
? this.getRangeParamsPreservingInlinePlaceholder()
|
|
600
619
|
: null;
|
|
@@ -609,6 +628,7 @@ export default class MathRichInput extends React.Component {
|
|
|
609
628
|
liveEditableHtml,
|
|
610
629
|
lastRenderedEditableHtml: this.lastRenderedEditableHtml,
|
|
611
630
|
currentRawText,
|
|
631
|
+
pendingNativeInputMatchesLiveDom,
|
|
612
632
|
preserveRangeParams,
|
|
613
633
|
afterComponentUpdateData: this.afterComponentUpdateData,
|
|
614
634
|
hasFocus: this.state.hasFocus,
|
|
@@ -2694,22 +2714,32 @@ export default class MathRichInput extends React.Component {
|
|
|
2694
2714
|
|
|
2695
2715
|
shouldComponentUpdate(nextProps, nextState) {
|
|
2696
2716
|
if (this.skipNextControlledValueRender === true) {
|
|
2717
|
+
const controlledValueArrived =
|
|
2718
|
+
nextProps.value === this.skipNextControlledValue;
|
|
2697
2719
|
const canSkip =
|
|
2698
|
-
|
|
2699
|
-
nextState === this.state;
|
|
2720
|
+
controlledValueArrived && nextState === this.state;
|
|
2700
2721
|
|
|
2701
2722
|
debugMathRichInput("shouldComponentUpdate:native-input-gate", {
|
|
2702
2723
|
canSkip,
|
|
2703
2724
|
nextValue: nextProps.value,
|
|
2704
2725
|
skipNextControlledValue: this.skipNextControlledValue,
|
|
2726
|
+
controlledValueArrived,
|
|
2705
2727
|
currentPropsValue: this.props.value,
|
|
2706
2728
|
stateChanged: nextState !== this.state,
|
|
2707
2729
|
innerHTML: this.editableDiv ? this.editableDiv.innerHTML : null,
|
|
2708
2730
|
selection: getSelectionSnapshot(this.editableDiv),
|
|
2709
2731
|
});
|
|
2710
2732
|
|
|
2711
|
-
|
|
2712
|
-
this.
|
|
2733
|
+
// A controlled host may commit an unrelated render before it echoes the
|
|
2734
|
+
// value from this native input event. Keep the gate armed through that
|
|
2735
|
+
// stale render so getEditableHtmlForRender can preserve the browser DOM
|
|
2736
|
+
// and its selection. The time-bounded fallback armed by
|
|
2737
|
+
// applyChangesToComponent keeps a host that rejects the value from
|
|
2738
|
+
// leaving the gate armed indefinitely.
|
|
2739
|
+
if (controlledValueArrived) {
|
|
2740
|
+
this.skipNextControlledValueRender = false;
|
|
2741
|
+
this.skipNextControlledValue = null;
|
|
2742
|
+
}
|
|
2713
2743
|
|
|
2714
2744
|
if (canSkip) return false;
|
|
2715
2745
|
}
|