@khanacademy/perseus-editor 2.6.8 → 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 +20 -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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @khanacademy/perseus-editor
|
|
2
2
|
|
|
3
|
+
## 2.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a383823d: Bump @khanacademy/wonder-stuff-core to v1.5.1 (which adds needed support for `isTruthy` helper function)
|
|
8
|
+
- Updated dependencies [a383823d]
|
|
9
|
+
- @khanacademy/perseus@11.2.1
|
|
10
|
+
|
|
11
|
+
## 2.7.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- 9ff8a575: Fix image widget caption styling
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [9ff8a575]
|
|
20
|
+
- Updated dependencies [1b618343]
|
|
21
|
+
- @khanacademy/perseus@11.2.0
|
|
22
|
+
|
|
3
23
|
## 2.6.8
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/es/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/es/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import ReactDOM__default from 'react-dom';
|
|
|
12
12
|
import classNames from 'classnames';
|
|
13
13
|
import { point, number, line, ray, vector } from '@khanacademy/kmath';
|
|
14
14
|
import * as KAS from '@khanacademy/kas';
|
|
15
|
+
import { isTruthy } from '@khanacademy/wonder-stuff-core';
|
|
15
16
|
import { View } from '@khanacademy/wonder-blocks-core';
|
|
16
17
|
import Spacing from '@khanacademy/wonder-blocks-spacing';
|
|
17
18
|
import * as Typography from '@khanacademy/wonder-blocks-typography';
|
|
@@ -26733,13 +26734,6 @@ const {
|
|
|
26733
26734
|
const {
|
|
26734
26735
|
getDependencies: getDependencies$2
|
|
26735
26736
|
} = Dependencies;
|
|
26736
|
-
const answerFormType = PropTypes.shape({
|
|
26737
|
-
considered: PropTypes.oneOf(PerseusExpressionAnswerFormConsidered).isRequired,
|
|
26738
|
-
value: PropTypes.string.isRequired,
|
|
26739
|
-
form: PropTypes.bool.isRequired,
|
|
26740
|
-
simplify: PropTypes.bool.isRequired
|
|
26741
|
-
});
|
|
26742
|
-
|
|
26743
26737
|
// Pick a key that isn't currently used by an answer in answerForms
|
|
26744
26738
|
const _makeNewKey = answerForms => {
|
|
26745
26739
|
// first note all the currently used keys in an array, used like a map :3
|
|
@@ -26769,9 +26763,6 @@ class ExpressionEditor extends React.Component {
|
|
|
26769
26763
|
// TODO(joel) - sucks if you edit some expression without
|
|
26770
26764
|
// backslashes or curly braces, then come back to the question and
|
|
26771
26765
|
// it's surprisingly not TeX anymore.
|
|
26772
|
-
this.change = (...args) => {
|
|
26773
|
-
return Changeable.change.apply(this, args);
|
|
26774
|
-
};
|
|
26775
26766
|
this.serialize = () => {
|
|
26776
26767
|
const formSerializables = ["value", "form", "simplify", "considered",
|
|
26777
26768
|
// it's a little weird to serialize the react key, but saves some
|
|
@@ -26788,7 +26779,7 @@ class ExpressionEditor extends React.Component {
|
|
|
26788
26779
|
if (this.props.answerForms.length === 0) {
|
|
26789
26780
|
issues.push("No answers specified");
|
|
26790
26781
|
} else {
|
|
26791
|
-
const hasCorrect =
|
|
26782
|
+
const hasCorrect = this.props.answerForms.some(form => {
|
|
26792
26783
|
return form.considered === "correct";
|
|
26793
26784
|
});
|
|
26794
26785
|
if (!hasCorrect) {
|
|
@@ -26833,7 +26824,6 @@ class ExpressionEditor extends React.Component {
|
|
|
26833
26824
|
this.newAnswer = () => {
|
|
26834
26825
|
const answerForms = this.props.answerForms.slice();
|
|
26835
26826
|
answerForms.push(this._newEmptyAnswerForm());
|
|
26836
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26837
26827
|
this.change({
|
|
26838
26828
|
answerForms
|
|
26839
26829
|
});
|
|
@@ -26841,39 +26831,34 @@ class ExpressionEditor extends React.Component {
|
|
|
26841
26831
|
this.handleRemoveForm = i => {
|
|
26842
26832
|
const answerForms = this.props.answerForms.slice();
|
|
26843
26833
|
answerForms.splice(i, 1);
|
|
26844
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26845
26834
|
this.change({
|
|
26846
26835
|
answerForms
|
|
26847
26836
|
});
|
|
26848
26837
|
};
|
|
26849
26838
|
this.updateForm = (i, props) => {
|
|
26850
26839
|
const answerForms = lens(this.props.answerForms).merge([i], props).freeze();
|
|
26851
|
-
|
|
26852
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26853
26840
|
this.change({
|
|
26854
26841
|
answerForms
|
|
26855
26842
|
});
|
|
26856
26843
|
};
|
|
26857
26844
|
this.handleReorder = components => {
|
|
26858
|
-
const answerForms =
|
|
26845
|
+
const answerForms = components.map(component => {
|
|
26859
26846
|
const form = _(component.props).pick("considered", "form", "simplify", "value");
|
|
26860
26847
|
// @ts-expect-error - TS2339 - Property 'key' does not exist on type 'Pick<any, "form" | "value" | "simplify" | "considered">'.
|
|
26861
26848
|
form.key = component.key;
|
|
26862
26849
|
return form;
|
|
26863
26850
|
});
|
|
26864
|
-
|
|
26865
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
|
|
26866
26851
|
this.change({
|
|
26867
26852
|
answerForms
|
|
26868
26853
|
});
|
|
26869
26854
|
};
|
|
26870
26855
|
this.handleButtonSet = changingName => {
|
|
26871
|
-
const buttonSetNames =
|
|
26856
|
+
const buttonSetNames = Object.keys(TexButtons.buttonSets);
|
|
26872
26857
|
|
|
26873
26858
|
// Filter to preserve order - using .union and .difference would always
|
|
26874
26859
|
// move the last added button set to the end.
|
|
26875
|
-
const buttonSets =
|
|
26876
|
-
return
|
|
26860
|
+
const buttonSets = buttonSetNames.filter(set => {
|
|
26861
|
+
return this.props.buttonSets.includes(set) !== (set === changingName);
|
|
26877
26862
|
});
|
|
26878
26863
|
this.props.onChange({
|
|
26879
26864
|
buttonSets
|
|
@@ -26884,17 +26869,16 @@ class ExpressionEditor extends React.Component {
|
|
|
26884
26869
|
// "basic+div". Toggle between the two of them.
|
|
26885
26870
|
// If someone can think of a more elegant formulation of this (there
|
|
26886
26871
|
// must be one!) feel free to change it.
|
|
26887
|
-
let keep
|
|
26888
|
-
|
|
26872
|
+
let keep;
|
|
26873
|
+
let remove;
|
|
26874
|
+
if (this.props.buttonSets.includes("basic+div")) {
|
|
26889
26875
|
keep = "basic";
|
|
26890
26876
|
remove = "basic+div";
|
|
26891
26877
|
} else {
|
|
26892
26878
|
keep = "basic+div";
|
|
26893
26879
|
remove = "basic";
|
|
26894
26880
|
}
|
|
26895
|
-
const buttonSets =
|
|
26896
|
-
|
|
26897
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 2.
|
|
26881
|
+
const buttonSets = this.props.buttonSets.filter(set => set !== remove).concat(keep);
|
|
26898
26882
|
this.change("buttonSets", buttonSets);
|
|
26899
26883
|
};
|
|
26900
26884
|
this.handleTexInsert = str => {
|
|
@@ -26904,7 +26888,7 @@ class ExpressionEditor extends React.Component {
|
|
|
26904
26888
|
};
|
|
26905
26889
|
this.handleFunctions = e => {
|
|
26906
26890
|
const newProps = {};
|
|
26907
|
-
newProps.functions =
|
|
26891
|
+
newProps.functions = e.target.value.split(/[ ,]+/).filter(isTruthy);
|
|
26908
26892
|
this.props.onChange(newProps);
|
|
26909
26893
|
};
|
|
26910
26894
|
let isTex;
|
|
@@ -26912,18 +26896,21 @@ class ExpressionEditor extends React.Component {
|
|
|
26912
26896
|
if (_props.answerForms.length === 0) {
|
|
26913
26897
|
isTex = true;
|
|
26914
26898
|
} else {
|
|
26915
|
-
isTex =
|
|
26899
|
+
isTex = _props.answerForms.some(form => {
|
|
26916
26900
|
const {
|
|
26917
26901
|
value
|
|
26918
26902
|
} = form;
|
|
26919
26903
|
// only TeX has backslashes and curly braces
|
|
26920
|
-
return
|
|
26904
|
+
return value.indexOf("\\") !== -1 || value.indexOf("{") !== -1;
|
|
26921
26905
|
});
|
|
26922
26906
|
}
|
|
26923
26907
|
this.state = {
|
|
26924
26908
|
isTex
|
|
26925
26909
|
};
|
|
26926
26910
|
}
|
|
26911
|
+
change(...args) {
|
|
26912
|
+
return Changeable.change.apply(this, args);
|
|
26913
|
+
}
|
|
26927
26914
|
render() {
|
|
26928
26915
|
const answerOptions = this.props.answerForms.map((obj, index) => {
|
|
26929
26916
|
const expressionProps = {
|
|
@@ -26957,11 +26944,11 @@ class ExpressionEditor extends React.Component {
|
|
|
26957
26944
|
});
|
|
26958
26945
|
|
|
26959
26946
|
// checkboxes to choose which sets of input buttons are shown
|
|
26960
|
-
const buttonSetChoices =
|
|
26947
|
+
const buttonSetChoices = Object.keys(TexButtons.buttonSets).map(name => {
|
|
26961
26948
|
// The first one gets special cased to always be checked, disabled,
|
|
26962
26949
|
// and float left.
|
|
26963
26950
|
const isFirst = name === "basic";
|
|
26964
|
-
const checked =
|
|
26951
|
+
const checked = this.props.buttonSets.includes(name) || isFirst;
|
|
26965
26952
|
const className = isFirst ? "button-set-label-float" : "button-set-label";
|
|
26966
26953
|
return /*#__PURE__*/React.createElement("label", {
|
|
26967
26954
|
className: className,
|
|
@@ -27021,12 +27008,6 @@ class ExpressionEditor extends React.Component {
|
|
|
27021
27008
|
}
|
|
27022
27009
|
|
|
27023
27010
|
// Find the next element in arr after val, wrapping around to the first.
|
|
27024
|
-
ExpressionEditor.propTypes = _extends({}, Changeable.propTypes, {
|
|
27025
|
-
answerForms: PropTypes.arrayOf(answerFormType),
|
|
27026
|
-
times: PropTypes.bool,
|
|
27027
|
-
buttonSets: TexButtons.buttonSetsType,
|
|
27028
|
-
functions: PropTypes.arrayOf(PropTypes.string)
|
|
27029
|
-
});
|
|
27030
27011
|
ExpressionEditor.widgetName = "expression";
|
|
27031
27012
|
ExpressionEditor.defaultProps = {
|
|
27032
27013
|
answerForms: [],
|
|
@@ -27071,7 +27052,6 @@ class AnswerOption extends React.Component {
|
|
|
27071
27052
|
render() {
|
|
27072
27053
|
let removeButton = null;
|
|
27073
27054
|
if (this.state.deleteFocused) {
|
|
27074
|
-
// @ts-expect-error - TS2322 - Type 'Element' is not assignable to type 'null'.
|
|
27075
27055
|
removeButton = /*#__PURE__*/React.createElement("button", {
|
|
27076
27056
|
type: "button",
|
|
27077
27057
|
className: "simple-button orange",
|
|
@@ -27079,7 +27059,6 @@ class AnswerOption extends React.Component {
|
|
|
27079
27059
|
onBlur: this.handleDeleteBlur
|
|
27080
27060
|
}, "I'm sure!");
|
|
27081
27061
|
} else {
|
|
27082
|
-
// @ts-expect-error - TS2322 - Type 'Element' is not assignable to type 'null'.
|
|
27083
27062
|
removeButton = /*#__PURE__*/React.createElement("button", {
|
|
27084
27063
|
type: "button",
|
|
27085
27064
|
className: "simple-button orange",
|
|
@@ -27118,16 +27097,6 @@ class AnswerOption extends React.Component {
|
|
|
27118
27097
|
}, removeButton)));
|
|
27119
27098
|
}
|
|
27120
27099
|
}
|
|
27121
|
-
AnswerOption.propTypes = _extends({}, Changeable.propTypes, {
|
|
27122
|
-
considered: PropTypes.oneOf(PerseusExpressionAnswerFormConsidered).isRequired,
|
|
27123
|
-
expressionProps: PropTypes.object.isRequired,
|
|
27124
|
-
// Must the answer have the same form as this answer.
|
|
27125
|
-
form: PropTypes.bool.isRequired,
|
|
27126
|
-
// Must the answer be simplified.
|
|
27127
|
-
simplify: PropTypes.bool.isRequired,
|
|
27128
|
-
onChange: PropTypes.func.isRequired,
|
|
27129
|
-
onDelete: PropTypes.func.isRequired
|
|
27130
|
-
});
|
|
27131
27100
|
|
|
27132
27101
|
const {
|
|
27133
27102
|
InlineIcon: InlineIcon$5,
|