@khanacademy/perseus 6.1.0 → 6.2.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @khanacademy/perseus
2
2
 
3
+ ## 6.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [a7f56710]
8
+ - Updated dependencies [a7f56710]
9
+ - @khanacademy/math-input@4.1.0
10
+
11
+ ## 6.2.0
12
+
13
+ ### Minor Changes
14
+
15
+ - e900688e: Centralize Key2MathQuill translator. TeXButtons send keypresses, not strings/functions anymore.
16
+
17
+ ### Patch Changes
18
+
19
+ - 83d93e8f: Remove the use of Record<string, never> which is unsafe
20
+ - 3a3c317d: Refactor MathWrapper to use shared key2MathQuill translator
21
+ - Updated dependencies [0d352105]
22
+ - Updated dependencies [c4b8d862]
23
+ - Updated dependencies [47055ffc]
24
+ - Updated dependencies [e900688e]
25
+ - Updated dependencies [3a3c317d]
26
+ - @khanacademy/math-input@4.0.0
27
+
3
28
  ## 6.1.0
4
29
 
5
30
  ### Minor Changes
@@ -31,7 +31,7 @@ declare class MathInput extends React.Component<Props, State> {
31
31
  handleMouseUp: (arg1: MouseEvent) => void;
32
32
  handleBlur: (arg1: React.FocusEvent) => void;
33
33
  _shouldShowButtons: () => boolean;
34
- insert: (arg1: any) => void;
34
+ insert: (value: any) => void;
35
35
  mathField: (arg1: any) => any;
36
36
  focus: () => void;
37
37
  blur: () => void;
@@ -37,7 +37,7 @@ declare class MathInput extends React.Component<Props, State> {
37
37
  handleMouseUp: (arg1: MouseEvent) => void;
38
38
  handleBlur: (arg1: SyntheticFocusEvent<>) => void;
39
39
  _shouldShowButtons: () => boolean;
40
- insert: (arg1: any) => void;
40
+ insert: (value: any) => void;
41
41
  mathField: (arg1: any) => any;
42
42
  focus: () => void;
43
43
  blur: () => void;
@@ -45,7 +45,7 @@ type SortableItem = {
45
45
  option: SortableOption;
46
46
  key: number;
47
47
  state: ItemState;
48
- endPosition: Position | Record<string, never>;
48
+ endPosition?: Position;
49
49
  width: number;
50
50
  height: number;
51
51
  };
@@ -58,7 +58,7 @@ declare type SortableItem = {|
58
58
  option: SortableOption,
59
59
  key: number,
60
60
  state: $Values<typeof ItemState>,
61
- endPosition: Position | { [key: string]: empty },
61
+ endPosition?: Position,
62
62
  width: number,
63
63
  height: number,
64
64
  |};
@@ -1,6 +1,6 @@
1
+ import { Keys } from "@khanacademy/math-input";
1
2
  import * as React from "react";
2
- type Inserter = string | ((input: any) => void);
3
- type ButtonSet = (props: any) => [React.ReactNode, Inserter];
3
+ type ButtonSet = (props: any) => [React.ReactNode, Keys];
4
4
  type ButtonSets = {
5
5
  readonly [key: string]: ReadonlyArray<ButtonSet>;
6
6
  };
@@ -8,7 +8,7 @@ declare const buttonSets: ButtonSets;
8
8
  export type ButtonSetsType = ReadonlyArray<keyof typeof buttonSets>;
9
9
  type Props = {
10
10
  sets: ButtonSetsType;
11
- onInsert: (arg1: Inserter) => void;
11
+ onInsert: (key: Keys) => void;
12
12
  className?: string;
13
13
  convertDotToTimes?: boolean;
14
14
  };
@@ -4,9 +4,9 @@
4
4
  * Flowgen v1.21.0
5
5
  * @flow
6
6
  */
7
+ import { Keys } from "@khanacademy/math-input";
7
8
  import * as React from "react";
8
- declare type Inserter = string | ((input: any) => void);
9
- declare type ButtonSet = (props: any) => [React.Node, Inserter];
9
+ declare type ButtonSet = (props: any) => [React.Node, Keys];
10
10
  declare type ButtonSets = {
11
11
  +[key: string]: $ReadOnlyArray<ButtonSet>,
12
12
  };
@@ -14,7 +14,7 @@ declare var buttonSets: ButtonSets;
14
14
  export type ButtonSetsType = $ReadOnlyArray<$Keys<typeof buttonSets>>;
15
15
  declare type Props = {|
16
16
  sets: ButtonSetsType,
17
- onInsert: (arg1: Inserter) => void,
17
+ onInsert: (key: Keys) => void,
18
18
  className?: string,
19
19
  convertDotToTimes?: boolean,
20
20
  |};
package/dist/es/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as KAS from '@khanacademy/kas';
2
- import { KeypadInput, KeypadType, keypadElementPropType, LegacyKeypad } from '@khanacademy/math-input';
2
+ import { keyTranslator, KeypadInput, KeypadType, keypadElementPropType, LegacyKeypad } from '@khanacademy/math-input';
3
3
  import * as PerseusLinter from '@khanacademy/perseus-linter';
4
4
  import { linterContextDefault, Rule, linterContextProps } from '@khanacademy/perseus-linter';
5
5
  import * as i18n from '@khanacademy/wonder-blocks-i18n';
@@ -138,10 +138,10 @@ const symbStyle = {
138
138
  const basic = [() => [/*#__PURE__*/React.createElement("span", {
139
139
  key: "plus",
140
140
  style: slightlyBig
141
- }, "+"), "+"], () => [/*#__PURE__*/React.createElement("span", {
141
+ }, "+"), "PLUS"], () => [/*#__PURE__*/React.createElement("span", {
142
142
  key: "minus",
143
143
  style: prettyBig
144
- }, "-"), "-"],
144
+ }, "-"), "MINUS"],
145
145
  // TODO(joel) - display as \cdot when appropriate
146
146
  props => {
147
147
  const {
@@ -151,12 +151,12 @@ props => {
151
151
  return [/*#__PURE__*/React.createElement(TeX, {
152
152
  key: "times",
153
153
  style: prettyBig
154
- }, i18n.doNotTranslate("\\times")), "\\times"];
154
+ }, i18n.doNotTranslate("\\times")), "TIMES"];
155
155
  }
