@khanacademy/perseus 48.1.0 → 48.2.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
@@ -239,6 +239,8 @@ const mockStrings = {
239
239
  addPoint: "Add Point",
240
240
  removePoint: "Remove Point",
241
241
  graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
242
+ selectAnAnswer: "Select an answer",
243
+ // The following strings are used for interactive graph SR descriptions.
242
244
  closePolygon: "Close shape",
243
245
  openPolygon: "Re-open shape",
244
246
  srPointAtCoordinates: ({
@@ -250,7 +252,29 @@ const mockStrings = {
250
252
  elements
251
253
  }) => `Interactive elements: ${elements}`,
252
254
  srNoInteractiveElements: "No interactive elements",
253
- selectAnAnswer: "Select an answer"
255
+ circleGraphAriaLabel: "A circle on a coordinate plane.",
256
+ circleShapeAriaLabel: ({
257
+ centerX,
258
+ centerY
259
+ }) => `Circle. The center point is at ${centerX} comma ${centerY}.`,
260
+ circleRadiusPointAriaLabel: ({
261
+ radiusPointX,
262
+ radiusPointY
263
+ }) => `Radius point at ${radiusPointX} comma ${radiusPointY}.`,
264
+ circleRadiusDescription: ({
265
+ radius
266
+ }) => `Circle radius is ${radius}.`,
267
+ circleOuterPointsDescription: ({
268
+ point1X,
269
+ point1Y,
270
+ point2X,
271
+ point2Y,
272
+ point3X,
273
+ point3Y,
274
+ point4X,
275
+ point4Y
276
+ }) => `Points on the circle at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, ${point3X} comma ${point3Y}, ${point4X} comma ${point4Y}.`
277
+ // The above strings are used for interactive graph SR descriptions.
254
278
  };
255
279
 
256
280
  /**
@@ -3520,9 +3544,9 @@ function loadGraphie(url, onDataLoaded) {
3520
3544
  };
3521
3545
  if (shouldUseLocalizedData()) {
3522
3546
  cacheData.localized = false;
3523
- // If there is isn't any localized data, fall back to
3524
- // the original, unlocalized data
3525
- retrieveData(getLocalizedDataUrl(url), dataLoadErrorHandler);
3547
+ // If there is isn't any localized data, use the error callback to try to
3548
+ // load the non-localized data. If that fails too, then we will throw an error.
3549
+ retrieveData(getLocalizedDataUrl(url), () => retrieveData(Util.getDataUrl(url), dataLoadErrorHandler));
3526
3550
  } else {
3527
3551
  retrieveData(Util.getDataUrl(url), dataLoadErrorHandler);
3528
3552
  }
@@ -34145,21 +34169,96 @@ function CircleGraph(props) {
34145
34169
  center,
34146
34170
  radiusPoint
34147
34171
  } = graphState;
34148
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MovableCircle, {
34172
+ const {
34173
+ strings
34174
+ } = usePerseusI18n();
34175
+ const [radiusPointAriaLive, setRadiusPointAriaLive] = React.useState("off");
34176
+ const radius = getRadius(graphState);
34177
+ const id = React.useId();
34178
+ const circleId = id + "-circle";
34179
+ const radiusId = id + "-radius";
34180
+ const outerPointsId = id + "-outer-points";
34181
+
34182
+ // Aria label strings
34183
+ const circleGraphAriaLabel = strings.circleGraphAriaLabel;
34184
+ const circleShapeAriaLabel = strings.circleShapeAriaLabel({
34185
+ centerX: center[0],
34186
+ centerY: center[1]
34187
+ });
34188
+ const circleRadiusPointAriaLabel = strings.circleRadiusPointAriaLabel({
34189
+ radiusPointX: radiusPoint[0],
34190
+ radiusPointY: radiusPoint[1]
34191
+ });
34192
+ const circleRadiusDescription = strings.circleRadiusDescription({
34193
+ radius
34194
+ });
34195
+ const circleOuterPointsDescription = strings.circleOuterPointsDescription({
34196
+ point1X: center[0] + radius,
34197
+ point1Y: center[1],
34198
+ point2X: center[0],
34199
+ point2Y: center[1] + radius,
34200
+ point3X: center[0] - radius,
34201
+ point3Y: center[1],
34202
+ point4X: center[0],
34203
+ point4Y: center[1] - radius
34204
+ });
34205
+ return /*#__PURE__*/React.createElement("g", {
34206
+ // Outer circle minimal description
34207
+ "aria-label": circleGraphAriaLabel,
34208
+ "aria-describedby": `${circleId} ${radiusId} ${outerPointsId}`
34209
+ }, /*#__PURE__*/React.createElement(MovableCircle, {
34210
+ id: circleId
34211
+ // Focusable circle aria label reads with every update
34212
+ // because of the aria-live property in the circle <g>.
34213
+ ,
34214
+ ariaLabel: circleShapeAriaLabel
34215
+ // Aria-describedby describes additional info on focus.
34216
+ ,
34217
+ ariaDescribedBy: `${radiusId} ${outerPointsId}`,
34149
34218
  center: center,
34150
- radius: getRadius(graphState),
34151
- onMove: c => dispatch(actions.circle.moveCenter(c))
34152
- }), /*#__PURE__*/React.createElement(MovablePoint$1, {
34219
+ radius: radius,
34220
+ onMove: c => {
34221
+ setRadiusPointAriaLive("off");
34222
+ dispatch(actions.circle.moveCenter(c));
34223
+ }
34224
+ }), /*#__PURE__*/React.createElement(MovablePoint$1
34225
+ // Radius point aria label reads with every update.
34226
+ , {
34227
+ ariaLabel: `${circleRadiusPointAriaLabel} ${circleRadiusDescription}`
34228
+ // Aria-describedby describes additional info on focus.
34229
+ ,
34230
+ ariaDescribedBy: `${outerPointsId}`
34231
+ // The radius point's aria-live property is set to "off" when
34232
+ // the circle is moved, so that it doesn't override the circle's
34233
+ // aria-live (since the point is moved along with the circle).
34234
+ // When the radius point is moved, the aria-live is set to
34235
+ // "polite" so that the radius is read out.
34236
+ ,
34237
+ ariaLive: radiusPointAriaLive,
34153
34238
  point: radiusPoint,
34154
34239
  sequenceNumber: 1,
34155
34240
  cursor: "ew-resize",
34156
34241
  onMove: newRadiusPoint => {
34242
+ setRadiusPointAriaLive("polite");
34157
34243
  dispatch(actions.circle.moveRadiusPoint(newRadiusPoint));
34158
34244
  }
34159
- }));
34245
+ }), /*#__PURE__*/React.createElement("g", {
34246
+ id: radiusId,
34247
+ style: {
34248
+ display: "hidden"
34249
+ }
34250
+ }, circleRadiusDescription), /*#__PURE__*/React.createElement("g", {
34251
+ id: outerPointsId,
34252
+ style: {
34253
+ display: "hidden"
34254
+ }
34255
+ }, circleOuterPointsDescription));
34160
34256
  }
