@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,164 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react/sort-comp */
|
|
2
|
-
import {components, TableWidget, Util} 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 {InfoTip, NumberInput} = components;
|
|
10
|
-
const Table = TableWidget.widget;
|
|
11
|
-
|
|
12
|
-
type Props = any;
|
|
13
|
-
|
|
14
|
-
class TableEditor extends React.Component<Props> {
|
|
15
|
-
static propTypes = {
|
|
16
|
-
rows: PropTypes.number,
|
|
17
|
-
columns: PropTypes.number,
|
|
18
|
-
headers: PropTypes.arrayOf(PropTypes.string),
|
|
19
|
-
answers: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)),
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
static widgetName = "table" as const;
|
|
23
|
-
|
|
24
|
-
static defaultProps: Props = (function () {
|
|
25
|
-
const defaultRows = 4;
|
|
26
|
-
const defaultColumns = 1;
|
|
27
|
-
const blankAnswers = _(defaultRows).times(function () {
|
|
28
|
-
return Util.stringArrayOfSize(defaultColumns);
|
|
29
|
-
});
|
|
30
|
-
return {
|
|
31
|
-
headers: [""],
|
|
32
|
-
rows: defaultRows,
|
|
33
|
-
columns: defaultColumns,
|
|
34
|
-
answers: blankAnswers,
|
|
35
|
-
};
|
|
36
|
-
})();
|
|
37
|
-
|
|
38
|
-
numberOfColumns = React.createRef<components.NumberInput>();
|
|
39
|
-
|
|
40
|
-
focus: () => void = () => {
|
|
41
|
-
this.numberOfColumns.current?.focus();
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
render(): React.ReactNode {
|
|
45
|
-
const tableProps = _.pick(
|
|
46
|
-
this.props,
|
|
47
|
-
"headers",
|
|
48
|
-
"answers",
|
|
49
|
-
"onChange",
|
|
50
|
-
"apiOptions",
|
|
51
|
-
);
|
|
52
|
-
_.extend(tableProps, {
|
|
53
|
-
editableHeaders: true,
|
|
54
|
-
Editor,
|
|
55
|
-
onFocus: () => {},
|
|
56
|
-
onBlur: () => {},
|
|
57
|
-
trackInteraction: () => {},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<div>
|
|
62
|
-
<div className="perseus-widget-row">
|
|
63
|
-
<label>
|
|
64
|
-
Number of columns:{" "}
|
|
65
|
-
<NumberInput
|
|
66
|
-
ref={this.numberOfColumns}
|
|
67
|
-
value={this.props.columns}
|
|
68
|
-
onChange={(val) => {
|
|
69
|
-
if (val) {
|
|
70
|
-
this.onSizeInput(this.props.rows, val);
|
|
71
|
-
}
|
|
72
|
-
}}
|
|
73
|
-
useArrowKeys={true}
|
|
74
|
-
/>
|
|
75
|
-
</label>
|
|
76
|
-
</div>
|
|
77
|
-
<div className="perseus-widget-row">
|
|
78
|
-
<label>
|
|
79
|
-
Number of rows:{" "}
|
|
80
|
-
<NumberInput
|
|
81
|
-
// eslint-disable-next-line react/no-string-refs
|
|
82
|
-
ref="numberOfRows"
|
|
83
|
-
value={this.props.rows}
|
|
84
|
-
onChange={(val) => {
|
|
85
|
-
if (val) {
|
|
86
|
-
this.onSizeInput(val, this.props.columns);
|
|
87
|
-
}
|
|
88
|
-
}}
|
|
89
|
-
useArrowKeys={true}
|
|
90
|
-
/>
|
|
91
|
-
</label>
|
|
92
|
-
</div>
|
|
93
|
-
<div>
|
|
94
|
-
{" "}
|
|
95
|
-
Table of answers:{" "}
|
|
96
|
-
<InfoTip>
|
|
97
|
-
<p>
|
|
98
|
-
The student has to fill out all cells in the table.
|
|
99
|
-
For partially filled tables create a table using the
|
|
100
|
-
template, and insert text input boxes as desired.
|
|
101
|
-
</p>
|
|
102
|
-
</InfoTip>
|
|
103
|
-
</div>
|
|
104
|
-
<div>
|
|
105
|
-
<Table {...tableProps} />
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
onSizeInput: (arg1: number, arg2: number) => void = (
|
|
112
|
-
numRawRows,
|
|
113
|
-
numRawColumns,
|
|
114
|
-
) => {
|
|
115
|
-
let rows = +numRawRows || 0;
|
|
116
|
-
let columns = +numRawColumns || 0;
|
|
117
|
-
rows = Math.min(Math.max(1, rows), 30);
|
|
118
|
-
columns = Math.min(Math.max(1, columns), 6);
|
|
119
|
-
const oldColumns = this.props.columns;
|
|
120
|
-
const oldRows = this.props.rows;
|
|
121
|
-
|
|
122
|
-
const answers = this.props.answers;
|
|
123
|
-
// Truncate if necessary; else, append
|
|
124
|
-
if (rows <= oldRows) {
|
|
125
|
-
answers.length = rows;
|
|
126
|
-
} else {
|
|
127
|
-
_(rows - oldRows).times(function () {
|
|
128
|
-
answers.push(Util.stringArrayOfSize(oldColumns));
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function fixColumnSizing(array: any) {
|
|
133
|
-
// Truncate if necessary; else, append
|
|
134
|
-
if (columns <= oldColumns) {
|
|
135
|
-
array.length = columns;
|
|
136
|
-
} else {
|
|
137
|
-
_(columns - oldColumns).times(function () {
|
|
138
|
-
array.push("");
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const headers = this.props.headers;
|
|
144
|
-
fixColumnSizing(headers);
|
|
145
|
-
_.each(answers, fixColumnSizing);
|
|
146
|
-
|
|
147
|
-
this.props.onChange({
|
|
148
|
-
rows: rows,
|
|
149
|
-
columns: columns,
|
|
150
|
-
answers: answers,
|
|
151
|
-
headers: headers,
|
|
152
|
-
});
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
serialize: () => any = () => {
|
|
156
|
-
const json = _.pick(this.props, "headers", "rows", "columns");
|
|
157
|
-
|
|
158
|
-
return _.extend({}, json, {
|
|
159
|
-
answers: _.map(this.props.answers, _.clone),
|
|
160
|
-
});
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export default TableEditor;
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react/no-unsafe */
|
|
2
|
-
import * as KAS from "@khanacademy/kas";
|
|
3
|
-
import {
|
|
4
|
-
components,
|
|
5
|
-
displaySigFigs,
|
|
6
|
-
icons,
|
|
7
|
-
Changeable,
|
|
8
|
-
EditorJsonify,
|
|
9
|
-
} from "@khanacademy/perseus";
|
|
10
|
-
import PropTypes from "prop-types";
|
|
11
|
-
import * as React from "react";
|
|
12
|
-
import _ from "underscore";
|
|
13
|
-
|
|
14
|
-
const {InlineIcon, NumberInput} = components;
|
|
15
|
-
const {iconOk, iconRemove} = icons;
|
|
16
|
-
|
|
17
|
-
// TODO(joel): teach KAS how to accept an answer only if it's expressed in
|
|
18
|
-
// terms of a certain type.
|
|
19
|
-
// TODO(joel): Allow sigfigs within a range rather than an exact expected
|
|
20
|
-
// value?
|
|
21
|
-
|
|
22
|
-
const ALL = "all" as const;
|
|
23
|
-
const SOME = "some" as const;
|
|
24
|
-
const MAX_SIGFIGS = 10;
|
|
25
|
-
|
|
26
|
-
const sigfigPrint = function (num: any, sigfigs: any) {
|
|
27
|
-
return displaySigFigs(num, sigfigs, -MAX_SIGFIGS, false);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// Extract the primitive units from a unit expression. This first simplifies
|
|
31
|
-
// `expr` to a `Mul` like "5 kg m / s^2" then removes the first term.
|
|
32
|
-
const primUnits = function (expr: any) {
|
|
33
|
-
return expr.simplify().asMul().partition()[1].flatten().simplify();
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
type UnitExampleProps = any;
|
|
37
|
-
type UnitExampleState = any;
|
|
38
|
-
|
|
39
|
-
// Show the name of a unit and whether it's recognized by KAS.
|
|
40
|
-
//
|
|
41
|
-
// In the future I plan for this to show an example of a thing that would be
|
|
42
|
-
// accepted in that unit.
|
|
43
|
-
class UnitExample extends React.Component<UnitExampleProps, UnitExampleState> {
|
|
44
|
-
// TODO(jangmi, CP-3288): Remove usage of `UNSAFE_componentWillMount`
|
|
45
|
-
UNSAFE_componentWillMount() {
|
|
46
|
-
// @ts-expect-error - TS2345 - Argument of type 'Readonly<any> & Readonly<{ children?: ReactNode; }>' is not assignable to parameter of type '{ name: any; original: any; sigfigs: any; }'.
|
|
47
|
-
this._checkValidity(this.props);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
UNSAFE_componentWillReceiveProps(nextProps: UnitExampleProps) {
|
|
51
|
-
this._checkValidity(nextProps);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
_checkValidity = ({name, original, sigfigs}) => {
|
|
55
|
-
const parseResult = KAS.unitParse(name);
|
|
56
|
-
let solvedExample = "";
|
|
57
|
-
|
|
58
|
-
// A unit is valid if it parses and is equivalent to the original.
|
|
59
|
-
let valid = true;
|
|
60
|
-
|
|
61
|
-
if (parseResult.parsed && original) {
|
|
62
|
-
const x = new KAS.Var("x");
|
|
63
|
-
const {unit} = parseResult;
|
|
64
|
-
const equality = new KAS.Eq(original, "=", new KAS.Mul(x, unit));
|
|
65
|
-
try {
|
|
66
|
-
const answer = equality.solveLinearEquationForVariable(x);
|
|
67
|
-
|
|
68
|
-
// The third parameter is the least significant decimal place.
|
|
69
|
-
// I.e. the index of the last place you care about
|
|
70
|
-
// (543210.(-1)(-2)(-3) etc). We use -10 because that should
|
|
71
|
-
// always be safe since we only care up to maximum 10 decimal
|
|
72
|
-
// places.
|
|
73
|
-
solvedExample = sigfigPrint(answer.eval(), sigfigs);
|
|
74
|
-
|
|
75
|
-
valid = KAS.compare(primUnits(original), primUnits(unit)).equal;
|
|
76
|
-
} catch (e: any) {
|
|
77
|
-
valid = false;
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
valid = false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
this.setState({
|
|
84
|
-
valid,
|
|
85
|
-
solvedExample,
|
|
86
|
-
});
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
render(): React.ReactNode {
|
|
90
|
-
let icon;
|
|
91
|
-
if (this.state.valid) {
|
|
92
|
-
icon = (
|
|
93
|
-
<span>
|
|
94
|
-
<span className="unit-example-okay">
|
|
95
|
-
<InlineIcon {...iconOk} />
|
|
96
|
-
</span>
|
|
97
|
-
{this.state.solvedExample}
|
|
98
|
-
</span>
|
|
99
|
-
);
|
|
100
|
-
} else {
|
|
101
|
-
icon = (
|
|
102
|
-
<span className="unit-example-not-okay">
|
|
103
|
-
<InlineIcon {...iconRemove} />
|
|
104
|
-
</span>
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<div>
|
|
110
|
-
{icon} {this.props.name}
|
|
111
|
-
</div>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
type UnitInputEditorProps = any;
|
|
117
|
-
|
|
118
|
-
class UnitInputEditor extends React.Component<UnitInputEditorProps> {
|
|
119
|
-
parsed: boolean | null | undefined;
|
|
120
|
-
groupId: string;
|
|
121
|
-
original: any | null | undefined;
|
|
122
|
-
|
|
123
|
-
static propTypes = {
|
|
124
|
-
...Changeable.propTypes,
|
|
125
|
-
value: PropTypes.string,
|
|
126
|
-
acceptingUnits: PropTypes.arrayOf(PropTypes.string),
|
|
127
|
-
accepting: PropTypes.oneOf([ALL, SOME]),
|
|
128
|
-
sigfigs: PropTypes.number,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
static widgetName = "unit-input" as const;
|
|
132
|
-
|
|
133
|
-
static defaultProps: UnitInputEditorProps = {
|
|
134
|
-
value: "5x10^5 kg m / s^2",
|
|
135
|
-
accepting: ALL,
|
|
136
|
-
sigfigs: 3,
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
constructor(props: UnitExampleProps) {
|
|
140
|
-
super(props);
|
|
141
|
-
|
|
142
|
-
this.groupId = _.uniqueId("accepting");
|
|
143
|
-
this._doOriginal(props);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
UNSAFE_componentWillReceiveProps(nextProps: UnitInputEditorProps) {
|
|
147
|
-
this._doOriginal(nextProps);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
change: (arg1: any, arg2: any, arg3: any) => any = (...args) => {
|
|
151
|
-
return Changeable.change.apply(this, args);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
handleAcceptingUnitsChange: (
|
|
155
|
-
arg1: React.ChangeEvent<HTMLInputElement>,
|
|
156
|
-
) => void = (event) => {
|
|
157
|
-
const acceptingUnits = event.target.value
|
|
158
|
-
.split(",")
|
|
159
|
-
.map((str) => str.trim())
|
|
160
|
-
.filter((str) => str !== "");
|
|
161
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
162
|
-
this.change({acceptingUnits});
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
handleSigfigChange: (arg1: number) => void = (sigfigs) => {
|
|
166
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
167
|
-
this.change({sigfigs});
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
_checkSigfigValidity: (arg1: number) => boolean = (sigfigs) => {
|
|
171
|
-
return sigfigs > 0 && sigfigs <= MAX_SIGFIGS;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
_setAccepting: (arg1: typeof SOME | typeof ALL) => void = (val) => {
|
|
175
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
176
|
-
this.change({accepting: val});
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
_doOriginal: (arg1: UnitExampleProps) => void = (props) => {
|
|
180
|
-
const tryParse = KAS.unitParse(props.value);
|
|
181
|
-
this.parsed = false;
|
|
182
|
-
|
|
183
|
-
// Only update this state if the unit parsed *and* it has a magnitude
|
|
184
|
-
// attached to it. KAS can also parse units without magnitudes ("1.2
|
|
185
|
-
// g" vs "g").
|
|
186
|
-
if (tryParse.parsed && tryParse.type === "unitMagnitude") {
|
|
187
|
-
this.original = tryParse.expr;
|
|
188
|
-
this.parsed = true;
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
onChange: (arg1: React.ChangeEvent<HTMLInputElement>) => void = (event) => {
|
|
193
|
-
this.props.onChange({value: event.target.value});
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
getSaveWarnings: () => ReadonlyArray<string> = () => {
|
|
197
|
-
const {value, accepting, acceptingUnits} = this.props;
|
|
198
|
-
const warnings: Array<string> = [];
|
|
199
|
-
|
|
200
|
-
const tryParse = KAS.unitParse(value);
|
|
201
|
-
if (!tryParse.parsed) {
|
|
202
|
-
warnings.push("Answer did not parse");
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (accepting === SOME && acceptingUnits.length === 0) {
|
|
206
|
-
warnings.push("There are no accepted units");
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return warnings;
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
serialize: () => any = () => {
|
|
213
|
-
return EditorJsonify.serialize.call(this);
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
render(): React.ReactNode {
|
|
217
|
-
const {acceptingUnits = [], accepting} = this.props;
|
|
218
|
-
let acceptingElem = null;
|
|
219
|
-
if (accepting === SOME) {
|
|
220
|
-
const unitsArr = acceptingUnits.map((name, i) => (
|
|
221
|
-
<UnitExample
|
|
222
|
-
name={name}
|
|
223
|
-
original={this.original || null}
|
|
224
|
-
sigfigs={this.props.sigfigs}
|
|
225
|
-
key={i}
|
|
226
|
-
/>
|
|
227
|
-
));
|
|
228
|
-
|
|
229
|
-
// @ts-expect-error - TS2322 - Type 'Element' is not assignable to type 'null'.
|
|
230
|
-
acceptingElem = (
|
|
231
|
-
<div>
|
|
232
|
-
<input
|
|
233
|
-
type="text"
|
|
234
|
-
defaultValue={acceptingUnits.join(", ")}
|
|
235
|
-
onChange={this.handleAcceptingUnitsChange}
|
|
236
|
-
/>{" "}
|
|
237
|
-
(comma-separated)
|
|
238
|
-
{unitsArr}
|
|
239
|
-
</div>
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return (
|
|
244
|
-
<div className="unit-editor">
|
|
245
|
-
<div>
|
|
246
|
-
<input
|
|
247
|
-
value={this.props.value}
|
|
248
|
-
className="unit-editor-canonical"
|
|
249
|
-
onChange={this.onChange}
|
|
250
|
-
/>{" "}
|
|
251
|
-
{this.parsed ? (
|
|
252
|
-
<span className="unit-example-okay">
|
|
253
|
-
<InlineIcon {...iconOk} />
|
|
254
|
-
</span>
|
|
255
|
-
) : (
|
|
256
|
-
<span className="unit-example-not-okay">
|
|
257
|
-
<InlineIcon {...iconRemove} />
|
|
258
|
-
</span>
|
|
259
|
-
)}
|
|
260
|
-
</div>
|
|
261
|
-
|
|
262
|
-
<div>
|
|
263
|
-
Significant Figures:{" "}
|
|
264
|
-
<NumberInput
|
|
265
|
-
value={this.props.sigfigs}
|
|
266
|
-
onChange={this.handleSigfigChange}
|
|
267
|
-
checkValidity={this._checkSigfigValidity}
|
|
268
|
-
useArrowKeys
|
|
269
|
-
/>
|
|
270
|
-
</div>
|
|
271
|
-
|
|
272
|
-
<div>
|
|
273
|
-
<label>
|
|
274
|
-
<input
|
|
275
|
-
type="radio"
|
|
276
|
-
name={this.groupId}
|
|
277
|
-
onChange={() => this._setAccepting(ALL)}
|
|
278
|
-
checked={this.props.accepting === ALL}
|
|
279
|
-
/>
|
|
280
|
-
{" Any equivalent unit "}
|
|
281
|
-
</label>
|
|
282
|
-
<label>
|
|
283
|
-
<input
|
|
284
|
-
type="radio"
|
|
285
|
-
name={this.groupId}
|
|
286
|
-
onChange={() => this._setAccepting(SOME)}
|
|
287
|
-
checked={this.props.accepting === SOME}
|
|
288
|
-
/>
|
|
289
|
-
{" Only these units "}
|
|
290
|
-
</label>
|
|
291
|
-
</div>
|
|
292
|
-
|
|
293
|
-
{acceptingElem}
|
|
294
|
-
</div>
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export default UnitInputEditor;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {components, Changeable, EditorJsonify} from "@khanacademy/perseus";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import _ from "underscore";
|
|
5
|
-
|
|
6
|
-
import BlurInput from "../components/blur-input";
|
|
7
|
-
|
|
8
|
-
const {InfoTip} = components;
|
|
9
|
-
|
|
10
|
-
const KA_VIDEO_URL = /khanacademy\.org\/.*\/v\/(.*)$/;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Turns Khan Academy URLs into the KA slugs, if possible. Any other URLs are
|
|
14
|
-
* returned unchanged.
|
|
15
|
-
*/
|
|
16
|
-
function getSlugFromUrl(url: string) {
|
|
17
|
-
const match = KA_VIDEO_URL.exec(url);
|
|
18
|
-
if (match) {
|
|
19
|
-
return match[1];
|
|
20
|
-
}
|
|
21
|
-
return url;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
type Props = any;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* This is the main editor for this widget, to specify all the options.
|
|
28
|
-
*/
|
|
29
|
-
class VideoEditor extends React.Component<Props> {
|
|
30
|
-
static propTypes = {
|
|
31
|
-
...Changeable.propTypes,
|
|
32
|
-
location: PropTypes.string,
|
|
33
|
-
onChange: PropTypes.func,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
static widgetName = "video" as const;
|
|
37
|
-
|
|
38
|
-
static defaultProps: Props = {
|
|
39
|
-
location: "",
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
_handleUrlChange: (arg1: string) => void = (url) => {
|
|
43
|
-
this.props.onChange({location: getSlugFromUrl(url)});
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
change: (arg1: any, arg2: any, arg3: any) => any = (...args) => {
|
|
47
|
-
return Changeable.change.apply(this, args);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
serialize: () => any = () => {
|
|
51
|
-
return EditorJsonify.serialize.call(this);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
render(): React.ReactNode {
|
|
55
|
-
return (
|
|
56
|
-
<div>
|
|
57
|
-
<label>
|
|
58
|
-
KA Video Slug:{" "}
|
|
59
|
-
<BlurInput
|
|
60
|
-
value={this.props.location}
|
|
61
|
-
style={{width: 290}}
|
|
62
|
-
onChange={this._handleUrlChange}
|
|
63
|
-
/>
|
|
64
|
-
<InfoTip>
|
|
65
|
-
KA video URLs will be converted to just the slug.
|
|
66
|
-
</InfoTip>
|
|
67
|
-
</label>
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export default VideoEditor;
|
package/tsconfig-build.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../tsconfig-shared.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "./dist",
|
|
5
|
-
"rootDir": "src",
|
|
6
|
-
"paths": {
|
|
7
|
-
"jsdiff": ["../../vendor/jsdiff/jsdiff.js"],
|
|
8
|
-
"hubble": ["../../vendor/hubble/hubble.js"],
|
|
9
|
-
// NOTE(kevinb): We have to repeat this here because TS doesn't do
|
|
10
|
-
// intelligent merge of tsconfig.json files when using `extends`.
|
|
11
|
-
"@khanacademy/*": [
|
|
12
|
-
"../*/src"
|
|
13
|
-
]
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"references": [
|
|
17
|
-
{"path": "../kas/tsconfig-build.json"},
|
|
18
|
-
{"path": "../kmath/tsconfig-build.json"},
|
|
19
|
-
{"path": "../perseus/tsconfig-build.json"},
|
|
20
|
-
{"path": "../perseus-core/tsconfig-build.json"},
|
|
21
|
-
]
|
|
22
|
-
}
|