156
156
  return [/*#__PURE__*/React.createElement(TeX, {
157
157
  key: "times",
158
158
  style: prettyBig
159
- }, i18n.doNotTranslate("\\cdot")), "\\cdot"];
159
+ }, i18n.doNotTranslate("\\cdot")), "CDOT"];
160
160
  }, () => {
161
161
  const {
162
162
  TeX
@@ -164,17 +164,7 @@ props => {
164
164
  return [/*#__PURE__*/React.createElement(TeX, {
165
165
  key: "frac",
166
166
  style: prettyBig
167
- }, i18n.doNotTranslate("\\frac{x}{y}")),
168
- // If there's something in the input that can become part of a
169
- // fraction, typing "/" puts it in the numerator. If not, typing
170
- // "/" does nothing. In that case, enter a \frac.
171
- input => {
172
- const contents = input.latex();
173
- input.typedText("/");
174
- if (input.latex() === contents) {
175
- input.cmd("\\frac");
176
- }
177
- }];
167
+ }, i18n.doNotTranslate("\\frac{x}{y}")), "FRAC"];
178
168
  }];
179
169
  const buttonSets = {
180
170
  basic,
@@ -184,7 +174,7 @@ const buttonSets = {
184
174
  } = getDependencies();
185
175
  return [/*#__PURE__*/React.createElement(TeX, {
186
176
  key: "div"
187
- }, i18n.doNotTranslate("\\div")), "\\div"];
177
+ }, i18n.doNotTranslate("\\div")), "DIVIDE"];
188
178
  }]),
