@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.
- package/CHANGELOG.md +15 -0
- package/dist/es/index.js +190 -329
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +190 -338
- package/dist/index.js.map +1 -1
- package/dist/widgets/interaction-editor/function-editor.d.ts +19 -20
- package/dist/widgets/interaction-editor/interaction-editor.d.ts +23 -14
- package/dist/widgets/interaction-editor/label-editor.d.ts +15 -16
- package/dist/widgets/interaction-editor/line-editor.d.ts +23 -24
- package/dist/widgets/interaction-editor/mathquill-input.d.ts +12 -0
- package/dist/widgets/interaction-editor/movable-line-editor.d.ts +23 -26
- package/dist/widgets/interaction-editor/movable-point-editor.d.ts +18 -22
- package/dist/widgets/interaction-editor/parametric-editor.d.ts +21 -22
- package/dist/widgets/interaction-editor/point-editor.d.ts +13 -14
- package/dist/widgets/interaction-editor/rectangle-editor.d.ts +17 -18
- package/package.json +3 -2
- package/src/widgets/__stories__/interaction-editor.stories.tsx +17 -4
- package/src/widgets/interaction-editor/constraint-editor.tsx +9 -21
- package/src/widgets/interaction-editor/function-editor.tsx +26 -29
- package/src/widgets/interaction-editor/interaction-editor.tsx +24 -17
- package/src/widgets/interaction-editor/label-editor.tsx +20 -24
- package/src/widgets/interaction-editor/line-editor.tsx +30 -34
- package/src/widgets/interaction-editor/mathquill-input.tsx +81 -0
- package/src/widgets/interaction-editor/movable-line-editor.tsx +30 -34
- package/src/widgets/interaction-editor/movable-point-editor.tsx +23 -26
- package/src/widgets/interaction-editor/parametric-editor.tsx +28 -33
- package/src/widgets/interaction-editor/point-editor.tsx +17 -24
- package/src/widgets/interaction-editor/rectangle-editor.tsx +23 -32
- 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
|
|
44
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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:
|
|
66
|
+
static defaultProps: DefaultProps = defaultInteractionProps;
|
|
60
67
|
|
|
61
|
-
state:
|
|
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:
|
|
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
|
-
|
|
12
|
+
import MathquillInput from "./mathquill-input";
|
|
13
|
+
|
|
14
|
+
const {TextInput} = components;
|
|
14
15
|
const {getDependencies} = Dependencies;
|
|
15
16
|
|
|
16
|
-
type
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
|
|
14
|
+
import MathquillInput from "./mathquill-input";
|
|
15
|
+
|
|
16
|
+
const {NumberInput} = components;
|
|
16
17
|
const {getDependencies} = Dependencies;
|
|
17
18
|
|
|
18
|
-
type
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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 {
|
|
13
|
+
const {NumberInput} = components;
|
|
14
14
|
const {getDependencies} = Dependencies;
|
|
15
15
|
|
|
16
|
-
type
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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 {
|
|
13
|
+
const {NumberInput} = components;
|
|
14
14
|
const {getDependencies} = Dependencies;
|
|
15
15
|
|
|
16
|
-
type
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
|
|
13
|
+
import MathquillInput from "./mathquill-input";
|
|
14
|
+
|
|
15
|
+
const {NumberInput} = components;
|
|
15
16
|
const {getDependencies} = Dependencies;
|
|
16
17
|
|
|
17
|
-
type
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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>
|