@khanacademy/perseus 19.1.9 → 19.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -244,7 +244,7 @@ class MathInput extends React.Component {
244
244
  className = className + " " + this.props.className;
245
245
  }
246
246
  return /*#__PURE__*/React.createElement(View, {
247
- style: [styles$B.outerWrapper, this.state.focused && styles$B.wrapperFocused, this.props.hasError && styles$B.wrapperError]
247
+ style: [styles$C.outerWrapper, this.state.focused && styles$C.wrapperFocused, this.props.hasError && styles$C.wrapperError]
248
248
  }, /*#__PURE__*/React.createElement("div", {
249
249
  style: {
250
250
  display: "flex",
@@ -277,7 +277,7 @@ class MathInput extends React.Component {
277
277
  var _this$props$keypadBut, _this$props;
278
278
  return /*#__PURE__*/React.createElement(PopoverContentCore, {
279
279
  closeButtonVisible: true,
280
- style: styles$B.popoverContent
280
+ style: styles$C.popoverContent
281
281
  }, /*#__PURE__*/React.createElement(DesktopKeypad, _extends({
282
282
  onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
283
283
  extraKeys: this.props.extraKeys,
@@ -321,9 +321,9 @@ const MathInputIcon = ({
321
321
  color = Color.offBlack;
322
322
  break;
323
323
  }
324
- const dynamicClass = active || focused ? styles$B.iconActive : styles$B.iconInactive;
324
+ const dynamicClass = active || focused ? styles$C.iconActive : styles$C.iconInactive;
325
325
  return /*#__PURE__*/React.createElement(View, {
326
- style: [styles$B.iconContainer, dynamicClass]
326
+ style: [styles$C.iconContainer, dynamicClass]
327
327
  }, /*#__PURE__*/React.createElement("svg", {
328
328
  xmlns: "http://www.w3.org/2000/svg",
329
329
  width: "16",
@@ -368,7 +368,7 @@ const inputFocused = {
368
368
  borderColor: Color.blue,
369
369
  margin: -1
370
370
  };
371
- const styles$B = StyleSheet.create({
371
+ const styles$C = StyleSheet.create({
372
372
  iconContainer: {
373
373
  display: "flex",
374
374
  justifyContent: "center",
@@ -10202,89 +10202,49 @@ const GraphUtils = {
10202
10202
  }
10203
10203
  })($, window, document);
10204
10204
 
10205
- /**
10206
- * A work-in-progress of _ methods for objects.
10207
- * That is, they take an object as a parameter,
10208
- * and return an object instead of an array.
10209
- *
10210
- * TODO(aria): Move this out of interactive2
10211
- */
10212
-
10213
- /**
10214
- * Does a pluck on keys inside objects in an object
10215
- *
10216
- * Ex:
10217
- * tools = {
10218
- * translation: {
10219
- * enabled: true
10220
- * },
10221
- * rotation: {
10222
- * enabled: false
10223
- * }
10224
- * };
10225
- * pluckObject(tools, "enabled") returns {
10226
- * translation: true
10227
- * rotation: false
10228
- * }
10229
- */
10230
- const pluck = function pluck(table, subKey) {
10231
- return _.object(_.map(table, function (value, key) {
10232
- return [key, value[subKey]];
10233
- }));
10234
- };
10235
-
10236
- /**
10237
- * Maps an object to an object
10238
- *
10239
- * > mapObject({a: '1', b: '2'}, (value, key) => {
10240
- * return value + 1;
10241
- * });
10242
- * {a: 2, b: 3}
10243
- */
10244
- const mapObject$2 = function mapObject(obj, lambda) {
10245
- const result = {};
10246
- _.each(_.keys(obj), function (key) {
10247
- // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
10248
- result[key] = lambda(obj[key], key);
10249
- });
10250
- return result;
10251
- };
10205
+ // Given `coord` and `angle`, find the point where a line extended
10206
+ // from `coord` in the direction of `angle` would be clipped by the
10207
+ // edge of the graphie canvas.
10208
+ const getClipPoint = function getClipPoint(graph, coord, angle) {
10209
+ // Actually put the arrowheads 4px from the edge so they have
10210
+ // a bit of room
10211
+ const xExtent = graph.range[0][1] - graph.range[0][0];
10212
+ const yExtent = graph.range[1][1] - graph.range[1][0];
10252
10213
 
10253
- /**
10254
- * Maps an array to an object
10255
- *
10256
- * > mapObjectFromArray(['a', 'b'], function(elem) {
10257
- * return elem + elem;
10258
- * });
10259
- * {a: 'aa', b: 'bb'}
10260
- */
10261
- const mapObjectFromArray$1 = function mapObjectFromArray(arr, lambda) {
10262
- const result = {};
10263
- _.each(arr, function (elem) {
10264
- result[elem] = lambda(elem);
10265
- });
10266
- return result;
10267
- };
10268
- var objective_ = {
10269
- pluck: pluck,
10270
- mapObject: mapObject$2,
10271
- mapObjectFromArray: mapObjectFromArray$1
10214
+ // shoot a point off into the distance ...
10215
+ const distance = xExtent + yExtent;
10216
+ // we need to scale the point according to the scale of the axes
10217
+ const angleVec = graph.unscaleVector(vector$1.cartFromPolarDeg(1, angle));
10218
+ const distVec = vector$1.scale(vector$1.normalize(angleVec), distance);
10219
+ const farCoord = vector$1.add(coord, distVec);
10220
+ const scaledAngle = vector$1.polarDegFromCart(angleVec)[1];
10221
+ // ... and then bring it back
10222
+ const clipPoint = graph.constrainToBoundsOnAngle(farCoord, 4, scaledAngle * Math.PI / 180);
10223
+ return clipPoint;
10272
10224
  };
10273
10225
 
10274
10226
  /* eslint-disable @babel/no-invalid-this */
10275
10227
 
10276
10228
  /*
10277
- * These functions, when called on the wrapped object, simply pass the
10229
+ * attr() and animate() simply pass the
10278
10230
  * arguments to the underlying Raphael object.
10279
10231
  */
10280
- const PASS_TO_RAPHAEL = ["attr", "animate"];
10281
- const WrappedDefaults = _.extend({
10282
- transform: function (transformation) {
10232
+
10233
+ class WrappedDrawing {
10234
+ constructor(graphie, initialPoint) {
10235
+ this.graphie = void 0;
10236
+ this.wrapper = void 0;
10237
+ this.visibleShape = void 0;
10238
+ this.initialPoint = void 0;
10239
+ this.graphie = graphie;
10240
+ this.initialPoint = initialPoint;
10241
+ }
10242
+ transform(transformation) {
10283
10243
  const prefixedTransform = InteractiveUtil.getPrefixedTransform();
10284
10244
  // @ts-expect-error - TS2538 - Type 'null' cannot be used as an index type. | TS2538 - Type 'undefined' cannot be used as an index type.
10285
10245
  this.wrapper.style[prefixedTransform] = transformation;
10286
- },
10287
- toFront: function () {
10246
+ }
10247
+ toFront() {
10288
10248
  const parentNode = this.wrapper.parentNode;
10289
10249
  // TODO(emily): Sometimes, we call `.remove()` but then hold a
10290
10250
  // reference to this object, and sometimes call `.toFront` on it.
@@ -10293,152 +10253,214 @@ const WrappedDefaults = _.extend({
10293
10253
  if (parentNode) {
10294
10254
  parentNode.appendChild(this.wrapper);
10295
10255
  }
10296
- },
10297
- toBack: function () {
10256
+ }
10257
+ toBack() {
10298
10258
  const parentNode = this.wrapper.parentNode;
10299
- if (parentNode.firstChild !== this.wrapper) {
10259
+ if (parentNode != null && parentNode.firstChild !== this.wrapper) {
10300
10260
  parentNode.insertBefore(this.wrapper, parentNode.firstChild);
10301
10261
  }
10302
- },
10303
- remove: function () {
10262
+ }
10263
+ remove() {
10304
10264
  this.visibleShape.remove();
10305
10265
  $(this.wrapper).remove();
10306
- },
10307
- getMouseTarget: function () {
10266
+ }
10267
+ getMouseTarget() {
10308
10268
  return this.visibleShape[0];
10309
- },
10310
- moveTo: function (point) {
10269
+ }
10270
+ moveTo(point) {
10311
10271
  const delta = vector$1.subtract(this.graphie.scalePoint(point), this.graphie.scalePoint(this.initialPoint));
10312
10272
  const do3dTransform = InteractiveUtil.getCanUse3dTransform();
10313
10273
  const transformation = "translateX(" + delta[0] + "px) " + "translateY(" + delta[1] + "px)" + (do3dTransform ? " translateZ(0)" : "");
10314
10274
  this.transform(transformation);
10315
- },
10316
- hide: function () {
10275
+ }
10276
+ hide() {
10317
10277
  this.visibleShape.hide();
10318
- },
10319
- show: function () {
10278
+ }
10279
+ show() {
10320
10280
  this.visibleShape.show();
10321
10281
  }
10322
- }, objective_.mapObjectFromArray(PASS_TO_RAPHAEL, function (attribute) {
10323
- return function (...args) {
10324
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10325
- this.visibleShape[attribute](...args);
10326
- };
10327
- }));
10282
+ attr(...args) {
10283
+ this.visibleShape.attr(...args);
10284
+ }
10285
+ animate(...args) {
10286
+ this.visibleShape.animate(...args);
10287
+ }
10288
+ }
10328
10289
 
10329
10290
  const DEFAULT_OPTIONS$2 = {
10330
- maxScale: 1,
10331
- mouselayer: false,
10332
- shadow: false,
10333
- disableMouseEventsOnWrapper: false
10291
+ center: null,
10292
+ // gets ignored in `graphie.fixedPath` if `null`
10293
+ createPath: null,
10294
+ // gets defaulted in `graphie.fixedPath` if `null`
10295
+ mouselayer: false
10334
10296
  };
10335
- const WrappedEllipse = function WrappedEllipse(graphie, center, radii, options) {
10336
- options = _.extend({}, DEFAULT_OPTIONS$2, options);
10337
-
10338
- // Add `wrapper`, `visibleShape`, and remaining properties.
10339
- const fixedEllipse = graphie.fixedEllipse(center, radii, options.maxScale, options.padding);
10340
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10341
- _.extend(this, fixedEllipse, {
10342
- graphie: graphie,
10343
- initialPoint: center
10344
- });
10345
- if (options.interactiveKindForTesting) {
10346
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10347
- this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10297
+ class WrappedPath extends WrappedDrawing {
10298
+ constructor(graphie, points, options) {
10299
+ const initialPoint = graphie.scalePoint(_.head(points));
10300
+ super(graphie, initialPoint);
10301
+ this.wrapper = void 0;
10302
+ this.visibleShape = void 0;
10303
+ options = _.extend({}, DEFAULT_OPTIONS$2, options);
10304
+ const fixedPath = graphie.fixedPath(points, options.center, options.createPath);
10305
+ this.wrapper = fixedPath.wrapper;
10306
+ this.visibleShape = fixedPath.visibleShape;
10307
+
10308
+ // Add to appropriate graphie layer
10309
+ if (options.mouselayer) {
10310
+ // Disable browser handling of all panning and zooming gestures on the
10311
+ // movable wrapper so that when moved the browser does not scroll page
10312
+ this.wrapper.style.touchAction = "none";
10313
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
10314
+ } else {
10315
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
10316
+ }
10348
10317
  }
10318
+ }
10349
10319
 
10350
- // Add to appropriate graphie layer
10351
- if (options.mouselayer) {
10352
- // Disable browser handling of all panning and zooming gestures on the
10353
- // movable wrapper so that when moved the browser does not scroll page
10354
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10355
- this.wrapper.style.touchAction = "none";
10356
-
10357
- // @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.
10358
- this.graphie.addToMouseLayerWrapper(this.wrapper);
10359
- } else {
10360
- // @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.
10361
- this.graphie.addToVisibleLayerWrapper(this.wrapper);
10320
+ class Arrowhead extends WrappedPath {
10321
+ constructor(graphie, style) {
10322
+ // Points that define the arrowhead
10323
+ const center = [0.75, 0];
10324
+ const points = [[-3, 4], [-2.75, 2.5], [0, 0.25], center, [0, -0.25], [-2.75, -2.5], [-3, -4]].map(point => {
10325
+ // Scale points by `Arrowhead.scale` around `center`
10326
+ const pv = vector$1.subtract(point, center);
10327
+ const pvScaled = vector$1.scale(pv, Arrowhead.scale);
10328
+ return vector$1.add(center, pvScaled);
10329
+ });
10330
+ const unscaledPoints = points.map(graphie.unscalePoint);
10331
+ super(graphie, unscaledPoints, {
10332
+ center: graphie.unscalePoint(center),
10333
+ createPath: createCubicPath
10334
+ });
10335
+ this.center = void 0;
10336
+ this.center = center;
10337
+ this.attr(_.extend({
10338
+ "stroke-linejoin": "round",
10339
+ "stroke-linecap": "round",
10340
+ "stroke-dasharray": ""
10341
+ }, style));
10362
10342
  }
10363
- if (options.shadow) {
10364
- const filter = "drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";
10365
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10366
- const wrapper = this.wrapper;
10367
- wrapper.style.filter = filter;
10368
-
10369
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10370
- this.moveTo = function (point) {
10371
- const delta = vector$1.subtract(this.graphie.scalePoint(point), this.graphie.scalePoint(this.initialPoint));
10372
- const do3dTransform = InteractiveUtil.getCanUse3dTransform();
10373
- const transform = "translateX(" + Math.round(delta[0]) + "px) " + "translateY(" + Math.round(delta[1]) + "px)" + (do3dTransform ? " translateZ(0)" : "");
10374
- this.transform(transform);
10375
- };
10343
+ toCoordAtAngle(coord, angle) {
10344
+ const clipPoint = this.graphie.scalePoint(getClipPoint(this.graphie, coord, angle));
10345
+ 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)");
10376
10346
  }
10377
- if (options.disableMouseEventsOnWrapper) {
10378
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10379
- this.wrapper.style.pointerEvents = "none";
10380
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10381
- this.visibleShape.node.style.pointerEvents = "auto";
10347
+ }
10348
+
10349
+ // We can't just pass in a path to `graph.fixedPath` as we need to modify
10350
+ // the points in some way, so instead we provide a function for creating
10351
+ // the path once the points have been transformed
10352
+ Arrowhead.scale = 1.4;
10353
+ const createCubicPath = function createCubicPath(points) {
10354
+ let path = "M" + points[0][0] + " " + points[0][1];
10355
+ for (let i = 1; i < points.length; i += 3) {
10356
+ path += "C" + points[i][0] + " " + points[i][1] + " " + points[i + 1][0] + " " + points[i + 1][1] + " " + points[i + 2][0] + " " + points[i + 2][1];
10382
10357
  }
10358
+ return path;
10383
10359
  };
10384
- _.extend(WrappedEllipse.prototype, WrappedDefaults);
10385
10360
 
10386
10361
  const DEFAULT_OPTIONS$1 = {
10387
- thickness: 2,
10388
- mouselayer: false
10362
+ maxScale: 1,
10363
+ mouselayer: false,
10364
+ shadow: false,
10365
+ disableMouseEventsOnWrapper: false
10389
10366
  };
10390
- const WrappedLine = function WrappedLine(graphie, start, end, options) {
10391
- options = _.extend({}, DEFAULT_OPTIONS$1, options);
10392
-
10393
- // Always make the line as large as possible and horizontal; this
10394
- // simplifies a lot of the transforms, e.g., we can rotate by exactly the
10395
- // angle of the argument points in `moveTo`.
10396
- const initialStart = [graphie.range[0][0], 0];
10397
- const initialEnd = [graphie.range[0][1], 0];
10367
+ class WrappedEllipse extends WrappedDrawing {
10368
+ constructor(graphie, center, radii, options) {
10369
+ super(graphie, center);
10370
+ this.initialPoint = void 0;
10371
+ this.wrapper = void 0;
10372
+ this.visibleShape = void 0;
10373
+ options = _.extend({}, DEFAULT_OPTIONS$1, options);
10374
+
10375
+ // Add `wrapper`, `visibleShape`, and remaining properties.
10376
+ const fixedEllipse = graphie.fixedEllipse(center, radii, options.maxScale, options.padding);
10377
+ this.visibleShape = fixedEllipse.visibleShape;
10378
+ this.wrapper = fixedEllipse.wrapper;
10379
+ this.graphie = graphie;
10380
+ this.initialPoint = center;
10381
+ if (options.interactiveKindForTesting) {
10382
+ this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10383
+ }
10398
10384
 
10399
- // Add `wrapper` and `visibleShape`
10400
- _.extend(
10401
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10402
- this, graphie.fixedLine(initialStart, initialEnd, options.thickness));
10403
- if (options.interactiveKindForTesting) {
10404
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10405
- this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10385
+ // Add to appropriate graphie layer
10386
+ if (options.mouselayer) {
10387
+ // Disable browser handling of all panning and zooming gestures on the
10388
+ // movable wrapper so that when moved the browser does not scroll page
10389
+ this.wrapper.style.touchAction = "none";
10390
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
10391
+ } else {
10392
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
10393
+ }
10394
+ if (options.shadow) {
10395
+ const filter = "drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";
10396
+ const wrapper = this.wrapper;
10397
+ wrapper.style.filter = filter;
10398
+ this.moveTo = function (point) {
10399
+ const delta = vector$1.subtract(this.graphie.scalePoint(point), this.graphie.scalePoint(this.initialPoint));
10400
+ const do3dTransform = InteractiveUtil.getCanUse3dTransform();
10401
+ const transform = "translateX(" + Math.round(delta[0]) + "px) " + "translateY(" + Math.round(delta[1]) + "px)" + (do3dTransform ? " translateZ(0)" : "");
10402
+ this.transform(transform);
10403
+ };
10404
+ }
10405
+ if (options.disableMouseEventsOnWrapper) {
10406
+ this.wrapper.style.pointerEvents = "none";
10407
+ // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10408
+ this.visibleShape.node.style.pointerEvents = "auto";
10409
+ }
10406
10410
  }
10411
+ }
10407
10412
 
10408
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10409
- this.visibleShape.attr(options.normalStyle);
10410
-
10411
- // Save properties for computing transformations
10412
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10413
- _.extend(this, {
10414
- graphie: graphie,
10415
- initialPoint: graphie.scalePoint(initialStart),
10416
- initialLength: point.distanceToPoint(graphie.scalePoint(initialStart), graphie.scalePoint(initialEnd))
10417
- });
10418
-
10419
- // Add to appropriate graphie layer
10420
- if (options.mouselayer) {
10421
- // Disable browser handling of all panning and zooming gestures on the
10422
- // movable wrapper so that when moved the browser does not scroll page
10423
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10424
- this.wrapper.style.touchAction = "none";
10413
+ const DEFAULT_OPTIONS = {
10414
+ thickness: 2,
10415
+ mouselayer: false
10416
+ };
10417
+ class WrappedLine extends WrappedDrawing {
10418
+ constructor(graphie, start, end, options) {
10419
+ // Always make the line as large as possible and horizontal; this
10420
+ // simplifies a lot of the transforms, e.g., we can rotate by exactly the
10421
+ // angle of the argument points in `moveTo`.
10422
+ const initialStart = [graphie.range[0][0], 0];
10423
+ const initialEnd = [graphie.range[0][1], 0];
10424
+ const initialPoint = graphie.scalePoint(initialStart);
10425
+ super(graphie, initialPoint);
10426
+ this.initialLength = void 0;
10427
+ this.wrapper = void 0;
10428
+ this.visibleShape = void 0;
10429
+ options = _.extend({}, DEFAULT_OPTIONS, options);
10430
+ const fixedLine = graphie.fixedLine(initialStart, initialEnd, options.thickness);
10431
+ this.wrapper = fixedLine.wrapper;
10432
+ this.visibleShape = fixedLine.visibleShape;
10433
+ if (options.interactiveKindForTesting) {
10434
+ this.wrapper.setAttribute("data-interactive-kind-for-testing", options.interactiveKindForTesting);
10435
+ }
10436
+ this.visibleShape.attr(options.normalStyle);
10437
+
10438
+ // Save properties for computing transformations
10439
+ this.initialPoint = initialPoint;
10440
+ this.initialLength = point.distanceToPoint(graphie.scalePoint(initialStart), graphie.scalePoint(initialEnd));
10441
+
10442
+ // Add to appropriate graphie layer
10443
+ if (options.mouselayer) {
10444
+ // Disable browser handling of all panning and zooming gestures on the
10445
+ // movable wrapper so that when moved the browser does not scroll page
10446
+ this.wrapper.style.touchAction = "none";
10447
+ this.graphie.addToMouseLayerWrapper(this.wrapper);
10448
+ } else {
10449
+ this.graphie.addToVisibleLayerWrapper(this.wrapper);
10450
+ }
10425
10451
 
10426
- // @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.
10427
- this.graphie.addToMouseLayerWrapper(this.wrapper);
10428
- } else {
10429
- // @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.
10430
- this.graphie.addToVisibleLayerWrapper(this.wrapper);
10452
+ // Move line to initial points
10453
+ this.moveTo(start, end);
10431
10454
  }
10432
-
10433
- // Move to argument points
10434
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10435
- this.moveTo(start, end);
10436
- };
10437
- _.extend(WrappedLine.prototype, WrappedDefaults, {
10438
- getMouseTarget: function () {
10455
+ getMouseTarget() {
10439
10456
  return this.wrapper;
10440
- },
10441
- moveTo: function (start, end) {
10457
+ }
10458
+
10459
+ // TODO(benchristel): we need to suppress a type error here because moveTo
10460
+ // takes 2 parameters here, but only 1 parameter in the superclass's
10461
+ // definition. Rename this method after confirming it's safe to do so
10462
+ // @ts-expect-error - TS2416: Property 'moveTo' in type 'WrappedLine' is not assignable to the same property in base type 'WrappedDefaults'.
10463
+ moveTo(start, end) {
10442
10464
  const scaledStart = this.graphie.scalePoint(start);
10443
10465
  const scaledEnd = this.graphie.scalePoint(end);
10444
10466
 
@@ -10454,45 +10476,7 @@ _.extend(WrappedLine.prototype, WrappedDefaults, {
10454
10476
  const transformation = "translateX(" + delta[0] + "px) " + "translateY(" + delta[1] + "px) " + (do3dTransform ? " translateZ(0)" : "") + "rotate(" + angle + "deg) " + "scaleX(" + scale + ") scaleY(1)";
10455
10477
  this.transform(transformation);
10456
10478
  }
10457
- });
10458
-
10459
- const DEFAULT_OPTIONS = {
10460
- center: null,
10461
- // gets ignored in `graphie.fixedPath` if `null`
10462
- createPath: null,
10463
- // gets defaulted in `graphie.fixedPath` if `null`
10464
- mouselayer: false
10465
- };
10466
- const WrappedPath = function WrappedPath(graphie, points, options) {
10467
- options = _.extend({}, DEFAULT_OPTIONS, options);
10468
-
10469
- // Add `wrapper` and `visibleShape`
10470
- _.extend(
10471
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10472
- this, graphie.fixedPath(points, options.center, options.createPath));
10473
-
10474
- // Add remaining properties
10475
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10476
- _.extend(this, {
10477
- graphie: graphie,
10478
- initialPoint: graphie.scalePoint(_.head(points))
10479
- });
10480
-
10481
- // Add to appropriate graphie layer
10482
- if (options.mouselayer) {
10483
- // Disable browser handling of all panning and zooming gestures on the
10484
- // movable wrapper so that when moved the browser does not scroll page
10485
- // @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
10486
- this.wrapper.style.touchAction = "none";
10487
-
10488
- // @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.
10489
- this.graphie.addToMouseLayerWrapper(this.wrapper);
10490
- } else {
10491
- // @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.
10492
- this.graphie.addToVisibleLayerWrapper(this.wrapper);
10493
- }
10494
- };
10495
- _.extend(WrappedPath.prototype, WrappedDefaults);
10479
+ }
10496
10480
 
10497
10481
  /**
10498
10482
  * A collection of geomtry-related utility functions
@@ -10717,9 +10701,6 @@ firstPoints, secondPoints) {
10717
10701
  }
10718
10702
 
10719
10703
  /* eslint-disable @babel/no-invalid-this */
10720
- const {
10721
- getCanUse3dTransform
10722
- } = InteractiveUtil;
10723
10704
  function scaledDistanceFromAngle(angle) {
10724
10705
  const a = 3.51470560176242 * 20;
10725
10706
  const b = 0.5687298702748785 * 20;
@@ -11603,52 +11584,15 @@ _.extend(GraphUtils.Graphie.prototype, {
11603
11584
  _.each(elements, function (element) {
11604
11585
  element.moveTo(start, end);
11605
11586
  });
11606
- const createArrow = function createArrow(graph, style) {
11607
- const center = [0.75, 0];
11608
- let points = [[-3, 4], [-2.75, 2.5], [0, 0.25], center, [0, -0.25], [-2.75, -2.5], [-3, -4]];
11609
- const scale = 1.4;
11610
- points = _.map(points, function (point) {
11611
- const pv = vector$1.subtract(point, center);
11612
- const pvScaled = vector$1.scale(pv, scale);
11613
- return vector$1.add(center, pvScaled);
11614
- });
11615
- const createCubicPath = function createCubicPath(points) {
11616
- let path = "M" + points[0][0] + " " + points[0][1];
11617
- for (let i = 1; i < points.length; i += 3) {
11618
- path += "C" + points[i][0] + " " + points[i][1] + " " + points[i + 1][0] + " " + points[i + 1][1] + " " + points[i + 2][0] + " " + points[i + 2][1];
11619
- }
11620
- return path;
11621
- };
11622
- const unscaledPoints = _.map(points, graph.unscalePoint);
11623
- const options = {
11624
- center: graph.unscalePoint(center),
11625
- createPath: createCubicPath
11626
- };
11627
- const arrowHead = new WrappedPath(graph, unscaledPoints, options);
11628
- arrowHead.attr(_.extend({
11629
- "stroke-linejoin": "round",
11630
- "stroke-linecap": "round",
11631
- "stroke-dasharray": ""
11632
- }, style));
11633
-
11634
- // Add custom function for transforming arrowheads that
11635
- // accounts for center, scaling, etc.
11636
- arrowHead.toCoordAtAngle = function (coord, angle) {
11637
- const clipPoint = graph.scalePoint(getClipPoint(graph, coord, angle));
11638
- const do3dTransform = getCanUse3dTransform();
11639
- 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)");
11640
- };
11641
- return arrowHead;
11642
- };
11643
11587
 
11644
11588
  // Add arrows
11645
11589
  if (this._arrows == null) {
11646
11590
  this._arrows = [];
11647
11591
  if (this.extendLine) {
11648
- this._arrows.push(createArrow(graph, this.normalStyle));
11649
- this._arrows.push(createArrow(graph, this.normalStyle));
11592
+ this._arrows.push(new Arrowhead(graph, this.normalStyle));
11593
+ this._arrows.push(new Arrowhead(graph, this.normalStyle));
11650
11594
  } else if (this.extendRay) {
11651
- this._arrows.push(createArrow(graph, this.normalStyle));
11595
+ this._arrows.push(new Arrowhead(graph, this.normalStyle));
11652
11596
  }
11653
11597
  }
11654
11598
  const coordForArrow = [this.coordA, this.coordZ];
@@ -14067,78 +14011,6 @@ const getScaledAngle = function getScaledAngle(line) {
14067
14011
  return vector$1.polarDegFromCart(vector$1.subtract(scaledZ, scaledA))[1];
14068
14012
  };
14069
14013
 
14070
- // Given `coord` and `angle`, find the point where a line extended
14071
- // from `coord` in the direction of `angle` would be clipped by the
14072
- // edge of the graphie canvas. Then draw an arrowhead at that point
14073
- // pointing in the direction of `angle`.
14074
- const getClipPoint = function getClipPoint(graph, coord, angle) {
14075
- // Actually put the arrowheads 4px from the edge so they have
14076
- // a bit of room
14077
- const xExtent = graph.range[0][1] - graph.range[0][0];
14078
- const yExtent = graph.range[1][1] - graph.range[1][0];
14079
-
14080
- // shoot a point off into the distance ...
14081
- const distance = xExtent + yExtent;
14082
- // we need to scale the point according to the scale of the axes
14083
- const angleVec = graph.unscaleVector(vector$1.cartFromPolarDeg(1, angle));
14084
- const distVec = vector$1.scale(vector$1.normalize(angleVec), distance);
14085
- const farCoord = vector$1.add(coord, distVec);
14086
- const scaledAngle = vector$1.polarDegFromCart(angleVec)[1];
14087
- // ... and then bring it back
14088
- const clipPoint = graph.constrainToBoundsOnAngle(farCoord, 4, scaledAngle * Math.PI / 180);
14089
- return clipPoint;
14090
- };
14091
-
14092
- // Given `coord` and `angle`, find the point where a line extended
14093
- // from `coord` in the direction of `angle` would be clipped by the
14094
- // edge of the graphie canvas. Then draw an arrowhead at that point
14095
- // pointing in the direction of `angle`.
14096
- const createArrow = function createArrow(graph, style) {
14097
- // Points that define the arrowhead
14098
- const center = [0.75, 0];
14099
- let points = [[-3, 4], [-2.75, 2.5], [0, 0.25], center, [0, -0.25], [-2.75, -2.5], [-3, -4]];
14100
-
14101
- // Scale points by 1.4 around (0.75, 0)
14102
- const scale = 1.4;
14103
- points = _.map(points, function (point) {
14104
- const pv = vector$1.subtract(point, center);
14105
- const pvScaled = vector$1.scale(pv, scale);
14106
- return vector$1.add(center, pvScaled);
14107
- });
14108
-
14109
- // We can't just pass in a path to `graph.fixedPath` as we need to modify
14110
- // the points in some way, so instead we provide a function for creating
14111
- // the path once the points have been transformed
14112
- const createCubicPath = function createCubicPath(points) {
14113
- let path = "M" + points[0][0] + " " + points[0][1];
14114
- for (let i = 1; i < points.length; i += 3) {
14115
- path += "C" + points[i][0] + " " + points[i][1] + " " + points[i + 1][0] + " " + points[i + 1][1] + " " + points[i + 2][0] + " " + points[i + 2][1];
14116
- }
14117
- return path;
14118
- };
14119
-
14120
- // Create arrowhead
14121
- const unscaledPoints = _.map(points, graph.unscalePoint);
14122
- const options = {
14123
- center: graph.unscalePoint(center),
14124
- createPath: createCubicPath
14125
- };
14126
- const arrowHead = new WrappedPath(graph, unscaledPoints, options);
14127
- arrowHead.attr(_.extend({
14128
- "stroke-linejoin": "round",
14129
- "stroke-linecap": "round",
14130
- "stroke-dasharray": ""
14131
- }, style));
14132
-
14133
- // Add custom function for transforming arrowheads that accounts for
14134
- // center, scaling, etc.
14135
- arrowHead.toCoordAtAngle = function (coord, angle) {
14136
- const clipPoint = graph.scalePoint(getClipPoint(graph, coord, angle));
14137
- arrowHead.transform("translateX(" + (clipPoint[0] + scale * center[0]) + "px) " + "translateY(" + (clipPoint[1] + scale * center[1]) + "px) " + "translateZ(0) " + "rotate(" + (360 - KhanMath.bound(angle)) + "deg)");
14138
- };
14139
- return arrowHead;
14140
- };
14141
-
14142
14014
  /**
14143
14015
  * MovableLine option functions
14144
14016
  */
@@ -14225,16 +14097,16 @@ const draw$3 = {
14225
14097
  // @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'?
14226
14098
  this._arrows.push(
14227
14099
  // @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; }'.
14228
- createArrow(this.graphie, this.normalStyle()));
14100
+ new Arrowhead(this.graphie, this.normalStyle()));
14229
14101
  // @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'?
14230
14102
  this._arrows.push(
14231
14103
  // @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; }'.
14232
- createArrow(this.graphie, this.normalStyle()));
14104
+ new Arrowhead(this.graphie, this.normalStyle()));
14233
14105
  } else if (state.extendRay) {
14234
14106
  // @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'?
14235
14107
  this._arrows.push(
14236
14108
  // @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; }'.
14237
- createArrow(this.graphie, this.normalStyle()));
14109
+ new Arrowhead(this.graphie, this.normalStyle()));
14238
14110
  }
14239
14111
  }
14240
14112
 
@@ -14380,6 +14252,75 @@ var MovableLineOptions = {
14380
14252
  }
14381
14253
  };
14382
14254
 
14255
+ /**
14256
+ * A work-in-progress of _ methods for objects.
14257
+ * That is, they take an object as a parameter,
14258
+ * and return an object instead of an array.
14259
+ *
14260
+ * TODO(aria): Move this out of interactive2
14261
+ */
14262
+
14263
+ /**
14264
+ * Does a pluck on keys inside objects in an object
14265
+ *
14266
+ * Ex:
14267
+ * tools = {
14268
+ * translation: {
14269
+ * enabled: true
14270
+ * },
14271
+ * rotation: {
14272
+ * enabled: false
14273
+ * }
14274
+ * };
14275
+ * pluckObject(tools, "enabled") returns {
14276
+ * translation: true
14277
+ * rotation: false
14278
+ * }
14279
+ */
14280
+ const pluck = function pluck(table, subKey) {
14281
+ return _.object(_.map(table, function (value, key) {
14282
+ return [key, value[subKey]];
14283
+ }));
14284
+ };
14285
+
14286
+ /**
14287
+ * Maps an object to an object
14288
+ *
14289
+ * > mapObject({a: '1', b: '2'}, (value, key) => {
14290
+ * return value + 1;
14291
+ * });
14292
+ * {a: 2, b: 3}
14293
+ */
14294
+ const mapObject$2 = function mapObject(obj, lambda) {
14295
+ const result = {};
14296
+ _.each(_.keys(obj), function (key) {
14297
+ // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
14298
+ result[key] = lambda(obj[key], key);
14299
+ });
14300
+ return result;
14301
+ };
14302
+
14303
+ /**
14304
+ * Maps an array to an object
14305
+ *
14306
+ * > mapObjectFromArray(['a', 'b'], function(elem) {
14307
+ * return elem + elem;
14308
+ * });
14309
+ * {a: 'aa', b: 'bb'}
14310
+ */
14311
+ const mapObjectFromArray$1 = function mapObjectFromArray(arr, lambda) {
14312
+ const result = {};
14313
+ _.each(arr, function (elem) {
14314
+ result[elem] = lambda(elem);
14315
+ });
14316
+ return result;
14317
+ };
14318
+ var objective_ = {
14319
+ pluck: pluck,
14320
+ mapObject: mapObject$2,
14321
+ mapObjectFromArray: mapObjectFromArray$1
14322
+ };
14323
+
14383
14324
  /**
14384
14325
  * MovableLine
14385
14326
  */
@@ -17907,33 +17848,33 @@ class Lint extends React.Component {
17907
17848
  let warningText;
17908
17849
  let warningTextStyle;
17909
17850
  if (this.props.severity === Severity.Error) {
17910
- severityStyle = styles$A.indicatorError;
17851
+ severityStyle = styles$B.indicatorError;
17911
17852
  warningText = "Error";
17912
- warningTextStyle = styles$A.publishBlockingError;
17853
+ warningTextStyle = styles$B.publishBlockingError;
17913
17854
  } else if (this.props.severity === Severity.Warning) {
17914
- severityStyle = styles$A.indicatorWarning;
17855
+ severityStyle = styles$B.indicatorWarning;
17915
17856
  warningText = "Warning";
17916
- warningTextStyle = styles$A.warning;
17857
+ warningTextStyle = styles$B.warning;
17917
17858
  } else {
17918
- severityStyle = styles$A.indicatorGuideline;
17859
+ severityStyle = styles$B.indicatorGuideline;
17919
17860
  warningText = "Recommendation";
17920
- warningTextStyle = styles$A.warning;
17861
+ warningTextStyle = styles$B.warning;
17921
17862
  }
17922
17863
  return /*#__PURE__*/React.createElement("a", {
17923
17864
  href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
17924
17865
  target: "lint-help-window",
17925
17866
  className: css(style)
17926
17867
  }, /*#__PURE__*/React.createElement("span", {
17927
- className: css(styles$A.indicator, severityStyle)
17868
+ className: css(styles$B.indicator, severityStyle)
17928
17869
  }, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
17929
- className: css(styles$A.tooltip, tooltipAbove && styles$A.tooltipAbove)
17870
+ className: css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
17930
17871
  }, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
17931
17872
  key: i,
17932
- className: css(styles$A.tooltipParagraph)
17873
+ className: css(styles$B.tooltipParagraph)
17933
17874
  }, /*#__PURE__*/React.createElement("span", {
17934
17875
  className: css(warningTextStyle)
17935
17876
  }, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
17936
- className: css(styles$A.tail, tooltipAbove && styles$A.tailAbove)
17877
+ className: css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
17937
17878
  })));
17938
17879
  };
17939
17880
  }
@@ -17971,20 +17912,20 @@ class Lint extends React.Component {
17971
17912
  }
17972
17913
  if (blockHighlight) {
17973
17914
  return /*#__PURE__*/React.createElement("span", {
17974
- className: css(styles$A.lintContainer, styles$A.lintContainerBlock)
17975
- }, this.renderLink(styles$A.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17915
+ className: css(styles$B.lintContainer, styles$B.lintContainerBlock)
17916
+ }, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17976
17917
  }
17977
17918
  if (inline) {
17978
17919
  return /*#__PURE__*/React.createElement("span", {
17979
- className: css(styles$A.lintContainer)
17980
- }, this.renderLink(styles$A.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17920
+ className: css(styles$B.lintContainer)
17921
+ }, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17981
17922
  }
17982
17923
  return /*#__PURE__*/React.createElement("div", {
17983
- className: css(styles$A.lintContainer)
17984
- }, this.renderLink(styles$A.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
17924
+ className: css(styles$B.lintContainer)
17925
+ }, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
17985
17926
  }
17986
17927
  }
17987
- const styles$A = StyleSheet.create({
17928
+ const styles$B = StyleSheet.create({
17988
17929
  // This is the class of the outermost element.
17989
17930
  // We use relative positioning so that the lint indicator can be
17990
17931
  // positioned absolutely relative to the position of the linty container.
@@ -19887,7 +19828,7 @@ class Renderer extends React.Component {
19887
19828
  paddingLeft: margin,
19888
19829
  paddingRight: margin
19889
19830
  };
19890
- const mobileInnerStyle = _extends({}, innerStyle, styles$z.mobileZoomableParentFix);
19831
+ const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
19891
19832
  return /*#__PURE__*/React.createElement("div", {
19892
19833
  key: state.key,
19893
19834
  className: "perseus-block-math",
@@ -20008,7 +19949,7 @@ class Renderer extends React.Component {
20008
19949
  paddingLeft: 0,
20009
19950
  paddingRight: 0
20010
19951
  };
20011
- const mobileInnerStyle = _extends({}, innerStyle, styles$z.mobileZoomableParentFix);
19952
+ const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
20012
19953
  const wrappedOutput = /*#__PURE__*/React.createElement("div", {
20013
19954
  style: _extends({}, mobileInnerStyle, {
20014
19955
  overflowX: "auto"
@@ -20655,7 +20596,7 @@ Renderer.defaultProps = {
20655
20596
  onSerializedStateUpdated: () => {},
20656
20597
  linterContext: PerseusLinter.linterContextDefault
20657
20598
  };
20658
- const styles$z = {
20599
+ const styles$A = {
20659
20600
  mobileZoomableParentFix: {
20660
20601
  // NOTE(abdul): There is an issue where transform animations will
20661
20602
  // cause the Zoomable component to disappear when running on the
@@ -21672,10 +21613,10 @@ class InputNumber extends React.Component {
21672
21613
  // Note: This is _very_ similar to what `numeric-input.jsx` does. If
21673
21614
  // you modify this, double-check if you also need to modify that
21674
21615
  // component.
21675
- const inputStyles = [styles$y.default, this.props.size === "small" ? styles$y.small : null, this.props.rightAlign ? styles$y.rightAlign : styles$y.leftAlign];
21616
+ const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
21676
21617
  // Unanswered
21677
21618
  if (rubric && !this.props.currentValue) {
21678
- inputStyles.push(styles$y.answerStateUnanswered);
21619
+ inputStyles.push(styles$z.answerStateUnanswered);
21679
21620
  }
21680
21621
  return /*#__PURE__*/React.createElement(InputWithExamples
21681
21622
  // eslint-disable-next-line react/no-string-refs
@@ -21760,7 +21701,7 @@ InputNumber.defaultProps = {
21760
21701
  apiOptions: ApiOptions.defaults,
21761
21702
  linterContext: linterContextDefault
21762
21703
  };
21763
- const styles$y = StyleSheet.create({
21704
+ const styles$z = StyleSheet.create({
21764
21705
  default: {
21765
21706
  width: 80,
21766
21707
  height: "auto"
@@ -22761,7 +22702,7 @@ const FocusRing = function FocusRing(props) {
22761
22702
  };
22762
22703
  return /*#__PURE__*/React.createElement("span", {
22763
22704
  "data-test-id": "focus-ring",
22764
- className: css(styles$x.ring),
22705
+ className: css(styles$y.ring),
22765
22706
  style: style
22766
22707
  }, children);
22767
22708
  };
@@ -22770,7 +22711,7 @@ FocusRing.defaultProps = {
22770
22711
  color: kaGreen$1,
22771
22712
  multipleSelect: false
22772
22713
  };
22773
- const styles$x = StyleSheet.create({
22714
+ const styles$y = StyleSheet.create({
22774
22715
  ring: {
22775
22716
  margin: "auto",
22776
22717
  display: "inline-block",
@@ -22807,7 +22748,7 @@ function getChoiceLetter(pos) {
22807
22748
  }
22808
22749
 
22809
22750
  const CHOICE_ICON_SIZE = 24;
22810
- const styles$w = StyleSheet.create({
22751
+ const styles$x = StyleSheet.create({
22811
22752
  iconWrapper: {
22812
22753
  display: "inline-block",
22813
22754
  position: "relative"
@@ -22830,7 +22771,7 @@ const CrossOutLine = function CrossOutLine(props) {
22830
22771
  width: CROSS_OUT_LINE_SIZE,
22831
22772
  height: CROSS_OUT_LINE_SIZE,
22832
22773
  viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
22833
- className: css(styles$v.crossOutLine),
22774
+ className: css(styles$w.crossOutLine),
22834
22775
  "data-test-id": "choice-icon__cross-out-line"
22835
22776
  }, /*#__PURE__*/React.createElement("line", {
22836
22777
  // The line stretches from the bottom-left to top-right.
@@ -22845,7 +22786,7 @@ const CrossOutLine = function CrossOutLine(props) {
22845
22786
  strokeLinecap: "round"
22846
22787
  }));
22847
22788
  };
22848
- const styles$v = StyleSheet.create({
22789
+ const styles$w = StyleSheet.create({
22849
22790
  crossOutLine: {
22850
22791
  // Center the icon within the container.
22851
22792
  position: "absolute",
@@ -22926,7 +22867,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
22926
22867
  } = props;
22927
22868
  const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
22928
22869
  return /*#__PURE__*/React.createElement("div", {
22929
- className: css(styles$w.iconWrapper)
22870
+ className: css(styles$x.iconWrapper)
22930
22871
  }, /*#__PURE__*/React.createElement(FocusRing, {
22931
22872
  color: Color.blue,
22932
22873
  visible: focused || hovered,
@@ -22935,13 +22876,13 @@ const ChoiceIcon = function ChoiceIcon(props) {
22935
22876
  // @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
22936
22877
  style: dynamicStyles,
22937
22878
  "data-test-id": "choice-icon__library-choice-icon",
22938
- className: css(styles$u.circle, showCorrectness && correct && styles$u.circleCorrect, showCorrectness && !correct && styles$u.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$u.circleIncorrectAnswered)
22879
+ className: css(styles$v.circle, showCorrectness && correct && styles$v.circleCorrect, showCorrectness && !correct && styles$v.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$v.circleIncorrectAnswered)
22939
22880
  // used in BaseRadio editMode to check
22940
22881
  // if we actually clicked on the radio icon
22941
22882
  ,
22942
22883
  "data-is-radio-icon": true
22943
22884
  }, /*#__PURE__*/React.createElement("div", {
22944
- className: css(styles$u.innerWrapper)
22885
+ className: css(styles$v.innerWrapper)
22945
22886
  }, /*#__PURE__*/React.createElement(ChoiceInner, {
22946
22887
  pos: pos,
22947
22888
  showCorrectness: showCorrectness,
@@ -22950,7 +22891,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
22950
22891
  color: dynamicStyles.borderColor
22951
22892
  }));
22952
22893
  };
22953
- const styles$u = StyleSheet.create({
22894
+ const styles$v = StyleSheet.create({
22954
22895
  innerWrapper: {
22955
22896
  width: CHOICE_ICON_SIZE,
22956
22897
  height: CHOICE_ICON_SIZE,
@@ -23042,19 +22983,19 @@ const OptionStatus = function OptionStatus(props) {
23042
22983
  }
23043
22984
  let textStyle;
23044
22985
  if (correct) {
23045
- textStyle = styles$t.correct;
22986
+ textStyle = styles$u.correct;
23046
22987
  } else {
23047
22988
  if (checked || previouslyAnswered) {
23048
- textStyle = styles$t.incorrectAnswered;
22989
+ textStyle = styles$u.incorrectAnswered;
23049
22990
  } else {
23050
- textStyle = styles$t.incorrect;
22991
+ textStyle = styles$u.incorrect;
23051
22992
  }
23052
22993
  }
23053
22994
  return /*#__PURE__*/React.createElement("div", {
23054
- className: css(styles$t.text, textStyle)
22995
+ className: css(styles$u.text, textStyle)
23055
22996
  }, renderText(checked, correct, crossedOut));
23056
22997
  };
23057
- const styles$t = StyleSheet.create({
22998
+ const styles$u = StyleSheet.create({
23058
22999
  text: {
23059
23000
  alignItems: "center",
23060
23001
  display: "flex",
@@ -23129,8 +23070,8 @@ const Choice = function Choice(props) {
23129
23070
  crossedOut: updatedCrossedOut
23130
23071
  });
23131
23072
  }
23132
- const descriptionClassName = classNames("description", css(styles$s.description));
23133
- const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$s.rationale));
23073
+ const descriptionClassName = classNames("description", css(styles$t.description));
23074
+ const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$t.rationale));
23134
23075
 
23135
23076
  // We want to show the choices as dimmed out when the choices are disabled.
23136
23077
  // However, we don't want to do this when we're in review mode in the
@@ -23294,7 +23235,7 @@ const Choice = function Choice(props) {
23294
23235
  "data-test-id": `perseus-radio-rationale-content-${pos}`
23295
23236
  }, rationale));
23296
23237
  };
23297
- const styles$s = StyleSheet.create({
23238
+ const styles$t = StyleSheet.create({
23298
23239
  description: {
23299
23240
  display: "inline-block",
23300
23241
  width: "100%"
@@ -23486,10 +23427,10 @@ const BaseRadio = function BaseRadio(props) {
23486
23427
  const isMobile = apiOptions.isMobile;
23487
23428
  const firstChoiceHighlighted = choices[0].highlighted;
23488
23429
  const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
23489
- const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$r.radio, styles$r.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$r.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$r.radioContainerLastHighlighted));
23490
- const instructionsClassName = classNames("instructions", css(styles$r.instructions, isMobile && styles$r.instructionsMobile));
23430
+ const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$s.radio, styles$s.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$s.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$s.radioContainerLastHighlighted));
23431
+ const instructionsClassName = classNames("instructions", css(styles$s.instructions, isMobile && styles$s.instructionsMobile));
23491
23432
  const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect);
23492
- const responsiveClassName = css(styles$r.responsiveFieldset);
23433
+ const responsiveClassName = css(styles$s.responsiveFieldset);
23493
23434
  const fieldset = /*#__PURE__*/React.createElement("fieldset", {
23494
23435
  className: `perseus-widget-radio-fieldset ${responsiveClassName}`
23495
23436
  }, /*#__PURE__*/React.createElement("legend", {
@@ -23540,7 +23481,7 @@ const BaseRadio = function BaseRadio(props) {
23540
23481
  const aphroditeClassName = checked => {
23541
23482
  // Whether or not to show correctness borders
23542
23483
  // for this choice and the next choice.
23543
- return 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);
23484
+ return 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);
23544
23485
  };
23545
23486
 
23546
23487
  // HACK(abdulrahman): Preloads the selection-state
@@ -23614,14 +23555,14 @@ const BaseRadio = function BaseRadio(props) {
23614
23555
  // Allow for horizontal scrolling if content is too wide, which may be
23615
23556
  // an issue especially on phones.
23616
23557
  return /*#__PURE__*/React.createElement("div", {
23617
- className: css(styles$r.responsiveContainer)
23558
+ className: css(styles$s.responsiveContainer)
23618
23559
  }, fieldset);
23619
23560
  };
23620
23561
  BaseRadio.defaultProps = {
23621
23562
  editMode: false,
23622
23563
  multipleSelect: false
23623
23564
  };
23624
- const styles$r = StyleSheet.create({
23565
+ const styles$s = StyleSheet.create({
23625
23566
  instructions: {
23626
23567
  display: "block",
23627
23568
  color: gray17,
@@ -24269,9 +24210,9 @@ class Categorizer extends React.Component {
24269
24210
  indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
24270
24211
  }
24271
24212
  const table = /*#__PURE__*/React.createElement("table", {
24272
- className: "categorizer-table " + css(styles$q.mobileTable)
24213
+ className: "categorizer-table " + css(styles$r.mobileTable)
24273
24214
  }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
24274
- className: css(styles$q.emptyHeaderCell)
24215
+ className: css(styles$r.emptyHeaderCell)
24275
24216
  }), this.props.categories.map((category, i) => {
24276
24217
  // Array index is the correct key here, as that's
24277
24218
  // how category grading actually works -- no way
@@ -24279,7 +24220,7 @@ class Categorizer extends React.Component {
24279
24220
  // middle. (If we later add that, this should be
24280
24221
  // fixed.)
24281
24222
  return /*#__PURE__*/React.createElement("th", {
24282
- className: css(styles$q.header),
24223
+ className: css(styles$r.header),
24283
24224
  key: i
24284
24225
  }, /*#__PURE__*/React.createElement(Renderer, {
24285
24226
  content: category,
@@ -24299,7 +24240,7 @@ class Categorizer extends React.Component {
24299
24240
  })), self.props.categories.map((catName, catNum) => {
24300
24241
  const selected = self.props.values[itemNum] === catNum;
24301
24242
  return /*#__PURE__*/React.createElement("td", {
24302
- className: "category " + css(styles$q.cell),
24243
+ className: "category " + css(styles$r.cell),
24303
24244
  key: catNum
24304
24245
  }, /*#__PURE__*/React.createElement("div", {
24305
24246
  className: ClassNames.INTERACTIVE,
@@ -24318,7 +24259,7 @@ class Categorizer extends React.Component {
24318
24259
  onChange: this.onChange.bind(this, itemNum, catNum),
24319
24260
  onClick: e => e.stopPropagation()
24320
24261
  }), !isMobile && /*#__PURE__*/React.createElement("span", {
24321
- className: css(styles$q.radioSpan, selected && styles$q.checkedRadioSpan, this.props.static && selected && styles$q.staticCheckedRadioSpan)
24262
+ className: css(styles$r.radioSpan, selected && styles$r.checkedRadioSpan, this.props.static && selected && styles$r.staticCheckedRadioSpan)
24322
24263
  }, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
24323
24264
  }));
24324
24265
  /* eslint-enable max-len */
@@ -24330,7 +24271,7 @@ class Categorizer extends React.Component {
24330
24271
  "categorizer-container": true,
24331
24272
  "static-mode": this.props.static
24332
24273
  });
24333
- const inlineStyles = this.props.apiOptions.isMobile ? [styles$q.fullBleedContainer] : [];
24274
+ const inlineStyles = this.props.apiOptions.isMobile ? [styles$r.fullBleedContainer] : [];
24334
24275
  return /*#__PURE__*/React.createElement("div", {
24335
24276
  className: extraClassNames + " " + css(...inlineStyles)
24336
24277
  }, table);
@@ -24375,7 +24316,7 @@ const pageMargin = 16;
24375
24316
 
24376
24317
  // Stylesheets aren't directly testable
24377
24318
  /* c8 ignore next */
24378
- const styles$q = StyleSheet.create({
24319
+ const styles$r = StyleSheet.create({
24379
24320
  mobileTable: {
24380
24321
  [mediaQueries.smOrSmaller]: {
24381
24322
  minWidth: "auto"
@@ -24482,7 +24423,7 @@ const toAbsoluteUrl = url => parseUrl(url).href;
24482
24423
  const {
24483
24424
  updateQueryString: updateQueryString$1
24484
24425
  } = Util;
24485
- function getUrlFromProgramID(programID) {
24426
+ function getUrlFromProgramID$1(programID) {
24486
24427
  const {
24487
24428
  InitialRequestUrl
24488
24429
  } = getDependencies();
@@ -24567,7 +24508,7 @@ class CSProgram extends React.Component {
24567
24508
  return /*#__PURE__*/React.createElement("div", null);
24568
24509
  }
24569
24510
  let styleContainer = false;
24570
- let url = getUrlFromProgramID(this.props.programID);
24511
+ let url = getUrlFromProgramID$1(this.props.programID);
24571
24512
  let className;
24572
24513
  const style = {
24573
24514
  height: this.props.height,
@@ -24611,7 +24552,7 @@ class CSProgram extends React.Component {
24611
24552
  // creator "went wild".
24612
24553
  // http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
24613
24554
  return /*#__PURE__*/React.createElement("div", {
24614
- className: css(styles$p.widthOverride, styleContainer && styles$p.container)
24555
+ className: css(styles$q.widthOverride, styleContainer && styles$q.container)
24615
24556
  }, /*#__PURE__*/React.createElement("iframe", {
24616
24557
  sandbox: sandboxOptions,
24617
24558
  src: url,
@@ -24640,7 +24581,7 @@ CSProgram.defaultProps = {
24640
24581
  // optional message
24641
24582
  message: null
24642
24583
  };
24643
- const styles$p = StyleSheet.create({
24584
+ const styles$q = StyleSheet.create({
24644
24585
  // Override the inherited width from the perseus paragraph class
24645
24586
  // 820 is minimum width for 420px editor and 400px canvas
24646
24587
  widthOverride: {
@@ -24685,7 +24626,7 @@ class Definition extends React.Component {
24685
24626
  }) => /*#__PURE__*/React.createElement(Popover, {
24686
24627
  content: /*#__PURE__*/React.createElement(PopoverContentCore, {
24687
24628
  color: "white",
24688
- style: styles$o.tooltipBody,
24629
+ style: styles$p.tooltipBody,
24689
24630
  closeButtonVisible: true
24690
24631
  }, /*#__PURE__*/React.createElement(Renderer, {
24691
24632
  apiOptions: this.props.apiOptions,
@@ -24716,7 +24657,7 @@ Definition.defaultProps = {
24716
24657
  togglePrompt: "define me",
24717
24658
  definition: "definition goes here"
24718
24659
  };
24719
- const styles$o = {
24660
+ const styles$p = {
24720
24661
  tooltipBody: {
24721
24662
  color: Color.offBlack,
24722
24663
  fontSize: 20,
@@ -24922,15 +24863,15 @@ class Explanation extends React.Component {
24922
24863
  const onClick = this._onClick;
24923
24864
  if (isMobile) {
24924
24865
  linkContainer = /*#__PURE__*/React.createElement("div", {
24925
- className: css(styles$n.linkContainer)
24866
+ className: css(styles$o.linkContainer)
24926
24867
  }, /*#__PURE__*/React.createElement("a", {
24927
- className: css(styles$n.mobileExplanationLink),
24868
+ className: css(styles$o.mobileExplanationLink),
24928
24869
  href: href,
24929
24870
  onClick: onClick,
24930
24871
  role: "button",
24931
24872
  "aria-expanded": this.state.expanded
24932
24873
  }, linkAnchor), this.state.expanded && /*#__PURE__*/React.createElement("svg", {
24933
- className: css(styles$n.disclosureArrow)
24874
+ className: css(styles$o.disclosureArrow)
24934
24875
  }, /*#__PURE__*/React.createElement("polygon", {
24935
24876
  style: {
24936
24877
  fill: backgroundColor
@@ -24943,13 +24884,13 @@ class Explanation extends React.Component {
24943
24884
  // an anchor tag (if rendered in a modal) or a Wonder Blocks
24944
24885
  // link component in lesson page, see: `article-page.jsx`.
24945
24886
  linkContainer = /*#__PURE__*/React.createElement("div", {
24946
- className: css(styles$n.linkContainer, styles$n.articleLink)
24887
+ className: css(styles$o.linkContainer, styles$o.articleLink)
24947
24888
  }, /*#__PURE__*/React.createElement(Link, {
24948
- className: css(styles$n.explanationLink)
24889
+ className: css(styles$o.explanationLink)
24949
24890
  // HACK(michaelpolyak): WB Link doesn't passthrough
24950
24891
  // class name.
24951
24892
  ,
24952
- style: styles$n.explanationLink,
24893
+ style: styles$o.explanationLink,
24953
24894
  href: href,
24954
24895
  onClick: onClick,
24955
24896
  role: "button",
@@ -24959,9 +24900,9 @@ class Explanation extends React.Component {
24959
24900
  // NOTE: For exercises, the baseElements `Link` is an
24960
24901
  // anchor tag, see: `perseus-api.jsx`.
24961
24902
  linkContainer = /*#__PURE__*/React.createElement("div", {
24962
- className: css(styles$n.linkContainer, styles$n.exerciseLink)
24903
+ className: css(styles$o.linkContainer, styles$o.exerciseLink)
24963
24904
  }, /*#__PURE__*/React.createElement(Link, {
24964
- className: css(styles$n.explanationLink),
24905
+ className: css(styles$o.explanationLink),
24965
24906
  href: href,
24966
24907
  onClick: onClick,
24967
24908
  role: "button",
@@ -24969,11 +24910,11 @@ class Explanation extends React.Component {
24969
24910
  }, `[${linkAnchor}]`));
24970
24911
  }
24971
24912
  }
24972
- const expandedStyle = isMobile ? styles$n.contentExpandedMobile : styles$n.contentExpanded;
24913
+ const expandedStyle = isMobile ? styles$o.contentExpandedMobile : styles$o.contentExpanded;
24973
24914
  return /*#__PURE__*/React.createElement("div", {
24974
- className: css(styles$n.container)
24915
+ className: css(styles$o.container)
24975
24916
  }, linkContainer, this.state.expanded && /*#__PURE__*/React.createElement("div", {
24976
- className: css(styles$n.content, isMobile && styles$n.contentMobile, this.state.expanded && expandedStyle)
24917
+ className: css(styles$o.content, isMobile && styles$o.contentMobile, this.state.expanded && expandedStyle)
24977
24918
  // eslint-disable-next-line react/no-string-refs
24978
24919
  ,
24979
24920
  ref: "content"
@@ -24997,7 +24938,7 @@ const verticalContentPadding = 10;
24997
24938
  const arrowWidth = 30;
24998
24939
  const arrowHeight = 14;
24999
24940
  const backgroundColor = gray95;
25000
- const styles$n = StyleSheet.create({
24941
+ const styles$o = StyleSheet.create({
25001
24942
  container: {
25002
24943
  display: "inline",
25003
24944
  position: "relative"
@@ -25102,15 +25043,15 @@ class GradedGroupAnswerBar extends React.Component {
25102
25043
  onCheckAnswer,
25103
25044
  onNextQuestion
25104
25045
  } = this.props;
25105
- const answerBarStyle = _extends({}, styles$m.answerBar, {
25046
+ const answerBarStyle = _extends({}, styles$n.answerBar, {
25106
25047
  backgroundColor: answerBarState === "CORRECT" ? Color.offWhite : "white",
25107
25048
  // Center the "Correct!" message only when there's no next question
25108
25049
  justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
25109
25050
  });
25110
25051
  const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
25111
- style: styles$m.text
25052
+ style: styles$n.text
25112
25053
  }, /*#__PURE__*/React.createElement("span", {
25113
- style: styles$m.tryAgainIcon
25054
+ style: styles$n.tryAgainIcon
25114
25055
  }, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
25115
25056
  style: {
25116
25057
  marginLeft: 8
@@ -25129,7 +25070,7 @@ class GradedGroupAnswerBar extends React.Component {
25129
25070
  return /*#__PURE__*/React.createElement("div", {
25130
25071
  style: answerBarStyle
25131
25072
  }, /*#__PURE__*/React.createElement("span", {
25132
- style: styles$m.text
25073
+ style: styles$n.text
25133
25074
  }, /*#__PURE__*/React.createElement("span", {
25134
25075
  style: {
25135
25076
  fontSize: 28,
@@ -25151,7 +25092,7 @@ class GradedGroupAnswerBar extends React.Component {
25151
25092
  }
25152
25093
  }
25153
25094
  const fontSize = 17;
25154
- const styles$m = {
25095
+ const styles$n = {
25155
25096
  answerBar: {
25156
25097
  display: "flex",
25157
25098
  alignItems: "center",
@@ -25337,7 +25278,7 @@ class GradedGroup extends React.Component {
25337
25278
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
25338
25279
  gradeStatus = i18n._("Incorrect");
25339
25280
  }
25340
- const mobileClass = this.props.inGradedGroupSet ? css(styles$l.gradedGroupInSet) : css(styles$l.gradedGroup);
25281
+ const mobileClass = this.props.inGradedGroupSet ? css(styles$m.gradedGroupInSet) : css(styles$m.gradedGroup);
25341
25282
  const classes = classNames({
25342
25283
  [mobileClass]: apiOptions.isMobile,
25343
25284
  "perseus-graded-group": true,
@@ -25356,7 +25297,7 @@ class GradedGroup extends React.Component {
25356
25297
  return /*#__PURE__*/React.createElement("div", {
25357
25298
  className: classes
25358
25299
  }, !!this.props.title && /*#__PURE__*/React.createElement("div", {
25359
- className: css(styles$l.title)
25300
+ className: css(styles$m.title)
25360
25301
  }, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
25361
25302
  // eslint-disable-next-line react/no-string-refs
25362
25303
  ref: "renderer",
@@ -25388,7 +25329,7 @@ class GradedGroup extends React.Component {
25388
25329
  }, i18n._("Next question")), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
25389
25330
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
25390
25331
  tabIndex: "0",
25391
- className: css(styles$l.explanationTitle),
25332
+ className: css(styles$m.explanationTitle),
25392
25333
  onClick: () => this.setState({
25393
25334
  showHint: false
25394
25335
  }),
@@ -25420,7 +25361,7 @@ class GradedGroup extends React.Component {
25420
25361
  showHint: true
25421
25362
  });
25422
25363
  },
25423
- className: css(styles$l.showHintLink)
25364
+ className: css(styles$m.showHintLink)
25424
25365
  }, i18n._("Explain"))), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
25425
25366
  apiOptions: apiOptions,
25426
25367
  answerBarState: answerBarState,
@@ -25441,7 +25382,7 @@ GradedGroup.defaultProps = {
25441
25382
  const traverseChildWidgets$3 = function traverseChildWidgets(props, traverseRenderer) {
25442
25383
  return _.extend({}, props, traverseRenderer(props));
25443
25384
  };
25444
- const styles$l = StyleSheet.create({
25385
+ const styles$m = StyleSheet.create({
25445
25386
  gradedGroupInSet: {
25446
25387
  // Reset a few desktop-only styles that come from graded-group.less
25447
25388
  marginLeft: 0,
@@ -25514,18 +25455,18 @@ class Indicators extends React.Component {
25514
25455
  return /*#__PURE__*/React.createElement("ul", {
25515
25456
  // reduntantly add class name for use in .less files--
25516
25457
  // the styles object key gets hashed
25517
- className: classNames(css(styles$k.indicatorContainer), "indicatorContainer")
25458
+ className: classNames(css(styles$l.indicatorContainer), "indicatorContainer")
25518
25459
  }, this.props.gradedGroups.map(({
25519
25460
  title
25520
25461
  }, i) => /*#__PURE__*/React.createElement("li", {
25521
- className: css(styles$k.indicator),
25462
+ className: css(styles$l.indicator),
25522
25463
  key: title
25523
25464
  }, /*#__PURE__*/React.createElement(Clickable, {
25524
25465
  role: "button",
25525
25466
  "aria-label": i18n._("Skip to %(title)s", {
25526
25467
  title
25527
25468
  }),
25528
- style: styles$k.indicatorButton,
25469
+ style: styles$l.indicatorButton,
25529
25470
  onClick: () => this.props.onChangeCurrentGroup(i),
25530
25471
  onKeyDown: e => this.handleKeyDown(e, i)
25531
25472
  }, ({
@@ -25533,9 +25474,9 @@ class Indicators extends React.Component {
25533
25474
  focused,
25534
25475
  pressed
25535
25476
  }) => /*#__PURE__*/React.createElement(View, {
25536
- style: [styles$k.indicatorDot, (hovered || focused || pressed) && styles$k.indicatorDotFocused]
25477
+ style: [styles$l.indicatorDot, (hovered || focused || pressed) && styles$l.indicatorDotFocused]
25537
25478
  }, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
25538
- style: styles$k.indicatorDotActive
25479
+ style: styles$l.indicatorDotActive
25539
25480
  }, /*#__PURE__*/React.createElement("span", {
25540
25481
  className: css(a11y.srOnly)
25541
25482
  }, i18n._("Current"))))))));
@@ -25601,7 +25542,7 @@ class GradedGroupSet extends React.Component {
25601
25542
  } = getDependencies();
25602
25543
  if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
25603
25544
  return /*#__PURE__*/React.createElement("div", {
25604
- className: css(styles$k.container)
25545
+ className: css(styles$l.container)
25605
25546
  }, this.props.gradedGroups.map((gradedGroup, i) => {
25606
25547
  return (
25607
25548
  /*#__PURE__*/
@@ -25624,13 +25565,13 @@ class GradedGroupSet extends React.Component {
25624
25565
  const numGroups = this.props.gradedGroups.length;
25625
25566
  const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
25626
25567
  return /*#__PURE__*/React.createElement("div", {
25627
- className: css(styles$k.container)
25568
+ className: css(styles$l.container)
25628
25569
  }, /*#__PURE__*/React.createElement("div", {
25629
- className: css(styles$k.top)
25570
+ className: css(styles$l.top)
25630
25571
  }, /*#__PURE__*/React.createElement("div", {
25631
- className: css(styles$k.title)
25572
+ className: css(styles$l.title)
25632
25573
  }, currentGroup.title), /*#__PURE__*/React.createElement("div", {
25633
- className: css(styles$k.spacer)
25574
+ className: css(styles$l.spacer)
25634
25575
  }), /*#__PURE__*/React.createElement(Indicators, {
25635
25576
  currentGroup: this.state.currentGroup,
25636
25577
  gradedGroups: this.props.gradedGroups,
@@ -25672,7 +25613,7 @@ var GradedGroupSet$1 = {
25672
25613
  tracking: "all",
25673
25614
  isLintable: true
25674
25615
  };
25675
- const styles$k = StyleSheet.create({
25616
+ const styles$l = StyleSheet.create({
25676
25617
  top: {
25677
25618
  display: "flex",
25678
25619
  flexDirection: "row"
@@ -25777,7 +25718,7 @@ class ButtonGroup extends React.Component {
25777
25718
  id: "" + i,
25778
25719
  ref: "button" + i,
25779
25720
  key: "" + i,
25780
- className: css(styles$j.buttonStyle, button.value === value && styles$j.selectedStyle),
25721
+ className: css(styles$k.buttonStyle, button.value === value && styles$k.selectedStyle),
25781
25722
  onClick: () => this.toggleSelect(button.value)
25782
25723
  }, button.content || "" + button.value);
25783
25724
  });
@@ -25794,7 +25735,7 @@ ButtonGroup.defaultProps = {
25794
25735
  value: null,
25795
25736
  allowEmpty: true
25796
25737
  };
25797
- const styles$j = StyleSheet.create({
25738
+ const styles$k = StyleSheet.create({
25798
25739
  buttonStyle: {
25799
25740
  backgroundColor: "white",
25800
25741
  border: "1px solid #ccc",
@@ -31078,7 +31019,7 @@ const HideAnswersToggle = props => {
31078
31019
  const switchId = idFactory.get("hide-answers-toggle");
31079
31020
  const labelId = idFactory.get("hide-answers-label");
31080
31021
  return /*#__PURE__*/React.createElement(View, {
31081
- style: styles$i.switchWrapper
31022
+ style: styles$j.switchWrapper
31082
31023
  }, /*#__PURE__*/React.createElement(Switch, {
31083
31024
  id: switchId,
31084
31025
  checked: props.areAnswersHidden,
@@ -31090,7 +31031,7 @@ const HideAnswersToggle = props => {
31090
31031
  tag: "label"
31091
31032
  }, strings.hideAnswersToggleLabel));
31092
31033
  };
31093
- const styles$i = StyleSheet.create({
31034
+ const styles$j = StyleSheet.create({
31094
31035
  switchWrapper: {
31095
31036
  display: "flex",
31096
31037
  flexDirection: "row",
@@ -31143,13 +31084,13 @@ const AnswerPill = props => {
31143
31084
  id: idFactory.get("perseus-label-image-widget-answer-pill"),
31144
31085
  onClick: correct ? undefined : onClick,
31145
31086
  ref: ref,
31146
- style: [style, popperStyle, styles$h.pill, correct && styles$h.correct, incorrect && styles$h.incorrect, (focused || hovered) && BringToFront]
31087
+ style: [style, popperStyle, styles$i.pill, correct && styles$i.correct, incorrect && styles$i.incorrect, (focused || hovered) && BringToFront]
31147
31088
  }, /*#__PURE__*/React.createElement(Renderer, {
31148
31089
  content: answerString,
31149
31090
  inline: true
31150
31091
  })));
31151
31092
  };
31152
- const styles$h = StyleSheet.create({
31093
+ const styles$i = StyleSheet.create({
31153
31094
  correct: {
31154
31095
  // WB green darkened by 18%
31155
31096
  backgroundColor: "#00880b"
@@ -31202,23 +31143,23 @@ class Marker extends React.Component {
31202
31143
  icon: iconNull
31203
31144
  };
31204
31145
  if (showCorrectness) {
31205
- iconStyles = [styles$g.markerGraded, showCorrectness === "correct" ? styles$g.markerCorrect : styles$g.markerIncorrect, isOpen && styles$g.markerSelected];
31146
+ iconStyles = [styles$h.markerGraded, showCorrectness === "correct" ? styles$h.markerCorrect : styles$h.markerIncorrect, isOpen && styles$h.markerSelected];
31206
31147
  args = _extends({}, args, {
31207
31148
  icon: showCorrectness === "correct" ? iconCheck : iconMinus
31208
31149
  });
31209
31150
  } else if (selectedAnswers && selectedAnswers.length > 0) {
31210
- iconStyles = [styles$g.markerFilled, isOpen && styles$g.markerSelected];
31151
+ iconStyles = [styles$h.markerFilled, isOpen && styles$h.markerSelected];
31211
31152
  } else if (isOpen) {
31212
- iconStyles = [styles$g.markerSelected];
31153
+ iconStyles = [styles$h.markerSelected];
31213
31154
  args = _extends({}, args, {
31214
31155
  icon: iconChevronDown,
31215
31156
  size: 8
31216
31157
  });
31217
31158
  } else if (showPulsate) {
31218
- iconStyles = [styles$g.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$g.markerUnfilledPulsateOnce : showPulsate && styles$g.markerUnfilledPulsateInfinite];
31159
+ iconStyles = [styles$h.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$h.markerUnfilledPulsateOnce : showPulsate && styles$h.markerUnfilledPulsateInfinite];
31219
31160
  }
31220
31161
  return /*#__PURE__*/React.createElement(View, {
31221
- style: [styles$g.markerIcon, iconStyles],
31162
+ style: [styles$h.markerIcon, iconStyles],
31222
31163
  ref: node => this._icon = node
31223
31164
  }, /*#__PURE__*/React.createElement(Icon, args));
31224
31165
  }
@@ -31240,7 +31181,7 @@ class Marker extends React.Component {
31240
31181
  const markerDisabled = showCorrectness === "correct";
31241
31182
  const active = hovered || focused;
31242
31183
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
31243
- style: [styles$g.marker, active && !markerDisabled && styles$g.markerActive]
31184
+ style: [styles$h.marker, active && !markerDisabled && styles$h.markerActive]
31244
31185
  // already translated in: /widgets/graded-group.tsx
31245
31186
  ,
31246
31187
  "aria-label": markerDisabled ? i18n._("Correct!") : label
@@ -31258,7 +31199,7 @@ class Marker extends React.Component {
31258
31199
  Marker.defaultProps = {
31259
31200
  selected: []
31260
31201
  };
31261
- const styles$g = StyleSheet.create({
31202
+ const styles$h = StyleSheet.create({
31262
31203
  marker: {
31263
31204
  position: "absolute",
31264
31205
  backgroundColor: Color.white,
@@ -31828,13 +31769,13 @@ class LabelImage extends React.Component {
31828
31769
  const promptString = isMobile ? multipleAnswers ? i18n._("Tap each dot on the image to select all answers that apply.") : i18n._("Tap each dot on the image to select an answer.") : multipleAnswers ? i18n._("Click each dot on the image to select all answers that apply.") : i18n._("Click each dot on the image to select an answer.");
31829
31770
  const choicesString = i18n._("Choices:");
31830
31771
  return /*#__PURE__*/React.createElement("div", {
31831
- className: classNames("perseus-label-image-widget-instructions", css(styles$f.instructions))
31772
+ className: classNames("perseus-label-image-widget-instructions", css(styles$g.instructions))
31832
31773
  }, /*#__PURE__*/React.createElement("div", {
31833
- className: css(styles$f.instructionsCaption)
31774
+ className: css(styles$g.instructionsCaption)
31834
31775
  }, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React.createElement("div", {
31835
- className: css(styles$f.instructionsChoices)
31776
+ className: css(styles$g.instructionsChoices)
31836
31777
  }, choices.map((choice, index) => /*#__PURE__*/React.createElement("div", {
31837
- className: css(styles$f.instructionsChoice),
31778
+ className: css(styles$g.instructionsChoice),
31838
31779
  key: index
31839
31780
  }, /*#__PURE__*/React.createElement(Renderer, {
31840
31781
  content: choice
@@ -31851,20 +31792,20 @@ class LabelImage extends React.Component {
31851
31792
  activeMarkerIndex
31852
31793
  } = this.state;
31853
31794
  return /*#__PURE__*/React.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React.createElement("div", {
31854
- className: css(styles$f.markersCanvas),
31795
+ className: css(styles$g.markersCanvas),
31855
31796
  style: {
31856
31797
  maxWidth: imageWidth,
31857
31798
  maxHeight: imageHeight
31858
31799
  }
31859
31800
  }, /*#__PURE__*/React.createElement("div", {
31860
- className: css(styles$f.imageContainer,
31801
+ className: css(styles$g.imageContainer,
31861
31802
  // Ensure image interaction is disabled while answer
31862
31803
  // choices popup is visible. This addresses specific
31863
31804
  // case where user may click on question image to
31864
31805
  // dismiss the popup. If the image is larger in size
31865
31806
  // than its rendered in the widget, this would
31866
31807
  // result in a zoom of the image.
31867
- activeMarkerIndex !== -1 && styles$f.imageInteractionDisabled)
31808
+ activeMarkerIndex !== -1 && styles$g.imageInteractionDisabled)
31868
31809
  }, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
31869
31810
  setAssetStatus
31870
31811
  }) => /*#__PURE__*/React.createElement(SvgImage, {
@@ -31888,7 +31829,7 @@ class LabelImage extends React.Component {
31888
31829
  }));
31889
31830
  }
31890
31831
  }
31891
- const styles$f = StyleSheet.create({
31832
+ const styles$g = StyleSheet.create({
31892
31833
  instructions: {
31893
31834
  paddingBottom: 16
31894
31835
  },
@@ -32245,7 +32186,7 @@ class Placeholder extends React.Component {
32245
32186
  const {
32246
32187
  layout
32247
32188
  } = this.props;
32248
- const className = css(styles$e.card, styles$e.placeholder, layout === Layout.HORIZONTAL && styles$e.horizontalCard);
32189
+ const className = css(styles$f.card, styles$f.placeholder, layout === Layout.HORIZONTAL && styles$f.horizontalCard);
32249
32190
  const style = {
32250
32191
  width: this.props.width,
32251
32192
  height: this.props.height
@@ -32428,7 +32369,7 @@ class Draggable extends React.Component {
32428
32369
  // We need to keep backwards compatbility with rules specified directly
32429
32370
  // in CSS. Hence the hacky tacking on of manual classNames.
32430
32371
  // See sortable.less for details.
32431
- let className = 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";
32372
+ let className = 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";
32432
32373
  if (!includePadding) {
32433
32374
  className += " perseus-sortable-draggable-unpadded";
32434
32375
  }
@@ -32635,7 +32576,7 @@ class Sortable extends React.Component {
32635
32576
  } = this.props;
32636
32577
  // We need to keep backwards compatbility with rules specified directly
32637
32578
  // in CSS. See sortable.less for details.
32638
- const className = css(styles$e.sortable) + " perseus-sortable";
32579
+ const className = css(styles$f.sortable) + " perseus-sortable";
32639
32580
  const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === Layout.VERTICAL;
32640
32581
  const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === Layout.HORIZONTAL;
32641
32582
  _.each(this.state.items, function (item, i, items) {
@@ -32877,7 +32818,7 @@ Sortable.defaultProps = {
32877
32818
  linterContext: PerseusLinter.linterContextDefault,
32878
32819
  waitForTexRendererToLoad: true
32879
32820
  };
32880
- const styles$e = StyleSheet.create({
32821
+ const styles$f = StyleSheet.create({
32881
32822
  sortable: {
32882
32823
  boxSizing: "border-box",
32883
32824
  float: "left",
@@ -33039,23 +32980,23 @@ class Matcher extends React.Component {
33039
32980
  };
33040
32981
  const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
33041
32982
  return /*#__PURE__*/React.createElement("table", {
33042
- className: css(styles$d.widget) + " " + HACKY_CSS_CLASSNAME
32983
+ className: css(styles$e.widget) + " " + HACKY_CSS_CLASSNAME
33043
32984
  }, /*#__PURE__*/React.createElement("tbody", null, showLabels && /*#__PURE__*/React.createElement("tr", {
33044
- className: css(styles$d.row)
32985
+ className: css(styles$e.row)
33045
32986
  }, /*#__PURE__*/React.createElement("th", {
33046
- className: css(styles$d.column, styles$d.columnLabel)
32987
+ className: css(styles$e.column, styles$e.columnLabel)
33047
32988
  }, /*#__PURE__*/React.createElement(Renderer, {
33048
32989
  content: this.props.labels[0] || "...",
33049
32990
  linterContext: this.props.linterContext
33050
32991
  })), /*#__PURE__*/React.createElement("th", {
33051
- className: css(styles$d.column, styles$d.columnRight, styles$d.columnLabel)
32992
+ className: css(styles$e.column, styles$e.columnRight, styles$e.columnLabel)
33052
32993
  }, /*#__PURE__*/React.createElement(Renderer, {
33053
32994
  content: this.props.labels[1] || "...",
33054
32995
  linterContext: this.props.linterContext
33055
32996
  }))), /*#__PURE__*/React.createElement("tr", {
33056
- className: css(styles$d.row)
32997
+ className: css(styles$e.row)
33057
32998
  }, /*#__PURE__*/React.createElement("td", {
33058
- className: css(styles$d.column)
32999
+ className: css(styles$e.column)
33059
33000
  }, /*#__PURE__*/React.createElement(Sortable, {
33060
33001
  options: left,
33061
33002
  layout: Layout.VERTICAL,
@@ -33070,7 +33011,7 @@ class Matcher extends React.Component {
33070
33011
  ,
33071
33012
  ref: "left"
33072
33013
  })), /*#__PURE__*/React.createElement("td", {
33073
- className: css(styles$d.column, styles$d.columnRight)
33014
+ className: css(styles$e.column, styles$e.columnRight)
33074
33015
  }, /*#__PURE__*/React.createElement(Sortable
33075
33016
  // @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
33076
33017
  , {
@@ -33123,7 +33064,7 @@ _.extend(Matcher, {
33123
33064
  });
33124
33065
  const padding = 5;
33125
33066
  const border = "1px solid #444";
33126
- const styles$d = StyleSheet.create({
33067
+ const styles$e = StyleSheet.create({
33127
33068
  widget: {
33128
33069
  paddingTop: padding,
33129
33070
  maxWidth: "100%",
@@ -33990,9 +33931,9 @@ function drawText(ctx, item) {
33990
33931
  if (item.value === null) {
33991
33932
  return;
33992
33933
  }
33993
- ctx.fillStyle = styles$c.fgColor;
33994
- ctx.font = styles$c.font;
33995
- ctx.fillText(item.value, item.pos[0] - styles$c.fontSizePx / 2 + 1, item.pos[1] + styles$c.fontSizePx / 2);
33934
+ ctx.fillStyle = styles$d.fgColor;
33935
+ ctx.font = styles$d.font;
33936
+ ctx.fillText(item.value, item.pos[0] - styles$d.fontSizePx / 2 + 1, item.pos[1] + styles$d.fontSizePx / 2);
33996
33937
  }
33997
33938
 
33998
33939
  /**
@@ -34013,16 +33954,16 @@ function drawText(ctx, item) {
34013
33954
  function drawDoubleLine(ctx, item) {
34014
33955
  // Outer line that forms both of the bond lines.
34015
33956
  let path = new Path2D();
34016
- ctx.lineWidth = 5 * styles$c.lineWidth;
34017
- ctx.strokeStyle = styles$c.fgColor;
33957
+ ctx.lineWidth = 5 * styles$d.lineWidth;
33958
+ ctx.strokeStyle = styles$d.fgColor;
34018
33959
  path.moveTo(item.startPos[0], item.startPos[1]);
34019
33960
  path.lineTo(item.endPos[0], item.endPos[1]);
34020
33961
  ctx.stroke(path);
34021
33962
 
34022
33963
  // Inner white line that separates the two bond lines.
34023
33964
  path = new Path2D();
34024
- ctx.lineWidth = 3 * styles$c.lineWidth;
34025
- ctx.strokeStyle = styles$c.bgColor;
33965
+ ctx.lineWidth = 3 * styles$d.lineWidth;
33966
+ ctx.strokeStyle = styles$d.bgColor;
34026
33967
  path.moveTo(item.startPos[0], item.startPos[1]);
34027
33968
  path.lineTo(item.endPos[0], item.endPos[1]);
34028
33969
  ctx.stroke(path);
@@ -34049,16 +33990,16 @@ function drawTripleLine(ctx, item) {
34049
33990
 
34050
33991
  // Outer line that will form the two outer bond lines.
34051
33992
  let path = new Path2D();
34052
- ctx.lineWidth = 7 * styles$c.lineWidth;
34053
- ctx.strokeStyle = styles$c.fgColor;
33993
+ ctx.lineWidth = 7 * styles$d.lineWidth;
33994
+ ctx.strokeStyle = styles$d.fgColor;
34054
33995
  path.moveTo(item.startPos[0], item.startPos[1]);
34055
33996
  path.lineTo(item.endPos[0], item.endPos[1]);
34056
33997
  ctx.stroke(path);
34057
33998
 
34058
33999
  // Middle white line that separates the bonds
34059
34000
  path = new Path2D();
34060
- ctx.lineWidth = 5 * styles$c.lineWidth;
34061
- ctx.strokeStyle = styles$c.bgColor;
34001
+ ctx.lineWidth = 5 * styles$d.lineWidth;
34002
+ ctx.strokeStyle = styles$d.bgColor;
34062
34003
  path.moveTo(item.startPos[0], item.startPos[1]);
34063
34004
  path.lineTo(item.endPos[0], item.endPos[1]);
34064
34005
  ctx.stroke(path);
@@ -34080,8 +34021,8 @@ function drawTripleLine(ctx, item) {
34080
34021
  */
34081
34022
  function drawLine(ctx, item) {
34082
34023
  const path = new Path2D();
34083
- ctx.lineWidth = styles$c.lineWidth;
34084
- ctx.strokeStyle = styles$c.fgColor;
34024
+ ctx.lineWidth = styles$d.lineWidth;
34025
+ ctx.strokeStyle = styles$d.fgColor;
34085
34026
  path.moveTo(item.startPos[0], item.startPos[1]);
34086
34027
  path.lineTo(item.endPos[0], item.endPos[1]);
34087
34028
  ctx.stroke(path);
@@ -34133,7 +34074,7 @@ function compareElements(item0, item1) {
34133
34074
  function draw(ctx, items) {
34134
34075
  items.sort(compareElements).forEach(drawItem(ctx));
34135
34076
  }
34136
- const styles$c = {
34077
+ const styles$d = {
34137
34078
  bgColor: "rgb(255, 255, 255)",
34138
34079
  fgColor: "rgb(0, 0, 0)",
34139
34080
  fontSizePx: 12,
@@ -36695,7 +36636,7 @@ class HighlightRenderer extends React.PureComponent {
36695
36636
  const rects = this.state.cachedHighlightRects;
36696
36637
  return /*#__PURE__*/React.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React.createElement("div", {
36697
36638
  key: index,
36698
- className: css(styles$b.highlightRect),
36639
+ className: css(styles$c.highlightRect),
36699
36640
  style: {
36700
36641
  // NOTE(mdr): We apply `position: absolute` here
36701
36642
  // rather than in Aphrodite styles, because
@@ -36714,7 +36655,7 @@ class HighlightRenderer extends React.PureComponent {
36714
36655
  })));
36715
36656
  }
36716
36657
  }
36717
- const styles$b = StyleSheet.create({
36658
+ const styles$c = StyleSheet.create({
36718
36659
  highlightRect: {
36719
36660
  background: "#fffabe" // highlighter yellow :)
36720
36661
  }
@@ -36795,7 +36736,7 @@ class HighlightTooltip extends React.PureComponent {
36795
36736
  // TooltipContent wouldn't let me overwrite
36796
36737
  // user-select and onClick
36797
36738
  const content = /*#__PURE__*/React.createElement("div", {
36798
- className: css(styles$a.tooltipLabel),
36739
+ className: css(styles$b.tooltipLabel),
36799
36740
  onClick: this.props.onClick
36800
36741
  }, this.props.label);
36801
36742
  const style = {
@@ -36815,7 +36756,7 @@ class HighlightTooltip extends React.PureComponent {
36815
36756
  }, /*#__PURE__*/React.createElement("div", null)));
36816
36757
  }
36817
36758
  }
36818
- const styles$a = StyleSheet.create({
36759
+ const styles$b = StyleSheet.create({
36819
36760
  tooltipLabel: {
36820
36761
  // Unlike most tooltip contents, we don't want this label to be
36821
36762
  // selectable. Selecting it is not only unhelpful, but dangerous: if
@@ -37367,7 +37308,7 @@ class HighlightableContent extends React.PureComponent {
37367
37308
  // starting point: https://phabricator.khanacademy.org/D35623?id=170698
37368
37309
  const buildHighlight = r => this._buildHighlight(r);
37369
37310
  return /*#__PURE__*/React.createElement("div", {
37370
- className: css(styles$9.container),
37311
+ className: css(styles$a.container),
37371
37312
  ref: container => this._container = container
37372
37313
  }, /*#__PURE__*/React.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React.createElement(HighlightingUI, {
37373
37314
  buildHighlight: buildHighlight,
@@ -37388,14 +37329,14 @@ class HighlightableContent extends React.PureComponent {
37388
37329
  onAddHighlight: this._handleAddHighlight,
37389
37330
  onRemoveHighlight: this._handleRemoveHighlight
37390
37331
  })), /*#__PURE__*/React.createElement("div", {
37391
- className: css(styles$9.content),
37332
+ className: css(styles$a.content),
37392
37333
  ref: content => this._content = content
37393
37334
  }, /*#__PURE__*/React.createElement(WordIndexer, {
37394
37335
  onWordsUpdate: this._handleWordsUpdate
37395
37336
  }, this.props.children)));
37396
37337
  }
37397
37338
  }
37398
- const styles$9 = StyleSheet.create({
37339
+ const styles$a = StyleSheet.create({
37399
37340
  // We render content with z-index 1, and highlights with z-index 0, so that
37400
37341
  // content will receive the browser's native pointer events. (Highlights
37401
37342
  // have their own magic code to manage hover detection, despite being
@@ -37795,7 +37736,7 @@ class LineHeightMeasurer extends React.Component {
37795
37736
  }
37796
37737
  render() {
37797
37738
  return /*#__PURE__*/React.createElement("div", {
37798
- className: css(styles$8.measurer),
37739
+ className: css(styles$9.measurer),
37799
37740
  "aria-hidden": "true"
37800
37741
  }, /*#__PURE__*/React.createElement("div", {
37801
37742
  ref: ref => this._line = ref,
@@ -37803,7 +37744,7 @@ class LineHeightMeasurer extends React.Component {
37803
37744
  }, "Line Height Measurement"));
37804
37745
  }
37805
37746
  }
37806
- const styles$8 = StyleSheet.create({
37747
+ const styles$9 = StyleSheet.create({
37807
37748
  measurer: {
37808
37749
  position: "absolute",
37809
37750
  top: 0,
@@ -39093,6 +39034,52 @@ var Plotter$1 = {
39093
39034
  staticTransform: staticTransform
39094
39035
  };
39095
39036
 
39037
+ /**
39038
+ * This widget is for embedding Khan Academy Python programs.
39039
+ */
39040
+ function getUrlFromProgramID(programID) {
39041
+ const path = `/python-program/${programID}/embedded`;
39042
+ return toAbsoluteUrl(path);
39043
+ }
39044
+ /* This renders the program in an iframe. */
39045
+ class PythonProgram extends React.Component {
39046
+ render() {
39047
+ const url = getUrlFromProgramID(this.props.programID);
39048
+ const iframeStyle = {
39049
+ height: this.props.height,
39050
+ width: "100%"
39051
+ };
39052
+ const sandboxOptions = ["allow-popups", "allow-same-origin", "allow-scripts", "allow-top-navigation"].join(" ");
39053
+
39054
+ // We sandbox the iframe so that we allowlist only the functionality
39055
+ // that we need. This makes it a bit safer in case some content
39056
+ // creator "went wild".
39057
+ // http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
39058
+ return /*#__PURE__*/React.createElement(View, {
39059
+ style: styles$8.container
39060
+ }, /*#__PURE__*/React.createElement("iframe", {
39061
+ sandbox: sandboxOptions,
39062
+ src: url,
39063
+ style: iframeStyle,
39064
+ allowFullScreen: true
39065
+ }));
39066
+ }
39067
+ }
39068
+ PythonProgram.defaultProps = {
39069
+ height: 400
39070
+ };
39071
+ const styles$8 = StyleSheet.create({
39072
+ container: {
39073
+ margin: "auto",
39074
+ width: "100%"
39075
+ }
39076
+ });
39077
+ var PythonProgram$1 = {
39078
+ name: "python-program",
39079
+ displayName: "Python Program",
39080
+ widget: PythonProgram
39081
+ };
39082
+
39096
39083
  class Separator extends React.Component {
39097
39084
  constructor(...args) {
39098
39085
  super(...args);
@@ -41528,7 +41515,7 @@ var Video$1 = {
41528
41515
  };
41529
41516
 
41530
41517
  /* eslint-disable import/no-named-as-default */
41531
- 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];
41518
+ 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];
41532
41519
 
41533
41520
  /**
41534
41521
  * This should be called by all clients, specifying whether extra widgets are
@@ -41568,7 +41555,7 @@ const init = function init(options) {
41568
41555
 
41569
41556
  // This file is processed by a Rollup plugin (replace) to inject the production
41570
41557
  const libName = "@khanacademy/perseus";
41571
- const libVersion = "19.1.9";
41558
+ const libVersion = "19.2.0";
41572
41559
  addLibraryVersionToPerseusDebug(libName, libVersion);
41573
41560
 
41574
41561
  const apiVersion = {
@@ -43014,6 +43001,8 @@ const ItemExtras = [
43014
43001
 
43015
43002
  // prettier-ignore
43016
43003
 
43004
+ // prettier-ignore
43005
+
43017
43006
  //prettier-ignore
43018
43007
 
43019
43008
  // A background image applied to various widgets.