189
179
  trig: [() => {
190
180
  const {
@@ -192,21 +182,21 @@ const buttonSets = {
192
182
  } = getDependencies();
193
183
  return [/*#__PURE__*/React.createElement(TeX, {
194
184
  key: "sin"
195
- }, i18n.doNotTranslate("\\sin")), "\\sin"];
185
+ }, i18n.doNotTranslate("\\sin")), "SIN"];
196
186
  }, () => {
197
187
  const {
198
188
  TeX
199
189
  } = getDependencies();
200
190
  return [/*#__PURE__*/React.createElement(TeX, {
201
191
  key: "cos"
202
- }, i18n.doNotTranslate("\\cos")), "\\cos"];
192
+ }, i18n.doNotTranslate("\\cos")), "COS"];
203
193
  }, () => {
204
194
  const {
205
195
  TeX
206
196
  } = getDependencies();
207
197
  return [/*#__PURE__*/React.createElement(TeX, {
208
198
  key: "tan"
209
- }, i18n.doNotTranslate("\\tan")), "\\tan"];
199
+ }, i18n.doNotTranslate("\\tan")), "TAN"];
210
200
  }, () => {
211
201
  const {
212
202
  TeX
@@ -214,7 +204,7 @@ const buttonSets = {
214
204
  return [/*#__PURE__*/React.createElement(TeX, {
215
205
  key: "theta",
216
206
  style: symbStyle
217
- }, i18n.doNotTranslate("\\theta")), "\\theta"];
207
+ }, i18n.doNotTranslate("\\theta")), "THETA"];
218
208
  }, () => {
219
209
  const {
220
210
  TeX
@@ -226,7 +216,7 @@ const buttonSets = {
226
216
  }, i18n.doNotTranslate("phi")), /*#__PURE__*/React.createElement(TeX, {
227
217
  key: "pi",
228
218
  style: symbStyle
229
- }, i18n.doNotTranslate("\\phi"))), "\\phi"];
219
+ }, i18n.doNotTranslate("\\phi"))), "PHI"];
230
220
  }],
231
221
  prealgebra: [() => {
232
222
  const {
@@ -234,7 +224,7 @@ const buttonSets = {
234
224
  } = getDependencies();
235
225
  return [/*#__PURE__*/React.createElement(TeX, {
236
226
  key: "sqrt"
237
- }, i18n.doNotTranslate("\\sqrt{x}")), "\\sqrt"];
227
+ }, i18n.doNotTranslate("\\sqrt{x}")), "SQRT"];
238
228
  },
239
229
  // TODO(joel) - how does desmos do this?
240
230
  () => {
@@ -243,10 +233,7 @@ const buttonSets = {
243
233
  } = getDependencies();
244
234
  return [/*#__PURE__*/React.createElement(TeX, {
245
235
  key: "nthroot"
246
- }, i18n.doNotTranslate("\\sqrt[3]{x}")), input => {
247
- input.typedText("nthroot3");
248
- input.keystroke("Right");
249
- }];
236
+ }, i18n.doNotTranslate("\\sqrt[3]{x}")), "NTHROOT3"];
250
237
  }, () => {
251
238
  const {
252
239
  TeX
@@ -254,17 +241,7 @@ const buttonSets = {
254
241
  return [/*#__PURE__*/React.createElement(TeX, {
255
242
  key: "pow",
256
243
  style: slightlyBig
257
- }, i18n.doNotTranslate("a^b")), input => {
258
- const contents = input.latex();
259
- input.typedText("^");
260
-
261
- // If the input hasn't changed (for example, if we're
262
- // attempting to add an exponent on an empty input or an empty
263
- // denominator), insert our own "a^b"
264
- if (input.latex() === contents) {
265
- input.typedText("a^b");
266
- }
267
- }];
244
+ }, i18n.doNotTranslate("a^b")), "POW"];
268
245
  }, () => {
269
246
  const {
270
247
  TeX
@@ -272,7 +249,7 @@ const buttonSets = {
272
249
  return [/*#__PURE__*/React.createElement(TeX, {
273
250
  key: "pi",
274
251
  style: slightlyBig
275
- }, i18n.doNotTranslate("\\pi")), "\\pi"];
252
+ }, i18n.doNotTranslate("\\pi")), "PI"];
276
253
  }],