34161
34257
  function MovableCircle(props) {
34162
34258
  const {
34259
+ id,
34260
+ ariaLabel,
34261
+ ariaDescribedBy,
34163
34262
  center,
34164
34263
  radius,
34165
34264
  onMove
@@ -34180,7 +34279,11 @@ function MovableCircle(props) {
34180
34279
  const [centerPx] = useTransformVectorsToPixels(center);
34181
34280
  const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
34182
34281
  return /*#__PURE__*/React.createElement("g", {
34282
+ "aria-label": ariaLabel,
34283
+ "aria-describedby": ariaDescribedBy,
34284
+ "aria-live": "polite",
34183
34285
  ref: draggableRef,
34286
+ role: "button",
34184
34287
  tabIndex: disableKeyboardInteraction ? -1 : 0,
34185
34288
  className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
34186
34289
  }, /*#__PURE__*/React.createElement("ellipse", {
@@ -34190,6 +34293,7 @@ function MovableCircle(props) {
34190
34293
  rx: radiiPx[X] + 3,
34191
34294
  ry: radiiPx[Y] + 3
34192
34295
  }), /*#__PURE__*/React.createElement("ellipse", {
34296
+ id: id,
34193
34297
  className: "circle",
34194
34298
  cx: centerPx[X],
34195
34299
  cy: centerPx[Y],
@@ -45172,7 +45276,7 @@ const init = function init() {
45172
45276
 
45173
45277
  // This file is processed by a Rollup plugin (replace) to inject the production
45174
45278
  const libName = "@khanacademy/perseus";
45175
- const libVersion = "48.1.0";
45279
+ const libVersion = "48.2.0";
45176
45280
  addLibraryVersionToPerseusDebug(libName, libVersion);
45177
45281
 
45178
45282
  const apiVersion = {