@khanacademy/perseus 7.2.0 → 7.2.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 +12 -0
- package/dist/es/index.css +61 -61
- package/dist/es/index.js +50 -119
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +61 -61
- package/dist/index.js +39 -77
- package/dist/index.js.map +1 -1
- package/dist/widgets/plotter.d.ts +47 -13
- package/dist/widgets/plotter.js.flow +47 -13
- package/package.json +2 -2
- package/src/__tests__/item-renderer.test.tsx +1 -1
- package/src/components/__stories__/image-loader.stories.tsx +1 -0
- package/src/components/graph.tsx +1 -0
- package/src/components/icon.tsx +1 -0
- package/src/components/image-loader.tsx +1 -0
- package/src/components/number-input.tsx +1 -0
- package/src/components/sortable.tsx +1 -0
- package/src/components/svg-image.tsx +1 -0
- package/src/components/tex-buttons.tsx +1 -0
- package/src/components/text-input.tsx +1 -0
- package/src/components/text-list-editor.tsx +1 -0
- package/src/components/zoomable.tsx +1 -0
- package/src/hints-renderer.tsx +1 -0
- package/src/index.ts +1 -0
- package/src/item-renderer.tsx +1 -0
- package/src/mixins/provide-keypad.tsx +1 -0
- package/src/multi-items/multi-renderer.tsx +1 -0
- package/src/renderer.tsx +1 -0
- package/src/server-item-renderer.tsx +1 -0
- package/src/styles/articles.less +8 -4
- package/src/styles/perseus-renderer.less +47 -38
- package/src/styles/util.less +1 -1
- package/src/styles/variables.boostrap.less +158 -182
- package/src/styles/variables.less +20 -20
- package/src/styles/variables.shared.less +162 -168
- package/src/styles/widgets/categorizer.less +1 -2
- package/src/styles/widgets/expression.less +7 -4
- package/src/styles/widgets/grapher.less +2 -1
- package/src/styles/widgets/image.less +3 -2
- package/src/styles/widgets/interactive-graph.less +4 -2
- package/src/styles/widgets/label-image.less +2 -1
- package/src/styles/widgets/matrix.less +11 -7
- package/src/styles/widgets/orderer.less +2 -1
- package/src/styles/widgets/passage.less +2 -1
- package/src/styles/widgets/plotter.less +4 -3
- package/src/styles/widgets/radio.less +4 -2
- package/src/styles/widgets/sortable.less +1 -1
- package/src/styles/widgets/table.less +2 -1
- package/src/styles/widgets/transformer.less +2 -1
- package/src/styles/widgets/unit.less +2 -1
- package/src/widgets/__stories__/plotter.stories.tsx +27 -0
- package/src/widgets/__testdata__/plotter.testdata.ts +36 -0
- package/src/widgets/__tests__/__snapshots__/plotter.test.tsx.snap +863 -0
- package/src/widgets/__tests__/plotter.test.tsx +65 -0
- package/src/widgets/categorizer.tsx +1 -0
- package/src/widgets/graded-group-set.tsx +1 -0
- package/src/widgets/graded-group.tsx +1 -0
- package/src/widgets/interaction.tsx +1 -0
- package/src/widgets/label-image/marker.tsx +1 -0
- package/src/widgets/matcher.tsx +1 -0
- package/src/widgets/orderer.tsx +1 -0
- package/src/widgets/passage-ref-target.tsx +1 -0
- package/src/widgets/plotter.tsx +108 -98
- package/src/widgets/radio/base-radio.tsx +1 -0
- package/src/widgets/radio/choice-icon/choice-icon.tsx +1 -0
- package/src/widgets/sorter.tsx +1 -0
- package/src/widgets/transformer.tsx +1 -0
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/es/index.js
CHANGED
|
@@ -120,6 +120,7 @@ var dependencies = /*#__PURE__*/Object.freeze({
|
|
|
120
120
|
getDependencies: getDependencies
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
123
124
|
const prettyBig = {
|
|
124
125
|
fontSize: "150%"
|
|
125
126
|
};
|
|
@@ -1176,7 +1177,7 @@ var changeable = /*#__PURE__*/Object.freeze({
|
|
|
1176
1177
|
propTypes: propTypes
|
|
1177
1178
|
});
|
|
1178
1179
|
|
|
1179
|
-
/* eslint-disable @
|
|
1180
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
1180
1181
|
const textWidthCache = {};
|
|
1181
1182
|
function getTextWidth(text) {
|
|
1182
1183
|
if (!textWidthCache[text]) {
|
|
@@ -20691,7 +20692,7 @@ MathOutput.defaultProps = {
|
|
|
20691
20692
|
onBlur: function () {}
|
|
20692
20693
|
};
|
|
20693
20694
|
|
|
20694
|
-
/* eslint-disable
|
|
20695
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
20695
20696
|
let lastId = 0;
|
|
20696
20697
|
function uniqueIdForInput(prefix = "input-") {
|
|
20697
20698
|
lastId++;
|
|
@@ -22141,36 +22142,7 @@ const scrollElementIntoView = (element, callback) => {
|
|
|
22141
22142
|
}, 0);
|
|
22142
22143
|
};
|
|
22143
22144
|
|
|
22144
|
-
|
|
22145
|
-
* SVG Icon React Component
|
|
22146
|
-
*
|
|
22147
|
-
* This component is designed to take in SVG paths and render icons based upon
|
|
22148
|
-
* them. If you are looking for an icon that we've used before you should look
|
|
22149
|
-
* in `icon-paths.js` which is a reference file for all the SVG paths that
|
|
22150
|
-
* we've used. You'll need to copy the object from that file into whichever
|
|
22151
|
-
* file you're using the icon and explicitly pass it in to the <Icon/> React
|
|
22152
|
-
* component.
|
|
22153
|
-
*
|
|
22154
|
-
* Sample usage:
|
|
22155
|
-
*
|
|
22156
|
-
* const dropdownIcon = `M5,6L0,0L10,0`;
|
|
22157
|
-
* <Icon icon={dropdownIcon} />
|
|
22158
|
-
*
|
|
22159
|
-
* Or:
|
|
22160
|
-
*
|
|
22161
|
-
* const dropdownIcon = {
|
|
22162
|
-
* path: `M5,6L0,0L10,0`,
|
|
22163
|
-
* height: 10,
|
|
22164
|
-
* width: 10,
|
|
22165
|
-
* };
|
|
22166
|
-
* <Icon icon={dropdownIcon} size={20} />
|
|
22167
|
-
*
|
|
22168
|
-
* A full list of all the existing icons can be seen here:
|
|
22169
|
-
* http://localhost:8080/react-sandbox/shared-styles-package/icon.jsx.fixture.js
|
|
22170
|
-
*
|
|
22171
|
-
* If you want to add an entirely new icon please read the note inside
|
|
22172
|
-
* the `icon-paths.js` file.
|
|
22173
|
-
*/
|
|
22145
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
22174
22146
|
// WARNING: This determines the *viewport* width and height, so a change here
|
|
22175
22147
|
// requires scaling the values of every SVG path passed in as a string
|
|
22176
22148
|
// without corresponding `width` and `height` values.
|
|
@@ -23770,7 +23742,7 @@ const WidgetJsonifyDeprecated = {
|
|
|
23770
23742
|
}
|
|
23771
23743
|
};
|
|
23772
23744
|
|
|
23773
|
-
/* eslint-disable
|
|
23745
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
23774
23746
|
class Categorizer extends React.Component {
|
|
23775
23747
|
constructor(..._args) {
|
|
23776
23748
|
super(..._args);
|
|
@@ -26783,7 +26755,7 @@ var Image$1 = {
|
|
|
26783
26755
|
isLintable: true
|
|
26784
26756
|
};
|
|
26785
26757
|
|
|
26786
|
-
/* eslint-disable @
|
|
26758
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
26787
26759
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'Label' does not exist on type 'typeof Graphie'.
|
|
26788
26760
|
const Label$1 = Graphie.Label;
|
|
26789
26761
|
// @ts-expect-error [FEI-5003] - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
@@ -27385,7 +27357,7 @@ var Interactive = {
|
|
|
27385
27357
|
hidden: true
|
|
27386
27358
|
};
|
|
27387
27359
|
|
|
27388
|
-
/* eslint-disable
|
|
27360
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
27389
27361
|
const defaultBackgroundImage$2 = {
|
|
27390
27362
|
url: null
|
|
27391
27363
|
};
|
|
@@ -30921,11 +30893,7 @@ const styles$h = StyleSheet.create({
|
|
|
30921
30893
|
}
|
|
30922
30894
|
});
|
|
30923
30895
|
|
|
30924
|
-
|
|
30925
|
-
* Controlled question image marker, rendered as a styled button element.
|
|
30926
|
-
*
|
|
30927
|
-
* The target for labeling question image with answers.
|
|
30928
|
-
*/
|
|
30896
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
30929
30897
|
class Marker extends React.Component {
|
|
30930
30898
|
constructor(...args) {
|
|
30931
30899
|
super(...args);
|
|
@@ -32791,7 +32759,7 @@ const styles$e = StyleSheet.create({
|
|
|
32791
32759
|
}
|
|
32792
32760
|
});
|
|
32793
32761
|
|
|
32794
|
-
/* eslint-disable
|
|
32762
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
32795
32763
|
const {
|
|
32796
32764
|
shuffle: shuffle$1,
|
|
32797
32765
|
seededRNG
|
|
@@ -38103,30 +38071,15 @@ var PassageRefTarget$1 = {
|
|
|
38103
38071
|
isLintable: true
|
|
38104
38072
|
};
|
|
38105
38073
|
|
|
38106
|
-
/* eslint-disable
|
|
38074
|
+
/* eslint-disable react/no-unsafe */
|
|
38107
38075
|
const {
|
|
38108
38076
|
deepEq: deepEq$1
|
|
38109
38077
|
} = Util;
|
|
38110
|
-
const BAR = "bar"
|
|
38111
|
-
|
|
38112
|
-
|
|
38113
|
-
|
|
38114
|
-
|
|
38115
|
-
({
|
|
38116
|
-
type: PropTypes.oneOf([BAR, LINE, PIC, HISTOGRAM, DOTPLOT]),
|
|
38117
|
-
labels: PropTypes.arrayOf(PropTypes.string),
|
|
38118
|
-
categories: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
|
|
38119
|
-
scaleY: PropTypes.number,
|
|
38120
|
-
maxY: PropTypes.number,
|
|
38121
|
-
snapsPerLine: PropTypes.number,
|
|
38122
|
-
picSize: PropTypes.number,
|
|
38123
|
-
pixBoxHeight: PropTypes.number,
|
|
38124
|
-
picUrl: PropTypes.string,
|
|
38125
|
-
plotDimensions: PropTypes.arrayOf(PropTypes.number),
|
|
38126
|
-
labelInterval: PropTypes.number,
|
|
38127
|
-
starting: PropTypes.arrayOf(PropTypes.number),
|
|
38128
|
-
static: PropTypes.bool
|
|
38129
|
-
});
|
|
38078
|
+
const BAR = "bar";
|
|
38079
|
+
const LINE = "line";
|
|
38080
|
+
const PIC = "pic";
|
|
38081
|
+
const HISTOGRAM = "histogram";
|
|
38082
|
+
const DOTPLOT = "dotplot";
|
|
38130
38083
|
class Plotter extends React.Component {
|
|
38131
38084
|
constructor(..._args) {
|
|
38132
38085
|
super(..._args);
|
|
@@ -38165,11 +38118,11 @@ class Plotter extends React.Component {
|
|
|
38165
38118
|
self.graphie = graphie;
|
|
38166
38119
|
self.graphie.pics = [];
|
|
38167
38120
|
self.graphie.dotTicks = [];
|
|
38168
|
-
const isBar = self.props.type === BAR
|
|
38169
|
-
|
|
38170
|
-
|
|
38171
|
-
|
|
38172
|
-
|
|
38121
|
+
const isBar = self.props.type === BAR;
|
|
38122
|
+
const isLine = self.props.type === LINE;
|
|
38123
|
+
const isPic = self.props.type === PIC;
|
|
38124
|
+
const isHistogram = self.props.type === HISTOGRAM;
|
|
38125
|
+
const isDotplot = self.props.type === DOTPLOT;
|
|
38173
38126
|
const isTiledPlot = isPic || isDotplot;
|
|
38174
38127
|
const config = {};
|
|
38175
38128
|
const c = config; // c for short
|
|
@@ -38230,9 +38183,7 @@ class Plotter extends React.Component {
|
|
|
38230
38183
|
|
|
38231
38184
|
// TODO(michaelpolyak): Handle other plot types: Dot, Histogram, Line.
|
|
38232
38185
|
if (isMobile && (isBar || isTiledPlot)) {
|
|
38233
|
-
const maxCategoryHeight = Math.max(0,
|
|
38234
|
-
// @ts-expect-error [FEI-5003] - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'number'.
|
|
38235
|
-
...Object.values(self.state.categoryHeights));
|
|
38186
|
+
const maxCategoryHeight = Math.max(0, ...Object.values(self.state.categoryHeights));
|
|
38236
38187
|
if (maxCategoryHeight) {
|
|
38237
38188
|
// Account for bottom label position, height.
|
|
38238
38189
|
let offsetY = 25;
|
|
@@ -38285,7 +38236,7 @@ class Plotter extends React.Component {
|
|
|
38285
38236
|
});
|
|
38286
38237
|
}
|
|
38287
38238
|
}
|
|
38288
|
-
if ((isBar || isLine) && isMobile) {
|
|
38239
|
+
if ((isBar || isLine) && isMobile && !this.props.static) {
|
|
38289
38240
|
self.graphie.dragPrompt = graphie.label([c.dimX / 2, c.dimY / 2], i18n._("Drag handles to make graph"), "center", false).css("font-weight", "bold").css("color", KhanColors.KA_GREEN).css("display", "none");
|
|
38290
38241
|
}
|
|
38291
38242
|
self.setupCategories(config);
|
|
@@ -38534,8 +38485,8 @@ class Plotter extends React.Component {
|
|
|
38534
38485
|
config.graph.bars[i].scale(1, Math.max(isMobile ? 0.2 : 0.01, height / config.scaleY), center[0], center[1]);
|
|
38535
38486
|
if (isHistogram) {
|
|
38536
38487
|
// Scale dividers between buckets
|
|
38537
|
-
const leftDivider = config.graph.dividers[i - 1]
|
|
38538
|
-
|
|
38488
|
+
const leftDivider = config.graph.dividers[i - 1];
|
|
38489
|
+
const rightDivider = config.graph.dividers[i];
|
|
38539
38490
|
if (leftDivider) {
|
|
38540
38491
|
const divHeight = Math.min(self.state.values[i - 1], height);
|
|
38541
38492
|
leftDivider.scale(1, Math.max(0.01, divHeight / config.scaleY), center[0], center[1]);
|
|
@@ -38860,38 +38811,13 @@ class Plotter extends React.Component {
|
|
|
38860
38811
|
return Plotter.validate(this.getUserInput(), rubric);
|
|
38861
38812
|
};
|
|
38862
38813
|
}
|
|
38863
|
-
render() {
|
|
38864
|
-
// TODO(kevinb) actually compute the size of the graphie correctly and
|
|
38865
|
-
// make it that size so we don't have to add extra padding. The value
|
|
38866
|
-
// was determined by eye-balling the layout. :(
|
|
38867
|
-
const paddingForBottomLabel = 75;
|
|
38868
|
-
const style = {
|
|
38869
|
-
marginBottom: this.props.labels[0] ? paddingForBottomLabel : 0
|
|
38870
|
-
};
|
|
38871
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
38872
|
-
className: "perseus-widget-plotter graphie " + ClassNames.INTERACTIVE
|
|
38873
|
-
// eslint-disable-next-line react/no-string-refs
|
|
38874
|
-
,
|
|
38875
|
-
ref: "graphieDiv",
|
|
38876
|
-
style: style
|
|
38877
|
-
});
|
|
38878
|
-
}
|
|
38879
|
-
componentDidUpdate(prevProps, prevState) {
|
|
38880
|
-
this.shouldSetupGraphie = this.shouldSetupGraphie || !_.isEqual(this.state.categoryHeights, prevState.categoryHeights);
|
|
38881
|
-
if (this.shouldSetupGraphie) {
|
|
38882
|
-
this.setupGraphie(prevState);
|
|
38883
|
-
}
|
|
38884
|
-
}
|
|
38885
38814
|
componentDidMount() {
|
|
38886
38815
|
this._isMounted = true;
|
|
38887
38816
|
this.setupGraphie(this.state);
|
|
38888
38817
|
}
|
|
38889
38818
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
38890
38819
|
const props = ["type", "labels", "categories", "scaleY", "maxY", "snapsPerLine", "picUrl", "labelInterval", "static"];
|
|
38891
|
-
this.shouldSetupGraphie = _.any(props,
|
|
38892
|
-
// @ts-expect-error [FEI-5003] - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
38893
|
-
return !_.isEqual(this.props[prop], nextProps[prop]);
|
|
38894
|
-
}, this);
|
|
38820
|
+
this.shouldSetupGraphie = _.any(props, prop => !_.isEqual(this.props[prop], nextProps[prop]), this);
|
|
38895
38821
|
if (!_.isEqual(this.props.starting, nextProps.starting) && !_.isEqual(this.state.values, nextProps.starting)) {
|
|
38896
38822
|
this.shouldSetupGraphie = true;
|
|
38897
38823
|
this.setState({
|
|
@@ -38899,16 +38825,32 @@ class Plotter extends React.Component {
|
|
|
38899
38825
|
});
|
|
38900
38826
|
}
|
|
38901
38827
|
}
|
|
38828
|
+
componentDidUpdate(prevProps, prevState) {
|
|
38829
|
+
this.shouldSetupGraphie = this.shouldSetupGraphie || !_.isEqual(this.state.categoryHeights, prevState.categoryHeights);
|
|
38830
|
+
if (this.shouldSetupGraphie) {
|
|
38831
|
+
this.setupGraphie(prevState);
|
|
38832
|
+
}
|
|
38833
|
+
}
|
|
38902
38834
|
componentWillUnmount() {
|
|
38903
38835
|
this._isMounted = false;
|
|
38904
38836
|
}
|
|
38837
|
+
render() {
|
|
38838
|
+
// TODO(kevinb) actually compute the size of the graphie correctly and
|
|
38839
|
+
// make it that size so we don't have to add extra padding. The value
|
|
38840
|
+
// was determined by eye-balling the layout. :(
|
|
38841
|
+
const paddingForBottomLabel = 75;
|
|
38842
|
+
const style = {
|
|
38843
|
+
marginBottom: this.props.labels[0] ? paddingForBottomLabel : 0
|
|
38844
|
+
};
|
|
38845
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
38846
|
+
className: "perseus-widget-plotter graphie " + ClassNames.INTERACTIVE
|
|
38847
|
+
// eslint-disable-next-line react/no-string-refs
|
|
38848
|
+
,
|
|
38849
|
+
ref: "graphieDiv",
|
|
38850
|
+
style: style
|
|
38851
|
+
});
|
|
38852
|
+
}
|
|
38905
38853
|
}
|
|
38906
|
-
Plotter.propTypes = {
|
|
38907
|
-
onChange: PropTypes.func.isRequired,
|
|
38908
|
-
trackInteraction: PropTypes.func.isRequired
|
|
38909
|
-
// TODO(alex): Figure out why lint chokes on this line
|
|
38910
|
-
// ...widgetPropTypes,
|
|
38911
|
-
};
|
|
38912
38854
|
Plotter.defaultProps = {
|
|
38913
38855
|
type: BAR,
|
|
38914
38856
|
labels: ["", ""],
|
|
@@ -39879,6 +39821,7 @@ var Simulator$1 = {
|
|
|
39879
39821
|
hidden: true
|
|
39880
39822
|
};
|
|
39881
39823
|
|
|
39824
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
39882
39825
|
const {
|
|
39883
39826
|
shuffle
|
|
39884
39827
|
} = Util;
|
|
@@ -43914,17 +43857,7 @@ registerWidgets(allWidgets);
|
|
|
43914
43857
|
const ItemVersion = getVersionVector();
|
|
43915
43858
|
ItemVersion["::renderer::"] = version.itemDataVersion;
|
|
43916
43859
|
|
|
43917
|
-
|
|
43918
|
-
* A mixin that renders a custom software keypad in additional to the base
|
|
43919
|
-
* component. The base component will receive blur events when the keypad is
|
|
43920
|
-
* dismissed and can access the keypad element itself so as to manage its
|
|
43921
|
-
* activation and dismissal.
|
|
43922
|
-
*
|
|
43923
|
-
* TODO(charlie): This would make a nicer higher-order component, except that
|
|
43924
|
-
* we need to expose methods on the base component (i.e., `ItemRenderer`). When
|
|
43925
|
-
* `ItemRenderer` and friends are written as ES6 Classes, we can have them
|
|
43926
|
-
* extend a `ProvideKeypad` component instead of using this mixin.
|
|
43927
|
-
*/
|
|
43860
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
43928
43861
|
// NOTE: This is not a real component. It's a collection of methods used to
|
|
43929
43862
|
// create and manage a Keypad instances.
|
|
43930
43863
|
// TODO(LP-10789): replace this with a React Context object to pass information
|
|
@@ -46874,9 +46807,7 @@ const EditorJsonify = {
|
|
|
46874
46807
|
}
|
|
46875
46808
|
};
|
|
46876
46809
|
|
|
46877
|
-
|
|
46878
|
-
* Main entry point
|
|
46879
|
-
*/
|
|
46810
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
46880
46811
|
const apiVersion = version.apiVersion;
|
|
46881
46812
|
const itemDataVersion = version.itemDataVersion;
|
|
46882
46813
|
|