@khanacademy/perseus-editor 2.6.0 → 2.6.2
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 +24 -0
- package/dist/article-editor.d.ts +1 -2
- package/dist/components/form-wrapped-text-field.d.ts +1 -10
- package/dist/components/graph-points-count-selector.d.ts +1 -1
- package/dist/es/index.js +414 -436
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +411 -435
- package/dist/index.js.map +1 -1
- package/dist/widgets/input-number-editor.d.ts +1 -2
- package/dist/widgets/interactive-graph-editor.d.ts +48 -47
- package/dist/widgets/plotter-editor.d.ts +47 -23
- package/package.json +12 -12
- package/src/__stories__/editor.stories.tsx +3 -1
- package/src/__tests__/i18n.test.ts +1 -1
- package/src/article-editor.tsx +13 -14
- package/src/components/checkbox.tsx +2 -1
- package/src/components/dropdown-option.tsx +13 -12
- package/src/components/form-wrapped-text-field.tsx +5 -2
- package/src/components/graph-points-count-selector.tsx +3 -1
- package/src/components/graph-settings.tsx +1 -1
- package/src/components/hover-behavior.ts +2 -2
- package/src/components/json-editor.tsx +2 -2
- package/src/components/sortable.tsx +1 -1
- package/src/components/util.ts +1 -1
- package/src/components/widget-editor.tsx +8 -7
- package/src/diffs/__tests__/structured-item-diff.test.ts +8 -8
- package/src/diffs/renderer-diff.tsx +3 -3
- package/src/diffs/split-diff.ts +2 -2
- package/src/diffs/structured-item-diff.tsx +11 -10
- package/src/diffs/text-diff.tsx +1 -1
- package/src/diffs/widget-diff.tsx +2 -2
- package/src/editor-page.tsx +8 -8
- package/src/editor.tsx +37 -36
- package/src/hint-editor.tsx +28 -27
- package/src/i18n.ts +4 -4
- package/src/iframe-content-renderer.tsx +10 -10
- package/src/item-editor.tsx +4 -4
- package/src/katex-mhchem/parser.js +24 -24
- package/src/multirenderer-editor.tsx +11 -11
- package/src/widgets/__stories__/label-image-editor.stories.tsx +1 -0
- package/src/widgets/__stories__/radio-editor.stories.tsx +1 -0
- package/src/widgets/categorizer-editor.tsx +3 -3
- package/src/widgets/cs-program-editor.tsx +2 -2
- package/src/widgets/definition-editor.tsx +3 -2
- package/src/widgets/dropdown-editor.tsx +9 -8
- package/src/widgets/example-graphie-widget-editor.tsx +1 -1
- package/src/widgets/example-graphie-widget.tsx +2 -2
- package/src/widgets/example-widget-editor.tsx +2 -2
- package/src/widgets/example-widget.tsx +4 -3
- package/src/widgets/explanation-editor.tsx +4 -3
- package/src/widgets/expression-editor.tsx +9 -9
- package/src/widgets/graded-group-editor.tsx +7 -6
- package/src/widgets/graded-group-set-editor.tsx +3 -3
- package/src/widgets/grapher-editor.tsx +3 -2
- package/src/widgets/group-editor.tsx +4 -3
- package/src/widgets/iframe-editor.tsx +5 -4
- package/src/widgets/input-number-editor.tsx +6 -6
- package/src/widgets/interaction-editor.tsx +103 -102
- package/src/widgets/interactive-graph-editor.tsx +12 -8
- package/src/widgets/label-image/marker.tsx +2 -1
- package/src/widgets/label-image/question-markers.tsx +1 -1
- package/src/widgets/lights-puzzle-editor.tsx +5 -4
- package/src/widgets/matrix-editor.tsx +2 -2
- package/src/widgets/measurer-editor.tsx +7 -6
- package/src/widgets/molecule-editor.tsx +2 -2
- package/src/widgets/number-line-editor.tsx +2 -1
- package/src/widgets/numeric-input-editor.tsx +2 -2
- package/src/widgets/orderer-editor.tsx +3 -2
- package/src/widgets/passage-editor.tsx +3 -3
- package/src/widgets/passage-ref-editor.tsx +4 -3
- package/src/widgets/passage-ref-target-editor.tsx +1 -1
- package/src/widgets/plotter-editor.tsx +253 -243
- package/src/widgets/radio/editor.tsx +3 -3
- package/src/widgets/reaction-diagram-editor.tsx +5 -5
- package/src/widgets/sequence-editor.tsx +1 -1
- package/src/widgets/simple-markdown-tester-editor.tsx +4 -3
- package/src/widgets/simple-markdown-tester.tsx +2 -2
- package/src/widgets/simulator-editor.tsx +1 -1
- package/src/widgets/sorter-editor.tsx +2 -1
- package/src/widgets/table-editor.tsx +1 -1
- package/src/widgets/transformer-editor.tsx +10 -10
- package/src/widgets/unit-editor.tsx +5 -5
- package/tsconfig-build.tsbuildinfo +1 -1
- package/dist/all-editors.js.flow +0 -8
- package/dist/all-widgets.js.flow +0 -34
- package/dist/article-editor.js.flow +0 -72
- package/dist/components/blur-input.js.flow +0 -25
- package/dist/components/checkbox.js.flow +0 -26
- package/dist/components/device-framer.js.flow +0 -20
- package/dist/components/drag-target.js.flow +0 -8
- package/dist/components/dropdown-option.js.flow +0 -49
- package/dist/components/form-wrapped-text-field.js.flow +0 -45
- package/dist/components/graph-points-count-selector.js.flow +0 -12
- package/dist/components/graph-settings.js.flow +0 -8
- package/dist/components/graph-type-selector.js.flow +0 -12
- package/dist/components/hover-behavior.js.flow +0 -48
- package/dist/components/json-editor.js.flow +0 -8
- package/dist/components/link.js.flow +0 -50
- package/dist/components/section-control-button.js.flow +0 -25
- package/dist/components/segment-count-selector.js.flow +0 -11
- package/dist/components/simple-button.js.flow +0 -18
- package/dist/components/sortable.js.flow +0 -8
- package/dist/components/util.js.flow +0 -9
- package/dist/components/viewport-resizer.js.flow +0 -22
- package/dist/components/widget-editor.js.flow +0 -91
- package/dist/components/widget-select.js.flow +0 -16
- package/dist/diffs/article-diff.js.flow +0 -71
- package/dist/diffs/item-diff.js.flow +0 -41
- package/dist/diffs/renderer-diff.js.flow +0 -25
- package/dist/diffs/split-diff.js.flow +0 -8
- package/dist/diffs/string-array-diff.js.flow +0 -11
- package/dist/diffs/structured-item-diff.js.flow +0 -37
- package/dist/diffs/tags-diff.js.flow +0 -24
- package/dist/diffs/text-diff.js.flow +0 -21
- package/dist/diffs/widget-diff-performer.js.flow +0 -8
- package/dist/diffs/widget-diff.js.flow +0 -31
- package/dist/editor-page.js.flow +0 -72
- package/dist/editor.js.flow +0 -96
- package/dist/hint-editor.js.flow +0 -87
- package/dist/i18n.js.flow +0 -13
- package/dist/iframe-content-renderer.js.flow +0 -28
- package/dist/index.js.flow +0 -23
- package/dist/item-editor.js.flow +0 -46
- package/dist/item-extras-editor.js.flow +0 -23
- package/dist/katex-error-view.js.flow +0 -24
- package/dist/multirenderer-editor.js.flow +0 -46
- package/dist/stateful-article-editor.js.flow +0 -16
- package/dist/stateful-editor-page.js.flow +0 -8
- package/dist/testing-widgets.js.flow +0 -34
- package/dist/util/points.js.flow +0 -9
- package/dist/util/register-all-widgets-and-editors-for-testing.js.flow +0 -7
- package/dist/widgets/categorizer-editor.js.flow +0 -62
- package/dist/widgets/cs-program-editor.js.flow +0 -25
- package/dist/widgets/definition-editor.js.flow +0 -23
- package/dist/widgets/dropdown-editor.js.flow +0 -37
- package/dist/widgets/example-graphie-widget-editor.js.flow +0 -25
- package/dist/widgets/example-graphie-widget.js.flow +0 -102
- package/dist/widgets/example-widget-editor.js.flow +0 -26
- package/dist/widgets/example-widget.js.flow +0 -86
- package/dist/widgets/explanation-editor.js.flow +0 -27
- package/dist/widgets/expression-editor.js.flow +0 -43
- package/dist/widgets/graded-group-editor.js.flow +0 -68
- package/dist/widgets/graded-group-set-editor.js.flow +0 -66
- package/dist/widgets/grapher-editor.js.flow +0 -21
- package/dist/widgets/group-editor.js.flow +0 -64
- package/dist/widgets/iframe-editor.js.flow +0 -24
- package/dist/widgets/image-editor.js.flow +0 -8
- package/dist/widgets/input-number-editor.js.flow +0 -77
- package/dist/widgets/interaction/constraint-editor.js.flow +0 -35
- package/dist/widgets/interaction-editor.js.flow +0 -36
- package/dist/widgets/interactive-graph-editor.js.flow +0 -5803
- package/dist/widgets/label-image/answer-choices.js.flow +0 -16
- package/dist/widgets/label-image/behavior.js.flow +0 -17
- package/dist/widgets/label-image/marker.js.flow +0 -32
- package/dist/widgets/label-image/question-markers.js.flow +0 -23
- package/dist/widgets/label-image/select-image.js.flow +0 -13
- package/dist/widgets/label-image-editor.js.flow +0 -44
- package/dist/widgets/lights-puzzle-editor.js.flow +0 -34
- package/dist/widgets/matcher-editor.js.flow +0 -28
- package/dist/widgets/matrix-editor.js.flow +0 -26
- package/dist/widgets/measurer-editor.js.flow +0 -42
- package/dist/widgets/molecule-editor.js.flow +0 -23
- package/dist/widgets/number-line-editor.js.flow +0 -45
- package/dist/widgets/numeric-input-editor.js.flow +0 -8
- package/dist/widgets/orderer-editor.js.flow +0 -30
- package/dist/widgets/passage-editor.js.flow +0 -24
- package/dist/widgets/passage-ref-editor.js.flow +0 -17
- package/dist/widgets/passage-ref-target-editor.js.flow +0 -22
- package/dist/widgets/plotter-editor.js.flow +0 -53
- package/dist/widgets/radio/editor.js.flow +0 -81
- package/dist/widgets/reaction-diagram-editor.js.flow +0 -26
- package/dist/widgets/sequence-editor.js.flow +0 -73
- package/dist/widgets/simple-markdown-tester-editor.js.flow +0 -23
- package/dist/widgets/simple-markdown-tester.js.flow +0 -61
- package/dist/widgets/simulator-editor.js.flow +0 -26
- package/dist/widgets/sorter-editor.js.flow +0 -22
- package/dist/widgets/table-editor.js.flow +0 -24
- package/dist/widgets/transformer-editor.js.flow +0 -17
- package/dist/widgets/unit-editor.js.flow +0 -41
- package/dist/widgets/video-editor.js.flow +0 -25
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/* eslint-disable @
|
|
1
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
2
|
+
/* eslint-disable react/no-unsafe */
|
|
2
3
|
import {number as knumber} from "@khanacademy/kmath";
|
|
3
4
|
import {
|
|
4
5
|
components,
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
6
7
|
PlotterWidget,
|
|
7
8
|
Util,
|
|
8
9
|
} from "@khanacademy/perseus";
|
|
9
|
-
import PropTypes from "prop-types";
|
|
10
10
|
import * as React from "react";
|
|
11
11
|
import ReactDOM from "react-dom";
|
|
12
12
|
import _ from "underscore";
|
|
@@ -16,11 +16,20 @@ import BlurInput from "../components/blur-input";
|
|
|
16
16
|
const {InfoTip, NumberInput, RangeInput, TextListEditor} = components;
|
|
17
17
|
const Plotter = PlotterWidget.widget;
|
|
18
18
|
|
|
19
|
-
const BAR = "bar"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
const BAR = "bar";
|
|
20
|
+
const LINE = "line";
|
|
21
|
+
const PIC = "pic";
|
|
22
|
+
const HISTOGRAM = "histogram";
|
|
23
|
+
const DOTPLOT = "dotplot";
|
|
24
|
+
|
|
25
|
+
const plotTypes = [BAR, LINE, PIC, HISTOGRAM, DOTPLOT];
|
|
26
|
+
type PlotType = typeof plotTypes[number];
|
|
27
|
+
|
|
28
|
+
const STARTING = "starting";
|
|
29
|
+
const CORRECT = "correct";
|
|
30
|
+
|
|
31
|
+
const editingStates = [STARTING, CORRECT];
|
|
32
|
+
type EditingState = typeof editingStates[number];
|
|
24
33
|
|
|
25
34
|
// Return a copy of array with length n, padded with given value
|
|
26
35
|
function padArray(array: any, n, value: any) {
|
|
@@ -38,39 +47,55 @@ const editorDefaults = {
|
|
|
38
47
|
snapsPerLine: 2,
|
|
39
48
|
} as const;
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
type:
|
|
43
|
-
labels:
|
|
44
|
-
categories:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
type Props = {
|
|
51
|
+
type: PlotType;
|
|
52
|
+
labels: Array<string>;
|
|
53
|
+
categories: ReadonlyArray<string | number>;
|
|
54
|
+
scaleY: number;
|
|
55
|
+
maxY: number;
|
|
56
|
+
snapsPerLine: number;
|
|
57
|
+
picSize: number;
|
|
58
|
+
picBoxHeight: number;
|
|
59
|
+
picUrl: string;
|
|
60
|
+
plotDimensions: ReadonlyArray<number>;
|
|
61
|
+
labelInterval: number;
|
|
62
|
+
starting: ReadonlyArray<number>;
|
|
63
|
+
correct: ReadonlyArray<number>;
|
|
64
|
+
static: boolean;
|
|
65
|
+
onChange: any;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
type DefaultProps = {
|
|
69
|
+
scaleY: Props["scaleY"];
|
|
70
|
+
maxY: Props["maxY"];
|
|
71
|
+
snapsPerLine: Props["snapsPerLine"];
|
|
72
|
+
correct: Props["correct"];
|
|
73
|
+
starting: Props["starting"];
|
|
74
|
+
type: Props["type"];
|
|
75
|
+
labels: Props["labels"];
|
|
76
|
+
categories: Props["categories"];
|
|
77
|
+
picSize: Props["picSize"];
|
|
78
|
+
picBoxHeight: Props["picBoxHeight"];
|
|
79
|
+
plotDimensions: Props["plotDimensions"];
|
|
80
|
+
labelInterval: Props["labelInterval"];
|
|
81
|
+
picUrl: Props["picUrl"];
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
type State = {
|
|
85
|
+
editing: EditingState;
|
|
86
|
+
pic: any;
|
|
87
|
+
loadedUrl: string | null;
|
|
88
|
+
minX: number | null;
|
|
89
|
+
maxX: number | null;
|
|
90
|
+
tickStep: number | null;
|
|
91
|
+
};
|
|
63
92
|
|
|
64
93
|
const formatNumber = (num) => "$" + knumber.round(num, 2) + "$";
|
|
65
94
|
|
|
66
|
-
type Props = any;
|
|
67
|
-
type State = any;
|
|
68
|
-
|
|
69
95
|
class PlotterEditor extends React.Component<Props, State> {
|
|
70
|
-
static propTypes = widgetPropTypes;
|
|
71
96
|
static widgetName = "plotter" as const;
|
|
72
97
|
|
|
73
|
-
static defaultProps:
|
|
98
|
+
static defaultProps: DefaultProps = {
|
|
74
99
|
...editorDefaults,
|
|
75
100
|
correct: [1],
|
|
76
101
|
starting: [1],
|
|
@@ -84,6 +109,7 @@ class PlotterEditor extends React.Component<Props, State> {
|
|
|
84
109
|
plotDimensions: [275, 200],
|
|
85
110
|
labelInterval: 1,
|
|
86
111
|
|
|
112
|
+
// @ts-expect-error - TS2322
|
|
87
113
|
get picUrl() {
|
|
88
114
|
const staticUrl = Dependencies.getDependencies().staticUrl;
|
|
89
115
|
if (staticUrl) {
|
|
@@ -95,7 +121,7 @@ class PlotterEditor extends React.Component<Props, State> {
|
|
|
95
121
|
};
|
|
96
122
|
|
|
97
123
|
state: State = {
|
|
98
|
-
editing: this.props.static ?
|
|
124
|
+
editing: this.props.static ? STARTING : CORRECT,
|
|
99
125
|
pic: null,
|
|
100
126
|
loadedUrl: null,
|
|
101
127
|
minX: null,
|
|
@@ -131,6 +157,169 @@ class PlotterEditor extends React.Component<Props, State> {
|
|
|
131
157
|
}
|
|
132
158
|
};
|
|
133
159
|
|
|
160
|
+
handleChangeTickStep: (arg1: number) => void = (value) => {
|
|
161
|
+
this.setState({
|
|
162
|
+
tickStep: value,
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
handleChangeRange: (arg1: [number, number]) => void = (newValue) => {
|
|
167
|
+
this.setState({
|
|
168
|
+
minX: newValue[0],
|
|
169
|
+
maxX: newValue[1],
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
changeLabelInterval: (arg1: number) => void = (value) => {
|
|
174
|
+
this.props.onChange({
|
|
175
|
+
labelInterval: value,
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
handlePlotterChange: (arg1: any) => void = (newProps) => {
|
|
180
|
+
const props: Record<string, any> = {};
|
|
181
|
+
props[this.state.editing] = newProps.values;
|
|
182
|
+
this.props.onChange(props);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
changeType: (arg1: any) => void = (type) => {
|
|
186
|
+
let categories;
|
|
187
|
+
if (type === HISTOGRAM) {
|
|
188
|
+
// Switching to histogram, add a label (0) to the left
|
|
189
|
+
// @ts-expect-error - TS2769
|
|
190
|
+
categories = [formatNumber(0)].concat(this.props.categories);
|
|
191
|
+
this.props.onChange({type: type, categories: categories});
|
|
192
|
+
} else if (this.props.type === HISTOGRAM) {
|
|
193
|
+
// Switching from histogram, remove a label from the left
|
|
194
|
+
categories = this.props.categories.slice(1);
|
|
195
|
+
this.props.onChange({type: type, categories: categories});
|
|
196
|
+
} else {
|
|
197
|
+
this.props.onChange({type: type});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (categories) {
|
|
201
|
+
// eslint-disable-next-line react/no-string-refs
|
|
202
|
+
const node = ReactDOM.findDOMNode(this.refs.categories);
|
|
203
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
204
|
+
node.value = categories.join(", ");
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
changeLabel: (arg1: number, arg2: any) => void = (i, e) => {
|
|
209
|
+
const labels = _.clone(this.props.labels);
|
|
210
|
+
labels[i] = e.target.value;
|
|
211
|
+
this.props.onChange({labels: labels});
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
changePicUrl: (arg1: string) => void = (value) => {
|
|
215
|
+
// We don't need the labels and other data in the plotter, so just
|
|
216
|
+
// extract the raw image and use that.
|
|
217
|
+
// TODO(emily): Maybe indicate that such a change has happened?
|
|
218
|
+
const url = Util.getRealImageUrl(value);
|
|
219
|
+
|
|
220
|
+
this.props.onChange({picUrl: url});
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
changeCategories: (arg1: any) => void = (categories) => {
|
|
224
|
+
let n = categories.length;
|
|
225
|
+
if (this.props.type === HISTOGRAM) {
|
|
226
|
+
// Histograms with n labels/categories have n - 1 buckets
|
|
227
|
+
n--;
|
|
228
|
+
}
|
|
229
|
+
const value = this.props.scaleY;
|
|
230
|
+
|
|
231
|
+
this.props.onChange({
|
|
232
|
+
categories: categories,
|
|
233
|
+
correct: padArray(this.props.correct, n, value),
|
|
234
|
+
starting: padArray(this.props.starting, n, value),
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
changeScale: (arg1: any) => void = (e) => {
|
|
239
|
+
const oldScale = this.props.scaleY;
|
|
240
|
+
const newScale = +e.target.value || editorDefaults.scaleY;
|
|
241
|
+
|
|
242
|
+
const scale = function (value: any) {
|
|
243
|
+
return (value * newScale) / oldScale;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const maxY = scale(this.props.maxY);
|
|
247
|
+
|
|
248
|
+
this.props.onChange({
|
|
249
|
+
scaleY: newScale,
|
|
250
|
+
maxY: maxY,
|
|
251
|
+
correct: _.map(this.props.correct, scale),
|
|
252
|
+
starting: _.map(this.props.starting, scale),
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
256
|
+
ReactDOM.findDOMNode(this.refs.maxY).value = maxY; // eslint-disable-line react/no-string-refs
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
changeMax: (arg1: any) => void = (e) => {
|
|
260
|
+
this.props.onChange({
|
|
261
|
+
maxY: +e.target.value || editorDefaults.maxY,
|
|
262
|
+
});
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
changeSnaps: (arg1: any) => void = (e) => {
|
|
266
|
+
this.props.onChange({
|
|
267
|
+
snapsPerLine: +e.target.value || editorDefaults.snapsPerLine,
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
changeEditing: (arg1: EditingState) => void = (editing) => {
|
|
272
|
+
this.setState({editing: editing});
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
setCategoriesFromScale: () => void = () => {
|
|
276
|
+
const scale = this.state.tickStep || 1;
|
|
277
|
+
const min = this.state.minX || 0;
|
|
278
|
+
const max = this.state.maxX || 0;
|
|
279
|
+
const length = Math.floor((max - min) / scale) * scale;
|
|
280
|
+
|
|
281
|
+
let categories;
|
|
282
|
+
if (this.props.type === HISTOGRAM || this.props.type === DOTPLOT) {
|
|
283
|
+
// Ranges for histogram and dotplot labels should start at zero
|
|
284
|
+
categories = _.range(0, length + scale, scale);
|
|
285
|
+
} else {
|
|
286
|
+
categories = _.range(scale, length + scale, scale);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
categories = _.map(categories, (num) => num + min);
|
|
290
|
+
categories = _.map(categories, formatNumber);
|
|
291
|
+
|
|
292
|
+
this.changeCategories(categories);
|
|
293
|
+
|
|
294
|
+
// eslint-disable-next-line react/no-string-refs
|
|
295
|
+
const node = ReactDOM.findDOMNode(this.refs.categories);
|
|
296
|
+
|
|
297
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
298
|
+
node.value = categories.join(", ");
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
serialize: () => any = () => {
|
|
302
|
+
const json = _.pick(
|
|
303
|
+
this.props,
|
|
304
|
+
"correct",
|
|
305
|
+
"starting",
|
|
306
|
+
"type",
|
|
307
|
+
"labels",
|
|
308
|
+
"categories",
|
|
309
|
+
"scaleY",
|
|
310
|
+
"maxY",
|
|
311
|
+
"snapsPerLine",
|
|
312
|
+
"labelInterval",
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
if (this.props.type === PIC) {
|
|
316
|
+
// @ts-expect-error - TS2339 - Property 'picUrl' does not exist on type 'Pick<Readonly<any> & Readonly<{ children?: ReactNode; }>, "type" | "correct" | "labels" | "categories" | "starting" | "scaleY" | "maxY" | "snapsPerLine" | "labelInterval">'.
|
|
317
|
+
json.picUrl = this.props.picUrl;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return json;
|
|
321
|
+
};
|
|
322
|
+
|
|
134
323
|
render(): React.ReactNode {
|
|
135
324
|
const setFromScale = _.contains(
|
|
136
325
|
[LINE, HISTOGRAM, DOTPLOT],
|
|
@@ -146,52 +335,34 @@ class PlotterEditor extends React.Component<Props, State> {
|
|
|
146
335
|
<div className="perseus-widget-plotter-editor">
|
|
147
336
|
<div>
|
|
148
337
|
Chart type:{" "}
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
type,
|
|
163
|
-
)}
|
|
164
|
-
/>
|
|
165
|
-
{type}
|
|
166
|
-
</label>
|
|
167
|
-
);
|
|
168
|
-
},
|
|
169
|
-
this,
|
|
170
|
-
)}
|
|
338
|
+
{plotTypes.map((type) => {
|
|
339
|
+
return (
|
|
340
|
+
<label key={type}>
|
|
341
|
+
<input
|
|
342
|
+
type="radio"
|
|
343
|
+
name="chart-type"
|
|
344
|
+
checked={this.props.type === type}
|
|
345
|
+
onChange={_.partial(this.changeType, type)}
|
|
346
|
+
/>
|
|
347
|
+
{type}
|
|
348
|
+
</label>
|
|
349
|
+
);
|
|
350
|
+
}, this)}
|
|
171
351
|
</div>
|
|
172
352
|
<div>
|
|
173
353
|
Labels:{" "}
|
|
174
|
-
{
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
)}
|
|
187
|
-
// @ts-expect-error [FEI-5003] - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
188
|
-
defaultValue={this.props.labels[i]}
|
|
189
|
-
/>
|
|
190
|
-
</label>
|
|
191
|
-
);
|
|
192
|
-
},
|
|
193
|
-
this,
|
|
194
|
-
)}
|
|
354
|
+
{["x", "y"].map((axis, i) => {
|
|
355
|
+
return (
|
|
356
|
+
<label key={axis}>
|
|
357
|
+
{axis + ":"}
|
|
358
|
+
<input
|
|
359
|
+
type="text"
|
|
360
|
+
onChange={_.partial(this.changeLabel, i)}
|
|
361
|
+
defaultValue={this.props.labels[i]}
|
|
362
|
+
/>
|
|
363
|
+
</label>
|
|
364
|
+
);
|
|
365
|
+
}, this)}
|
|
195
366
|
</div>
|
|
196
367
|
|
|
197
368
|
{setFromScale && (
|
|
@@ -332,16 +503,16 @@ class PlotterEditor extends React.Component<Props, State> {
|
|
|
332
503
|
)}
|
|
333
504
|
<div>
|
|
334
505
|
Editing values:{" "}
|
|
335
|
-
{
|
|
506
|
+
{editingStates.map((editing) => (
|
|
336
507
|
<label key={editing}>
|
|
337
508
|
<input
|
|
338
509
|
type="radio"
|
|
339
510
|
disabled={
|
|
340
|
-
editing ===
|
|
511
|
+
editing === CORRECT && this.props.static
|
|
341
512
|
}
|
|
342
513
|
checked={
|
|
343
514
|
this.props.static
|
|
344
|
-
? editing ===
|
|
515
|
+
? editing === STARTING
|
|
345
516
|
: this.state.editing === editing
|
|
346
517
|
}
|
|
347
518
|
onChange={(e) => this.changeEditing(editing)}
|
|
@@ -363,6 +534,7 @@ class PlotterEditor extends React.Component<Props, State> {
|
|
|
363
534
|
</p>
|
|
364
535
|
</InfoTip>
|
|
365
536
|
</div>
|
|
537
|
+
{/* @ts-expect-error - TS2769 */}
|
|
366
538
|
<Plotter
|
|
367
539
|
{...props}
|
|
368
540
|
starting={this.props[this.state.editing]}
|
|
@@ -371,168 +543,6 @@ class PlotterEditor extends React.Component<Props, State> {
|
|
|
371
543
|
</div>
|
|
372
544
|
);
|
|
373
545
|
}
|
|
374
|
-
|
|
375
|
-
handleChangeTickStep: (arg1: number) => void = (value) => {
|
|
376
|
-
this.setState({
|
|
377
|
-
tickStep: value,
|
|
378
|
-
});
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
handleChangeRange: (arg1: [number, number]) => void = (newValue) => {
|
|
382
|
-
this.setState({
|
|
383
|
-
minX: newValue[0],
|
|
384
|
-
maxX: newValue[1],
|
|
385
|
-
});
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
changeLabelInterval: (arg1: number) => void = (value) => {
|
|
389
|
-
this.props.onChange({
|
|
390
|
-
labelInterval: value,
|
|
391
|
-
});
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
handlePlotterChange: (arg1: any) => void = (newProps) => {
|
|
395
|
-
const props: Record<string, any> = {};
|
|
396
|
-
props[this.state.editing] = newProps.values;
|
|
397
|
-
this.props.onChange(props);
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
changeType: (arg1: any) => void = (type) => {
|
|
401
|
-
let categories;
|
|
402
|
-
if (type === HISTOGRAM) {
|
|
403
|
-
// Switching to histogram, add a label (0) to the left
|
|
404
|
-
categories = [formatNumber(0)].concat(this.props.categories);
|
|
405
|
-
this.props.onChange({type: type, categories: categories});
|
|
406
|
-
} else if (this.props.type === HISTOGRAM) {
|
|
407
|
-
// Switching from histogram, remove a label from the left
|
|
408
|
-
categories = this.props.categories.slice(1);
|
|
409
|
-
this.props.onChange({type: type, categories: categories});
|
|
410
|
-
} else {
|
|
411
|
-
this.props.onChange({type: type});
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
if (categories) {
|
|
415
|
-
// eslint-disable-next-line react/no-string-refs
|
|
416
|
-
const node = ReactDOM.findDOMNode(this.refs.categories);
|
|
417
|
-
// @ts-expect-error [FEI-5003] - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
418
|
-
node.value = categories.join(", ");
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
changeLabel: (arg1: number, arg2: any) => void = (i, e) => {
|
|
423
|
-
const labels = _.clone(this.props.labels);
|
|
424
|
-
labels[i] = e.target.value;
|
|
425
|
-
this.props.onChange({labels: labels});
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
changePicUrl: (arg1: string) => void = (value) => {
|
|
429
|
-
// We don't need the labels and other data in the plotter, so just
|
|
430
|
-
// extract the raw image and use that.
|
|
431
|
-
// TODO(emily): Maybe indicate that such a change has happened?
|
|
432
|
-
const url = Util.getRealImageUrl(value);
|
|
433
|
-
|
|
434
|
-
this.props.onChange({picUrl: url});
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
changeCategories: (arg1: any) => void = (categories) => {
|
|
438
|
-
let n = categories.length;
|
|
439
|
-
if (this.props.type === HISTOGRAM) {
|
|
440
|
-
// Histograms with n labels/categories have n - 1 buckets
|
|
441
|
-
n--;
|
|
442
|
-
}
|
|
443
|
-
const value = this.props.scaleY;
|
|
444
|
-
|
|
445
|
-
this.props.onChange({
|
|
446
|
-
categories: categories,
|
|
447
|
-
correct: padArray(this.props.correct, n, value),
|
|
448
|
-
starting: padArray(this.props.starting, n, value),
|
|
449
|
-
});
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
changeScale: (arg1: any) => void = (e) => {
|
|
453
|
-
const oldScale = this.props.scaleY;
|
|
454
|
-
const newScale = +e.target.value || editorDefaults.scaleY;
|
|
455
|
-
|
|
456
|
-
const scale = function (value: any) {
|
|
457
|
-
return (value * newScale) / oldScale;
|
|
458
|
-
};
|
|
459
|
-
|
|
460
|
-
const maxY = scale(this.props.maxY);
|
|
461
|
-
|
|
462
|
-
this.props.onChange({
|
|
463
|
-
scaleY: newScale,
|
|
464
|
-
maxY: maxY,
|
|
465
|
-
correct: _.map(this.props.correct, scale),
|
|
466
|
-
starting: _.map(this.props.starting, scale),
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// @ts-expect-error [FEI-5003] - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
470
|
-
ReactDOM.findDOMNode(this.refs.maxY).value = maxY; // eslint-disable-line react/no-string-refs
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
changeMax: (arg1: any) => void = (e) => {
|
|
474
|
-
this.props.onChange({
|
|
475
|
-
maxY: +e.target.value || editorDefaults.maxY,
|
|
476
|
-
});
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
changeSnaps: (arg1: any) => void = (e) => {
|
|
480
|
-
this.props.onChange({
|
|
481
|
-
snapsPerLine: +e.target.value || editorDefaults.snapsPerLine,
|
|
482
|
-
});
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
changeEditing: (arg1: string) => void = (editing) => {
|
|
486
|
-
this.setState({editing: editing});
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
setCategoriesFromScale: () => void = () => {
|
|
490
|
-
const scale = this.state.tickStep || 1;
|
|
491
|
-
const min = this.state.minX || 0;
|
|
492
|
-
const max = this.state.maxX || 0;
|
|
493
|
-
const length = Math.floor((max - min) / scale) * scale;
|
|
494
|
-
|
|
495
|
-
let categories;
|
|
496
|
-
if (this.props.type === HISTOGRAM || this.props.type === DOTPLOT) {
|
|
497
|
-
// Ranges for histogram and dotplot labels should start at zero
|
|
498
|
-
categories = _.range(0, length + scale, scale);
|
|
499
|
-
} else {
|
|
500
|
-
categories = _.range(scale, length + scale, scale);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
categories = _.map(categories, (num) => num + min);
|
|
504
|
-
categories = _.map(categories, formatNumber);
|
|
505
|
-
|
|
506
|
-
this.changeCategories(categories);
|
|
507
|
-
|
|
508
|
-
// eslint-disable-next-line react/no-string-refs
|
|
509
|
-
const node = ReactDOM.findDOMNode(this.refs.categories);
|
|
510
|
-
|
|
511
|
-
// @ts-expect-error [FEI-5003] - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
512
|
-
node.value = categories.join(", ");
|
|
513
|
-
};
|
|
514
|
-
|
|
515
|
-
serialize: () => any = () => {
|
|
516
|
-
const json = _.pick(
|
|
517
|
-
this.props,
|
|
518
|
-
"correct",
|
|
519
|
-
"starting",
|
|
520
|
-
"type",
|
|
521
|
-
"labels",
|
|
522
|
-
"categories",
|
|
523
|
-
"scaleY",
|
|
524
|
-
"maxY",
|
|
525
|
-
"snapsPerLine",
|
|
526
|
-
"labelInterval",
|
|
527
|
-
);
|
|
528
|
-
|
|
529
|
-
if (this.props.type === PIC) {
|
|
530
|
-
// @ts-expect-error [FEI-5003] - TS2339 - Property 'picUrl' does not exist on type 'Pick<Readonly<any> & Readonly<{ children?: ReactNode; }>, "type" | "correct" | "labels" | "categories" | "starting" | "scaleY" | "maxY" | "snapsPerLine" | "labelInterval">'.
|
|
531
|
-
json.picUrl = this.props.picUrl;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
return json;
|
|
535
|
-
};
|
|
536
546
|
}
|
|
537
547
|
|
|
538
548
|
export default PlotterEditor;
|
|
@@ -248,7 +248,7 @@ class RadioEditor extends React.Component<any> {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
change: (...args: ReadonlyArray<unknown>) => any = (...args) => {
|
|
251
|
-
// @ts-expect-error
|
|
251
|
+
// @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
|
|
252
252
|
return Changeable.change.apply(this, args);
|
|
253
253
|
};
|
|
254
254
|
|
|
@@ -355,7 +355,7 @@ class RadioEditor extends React.Component<any> {
|
|
|
355
355
|
},
|
|
356
356
|
() => {
|
|
357
357
|
// eslint-disable-next-line react/no-string-refs
|
|
358
|
-
// @ts-expect-error
|
|
358
|
+
// @ts-expect-error - TS2339 - Property 'refs' does not exist on type 'ReactInstance'.
|
|
359
359
|
this.refs[`choice-editor${addIndex}`].refs[
|
|
360
360
|
"content-editor"
|
|
361
361
|
].focus();
|
|
@@ -369,7 +369,7 @@ class RadioEditor extends React.Component<any> {
|
|
|
369
369
|
|
|
370
370
|
focus: () => boolean = () => {
|
|
371
371
|
// eslint-disable-next-line react/no-string-refs
|
|
372
|
-
// @ts-expect-error
|
|
372
|
+
// @ts-expect-error - TS2339 - Property 'refs' does not exist on type 'ReactInstance'.
|
|
373
373
|
this.refs["choice-editor0"].refs["content-editor"].focus();
|
|
374
374
|
return true;
|
|
375
375
|
};
|
|
@@ -29,20 +29,20 @@ class ReactionDiagramWidgetEditor extends React.Component<Props> {
|
|
|
29
29
|
|
|
30
30
|
updateMolecule: (arg1: number) => (arg1: string) => void = (idx) => {
|
|
31
31
|
return function (newValue: string) {
|
|
32
|
-
// @ts-expect-error
|
|
32
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
33
33
|
const newSmiles = [...this.props.smiles];
|
|
34
34
|
newSmiles[idx] = newValue;
|
|
35
|
-
// @ts-expect-error
|
|
35
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
36
36
|
this.change({smiles: newSmiles});
|
|
37
37
|
}.bind(this);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
updateRotation: (arg1: number) => (arg1: any) => void = (idx) => {
|
|
41
41
|
return function (newValue) {
|
|
42
|
-
// @ts-expect-error
|
|
42
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
43
43
|
const newRot = [...this.props.rotationAngle];
|
|
44
44
|
newRot[idx] = newValue;
|
|
45
|
-
// @ts-expect-error
|
|
45
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
46
46
|
this.change({rotationAngle: newRot});
|
|
47
47
|
}.bind(this);
|
|
48
48
|
};
|
|
@@ -56,7 +56,7 @@ class ReactionDiagramWidgetEditor extends React.Component<Props> {
|
|
|
56
56
|
return {...sep};
|
|
57
57
|
});
|
|
58
58
|
newSep[idx][propName] = newValue;
|
|
59
|
-
// @ts-expect-error
|
|
59
|
+
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
60
60
|
this.change({separators: newSep});
|
|
61
61
|
};
|
|
62
62
|
};
|
|
@@ -139,7 +139,7 @@ class SequenceEditor extends React.Component<SequenceEditorProps> {
|
|
|
139
139
|
return {
|
|
140
140
|
json: _.times(this.props.json.length, (i) => {
|
|
141
141
|
// eslint-disable-next-line react/no-string-refs
|
|
142
|
-
// @ts-expect-error
|
|
142
|
+
// @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
|
|
143
143
|
return this.refs["editor" + i].serialize();
|
|
144
144
|
}),
|
|
145
145
|
};
|