@zzish/math-rich-input 0.1.47 → 0.1.49

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
@@ -9,238 +9,253 @@ 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) ? "\u2318" : "CTRL+";
12
+ const CTRL_OR_META = /(Mac)/i.test(window.navigator.platform)
13
+ ? "\u2318"
14
+ : "CTRL+";
13
15
 
14
16
  export default class Toolbar extends React.Component {
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);
17
+ constructor(props) {
18
+ super(props);
19
+
20
+ this.state = {
21
+ showAccents: false,
22
+ top: DEFAULT_TOP,
23
+ right: DEFAULT_RIGHT,
24
+ shouldHorizontiallyAlign: false,
55
25
  };
56
26
 
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)
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"
69
92
  );
70
- };
93
+ return;
94
+ }
71
95
 
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
- }
96
+ let inputBounds = node.getBoundingClientRect();
97
+ let thisBounds = thisBar.getBoundingClientRect();
85
98
 
86
- let inputBounds = node.getBoundingClientRect();
87
- let thisBounds = thisBar.getBoundingClientRect();
99
+ this.shouldUpdatePosition = false;
88
100
 
89
- this.shouldUpdatePosition = false;
101
+ // Vertically align above input field
102
+ let top =
103
+ (thisBounds.height + BOTTOM_MARGIN + this.props.extraMargin) * -1;
90
104
 
91
- // Vertically align above input field
92
- let top = (thisBounds.height + BOTTOM_MARGIN + this.props.extraMargin) * -1;
105
+ // Horizontally align
106
+ let right = 0; // right align
93
107
 
