@khanacademy/perseus-editor 6.4.1 → 6.5.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/index.js CHANGED
@@ -67,7 +67,7 @@ var trashIcon__default = /*#__PURE__*/_interopDefaultLegacy(trashIcon);
67
67
 
68
68
  // This file is processed by a Rollup plugin (replace) to inject the production
69
69
  const libName = "@khanacademy/perseus-editor";
70
- const libVersion = "6.4.1";
70
+ const libVersion = "6.5.0";
71
71
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
72
72
 
73
73
  function _extends() {
@@ -262,13 +262,13 @@ class SectionControlButton extends React__namespace.Component {
262
262
  role: "button",
263
263
  hideDefaultFocusRing: true,
264
264
  "aria-label": title,
265
- style: styles$y.button
265
+ style: styles$z.button
266
266
  }, _ref => {
267
267
  return /*#__PURE__*/React__namespace.createElement(InlineIcon$b, icon);
268
268
  });
269
269
  }
270
270
  }
271
- const styles$y = aphrodite.StyleSheet.create({
271
+ const styles$z = aphrodite.StyleSheet.create({
272
272
  button: {
273
273
  backgroundColor: wonderBlocksTokens.color.gold,
274
274
  margin: 2,
@@ -20768,6 +20768,27 @@ class WidgetSelect extends React__namespace.Component {
20768
20768
  }
20769
20769
  }
20770
20770
 
20771
+ /**
20772
+ * Displays a caret in either expanded or collapsed state. For use in headings
20773
+ * that collapse a region.
20774
+ */
20775
+ function ToggleableCaret(props) {
20776
+ const iconStyle = props.isExpanded ? styles$y.expanded : styles$y.collapsed;
20777
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
20778
+ icon: caretRight__default["default"],
20779
+ style: iconStyle
20780
+ });
20781
+ }
20782
+ const styles$y = aphrodite.StyleSheet.create({
20783
+ collapsed: {
20784
+ transition: ".15s"
20785
+ },
20786
+ expanded: {
20787
+ transform: "rotate(90deg)",
20788
+ transition: ".15s"
20789
+ }
20790
+ });
20791
+
20771
20792
  /**
20772
20793
  * Displays a collapsable list of TeX rendering errors.
20773
20794
  */
@@ -20787,15 +20808,13 @@ class TexErrorView extends React__namespace.Component {
20787
20808
  const {
20788
20809
  showErrors
20789
20810
  } = this.state;
20790
- const iconStyle = showErrors ? styles$x.iconExpanded : styles$x.iconCollapsed;
20791
20811
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
20792
20812
  style: styles$x.errorContainer
20793
20813
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
20794
20814
  style: styles$x.title,
20795
20815
  onClick: this.handleToggleTexErrors
20796
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
20797
- icon: caretRight__default["default"],
20798
- style: iconStyle
20816
+ }, /*#__PURE__*/React__namespace.createElement(ToggleableCaret, {
20817
+ isExpanded: showErrors
20799
20818
  }), "\xA0 TeX Errors (", errorList.length, ")"), showErrors && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
20800
20819
  style: styles$x.errorExplanation
20801
20820
  }, "If your math doesn't display correctly, these errors might help you troubleshoot. Message #content-kitchen for help."), showErrors && errorList.map((e, index) => /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
@@ -20828,13 +20847,6 @@ const styles$x = aphrodite.StyleSheet.create({
20828
20847
  },
20829
20848
  error: {
20830
20849
  padding: "4px 10px"
20831
- },
20832
- iconCollapsed: {
20833
- transition: ".15s"
20834
- },
20835
- iconExpanded: {
20836
- transform: "rotate(90deg)",
20837
- transition: ".15s"
20838
20850
  }
20839
20851
  });
20840
20852
 
