@khanacademy/perseus-editor 2.15.5 → 2.15.7

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/es/index.js +190 -329
  3. package/dist/es/index.js.map +1 -1
  4. package/dist/index.js +190 -338
  5. package/dist/index.js.map +1 -1
  6. package/dist/widgets/interaction-editor/function-editor.d.ts +19 -20
  7. package/dist/widgets/interaction-editor/interaction-editor.d.ts +23 -14
  8. package/dist/widgets/interaction-editor/label-editor.d.ts +15 -16
  9. package/dist/widgets/interaction-editor/line-editor.d.ts +23 -24
  10. package/dist/widgets/interaction-editor/mathquill-input.d.ts +12 -0
  11. package/dist/widgets/interaction-editor/movable-line-editor.d.ts +23 -26
  12. package/dist/widgets/interaction-editor/movable-point-editor.d.ts +18 -22
  13. package/dist/widgets/interaction-editor/parametric-editor.d.ts +21 -22
  14. package/dist/widgets/interaction-editor/point-editor.d.ts +13 -14
  15. package/dist/widgets/interaction-editor/rectangle-editor.d.ts +17 -18
  16. package/package.json +3 -2
  17. package/src/widgets/__stories__/interaction-editor.stories.tsx +17 -4
  18. package/src/widgets/interaction-editor/constraint-editor.tsx +9 -21
  19. package/src/widgets/interaction-editor/function-editor.tsx +26 -29
  20. package/src/widgets/interaction-editor/interaction-editor.tsx +24 -17
  21. package/src/widgets/interaction-editor/label-editor.tsx +20 -24
  22. package/src/widgets/interaction-editor/line-editor.tsx +30 -34
  23. package/src/widgets/interaction-editor/mathquill-input.tsx +81 -0
  24. package/src/widgets/interaction-editor/movable-line-editor.tsx +30 -34
  25. package/src/widgets/interaction-editor/movable-point-editor.tsx +23 -26
  26. package/src/widgets/interaction-editor/parametric-editor.tsx +28 -33
  27. package/src/widgets/interaction-editor/point-editor.tsx +17 -24
  28. package/src/widgets/interaction-editor/rectangle-editor.tsx +23 -32
  29. package/tsconfig-build.tsbuildinfo +1 -1
@@ -7,7 +7,6 @@ import {
7
7
  Util,
8
8
  ElementContainer,
9
9
  } from "@khanacademy/perseus";
10
- import PropTypes from "prop-types";
11
10
  import * as React from "react";
12
11
  import _ from "underscore";
13
12
 
@@ -40,30 +39,38 @@ const defaultInteractionProps = {
40
39
  elements: [],
41
40
  } as const;
42
41
 
43
- type InteractionEditorProps = any;
44
- type InteractionEditorState = any;
42
+ type Graph = {
43
+ box: ReadonlyArray<number>;
44
+ labels: ReadonlyArray<string>;
45
+ range: ReadonlyArray<ReadonlyArray<number>>;
46
+ tickStep: ReadonlyArray<number>;
47
+ gridStep: ReadonlyArray<number>;
48
+ markings: string;
49
+ valid?: boolean;
50
+ };
45
51
 
