@khanacademy/perseus 20.0.2 → 20.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
@@ -23,16 +23,18 @@ import { entries, UnreachableCaseError, keys } from '@khanacademy/wonder-stuff-c
23
23
  import { CircularSpinner } from '@khanacademy/wonder-blocks-progress-spinner';
24
24
  import SimpleMarkdown from '@khanacademy/simple-markdown';
25
25
  import { pureMarkdownRules } from '@khanacademy/pure-markdown';
26
- import { TextField } from '@khanacademy/wonder-blocks-form';
26
+ import { TextField, Checkbox } from '@khanacademy/wonder-blocks-form';
27
27
  import Button from '@khanacademy/wonder-blocks-button';
28
28
  import { Strut } from '@khanacademy/wonder-blocks-layout';
29
29
  import Banner from '@khanacademy/wonder-blocks-banner';
30
30
  import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-blocks-dropdown';
31
31
  import debounce$2 from 'lodash.debounce';
32
- import { vec, Line as Line$3, MovablePoint as MovablePoint$5, Coordinates, Mafs } from 'mafs';
32
+ import { vec, useMovable, useTransformContext, MovablePoint as MovablePoint$5, Coordinates, Mafs } from 'mafs';
33
+ import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
34
+ import questionIcon from '@phosphor-icons/core/regular/question.svg';
35
+ import { LabelSmall, LabelMedium } from '@khanacademy/wonder-blocks-typography';
33
36
  import createReactClass from 'create-react-class';
34
37
  import Switch from '@khanacademy/wonder-blocks-switch';
35
- import { LabelMedium } from '@khanacademy/wonder-blocks-typography';
36
38
  import Pill from '@khanacademy/wonder-blocks-pill';
37
39
  import { Popper } from 'react-popper';
38
40
  import Link from '@khanacademy/wonder-blocks-link';