277
254
  logarithms: [() => {
278
255
  const {
@@ -280,27 +257,21 @@ const buttonSets = {
280
257
  } = getDependencies();
281
258
  return [/*#__PURE__*/React.createElement(TeX, {
282
259
  key: "log"
283
- }, i18n.doNotTranslate("\\log")), "\\log"];
260
+ }, i18n.doNotTranslate("\\log")), "LOG"];
284
261
  }, () => {
285
262
  const {
286
263
  TeX
287
264
  } = getDependencies();
288
265
  return [/*#__PURE__*/React.createElement(TeX, {
289
266
  key: "ln"
290
- }, i18n.doNotTranslate("\\ln")), "\\ln"];
267
+ }, i18n.doNotTranslate("\\ln")), "LN"];
291
268
  }, () => {
292
269
  const {
293
270
  TeX
294
271
  } = getDependencies();
295
272
  return [/*#__PURE__*/React.createElement(TeX, {
296
273
  key: "log_b"
297
- }, i18n.doNotTranslate("\\log_b")), input => {
298
- input.typedText("log_");
299
- input.keystroke("Right");
300
- input.typedText("(");
301
- input.keystroke("Left");
302
- input.keystroke("Left");
303
- }];
274
+ }, i18n.doNotTranslate("\\log_b")), "LOG_B"];
304
275
  }],
305
276
  "basic relations": [() => {
306
277
  const {
@@ -308,21 +279,21 @@ const buttonSets = {
308
279
  } = getDependencies();
309
280
  return [/*#__PURE__*/React.createElement(TeX, {
310
281
  key: "eq"
311
- }, "="), "="];
282
+ }, "="), "EQUAL"];
312
283
  }, () => {
313
284
  const {
314
285
  TeX
315
286
  } = getDependencies();
316
287
  return [/*#__PURE__*/React.createElement(TeX, {
317
288
  key: "lt"
318
- }, i18n.doNotTranslate("\\lt")), "\\lt"];
289
+ }, i18n.doNotTranslate("\\lt")), "LT"];
319
290
  }, () => {
320
291
  const {
321
292
  TeX
322
293
  } = getDependencies();
323
294
  return [/*#__PURE__*/React.createElement(TeX, {
324
295
  key: "gt"
325
- }, i18n.doNotTranslate("\\gt")), "\\gt"];
296
+ }, i18n.doNotTranslate("\\gt")), "GT"];
326
297
  }],
327
298
  "advanced relations": [() => {
328
299
  const {
@@ -330,21 +301,21 @@ const buttonSets = {
330
301
  } = getDependencies();
331
302
  return [/*#__PURE__*/React.createElement(TeX, {
332
303
  key: "neq"
333
- }, i18n.doNotTranslate("\\neq")), "\\neq"];
304
+ }, i18n.doNotTranslate("\\neq")), "NEQ"];
334
305
  }, () => {
335
306
  const {
336
307
  TeX
337
308
  } = getDependencies();
338
309
  return [/*#__PURE__*/React.createElement(TeX, {
339
310
  key: "leq"
340
- }, i18n.doNotTranslate("\\leq")), "\\leq"];
311
+ }, i18n.doNotTranslate("\\leq")), "LEQ"];
341
312
  }, () => {
342
313
  const {
343
314
  TeX
344
315
  } = getDependencies();
345
316
  return [/*#__PURE__*/React.createElement(TeX, {
346
317
  key: "geq"
347
- }, i18n.doNotTranslate("\\geq")), "\\geq"];
318
+ }, i18n.doNotTranslate("\\geq")), "GEQ"];
348
319
  }]
349
320
  };
350
321
  const buttonSetsPropType = PropTypes.arrayOf(PropTypes.oneOf(_(buttonSets).keys()));