94
- // Horizontally align
95
- let right = 0; // right align
108
+ let shouldHorizontiallyAlign = false;
109
+ if (thisBounds.width > inputBounds.width) {
110
+ shouldHorizontiallyAlign = true;
96
111
 
97
- let shouldHorizontiallyAlign = false;
98
- if (thisBounds.width > inputBounds.width) {
99
- shouldHorizontiallyAlign = true;
112
+ if (this.isInViewport(thisBar)) {
113
+ right = right - (thisBounds.width - inputBounds.width) / 2;
114
+ } // else remain right aligned
115
+ }
100
116
 
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
- }
117
+ this.setState({ right, top, shouldHorizontiallyAlign });
118
+ } else {
119
+ this.shouldUpdatePosition = true;
120
+ }
121
+ }
122
+
123
+ render() {
124
+ this.suppliedClickHandler = this.props.onButtonClick;
125
+ this.suppliedAccentLetterFetcher = this.props.fetchAccentLetter;
126
+ this.suppliedAccentLetterInserter = this.props.insertAccentLetter;
127
+
128
+ let enableFontStyling = this.props.enableFontStyling ?? true;
129
+ let enableMath = this.props.enableMath ?? true;
130
+
131
+ let katexHTML = katex.renderToString("f(x)");
132
+ // Not really necessary, but lets clean out some unnessary mathml nodes
133
+ let start = katexHTML.indexOf('<span class="katex-mathml">');
134
+ let end = -1;
135
+ if (start > 0) end = katexHTML.indexOf("</math></span>", start + 30);
136
+ if (end > 0)
137
+ katexHTML = katexHTML.substring(0, start) + katexHTML.substring(end + 14);
138
+
139
+ // Set up the tranlation to place the toolbar where we want it
140
+ let style = { ...this.props.style };
141
+ // if (this.state.translateX !== DEFAULT_TRANSLATE) {
142
+ // style.transform = "translate("+this.state.translateX+"px, "+this.state.translateY+"px)";
143
+ // }
144
+ if (this.state.right !== DEFAULT_RIGHT || this.state.top !== DEFAULT_TOP) {
145
+ if (!this.props.compactMode || this.state.shouldHorizontiallyAlign) {
146
+ style.right = this.state.right + "px";
147
+ }
148
+ style.top = this.state.top + "px";
110
149
  }
111
150
 
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";
151
+ return (
152
+ <div className="Toolbar" style={style} ref={(r) => (this.toolbar = r)}>
153
+ {enableFontStyling && (
154
+ <>
155
+ <button
156
+ name="Bold"
157
+ className={
158
+ "Toolbar-button TB-narrow" +
159
+ (this.props.activeButtons.bold ? " TB-selected" : "")
160
+ }
161
+ onClick={(e) => e.preventDefault()}
162
+ onMouseDown={(e) => e.preventDefault()}
163
+ onMouseUp={(e) => this.handleButtonClick(e, "Bold")}
164
+ >
165
+ <b>B</b>
166
+ </button>
167
+
168
+ <button
169
+ name="Italic"
170
+ className={
171
+ "Toolbar-button TB-narrow" +
172
+ (this.props.activeButtons.italic ? " TB-selected" : "")
173
+ }
174
+ onClick={(e) => e.preventDefault()}
175
+ onMouseDown={(e) => e.preventDefault()}
176
+ onMouseUp={(e) => this.handleButtonClick(e, "Italic")}
177
+ >
178
+ <i>I</i>
179
+ </button>
180
+
181
+ <button
182
+ name="Underline"
183
+ className={
184
+ "Toolbar-button TB-narrow" +
185
+ (this.props.activeButtons.underline ? " TB-selected" : "")
186
+ }
187
+ onClick={(e) => e.preventDefault()}
188
+ onMouseDown={(e) => e.preventDefault()}
189
+ onMouseUp={(e) => this.handleButtonClick(e, "Underline")}
190
+ >
191
+ <u>U</u>
192
+ </button>
193
+
194
+ <button
195
+ name="Superscript"
196
+ className={
197
+ "Toolbar-button TB-narrow" +
198
+ (this.props.activeButtons.superscript ? " TB-selected" : "")
199
+ }
200
+ onClick={(e) => e.preventDefault()}
201
+ onMouseDown={(e) => e.preventDefault()}
202
+ onMouseUp={(e) => this.handleButtonClick(e, "Superscript")}
203
+ >
204
+ a<sup>x</sup>
205
+ </button>
206
+
207
+ <button
208
+ name="Subscript"
209
+ className={
210
+ "Toolbar-button TB-narrow" +
211
+ (this.props.activeButtons.subscript ? " TB-selected" : "")
212
+ }
213
+ onClick={(e) => e.preventDefault()}
214
+ onMouseDown={(e) => e.preventDefault()}
215
+ onMouseUp={(e) => this.handleButtonClick(e, "Subscript")}
216
+ >
217
+ a<sub>x</sub>
218
+ </button>
219
+ </>
220
+ )}
221
+
222
+ <button
223
+ name="Accents"
224
+ className={
225
+ "Toolbar-button TB-narrow" +
226
+ (this.state.showAccents ? " TB-selected" : "")
227
+ }
228
+ onMouseDown={(e) => e.preventDefault()}
229
+ onClick={(e) => e.preventDefault()}
230
+ onMouseUp={(e) => this.showOrHideAccentBar(e)}
231
+ >
232
+ á
233
+ </button>
234
+
235
+ {enableMath && (
236
+ <button
237
+ name="Equation"
238
+ className="Toolbar-button TB-wide"
239
+ onMouseDown={(e) => this.handleButtonClick(e, "Equation")}
240
+ >
241
+ <div dangerouslySetInnerHTML={{ __html: katexHTML }} />
242
+ <span className="tooltiptext">
243
+ Insert equation [{CTRL_OR_META}Enter]
244
+ </span>
245
+ </button>
246
+ )}
247
+
248
+ {this.state.showAccents && (
249
+ <AccentBar
250
+ accentLetter={this.accentLetter}
251
+ keyPressed={this.props.keyPressed}
252
+ fetchAccentLetter={this.props.fetchAccentLetter}
253
+ onButtonClick={(e, oldCharacter, newCharacter) =>
254
+ this.handleAccentButtonClick(e, oldCharacter, newCharacter)
135
255
  }
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
- }
256
+ />
257
+ )}
258
+ </div>
259
+ );
260
+ }
246
261
  }