@khanacademy/perseus-editor 6.4.1 → 6.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,7 @@
2
2
  import type { LockedPointType } from "@khanacademy/perseus";
3
3
  type Props = {
4
4
  coord: [number, number];
5
+ error?: boolean;
5
6
  onChangeProps: (newProps: Partial<LockedPointType>) => void;
6
7
  };
7
8
  declare const CoordinatePairInput: (props: Props) => JSX.Element;
@@ -11,6 +11,10 @@ export type Props = AccordionProps & LockedPointType & {
11
11
  * Whether the extra point settings are toggled open.
12
12
  */
13
13
  showPoint?: boolean;
14
+ /**
15
+ * Optional error message to display.
16
+ */
17
+ error?: string | null;
14
18
  /**
15
19
  * Called when the extra settings toggle switch is changed.
16
20
  */
@@ -66,6 +66,7 @@ type Props = {
66
66
  onChange: (arg1: Partial<Props>) => void;
67
67
  };
68
68
  type State = {
69
+ isExpanded: boolean;
69
70
  labelsTextbox: ReadonlyArray<string>;
70
71
  gridStepTextbox: [x: number, y: number];
71
72
  snapStepTextbox: [x: number, y: number];
@@ -78,13 +79,21 @@ declare class InteractiveGraphSettings extends React.Component<Props, State> {
78
79
  bgUrlRef: React.RefObject<HTMLInputElement>;
79
80
  labelXRef: React.RefObject<HTMLInputElement>;
80
81
  labelYRef: React.RefObject<HTMLInputElement>;
81
- static stateFromProps(props: any): {
82
- labelsTextbox: any;
83
- gridStepTextbox: any;
84
- snapStepTextbox: any;
85
- stepTextbox: any;
86
- rangeTextbox: any;
87
- backgroundImage: any;
82
+ static stateFromProps(props: Props): {
83
+ labelsTextbox: readonly string[];
84
+ gridStepTextbox: [x: number, y: number];
85
+ snapStepTextbox: [x: number, y: number];
86
+ stepTextbox: [x: number, y: number];
87
+ rangeTextbox: [x: Range, y: Range];
88
+ backgroundImage: {
89
+ url: string | null | undefined;
90
+ width?: number | undefined;
91
+ height?: number | undefined;
92
+ top?: number | undefined;
93
+ left?: number | undefined;
94
+ scale?: string | number | undefined;
95
+ bottom?: number | undefined;
96
+ };
88
97
  };
89
98
  constructor(props: Props);
90
99
  static defaultProps: {
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ type Props = {
3
+ isExpanded: boolean;
4
+ };
5
+ /**
6
+ * Displays a caret in either expanded or collapsed state. For use in headings
7
+ * that collapse a region.
8
+ */
9
+ declare function ToggleableCaret(props: Props): JSX.Element;
10
+ export default ToggleableCaret;
package/dist/es/index.js CHANGED
@@ -29,7 +29,7 @@ import trashIcon from '@phosphor-icons/core/bold/trash-bold.svg';
29
29
 
30
30
  // This file is processed by a Rollup plugin (replace) to inject the production
31
31
  const libName = "@khanacademy/perseus-editor";
32
- const libVersion = "6.4.1";
32
+ const libVersion = "6.5.1";
33
33
  addLibraryVersionToPerseusDebug(libName, libVersion);
34
34
 
35
35
  function _extends() {
@@ -219,7 +219,7 @@ class SectionControlButton extends React.Component {
219
219
  role: "button",
220
220
  hideDefaultFocusRing: true,
221
221
  "aria-label": title,
222
- style: styles$y.button
222
+ style: styles$z.button
223
223
  }, ({
224
224
  hovered,
225
225
  focused,
@@ -227,7 +227,7 @@ class SectionControlButton extends React.Component {
227
227
  }) => /*#__PURE__*/React.createElement(InlineIcon$b, icon));
228
228
  }
229
229
  }
230
- const styles$y = StyleSheet.create({
230
+ const styles$z = StyleSheet.create({
231
231
  button: {
232
232
  backgroundColor: color.gold,
233
233
  margin: 2,
@@ -20727,6 +20727,27 @@ class WidgetSelect extends React.Component {
20727
20727
  }
20728
20728
  }
20729
20729
 
20730
+ /**
20731
+ * Displays a caret in either expanded or collapsed state. For use in headings
20732
+ * that collapse a region.
20733
+ */
20734
+ function ToggleableCaret(props) {
20735
+ const iconStyle = props.isExpanded ? styles$y.expanded : styles$y.collapsed;
20736
+ return /*#__PURE__*/React.createElement(PhosphorIcon, {
20737
+ icon: caretRight,
20738
+ style: iconStyle
20739
+ });
20740
+ }
20741
+ const styles$y = StyleSheet.create({
20742
+ collapsed: {
20743
+ transition: ".15s"
20744
+ },
20745
+ expanded: {
20746
+ transform: "rotate(90deg)",
20747
+ transition: ".15s"
20748
+ }
20749
+ });
20750
+
20730
20751
  /**
20731
20752
  * Displays a collapsable list of TeX rendering errors.
20732
20753
  */
@@ -20749,15 +20770,13 @@ class TexErrorView extends React.Component {
20749
20770
  const {
20750
20771
  showErrors
20751
20772
  } = this.state;
20752
- const iconStyle = showErrors ? styles$x.iconExpanded : styles$x.iconCollapsed;
20753
20773
  return /*#__PURE__*/React.createElement(View, {
20754
20774
  style: styles$x.errorContainer
20755
20775
  }, /*#__PURE__*/React.createElement(View, {
20756
20776
  style: styles$x.title,
20757
20777
  onClick: this.handleToggleTexErrors
20758
- }, /*#__PURE__*/React.createElement(PhosphorIcon, {
20759
- icon: caretRight,
20760
- style: iconStyle
20778
+ }, /*#__PURE__*/React.createElement(ToggleableCaret, {
20779
+ isExpanded: showErrors
20761
20780
  }), "\xA0 TeX Errors (", errorList.length, ")"), showErrors && /*#__PURE__*/React.createElement(View, {
20762
20781
  style: styles$x.errorExplanation
20763
20782
  }, "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.createElement(View, {
@@ -20790,13 +20809,6 @@ const styles$x = StyleSheet.create({
20790
20809
  },
20791
20810
  error: {
20792
20811
  padding: "4px 10px"
20793
- },
20794
- iconCollapsed: {
20795
- transition: ".15s"
20796
- },
20797
- iconExpanded: {
20798
- transform: "rotate(90deg)",
20799
- transition: ".15s"
20800
20812
  }
20801
20813
  });
20802
20814
 
@@ -29584,6 +29596,30 @@ const defaultBackgroundImage$1 = {
29584
29596
  function numSteps(range, step) {
29585
29597
  return Math.floor((range[1] - range[0]) / step);
29586
29598
  }
29599
+ function Heading({
29600
+ title,
29601
+ isOpen,
29602
+ onToggle
29603
+ }) {
29604
+ return /*#__PURE__*/React.createElement(View, {
29605
+ style: {
29606
+ flexDirection: "row",
29607
+ justifyContent: "space-between",
29608
+ backgroundColor: color.offBlack8,
29609
+ padding: spacing.xSmall_8,
29610
+ marginTop: spacing.small_12,
29611
+ // NOTE(jeremy): This is the inverse of the @editorPadding CSS
29612
+ // variable found in perseus-editor.less. For now, it must
29613
+ // match otherwise there's a gap from this header to the edge
29614
+ // of the editor borders.
29615
+ marginInline: -10,
29616
+ cursor: "pointer"
29617
+ },
29618
+ onClick: () => onToggle == null ? void 0 : onToggle(!isOpen)
29619
+ }, /*#__PURE__*/React.createElement(LabelSmall, null, title), /*#__PURE__*/React.createElement(ToggleableCaret, {
29620
+ isExpanded: isOpen
29621
+ }));
29622
+ }
29587
29623
  class InteractiveGraphSettings extends React.Component {
29588
29624
  static stateFromProps(props) {
29589
29625
  return {
@@ -29836,7 +29872,9 @@ class InteractiveGraphSettings extends React.Component {
29836
29872
  });
29837
29873
  }
29838
29874
  };
29839
- this.state = InteractiveGraphSettings.stateFromProps(props);
29875
+ this.state = _extends({
29876
+ isExpanded: true
29877
+ }, InteractiveGraphSettings.stateFromProps(props));
29840
29878
  }
29841
29879
  componentDidMount() {
29842
29880
  // TODO(scottgrant): This is a hack to remove the deprecated call to
@@ -29855,7 +29893,13 @@ class InteractiveGraphSettings extends React.Component {
29855
29893
  this._isMounted = false;
29856
29894
  }
29857
29895
  render() {
29858
- return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
29896
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Heading, {
29897
+ title: "Common Graph Settings",
29898
+ isOpen: this.state.isExpanded,
29899
+ onToggle: () => this.setState({
29900
+ isExpanded: !this.state.isExpanded
29901
+ })
29902
+ }), this.state.isExpanded && /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement("div", {
29859
29903
  className: "graph-settings"
29860
29904
  }, /*#__PURE__*/React.createElement("div", {
29861
29905
  className: "perseus-widget-row"
@@ -30040,7 +30084,7 @@ class InteractiveGraphSettings extends React.Component {
30040
30084
  key: value,
30041
30085
  value: `${value}`,
30042
30086
  label: `${value}`
30043
- })))))));
30087
+ }))))))));
30044
30088
  }
