1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
import React, { Component, createRef } from 'react';
// Import JQuery, required for the functioning of the equation editor
import $ from 'jquery';
import './EquationEditor.scss';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).jQuery = $;
// eslint-disable-next-line @typescript-eslint/no-require-imports
require('mathquill/build/mathquill');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).MathQuill = (window as any).MathQuill.getInterface(1);
type EquationEditorProps = {
onChange(latex: string): void;
value: string;
spaceBehavesLikeTab?: boolean;
autoCommands: string;
autoOperatorNames: string;
onEnter?(): void;
};
/**
* @typedef {EquationEditorProps} props
* @prop {Function} onChange Triggered when content of the equation editor changes
* @prop {string} value Content of the equation handler
* @prop {boolean}[false] spaceBehavesLikeTab Whether spacebar should simulate tab behavior
* @prop {string} autoCommands List of commands for which you only have to type the name of the
* command with a \ in front of it. Examples: pi theta rho sum
* @prop {string} autoOperatorNames List of operators for which you only have to type the name of the
* operator with a \ in front of it. Examples: sin cos tan
* @prop {Function} onEnter Triggered when enter is pressed in the equation editor
* @extends {Component<EquationEditorProps>}
*/
class EquationEditor extends Component<EquationEditorProps> {
element: React.RefObject<HTMLSpanElement>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
mathField: any;
ignoreEditEvents: number;
// Element needs to be in the class format and thus requires a constructor. The steps that are run
// in the constructor is to make sure that React can succesfully communicate with the equation
// editor.
constructor(props: EquationEditorProps) {
super(props);
this.element = createRef<HTMLSpanElement>();
this.mathField = null;
// MathJax apparently fire 2 edit events on startup.
this.ignoreEditEvents = 2;
}
componentDidMount() {
const { onChange, value, spaceBehavesLikeTab, autoCommands, autoOperatorNames, onEnter } = this.props;
const config = {
handlers: {
edit: () => {
if (this.ignoreEditEvents <= 0) onChange(this.mathField.latex());
else this.ignoreEditEvents -= 1;
},
enter: onEnter,
},
spaceBehavesLikeTab,
autoCommands,
autoOperatorNames,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.mathField = (window as any).MathQuill.MathField(this.element.current, config);
this.mathField.latex(value || '');
}
componentDidUpdate(prevProps: Readonly<EquationEditorProps>): void {
!prevProps.value && this.mathField.latex(this.props.value || '');
}
render() {
return <span ref={this.element} style={{ border: '0px', boxShadow: 'None' }} />;
}
}
export default EquationEditor;
|