@@ -29664,6 +29676,31 @@ const defaultBackgroundImage$1 = {
29664
29676
  function numSteps(range, step) {
29665
29677
  return Math.floor((range[1] - range[0]) / step);
29666
29678
  }
29679
+ function Heading(_ref) {
29680
+ let {
29681
+ title,
29682
+ isOpen,
29683
+ onToggle
29684
+ } = _ref;
29685
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
29686
+ style: {
29687
+ flexDirection: "row",
29688
+ justifyContent: "space-between",
29689
+ backgroundColor: wonderBlocksTokens.color.offBlack8,
29690
+ padding: wonderBlocksTokens.spacing.xSmall_8,
29691
+ marginTop: wonderBlocksTokens.spacing.small_12,
29692
+ // NOTE(jeremy): This is the inverse of the @editorPadding CSS
29693
+ // variable found in perseus-editor.less. For now, it must
29694
+ // match otherwise there's a gap from this header to the edge
29695
+ // of the editor borders.
29696
+ marginInline: -10,
29697
+ cursor: "pointer"
29698
+ },
29699
+ onClick: () => onToggle?.(!isOpen)
29700
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, null, title), /*#__PURE__*/React__namespace.createElement(ToggleableCaret, {
29701
+ isExpanded: isOpen
29702
+ }));
29703
+ }
29667
29704
  class InteractiveGraphSettings extends React__namespace.Component {
29668
29705
  _isMounted = false;
29669
29706
  bgUrlRef = /*#__PURE__*/React__namespace.createRef();
@@ -29684,7 +29721,10 @@ class InteractiveGraphSettings extends React__namespace.Component {
29684
29721
  }
29685
29722
  constructor(props) {
29686
29723
  super(props);
29687
- this.state = InteractiveGraphSettings.stateFromProps(props);
29724
+ this.state = {
29725
+ isExpanded: true,
29726
+ ...InteractiveGraphSettings.stateFromProps(props)
29727
+ };
29688
29728
  }
29689
29729
  static defaultProps = {
29690
29730
  box: [perseus.interactiveSizes.defaultBoxSizeSmall, perseus.interactiveSizes.defaultBoxSizeSmall],
@@ -29962,7 +30002,13 @@ class InteractiveGraphSettings extends React__namespace.Component {
29962
30002
  };
29963
30003
 
29964
30004
  render() {
29965
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
30005
+ return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
30006
+ title: "Common Graph Settings",
30007
+ isOpen: this.state.isExpanded,
30008
+ onToggle: () => this.setState({
30009
+ isExpanded: !this.state.isExpanded
30010
+ })
30011
+ }), this.state.isExpanded && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement("div", {
29966
30012
  className: "graph-settings"
29967
30013
  }, /*#__PURE__*/React__namespace.createElement("div", {
29968
30014
  className: "perseus-widget-row"
@@ -30149,7 +30195,7 @@ class InteractiveGraphSettings extends React__namespace.Component {
30149
30195
  key: value,
30150
30196
  value: `${value}`,
30151
30197
  label: `${value}`
30152
- })))))));
30198
+ }))))))));
30153
30199
  }
30154
30200
  }
30155
30201
  const styles$o = aphrodite.StyleSheet.create({
@@ -30373,6 +30419,7 @@ const styles$l = aphrodite.StyleSheet.create({
30373
30419
  const CoordinatePairInput = props => {
30374
30420
  const {
30375
30421
  coord,
30422
+ error,
30376
30423
  onChangeProps
30377
30424
  } = props;
30378
30425
 
@@ -30406,7 +30453,7 @@ const CoordinatePairInput = props => {
30406
30453
  coord: newCoords
30407
30454
  });
30408
30455
  }
30409
- return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30456
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30410
30457
  style: [styles$k.row, styles$k.spaceUnder]
30411
30458
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
30412
30459
  htmlFor: xCoordId,
@@ -30417,7 +30464,7 @@ const CoordinatePairInput = props => {
30417
30464
  type: "number",
30418
30465
  value: coordState[0],
30419
30466
  onChange: newValue => handleCoordChange(newValue, 0),
30420
- style: styles$k.textField
30467
+ style: [styles$k.textField, error ? styles$k.errorField : undefined]
30421
30468
  }), /*#__PURE__*/React__namespace.createElement(Strut, {
30422
30469
  size: wonderBlocksTokens.spacing.medium_16
30423
30470
  }), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
@@ -30429,8 +30476,8 @@ const CoordinatePairInput = props => {
30429
30476
  type: "number",
30430
30477
  value: coordState[1],
30431
30478
  onChange: newValue => handleCoordChange(newValue, 1),
30432
- style: styles$k.textField
30433
- }));
30479
+ style: [styles$k.textField, error ? styles$k.errorField : undefined]
30480
+ })));
30434
30481
  };
30435
30482
  const styles$k = aphrodite.StyleSheet.create({
30436
30483
  row: {
@@ -30445,6 +30492,10 @@ const styles$k = aphrodite.StyleSheet.create({
30445
30492
  },
30446
30493
  textField: {
30447
30494
  width: wonderBlocksTokens.spacing.xxxLarge_64
30495
+ },
30496
+ errorField: {
30497
+ borderColor: wonderBlocksTokens.color.red,
30498
+ backgroundColor: wonderBlocksTokens.color.fadedRed8
30448
30499
  }
30449
30500
  });
30450
30501
 
@@ -30536,6 +30587,7 @@ const DefiningPointSettings = props => {
30536
30587
  filled = true,
30537
30588
  label,
30538
30589
  showPoint = "false",
30590
+ error,
30539
30591
  onChangeProps,
30540
30592
  onTogglePoint
30541
30593
  } = props;
@@ -30562,6 +30614,7 @@ const DefiningPointSettings = props => {
30562
30614
  }))
