@khanacademy/perseus-editor 4.1.5 → 4.1.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/dist/es/index.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +9 -6
- package/.babelrc.js +0 -8
- package/.eslintrc.js +0 -12
- package/CHANGELOG.md +0 -1155
- package/src/README.md +0 -7
- package/src/__stories__/editor-page.stories.tsx +0 -65
- package/src/__stories__/editor.stories.tsx +0 -134
- package/src/__stories__/item-editor.stories.tsx +0 -41
- package/src/__stories__/tex-error-view.stories.tsx +0 -26
- package/src/__testdata__/input-number.testdata.ts +0 -27
- package/src/__tests__/editor.test.tsx +0 -142
- package/src/__tests__/hint-editor.test.tsx +0 -83
- package/src/__tests__/i18n.test.ts +0 -501
- package/src/__tests__/integration.test.ts +0 -5
- package/src/__tests__/item-extras-editor.test.tsx +0 -85
- package/src/__tests__/traversal.test.ts +0 -377
- package/src/all-editors.test.ts +0 -16
- package/src/all-editors.ts +0 -83
- package/src/all-widgets.ts +0 -7
- package/src/article-editor.tsx +0 -438
- package/src/components/__stories__/blur-input.stories.tsx +0 -22
- package/src/components/__stories__/section-control-button.stories.tsx +0 -26
- package/src/components/__tests__/blur-input.test.tsx +0 -67
- package/src/components/blur-input.tsx +0 -69
- package/src/components/checkbox.tsx +0 -194
- package/src/components/device-framer.tsx +0 -90
- package/src/components/drag-target.tsx +0 -87
- package/src/components/dropdown-option.tsx +0 -311
- package/src/components/form-wrapped-text-field.tsx +0 -245
- package/src/components/graph-points-count-selector.tsx +0 -31
- package/src/components/graph-settings.tsx +0 -627
- package/src/components/graph-type-selector.tsx +0 -31
- package/src/components/hover-behavior.ts +0 -177
- package/src/components/json-editor.tsx +0 -121
- package/src/components/link.ts +0 -173
- package/src/components/section-control-button.tsx +0 -53
- package/src/components/segment-count-selector.tsx +0 -27
- package/src/components/simple-button.tsx +0 -85
- package/src/components/sortable.tsx +0 -187
- package/src/components/util.ts +0 -38
- package/src/components/viewport-resizer.tsx +0 -72
- package/src/components/widget-editor.tsx +0 -222
- package/src/components/widget-select.tsx +0 -48
- package/src/diffs/__stories__/perseus-diff-wrapper.tsx +0 -11
- package/src/diffs/__stories__/structured-item-diff.stories.tsx +0 -855
- package/src/diffs/__stories__/tags-diff.stories.tsx +0 -36
- package/src/diffs/__stories__/text-diff.stories.tsx +0 -35
- package/src/diffs/__tests__/split-diff.test.ts +0 -33
- package/src/diffs/__tests__/string-array-diff.test.ts +0 -73
- package/src/diffs/__tests__/structured-item-diff.test.ts +0 -433
- package/src/diffs/__tests__/widget-diff-performer.test.ts +0 -43
- package/src/diffs/article-diff.tsx +0 -69
- package/src/diffs/item-diff.tsx +0 -76
- package/src/diffs/renderer-diff.tsx +0 -137
- package/src/diffs/split-diff.ts +0 -31
- package/src/diffs/string-array-diff.ts +0 -74
- package/src/diffs/structured-item-diff.tsx +0 -275
- package/src/diffs/tags-diff.tsx +0 -49
- package/src/diffs/text-diff.tsx +0 -193
- package/src/diffs/widget-diff-performer.ts +0 -69
- package/src/diffs/widget-diff.tsx +0 -290
- package/src/editor-page.tsx +0 -325
- package/src/editor.tsx +0 -1099
- package/src/hint-editor.tsx +0 -469
- package/src/i18n.ts +0 -140
- package/src/iframe-content-renderer.tsx +0 -188
- package/src/index.ts +0 -30
- package/src/item-editor.tsx +0 -158
- package/src/item-extras-editor.tsx +0 -230
- package/src/katex-mhchem/index.js +0 -73
- package/src/katex-mhchem/parser.js +0 -2659
- package/src/multirenderer-editor.tsx +0 -1061
- package/src/stateful-article-editor.tsx +0 -173
- package/src/stateful-editor-page.tsx +0 -88
- package/src/styles/perseus-editor.less +0 -1321
- package/src/testing-widgets.ts +0 -11
- package/src/tex-error-view.tsx +0 -90
- package/src/util/points.test.ts +0 -24
- package/src/util/points.ts +0 -13
- package/src/util/register-all-widgets-and-editors-for-testing.test.ts +0 -17
- package/src/util/register-all-widgets-and-editors-for-testing.ts +0 -17
- package/src/version.ts +0 -10
- package/src/widgets/__stories__/categorizer-editor.stories.tsx +0 -24
- package/src/widgets/__stories__/definition-editor.stories.tsx +0 -18
- package/src/widgets/__stories__/dropdown-editor.stories.tsx +0 -18
- package/src/widgets/__stories__/explanation-editor.stories.tsx +0 -18
- package/src/widgets/__stories__/expression-editor.stories.tsx +0 -122
- package/src/widgets/__stories__/image-editor.stories.tsx +0 -72
- package/src/widgets/__stories__/input-number-editor.stories.tsx +0 -18
- package/src/widgets/__stories__/interaction-editor.stories.tsx +0 -37
- package/src/widgets/__stories__/label-image-editor.stories.tsx +0 -99
- package/src/widgets/__stories__/matcher-editor.stories.tsx +0 -18
- package/src/widgets/__stories__/number-line-editor.stories.tsx +0 -18
- package/src/widgets/__stories__/numeric-input-editor.stories.tsx +0 -18
- package/src/widgets/__stories__/radio-editor.stories.tsx +0 -116
- package/src/widgets/__stories__/sorter-editor.stories.tsx +0 -18
- package/src/widgets/__tests__/categorizer-editor.test.tsx +0 -51
- package/src/widgets/__tests__/definition-editor.test.tsx +0 -41
- package/src/widgets/__tests__/dropdown-editor.test.tsx +0 -57
- package/src/widgets/__tests__/explanation-editor.test.tsx +0 -59
- package/src/widgets/__tests__/expression-editor.test.tsx +0 -403
- package/src/widgets/__tests__/input-number-editor.test.tsx +0 -128
- package/src/widgets/__tests__/matcher-editor.test.tsx +0 -47
- package/src/widgets/__tests__/number-line-editor.test.tsx +0 -144
- package/src/widgets/__tests__/numeric-input-editor.test.tsx +0 -177
- package/src/widgets/__tests__/radio-editor.test.tsx +0 -118
- package/src/widgets/__tests__/sorter-editor.test.tsx +0 -55
- package/src/widgets/categorizer-editor.tsx +0 -104
- package/src/widgets/cs-program-editor.tsx +0 -256
- package/src/widgets/definition-editor.tsx +0 -77
- package/src/widgets/deprecated-standin-editor.tsx +0 -29
- package/src/widgets/dropdown-editor.tsx +0 -211
- package/src/widgets/example-graphie-widget-editor.tsx +0 -70
- package/src/widgets/example-graphie-widget.tsx +0 -172
- package/src/widgets/example-widget-editor.tsx +0 -62
- package/src/widgets/example-widget.tsx +0 -154
- package/src/widgets/explanation-editor.tsx +0 -92
- package/src/widgets/expression-editor.tsx +0 -557
- package/src/widgets/graded-group-editor.tsx +0 -161
- package/src/widgets/graded-group-set-editor.tsx +0 -104
- package/src/widgets/grapher-editor.tsx +0 -155
- package/src/widgets/group-editor.tsx +0 -83
- package/src/widgets/iframe-editor.tsx +0 -202
- package/src/widgets/image-editor.tsx +0 -367
- package/src/widgets/input-number-editor.tsx +0 -288
- package/src/widgets/interaction-editor/constraint-editor.tsx +0 -134
- package/src/widgets/interaction-editor/function-editor.tsx +0 -108
- package/src/widgets/interaction-editor/index.ts +0 -3
- package/src/widgets/interaction-editor/interaction-editor.tsx +0 -749
- package/src/widgets/interaction-editor/label-editor.tsx +0 -87
- package/src/widgets/interaction-editor/line-editor.tsx +0 -125
- package/src/widgets/interaction-editor/mathquill-input.tsx +0 -81
- package/src/widgets/interaction-editor/movable-line-editor.tsx +0 -121
- package/src/widgets/interaction-editor/movable-point-editor.tsx +0 -89
- package/src/widgets/interaction-editor/parametric-editor.tsx +0 -117
- package/src/widgets/interaction-editor/point-editor.tsx +0 -72
- package/src/widgets/interaction-editor/rectangle-editor.tsx +0 -96
- package/src/widgets/interactive-graph-editor.tsx +0 -571
- package/src/widgets/label-image/__stories__/answer-choices.stories.tsx +0 -82
- package/src/widgets/label-image/__stories__/behavior.stories.tsx +0 -31
- package/src/widgets/label-image/__stories__/marker.stories.tsx +0 -75
- package/src/widgets/label-image/__stories__/question-markers.stories.tsx +0 -107
- package/src/widgets/label-image/__stories__/select-image.stories.tsx +0 -59
- package/src/widgets/label-image/answer-choices.tsx +0 -231
- package/src/widgets/label-image/behavior.tsx +0 -122
- package/src/widgets/label-image/marker.tsx +0 -290
- package/src/widgets/label-image/question-markers.tsx +0 -176
- package/src/widgets/label-image/select-image.tsx +0 -81
- package/src/widgets/label-image-editor.tsx +0 -252
- package/src/widgets/lights-puzzle-editor.tsx +0 -278
- package/src/widgets/matcher-editor.tsx +0 -149
- package/src/widgets/matrix-editor.tsx +0 -156
- package/src/widgets/measurer-editor.tsx +0 -253
- package/src/widgets/molecule-editor.tsx +0 -64
- package/src/widgets/number-line-editor.tsx +0 -512
- package/src/widgets/numeric-input-editor.tsx +0 -536
- package/src/widgets/orderer-editor.tsx +0 -172
- package/src/widgets/passage-editor.tsx +0 -117
- package/src/widgets/passage-ref-editor.tsx +0 -80
- package/src/widgets/passage-ref-target-editor.tsx +0 -49
- package/src/widgets/plotter-editor.tsx +0 -542
- package/src/widgets/radio/editor.tsx +0 -398
- package/src/widgets/reaction-diagram-editor.tsx +0 -131
- package/src/widgets/sequence-editor.tsx +0 -205
- package/src/widgets/simple-markdown-tester-editor.tsx +0 -86
- package/src/widgets/simple-markdown-tester.tsx +0 -92
- package/src/widgets/simulator-editor.tsx +0 -146
- package/src/widgets/sorter-editor.tsx +0 -103
- package/src/widgets/table-editor.tsx +0 -164
- package/src/widgets/unit-editor.tsx +0 -299
- package/src/widgets/video-editor.tsx +0 -73
- package/tsconfig-build.json +0 -22
- package/tsconfig-build.tsbuildinfo +0 -1
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
/* eslint-disable jsx-a11y/anchor-is-valid, no-alert, react/sort-comp */
|
|
2
|
-
import {components, icons, ApiOptions} from "@khanacademy/perseus";
|
|
3
|
-
import PropTypes from "prop-types";
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
import _ from "underscore";
|
|
6
|
-
|
|
7
|
-
import Editor from "../editor";
|
|
8
|
-
|
|
9
|
-
const {InlineIcon} = components;
|
|
10
|
-
const {iconCircleArrowDown, iconCircleArrowUp, iconPlus, iconTrash} = icons;
|
|
11
|
-
|
|
12
|
-
type StepControlButtonProps = any;
|
|
13
|
-
|
|
14
|
-
class StepControlButton extends React.Component<StepControlButtonProps> {
|
|
15
|
-
render(): React.ReactNode {
|
|
16
|
-
return (
|
|
17
|
-
<a
|
|
18
|
-
href="#"
|
|
19
|
-
className={
|
|
20
|
-
"step-control-button " +
|
|
21
|
-
"simple-button " +
|
|
22
|
-
"simple-button--small " +
|
|
23
|
-
"orange"
|
|
24
|
-
}
|
|
25
|
-
onClick={(e) => {
|
|
26
|
-
e.preventDefault();
|
|
27
|
-
this.props.onClick();
|
|
28
|
-
}}
|
|
29
|
-
>
|
|
30
|
-
<InlineIcon {...this.props.icon} />
|
|
31
|
-
</a>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
type SequenceEditorProps = any;
|
|
37
|
-
|
|
38
|
-
class SequenceEditor extends React.Component<SequenceEditorProps> {
|
|
39
|
-
static propTypes = {
|
|
40
|
-
json: PropTypes.arrayOf(
|
|
41
|
-
PropTypes.shape({
|
|
42
|
-
content: PropTypes.string,
|
|
43
|
-
widgets: PropTypes.objectOf(PropTypes.any),
|
|
44
|
-
images: PropTypes.objectOf(PropTypes.any),
|
|
45
|
-
}),
|
|
46
|
-
),
|
|
47
|
-
apiOptions: ApiOptions.propTypes,
|
|
48
|
-
onChange: PropTypes.func.isRequired,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
static widgetName = "sequence" as const;
|
|
52
|
-
|
|
53
|
-
static defaultProps: SequenceEditorProps = {
|
|
54
|
-
json: [
|
|
55
|
-
{
|
|
56
|
-
content: "",
|
|
57
|
-
widgets: {},
|
|
58
|
-
images: {},
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
render(): React.ReactNode {
|
|
64
|
-
return (
|
|
65
|
-
<div className="perseus-sequence-editor">
|
|
66
|
-
{_.map(this.props.json, (json, i) => {
|
|
67
|
-
return (
|
|
68
|
-
<div key={i}>
|
|
69
|
-
Step {i + 1}
|
|
70
|
-
<div
|
|
71
|
-
style={{
|
|
72
|
-
display: "inline-block",
|
|
73
|
-
float: "right",
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
76
|
-
{i + 1 < this.props.json.length && (
|
|
77
|
-
<StepControlButton
|
|
78
|
-
icon={iconCircleArrowDown}
|
|
79
|
-
onClick={() => {
|
|
80
|
-
this._handleMoveStepLater(i);
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
83
|
-
)}
|
|
84
|
-
{i > 0 && (
|
|
85
|
-
<StepControlButton
|
|
86
|
-
icon={iconCircleArrowUp}
|
|
87
|
-
onClick={() => {
|
|
88
|
-
this._handleMoveStepEarlier(i);
|
|
89
|
-
}}
|
|
90
|
-
/>
|
|
91
|
-
)}
|
|
92
|
-
<StepControlButton
|
|
93
|
-
icon={iconTrash}
|
|
94
|
-
onClick={() => {
|
|
95
|
-
const msg =
|
|
96
|
-
"Are you sure you " +
|
|
97
|
-
"want to remove step " +
|
|
98
|
-
(i + 1) +
|
|
99
|
-
"?";
|
|
100
|
-
if (confirm(msg)) {
|
|
101
|
-
this._handleRemoveStep(i);
|
|
102
|
-
}
|
|
103
|
-
}}
|
|
104
|
-
/>
|
|
105
|
-
<StepControlButton
|
|
106
|
-
icon={iconPlus}
|
|
107
|
-
onClick={() => {
|
|
108
|
-
this._handleAddStepAfter(i);
|
|
109
|
-
}}
|
|
110
|
-
/>
|
|
111
|
-
</div>
|
|
112
|
-
<Editor
|
|
113
|
-
ref={"editor" + i}
|
|
114
|
-
apiOptions={this.props.apiOptions}
|
|
115
|
-
content={json.content}
|
|
116
|
-
widgets={json.widgets}
|
|
117
|
-
images={json.images}
|
|
118
|
-
widgetEnabled={true}
|
|
119
|
-
immutableWidgets={false}
|
|
120
|
-
onChange={_.partial(
|
|
121
|
-
this._handleEditorChange,
|
|
122
|
-
i,
|
|
123
|
-
)}
|
|
124
|
-
/>
|
|
125
|
-
</div>
|
|
126
|
-
);
|
|
127
|
-
})}
|
|
128
|
-
</div>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
_handleEditorChange: (arg1: number, arg2: any) => void = (i, newProps) => {
|
|
133
|
-
const steps = _.clone(this.props.json);
|
|
134
|
-
steps[i] = _.extend({}, steps[i], newProps);
|
|
135
|
-
this.props.onChange({json: steps});
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
serialize: () => any = () => {
|
|
139
|
-
return {
|
|
140
|
-
json: _.times(this.props.json.length, (i) => {
|
|
141
|
-
// eslint-disable-next-line react/no-string-refs
|
|
142
|
-
// @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
|
|
143
|
-
return this.refs["editor" + i].serialize();
|
|
144
|
-
}),
|
|
145
|
-
};
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
_handleMoveStepEarlier: (arg1: number) => void = (i) => {
|
|
149
|
-
if (i === 0) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const steps = _.clone(this.props.json);
|
|
153
|
-
const step = steps[i];
|
|
154
|
-
steps.splice(i, 1);
|
|
155
|
-
steps.splice(i - 1, 0, step);
|
|
156
|
-
this.props.onChange({
|
|
157
|
-
json: steps,
|
|
158
|
-
});
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
_handleMoveStepLater: (arg1: number) => void = (i) => {
|
|
162
|
-
const steps = _.clone(this.props.json);
|
|
163
|
-
if (i + 1 === steps.length) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const step = steps[i];
|
|
167
|
-
steps.splice(i, 1);
|
|
168
|
-
steps.splice(i + 1, 0, step);
|
|
169
|
-
this.props.onChange({
|
|
170
|
-
json: steps,
|
|
171
|
-
});
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
_handleAddStepAfter: (arg1: number) => void = (i) => {
|
|
175
|
-
// We do a full serialization here because we
|
|
176
|
-
// might be copying widgets:
|
|
177
|
-
const steps = _.clone(this.props.json);
|
|
178
|
-
// Here we do magic to allow you to copy-paste
|
|
179
|
-
// things from the previous section into the new
|
|
180
|
-
// section while preserving widgets.
|
|
181
|
-
// To enable this, we preserve the widgets
|
|
182
|
-
// object for the new section, but wipe out
|
|
183
|
-
// the content.
|
|
184
|
-
const newStep =
|
|
185
|
-
i >= 0
|
|
186
|
-
? {
|
|
187
|
-
widgets: steps[i].widgets,
|
|
188
|
-
}
|
|
189
|
-
: {};
|
|
190
|
-
steps.splice(i + 1, 0, newStep);
|
|
191
|
-
this.props.onChange({
|
|
192
|
-
json: steps,
|
|
193
|
-
});
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
_handleRemoveStep: (arg1: number) => void = (i) => {
|
|
197
|
-
const steps = _.clone(this.props.json);
|
|
198
|
-
steps.splice(i, 1);
|
|
199
|
-
this.props.onChange({
|
|
200
|
-
json: steps,
|
|
201
|
-
});
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export default SequenceEditor;
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
2
|
-
/* eslint-disable react/sort-comp */
|
|
3
|
-
/**
|
|
4
|
-
* This is the editor for the simple-markdown-tester widget. This is what shows
|
|
5
|
-
* up on the left side of the screen in the demo. Only the question writer
|
|
6
|
-
* sees this.
|
|
7
|
-
*/
|
|
8
|
-
import {Changeable, EditorJsonify} from "@khanacademy/perseus";
|
|
9
|
-
import * as React from "react";
|
|
10
|
-
|
|
11
|
-
type TextAreaProps = any;
|
|
12
|
-
|
|
13
|
-
class TextArea extends React.Component<TextAreaProps> {
|
|
14
|
-
render(): React.ReactNode {
|
|
15
|
-
return (
|
|
16
|
-
<textarea
|
|
17
|
-
// eslint-disable-next-line react/no-string-refs
|
|
18
|
-
ref="input"
|
|
19
|
-
value={this.props.value || ""}
|
|
20
|
-
onChange={this.changeValue}
|
|
21
|
-
/>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
focus = () => {
|
|
26
|
-
// eslint-disable-next-line react/no-string-refs
|
|
27
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
|
|
28
|
-
this.refs.input.focus();
|
|
29
|
-
return true;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
changeValue = (e: any) => {
|
|
33
|
-
// Translating from the js event e to the value
|
|
34
|
-
// of the textbox to send to onChange
|
|
35
|
-
this.props.onChange(e.target.value);
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
type SimpleMarkdownTesterEditorProps = any;
|
|
40
|
-
|
|
41
|
-
class SimpleMarkdownTesterEditor extends React.Component<SimpleMarkdownTesterEditorProps> {
|
|
42
|
-
static propTypes = {
|
|
43
|
-
...Changeable.propTypes,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
static widgetName = "simple-markdown-tester" as const;
|
|
47
|
-
|
|
48
|
-
static defaultProps: SimpleMarkdownTesterEditorProps = {
|
|
49
|
-
value: "",
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
input = React.createRef<TextArea>();
|
|
53
|
-
|
|
54
|
-
render(): React.ReactNode {
|
|
55
|
-
return (
|
|
56
|
-
<div>
|
|
57
|
-
<label>
|
|
58
|
-
<div>Simple markdown contents:</div>
|
|
59
|
-
<div>
|
|
60
|
-
<TextArea
|
|
61
|
-
value={this.props.value}
|
|
62
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
63
|
-
onChange={this.change("value")}
|
|
64
|
-
ref={this.input}
|
|
65
|
-
/>
|
|
66
|
-
</div>
|
|
67
|
-
</label>
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
change: (arg1: any, arg2: any, arg3: any) => any = (...args) => {
|
|
73
|
-
return Changeable.change.apply(this, args);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
focus: () => boolean = () => {
|
|
77
|
-
this.input.current?.focus();
|
|
78
|
-
return true;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
serialize: () => any = () => {
|
|
82
|
-
return EditorJsonify.serialize.call(this);
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export default SimpleMarkdownTesterEditor;
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react/sort-comp */
|
|
2
|
-
import {Changeable, PerseusMarkdown} from "@khanacademy/perseus";
|
|
3
|
-
import PropTypes from "prop-types";
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
import _ from "underscore";
|
|
6
|
-
|
|
7
|
-
const mdParse = PerseusMarkdown.parse;
|
|
8
|
-
const mdOutput = PerseusMarkdown.basicOutput;
|
|
9
|
-
|
|
10
|
-
type Props = any;
|
|
11
|
-
|
|
12
|
-
class SimpleMarkdownTester extends React.Component<Props> {
|
|
13
|
-
static propTypes = {
|
|
14
|
-
...Changeable.propTypes,
|
|
15
|
-
value: PropTypes.string,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
static defaultProps: Props = {
|
|
19
|
-
value: "",
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* This is the widget's grading function.
|
|
24
|
-
*
|
|
25
|
-
* simpleValidate generally defers to this function
|
|
26
|
-
*
|
|
27
|
-
* state is usually the result of toJSON on the widget
|
|
28
|
-
* rubric is the result of calling toJSON() on the editor
|
|
29
|
-
*/
|
|
30
|
-
static validate(state: any, rubric: any): any {
|
|
31
|
-
return {
|
|
32
|
-
type: "points",
|
|
33
|
-
earned: 0,
|
|
34
|
-
total: 0,
|
|
35
|
-
message: null,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
change: (arg1: any, arg2: any, arg3: any) => any = (...args) => {
|
|
40
|
-
return Changeable.change.apply(this, args);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
toJSON: () => Record<any, any> = () => {
|
|
44
|
-
return {};
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
render(): React.ReactNode {
|
|
48
|
-
// @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
|
|
49
|
-
const parsed = mdParse(this.props.value);
|
|
50
|
-
const output = mdOutput(parsed);
|
|
51
|
-
return <div>{output}</div>;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Widgets that are focusable should add a focus method that returns
|
|
56
|
-
* true if focusing succeeded. The first such widget found will be
|
|
57
|
-
* focused on page load.
|
|
58
|
-
*/
|
|
59
|
-
focus: () => boolean = () => {
|
|
60
|
-
// eslint-disable-next-line react/no-string-refs
|
|
61
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
|
|
62
|
-
this.refs.input.focus();
|
|
63
|
-
return true;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* simpleValidate is called for grading. Rubric is the result of calling
|
|
68
|
-
* toJSON() on the editor that created this widget.
|
|
69
|
-
*
|
|
70
|
-
* Should return an object representing the grading result, such as
|
|
71
|
-
* {
|
|
72
|
-
* type: "points",
|
|
73
|
-
* earned: 1,
|
|
74
|
-
* total: 1,
|
|
75
|
-
* message: null
|
|
76
|
-
* }
|
|
77
|
-
*/
|
|
78
|
-
simpleValidate: (arg1: any) => any = (rubric) => {
|
|
79
|
-
return SimpleMarkdownTester.validate(this.toJSON(), rubric);
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* For this widget to work, we must import this file in src/all-widgets.js
|
|
85
|
-
*/
|
|
86
|
-
export default {
|
|
87
|
-
name: "simple-markdown-tester",
|
|
88
|
-
displayName: "Simple Markdown Tester",
|
|
89
|
-
hidden: true, // Hides this widget from the Perseus.Editor widget select
|
|
90
|
-
widget: SimpleMarkdownTester,
|
|
91
|
-
transform: _.identity,
|
|
92
|
-
};
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react/sort-comp */
|
|
2
|
-
import {components, Changeable, EditorJsonify} from "@khanacademy/perseus";
|
|
3
|
-
import * as i18n from "@khanacademy/wonder-blocks-i18n";
|
|
4
|
-
import PropTypes from "prop-types";
|
|
5
|
-
import * as React from "react";
|
|
6
|
-
import _ from "underscore";
|
|
7
|
-
|
|
8
|
-
const {InfoTip, NumberInput} = components;
|
|
9
|
-
|
|
10
|
-
const maxTrials = 5000;
|
|
11
|
-
|
|
12
|
-
type Props = any;
|
|
13
|
-
|
|
14
|
-
class SimulatorEditor extends React.Component<Props> {
|
|
15
|
-
static propTypes = {
|
|
16
|
-
...Changeable.propTypes,
|
|
17
|
-
xAxisLabel: PropTypes.string,
|
|
18
|
-
yAxisLabel: PropTypes.string,
|
|
19
|
-
numTrials: PropTypes.number,
|
|
20
|
-
proportionLabel: PropTypes.string,
|
|
21
|
-
proportionOrPercentage: PropTypes.string,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
static widgetName = "simulator" as const;
|
|
25
|
-
|
|
26
|
-
static defaultProps: Props = {
|
|
27
|
-
xAxisLabel: "Proportion (%)",
|
|
28
|
-
yAxisLabel: "Number of times seen",
|
|
29
|
-
numTrials: 100,
|
|
30
|
-
proportionLabel: "Underlying proportion",
|
|
31
|
-
proportionOrPercentage: "proportion",
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
render(): React.ReactNode {
|
|
35
|
-
return (
|
|
36
|
-
<div className="perseus-widget-simulator">
|
|
37
|
-
<div>
|
|
38
|
-
{i18n._("X-Axis Label")}:
|
|
39
|
-
<input
|
|
40
|
-
type="text"
|
|
41
|
-
className="graph-settings-axis-label"
|
|
42
|
-
value={this.props.xAxisLabel}
|
|
43
|
-
onChange={_.partial(
|
|
44
|
-
this.handleTargetValueChange,
|
|
45
|
-
"xAxisLabel",
|
|
46
|
-
)}
|
|
47
|
-
/>
|
|
48
|
-
</div>
|
|
49
|
-
<div>
|
|
50
|
-
{i18n._("Y-Axis Label")}:
|
|
51
|
-
<input
|
|
52
|
-
type="text"
|
|
53
|
-
className="graph-settings-axis-label"
|
|
54
|
-
value={this.props.yAxisLabel}
|
|
55
|
-
onChange={_.partial(
|
|
56
|
-
this.handleTargetValueChange,
|
|
57
|
-
"yAxisLabel",
|
|
58
|
-
)}
|
|
59
|
-
/>
|
|
60
|
-
</div>
|
|
61
|
-
<div>
|
|
62
|
-
{i18n._('"True Proportion" Label')}:
|
|
63
|
-
<input
|
|
64
|
-
type="text"
|
|
65
|
-
className="graph-settings-axis-label"
|
|
66
|
-
value={this.props.proportionLabel}
|
|
67
|
-
onChange={_.partial(
|
|
68
|
-
this.handleTargetValueChange,
|
|
69
|
-
"proportionLabel",
|
|
70
|
-
)}
|
|
71
|
-
/>
|
|
72
|
-
<InfoTip>
|
|
73
|
-
<p>
|
|
74
|
-
This text will be displayed next to the box in which
|
|
75
|
-
the user enters the sample proportion for their
|
|
76
|
-
simulation. For example, if your question is about
|
|
77
|
-
surveying for approval ratings, you might want this
|
|
78
|
-
to say "Sample approval rating".
|
|
79
|
-
</p>
|
|
80
|
-
</InfoTip>
|
|
81
|
-
</div>
|
|
82
|
-
<div>
|
|
83
|
-
{i18n._("Proportion or Percentage")}:
|
|
84
|
-
<select
|
|
85
|
-
className="perseus-widget-dropdown"
|
|
86
|
-
value={this.props.proportionOrPercentage}
|
|
87
|
-
onChange={_.partial(
|
|
88
|
-
this.handleTargetValueChange,
|
|
89
|
-
"proportionOrPercentage",
|
|
90
|
-
)}
|
|
91
|
-
>
|
|
92
|
-
<option key="proportion" value="proportion">
|
|
93
|
-
Proportion
|
|
94
|
-
</option>
|
|
95
|
-
<option key="percentage" value="percentage">
|
|
96
|
-
Percentage
|
|
97
|
-
</option>
|
|
98
|
-
</select>
|
|
99
|
-
<InfoTip>
|
|
100
|
-
<p>
|
|
101
|
-
Do you want the user to describe their simulation in
|
|
102
|
-
terms of a proportion or a percentage?
|
|
103
|
-
</p>
|
|
104
|
-
</InfoTip>
|
|
105
|
-
</div>
|
|
106
|
-
<div>
|
|
107
|
-
{i18n._("Number of trials")}:
|
|
108
|
-
<NumberInput
|
|
109
|
-
value={this.props.numTrials}
|
|
110
|
-
checkValidity={(val) => {
|
|
111
|
-
return val >= 0 && val <= maxTrials;
|
|
112
|
-
}}
|
|
113
|
-
onChange={this.change("numTrials")}
|
|
114
|
-
/>
|
|
115
|
-
<InfoTip>
|
|
116
|
-
<p>
|
|
117
|
-
This controls the number of trials used in the
|
|
118
|
-
simulation. For example, if you set this to 50, then
|
|
119
|
-
the survey will be conducted 50 times. Warning:
|
|
120
|
-
setting this too high (i.e., greater than 5000 or
|
|
121
|
-
so) will freeze the page.
|
|
122
|
-
</p>
|
|
123
|
-
</InfoTip>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
change: (...args: ReadonlyArray<unknown>) => any = (...args) => {
|
|
130
|
-
// @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
|
|
131
|
-
return Changeable.change.apply(this, args);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
handleTargetValueChange: (arg1: string, arg2: any) => void = (
|
|
135
|
-
propName,
|
|
136
|
-
e,
|
|
137
|
-
) => {
|
|
138
|
-
this.change(propName, e.target.value);
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
serialize: () => any = () => {
|
|
142
|
-
return EditorJsonify.serialize.call(this);
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export default SimulatorEditor;
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
2
|
-
/* eslint-disable react/forbid-prop-types */
|
|
3
|
-
import {components} from "@khanacademy/perseus";
|
|
4
|
-
import PropTypes from "prop-types";
|
|
5
|
-
import * as React from "react";
|
|
6
|
-
import _ from "underscore";
|
|
7
|
-
|
|
8
|
-
const {InfoTip, PropCheckBox, TextListEditor} = components;
|
|
9
|
-
|
|
10
|
-
const HORIZONTAL = "horizontal";
|
|
11
|
-
const VERTICAL = "vertical";
|
|
12
|
-
|
|
13
|
-
type Props = any;
|
|
14
|
-
|
|
15
|
-
class SorterEditor extends React.Component<Props> {
|
|
16
|
-
static propTypes = {
|
|
17
|
-
correct: PropTypes.array,
|
|
18
|
-
layout: PropTypes.oneOf([HORIZONTAL, VERTICAL]),
|
|
19
|
-
padding: PropTypes.bool,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
static widgetName = "sorter" as const;
|
|
23
|
-
|
|
24
|
-
static defaultProps: Props = {
|
|
25
|
-
correct: ["$x$", "$y$", "$z$"],
|
|
26
|
-
layout: HORIZONTAL,
|
|
27
|
-
padding: true,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
onLayoutChange: (arg1: React.ChangeEvent<HTMLInputElement>) => void = (
|
|
31
|
-
e,
|
|
32
|
-
) => {
|
|
33
|
-
this.props.onChange({layout: e.target.value});
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
serialize: (arg1: any) => void = () => {
|
|
37
|
-
return _.pick(this.props, "correct", "layout", "padding");
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
render(): React.ReactNode {
|
|
41
|
-
const editor = this;
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div>
|
|
45
|
-
<div>
|
|
46
|
-
{" "}
|
|
47
|
-
Correct answer:{" "}
|
|
48
|
-
<InfoTip>
|
|
49
|
-
<p>
|
|
50
|
-
Enter the correct answer (in the correct order)
|
|
51
|
-
here. The preview on the right will have the cards
|
|
52
|
-
in a randomized order, which is how the student will
|
|
53
|
-
see them.
|
|
54
|
-
</p>
|
|
55
|
-
</InfoTip>
|
|
56
|
-
</div>
|
|
57
|
-
<TextListEditor
|
|
58
|
-
options={this.props.correct}
|
|
59
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
60
|
-
onChange={function (options, cb) {
|
|
61
|
-
editor.props.onChange({correct: options}, cb);
|
|
62
|
-
}}
|
|
63
|
-
layout={this.props.layout}
|
|
64
|
-
/>
|
|
65
|
-
<div>
|
|
66
|
-
<label>
|
|
67
|
-
{" "}
|
|
68
|
-
Layout:{" "}
|
|
69
|
-
<select
|
|
70
|
-
value={this.props.layout}
|
|
71
|
-
// @ts-expect-error - TS2322 - Type '(arg1: ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'ChangeEventHandler<HTMLSelectElement>'.
|
|
72
|
-
onChange={this.onLayoutChange}
|
|
73
|
-
>
|
|
74
|
-
<option value={HORIZONTAL}>Horizontal</option>
|
|
75
|
-
<option value={VERTICAL}>Vertical</option>
|
|
76
|
-
</select>
|
|
77
|
-
</label>
|
|
78
|
-
<InfoTip>
|
|
79
|
-
<p>
|
|
80
|
-
Use the horizontal layout for short text and small
|
|
81
|
-
images. The vertical layout is best for longer text
|
|
82
|
-
and larger images.
|
|
83
|
-
</p>
|
|
84
|
-
</InfoTip>
|
|
85
|
-
</div>
|
|
86
|
-
<div>
|
|
87
|
-
<PropCheckBox
|
|
88
|
-
label="Padding:"
|
|
89
|
-
padding={this.props.padding}
|
|
90
|
-
onChange={this.props.onChange}
|
|
91
|
-
/>
|
|
92
|
-
<InfoTip>
|
|
93
|
-
<p>
|
|
94
|
-
Padding is good for text, but not needed for images.
|
|
95
|
-
</p>
|
|
96
|
-
</InfoTip>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export default SorterEditor;
|