@khanacademy/perseus 49.0.1 → 49.0.3

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
@@ -244,11 +244,11 @@ const mockStrings = {
244
244
  tan: "tan",
245
245
  simulationLoadFail: "Sorry, this simulation cannot load.",
246
246
  simulationLocaleWarning: "Sorry, this simulation isn't available in your language.",
247
- addPoint: "Add Point",
248
- removePoint: "Remove Point",
249
- graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
250
247
  selectAnAnswer: "Select an answer",
251
248
  // The following strings are used for interactive graph SR descriptions.
249
+ graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
250
+ addPoint: "Add Point",
251
+ removePoint: "Remove Point",
252
252
  closePolygon: "Close shape",
253
253
  openPolygon: "Re-open shape",
254
254
  srPointAtCoordinates: ({
@@ -260,19 +260,19 @@ const mockStrings = {
260
260
  elements
261
261
  }) => `Interactive elements: ${elements}`,
262
262
  srNoInteractiveElements: "No interactive elements",
263
- circleGraphAriaLabel: "A circle on a coordinate plane.",
264
- circleShapeAriaLabel: ({
263
+ srCircleGraph: "A circle on a coordinate plane.",
264
+ srCircleShape: ({
265
265
  centerX,
266
266
  centerY
267
267
  }) => `Circle. The center point is at ${centerX} comma ${centerY}.`,
268
- circleRadiusPointAriaLabel: ({
268
+ srCircleRadiusPoint: ({
269
269
  radiusPointX,
270
270
  radiusPointY
271
271
  }) => `Radius point at ${radiusPointX} comma ${radiusPointY}.`,
272
- circleRadiusDescription: ({
272
+ srCircleRadius: ({
273
273
  radius
274
274
  }) => `Circle radius is ${radius}.`,
275
- circleOuterPointsDescription: ({
275
+ srCircleOuterPoints: ({
276
276
  point1X,
277
277
  point1Y,
278
278
  point2X,
@@ -281,7 +281,29 @@ const mockStrings = {
281
281
  point3Y,
282
282
  point4X,
283
283
  point4Y
284
- }) => `Points on the circle at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, ${point3X} comma ${point3Y}, ${point4X} comma ${point4Y}.`
284
+ }) => `Points on the circle at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, ${point3X} comma ${point3Y}, ${point4X} comma ${point4Y}.`,
285
+ srLinearGraph: "A line on a coordinate plane.",
286
+ srLinearGraphPoints: ({
287
+ point1X,
288
+ point1Y,
289
+ point2X,
290
+ point2Y
291
+ }) => `The line has two points, point 1 at ${point1X} comma ${point1Y} and point 2 at ${point2X} comma ${point2Y}.`,
292
+ srLinearGraphSlopeIncreasing: "Its slope increases from left to right.",
293
+ srLinearGraphSlopeDecreasing: "Its slope decreases from left to right.",
294
+ srLinearGraphSlopeHorizontal: "Its slope is zero.",
295
+ srLinearGraphSlopeVertical: "Its slope is undefined.",
296
+ srLinearGraphXOnlyIntercept: ({
297
+ xIntercept
298
+ }) => `The line crosses the X-axis at ${xIntercept} comma 0.`,
299
+ srLinearGraphYOnlyIntercept: ({
300
+ yIntercept
301
+ }) => `The line crosses the Y-axis at 0 comma ${yIntercept}.`,
302
+ srLinearGraphBothIntercepts: ({
303
+ xIntercept,
304
+ yIntercept
305
+ }) => `The line crosses the X-axis at ${xIntercept} comma 0 and the Y-axis at 0 comma ${yIntercept}.`,
306
+ srLinearGraphOriginIntercept: "The line crosses the x and y axes at the graph's origin."
285
307
  // The above strings are used for interactive graph SR descriptions.
286
308
  };
287
309
 
@@ -27376,11 +27398,21 @@ class Dropdown extends React.Component {
27376
27398
  key: "placeholder",
27377
27399
  value: "0",
27378
27400
  disabled: true,
27379
- label: this.props.placeholder || " "
27401
+ label: /*#__PURE__*/React.createElement(Renderer, {
27402
+ content: this.props.placeholder,
27403
+ strings: this.context.strings,
27404
+ inline: true
27405
+ }),
27406
+ labelAsText: this.props.placeholder
27380
27407
  }), ...this.props.choices.map((choice, i) => /*#__PURE__*/React.createElement(OptionItem, {
27381
27408
  key: String(i + 1),
27382
27409
  value: String(i + 1),
27383
- label: choice
27410
+ label: /*#__PURE__*/React.createElement(Renderer, {
27411
+ content: choice,
27412
+ strings: this.context.strings,
27413
+ inline: true
27414
+ }),
27415
+ labelAsText: choice
27384
27416
  }))];
27385
27417
  return /*#__PURE__*/React.createElement(Id, null, dropdownId => /*#__PURE__*/React.createElement(View
27386
27418
  // NOTE(jared): These are required to prevent weird behavior
@@ -27407,7 +27439,8 @@ class Dropdown extends React.Component {
27407
27439
  // all dropdowns.
27408
27440
  // See https://khanacademy.atlassian.net/browse/WB-1671
27409
27441
  ,
27410
- role: "combobox"
27442
+ role: "combobox",
27443
+ showOpenerLabelAsText: false
27411
27444
  }, children)));
27412
27445
  }
27413
27446
  }
@@ -33817,6 +33850,8 @@ const noop$1 = () => {};
33817
33850
 
33818
33851
  const MovableLine = props => {
33819
33852
  const {
33853
+ ariaLabels,
33854
+ ariaDescribedBy,
33820
33855
  onMoveLine = () => {},
33821
33856
  onMovePoint = () => {},
33822
33857
  color,
@@ -33839,6 +33874,8 @@ const MovableLine = props => {
33839
33874
  visiblePoint: visiblePoint1,
33840
33875
  focusableHandle: focusableHandle1
33841
33876
  } = useControlPoint({
33877
+ ariaLabel: ariaLabels == null ? void 0 : ariaLabels.point1AriaLabel,
33878
+ ariaDescribedBy: ariaDescribedBy,
33842
33879
  point: start,
33843
33880
  sequenceNumber: 1,
33844
33881
  color,
@@ -33848,6 +33885,8 @@ const MovableLine = props => {
33848
33885
  visiblePoint: visiblePoint2,
33849
33886
  focusableHandle: focusableHandle2
33850
33887
  } = useControlPoint({
33888
+ ariaLabel: ariaLabels == null ? void 0 : ariaLabels.point2AriaLabel,
33889
+ ariaDescribedBy: ariaDescribedBy,
33851
33890
  point: end,
33852
33891
  sequenceNumber: 2,
33853
33892
  color,
@@ -34121,6 +34160,12 @@ function getGradableGraph(state, initialGraph) {
34121
34160
  });
34122
34161
  }
34123
34162
  if (state.type === "point" && initialGraph.type === "point") {
34163
+ // The unlimited point graph must have at least 1 coordinate or else it is not considered score-able.
34164
+ if (state.numPoints === "unlimited" && state.coords.length === 0) {
34165
+ return _extends({}, initialGraph, {
34166
+ coords: null
34167
+ });
34168
+ }
34124
34169
  return _extends({}, initialGraph, {
34125
34170
  coords: state.coords
34126
34171
  });
@@ -34194,7 +34239,8 @@ function CircleGraph(props) {
34194
34239
  radiusPoint
34195
34240
  } = graphState;
34196
34241
  const {
34197
- strings
34242
+ strings,
34243
+ locale
34198
34244
  } = usePerseusI18n();
34199
34245
  const [radiusPointAriaLive, setRadiusPointAriaLive] = React.useState("off");
34200
34246
  const radius = getRadius(graphState);
@@ -34204,27 +34250,27 @@ function CircleGraph(props) {
34204
34250
  const outerPointsId = id + "-outer-points";
34205
34251
 
34206
34252
  // Aria label strings
34207
- const circleGraphAriaLabel = strings.circleGraphAriaLabel;
34208
- const circleShapeAriaLabel = strings.circleShapeAriaLabel({
34209
- centerX: center[0],
34210
- centerY: center[1]
34253
+ const circleGraphAriaLabel = strings.srCircleGraph;
34254
+ const circleShapeAriaLabel = strings.srCircleShape({
34255
+ centerX: srFormatNumber(center[0], locale),
34256
+ centerY: srFormatNumber(center[1], locale)
34211
34257
  });
34212
- const circleRadiusPointAriaLabel = strings.circleRadiusPointAriaLabel({
34213
- radiusPointX: radiusPoint[0],
34214
- radiusPointY: radiusPoint[1]
34258
+ const circleRadiusPointAriaLabel = strings.srCircleRadiusPoint({
34259
+ radiusPointX: srFormatNumber(radiusPoint[0], locale),
34260
+ radiusPointY: srFormatNumber(radiusPoint[1], locale)
34215
34261
  });
34216
- const circleRadiusDescription = strings.circleRadiusDescription({
34262
+ const circleRadiusDescription = strings.srCircleRadius({
34217
34263
  radius
34218
34264
  });
34219
- const circleOuterPointsDescription = strings.circleOuterPointsDescription({
34220
- point1X: center[0] + radius,
34221
- point1Y: center[1],
34222
- point2X: center[0],
34223
- point2Y: center[1] + radius,
34224
- point3X: center[0] - radius,
34225
- point3Y: center[1],
34226
- point4X: center[0],
34227
- point4Y: center[1] - radius
34265
+ const circleOuterPointsDescription = strings.srCircleOuterPoints({
34266
+ point1X: srFormatNumber(center[0] + radius, locale),
34267
+ point1Y: srFormatNumber(center[1], locale),
34268
+ point2X: srFormatNumber(center[0], locale),
34269
+ point2Y: srFormatNumber(center[1] + radius, locale),
34270
+ point3X: srFormatNumber(center[0] - radius, locale),
34271
+ point3Y: srFormatNumber(center[1], locale),
34272
+ point4X: srFormatNumber(center[0], locale),
34273
+ point4Y: srFormatNumber(center[1] - radius, locale)
34228
34274
  });
34229
34275
  return /*#__PURE__*/React.createElement("g", {
34230
34276
  // Outer circle minimal description
@@ -34380,12 +34426,67 @@ const LinearGraph = (props, key) => {
34380
34426
  const {
34381
34427
  coords: line
34382
34428
  } = props.graphState;
34429
+ const {
34430
+ strings,
34431
+ locale
34432
+ } = usePerseusI18n();
34433
+ const id = React.useId();
34434
+ const pointsDescriptionId = id + "-points";
34435
+ const interceptDescriptionId = id + "-intercept";
34436
+ const slopeDescriptionId = id + "-slope";
34437
+
34438
+ // Aria label strings
34439
+ const linearGraphPointsDescription = strings.srLinearGraphPoints({
34440
+ point1X: srFormatNumber(line[0][0], locale),
34441
+ point1Y: srFormatNumber(line[0][1], locale),
34442
+ point2X: srFormatNumber(line[1][0], locale),
34443
+ point2Y: srFormatNumber(line[1][1], locale)
34444
+ });
34445
+
34446
+ // Slope description
34447
+ const slope = (line[1][1] - line[0][1]) / (line[1][0] - line[0][0]);
34448
+ let slopeString = "";
34449
+ if (slope === Infinity || slope === -Infinity) {
34450
+ slopeString = strings.srLinearGraphSlopeVertical;
34451
+ } else if (slope === 0) {
34452
+ slopeString = strings.srLinearGraphSlopeHorizontal;
34453
+ } else {
34454
+ slopeString = slope > 0 ? strings.srLinearGraphSlopeIncreasing : strings.srLinearGraphSlopeDecreasing;
34455
+ }
34456
+
34457
+ // Intersection description
34458
+ const xIntercept = (0 - line[0][1]) / slope + line[0][0];
34459
+ const yIntercept = line[0][1] - slope * line[0][0];
34460
+ const hasXIntercept = xIntercept !== Infinity && xIntercept !== -Infinity;
34461
+ const hasYIntercept = yIntercept !== Infinity && yIntercept !== -Infinity;
34462
+ let interceptString;
34463
+ if (hasXIntercept && hasYIntercept) {
34464
+ // Describe both intercepts in the same sentence.
34465
+ interceptString = xIntercept === 0 && yIntercept === 0 ? strings.srLinearGraphOriginIntercept : strings.srLinearGraphBothIntercepts({
34466
+ xIntercept: srFormatNumber(xIntercept, locale),
34467
+ yIntercept: srFormatNumber(yIntercept, locale)
34468
+ });
34469
+ } else {
34470
+ // Describe only one intercept.
34471
+ interceptString = hasXIntercept ? strings.srLinearGraphXOnlyIntercept({
34472
+ xIntercept: srFormatNumber(xIntercept, locale)
34473
+ }) : strings.srLinearGraphYOnlyIntercept({
34474
+ yIntercept: srFormatNumber(yIntercept, locale)
34475
+ });
34476
+ }
34383
34477
 
34384
34478
  // Linear graphs only have one line
34385
34479
  // (LEMS-2050): Update the reducer so that we have a separate action for moving one line
34386
34480
  // and another action for moving multiple lines
34387
- return /*#__PURE__*/React.createElement(MovableLine, {
34481
+ return /*#__PURE__*/React.createElement("g", {
34482
+ className: "linear-graph-container"
34483
+ // Outer line minimal description
34484
+ ,
34485
+ "aria-label": strings.srLinearGraph,
34486
+ "aria-describedby": `${pointsDescriptionId} ${interceptDescriptionId} ${slopeDescriptionId}`
34487
+ }, /*#__PURE__*/React.createElement(MovableLine, {
34388
34488
  key: 0,
34489
+ ariaDescribedBy: `${interceptDescriptionId} ${slopeDescriptionId}`,
34389
34490
  points: line,
34390
34491
  onMoveLine: delta => {
34391
34492
  dispatch(actions.linear.moveLine(delta));
@@ -34396,7 +34497,22 @@ const LinearGraph = (props, key) => {
34396
34497
  },
34397
34498
  onMovePoint: (endpointIndex, destination) => dispatch(actions.linear.movePoint(endpointIndex, destination)),
34398
34499
  color: "var(--movable-line-stroke-color)"
34399
- });
34500
+ }), /*#__PURE__*/React.createElement("g", {
34501
+ id: pointsDescriptionId,
34502
+ style: {
34503
+ display: "hidden"
34504
+ }
34505
+ }, linearGraphPointsDescription), /*#__PURE__*/React.createElement("g", {
34506
+ id: interceptDescriptionId,
34507
+ style: {
34508
+ display: "hidden"
34509
+ }
34510
+ }, interceptString), /*#__PURE__*/React.createElement("g", {
34511
+ id: slopeDescriptionId,
34512
+ style: {
34513
+ display: "hidden"
34514
+ }
34515
+ }, slopeString));
34400
34516
  };
34401
34517
 
34402
34518
  function renderLinearSystemGraph(state, dispatch) {
@@ -45315,7 +45431,7 @@ const init = function init() {
45315
45431
 
45316
45432
  // This file is processed by a Rollup plugin (replace) to inject the production
45317
45433
  const libName = "@khanacademy/perseus";
45318
- const libVersion = "49.0.1";
45434
+ const libVersion = "49.0.3";
45319
45435
  addLibraryVersionToPerseusDebug(libName, libVersion);
45320
45436
 
45321
45437
  const apiVersion = {