30045
30089
  }
30046
30090
  InteractiveGraphSettings.defaultProps = {
@@ -30280,6 +30324,7 @@ const styles$l = StyleSheet.create({
30280
30324
  const CoordinatePairInput = props => {
30281
30325
  const {
30282
30326
  coord,
30327
+ error,
30283
30328
  onChangeProps
30284
30329
  } = props;
30285
30330
 
@@ -30313,7 +30358,7 @@ const CoordinatePairInput = props => {
30313
30358
  coord: newCoords
30314
30359
  });
30315
30360
  }
30316
- return /*#__PURE__*/React.createElement(View, {
30361
+ return /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(View, {
30317
30362
  style: [styles$k.row, styles$k.spaceUnder]
30318
30363
  }, /*#__PURE__*/React.createElement(LabelMedium, {
30319
30364
  htmlFor: xCoordId,
@@ -30324,7 +30369,7 @@ const CoordinatePairInput = props => {
30324
30369
  type: "number",
30325
30370
  value: coordState[0],
30326
30371
  onChange: newValue => handleCoordChange(newValue, 0),
30327
- style: styles$k.textField
30372
+ style: [styles$k.textField, error ? styles$k.errorField : undefined]
30328
30373
  }), /*#__PURE__*/React.createElement(Strut, {
30329
30374
  size: spacing.medium_16
30330
30375
  }), /*#__PURE__*/React.createElement(LabelMedium, {
@@ -30336,8 +30381,8 @@ const CoordinatePairInput = props => {
30336
30381
  type: "number",
30337
30382
  value: coordState[1],
30338
30383
  onChange: newValue => handleCoordChange(newValue, 1),
30339
- style: styles$k.textField
30340
- }));
30384
+ style: [styles$k.textField, error ? styles$k.errorField : undefined]
30385
+ })));
30341
30386
  };
30342
30387
  const styles$k = StyleSheet.create({
30343
30388
  row: {
@@ -30352,6 +30397,10 @@ const styles$k = StyleSheet.create({
30352
30397
  },
30353
30398
  textField: {
30354
30399
  width: spacing.xxxLarge_64
30400
+ },
30401
+ errorField: {
30402
+ borderColor: color.red,
30403
+ backgroundColor: color.fadedRed8
30355
30404
  }
30356
30405
  });
30357
30406
 
@@ -30443,6 +30492,7 @@ const DefiningPointSettings = props => {
30443
30492
  filled = true,
30444
30493
  label,
30445
30494
  showPoint = "false",
30495
+ error,
30446
30496
  onChangeProps,
30447
30497
  onTogglePoint
30448
30498
  } = props;
@@ -30469,6 +30519,7 @@ const DefiningPointSettings = props => {
30469
30519
  }))
30470
30520
  }, /*#__PURE__*/React.createElement(CoordinatePairInput, {
30471
30521
  coord: coord,
30522
+ error: !!error,
30472
30523
  onChangeProps: onChangeProps
30473
30524
  }), onTogglePoint && /*#__PURE__*/React.createElement(LabeledSwitch, {
30474
30525
  label: "show point on graph",
@@ -30569,6 +30620,7 @@ const styles$f = StyleSheet.create({
30569
30620
  }
30570
30621
  });
30571
30622
 
30623
+ const lengthZeroStr = "The line cannot have length 0.";
30572
30624
  const LockedLineSettings = props => {
30573
30625
  const {
30574
30626
  kind,
@@ -30590,6 +30642,7 @@ const LockedLineSettings = props => {
30590
30642
  const capitalizeKind = kind.charAt(0).toUpperCase() + kind.slice(1);
30591
30643
  const lineLabel = `${capitalizeKind} (${point1.coord[0]},
30592
30644
  ${point1.coord[1]}), (${point2.coord[0]}, ${point2.coord[1]})`;
30645
+ const isInvalid = point1.coord[0] === point2.coord[0] && point1.coord[1] === point2.coord[1];
30593
30646
  function handleChangePoint(newPointProps, index) {
30594
30647
  const newPoints = [...points];
30595
30648
  newPoints[index] = _extends({}, points[index], newPointProps);
@@ -30637,12 +30690,12 @@ const LockedLineSettings = props => {
30637
30690
  }, /*#__PURE__*/React.createElement(OptionItem, {
30638
30691
  value: "line",
30639
30692
  label: "line"
30640
- }), /*#__PURE__*/React.createElement(OptionItem, {
30641
- value: "segment",
30642
- label: "segment"
30643
30693
  }), /*#__PURE__*/React.createElement(OptionItem, {
30644
30694
  value: "ray",
30645
30695
  label: "ray"
30696
+ }), /*#__PURE__*/React.createElement(OptionItem, {
30697
+ value: "segment",
30698
+ label: "segment"
30646
30699
  }))), /*#__PURE__*/React.createElement(View, {
30647
30700
  style: [styles$e.row, styles$e.spaceUnder]
30648
30701
  }, /*#__PURE__*/React.createElement(ColorSelect, {
@@ -30672,9 +30725,12 @@ const LockedLineSettings = props => {
30672
30725
  }), /*#__PURE__*/React.createElement(OptionItem, {
30673
30726
  value: "dashed",
30674
30727
  label: "dashed"
30675
- })))), /*#__PURE__*/React.createElement(DefiningPointSettings, _extends({
30728
+ })))), isInvalid && /*#__PURE__*/React.createElement(LabelMedium, {
30729
+ style: styles$e.errorText
30730
+ }, lengthZeroStr), /*#__PURE__*/React.createElement(DefiningPointSettings, _extends({
30676
30731
  label: "Point 1",
30677
- showPoint: showPoint1
30732
+ showPoint: showPoint1,
30733
+ error: isInvalid ? lengthZeroStr : null
30678
30734
  }, point1, {
30679
30735
  onTogglePoint: newValue => onChangeProps({
30680
30736
  showPoint1: newValue
@@ -30682,7 +30738,8 @@ const LockedLineSettings = props => {
30682
30738
  onChangeProps: newProps => handleChangePoint(newProps, 0)
30683
30739
  })), /*#__PURE__*/React.createElement(DefiningPointSettings, _extends({
30684
30740
  label: "Point 2",
30685
- showPoint: showPoint2
30741
+ showPoint: showPoint2,
30742
+ error: isInvalid ? lengthZeroStr : null
30686
30743
  }, point2, {
30687
30744
  onTogglePoint: newValue => onChangeProps({
30688
30745
  showPoint2: newValue
@@ -30709,6 +30766,9 @@ const styles$e = StyleSheet.create({
30709
30766
  selectMarginOffset: {
30710
30767
  // Align with the point settings accordions.
30711
30768
  marginInlineEnd: -spacing.xxxSmall_4
30769
+ },
30770
+ errorText: {
30771
+ color: color.red
30712
30772
  }
30713
30773
  });
30714
30774
 
@@ -30865,7 +30925,8 @@ const LockedFiguresSection = props => {
30865
30925
  var _props$figures;
30866
30926
  // Keep track of all figures' accordions' expanded states for the
30867
30927
  // expand/collapse all button. Set the whole array to false initially.
30868
- const [expandedStates, setExpandedStates] = React.useState(Array((_props$figures = props.figures) == null ? void 0 : _props$figures.length).fill(false));
30928
+ const collapsedStateArray = Array(((_props$figures = props.figures) != null ? _props$figures : []).length).fill(false);
30929
+ const [expandedStates, setExpandedStates] = React.useState(collapsedStateArray);
30869
30930
  const uniqueId = useUniqueIdWithMock().get("locked-figures-section");
30870
30931
  const {
30871
30932
  figures,