@khanacademy/perseus-editor 2.17.0 → 3.0.0
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 +11 -0
- package/dist/components/widget-editor.d.ts +4 -4
- package/dist/editor.d.ts +5 -5
- package/dist/es/index.js +32 -38
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +19 -25
- package/dist/index.js.map +1 -1
- package/dist/widgets/deprecated-standin-editor.d.ts +10 -0
- package/package.json +2 -2
- package/src/all-editors.ts +2 -0
- package/src/components/widget-editor.tsx +10 -22
- package/src/editor.tsx +28 -31
- package/src/index.ts +4 -0
- package/src/util/register-all-widgets-and-editors-for-testing.ts +4 -0
- package/src/widgets/deprecated-standin-editor.tsx +29 -0
- package/tsconfig-build.tsbuildinfo +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
type Props = {
|
|
3
|
+
onChange: (options: any) => void;
|
|
4
|
+
};
|
|
5
|
+
declare class DeprecatedStandinEditor extends React.Component<Props> {
|
|
6
|
+
static widgetName: "deprecated-standin";
|
|
7
|
+
serialize(): any;
|
|
8
|
+
render(): React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export default DeprecatedStandinEditor;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Perseus editors",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "3.0.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@khanacademy/kas": "^0.3.7",
|
|
26
26
|
"@khanacademy/kmath": "^0.1.8",
|
|
27
27
|
"@khanacademy/math-input": "^16.5.0",
|
|
28
|
-
"@khanacademy/perseus": "^
|
|
28
|
+
"@khanacademy/perseus": "^18.0.0",
|
|
29
29
|
"@khanacademy/perseus-core": "1.4.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
package/src/all-editors.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import CategorizerEditor from "./widgets/categorizer-editor";
|
|
2
2
|
import CSProgramEditor from "./widgets/cs-program-editor";
|
|
3
3
|
import DefinitionEditor from "./widgets/definition-editor";
|
|
4
|
+
import DeprecatedStandinEditor from "./widgets/deprecated-standin-editor";
|
|
4
5
|
import DropdownEditor from "./widgets/dropdown-editor";
|
|
5
6
|
import ExampleGraphieWidgetEditor from "./widgets/example-graphie-widget-editor";
|
|
6
7
|
import ExampleWidgetEditor from "./widgets/example-widget-editor";
|
|
@@ -80,4 +81,5 @@ export default [
|
|
|
80
81
|
UnitEditor,
|
|
81
82
|
VideoEditor,
|
|
82
83
|
RadioEditor,
|
|
84
|
+
DeprecatedStandinEditor,
|
|
83
85
|
];
|
|
@@ -10,33 +10,33 @@ import _ from "underscore";
|
|
|
10
10
|
|
|
11
11
|
import SectionControlButton from "./section-control-button";
|
|
12
12
|
|
|
13
|
-
import type {Alignment,
|
|
13
|
+
import type {Alignment, PerseusWidget} from "@khanacademy/perseus";
|
|
14
14
|
|
|
15
|
-
const {InlineIcon
|
|
15
|
+
const {InlineIcon} = components;
|
|
16
16
|
const {iconChevronDown, iconChevronRight, iconTrash} = icons;
|
|
17
17
|
|
|
18
18
|
type WidgetEditorProps = {
|
|
19
19
|
// Unserialized props
|
|
20
20
|
id: string;
|
|
21
21
|
onChange: (
|
|
22
|
-
widgetInfo:
|
|
22
|
+
widgetInfo: PerseusWidget,
|
|
23
23
|
cb?: () => unknown,
|
|
24
24
|
silent?: boolean,
|
|
25
25
|
) => unknown;
|
|
26
26
|
onRemove: () => unknown;
|
|
27
27
|
apiOptions: any;
|
|
28
|
-
} &
|
|
28
|
+
} & PerseusWidget;
|
|
29
29
|
|
|
30
30
|
type WidgetEditorState = {
|
|
31
31
|
showWidget: boolean;
|
|
32
|
-
widgetInfo:
|
|
32
|
+
widgetInfo: PerseusWidget;
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
const _upgradeWidgetInfo = (props: WidgetEditorProps):
|
|
35
|
+
const _upgradeWidgetInfo = (props: WidgetEditorProps): PerseusWidget => {
|
|
36
36
|
// We can't call serialize here because this.refs.widget
|
|
37
37
|
// doesn't exist before this component is mounted.
|
|
38
38
|
const filteredProps = _.omit(props, WIDGET_PROP_DENYLIST);
|
|
39
|
-
// @ts-expect-error
|
|
39
|
+
// @ts-expect-error TS(2345) Type '"categorizer" | undefined' is not assignable to type '"deprecated-standin"'.
|
|
40
40
|
return Widgets.upgradeWidgetInfoToLatestVersion(filteredProps);
|
|
41
41
|
};
|
|
42
42
|
|
|
@@ -53,14 +53,12 @@ class WidgetEditor extends React.Component<
|
|
|
53
53
|
super(props);
|
|
54
54
|
this.state = {
|
|
55
55
|
showWidget: false,
|
|
56
|
-
// @ts-expect-error - TS2322 - Type 'ReactElement<any, any> | null' is not assignable to type 'PerseusWidget'.
|
|
57
56
|
widgetInfo: _upgradeWidgetInfo(props),
|
|
58
57
|
};
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
// eslint-disable-next-line react/no-unsafe
|
|
62
61
|
UNSAFE_componentWillReceiveProps(nextProps: WidgetEditorProps) {
|
|
63
|
-
// @ts-expect-error - TS2322 - Type 'ReactElement<any, any> | null' is not assignable to type 'PerseusWidget'.
|
|
64
62
|
this.setState({widgetInfo: _upgradeWidgetInfo(nextProps)});
|
|
65
63
|
}
|
|
66
64
|
|
|
@@ -77,7 +75,7 @@ class WidgetEditor extends React.Component<
|
|
|
77
75
|
const newWidgetInfo = Object.assign(
|
|
78
76
|
{},
|
|
79
77
|
this.state.widgetInfo,
|
|
80
|
-
) as
|
|
78
|
+
) as PerseusWidget;
|
|
81
79
|
newWidgetInfo.options = Object.assign(
|
|
82
80
|
// eslint-disable-next-line react/no-string-refs
|
|
83
81
|
// @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
|
|
@@ -91,7 +89,7 @@ class WidgetEditor extends React.Component<
|
|
|
91
89
|
e.preventDefault();
|
|
92
90
|
const newWidgetInfo = Object.assign({}, this.state.widgetInfo, {
|
|
93
91
|
static: !this.state.widgetInfo.static,
|
|
94
|
-
}) as
|
|
92
|
+
}) as PerseusWidget;
|
|
95
93
|
this.props.onChange(newWidgetInfo);
|
|
96
94
|
};
|
|
97
95
|
|
|
@@ -100,7 +98,7 @@ class WidgetEditor extends React.Component<
|
|
|
100
98
|
const newWidgetInfo = Object.assign(
|
|
101
99
|
{},
|
|
102
100
|
this.state.widgetInfo,
|
|
103
|
-
) as
|
|
101
|
+
) as PerseusWidget;
|
|
104
102
|
newWidgetInfo.alignment = newAlignment;
|
|
105
103
|
this.props.onChange(newWidgetInfo);
|
|
106
104
|
};
|
|
@@ -145,15 +143,6 @@ class WidgetEditor extends React.Component<
|
|
|
145
143
|
|
|
146
144
|
const supportsStaticMode = Widgets.supportsStaticMode(widgetInfo.type);
|
|
147
145
|
|
|
148
|
-
const isUngradedEnabled = widgetInfo.type === "transformer";
|
|
149
|
-
const gradedPropBox = (
|
|
150
|
-
<PropCheckBox
|
|
151
|
-
label="Graded:"
|
|
152
|
-
graded={widgetInfo.graded}
|
|
153
|
-
onChange={this.props.onChange}
|
|
154
|
-
/>
|
|
155
|
-
);
|
|
156
|
-
|
|
157
146
|
return (
|
|
158
147
|
<div className="perseus-widget-editor">
|
|
159
148
|
<div
|
|
@@ -214,7 +203,6 @@ class WidgetEditor extends React.Component<
|
|
|
214
203
|
(this.state.showWidget ? "enter" : "leave")
|
|
215
204
|
}
|
|
216
205
|
>
|
|
217
|
-
{isUngradedEnabled && gradedPropBox}
|
|
218
206
|
{Ed && (
|
|
219
207
|
<Ed
|
|
220
208
|
// eslint-disable-next-line react/no-string-refs
|
package/src/editor.tsx
CHANGED
|
@@ -25,7 +25,7 @@ import WidgetEditor from "./components/widget-editor";
|
|
|
25
25
|
import WidgetSelect from "./components/widget-select";
|
|
26
26
|
import TexErrorView from "./tex-error-view";
|
|
27
27
|
|
|
28
|
-
import type {ChangeHandler,
|
|
28
|
+
import type {ChangeHandler, PerseusWidget} from "@khanacademy/perseus";
|
|
29
29
|
|
|
30
30
|
// like [[snowman input-number 1]]
|
|
31
31
|
const widgetPlaceholder = "[[\u2603 {id}]]";
|
|
@@ -114,7 +114,7 @@ type Props = Readonly<{
|
|
|
114
114
|
replace?: any;
|
|
115
115
|
placeholder: string;
|
|
116
116
|
widgets: {
|
|
117
|
-
[name: string]:
|
|
117
|
+
[name: string]: PerseusWidget;
|
|
118
118
|
};
|
|
119
119
|
images: any;
|
|
120
120
|
disabled: boolean;
|
|
@@ -141,7 +141,7 @@ type DefaultProps = {
|
|
|
141
141
|
warnNoWidgets: boolean;
|
|
142
142
|
widgetEnabled: boolean;
|
|
143
143
|
widgets: {
|
|
144
|
-
[name: string]:
|
|
144
|
+
[name: string]: PerseusWidget;
|
|
145
145
|
};
|
|
146
146
|
};
|
|
147
147
|
|
|
@@ -245,37 +245,35 @@ class Editor extends React.Component<Props, State> {
|
|
|
245
245
|
clearTimeout(this.deferredChange);
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
getWidgetEditor
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
);
|
|
269
|
-
};
|
|
248
|
+
getWidgetEditor(
|
|
249
|
+
id: string,
|
|
250
|
+
type: PerseusWidget["type"],
|
|
251
|
+
): undefined | React.ReactNode {
|
|
252
|
+
if (!Widgets.getEditor(type)) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
return (
|
|
256
|
+
<WidgetEditor
|
|
257
|
+
ref={id}
|
|
258
|
+
id={id}
|
|
259
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
260
|
+
onChange={this._handleWidgetEditorChange.bind(this, id)}
|
|
261
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
262
|
+
onRemove={this._handleWidgetEditorRemove.bind(this, id)}
|
|
263
|
+
apiOptions={this.props.apiOptions}
|
|
264
|
+
{...this.props.widgets[id]}
|
|
265
|
+
/>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
270
268
|
|
|
271
269
|
_handleWidgetEditorChange: (
|
|
272
270
|
id: string,
|
|
273
|
-
newWidgetInfo:
|
|
271
|
+
newWidgetInfo: PerseusWidget,
|
|
274
272
|
cb?: () => unknown,
|
|
275
273
|
silent?: boolean,
|
|
276
274
|
) => void = (
|
|
277
275
|
id: string,
|
|
278
|
-
newWidgetInfo:
|
|
276
|
+
newWidgetInfo: PerseusWidget,
|
|
279
277
|
cb?: () => unknown,
|
|
280
278
|
silent?: boolean,
|
|
281
279
|
) => {
|
|
@@ -685,14 +683,13 @@ class Editor extends React.Component<Props, State> {
|
|
|
685
683
|
const newContent = newPrelude + widgetContent + newPostlude;
|
|
686
684
|
|
|
687
685
|
const newWidgets = _.clone(this.props.widgets);
|
|
686
|
+
// @ts-expect-error TS(2345) Type '"categorizer" | undefined' is not assignable to type '"deprecated-standin"'.
|
|
688
687
|
newWidgets[id] = {
|
|
689
688
|
options: Widgets.getEditor(widgetType)?.defaultProps,
|
|
690
|
-
|
|
691
|
-
type: widgetType,
|
|
689
|
+
type: widgetType as PerseusWidget["type"],
|
|
692
690
|
// Track widget version on creation, so that a widget editor
|
|
693
691
|
// without a valid version prop can only possibly refer to a
|
|
694
692
|
// pre-versioning creation time.
|
|
695
|
-
// @ts-expect-error - TS2322 - Type 'Version | null | undefined' is not assignable to type 'Version | undefined'.
|
|
696
693
|
version: Widgets.getVersion(widgetType),
|
|
697
694
|
};
|
|
698
695
|
|
|
@@ -940,7 +937,7 @@ class Editor extends React.Component<Props, State> {
|
|
|
940
937
|
const match = Util.rWidgetParts.exec(pieces[i]);
|
|
941
938
|
if (match != null) {
|
|
942
939
|
const id = match[1];
|
|
943
|
-
const type = match[2];
|
|
940
|
+
const type = match[2] as PerseusWidget["type"];
|
|
944
941
|
|
|
945
942
|
const selected = false;
|
|
946
943
|
// TODO(alpert):
|
package/src/index.ts
CHANGED
|
@@ -24,4 +24,8 @@ import AllWidgets from "./all-widgets";
|
|
|
24
24
|
Widgets.registerEditors(AllEditors);
|
|
25
25
|
Widgets.registerWidgets(AllWidgets);
|
|
26
26
|
|
|
27
|
+
// When it's time to ship transformer's deprecation uncomment
|
|
28
|
+
// Widgets.replaceEditor("transformer", "deprecated-standin");
|
|
29
|
+
// Widgets.replaceWidget("transformer", "deprecatd-standin");
|
|
30
|
+
|
|
27
31
|
export {AllEditors, AllWidgets};
|
|
@@ -11,4 +11,8 @@ import allWidgets from "../all-widgets";
|
|
|
11
11
|
export const registerAllWidgetsAndEditorsForTesting = () => {
|
|
12
12
|
Widgets.registerWidgets(allWidgets);
|
|
13
13
|
Widgets.registerEditors(allEditors);
|
|
14
|
+
|
|
15
|
+
// When it's time to ship transformer's deprecation uncomment
|
|
16
|
+
// Widgets.replaceEditor("transformer", "deprecated-standin");
|
|
17
|
+
// Widgets.replaceWidget("transformer", "deprecatd-standin");
|
|
14
18
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {EditorJsonify} from "@khanacademy/perseus";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
// Callback for when a widget prop is changed.
|
|
6
|
+
onChange: (options: any) => void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
class DeprecatedStandinEditor extends React.Component<Props> {
|
|
10
|
+
static widgetName = "deprecated-standin" as const;
|
|
11
|
+
|
|
12
|
+
serialize(): any {
|
|
13
|
+
return EditorJsonify.serialize.call(this);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
render(): React.ReactNode {
|
|
17
|
+
return (
|
|
18
|
+
<div>
|
|
19
|
+
<p>This widget has been deprecated and removed</p>
|
|
20
|
+
<p>
|
|
21
|
+
Learners will see a message and they will not be graded on
|
|
22
|
+
this part. Please replace this widget with a supported one.
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default DeprecatedStandinEditor;
|