@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/index.js CHANGED
@@ -365,11 +365,11 @@ const mockStrings = {
365
365
  tan: "tan",
366
366
  simulationLoadFail: "Sorry, this simulation cannot load.",
367
367
  simulationLocaleWarning: "Sorry, this simulation isn't available in your language.",
368
- addPoint: "Add Point",
369
- removePoint: "Remove Point",
370
- graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
371
368
  selectAnAnswer: "Select an answer",
372
369
  // The following strings are used for interactive graph SR descriptions.
370
+ graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
371
+ addPoint: "Add Point",
372
+ removePoint: "Remove Point",
373
373
  closePolygon: "Close shape",
374
374
  openPolygon: "Re-open shape",
375
375
  srPointAtCoordinates: _ref27 => {
@@ -387,28 +387,28 @@ const mockStrings = {
387
387
  return `Interactive elements: ${elements}`;
388
388
  },
389
389
  srNoInteractiveElements: "No interactive elements",
390
- circleGraphAriaLabel: "A circle on a coordinate plane.",
391
- circleShapeAriaLabel: _ref29 => {
390
+ srCircleGraph: "A circle on a coordinate plane.",
391
+ srCircleShape: _ref29 => {
392
392
  let {
393
393
  centerX,
394
394
  centerY
395
395
  } = _ref29;
396
396
  return `Circle. The center point is at ${centerX} comma ${centerY}.`;
397
397
  },
398
- circleRadiusPointAriaLabel: _ref30 => {
398
+ srCircleRadiusPoint: _ref30 => {
399
399
  let {
400
400
  radiusPointX,
401
401
  radiusPointY
402
402
  } = _ref30;
403
403
  return `Radius point at ${radiusPointX} comma ${radiusPointY}.`;
404
404
  },
405
- circleRadiusDescription: _ref31 => {
405
+ srCircleRadius: _ref31 => {
406
406
  let {
407
407
  radius
408
408
  } = _ref31;
409
409
  return `Circle radius is ${radius}.`;
410
410
  },
411
- circleOuterPointsDescription: _ref32 => {
411
+ srCircleOuterPoints: _ref32 => {
412
412
  let {
413
413
  point1X,
414
414
  point1Y,
@@ -420,7 +420,41 @@ const mockStrings = {
420
420
  point4Y
421
421
  } = _ref32;
422
422
  return `Points on the circle at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, ${point3X} comma ${point3Y}, ${point4X} comma ${point4Y}.`;
423
- }
423
+ },
424
+ srLinearGraph: "A line on a coordinate plane.",
425
+ srLinearGraphPoints: _ref33 => {
426
+ let {
427
+ point1X,
428
+ point1Y,
429
+ point2X,
430
+ point2Y
431
+ } = _ref33;
432
+ return `The line has two points, point 1 at ${point1X} comma ${point1Y} and point 2 at ${point2X} comma ${point2Y}.`;
433
+ },
434
+ srLinearGraphSlopeIncreasing: "Its slope increases from left to right.",
435
+ srLinearGraphSlopeDecreasing: "Its slope decreases from left to right.",
436
+ srLinearGraphSlopeHorizontal: "Its slope is zero.",
437
+ srLinearGraphSlopeVertical: "Its slope is undefined.",
438
+ srLinearGraphXOnlyIntercept: _ref34 => {
439
+ let {
440
+ xIntercept
441
+ } = _ref34;
442
+ return `The line crosses the X-axis at ${xIntercept} comma 0.`;
443
+ },
444
+ srLinearGraphYOnlyIntercept: _ref35 => {
445
+ let {
446
+ yIntercept
447
+ } = _ref35;
448
+ return `The line crosses the Y-axis at 0 comma ${yIntercept}.`;
449
+ },
450
+ srLinearGraphBothIntercepts: _ref36 => {
451
+ let {
452
+ xIntercept,
453
+ yIntercept
454
+ } = _ref36;
455
+ return `The line crosses the X-axis at ${xIntercept} comma 0 and the Y-axis at 0 comma ${yIntercept}.`;
456
+ },
457
+ srLinearGraphOriginIntercept: "The line crosses the x and y axes at the graph's origin."
424
458
  // The above strings are used for interactive graph SR descriptions.
425
459
  };
426
460
 
@@ -27629,11 +27663,21 @@ class Dropdown extends React__namespace.Component {
27629
27663
  key: "placeholder",
27630
27664
  value: "0",
27631
27665
  disabled: true,
27632
- label: this.props.placeholder || " "
27666
+ label: /*#__PURE__*/React__namespace.createElement(Renderer, {
27667
+ content: this.props.placeholder,
27668
+ strings: this.context.strings,
27669
+ inline: true
27670
+ }),
27671
+ labelAsText: this.props.placeholder
27633
27672
  }), ...this.props.choices.map((choice, i) => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
27634
27673
  key: String(i + 1),
27635
27674
  value: String(i + 1),
27636
- label: choice
27675
+ label: /*#__PURE__*/React__namespace.createElement(Renderer, {
27676
+ content: choice,
27677
+ strings: this.context.strings,
27678
+ inline: true
27679
+ }),
27680
+ labelAsText: choice
27637
27681
  }))];
27638
27682
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.Id, null, dropdownId => /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View
27639
27683
  // NOTE(jared): These are required to prevent weird behavior
@@ -27660,7 +27704,8 @@ class Dropdown extends React__namespace.Component {
27660
27704
  // all dropdowns.
27661
27705
  // See https://khanacademy.atlassian.net/browse/WB-1671
27662
27706
  ,
27663
- role: "combobox"
27707
+ role: "combobox",
27708
+ showOpenerLabelAsText: false
27664
27709
  }, children)));
