@zzish/math-rich-input 0.1.0
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 +253 -0
- package/babel.config.js +6 -0
- package/dist/index.js +23034 -0
- package/dist/math-rich-input.css +923 -0
- package/package.json +44 -0
- package/rollup.config.js +31 -0
- package/src/AccentBar.css +169 -0
- package/src/AccentBar.jsx +771 -0
- package/src/EquationEditor.css +258 -0
- package/src/EquationEditor.jsx +583 -0
- package/src/EquationEditorModal.css +164 -0
- package/src/EquationEditorModal.jsx +81 -0
- package/src/MathRichArea.jsx +103 -0
- package/src/MathRichInput.css +63 -0
- package/src/MathRichInput.jsx +1651 -0
- package/src/SymbolButton.css +130 -0
- package/src/SymbolButton.jsx +96 -0
- package/src/Toolbar.css +142 -0
- package/src/Toolbar.jsx +219 -0
- package/src/equationEditorButtonsHelper.js +590 -0
- package/src/index.js +5 -0
- package/src/katexHelper.js +39 -0
- package/src/mathRichInputHelper.js +785 -0
- package/src/mimeTypeHelper.js +201 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
|
|
2
|
+
.EquationEditorModal-background {
|
|
3
|
+
position: fixed;
|
|
4
|
+
top: 0;
|
|
5
|
+
left: 0;
|
|
6
|
+
width:100%;
|
|
7
|
+
height: 100%;
|
|
8
|
+
background: black;
|
|
9
|
+
z-index: 99;
|
|
10
|
+
animation: 0.3s shade;
|
|
11
|
+
animation-fill-mode: forwards;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@keyframes shade {
|
|
15
|
+
00% {
|
|
16
|
+
opacity: 0;
|
|
17
|
+
}
|
|
18
|
+
100% {
|
|
19
|
+
opacity: 0.6;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.EquationEditorModal {
|
|
24
|
+
background: white;
|
|
25
|
+
border:1px solid #808080;
|
|
26
|
+
border-radius:10px;
|
|
27
|
+
box-shadow: 0px 2px 5px 1px #a0a0a0;
|
|
28
|
+
position:fixed;
|
|
29
|
+
max-width:500px;
|
|
30
|
+
width: 98%;
|
|
31
|
+
top:50%;
|
|
32
|
+
left:50%;
|
|
33
|
+
/* transform: translate(-50%,-50%); */
|
|
34
|
+
z-index: 100;
|
|
35
|
+
animation: 0.3s rise;
|
|
36
|
+
animation-fill-mode: forwards;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@keyframes rise {
|
|
40
|
+
00% {
|
|
41
|
+
transform: translate(-50%,100%);
|
|
42
|
+
opacity:0.0;
|
|
43
|
+
}
|
|
44
|
+
100% {
|
|
45
|
+
transform: translate(-50%,-50%);
|
|
46
|
+
opacity:1.0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.EquationEditorModal-mobile {
|
|
51
|
+
background: white;
|
|
52
|
+
border:1px solid #808080;
|
|
53
|
+
border-radius:10px;
|
|
54
|
+
box-shadow: 0px 2px 5px 1px #a0a0a0;
|
|
55
|
+
position:fixed;
|
|
56
|
+
max-width:500px;
|
|
57
|
+
width: 99%;
|
|
58
|
+
top:0%;
|
|
59
|
+
left:50%;
|
|
60
|
+
transform: translate(-50%, 1px);
|
|
61
|
+
z-index: 100;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.EquationEditorModal .title {
|
|
65
|
+
font-size: 14px;
|
|
66
|
+
color: #404040;
|
|
67
|
+
text-align: left;
|
|
68
|
+
background: #E0E0E0;
|
|
69
|
+
border:0px;
|
|
70
|
+
border-radius:5px 5px 0px 0px;
|
|
71
|
+
height:30px;
|
|
72
|
+
padding:20px 0px 5px 20px;
|
|
73
|
+
margin:0px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.EquationEditorModal-mobile .title {
|
|
77
|
+
font-size: 14px;
|
|
78
|
+
color: #404040;
|
|
79
|
+
text-align: left;
|
|
80
|
+
background: #E0E0E0;
|
|
81
|
+
border:0px;
|
|
82
|
+
border-radius:5px 5px 0px 0px;
|
|
83
|
+
height:30px;
|
|
84
|
+
padding:20px 0px 5px 20px;
|
|
85
|
+
margin:0px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.EquationEditorModal .expertModeSwitch {
|
|
89
|
+
/* background: url(images/settings-icon.png) no-repeat; */
|
|
90
|
+
float:right;
|
|
91
|
+
/* width:36px;
|
|
92
|
+
height:36px; */
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.EquationEditorModal .expertModeSwitch .switch{
|
|
96
|
+
margin-right:10px;
|
|
97
|
+
margin-left:10px;
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* The switch - the box around the slider */
|
|
102
|
+
.switch {
|
|
103
|
+
position: relative;
|
|
104
|
+
display: inline-block;
|
|
105
|
+
width: 35px;
|
|
106
|
+
height: 22px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Hide default HTML checkbox */
|
|
110
|
+
.switch input {
|
|
111
|
+
opacity: 0;
|
|
112
|
+
width: 0;
|
|
113
|
+
height: 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* The slider */
|
|
117
|
+
.slider {
|
|
118
|
+
position: absolute;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
top: 0;
|
|
121
|
+
left: 0;
|
|
122
|
+
right: 0;
|
|
123
|
+
bottom: 0;
|
|
124
|
+
background-color: #ccc;
|
|
125
|
+
-webkit-transition: .4s;
|
|
126
|
+
transition: .4s;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.slider:before {
|
|
130
|
+
position: absolute;
|
|
131
|
+
content: "";
|
|
132
|
+
height: 14px;
|
|
133
|
+
width: 14px;
|
|
134
|
+
left: 4px;
|
|
135
|
+
bottom: 4px;
|
|
136
|
+
background-color: white;
|
|
137
|
+
-webkit-transition: .4s;
|
|
138
|
+
transition: .4s;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
input:checked + .slider {
|
|
142
|
+
background-color: #663676;
|
|
143
|
+
;
|
|
144
|
+
/* background-color: #2196F3; */
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
input:focus + .slider {
|
|
148
|
+
box-shadow: 0 0 1px #2196F3;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
input:checked + .slider:before {
|
|
152
|
+
-webkit-transform: translateX(13px);
|
|
153
|
+
-ms-transform: translateX(13px);
|
|
154
|
+
transform: translateX(13px);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Rounded sliders */
|
|
158
|
+
.slider.round {
|
|
159
|
+
border-radius: 18px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.slider.round:before {
|
|
163
|
+
border-radius: 50%;
|
|
164
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import EquationEditor from './EquationEditor'
|
|
3
|
+
|
|
4
|
+
import './EquationEditorModal.css';
|
|
5
|
+
|
|
6
|
+
let GLOBAL_lastSelectedExpertMode = false
|
|
7
|
+
|
|
8
|
+
export default class EquationEditorModal extends React.Component {
|
|
9
|
+
constructor(props) {
|
|
10
|
+
super(props);
|
|
11
|
+
|
|
12
|
+
this.state = {
|
|
13
|
+
useExpertMode: GLOBAL_lastSelectedExpertMode
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this.handleCloseCallback = props.handleClose
|
|
17
|
+
this.handleInsertCallback = props.handleInsert
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
handleInsert = (latex) => {
|
|
21
|
+
this.handleInsertCallback(latex)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
handleClose = () => {
|
|
25
|
+
this.handleCloseCallback()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
componentDidMount() {
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
isMobile() {
|
|
32
|
+
return ((window.innerHeight > window.innerWidth) && (window.innerHeight < 820)) ||
|
|
33
|
+
(window.innerHeight < 500)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
handleExpertModeSwitchChange(e) {
|
|
37
|
+
GLOBAL_lastSelectedExpertMode = this.expertModeSwitch.checked
|
|
38
|
+
this.setState({useExpertMode:this.expertModeSwitch.checked})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
render() {
|
|
42
|
+
let useClass="EquationEditorModal"
|
|
43
|
+
if (this.isMobile())
|
|
44
|
+
useClass="EquationEditorModal-mobile"
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<div
|
|
49
|
+
className="EquationEditorModal-background"
|
|
50
|
+
onClick={this.handleClose} >
|
|
51
|
+
</div>
|
|
52
|
+
<div
|
|
53
|
+
className={useClass}
|
|
54
|
+
ref={(r) => this.modalDiv = r} >
|
|
55
|
+
{ !this.isMobile() &&
|
|
56
|
+
<div className="title">
|
|
57
|
+
Equation Editor
|
|
58
|
+
<div className="expertModeSwitch">
|
|
59
|
+
Expert mode
|
|
60
|
+
<label className="switch">
|
|
61
|
+
<input type="checkbox"
|
|
62
|
+
ref={(r) => this.expertModeSwitch = r}
|
|
63
|
+
onChange={(e) => this.handleExpertModeSwitchChange(e)}
|
|
64
|
+
checked = {this.state.useExpertMode}
|
|
65
|
+
/>
|
|
66
|
+
<span className="slider round"></span>
|
|
67
|
+
</label>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
}
|
|
71
|
+
<EquationEditor
|
|
72
|
+
ref={(r) => this.equationEditor = r}
|
|
73
|
+
latex={this.props.latex}
|
|
74
|
+
useExpertMode={this.state.useExpertMode}
|
|
75
|
+
handleInsert={this.handleInsert}
|
|
76
|
+
handleCancel={this.handleClose}/>
|
|
77
|
+
</div>
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import katex from "katex";
|
|
4
|
+
import {setupKatex} from "./katexHelper"
|
|
5
|
+
import {rawTextToHtml} from './mathRichInputHelper'
|
|
6
|
+
import {MIME_TYPE_TEX, MIME_TYPE_HTML, MIME_TYPE_ZZISH_HTML_MATH,
|
|
7
|
+
isTextLatexMath, isTextHtml, isTextHtmlMath} from './mimeTypeHelper'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function getAllTextNodes(node, nodes=null) {
|
|
11
|
+
if (node === null) {
|
|
12
|
+
console.warn("Deverloper supplied a null node. Ignoring")
|
|
13
|
+
return nodes
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (nodes === null) {
|
|
17
|
+
nodes = []
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
21
|
+
nodes.push(node)
|
|
22
|
+
return nodes
|
|
23
|
+
}
|
|
24
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
25
|
+
if (node.className === "katex" || node.className === "MathRichInput")
|
|
26
|
+
return nodes
|
|
27
|
+
if (node.tagName === "SCRIPT")
|
|
28
|
+
return nodes
|
|
29
|
+
let render = node.getAttribute("data-render")
|
|
30
|
+
if (render !== null && render === "false") {
|
|
31
|
+
console.log("Ignoring")
|
|
32
|
+
return nodes
|
|
33
|
+
}
|
|
34
|
+
} else if (node.nodeType !== Node.DOCUMENT_NODE) {
|
|
35
|
+
return nodes
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (node.childNodes === null || node.childNodes === undefined)
|
|
39
|
+
return nodes
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < node.childNodes.length; i++)
|
|
42
|
+
getAllTextNodes(node.childNodes[i], nodes)
|
|
43
|
+
|
|
44
|
+
return nodes
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function renderMathInNode(node) {
|
|
48
|
+
try {
|
|
49
|
+
let textNodes = getAllTextNodes(node)
|
|
50
|
+
for (let i = 0; i < textNodes.length; i++) {
|
|
51
|
+
try {
|
|
52
|
+
const text = textNodes[i].nodeValue
|
|
53
|
+
|
|
54
|
+
let mime_type = null
|
|
55
|
+
if (isTextHtmlMath(text))
|
|
56
|
+
mime_type = MIME_TYPE_ZZISH_HTML_MATH
|
|
57
|
+
else if (isTextHtml(text))
|
|
58
|
+
mime_type = MIME_TYPE_HTML
|
|
59
|
+
else if (isTextLatexMath(text))
|
|
60
|
+
mime_type = MIME_TYPE_TEX
|
|
61
|
+
|
|
62
|
+
if (mime_type !== null) {
|
|
63
|
+
const html = rawTextToHtml(katex, text, mime_type)
|
|
64
|
+
const new_node = document.createElement("span")
|
|
65
|
+
new_node.innerHTML = html
|
|
66
|
+
textNodes[i].replaceWith(new_node)
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.log(error)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.log(error)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function renderMathInNodeArray(nodes) {
|
|
78
|
+
for (let i = 0; i < nodes.length; i++)
|
|
79
|
+
renderMathInNode(nodes[i])
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default class MathRichArea extends React.Component {
|
|
83
|
+
|
|
84
|
+
constructor(props) {
|
|
85
|
+
super(props);
|
|
86
|
+
this.state = {
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
componentDidMount() {
|
|
91
|
+
try {
|
|
92
|
+
setupKatex()
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error(error)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
render() {
|
|
99
|
+
let html = rawTextToHtml(katex, this.props.children, this.props.mime_type)
|
|
100
|
+
|
|
101
|
+
return <span dangerouslySetInnerHTML={{__html: html}}></span>
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
.MathRichInput-Container {
|
|
2
|
+
margin:10px;
|
|
3
|
+
border-radius:5px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.MathRichInput-Container:focus-within {
|
|
7
|
+
background-color: white!important;
|
|
8
|
+
outline: 0px;
|
|
9
|
+
border:1px solid #663676;
|
|
10
|
+
/* box-shadow: inset 1px 1px 5px #a0a0a0; */
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.MathRichInput-scrollview {
|
|
14
|
+
display:flex;
|
|
15
|
+
overflow:scroll;
|
|
16
|
+
border-radius:5px;
|
|
17
|
+
overflow: overlay;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.MathRichInput P {
|
|
21
|
+
padding:0px;
|
|
22
|
+
margin:0px
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.MathRichInput {
|
|
26
|
+
font-size: 18px;
|
|
27
|
+
padding: 10px;
|
|
28
|
+
width: 100%;
|
|
29
|
+
border-radius: 5px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.MathRichInput:focus {
|
|
33
|
+
outline:0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.MathRichInput .katex {
|
|
37
|
+
border:0px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.MathRichInput .base { /* Combine the katex and base class name to ensure the whole equation is surrounded */
|
|
41
|
+
background-color: #f0f0f0;
|
|
42
|
+
border: 0px;
|
|
43
|
+
border: 1px dotted #D0D0D0;
|
|
44
|
+
border-radius: 5px;
|
|
45
|
+
padding: 2px 2px 2px 2px;
|
|
46
|
+
margin: 0px 2px 0px 2px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.katex .mathnormal {
|
|
50
|
+
/* font-family: KaTeX_Caligraphic; */
|
|
51
|
+
font-family: KaTeX_Math;
|
|
52
|
+
font-style: italic;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.MathRichInput .katex-error {
|
|
56
|
+
background-color: #f0f0f0;
|
|
57
|
+
border: 0px;
|
|
58
|
+
border: 1px dotted #ff8080;
|
|
59
|
+
border-radius: 5px;
|
|
60
|
+
padding: 2px 2px 2px 2px;
|
|
61
|
+
margin: 0px 2px 0px 2px;
|
|
62
|
+
}
|
|
63
|
+
|