@khanacademy/perseus 56.1.0 → 57.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 CHANGED
@@ -16542,7 +16542,7 @@ Zoomable.defaultProps = {
16542
16542
  * measurements.
16543
16543
  */
16544
16544
  const computeMathBounds = (parentNode, parentBounds) => {
16545
- const textElement = parentNode.querySelector(".katex-html") || parentNode.querySelector(".MathJax");
16545
+ const textElement = parentNode.querySelector(".MathJax");
16546
16546
  const textBounds = {
16547
16547
  // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'offsetWidth' does not exist on type 'Element'.
16548
16548
  width: textElement.offsetWidth,
@@ -18020,17 +18020,6 @@ class WidgetContainer extends React.Component {
18020
18020
  widget_id: this.props.id
18021
18021
  },
18022
18022
  onError: error => {
18023
- // TODO(LEMS-2826): Remove analytics event in LEMS-2826 in favor of ti below.
18024
- analytics.onAnalyticsEvent({
18025
- type: "perseus:widget-rendering-error",
18026
- payload: {
18027
- widgetSubType: subType,
18028
- widgetType: type,
18029
- widgetId: this.props.id,
18030
- message: error.message,
18031
- userAgent: userAgent
18032
- }
18033
- });
18034
18023
  analytics.onAnalyticsEvent({
18035
18024
  type: "perseus:widget-rendering-error:ti",
18036
18025
  payload: {
@@ -18636,14 +18625,7 @@ class Renderer extends React.Component {
18636
18625
  }, content)))));
18637
18626
  }
18638
18627
  if (node.type === "math") {
18639
- // Replace uses of \begin{align}...\end{align} which KaTeX doesn't
18640
- // support (yet) with \begin{aligned}...\end{aligned} which renders
18641
- // the same is supported by KaTeX. It does the same for align*.
18642
- // TODO(kevinb) update content to use aligned instead of align.
18643
- // TODO(LEMS-1608) Remove this replacement as MathJax supports the
18644
- // "align" macro correctly (and, in fact, it is not synonymous with
18645
- // "aligned").
18646
- const tex = node.content.replace(/\{align[*]?\}/g, "{aligned}");
18628
+ const tex = node.content;
18647
18629
 
18648
18630
  // We render math here instead of in perseus-markdown.jsx
18649
18631
  // because we need to pass it our onRender callback.
@@ -24025,7 +24007,8 @@ const _choiceTransform = (widgetOptions, strings, problemNum) => {
24025
24007
  // Add meta-information to choices
24026
24008
  const choices = widgetOptions.choices.map((choice, i) => {
24027
24009
  return _extends({}, choice, {
24028
- originalIndex: i
24010
+ originalIndex: i,
24011
+ correct: Boolean(choice.correct)
24029
24012
  });
24030
24013
  });
24031
24014
 
@@ -25015,7 +24998,7 @@ class GradedGroupAnswerBar extends React.Component {
25015
24998
  }
25016
24999
  }
25017
25000
  GradedGroupAnswerBar.contextType = PerseusI18nContext;
25018
- const fontSize = 17;
25001
+ const fontSize$1 = 17;
25019
25002
  const styles$j = {
25020
25003
  answerBar: {
25021
25004
  display: "flex",
@@ -25040,7 +25023,7 @@ const styles$j = {
25040
25023
  flexDirection: "row",
25041
25024
  alignItems: "center",
25042
25025
  fontWeight: "bold",
25043
- fontSize: fontSize
25026
+ fontSize: fontSize$1
25044
25027
  }
25045
25028
  };
25046
25029
 
@@ -27696,6 +27679,7 @@ const defaultGraphConfig = {
27696
27679
  width: 0,
27697
27680
  height: 0,
27698
27681
  labels: [],
27682
+ labelLocation: "onAxis",
27699
27683
  disableKeyboardInteraction: false,
27700
27684
  interactiveColor: "var(--mafs-blue)"
27701
27685
  };
@@ -27911,6 +27895,8 @@ function escapeIfUnescaped(character) {
27911
27895
  }
27912
27896
  }
27913
27897
 
27898
+ // Exported for testing purposes
27899
+ const fontSize = 14;
27914
27900
  function AxisLabels({
27915
27901
  i18n
27916
27902
  }) {
@@ -27918,24 +27904,26 @@ function AxisLabels({
27918
27904
  range,
27919
27905
  labels,
27920
27906
  width,
27921
- height
27907
+ height,
27908
+ labelLocation
27922
27909
  } = useGraphConfig();
27923
27910
  const {
27924
27911
  strings
27925
27912
  } = i18n;
27926
- const yAxisLabelLocation = [0, range[Y][MAX]];
27927
- const xAxisLabelLocation = [range[X][MAX], 0];
27928
- const [xAxisLabelText, yAxisLabelText] = labels;
27929
27913
  const graphInfo = {
27930
27914
  range,
27931
27915
  width,
27932
27916
  height
27933
27917
  };
27934
- const [x1, y1] = pointToPixel(xAxisLabelLocation, graphInfo);
27935
- // The default location for the y-axis-label is at the maximum y point
27936
- // This is just underneath the tick line for that point. The -24 moves the
27937
- // label up one grid square, so it sits on top of the graph
27938
- const [x2, y2] = vec.add(pointToPixel(yAxisLabelLocation, graphInfo), [0, -24]);
27918
+
27919
+ // Get the position of the main axis labels
27920
+ const [xAxisLabelLocation, yAxisLabelLocation] = getLabelPosition(graphInfo, labelLocation);
27921
+ const [xAxisLabelText, yAxisLabelText] = labels;
27922
+
27923
+ // If the labels are rotated, we need to center the
27924
+ // x-axis label along the bottom of the graph.
27925
+ const xLabelTransform = labelLocation === "onAxis" ? "translate(7px, -50%)" : "translate(-50%, -50%)";
27926
+ const yLabelTransform = labelLocation === "onAxis" ? "translate(-50%, 0px)" : "translate(-50%, 0px) rotate(-90deg)";
27939
27927
  const {
27940
27928
  TeX
27941
27929
  } = getDependencies();
@@ -27943,22 +27931,53 @@ function AxisLabels({
27943
27931
  "aria-label": strings.xAxis,
27944
27932
  style: {
27945
27933
  position: "absolute",
27946
- left: x1,
27947
- top: y1,
27948
- fontSize: "14px",
27949
- transform: "translate(7px, -50%)"
27934
+ left: xAxisLabelLocation[X],
27935
+ top: xAxisLabelLocation[Y],
27936
+ fontSize: fontSize + "px",
27937
+ transform: xLabelTransform
27950
27938
  }
27951
27939
  }, /*#__PURE__*/React__default.createElement(TeX, null, replaceOutsideTeX(xAxisLabelText))), /*#__PURE__*/React__default.createElement("span", {
27952
27940
  "aria-label": strings.yAxis,
27953
27941
  style: {
27954
27942
  position: "absolute",
27955
- left: x2,
27956
- top: y2,
27957
- fontSize: "14px",
27958
- transform: "translate(-50%, 0px)"
27943
+ left: yAxisLabelLocation[X],
27944
+ top: yAxisLabelLocation[Y],
27945
+ fontSize: fontSize + "px",
27946
+ transform: yLabelTransform
27959
27947
  }
27960
27948
  }, /*#__PURE__*/React__default.createElement(TeX, null, replaceOutsideTeX(yAxisLabelText))));
27961
27949
  }
27950
+ const getLabelPosition = (graphInfo, labelLocation) => {
27951
+ // If the labels are placed along the edge of the graph, we need to place them at the
27952
+ // center of the graph, which is the average of the min and max values of the axes.
27953
+ if (labelLocation === "alongEdge") {
27954
+ // Offset the labels by a certain amount based on the range of the graph, to ensure that
27955
+ // the labels do not overlap with the axis tick if they are out of the graph bounds.
27956
+ const xAxisLabelOffset = graphInfo.range[Y][MIN] >= 0 ? [0, fontSize * 3] // Move the label down by 3 font sizes if the y-axis min is positive
27957
+ : [0, fontSize]; // Move the label down by 1 font size if the y-axis min is negative
27958
+ const yAxisLabelOffset = graphInfo.range[X][MIN] >= 0 ? [-fontSize * 3, -fontSize] // Move the label left by 3 font sizes if the x-axis min is positive
27959
+ : [-fontSize, -fontSize]; // Move the label left by 1 font size if the x-axis min is negative
27960
+
27961
+ // Calculate the location of the labels to be halfway between the min and max values of the axes
27962
+ const xAxisLabelLocation = [(graphInfo.range[X][MIN] + graphInfo.range[X][MAX]) / 2, graphInfo.range[Y][MIN]];
27963
+ const yAxisLabelLocation = [graphInfo.range[X][MIN], (graphInfo.range[Y][MIN] + graphInfo.range[Y][MAX]) / 2];
27964
+
27965
+ // Convert the Vector2 coordinates to pixel coordinates and add the offsets
27966
+ const _xLabel = vec.add(pointToPixel(xAxisLabelLocation, graphInfo), xAxisLabelOffset);
27967
+ const _yLabel = vec.add(pointToPixel(yAxisLabelLocation, graphInfo), yAxisLabelOffset);
27968
+ return [_xLabel, _yLabel];
27969
+ }
27970
+
27971
+ // Otherwise, the labels are placed on the axes (default), and we need to
27972
+ // place them at the end of the axis, which is the maximum value of the axis.
27973
+ const xLabelInitial = [graphInfo.range[X][MAX], 0];
27974
+ const yLabelInitial = [0, graphInfo.range[Y][MAX]];
27975
+ const yLabelOffset = [0, -fontSize * 2]; // Move the y-axis label up by 2 font sizes
27976
+
27977
+ const xLabel = pointToPixel(xLabelInitial, graphInfo);
27978
+ const yLabel = vec.add(pointToPixel(yLabelInitial, graphInfo), yLabelOffset);
27979
+ return [xLabel, yLabel];
27980
+ };
27962
27981
 
27963
27982
  // The size of the ticks and labels in pixels
27964
27983
  const tickSize = 10;
@@ -29860,7 +29879,7 @@ const PolygonAngle = ({
29860
29879
  }), /*#__PURE__*/React.createElement("feComposite", {
29861
29880
  operator: "over",
29862
29881
  in: "SourceGraphic"
29863
- }))), !isOutside && isRightAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
29882
+ }))), !isOutside && isRightPolygonAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
29864
29883
  start: [x1, y1],