46
- class InteractionEditor extends React.Component<
47
- InteractionEditorProps,
48
- InteractionEditorState
49
- > {
50
- // TODO(eater): Make more better
51
- static propTypes = {
52
- ...Changeable.propTypes,
53
- // eslint-disable-next-line react/forbid-prop-types
54
- elements: PropTypes.arrayOf(PropTypes.object),
55
- graph: PropTypes.objectOf(PropTypes.any),
56
- };
52
+ type Props = Changeable.ChangeableProps & {
53
+ elements: ReadonlyArray<any>;
54
+ graph: Graph;
55
+ };
56
+
57
+ type DefaultProps = {
58
+ elements: Props["elements"];
59
+ graph: Props["graph"];
60
+ };
61
+
62
+ type State = any;
57
63
 
64
+ class InteractionEditor extends React.Component<Props, State> {
58
65
  static widgetName = "interaction" as const;
59
- static defaultProps: InteractionEditorProps = defaultInteractionProps;
66
+ static defaultProps: DefaultProps = defaultInteractionProps;
60
67
 
61
- state: InteractionEditorState = {
68
+ state: State = {
62
69
  usedVarSubscripts: this._getAllVarSubscripts(this.props.elements),
63
70
  usedFunctionNames: this._getAllFunctionNames(this.props.elements),
64
71
  };
65
72
 
66
- UNSAFE_componentWillReceiveProps(nextProps: InteractionEditorProps) {
73
+ UNSAFE_componentWillReceiveProps(nextProps: Props) {
67
74
  this.setState({
68
75
  usedVarSubscripts: this._getAllVarSubscripts(nextProps.elements),
69
76
  usedFunctionNames: this._getAllFunctionNames(nextProps.elements),
@@ -6,31 +6,32 @@ import {
6
6
  KhanColors,
7
7
  ColorPicker,
8
8
  } from "@khanacademy/perseus";
9
- import PropTypes from "prop-types";
10
9
  import * as React from "react";
11
10
  import _ from "underscore";
12
11
 
13
- const {MathInput, TextInput} = components;
12
+ import MathquillInput from "./mathquill-input";
13
+
14
+ const {TextInput} = components;
14
15
  const {getDependencies} = Dependencies;
15
16
 
16
- type LabelEditorProps = any;
17
+ type Props = Changeable.ChangeableProps & {
18
+ color: string;
19
+ coordX: string;
20
+ coordY: string;
21
+ label: string;
22
+ };
23
+
24
+ type DefaultProps = {
25
+ color: Props["color"];
26
+ coordX: Props["coordX"];
27
+ coordY: Props["coordY"];
28
+ label: Props["label"];
29
+ };
17
30
 
18
- //
19
31
  // Editor for labels
20
- //
21
- // TODO(eater): Factor this out maybe?
22
32
  // TODO(eater): Add text direction
23
- //
24
- class LabelEditor extends React.Component<LabelEditorProps> {
25
- static propTypes = {
26
- ...Changeable.propTypes,
27
- color: PropTypes.string,
28
- coordX: PropTypes.string,
29
- coordY: PropTypes.string,
30
- label: PropTypes.string,
31
- };
32
-
33
- static defaultProps = {
33
+ class LabelEditor extends React.Component<Props> {
34
+ static defaultProps: DefaultProps = {
34
35
  coordX: "0",
35
36
  coordY: "0",
36
37
  color: KhanColors.BLACK,
@@ -47,7 +48,6 @@ class LabelEditor extends React.Component<LabelEditorProps> {
47
48
 
48
49
  render(): React.ReactNode {
49
50
  const {TeX} = getDependencies();
50
- const analyticsStub = {onAnalyticsEvent: () => Promise.resolve()};
51
51
 
52
52
  return (
53
53
  <div className="graph-settings">
@@ -62,18 +62,14 @@ class LabelEditor extends React.Component<LabelEditorProps> {
62
62
  </div>
63
63
  <div className="perseus-widget-row">
64
64
  Location: <TeX>\Large(</TeX>
65
- <MathInput
66
- buttonsVisible="never"
65
+ <MathquillInput
67
66
  value={this.props.coordX}
68
67
  onChange={this.change("coordX")}
69
- analytics={analyticsStub}
70
68
  />
71
69
  <TeX>,</TeX>{" "}
72
- <MathInput
73
- buttonsVisible="never"
70
+ <MathquillInput
74
71
  value={this.props.coordY}
75
72
  onChange={this.change("coordY")}
76
- analytics={analyticsStub}
77
73
  />
78
74
  <TeX>\Large)</TeX>
79
75
  </div>
@@ -8,34 +8,39 @@ import {
8
8
  ColorPicker,
9
9
  DashPicker,
10
10
  } from "@khanacademy/perseus";
11
- import PropTypes from "prop-types";
12
11
  import * as React from "react";
13
12
  import _ from "underscore";
14
13
 
15
- const {MathInput, NumberInput} = components;
14
+ import MathquillInput from "./mathquill-input";
15
+
16
+ const {NumberInput} = components;
16
17
  const {getDependencies} = Dependencies;
17
18
 
18
- type LineEditorProps = any;
19
+ type Props = Changeable.ChangeableProps & {
20
+ startX: string;
21
+ startY: string;
22
+ endX: string;
23
+ endY: string;
24
+ color: string;
25
+ strokeDasharray: string;
26
+ arrows: string;
27
+ strokeWidth: number;
28
+ };
19
29
 
20
- //
21
- // Editor for non-interactive line segments
22
- //
23
- // TODO(eater): Factor this out
24
- //
25
- class LineEditor extends React.Component<LineEditorProps> {
26
- static propTypes = {
27
- ...Changeable.propTypes,
28
- startX: PropTypes.string,
29
- startY: PropTypes.string,
30
- endX: PropTypes.string,
31
- endY: PropTypes.string,
32
- color: PropTypes.string,
33
- strokeDasharray: PropTypes.string,
34
- arrows: PropTypes.string,
35
- strokeWidth: PropTypes.number,
36
- };
30
+ type DefaultProps = {
31
+ startX: Props["startX"];
32
+ startY: Props["startY"];
33
+ endX: Props["endX"];
34
+ endY: Props["endY"];
35
+ color: Props["color"];
36
+ strokeDasharray: Props["strokeDasharray"];
37
+ arrows: Props["arrows"];
38
+ strokeWidth: Props["strokeWidth"];
39
+ };
37
40
 
38
- static defaultProps = {
41
+ // Editor for non-interactive line segments
42
+ class LineEditor extends React.Component<Props> {
43
+ static defaultProps: DefaultProps = {
39
44
  startX: "-5",
40
45
  startY: "5",
41
46
  endX: "5",
@@ -56,41 +61,32 @@ class LineEditor extends React.Component<LineEditorProps> {
56
61
 
57
62
  render(): React.ReactNode {
58
63
  const {TeX} = getDependencies();
59
- const analyticsStub = {onAnalyticsEvent: () => Promise.resolve()};
60
64
 
61
65
  return (
62
66
  <div className="graph-settings">
63
67
  <div className="perseus-widget-row">
64
68
  Start: <TeX>\Large(</TeX>
65
- <MathInput
66
- buttonsVisible="never"
69
+ <MathquillInput
67
70
  value={this.props.startX}
68
71
  onChange={this.change("startX")}
69
- analytics={analyticsStub}
70
72
  />
71
73
  <TeX>,</TeX>{" "}
72
- <MathInput
73
- buttonsVisible="never"
74
+ <MathquillInput
74
75
  value={this.props.startY}
75
76
  onChange={this.change("startY")}
76
- analytics={analyticsStub}
77
77
  />
78
78
  <TeX>\Large)</TeX>
79
79
  </div>
80
80
  <div className="perseus-widget-row">
81
81
  End: <TeX>\Large(</TeX>
82
- <MathInput
83
- buttonsVisible="never"
82
+ <MathquillInput
84
83
  value={this.props.endX}
85
84
  onChange={this.change("endX")}
86
- analytics={analyticsStub}
87
85
  />
88
86
  <TeX>,</TeX>{" "}
89
- <MathInput
90
- buttonsVisible="never"
87
+ <MathquillInput
91
88
  value={this.props.endY}
92
89
  onChange={this.change("endY")}
93
- analytics={analyticsStub}
94
90
  />
95
91
  <TeX>\Large)</TeX>
96
92
  </div>
@@ -0,0 +1,81 @@
1
+ import {createMathField} from "@khanacademy/math-input";
2
+ import Color from "@khanacademy/wonder-blocks-color";
3
+ import {View} from "@khanacademy/wonder-blocks-core";
4
+ import {StyleSheet} from "aphrodite";
5
+ import * as React from "react";
6
+ import {useRef, useEffect} from "react";
7
+
8
+ import type {MathFieldInterface} from "@khanacademy/math-input";
9
+
10
+ type Props = {
11
+ value: string;
12
+ onChange: (value: string) => void;
13
+ };
14
+
15
+ /**
16
+ * A simple Mathquill MathField input for the InteractionEditor.
17
+ * Unlike our other uses of Mathquill, we're not using a keypad here;
18
+ * it's just the input itself for use writing TeX.
19
+ */
20
+ export default function MathquillInput(props: Props) {
21
+ const mathFieldWrapperRef = useRef<HTMLSpanElement>(null);
22
+ const mathFieldInstance = useRef<MathFieldInterface>();
23
+
24
+ useEffect(() => {
25
+ // If we have the mount for the input, but not the input
26
+ // make a new Mathquill input
27
+ if (mathFieldWrapperRef.current && !mathFieldInstance.current) {
28
+ // Initialize MathQuill.MathField instance
29
+ mathFieldInstance.current = createMathField(
30
+ mathFieldWrapperRef.current,
31
+ (baseConfig) => ({
32
+ ...baseConfig,
33
+ handlers: {
34
+ edit: (mathField) => {
35
+ // This handler is guaranteed to be called on change, but
36
+ // unlike React it sometimes generates false positives.
37
+ // One of these is on initialization (with an empty string
38
+ // value), so we have to guard against that below.
39
+ let value = mathField.latex();
40
+
41
+ // Provide a MathQuill-compatible way to generate the
42
+ // not-equals sign without pasting unicode or typing TeX
43
+ value = value.replace(/<>/g, "\\ne");
44
+
45
+ if (props.value !== value) {
46
+ props.onChange(value);
47
+ }
48
+ },
49
+ upOutOf: (mathField) => {
50
+ // This handler is called when the user presses the up
51
+ // arrow key, but there is nowhere in the expression to go
52
+ // up to (no numerator or exponent). For ease of use,
53
+ // interpret this as an attempt to create an exponent.
54
+ mathField.typedText("^");
55
+ },
56
+ },
57
+ }),
58
+ );
59
+ }
60
+ });
61
+
62
+ return (
63
+ <View style={styles.outerWrapper}>
64
+ <span
65
+ ref={mathFieldWrapperRef}
66
+ className="perseus-math-input mq-editable-field mq-math-mode"
67
+ />
68
+ </View>
69
+ );
70
+ }
71
+
72
+ const styles = StyleSheet.create({
73
+ outerWrapper: {
74
+ display: "inline-block",
75
+ borderStyle: "solid",
76
+ borderWidth: 1,
77
+ borderColor: Color.offBlack50,
78
+ borderRadius: 3,
79
+ background: Color.white,
80
+ },
81
+ });
@@ -4,36 +4,41 @@ import {
4
4
  Dependencies,
5
5
  EditorJsonify,
6
6
  } from "@khanacademy/perseus";
7
- import PropTypes from "prop-types";
8
7
  import * as React from "react";
9
8
  import _ from "underscore";
10
9
 
11
10
  import ConstraintEditor from "./constraint-editor";
11
+ import MathquillInput from "./mathquill-input";
12
12
 
13
- const {MathInput, NumberInput} = components;
13
+ const {NumberInput} = components;
14
14
  const {getDependencies} = Dependencies;
15
15
 
16
- type MovableLineEditorProps = any;
16
+ type Props = Changeable.ChangeableProps & {
17
+ startX: string;
18
+ startY: string;
19
+ endX: string;
20
+ endY: string;
21
+ constraint: string;
22
+ snap: number;
23
+ constraintFn: string;
24
+ startSubscript: number;
25
+ endSubscript: number;
26
+ };
27
+
28
+ type DefaultProps = {
29
+ startX: Props["startX"];
30
+ startY: Props["startY"];
31
+ endX: Props["endX"];
32
+ endY: Props["endY"];
33
+ constraint: Props["constraint"];
34
+ snap: Props["snap"];
35
+ constraintFn: Props["constraintFn"];
36
+ };
17
37
 
18
- //
19
38
  // Editor for interactive movable line segments
20
- //
21
- // TODO(eater): Factor this out
22
39
  // TODO(eater): Rethink how constraints are represented
23
- //
24
- class MovableLineEditor extends React.Component<MovableLineEditorProps> {
25
- static propTypes = {
26
- ...Changeable.propTypes,
27
- startX: PropTypes.string,
28
- startY: PropTypes.string,
29
- endX: PropTypes.string,
30
- endY: PropTypes.string,
31
- constraint: PropTypes.string,
32
- snap: PropTypes.number,
33
- constraintFn: PropTypes.string,
34
- };
35
-
36
- static defaultProps = {
40
+ class MovableLineEditor extends React.Component<Props> {
41
+ static defaultProps: DefaultProps = {
37
42
  startX: "-5",
38
43
  startY: "5",
39
44
  endX: "5",
@@ -41,6 +46,7 @@ class MovableLineEditor extends React.Component<MovableLineEditorProps> {
41
46
  constraint: "none",
42
47
  snap: 0.5,
43
48
  constraintFn: "0",
49
+ // @ts-expect-error - TS2561
44
50
  constraintXMin: "-10",
45
51
  constraintXMax: "10",
46
52
  constraintYMin: "-10",
@@ -57,42 +63,33 @@ class MovableLineEditor extends React.Component<MovableLineEditorProps> {
57
63
 
58
64
  render(): React.ReactNode {
59
65
  const {TeX} = getDependencies();
60
- const analyticsStub = {onAnalyticsEvent: () => Promise.resolve()};
61
66
 
62
67
  return (
63
68
  <div className="graph-settings">
64
69
  Initial position:
65
70
  <div className="perseus-widget-row">
66
71
  Start: <TeX>\Large(</TeX>
67
- <MathInput
68
- buttonsVisible="never"
72
+ <MathquillInput
69
73
  value={this.props.startX}
70
74
  onChange={this.change("startX")}
71
- analytics={analyticsStub}
72
75
  />
73
76
  <TeX>,</TeX>{" "}
74
- <MathInput
75
- buttonsVisible="never"
77
+ <MathquillInput
76
78
  value={this.props.startY}
77
79
  onChange={this.change("startY")}
78
- analytics={analyticsStub}
79
80
  />
80
81
  <TeX>\Large)</TeX>
81
82
  </div>
82
83
  <div className="perseus-widget-row">
83
84
  End: <TeX>\Large(</TeX>
84
- <MathInput
85
- buttonsVisible="never"
85
+ <MathquillInput
86
86
  value={this.props.endX}
87
87
  onChange={this.change("endX")}
88
- analytics={analyticsStub}
89
88
  />
90
89
  <TeX>,</TeX>{" "}
91
- <MathInput
92
- buttonsVisible="never"
90
+ <MathquillInput
93
91
  value={this.props.endY}
94
92
  onChange={this.change("endY")}
95
- analytics={analyticsStub}
96
93
  />
97
94
  <TeX>\Large)</TeX>
98
95
  </div>
@@ -115,7 +112,6 @@ class MovableLineEditor extends React.Component<MovableLineEditorProps> {
115
112
  <div className="perseus-widget-row">
116
113
  All constraints are applied to the start point.
117
114
  </div>
118
- {/* @ts-expect-error - TS2769 - No overload matches this call. */}
119
115
  <ConstraintEditor {...this.props} />
120
116
  </div>
121
117
  );
@@ -4,39 +4,42 @@ import {
4
4
  Dependencies,
5
5
  EditorJsonify,
6
6
  } from "@khanacademy/perseus";
7
- import PropTypes from "prop-types";
8
7
  import * as React from "react";
9
8
  import _ from "underscore";
10
9
 
11
10
  import ConstraintEditor from "./constraint-editor";
11
+ import MathquillInput from "./mathquill-input";
12
12
 
13
- const {MathInput, NumberInput} = components;
13
+ const {NumberInput} = components;
14
14
  const {getDependencies} = Dependencies;
15
15
 
16
- type MovablePointEditorProps = any;
16
+ type Props = Changeable.ChangeableProps & {
17
+ startX: string;
18
+ startY: string;
19
+ constraint: string;
20
+ snap: number;
21
+ constraintFn: string;
22
+ varSubscript: number;
23
+ };
24
+
25
+ type DefaultProps = {
26
+ startX: Props["startX"];
27
+ startY: Props["startY"];
28
+ constraint: Props["constraint"];
29
+ snap: Props["snap"];
30
+ constraintFn: Props["constraintFn"];
31
+ };
17
32
 
18
- //
19
33
  // Editor for interactive movable points
20
- //
21
- // TODO(eater): Factor this out
22
34
  // TODO(eater): Rethink how constraints are represented
23
- //
24
- class MovablePointEditor extends React.Component<MovablePointEditorProps> {
25
- static propTypes = {
26
- ...Changeable.propTypes,
27
- startX: PropTypes.string,
28
- startY: PropTypes.string,
29
- constraint: PropTypes.string,
30
- snap: PropTypes.number,
31
- constraintFn: PropTypes.string,
32
- };
33
-
34
- static defaultProps = {
35
+ class MovablePointEditor extends React.Component<Props> {
36
+ static defaultProps: DefaultProps = {
35
37
  startX: "0",
36
38
  startY: "0",
37
39
  constraint: "none",
38
40
  snap: 0.5,
39
41
  constraintFn: "0",
42
+ // @ts-expect-error - TS2561
40
43
  constraintXMin: "-10",
41
44
  constraintXMax: "10",
42
45
  constraintYMin: "-10",
@@ -53,24 +56,19 @@ class MovablePointEditor extends React.Component<MovablePointEditorProps> {
53
56
 
54
57
  render(): React.ReactNode {
55
58
  const {TeX} = getDependencies();
56
- const analyticsStub = {onAnalyticsEvent: () => Promise.resolve()};
57
59
 
58
60
  return (
59
61
  <div className="graph-settings">
60
62
  <div className="perseus-widget-row">
61
63
  Start: <TeX>\Large(</TeX>
62
- <MathInput
63
- buttonsVisible="never"
64
+ <MathquillInput
64
65
  value={this.props.startX}
65
66
  onChange={this.change("startX")}
66
- analytics={analyticsStub}
67
67
  />
68
68
  <TeX>,</TeX>{" "}
69
- <MathInput
70
- buttonsVisible="never"
69
+ <MathquillInput
71
70
  value={this.props.startY}
72
71
  onChange={this.change("startY")}
73
- analytics={analyticsStub}
74
72
  />
75
73
  <TeX>\Large)</TeX>
76
74
  </div>
@@ -82,7 +80,6 @@ class MovablePointEditor extends React.Component<MovablePointEditorProps> {
82
80
  onChange={this.change("varSubscript")}
83
81
  />
84
82
  </div>
85
- {/* @ts-expect-error - TS2769 - No overload matches this call. */}
86
83
  <ConstraintEditor {...this.props} />
87
84
  </div>
88
85
  );
@@ -7,33 +7,37 @@ import {
7
7
  ColorPicker,
8
8
  DashPicker,
9
9
  } from "@khanacademy/perseus";
10
- import PropTypes from "prop-types";
11
10
  import * as React from "react";
12
11
  import _ from "underscore";
13
12
 
14
- const {MathInput, NumberInput} = components;
13
+ import MathquillInput from "./mathquill-input";
14
+
15
+ const {NumberInput} = components;
15
16
  const {getDependencies} = Dependencies;
16
17
 
17
- type ParametricEditorProps = any;
18
+ type Props = Changeable.ChangeableProps & {
19
+ x: string;
20
+ y: string;
21
+ rangeMin: string;
22
+ rangeMax: string;
23
+ color: string;
24
+ strokeDasharray: string;
25
+ strokeWidth: number;
26
+ };
18
27
 
19
- //
20
- // Editor for parametric plots
21
- //
22
- // TODO(eater): Factor this out
23
- //
24
- class ParametricEditor extends React.Component<ParametricEditorProps> {
25
- static propTypes = {
26
- ...Changeable.propTypes,
27
- x: PropTypes.string,
28
- y: PropTypes.string,
29
- rangeMin: PropTypes.string,
30
- rangeMax: PropTypes.string,
31
- color: PropTypes.string,
32
- strokeDashArray: PropTypes.string,
33
- strokeWidth: PropTypes.number,
34
- };
28
+ type DefaultProps = {
29
+ x: Props["x"];
30
+ y: Props["y"];
31
+ rangeMin: Props["rangeMin"];
32
+ rangeMax: Props["rangeMax"];
33
+ color: Props["color"];
34
+ strokeDasharray: Props["strokeDasharray"];
35
+ strokeWidth: Props["strokeWidth"];
36
+ };
35
37
 
36
- static defaultProps = {
38
+ // Editor for parametric plots
39
+ class ParametricEditor extends React.Component<Props> {
40
+ static defaultProps: DefaultProps = {
37
41
  x: "cos(t)",
38
42
  y: "sin(t)",
39
43
  rangeMin: "0",
@@ -53,42 +57,33 @@ class ParametricEditor extends React.Component<ParametricEditorProps> {
53
57
 
54
58
  render(): React.ReactNode {
55
59
  const {TeX} = getDependencies();
56
- const analyticsStub = {onAnalyticsEvent: () => Promise.resolve()};
57
60
 
58
61
  return (
59
62
  <div className="graph-settings">
60
63
  <div className="perseus-widget-row">
61
64
  <TeX>X(t) =</TeX>{" "}
62
- <MathInput
63
- buttonsVisible="never"
65
+ <MathquillInput
64
66
  value={this.props.x}
65
67
  onChange={this.change("x")}
66
- analytics={analyticsStub}
67
68
  />
68
69
  </div>
69
70
  <div className="perseus-widget-row">
70
71
  <TeX>Y(t) =</TeX>{" "}
71
- <MathInput
72
- buttonsVisible="never"
72
+ <MathquillInput
73
73
  value={this.props.y}
74
74
  onChange={this.change("y")}
75
- analytics={analyticsStub}
76
75
  />
77
76
  </div>
78
77
  <div className="perseus-widget-row">
79
78
  Range: <TeX>\Large(</TeX>
80
- <MathInput
81
- buttonsVisible="never"
79
+ <MathquillInput
82
80
  value={this.props.rangeMin}
83
81
  onChange={this.change("rangeMin")}
84
- analytics={analyticsStub}
85
82
  />
86
83
  <TeX>,</TeX>{" "}
87
- <MathInput
88
- buttonsVisible="never"
84
+ <MathquillInput
89
85
  value={this.props.rangeMax}
90
86
  onChange={this.change("rangeMax")}
91
- analytics={analyticsStub}
92
87
  />
93
88
  <TeX>\Large)</TeX>
94
89
  </div>