30563
30615
  }, /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
30564
30616
  coord: coord,
30617
+ error: !!error,
30565
30618
  onChangeProps: onChangeProps
30566
30619
  }), onTogglePoint && /*#__PURE__*/React__namespace.createElement(LabeledSwitch, {
30567
30620
  label: "show point on graph",
@@ -30662,6 +30715,7 @@ const styles$f = aphrodite.StyleSheet.create({
30662
30715
  }
30663
30716
  });
30664
30717
 
30718
+ const lengthZeroStr = "The line cannot have length 0.";
30665
30719
  const LockedLineSettings = props => {
30666
30720
  const {
30667
30721
  kind,
@@ -30683,6 +30737,7 @@ const LockedLineSettings = props => {
30683
30737
  const capitalizeKind = kind.charAt(0).toUpperCase() + kind.slice(1);
30684
30738
  const lineLabel = `${capitalizeKind} (${point1.coord[0]},
30685
30739
  ${point1.coord[1]}), (${point2.coord[0]}, ${point2.coord[1]})`;
30740
+ const isInvalid = point1.coord[0] === point2.coord[0] && point1.coord[1] === point2.coord[1];
30686
30741
  function handleChangePoint(newPointProps, index) {
30687
30742
  const newPoints = [...points];
30688
30743
  newPoints[index] = {
@@ -30735,12 +30790,12 @@ const LockedLineSettings = props => {
30735
30790
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30736
30791
  value: "line",
30737
30792
  label: "line"
30738
- }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30739
- value: "segment",
30740
- label: "segment"
30741
30793
  }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30742
30794
  value: "ray",
30743
30795
  label: "ray"
30796
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30797
+ value: "segment",
30798
+ label: "segment"
30744
30799
  }))), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30745
30800
  style: [styles$e.row, styles$e.spaceUnder]
30746
30801
  }, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
@@ -30770,9 +30825,12 @@ const LockedLineSettings = props => {
30770
30825
  }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30771
30826
  value: "dashed",
30772
30827
  label: "dashed"
30773
- })))), /*#__PURE__*/React__namespace.createElement(DefiningPointSettings, _extends({
30828
+ })))), isInvalid && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
30829
+ style: styles$e.errorText
30830
+ }, lengthZeroStr), /*#__PURE__*/React__namespace.createElement(DefiningPointSettings, _extends({
30774
30831
  label: "Point 1",
30775
- showPoint: showPoint1
30832
+ showPoint: showPoint1,
30833
+ error: isInvalid ? lengthZeroStr : null
30776
30834
  }, point1, {
30777
30835
  onTogglePoint: newValue => onChangeProps({
30778
30836
  showPoint1: newValue
@@ -30780,7 +30838,8 @@ const LockedLineSettings = props => {
30780
30838
  onChangeProps: newProps => handleChangePoint(newProps, 0)
30781
30839
  })), /*#__PURE__*/React__namespace.createElement(DefiningPointSettings, _extends({
30782
30840
  label: "Point 2",
30783
- showPoint: showPoint2
30841
+ showPoint: showPoint2,
30842
+ error: isInvalid ? lengthZeroStr : null
30784
30843
  }, point2, {
30785
30844
  onTogglePoint: newValue => onChangeProps({
30786
30845
  showPoint2: newValue
@@ -30807,6 +30866,9 @@ const styles$e = aphrodite.StyleSheet.create({
30807
30866
  selectMarginOffset: {
30808
30867
  // Align with the point settings accordions.
30809
30868
  marginInlineEnd: -wonderBlocksTokens.spacing.xxxSmall_4
30869
+ },
30870
+ errorText: {
30871
+ color: wonderBlocksTokens.color.red
30810
30872
  }
30811
30873
  });
30812
30874
 
@@ -30963,7 +31025,8 @@ function getDefaultFigureForType(type) {
30963
31025
  const LockedFiguresSection = props => {
30964
31026
  // Keep track of all figures' accordions' expanded states for the
30965
31027
  // expand/collapse all button. Set the whole array to false initially.
30966
- const [expandedStates, setExpandedStates] = React__namespace.useState(Array(props.figures?.length).fill(false));
31028
+ const collapsedStateArray = Array((props.figures ?? []).length).fill(false);
31029
+ const [expandedStates, setExpandedStates] = React__namespace.useState(collapsedStateArray);
30967
31030
  const uniqueId = wonderBlocksCore.useUniqueIdWithMock().get("locked-figures-section");
30968
31031
  const {
30969
31032
  figures,