27665
27710
  }
27666
27711
  }
@@ -34119,6 +34164,8 @@ const noop$1 = () => {};
34119
34164
 
34120
34165
  const MovableLine = props => {
34121
34166
  const {
34167
+ ariaLabels,
34168
+ ariaDescribedBy,
34122
34169
  onMoveLine = () => {},
34123
34170
  onMovePoint = () => {},
34124
34171
  color,
@@ -34141,6 +34188,8 @@ const MovableLine = props => {
34141
34188
  visiblePoint: visiblePoint1,
34142
34189
  focusableHandle: focusableHandle1
34143
34190
  } = useControlPoint({
34191
+ ariaLabel: ariaLabels?.point1AriaLabel,
34192
+ ariaDescribedBy: ariaDescribedBy,
34144
34193
  point: start,
34145
34194
  sequenceNumber: 1,
34146
34195
  color,
@@ -34150,6 +34199,8 @@ const MovableLine = props => {
34150
34199
  visiblePoint: visiblePoint2,
34151
34200
  focusableHandle: focusableHandle2
34152
34201
  } = useControlPoint({
34202
+ ariaLabel: ariaLabels?.point2AriaLabel,
34203
+ ariaDescribedBy: ariaDescribedBy,
34153
34204
  point: end,
34154
34205
  sequenceNumber: 2,
34155
34206
  color,
@@ -34432,6 +34483,13 @@ function getGradableGraph(state, initialGraph) {
34432
34483
  };
34433
34484
  }
34434
34485
  if (state.type === "point" && initialGraph.type === "point") {
34486
+ // The unlimited point graph must have at least 1 coordinate or else it is not considered score-able.
34487
+ if (state.numPoints === "unlimited" && state.coords.length === 0) {
34488
+ return {
34489
+ ...initialGraph,
34490
+ coords: null
34491
+ };
34492
+ }
34435
34493
  return {
34436
34494
  ...initialGraph,
34437
34495
  coords: state.coords
@@ -34510,7 +34568,8 @@ function CircleGraph(props) {
34510
34568
  radiusPoint
34511
34569
  } = graphState;
34512
34570
  const {
34513
- strings
34571
+ strings,
34572
+ locale
34514
34573
  } = usePerseusI18n();
34515
34574
  const [radiusPointAriaLive, setRadiusPointAriaLive] = React__namespace.useState("off");
34516
34575
  const radius = getRadius(graphState);
@@ -34520,27 +34579,27 @@ function CircleGraph(props) {
34520
34579
  const outerPointsId = id + "-outer-points";
34521
34580
 
34522
34581
  // Aria label strings
34523
- const circleGraphAriaLabel = strings.circleGraphAriaLabel;
34524
- const circleShapeAriaLabel = strings.circleShapeAriaLabel({
34525
- centerX: center[0],
34526
- centerY: center[1]
34582
+ const circleGraphAriaLabel = strings.srCircleGraph;
34583
+ const circleShapeAriaLabel = strings.srCircleShape({
34584
+ centerX: srFormatNumber(center[0], locale),
34585
+ centerY: srFormatNumber(center[1], locale)
34527
34586
  });
34528
- const circleRadiusPointAriaLabel = strings.circleRadiusPointAriaLabel({
34529
- radiusPointX: radiusPoint[0],
34530
- radiusPointY: radiusPoint[1]
34587
+ const circleRadiusPointAriaLabel = strings.srCircleRadiusPoint({
34588
+ radiusPointX: srFormatNumber(radiusPoint[0], locale),
34589
+ radiusPointY: srFormatNumber(radiusPoint[1], locale)
34531
34590
  });
34532
- const circleRadiusDescription = strings.circleRadiusDescription({
34591
+ const circleRadiusDescription = strings.srCircleRadius({
34533
34592
  radius
34534
34593
  });
34535
- const circleOuterPointsDescription = strings.circleOuterPointsDescription({
34536
- point1X: center[0] + radius,
34537
- point1Y: center[1],
34538
- point2X: center[0],
34539
- point2Y: center[1] + radius,
34540
- point3X: center[0] - radius,
34541
- point3Y: center[1],
34542
- point4X: center[0],
34543
- point4Y: center[1] - radius
34594
+ const circleOuterPointsDescription = strings.srCircleOuterPoints({
34595
+ point1X: srFormatNumber(center[0] + radius, locale),
34596
+ point1Y: srFormatNumber(center[1], locale),
34597
+ point2X: srFormatNumber(center[0], locale),
34598
+ point2Y: srFormatNumber(center[1] + radius, locale),
34599
+ point3X: srFormatNumber(center[0] - radius, locale),
34600
+ point3Y: srFormatNumber(center[1], locale),
34601
+ point4X: srFormatNumber(center[0], locale),
34602
+ point4Y: srFormatNumber(center[1] - radius, locale)
34544
34603
  });
34545
34604
  return /*#__PURE__*/React__namespace.createElement("g", {
34546
34605
  // Outer circle minimal description
@@ -34696,12 +34755,67 @@ const LinearGraph = (props, key) => {
34696
34755
  const {
34697
34756
  coords: line
34698
34757
  } = props.graphState;
34758
+ const {
34759
+ strings,
34760
+ locale
34761
+ } = usePerseusI18n();
34762
+ const id = React__namespace.useId();
34763
+ const pointsDescriptionId = id + "-points";
34764
+ const interceptDescriptionId = id + "-intercept";
34765
+ const slopeDescriptionId = id + "-slope";
34766
+
34767
+ // Aria label strings
34768
+ const linearGraphPointsDescription = strings.srLinearGraphPoints({
34769
+ point1X: srFormatNumber(line[0][0], locale),
34770
+ point1Y: srFormatNumber(line[0][1], locale),
34771
+ point2X: srFormatNumber(line[1][0], locale),
34772
+ point2Y: srFormatNumber(line[1][1], locale)
34773
+ });
34774
+
34775
+ // Slope description
34776
+ const slope = (line[1][1] - line[0][1]) / (line[1][0] - line[0][0]);
34777
+ let slopeString = "";
34778
+ if (slope === Infinity || slope === -Infinity) {
34779
+ slopeString = strings.srLinearGraphSlopeVertical;
34780
+ } else if (slope === 0) {
34781
+ slopeString = strings.srLinearGraphSlopeHorizontal;
34782
+ } else {
34783
+ slopeString = slope > 0 ? strings.srLinearGraphSlopeIncreasing : strings.srLinearGraphSlopeDecreasing;
34784
+ }
34785
+
34786
+ // Intersection description
34787
+ const xIntercept = (0 - line[0][1]) / slope + line[0][0];
34788
+ const yIntercept = line[0][1] - slope * line[0][0];
34789
+ const hasXIntercept = xIntercept !== Infinity && xIntercept !== -Infinity;
34790
+ const hasYIntercept = yIntercept !== Infinity && yIntercept !== -Infinity;
34791
+ let interceptString;
34792
+ if (hasXIntercept && hasYIntercept) {
34793
+ // Describe both intercepts in the same sentence.
34794
+ interceptString = xIntercept === 0 && yIntercept === 0 ? strings.srLinearGraphOriginIntercept : strings.srLinearGraphBothIntercepts({
34795
+ xIntercept: srFormatNumber(xIntercept, locale),
34796
+ yIntercept: srFormatNumber(yIntercept, locale)
34797
+ });
34798
+ } else {
34799
+ // Describe only one intercept.
34800
+ interceptString = hasXIntercept ? strings.srLinearGraphXOnlyIntercept({
34801
+ xIntercept: srFormatNumber(xIntercept, locale)
34802
+ }) : strings.srLinearGraphYOnlyIntercept({
34803
+ yIntercept: srFormatNumber(yIntercept, locale)
34804
+ });
34805
+ }
34699
34806
 
34700
34807
  // Linear graphs only have one line
34701
34808
  // (LEMS-2050): Update the reducer so that we have a separate action for moving one line
34702
34809
  // and another action for moving multiple lines
34703
- return /*#__PURE__*/React__namespace.createElement(MovableLine, {
34810
+ return /*#__PURE__*/React__namespace.createElement("g", {
34811
+ className: "linear-graph-container"
34812
+ // Outer line minimal description
34813
+ ,
34814
+ "aria-label": strings.srLinearGraph,
34815
+ "aria-describedby": `${pointsDescriptionId} ${interceptDescriptionId} ${slopeDescriptionId}`
34816
+ }, /*#__PURE__*/React__namespace.createElement(MovableLine, {
34704
34817
  key: 0,
34818
+ ariaDescribedBy: `${interceptDescriptionId} ${slopeDescriptionId}`,
34705
34819
  points: line,
34706
34820
  onMoveLine: delta => {
34707
34821
  dispatch(actions.linear.moveLine(delta));
@@ -34712,7 +34826,22 @@ const LinearGraph = (props, key) => {
34712
34826
  },
34713
34827
  onMovePoint: (endpointIndex, destination) => dispatch(actions.linear.movePoint(endpointIndex, destination)),
34714
34828
  color: "var(--movable-line-stroke-color)"
34715
- });
34829
+ }), /*#__PURE__*/React__namespace.createElement("g", {
34830
+ id: pointsDescriptionId,
34831
+ style: {
34832
+ display: "hidden"
34833
+ }
34834
+ }, linearGraphPointsDescription), /*#__PURE__*/React__namespace.createElement("g", {
34835
+ id: interceptDescriptionId,
34836
+ style: {
34837
+ display: "hidden"
34838
+ }
34839
+ }, interceptString), /*#__PURE__*/React__namespace.createElement("g", {
34840
+ id: slopeDescriptionId,
34841
+ style: {
34842
+ display: "hidden"
34843
+ }
34844
+ }, slopeString));
34716
34845
  };
34717
34846
 
34718
34847
  function renderLinearSystemGraph(state, dispatch) {
@@ -45670,7 +45799,7 @@ const init = function () {
45670
45799
 
45671
45800
  // This file is processed by a Rollup plugin (replace) to inject the production
45672
45801
  const libName = "@khanacademy/perseus";
45673
- const libVersion = "49.0.1";
45802
+ const libVersion = "49.0.3";
45674
45803
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
45675
45804
 
45676
45805
  const apiVersion = {