@khanacademy/perseus-editor 11.3.0 → 11.4.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
@@ -13,15 +13,15 @@ import { View, useUniqueIdWithMock } from '@khanacademy/wonder-blocks-core';
13
13
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
14
14
  import caretRight from '@phosphor-icons/core/bold/caret-right-bold.svg';
15
15
  import classNames from 'classnames';
16
- import { Checkbox as Checkbox$1, TextField } from '@khanacademy/wonder-blocks-form';
16
+ import { Checkbox as Checkbox$1, LabeledTextField, TextField } from '@khanacademy/wonder-blocks-form';
17
17
  import ReactDOM from 'react-dom';
18
18
  import { point, vector, number } from '@khanacademy/kmath';
19
19
  import * as KAS from '@khanacademy/kas';
20
+ import Button from '@khanacademy/wonder-blocks-button';
21
+ import { HeadingSmall, HeadingXSmall, LabelSmall, LabelLarge, LabelMedium, LabelXSmall, BodyMonospace } from '@khanacademy/wonder-blocks-typography';
20
22
  import { isTruthy, UnreachableCaseError } from '@khanacademy/wonder-stuff-core';
21
23
  import { useMathInputI18n, createMathField } from '@khanacademy/math-input';
22
24
  import { ActionMenu, ActionItem, SingleSelect, OptionItem } from '@khanacademy/wonder-blocks-dropdown';
23
- import { LabelSmall, LabelLarge, LabelMedium, LabelXSmall, BodyMonospace } from '@khanacademy/wonder-blocks-typography';
24
- import Button from '@khanacademy/wonder-blocks-button';
25
25
  import { AccordionSection } from '@khanacademy/wonder-blocks-accordion';
26
26
  import IconButton from '@khanacademy/wonder-blocks-icon-button';
27
27
  import caretDoubleDownIcon from '@phosphor-icons/core/bold/caret-double-down-bold.svg';
@@ -37,7 +37,7 @@ import arrowCounterClockwise from '@phosphor-icons/core/bold/arrow-counter-clock
37
37
 
38
38
  // This file is processed by a Rollup plugin (replace) to inject the production
39
39
  const libName = "@khanacademy/perseus-editor";
40
- const libVersion = "11.3.0";
40
+ const libVersion = "11.4.0";
41
41
  addLibraryVersionToPerseusDebug(libName, libVersion);
42
42
 
43
43
  function _extends() {
@@ -227,7 +227,7 @@ class SectionControlButton extends React.Component {
227
227
  role: "button",
228
228
  hideDefaultFocusRing: true,
229
229
  "aria-label": title,
230
- style: styles$P.button
230
+ style: styles$R.button
231
231
  }, ({
232
232
  hovered,
233
233
  focused,
@@ -235,7 +235,7 @@ class SectionControlButton extends React.Component {
235
235
  }) => /*#__PURE__*/React.createElement(InlineIcon$a, icon));
236
236
  }
237
237
  }