@@ -383,6 +354,19 @@ class TexButtons extends React.Component {
383
354
  TexButtons.buttonSets = buttonSets;
384
355
  TexButtons.buttonSetsType = buttonSetsPropType;
385
356
 
357
+ const customKeyTranslator = _extends({}, keyTranslator, {
358
+ // If there's something in the input that can become part of a
359
+ // fraction, typing "/" puts it in the numerator. If not, typing
360
+ // "/" does nothing. In that case, enter a \frac.
361
+ FRAC: mathQuill => {
362
+ const contents = mathQuill.latex();
363
+ mathQuill.typedText("/");
364
+ if (mathQuill.latex() === contents) {
365
+ mathQuill.cmd("\\frac");
366
+ }
367
+ }
368
+ });
369
+
386
370
  // A WYSIWYG math input that calls `onChange(LaTeX-string)`
387
371
  class MathInput extends React.Component {
388
372
  constructor(...args) {
@@ -444,6 +428,17 @@ class MathInput extends React.Component {
444
428
  this.insert = value => {
445
429
  // @ts-expect-error [FEI-5003] - TS2554 - Expected 1 arguments, but got 0.
446
430
  const input = this.mathField();
431
+ const inputModifier = customKeyTranslator[value];
432
+ if (inputModifier) {
433
+ inputModifier(input, value);
434
+ input.focus();
435
+ return;
436
+ }
437
+
438
+ // note(Matthew): I'm not sure this is still being used
439
+ // but it fails tests when I remove it and the way we call
440
+ // methods directly on components makes it difficult to confirm
441
+ // if it's dead code
447
442
  if (_(value).isFunction()) {
448
443
  value(input);
449
444
  } else if (value[0] === "\\") {
@@ -2587,11 +2582,6 @@ class Expression extends React.Component {
2587
2582
  // @ts-expect-error [FEI-5003] - TS2339 - Property 'blur' does not exist on type 'ReactInstance'.
2588
2583
  this.refs.input.blur();
2589
2584
  };
2590
- this.insert = text => {
2591
- // eslint-disable-next-line react/no-string-refs
2592
- // @ts-expect-error [FEI-5003] - TS2339 - Property 'insert' does not exist on type 'ReactInstance'.
2593
- this.refs.input.insert(text);
2594
- };
2595
2585
  this.getInputPaths = () => {
2596
2586
  // The widget itself is an input, so we return a single empty list to
2597
2587
  // indicate this.
@@ -2764,6 +2754,12 @@ class Expression extends React.Component {
2764
2754
  }
2765
2755
  //#endregion
2766
2756
 
2757
+ // HACK(joel)
2758
+ insert(keyPressed) {
2759
+ // eslint-disable-next-line react/no-string-refs
2760
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'insert' does not exist on type 'ReactInstance'.
2761
+ this.refs.input.insert(keyPressed);
2762
+ }
2767
2763
  render() {
2768
2764
  if (this.props.apiOptions.customKeypad) {
2769
2765
  return /*#__PURE__*/React.createElement(KeypadInput
@@ -32339,7 +32335,7 @@ class Draggable extends React.Component {
32339
32335
  if (this.props.state === prevProps.state) {
32340
32336
  return;
32341
32337
  }
32342
- if (this.props.state === ItemState.ANIMATING) {
32338
+ if (this.props.state === ItemState.ANIMATING && this.props.endPosition) {
32343
32339
  // Start animating
32344
32340
  const current = this.getCurrentPosition();
32345
32341
  const duration = 15 * Math.sqrt(Math.sqrt(Math.pow(this.props.endPosition.left - current.left, 2) + Math.pow(this.props.endPosition.top - current.top, 2)));
@@ -32409,7 +32405,6 @@ class Sortable extends React.Component {
32409
32405
  option: option,
32410
32406
  key: i,
32411
32407
  state,
32412
- endPosition: {},
32413
32408
  width: 0,
32414
32409
  height: 0
32415
32410
  };