@pie-lib/math-input-mathlive 1.0.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 +119 -0
- package/lib/__tests__/index.test.js +118 -0
- package/lib/__tests__/index.test.js.map +1 -0
- package/lib/__tests__/latex-bridge.test.js +186 -0
- package/lib/__tests__/latex-bridge.test.js.map +1 -0
- package/lib/__tests__/mathlive-instance.test.js +137 -0
- package/lib/__tests__/mathlive-instance.test.js.map +1 -0
- package/lib/horizontal-keypad.js +101 -0
- package/lib/horizontal-keypad.js.map +1 -0
- package/lib/index.js +143 -0
- package/lib/index.js.map +1 -0
- package/lib/keypad/index.js +365 -0
- package/lib/keypad/index.js.map +1 -0
- package/lib/keypad/keys-layout.js +22 -0
- package/lib/keypad/keys-layout.js.map +1 -0
- package/lib/keys/basic-operators.js +33 -0
- package/lib/keys/basic-operators.js.map +1 -0
- package/lib/keys/chars.js +12 -0
- package/lib/keys/chars.js.map +1 -0
- package/lib/keys/comparison.js +39 -0
- package/lib/keys/comparison.js.map +1 -0
- package/lib/keys/constants.js +37 -0
- package/lib/keys/constants.js.map +1 -0
- package/lib/keys/digits.js +46 -0
- package/lib/keys/digits.js.map +1 -0
- package/lib/keys/edit.js +14 -0
- package/lib/keys/edit.js.map +1 -0
- package/lib/keys/exponent.js +30 -0
- package/lib/keys/exponent.js.map +1 -0
- package/lib/keys/fractions.js +29 -0
- package/lib/keys/fractions.js.map +1 -0
- package/lib/keys/geometry.js +140 -0
- package/lib/keys/geometry.js.map +1 -0
- package/lib/keys/grades.js +259 -0
- package/lib/keys/grades.js.map +1 -0
- package/lib/keys/index.js +35 -0
- package/lib/keys/index.js.map +1 -0
- package/lib/keys/log.js +27 -0
- package/lib/keys/log.js.map +1 -0
- package/lib/keys/logic.js +19 -0
- package/lib/keys/logic.js.map +1 -0
- package/lib/keys/matrices.js +19 -0
- package/lib/keys/matrices.js.map +1 -0
- package/lib/keys/misc.js +62 -0
- package/lib/keys/misc.js.map +1 -0
- package/lib/keys/navigation.js +20 -0
- package/lib/keys/navigation.js.map +1 -0
- package/lib/keys/operators.js +15 -0
- package/lib/keys/operators.js.map +1 -0
- package/lib/keys/statistics.js +40 -0
- package/lib/keys/statistics.js.map +1 -0
- package/lib/keys/sub-sup.js +19 -0
- package/lib/keys/sub-sup.js.map +1 -0
- package/lib/keys/trigonometry.js +45 -0
- package/lib/keys/trigonometry.js.map +1 -0
- package/lib/keys/utils.js +87 -0
- package/lib/keys/utils.js.map +1 -0
- package/lib/keys/vars.js +24 -0
- package/lib/keys/vars.js.map +1 -0
- package/lib/latex-bridge.js +195 -0
- package/lib/latex-bridge.js.map +1 -0
- package/lib/math-input.js +143 -0
- package/lib/math-input.js.map +1 -0
- package/lib/mathlive-instance.js +319 -0
- package/lib/mathlive-instance.js.map +1 -0
- package/lib/mf/common-styles.js +111 -0
- package/lib/mf/common-styles.js.map +1 -0
- package/lib/mf/index.js +72 -0
- package/lib/mf/index.js.map +1 -0
- package/lib/mf/input.js +266 -0
- package/lib/mf/input.js.map +1 -0
- package/lib/mf/static.js +396 -0
- package/lib/mf/static.js.map +1 -0
- package/package.json +31 -0
- package/src/__tests__/index.test.jsx +109 -0
- package/src/__tests__/latex-bridge.test.js +151 -0
- package/src/__tests__/mathlive-instance.test.js +130 -0
- package/src/horizontal-keypad.jsx +73 -0
- package/src/index.jsx +63 -0
- package/src/keypad/index.jsx +335 -0
- package/src/keypad/keys-layout.js +16 -0
- package/src/keys/basic-operators.js +32 -0
- package/src/keys/chars.js +5 -0
- package/src/keys/comparison.js +28 -0
- package/src/keys/constants.js +35 -0
- package/src/keys/digits.js +40 -0
- package/src/keys/edit.js +3 -0
- package/src/keys/exponent.js +28 -0
- package/src/keys/fractions.js +26 -0
- package/src/keys/geometry.js +144 -0
- package/src/keys/grades.js +367 -0
- package/src/keys/index.js +20 -0
- package/src/keys/log.js +22 -0
- package/src/keys/logic.js +15 -0
- package/src/keys/matrices.js +15 -0
- package/src/keys/misc.js +65 -0
- package/src/keys/navigation.js +8 -0
- package/src/keys/operators.js +10 -0
- package/src/keys/statistics.js +38 -0
- package/src/keys/sub-sup.js +15 -0
- package/src/keys/trigonometry.js +15 -0
- package/src/keys/utils.js +66 -0
- package/src/keys/vars.js +19 -0
- package/src/latex-bridge.js +190 -0
- package/src/math-input.jsx +115 -0
- package/src/mathlive-instance.js +286 -0
- package/src/mf/common-styles.js +108 -0
- package/src/mf/index.js +26 -0
- package/src/mf/input.jsx +223 -0
- package/src/mf/static.jsx +358 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Button from '@mui/material/Button';
|
|
4
|
+
import IconButton from '@mui/material/IconButton';
|
|
5
|
+
import { styled } from '@mui/material/styles';
|
|
6
|
+
import debug from 'debug';
|
|
7
|
+
import { flatten } from 'lodash-es';
|
|
8
|
+
import { color } from '@pie-lib/render-ui';
|
|
9
|
+
|
|
10
|
+
import { baseSet } from '../keys';
|
|
11
|
+
import { sortKeys } from './keys-layout';
|
|
12
|
+
import { commonKeyboardStyles } from '../mf/common-styles';
|
|
13
|
+
import { loadMathLive, latexToMarkup } from '../mathlive-instance';
|
|
14
|
+
|
|
15
|
+
const log = debug('pie-lib:math-input-mathlive:keypad');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A LaTeX keypad label.
|
|
19
|
+
*
|
|
20
|
+
* The MathQuill implementation rendered every LaTeX label as its own
|
|
21
|
+
* `MQ.StaticMath` instance. Here each label is static HTML produced once by
|
|
22
|
+
* `convertLatexToMarkup`, so a 40-key keypad no longer creates 40 live math
|
|
23
|
+
* instances.
|
|
24
|
+
*/
|
|
25
|
+
const LabelHolder = styled('span')({
|
|
26
|
+
pointerEvents: 'none',
|
|
27
|
+
textTransform: 'none',
|
|
28
|
+
color: color.text(),
|
|
29
|
+
display: 'inline-flex',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
justifyContent: 'center',
|
|
32
|
+
lineHeight: 1,
|
|
33
|
+
// Answer-block / empty-slot boxes inside a label.
|
|
34
|
+
'& .ML__placeholder': {
|
|
35
|
+
backgroundColor: color.keypadEmptyPlaceholder(),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export class LatexLabel extends React.Component {
|
|
40
|
+
static propTypes = {
|
|
41
|
+
latex: PropTypes.string.isRequired,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
constructor(props) {
|
|
45
|
+
super(props);
|
|
46
|
+
this.state = { markup: latexToMarkup(props.latex) };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async componentDidMount() {
|
|
50
|
+
// MathLive may not have finished loading when the keypad first mounts.
|
|
51
|
+
if (!this.state.markup) {
|
|
52
|
+
await loadMathLive();
|
|
53
|
+
|
|
54
|
+
if (!this.unmounted) {
|
|
55
|
+
this.setState({ markup: latexToMarkup(this.props.latex) });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
componentDidUpdate(prevProps) {
|
|
61
|
+
if (prevProps.latex !== this.props.latex) {
|
|
62
|
+
this.setState({ markup: latexToMarkup(this.props.latex) });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
componentWillUnmount() {
|
|
67
|
+
this.unmounted = true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
render() {
|
|
71
|
+
const { markup } = this.state;
|
|
72
|
+
|
|
73
|
+
// Fall back to the raw latex so a button is never blank.
|
|
74
|
+
return markup ? (
|
|
75
|
+
// eslint-disable-next-line react/no-danger
|
|
76
|
+
<LabelHolder dangerouslySetInnerHTML={{ __html: markup }} />
|
|
77
|
+
) : (
|
|
78
|
+
<LabelHolder>{this.props.latex}</LabelHolder>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const createCustomLayout = (layoutObj) => {
|
|
84
|
+
if (layoutObj) {
|
|
85
|
+
return {
|
|
86
|
+
gridTemplateColumns: `repeat(${layoutObj.columns}, minmax(min-content, 150px))`,
|
|
87
|
+
gridTemplateRows: `repeat(${layoutObj.rows}, minmax(40px, 60px))`,
|
|
88
|
+
gridAutoFlow: 'initial',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {};
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const KeyPadContainer = styled('div')(() => ({
|
|
96
|
+
...commonKeyboardStyles,
|
|
97
|
+
width: '100%',
|
|
98
|
+
display: 'grid',
|
|
99
|
+
gridTemplateRows: 'repeat(5, minmax(40px, 60px))',
|
|
100
|
+
gridRowGap: '0px',
|
|
101
|
+
gridColumnGap: '0px',
|
|
102
|
+
gridAutoFlow: 'column',
|
|
103
|
+
'&.character': {
|
|
104
|
+
textTransform: 'initial !important',
|
|
105
|
+
gridTemplateRows: 'repeat(5, minmax(40px, 50px)) !important',
|
|
106
|
+
},
|
|
107
|
+
'&.language': {
|
|
108
|
+
gridTemplateRows: 'repeat(4, minmax(40px, 50px)) !important',
|
|
109
|
+
'& *': {
|
|
110
|
+
fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
}));
|
|
114
|
+
|
|
115
|
+
const buttonBackground = (category) => ({
|
|
116
|
+
backgroundColor: category === 'operators' ? color.keypadButtonOperator() : color.keypadButton(),
|
|
117
|
+
'&:hover': {
|
|
118
|
+
backgroundColor: category === 'operators' ? color.keypadButtonOperatorHover() : color.keypadButtonHover(),
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const StyledButton = styled(Button)(({ category, isDelete, isComma, isDot }) => ({
|
|
123
|
+
minWidth: 'auto',
|
|
124
|
+
textTransform: 'none',
|
|
125
|
+
fontSize: isComma || isDot ? '200% !important' : '140% !important',
|
|
126
|
+
lineHeight: isComma || isDot ? '100%' : 'normal',
|
|
127
|
+
color: color.text(),
|
|
128
|
+
...buttonBackground(category),
|
|
129
|
+
borderRadius: 0,
|
|
130
|
+
...(isDelete && {
|
|
131
|
+
fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important',
|
|
132
|
+
}),
|
|
133
|
+
}));
|
|
134
|
+
|
|
135
|
+
const StyledLatexButtonWrapper = styled(Button)(({ category }) => ({
|
|
136
|
+
textTransform: 'none',
|
|
137
|
+
padding: 0,
|
|
138
|
+
margin: 0,
|
|
139
|
+
fontSize: '110% !important',
|
|
140
|
+
minWidth: 'auto',
|
|
141
|
+
borderRadius: 0,
|
|
142
|
+
...buttonBackground(category),
|
|
143
|
+
}));
|
|
144
|
+
|
|
145
|
+
const StyledIconButton = styled(IconButton)(({ category }) => ({
|
|
146
|
+
minWidth: 'auto',
|
|
147
|
+
...buttonBackground(category),
|
|
148
|
+
borderRadius: 0,
|
|
149
|
+
'& .icon': {
|
|
150
|
+
height: '30px',
|
|
151
|
+
},
|
|
152
|
+
}));
|
|
153
|
+
|
|
154
|
+
export class KeyPad extends React.Component {
|
|
155
|
+
static propTypes = {
|
|
156
|
+
className: PropTypes.string,
|
|
157
|
+
controlledKeypadMode: PropTypes.bool,
|
|
158
|
+
baseSet: PropTypes.array,
|
|
159
|
+
additionalKeys: PropTypes.array,
|
|
160
|
+
layoutForKeyPad: PropTypes.object,
|
|
161
|
+
onPress: PropTypes.func.isRequired,
|
|
162
|
+
onFocus: PropTypes.func,
|
|
163
|
+
noDecimal: PropTypes.bool,
|
|
164
|
+
setKeypadInteraction: PropTypes.func,
|
|
165
|
+
mode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
static defaultProps = {
|
|
169
|
+
baseSet: baseSet,
|
|
170
|
+
noDecimal: false,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
constructor(props) {
|
|
174
|
+
super(props);
|
|
175
|
+
this.keypadRef = React.createRef();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
componentDidMount() {
|
|
179
|
+
// Ensure MathLive is available for the LaTeX labels.
|
|
180
|
+
loadMathLive();
|
|
181
|
+
|
|
182
|
+
const keyPadElement = this.keypadRef?.current;
|
|
183
|
+
const mainContainer = keyPadElement?.closest('.main-container');
|
|
184
|
+
const currentToolbar = keyPadElement?.closest('.pie-toolbar');
|
|
185
|
+
|
|
186
|
+
// need only for math keyboard so we need also controlledKeypadMode
|
|
187
|
+
if (this.props.controlledKeypadMode && mainContainer && currentToolbar) {
|
|
188
|
+
const mainContainerPosition = mainContainer.getBoundingClientRect();
|
|
189
|
+
const currentToolbarPosition = currentToolbar.getBoundingClientRect();
|
|
190
|
+
const difference =
|
|
191
|
+
mainContainerPosition.top +
|
|
192
|
+
mainContainerPosition.height -
|
|
193
|
+
(currentToolbarPosition.top + currentToolbarPosition.height);
|
|
194
|
+
|
|
195
|
+
if (difference < 0) {
|
|
196
|
+
const totalHeight = mainContainerPosition.height + mainContainerPosition.top - difference;
|
|
197
|
+
|
|
198
|
+
mainContainer.style.height = `${totalHeight}px`;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (keyPadElement) {
|
|
203
|
+
keyPadElement.addEventListener('touchstart', this.handleKeypadInteraction, true);
|
|
204
|
+
keyPadElement.addEventListener('mousedown', this.handleKeypadInteraction, true);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
componentWillUnmount() {
|
|
209
|
+
const keyPadElement = this.keypadRef?.current;
|
|
210
|
+
|
|
211
|
+
if (this.props.controlledKeypadMode && keyPadElement) {
|
|
212
|
+
const mainContainer = keyPadElement.closest('.main-container');
|
|
213
|
+
|
|
214
|
+
if (mainContainer) {
|
|
215
|
+
mainContainer.style.height = 'unset';
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (keyPadElement) {
|
|
220
|
+
keyPadElement.removeEventListener('touchstart', this.handleKeypadInteraction, true);
|
|
221
|
+
keyPadElement.removeEventListener('mousedown', this.handleKeypadInteraction, true);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
handleKeypadInteraction = () => {
|
|
226
|
+
if (this.props.setKeypadInteraction) {
|
|
227
|
+
this.props.setKeypadInteraction(true);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
buttonClick = (key) => {
|
|
232
|
+
log('[buttonClick]', key);
|
|
233
|
+
this.props.onPress(key);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
flowKeys = (base, extras) => flatten([...sortKeys(base), ...sortKeys(extras)]);
|
|
237
|
+
|
|
238
|
+
keyIsNotAllowed = (key) => {
|
|
239
|
+
const { noDecimal } = this.props;
|
|
240
|
+
|
|
241
|
+
return !!(
|
|
242
|
+
((key.write === '.' && key.label === '.') || (key.write === ',' && key.label === ',')) &&
|
|
243
|
+
noDecimal
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
render() {
|
|
248
|
+
const { className, baseSet: base, additionalKeys, layoutForKeyPad, onFocus, mode } = this.props;
|
|
249
|
+
|
|
250
|
+
const noBaseSet = ['non-negative-integers', 'integers', 'decimals', 'fractions', 'item-authoring', 'language'];
|
|
251
|
+
const keysWithoutBaseSet = noBaseSet.includes(mode);
|
|
252
|
+
const allKeys = keysWithoutBaseSet
|
|
253
|
+
? this.flowKeys([], additionalKeys || [])
|
|
254
|
+
: this.flowKeys(base, additionalKeys || []);
|
|
255
|
+
|
|
256
|
+
const shift = allKeys.length % 5 ? 1 : 0;
|
|
257
|
+
const style = {
|
|
258
|
+
gridTemplateColumns: `repeat(${Math.floor(allKeys.length / 5) + shift}, minmax(min-content, 150px))`,
|
|
259
|
+
...createCustomLayout(layoutForKeyPad),
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<KeyPadContainer
|
|
264
|
+
ref={this.keypadRef}
|
|
265
|
+
className={[className, mode].filter(Boolean).join(' ')}
|
|
266
|
+
style={style}
|
|
267
|
+
onFocus={onFocus}
|
|
268
|
+
>
|
|
269
|
+
{allKeys.map((k, index) => {
|
|
270
|
+
if (!k) {
|
|
271
|
+
return <span key={`empty-${index}`} />;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const key = `${k.label || k.latex || k.command}-${index}`;
|
|
275
|
+
const category = !keysWithoutBaseSet ? k.category : undefined;
|
|
276
|
+
const extra = { ...(k.actions || {}), ...(k.extraProps || {}) };
|
|
277
|
+
const onClick = this.buttonClick.bind(this, k);
|
|
278
|
+
const disabled = this.keyIsNotAllowed(k);
|
|
279
|
+
const ariaLabel = k.ariaLabel ? k.ariaLabel : k.name || k.label;
|
|
280
|
+
|
|
281
|
+
if (k.latex) {
|
|
282
|
+
return (
|
|
283
|
+
<StyledLatexButtonWrapper
|
|
284
|
+
key={key}
|
|
285
|
+
onClick={onClick}
|
|
286
|
+
disabled={disabled}
|
|
287
|
+
category={category}
|
|
288
|
+
aria-label={ariaLabel}
|
|
289
|
+
{...extra}
|
|
290
|
+
>
|
|
291
|
+
<LatexLabel latex={k.latex} />
|
|
292
|
+
</StyledLatexButtonWrapper>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (k.label) {
|
|
297
|
+
return (
|
|
298
|
+
<StyledButton
|
|
299
|
+
key={key}
|
|
300
|
+
onClick={onClick}
|
|
301
|
+
disabled={disabled}
|
|
302
|
+
category={category}
|
|
303
|
+
isDelete={k.label === '⌫'}
|
|
304
|
+
isComma={k.label === ','}
|
|
305
|
+
isDot={k.label === '.'}
|
|
306
|
+
aria-label={ariaLabel}
|
|
307
|
+
{...extra}
|
|
308
|
+
>
|
|
309
|
+
{k.label}
|
|
310
|
+
</StyledButton>
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const Icon = k.icon ? k.icon : 'div';
|
|
315
|
+
|
|
316
|
+
return (
|
|
317
|
+
<StyledIconButton
|
|
318
|
+
key={key}
|
|
319
|
+
tabIndex={'-1'}
|
|
320
|
+
onClick={onClick}
|
|
321
|
+
disabled={disabled}
|
|
322
|
+
category={category}
|
|
323
|
+
size="large"
|
|
324
|
+
{...extra}
|
|
325
|
+
>
|
|
326
|
+
<Icon className="icon" />
|
|
327
|
+
</StyledIconButton>
|
|
328
|
+
);
|
|
329
|
+
})}
|
|
330
|
+
</KeyPadContainer>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export default KeyPad;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { times, zip } from 'lodash-es';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sort additional keys.
|
|
5
|
+
*
|
|
6
|
+
* Expects an array of rows.
|
|
7
|
+
* @param {} keys
|
|
8
|
+
*/
|
|
9
|
+
export const sortKeys = (keys) => {
|
|
10
|
+
// add any missing rows
|
|
11
|
+
times(5 - keys.length, () => keys.push([]));
|
|
12
|
+
|
|
13
|
+
const out = zip.apply(null, keys);
|
|
14
|
+
|
|
15
|
+
return out;
|
|
16
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DIVIDE, MULTIPLY } from './chars';
|
|
2
|
+
import { mkSet } from './utils';
|
|
3
|
+
|
|
4
|
+
const set = mkSet('operators');
|
|
5
|
+
|
|
6
|
+
export const equals = set({
|
|
7
|
+
write: '=',
|
|
8
|
+
label: '=',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const plus = set({
|
|
12
|
+
write: '+',
|
|
13
|
+
label: '+',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const minus = set({
|
|
17
|
+
write: '−',
|
|
18
|
+
label: '−',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const divide = set({
|
|
22
|
+
name: 'divide',
|
|
23
|
+
label: DIVIDE,
|
|
24
|
+
command: '\\divide',
|
|
25
|
+
otherNotation: '\\div',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const multiply = set({
|
|
29
|
+
name: 'multiply',
|
|
30
|
+
label: MULTIPLY,
|
|
31
|
+
command: '\\times',
|
|
32
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const set = (o) => ({ ...o, category: 'comparison' });
|
|
2
|
+
|
|
3
|
+
export const lessThan = set({
|
|
4
|
+
name: 'Less than',
|
|
5
|
+
latex: '<',
|
|
6
|
+
command: '\\lt',
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export const greaterThan = set({
|
|
10
|
+
name: 'Greater than',
|
|
11
|
+
latex: '>',
|
|
12
|
+
command: '\\gt',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const lessThanEqual = set({
|
|
16
|
+
name: 'Less than or equal',
|
|
17
|
+
latex: '\\le',
|
|
18
|
+
symbol: '<=',
|
|
19
|
+
command: '\\le',
|
|
20
|
+
ariaLabel: 'less than or equal to',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const greaterThanEqual = set({
|
|
24
|
+
name: 'Greater than or equal',
|
|
25
|
+
symbol: '>=',
|
|
26
|
+
command: '\\ge',
|
|
27
|
+
latex: '\\ge',
|
|
28
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { mkSet } from './utils';
|
|
2
|
+
|
|
3
|
+
const set = mkSet('constants');
|
|
4
|
+
|
|
5
|
+
export const pi = set({
|
|
6
|
+
name: 'Pi',
|
|
7
|
+
label: 'π',
|
|
8
|
+
latex: '\\pi',
|
|
9
|
+
command: '\\pi',
|
|
10
|
+
category: 'constants',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const eulers = set({
|
|
14
|
+
name: 'Eulers',
|
|
15
|
+
label: 'e',
|
|
16
|
+
latex: 'e',
|
|
17
|
+
command: 'e',
|
|
18
|
+
category: 'constants',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const infinity = set({
|
|
22
|
+
name: 'Infinity',
|
|
23
|
+
label: '\\infty',
|
|
24
|
+
latex: '\\infty',
|
|
25
|
+
command: '\\infty',
|
|
26
|
+
category: 'constants',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const halfInfinity = set({
|
|
30
|
+
name: 'Half Infinity',
|
|
31
|
+
label: '\\propto',
|
|
32
|
+
latex: '\\propto',
|
|
33
|
+
command: '\\propto',
|
|
34
|
+
category: 'constants',
|
|
35
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { times } from 'lodash-es';
|
|
2
|
+
|
|
3
|
+
const digitMap = {
|
|
4
|
+
0: 'zero',
|
|
5
|
+
1: 'one',
|
|
6
|
+
2: 'two',
|
|
7
|
+
3: 'three',
|
|
8
|
+
4: 'four',
|
|
9
|
+
5: 'five',
|
|
10
|
+
6: 'six',
|
|
11
|
+
7: 'seven',
|
|
12
|
+
8: 'eight',
|
|
13
|
+
9: 'nine',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const comma = { name: 'comma', label: ',', write: ',', category: 'digit' };
|
|
17
|
+
|
|
18
|
+
const decimalPoint = {
|
|
19
|
+
name: 'decimal-point',
|
|
20
|
+
label: '.',
|
|
21
|
+
write: '.',
|
|
22
|
+
category: 'digit',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default times(10, String)
|
|
26
|
+
.map((n) => {
|
|
27
|
+
return {
|
|
28
|
+
name: digitMap[n],
|
|
29
|
+
write: n,
|
|
30
|
+
label: n,
|
|
31
|
+
category: 'digit',
|
|
32
|
+
};
|
|
33
|
+
})
|
|
34
|
+
.reduce(
|
|
35
|
+
(acc, o) => {
|
|
36
|
+
acc[o.name] = o;
|
|
37
|
+
return acc;
|
|
38
|
+
},
|
|
39
|
+
{ comma, decimalPoint },
|
|
40
|
+
);
|
package/src/keys/edit.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { mkSet } from './utils';
|
|
2
|
+
|
|
3
|
+
const set = mkSet('exponent');
|
|
4
|
+
|
|
5
|
+
export const squared = set({
|
|
6
|
+
name: 'Squared',
|
|
7
|
+
latex: 'x^2',
|
|
8
|
+
write: '^2',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const xToPowerOfN = set({
|
|
12
|
+
name: 'X to the power of n',
|
|
13
|
+
latex: 'x^{}',
|
|
14
|
+
command: '^',
|
|
15
|
+
ariaLabel: 'exponent',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const squareRoot = set({
|
|
19
|
+
name: 'Square root',
|
|
20
|
+
latex: '\\sqrt{}',
|
|
21
|
+
command: '\\sqrt',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const nthRoot = set({
|
|
25
|
+
name: 'Nth root',
|
|
26
|
+
latex: '\\sqrt[{}]{}',
|
|
27
|
+
command: '\\nthroot',
|
|
28
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { mkSet } from './utils';
|
|
2
|
+
|
|
3
|
+
const set = mkSet('fractions');
|
|
4
|
+
|
|
5
|
+
export const blankOverBlank = set({
|
|
6
|
+
name: 'blank/blank',
|
|
7
|
+
latex: '\\frac{}{}',
|
|
8
|
+
command: '\\frac',
|
|
9
|
+
ariaLabel: 'fraction',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const xOverBlank = set({
|
|
13
|
+
latex: '\\frac{x}{ }',
|
|
14
|
+
name: 'X/blank',
|
|
15
|
+
label: 'x/[]',
|
|
16
|
+
command: '/',
|
|
17
|
+
ariaLabel: 'x over blank fraction',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const xBlankBlank = set({
|
|
21
|
+
name: 'X (blank/blank)',
|
|
22
|
+
latex: 'x\\frac{}{}',
|
|
23
|
+
label: 'x([]/[])',
|
|
24
|
+
command: '\\frac',
|
|
25
|
+
ariaLabel: 'mixed number',
|
|
26
|
+
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const set = (o) => ({ ...o, category: 'geometry' });
|
|
2
|
+
|
|
3
|
+
export const overline = set({
|
|
4
|
+
name: 'Line',
|
|
5
|
+
latex: '\\overline{}',
|
|
6
|
+
command: '\\overline',
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export const overRightArrow = set({
|
|
10
|
+
name: 'Ray',
|
|
11
|
+
latex: '\\overrightarrow{}',
|
|
12
|
+
command: '\\overrightarrow',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const overLeftRightArrow = set({
|
|
16
|
+
name: 'Segment',
|
|
17
|
+
latex: '\\overleftrightarrow{\\overline{}}', // used this notation to display the pink box
|
|
18
|
+
symbol: 'AB',
|
|
19
|
+
command: '\\overleftrightarrow',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const segment = set({
|
|
23
|
+
name: 'Segment',
|
|
24
|
+
latex: '\\overleftrightarrow{AB}',
|
|
25
|
+
write: '\\overleftrightarrow{AB}',
|
|
26
|
+
label: 'AB',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const parallel = set({
|
|
30
|
+
name: 'Parallel',
|
|
31
|
+
latex: '\\parallel',
|
|
32
|
+
command: '\\parallel',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export const notParallel = set({
|
|
36
|
+
name: 'Not Parallel',
|
|
37
|
+
latex: '\\nparallel',
|
|
38
|
+
command: '\\nparallel',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const perpindicular = set({
|
|
42
|
+
name: 'Perpendicular',
|
|
43
|
+
latex: '\\perp',
|
|
44
|
+
command: '\\perpendicular',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export const angle = set({
|
|
48
|
+
name: 'Angle',
|
|
49
|
+
latex: '\\angle',
|
|
50
|
+
command: '\\angle',
|
|
51
|
+
});
|
|
52
|
+
export const overArc = set({
|
|
53
|
+
name: 'Over arc',
|
|
54
|
+
latex: '\\overarc{\\overline{}}', // used this notation to display the pink box
|
|
55
|
+
command: '\\overarc',
|
|
56
|
+
});
|
|
57
|
+
export const measureOfAngle = set({
|
|
58
|
+
name: 'Measured Angle',
|
|
59
|
+
latex: '\\measuredangle',
|
|
60
|
+
command: ['m', '\\angle'],
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export const triangle = set({
|
|
64
|
+
name: 'Triangle',
|
|
65
|
+
latex: '\\triangle',
|
|
66
|
+
command: '\\triangle',
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const square = set({
|
|
70
|
+
name: 'Square',
|
|
71
|
+
latex: '\\square',
|
|
72
|
+
command: '\\square',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export const parallelogram = set({
|
|
76
|
+
name: 'Parallelogram',
|
|
77
|
+
latex: '\\parallelogram',
|
|
78
|
+
command: '\\parallelogram',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export const circledDot = set({
|
|
82
|
+
name: 'Circled Dot',
|
|
83
|
+
latex: '\\odot',
|
|
84
|
+
command: '\\odot',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
export const degree = set({
|
|
88
|
+
name: 'Degree',
|
|
89
|
+
latex: '\\degree',
|
|
90
|
+
command: '\\degree',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export const similarTo = set({
|
|
94
|
+
name: 'Similar',
|
|
95
|
+
command: '\\sim',
|
|
96
|
+
latex: '\\sim',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export const congruentTo = set({
|
|
100
|
+
name: 'Congruent To',
|
|
101
|
+
command: '\\cong',
|
|
102
|
+
latex: '\\cong',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
export const notCongruentTo = set({
|
|
106
|
+
name: 'Not Congruent To',
|
|
107
|
+
command: '\\ncong',
|
|
108
|
+
latex: '\\ncong',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
export const primeArcminute = set({
|
|
112
|
+
name: 'Prime',
|
|
113
|
+
label: 'pam',
|
|
114
|
+
// eslint-disable-next-line
|
|
115
|
+
latex: "'",
|
|
116
|
+
// eslint-disable-next-line
|
|
117
|
+
write: "'",
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export const doublePrimeArcSecond = set({
|
|
121
|
+
name: 'Double Prime',
|
|
122
|
+
// eslint-disable-next-line
|
|
123
|
+
latex: "''",
|
|
124
|
+
// eslint-disable-next-line
|
|
125
|
+
write: "''",
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
export const leftArrow = set({
|
|
129
|
+
name: 'Left Arrow',
|
|
130
|
+
latex: '\\leftarrow',
|
|
131
|
+
command: '\\leftarrow',
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
export const rightArrow = set({
|
|
135
|
+
name: 'Right Arrow',
|
|
136
|
+
latex: '\\rightarrow',
|
|
137
|
+
command: '\\rightarrow',
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
export const leftrightArrow = set({
|
|
141
|
+
name: 'Left and Right Arrow',
|
|
142
|
+
latex: '\\leftrightarrow',
|
|
143
|
+
command: '\\leftrightarrow',
|
|
144
|
+
});
|