29865
29884
  vertex: [x2, y2],
29866
29885
  end: [x3, y3]
@@ -34208,6 +34227,7 @@ const MafsGraph = props => {
34208
34227
  state,
34209
34228
  dispatch,
34210
34229
  labels,
34230
+ labelLocation,
34211
34231
  readOnly,
34212
34232
  fullGraphAriaLabel,
34213
34233
  fullGraphAriaDescription
@@ -34288,6 +34308,7 @@ const MafsGraph = props => {
34288
34308
  width,
34289
34309
  height,
34290
34310
  labels,
34311
+ labelLocation,
34291
34312
  disableKeyboardInteraction: disableInteraction,
34292
34313
  // If the graph is read-only or static, we want to make it
34293
34314
  // visually clear that the graph is no longer interactive.
@@ -41399,7 +41420,7 @@ const addLibraryVersionToPerseusDebug = (libraryName, libraryVersion) => {
41399
41420
 
41400
41421
  // This file is processed by a Rollup plugin (replace) to inject the production
41401
41422
  const libName = "@khanacademy/perseus";
41402
- const libVersion = "56.1.0";
41423
+ const libVersion = "57.0.0";
41403
41424
  addLibraryVersionToPerseusDebug(libName, libVersion);
41404
41425
 
41405
41426
  const apiVersion = {