@@ -42,12 +44,14 @@ function _extends() {
42
44
  _extends = Object.assign ? Object.assign.bind() : function (target) {
43
45
  for (var i = 1; i < arguments.length; i++) {
44
46
  var source = arguments[i];
47
+
45
48
  for (var key in source) {
46
49
  if (Object.prototype.hasOwnProperty.call(source, key)) {
47
50
  target[key] = source[key];
48
51
  }
49
52
  }
50
53
  }
54
+
51
55
  return target;
52
56
  };
53
57
  return _extends.apply(this, arguments);
@@ -58,11 +62,13 @@ function _objectWithoutPropertiesLoose(source, excluded) {
58
62
  var target = {};
59
63
  var sourceKeys = Object.keys(source);
60
64
  var key, i;
65
+
61
66
  for (i = 0; i < sourceKeys.length; i++) {
62
67
  key = sourceKeys[i];
63
68
  if (excluded.indexOf(key) >= 0) continue;
64
69
  target[key] = source[key];
65
70
  }
71
+
66
72
  return target;
67
73
  }
68
74
 
@@ -257,7 +263,7 @@ class MathInput extends React.Component {
257
263
  className = className + " " + this.props.className;
258
264
  }
259
265
  return /*#__PURE__*/React.createElement(View, {
260
- style: [styles$C.outerWrapper, this.state.focused && styles$C.wrapperFocused, this.props.hasError && styles$C.wrapperError]
266
+ style: [styles$D.outerWrapper, this.state.focused && styles$D.wrapperFocused, this.props.hasError && styles$D.wrapperError]
261
267
  }, /*#__PURE__*/React.createElement("div", {
262
268
  style: {
263
269
  display: "flex",
@@ -290,7 +296,7 @@ class MathInput extends React.Component {
290
296
  var _this$props$keypadBut, _this$props;
291
297
  return /*#__PURE__*/React.createElement(PopoverContentCore, {
292
298
  closeButtonVisible: true,
293
- style: styles$C.popoverContent
299
+ style: styles$D.popoverContent
294
300
  }, /*#__PURE__*/React.createElement(DesktopKeypad, _extends({
295
301
  onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
296
302
  extraKeys: this.props.extraKeys,
@@ -334,9 +340,9 @@ const MathInputIcon = ({
334
340
  color = Color.offBlack;
335
341
  break;
336
342
  }
337
- const dynamicClass = active || focused ? styles$C.iconActive : styles$C.iconInactive;
343
+ const dynamicClass = active || focused ? styles$D.iconActive : styles$D.iconInactive;
338
344
  return /*#__PURE__*/React.createElement(View, {
339
- style: [styles$C.iconContainer, dynamicClass]
345
+ style: [styles$D.iconContainer, dynamicClass]
340
346
  }, /*#__PURE__*/React.createElement("svg", {
341
347
  xmlns: "http://www.w3.org/2000/svg",
342
348
  width: "16",
@@ -381,7 +387,7 @@ const inputFocused = {
381
387
  borderColor: Color.blue,
382
388
  margin: -1
383
389
  };
384
- const styles$C = StyleSheet.create({
390
+ const styles$D = StyleSheet.create({
385
391
  iconContainer: {
386
392
  display: "flex",
387
393
  justifyContent: "center",
@@ -4235,6 +4241,7 @@ function _classPrivateFieldBase(receiver, privateKey) {
4235
4241
  if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
4236
4242
  throw new TypeError("attempted to use private field on non-instance");
4237
4243
  }
4244
+
4238
4245
  return receiver;
4239
4246
  }
4240
4247
 
@@ -17876,33 +17883,33 @@ class Lint extends React.Component {
17876
17883
  let warningText;
17877
17884
  let warningTextStyle;
17878
17885
  if (this.props.severity === Severity.Error) {
17879
- severityStyle = styles$B.indicatorError;
17886
+ severityStyle = styles$C.indicatorError;
17880
17887
  warningText = "Error";
17881
- warningTextStyle = styles$B.publishBlockingError;
17888
+ warningTextStyle = styles$C.publishBlockingError;
17882
17889
  } else if (this.props.severity === Severity.Warning) {
17883
- severityStyle = styles$B.indicatorWarning;
17890
+ severityStyle = styles$C.indicatorWarning;
17884
17891
  warningText = "Warning";
17885
- warningTextStyle = styles$B.warning;
17892
+ warningTextStyle = styles$C.warning;
17886
17893
  } else {
17887
- severityStyle = styles$B.indicatorGuideline;
17894
+ severityStyle = styles$C.indicatorGuideline;
17888
17895
  warningText = "Recommendation";
17889
- warningTextStyle = styles$B.warning;
17896
+ warningTextStyle = styles$C.warning;
17890
17897
  }
17891
17898
  return /*#__PURE__*/React.createElement("a", {
17892
17899
  href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
17893
17900
  target: "lint-help-window",
17894
17901
  className: css(style)
17895
17902
  }, /*#__PURE__*/React.createElement("span", {
17896
- className: css(styles$B.indicator, severityStyle)
17903
+ className: css(styles$C.indicator, severityStyle)
17897
17904
  }, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
17898
- className: css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
17905
+ className: css(styles$C.tooltip, tooltipAbove && styles$C.tooltipAbove)
17899
17906
  }, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
17900
17907
  key: i,
17901
- className: css(styles$B.tooltipParagraph)
17908
+ className: css(styles$C.tooltipParagraph)
17902
17909
  }, /*#__PURE__*/React.createElement("span", {
17903
17910
  className: css(warningTextStyle)
17904
17911
  }, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
17905
- className: css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
17912
+ className: css(styles$C.tail, tooltipAbove && styles$C.tailAbove)
17906
17913
  })));
17907
17914
  };
17908
17915
  }
@@ -17940,20 +17947,20 @@ class Lint extends React.Component {
17940
17947
  }
17941
17948
  if (blockHighlight) {
17942
17949
  return /*#__PURE__*/React.createElement("span", {
17943
- className: css(styles$B.lintContainer, styles$B.lintContainerBlock)
17944
- }, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17950
+ className: css(styles$C.lintContainer, styles$C.lintContainerBlock)
17951
+ }, this.renderLink(styles$C.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17945
17952
  }
17946
17953
  if (inline) {
17947
17954
  return /*#__PURE__*/React.createElement("span", {
17948
- className: css(styles$B.lintContainer)
17949
- }, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17955
+ className: css(styles$C.lintContainer)
17956
+ }, this.renderLink(styles$C.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
17950
17957
  }
17951
17958
  return /*#__PURE__*/React.createElement("div", {
17952
- className: css(styles$B.lintContainer)
17953
- }, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
17959
+ className: css(styles$C.lintContainer)
17960
+ }, this.renderLink(styles$C.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
17954
17961
  }
17955
17962
  }
17956
- const styles$B = StyleSheet.create({
17963
+ const styles$C = StyleSheet.create({
17957
17964
  // This is the class of the outermost element.
17958
17965
  // We use relative positioning so that the lint indicator can be
17959
17966
  // positioned absolutely relative to the position of the linty container.
@@ -19878,7 +19885,7 @@ class Renderer extends React.Component {
19878
19885
  paddingLeft: margin,
19879
19886
  paddingRight: margin
19880
19887
  };
19881
- const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
19888
+ const mobileInnerStyle = _extends({}, innerStyle, styles$B.mobileZoomableParentFix);
19882
19889
  return /*#__PURE__*/React.createElement("div", {
19883
19890
  key: state.key,
19884
19891
  className: "perseus-block-math",
@@ -19999,7 +20006,7 @@ class Renderer extends React.Component {
19999
20006
  paddingLeft: 0,
20000
20007
  paddingRight: 0
20001
20008
  };
20002
- const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
20009
+ const mobileInnerStyle = _extends({}, innerStyle, styles$B.mobileZoomableParentFix);
20003
20010
  const wrappedOutput = /*#__PURE__*/React.createElement("div", {
20004
20011
  style: _extends({}, mobileInnerStyle, {
20005
20012
  overflowX: "auto"
@@ -20646,7 +20653,7 @@ Renderer.defaultProps = {
20646
20653
  onSerializedStateUpdated: () => {},
20647
20654
  linterContext: PerseusLinter.linterContextDefault
20648
20655
  };
20649
- const styles$A = {
20656
+ const styles$B = {
20650
20657
  mobileZoomableParentFix: {
20651
20658
  // NOTE(abdul): There is an issue where transform animations will
20652
20659
  // cause the Zoomable component to disappear when running on the
@@ -21654,10 +21661,10 @@ class InputNumber extends React.Component {
21654
21661
  // Note: This is _very_ similar to what `numeric-input.jsx` does. If
21655
21662
  // you modify this, double-check if you also need to modify that
21656
21663
  // component.
21657
- const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
21664
+ const inputStyles = [styles$A.default, this.props.size === "small" ? styles$A.small : null, this.props.rightAlign ? styles$A.rightAlign : styles$A.leftAlign];
21658
21665
  // Unanswered
21659
21666
  if (rubric && !this.props.currentValue) {
21660
- inputStyles.push(styles$z.answerStateUnanswered);
21667
+ inputStyles.push(styles$A.answerStateUnanswered);
21661
21668
  }
21662
21669
  return /*#__PURE__*/React.createElement(InputWithExamples
21663
21670
  // eslint-disable-next-line react/no-string-refs
@@ -21742,7 +21749,7 @@ InputNumber.defaultProps = {
21742
21749
  apiOptions: ApiOptions.defaults,
21743
21750
  linterContext: linterContextDefault
21744
21751
  };
21745
- const styles$z = StyleSheet.create({
21752
+ const styles$A = StyleSheet.create({
21746
21753
  default: {
21747
21754
  width: 80,
21748
21755
  height: "auto"
@@ -22734,7 +22741,7 @@ const FocusRing = function FocusRing(props) {
22734
22741
  };
22735
22742
  return /*#__PURE__*/React.createElement("span", {
22736
22743
  "data-test-id": "focus-ring",
22737
- className: css(styles$y.ring),
22744
+ className: css(styles$z.ring),
22738
22745
  style: style
22739
22746
  }, children);
22740
22747
  };
@@ -22743,7 +22750,7 @@ FocusRing.defaultProps = {
22743
22750
  color: kaGreen$1,
22744
22751
  multipleSelect: false
22745
22752
  };
22746
- const styles$y = StyleSheet.create({
22753
+ const styles$z = StyleSheet.create({
22747
22754
  ring: {
22748
22755
  margin: "auto",
22749
22756
  display: "inline-block",
@@ -22780,7 +22787,7 @@ function getChoiceLetter(pos) {
22780
22787
  }
22781
22788
 
22782
22789
  const CHOICE_ICON_SIZE = 24;
22783
- const styles$x = StyleSheet.create({
22790
+ const styles$y = StyleSheet.create({
22784
22791
  iconWrapper: {
22785
22792
  display: "inline-block",
22786
22793
  position: "relative"
@@ -22803,7 +22810,7 @@ const CrossOutLine = function CrossOutLine(props) {
22803
22810
  width: CROSS_OUT_LINE_SIZE,
22804
22811
  height: CROSS_OUT_LINE_SIZE,
22805
22812
  viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
22806
- className: css(styles$w.crossOutLine),
22813
+ className: css(styles$x.crossOutLine),
22807
22814
  "data-test-id": "choice-icon__cross-out-line"
22808
22815
  }, /*#__PURE__*/React.createElement("line", {
22809
22816
  // The line stretches from the bottom-left to top-right.
@@ -22818,7 +22825,7 @@ const CrossOutLine = function CrossOutLine(props) {
22818
22825
  strokeLinecap: "round"
22819
22826
  }));
22820
22827
  };
22821
- const styles$w = StyleSheet.create({
22828
+ const styles$x = StyleSheet.create({
22822
22829
  crossOutLine: {
22823
22830
  // Center the icon within the container.
22824
22831
  position: "absolute",
@@ -22899,7 +22906,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
22899
22906
  } = props;
22900
22907
  const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
22901
22908
  return /*#__PURE__*/React.createElement("div", {
22902
- className: css(styles$x.iconWrapper)
22909
+ className: css(styles$y.iconWrapper)
22903
22910
  }, /*#__PURE__*/React.createElement(FocusRing, {
22904
22911
  color: Color.blue,
22905
22912
  visible: focused || hovered,
@@ -22908,13 +22915,13 @@ const ChoiceIcon = function ChoiceIcon(props) {
22908
22915
  // @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
22909
22916
  style: dynamicStyles,
22910
22917
  "data-test-id": "choice-icon__library-choice-icon",
22911
- className: css(styles$v.circle, showCorrectness && correct && styles$v.circleCorrect, showCorrectness && !correct && styles$v.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$v.circleIncorrectAnswered)
22918
+ className: css(styles$w.circle, showCorrectness && correct && styles$w.circleCorrect, showCorrectness && !correct && styles$w.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$w.circleIncorrectAnswered)
22912
22919
  // used in BaseRadio editMode to check
22913
22920
  // if we actually clicked on the radio icon
22914
22921
  ,
22915
22922
  "data-is-radio-icon": true
22916
22923
  }, /*#__PURE__*/React.createElement("div", {
22917
- className: css(styles$v.innerWrapper)
22924
+ className: css(styles$w.innerWrapper)
22918
22925
  }, /*#__PURE__*/React.createElement(ChoiceInner, {
22919
22926
  pos: pos,
22920
22927
  showCorrectness: showCorrectness,
@@ -22923,7 +22930,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
22923
22930
  color: dynamicStyles.borderColor
22924
22931
  }));
22925
22932
  };
22926
- const styles$v = StyleSheet.create({
22933
+ const styles$w = StyleSheet.create({
22927
22934
  innerWrapper: {
22928
22935
  width: CHOICE_ICON_SIZE,
22929
22936
  height: CHOICE_ICON_SIZE,
@@ -23015,19 +23022,19 @@ const OptionStatus = function OptionStatus(props) {
23015
23022
  }
23016
23023
  let textStyle;
23017
23024
  if (correct) {
23018
- textStyle = styles$u.correct;
23025
+ textStyle = styles$v.correct;
23019
23026
  } else {
23020
23027
  if (checked || previouslyAnswered) {
23021
- textStyle = styles$u.incorrectAnswered;
23028
+ textStyle = styles$v.incorrectAnswered;
23022
23029
  } else {
23023
- textStyle = styles$u.incorrect;
23030
+ textStyle = styles$v.incorrect;
23024
23031
  }
23025
23032
  }
23026
23033
  return /*#__PURE__*/React.createElement("div", {
23027
- className: css(styles$u.text, textStyle)
23034
+ className: css(styles$v.text, textStyle)
23028
23035
  }, renderText(checked, correct, crossedOut));
23029
23036
  };
23030
- const styles$u = StyleSheet.create({
23037
+ const styles$v = StyleSheet.create({
23031
23038
  text: {
23032
23039
  alignItems: "center",
23033
23040
  display: "flex",
@@ -23102,8 +23109,8 @@ const Choice = function Choice(props) {
23102
23109
  crossedOut: updatedCrossedOut
23103
23110
  });
23104
23111
  }
23105
- const descriptionClassName = classNames("description", css(styles$t.description));
23106
- const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$t.rationale));
23112
+ const descriptionClassName = classNames("description", css(styles$u.description));
23113
+ const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$u.rationale));
23107
23114
 
23108
23115
  // We want to show the choices as dimmed out when the choices are disabled.
23109
23116
  // However, we don't want to do this when we're in review mode in the
@@ -23267,7 +23274,7 @@ const Choice = function Choice(props) {
23267
23274
  "data-test-id": `perseus-radio-rationale-content-${pos}`
23268
23275
  }, rationale));
23269
23276
  };
23270
- const styles$t = StyleSheet.create({
23277
+ const styles$u = StyleSheet.create({
23271
23278
  description: {
23272
23279
  display: "inline-block",
23273
23280
  width: "100%"
@@ -23459,10 +23466,10 @@ const BaseRadio = function BaseRadio(props) {
23459
23466
  const isMobile = apiOptions.isMobile;
23460
23467
  const firstChoiceHighlighted = choices[0].highlighted;
23461
23468
  const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
23462
- 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));
23463
- const instructionsClassName = classNames("instructions", css(styles$s.instructions, isMobile && styles$s.instructionsMobile));
23469
+ const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$t.radio, styles$t.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$t.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$t.radioContainerLastHighlighted));
23470
+ const instructionsClassName = classNames("instructions", css(styles$t.instructions, isMobile && styles$t.instructionsMobile));
23464
23471
  const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect);
23465
- const responsiveClassName = css(styles$s.responsiveFieldset);
23472
+ const responsiveClassName = css(styles$t.responsiveFieldset);
23466
23473
  const fieldset = /*#__PURE__*/React.createElement("fieldset", {
23467
23474
  className: `perseus-widget-radio-fieldset ${responsiveClassName}`
23468
23475
  }, /*#__PURE__*/React.createElement("legend", {
@@ -23513,7 +23520,7 @@ const BaseRadio = function BaseRadio(props) {
23513
23520
  const aphroditeClassName = checked => {
23514
23521
  // Whether or not to show correctness borders
23515
23522
  // for this choice and the next choice.
23516
- 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);
23523
+ return css(sharedStyles.aboveScratchpad, styles$t.item, styles$t.responsiveItem, checked && styles$t.selectedItem, checked && choice.highlighted && styles$t.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$t.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$t.nextHighlighted);
23517
23524
  };
23518
23525
 
23519
23526
  // HACK(abdulrahman): Preloads the selection-state
@@ -23587,14 +23594,14 @@ const BaseRadio = function BaseRadio(props) {
23587
23594
  // Allow for horizontal scrolling if content is too wide, which may be
23588
23595
  // an issue especially on phones.
23589
23596
  return /*#__PURE__*/React.createElement("div", {
23590
- className: css(styles$s.responsiveContainer)
23597
+ className: css(styles$t.responsiveContainer)
23591
23598
  }, fieldset);
23592
23599
  };
23593
23600
  BaseRadio.defaultProps = {
23594
23601
  editMode: false,
23595
23602
  multipleSelect: false
23596
23603
  };
23597
- const styles$s = StyleSheet.create({
23604
+ const styles$t = StyleSheet.create({
23598
23605
  instructions: {
23599
23606
  display: "block",
23600
23607
  color: gray17,
@@ -24235,9 +24242,9 @@ class Categorizer extends React.Component {
24235
24242
  indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
24236
24243
  }
24237
24244
  const table = /*#__PURE__*/React.createElement("table", {
24238
- className: "categorizer-table " + css(styles$r.mobileTable)
24245
+ className: "categorizer-table " + css(styles$s.mobileTable)
24239
24246
  }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
24240
- className: css(styles$r.emptyHeaderCell)
24247
+ className: css(styles$s.emptyHeaderCell)
24241
24248
  }), this.props.categories.map((category, i) => {
24242
24249
  // Array index is the correct key here, as that's
24243
24250
  // how category grading actually works -- no way
@@ -24245,7 +24252,7 @@ class Categorizer extends React.Component {
24245
24252
  // middle. (If we later add that, this should be
24246
24253
  // fixed.)
24247
24254
  return /*#__PURE__*/React.createElement("th", {
24248
- className: css(styles$r.header),
24255
+ className: css(styles$s.header),
24249
24256
  key: i
24250
24257
  }, /*#__PURE__*/React.createElement(Renderer, {
24251
24258
  content: category,
@@ -24265,7 +24272,7 @@ class Categorizer extends React.Component {
24265
24272
  })), self.props.categories.map((catName, catNum) => {
24266
24273
  const selected = self.props.values[itemNum] === catNum;
24267
24274
  return /*#__PURE__*/React.createElement("td", {
24268
- className: "category " + css(styles$r.cell),
24275
+ className: "category " + css(styles$s.cell),
24269
24276
  key: catNum
24270
24277
  }, /*#__PURE__*/React.createElement("div", {
24271
24278
  className: ClassNames.INTERACTIVE,
@@ -24280,7 +24287,7 @@ class Categorizer extends React.Component {
24280
24287
  onChange: () => this.onChange(itemNum, catNum),
24281
24288
  onClick: e => e.stopPropagation()
24282
24289
  }), !isMobile && /*#__PURE__*/React.createElement("span", {
24283
- className: css(styles$r.radioSpan, selected && styles$r.checkedRadioSpan, this.props.static && selected && styles$r.staticCheckedRadioSpan)
24290
+ className: css(styles$s.radioSpan, selected && styles$s.checkedRadioSpan, this.props.static && selected && styles$s.staticCheckedRadioSpan)
24284
24291
  }, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
24285
24292
  }));
24286
24293
  /* eslint-enable max-len */
@@ -24292,7 +24299,7 @@ class Categorizer extends React.Component {
24292
24299
  "categorizer-container": true,
24293
24300
  "static-mode": this.props.static
24294
24301
  });
24295
- const inlineStyles = this.props.apiOptions.isMobile ? [styles$r.fullBleedContainer] : [];
24302
+ const inlineStyles = this.props.apiOptions.isMobile ? [styles$s.fullBleedContainer] : [];
24296
24303
  return /*#__PURE__*/React.createElement("div", {
24297
24304
  className: extraClassNames + " " + css(...inlineStyles)
24298
24305
  }, table);
@@ -24344,7 +24351,7 @@ const pageMargin = 16;
24344
24351
 
24345
24352
  // Stylesheets aren't directly testable
24346
24353
  /* c8 ignore next */
24347
- const styles$r = StyleSheet.create({
24354
+ const styles$s = StyleSheet.create({
24348
24355
  mobileTable: {
24349
24356
  [mediaQueries.smOrSmaller]: {
24350
24357
  minWidth: "auto"
@@ -24580,7 +24587,7 @@ class CSProgram extends React.Component {
24580
24587
  // creator "went wild".
24581
24588
  // http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
24582
24589
  return /*#__PURE__*/React.createElement("div", {
24583
- className: css(styles$q.widthOverride, styleContainer && styles$q.container)
24590
+ className: css(styles$r.widthOverride, styleContainer && styles$r.container)
24584
24591
  }, /*#__PURE__*/React.createElement("iframe", {
24585
24592
  sandbox: sandboxOptions,
24586
24593
  src: url,
@@ -24609,7 +24616,7 @@ CSProgram.defaultProps = {
24609
24616
  // optional message
24610
24617
  message: null
24611
24618
  };
24612
- const styles$q = StyleSheet.create({
24619
+ const styles$r = StyleSheet.create({
24613
24620
  // Override the inherited width from the perseus paragraph class
24614
24621
  // 820 is minimum width for 420px editor and 400px canvas
24615
24622
  widthOverride: {
@@ -24654,7 +24661,7 @@ class Definition extends React.Component {
24654
24661
  }) => /*#__PURE__*/React.createElement(Popover, {
24655
24662
  content: /*#__PURE__*/React.createElement(PopoverContentCore, {
24656
24663
  color: "white",
24657
- style: styles$p.tooltipBody,
24664
+ style: styles$q.tooltipBody,
24658
24665
  closeButtonVisible: true
24659
24666
  }, /*#__PURE__*/React.createElement(Renderer, {
24660
24667
  apiOptions: this.props.apiOptions,
@@ -24685,7 +24692,7 @@ Definition.defaultProps = {
24685
24692
  togglePrompt: "define me",
24686
24693
  definition: "definition goes here"
24687
24694
  };
24688
- const styles$p = {
24695
+ const styles$q = {
24689
24696
  tooltipBody: {
24690
24697
  color: Color.offBlack,
24691
24698
  fontSize: 20,
@@ -24888,15 +24895,15 @@ class Explanation extends React.Component {
24888
24895
  const onClick = this._onClick;
24889
24896
  if (isMobile) {
24890
24897
  promptContainer = /*#__PURE__*/React.createElement("div", {
24891
- className: css(styles$o.linkContainer)
24898
+ className: css(styles$p.linkContainer)
24892
24899
  }, /*#__PURE__*/React.createElement("a", {
24893
- className: css(styles$o.mobileExplanationLink),
24900
+ className: css(styles$p.mobileExplanationLink),
24894
24901
  href: href,
24895
24902
  onClick: onClick,
24896
24903
  role: "button",
24897
24904
  "aria-expanded": this.state.expanded
24898
24905
  }, promptText), this.state.expanded && /*#__PURE__*/React.createElement("svg", {
24899
- className: css(styles$o.disclosureArrow)
24906
+ className: css(styles$p.disclosureArrow)
24900
24907
  }, /*#__PURE__*/React.createElement("polygon", {
24901
24908
  style: {
24902
24909
  fill: backgroundColor
@@ -24904,7 +24911,7 @@ class Explanation extends React.Component {
24904
24911
  points: `0,${arrowHeight} ` + `${arrowWidth},${arrowHeight} ` + `${arrowWidth / 2},0`
24905
24912
  })));
24906
24913
  } else {
24907
- const viewStyling = isArticle ? [styles$o.explanationLink, styles$o.articleLink] : [styles$o.explanationLink, styles$o.exerciseLink];
24914
+ const viewStyling = isArticle ? [styles$p.explanationLink, styles$p.articleLink] : [styles$p.explanationLink, styles$p.exerciseLink];
24908
24915
  promptContainer = /*#__PURE__*/React.createElement(Clickable, {
24909
24916
  onClick: onClick,
24910
24917
  "aria-expanded": this.state.expanded
@@ -24912,11 +24919,11 @@ class Explanation extends React.Component {
24912
24919
  style: viewStyling
24913
24920
  }, `[${promptText}]`));
24914
24921
  }
24915
- const expandedStyle = isMobile ? styles$o.contentExpandedMobile : styles$o.contentExpanded;
24922
+ const expandedStyle = isMobile ? styles$p.contentExpandedMobile : styles$p.contentExpanded;
24916
24923
  return /*#__PURE__*/React.createElement("div", {
24917
- className: css(styles$o.container)
24924
+ className: css(styles$p.container)
24918
24925
  }, promptContainer, this.state.expanded && /*#__PURE__*/React.createElement("div", {
24919
- className: css(styles$o.content, isMobile && styles$o.contentMobile, this.state.expanded && expandedStyle)
24926
+ className: css(styles$p.content, isMobile && styles$p.contentMobile, this.state.expanded && expandedStyle)
24920
24927
  // eslint-disable-next-line react/no-string-refs
24921
24928
  ,
24922
24929
  ref: "content"
@@ -24940,7 +24947,7 @@ const verticalContentPadding = 10;
24940
24947
  const arrowWidth = 30;
24941
24948
  const arrowHeight = 14;
24942
24949
  const backgroundColor = gray95;
24943
- const styles$o = StyleSheet.create({
24950
+ const styles$p = StyleSheet.create({
24944
24951
  container: {
24945
24952
  display: "inline",
24946
24953
  position: "relative"
@@ -25045,15 +25052,15 @@ class GradedGroupAnswerBar extends React.Component {
25045
25052
  onCheckAnswer,
25046
25053
  onNextQuestion
25047
25054
  } = this.props;
25048
- const answerBarStyle = _extends({}, styles$n.answerBar, {
25055
+ const answerBarStyle = _extends({}, styles$o.answerBar, {
25049
25056
  backgroundColor: answerBarState === "CORRECT" ? Color.offWhite : "white",
25050
25057
  // Center the "Correct!" message only when there's no next question
25051
25058
  justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
25052
25059
  });
25053
25060
  const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
25054
- style: styles$n.text
25061
+ style: styles$o.text
25055
25062
  }, /*#__PURE__*/React.createElement("span", {
25056
- style: styles$n.tryAgainIcon
25063
+ style: styles$o.tryAgainIcon
25057
25064
  }, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
25058
25065
  style: {
25059
25066
  marginLeft: 8
@@ -25072,7 +25079,7 @@ class GradedGroupAnswerBar extends React.Component {
25072
25079
  return /*#__PURE__*/React.createElement("div", {
25073
25080
  style: answerBarStyle
25074
25081
  }, /*#__PURE__*/React.createElement("span", {
25075
- style: styles$n.text
25082
+ style: styles$o.text
25076
25083
  }, /*#__PURE__*/React.createElement("span", {
25077
25084
  style: {
25078
25085
  fontSize: 28,
@@ -25094,7 +25101,7 @@ class GradedGroupAnswerBar extends React.Component {
25094
25101
  }
25095
25102
  }
25096
25103
  const fontSize = 17;
25097
- const styles$n = {
25104
+ const styles$o = {
25098
25105
  answerBar: {
25099
25106
  display: "flex",
25100
25107
  alignItems: "center",
@@ -25280,7 +25287,7 @@ class GradedGroup extends React.Component {
25280
25287
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
25281
25288
  gradeStatus = i18n._("Incorrect");
25282
25289
  }
25283
- const mobileClass = this.props.inGradedGroupSet ? css(styles$m.gradedGroupInSet) : css(styles$m.gradedGroup);
25290
+ const mobileClass = this.props.inGradedGroupSet ? css(styles$n.gradedGroupInSet) : css(styles$n.gradedGroup);
25284
25291
  const classes = classNames({
25285
25292
  [mobileClass]: apiOptions.isMobile,
25286
25293
  "perseus-graded-group": true,
@@ -25299,7 +25306,7 @@ class GradedGroup extends React.Component {
25299
25306
  return /*#__PURE__*/React.createElement("div", {
25300
25307
  className: classes
25301
25308
  }, !!this.props.title && /*#__PURE__*/React.createElement("div", {
25302
- className: css(styles$m.title)
25309
+ className: css(styles$n.title)
25303
25310
  }, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
25304
25311
  // eslint-disable-next-line react/no-string-refs
25305
25312
  ref: "renderer",
@@ -25331,7 +25338,7 @@ class GradedGroup extends React.Component {
25331
25338
  }, i18n._("Next question")), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
25332
25339
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
25333
25340
  tabIndex: "0",
25334
- className: css(styles$m.explanationTitle),
25341
+ className: css(styles$n.explanationTitle),
25335
25342
  onClick: () => this.setState({
25336
25343
  showHint: false
25337
25344
  }),
@@ -25363,7 +25370,7 @@ class GradedGroup extends React.Component {
25363
25370
  showHint: true
25364
25371
  });
25365
25372
  },
25366
- className: css(styles$m.showHintLink)
25373
+ className: css(styles$n.showHintLink)
25367
25374
  }, i18n._("Explain"))), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
25368
25375
  apiOptions: apiOptions,
25369
25376
  answerBarState: answerBarState,
@@ -25384,7 +25391,7 @@ GradedGroup.defaultProps = {
25384
25391
  const traverseChildWidgets$2 = function traverseChildWidgets(props, traverseRenderer) {
25385
25392
  return _.extend({}, props, traverseRenderer(props));
25386
25393
  };
25387
- const styles$m = StyleSheet.create({
25394
+ const styles$n = StyleSheet.create({
25388
25395
  gradedGroupInSet: {
25389
25396
  // Reset a few desktop-only styles that come from graded-group.less
25390
25397
  marginLeft: 0,
@@ -25457,18 +25464,18 @@ class Indicators extends React.Component {
25457
25464
  return /*#__PURE__*/React.createElement("ul", {
25458
25465
  // reduntantly add class name for use in .less files--
25459
25466
  // the styles object key gets hashed
25460
- className: classNames(css(styles$l.indicatorContainer), "indicatorContainer")
25467
+ className: classNames(css(styles$m.indicatorContainer), "indicatorContainer")
25461
25468
  }, this.props.gradedGroups.map(({
25462
25469
  title
25463
25470
  }, i) => /*#__PURE__*/React.createElement("li", {
25464
- className: css(styles$l.indicator),
25471
+ className: css(styles$m.indicator),
25465
25472
  key: title
25466
25473
  }, /*#__PURE__*/React.createElement(Clickable, {
25467
25474
  role: "button",
25468
25475
  "aria-label": i18n._("Skip to %(title)s", {
25469
25476
  title
25470
25477
  }),
25471
- style: styles$l.indicatorButton,
25478
+ style: styles$m.indicatorButton,
25472
25479
  onClick: () => this.props.onChangeCurrentGroup(i),
25473
25480
  onKeyDown: e => this.handleKeyDown(e, i)
25474
25481
  }, ({
@@ -25476,9 +25483,9 @@ class Indicators extends React.Component {
25476
25483
  focused,
25477
25484
  pressed
25478
25485
  }) => /*#__PURE__*/React.createElement(View, {
25479
- style: [styles$l.indicatorDot, (hovered || focused || pressed) && styles$l.indicatorDotFocused]
25486
+ style: [styles$m.indicatorDot, (hovered || focused || pressed) && styles$m.indicatorDotFocused]
25480
25487
  }, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
25481
- style: styles$l.indicatorDotActive
25488
+ style: styles$m.indicatorDotActive
25482
25489
  }, /*#__PURE__*/React.createElement("span", {
25483
25490
  className: css(a11y.srOnly)
25484
25491
  }, i18n._("Current"))))))));
@@ -25544,7 +25551,7 @@ class GradedGroupSet extends React.Component {
25544
25551
  } = getDependencies();
25545
25552
  if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
25546
25553
  return /*#__PURE__*/React.createElement("div", {
25547
- className: css(styles$l.container)
25554
+ className: css(styles$m.container)
25548
25555
  }, this.props.gradedGroups.map((gradedGroup, i) => {
25549
25556
  return (
25550
25557
  /*#__PURE__*/
@@ -25567,13 +25574,13 @@ class GradedGroupSet extends React.Component {
25567
25574
  const numGroups = this.props.gradedGroups.length;
25568
25575
  const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
25569
25576
  return /*#__PURE__*/React.createElement("div", {
25570
- className: css(styles$l.container)
25577
+ className: css(styles$m.container)
25571
25578
  }, /*#__PURE__*/React.createElement("div", {
25572
- className: css(styles$l.top)
25579
+ className: css(styles$m.top)
25573
25580
  }, /*#__PURE__*/React.createElement("div", {
25574
- className: css(styles$l.title)
25581
+ className: css(styles$m.title)
25575
25582
  }, currentGroup.title), /*#__PURE__*/React.createElement("div", {
25576
- className: css(styles$l.spacer)
25583
+ className: css(styles$m.spacer)
25577
25584
  }), /*#__PURE__*/React.createElement(Indicators, {
25578
25585
  currentGroup: this.state.currentGroup,
25579
25586
  gradedGroups: this.props.gradedGroups,
@@ -25615,7 +25622,7 @@ var GradedGroupSet$1 = {
25615
25622
  tracking: "all",
25616
25623
  isLintable: true
25617
25624
  };
25618
- const styles$l = StyleSheet.create({
25625
+ const styles$m = StyleSheet.create({
25619
25626
  top: {
25620
25627
  display: "flex",
25621
25628
  flexDirection: "row"
@@ -25720,7 +25727,7 @@ class ButtonGroup extends React.Component {
25720
25727
  id: "" + i,
25721
25728
  ref: "button" + i,
25722
25729
  key: "" + i,
25723
- className: css(styles$k.buttonStyle, button.value === value && styles$k.selectedStyle),
25730
+ className: css(styles$l.buttonStyle, button.value === value && styles$l.selectedStyle),
25724
25731
  onClick: () => this.toggleSelect(button.value)
25725
25732
  }, button.content || "" + button.value);
25726
25733
  });
@@ -25737,7 +25744,7 @@ ButtonGroup.defaultProps = {
25737
25744
  value: null,
25738
25745
  allowEmpty: true
25739
25746
  };
25740
- const styles$k = StyleSheet.create({
25747
+ const styles$l = StyleSheet.create({
25741
25748
  buttonStyle: {
25742
25749
  backgroundColor: "white",
25743
25750
  border: "1px solid #ccc",
@@ -28239,18 +28246,51 @@ const SegmentGraph = props => {
28239
28246
  })));
28240
28247
  };
28241
28248
  const SegmentView = props => {
28242
- const [pt1, pt2] = props.segment;
28249
+ const {
28250
+ onMoveSegment,
28251
+ segment: [pt1, pt2]
28252
+ } = props;
28243
28253
  const midpoint = vec.midpoint(pt1, pt2);
28244
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Line$3.Segment, {
28245
- point1: pt1,
28246
- point2: pt2
28247
- }), /*#__PURE__*/React.createElement(MovablePoint$5, {
28254
+ const segment = useRef(null);
28255
+ const {
28256
+ dragging: isDraggingSegment
28257
+ } = useMovable({
28258
+ gestureTarget: segment,
28248
28259
  point: midpoint,
28249
- color: Color.blue,
28250
28260
  onMove: newPoint => {
28251
- props.onMoveSegment(vec.sub(newPoint, midpoint));
28261
+ onMoveSegment(vec.sub(newPoint, midpoint));
28262
+ },
28263
+ constrain: p => p
28264
+ });
28265
+ const {
28266
+ viewTransform,
28267
+ userTransform
28268
+ } = useTransformContext();
28269
+ const transform = vec.matrixMult(viewTransform, userTransform);
28270
+ const scaledPoint1 = vec.transform(pt1, transform);
28271
+ const scaledPoint2 = vec.transform(pt2, transform);
28272
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("g", {
28273
+ ref: segment,
28274
+ tabIndex: 0,
28275
+ className: "movable-segment",
28276
+ style: {
28277
+ cursor: isDraggingSegment ? "grabbing" : "grab"
28252
28278
  }
28253
- }), /*#__PURE__*/React.createElement(MovablePoint$5, {
28279
+ }, /*#__PURE__*/React.createElement(SVGLine, {
28280
+ start: scaledPoint1,
28281
+ end: scaledPoint2,
28282
+ style: {
28283
+ stroke: "transparent",
28284
+ strokeWidth: 30
28285
+ }
28286
+ }), /*#__PURE__*/React.createElement(SVGLine, {
28287
+ start: scaledPoint1,
28288
+ end: scaledPoint2,
28289
+ style: {
28290
+ stroke: "var(--mafs-segment-stroke-color)",
28291
+ strokeWidth: "var(--mafs-segment-stroke-weight)"
28292
+ }
28293
+ })), /*#__PURE__*/React.createElement(MovablePoint$5, {
28254
28294
  point: pt1,
28255
28295
  color: Color.blue,
28256
28296
  onMove: newPoint => {
@@ -28264,6 +28304,20 @@ const SegmentView = props => {
28264
28304
  }
28265
28305
  }));
28266
28306
  };
28307
+ function SVGLine(props) {
28308
+ const {
28309
+ start,
28310
+ end,
28311
+ style
28312
+ } = props;
28313
+ return /*#__PURE__*/React.createElement("line", {
28314
+ x1: start[0],
28315
+ y1: start[1],
28316
+ x2: end[0],
28317
+ y2: end[1],
28318
+ style: style
28319
+ });
28320
+ }
28267
28321
 
28268
28322
  const renderLineLabel = (n, [min, max]) => n !== -1 && n !== min && n !== max;
28269
28323
  const axisOptions = (props, index) => ({
@@ -28433,7 +28487,7 @@ const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
28433
28487
  width: "24",
28434
28488
  height: "24",
28435
28489
  viewBox: "0 0 24 24",
28436
- className: css(styles$j.icon)
28490
+ className: css(styles$k.icon)
28437
28491
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
28438
28492
  id: "a",
28439
28493
  d: "M7.401 10.035c-1.424.748-2.599 1.905-3.544 " + "3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 " + "12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 " + "1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-" + "3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 " + "0 0 0 0 6z"
@@ -28464,7 +28518,7 @@ const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
28464
28518
  width: "24",
28465
28519
  height: "24",
28466
28520
  viewBox: "0 0 24 24",
28467
- className: css(styles$j.icon)
28521
+ className: css(styles$k.icon)
28468
28522
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
28469
28523
  id: "a",
28470
28524
  d: "M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 " + "7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 " + "1.028c-.945-1.574-2.12-2.73-3.544-3.48.258." + "604.401 1.268.401 1.966 0 1.02-.305 " + "1.967-.828 2.757l2.535 2.536a1 1 0 0 " + "1-1.414 1.414l-12-12a1 1 0 0 1 " + "1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 " + "0-4.001-4.001l4 4.001zM6.072 8.486l2.976 " + "2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 " + "0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 " + "3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 " + "2.363-3.085 3.929-4z"
@@ -28498,20 +28552,20 @@ const HUD = ({
28498
28552
  let state;
28499
28553
  let icon;
28500
28554
  if (enabled) {
28501
- state = styles$j.enabled;
28555
+ state = styles$k.enabled;
28502
28556
  icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
28503
28557
  } else {
28504
- state = styles$j.disabled;
28558
+ state = styles$k.disabled;
28505
28559
  icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
28506
28560
  }
28507
28561
  return /*#__PURE__*/React.createElement("button", {
28508
- className: css(styles$j.hud, _fixedPosition && styles$j.hudFixedPosition, state),
28562
+ className: css(styles$k.hud, _fixedPosition && styles$k.hudFixedPosition, state),
28509
28563
  onClick: e => {
28510
28564
  onClick();
28511
28565
  }
28512
28566
  }, icon, message);
28513
28567
  };
28514
- const styles$j = StyleSheet.create({
28568
+ const styles$k = StyleSheet.create({
28515
28569
  hud: {
28516
28570
  boxSizing: "border-box",
28517
28571
  height: 36,
@@ -28575,7 +28629,7 @@ const triangleBeforeAfter = {
28575
28629
  top: "0",
28576
28630
  width: "0"
28577
28631
  };
28578
- const styles$i = StyleSheet.create({
28632
+ const styles$j = StyleSheet.create({
28579
28633
  infoTip: {
28580
28634
  display: "inline-block",
28581
28635
  marginLeft: "5px",
@@ -28614,7 +28668,6 @@ const styles$i = StyleSheet.create({
28614
28668
  width: "240px"
28615
28669
  }
28616
28670
  });
28617
- const questionMark = "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBB" + "ZG9iZSBJbWFnZVJlYWR5ccllPAAAA3NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/" + "eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+" + "IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2Jl" + "IFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAg" + "ICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5" + "LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9" + "IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHht" + "bG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3Vy" + "Y2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHht" + "cE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo2N2M3NTAxYS04YmVlLTQ0M2Mt" + "YmRiNS04OGM2N2IxN2NhYzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUJCRTk4" + "Qjc4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5p" + "aWQ6OUJCRTk4QjY4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcDpDcmVhdG9yVG9v" + "bD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRG" + "cm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NGE5ZDI0OTMtODk1NC00OGFkLTlh" + "MTgtZDAwM2MwYWNjNDJlIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY3Yzc1MDFh" + "LThiZWUtNDQzYy1iZGI1LTg4YzY3YjE3Y2FjMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4g" + "PC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pqm89uYAAADM" + "SURBVHjaXJA9DoJAEIUH1M4TUHIFsCMGen9OwCGw1YRGW2ntKel0exsojHIBC0ouQAyU" + "viFDstmXfNmZeS+zm7XSNCXRFiRgJf0bXIHixpbhGdxBBJYC1w/xaA424MhNEATkui71" + "fU9KqfEU78UbD9PdbJRlOdae55GmhIP+1NV1TcMwkOM41DSNHvRtMhTHMRVFQW3b6mOL" + "gx99kue5GRp/gIOZuZGvNpTNwjD8oliANU+qqqKu6/TQBdymN57AHjzBT+B6Jx79BRgA" + "vc49kQA4yxgAAAAASUVORK5CYII=";
28618
28671
  class InfoTip$1 extends React.Component {
28619
28672
  constructor(...args) {
28620
28673
  super(...args);
@@ -28634,23 +28687,22 @@ class InfoTip$1 extends React.Component {
28634
28687
  }
28635
28688
  render() {
28636
28689
  return /*#__PURE__*/React.createElement("div", {
28637
- className: css(styles$i.infoTip)
28638
- }, /*#__PURE__*/React.createElement("img", {
28639
- alt: "",
28640
- width: 10,
28641
- height: 10,
28642
- src: questionMark,
28690
+ className: css(styles$j.infoTip)
28691
+ }, /*#__PURE__*/React.createElement(View, {
28643
28692
  onMouseEnter: this.handleMouseEnter,
28644
28693
  onMouseLeave: this.handleMouseLeave
28645
- }), /*#__PURE__*/React.createElement("div", {
28646
- className: css(styles$i.infoTipContainer),
28694
+ }, /*#__PURE__*/React.createElement(PhosphorIcon, {
28695
+ size: "small",
28696
+ icon: questionIcon
28697
+ })), /*#__PURE__*/React.createElement("div", {
28698
+ className: css(styles$j.infoTipContainer),
28647
28699
  style: {
28648
28700
  display: this.state.hover ? "block" : "none"
28649
28701
  }
28650
28702
  }, /*#__PURE__*/React.createElement("div", {
28651
- className: css(styles$i.infoTipTriangle)
28703
+ className: css(styles$j.infoTipTriangle)
28652
28704
  }), /*#__PURE__*/React.createElement("div", {
28653
- className: css(styles$i.verticalShadow, styles$i.infoTipContentContainer)
28705
+ className: css(styles$j.verticalShadow, styles$j.infoTipContentContainer)
28654
28706
  }, this.props.children)));
28655
28707
  }
28656
28708
  }
@@ -28725,7 +28777,7 @@ class MultiButtonGroup extends React.Component {
28725
28777
  id: "" + i,
28726
28778
  key: "" + i,
28727
28779
  ref: "button" + i,
28728
- className: css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
28780
+ className: css(styles$i.buttonStyle, selected && styles$i.selectedStyle),
28729
28781
  onClick: () => this.toggleSelect(button.value)
28730
28782
  }, button.content || "" + button.value);
28731
28783
  });
@@ -28741,7 +28793,7 @@ MultiButtonGroup.defaultProps = {
28741
28793
  values: [],
28742
28794
  allowEmpty: true
28743
28795
  };
28744
- const styles$h = StyleSheet.create({
28796
+ const styles$i = StyleSheet.create({
28745
28797
  buttonStyle: {
28746
28798
  backgroundColor: "white",
28747
28799
  border: "1px solid #ccc",
@@ -28999,11 +29051,12 @@ const PropCheckBox = createReactClass({
28999
29051
  },
29000
29052
  render: function () {
29001
29053
  const propName = this.propName();
29002
- return /*#__PURE__*/React.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React.createElement("input", {
29003
- type: "checkbox",
29054
+ return /*#__PURE__*/React.createElement("label", {
29055
+ className: css(styles$h.labeledCheckbox)
29056
+ }, this._labelAlignLeft() && /*#__PURE__*/React.createElement(LabelSmall, null, this.props.label), /*#__PURE__*/React.createElement(Checkbox, {
29004
29057
  checked: this.props[propName],
29005
29058
  onChange: this.toggle
29006
- }), !this._labelAlignLeft() && this.props.label);
29059
+ }), !this._labelAlignLeft() && /*#__PURE__*/React.createElement(LabelSmall, null, this.props.label));
29007
29060
  },
29008
29061
  toggle: function () {
29009
29062
  const propName = this.propName();
@@ -29012,6 +29065,13 @@ const PropCheckBox = createReactClass({
29012
29065
  this.props.onChange(changes);
29013
29066
  }
29014
29067
  });
29068
+ const styles$h = StyleSheet.create({
29069
+ labeledCheckbox: {
29070
+ display: "flex",
29071
+ flexDirection: "row",
29072
+ alignItems: "center"
29073
+ }
29074
+ });
29015
29075
 
29016
29076
  const truth = () => true;
29017
29077
 
@@ -41179,7 +41239,7 @@ const init = function init(options) {
41179
41239
 
41180
41240
  // This file is processed by a Rollup plugin (replace) to inject the production
41181
41241
  const libName = "@khanacademy/perseus";
41182
- const libVersion = "20.0.2";
41242
+ const libVersion = "20.1.0";
41183
41243
  addLibraryVersionToPerseusDebug(libName, libVersion);
41184
41244
 
41185
41245
  const apiVersion = {