@khanacademy/perseus 10.0.0 → 10.1.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
@@ -2931,6 +2931,17 @@ const ExpressionWithDependencies = /*#__PURE__*/React.forwardRef((props, ref) =>
2931
2931
  analytics: deps.analytics
2932
2932
  }, props));
2933
2933
  });
2934
+
2935
+ // HACK: Propogate "static" methods onto our wrapper component.
2936
+ // In the future we should adjust client apps to not depend on these static
2937
+ // methods and instead adjust Peresus to provide these facilities through
2938
+ // instance methods on our Renderers.
2939
+ // @ts-expect-error - TS2339 - Property 'validate' does not exist on type
2940
+ ExpressionWithDependencies.validate = Expression.validate;
2941
+ // @ts-expect-error - TS2339 - Property 'validate' does not exist on type
2942
+ ExpressionWithDependencies.getUserInputFromProps = Expression.getUserInputFromProps;
2943
+ // @ts-expect-error - TS2339 - Property 'validate' does not exist on type
2944
+ ExpressionWithDependencies.getOneCorrectAnswerFromRubric = Expression.getOneCorrectAnswerFromRubric;
2934
2945
  var Expression$1 = {
2935
2946
  name: "expression",
2936
2947
  displayName: "Expression / Equation",
@@ -17555,7 +17566,8 @@ class Zoomable extends React.Component {
17555
17566
  zoomed
17556
17567
  } = this.state;
17557
17568
  const {
17558
- animateHeight
17569
+ animateHeight,
17570
+ disableEntranceAnimation
17559
17571
  } = this.props;
17560
17572
  const property = animateHeight ? "opacity transform height" : "opacity transform";
17561
17573
 
@@ -17567,7 +17579,9 @@ class Zoomable extends React.Component {
17567
17579
  } : {};
17568
17580
 
17569
17581
  // Do a fancy little slide as we fade the contents in the first time.
17570
- const translateOffset = visible ? "" : " translate(0, 8px)";
17582
+ const shouldSlide = !disableEntranceAnimation && !visible;
17583
+ const translateOffset = shouldSlide ? " translate(0, 8px)" : "";
17584
+ const opacity = shouldSlide ? 0 : 1;
17571
17585
  const scaleString = (scale != null ? scale : 1).toString();
17572
17586
  const transform = zoomed ? `scale(1, 1) ${translateOffset}` : `scale(${scaleString}, ${scaleString}) ${translateOffset}`;
17573
17587
  const style = _extends({
@@ -17576,7 +17590,7 @@ class Zoomable extends React.Component {
17576
17590
  height: zoomed ? expandedHeight : compactHeight,
17577
17591
  transform: transform,
17578
17592
  transformOrigin: "0 0",
17579
- opacity: visible ? 1 : 0,
17593
+ opacity: opacity,
17580
17594
  WebkitTapHighlightColor: "transparent"
17581
17595
  }, transitionStyle);
17582
17596
  return /*#__PURE__*/React.createElement("span", {
@@ -17594,6 +17608,7 @@ class Zoomable extends React.Component {
17594
17608
  Zoomable.defaultProps = {
17595
17609
  animateHeight: false,
17596
17610
  readyToMeasure: true,
17611
+ disableEntranceAnimation: false,
17597
17612
  computeChildBounds: parentNode => {
17598
17613
  const firstChild = parentNode.firstElementChild;
17599
17614
  return {
@@ -17644,7 +17659,9 @@ class ZoomableTeX extends React.Component {
17644
17659
  render() {
17645
17660
  return /*#__PURE__*/React.createElement(Zoomable, {
17646
17661
  readyToMeasure: this.state.isRendered,
17647
- computeChildBounds: computeMathBounds
17662
+ computeChildBounds: computeMathBounds,
17663
+ animateHeight: false,
17664
+ disableEntranceAnimation: true
17648
17665
  }, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
17649
17666
  setAssetStatus
17650
17667
  }) => /*#__PURE__*/React.createElement(Tex, {
@@ -17888,33 +17905,33 @@ class Lint extends React.Component {
17888
17905
  let warningText;
17889
17906
  let warningTextStyle;
17890
17907
  if (this.props.severity === Severity.Error) {
17891
- severityStyle = styles$A.indicatorError;
17908
+ severityStyle = styles$z.indicatorError;
17892
17909
  warningText = "Error";
17893
- warningTextStyle = styles$A.publishBlockingError;
17910
+ warningTextStyle = styles$z.publishBlockingError;
17894
17911
  } else if (this.props.severity === Severity.Warning) {
17895
- severityStyle = styles$A.indicatorWarning;
17912
+ severityStyle = styles$z.indicatorWarning;
17896
17913
  warningText = "Warning";
17897
- warningTextStyle = styles$A.warning;
17914
+ warningTextStyle = styles$z.warning;
17898
17915
  } else {
17899
- severityStyle = styles$A.indicatorGuideline;
17916
+ severityStyle = styles$z.indicatorGuideline;
17900
17917
  warningText = "Recommendation";
17901
- warningTextStyle = styles$A.warning;
17918
+ warningTextStyle = styles$z.warning;
17902
17919
  }
17903
17920
  return /*#__PURE__*/React.createElement("a", {
17904
17921
  href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
17905
17922
  target: "lint-help-window",
17906
17923
  className: css(style)
17907
17924
  }, /*#__PURE__*/React.createElement("span", {
17908
- className: css(styles$A.indicator, severityStyle)
17925
+ className: css(styles$z.indicator, severityStyle)
17909
17926
  }, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
17910
- className: css(styles$A.tooltip, tooltipAbove && styles$A.tooltipAbove)
17927
+ className: css(styles$z.tooltip, tooltipAbove && styles$z.tooltipAbove)
17911
17928
  }, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
17912
17929
  key: i,
17913
- className: css(styles$A.tooltipParagraph)
17930
+ className: css(styles$z.tooltipParagraph)
17914
17931
  }, /*#__PURE__*/React.createElement("span", {
17915
17932
  className: css(warningTextStyle)
17916
17933
  }, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
17917
- className: css(styles$A.tail, tooltipAbove && styles$A.tailAbove)
17934
+ className: css(styles$z.tail, tooltipAbove && styles$z.tailAbove)
17918
17935
  })));
17919
17936
  };
17920
17937
  }
@@ -17958,20 +17975,20 @@ class Lint extends React.Component {
17958
17975
  }
17959
17976
  if (blockHighlight) {
17960
17977
  return /*#__PURE__*/React.createElement("span", {
17961
- className: css(styles$A.lintContainer, styles$A.lintContainerBlock)
17962
- }, this.renderLink(styles$A.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17978
+ className: css(styles$z.lintContainer, styles$z.lintContainerBlock)
17979
+ }, this.renderLink(styles$z.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17963
17980
  }
17964
17981
  if (inline) {
17965
17982
  return /*#__PURE__*/React.createElement("span", {
17966
- className: css(styles$A.lintContainer)
17967
- }, this.renderLink(styles$A.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17983
+ className: css(styles$z.lintContainer)
17984
+ }, this.renderLink(styles$z.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17968
17985
  }
17969
17986
  return /*#__PURE__*/React.createElement("div", {
17970
- className: css(styles$A.lintContainer)
17971
- }, this.renderLink(styles$A.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
17987
+ className: css(styles$z.lintContainer)
17988
+ }, this.renderLink(styles$z.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
17972
17989
  }
17973
17990
  }
17974
- const styles$A = StyleSheet.create({
17991
+ const styles$z = StyleSheet.create({
17975
17992
  // This is the class of the outermost element.
17976
17993
  // We use relative positioning so that the lint indicator can be
17977
17994
  // positioned absolutely relative to the position of the linty container.
@@ -19719,7 +19736,7 @@ class Renderer extends React.Component {
19719
19736
  paddingLeft: margin,
19720
19737
  paddingRight: margin
19721
19738
  };
19722
- const mobileInnerStyle = _extends({}, innerStyle, styles$z.mobileZoomableParentFix);
19739
+ const mobileInnerStyle = _extends({}, innerStyle, styles$y.mobileZoomableParentFix);
19723
19740
  return /*#__PURE__*/React.createElement("div", {
19724
19741
  key: state.key,
19725
19742
  className: "perseus-block-math",
@@ -19840,7 +19857,7 @@ class Renderer extends React.Component {
19840
19857
  paddingLeft: 0,
19841
19858
  paddingRight: 0
19842
19859
  };
19843
- const mobileInnerStyle = _extends({}, innerStyle, styles$z.mobileZoomableParentFix);
19860
+ const mobileInnerStyle = _extends({}, innerStyle, styles$y.mobileZoomableParentFix);
19844
19861
  const wrappedOutput = /*#__PURE__*/React.createElement("div", {
19845
19862
  style: _extends({}, mobileInnerStyle, {
19846
19863
  overflowX: "auto"
@@ -20456,7 +20473,7 @@ Renderer.defaultProps = {
20456
20473
  onSerializedStateUpdated: () => {},
20457
20474
  linterContext: PerseusLinter.linterContextDefault
20458
20475
  };
20459
- const styles$z = {
20476
+ const styles$y = {
20460
20477
  mobileZoomableParentFix: {
20461
20478
  // NOTE(abdul): There is an issue where transform animations will
20462
20479
  // cause the Zoomable component to disappear when running on the
@@ -21234,10 +21251,10 @@ class InputNumber extends React.Component {
21234
21251
  // Note: This is _very_ similar to what `numeric-input.jsx` does. If
21235
21252
  // you modify this, double-check if you also need to modify that
21236
21253
  // component.
21237
- const inputStyles = [styles$y.default, this.props.size === "small" ? styles$y.small : null, this.props.rightAlign ? styles$y.rightAlign : styles$y.leftAlign];
21254
+ const inputStyles = [styles$x.default, this.props.size === "small" ? styles$x.small : null, this.props.rightAlign ? styles$x.rightAlign : styles$x.leftAlign];
21238
21255
  // Unanswered
21239
21256
  if (rubric && !this.props.currentValue) {
21240
- inputStyles.push(styles$y.answerStateUnanswered);
21257
+ inputStyles.push(styles$x.answerStateUnanswered);
21241
21258
  }
21242
21259
  return /*#__PURE__*/React.createElement(InputWithExamples
21243
21260
  // eslint-disable-next-line react/no-string-refs
@@ -21322,7 +21339,7 @@ InputNumber.defaultProps = {
21322
21339
  apiOptions: ApiOptions.defaults,
21323
21340
  linterContext: linterContextDefault
21324
21341
  };
21325
- const styles$y = StyleSheet.create({
21342
+ const styles$x = StyleSheet.create({
21326
21343
  default: {
21327
21344
  width: 80,
21328
21345
  height: "auto"
@@ -22311,7 +22328,7 @@ const FocusRing = function FocusRing(props) {
22311
22328
  };
22312
22329
  return /*#__PURE__*/React.createElement("span", {
22313
22330
  "data-test-id": "focus-ring",
22314
- className: css(styles$x.ring),
22331
+ className: css(styles$w.ring),
22315
22332
  style: style
22316
22333
  }, children);
22317
22334
  };
@@ -22320,7 +22337,7 @@ FocusRing.defaultProps = {
22320
22337
  color: kaGreen$1,
22321
22338
  multipleSelect: false
22322
22339
  };
22323
- const styles$x = StyleSheet.create({
22340
+ const styles$w = StyleSheet.create({
22324
22341
  ring: {
22325
22342
  margin: "auto",
22326
22343
  display: "inline-block",
@@ -22357,7 +22374,7 @@ function getChoiceLetter(pos) {
22357
22374
  }
22358
22375
 
22359
22376
  const CHOICE_ICON_SIZE = 24;
22360
- const styles$w = StyleSheet.create({
22377
+ const styles$v = StyleSheet.create({
22361
22378
  iconWrapper: {
22362
22379
  display: "inline-block",
22363
22380
  position: "relative"
@@ -22380,7 +22397,7 @@ const CrossOutLine = function CrossOutLine(props) {
22380
22397
  width: CROSS_OUT_LINE_SIZE,
22381
22398
  height: CROSS_OUT_LINE_SIZE,
22382
22399
  viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
22383
- className: css(styles$v.crossOutLine),
22400
+ className: css(styles$u.crossOutLine),
22384
22401
  "data-test-id": "choice-icon__cross-out-line"
22385
22402
  }, /*#__PURE__*/React.createElement("line", {
22386
22403
  // The line stretches from the bottom-left to top-right.
@@ -22395,7 +22412,7 @@ const CrossOutLine = function CrossOutLine(props) {
22395
22412
  strokeLinecap: "round"
22396
22413
  }));
22397
22414
  };
22398
- const styles$v = StyleSheet.create({
22415
+ const styles$u = StyleSheet.create({
22399
22416
  crossOutLine: {
22400
22417
  // Center the icon within the container.
22401
22418
  position: "absolute",
@@ -22476,7 +22493,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
22476
22493
  } = props;
22477
22494
  const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
22478
22495
  return /*#__PURE__*/React.createElement("div", {
22479
- className: css(styles$w.iconWrapper)
22496
+ className: css(styles$v.iconWrapper)
22480
22497
  }, /*#__PURE__*/React.createElement(FocusRing, {
22481
22498
  color: Color.blue,
22482
22499
  visible: focused || hovered,
@@ -22485,13 +22502,13 @@ const ChoiceIcon = function ChoiceIcon(props) {
22485
22502
  // @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
22486
22503
  style: dynamicStyles,
22487
22504
  "data-test-id": "choice-icon__library-choice-icon",
22488
- className: css(styles$u.circle, showCorrectness && correct && styles$u.circleCorrect, showCorrectness && !correct && styles$u.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$u.circleIncorrectAnswered)
22505
+ className: css(styles$t.circle, showCorrectness && correct && styles$t.circleCorrect, showCorrectness && !correct && styles$t.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$t.circleIncorrectAnswered)
22489
22506
  // used in BaseRadio editMode to check
22490
22507
  // if we actually clicked on the radio icon
22491
22508
  ,
22492
22509
  "data-is-radio-icon": true
22493
22510
  }, /*#__PURE__*/React.createElement("div", {
22494
- className: css(styles$u.innerWrapper)
22511
+ className: css(styles$t.innerWrapper)
22495
22512
  }, /*#__PURE__*/React.createElement(ChoiceInner, {
22496
22513
  pos: pos,
22497
22514
  showCorrectness: showCorrectness,
@@ -22500,7 +22517,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
22500
22517
  color: dynamicStyles.borderColor
22501
22518
  }));
22502
22519
  };
22503
- const styles$u = StyleSheet.create({
22520
+ const styles$t = StyleSheet.create({
22504
22521
  innerWrapper: {
22505
22522
  width: CHOICE_ICON_SIZE,
22506
22523
  height: CHOICE_ICON_SIZE,
@@ -22592,19 +22609,19 @@ const OptionStatus = function OptionStatus(props) {
22592
22609
  }
22593
22610
  let textStyle;
22594
22611
  if (correct) {
22595
- textStyle = styles$t.correct;
22612
+ textStyle = styles$s.correct;
22596
22613
  } else {
22597
22614
  if (checked || previouslyAnswered) {
22598
- textStyle = styles$t.incorrectAnswered;
22615
+ textStyle = styles$s.incorrectAnswered;
22599
22616
  } else {
22600
- textStyle = styles$t.incorrect;
22617
+ textStyle = styles$s.incorrect;
22601
22618
  }
22602
22619
  }
22603
22620
  return /*#__PURE__*/React.createElement("div", {
22604
- className: css(styles$t.text, textStyle)
22621
+ className: css(styles$s.text, textStyle)
22605
22622
  }, renderText(checked, correct, crossedOut));
22606
22623
  };
22607
- const styles$t = StyleSheet.create({
22624
+ const styles$s = StyleSheet.create({
22608
22625
  text: {
22609
22626
  alignItems: "center",
22610
22627
  display: "flex",
@@ -22679,8 +22696,8 @@ const Choice = function Choice(props) {
22679
22696
  crossedOut: updatedCrossedOut
22680
22697
  });
22681
22698
  }
22682
- const descriptionClassName = classNames("description", css(styles$s.description));
22683
- const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$s.rationale));
22699
+ const descriptionClassName = classNames("description", css(styles$r.description));
22700
+ const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$r.rationale));
22684
22701
 
22685
22702
  // We want to show the choices as dimmed out when the choices are disabled.
22686
22703
  // However, we don't want to do this when we're in review mode in the
@@ -22839,7 +22856,7 @@ const Choice = function Choice(props) {
22839
22856
  "data-test-id": `perseus-radio-rationale-content-${pos}`
22840
22857
  }, rationale));
22841
22858
  };
22842
- const styles$s = StyleSheet.create({
22859
+ const styles$r = StyleSheet.create({
22843
22860
  description: {
22844
22861
  display: "inline-block",
22845
22862
  width: "100%"
@@ -23030,10 +23047,10 @@ const BaseRadio = function BaseRadio(props) {
23030
23047
  const isMobile = apiOptions.isMobile;
23031
23048
  const firstChoiceHighlighted = choices[0].highlighted;
23032
23049
  const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
23033
- 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));
23034
- const instructionsClassName = classNames("instructions", css(styles$r.instructions, isMobile && styles$r.instructionsMobile));
23050
+ const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$q.radio, styles$q.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$q.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$q.radioContainerLastHighlighted));
23051
+ const instructionsClassName = classNames("instructions", css(styles$q.instructions, isMobile && styles$q.instructionsMobile));
23035
23052
  const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect);
23036
- const responsiveClassName = css(styles$r.responsiveFieldset);
23053
+ const responsiveClassName = css(styles$q.responsiveFieldset);
23037
23054
  const fieldset = /*#__PURE__*/React.createElement("fieldset", {
23038
23055
  className: `perseus-widget-radio-fieldset ${responsiveClassName}`
23039
23056
  }, /*#__PURE__*/React.createElement("legend", {
@@ -23084,7 +23101,7 @@ const BaseRadio = function BaseRadio(props) {
23084
23101
  const aphroditeClassName = checked => {
23085
23102
  // Whether or not to show correctness borders
23086
23103
  // for this choice and the next choice.
23087
- 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);
23104
+ return css(sharedStyles.aboveScratchpad, styles$q.item, styles$q.responsiveItem, checked && styles$q.selectedItem, checked && choice.highlighted && styles$q.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$q.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$q.nextHighlighted);
23088
23105
  };
23089
23106
 
23090
23107
  // HACK(abdulrahman): Preloads the selection-state
@@ -23158,14 +23175,14 @@ const BaseRadio = function BaseRadio(props) {
23158
23175
  // Allow for horizontal scrolling if content is too wide, which may be
23159
23176
  // an issue especially on phones.
23160
23177
  return /*#__PURE__*/React.createElement("div", {
23161
- className: css(styles$r.responsiveContainer)
23178
+ className: css(styles$q.responsiveContainer)
23162
23179
  }, fieldset);
23163
23180
  };
23164
23181
  BaseRadio.defaultProps = {
23165
23182
  editMode: false,
23166
23183
  multipleSelect: false
23167
23184
  };
23168
- const styles$r = StyleSheet.create({
23185
+ const styles$q = StyleSheet.create({
23169
23186
  instructions: {
23170
23187
  display: "block",
23171
23188
  color: gray17,
@@ -23804,9 +23821,9 @@ class Categorizer extends React.Component {
23804
23821
  indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
23805
23822
  }
23806
23823
  const table = /*#__PURE__*/React.createElement("table", {
23807
- className: "categorizer-table " + css(styles$q.mobileTable)
23824
+ className: "categorizer-table " + css(styles$p.mobileTable)
23808
23825
  }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
23809
- className: css(styles$q.emptyHeaderCell)
23826
+ className: css(styles$p.emptyHeaderCell)
23810
23827
  }), this.props.categories.map((category, i) => {
23811
23828
  // Array index is the correct key here, as that's
23812
23829
  // how category grading actually works -- no way
@@ -23814,7 +23831,7 @@ class Categorizer extends React.Component {
23814
23831
  // middle. (If we later add that, this should be
23815
23832
  // fixed.)
23816
23833
  return /*#__PURE__*/React.createElement("th", {
23817
- className: css(styles$q.header),
23834
+ className: css(styles$p.header),
23818
23835
  key: i
23819
23836
  }, /*#__PURE__*/React.createElement(Renderer, {
23820
23837
  content: category,
@@ -23834,7 +23851,7 @@ class Categorizer extends React.Component {
23834
23851
  })), self.props.categories.map((catName, catNum) => {
23835
23852
  const selected = self.props.values[itemNum] === catNum;
23836
23853
  return /*#__PURE__*/React.createElement("td", {
23837
- className: "category " + css(styles$q.cell),
23854
+ className: "category " + css(styles$p.cell),
23838
23855
  key: catNum
23839
23856
  }, /*#__PURE__*/React.createElement("div", {
23840
23857
  className: ClassNames.INTERACTIVE,
@@ -23853,7 +23870,7 @@ class Categorizer extends React.Component {
23853
23870
  onChange: this.onChange.bind(this, itemNum, catNum),
23854
23871
  onClick: e => e.stopPropagation()
23855
23872
  }), !isMobile && /*#__PURE__*/React.createElement("span", {
23856
- className: css(styles$q.radioSpan, selected && styles$q.checkedRadioSpan, this.props.static && selected && styles$q.staticCheckedRadioSpan)
23873
+ className: css(styles$p.radioSpan, selected && styles$p.checkedRadioSpan, this.props.static && selected && styles$p.staticCheckedRadioSpan)
23857
23874
  }, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
23858
23875
  }));
23859
23876
  /* eslint-enable max-len */
@@ -23865,7 +23882,7 @@ class Categorizer extends React.Component {
23865
23882
  "categorizer-container": true,
23866
23883
  "static-mode": this.props.static
23867
23884
  });
23868
- const inlineStyles = this.props.apiOptions.isMobile ? [styles$q.fullBleedContainer] : [];
23885
+ const inlineStyles = this.props.apiOptions.isMobile ? [styles$p.fullBleedContainer] : [];
23869
23886
  return /*#__PURE__*/React.createElement("div", {
23870
23887
  className: extraClassNames + " " + css(...inlineStyles)
23871
23888
  }, table);
@@ -23910,7 +23927,7 @@ const pageMargin = 16;
23910
23927
 
23911
23928
  // Stylesheets aren't directly testable
23912
23929
  /* c8 ignore next */
23913
- const styles$q = StyleSheet.create({
23930
+ const styles$p = StyleSheet.create({
23914
23931
  mobileTable: {
23915
23932
  [mediaQueries.smOrSmaller]: {
23916
23933
  minWidth: "auto"
@@ -24146,7 +24163,7 @@ class CSProgram extends React.Component {
24146
24163
  // creator "went wild".
24147
24164
  // http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
24148
24165
  return /*#__PURE__*/React.createElement("div", {
24149
- className: css(styles$p.widthOverride, styleContainer && styles$p.container)
24166
+ className: css(styles$o.widthOverride, styleContainer && styles$o.container)
24150
24167
  }, /*#__PURE__*/React.createElement("iframe", {
24151
24168
  sandbox: sandboxOptions,
24152
24169
  src: url,
@@ -24175,7 +24192,7 @@ CSProgram.defaultProps = {
24175
24192
  // optional message
24176
24193
  message: null
24177
24194
  };
24178
- const styles$p = StyleSheet.create({
24195
+ const styles$o = StyleSheet.create({
24179
24196
  // Override the inherited width from the perseus paragraph class
24180
24197
  // 820 is minimum width for 420px editor and 400px canvas
24181
24198
  widthOverride: {
@@ -24218,7 +24235,7 @@ class Definition extends React.Component {
24218
24235
  }) => /*#__PURE__*/React.createElement(Popover, {
24219
24236
  content: /*#__PURE__*/React.createElement(PopoverContentCore, {
24220
24237
  color: "white",
24221
- style: styles$o.tooltipBody,
24238
+ style: styles$n.tooltipBody,
24222
24239
  closeButtonVisible: true
24223
24240
  }, /*#__PURE__*/React.createElement(Renderer, {
24224
24241
  apiOptions: this.props.apiOptions,
@@ -24249,7 +24266,7 @@ Definition.defaultProps = {
24249
24266
  togglePrompt: "define me",
24250
24267
  definition: "definition goes here"
24251
24268
  };
24252
- const styles$o = {
24269
+ const styles$n = {
24253
24270
  tooltipBody: {
24254
24271
  color: Color.offBlack,
24255
24272
  fontSize: 20,
@@ -24408,15 +24425,15 @@ class Explanation extends React.Component {
24408
24425
  const onClick = this._onClick;
24409
24426
  if (isMobile) {
24410
24427
  linkContainer = /*#__PURE__*/React.createElement("div", {
24411
- className: css(styles$n.linkContainer)
24428
+ className: css(styles$m.linkContainer)
24412
24429
  }, /*#__PURE__*/React.createElement("a", {
24413
- className: css(styles$n.mobileExplanationLink),
24430
+ className: css(styles$m.mobileExplanationLink),
24414
24431
  href: href,
24415
24432
  onClick: onClick,
24416
24433
  role: "button",
24417
24434
  "aria-expanded": this.state.expanded
24418
24435
  }, linkAnchor), this.state.expanded && /*#__PURE__*/React.createElement("svg", {
24419
- className: css(styles$n.disclosureArrow)
24436
+ className: css(styles$m.disclosureArrow)
24420
24437
  }, /*#__PURE__*/React.createElement("polygon", {
24421
24438
  style: {
24422
24439
  fill: backgroundColor
@@ -24429,13 +24446,13 @@ class Explanation extends React.Component {
24429
24446
  // an anchor tag (if rendered in a modal) or a Wonder Blocks
24430
24447
  // link component in lesson page, see: `article-page.jsx`.
24431
24448
  linkContainer = /*#__PURE__*/React.createElement("div", {
24432
- className: css(styles$n.linkContainer, styles$n.articleLink)
24449
+ className: css(styles$m.linkContainer, styles$m.articleLink)
24433
24450
  }, /*#__PURE__*/React.createElement(Link, {
24434
- className: css(styles$n.explanationLink)
24451
+ className: css(styles$m.explanationLink)
24435
24452
  // HACK(michaelpolyak): WB Link doesn't passthrough
24436
24453
  // class name.
24437
24454
  ,
24438
- style: styles$n.explanationLink,
24455
+ style: styles$m.explanationLink,
24439
24456
  href: href,
24440
24457
  onClick: onClick,
24441
24458
  role: "button",
@@ -24445,9 +24462,9 @@ class Explanation extends React.Component {
24445
24462
  // NOTE: For exercises, the baseElements `Link` is an
24446
24463
  // anchor tag, see: `perseus-api.jsx`.
24447
24464
  linkContainer = /*#__PURE__*/React.createElement("div", {
24448
- className: css(styles$n.linkContainer, styles$n.exerciseLink)
24465
+ className: css(styles$m.linkContainer, styles$m.exerciseLink)
24449
24466
  }, /*#__PURE__*/React.createElement(Link, {
24450
- className: css(styles$n.explanationLink),
24467
+ className: css(styles$m.explanationLink),
24451
24468
  href: href,
24452
24469
  onClick: onClick,
24453
24470
  role: "button",
@@ -24455,11 +24472,11 @@ class Explanation extends React.Component {
24455
24472
  }, `[${linkAnchor}]`));
24456
24473
  }
24457
24474
  }
24458
- const expandedStyle = isMobile ? styles$n.contentExpandedMobile : styles$n.contentExpanded;
24475
+ const expandedStyle = isMobile ? styles$m.contentExpandedMobile : styles$m.contentExpanded;
24459
24476
  return /*#__PURE__*/React.createElement("div", {
24460
- className: css(styles$n.container)
24477
+ className: css(styles$m.container)
24461
24478
  }, linkContainer, this.state.expanded && /*#__PURE__*/React.createElement("div", {
24462
- className: css(styles$n.content, isMobile && styles$n.contentMobile, this.state.expanded && expandedStyle)
24479
+ className: css(styles$m.content, isMobile && styles$m.contentMobile, this.state.expanded && expandedStyle)
24463
24480
  // eslint-disable-next-line react/no-string-refs
24464
24481
  ,
24465
24482
  ref: "content"
@@ -24483,7 +24500,7 @@ const verticalContentPadding = 10;
24483
24500
  const arrowWidth = 30;
24484
24501
  const arrowHeight = 14;
24485
24502
  const backgroundColor = gray95;
24486
- const styles$n = StyleSheet.create({
24503
+ const styles$m = StyleSheet.create({
24487
24504
  container: {
24488
24505
  display: "inline",
24489
24506
  position: "relative"
@@ -24608,15 +24625,15 @@ class GradedGroupAnswerBar extends React.Component {
24608
24625
  onCheckAnswer,
24609
24626
  onNextQuestion
24610
24627
  } = this.props;
24611
- const answerBarStyle = _extends({}, styles$m.answerBar, {
24628
+ const answerBarStyle = _extends({}, styles$l.answerBar, {
24612
24629
  backgroundColor: answerBarState === "CORRECT" ? Color.offWhite : "white",
24613
24630
  // Center the "Correct!" message only when there's no next question
24614
24631
  justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
24615
24632
  });
24616
24633
  const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
24617
- style: styles$m.text
24634
+ style: styles$l.text
24618
24635
  }, /*#__PURE__*/React.createElement("span", {
24619
- style: styles$m.tryAgainIcon
24636
+ style: styles$l.tryAgainIcon
24620
24637
  }, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
24621
24638
  style: {
24622
24639
  marginLeft: 8
@@ -24635,7 +24652,7 @@ class GradedGroupAnswerBar extends React.Component {
24635
24652
  return /*#__PURE__*/React.createElement("div", {
24636
24653
  style: answerBarStyle
24637
24654
  }, /*#__PURE__*/React.createElement("span", {
24638
- style: styles$m.text
24655
+ style: styles$l.text
24639
24656
  }, /*#__PURE__*/React.createElement("span", {
24640
24657
  style: {
24641
24658
  fontSize: 28,
@@ -24657,7 +24674,7 @@ class GradedGroupAnswerBar extends React.Component {
24657
24674
  }
24658
24675
  }
24659
24676
  const fontSize = 17;
24660
- const styles$m = {
24677
+ const styles$l = {
24661
24678
  answerBar: {
24662
24679
  display: "flex",
24663
24680
  alignItems: "center",
@@ -24834,7 +24851,7 @@ class GradedGroup extends React.Component {
24834
24851
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
24835
24852
  gradeStatus = i18n._("Incorrect");
24836
24853
  }
24837
- const mobileClass = this.props.inGradedGroupSet ? css(styles$l.gradedGroupInSet) : css(styles$l.gradedGroup);
24854
+ const mobileClass = this.props.inGradedGroupSet ? css(styles$k.gradedGroupInSet) : css(styles$k.gradedGroup);
24838
24855
  const classes = classNames({
24839
24856
  [mobileClass]: apiOptions.isMobile,
24840
24857
  "perseus-graded-group": true,
@@ -24853,7 +24870,7 @@ class GradedGroup extends React.Component {
24853
24870
  return /*#__PURE__*/React.createElement("div", {
24854
24871
  className: classes
24855
24872
  }, !!this.props.title && /*#__PURE__*/React.createElement("div", {
24856
- className: css(styles$l.title)
24873
+ className: css(styles$k.title)
24857
24874
  }, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
24858
24875
  // eslint-disable-next-line react/no-string-refs
24859
24876
  ref: "renderer",
@@ -24885,7 +24902,7 @@ class GradedGroup extends React.Component {
24885
24902
  }, i18n._("Next question")), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
24886
24903
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
24887
24904
  tabIndex: "0",
24888
- className: css(styles$l.explanationTitle),
24905
+ className: css(styles$k.explanationTitle),
24889
24906
  onClick: () => this.setState({
24890
24907
  showHint: false
24891
24908
  }),
@@ -24917,7 +24934,7 @@ class GradedGroup extends React.Component {
24917
24934
  showHint: true
24918
24935
  });
24919
24936
  },
24920
- className: css(styles$l.showHintLink)
24937
+ className: css(styles$k.showHintLink)
24921
24938
  }, i18n._("Explain"))), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
24922
24939
  apiOptions: apiOptions,
24923
24940
  answerBarState: answerBarState,
@@ -24938,7 +24955,7 @@ GradedGroup.defaultProps = {
24938
24955
  const traverseChildWidgets$3 = function traverseChildWidgets(props, traverseRenderer) {
24939
24956
  return _.extend({}, props, traverseRenderer(props));
24940
24957
  };
24941
- const styles$l = StyleSheet.create({
24958
+ const styles$k = StyleSheet.create({
24942
24959
  gradedGroupInSet: {
24943
24960
  // Reset a few desktop-only styles that come from graded-group.less
24944
24961
  marginLeft: 0,
@@ -25009,7 +25026,7 @@ class Indicators extends React.Component {
25009
25026
  }
25010
25027
  render() {
25011
25028
  return /*#__PURE__*/React.createElement("ul", {
25012
- className: css(styles$k.indicatorContainer)
25029
+ className: css(styles$j.indicatorContainer)
25013
25030
  }, this.props.gradedGroups.map(({
25014
25031
  title
25015
25032
  }, i) => /*#__PURE__*/React.createElement("li", {
@@ -25018,7 +25035,7 @@ class Indicators extends React.Component {
25018
25035
  title
25019
25036
  }),
25020
25037
  key: title,
25021
- className: css(styles$k.indicator, i === this.props.currentGroup && styles$k.selectedIndicator),
25038
+ className: css(styles$j.indicator, i === this.props.currentGroup && styles$j.selectedIndicator),
25022
25039
  tabIndex: 0,
25023
25040
  onClick: () => this.props.onChangeCurrentGroup(i),
25024
25041
  onKeyDown: e => this.handleKeyDown(e, i)
@@ -25082,7 +25099,7 @@ class GradedGroupSet extends React.Component {
25082
25099
  } = getDependencies();
25083
25100
  if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
25084
25101
  return /*#__PURE__*/React.createElement("div", {
25085
- className: css(styles$k.container)
25102
+ className: css(styles$j.container)
25086
25103
  }, this.props.gradedGroups.map((gradedGroup, i) => {
25087
25104
  return (
25088
25105
  /*#__PURE__*/
@@ -25105,13 +25122,13 @@ class GradedGroupSet extends React.Component {
25105
25122
  const numGroups = this.props.gradedGroups.length;
25106
25123
  const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
25107
25124
  return /*#__PURE__*/React.createElement("div", {
25108
- className: css(styles$k.container)
25125
+ className: css(styles$j.container)
25109
25126
  }, /*#__PURE__*/React.createElement("div", {
25110
- className: css(styles$k.top)
25127
+ className: css(styles$j.top)
25111
25128
  }, /*#__PURE__*/React.createElement("div", {
25112
- className: css(styles$k.title)
25129
+ className: css(styles$j.title)
25113
25130
  }, currentGroup.title), /*#__PURE__*/React.createElement("div", {
25114
- className: css(styles$k.spacer)
25131
+ className: css(styles$j.spacer)
25115
25132
  }), /*#__PURE__*/React.createElement(Indicators, {
25116
25133
  currentGroup: this.state.currentGroup,
25117
25134
  gradedGroups: this.props.gradedGroups,
@@ -25153,7 +25170,7 @@ var GradedGroupSet$1 = {
25153
25170
  tracking: "all",
25154
25171
  isLintable: true
25155
25172
  };
25156
- const styles$k = StyleSheet.create({
25173
+ const styles$j = StyleSheet.create({
25157
25174
  top: {
25158
25175
  display: "flex",
25159
25176
  flexDirection: "row"
@@ -25235,7 +25252,7 @@ class ButtonGroup extends React.Component {
25235
25252
  id: "" + i,
25236
25253
  ref: "button" + i,
25237
25254
  key: "" + i,
25238
- className: css(styles$j.buttonStyle, button.value === value && styles$j.selectedStyle),
25255
+ className: css(styles$i.buttonStyle, button.value === value && styles$i.selectedStyle),
25239
25256
  onClick: () => this.toggleSelect(button.value)
25240
25257
  }, button.content || "" + button.value);
25241
25258
  });
@@ -25252,7 +25269,7 @@ ButtonGroup.defaultProps = {
25252
25269
  value: null,
25253
25270
  allowEmpty: true
25254
25271
  };
25255
- const styles$j = StyleSheet.create({
25272
+ const styles$i = StyleSheet.create({
25256
25273
  buttonStyle: {
25257
25274
  backgroundColor: "white",
25258
25275
  border: "1px solid #ccc",
@@ -26687,10 +26704,9 @@ class ImageWidget extends React.Component {
26687
26704
  // This minWidth takes precedence over minWidth applied via
26688
26705
  // Aphrodite.
26689
26706
  const minWidth = isImageFullWidth ? null : "0 !important";
26690
- titleAndCaption = /*#__PURE__*/React.createElement("div", {
26707
+ titleAndCaption = /*#__PURE__*/React.createElement("figcaption", {
26691
26708
  className: className
26692
26709
  }, /*#__PURE__*/React.createElement("div", {
26693
- className: css(styles$i.caption),
26694
26710
  style: {
26695
26711
  // @ts-expect-error - TS2322 - Type 'string | null' is not assignable to type 'MinWidth<string | number> | undefined'.
26696
26712
  minWidth: minWidth
@@ -26701,7 +26717,7 @@ class ImageWidget extends React.Component {
26701
26717
  linterContext: this.props.linterContext
26702
26718
  })));
26703
26719
  }
26704
- return /*#__PURE__*/React.createElement("div", {
26720
+ return /*#__PURE__*/React.createElement("figure", {
26705
26721
  className: "perseus-image-widget"
26706
26722
  }, image, alt, titleAndCaption);
26707
26723
  }
@@ -26717,7 +26733,7 @@ class ImageWidget extends React.Component {
26717
26733
  }));
26718
26734
  }
26719
26735
  if (this.props.caption) {
26720
- caption = /*#__PURE__*/React.createElement("div", {
26736
+ caption = /*#__PURE__*/React.createElement("figcaption", {
26721
26737
  className: "perseus-image-caption"
26722
26738
  }, /*#__PURE__*/React.createElement(Renderer, {
26723
26739
  content: this.props.caption,
@@ -26725,7 +26741,7 @@ class ImageWidget extends React.Component {
26725
26741
  linterContext: this.props.linterContext
26726
26742
  }));
26727
26743
  }
26728
- return /*#__PURE__*/React.createElement("div", {
26744
+ return /*#__PURE__*/React.createElement("figure", {
26729
26745
  className: "perseus-image-widget"
26730
26746
  }, title, image, alt, caption);
26731
26747
  }
@@ -26749,22 +26765,6 @@ ImageWidget.defaultProps = {
26749
26765
  caption: "",
26750
26766
  linterContext: linterContextDefault
26751
26767
  };
26752
- const styles$i = StyleSheet.create({
26753
- caption: {
26754
- display: "inline-block",
26755
- marginTop: baseUnitPx,
26756
- maxWidth: 640,
26757
- [mediaQueries.lgOrSmaller]: {
26758
- // TODO(david): This maxWidth is not being used because
26759
- // it's overriden by the 512px max-width we have on
26760
- // paragraphs.
26761
- maxWidth: 540
26762
- },
26763
- [mediaQueries.smOrSmaller]: {
26764
- maxWidth: 450
26765
- }
26766
- }
26767
- });
26768
26768
  var Image$1 = {
26769
26769
  name: "image",
26770
26770
  // This widget's accessibility depends on its contents: if the image has