@khanacademy/perseus-editor 2.6.7 → 2.7.1
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 +27 -0
- package/dist/es/index.css +3 -0
- package/dist/es/index.js +18 -49
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +3 -0
- package/dist/index.js +29 -65
- package/dist/index.js.map +1 -1
- package/dist/widgets/expression-editor.d.ts +19 -17
- package/package.json +4 -2
- package/src/styles/perseus-editor.less +5 -0
- package/src/widgets/__stories__/expression-editor.stories.tsx +1 -2
- package/src/widgets/expression-editor.tsx +78 -79
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/index.css
CHANGED
|
@@ -191,6 +191,9 @@
|
|
|
191
191
|
#perseus #problemarea #workarea {
|
|
192
192
|
margin: 0;
|
|
193
193
|
}
|
|
194
|
+
#perseus #problemarea #workarea .perseus-image-caption {
|
|
195
|
+
top: 0px !important;
|
|
196
|
+
}
|
|
194
197
|
#perseus .perseus-question-container > div,
|
|
195
198
|
#perseus .perseus-answer-container > div {
|
|
196
199
|
padding-bottom: 25px;
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var ReactDOM = require('react-dom');
|
|
|
15
15
|
var classNames = require('classnames');
|
|
16
16
|
var kmath = require('@khanacademy/kmath');
|
|
17
17
|
var KAS = require('@khanacademy/kas');
|
|
18
|
+
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
18
19
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
19
20
|
var Spacing = require('@khanacademy/wonder-blocks-spacing');
|
|
20
21
|
var Typography = require('@khanacademy/wonder-blocks-typography');
|
|
@@ -26808,13 +26809,6 @@ const {
|
|
|
26808
26809
|
const {
|
|
26809
26810
|
getDependencies: getDependencies$2
|
|
26810
26811
|
} = perseus.Dependencies;
|
|
26811
|
-
const answerFormType = PropTypes__default["default"].shape({
|
|
26812
|
-
considered: PropTypes__default["default"].oneOf(perseus.PerseusExpressionAnswerFormConsidered).isRequired,
|
|
26813
|
-
value: PropTypes__default["default"].string.isRequired,
|
|
26814
|
-
form: PropTypes__default["default"].bool.isRequired,
|
|
26815
|
-
simplify: PropTypes__default["default"].bool.isRequired
|
|
26816
|
-
});
|
|
26817
|
-
|
|
26818
26812
|
// Pick a key that isn't currently used by an answer in answerForms
|
|
26819
26813
|
const _makeNewKey = answerForms => {
|
|
26820
26814
|
// first note all the currently used keys in an array, used like a map :3
|
|
@@ -26838,15 +26832,12 @@ const _makeNewKey = answerForms => {
|
|
|
26838
26832
|
};
|
|
26839
26833
|
class ExpressionEditor extends React__namespace.Component {
|
|
26840
26834
|
constructor(_props) {
|
|
26841
|
-
var _this;
|
|
26842
26835
|
super(_props);
|
|
26843
|
-
|
|
26844
|
-
|
|
26845
|
-
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
return perseus.Changeable.change.apply(_this, args);
|
|
26849
|
-
});
|
|
26836
|
+
// Is the format of `value` TeX or plain text?
|
|
26837
|
+
// TODO(alex): Remove after backfilling everything to TeX
|
|
26838
|
+
// TODO(joel) - sucks if you edit some expression without
|
|
26839
|
+
// backslashes or curly braces, then come back to the question and
|
|
26840
|
+
// it's surprisingly not TeX anymore.
|
|
26850
26841
|
_defineProperty(this, "serialize", () => {
|
|
26851
26842
|
const formSerializables = ["value", "form", "simplify", "considered",
|
|
26852
26843
|
// it's a little weird to serialize the react key, but saves some
|
|
@@ -26863,7 +26854,7 @@ class ExpressionEditor extends React__namespace.Component {
|
|
|
26863
26854
|
if (this.props.answerForms.length === 0) {
|
|
26864
26855
|
issues.push("No answers specified");
|
|
26865
26856
|
} else {
|
|
26866
|
-
const hasCorrect =
|
|
26857
|
+
const hasCorrect = this.props.answerForms.some(form => {
|
|
26867
26858
|
return form.considered === "correct";
|
|
26868
26859
|
});
|
|
26869
26860
|
if (!hasCorrect) {
|
|
@@ -26907,7 +26898,6 @@ class ExpressionEditor extends React__namespace.Component {
|
|
|
26907
26898
|
_defineProperty(this, "newAnswer", () => {
|
|
26908
26899
|
const answerForms = this.props.answerForms.slice();
|
|
26909
26900
|
answerForms.push(this._newEmptyAnswerForm());
|
|
26910
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26911
26901
|
this.change({
|
|
26912
26902
|
answerForms
|
|
26913
26903
|
});
|
|
@@ -26915,39 +26905,34 @@ class ExpressionEditor extends React__namespace.Component {
|
|
|
26915
26905
|
_defineProperty(this, "handleRemoveForm", i => {
|
|
26916
26906
|
const answerForms = this.props.answerForms.slice();
|
|
26917
26907
|
answerForms.splice(i, 1);
|
|
26918
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26919
26908
|
this.change({
|
|
26920
26909
|
answerForms
|
|
26921
26910
|
});
|
|
26922
26911
|
});
|
|
26923
26912
|
_defineProperty(this, "updateForm", (i, props) => {
|
|
26924
26913
|
const answerForms = lens(this.props.answerForms).merge([i], props).freeze();
|
|
26925
|
-
|
|
26926
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26927
26914
|
this.change({
|
|
26928
26915
|
answerForms
|
|
26929
26916
|
});
|
|
26930
26917
|
});
|
|
26931
26918
|
_defineProperty(this, "handleReorder", components => {
|
|
26932
|
-
const answerForms =
|
|
26919
|
+
const answerForms = components.map(component => {
|
|
26933
26920
|
const form = ___default["default"](component.props).pick("considered", "form", "simplify", "value");
|
|
26934
26921
|
// @ts-expect-error - TS2339 - Property 'key' does not exist on type 'Pick<any, "form" | "value" | "simplify" | "considered">'.
|
|
26935
26922
|
form.key = component.key;
|
|
26936
26923
|
return form;
|
|
26937
26924
|
});
|
|
26938
|
-
|
|
26939
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26940
26925
|
this.change({
|
|
26941
26926
|
answerForms
|
|
26942
26927
|
});
|
|
26943
26928
|
});
|
|
26944
26929
|
_defineProperty(this, "handleButtonSet", changingName => {
|
|
26945
|
-
const buttonSetNames =
|
|
26930
|
+
const buttonSetNames = Object.keys(TexButtons.buttonSets);
|
|
26946
26931
|
|
|
26947
26932
|
// Filter to preserve order - using .union and .difference would always
|
|
26948
26933
|
// move the last added button set to the end.
|
|
26949
|
-
const buttonSets =
|
|
26950
|
-
return
|
|
26934
|
+
const buttonSets = buttonSetNames.filter(set => {
|
|
26935
|
+
return this.props.buttonSets.includes(set) !== (set === changingName);
|
|
26951
26936
|
});
|
|
26952
26937
|
this.props.onChange({
|
|
26953
26938
|
buttonSets
|
|
@@ -26958,17 +26943,16 @@ class ExpressionEditor extends React__namespace.Component {
|
|
|
26958
26943
|
// "basic+div". Toggle between the two of them.
|
|
26959
26944
|
// If someone can think of a more elegant formulation of this (there
|
|
26960
26945
|
// must be one!) feel free to change it.
|
|
26961
|
-
let keep
|
|
26962
|
-
|
|
26946
|
+
let keep;
|
|
26947
|
+
let remove;
|
|
26948
|
+
if (this.props.buttonSets.includes("basic+div")) {
|
|
26963
26949
|
keep = "basic";
|
|
26964
26950
|
remove = "basic+div";
|
|
26965
26951
|
} else {
|
|
26966
26952
|
keep = "basic+div";
|
|
26967
26953
|
remove = "basic";
|
|
26968
26954
|
}
|
|
26969
|
-
const buttonSets =
|
|
26970
|
-
|
|
26971
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 2.
|
|
26955
|
+
const buttonSets = this.props.buttonSets.filter(set => set !== remove).concat(keep);
|
|
26972
26956
|
this.change("buttonSets", buttonSets);
|
|
26973
26957
|
});
|
|
26974
26958
|
_defineProperty(this, "handleTexInsert", str => {
|
|
@@ -26978,32 +26962,32 @@ class ExpressionEditor extends React__namespace.Component {
|
|
|
26978
26962
|
});
|
|
26979
26963
|
_defineProperty(this, "handleFunctions", e => {
|
|
26980
26964
|
const newProps = {};
|
|
26981
|
-
newProps.functions =
|
|
26965
|
+
newProps.functions = e.target.value.split(/[ ,]+/).filter(wonderStuffCore.isTruthy);
|
|
26982
26966
|
this.props.onChange(newProps);
|
|
26983
26967
|
});
|
|
26984
|
-
// Is the format of `value` TeX or plain text?
|
|
26985
|
-
// TODO(alex): Remove after backfilling everything to TeX
|
|
26986
|
-
// TODO(joel) - sucks if you edit some expression without
|
|
26987
|
-
// backslashes or curly braces, then come back to the question and
|
|
26988
|
-
// it's surprisingly not TeX anymore.
|
|
26989
|
-
|
|
26990
26968
|
let isTex;
|
|
26991
26969
|
// default to TeX if new;
|
|
26992
26970
|
if (_props.answerForms.length === 0) {
|
|
26993
26971
|
isTex = true;
|
|
26994
26972
|
} else {
|
|
26995
|
-
isTex =
|
|
26973
|
+
isTex = _props.answerForms.some(form => {
|
|
26996
26974
|
const {
|
|
26997
26975
|
value
|
|
26998
26976
|
} = form;
|
|
26999
26977
|
// only TeX has backslashes and curly braces
|
|
27000
|
-
return
|
|
26978
|
+
return value.indexOf("\\") !== -1 || value.indexOf("{") !== -1;
|
|
27001
26979
|
});
|
|
27002
26980
|
}
|
|
27003
26981
|
this.state = {
|
|
27004
26982
|
isTex
|
|
27005
26983
|
};
|
|
27006
26984
|
}
|
|
26985
|
+
change() {
|
|
26986
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
26987
|
+
args[_key] = arguments[_key];
|
|
26988
|
+
}
|
|
26989
|
+
return perseus.Changeable.change.apply(this, args);
|
|
26990
|
+
}
|
|
27007
26991
|
render() {
|
|
27008
26992
|
const answerOptions = this.props.answerForms.map((obj, index) => {
|
|
27009
26993
|
const expressionProps = {
|
|
@@ -27037,11 +27021,11 @@ class ExpressionEditor extends React__namespace.Component {
|
|
|
27037
27021
|
});
|
|
27038
27022
|
|
|
27039
27023
|
// checkboxes to choose which sets of input buttons are shown
|
|
27040
|
-
const buttonSetChoices =
|
|
27024
|
+
const buttonSetChoices = Object.keys(TexButtons.buttonSets).map(name => {
|
|
27041
27025
|
// The first one gets special cased to always be checked, disabled,
|
|
27042
27026
|
// and float left.
|
|
27043
27027
|
const isFirst = name === "basic";
|
|
27044
|
-
const checked =
|
|
27028
|
+
const checked = this.props.buttonSets.includes(name) || isFirst;
|
|
27045
27029
|
const className = isFirst ? "button-set-label-float" : "button-set-label";
|
|
27046
27030
|
return /*#__PURE__*/React__namespace.createElement("label", {
|
|
27047
27031
|
className: className,
|
|
@@ -27101,13 +27085,6 @@ class ExpressionEditor extends React__namespace.Component {
|
|
|
27101
27085
|
}
|
|
27102
27086
|
|
|
27103
27087
|
// Find the next element in arr after val, wrapping around to the first.
|
|
27104
|
-
_defineProperty(ExpressionEditor, "propTypes", {
|
|
27105
|
-
...perseus.Changeable.propTypes,
|
|
27106
|
-
answerForms: PropTypes__default["default"].arrayOf(answerFormType),
|
|
27107
|
-
times: PropTypes__default["default"].bool,
|
|
27108
|
-
buttonSets: TexButtons.buttonSetsType,
|
|
27109
|
-
functions: PropTypes__default["default"].arrayOf(PropTypes__default["default"].string)
|
|
27110
|
-
});
|
|
27111
27088
|
_defineProperty(ExpressionEditor, "widgetName", "expression");
|
|
27112
27089
|
_defineProperty(ExpressionEditor, "defaultProps", {
|
|
27113
27090
|
answerForms: [],
|
|
@@ -27122,9 +27099,9 @@ const findNextIn = function (arr, val) {
|
|
|
27122
27099
|
};
|
|
27123
27100
|
class AnswerOption extends React__namespace.Component {
|
|
27124
27101
|
constructor() {
|
|
27125
|
-
var
|
|
27102
|
+
var _this;
|
|
27126
27103
|
super(...arguments);
|
|
27127
|
-
|
|
27104
|
+
_this = this;
|
|
27128
27105
|
_defineProperty(this, "state", {
|
|
27129
27106
|
deleteFocused: false
|
|
27130
27107
|
});
|
|
@@ -27137,7 +27114,7 @@ class AnswerOption extends React__namespace.Component {
|
|
|
27137
27114
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
27138
27115
|
args[_key2] = arguments[_key2];
|
|
27139
27116
|
}
|
|
27140
|
-
return perseus.Changeable.change.apply(
|
|
27117
|
+
return perseus.Changeable.change.apply(_this, args);
|
|
27141
27118
|
});
|
|
27142
27119
|
_defineProperty(this, "handleImSure", () => {
|
|
27143
27120
|
this.props.onDelete();
|
|
@@ -27157,7 +27134,6 @@ class AnswerOption extends React__namespace.Component {
|
|
|
27157
27134
|
render() {
|
|
27158
27135
|
let removeButton = null;
|
|
27159
27136
|
if (this.state.deleteFocused) {
|
|
27160
|
-
// @ts-expect-error - TS2322 - Type 'Element' is not assignable to type 'null'.
|
|
27161
27137
|
removeButton = /*#__PURE__*/React__namespace.createElement("button", {
|
|
27162
27138
|
type: "button",
|
|
27163
27139
|
className: "simple-button orange",
|
|
@@ -27165,7 +27141,6 @@ class AnswerOption extends React__namespace.Component {
|
|
|
27165
27141
|
onBlur: this.handleDeleteBlur
|
|
27166
27142
|
}, "I'm sure!");
|
|
27167
27143
|
} else {
|
|
27168
|
-
// @ts-expect-error - TS2322 - Type 'Element' is not assignable to type 'null'.
|
|
27169
27144
|
removeButton = /*#__PURE__*/React__namespace.createElement("button", {
|
|
27170
27145
|
type: "button",
|
|
27171
27146
|
className: "simple-button orange",
|
|
@@ -27204,17 +27179,6 @@ class AnswerOption extends React__namespace.Component {
|
|
|
27204
27179
|
}, removeButton)));
|
|
27205
27180
|
}
|
|
27206
27181
|
}
|
|
27207
|
-
_defineProperty(AnswerOption, "propTypes", {
|
|
27208
|
-
...perseus.Changeable.propTypes,
|
|
27209
|
-
considered: PropTypes__default["default"].oneOf(perseus.PerseusExpressionAnswerFormConsidered).isRequired,
|
|
27210
|
-
expressionProps: PropTypes__default["default"].object.isRequired,
|
|
27211
|
-
// Must the answer have the same form as this answer.
|
|
27212
|
-
form: PropTypes__default["default"].bool.isRequired,
|
|
27213
|
-
// Must the answer be simplified.
|
|
27214
|
-
simplify: PropTypes__default["default"].bool.isRequired,
|
|
27215
|
-
onChange: PropTypes__default["default"].func.isRequired,
|
|
27216
|
-
onDelete: PropTypes__default["default"].func.isRequired
|
|
27217
|
-
});
|
|
27218
27182
|
|
|
27219
27183
|
const {
|
|
27220
27184
|
InlineIcon: InlineIcon$5,
|