@khanacademy/perseus 19.1.9 → 19.2.1

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
@@ -278,7 +278,7 @@ class MathInput extends React__namespace.Component {
278
278
  className = className + " " + this.props.className;
279
279
  }
280
280
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
281
- style: [styles$B.outerWrapper, this.state.focused && styles$B.wrapperFocused, this.props.hasError && styles$B.wrapperError]
281
+ style: [styles$C.outerWrapper, this.state.focused && styles$C.wrapperFocused, this.props.hasError && styles$C.wrapperError]
282
282
  }, /*#__PURE__*/React__namespace.createElement("div", {
283
283
  style: {
284
284
  display: "flex",
@@ -309,7 +309,7 @@ class MathInput extends React__namespace.Component {
309
309
  dismissEnabled: true,
310
310
  content: () => /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
311
311
  closeButtonVisible: true,
312
- style: styles$B.popoverContent
312
+ style: styles$C.popoverContent
313
313
  }, /*#__PURE__*/React__namespace.createElement(mathInput.DesktopKeypad, _extends({
314
314
  onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
315
315
  extraKeys: this.props.extraKeys,
@@ -349,9 +349,9 @@ const MathInputIcon = _ref => {
349
349
  color = Color__default["default"].offBlack;
350
350
  break;
351
351
  }
352
- const dynamicClass = active || focused ? styles$B.iconActive : styles$B.iconInactive;
352
+ const dynamicClass = active || focused ? styles$C.iconActive : styles$C.iconInactive;
353
353
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
354
- style: [styles$B.iconContainer, dynamicClass]
354
+ style: [styles$C.iconContainer, dynamicClass]
355
355
  }, /*#__PURE__*/React__namespace.createElement("svg", {
356
356
  xmlns: "http://www.w3.org/2000/svg",
357
357
  width: "16",
@@ -396,7 +396,7 @@ const inputFocused = {
396
396
  borderColor: Color__default["default"].blue,
397
397
  margin: -1
398
398
  };
399
- const styles$B = aphrodite.StyleSheet.create({
399
+ const styles$C = aphrodite.StyleSheet.create({
400
400
  iconContainer: {
401
401
  display: "flex",
402
402
  justifyContent: "center",
@@ -2421,6 +2421,7 @@ ExpressionWithDependencies.getOneCorrectAnswerFromRubric = Expression.getOneCorr
2421
2421
  var Expression$1 = {
2422
2422
  name: "expression",
2423
2423
  displayName: "Expression / Equation",
2424
+ accessible: true,
2424
2425
  defaultAlignment: "inline-block",
2425
2426
  widget: ExpressionWithDependencies,
2426
2427
  transform: widgetOptions => {
@@ -10212,89 +10213,45 @@ const GraphUtils = {
10212
10213
  }
10213
10214
  })($__default["default"], window, document);
10214
10215
 
10215
- /**
10216
- * A work-in-progress of _ methods for objects.
10217
- * That is, they take an object as a parameter,
10218
- * and return an object instead of an array.
10219
- *
10220
- * TODO(aria): Move this out of interactive2
10221
- */
10222
-
10223
- /**
10224
- * Does a pluck on keys inside objects in an object
10225
- *
10226
- * Ex:
10227
- * tools = {
10228
- * translation: {
10229
- * enabled: true
10230
- * },
10231
- * rotation: {
10232
- * enabled: false
10233
- * }
10234
- * };
10235
- * pluckObject(tools, "enabled") returns {
10236
- * translation: true
10237
- * rotation: false
10238
- * }
10239
- */
10240
- const pluck = function (table, subKey) {
10241
- return ___default["default"].object(___default["default"].map(table, function (value, key) {
10242
- return [key, value[subKey]];
10243
- }));
10244
- };
10245
-
10246
- /**
10247
- * Maps an object to an object
10248
- *
10249
- * > mapObject({a: '1', b: '2'}, (value, key) => {
10250
- * return value + 1;
10251
- * });
10252
- * {a: 2, b: 3}
10253
- */
10254
- const mapObject$2 = function (obj, lambda) {
10255
- const result = {};
10256
- ___default["default"].each(___default["default"].keys(obj), function (key) {
10257
- // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
10258
- result[key] = lambda(obj[key], key);
10259
- });
10260
- return result;
10261
- };
10216
+ // Given `coord` and `angle`, find the point where a line extended
10217
+ // from `coord` in the direction of `angle` would be clipped by the
10218
+ // edge of the graphie canvas.
10219
+ const getClipPoint = function (graph, coord, angle) {
10220
+ // Actually put the arrowheads 4px from the edge so they have
10221
+ // a bit of room
10222
+ const xExtent = graph.range[0][1] - graph.range[0][0];
10223
+ const yExtent = graph.range[1][1] - graph.range[1][0];
10262
10224
 
10263
- /**
10264
- * Maps an array to an object
10265
- *
10266
- * > mapObjectFromArray(['a', 'b'], function(elem) {
10267
- * return elem + elem;
10268
- * });
10269
- * {a: 'aa', b: 'bb'}
10270
- */
10271
- const mapObjectFromArray$1 = function (arr, lambda) {
10272
- const result = {};
10273
- ___default["default"].each(arr, function (elem) {
10274
- result[elem] = lambda(elem);
10275
- });
10276
- return result;
10277
- };
10278
- var objective_ = {
10279
- pluck: pluck,
10280
- mapObject: mapObject$2,
10281
- mapObjectFromArray: mapObjectFromArray$1
10225
+ // shoot a point off into the distance ...
10226
+ const distance = xExtent + yExtent;
10227
+ // we need to scale the point according to the scale of the axes
10228
+ const angleVec = graph.unscaleVector(kmath.vector.cartFromPolarDeg(1, angle));
10229
+ const distVec = kmath.vector.scale(kmath.vector.normalize(angleVec), distance);
10230
+ const farCoord = kmath.vector.add(coord, distVec);
10231
+ const scaledAngle = kmath.vector.polarDegFromCart(angleVec)[1];
10232
+ // ... and then bring it back
10233
+ const clipPoint = graph.constrainToBoundsOnAngle(farCoord, 4, scaledAngle * Math.PI / 180);
10234
+ return clipPoint;
10282
10235
  };
10283
10236
 
10284
10237
  /* eslint-disable @babel/no-invalid-this */
10285
10238
 
10286
10239
  /*
10287
- * These functions, when called on the wrapped object, simply pass the
10240
+ * attr() and animate() simply pass the
10288
10241
  * arguments to the underlying Raphael object.
10289
10242
  */
10290
- const PASS_TO_RAPHAEL = ["attr", "animate"];
10291
- const WrappedDefaults = ___default["default"].extend({
10292
- transform: function (transformation) {
10243
+
10244
+ class WrappedDrawing {
10245
+ constructor(graphie, initialPoint) {
10246
+ this.graphie = graphie;
10247
+ this.initialPoint = initialPoint;
10248
+ }
10249
+ transform(transformation) {
10293
10250
  const prefixedTransform = InteractiveUtil.getPrefixedTransform();
10294
10251
  // @ts-expect-error - TS2538 - Type 'null' cannot be used as an index type. | TS2538 - Type 'undefined' cannot be used as an index type.
10295
10252
  this.wrapper.style[prefixedTransform] = transformation;
10296
- },
10297
- toFront: function () {
10253
+ }
10254
+ toFront() {
10298
10255
  const parentNode = this.wrapper.parentNode;
10299
10256
  // TODO(emily): Sometimes, we call `.remove()` but then hold a
10300
10257
  // reference to this object, and sometimes call `.toFront` on it.
@@ -10303,152 +10260,205 @@ const WrappedDefaults = ___default["default"].extend({
10303
10260
  if (parentNode) {
10304
10261
  parentNode.appendChild(this.wrapper);
10305
10262
  }
10306
- },
10307
- toBack: function () {
10263
+ }
10264
+ toBack() {
10308
10265
  const parentNode = this.wrapper.parentNode;
10309
- if (parentNode.firstChild !== this.wrapper) {
10266
+ if (parentNode != null && parentNode.firstChild !== this.wrapper) {
10310
10267
  parentNode.insertBefore(this.wrapper, parentNode.firstChild);
10311
10268
  }
10312
- },
10313
- remove: function () {
10269
+ }
10270
+ remove() {
10314
10271
  this.visibleShape.remove();
10315
10272
  $__default["default"](this.wrapper).remove();
10316
- },
10317
- getMouseTarget: function () {
10273
+ }
10274
+ getMouseTarget() {
10318
10275
  return this.visibleShape[0];
10319
- },
10320
- moveTo: function (point) {
10276
+ }
10277
+ moveTo(point) {
10321
10278
  const delta = kmath.vector.subtract(this.graphie.scalePoint(point), this.graphie.scalePoint(this.initialPoint));
10322
10279
  const do3dTransform = InteractiveUtil.getCanUse3dTransform();
10323
10280
  const transformation = "translateX(" + delta[0] + "px) " + "translateY(" + delta[1] + "px)" + (do3dTransform ? " translateZ(0)" : "");
10324
10281
  this.transform(transformation);
10325
- },
10326
- hide: function () {
10282
+ }
10283
+ hide() {
10327
10284
  this.visibleShape.hide();
10328
- },
10329
- show: function () {
10285
+ }
10286
+ show() {
10330
10287
  this.visibleShape.show();
10331
10288
  }
10332
- }, objective_.mapObjectFromArray(PASS_TO_RAPHAEL, function (attribute) {
10333
- return function () {
10334
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10335
- this.visibleShape[attribute](...arguments);
10336
- };
10337
- }));
10289
+ attr() {
10290
+ this.visibleShape.attr(...arguments);
10291
+ }
10292
+ animate() {
10293
+ this.visibleShape.animate(...arguments);
10294
+ }
10295
+ }
10338
10296
 
10339
10297
  const DEFAULT_OPTIONS$2 = {
10340
- maxScale: 1,
10341
- mouselayer: false,
10342
- shadow: false,
10343
- disableMouseEventsOnWrapper: false
10298
+ center: null,
10299
+ // gets ignored in `graphie.fixedPath` if `null`
10300
+ createPath: null,
10301
+ // gets defaulted in `graphie.fixedPath` if `null`
10302
+ mouselayer: false
10344
10303
  };
10345
- const WrappedEllipse = function (graphie, center, radii, options) {
10346
- options = ___default["default"].extend({}, DEFAULT_OPTIONS$2, options);
10347
-
10348
- // Add `wrapper`, `visibleShape`, and remaining properties.
10349
- const fixedEllipse = graphie.fixedEllipse(center, radii, options.maxScale, options.padding);
10350
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10351
- ___default["default"].extend(this, fixedEllipse, {
10352
- graphie: graphie,
10353
- initialPoint: center
10354
- });
10355
- if (options.interactiveKindForTesting) {
10356
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10357
- this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10304
+ class WrappedPath extends WrappedDrawing {
10305
+ constructor(graphie, points, options) {
10306
+ const initialPoint = graphie.scalePoint(___default["default"].head(points));
10307
+ super(graphie, initialPoint);
10308
+ options = ___default["default"].extend({}, DEFAULT_OPTIONS$2, options);
10309
+ const fixedPath = graphie.fixedPath(points, options.center, options.createPath);
10310
+ this.wrapper = fixedPath.wrapper;
10311
+ this.visibleShape = fixedPath.visibleShape;
10312
+
10313
+ // Add to appropriate graphie layer
10314
+ if (options.mouselayer) {
10315
+ // Disable browser handling of all panning and zooming gestures on the
10316
+ // movable wrapper so that when moved the browser does not scroll page
10317
+ this.wrapper.style.touchAction = "none";
10318
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
10319
+ } else {
10320
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
10321
+ }
10358
10322
  }
10323
+ }
10359
10324
 
10360
- // Add to appropriate graphie layer
10361
- if (options.mouselayer) {
10362
- // Disable browser handling of all panning and zooming gestures on the
10363
- // movable wrapper so that when moved the browser does not scroll page
10364
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10365
- this.wrapper.style.touchAction = "none";
10366
-
10367
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10368
- this.graphie.addToMouseLayerWrapper(this.wrapper);
10369
- } else {
10370
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10371
- this.graphie.addToVisibleLayerWrapper(this.wrapper);
10325
+ class Arrowhead extends WrappedPath {
10326
+ static scale = 1.4;
10327
+ constructor(graphie, style) {
10328
+ // Points that define the arrowhead
10329
+ const center = [0.75, 0];
10330
+ const points = [[-3, 4], [-2.75, 2.5], [0, 0.25], center, [0, -0.25], [-2.75, -2.5], [-3, -4]].map(point => {
10331
+ // Scale points by `Arrowhead.scale` around `center`
10332
+ const pv = kmath.vector.subtract(point, center);
10333
+ const pvScaled = kmath.vector.scale(pv, Arrowhead.scale);
10334
+ return kmath.vector.add(center, pvScaled);
10335
+ });
10336
+ const unscaledPoints = points.map(graphie.unscalePoint);
10337
+ super(graphie, unscaledPoints, {
10338
+ center: graphie.unscalePoint(center),
10339
+ createPath: createCubicPath
10340
+ });
10341
+ this.center = center;
10342
+ this.attr(___default["default"].extend({
10343
+ "stroke-linejoin": "round",
10344
+ "stroke-linecap": "round",
10345
+ "stroke-dasharray": ""
10346
+ }, style));
10372
10347
  }
10373
- if (options.shadow) {
10374
- const filter = "drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";
10375
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10376
- const wrapper = this.wrapper;
10377
- wrapper.style.filter = filter;
10378
-
10379
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10380
- this.moveTo = function (point) {
10381
- const delta = kmath.vector.subtract(this.graphie.scalePoint(point), this.graphie.scalePoint(this.initialPoint));
10382
- const do3dTransform = InteractiveUtil.getCanUse3dTransform();
10383
- const transform = "translateX(" + Math.round(delta[0]) + "px) " + "translateY(" + Math.round(delta[1]) + "px)" + (do3dTransform ? " translateZ(0)" : "");
10384
- this.transform(transform);
10385
- };
10348
+ toCoordAtAngle(coord, angle) {
10349
+ const clipPoint = this.graphie.scalePoint(getClipPoint(this.graphie, coord, angle));
10350
+ this.transform("translateX(" + (clipPoint[0] + Arrowhead.scale * this.center[0]) + "px) " + "translateY(" + (clipPoint[1] + Arrowhead.scale * this.center[1]) + "px) " + "translateZ(0) " + "rotate(" + (360 - KhanMath.bound(angle)) + "deg)");
10386
10351
  }
10387
- if (options.disableMouseEventsOnWrapper) {
10388
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10389
- this.wrapper.style.pointerEvents = "none";
10390
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10391
- this.visibleShape.node.style.pointerEvents = "auto";
10352
+ }
10353
+
10354
+ // We can't just pass in a path to `graph.fixedPath` as we need to modify
10355
+ // the points in some way, so instead we provide a function for creating
10356
+ // the path once the points have been transformed
10357
+ const createCubicPath = function (points) {
10358
+ let path = "M" + points[0][0] + " " + points[0][1];
10359
+ for (let i = 1; i < points.length; i += 3) {
10360
+ path += "C" + points[i][0] + " " + points[i][1] + " " + points[i + 1][0] + " " + points[i + 1][1] + " " + points[i + 2][0] + " " + points[i + 2][1];
10392
10361
  }
10362
+ return path;
10393
10363
  };
10394
- ___default["default"].extend(WrappedEllipse.prototype, WrappedDefaults);
10395
10364
 
10396
10365
  const DEFAULT_OPTIONS$1 = {
10397
- thickness: 2,
10398
- mouselayer: false
10366
+ maxScale: 1,
10367
+ mouselayer: false,
10368
+ shadow: false,
10369
+ disableMouseEventsOnWrapper: false
10399
10370
  };
10400
- const WrappedLine = function (graphie, start, end, options) {
10401
- options = ___default["default"].extend({}, DEFAULT_OPTIONS$1, options);
10371
+ class WrappedEllipse extends WrappedDrawing {
10372
+ constructor(graphie, center, radii, options) {
10373
+ super(graphie, center);
10374
+ options = ___default["default"].extend({}, DEFAULT_OPTIONS$1, options);
10402
10375
 
10403
- // Always make the line as large as possible and horizontal; this
10404
- // simplifies a lot of the transforms, e.g., we can rotate by exactly the
10405
- // angle of the argument points in `moveTo`.
10406
- const initialStart = [graphie.range[0][0], 0];
10407
- const initialEnd = [graphie.range[0][1], 0];
10376
+ // Add `wrapper`, `visibleShape`, and remaining properties.
10377
+ const fixedEllipse = graphie.fixedEllipse(center, radii, options.maxScale, options.padding);
10378
+ this.visibleShape = fixedEllipse.visibleShape;
10379
+ this.wrapper = fixedEllipse.wrapper;
10380
+ this.graphie = graphie;
10381
+ this.initialPoint = center;
10382
+ if (options.interactiveKindForTesting) {
10383
+ this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10384
+ }
10408
10385
 
10409
- // Add `wrapper` and `visibleShape`
10410
- ___default["default"].extend(
10411
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10412
- this, graphie.fixedLine(initialStart, initialEnd, options.thickness));
10413
- if (options.interactiveKindForTesting) {
10414
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10415
- this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10386
+ // Add to appropriate graphie layer
10387
+ if (options.mouselayer) {
10388
+ // Disable browser handling of all panning and zooming gestures on the
10389
+ // movable wrapper so that when moved the browser does not scroll page
10390
+ this.wrapper.style.touchAction = "none";
10391
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
10392
+ } else {
10393
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
10394
+ }
10395
+ if (options.shadow) {
10396
+ const filter = "drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";
10397
+ const wrapper = this.wrapper;
10398
+ wrapper.style.filter = filter;
10399
+ this.moveTo = function (point) {
10400
+ const delta = kmath.vector.subtract(this.graphie.scalePoint(point), this.graphie.scalePoint(this.initialPoint));
10401
+ const do3dTransform = InteractiveUtil.getCanUse3dTransform();
10402
+ const transform = "translateX(" + Math.round(delta[0]) + "px) " + "translateY(" + Math.round(delta[1]) + "px)" + (do3dTransform ? " translateZ(0)" : "");
10403
+ this.transform(transform);
10404
+ };
10405
+ }
10406
+ if (options.disableMouseEventsOnWrapper) {
10407
+ this.wrapper.style.pointerEvents = "none";
10408
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10409
+ this.visibleShape.node.style.pointerEvents = "auto";
10410
+ }
10416
10411
  }
10412
+ }
10417
10413
 
10418
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10419
- this.visibleShape.attr(options.normalStyle);
10420
-
10421
- // Save properties for computing transformations
10422
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10423
- ___default["default"].extend(this, {
10424
- graphie: graphie,
10425
- initialPoint: graphie.scalePoint(initialStart),
10426
- initialLength: kmath.point.distanceToPoint(graphie.scalePoint(initialStart), graphie.scalePoint(initialEnd))
10427
- });
10428
-
10429
- // Add to appropriate graphie layer
10430
- if (options.mouselayer) {
10431
- // Disable browser handling of all panning and zooming gestures on the
10432
- // movable wrapper so that when moved the browser does not scroll page
10433
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10434
- this.wrapper.style.touchAction = "none";
10414
+ const DEFAULT_OPTIONS = {
10415
+ thickness: 2,
10416
+ mouselayer: false
10417
+ };
10418
+ class WrappedLine extends WrappedDrawing {
10419
+ constructor(graphie, start, end, options) {
10420
+ // Always make the line as large as possible and horizontal; this
10421
+ // simplifies a lot of the transforms, e.g., we can rotate by exactly the
10422
+ // angle of the argument points in `moveTo`.
10423
+ const initialStart = [graphie.range[0][0], 0];
10424
+ const initialEnd = [graphie.range[0][1], 0];
10425
+ const initialPoint = graphie.scalePoint(initialStart);
10426
+ super(graphie, initialPoint);
10427
+ options = ___default["default"].extend({}, DEFAULT_OPTIONS, options);
10428
+ const fixedLine = graphie.fixedLine(initialStart, initialEnd, options.thickness);
10429
+ this.wrapper = fixedLine.wrapper;
10430
+ this.visibleShape = fixedLine.visibleShape;
10431
+ if (options.interactiveKindForTesting) {
10432
+ this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10433
+ }
10434
+ this.visibleShape.attr(options.normalStyle);
10435
+
10436
+ // Save properties for computing transformations
10437
+ this.initialPoint = initialPoint;
10438
+ this.initialLength = kmath.point.distanceToPoint(graphie.scalePoint(initialStart), graphie.scalePoint(initialEnd));
10439
+
10440
+ // Add to appropriate graphie layer
10441
+ if (options.mouselayer) {
10442
+ // Disable browser handling of all panning and zooming gestures on the
10443
+ // movable wrapper so that when moved the browser does not scroll page
10444
+ this.wrapper.style.touchAction = "none";
10445
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
10446
+ } else {
10447
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
10448
+ }
10435
10449
 
10436
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10437
- this.graphie.addToMouseLayerWrapper(this.wrapper);
10438
- } else {
10439
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10440
- this.graphie.addToVisibleLayerWrapper(this.wrapper);
10450
+ // Move line to initial points
10451
+ this.moveTo(start, end);
10441
10452
  }
10442
-
10443
- // Move to argument points
10444
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10445
- this.moveTo(start, end);
10446
- };
10447
- ___default["default"].extend(WrappedLine.prototype, WrappedDefaults, {
10448
- getMouseTarget: function () {
10453
+ getMouseTarget() {
10449
10454
  return this.wrapper;
10450
- },
10451
- moveTo: function (start, end) {
10455
+ }
10456
+
10457
+ // TODO(benchristel): we need to suppress a type error here because moveTo
10458
+ // takes 2 parameters here, but only 1 parameter in the superclass's
10459
+ // definition. Rename this method after confirming it's safe to do so
10460
+ // @ts-expect-error - TS2416: Property 'moveTo' in type 'WrappedLine' is not assignable to the same property in base type 'WrappedDefaults'.
10461
+ moveTo(start, end) {
10452
10462
  const scaledStart = this.graphie.scalePoint(start);
10453
10463
  const scaledEnd = this.graphie.scalePoint(end);
10454
10464
 
@@ -10464,45 +10474,7 @@ ___default["default"].extend(WrappedLine.prototype, WrappedDefaults, {
10464
10474
  const transformation = "translateX(" + delta[0] + "px) " + "translateY(" + delta[1] + "px) " + (do3dTransform ? " translateZ(0)" : "") + "rotate(" + angle + "deg) " + "scaleX(" + scale + ") scaleY(1)";
10465
10475
  this.transform(transformation);
10466
10476
  }
10467
- });
10468
-
10469
- const DEFAULT_OPTIONS = {
10470
- center: null,
10471
- // gets ignored in `graphie.fixedPath` if `null`
10472
- createPath: null,
10473
- // gets defaulted in `graphie.fixedPath` if `null`
10474
- mouselayer: false
10475
- };
10476
- const WrappedPath = function (graphie, points, options) {
10477
- options = ___default["default"].extend({}, DEFAULT_OPTIONS, options);
10478
-
10479
- // Add `wrapper` and `visibleShape`
10480
- ___default["default"].extend(
10481
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10482
- this, graphie.fixedPath(points, options.center, options.createPath));
10483
-
10484
- // Add remaining properties
10485
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10486
- ___default["default"].extend(this, {
10487
- graphie: graphie,
10488
- initialPoint: graphie.scalePoint(___default["default"].head(points))
10489
- });
10490
-
10491
- // Add to appropriate graphie layer
10492
- if (options.mouselayer) {
10493
- // Disable browser handling of all panning and zooming gestures on the
10494
- // movable wrapper so that when moved the browser does not scroll page
10495
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10496
- this.wrapper.style.touchAction = "none";
10497
-
10498
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10499
- this.graphie.addToMouseLayerWrapper(this.wrapper);
10500
- } else {
10501
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10502
- this.graphie.addToVisibleLayerWrapper(this.wrapper);
10503
- }
10504
- };
10505
- ___default["default"].extend(WrappedPath.prototype, WrappedDefaults);
10477
+ }
10506
10478
 
10507
10479
  /**
10508
10480
  * A collection of geomtry-related utility functions
@@ -10728,9 +10700,6 @@ firstPoints, secondPoints) {
10728
10700
  }
10729
10701
 
10730
10702
  /* eslint-disable @babel/no-invalid-this */
10731
- const {
10732
- getCanUse3dTransform
10733
- } = InteractiveUtil;
10734
10703
  function scaledDistanceFromAngle(angle) {
10735
10704
  const a = 3.51470560176242 * 20;
10736
10705
  const b = 0.5687298702748785 * 20;
@@ -11614,52 +11583,15 @@ ___default["default"].extend(GraphUtils.Graphie.prototype, {
11614
11583
  ___default["default"].each(elements, function (element) {
11615
11584
  element.moveTo(start, end);
11616
11585
  });
11617
- const createArrow = function (graph, style) {
11618
- const center = [0.75, 0];
11619
- let points = [[-3, 4], [-2.75, 2.5], [0, 0.25], center, [0, -0.25], [-2.75, -2.5], [-3, -4]];
11620
- const scale = 1.4;
11621
- points = ___default["default"].map(points, function (point) {
11622
- const pv = kmath.vector.subtract(point, center);
11623
- const pvScaled = kmath.vector.scale(pv, scale);
11624
- return kmath.vector.add(center, pvScaled);
11625
- });
11626
- const createCubicPath = function (points) {
11627
- let path = "M" + points[0][0] + " " + points[0][1];
11628
- for (let i = 1; i < points.length; i += 3) {
11629
- path += "C" + points[i][0] + " " + points[i][1] + " " + points[i + 1][0] + " " + points[i + 1][1] + " " + points[i + 2][0] + " " + points[i + 2][1];
11630
- }
11631
- return path;
11632
- };
11633
- const unscaledPoints = ___default["default"].map(points, graph.unscalePoint);
11634
- const options = {
11635
- center: graph.unscalePoint(center),
11636
- createPath: createCubicPath
11637
- };
11638
- const arrowHead = new WrappedPath(graph, unscaledPoints, options);
11639
- arrowHead.attr(___default["default"].extend({
11640
- "stroke-linejoin": "round",
11641
- "stroke-linecap": "round",
11642
- "stroke-dasharray": ""
11643
- }, style));
11644
-
11645
- // Add custom function for transforming arrowheads that
11646
- // accounts for center, scaling, etc.
11647
- arrowHead.toCoordAtAngle = function (coord, angle) {
11648
- const clipPoint = graph.scalePoint(getClipPoint(graph, coord, angle));
11649
- const do3dTransform = getCanUse3dTransform();
11650
- arrowHead.transform("translateX(" + (clipPoint[0] + scale * center[0]) + "px) " + "translateY(" + (clipPoint[1] + scale * center[1]) + "px) " + (do3dTransform ? "translateZ(0) " : "") + "rotate(" + (360 - KhanMath.bound(angle)) + "deg)");
11651
- };
11652
- return arrowHead;
11653
- };
11654
11586
 
11655
11587
  // Add arrows
11656
11588
  if (this._arrows == null) {
11657
11589
  this._arrows = [];
11658
11590
  if (this.extendLine) {
11659
- this._arrows.push(createArrow(graph, this.normalStyle));
11660
- this._arrows.push(createArrow(graph, this.normalStyle));
11591
+ this._arrows.push(new Arrowhead(graph, this.normalStyle));
11592
+ this._arrows.push(new Arrowhead(graph, this.normalStyle));
11661
11593
  } else if (this.extendRay) {
11662
- this._arrows.push(createArrow(graph, this.normalStyle));
11594
+ this._arrows.push(new Arrowhead(graph, this.normalStyle));
11663
11595
  }
11664
11596
  }
11665
11597
  const coordForArrow = [this.coordA, this.coordZ];
@@ -14100,78 +14032,6 @@ const getScaledAngle = function (line) {
14100
14032
  return kmath.vector.polarDegFromCart(kmath.vector.subtract(scaledZ, scaledA))[1];
14101
14033
  };
14102
14034
 
14103
- // Given `coord` and `angle`, find the point where a line extended
14104
- // from `coord` in the direction of `angle` would be clipped by the
14105
- // edge of the graphie canvas. Then draw an arrowhead at that point
14106
- // pointing in the direction of `angle`.
14107
- const getClipPoint = function (graph, coord, angle) {
14108
- // Actually put the arrowheads 4px from the edge so they have
14109
- // a bit of room
14110
- const xExtent = graph.range[0][1] - graph.range[0][0];
14111
- const yExtent = graph.range[1][1] - graph.range[1][0];
14112
-
14113
- // shoot a point off into the distance ...
14114
- const distance = xExtent + yExtent;
14115
- // we need to scale the point according to the scale of the axes
14116
- const angleVec = graph.unscaleVector(kmath.vector.cartFromPolarDeg(1, angle));
14117
- const distVec = kmath.vector.scale(kmath.vector.normalize(angleVec), distance);
14118
- const farCoord = kmath.vector.add(coord, distVec);
14119
- const scaledAngle = kmath.vector.polarDegFromCart(angleVec)[1];
14120
- // ... and then bring it back
14121
- const clipPoint = graph.constrainToBoundsOnAngle(farCoord, 4, scaledAngle * Math.PI / 180);
14122
- return clipPoint;
14123
- };
14124
-
14125
- // Given `coord` and `angle`, find the point where a line extended
14126
- // from `coord` in the direction of `angle` would be clipped by the
14127
- // edge of the graphie canvas. Then draw an arrowhead at that point
14128
- // pointing in the direction of `angle`.
14129
- const createArrow = function (graph, style) {
14130
- // Points that define the arrowhead
14131
- const center = [0.75, 0];
14132
- let points = [[-3, 4], [-2.75, 2.5], [0, 0.25], center, [0, -0.25], [-2.75, -2.5], [-3, -4]];
14133
-
14134
- // Scale points by 1.4 around (0.75, 0)
14135
- const scale = 1.4;
14136
- points = ___default["default"].map(points, function (point) {
14137
- const pv = kmath.vector.subtract(point, center);
14138
- const pvScaled = kmath.vector.scale(pv, scale);
14139
- return kmath.vector.add(center, pvScaled);
14140
- });
14141
-
14142
- // We can't just pass in a path to `graph.fixedPath` as we need to modify
14143
- // the points in some way, so instead we provide a function for creating
14144
- // the path once the points have been transformed
14145
- const createCubicPath = function (points) {
14146
- let path = "M" + points[0][0] + " " + points[0][1];
14147
- for (let i = 1; i < points.length; i += 3) {
14148
- path += "C" + points[i][0] + " " + points[i][1] + " " + points[i + 1][0] + " " + points[i + 1][1] + " " + points[i + 2][0] + " " + points[i + 2][1];
14149
- }
14150
- return path;
14151
- };
14152
-
14153
- // Create arrowhead
14154
- const unscaledPoints = ___default["default"].map(points, graph.unscalePoint);
14155
- const options = {
14156
- center: graph.unscalePoint(center),
14157
- createPath: createCubicPath
14158
- };
14159
- const arrowHead = new WrappedPath(graph, unscaledPoints, options);
14160
- arrowHead.attr(___default["default"].extend({
14161
- "stroke-linejoin": "round",
14162
- "stroke-linecap": "round",
14163
- "stroke-dasharray": ""
14164
- }, style));
14165
-
14166
- // Add custom function for transforming arrowheads that accounts for
14167
- // center, scaling, etc.
14168
- arrowHead.toCoordAtAngle = function (coord, angle) {
14169
- const clipPoint = graph.scalePoint(getClipPoint(graph, coord, angle));
14170
- arrowHead.transform("translateX(" + (clipPoint[0] + scale * center[0]) + "px) " + "translateY(" + (clipPoint[1] + scale * center[1]) + "px) " + "translateZ(0) " + "rotate(" + (360 - KhanMath.bound(angle)) + "deg)");
14171
- };
14172
- return arrowHead;
14173
- };
14174
-
14175
14035
  /**
14176
14036
  * MovableLine option functions
14177
14037
  */
@@ -14258,16 +14118,16 @@ const draw$3 = {
14258
14118
  // @ts-expect-error - TS2551 - Property '_arrows' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. Did you mean 'arrows'?
14259
14119
  this._arrows.push(
14260
14120
  // @ts-expect-error - TS2339 - Property 'graphie' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. | TS2339 - Property 'normalStyle' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'.
14261
- createArrow(this.graphie, this.normalStyle()));
14121
+ new Arrowhead(this.graphie, this.normalStyle()));
14262
14122
  // @ts-expect-error - TS2551 - Property '_arrows' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. Did you mean 'arrows'?
14263
14123
  this._arrows.push(
14264
14124
  // @ts-expect-error - TS2339 - Property 'graphie' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. | TS2339 - Property 'normalStyle' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'.
14265
- createArrow(this.graphie, this.normalStyle()));
14125
+ new Arrowhead(this.graphie, this.normalStyle()));
14266
14126
  } else if (state.extendRay) {
14267
14127
  // @ts-expect-error - TS2551 - Property '_arrows' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. Did you mean 'arrows'?
14268
14128
  this._arrows.push(
14269
14129
  // @ts-expect-error - TS2339 - Property 'graphie' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. | TS2339 - Property 'normalStyle' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'.
14270
- createArrow(this.graphie, this.normalStyle()));
14130
+ new Arrowhead(this.graphie, this.normalStyle()));
14271
14131
  }
14272
14132
  }
14273
14133
 
@@ -14413,6 +14273,75 @@ var MovableLineOptions = {
14413
14273
  }
14414
14274
  };
14415
14275
 
14276
+ /**
14277
+ * A work-in-progress of _ methods for objects.
14278
+ * That is, they take an object as a parameter,
14279
+ * and return an object instead of an array.
14280
+ *
14281
+ * TODO(aria): Move this out of interactive2
14282
+ */
14283
+
14284
+ /**
14285
+ * Does a pluck on keys inside objects in an object
14286
+ *
14287
+ * Ex:
14288
+ * tools = {
14289
+ * translation: {
14290
+ * enabled: true
14291
+ * },
14292
+ * rotation: {
14293
+ * enabled: false
14294
+ * }
14295
+ * };
14296
+ * pluckObject(tools, "enabled") returns {
14297
+ * translation: true
14298
+ * rotation: false
14299
+ * }
14300
+ */
14301
+ const pluck = function (table, subKey) {
14302
+ return ___default["default"].object(___default["default"].map(table, function (value, key) {
14303
+ return [key, value[subKey]];
14304
+ }));
14305
+ };
14306
+
14307
+ /**
14308
+ * Maps an object to an object
14309
+ *
14310
+ * > mapObject({a: '1', b: '2'}, (value, key) => {
14311
+ * return value + 1;
14312
+ * });
14313
+ * {a: 2, b: 3}
14314
+ */
14315
+ const mapObject$2 = function (obj, lambda) {
14316
+ const result = {};
14317
+ ___default["default"].each(___default["default"].keys(obj), function (key) {
14318
+ // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
14319
+ result[key] = lambda(obj[key], key);
14320
+ });
14321
+ return result;
14322
+ };
14323
+
14324
+ /**
14325
+ * Maps an array to an object
14326
+ *
14327
+ * > mapObjectFromArray(['a', 'b'], function(elem) {
14328
+ * return elem + elem;
14329
+ * });
14330
+ * {a: 'aa', b: 'bb'}
14331
+ */
14332
+ const mapObjectFromArray$1 = function (arr, lambda) {
14333
+ const result = {};
14334
+ ___default["default"].each(arr, function (elem) {
14335
+ result[elem] = lambda(elem);
14336
+ });
14337
+ return result;
14338
+ };
14339
+ var objective_ = {
14340
+ pluck: pluck,
14341
+ mapObject: mapObject$2,
14342
+ mapObjectFromArray: mapObjectFromArray$1
14343
+ };
14344
+
14416
14345
  /**
14417
14346
  * MovableLine
14418
14347
  */
@@ -17975,33 +17904,33 @@ class Lint extends React__namespace.Component {
17975
17904
  let warningText;
17976
17905
  let warningTextStyle;
17977
17906
  if (this.props.severity === Severity.Error) {
17978
- severityStyle = styles$A.indicatorError;
17907
+ severityStyle = styles$B.indicatorError;
17979
17908
  warningText = "Error";
17980
- warningTextStyle = styles$A.publishBlockingError;
17909
+ warningTextStyle = styles$B.publishBlockingError;
17981
17910
  } else if (this.props.severity === Severity.Warning) {
17982
- severityStyle = styles$A.indicatorWarning;
17911
+ severityStyle = styles$B.indicatorWarning;
17983
17912
  warningText = "Warning";
17984
- warningTextStyle = styles$A.warning;
17913
+ warningTextStyle = styles$B.warning;
17985
17914
  } else {
17986
- severityStyle = styles$A.indicatorGuideline;
17915
+ severityStyle = styles$B.indicatorGuideline;
17987
17916
  warningText = "Recommendation";
17988
- warningTextStyle = styles$A.warning;
17917
+ warningTextStyle = styles$B.warning;
17989
17918
  }
17990
17919
  return /*#__PURE__*/React__namespace.createElement("a", {
17991
17920
  href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
17992
17921
  target: "lint-help-window",
17993
17922
  className: aphrodite.css(style)
17994
17923
  }, /*#__PURE__*/React__namespace.createElement("span", {
17995
- className: aphrodite.css(styles$A.indicator, severityStyle)
17924
+ className: aphrodite.css(styles$B.indicator, severityStyle)
17996
17925
  }, this.props.severity === 1 && /*#__PURE__*/React__namespace.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React__namespace.createElement("div", {
17997
- className: aphrodite.css(styles$A.tooltip, tooltipAbove && styles$A.tooltipAbove)
17926
+ className: aphrodite.css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
17998
17927
  }, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React__namespace.createElement("p", {
17999
17928
  key: i,
18000
- className: aphrodite.css(styles$A.tooltipParagraph)
17929
+ className: aphrodite.css(styles$B.tooltipParagraph)
18001
17930
  }, /*#__PURE__*/React__namespace.createElement("span", {
18002
17931
  className: aphrodite.css(warningTextStyle)
18003
17932
  }, warningText, ":", " "), m)), /*#__PURE__*/React__namespace.createElement("div", {
18004
- className: aphrodite.css(styles$A.tail, tooltipAbove && styles$A.tailAbove)
17933
+ className: aphrodite.css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
18005
17934
  })));
18006
17935
  };
18007
17936
 
@@ -18029,20 +17958,20 @@ class Lint extends React__namespace.Component {
18029
17958
  }
18030
17959
  if (blockHighlight) {
18031
17960
  return /*#__PURE__*/React__namespace.createElement("span", {
18032
- className: aphrodite.css(styles$A.lintContainer, styles$A.lintContainerBlock)
18033
- }, this.renderLink(styles$A.radioWidgetHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
17961
+ className: aphrodite.css(styles$B.lintContainer, styles$B.lintContainerBlock)
17962
+ }, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
18034
17963
  }
18035
17964
  if (inline) {
18036
17965
  return /*#__PURE__*/React__namespace.createElement("span", {
18037
- className: aphrodite.css(styles$A.lintContainer)
18038
- }, this.renderLink(styles$A.inlineHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
17966
+ className: aphrodite.css(styles$B.lintContainer)
17967
+ }, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
18039
17968
  }
18040
17969
  return /*#__PURE__*/React__namespace.createElement("div", {
18041
- className: aphrodite.css(styles$A.lintContainer)
18042
- }, this.renderLink(styles$A.hoverTarget), /*#__PURE__*/React__namespace.createElement("div", null, children));
17970
+ className: aphrodite.css(styles$B.lintContainer)
17971
+ }, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React__namespace.createElement("div", null, children));
18043
17972
  }
18044
17973
  }
18045
- const styles$A = aphrodite.StyleSheet.create({
17974
+ const styles$B = aphrodite.StyleSheet.create({
18046
17975
  // This is the class of the outermost element.
18047
17976
  // We use relative positioning so that the lint indicator can be
18048
17977
  // positioned absolutely relative to the position of the linty container.
@@ -20144,7 +20073,7 @@ class Renderer extends React__namespace.Component {
20144
20073
  };
20145
20074
  const mobileInnerStyle = {
20146
20075
  ...innerStyle,
20147
- ...styles$z.mobileZoomableParentFix
20076
+ ...styles$A.mobileZoomableParentFix
20148
20077
  };
20149
20078
  return /*#__PURE__*/React__namespace.createElement("div", {
20150
20079
  key: state.key,
@@ -20281,7 +20210,7 @@ class Renderer extends React__namespace.Component {
20281
20210
  };
20282
20211
  const mobileInnerStyle = {
20283
20212
  ...innerStyle,
20284
- ...styles$z.mobileZoomableParentFix
20213
+ ...styles$A.mobileZoomableParentFix
20285
20214
  };
20286
20215
  const wrappedOutput = /*#__PURE__*/React__namespace.createElement("div", {
20287
20216
  style: {
@@ -20789,7 +20718,7 @@ class Renderer extends React__namespace.Component {
20789
20718
  return this.lastRenderedMarkdown;
20790
20719
  }
20791
20720
  }
20792
- const styles$z = {
20721
+ const styles$A = {
20793
20722
  mobileZoomableParentFix: {
20794
20723
  // NOTE(abdul): There is an issue where transform animations will
20795
20724
  // cause the Zoomable component to disappear when running on the
@@ -21724,10 +21653,10 @@ class InputNumber extends React__namespace.Component {
21724
21653
  // Note: This is _very_ similar to what `numeric-input.jsx` does. If
21725
21654
  // you modify this, double-check if you also need to modify that
21726
21655
  // component.
21727
- const inputStyles = [styles$y.default, this.props.size === "small" ? styles$y.small : null, this.props.rightAlign ? styles$y.rightAlign : styles$y.leftAlign];
21656
+ const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
21728
21657
  // Unanswered
21729
21658
  if (rubric && !this.props.currentValue) {
21730
- inputStyles.push(styles$y.answerStateUnanswered);
21659
+ inputStyles.push(styles$z.answerStateUnanswered);
21731
21660
  }
21732
21661
  return /*#__PURE__*/React__namespace.createElement(InputWithExamples
21733
21662
  // eslint-disable-next-line react/no-string-refs
@@ -21875,7 +21804,7 @@ class InputNumber extends React__namespace.Component {
21875
21804
  return answerString;
21876
21805
  }
21877
21806
  }
21878
- const styles$y = aphrodite.StyleSheet.create({
21807
+ const styles$z = aphrodite.StyleSheet.create({
21879
21808
  default: {
21880
21809
  width: 80,
21881
21810
  height: "auto"
@@ -22873,7 +22802,7 @@ const FocusRing = function (props) {
22873
22802
  };
22874
22803
  return /*#__PURE__*/React__namespace.createElement("span", {
22875
22804
  "data-test-id": "focus-ring",
22876
- className: aphrodite.css(styles$x.ring),
22805
+ className: aphrodite.css(styles$y.ring),
22877
22806
  style: style
22878
22807
  }, children);
22879
22808
  };
@@ -22882,7 +22811,7 @@ FocusRing.defaultProps = {
22882
22811
  color: kaGreen$1,
22883
22812
  multipleSelect: false
22884
22813
  };
22885
- const styles$x = aphrodite.StyleSheet.create({
22814
+ const styles$y = aphrodite.StyleSheet.create({
22886
22815
  ring: {
22887
22816
  margin: "auto",
22888
22817
  display: "inline-block",
@@ -22919,7 +22848,7 @@ function getChoiceLetter(pos) {
22919
22848
  }
22920
22849
 
22921
22850
  const CHOICE_ICON_SIZE = 24;
22922
- const styles$w = aphrodite.StyleSheet.create({
22851
+ const styles$x = aphrodite.StyleSheet.create({
22923
22852
  iconWrapper: {
22924
22853
  display: "inline-block",
22925
22854
  position: "relative"
@@ -22942,7 +22871,7 @@ const CrossOutLine = function (props) {
22942
22871
  width: CROSS_OUT_LINE_SIZE,
22943
22872
  height: CROSS_OUT_LINE_SIZE,
22944
22873
  viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
22945
- className: aphrodite.css(styles$v.crossOutLine),
22874
+ className: aphrodite.css(styles$w.crossOutLine),
22946
22875
  "data-test-id": "choice-icon__cross-out-line"
22947
22876
  }, /*#__PURE__*/React__namespace.createElement("line", {
22948
22877
  // The line stretches from the bottom-left to top-right.
@@ -22957,7 +22886,7 @@ const CrossOutLine = function (props) {
22957
22886
  strokeLinecap: "round"
22958
22887
  }));
22959
22888
  };
22960
- const styles$v = aphrodite.StyleSheet.create({
22889
+ const styles$w = aphrodite.StyleSheet.create({
22961
22890
  crossOutLine: {
22962
22891
  // Center the icon within the container.
22963
22892
  position: "absolute",
@@ -23038,7 +22967,7 @@ const ChoiceIcon = function (props) {
23038
22967
  } = props;
23039
22968
  const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
23040
22969
  return /*#__PURE__*/React__namespace.createElement("div", {
23041
- className: aphrodite.css(styles$w.iconWrapper)
22970
+ className: aphrodite.css(styles$x.iconWrapper)
23042
22971
  }, /*#__PURE__*/React__namespace.createElement(FocusRing, {
23043
22972
  color: Color__default["default"].blue,
23044
22973
  visible: focused || hovered,
@@ -23047,13 +22976,13 @@ const ChoiceIcon = function (props) {
23047
22976
  // @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
23048
22977
  style: dynamicStyles,
23049
22978
  "data-test-id": "choice-icon__library-choice-icon",
23050
- className: aphrodite.css(styles$u.circle, showCorrectness && correct && styles$u.circleCorrect, showCorrectness && !correct && styles$u.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$u.circleIncorrectAnswered)
22979
+ className: aphrodite.css(styles$v.circle, showCorrectness && correct && styles$v.circleCorrect, showCorrectness && !correct && styles$v.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$v.circleIncorrectAnswered)
23051
22980
  // used in BaseRadio editMode to check
23052
22981
  // if we actually clicked on the radio icon
23053
22982
  ,
23054
22983
  "data-is-radio-icon": true
23055
22984
  }, /*#__PURE__*/React__namespace.createElement("div", {
23056
- className: aphrodite.css(styles$u.innerWrapper)
22985
+ className: aphrodite.css(styles$v.innerWrapper)
23057
22986
  }, /*#__PURE__*/React__namespace.createElement(ChoiceInner, {
23058
22987
  pos: pos,
23059
22988
  showCorrectness: showCorrectness,
@@ -23062,7 +22991,7 @@ const ChoiceIcon = function (props) {
23062
22991
  color: dynamicStyles.borderColor
23063
22992
  }));
23064
22993
  };
23065
- const styles$u = aphrodite.StyleSheet.create({
22994
+ const styles$v = aphrodite.StyleSheet.create({
23066
22995
  innerWrapper: {
23067
22996
  width: CHOICE_ICON_SIZE,
23068
22997
  height: CHOICE_ICON_SIZE,
@@ -23154,19 +23083,19 @@ const OptionStatus = function (props) {
23154
23083
  }
23155
23084
  let textStyle;
23156
23085
  if (correct) {
23157
- textStyle = styles$t.correct;
23086
+ textStyle = styles$u.correct;
23158
23087
  } else {
23159
23088
  if (checked || previouslyAnswered) {
23160
- textStyle = styles$t.incorrectAnswered;
23089
+ textStyle = styles$u.incorrectAnswered;
23161
23090
  } else {
23162
- textStyle = styles$t.incorrect;
23091
+ textStyle = styles$u.incorrect;
23163
23092
  }
23164
23093
  }
23165
23094
  return /*#__PURE__*/React__namespace.createElement("div", {
23166
- className: aphrodite.css(styles$t.text, textStyle)
23095
+ className: aphrodite.css(styles$u.text, textStyle)
23167
23096
  }, renderText(checked, correct, crossedOut));
23168
23097
  };
23169
- const styles$t = aphrodite.StyleSheet.create({
23098
+ const styles$u = aphrodite.StyleSheet.create({
23170
23099
  text: {
23171
23100
  alignItems: "center",
23172
23101
  display: "flex",
@@ -23240,8 +23169,8 @@ const Choice = function (props) {
23240
23169
  crossedOut: updatedCrossedOut
23241
23170
  });
23242
23171
  }
23243
- const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$s.description));
23244
- const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$s.rationale));
23172
+ const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$t.description));
23173
+ const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$t.rationale));
23245
23174
 
23246
23175
  // We want to show the choices as dimmed out when the choices are disabled.
23247
23176
  // However, we don't want to do this when we're in review mode in the
@@ -23412,7 +23341,7 @@ const Choice = function (props) {
23412
23341
  "data-test-id": `perseus-radio-rationale-content-${pos}`
23413
23342
  }, rationale));
23414
23343
  };
23415
- const styles$s = aphrodite.StyleSheet.create({
23344
+ const styles$t = aphrodite.StyleSheet.create({
23416
23345
  description: {
23417
23346
  display: "inline-block",
23418
23347
  width: "100%"
@@ -23604,10 +23533,10 @@ const BaseRadio = function (props) {
23604
23533
  const isMobile = apiOptions.isMobile;
23605
23534
  const firstChoiceHighlighted = choices[0].highlighted;
23606
23535
  const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
23607
- const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$r.radio, styles$r.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$r.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$r.radioContainerLastHighlighted));
23608
- const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$r.instructions, isMobile && styles$r.instructionsMobile));
23536
+ const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$s.radio, styles$s.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$s.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$s.radioContainerLastHighlighted));
23537
+ const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$s.instructions, isMobile && styles$s.instructionsMobile));
23609
23538
  const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect);
23610
- const responsiveClassName = aphrodite.css(styles$r.responsiveFieldset);
23539
+ const responsiveClassName = aphrodite.css(styles$s.responsiveFieldset);
23611
23540
  const fieldset = /*#__PURE__*/React__namespace.createElement("fieldset", {
23612
23541
  className: `perseus-widget-radio-fieldset ${responsiveClassName}`
23613
23542
  }, /*#__PURE__*/React__namespace.createElement("legend", {
@@ -23658,7 +23587,7 @@ const BaseRadio = function (props) {
23658
23587
  const aphroditeClassName = checked => {
23659
23588
  // Whether or not to show correctness borders
23660
23589
  // for this choice and the next choice.
23661
- return aphrodite.css(sharedStyles.aboveScratchpad, styles$r.item, styles$r.responsiveItem, checked && styles$r.selectedItem, checked && choice.highlighted && styles$r.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$r.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$r.nextHighlighted);
23590
+ return aphrodite.css(sharedStyles.aboveScratchpad, styles$s.item, styles$s.responsiveItem, checked && styles$s.selectedItem, checked && choice.highlighted && styles$s.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$s.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$s.nextHighlighted);
23662
23591
  };
23663
23592
 
23664
23593
  // HACK(abdulrahman): Preloads the selection-state
@@ -23732,14 +23661,14 @@ const BaseRadio = function (props) {
23732
23661
  // Allow for horizontal scrolling if content is too wide, which may be
23733
23662
  // an issue especially on phones.
23734
23663
  return /*#__PURE__*/React__namespace.createElement("div", {
23735
- className: aphrodite.css(styles$r.responsiveContainer)
23664
+ className: aphrodite.css(styles$s.responsiveContainer)
23736
23665
  }, fieldset);
23737
23666
  };
23738
23667
  BaseRadio.defaultProps = {
23739
23668
  editMode: false,
23740
23669
  multipleSelect: false
23741
23670
  };
23742
- const styles$r = aphrodite.StyleSheet.create({
23671
+ const styles$s = aphrodite.StyleSheet.create({
23743
23672
  instructions: {
23744
23673
  display: "block",
23745
23674
  color: gray17,
@@ -24398,9 +24327,9 @@ class Categorizer extends React__namespace.Component {
24398
24327
  indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
24399
24328
  }
24400
24329
  const table = /*#__PURE__*/React__namespace.createElement("table", {
24401
- className: "categorizer-table " + aphrodite.css(styles$q.mobileTable)
24330
+ className: "categorizer-table " + aphrodite.css(styles$r.mobileTable)
24402
24331
  }, /*#__PURE__*/React__namespace.createElement("thead", null, /*#__PURE__*/React__namespace.createElement("tr", null, /*#__PURE__*/React__namespace.createElement("td", {
24403
- className: aphrodite.css(styles$q.emptyHeaderCell)
24332
+ className: aphrodite.css(styles$r.emptyHeaderCell)
24404
24333
  }), this.props.categories.map((category, i) => {
24405
24334
  // Array index is the correct key here, as that's
24406
24335
  // how category grading actually works -- no way
@@ -24408,7 +24337,7 @@ class Categorizer extends React__namespace.Component {
24408
24337
  // middle. (If we later add that, this should be
24409
24338
  // fixed.)
24410
24339
  return /*#__PURE__*/React__namespace.createElement("th", {
24411
- className: aphrodite.css(styles$q.header),
24340
+ className: aphrodite.css(styles$r.header),
24412
24341
  key: i
24413
24342
  }, /*#__PURE__*/React__namespace.createElement(Renderer, {
24414
24343
  content: category,
@@ -24428,7 +24357,7 @@ class Categorizer extends React__namespace.Component {
24428
24357
  })), self.props.categories.map((catName, catNum) => {
24429
24358
  const selected = self.props.values[itemNum] === catNum;
24430
24359
  return /*#__PURE__*/React__namespace.createElement("td", {
24431
- className: "category " + aphrodite.css(styles$q.cell),
24360
+ className: "category " + aphrodite.css(styles$r.cell),
24432
24361
  key: catNum
24433
24362
  }, /*#__PURE__*/React__namespace.createElement("div", {
24434
24363
  className: ClassNames.INTERACTIVE,
@@ -24447,7 +24376,7 @@ class Categorizer extends React__namespace.Component {
24447
24376
  onChange: this.onChange.bind(this, itemNum, catNum),
24448
24377
  onClick: e => e.stopPropagation()
24449
24378
  }), !isMobile && /*#__PURE__*/React__namespace.createElement("span", {
24450
- className: aphrodite.css(styles$q.radioSpan, selected && styles$q.checkedRadioSpan, this.props.static && selected && styles$q.staticCheckedRadioSpan)
24379
+ className: aphrodite.css(styles$r.radioSpan, selected && styles$r.checkedRadioSpan, this.props.static && selected && styles$r.staticCheckedRadioSpan)
24451
24380
  }, selected ? /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircleThin))));
24452
24381
  }));
24453
24382
  /* eslint-enable max-len */
@@ -24459,7 +24388,7 @@ class Categorizer extends React__namespace.Component {
24459
24388
  "categorizer-container": true,
24460
24389
  "static-mode": this.props.static
24461
24390
  });
24462
- const inlineStyles = this.props.apiOptions.isMobile ? [styles$q.fullBleedContainer] : [];
24391
+ const inlineStyles = this.props.apiOptions.isMobile ? [styles$r.fullBleedContainer] : [];
24463
24392
  return /*#__PURE__*/React__namespace.createElement("div", {
24464
24393
  className: extraClassNames + " " + aphrodite.css(...inlineStyles)
24465
24394
  }, table);
@@ -24508,7 +24437,7 @@ const pageMargin = 16;
24508
24437
 
24509
24438
  // Stylesheets aren't directly testable
24510
24439
  /* c8 ignore next */
24511
- const styles$q = aphrodite.StyleSheet.create({
24440
+ const styles$r = aphrodite.StyleSheet.create({
24512
24441
  mobileTable: {
24513
24442
  [mediaQueries.smOrSmaller]: {
24514
24443
  minWidth: "auto"
@@ -24618,7 +24547,7 @@ const toAbsoluteUrl = url => parseUrl(url).href;
24618
24547
  const {
24619
24548
  updateQueryString: updateQueryString$1
24620
24549
  } = Util;
24621
- function getUrlFromProgramID(programID) {
24550
+ function getUrlFromProgramID$1(programID) {
24622
24551
  const {
24623
24552
  InitialRequestUrl
24624
24553
  } = getDependencies();
@@ -24727,7 +24656,7 @@ class CSProgram extends React__namespace.Component {
24727
24656
  return /*#__PURE__*/React__namespace.createElement("div", null);
24728
24657
  }
24729
24658
  let styleContainer = false;
24730
- let url = getUrlFromProgramID(this.props.programID);
24659
+ let url = getUrlFromProgramID$1(this.props.programID);
24731
24660
  let className;
24732
24661
  const style = {
24733
24662
  height: this.props.height,
@@ -24771,7 +24700,7 @@ class CSProgram extends React__namespace.Component {
24771
24700
  // creator "went wild".
24772
24701
  // http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
24773
24702
  return /*#__PURE__*/React__namespace.createElement("div", {
24774
- className: aphrodite.css(styles$p.widthOverride, styleContainer && styles$p.container)
24703
+ className: aphrodite.css(styles$q.widthOverride, styleContainer && styles$q.container)
24775
24704
  }, /*#__PURE__*/React__namespace.createElement("iframe", {
24776
24705
  sandbox: sandboxOptions,
24777
24706
  src: url,
@@ -24781,7 +24710,7 @@ class CSProgram extends React__namespace.Component {
24781
24710
  }));
24782
24711
  }
24783
24712
  }
24784
- const styles$p = aphrodite.StyleSheet.create({
24713
+ const styles$q = aphrodite.StyleSheet.create({
24785
24714
  // Override the inherited width from the perseus paragraph class
24786
24715
  // 820 is minimum width for 420px editor and 400px canvas
24787
24716
  widthOverride: {
@@ -24829,7 +24758,7 @@ class Definition extends React__namespace.Component {
24829
24758
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.Popover, {
24830
24759
  content: /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
24831
24760
  color: "white",
24832
- style: styles$o.tooltipBody,
24761
+ style: styles$p.tooltipBody,
24833
24762
  closeButtonVisible: true
24834
24763
  }, /*#__PURE__*/React__namespace.createElement(Renderer, {
24835
24764
  apiOptions: this.props.apiOptions,
@@ -24860,7 +24789,7 @@ class Definition extends React__namespace.Component {
24860
24789
  });
24861
24790
  }
24862
24791
  }
24863
- const styles$o = {
24792
+ const styles$p = {
24864
24793
  tooltipBody: {
24865
24794
  color: Color__default["default"].offBlack,
24866
24795
  fontSize: 20,
@@ -25064,15 +24993,15 @@ class Explanation extends React__namespace.Component {
25064
24993
  const onClick = this._onClick;
25065
24994
  if (isMobile) {
25066
24995
  linkContainer = /*#__PURE__*/React__namespace.createElement("div", {
25067
- className: aphrodite.css(styles$n.linkContainer)
24996
+ className: aphrodite.css(styles$o.linkContainer)
25068
24997
  }, /*#__PURE__*/React__namespace.createElement("a", {
25069
- className: aphrodite.css(styles$n.mobileExplanationLink),
24998
+ className: aphrodite.css(styles$o.mobileExplanationLink),
25070
24999
  href: href,
25071
25000
  onClick: onClick,
25072
25001
  role: "button",
25073
25002
  "aria-expanded": this.state.expanded
25074
25003
  }, linkAnchor), this.state.expanded && /*#__PURE__*/React__namespace.createElement("svg", {
25075
- className: aphrodite.css(styles$n.disclosureArrow)
25004
+ className: aphrodite.css(styles$o.disclosureArrow)
25076
25005
  }, /*#__PURE__*/React__namespace.createElement("polygon", {
25077
25006
  style: {
25078
25007
  fill: backgroundColor
@@ -25085,13 +25014,13 @@ class Explanation extends React__namespace.Component {
25085
25014
  // an anchor tag (if rendered in a modal) or a Wonder Blocks
25086
25015
  // link component in lesson page, see: `article-page.jsx`.
25087
25016
  linkContainer = /*#__PURE__*/React__namespace.createElement("div", {
25088
- className: aphrodite.css(styles$n.linkContainer, styles$n.articleLink)
25017
+ className: aphrodite.css(styles$o.linkContainer, styles$o.articleLink)
25089
25018
  }, /*#__PURE__*/React__namespace.createElement(Link, {
25090
- className: aphrodite.css(styles$n.explanationLink)
25019
+ className: aphrodite.css(styles$o.explanationLink)
25091
25020
  // HACK(michaelpolyak): WB Link doesn't passthrough
25092
25021
  // class name.
25093
25022
  ,
25094
- style: styles$n.explanationLink,
25023
+ style: styles$o.explanationLink,
25095
25024
  href: href,
25096
25025
  onClick: onClick,
25097
25026
  role: "button",
@@ -25101,9 +25030,9 @@ class Explanation extends React__namespace.Component {
25101
25030
  // NOTE: For exercises, the baseElements `Link` is an
25102
25031
  // anchor tag, see: `perseus-api.jsx`.
25103
25032
  linkContainer = /*#__PURE__*/React__namespace.createElement("div", {
25104
- className: aphrodite.css(styles$n.linkContainer, styles$n.exerciseLink)
25033
+ className: aphrodite.css(styles$o.linkContainer, styles$o.exerciseLink)
25105
25034
  }, /*#__PURE__*/React__namespace.createElement(Link, {
25106
- className: aphrodite.css(styles$n.explanationLink),
25035
+ className: aphrodite.css(styles$o.explanationLink),
25107
25036
  href: href,
25108
25037
  onClick: onClick,
25109
25038
  role: "button",
@@ -25111,11 +25040,11 @@ class Explanation extends React__namespace.Component {
25111
25040
  }, `[${linkAnchor}]`));
25112
25041
  }
25113
25042
  }
25114
- const expandedStyle = isMobile ? styles$n.contentExpandedMobile : styles$n.contentExpanded;
25043
+ const expandedStyle = isMobile ? styles$o.contentExpandedMobile : styles$o.contentExpanded;
25115
25044
  return /*#__PURE__*/React__namespace.createElement("div", {
25116
- className: aphrodite.css(styles$n.container)
25045
+ className: aphrodite.css(styles$o.container)
25117
25046
  }, linkContainer, this.state.expanded && /*#__PURE__*/React__namespace.createElement("div", {
25118
- className: aphrodite.css(styles$n.content, isMobile && styles$n.contentMobile, this.state.expanded && expandedStyle)
25047
+ className: aphrodite.css(styles$o.content, isMobile && styles$o.contentMobile, this.state.expanded && expandedStyle)
25119
25048
  // eslint-disable-next-line react/no-string-refs
25120
25049
  ,
25121
25050
  ref: "content"
@@ -25138,7 +25067,7 @@ const verticalContentPadding = 10;
25138
25067
  const arrowWidth = 30;
25139
25068
  const arrowHeight = 14;
25140
25069
  const backgroundColor = gray95;
25141
- const styles$n = aphrodite.StyleSheet.create({
25070
+ const styles$o = aphrodite.StyleSheet.create({
25142
25071
  container: {
25143
25072
  display: "inline",
25144
25073
  position: "relative"
@@ -25244,15 +25173,15 @@ class GradedGroupAnswerBar extends React__namespace.Component {
25244
25173
  onNextQuestion
25245
25174
  } = this.props;
25246
25175
  const answerBarStyle = {
25247
- ...styles$m.answerBar,
25176
+ ...styles$n.answerBar,
25248
25177
  backgroundColor: answerBarState === "CORRECT" ? Color__default["default"].offWhite : "white",
25249
25178
  // Center the "Correct!" message only when there's no next question
25250
25179
  justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
25251
25180
  };
25252
25181
  const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React__namespace.createElement("span", {
25253
- style: styles$m.text
25182
+ style: styles$n.text
25254
25183
  }, /*#__PURE__*/React__namespace.createElement("span", {
25255
- style: styles$m.tryAgainIcon
25184
+ style: styles$n.tryAgainIcon
25256
25185
  }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React__namespace.createElement("span", {
25257
25186
  style: {
25258
25187
  marginLeft: 8
@@ -25271,7 +25200,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
25271
25200
  return /*#__PURE__*/React__namespace.createElement("div", {
25272
25201
  style: answerBarStyle
25273
25202
  }, /*#__PURE__*/React__namespace.createElement("span", {
25274
- style: styles$m.text
25203
+ style: styles$n.text
25275
25204
  }, /*#__PURE__*/React__namespace.createElement("span", {
25276
25205
  style: {
25277
25206
  fontSize: 28,
@@ -25293,7 +25222,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
25293
25222
  }
25294
25223
  }
25295
25224
  const fontSize = 17;
25296
- const styles$m = {
25225
+ const styles$n = {
25297
25226
  answerBar: {
25298
25227
  display: "flex",
25299
25228
  alignItems: "center",
@@ -25493,7 +25422,7 @@ class GradedGroup extends React__namespace.Component {
25493
25422
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
25494
25423
  gradeStatus = i18n__namespace._("Incorrect");
25495
25424
  }
25496
- const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$l.gradedGroupInSet) : aphrodite.css(styles$l.gradedGroup);
25425
+ const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$m.gradedGroupInSet) : aphrodite.css(styles$m.gradedGroup);
25497
25426
  const classes = classNames__default["default"]({
25498
25427
  [mobileClass]: apiOptions.isMobile,
25499
25428
  "perseus-graded-group": true,
@@ -25512,7 +25441,7 @@ class GradedGroup extends React__namespace.Component {
25512
25441
  return /*#__PURE__*/React__namespace.createElement("div", {
25513
25442
  className: classes
25514
25443
  }, !!this.props.title && /*#__PURE__*/React__namespace.createElement("div", {
25515
- className: aphrodite.css(styles$l.title)
25444
+ className: aphrodite.css(styles$m.title)
25516
25445
  }, this.props.title), /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, this.props, {
25517
25446
  // eslint-disable-next-line react/no-string-refs
25518
25447
  ref: "renderer",
@@ -25545,7 +25474,7 @@ class GradedGroup extends React__namespace.Component {
25545
25474
  }, i18n__namespace._("Next question")), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("button", {
25546
25475
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
25547
25476
  tabIndex: "0",
25548
- className: aphrodite.css(styles$l.explanationTitle),
25477
+ className: aphrodite.css(styles$m.explanationTitle),
25549
25478
  onClick: () => this.setState({
25550
25479
  showHint: false
25551
25480
  }),
@@ -25577,7 +25506,7 @@ class GradedGroup extends React__namespace.Component {
25577
25506
  showHint: true
25578
25507
  });
25579
25508
  },
25580
- className: aphrodite.css(styles$l.showHintLink)
25509
+ className: aphrodite.css(styles$m.showHintLink)
25581
25510
  }, i18n__namespace._("Explain"))), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React__namespace.createElement(GradedGroupAnswerBar, {
25582
25511
  apiOptions: apiOptions,
25583
25512
  answerBarState: answerBarState,
@@ -25589,7 +25518,7 @@ class GradedGroup extends React__namespace.Component {
25589
25518
  const traverseChildWidgets$3 = function (props, traverseRenderer) {
25590
25519
  return ___default["default"].extend({}, props, traverseRenderer(props));
25591
25520
  };
25592
- const styles$l = aphrodite.StyleSheet.create({
25521
+ const styles$m = aphrodite.StyleSheet.create({
25593
25522
  gradedGroupInSet: {
25594
25523
  // Reset a few desktop-only styles that come from graded-group.less
25595
25524
  marginLeft: 0,
@@ -25659,20 +25588,20 @@ class Indicators extends React__namespace.Component {
25659
25588
  return /*#__PURE__*/React__namespace.createElement("ul", {
25660
25589
  // reduntantly add class name for use in .less files--
25661
25590
  // the styles object key gets hashed
25662
- className: classNames__default["default"](aphrodite.css(styles$k.indicatorContainer), "indicatorContainer")
25591
+ className: classNames__default["default"](aphrodite.css(styles$l.indicatorContainer), "indicatorContainer")
25663
25592
  }, this.props.gradedGroups.map((_ref, i) => {
25664
25593
  let {
25665
25594
  title
25666
25595
  } = _ref;
25667
25596
  return /*#__PURE__*/React__namespace.createElement("li", {
25668
- className: aphrodite.css(styles$k.indicator),
25597
+ className: aphrodite.css(styles$l.indicator),
25669
25598
  key: title
25670
25599
  }, /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
25671
25600
  role: "button",
25672
25601
  "aria-label": i18n__namespace._("Skip to %(title)s", {
25673
25602
  title
25674
25603
  }),
25675
- style: styles$k.indicatorButton,
25604
+ style: styles$l.indicatorButton,
25676
25605
  onClick: () => this.props.onChangeCurrentGroup(i),
25677
25606
  onKeyDown: e => this.handleKeyDown(e, i)
25678
25607
  }, _ref2 => {
@@ -25682,9 +25611,9 @@ class Indicators extends React__namespace.Component {
25682
25611
  pressed
25683
25612
  } = _ref2;
25684
25613
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
25685
- style: [styles$k.indicatorDot, (hovered || focused || pressed) && styles$k.indicatorDotFocused]
25614
+ style: [styles$l.indicatorDot, (hovered || focused || pressed) && styles$l.indicatorDotFocused]
25686
25615
  }, i === this.props.currentGroup && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
25687
- style: styles$k.indicatorDotActive
25616
+ style: styles$l.indicatorDotActive
25688
25617
  }, /*#__PURE__*/React__namespace.createElement("span", {
25689
25618
  className: aphrodite.css(a11y.srOnly)
25690
25619
  }, i18n__namespace._("Current"))));
@@ -25760,7 +25689,7 @@ class GradedGroupSet extends React__namespace.Component {
25760
25689
  } = getDependencies();
25761
25690
  if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
25762
25691
  return /*#__PURE__*/React__namespace.createElement("div", {
25763
- className: aphrodite.css(styles$k.container)
25692
+ className: aphrodite.css(styles$l.container)
25764
25693
  }, this.props.gradedGroups.map((gradedGroup, i) => {
25765
25694
  return (
25766
25695
  /*#__PURE__*/
@@ -25783,13 +25712,13 @@ class GradedGroupSet extends React__namespace.Component {
25783
25712
  const numGroups = this.props.gradedGroups.length;
25784
25713
  const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
25785
25714
  return /*#__PURE__*/React__namespace.createElement("div", {
25786
- className: aphrodite.css(styles$k.container)
25715
+ className: aphrodite.css(styles$l.container)
25787
25716
  }, /*#__PURE__*/React__namespace.createElement("div", {
25788
- className: aphrodite.css(styles$k.top)
25717
+ className: aphrodite.css(styles$l.top)
25789
25718
  }, /*#__PURE__*/React__namespace.createElement("div", {
25790
- className: aphrodite.css(styles$k.title)
25719
+ className: aphrodite.css(styles$l.title)
25791
25720
  }, currentGroup.title), /*#__PURE__*/React__namespace.createElement("div", {
25792
- className: aphrodite.css(styles$k.spacer)
25721
+ className: aphrodite.css(styles$l.spacer)
25793
25722
  }), /*#__PURE__*/React__namespace.createElement(Indicators, {
25794
25723
  currentGroup: this.state.currentGroup,
25795
25724
  gradedGroups: this.props.gradedGroups,
@@ -25827,7 +25756,7 @@ var GradedGroupSet$1 = {
25827
25756
  tracking: "all",
25828
25757
  isLintable: true
25829
25758
  };
25830
- const styles$k = aphrodite.StyleSheet.create({
25759
+ const styles$l = aphrodite.StyleSheet.create({
25831
25760
  top: {
25832
25761
  display: "flex",
25833
25762
  flexDirection: "row"
@@ -25932,7 +25861,7 @@ class ButtonGroup extends React__namespace.Component {
25932
25861
  id: "" + i,
25933
25862
  ref: "button" + i,
25934
25863
  key: "" + i,
25935
- className: aphrodite.css(styles$j.buttonStyle, button.value === value && styles$j.selectedStyle),
25864
+ className: aphrodite.css(styles$k.buttonStyle, button.value === value && styles$k.selectedStyle),
25936
25865
  onClick: () => this.toggleSelect(button.value)
25937
25866
  }, button.content || "" + button.value);
25938
25867
  });
@@ -25945,7 +25874,7 @@ class ButtonGroup extends React__namespace.Component {
25945
25874
  }, buttons);
25946
25875
  }
25947
25876
  }
25948
- const styles$j = aphrodite.StyleSheet.create({
25877
+ const styles$k = aphrodite.StyleSheet.create({
25949
25878
  buttonStyle: {
25950
25879
  backgroundColor: "white",
25951
25880
  border: "1px solid #ccc",
@@ -31215,7 +31144,7 @@ const HideAnswersToggle = props => {
31215
31144
  const switchId = idFactory.get("hide-answers-toggle");
31216
31145
  const labelId = idFactory.get("hide-answers-label");
31217
31146
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
31218
- style: styles$i.switchWrapper
31147
+ style: styles$j.switchWrapper
31219
31148
  }, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
31220
31149
  id: switchId,
31221
31150
  checked: props.areAnswersHidden,
@@ -31227,7 +31156,7 @@ const HideAnswersToggle = props => {
31227
31156
  tag: "label"
31228
31157
  }, strings.hideAnswersToggleLabel));
31229
31158
  };
31230
- const styles$i = aphrodite.StyleSheet.create({
31159
+ const styles$j = aphrodite.StyleSheet.create({
31231
31160
  switchWrapper: {
31232
31161
  display: "flex",
31233
31162
  flexDirection: "row",
@@ -31282,14 +31211,14 @@ const AnswerPill = props => {
31282
31211
  id: idFactory.get("perseus-label-image-widget-answer-pill"),
31283
31212
  onClick: correct ? undefined : onClick,
31284
31213
  ref: ref,
31285
- style: [style, popperStyle, styles$h.pill, correct && styles$h.correct, incorrect && styles$h.incorrect, (focused || hovered) && BringToFront]
31214
+ style: [style, popperStyle, styles$i.pill, correct && styles$i.correct, incorrect && styles$i.incorrect, (focused || hovered) && BringToFront]
31286
31215
  }, /*#__PURE__*/React__namespace.createElement(Renderer, {
31287
31216
  content: answerString,
31288
31217
  inline: true
31289
31218
  }));
31290
31219
  });
31291
31220
  };
31292
- const styles$h = aphrodite.StyleSheet.create({
31221
+ const styles$i = aphrodite.StyleSheet.create({
31293
31222
  correct: {
31294
31223
  // WB green darkened by 18%
31295
31224
  backgroundColor: "#00880b"
@@ -31343,25 +31272,25 @@ class Marker extends React__namespace.Component {
31343
31272
  icon: iconNull
31344
31273
  };
31345
31274
  if (showCorrectness) {
31346
- iconStyles = [styles$g.markerGraded, showCorrectness === "correct" ? styles$g.markerCorrect : styles$g.markerIncorrect, isOpen && styles$g.markerSelected];
31275
+ iconStyles = [styles$h.markerGraded, showCorrectness === "correct" ? styles$h.markerCorrect : styles$h.markerIncorrect, isOpen && styles$h.markerSelected];
31347
31276
  args = {
31348
31277
  ...args,
31349
31278
  icon: showCorrectness === "correct" ? iconCheck : iconMinus
31350
31279
  };
31351
31280
  } else if (selectedAnswers && selectedAnswers.length > 0) {
31352
- iconStyles = [styles$g.markerFilled, isOpen && styles$g.markerSelected];
31281
+ iconStyles = [styles$h.markerFilled, isOpen && styles$h.markerSelected];
31353
31282
  } else if (isOpen) {
31354
- iconStyles = [styles$g.markerSelected];
31283
+ iconStyles = [styles$h.markerSelected];
31355
31284
  args = {
31356
31285
  ...args,
31357
31286
  icon: iconChevronDown,
31358
31287
  size: 8
31359
31288
  };
31360
31289
  } else if (showPulsate) {
31361
- iconStyles = [styles$g.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$g.markerUnfilledPulsateOnce : showPulsate && styles$g.markerUnfilledPulsateInfinite];
31290
+ iconStyles = [styles$h.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$h.markerUnfilledPulsateOnce : showPulsate && styles$h.markerUnfilledPulsateInfinite];
31362
31291
  }
31363
31292
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
31364
- style: [styles$g.markerIcon, iconStyles],
31293
+ style: [styles$h.markerIcon, iconStyles],
31365
31294
  ref: node => this._icon = node
31366
31295
  }, /*#__PURE__*/React__namespace.createElement(Icon, args));
31367
31296
  }
@@ -31382,7 +31311,7 @@ class Marker extends React__namespace.Component {
31382
31311
  const markerDisabled = showCorrectness === "correct";
31383
31312
  const active = hovered || focused;
31384
31313
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
31385
- style: [styles$g.marker, active && !markerDisabled && styles$g.markerActive]
31314
+ style: [styles$h.marker, active && !markerDisabled && styles$h.markerActive]
31386
31315
  // already translated in: /widgets/graded-group.tsx
31387
31316
  ,
31388
31317
  "aria-label": markerDisabled ? i18n__namespace._("Correct!") : label
@@ -31397,7 +31326,7 @@ class Marker extends React__namespace.Component {
31397
31326
  }));
31398
31327
  }
31399
31328
  }
31400
- const styles$g = aphrodite.StyleSheet.create({
31329
+ const styles$h = aphrodite.StyleSheet.create({
31401
31330
  marker: {
31402
31331
  position: "absolute",
31403
31332
  backgroundColor: Color__default["default"].white,
@@ -31974,13 +31903,13 @@ class LabelImage extends React__namespace.Component {
31974
31903
  const promptString = isMobile ? multipleAnswers ? i18n__namespace._("Tap each dot on the image to select all answers that apply.") : i18n__namespace._("Tap each dot on the image to select an answer.") : multipleAnswers ? i18n__namespace._("Click each dot on the image to select all answers that apply.") : i18n__namespace._("Click each dot on the image to select an answer.");
31975
31904
  const choicesString = i18n__namespace._("Choices:");
31976
31905
  return /*#__PURE__*/React__namespace.createElement("div", {
31977
- className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$f.instructions))
31906
+ className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$g.instructions))
31978
31907
  }, /*#__PURE__*/React__namespace.createElement("div", {
31979
- className: aphrodite.css(styles$f.instructionsCaption)
31908
+ className: aphrodite.css(styles$g.instructionsCaption)
31980
31909
  }, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React__namespace.createElement("div", {
31981
- className: aphrodite.css(styles$f.instructionsChoices)
31910
+ className: aphrodite.css(styles$g.instructionsChoices)
31982
31911
  }, choices.map((choice, index) => /*#__PURE__*/React__namespace.createElement("div", {
31983
- className: aphrodite.css(styles$f.instructionsChoice),
31912
+ className: aphrodite.css(styles$g.instructionsChoice),
31984
31913
  key: index
31985
31914
  }, /*#__PURE__*/React__namespace.createElement(Renderer, {
31986
31915
  content: choice
@@ -31997,20 +31926,20 @@ class LabelImage extends React__namespace.Component {
31997
31926
  activeMarkerIndex
31998
31927
  } = this.state;
31999
31928
  return /*#__PURE__*/React__namespace.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React__namespace.createElement("div", {
32000
- className: aphrodite.css(styles$f.markersCanvas),
31929
+ className: aphrodite.css(styles$g.markersCanvas),
32001
31930
  style: {
32002
31931
  maxWidth: imageWidth,
32003
31932
  maxHeight: imageHeight
32004
31933
  }
32005
31934
  }, /*#__PURE__*/React__namespace.createElement("div", {
32006
- className: aphrodite.css(styles$f.imageContainer,
31935
+ className: aphrodite.css(styles$g.imageContainer,
32007
31936
  // Ensure image interaction is disabled while answer
32008
31937
  // choices popup is visible. This addresses specific
32009
31938
  // case where user may click on question image to
32010
31939
  // dismiss the popup. If the image is larger in size
32011
31940
  // than its rendered in the widget, this would
32012
31941
  // result in a zoom of the image.
32013
- activeMarkerIndex !== -1 && styles$f.imageInteractionDisabled)
31942
+ activeMarkerIndex !== -1 && styles$g.imageInteractionDisabled)
32014
31943
  }, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref3 => {
32015
31944
  let {
32016
31945
  setAssetStatus
@@ -32036,7 +31965,7 @@ class LabelImage extends React__namespace.Component {
32036
31965
  }));
32037
31966
  }
32038
31967
  }
32039
- const styles$f = aphrodite.StyleSheet.create({
31968
+ const styles$g = aphrodite.StyleSheet.create({
32040
31969
  instructions: {
32041
31970
  paddingBottom: 16
32042
31971
  },
@@ -32397,7 +32326,7 @@ class Placeholder extends React__namespace.Component {
32397
32326
  const {
32398
32327
  layout
32399
32328
  } = this.props;
32400
- const className = aphrodite.css(styles$e.card, styles$e.placeholder, layout === Layout.HORIZONTAL && styles$e.horizontalCard);
32329
+ const className = aphrodite.css(styles$f.card, styles$f.placeholder, layout === Layout.HORIZONTAL && styles$f.horizontalCard);
32401
32330
  const style = {
32402
32331
  width: this.props.width,
32403
32332
  height: this.props.height
@@ -32495,7 +32424,7 @@ class Draggable extends React__namespace.Component {
32495
32424
  // We need to keep backwards compatbility with rules specified directly
32496
32425
  // in CSS. Hence the hacky tacking on of manual classNames.
32497
32426
  // See sortable.less for details.
32498
- let className = aphrodite.css(styles$e.card, styles$e.draggable, layout === Layout.HORIZONTAL && styles$e.horizontalCard, layout === Layout.VERTICAL && styles$e.verticalCard, type === ItemState.DRAGGING && styles$e.dragging, type === ItemState.DISABLED && styles$e.disabled, !includePadding && styles$e.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
32427
+ let className = aphrodite.css(styles$f.card, styles$f.draggable, layout === Layout.HORIZONTAL && styles$f.horizontalCard, layout === Layout.VERTICAL && styles$f.verticalCard, type === ItemState.DRAGGING && styles$f.dragging, type === ItemState.DISABLED && styles$f.disabled, !includePadding && styles$f.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
32499
32428
  if (!includePadding) {
32500
32429
  className += " perseus-sortable-draggable-unpadded";
32501
32430
  }
@@ -32795,7 +32724,7 @@ class Sortable extends React__namespace.Component {
32795
32724
  } = this.props;
32796
32725
  // We need to keep backwards compatbility with rules specified directly
32797
32726
  // in CSS. See sortable.less for details.
32798
- const className = aphrodite.css(styles$e.sortable) + " perseus-sortable";
32727
+ const className = aphrodite.css(styles$f.sortable) + " perseus-sortable";
32799
32728
  const syncWidth = this.props.constraints?.width || layout === Layout.VERTICAL;
32800
32729
  const syncHeight = this.props.constraints?.height || layout === Layout.HORIZONTAL;
32801
32730
  ___default["default"].each(this.state.items, function (item, i, items) {
@@ -33026,7 +32955,7 @@ class Sortable extends React__namespace.Component {
33026
32955
  return ___default["default"].pluck(this.state.items, "option");
33027
32956
  }
33028
32957
  }
33029
- const styles$e = aphrodite.StyleSheet.create({
32958
+ const styles$f = aphrodite.StyleSheet.create({
33030
32959
  sortable: {
33031
32960
  boxSizing: "border-box",
33032
32961
  float: "left",
@@ -33154,23 +33083,23 @@ class Matcher extends React__namespace.Component {
33154
33083
  };
33155
33084
  const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
33156
33085
  return /*#__PURE__*/React__namespace.createElement("table", {
33157
- className: aphrodite.css(styles$d.widget) + " " + HACKY_CSS_CLASSNAME
33086
+ className: aphrodite.css(styles$e.widget) + " " + HACKY_CSS_CLASSNAME
33158
33087
  }, /*#__PURE__*/React__namespace.createElement("tbody", null, showLabels && /*#__PURE__*/React__namespace.createElement("tr", {
33159
- className: aphrodite.css(styles$d.row)
33088
+ className: aphrodite.css(styles$e.row)
33160
33089
  }, /*#__PURE__*/React__namespace.createElement("th", {
33161
- className: aphrodite.css(styles$d.column, styles$d.columnLabel)
33090
+ className: aphrodite.css(styles$e.column, styles$e.columnLabel)
33162
33091
  }, /*#__PURE__*/React__namespace.createElement(Renderer, {
33163
33092
  content: this.props.labels[0] || "...",
33164
33093
  linterContext: this.props.linterContext
33165
33094
  })), /*#__PURE__*/React__namespace.createElement("th", {
33166
- className: aphrodite.css(styles$d.column, styles$d.columnRight, styles$d.columnLabel)
33095
+ className: aphrodite.css(styles$e.column, styles$e.columnRight, styles$e.columnLabel)
33167
33096
  }, /*#__PURE__*/React__namespace.createElement(Renderer, {
33168
33097
  content: this.props.labels[1] || "...",
33169
33098
  linterContext: this.props.linterContext
33170
33099
  }))), /*#__PURE__*/React__namespace.createElement("tr", {
33171
- className: aphrodite.css(styles$d.row)
33100
+ className: aphrodite.css(styles$e.row)
33172
33101
  }, /*#__PURE__*/React__namespace.createElement("td", {
33173
- className: aphrodite.css(styles$d.column)
33102
+ className: aphrodite.css(styles$e.column)
33174
33103
  }, /*#__PURE__*/React__namespace.createElement(Sortable, {
33175
33104
  options: left,
33176
33105
  layout: Layout.VERTICAL,
@@ -33185,7 +33114,7 @@ class Matcher extends React__namespace.Component {
33185
33114
  ,
33186
33115
  ref: "left"
33187
33116
  })), /*#__PURE__*/React__namespace.createElement("td", {
33188
- className: aphrodite.css(styles$d.column, styles$d.columnRight)
33117
+ className: aphrodite.css(styles$e.column, styles$e.columnRight)
33189
33118
  }, /*#__PURE__*/React__namespace.createElement(Sortable
33190
33119
  // @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
33191
33120
  , {
@@ -33271,7 +33200,7 @@ ___default["default"].extend(Matcher, {
33271
33200
  });
33272
33201
  const padding = 5;
33273
33202
  const border = "1px solid #444";
33274
- const styles$d = aphrodite.StyleSheet.create({
33203
+ const styles$e = aphrodite.StyleSheet.create({
33275
33204
  widget: {
33276
33205
  paddingTop: padding,
33277
33206
  maxWidth: "100%",
@@ -34144,9 +34073,9 @@ function drawText(ctx, item) {
34144
34073
  if (item.value === null) {
34145
34074
  return;
34146
34075
  }
34147
- ctx.fillStyle = styles$c.fgColor;
34148
- ctx.font = styles$c.font;
34149
- ctx.fillText(item.value, item.pos[0] - styles$c.fontSizePx / 2 + 1, item.pos[1] + styles$c.fontSizePx / 2);
34076
+ ctx.fillStyle = styles$d.fgColor;
34077
+ ctx.font = styles$d.font;
34078
+ ctx.fillText(item.value, item.pos[0] - styles$d.fontSizePx / 2 + 1, item.pos[1] + styles$d.fontSizePx / 2);
34150
34079
  }
34151
34080
 
34152
34081
  /**
@@ -34167,16 +34096,16 @@ function drawText(ctx, item) {
34167
34096
  function drawDoubleLine(ctx, item) {
34168
34097
  // Outer line that forms both of the bond lines.
34169
34098
  let path = new Path2D();
34170
- ctx.lineWidth = 5 * styles$c.lineWidth;
34171
- ctx.strokeStyle = styles$c.fgColor;
34099
+ ctx.lineWidth = 5 * styles$d.lineWidth;
34100
+ ctx.strokeStyle = styles$d.fgColor;
34172
34101
  path.moveTo(item.startPos[0], item.startPos[1]);
34173
34102
  path.lineTo(item.endPos[0], item.endPos[1]);
34174
34103
  ctx.stroke(path);
34175
34104
 
34176
34105
  // Inner white line that separates the two bond lines.
34177
34106
  path = new Path2D();
34178
- ctx.lineWidth = 3 * styles$c.lineWidth;
34179
- ctx.strokeStyle = styles$c.bgColor;
34107
+ ctx.lineWidth = 3 * styles$d.lineWidth;
34108
+ ctx.strokeStyle = styles$d.bgColor;
34180
34109
  path.moveTo(item.startPos[0], item.startPos[1]);
34181
34110
  path.lineTo(item.endPos[0], item.endPos[1]);
34182
34111
  ctx.stroke(path);
@@ -34203,16 +34132,16 @@ function drawTripleLine(ctx, item) {
34203
34132
 
34204
34133
  // Outer line that will form the two outer bond lines.
34205
34134
  let path = new Path2D();
34206
- ctx.lineWidth = 7 * styles$c.lineWidth;
34207
- ctx.strokeStyle = styles$c.fgColor;
34135
+ ctx.lineWidth = 7 * styles$d.lineWidth;
34136
+ ctx.strokeStyle = styles$d.fgColor;
34208
34137
  path.moveTo(item.startPos[0], item.startPos[1]);
34209
34138
  path.lineTo(item.endPos[0], item.endPos[1]);
34210
34139
  ctx.stroke(path);
34211
34140
 
34212
34141
  // Middle white line that separates the bonds
34213
34142
  path = new Path2D();
34214
- ctx.lineWidth = 5 * styles$c.lineWidth;
34215
- ctx.strokeStyle = styles$c.bgColor;
34143
+ ctx.lineWidth = 5 * styles$d.lineWidth;
34144
+ ctx.strokeStyle = styles$d.bgColor;
34216
34145
  path.moveTo(item.startPos[0], item.startPos[1]);
34217
34146
  path.lineTo(item.endPos[0], item.endPos[1]);
34218
34147
  ctx.stroke(path);
@@ -34234,8 +34163,8 @@ function drawTripleLine(ctx, item) {
34234
34163
  */
34235
34164
  function drawLine(ctx, item) {
34236
34165
  const path = new Path2D();
34237
- ctx.lineWidth = styles$c.lineWidth;
34238
- ctx.strokeStyle = styles$c.fgColor;
34166
+ ctx.lineWidth = styles$d.lineWidth;
34167
+ ctx.strokeStyle = styles$d.fgColor;
34239
34168
  path.moveTo(item.startPos[0], item.startPos[1]);
34240
34169
  path.lineTo(item.endPos[0], item.endPos[1]);
34241
34170
  ctx.stroke(path);
@@ -34287,7 +34216,7 @@ function compareElements(item0, item1) {
34287
34216
  function draw(ctx, items) {
34288
34217
  items.sort(compareElements).forEach(drawItem(ctx));
34289
34218
  }
34290
- const styles$c = {
34219
+ const styles$d = {
34291
34220
  bgColor: "rgb(255, 255, 255)",
34292
34221
  fgColor: "rgb(0, 0, 0)",
34293
34222
  fontSizePx: 12,
@@ -36851,7 +36780,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
36851
36780
  const rects = this.state.cachedHighlightRects;
36852
36781
  return /*#__PURE__*/React__namespace.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React__namespace.createElement("div", {
36853
36782
  key: index,
36854
- className: aphrodite.css(styles$b.highlightRect),
36783
+ className: aphrodite.css(styles$c.highlightRect),
36855
36784
  style: {
36856
36785
  // NOTE(mdr): We apply `position: absolute` here
36857
36786
  // rather than in Aphrodite styles, because
@@ -36870,7 +36799,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
36870
36799
  })));
36871
36800
  }
36872
36801
  }
36873
- const styles$b = aphrodite.StyleSheet.create({
36802
+ const styles$c = aphrodite.StyleSheet.create({
36874
36803
  highlightRect: {
36875
36804
  background: "#fffabe" // highlighter yellow :)
36876
36805
  }
@@ -36951,7 +36880,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
36951
36880
  // TooltipContent wouldn't let me overwrite
36952
36881
  // user-select and onClick
36953
36882
  const content = /*#__PURE__*/React__namespace.createElement("div", {
36954
- className: aphrodite.css(styles$a.tooltipLabel),
36883
+ className: aphrodite.css(styles$b.tooltipLabel),
36955
36884
  onClick: this.props.onClick
36956
36885
  }, this.props.label);
36957
36886
  const style = {
@@ -36971,7 +36900,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
36971
36900
  }, /*#__PURE__*/React__namespace.createElement("div", null)));
36972
36901
  }
36973
36902
  }
36974
- const styles$a = aphrodite.StyleSheet.create({
36903
+ const styles$b = aphrodite.StyleSheet.create({
36975
36904
  tooltipLabel: {
36976
36905
  // Unlike most tooltip contents, we don't want this label to be
36977
36906
  // selectable. Selecting it is not only unhelpful, but dangerous: if
@@ -37529,7 +37458,7 @@ class HighlightableContent extends React__namespace.PureComponent {
37529
37458
  // starting point: https://phabricator.khanacademy.org/D35623?id=170698
37530
37459
  const buildHighlight = r => this._buildHighlight(r);
37531
37460
  return /*#__PURE__*/React__namespace.createElement("div", {
37532
- className: aphrodite.css(styles$9.container),
37461
+ className: aphrodite.css(styles$a.container),
37533
37462
  ref: container => this._container = container
37534
37463
  }, /*#__PURE__*/React__namespace.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React__namespace.createElement(HighlightingUI, {
37535
37464
  buildHighlight: buildHighlight,
@@ -37550,14 +37479,14 @@ class HighlightableContent extends React__namespace.PureComponent {
37550
37479
  onAddHighlight: this._handleAddHighlight,
37551
37480
  onRemoveHighlight: this._handleRemoveHighlight
37552
37481
  })), /*#__PURE__*/React__namespace.createElement("div", {
37553
- className: aphrodite.css(styles$9.content),
37482
+ className: aphrodite.css(styles$a.content),
37554
37483
  ref: content => this._content = content
37555
37484
  }, /*#__PURE__*/React__namespace.createElement(WordIndexer, {
37556
37485
  onWordsUpdate: this._handleWordsUpdate
37557
37486
  }, this.props.children)));
37558
37487
  }
37559
37488
  }
37560
- const styles$9 = aphrodite.StyleSheet.create({
37489
+ const styles$a = aphrodite.StyleSheet.create({
37561
37490
  // We render content with z-index 1, and highlights with z-index 0, so that
37562
37491
  // content will receive the browser's native pointer events. (Highlights
37563
37492
  // have their own magic code to manage hover detection, despite being
@@ -37953,7 +37882,7 @@ class LineHeightMeasurer extends React__namespace.Component {
37953
37882
  }
37954
37883
  render() {
37955
37884
  return /*#__PURE__*/React__namespace.createElement("div", {
37956
- className: aphrodite.css(styles$8.measurer),
37885
+ className: aphrodite.css(styles$9.measurer),
37957
37886
  "aria-hidden": "true"
37958
37887
  }, /*#__PURE__*/React__namespace.createElement("div", {
37959
37888
  ref: ref => this._line = ref,
@@ -37961,7 +37890,7 @@ class LineHeightMeasurer extends React__namespace.Component {
37961
37890
  }, "Line Height Measurement"));
37962
37891
  }
37963
37892
  }
37964
- const styles$8 = aphrodite.StyleSheet.create({
37893
+ const styles$9 = aphrodite.StyleSheet.create({
37965
37894
  measurer: {
37966
37895
  position: "absolute",
37967
37896
  top: 0,
@@ -39248,6 +39177,52 @@ var Plotter$1 = {
39248
39177
  staticTransform: staticTransform
39249
39178
  };
39250
39179
 
39180
+ /**
39181
+ * This widget is for embedding Khan Academy Python programs.
39182
+ */
39183
+ function getUrlFromProgramID(programID) {
39184
+ const path = `/python-program/${programID}/embedded`;
39185
+ return toAbsoluteUrl(path);
39186
+ }
39187
+ /* This renders the program in an iframe. */
39188
+ class PythonProgram extends React__namespace.Component {
39189
+ static defaultProps = {
39190
+ height: 400
39191
+ };
39192
+ render() {
39193
+ const url = getUrlFromProgramID(this.props.programID);
39194
+ const iframeStyle = {
39195
+ height: this.props.height,
39196
+ width: "100%"
39197
+ };
39198
+ const sandboxOptions = ["allow-popups", "allow-same-origin", "allow-scripts", "allow-top-navigation"].join(" ");
39199
+
39200
+ // We sandbox the iframe so that we allowlist only the functionality
39201
+ // that we need. This makes it a bit safer in case some content
39202
+ // creator "went wild".
39203
+ // http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
39204
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
39205
+ style: styles$8.container
39206
+ }, /*#__PURE__*/React__namespace.createElement("iframe", {
39207
+ sandbox: sandboxOptions,
39208
+ src: url,
39209
+ style: iframeStyle,
39210
+ allowFullScreen: true
39211
+ }));
39212
+ }
39213
+ }
39214
+ const styles$8 = aphrodite.StyleSheet.create({
39215
+ container: {
39216
+ margin: "auto",
39217
+ width: "100%"
39218
+ }
39219
+ });
39220
+ var PythonProgram$1 = {
39221
+ name: "python-program",
39222
+ displayName: "Python Program",
39223
+ widget: PythonProgram
39224
+ };
39225
+
39251
39226
  class Separator extends React__namespace.Component {
39252
39227
  arrowLength = 100;
39253
39228
  static propTypes = {
@@ -41682,7 +41657,7 @@ var Video$1 = {
41682
41657
  };
41683
41658
 
41684
41659
  /* eslint-disable import/no-named-as-default */
41685
- var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1, Unit, Video$1, DeprecatedStandin$1];
41660
+ var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, PythonProgram$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1, Unit, Video$1, DeprecatedStandin$1];
41686
41661
 
41687
41662
  /**
41688
41663
  * This should be called by all clients, specifying whether extra widgets are
@@ -41722,7 +41697,7 @@ const init = function (options) {
41722
41697
 
41723
41698
  // This file is processed by a Rollup plugin (replace) to inject the production
41724
41699
  const libName = "@khanacademy/perseus";
41725
- const libVersion = "19.1.9";
41700
+ const libVersion = "19.2.1";
41726
41701
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
41727
41702
 
41728
41703
  const apiVersion = {
@@ -43167,6 +43142,8 @@ const ItemExtras = [
43167
43142
 
43168
43143
  // prettier-ignore
43169
43144
 
43145
+ // prettier-ignore
43146
+
43170
43147
  //prettier-ignore
43171
43148
 
43172
43149
  // A background image applied to various widgets.