@zzish/math-rich-input 0.1.42 → 0.1.44

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/src/Toolbar.jsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import katex from "katex";
3
3
 
4
- import AccentBar from "./AccentBar";
4
+ import AccentBar from "./AccentBar.jsx";
5
5
 
6
6
  import "./Toolbar.css";
7
7
 
@@ -9,252 +9,238 @@ const DEFAULT_TOP = 0;
9
9
  const DEFAULT_RIGHT = 0;
10
10
  const BOTTOM_MARGIN = 5;
11
11
 
12
- const CTRL_OR_META = /(Mac)/i.test(window.navigator.platform)
13
- ? "\u2318"
14
- : "CTRL+";
12
+ const CTRL_OR_META = /(Mac)/i.test(window.navigator.platform) ? "\u2318" : "CTRL+";
15
13
 
16
14
  export default class Toolbar extends React.Component {
17
- constructor(props) {
18
- super(props);
19
-
20
- this.state = {
21
- showAccents: false,
22
- top: DEFAULT_TOP,
23
- right: DEFAULT_RIGHT,
24
- shouldHorizontiallyAlign: false,
15
+ constructor(props) {
16
+ super(props);
17
+
18
+ this.state = {
19
+ showAccents: false,
20
+ top: DEFAULT_TOP,
21
+ right: DEFAULT_RIGHT,
22
+ shouldHorizontiallyAlign: false,
23
+ };
24
+
25
+ this.handleButtonClick = this.handleButtonClick.bind(this);
26
+
27
+ this.suppliedClickHandler = null;
28
+ this.suppliedAccentLetterFetcher = null;
29
+ this.suppliedAccentLetterReplacer = null;
30
+ this.accentLetter = null;
31
+ this.shouldUpdatePosition = true;
32
+ }
33
+
34
+ handleButtonClick = (event, buttonName) => {
35
+ this.suppliedClickHandler(event, buttonName);
36
+ };
37
+
38
+ showAccentBar = (event) => {
39
+ if (!this.state.showAccents) this.accentLetter = this.suppliedAccentLetterFetcher();
40
+ this.setState({ showAccents: true });
41
+ event.preventDefault();
42
+ };
43
+
44
+ hideAccentBar = (event) => {
45
+ this.setState({ showAccents: false });
46
+ };
47
+
48
+ showOrHideAccentBar = (event) => {
49
+ if (!this.state.showAccents) this.accentLetter = this.suppliedAccentLetterFetcher();
50
+ this.setState({ showAccents: !this.state.showAccents });
51
+ };
52
+
53
+ handleButtonClick = (event, buttonName) => {
54
+ this.suppliedClickHandler(event, buttonName);
25
55
  };
26
56
 
27
- this.handleButtonClick = this.handleButtonClick.bind(this);
28
-
29
- this.suppliedClickHandler = null;
30
- this.suppliedAccentLetterFetcher = null;
31
- this.suppliedAccentLetterReplacer = null;
32
- this.accentLetter = null;
33
- this.shouldUpdatePosition = true;
34
- }
35
-
36
- handleButtonClick = (event, buttonName) => {
37
- this.suppliedClickHandler(event, buttonName);
38
- };
39
-
40
- showAccentBar = (event) => {
41
- if (!this.state.showAccents)
42
- this.accentLetter = this.suppliedAccentLetterFetcher();
43
- this.setState({ showAccents: true });
44
- event.preventDefault();
45
- };
46
-
47
- hideAccentBar = (event) => {
48
- this.setState({ showAccents: false });
49
- };
50
-
51
- showOrHideAccentBar = (event) => {
52
- if (!this.state.showAccents)
53
- this.accentLetter = this.suppliedAccentLetterFetcher();
54
- this.setState({ showAccents: !this.state.showAccents });
55
- };
56
-
57
- handleButtonClick = (event, buttonName) => {
58
- this.suppliedClickHandler(event, buttonName);
59
- };
60
-
61
- handleAccentButtonClick = (event, oldCharacter, newCharacter) => {
62
- this.suppliedAccentLetterInserter(event, oldCharacter, newCharacter);
63
- // this.hideAccentBar(null)
64
- };
65
-
66
- isInViewport = (element) => {
67
- const rect = element.getBoundingClientRect();
68
- return (
69
- rect.top >= 0 &&
70
- rect.left >= 0 &&
71
- rect.bottom <=
72
- (window.innerHeight || document.documentElement.clientHeight) &&
73
- rect.right <= (window.innerWidth || document.documentElement.clientWidth)
74
- );
75
- };
76
-
77
- componentDidMount() {
78
- // We render once to find out the component's preferred size and then render again to update it
79
- if (this.shouldUpdatePosition) {
80
- // Lets position the accent bar below the input field and right aligned
81
- let thisBar = this.toolbar;
82
- let node = thisBar.parentNode;
83
- while (
84
- node !== null &&
85
- !node.classList.contains("MathRichInput-Container")
86
- )
87
- node = node.parentNode;
88
-
89
- if (node === null) {
90
- console.error(
91
- "Could not find ancestor MathRichInput-Container find parent"
57
+ handleAccentButtonClick = (event, oldCharacter, newCharacter) => {
58
+ this.suppliedAccentLetterInserter(event, oldCharacter, newCharacter);
59
+ // this.hideAccentBar(null)
60
+ };
61
+
62
+ isInViewport = (element) => {
63
+ const rect = element.getBoundingClientRect();
64
+ return (
65
+ rect.top >= 0 &&
66
+ rect.left >= 0 &&
67
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
68
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth)
92
69
  );
93
- return;
94
- }
70
+ };
95
71
 
96
- let inputBounds = node.getBoundingClientRect();
97
- let thisBounds = thisBar.getBoundingClientRect();
72
+ componentDidMount() {
73
+ // We render once to find out the component's preferred size and then render again to update it
74
+ if (this.shouldUpdatePosition) {
75
+ // Lets position the accent bar below the input field and right aligned
76
+ let thisBar = this.toolbar;
77
+ let node = thisBar.parentNode;
78
+ while (node !== null && !node.classList.contains("MathRichInput-Container"))
79
+ node = node.parentNode;
80
+
81
+ if (node === null) {
82
+ console.error("Could not find ancestor MathRichInput-Container find parent");
83
+ return;
84
+ }
98
85
 
99
- this.shouldUpdatePosition = false;
86
+ let inputBounds = node.getBoundingClientRect();
87
+ let thisBounds = thisBar.getBoundingClientRect();
100
88
 
101
- // Vertically align above input field
102
- let top = (thisBounds.height + BOTTOM_MARGIN) * -1;
89
+ this.shouldUpdatePosition = false;
103
90
 
104
- // Horizontally align
105
- let right = 0; // right align
91
+ // Vertically align above input field
92
+ let top = (thisBounds.height + BOTTOM_MARGIN + this.props.extraMargin) * -1;
106
93
 
107
- let shouldHorizontiallyAlign = false;
108
- if (thisBounds.width > inputBounds.width) {
109
- shouldHorizontiallyAlign = true;
94
+ // Horizontally align
95
+ let right = 0; // right align
110
96
 
111
- if (this.isInViewport(thisBar)) {
112
- right = right - (thisBounds.width - inputBounds.width) / 2;
113
- } // else remain right aligned
114
- }
97
+ let shouldHorizontiallyAlign = false;
98
+ if (thisBounds.width > inputBounds.width) {
99
+ shouldHorizontiallyAlign = true;
115
100
 
116
- this.setState({ right, top, shouldHorizontiallyAlign });
117
- } else {
118
- this.shouldUpdatePosition = true;
119
- }
120
- }
121
-
122
- render() {
123
- this.suppliedClickHandler = this.props.onButtonClick;
124
- this.suppliedAccentLetterFetcher = this.props.fetchAccentLetter;
125
- this.suppliedAccentLetterInserter = this.props.insertAccentLetter;
126
-
127
- let enableFontStyling = this.props.enableFontStyling ?? true;
128
- let enableMath = this.props.enableMath ?? true;
129
-
130
- let katexHTML = katex.renderToString("f(x)");
131
- // Not really necessary, but lets clean out some unnessary mathml nodes
132
- let start = katexHTML.indexOf('<span class="katex-mathml">');
133
- let end = -1;
134
- if (start > 0) end = katexHTML.indexOf("</math></span>", start + 30);
135
- if (end > 0)
136
- katexHTML = katexHTML.substring(0, start) + katexHTML.substring(end + 14);
137
-
138
- // Set up the tranlation to place the toolbar where we want it
139
- let style = { ...this.props.style };
140
- // if (this.state.translateX !== DEFAULT_TRANSLATE) {
141
- // style.transform = "translate("+this.state.translateX+"px, "+this.state.translateY+"px)";
142
- // }
143
- if (this.state.right !== DEFAULT_RIGHT || this.state.top !== DEFAULT_TOP) {
144
- if (!this.props.compactMode || this.state.shouldHorizontiallyAlign) {
145
- style.right = this.state.right + "px";
146
- }
147
- style.top = this.state.top + "px";
101
+ if (this.isInViewport(thisBar)) {
102
+ right = right - (thisBounds.width - inputBounds.width) / 2;
103
+ } // else remain right aligned
104
+ }
105
+
106
+ this.setState({ right, top, shouldHorizontiallyAlign });
107
+ } else {
108
+ this.shouldUpdatePosition = true;
109
+ }
148
110
  }
149
111
 
150
- return (
151
- <div className="Toolbar" style={style} ref={(r) => (this.toolbar = r)}>
152
- {enableFontStyling && (
153
- <>
154
- <button
155
- name="Bold"
156
- className={
157
- "Toolbar-button TB-narrow" +
158
- (this.props.activeButtons.bold ? " TB-selected" : "")
159
- }
160
- onClick={(e) => e.preventDefault()}
161
- onMouseDown={(e) => e.preventDefault()}
162
- onMouseUp={(e) => this.handleButtonClick(e, "Bold")}
163
- >
164
- <b>B</b>
165
- </button>
166
-
167
- <button
168
- name="Italic"
169
- className={
170
- "Toolbar-button TB-narrow" +
171
- (this.props.activeButtons.italic ? " TB-selected" : "")
172
- }
173
- onClick={(e) => e.preventDefault()}
174
- onMouseDown={(e) => e.preventDefault()}
175
- onMouseUp={(e) => this.handleButtonClick(e, "Italic")}
176
- >
177
- <i>I</i>
178
- </button>
179
-
180
- <button
181
- name="Underline"
182
- className={
183
- "Toolbar-button TB-narrow" +
184
- (this.props.activeButtons.underline ? " TB-selected" : "")
185
- }
186
- onClick={(e) => e.preventDefault()}
187
- onMouseDown={(e) => e.preventDefault()}
188
- onMouseUp={(e) => this.handleButtonClick(e, "Underline")}
189
- >
190
- <u>U</u>
191
- </button>
192
-
193
- <button
194
- name="Superscript"
195
- className={
196
- "Toolbar-button TB-narrow" +
197
- (this.props.activeButtons.superscript ? " TB-selected" : "")
198
- }
199
- onClick={(e) => e.preventDefault()}
200
- onMouseDown={(e) => e.preventDefault()}
201
- onMouseUp={(e) => this.handleButtonClick(e, "Superscript")}
202
- >
203
- a<sup>x</sup>
204
- </button>
205
-
206
- <button
207
- name="Subscript"
208
- className={
209
- "Toolbar-button TB-narrow" +
210
- (this.props.activeButtons.subscript ? " TB-selected" : "")
211
- }
212
- onClick={(e) => e.preventDefault()}
213
- onMouseDown={(e) => e.preventDefault()}
214
- onMouseUp={(e) => this.handleButtonClick(e, "Subscript")}
215
- >
216
- a<sub>x</sub>
217
- </button>
218
- </>
219
- )}
220
-
221
- <button
222
- name="Accents"
223
- className={
224
- "Toolbar-button TB-narrow" +
225
- (this.state.showAccents ? " TB-selected" : "")
226
- }
227
- onMouseDown={(e) => e.preventDefault()}
228
- onClick={(e) => e.preventDefault()}
229
- onMouseUp={(e) => this.showOrHideAccentBar(e)}
230
- >
231
- á
232
- </button>
233
-
234
- {enableMath && (
235
- <button
236
- name="Equation"
237
- className="Toolbar-button TB-wide"
238
- onMouseDown={(e) => this.handleButtonClick(e, "Equation")}
239
- >
240
- <div dangerouslySetInnerHTML={{ __html: katexHTML }} />
241
- <span className="tooltiptext">
242
- Insert equation [{CTRL_OR_META}Enter]
243
- </span>
244
- </button>
245
- )}
246
-
247
- {this.state.showAccents && (
248
- <AccentBar
249
- accentLetter={this.accentLetter}
250
- keyPressed={this.props.keyPressed}
251
- fetchAccentLetter={this.props.fetchAccentLetter}
252
- onButtonClick={(e, oldCharacter, newCharacter) =>
253
- this.handleAccentButtonClick(e, oldCharacter, newCharacter)
112
+ render() {
113
+ this.suppliedClickHandler = this.props.onButtonClick;
114
+ this.suppliedAccentLetterFetcher = this.props.fetchAccentLetter;
115
+ this.suppliedAccentLetterInserter = this.props.insertAccentLetter;
116
+
117
+ let enableFontStyling = this.props.enableFontStyling ?? true;
118
+ let enableMath = this.props.enableMath ?? true;
119
+
120
+ let katexHTML = katex.renderToString("f(x)");
121
+ // Not really necessary, but lets clean out some unnessary mathml nodes
122
+ let start = katexHTML.indexOf('<span class="katex-mathml">');
123
+ let end = -1;
124
+ if (start > 0) end = katexHTML.indexOf("</math></span>", start + 30);
125
+ if (end > 0) katexHTML = katexHTML.substring(0, start) + katexHTML.substring(end + 14);
126
+
127
+ // Set up the tranlation to place the toolbar where we want it
128
+ let style = { ...this.props.style };
129
+ // if (this.state.translateX !== DEFAULT_TRANSLATE) {
130
+ // style.transform = "translate("+this.state.translateX+"px, "+this.state.translateY+"px)";
131
+ // }
132
+ if (this.state.right !== DEFAULT_RIGHT || this.state.top !== DEFAULT_TOP) {
133
+ if (!this.props.compactMode || this.state.shouldHorizontiallyAlign) {
134
+ style.right = this.state.right + "px";
254
135
  }
255
- />
256
- )}
257
- </div>
258
- );
259
- }
136
+ style.top = this.state.top + "px";
137
+ }
138
+
139
+ return (
140
+ <div className="Toolbar" style={style} ref={(r) => (this.toolbar = r)}>
141
+ {enableFontStyling && (
142
+ <>
143
+ <button
144
+ name="Bold"
145
+ className={
146
+ "Toolbar-button TB-narrow" +
147
+ (this.props.activeButtons.bold ? " TB-selected" : "")
148
+ }
149
+ onClick={(e) => e.preventDefault()}
150
+ onMouseDown={(e) => e.preventDefault()}
151
+ onMouseUp={(e) => this.handleButtonClick(e, "Bold")}
152
+ >
153
+ <b>B</b>
154
+ </button>
155
+
156
+ <button
157
+ name="Italic"
158
+ className={
159
+ "Toolbar-button TB-narrow" +
160
+ (this.props.activeButtons.italic ? " TB-selected" : "")
161
+ }
162
+ onClick={(e) => e.preventDefault()}
163
+ onMouseDown={(e) => e.preventDefault()}
164
+ onMouseUp={(e) => this.handleButtonClick(e, "Italic")}
165
+ >
166
+ <i>I</i>
167
+ </button>
168
+
169
+ <button
170
+ name="Underline"
171
+ className={
172
+ "Toolbar-button TB-narrow" +
173
+ (this.props.activeButtons.underline ? " TB-selected" : "")
174
+ }
175
+ onClick={(e) => e.preventDefault()}
176
+ onMouseDown={(e) => e.preventDefault()}
177
+ onMouseUp={(e) => this.handleButtonClick(e, "Underline")}
178
+ >
179
+ <u>U</u>
180
+ </button>
181
+
182
+ <button
183
+ name="Superscript"
184
+ className={
185
+ "Toolbar-button TB-narrow" +
186
+ (this.props.activeButtons.superscript ? " TB-selected" : "")
187
+ }
188
+ onClick={(e) => e.preventDefault()}
189
+ onMouseDown={(e) => e.preventDefault()}
190
+ onMouseUp={(e) => this.handleButtonClick(e, "Superscript")}
191
+ >
192
+ a<sup>x</sup>
193
+ </button>
194
+
195
+ <button
196
+ name="Subscript"
197
+ className={
198
+ "Toolbar-button TB-narrow" +
199
+ (this.props.activeButtons.subscript ? " TB-selected" : "")
200
+ }
201
+ onClick={(e) => e.preventDefault()}
202
+ onMouseDown={(e) => e.preventDefault()}
203
+ onMouseUp={(e) => this.handleButtonClick(e, "Subscript")}
204
+ >
205
+ a<sub>x</sub>
206
+ </button>
207
+ </>
208
+ )}
209
+
210
+ <button
211
+ name="Accents"
212
+ className={
213
+ "Toolbar-button TB-narrow" + (this.state.showAccents ? " TB-selected" : "")
214
+ }
215
+ onMouseDown={(e) => e.preventDefault()}
216
+ onClick={(e) => e.preventDefault()}
217
+ onMouseUp={(e) => this.showOrHideAccentBar(e)}
218
+ >
219
+ á
220
+ </button>
221
+
222
+ {enableMath && (
223
+ <button
224
+ name="Equation"
225
+ className="Toolbar-button TB-wide"
226
+ onMouseDown={(e) => this.handleButtonClick(e, "Equation")}
227
+ >
228
+ <div dangerouslySetInnerHTML={{ __html: katexHTML }} />
229
+ <span className="tooltiptext">Insert equation [{CTRL_OR_META}Enter]</span>
230
+ </button>
231
+ )}
232
+
233
+ {this.state.showAccents && (
234
+ <AccentBar
235
+ accentLetter={this.accentLetter}
236
+ keyPressed={this.props.keyPressed}
237
+ fetchAccentLetter={this.props.fetchAccentLetter}
238
+ onButtonClick={(e, oldCharacter, newCharacter) =>
239
+ this.handleAccentButtonClick(e, oldCharacter, newCharacter)
240
+ }
241
+ />
242
+ )}
243
+ </div>
244
+ );
245
+ }
260
246
  }
package/src/index.js CHANGED
@@ -1,9 +1,5 @@
1
- import MathRichInput from "./MathRichInput";
2
- import MathRichArea from "./MathRichArea";
3
- import { renderMathInNode } from "./MathRichArea";
1
+ import MathRichInput from "./MathRichInput.jsx";
2
+ import MathRichArea from "./MathRichArea.jsx";
3
+ import { renderMathInNode } from "./MathRichArea.jsx";
4
4
 
5
- export {
6
- MathRichInput,
7
- MathRichArea,
8
- renderMathInNode
9
- }
5
+ export { MathRichInput, MathRichArea, renderMathInNode };