238
- const styles$P = StyleSheet.create({
238
+ const styles$R = StyleSheet.create({
239
239
  button: {
240
240
  backgroundColor: color.gold,
241
241
  margin: 2,
@@ -20740,13 +20740,13 @@ class WidgetSelect extends React.Component {
20740
20740
  * that collapse a region.
20741
20741
  */
20742
20742
  function ToggleableCaret(props) {
20743
- const iconStyle = props.isExpanded ? styles$O.expanded : styles$O.collapsed;
20743
+ const iconStyle = props.isExpanded ? styles$Q.expanded : styles$Q.collapsed;
20744
20744
  return /*#__PURE__*/React.createElement(PhosphorIcon, {
20745
20745
  icon: caretRight,
20746
20746
  style: iconStyle
20747
20747
  });
20748
20748
  }
20749
- const styles$O = StyleSheet.create({
20749
+ const styles$Q = StyleSheet.create({
20750
20750
  collapsed: {
20751
20751
  transition: ".15s"
20752
20752
  },
@@ -20779,16 +20779,16 @@ class TexErrorView extends React.Component {
20779
20779
  showErrors
20780
20780
  } = this.state;
20781
20781
  return /*#__PURE__*/React.createElement(View, {
20782
- style: styles$N.errorContainer
20782
+ style: styles$P.errorContainer
20783
20783
  }, /*#__PURE__*/React.createElement(View, {
20784
- style: styles$N.title,
20784
+ style: styles$P.title,
20785
20785
  onClick: this.handleToggleTexErrors
20786
20786
  }, /*#__PURE__*/React.createElement(ToggleableCaret, {
20787
20787
  isExpanded: showErrors
20788
20788
  }), "\xA0 TeX Errors (", errorList.length, ")"), showErrors && /*#__PURE__*/React.createElement(View, {
20789
- style: styles$N.errorExplanation
20789
+ style: styles$P.errorExplanation
20790
20790
  }, "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, {
20791
- style: styles$N.error,
20791
+ style: styles$P.error,
20792
20792
  key: index
20793
20793
  }, /*#__PURE__*/React.createElement(View, {
20794
20794
  style: {
@@ -20797,7 +20797,7 @@ class TexErrorView extends React.Component {
20797
20797
  }, e.math), /*#__PURE__*/React.createElement(View, null, e.message))));
20798
20798
  }
20799
20799
  }
20800
- const styles$N = StyleSheet.create({
20800
+ const styles$P = StyleSheet.create({
20801
20801
  title: {
20802
20802
  backgroundColor: "#eee",
20803
20803
  fontSize: "1.25em",
@@ -23910,7 +23910,7 @@ ItemExtrasEditor.defaultProps = {
23910
23910
  zTable: false
23911
23911
  };
23912
23912
  const ItemExtraCheckbox = props => /*#__PURE__*/React.createElement(View, {
23913
- style: [styles$M.checkbox, props.indent ? styles$M.indented : undefined]
23913
+ style: [styles$O.checkbox, props.indent ? styles$O.indented : undefined]
23914
23914
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
23915
23915
  label: /*#__PURE__*/React.createElement(View, {
23916
23916
  style: {
@@ -23920,7 +23920,7 @@ const ItemExtraCheckbox = props => /*#__PURE__*/React.createElement(View, {
23920
23920
  checked: props.checked,
23921
23921
  onChange: newCheckedState => props.onChange(newCheckedState)
23922
23922
  }));
23923
- const styles$M = StyleSheet.create({
23923
+ const styles$O = StyleSheet.create({
23924
23924
  indented: {
23925
23925
  marginInlineStart: spacing.large_24
23926
23926
  }
@@ -24591,7 +24591,7 @@ class SimpleButton extends React.Component {
24591
24591
  } = _this$props,
24592
24592
  otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
24593
24593
  return /*#__PURE__*/React.createElement("div", _extends({
24594
- className: css(styles$L.baseButton, color === "green" && styles$L.green, color === "orange" && styles$L.orange),
24594
+ className: css(styles$N.baseButton, color === "green" && styles$N.green, color === "orange" && styles$N.orange),
24595
24595
  onClick: onClick
24596
24596
  }, otherProps), children);
24597
24597
  }
@@ -24606,7 +24606,7 @@ SimpleButton.defaultProps = {
24606
24606
  color: "green",
24607
24607
  onClick: () => {}
24608
24608
  };
24609
- const styles$L = StyleSheet.create({
24609
+ const styles$N = StyleSheet.create({
24610
24610
  baseButton: {
24611
24611
  top: "0",
24612
24612
  fontSize: "11px",
@@ -24826,23 +24826,23 @@ const LeafContainer = ({
24826
24826
  }) => {
24827
24827
  const hasPreviewHeading = shape.type === "content" || shape.type === "hint";
24828
24828
  const previewHeading = hasPreviewHeading && /*#__PURE__*/React.createElement("div", {
24829
- className: css(styles$K.containerHeader)
24829
+ className: css(styles$M.containerHeader)
24830
24830
  }, /*#__PURE__*/React.createElement(Header, {
24831
24831
  depth: path.length,
24832
- className: css(styles$K.containerTitle)
24832
+ className: css(styles$M.containerTitle)
24833
24833
  }, capitalize(name)));
24834
24834
  return /*#__PURE__*/React.createElement("div", {
24835
- className: css(styles$K.container)
24835
+ className: css(styles$M.container)
24836
24836
  }, /*#__PURE__*/React.createElement("span", {
24837
- className: css(styles$K.row, styles$K.rowHeading)
24837
+ className: css(styles$M.row, styles$M.rowHeading)
24838
24838
  }, /*#__PURE__*/React.createElement("div", {
24839
- className: css(styles$K.columnLeft)
24839
+ className: css(styles$M.columnLeft)
24840
24840
  }, /*#__PURE__*/React.createElement("div", {
24841
- className: "pod-title " + css(styles$K.containerHeader)
24841
+ className: "pod-title " + css(styles$M.containerHeader)
24842
24842
  }, /*#__PURE__*/React.createElement("div", {
24843
- className: css(styles$K.containerTitle)
24843
+ className: css(styles$M.containerTitle)
24844
24844
  }, capitalize(name)), controls)), /*#__PURE__*/React.createElement("div", {
24845
- className: css(styles$K.columnRight)
24845
+ className: css(styles$M.columnRight)
24846
24846
  }, previewHeading)), children);
24847
24847
  };
24848
24848
  const ArrayContainer = props => {
@@ -24855,11 +24855,11 @@ const ArrayContainer = props => {
24855
24855
  actions
24856
24856
  } = props;
24857
24857
  return /*#__PURE__*/React.createElement("div", {
24858
- className: css(styles$K.container)
24858
+ className: css(styles$M.container)
24859
24859
  }, controls && /*#__PURE__*/React.createElement("div", {
24860
- className: css(styles$K.columnLeft, styles$K.containerHeader)
24860
+ className: css(styles$M.columnLeft, styles$M.containerHeader)
24861
24861
  }, controls), /*#__PURE__*/React.createElement("div", null, children), /*#__PURE__*/React.createElement("div", {
24862
- className: css(styles$K.columnLeft)
24862
+ className: css(styles$M.columnLeft)
24863
24863
  }, /*#__PURE__*/React.createElement("a", {
24864
24864
  href: "javascript:void 0",
24865
24865
  onClick: () => actions.addArrayElement(path, shape.elementShape)
@@ -24872,28 +24872,28 @@ const ObjectContainer = ({
24872
24872
  path
24873
24873
  }) => {
24874
24874
  const headingEditor = /*#__PURE__*/React.createElement("div", {
24875
- className: css(styles$K.containerHeader)
24875
+ className: css(styles$M.containerHeader)
24876
24876
  }, /*#__PURE__*/React.createElement(Header, {
24877
24877
  depth: path.length,
24878
- className: css(styles$K.containerTitle)
24878
+ className: css(styles$M.containerTitle)
24879
24879
  }, capitalize(name)), controls);
24880
24880
  const headingPreview = (name || controls) && /*#__PURE__*/React.createElement("div", {
24881
- className: css(styles$K.containerHeader, styles$K.previewCollectionHeader)
24881
+ className: css(styles$M.containerHeader, styles$M.previewCollectionHeader)
24882
24882
  }, /*#__PURE__*/React.createElement(Header, {
24883
24883
  depth: path.length,
24884
- className: css(styles$K.containerTitle)
24884
+ className: css(styles$M.containerTitle)
24885
24885
  }, capitalize(name)));
24886
24886
  const hasBothHeadings = headingEditor && headingPreview;
24887
24887
  return /*#__PURE__*/React.createElement("div", {
24888
- className: css(styles$K.container)
24888
+ className: css(styles$M.container)
24889
24889
  }, hasBothHeadings && /*#__PURE__*/React.createElement("span", {
24890
- className: css(styles$K.row)
24890
+ className: css(styles$M.row)
24891
24891
  }, /*#__PURE__*/React.createElement("div", {
24892
- className: css(styles$K.columnLeft)
24892
+ className: css(styles$M.columnLeft)
24893
24893
  }, headingEditor), /*#__PURE__*/React.createElement("div", {
24894
- className: css(styles$K.columnRight)
24894
+ className: css(styles$M.columnRight)
24895
24895
  }, headingPreview)), /*#__PURE__*/React.createElement("div", {
24896
- className: css(path.length > 0 && styles$K.contentIndent)
24896
+ className: css(path.length > 0 && styles$M.contentIndent)
24897
24897
  }, children));
24898
24898
  };
24899
24899
 
@@ -25016,11 +25016,11 @@ const ItemNodeContent = withStickiness(props => {
25016
25016
  className: "framework-perseus"
25017
25017
  }, lens(renderers).get(path));
25018
25018
  return /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("div", {
25019
- className: css(styles$K.row)
25019
+ className: css(styles$M.row)
25020
25020
  }, /*#__PURE__*/React.createElement("div", {
25021
- className: css(styles$K.columnLeft)
25021
+ className: css(styles$M.columnLeft)
25022
25022
  }, /*#__PURE__*/React.createElement("div", {
25023
- className: css(sticky && styles$K.sticky)
25023
+ className: css(sticky && styles$M.sticky)
25024
25024
  },
25025
25025
  /*#__PURE__*/
25026
25026
  // @ts-expect-error - TS2769 - No overload matches this call.
@@ -25028,9 +25028,9 @@ const ItemNodeContent = withStickiness(props => {
25028
25028
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25029
25029
  apiOptions: apiOptions
25030
25030
  })))), /*#__PURE__*/React.createElement("div", {
25031
- className: css(styles$K.columnRight)
25031
+ className: css(styles$M.columnRight)
25032
25032
  }, /*#__PURE__*/React.createElement("div", {
25033
- className: css(sticky && styles$K.sticky)
25033
+ className: css(sticky && styles$M.sticky)
25034
25034
  }, preview))));
25035
25035
  });
25036
25036
  const HintNodeContent = withStickiness(props => {
@@ -25046,13 +25046,13 @@ const HintNodeContent = withStickiness(props => {
25046
25046
  className: "framework-perseus"
25047
25047
  }, lens(renderers).get(path));
25048
25048
  return /*#__PURE__*/React.createElement("div", {
25049
- className: css(styles$K.row)
25049
+ className: css(styles$M.row)
25050
25050
  }, /*#__PURE__*/React.createElement("div", {
25051
- className: css(styles$K.columnLeft)
25051
+ className: css(styles$M.columnLeft)
25052
25052
  }, /*#__PURE__*/React.createElement("div", {
25053
- className: css(sticky && styles$K.sticky)
25053
+ className: css(sticky && styles$M.sticky)
25054
25054
  }, /*#__PURE__*/React.createElement(HintEditor, _extends({}, data, {
25055
- className: css(styles$K.hintEditor),
25055
+ className: css(styles$M.hintEditor),
25056
25056
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25057
25057
  apiOptions: apiOptions,
25058
25058
  showTitle: false,
@@ -25067,9 +25067,9 @@ const HintNodeContent = withStickiness(props => {
25067
25067
  isFirst: true,
25068
25068
  isLast: true
25069
25069
  })))), /*#__PURE__*/React.createElement("div", {
25070
- className: css(styles$K.columnRight)
25070
+ className: css(styles$M.columnRight)
25071
25071
  }, /*#__PURE__*/React.createElement("div", {
25072
- className: css(sticky && styles$K.sticky)
25072
+ className: css(sticky && styles$M.sticky)
25073
25073
  }, preview)));
25074
25074
  });
25075
25075
  const TagsNodeContent = props => {
@@ -25086,9 +25086,9 @@ const TagsNodeContent = props => {
25086
25086
  return null;
25087
25087
  }
25088
25088
  return /*#__PURE__*/React.createElement("div", {
25089
- className: css(styles$K.columnLeft)
25089
+ className: css(styles$M.columnLeft)
25090
25090
  }, /*#__PURE__*/React.createElement("div", {
25091
- className: css(styles$K.tagsEditor)
25091
+ className: css(styles$M.tagsEditor)
25092
25092
  }, /*#__PURE__*/React.createElement(GroupMetadataEditor, {
25093
25093
  value: data,
25094
25094
  onChange: newVal => actions.setValueAtPath(path, newVal),
@@ -25119,23 +25119,23 @@ const ArrayNodeContent = props => {
25119
25119
  const subpath = path.concat(i);
25120
25120
  const controls = [i > 0 && /*#__PURE__*/React.createElement("div", {
25121
25121
  key: "moveArrayElementUp",
25122
- className: css(styles$K.control)
25122
+ className: css(styles$M.control)
25123
25123
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25124
25124
  color: "orange",
25125
25125
  title: "Move up",
25126
25126
  onClick: () => actions.moveArrayElementUp(subpath)
25127
25127
  }, /*#__PURE__*/React.createElement("div", {
25128
- className: css(styles$K.verticalFlip)
25128
+ className: css(styles$M.verticalFlip)
25129
25129
  }, /*#__PURE__*/React.createElement(InlineIcon$5, iconChevronDown)))), i < data.length - 1 && /*#__PURE__*/React.createElement("div", {
25130
25130
  key: "moveArrayElementDown",
25131
- className: css(styles$K.control)
25131
+ className: css(styles$M.control)
25132
25132
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25133
25133
  color: "orange",
25134
25134
  title: "Move down",
25135
25135
  onClick: () => actions.moveArrayElementDown(subpath)
25136
25136
  }, /*#__PURE__*/React.createElement(InlineIcon$5, iconChevronDown))), /*#__PURE__*/React.createElement("div", {
25137
25137
  key: "removeArrayElement",
25138
- className: css(styles$K.control)
25138
+ className: css(styles$M.control)
25139
25139
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25140
25140
  color: "orange",
25141
25141
  title: "Delete",
@@ -25143,7 +25143,7 @@ const ArrayNodeContent = props => {
25143
25143
  }, /*#__PURE__*/React.createElement(InlineIcon$5, iconTrash$4)))];
25144
25144
  return /*#__PURE__*/React.createElement("div", {
25145
25145
  key: i,
25146
- className: css(styles$K.arrayElement, !elementIsLeaf && styles$K.arrayElementAndNotLeaf)
25146
+ className: css(styles$M.arrayElement, !elementIsLeaf && styles$M.arrayElementAndNotLeaf)
25147
25147
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25148
25148
  key: i,
25149
25149
  shape: shape.elementShape,
@@ -25169,7 +25169,7 @@ const ObjectNodeContent = props => {
25169
25169
  // made sense to the shape's author is the order in which we'll iterate :)
25170
25170
  const children = Object.keys(shape.shape).map(subkey => /*#__PURE__*/React.createElement("div", {
25171
25171
  key: subkey,
25172
- className: css(styles$K.objectElement)
25172
+ className: css(styles$M.objectElement)
25173
25173
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25174
25174
  shape: shape.shape[subkey],
25175
25175
  data: data[subkey],
@@ -25336,7 +25336,7 @@ class MultiRendererEditor extends React.Component {
25336
25336
  }, this._renderContent());
25337
25337
  }
25338
25338
  }
25339
- const styles$K = StyleSheet.create({
25339
+ const styles$M = StyleSheet.create({
25340
25340
  // This is used in a number of places throughout this file.
25341
25341
  container: {},
25342
25342
  // eslint-disable-next-line react-native/no-unused-styles
@@ -25826,7 +25826,7 @@ CSProgramEditor.defaultProps = {
25826
25826
  };
25827
25827
 
25828
25828
  const {
25829
- TextInput: TextInput$9
25829
+ TextInput: TextInput$8
25830
25830
  } = components;
25831
25831
  class DefinitionEditor extends React.Component {
25832
25832
  constructor(..._args) {
@@ -25846,7 +25846,7 @@ class DefinitionEditor extends React.Component {
25846
25846
  target: "_blank"
25847
25847
  }, "Definition style guide"), /*#__PURE__*/React.createElement("div", {
25848
25848
  className: "perseus-widget-row"
25849
- }, /*#__PURE__*/React.createElement("label", null, "Word to be defined:", " ", /*#__PURE__*/React.createElement(TextInput$9, {
25849
+ }, /*#__PURE__*/React.createElement("label", null, "Word to be defined:", " ", /*#__PURE__*/React.createElement(TextInput$8, {
25850
25850
  value: this.props.togglePrompt
25851
25851
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
25852
25852
  ,
@@ -26255,7 +26255,7 @@ ExampleWidgetEditor.defaultProps = {
26255
26255
  };
26256
26256
 
26257
26257
  const {
26258
- TextInput: TextInput$8
26258
+ TextInput: TextInput$7
26259
26259
  } = components;
26260
26260
  const defaultExplanationProps = {
26261
26261
  showPrompt: "Explain",
@@ -26279,14 +26279,14 @@ class ExplanationEditor extends React.Component {
26279
26279
  className: "perseus-widget-explanation-editor"
26280
26280
  }, /*#__PURE__*/React.createElement("div", {
26281
26281
  className: "perseus-widget-row"
26282
- }, /*#__PURE__*/React.createElement("label", null, "Prompt to show explanation:", " ", /*#__PURE__*/React.createElement(TextInput$8, {
26282
+ }, /*#__PURE__*/React.createElement("label", null, "Prompt to show explanation:", " ", /*#__PURE__*/React.createElement(TextInput$7, {
26283
26283
  value: this.props.showPrompt
26284
26284
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26285
26285
  ,
26286
26286
  onChange: this.change("showPrompt")
26287
26287
  }))), /*#__PURE__*/React.createElement("div", {
26288
26288
  className: "perseus-widget-row"
26289
- }, /*#__PURE__*/React.createElement("label", null, "Prompt to hide explanation:", " ", /*#__PURE__*/React.createElement(TextInput$8, {
26289
+ }, /*#__PURE__*/React.createElement("label", null, "Prompt to hide explanation:", " ", /*#__PURE__*/React.createElement(TextInput$7, {
26290
26290
  value: this.props.hidePrompt
26291
26291
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26292
26292
  ,
@@ -26323,9 +26323,106 @@ ExplanationEditor.propTypes = _extends({}, Changeable.propTypes, {
26323
26323
  ExplanationEditor.widgetName = "explanation";
26324
26324
  ExplanationEditor.defaultProps = defaultExplanationProps;
26325
26325
 
26326
+ const mediaDefaultSpecLargeMarginWidth = spacing.large_24;
26327
+ const MEDIA_DEFAULT_SPEC = {
26328
+ small: {
26329
+ query: "(max-width: 767px)",
26330
+ totalColumns: 4,
26331
+ gutterWidth: spacing.medium_16,
26332
+ marginWidth: spacing.medium_16
26333
+ },
26334
+ medium: {
26335
+ query: "(min-width: 768px) and (max-width: 1023px)",
26336
+ totalColumns: 8,
26337
+ gutterWidth: spacing.xLarge_32,
26338
+ marginWidth: spacing.large_24
26339
+ },
26340
+ large: {
26341
+ query: "(min-width: 1024px)",
26342
+ totalColumns: 12,
26343
+ gutterWidth: spacing.xLarge_32,
26344
+ marginWidth: mediaDefaultSpecLargeMarginWidth,
26345
+ maxWidth: 1120 + mediaDefaultSpecLargeMarginWidth * 2
26346
+ }
26347
+ };
26348
+ ({
26349
+ large: {
26350
+ query: "(min-width: 1px)",
26351
+ totalColumns: 12,
26352
+ gutterWidth: spacing.xLarge_32,
26353
+ marginWidth: spacing.medium_16
26354
+ }
26355
+ });
26356
+ ({
26357
+ small: {
26358
+ query: "(max-width: 767px)",
26359
+ totalColumns: 4,
26360
+ gutterWidth: spacing.medium_16,
26361
+ marginWidth: spacing.medium_16
26362
+ },
26363
+ large: {
26364
+ query: "(min-width: 768px)",
26365
+ totalColumns: 12,
26366
+ gutterWidth: spacing.xLarge_32,
26367
+ marginWidth: spacing.xxLarge_48
26368
+ }
26369
+ });
26370
+
26371
+ const defaultContext = {
26372
+ ssrSize: "large",
26373
+ mediaSpec: MEDIA_DEFAULT_SPEC
26374
+ };
26375
+ const MediaLayoutContext = React.createContext(defaultContext);
26376
+ MediaLayoutContext.displayName = "MediaLayoutContext";
26377
+
26378
+ class Spring extends React.Component {
26379
+ render() {
26380
+ const {
26381
+ style
26382
+ } = this.props;
26383
+ return React.createElement(View, {
26384
+ "aria-hidden": "true",
26385
+ style: [styles$L.grow, style]
26386
+ });
26387
+ }
26388
+ }
26389
+ const styles$L = StyleSheet.create({
26390
+ grow: {
26391
+ flexGrow: 1
26392
+ }
26393
+ });
26394
+
26395
+ class Strut extends React.Component {
26396
+ render() {
26397
+ const {
26398
+ size,
26399
+ style
26400
+ } = this.props;
26401
+ return React.createElement(View, {
26402
+ "aria-hidden": "true",
26403
+ style: [strutStyle(size), style]
26404
+ });
26405
+ }
26406
+ }
26407
+ const strutStyle = size => {
26408
+ return {
26409
+ width: size,
26410
+ MsFlexBasis: size,
26411
+ MsFlexPreferredSize: size,
26412
+ WebkitFlexBasis: size,
26413
+ flexBasis: size,
26414
+ flexShrink: 0
26415
+ };
26416
+ };
26417
+
26326
26418
  const PT = PropTypes;
26327
26419
 
26328
- // Takes an array of components to sort
26420
+ /**
26421
+ * Takes an array of components to sort.
26422
+ * As of 08/05/24, there are two sortable components
26423
+ * (one in perseus and one in perseus-editor).
26424
+ * As far as I can tell, this one is only used in ExpressionEditor.
26425
+ */
26329
26426
  // eslint-disable-next-line react/no-unsafe
26330
26427
  const SortableArea = createReactClass({
26331
26428
  displayName: "SortableArea",
@@ -26482,6 +26579,7 @@ const SortableItem = createReactClass({
26482
26579
  e.preventDefault();
26483
26580
  },
26484
26581
  render: function () {
26582
+ // I think these might be getting styles from Webapp
26485
26583
  let dragState = "sortable-disabled";
26486
26584
  if (this.props.dragging) {
26487
26585
  dragState = "sortable-dragging";
@@ -26490,7 +26588,7 @@ const SortableItem = createReactClass({
26490
26588
  }
26491
26589
  return /*#__PURE__*/React.createElement("li", {
26492
26590
  draggable: this.props.draggable,
26493
- className: dragState,
26591
+ className: [dragState, css(styles$K.sortableListItem)].join(" "),
26494
26592
  onDragStart: this.handleDragStart,
26495
26593
  onDrop: this.handleDrop,
26496
26594
  onDragEnter: this.handleDragEnter,
@@ -26498,10 +26596,14 @@ const SortableItem = createReactClass({
26498
26596
  }, this.props.component);
26499
26597
  }
26500
26598
  });
26599
+ const styles$K = StyleSheet.create({
26600
+ sortableListItem: {
26601
+ margin: "5px 0"
26602
+ }
26603
+ });
26501
26604
 
26502
26605
  const {
26503
- InfoTip: InfoTip$i,
26504
- TextInput: TextInput$7
26606
+ InfoTip: InfoTip$i
26505
26607
  } = components;
26506
26608
 
26507
26609
  // types for iterables
@@ -26540,8 +26642,8 @@ const _makeNewKey = answerForms => {
26540
26642
  return usedKeys.length;
26541
26643
  };
26542
26644
  class ExpressionEditor extends React.Component {
26543
- constructor(...args) {
26544
- super(...args);
26645
+ constructor(_props) {
26646
+ super(_props);
26545
26647
  this.serialize = () => {
26546
26648
  const formSerializables = ["value", "form", "simplify", "considered",
26547
26649
  // it's a little weird to serialize the react key, but saves some
@@ -26670,11 +26772,17 @@ class ExpressionEditor extends React.Component {
26670
26772
  this.refs.expression.insert(str);
26671
26773
  };
26672
26774
  // called when the function variables change
26673
- this.handleFunctions = e => {
26775
+ this.handleFunctions = value => {
26776
+ this.setState({
26777
+ functionsInternal: value
26778
+ });
26674
26779
  const newProps = {};
26675
- newProps.functions = e.target.value.split(/[ ,]+/).filter(isTruthy);
26780
+ newProps.functions = value.split(/[ ,]+/).filter(isTruthy);
26676
26781
  this.props.onChange(newProps);
26677
26782
  };
26783
+ this.state = {
26784
+ functionsInternal: this.props.functions.join(" ")
26785
+ };
26678
26786
  }
26679
26787
  change(...args) {
26680
26788
  return Changeable.change.apply(this, args);
@@ -26712,81 +26820,69 @@ class ExpressionEditor extends React.Component {
26712
26820
  }, obj)));
26713
26821
  const sortable = /*#__PURE__*/React.createElement(SortableArea, {
26714
26822
  components: answerOptions,
26715
- onReorder: this.handleReorder,
26716
- className: "answer-options-list"
26823
+ onReorder: this.handleReorder
26717
26824
  });
26718
26825
 
26719
26826
  // checkboxes to choose which sets of input buttons are shown
26720
26827
  const buttonSetChoices = buttonSetsList.map(name => {
26721
26828
  // The first one gets special cased to always be checked, disabled,
26722
26829
  // and float left.
26723
- const isFirst = name === "basic";
26724
- const checked = this.props.buttonSets.includes(name) || isFirst;
26725
- return /*#__PURE__*/React.createElement("label", {
26726
- className: "button-set-label",
26727
- key: name
26728
- }, /*#__PURE__*/React.createElement("input", {
26729
- type: "checkbox",
26830
+ const isBasic = name === "basic";
26831
+ const checked = this.props.buttonSets.includes(name) || isBasic;
26832
+ return /*#__PURE__*/React.createElement(Checkbox$1, {
26833
+ key: name,
26834
+ label: name,
26730
26835
  checked: checked,
26731
- disabled: isFirst,
26836
+ disabled: isBasic,
26732
26837
  onChange: () => this.handleButtonSet(name)
26733
- }), name);
26838
+ });
26734
26839
  });
26735
- const {
26736
- TeX
26737
- } = Dependencies.getDependencies(); // OldExpression only
26738
-
26739
- buttonSetChoices.unshift( /*#__PURE__*/React.createElement("label", {
26740
- className: "button-set-label",
26741
- key: "show-div"
26742
- }, /*#__PURE__*/React.createElement("input", {
26743
- type: "checkbox",
26840
+ buttonSetChoices.unshift( /*#__PURE__*/React.createElement(Checkbox$1, {
26841
+ key: "show \xF7 button",
26842
+ label: "show \xF7 button",
26843
+ checked: this.props.buttonSets.includes("basic+div"),
26744
26844
  onChange: this.handleToggleDiv
26745
- }), /*#__PURE__*/React.createElement("span", {
26746
- className: "show-div-button"
26747
- }, "show ", /*#__PURE__*/React.createElement(TeX, null, "\\div"), " button")));
26748
- return /*#__PURE__*/React.createElement("div", {
26749
- className: "perseus-widget-expression-editor"
26750
- }, /*#__PURE__*/React.createElement("h3", {
26751
- className: "expression-editor-h3"
26752
- }, "Global Options"), /*#__PURE__*/React.createElement("div", {
26753
- className: "perseus-widget-row"
26754
- }, /*#__PURE__*/React.createElement("label", null, "Visible label:", " ", /*#__PURE__*/React.createElement(TextInput$7, {
26755
- value: this.props.visibleLabel,
26845
+ }));
26846
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(HeadingSmall, null, "Global Options"), /*#__PURE__*/React.createElement("div", {
26847
+ className: css(styles$J.paddedY)
26848
+ }, /*#__PURE__*/React.createElement(LabeledTextField, {
26849
+ label: "Visible label",
26850
+ value: this.props.visibleLabel || "",
26756
26851
  onChange: this.change("visibleLabel")
26757
- })), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."))), /*#__PURE__*/React.createElement("div", {
26758
- className: "perseus-widget-row"
26759
- }, /*#__PURE__*/React.createElement("label", null, "Aria label:", " ", /*#__PURE__*/React.createElement(TextInput$7, {
26760
- value: this.props.ariaLabel,
26852
+ }), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."))), /*#__PURE__*/React.createElement("div", {
26853
+ className: css(styles$J.paddedY)
26854
+ }, /*#__PURE__*/React.createElement(LabeledTextField, {
26855
+ label: "Aria label",
26856
+ value: this.props.ariaLabel || "",
26761
26857
  onChange: this.change("ariaLabel")
26762
- })), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see", " ", /*#__PURE__*/React.createElement("a", {
26858
+ }), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see", " ", /*#__PURE__*/React.createElement("a", {
26763
26859
  href: "https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",
26764
26860
  target: "_blank"
26765
- }, "this article.")))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Checkbox$1, {
26766
- label: "Use \xD7 for rendering multiplication instead of a center dot.",
26861
+ }, "this article.")))), /*#__PURE__*/React.createElement("div", {
26862
+ className: css(styles$J.paddedY)
26863
+ }, /*#__PURE__*/React.createElement(LabeledTextField, {
26864
+ label: "Function variables",
26865
+ value: this.state.functionsInternal,
26866
+ onChange: this.handleFunctions
26867
+ }), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means \"f of x\" and not \"f times x\"."))), /*#__PURE__*/React.createElement("div", {
26868
+ className: css(styles$J.paddedY)
26869
+ }, /*#__PURE__*/React.createElement(Checkbox$1, {
26870
+ label: "Use \xD7 instead of \u22C5 for multiplication",
26767
26871
  checked: this.props.times,
26768
26872
  onChange: value => {
26769
26873
  this.props.onChange({
26770
26874
  times: value
26771
26875
  });
26772
26876
  }
26773
- }), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "Function variables: ", /*#__PURE__*/React.createElement("input", {
26774
- type: "text",
26775
- defaultValue: this.props.functions.join(" "),
26776
- onChange: this.handleFunctions
26777
- })), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means \"f of x\" and not \"f times x\"."))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, "Button sets:"), buttonSetChoices), /*#__PURE__*/React.createElement("h3", {
26778
- className: "expression-editor-h3"
26779
- }, "Answers"), /*#__PURE__*/React.createElement("p", {
26877
+ }), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."))), /*#__PURE__*/React.createElement("div", {
26878
+ className: css(styles$J.paddedY)
26879
+ }, /*#__PURE__*/React.createElement(HeadingXSmall, null, "Button Sets"), buttonSetChoices), /*#__PURE__*/React.createElement(HeadingSmall, null, "Answers"), /*#__PURE__*/React.createElement("p", {
26780
26880
  style: {
26781
26881
  margin: "4px 0"
26782
26882
  }
26783
- }, "student responses area matched against these from top to bottom"), sortable, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
26784
- className: "simple-button orange",
26785
- style: {
26786
- fontSize: 13
26787
- },
26788
- onClick: this.newAnswer,
26789
- type: "button"
26883
+ }, "student responses area matched against these from top to bottom"), sortable, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Button, {
26884
+ size: "small",
26885
+ onClick: this.newAnswer
26790
26886
  }, "Add new answer")));
26791
26887
  }
26792
26888
  }
@@ -26810,17 +26906,17 @@ class AnswerOption extends React.Component {
26810
26906
  this.state = {
26811
26907
  deleteFocused: false
26812
26908
  };
26813
- this.handleDeleteBlur = () => {
26814
- this.setState({
26815
- deleteFocused: false
26816
- });
26817
- };
26818
26909
  this.change = (...args) => {
26819
26910
  return Changeable.change.apply(this, args);
26820
26911
  };
26821
26912
  this.handleImSure = () => {
26822
26913
  this.props.onDelete();
26823
26914
  };
26915
+ this.handleCancelDelete = () => {
26916
+ this.setState({
26917
+ deleteFocused: false
26918
+ });
26919
+ };
26824
26920
  this.handleDelete = () => {
26825
26921
  this.setState({
26826
26922
  deleteFocused: true
@@ -26834,36 +26930,34 @@ class AnswerOption extends React.Component {
26834
26930
  };
26835
26931
  }
26836
26932
  render() {
26837
- let removeButton = null;
26838
- if (this.state.deleteFocused) {
26839
- removeButton = /*#__PURE__*/React.createElement("button", {
26840
- type: "button",
26841
- className: "simple-button orange",
26842
- onClick: this.handleImSure,
26843
- onBlur: this.handleDeleteBlur
26844
- }, "I'm sure!");
26845
- } else {
26846
- removeButton = /*#__PURE__*/React.createElement("button", {
26847
- type: "button",
26848
- className: "simple-button orange",
26849
- onClick: this.handleDelete
26850
- }, "Delete");
26851
- }
26933
+ const removeButton = this.state.deleteFocused ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
26934
+ size: "small",
26935
+ onClick: this.handleImSure,
26936
+ color: "destructive"
26937
+ }, "I'm sure!"), /*#__PURE__*/React.createElement(Strut, {
26938
+ size: spacing.small_12
26939
+ }), /*#__PURE__*/React.createElement(Button, {
26940
+ size: "small",
26941
+ onClick: this.handleCancelDelete,
26942
+ light: true
26943
+ }, "Cancel")) : /*#__PURE__*/React.createElement(Button, {
26944
+ size: "small",
26945
+ onClick: this.handleDelete,
26946
+ color: "destructive",
26947
+ light: true
26948
+ }, "Delete");
26949
+ const answerStatusCss = css(styles$J.answerStatus, this.props.considered === "wrong" && styles$J.answerStatusWrong, this.props.considered === "correct" && styles$J.answerStatusCorrect, this.props.considered === "ungraded" && styles$J.answerStatusUngraded);
26852
26950
  return /*#__PURE__*/React.createElement("div", {
26853
- className: "expression-answer-option"
26951
+ className: css(styles$J.answerOption)
26854
26952
  }, /*#__PURE__*/React.createElement("div", {
26855
- className: "answer-handle"
26953
+ className: css(styles$J.answerHandle)
26856
26954
  }), /*#__PURE__*/React.createElement("div", {
26857
- className: "answer-body"
26858
- }, /*#__PURE__*/React.createElement("div", {
26859
- className: "answer-considered"
26860
- }, /*#__PURE__*/React.createElement("div", {
26955
+ className: css(styles$J.answerBody)
26956
+ }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
26861
26957
  onClick: this.toggleConsidered,
26862
- className: "answer-status " + this.props.considered
26863
- }, this.props.considered), /*#__PURE__*/React.createElement("div", {
26864
- className: "answer-expression"
26865
- }, /*#__PURE__*/React.createElement(Expression, this.props.expressionProps))), /*#__PURE__*/React.createElement("div", {
26866
- className: "answer-option"
26958
+ className: answerStatusCss
26959
+ }, this.props.considered), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Expression, this.props.expressionProps))), /*#__PURE__*/React.createElement("div", {
26960
+ className: css(styles$J.paddedY, styles$J.paddedX)
26867
26961
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
26868
26962
  label: "Answer expression must have the same form.",
26869
26963
  checked: this.props.form,
@@ -26873,7 +26967,7 @@ class AnswerOption extends React.Component {
26873
26967
  });
26874
26968
  }
26875
26969
  }), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "The student's answer must be in the same form. Commutativity and excess negative signs are ignored."))), /*#__PURE__*/React.createElement("div", {
26876
- className: "answer-option"
26970
+ className: css(styles$J.paddedY, styles$J.paddedX)
26877
26971
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
26878
26972
  label: "Answer expression must be fully expanded and simplified.",
26879
26973
  checked: this.props.simplify,
@@ -26883,10 +26977,53 @@ class AnswerOption extends React.Component {
26883
26977
  });
26884
26978
  }
26885
26979
  }), /*#__PURE__*/React.createElement(InfoTip$i, null, /*#__PURE__*/React.createElement("p", null, "The student's answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response \"Your answer is not fully expanded and simplified.\""))), /*#__PURE__*/React.createElement("div", {
26886
- className: "remove-container"
26980
+ className: css(styles$J.buttonRow, styles$J.paddedY)
26887
26981
  }, removeButton)));
26888
26982
  }
26889
26983
  }
26984
+ const styles$J = StyleSheet.create({
26985
+ paddedX: {
26986
+ paddingLeft: spacing.xSmall_8,
26987
+ paddingRight: spacing.xSmall_8
26988
+ },
26989
+ paddedY: {
26990
+ paddingTop: spacing.xxSmall_6,
26991
+ paddingBottom: spacing.xxSmall_6
26992
+ },
26993
+ answerOption: {
26994
+ border: "1px solid #ddd",
26995
+ borderRadius: "3px",
26996
+ display: "flex"
26997
+ },
26998
+ answerHandle: {
26999
+ // textured draggy handle
27000
+ background: "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==) no-repeat 50% 50%",
27001
+ borderRight: "1px solid #ddd",
27002
+ cursor: "move",
27003
+ width: "20px",
27004
+ minWidth: "20px"
27005
+ },
27006
+ answerStatus: {
27007
+ border: "none",
27008
+ userSelect: "none",
27009
+ width: "100px",
27010
+ paddingTop: spacing.small_12,
27011
+ paddingBottom: spacing.small_12
27012
+ },
27013
+ answerStatusWrong: {
27014
+ backgroundColor: color.fadedRed16
27015
+ },
27016
+ answerStatusCorrect: {
27017
+ backgroundColor: color.fadedGreen16
27018
+ },
27019
+ answerStatusUngraded: {
27020
+ backgroundColor: color.fadedBlue16
27021
+ },
27022
+ answerBody: {},
27023
+ buttonRow: {
27024
+ display: "flex"
27025
+ }
27026
+ });
26890
27027
 
26891
27028
  const {
26892
27029
  InlineIcon: InlineIcon$3,
@@ -26939,10 +27076,10 @@ class GradedGroupEditor extends React.Component {
26939
27076
  }, /*#__PURE__*/React.createElement("div", {
26940
27077
  className: "perseus-widget-row"
26941
27078
  }, /*#__PURE__*/React.createElement("label", {
26942
- className: css(styles$J.title)
27079
+ className: css(styles$I.title)
26943
27080
  }, "Title:", " ", /*#__PURE__*/React.createElement(TextInput$6, {
26944
27081
  value: this.props.title,
26945
- className: css(styles$J.input)
27082
+ className: css(styles$I.input)
26946
27083
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26947
27084
  ,
26948
27085
  onChange: this.change("title")
@@ -26967,7 +27104,7 @@ class GradedGroupEditor extends React.Component {
26967
27104
  }, /*#__PURE__*/React.createElement(InlineIcon$3, iconPlus$1), " Add a hint"), this.props.hint && /*#__PURE__*/React.createElement("div", {
26968
27105
  className: "perseus-hint-editor"
26969
27106
  }, /*#__PURE__*/React.createElement("div", {
26970
- className: css(styles$J.hintsTitle)
27107
+ className: css(styles$I.hintsTitle)
26971
27108
  }, "Hint"), /*#__PURE__*/React.createElement(Editor, {
26972
27109
  ref: this.hintEditor,
26973
27110
  content: this.props.hint ? this.props.hint.content : "",
@@ -27004,7 +27141,7 @@ GradedGroupEditor.defaultProps = {
27004
27141
  images: {},
27005
27142
  hint: null
27006
27143
  };
27007
- const styles$J = StyleSheet.create({
27144
+ const styles$I = StyleSheet.create({
27008
27145
  title: {
27009
27146
  fontSize: 18,
27010
27147
  fontWeight: "bold"
@@ -28359,13 +28496,13 @@ function MathquillInput(props) {
28359
28496
  }
28360
28497
  });
28361
28498
  return /*#__PURE__*/React.createElement(View, {
28362
- style: styles$I.outerWrapper
28499
+ style: styles$H.outerWrapper
28363
28500
  }, /*#__PURE__*/React.createElement("span", {
28364
28501
  ref: mathFieldWrapperRef,
28365
28502
  className: "perseus-math-input mq-editable-field mq-math-mode"
28366
28503
  }));
28367
28504
  }
28368
- const styles$I = StyleSheet.create({
28505
+ const styles$H = StyleSheet.create({
28369
28506
  outerWrapper: {
28370
28507
  display: "inline-block",
28371
28508
  borderStyle: "solid",
@@ -29411,16 +29548,16 @@ const LabeledRow = props => {
29411
29548
  style
29412
29549
  } = props;
29413
29550
  return /*#__PURE__*/React.createElement("label", {
29414
- className: css(styles$H.label)
29551
+ className: css(styles$G.label)
29415
29552
  }, /*#__PURE__*/React.createElement(View, {
29416
- style: [styles$H.row, style]
29553
+ style: [styles$G.row, style]
29417
29554
  }, labelSide === "start" || /*#__PURE__*/React.createElement(LabelSmall, {
29418
- style: styles$H.spaceEnd
29555
+ style: styles$G.spaceEnd
29419
29556
  }, label), children, labelSide === "end" && /*#__PURE__*/React.createElement(LabelSmall, {
29420
- style: styles$H.spaceStart
29557
+ style: styles$G.spaceStart
29421
29558
  }, label)));
29422
29559
  };
29423
- const styles$H = StyleSheet.create({
29560
+ const styles$G = StyleSheet.create({
29424
29561
  label: {
29425
29562
  width: "fit-content"
29426
29563
  },
@@ -29438,98 +29575,6 @@ const styles$H = StyleSheet.create({
29438
29575
  }
29439
29576
  });
29440
29577
 
29441
- const mediaDefaultSpecLargeMarginWidth = spacing.large_24;
29442
- const MEDIA_DEFAULT_SPEC = {
29443
- small: {
29444
- query: "(max-width: 767px)",
29445
- totalColumns: 4,
29446
- gutterWidth: spacing.medium_16,
29447
- marginWidth: spacing.medium_16
29448
- },
29449
- medium: {
29450
- query: "(min-width: 768px) and (max-width: 1023px)",
29451
- totalColumns: 8,
29452
- gutterWidth: spacing.xLarge_32,
29453
- marginWidth: spacing.large_24
29454
- },
29455
- large: {
29456
- query: "(min-width: 1024px)",
29457
- totalColumns: 12,
29458
- gutterWidth: spacing.xLarge_32,
29459
- marginWidth: mediaDefaultSpecLargeMarginWidth,
29460
- maxWidth: 1120 + mediaDefaultSpecLargeMarginWidth * 2
29461
- }
29462
- };
29463
- ({
29464
- large: {
29465
- query: "(min-width: 1px)",
29466
- totalColumns: 12,
29467
- gutterWidth: spacing.xLarge_32,
29468
- marginWidth: spacing.medium_16
29469
- }
29470
- });
29471
- ({
29472
- small: {
29473
- query: "(max-width: 767px)",
29474
- totalColumns: 4,
29475
- gutterWidth: spacing.medium_16,
29476
- marginWidth: spacing.medium_16
29477
- },
29478
- large: {
29479
- query: "(min-width: 768px)",
29480
- totalColumns: 12,
29481
- gutterWidth: spacing.xLarge_32,
29482
- marginWidth: spacing.xxLarge_48
29483
- }
29484
- });
29485
-
29486
- const defaultContext = {
29487
- ssrSize: "large",
29488
- mediaSpec: MEDIA_DEFAULT_SPEC
29489
- };
29490
- const MediaLayoutContext = React.createContext(defaultContext);
29491
- MediaLayoutContext.displayName = "MediaLayoutContext";
29492
-
29493
- class Spring extends React.Component {
29494
- render() {
29495
- const {
29496
- style
29497
- } = this.props;
29498
- return React.createElement(View, {
29499
- "aria-hidden": "true",
29500
- style: [styles$G.grow, style]
29501
- });
29502
- }
29503
- }
29504
- const styles$G = StyleSheet.create({
29505
- grow: {
29506
- flexGrow: 1
29507
- }
29508
- });
29509
-
29510
- class Strut extends React.Component {
29511
- render() {
29512
- const {
29513
- size,
29514
- style
29515
- } = this.props;
29516
- return React.createElement(View, {
29517
- "aria-hidden": "true",
29518
- style: [strutStyle(size), style]
29519
- });
29520
- }
29521
- }
29522
- const strutStyle = size => {
29523
- return {
29524
- width: size,
29525
- MsFlexBasis: size,
29526
- MsFlexPreferredSize: size,
29527
- WebkitFlexBasis: size,
29528
- flexBasis: size,
29529
- flexShrink: 0
29530
- };
29531
- };
29532
-
29533
29578
  function Heading({
29534
29579
  title,
29535
29580
  isOpen,
@@ -31942,6 +31987,29 @@ const StartCoordsCircle = props => {
31942
31987
  startCoords,
31943
31988
  onChange
31944
31989
  } = props;
31990
+ const [radiusState, setRadiusState] = React.useState(startCoords.radius.toString());
31991
+
31992
+ // Update the local state when the props change. (Specifically, when
31993
+ // the radius is reset from the "Use default start coordinates" button.)
31994
+ React.useEffect(() => {
31995
+ setRadiusState(startCoords.radius.toString());
31996
+ }, [startCoords.radius]);
31997
+ function handleRadiuschange(newValue) {
31998
+ // Update the local state to update the input field.
31999
+ setRadiusState(newValue);
32000
+
32001
+ // Assume the user is in the middle of typing. Don't update
32002
+ // the props until they've finished typing a valid number.
32003
+ if (isNaN(+newValue) || newValue === "" || +newValue === 0) {
32004
+ return;
32005
+ }
32006
+
32007
+ // Update the props (update the graph).
32008
+ onChange({
32009
+ center: startCoords.center,
32010
+ radius: parseFloat(newValue)
32011
+ });
32012
+ }
31945
32013
  return /*#__PURE__*/React.createElement(View, {
31946
32014
  style: styles$g.tile
31947
32015
  }, /*#__PURE__*/React.createElement(View, {
@@ -31957,18 +32025,14 @@ const StartCoordsCircle = props => {
31957
32025
  })
31958
32026
  })), /*#__PURE__*/React.createElement(Strut, {
31959
32027
  size: spacing.small_12
31960
- }), /*#__PURE__*/React.createElement(View, {
32028
+ }), /*#__PURE__*/React.createElement(LabelLarge, {
32029
+ tag: "label",
31961
32030
  style: styles$g.row
31962
- }, /*#__PURE__*/React.createElement(LabelLarge, null, "Radius:"), /*#__PURE__*/React.createElement(Strut, {
32031
+ }, "Radius:", /*#__PURE__*/React.createElement(Strut, {
31963
32032
  size: spacing.small_12
31964
32033
  }), /*#__PURE__*/React.createElement(ScrolllessNumberTextField, {
31965
- value: startCoords.radius.toString(),
31966
- onChange: value => {
31967
- onChange({
31968
- center: startCoords.center,
31969
- radius: parseFloat(value)
31970
- });
31971
- },
32034
+ value: radiusState,
32035
+ onChange: handleRadiuschange,
31972
32036
  style: styles$g.textField
31973
32037
  })));
31974
32038
  };
@@ -31980,6 +32044,7 @@ const styles$g = StyleSheet.create({
31980
32044
  borderRadius: spacing.xSmall_8
31981
32045
  },
31982
32046
  row: {
32047
+ display: "flex",
31983
32048
  flexDirection: "row",
31984
32049
  alignItems: "center"
31985
32050
  },
@@ -35121,7 +35186,7 @@ class NumericInputEditor extends React.Component {
35121
35186
  }));
35122
35187
  const labelText = /*#__PURE__*/React.createElement("div", {
35123
35188
  className: "perseus-widget-row"
35124
- }, /*#__PURE__*/React.createElement("label", null, "Label text:", " ", /*#__PURE__*/React.createElement(TextInput$3, {
35189
+ }, /*#__PURE__*/React.createElement("label", null, "Aria label", /*#__PURE__*/React.createElement(TextInput$3, {
35125
35190
  value: this.props.labelText,
35126
35191
  onChange: this.change("labelText")
35127
35192
  })), /*#__PURE__*/React.createElement(InfoTip$7, null, /*#__PURE__*/React.createElement("p", null, "Text to describe this input. This will be shown to users using screenreaders.")));
@@ -35265,11 +35330,11 @@ class NumericInputEditor extends React.Component {
35265
35330
  });
35266
35331
  return /*#__PURE__*/React.createElement("div", {
35267
35332
  className: "perseus-input-number-editor"
35268
- }, /*#__PURE__*/React.createElement("div", {
35333
+ }, labelText, inputSize, rightAlign, coefficientCheck, /*#__PURE__*/React.createElement("div", {
35269
35334
  className: "ui-title"
35270
35335
  }, "User input"), /*#__PURE__*/React.createElement("div", {
35271
35336
  className: "msg-title"
35272
- }, "Message shown to user on attempt"), generateInputAnswerEditors(), addAnswerButton, inputSize, rightAlign, coefficientCheck, labelText);
35337
+ }, "Message shown to user on attempt"), generateInputAnswerEditors(), addAnswerButton);
35273
35338
  }
35274
35339
  }
35275
35340
  NumericInputEditor.contextType = PerseusI18nContext;