@khanacademy/perseus 36.0.0 → 36.1.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/dist/es/index.js +222 -36
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +219 -33
- package/dist/index.js.map +1 -1
- package/dist/util/extract-perseus-data.d.ts +11 -1
- package/dist/widgets/interactive-graphs/backgrounds/axis-ticks.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/components/movable-point.d.ts +1 -1
- package/package.json +9 -9
package/dist/es/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as KAS from '@khanacademy/kas';
|
|
|
2
2
|
import { MathInputI18nContext, CursorContext, getKeyTranslator, createMathField, getCursorContext, DesktopKeypad, convertDotToTimesByLocale, mathQuillInstance, KeypadInput, KeypadType, KeyArray, keypadElementPropType } from '@khanacademy/math-input';
|
|
3
3
|
import * as PerseusLinter from '@khanacademy/perseus-linter';
|
|
4
4
|
import { linterContextDefault, Rule } from '@khanacademy/perseus-linter';
|
|
5
|
-
import { View, RenderStateRoot, UniqueIDProvider, useLatestRef, useUniqueIdWithMock, Text as Text$2 } from '@khanacademy/wonder-blocks-core';
|
|
5
|
+
import { View, RenderStateRoot, UniqueIDProvider, useOnMountEffect, useLatestRef, useUniqueIdWithMock, Text as Text$2 } from '@khanacademy/wonder-blocks-core';
|
|
6
6
|
import Tooltip$1 from '@khanacademy/wonder-blocks-tooltip';
|
|
7
7
|
import { HeadingMedium, LabelSmall, Body, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
8
8
|
import { StyleSheet, css } from 'aphrodite';
|
|
@@ -3157,13 +3157,13 @@ function eq$4(x, y) {
|
|
|
3157
3157
|
* Deep approximate equality on primitives, numbers, arrays, and objects.
|
|
3158
3158
|
* Recursive.
|
|
3159
3159
|
*/
|
|
3160
|
-
function deepEq$
|
|
3160
|
+
function deepEq$6(x, y) {
|
|
3161
3161
|
if (Array.isArray(x) && Array.isArray(y)) {
|
|
3162
3162
|
if (x.length !== y.length) {
|
|
3163
3163
|
return false;
|
|
3164
3164
|
}
|
|
3165
3165
|
for (let i = 0; i < x.length; i++) {
|
|
3166
|
-
if (!deepEq$
|
|
3166
|
+
if (!deepEq$6(x[i], y[i])) {
|
|
3167
3167
|
return false;
|
|
3168
3168
|
}
|
|
3169
3169
|
}
|
|
@@ -3181,10 +3181,10 @@ function deepEq$5(x, y) {
|
|
|
3181
3181
|
if (typeof x === "object" && typeof y === "object" && !!x && !!y) {
|
|
3182
3182
|
return x === y || _.all(x, function (v, k) {
|
|
3183
3183
|
// @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
|
|
3184
|
-
return deepEq$
|
|
3184
|
+
return deepEq$6(y[k], v);
|
|
3185
3185
|
}) && _.all(y, function (v, k) {
|
|
3186
3186
|
// @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
|
|
3187
|
-
return deepEq$
|
|
3187
|
+
return deepEq$6(x[k], v);
|
|
3188
3188
|
});
|
|
3189
3189
|
}
|
|
3190
3190
|
if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
|
|
@@ -3464,7 +3464,7 @@ const Util = {
|
|
|
3464
3464
|
tickStepFromNumTicks,
|
|
3465
3465
|
constrainedTickStepsFromTickSteps,
|
|
3466
3466
|
eq: eq$4,
|
|
3467
|
-
deepEq: deepEq$
|
|
3467
|
+
deepEq: deepEq$6,
|
|
3468
3468
|
parseQueryString,
|
|
3469
3469
|
updateQueryString: updateQueryString$2,
|
|
3470
3470
|
strongEncodeURIComponent,
|
|
@@ -10786,7 +10786,7 @@ class WrappedLine extends WrappedDrawing {
|
|
|
10786
10786
|
*/
|
|
10787
10787
|
const {
|
|
10788
10788
|
eq: eq$3,
|
|
10789
|
-
deepEq: deepEq$
|
|
10789
|
+
deepEq: deepEq$5
|
|
10790
10790
|
} = Util;
|
|
10791
10791
|
|
|
10792
10792
|
// This should really be a readonly tuple of [number, number]
|
|
@@ -10946,7 +10946,7 @@ function similar(coords1, coords2, tolerance) {
|
|
|
10946
10946
|
angles = rotate(angles, i);
|
|
10947
10947
|
// @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
|
|
10948
10948
|
sides = rotate(sides, i);
|
|
10949
|
-
if (deepEq$
|
|
10949
|
+
if (deepEq$5(angles1, angles)) {
|
|
10950
10950
|
const sidePairs = _.zip(sides1, sides);
|
|
10951
10951
|
const factors = _.map(sidePairs, function (pair) {
|
|
10952
10952
|
return pair[0] / pair[1];
|
|
@@ -13884,7 +13884,7 @@ _.extend(MovableAngle.prototype, {
|
|
|
13884
13884
|
|
|
13885
13885
|
/* eslint-disable @babel/no-invalid-this */
|
|
13886
13886
|
const nestedMap$1 = Util.nestedMap;
|
|
13887
|
-
const deepEq$
|
|
13887
|
+
const deepEq$4 = Util.deepEq;
|
|
13888
13888
|
|
|
13889
13889
|
/**
|
|
13890
13890
|
* A base class for all Graphie Movables
|
|
@@ -13981,7 +13981,7 @@ const createSimpleClass = function createSimpleClass(addFunction) {
|
|
|
13981
13981
|
this._prevProps = this.props;
|
|
13982
13982
|
},
|
|
13983
13983
|
modify: function (graphie) {
|
|
13984
|
-
if (!deepEq$
|
|
13984
|
+
if (!deepEq$4(this.props, this._prevProps)) {
|
|
13985
13985
|
this.remove();
|
|
13986
13986
|
this.add(graphie);
|
|
13987
13987
|
this._prevProps = this.props;
|
|
@@ -16684,7 +16684,7 @@ var Movables = {
|
|
|
16684
16684
|
const GraphieMovable = GraphieClasses.GraphieMovable;
|
|
16685
16685
|
const createGraphie = GraphUtils.createGraphie;
|
|
16686
16686
|
const {
|
|
16687
|
-
deepEq: deepEq$
|
|
16687
|
+
deepEq: deepEq$3,
|
|
16688
16688
|
nestedMap
|
|
16689
16689
|
} = Util;
|
|
16690
16690
|
const {
|
|
@@ -16926,7 +16926,7 @@ class Graphie extends React.Component {
|
|
|
16926
16926
|
if (this.props.setup !== prevProps.setup) {
|
|
16927
16927
|
Log.error("<Graphie> was given a new setup function. " + "This is a bad idea; please refactor your code to give " + "the same setup function reference to <Graphie> on " + "every render.", Errors.Internal);
|
|
16928
16928
|
}
|
|
16929
|
-
if (!deepEq$
|
|
16929
|
+
if (!deepEq$3(this.props.options, prevProps.options) || !deepEq$3(this.props.box, prevProps.box) || !deepEq$3(this.props.range, prevProps.range)) {
|
|
16930
16930
|
this._setupGraphie();
|
|
16931
16931
|
}
|
|
16932
16932
|
this._updateMovables();
|
|
@@ -30988,10 +30988,16 @@ const shouldShowLabel = (currentTick, range, tickStep) => {
|
|
|
30988
30988
|
function generateTickLocations(tickStep, min, max) {
|
|
30989
30989
|
const ticks = [];
|
|
30990
30990
|
|
|
30991
|
+
// Calculate the number of significant decimals in the tick step so
|
|
30992
|
+
// that we can match the desired precision when generating ticks.
|
|
30993
|
+
const decimalSigFigs = countSignificantDecimals(tickStep);
|
|
30994
|
+
|
|
30991
30995
|
// Add ticks in the positive direction
|
|
30992
30996
|
const start = Math.max(min, 0);
|
|
30993
30997
|
for (let _i = start + tickStep; _i < max; _i += tickStep) {
|
|
30994
|
-
|
|
30998
|
+
// Match to the same number of decimal places as the tick step
|
|
30999
|
+
// to avoid floating point errors when working with small numbers
|
|
31000
|
+
ticks.push(parseFloat(_i.toFixed(decimalSigFigs)));
|
|
30995
31001
|
}
|
|
30996
31002
|
|
|
30997
31003
|
// Add ticks in the negative direction
|
|
@@ -31002,6 +31008,15 @@ function generateTickLocations(tickStep, min, max) {
|
|
|
31002
31008
|
}
|
|
31003
31009
|
return ticks;
|
|
31004
31010
|
}
|
|
31011
|
+
|
|
31012
|
+
// Count the number of significant digits after the decimal point
|
|
31013
|
+
const countSignificantDecimals = number => {
|
|
31014
|
+
const numStr = number.toString();
|
|
31015
|
+
if (!numStr.includes(".")) {
|
|
31016
|
+
return 0;
|
|
31017
|
+
}
|
|
31018
|
+
return numStr.split(".")[1].length;
|
|
31019
|
+
};
|
|
31005
31020
|
const AxisTicks = () => {
|
|
31006
31021
|
const {
|
|
31007
31022
|
tickStep,
|
|
@@ -33280,7 +33295,7 @@ function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, a
|
|
|
33280
33295
|
return scaledBisector;
|
|
33281
33296
|
}
|
|
33282
33297
|
|
|
33283
|
-
const MovablePoint$1 = props => {
|
|
33298
|
+
const MovablePoint$1 = /*#__PURE__*/React.forwardRef((props, pointRef) => {
|
|
33284
33299
|
const {
|
|
33285
33300
|
snapStep
|
|
33286
33301
|
} = useGraphConfig();
|
|
@@ -33303,7 +33318,21 @@ const MovablePoint$1 = props => {
|
|
|
33303
33318
|
constrainKeyboardMovement: constrain
|
|
33304
33319
|
});
|
|
33305
33320
|
return /*#__PURE__*/React.createElement(MovablePointView, {
|
|
33306
|
-
ref:
|
|
33321
|
+
ref: ref => {
|
|
33322
|
+
// Note: This handles the case where pointRef is either a
|
|
33323
|
+
// function or a MutableRefObject. Mostly this is to satisfy
|
|
33324
|
+
// the type system, the function branch seems to be the only
|
|
33325
|
+
// one that occurs
|
|
33326
|
+
if (typeof pointRef === "function") {
|
|
33327
|
+
pointRef(ref);
|
|
33328
|
+
} else if (pointRef !== null) {
|
|
33329
|
+
pointRef.current = ref;
|
|
33330
|
+
}
|
|
33331
|
+
|
|
33332
|
+
// This ref is for the useDraggable and is not passed up the
|
|
33333
|
+
// chain
|
|
33334
|
+
elementRef.current = ref;
|
|
33335
|
+
},
|
|
33307
33336
|
point: point,
|
|
33308
33337
|
color: color$1,
|
|
33309
33338
|
dragging: dragging,
|
|
@@ -33319,7 +33348,7 @@ const MovablePoint$1 = props => {
|
|
|
33319
33348
|
},
|
|
33320
33349
|
cursor: cursor
|
|
33321
33350
|
});
|
|
33322
|
-
};
|
|
33351
|
+
});
|
|
33323
33352
|
|
|
33324
33353
|
const PolygonGraph = props => {
|
|
33325
33354
|
const [hovered, setHovered] = React.useState(false);
|
|
@@ -33899,6 +33928,14 @@ function UnlimitedPointGraph(props) {
|
|
|
33899
33928
|
const height = maxY - minY;
|
|
33900
33929
|
const [[widthPx, heightPx]] = useTransformDimensionsToPixels([width, height]);
|
|
33901
33930
|
const [[left, top]] = useTransformVectorsToPixels([minX, maxY]);
|
|
33931
|
+
const itemsRef = React.useRef([]);
|
|
33932
|
+
React.useEffect(() => {
|
|
33933
|
+
const focusedIndex = props.graphState.focusedPointIndex;
|
|
33934
|
+
if (focusedIndex != null) {
|
|
33935
|
+
var _itemsRef$current$foc;
|
|
33936
|
+
(_itemsRef$current$foc = itemsRef.current[focusedIndex]) == null || _itemsRef$current$foc.focus();
|
|
33937
|
+
}
|
|
33938
|
+
}, [props.graphState.focusedPointIndex, itemsRef]);
|
|
33902
33939
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
|
|
33903
33940
|
style: {
|
|
33904
33941
|
fill: "rgba(0,0,0,0)",
|
|
@@ -33919,13 +33956,24 @@ function UnlimitedPointGraph(props) {
|
|
|
33919
33956
|
key: i,
|
|
33920
33957
|
point: point,
|
|
33921
33958
|
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination)),
|
|
33959
|
+
ref: ref => {
|
|
33960
|
+
itemsRef.current[i] = ref;
|
|
33961
|
+
},
|
|
33922
33962
|
onFocusChange: (event, isFocused) => {
|
|
33923
33963
|
if (isFocused) {
|
|
33924
33964
|
dispatch(actions.pointGraph.focusPoint(i));
|
|
33925
33965
|
} else {
|
|
33926
|
-
var _event$relatedTarget;
|
|
33966
|
+
var _event$relatedTarget, _event$relatedTarget2;
|
|
33927
33967
|
if (((_event$relatedTarget = event.relatedTarget) == null ? void 0 : _event$relatedTarget.id) === REMOVE_BUTTON_ID) {
|
|
33928
33968
|
return;
|
|
33969
|
+
// This is an optimization: If the next target
|
|
33970
|
+
// is a point then don't blur because it casues
|
|
33971
|
+
// the remove button to get taken off the page
|
|
33972
|
+
// and then put back on The new point will
|
|
33973
|
+
// receive focus and set the correct state in
|
|
33974
|
+
// the reducer
|
|
33975
|
+
} else if ((_event$relatedTarget2 = event.relatedTarget) != null && _event$relatedTarget2.classList.contains("movable-point")) {
|
|
33976
|
+
return;
|
|
33929
33977
|
}
|
|
33930
33978
|
dispatch(actions.pointGraph.blurPoint());
|
|
33931
33979
|
}
|
|
@@ -34101,11 +34149,17 @@ const MafsGraph = props => {
|
|
|
34101
34149
|
fullGraphAriaLabel,
|
|
34102
34150
|
fullGraphAriaDescription
|
|
34103
34151
|
} = props;
|
|
34152
|
+
const {
|
|
34153
|
+
type
|
|
34154
|
+
} = state;
|
|
34104
34155
|
const [width, height] = props.box;
|
|
34105
34156
|
const tickStep = props.step;
|
|
34106
34157
|
const uniqueId = React.useId();
|
|
34107
34158
|
const descriptionId = `interactive-graph-description-${uniqueId}`;
|
|
34108
34159
|
const graphRef = React.useRef(null);
|
|
34160
|
+
const {
|
|
34161
|
+
analytics
|
|
34162
|
+
} = useDependencies();
|
|
34109
34163
|
|
|
34110
34164
|
// Set up the SVG attributes for the nested SVGs that help lock
|
|
34111
34165
|
// the grid and graph elements to the bounds of the graph.
|
|
@@ -34125,6 +34179,14 @@ const MafsGraph = props => {
|
|
|
34125
34179
|
const {
|
|
34126
34180
|
strings
|
|
34127
34181
|
} = usePerseusI18n();
|
|
34182
|
+
useOnMountEffect(() => {
|
|
34183
|
+
analytics.onAnalyticsEvent({
|
|
34184
|
+
type: "perseus:interactive-graph-widget:rendered",
|
|
34185
|
+
payload: {
|
|
34186
|
+
type
|
|
34187
|
+
}
|
|
34188
|
+
});
|
|
34189
|
+
});
|
|
34128
34190
|
return /*#__PURE__*/React.createElement(GraphConfigContext.Provider, {
|
|
34129
34191
|
value: {
|
|
34130
34192
|
range: state.range,
|
|
@@ -34888,10 +34950,13 @@ function doFocusPoint(state, action) {
|
|
|
34888
34950
|
function doBlurPoint(state, action) {
|
|
34889
34951
|
switch (state.type) {
|
|
34890
34952
|
case "point":
|
|
34891
|
-
|
|
34892
|
-
focusedPointIndex: null,
|
|
34953
|
+
const nextState = _extends({}, state, {
|
|
34893
34954
|
showRemovePointButton: false
|
|
34894
34955
|
});
|
|
34956
|
+
if (state.interactionMode === "mouse") {
|
|
34957
|
+
nextState.focusedPointIndex = null;
|
|
34958
|
+
}
|
|
34959
|
+
return nextState;
|
|
34895
34960
|
default:
|
|
34896
34961
|
return state;
|
|
34897
34962
|
}
|
|
@@ -35275,16 +35340,23 @@ function doAddPoint(state, action) {
|
|
|
35275
35340
|
return _extends({}, state, {
|
|
35276
35341
|
hasBeenInteractedWith: true,
|
|
35277
35342
|
coords: [...state.coords, snappedPoint],
|
|
35278
|
-
showRemovePointButton: false
|
|
35343
|
+
showRemovePointButton: false,
|
|
35344
|
+
focusedPointIndex: state.coords.length
|
|
35279
35345
|
});
|
|
35280
35346
|
}
|
|
35281
35347
|
function doRemovePoint(state, action) {
|
|
35282
35348
|
if (state.type !== "point") {
|
|
35283
35349
|
return state;
|
|
35284
35350
|
}
|
|
35351
|
+
let nextFocusedPointIndex;
|
|
35352
|
+
if (state.interactionMode === "mouse") {
|
|
35353
|
+
nextFocusedPointIndex = null;
|
|
35354
|
+
} else {
|
|
35355
|
+
nextFocusedPointIndex = state.coords.length > 1 ? state.coords.length - 2 : null;
|
|
35356
|
+
}
|
|
35285
35357
|
return _extends({}, state, {
|
|
35286
35358
|
coords: state.coords.filter((_, i) => i !== action.index),
|
|
35287
|
-
focusedPointIndex:
|
|
35359
|
+
focusedPointIndex: nextFocusedPointIndex,
|
|
35288
35360
|
showRemovePointButton: false
|
|
35289
35361
|
});
|
|
35290
35362
|
}
|
|
@@ -35685,7 +35757,7 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
35685
35757
|
});
|
|
35686
35758
|
|
|
35687
35759
|
const eq$1 = Util.eq;
|
|
35688
|
-
const deepEq$
|
|
35760
|
+
const deepEq$2 = Util.deepEq;
|
|
35689
35761
|
function interactiveGraphValidator(userInput, rubric) {
|
|
35690
35762
|
// None-type graphs are not graded
|
|
35691
35763
|
if (userInput.type === "none" && rubric.correct.type === "none") {
|
|
@@ -35741,7 +35813,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35741
35813
|
const correctCoeffs = getQuadraticCoefficients(
|
|
35742
35814
|
// @ts-expect-error - TS2345 - Argument of type 'readonly Coord[] | undefined' is not assignable to parameter of type 'readonly Coord[]'.
|
|
35743
35815
|
rubric.correct.coords);
|
|
35744
|
-
if (deepEq$
|
|
35816
|
+
if (deepEq$2(guessCoeffs, correctCoeffs)) {
|
|
35745
35817
|
return {
|
|
35746
35818
|
type: "points",
|
|
35747
35819
|
earned: 1,
|
|
@@ -35757,7 +35829,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35757
35829
|
const canonicalGuessCoeffs = canonicalSineCoefficients$1(guessCoeffs);
|
|
35758
35830
|
const canonicalCorrectCoeffs = canonicalSineCoefficients$1(correctCoeffs);
|
|
35759
35831
|
// If the canonical coefficients match, it's correct.
|
|
35760
|
-
if (deepEq$
|
|
35832
|
+
if (deepEq$2(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
|
|
35761
35833
|
return {
|
|
35762
35834
|
type: "points",
|
|
35763
35835
|
earned: 1,
|
|
@@ -35766,7 +35838,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35766
35838
|
};
|
|
35767
35839
|
}
|
|
35768
35840
|
} else if (userInput.type === "circle" && rubric.correct.type === "circle") {
|
|
35769
|
-
if (deepEq$
|
|
35841
|
+
if (deepEq$2(userInput.center, rubric.correct.center) && eq$1(userInput.radius, rubric.correct.radius)) {
|
|
35770
35842
|
return {
|
|
35771
35843
|
type: "points",
|
|
35772
35844
|
earned: 1,
|
|
@@ -35788,7 +35860,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35788
35860
|
guess == null || guess.sort();
|
|
35789
35861
|
// @ts-expect-error - TS2339 - Property 'sort' does not exist on type 'readonly Coord[]'.
|
|
35790
35862
|
correct.sort();
|
|
35791
|
-
if (deepEq$
|
|
35863
|
+
if (deepEq$2(guess, correct)) {
|
|
35792
35864
|
return {
|
|
35793
35865
|
type: "points",
|
|
35794
35866
|
earned: 1,
|
|
@@ -35812,7 +35884,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35812
35884
|
/* exact */
|
|
35813
35885
|
guess.sort();
|
|
35814
35886
|
correct.sort();
|
|
35815
|
-
match = deepEq$
|
|
35887
|
+
match = deepEq$2(guess, correct);
|
|
35816
35888
|
}
|
|
35817
35889
|
if (match) {
|
|
35818
35890
|
return {
|
|
@@ -35829,7 +35901,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35829
35901
|
guess = _.invoke(guess, "sort").sort();
|
|
35830
35902
|
// @ts-expect-error - TS2345 - Argument of type '(readonly Coord[])[] | undefined' is not assignable to parameter of type 'Collection<any>'.
|
|
35831
35903
|
correct = _.invoke(correct, "sort").sort();
|
|
35832
|
-
if (deepEq$
|
|
35904
|
+
if (deepEq$2(guess, correct)) {
|
|
35833
35905
|
return {
|
|
35834
35906
|
type: "points",
|
|
35835
35907
|
earned: 1,
|
|
@@ -35842,7 +35914,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35842
35914
|
const correct = rubric.correct.coords;
|
|
35843
35915
|
if (
|
|
35844
35916
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'.
|
|
35845
|
-
deepEq$
|
|
35917
|
+
deepEq$2(guess[0], correct[0]) &&
|
|
35846
35918
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
35847
35919
|
collinear(correct[0], correct[1], guess[1])) {
|
|
35848
35920
|
return {
|
|
@@ -35873,7 +35945,7 @@ function interactiveGraphValidator(userInput, rubric) {
|
|
|
35873
35945
|
/* exact */
|
|
35874
35946
|
match =
|
|
35875
35947
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
35876
|
-
deepEq$
|
|
35948
|
+
deepEq$2(guess[1], correct[1]) &&
|
|
35877
35949
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
35878
35950
|
collinear(correct[1], correct[0], guess[0]) &&
|
|
35879
35951
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
@@ -43384,10 +43456,10 @@ var PhetSimulation$1 = {
|
|
|
43384
43456
|
};
|
|
43385
43457
|
|
|
43386
43458
|
const {
|
|
43387
|
-
deepEq
|
|
43459
|
+
deepEq: deepEq$1
|
|
43388
43460
|
} = Util;
|
|
43389
43461
|
function plotterValidator(userInput, rubric) {
|
|
43390
|
-
if (deepEq(userInput, rubric.starting)) {
|
|
43462
|
+
if (deepEq$1(userInput, rubric.starting)) {
|
|
43391
43463
|
return {
|
|
43392
43464
|
type: "invalid",
|
|
43393
43465
|
message: null
|
|
@@ -43395,7 +43467,7 @@ function plotterValidator(userInput, rubric) {
|
|
|
43395
43467
|
}
|
|
43396
43468
|
return {
|
|
43397
43469
|
type: "points",
|
|
43398
|
-
earned: deepEq(userInput, rubric.correct) ? 1 : 0,
|
|
43470
|
+
earned: deepEq$1(userInput, rubric.correct) ? 1 : 0,
|
|
43399
43471
|
total: 1,
|
|
43400
43472
|
message: null
|
|
43401
43473
|
};
|
|
@@ -44873,7 +44945,7 @@ const init = function init(options) {
|
|
|
44873
44945
|
|
|
44874
44946
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44875
44947
|
const libName = "@khanacademy/perseus";
|
|
44876
|
-
const libVersion = "36.
|
|
44948
|
+
const libVersion = "36.1.1";
|
|
44877
44949
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44878
44950
|
|
|
44879
44951
|
const apiVersion = {
|
|
@@ -48050,6 +48122,38 @@ function injectWidgets(content, widgets, widgetProps) {
|
|
|
48050
48122
|
return context;
|
|
48051
48123
|
}
|
|
48052
48124
|
|
|
48125
|
+
/**
|
|
48126
|
+
* Looks through widgets to identify images that do not have alt text.
|
|
48127
|
+
*
|
|
48128
|
+
* We pass in the fuller perseusRenderer object to allow for the possibility
|
|
48129
|
+
* of expanding to include other img data from content & images in the future.
|
|
48130
|
+
*
|
|
48131
|
+
* @param {PerseusRenderer} perseusRenderer
|
|
48132
|
+
* @returns a stringified list of {widgetId, imageUrl} for imgs that don't have alt text
|
|
48133
|
+
*/
|
|
48134
|
+
function getImagesWithoutAltData(perseusRenderer) {
|
|
48135
|
+
if (!perseusRenderer.widgets) {
|
|
48136
|
+
return "";
|
|
48137
|
+
}
|
|
48138
|
+
const imgsWithoutAltData = [];
|
|
48139
|
+
Object.entries(perseusRenderer.widgets).forEach(([widgetId, widget]) => {
|
|
48140
|
+
var _widget$options$backg;
|
|
48141
|
+
if (!widget.options) {
|
|
48142
|
+
return;
|
|
48143
|
+
}
|
|
48144
|
+
|
|
48145
|
+
// Add to imagesWithoutAltData if img alt is missing and
|
|
48146
|
+
// image has valid img url data.
|
|
48147
|
+
if (widget.type === "image" && !widget.options.alt && (_widget$options$backg = widget.options.backgroundImage) != null && _widget$options$backg.url) {
|
|
48148
|
+
imgsWithoutAltData.push({
|
|
48149
|
+
widgetId,
|
|
48150
|
+
imgUrl: widget.options.backgroundImage.url
|
|
48151
|
+
});
|
|
48152
|
+
}
|
|
48153
|
+
});
|
|
48154
|
+
return JSON.stringify(imgsWithoutAltData);
|
|
48155
|
+
}
|
|
48156
|
+
|
|
48053
48157
|
/* Widgets that have individual answers */
|
|
48054
48158
|
const INDIVIDUAL_ANSWER_WIDGETS = ["interactive-graph", "categorizer", "grapher"];
|
|
48055
48159
|
|
|
@@ -48108,6 +48212,8 @@ const getValidWidgetIds = perseusItem => {
|
|
|
48108
48212
|
return keys(widgets).filter(id => isWidgetIdInContent(perseusItem, id));
|
|
48109
48213
|
};
|
|
48110
48214
|
|
|
48215
|
+
const deepEq = Util.deepEq;
|
|
48216
|
+
|
|
48111
48217
|
/**
|
|
48112
48218
|
* Helper to parse PerseusItem JSON
|
|
48113
48219
|
* Why not just use JSON.parse? We want:
|
|
@@ -48117,7 +48223,87 @@ const getValidWidgetIds = perseusItem => {
|
|
|
48117
48223
|
* @returns {PerseusItem} the parsed PerseusItem object
|
|
48118
48224
|
*/
|
|
48119
48225
|
function parsePerseusItem(json) {
|
|
48120
|
-
|
|
48226
|
+
const randomPhrase = buildRandomPhrase();
|
|
48227
|
+
const randomHintPhrase = buildRandomPhrase();
|
|
48228
|
+
const randomString = buildRandomString();
|
|
48229
|
+
const testingObject = JSON.stringify({
|
|
48230
|
+
answerArea: {
|
|
48231
|
+
calculator: false,
|
|
48232
|
+
chi2Table: false,
|
|
48233
|
+
financialCalculatorMonthlyPayment: false,
|
|
48234
|
+
financialCalculatorTimeToPayOff: false,
|
|
48235
|
+
financialCalculatorTotalAmount: false,
|
|
48236
|
+
periodicTable: false,
|
|
48237
|
+
periodicTableWithKey: false,
|
|
48238
|
+
tTable: false,
|
|
48239
|
+
zTable: false
|
|
48240
|
+
},
|
|
48241
|
+
hints: [randomHintPhrase, `=${Math.floor(Math.random() * 50) + 1}`],
|
|
48242
|
+
itemDataVersion: {
|
|
48243
|
+
major: 0,
|
|
48244
|
+
minor: 1
|
|
48245
|
+
},
|
|
48246
|
+
question: {
|
|
48247
|
+
content: `${randomPhrase}`,
|
|
48248
|
+
images: {},
|
|
48249
|
+
widgets: {
|
|
48250
|
+
expression1: {
|
|
48251
|
+
alignment: "default",
|
|
48252
|
+
graded: false,
|
|
48253
|
+
options: {
|
|
48254
|
+
answerForms: [{
|
|
48255
|
+
considered: "wrong",
|
|
48256
|
+
form: false,
|
|
48257
|
+
key: 0,
|
|
48258
|
+
simplify: false,
|
|
48259
|
+
value: `${randomString}`
|
|
48260
|
+
}],
|
|
48261
|
+
ariaLabel: "Answer",
|
|
48262
|
+
buttonSets: ["basic"],
|
|
48263
|
+
functions: ["f", "g", "h"],
|
|
48264
|
+
static: true,
|
|
48265
|
+
times: false,
|
|
48266
|
+
visibleLabel: "Answer"
|
|
48267
|
+
},
|
|
48268
|
+
static: true,
|
|
48269
|
+
type: "expression",
|
|
48270
|
+
version: {
|
|
48271
|
+
major: 1,
|
|
48272
|
+
minor: 0
|
|
48273
|
+
}
|
|
48274
|
+
}
|
|
48275
|
+
}
|
|
48276
|
+
}
|
|
48277
|
+
});
|
|
48278
|
+
// @ts-expect-error TS2550: Property 'replaceAll' does not exist on type 'string'.
|
|
48279
|
+
const testJSON = buildTestData(testingObject.replaceAll('"', '\\"'));
|
|
48280
|
+
const parsedJSON = JSON.parse(testJSON);
|
|
48281
|
+
const parsedItemData = parsedJSON.data.assessmentItem.item.itemData;
|
|
48282
|
+
const isNotCheating = deepEq(parsedItemData, testingObject);
|
|
48283
|
+
if (isNotCheating) {
|
|
48284
|
+
return JSON.parse(json);
|
|
48285
|
+
}
|
|
48286
|
+
throw new Error("Something went wrong.");
|
|
48287
|
+
}
|
|
48288
|
+
function buildRandomString() {
|
|
48289
|
+
let randomString = "";
|
|
48290
|
+
const randomLength = Math.floor(Math.random() * 8) + 3;
|
|
48291
|
+
for (let i = 0; i < randomLength; i++) {
|
|
48292
|
+
const randomLetter = String.fromCharCode(97 + Math.floor(Math.random() * 26));
|
|
48293
|
+
randomString += randomLetter;
|
|
48294
|
+
}
|
|
48295
|
+
return randomString;
|
|
48296
|
+
}
|
|
48297
|
+
function buildRandomPhrase() {
|
|
48298
|
+
const phrases = [];
|
|
48299
|
+
const randomLength = Math.floor(Math.random() * 10) + 5;
|
|
48300
|
+
for (let i = 0; i < randomLength; i++) {
|
|
48301
|
+
phrases.push(buildRandomString());
|
|
48302
|
+
}
|
|
48303
|
+
return phrases.join(" ");
|
|
48304
|
+
}
|
|
48305
|
+
function buildTestData(testObject) {
|
|
48306
|
+
return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`;
|
|
48121
48307
|
}
|
|
48122
48308
|
|
|
48123
48309
|
const genericPerseusItemData = {
|
|
@@ -48319,5 +48505,5 @@ const EditorJsonify = {
|
|
|
48319
48505
|
}
|
|
48320
48506
|
};
|
|
48321
48507
|
|
|
48322
|
-
export { ApiOptions, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, dependencies as Dependencies, EditorJsonify, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAngleCoords, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getCorrectAnswerForWidgetId, getLineCoords, getLinearSystemCoords, getPointCoords, getPolygonCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, makeSafeUrl, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
48508
|
+
export { ApiOptions, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, dependencies as Dependencies, EditorJsonify, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAngleCoords, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getCorrectAnswerForWidgetId, getImagesWithoutAltData, getLineCoords, getLinearSystemCoords, getPointCoords, getPolygonCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, makeSafeUrl, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
48323
48509
|
//# sourceMappingURL=index.js.map
|