@khanacademy/perseus 37.0.1 → 38.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/dist/es/index.js +77 -54
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +77 -54
- package/dist/index.js.map +1 -1
- package/dist/multi-items/item-types.d.ts +4 -3
- package/dist/perseus-api.d.ts +6 -6
- package/dist/perseus-types.d.ts +31 -30
- package/dist/server-item-renderer.d.ts +6 -6
- package/dist/types.d.ts +1 -4
- package/dist/validation.types.d.ts +4 -11
- package/dist/widgets/expression/expression.d.ts +36 -36
- package/dist/widgets/grapher/grapher-types.d.ts +58 -0
- package/dist/widgets/grapher/grapher-validator.d.ts +1 -1
- package/dist/widgets/grapher/util.d.ts +16 -3
- package/dist/widgets/label-image/label-image.d.ts +12 -12
- package/package.json +1 -1
package/dist/es/index.js
CHANGED
|
@@ -9967,9 +9967,6 @@ const setLabelMargins = function setLabelMargins(span, size) {
|
|
|
9967
9967
|
// Inherited line-height values can really mess up placement.
|
|
9968
9968
|
$container.css("line-height", "normal");
|
|
9969
9969
|
|
|
9970
|
-
// TODO: Verify that this change doesn't impact other graphies
|
|
9971
|
-
// Check the full list of consuming widgets.
|
|
9972
|
-
|
|
9973
9970
|
// If the change in line-height affected the height of the element,
|
|
9974
9971
|
// then the height used for calculations should be updated.
|
|
9975
9972
|
// This can happen when the first label in the container calls this method,
|
|
@@ -28275,7 +28272,7 @@ const Exponential = _.extend({}, PlotDefaults, {
|
|
|
28275
28272
|
* coordinate, and `false` uses oldCoord as the resulting coordinate.
|
|
28276
28273
|
*/
|
|
28277
28274
|
extraCoordConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
|
|
28278
|
-
const y =
|
|
28275
|
+
const y = asymptote[0][1];
|
|
28279
28276
|
return _.all(coords, coord => coord[1] !== y);
|
|
28280
28277
|
},
|
|
28281
28278
|
extraAsymptoteConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
|
|
@@ -28299,7 +28296,7 @@ const Exponential = _.extend({}, PlotDefaults, {
|
|
|
28299
28296
|
getCoefficients: function (coords, asymptote) {
|
|
28300
28297
|
const p1 = coords[0];
|
|
28301
28298
|
const p2 = coords[1];
|
|
28302
|
-
const c =
|
|
28299
|
+
const c = asymptote[0][1];
|
|
28303
28300
|
const b = Math.log((p1[1] - c) / (p2[1] - c)) / (p1[0] - p2[0]);
|
|
28304
28301
|
const a = (p1[1] - c) / Math.exp(b * p1[0]);
|
|
28305
28302
|
return [a, b, c];
|
|
@@ -28326,7 +28323,7 @@ const Logarithm = _.extend({}, PlotDefaults, {
|
|
|
28326
28323
|
defaultCoords: [[0.55, 0.5], [0.75, 0.75]],
|
|
28327
28324
|
defaultAsymptote: [[0.5, 0], [0.5, 1.0]],
|
|
28328
28325
|
extraCoordConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
|
|
28329
|
-
const x =
|
|
28326
|
+
const x = asymptote[0][0];
|
|
28330
28327
|
return _.all(coords, coord => coord[0] !== x) && coords[0][1] !== coords[1][1];
|
|
28331
28328
|
},
|
|
28332
28329
|
extraAsymptoteConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
|
|
@@ -28354,10 +28351,12 @@ const Logarithm = _.extend({}, PlotDefaults, {
|
|
|
28354
28351
|
// logic between the two 'models'.
|
|
28355
28352
|
const flip = coord => [coord[1], coord[0]];
|
|
28356
28353
|
const inverseCoeffs = Exponential.getCoefficients(_.map(coords, flip), _.map(asymptote, flip));
|
|
28357
|
-
|
|
28358
|
-
|
|
28359
|
-
|
|
28360
|
-
|
|
28354
|
+
if (inverseCoeffs) {
|
|
28355
|
+
const c = -inverseCoeffs[2] / inverseCoeffs[0];
|
|
28356
|
+
const b = 1 / inverseCoeffs[0];
|
|
28357
|
+
const a = 1 / inverseCoeffs[1];
|
|
28358
|
+
return [a, b, c];
|
|
28359
|
+
}
|
|
28361
28360
|
},
|
|
28362
28361
|
getFunctionForCoeffs: function (coeffs, x, asymptote) {
|
|
28363
28362
|
const a = coeffs[0],
|
|
@@ -28421,11 +28420,9 @@ const functionTypeMapping = {
|
|
|
28421
28420
|
absolute_value: AbsoluteValue
|
|
28422
28421
|
};
|
|
28423
28422
|
const allTypes = _.keys(functionTypeMapping);
|
|
28424
|
-
function functionForType(
|
|
28425
|
-
//
|
|
28426
|
-
//
|
|
28427
|
-
// is a big amount of work/change.
|
|
28428
|
-
type) {
|
|
28423
|
+
function functionForType(type) {
|
|
28424
|
+
// @ts-expect-error: TypeScript doesn't know how to use deal with generics
|
|
28425
|
+
// and conditional types in this way.
|
|
28429
28426
|
return functionTypeMapping[type];
|
|
28430
28427
|
}
|
|
28431
28428
|
const getEquationString = props => {
|
|
@@ -28490,12 +28487,13 @@ const defaultPlotProps = (type, graph) => {
|
|
|
28490
28487
|
// widget before even reading the question; you can't lose, but you
|
|
28491
28488
|
// might get a free win.
|
|
28492
28489
|
const model = functionForType(type);
|
|
28490
|
+
const defaultAsymptote = "defaultAsymptote" in model ? model.defaultAsymptote : null;
|
|
28493
28491
|
const gridStep = [1, 1];
|
|
28494
28492
|
// @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type '[number, number]'.
|
|
28495
28493
|
const snapStep = Util.snapStepFromGridStep(gridStep);
|
|
28496
28494
|
return {
|
|
28497
28495
|
type,
|
|
28498
|
-
asymptote: maybePointsFromNormalized(
|
|
28496
|
+
asymptote: maybePointsFromNormalized(defaultAsymptote, graph.range, graph.step, snapStep),
|
|
28499
28497
|
coords: null
|
|
28500
28498
|
};
|
|
28501
28499
|
};
|
|
@@ -28555,8 +28553,19 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
28555
28553
|
typeToButton: typeToButton
|
|
28556
28554
|
});
|
|
28557
28555
|
|
|
28558
|
-
function
|
|
28559
|
-
if (
|
|
28556
|
+
function getCoefficientsByType(data) {
|
|
28557
|
+
if (data.type === "exponential" || data.type === "logarithm") {
|
|
28558
|
+
const grader = functionForType(data.type);
|
|
28559
|
+
return grader.getCoefficients(data.coords, data.asymptote);
|
|
28560
|
+
} else if (data.type === "linear" || data.type === "quadratic" || data.type === "absolute_value" || data.type === "sinusoid" || data.type === "tangent") {
|
|
28561
|
+
const grader = functionForType(data.type);
|
|
28562
|
+
return grader.getCoefficients(data.coords);
|
|
28563
|
+
} else {
|
|
28564
|
+
throw new PerseusError("Invalid grapher type", Errors.InvalidInput);
|
|
28565
|
+
}
|
|
28566
|
+
}
|
|
28567
|
+
function grapherValidator(userInput, rubric) {
|
|
28568
|
+
if (userInput.type !== rubric.correct.type) {
|
|
28560
28569
|
return {
|
|
28561
28570
|
type: "points",
|
|
28562
28571
|
earned: 0,
|
|
@@ -28566,7 +28575,7 @@ function grapherValidator(state, rubric) {
|
|
|
28566
28575
|
}
|
|
28567
28576
|
|
|
28568
28577
|
// We haven't moved the coords
|
|
28569
|
-
if (
|
|
28578
|
+
if (userInput.coords == null) {
|
|
28570
28579
|
return {
|
|
28571
28580
|
type: "invalid",
|
|
28572
28581
|
message: null
|
|
@@ -28574,11 +28583,9 @@ function grapherValidator(state, rubric) {
|
|
|
28574
28583
|
}
|
|
28575
28584
|
|
|
28576
28585
|
// Get new function handler for grading
|
|
28577
|
-
const grader = functionForType(
|
|
28578
|
-
const guessCoeffs =
|
|
28579
|
-
const correctCoeffs =
|
|
28580
|
-
// @ts-expect-error - TS(2339) - Property 'asymptote' does not exist on type '{ type: "absolute_value"; coords: [Coord, Coord]; }'
|
|
28581
|
-
rubric.correct.asymptote);
|
|
28586
|
+
const grader = functionForType(userInput.type);
|
|
28587
|
+
const guessCoeffs = getCoefficientsByType(userInput);
|
|
28588
|
+
const correctCoeffs = getCoefficientsByType(rubric.correct);
|
|
28582
28589
|
if (guessCoeffs == null || correctCoeffs == null) {
|
|
28583
28590
|
return {
|
|
28584
28591
|
type: "invalid",
|
|
@@ -42060,17 +42067,23 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
|
|
|
42060
42067
|
const results = [];
|
|
42061
42068
|
|
|
42062
42069
|
// For convenience, extract some props into separate variables
|
|
42063
|
-
const
|
|
42064
|
-
|
|
42070
|
+
const {
|
|
42071
|
+
range,
|
|
42072
|
+
labelRange,
|
|
42073
|
+
labelStyle,
|
|
42074
|
+
labelTicks,
|
|
42075
|
+
tickStep,
|
|
42076
|
+
numDivisions
|
|
42077
|
+
} = props;
|
|
42065
42078
|
const leftLabel = labelRange[0] == null ? range[0] : labelRange[0];
|
|
42066
42079
|
const rightLabel = labelRange[1] == null ? range[1] : labelRange[1];
|
|
42067
42080
|
|
|
42068
42081
|
// Find base via GCD for non-reduced fractions
|
|
42069
42082
|
let base;
|
|
42070
|
-
if (
|
|
42083
|
+
if (labelStyle === "non-reduced") {
|
|
42071
42084
|
const fractions = [leftLabel, rightLabel];
|
|
42072
|
-
for (let i = 0; i <=
|
|
42073
|
-
const x = range[0] + i *
|
|
42085
|
+
for (let i = 0; i <= numDivisions; i++) {
|
|
42086
|
+
const x = range[0] + i * tickStep;
|
|
42074
42087
|
fractions.push(x);
|
|
42075
42088
|
}
|
|
42076
42089
|
const getDenom = x => number.toFraction(x)[1];
|
|
@@ -42079,30 +42092,40 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
|
|
|
42079
42092
|
} else {
|
|
42080
42093
|
base = undefined;
|
|
42081
42094
|
}
|
|
42082
|
-
|
|
42083
|
-
// Draw and save the tick marks and tick labels
|
|
42084
|
-
for (let i = 0; i <= props.numDivisions; i++) {
|
|
42085
|
-
const x = range[0] + i * props.tickStep;
|
|
42086
|
-
results.push(graphie.line([x, -0.2], [x, 0.2]));
|
|
42087
|
-
const labelTicks = props.labelTicks;
|
|
42088
|
-
if (labelTicks || props.labelStyle === "decimal ticks") {
|
|
42089
|
-
if (x === leftLabel || x === rightLabel) {
|
|
42090
|
-
results.push(graphie.style({
|
|
42091
|
-
color: KhanColors.BLUE
|
|
42092
|
-
}, () => _label(graphie, props.labelStyle, x, x, base)));
|
|
42093
|
-
} else {
|
|
42094
|
-
results.push(_label(graphie, props.labelStyle, x, x, base));
|
|
42095
|
-
}
|
|
42096
|
-
}
|
|
42097
|
-
}
|
|
42098
|
-
|
|
42099
|
-
// Render the labels' lines
|
|
42100
|
-
graphie.style({
|
|
42095
|
+
const highlightedLineStyle = {
|
|
42101
42096
|
stroke: KhanColors.BLUE,
|
|
42102
42097
|
strokeWidth: 3.5
|
|
42103
|
-
}
|
|
42104
|
-
|
|
42105
|
-
|
|
42098
|
+
};
|
|
42099
|
+
const highlightedTextStyle = {
|
|
42100
|
+
color: KhanColors.BLUE
|
|
42101
|
+
};
|
|
42102
|
+
|
|
42103
|
+
// Generate an array of tick numbers:
|
|
42104
|
+
// `Array(props.numDivisions)` makes an array of null values - one for every division marker
|
|
42105
|
+
// `.keys()` gets the index values for each marker placeholder
|
|
42106
|
+
// `.map()` converts the index values into actual tick numbers
|
|
42107
|
+
const initialTicks = [...Array(numDivisions).keys()].map(index => range[0] + index * tickStep);
|
|
42108
|
+
|
|
42109
|
+
// .sort() comparator
|
|
42110
|
+
const byNumericAscending = (a, b) => a - b;
|
|
42111
|
+
|
|
42112
|
+
// Ensure that any label markers and range endpoints are included in the array
|
|
42113
|
+
// Using `Set()` prevents duplication of tick numbers (and is quite performant)
|
|
42114
|
+
const allTicks = [...new Set([...initialTicks, leftLabel, rightLabel, ...range])].sort(byNumericAscending);
|
|
42115
|
+
|
|
42116
|
+
// Cycle through each tick number and add a tick line, and a label (if needed)
|
|
42117
|
+
allTicks.forEach(tick => {
|
|
42118
|
+
const tickIsHighlighted = tick === leftLabel || tick === rightLabel;
|
|
42119
|
+
const lineStyle = tickIsHighlighted ? highlightedLineStyle : null;
|
|
42120
|
+
const textStyle = tickIsHighlighted ? highlightedTextStyle : null;
|
|
42121
|
+
graphie.style(lineStyle, () => {
|
|
42122
|
+
results.push(graphie.line([tick, -0.2], [tick, 0.2]));
|
|
42123
|
+
});
|
|
42124
|
+
if (labelTicks || tickIsHighlighted || labelStyle === "decimal ticks") {
|
|
42125
|
+
graphie.style(textStyle, () => {
|
|
42126
|
+
results.push(_label(graphie, labelStyle, tick, tick, base));
|
|
42127
|
+
});
|
|
42128
|
+
}
|
|
42106
42129
|
});
|
|
42107
42130
|
return results;
|
|
42108
42131
|
});
|
|
@@ -42781,7 +42804,7 @@ class Orderer extends React.Component {
|
|
|
42781
42804
|
list.splice(index, 0, newCard);
|
|
42782
42805
|
}
|
|
42783
42806
|
this.props.onChange({
|
|
42784
|
-
// @ts-expect-error - TS2345 - Argument of type '{ current: any[]; }' is not assignable to parameter of type '{ hints?: readonly Hint[] | undefined; replace?: boolean | undefined; content?: string | undefined; widgets?:
|
|
42807
|
+
// @ts-expect-error - TS2345 - Argument of type '{ current: any[]; }' is not assignable to parameter of type '{ hints?: readonly Hint[] | undefined; replace?: boolean | undefined; content?: string | undefined; widgets?: PerseusWidgetsMap | undefined; images?: ImageDict | undefined; ... 13 more ...; plot?: any; }'.
|
|
42785
42808
|
current: list
|
|
42786
42809
|
});
|
|
42787
42810
|
this.setState({
|
|
@@ -42943,7 +42966,7 @@ class Orderer extends React.Component {
|
|
|
42943
42966
|
};
|
|
42944
42967
|
});
|
|
42945
42968
|
this.props.onChange({
|
|
42946
|
-
// @ts-expect-error - TS2345 - Argument of type '{ current: { content: string; }[]; }' is not assignable to parameter of type '{ hints?: readonly Hint[] | undefined; replace?: boolean | undefined; content?: string | undefined; widgets?:
|
|
42969
|
+
// @ts-expect-error - TS2345 - Argument of type '{ current: { content: string; }[]; }' is not assignable to parameter of type '{ hints?: readonly Hint[] | undefined; replace?: boolean | undefined; content?: string | undefined; widgets?: PerseusWidgetsMap | undefined; images?: ImageDict | undefined; ... 13 more ...; plot?: any; }'.
|
|
42947
42970
|
current: list
|
|
42948
42971
|
});
|
|
42949
42972
|
this.setState({
|
|
@@ -44804,7 +44827,7 @@ const init = function init(options) {
|
|
|
44804
44827
|
|
|
44805
44828
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44806
44829
|
const libName = "@khanacademy/perseus";
|
|
44807
|
-
const libVersion = "
|
|
44830
|
+
const libVersion = "38.0.0";
|
|
44808
44831
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44809
44832
|
|
|
44810
44833
|
const apiVersion = {
|