@khanacademy/perseus 36.0.0 → 36.1.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 +100 -11
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +97 -8
- package/dist/index.js.map +1 -1
- package/dist/util/extract-perseus-data.d.ts +11 -1
- package/dist/widgets/interactive-graphs/graphs/components/movable-point.d.ts +1 -1
- package/package.json +9 -9
package/dist/index.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ export { default as KhanColors } from "./util/colors";
|
|
|
61
61
|
export { default as preprocessTex } from "./util/tex-preprocess";
|
|
62
62
|
export { registerAllWidgetsForTesting } from "./util/register-all-widgets-for-testing";
|
|
63
63
|
export * as SizingUtils from "./util/sizing-utils";
|
|
64
|
-
export { getAnswersFromWidgets, injectWidgets, isWrongAnswerSupported, shouldHaveIndividualAnswer, isWidgetIdInContent, getValidWidgetIds, getCorrectAnswerForWidgetId, getAnswerFromUserInput, } from "./util/extract-perseus-data";
|
|
64
|
+
export { getAnswersFromWidgets, injectWidgets, isWrongAnswerSupported, shouldHaveIndividualAnswer, isWidgetIdInContent, getValidWidgetIds, getCorrectAnswerForWidgetId, getAnswerFromUserInput, getImagesWithoutAltData, } from "./util/extract-perseus-data";
|
|
65
65
|
export { parsePerseusItem } from "./util/parse-perseus-json";
|
|
66
66
|
export { generateTestPerseusItem, genericPerseusItemData, generateTestRadioWidget, generateTestInteractiveGraphWidget, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestNumericInputWidget, } from "./util/test-utils";
|
|
67
67
|
export { getWidgetTypeByWidgetId, contentHasWidgetType, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetsMapFromItemData, getWidgetFromWidgetMap, getWidgetsFromWidgetMap, } from "./widget-type-utils";
|
package/dist/index.js
CHANGED
|
@@ -33597,7 +33597,7 @@ function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, a
|
|
|
33597
33597
|
return scaledBisector;
|
|
33598
33598
|
}
|
|
33599
33599
|
|
|
33600
|
-
const MovablePoint$1 = props => {
|
|
33600
|
+
const MovablePoint$1 = /*#__PURE__*/React__namespace.forwardRef((props, pointRef) => {
|
|
33601
33601
|
const {
|
|
33602
33602
|
snapStep
|
|
33603
33603
|
} = useGraphConfig();
|
|
@@ -33620,7 +33620,21 @@ const MovablePoint$1 = props => {
|
|
|
33620
33620
|
constrainKeyboardMovement: constrain
|
|
33621
33621
|
});
|
|
33622
33622
|
return /*#__PURE__*/React__namespace.createElement(MovablePointView, {
|
|
33623
|
-
ref:
|
|
33623
|
+
ref: ref => {
|
|
33624
|
+
// Note: This handles the case where pointRef is either a
|
|
33625
|
+
// function or a MutableRefObject. Mostly this is to satisfy
|
|
33626
|
+
// the type system, the function branch seems to be the only
|
|
33627
|
+
// one that occurs
|
|
33628
|
+
if (typeof pointRef === "function") {
|
|
33629
|
+
pointRef(ref);
|
|
33630
|
+
} else if (pointRef !== null) {
|
|
33631
|
+
pointRef.current = ref;
|
|
33632
|
+
}
|
|
33633
|
+
|
|
33634
|
+
// This ref is for the useDraggable and is not passed up the
|
|
33635
|
+
// chain
|
|
33636
|
+
elementRef.current = ref;
|
|
33637
|
+
},
|
|
33624
33638
|
point: point,
|
|
33625
33639
|
color: color,
|
|
33626
33640
|
dragging: dragging,
|
|
@@ -33635,7 +33649,7 @@ const MovablePoint$1 = props => {
|
|
|
33635
33649
|
},
|
|
33636
33650
|
cursor: cursor
|
|
33637
33651
|
});
|
|
33638
|
-
};
|
|
33652
|
+
});
|
|
33639
33653
|
|
|
33640
33654
|
const PolygonGraph = props => {
|
|
33641
33655
|
const [hovered, setHovered] = React__namespace.useState(false);
|
|
@@ -34225,6 +34239,13 @@ function UnlimitedPointGraph(props) {
|
|
|
34225
34239
|
const height = maxY - minY;
|
|
34226
34240
|
const [[widthPx, heightPx]] = useTransformDimensionsToPixels([width, height]);
|
|
34227
34241
|
const [[left, top]] = useTransformVectorsToPixels([minX, maxY]);
|
|
34242
|
+
const itemsRef = React__namespace.useRef([]);
|
|
34243
|
+
React__namespace.useEffect(() => {
|
|
34244
|
+
const focusedIndex = props.graphState.focusedPointIndex;
|
|
34245
|
+
if (focusedIndex != null) {
|
|
34246
|
+
itemsRef.current[focusedIndex]?.focus();
|
|
34247
|
+
}
|
|
34248
|
+
}, [props.graphState.focusedPointIndex, itemsRef]);
|
|
34228
34249
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("rect", {
|
|
34229
34250
|
style: {
|
|
34230
34251
|
fill: "rgba(0,0,0,0)",
|
|
@@ -34245,12 +34266,23 @@ function UnlimitedPointGraph(props) {
|
|
|
34245
34266
|
key: i,
|
|
34246
34267
|
point: point,
|
|
34247
34268
|
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination)),
|
|
34269
|
+
ref: ref => {
|
|
34270
|
+
itemsRef.current[i] = ref;
|
|
34271
|
+
},
|
|
34248
34272
|
onFocusChange: (event, isFocused) => {
|
|
34249
34273
|
if (isFocused) {
|
|
34250
34274
|
dispatch(actions.pointGraph.focusPoint(i));
|
|
34251
34275
|
} else {
|
|
34252
34276
|
if (event.relatedTarget?.id === REMOVE_BUTTON_ID) {
|
|
34253
34277
|
return;
|
|
34278
|
+
// This is an optimization: If the next target
|
|
34279
|
+
// is a point then don't blur because it casues
|
|
34280
|
+
// the remove button to get taken off the page
|
|
34281
|
+
// and then put back on The new point will
|
|
34282
|
+
// receive focus and set the correct state in
|
|
34283
|
+
// the reducer
|
|
34284
|
+
} else if (event.relatedTarget?.classList.contains("movable-point")) {
|
|
34285
|
+
return;
|
|
34254
34286
|
}
|
|
34255
34287
|
dispatch(actions.pointGraph.blurPoint());
|
|
34256
34288
|
}
|
|
@@ -34425,11 +34457,17 @@ const MafsGraph = props => {
|
|
|
34425
34457
|
fullGraphAriaLabel,
|
|
34426
34458
|
fullGraphAriaDescription
|
|
34427
34459
|
} = props;
|
|
34460
|
+
const {
|
|
34461
|
+
type
|
|
34462
|
+
} = state;
|
|
34428
34463
|
const [width, height] = props.box;
|
|
34429
34464
|
const tickStep = props.step;
|
|
34430
34465
|
const uniqueId = React__namespace.useId();
|
|
34431
34466
|
const descriptionId = `interactive-graph-description-${uniqueId}`;
|
|
34432
34467
|
const graphRef = React__namespace.useRef(null);
|
|
34468
|
+
const {
|
|
34469
|
+
analytics
|
|
34470
|
+
} = useDependencies();
|
|
34433
34471
|
|
|
34434
34472
|
// Set up the SVG attributes for the nested SVGs that help lock
|
|
34435
34473
|
// the grid and graph elements to the bounds of the graph.
|
|
@@ -34449,6 +34487,14 @@ const MafsGraph = props => {
|
|
|
34449
34487
|
const {
|
|
34450
34488
|
strings
|
|
34451
34489
|
} = usePerseusI18n();
|
|
34490
|
+
wonderBlocksCore.useOnMountEffect(() => {
|
|
34491
|
+
analytics.onAnalyticsEvent({
|
|
34492
|
+
type: "perseus:interactive-graph-widget:rendered",
|
|
34493
|
+
payload: {
|
|
34494
|
+
type
|
|
34495
|
+
}
|
|
34496
|
+
});
|
|
34497
|
+
});
|
|
34452
34498
|
return /*#__PURE__*/React__namespace.createElement(GraphConfigContext.Provider, {
|
|
34453
34499
|
value: {
|
|
34454
34500
|
range: state.range,
|
|
@@ -35233,11 +35279,14 @@ function doFocusPoint(state, action) {
|
|
|
35233
35279
|
function doBlurPoint(state, action) {
|
|
35234
35280
|
switch (state.type) {
|
|
35235
35281
|
case "point":
|
|
35236
|
-
|
|
35282
|
+
const nextState = {
|
|
35237
35283
|
...state,
|
|
35238
|
-
focusedPointIndex: null,
|
|
35239
35284
|
showRemovePointButton: false
|
|
35240
35285
|
};
|
|
35286
|
+
if (state.interactionMode === "mouse") {
|
|
35287
|
+
nextState.focusedPointIndex = null;
|
|
35288
|
+
}
|
|
35289
|
+
return nextState;
|
|
35241
35290
|
default:
|
|
35242
35291
|
return state;
|
|
35243
35292
|
}
|
|
@@ -35640,17 +35689,24 @@ function doAddPoint(state, action) {
|
|
|
35640
35689
|
...state,
|
|
35641
35690
|
hasBeenInteractedWith: true,
|
|
35642
35691
|
coords: [...state.coords, snappedPoint],
|
|
35643
|
-
showRemovePointButton: false
|
|
35692
|
+
showRemovePointButton: false,
|
|
35693
|
+
focusedPointIndex: state.coords.length
|
|
35644
35694
|
};
|
|
35645
35695
|
}
|
|
35646
35696
|
function doRemovePoint(state, action) {
|
|
35647
35697
|
if (state.type !== "point") {
|
|
35648
35698
|
return state;
|
|
35649
35699
|
}
|
|
35700
|
+
let nextFocusedPointIndex;
|
|
35701
|
+
if (state.interactionMode === "mouse") {
|
|
35702
|
+
nextFocusedPointIndex = null;
|
|
35703
|
+
} else {
|
|
35704
|
+
nextFocusedPointIndex = state.coords.length > 1 ? state.coords.length - 2 : null;
|
|
35705
|
+
}
|
|
35650
35706
|
return {
|
|
35651
35707
|
...state,
|
|
35652
35708
|
coords: state.coords.filter((_, i) => i !== action.index),
|
|
35653
|
-
focusedPointIndex:
|
|
35709
|
+
focusedPointIndex: nextFocusedPointIndex,
|
|
35654
35710
|
showRemovePointButton: false
|
|
35655
35711
|
};
|
|
35656
35712
|
}
|
|
@@ -45238,7 +45294,7 @@ const init = function (options) {
|
|
|
45238
45294
|
|
|
45239
45295
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45240
45296
|
const libName = "@khanacademy/perseus";
|
|
45241
|
-
const libVersion = "36.
|
|
45297
|
+
const libVersion = "36.1.0";
|
|
45242
45298
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45243
45299
|
|
|
45244
45300
|
const apiVersion = {
|
|
@@ -48426,6 +48482,38 @@ function injectWidgets(content, widgets, widgetProps) {
|
|
|
48426
48482
|
return context;
|
|
48427
48483
|
}
|
|
48428
48484
|
|
|
48485
|
+
/**
|
|
48486
|
+
* Looks through widgets to identify images that do not have alt text.
|
|
48487
|
+
*
|
|
48488
|
+
* We pass in the fuller perseusRenderer object to allow for the possibility
|
|
48489
|
+
* of expanding to include other img data from content & images in the future.
|
|
48490
|
+
*
|
|
48491
|
+
* @param {PerseusRenderer} perseusRenderer
|
|
48492
|
+
* @returns a stringified list of {widgetId, imageUrl} for imgs that don't have alt text
|
|
48493
|
+
*/
|
|
48494
|
+
function getImagesWithoutAltData(perseusRenderer) {
|
|
48495
|
+
if (!perseusRenderer.widgets) {
|
|
48496
|
+
return "";
|
|
48497
|
+
}
|
|
48498
|
+
const imgsWithoutAltData = [];
|
|
48499
|
+
Object.entries(perseusRenderer.widgets).forEach(_ref3 => {
|
|
48500
|
+
let [widgetId, widget] = _ref3;
|
|
48501
|
+
if (!widget.options) {
|
|
48502
|
+
return;
|
|
48503
|
+
}
|
|
48504
|
+
|
|
48505
|
+
// Add to imagesWithoutAltData if img alt is missing and
|
|
48506
|
+
// image has valid img url data.
|
|
48507
|
+
if (widget.type === "image" && !widget.options.alt && widget.options.backgroundImage?.url) {
|
|
48508
|
+
imgsWithoutAltData.push({
|
|
48509
|
+
widgetId,
|
|
48510
|
+
imgUrl: widget.options.backgroundImage.url
|
|
48511
|
+
});
|
|
48512
|
+
}
|
|
48513
|
+
});
|
|
48514
|
+
return JSON.stringify(imgsWithoutAltData);
|
|
48515
|
+
}
|
|
48516
|
+
|
|
48429
48517
|
/* Widgets that have individual answers */
|
|
48430
48518
|
const INDIVIDUAL_ANSWER_WIDGETS = ["interactive-graph", "categorizer", "grapher"];
|
|
48431
48519
|
|
|
@@ -48758,6 +48846,7 @@ exports.getAnswerFromUserInput = getAnswerFromUserInput;
|
|
|
48758
48846
|
exports.getAnswersFromWidgets = getAnswersFromWidgets;
|
|
48759
48847
|
exports.getCircleCoords = getCircleCoords;
|
|
48760
48848
|
exports.getCorrectAnswerForWidgetId = getCorrectAnswerForWidgetId;
|
|
48849
|
+
exports.getImagesWithoutAltData = getImagesWithoutAltData;
|
|
48761
48850
|
exports.getLineCoords = getLineCoords;
|
|
48762
48851
|
exports.getLinearSystemCoords = getLinearSystemCoords;
|
|
48763
48852
|
exports.getPointCoords = getPointCoords;
|