@khanacademy/perseus-editor 5.0.2 → 5.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/index.js CHANGED
@@ -21,8 +21,13 @@ var kmath = require('@khanacademy/kmath');
21
21
  var KAS = require('@khanacademy/kas');
22
22
  var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
23
23
  var mathInput = require('@khanacademy/math-input');
24
+ var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
25
+ var wonderBlocksForm = require('@khanacademy/wonder-blocks-form');
24
26
  var Spacing = require('@khanacademy/wonder-blocks-spacing');
25
- var Typography = require('@khanacademy/wonder-blocks-typography');
27
+ var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
28
+ var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
29
+ var IconButton = require('@khanacademy/wonder-blocks-icon-button');
30
+ var trashIcon = require('@phosphor-icons/core/bold/trash-bold.svg');
26
31
  var Button = require('@khanacademy/wonder-blocks-button');
27
32
  var i18n$1 = require('@khanacademy/wonder-blocks-i18n');
28
33
 
@@ -58,13 +63,14 @@ var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
58
63
  var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
59
64
  var KAS__namespace = /*#__PURE__*/_interopNamespace(KAS);
60
65
  var Spacing__default = /*#__PURE__*/_interopDefaultLegacy(Spacing);
61
- var Typography__namespace = /*#__PURE__*/_interopNamespace(Typography);
66
+ var IconButton__default = /*#__PURE__*/_interopDefaultLegacy(IconButton);
67
+ var trashIcon__default = /*#__PURE__*/_interopDefaultLegacy(trashIcon);
62
68
  var Button__default = /*#__PURE__*/_interopDefaultLegacy(Button);
63
69
  var i18n__namespace = /*#__PURE__*/_interopNamespace(i18n$1);
64
70
 
65
71
  // This file is processed by a Rollup plugin (replace) to inject the production
66
72
  const libName = "@khanacademy/perseus-editor";
67
- const libVersion = "5.0.2";
73
+ const libVersion = "5.1.0";
68
74
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
69
75
 
70
76
  function _extends() {
@@ -258,13 +264,13 @@ class SectionControlButton extends React__namespace.Component {
258
264
  role: "button",
259
265
  hideDefaultFocusRing: true,
260
266
  "aria-label": title,
261
- style: styles$g.button
267
+ style: styles$q.button
262
268
  }, _ref => {
263
269
  return /*#__PURE__*/React__namespace.createElement(InlineIcon$b, icon);
264
270
  });
265
271
  }
266
272
  }
267
- const styles$g = aphrodite.StyleSheet.create({
273
+ const styles$q = aphrodite.StyleSheet.create({
268
274
  button: {
269
275
  backgroundColor: Color__default["default"].gold,
270
276
  margin: 2,
@@ -20782,19 +20788,19 @@ class TexErrorView extends React__namespace.Component {
20782
20788
  const {
20783
20789
  showErrors
20784
20790
  } = this.state;
20785
- const iconStyle = showErrors ? styles$f.iconExpanded : styles$f.iconCollapsed;
20791
+ const iconStyle = showErrors ? styles$p.iconExpanded : styles$p.iconCollapsed;
20786
20792
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
20787
- style: styles$f.errorContainer
20793
+ style: styles$p.errorContainer
20788
20794
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
20789
- style: styles$f.title,
20795
+ style: styles$p.title,
20790
20796
  onClick: this.handleToggleTexErrors
20791
20797
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
20792
20798
  icon: caretRight__default["default"],
20793
20799
  style: iconStyle
20794
20800
  }), "\xA0 TeX Errors (", errorList.length, ")"), showErrors && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
20795
- style: styles$f.errorExplanation
20801
+ style: styles$p.errorExplanation
20796
20802
  }, "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, {
20797
- style: styles$f.error,
20803
+ style: styles$p.error,
20798
20804
  key: index
20799
20805
  }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
20800
20806
  style: {
@@ -20803,7 +20809,7 @@ class TexErrorView extends React__namespace.Component {
20803
20809
  }, e.math), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, e.message))));
20804
20810
  }
20805
20811
  }
20806
- const styles$f = aphrodite.StyleSheet.create({
20812
+ const styles$p = aphrodite.StyleSheet.create({
20807
20813
  title: {
20808
20814
  backgroundColor: "#eee",
20809
20815
  fontSize: "1.25em",
@@ -24581,12 +24587,12 @@ class SimpleButton extends React__namespace.Component {
24581
24587
  ...otherProps
24582
24588
  } = this.props;
24583
24589
  return /*#__PURE__*/React__namespace.createElement("div", _extends({
24584
- className: aphrodite.css(styles$e.baseButton, color === "green" && styles$e.green, color === "orange" && styles$e.orange),
24590
+ className: aphrodite.css(styles$o.baseButton, color === "green" && styles$o.green, color === "orange" && styles$o.orange),
24585
24591
  onClick: onClick
24586
24592
  }, otherProps), children);
24587
24593
  }
24588
24594
  }
24589
- const styles$e = aphrodite.StyleSheet.create({
24595
+ const styles$o = aphrodite.StyleSheet.create({
24590
24596
  baseButton: {
24591
24597
  top: "0",
24592
24598
  fontSize: "11px",
@@ -24799,23 +24805,23 @@ const LeafContainer = _ref2 => {
24799
24805
  } = _ref2;
24800
24806
  const hasPreviewHeading = shape.type === "content" || shape.type === "hint";
24801
24807
  const previewHeading = hasPreviewHeading && /*#__PURE__*/React__namespace.createElement("div", {
24802
- className: aphrodite.css(styles$d.containerHeader)
24808
+ className: aphrodite.css(styles$n.containerHeader)
24803
24809
  }, /*#__PURE__*/React__namespace.createElement(Header, {
24804
24810
  depth: path.length,
24805
- className: aphrodite.css(styles$d.containerTitle)
24811
+ className: aphrodite.css(styles$n.containerTitle)
24806
24812
  }, capitalize(name)));
24807
24813
  return /*#__PURE__*/React__namespace.createElement("div", {
24808
- className: aphrodite.css(styles$d.container)
24814
+ className: aphrodite.css(styles$n.container)
24809
24815
  }, /*#__PURE__*/React__namespace.createElement("span", {
24810
- className: aphrodite.css(styles$d.row, styles$d.rowHeading)
24816
+ className: aphrodite.css(styles$n.row, styles$n.rowHeading)
24811
24817
  }, /*#__PURE__*/React__namespace.createElement("div", {
24812
- className: aphrodite.css(styles$d.columnLeft)
24818
+ className: aphrodite.css(styles$n.columnLeft)
24813
24819
  }, /*#__PURE__*/React__namespace.createElement("div", {
24814
- className: "pod-title " + aphrodite.css(styles$d.containerHeader)
24820
+ className: "pod-title " + aphrodite.css(styles$n.containerHeader)
24815
24821
  }, /*#__PURE__*/React__namespace.createElement("div", {
24816
- className: aphrodite.css(styles$d.containerTitle)
24822
+ className: aphrodite.css(styles$n.containerTitle)
24817
24823
  }, capitalize(name)), controls)), /*#__PURE__*/React__namespace.createElement("div", {
24818
- className: aphrodite.css(styles$d.columnRight)
24824
+ className: aphrodite.css(styles$n.columnRight)
24819
24825
  }, previewHeading)), children);
24820
24826
  };
24821
24827
  const ArrayContainer = props => {
@@ -24828,11 +24834,11 @@ const ArrayContainer = props => {
24828
24834
  actions
24829
24835
  } = props;
24830
24836
  return /*#__PURE__*/React__namespace.createElement("div", {
24831
- className: aphrodite.css(styles$d.container)
24837
+ className: aphrodite.css(styles$n.container)
24832
24838
  }, controls && /*#__PURE__*/React__namespace.createElement("div", {
24833
- className: aphrodite.css(styles$d.columnLeft, styles$d.containerHeader)
24839
+ className: aphrodite.css(styles$n.columnLeft, styles$n.containerHeader)
24834
24840
  }, controls), /*#__PURE__*/React__namespace.createElement("div", null, children), /*#__PURE__*/React__namespace.createElement("div", {
24835
- className: aphrodite.css(styles$d.columnLeft)
24841
+ className: aphrodite.css(styles$n.columnLeft)
24836
24842
  }, /*#__PURE__*/React__namespace.createElement("a", {
24837
24843
  href: "javascript:void 0",
24838
24844
  onClick: () => actions.addArrayElement(path, shape.elementShape)
@@ -24846,28 +24852,28 @@ const ObjectContainer = _ref3 => {
24846
24852
  path
24847
24853
  } = _ref3;
24848
24854
  const headingEditor = /*#__PURE__*/React__namespace.createElement("div", {
24849
- className: aphrodite.css(styles$d.containerHeader)
24855
+ className: aphrodite.css(styles$n.containerHeader)
24850
24856
  }, /*#__PURE__*/React__namespace.createElement(Header, {
24851
24857
  depth: path.length,
24852
- className: aphrodite.css(styles$d.containerTitle)
24858
+ className: aphrodite.css(styles$n.containerTitle)
24853
24859
  }, capitalize(name)), controls);
24854
24860
  const headingPreview = (name || controls) && /*#__PURE__*/React__namespace.createElement("div", {
24855
- className: aphrodite.css(styles$d.containerHeader, styles$d.previewCollectionHeader)
24861
+ className: aphrodite.css(styles$n.containerHeader, styles$n.previewCollectionHeader)
24856
24862
  }, /*#__PURE__*/React__namespace.createElement(Header, {
24857
24863
  depth: path.length,
24858
- className: aphrodite.css(styles$d.containerTitle)
24864
+ className: aphrodite.css(styles$n.containerTitle)
24859
24865
  }, capitalize(name)));
24860
24866
  const hasBothHeadings = headingEditor && headingPreview;
24861
24867
  return /*#__PURE__*/React__namespace.createElement("div", {
24862
- className: aphrodite.css(styles$d.container)
24868
+ className: aphrodite.css(styles$n.container)
24863
24869
  }, hasBothHeadings && /*#__PURE__*/React__namespace.createElement("span", {
24864
- className: aphrodite.css(styles$d.row)
24870
+ className: aphrodite.css(styles$n.row)
24865
24871
  }, /*#__PURE__*/React__namespace.createElement("div", {
24866
- className: aphrodite.css(styles$d.columnLeft)
24872
+ className: aphrodite.css(styles$n.columnLeft)
24867
24873
  }, headingEditor), /*#__PURE__*/React__namespace.createElement("div", {
24868
- className: aphrodite.css(styles$d.columnRight)
24874
+ className: aphrodite.css(styles$n.columnRight)
24869
24875
  }, headingPreview)), /*#__PURE__*/React__namespace.createElement("div", {
24870
- className: aphrodite.css(path.length > 0 && styles$d.contentIndent)
24876
+ className: aphrodite.css(path.length > 0 && styles$n.contentIndent)
24871
24877
  }, children));
24872
24878
  };
24873
24879
 
@@ -24987,11 +24993,11 @@ const ItemNodeContent = withStickiness(props => {
24987
24993
  className: "framework-perseus"
24988
24994
  }, lens(renderers).get(path));
24989
24995
  return /*#__PURE__*/React__namespace.createElement("span", null, /*#__PURE__*/React__namespace.createElement("div", {
24990
- className: aphrodite.css(styles$d.row)
24996
+ className: aphrodite.css(styles$n.row)
24991
24997
  }, /*#__PURE__*/React__namespace.createElement("div", {
24992
- className: aphrodite.css(styles$d.columnLeft)
24998
+ className: aphrodite.css(styles$n.columnLeft)
24993
24999
  }, /*#__PURE__*/React__namespace.createElement("div", {
24994
- className: aphrodite.css(sticky && styles$d.sticky)
25000
+ className: aphrodite.css(sticky && styles$n.sticky)
24995
25001
  },
24996
25002
  /*#__PURE__*/
24997
25003
  // @ts-expect-error - TS2769 - No overload matches this call.
@@ -24999,9 +25005,9 @@ const ItemNodeContent = withStickiness(props => {
24999
25005
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25000
25006
  apiOptions: apiOptions
25001
25007
  })))), /*#__PURE__*/React__namespace.createElement("div", {
25002
- className: aphrodite.css(styles$d.columnRight)
25008
+ className: aphrodite.css(styles$n.columnRight)
25003
25009
  }, /*#__PURE__*/React__namespace.createElement("div", {
25004
- className: aphrodite.css(sticky && styles$d.sticky)
25010
+ className: aphrodite.css(sticky && styles$n.sticky)
25005
25011
  }, preview))));
25006
25012
  });
25007
25013
  const HintNodeContent = withStickiness(props => {
@@ -25017,13 +25023,13 @@ const HintNodeContent = withStickiness(props => {
25017
25023
  className: "framework-perseus"
25018
25024
  }, lens(renderers).get(path));
25019
25025
  return /*#__PURE__*/React__namespace.createElement("div", {
25020
- className: aphrodite.css(styles$d.row)
25026
+ className: aphrodite.css(styles$n.row)
25021
25027
  }, /*#__PURE__*/React__namespace.createElement("div", {
25022
- className: aphrodite.css(styles$d.columnLeft)
25028
+ className: aphrodite.css(styles$n.columnLeft)
25023
25029
  }, /*#__PURE__*/React__namespace.createElement("div", {
25024
- className: aphrodite.css(sticky && styles$d.sticky)
25030
+ className: aphrodite.css(sticky && styles$n.sticky)
25025
25031
  }, /*#__PURE__*/React__namespace.createElement(HintEditor, _extends({}, data, {
25026
- className: aphrodite.css(styles$d.hintEditor),
25032
+ className: aphrodite.css(styles$n.hintEditor),
25027
25033
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25028
25034
  apiOptions: apiOptions,
25029
25035
  showTitle: false,
@@ -25038,9 +25044,9 @@ const HintNodeContent = withStickiness(props => {
25038
25044
  isFirst: true,
25039
25045
  isLast: true
25040
25046
  })))), /*#__PURE__*/React__namespace.createElement("div", {
25041
- className: aphrodite.css(styles$d.columnRight)
25047
+ className: aphrodite.css(styles$n.columnRight)
25042
25048
  }, /*#__PURE__*/React__namespace.createElement("div", {
25043
- className: aphrodite.css(sticky && styles$d.sticky)
25049
+ className: aphrodite.css(sticky && styles$n.sticky)
25044
25050
  }, preview)));
25045
25051
  });
25046
25052
  const TagsNodeContent = props => {
@@ -25057,9 +25063,9 @@ const TagsNodeContent = props => {
25057
25063
  return null;
25058
25064
  }
25059
25065
  return /*#__PURE__*/React__namespace.createElement("div", {
25060
- className: aphrodite.css(styles$d.columnLeft)
25066
+ className: aphrodite.css(styles$n.columnLeft)
25061
25067
  }, /*#__PURE__*/React__namespace.createElement("div", {
25062
- className: aphrodite.css(styles$d.tagsEditor)
25068
+ className: aphrodite.css(styles$n.tagsEditor)
25063
25069
  }, /*#__PURE__*/React__namespace.createElement(GroupMetadataEditor, {
25064
25070
  value: data,
25065
25071
  onChange: newVal => actions.setValueAtPath(path, newVal),
@@ -25090,23 +25096,23 @@ const ArrayNodeContent = props => {
25090
25096
  const subpath = path.concat(i);
25091
25097
  const controls = [i > 0 && /*#__PURE__*/React__namespace.createElement("div", {
25092
25098
  key: "moveArrayElementUp",
25093
- className: aphrodite.css(styles$d.control)
25099
+ className: aphrodite.css(styles$n.control)
25094
25100
  }, /*#__PURE__*/React__namespace.createElement(SimpleButton, {
25095
25101
  color: "orange",
25096
25102
  title: "Move up",
25097
25103
  onClick: () => actions.moveArrayElementUp(subpath)
25098
25104
  }, /*#__PURE__*/React__namespace.createElement("div", {
25099
- className: aphrodite.css(styles$d.verticalFlip)
25105
+ className: aphrodite.css(styles$n.verticalFlip)
25100
25106
  }, /*#__PURE__*/React__namespace.createElement(InlineIcon$6, iconChevronDown)))), i < data.length - 1 && /*#__PURE__*/React__namespace.createElement("div", {
25101
25107
  key: "moveArrayElementDown",
25102
- className: aphrodite.css(styles$d.control)
25108
+ className: aphrodite.css(styles$n.control)
25103
25109
  }, /*#__PURE__*/React__namespace.createElement(SimpleButton, {
25104
25110
  color: "orange",
25105
25111
  title: "Move down",
25106
25112
  onClick: () => actions.moveArrayElementDown(subpath)
25107
25113
  }, /*#__PURE__*/React__namespace.createElement(InlineIcon$6, iconChevronDown))), /*#__PURE__*/React__namespace.createElement("div", {
25108
25114
  key: "removeArrayElement",
25109
- className: aphrodite.css(styles$d.control)
25115
+ className: aphrodite.css(styles$n.control)
25110
25116
  }, /*#__PURE__*/React__namespace.createElement(SimpleButton, {
25111
25117
  color: "orange",
25112
25118
  title: "Delete",
@@ -25114,7 +25120,7 @@ const ArrayNodeContent = props => {
25114
25120
  }, /*#__PURE__*/React__namespace.createElement(InlineIcon$6, iconTrash$4)))];
25115
25121
  return /*#__PURE__*/React__namespace.createElement("div", {
25116
25122
  key: i,
25117
- className: aphrodite.css(styles$d.arrayElement, !elementIsLeaf && styles$d.arrayElementAndNotLeaf)
25123
+ className: aphrodite.css(styles$n.arrayElement, !elementIsLeaf && styles$n.arrayElementAndNotLeaf)
25118
25124
  }, /*#__PURE__*/React__namespace.createElement(NodeContainer, _extends({}, otherProps, {
25119
25125
  key: i,
25120
25126
  shape: shape.elementShape,
@@ -25140,7 +25146,7 @@ const ObjectNodeContent = props => {
25140
25146
  // made sense to the shape's author is the order in which we'll iterate :)
25141
25147
  const children = Object.keys(shape.shape).map(subkey => /*#__PURE__*/React__namespace.createElement("div", {
25142
25148
  key: subkey,
25143
- className: aphrodite.css(styles$d.objectElement)
25149
+ className: aphrodite.css(styles$n.objectElement)
25144
25150
  }, /*#__PURE__*/React__namespace.createElement(NodeContainer, _extends({}, otherProps, {
25145
25151
  shape: shape.shape[subkey],
25146
25152
  data: data[subkey],
@@ -25309,7 +25315,7 @@ class MultiRendererEditor extends React__namespace.Component {
25309
25315
  }, this._renderContent());
25310
25316
  }
25311
25317
  }
25312
- const styles$d = aphrodite.StyleSheet.create({
25318
+ const styles$n = aphrodite.StyleSheet.create({
25313
25319
  // This is used in a number of places throughout this file.
25314
25320
  container: {},
25315
25321
  // eslint-disable-next-line react-native/no-unused-styles
@@ -25461,47 +25467,47 @@ const StatefulArticleEditor = createReactClass__default["default"]({
25461
25467
  screen
25462
25468
  } = this.state;
25463
25469
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
25464
- style: styles$c.controlBar
25470
+ style: styles$m.controlBar
25465
25471
  }, /*#__PURE__*/React__namespace.createElement("span", {
25466
- style: styles$c.controls
25472
+ style: styles$m.controls
25467
25473
  }, "Mode:", " ", /*#__PURE__*/React__namespace.createElement("span", {
25468
25474
  onClick: () => this.setState({
25469
25475
  mode: "edit"
25470
25476
  }),
25471
- style: mode === "edit" ? styles$c.controlSelected : styles$c.control
25477
+ style: mode === "edit" ? styles$m.controlSelected : styles$m.control
25472
25478
  }, "EDIT"), " | ", /*#__PURE__*/React__namespace.createElement("span", {
25473
25479
  onClick: () => this.setState({
25474
25480
  mode: "preview"
25475
25481
  }),
25476
- style: mode === "preview" ? styles$c.controlSelected : styles$c.control
25482
+ style: mode === "preview" ? styles$m.controlSelected : styles$m.control
25477
25483
  }, "PREVIEW"), " | ", /*#__PURE__*/React__namespace.createElement("span", {
25478
25484
  onClick: () => this.setState({
25479
25485
  mode: "json"
25480
25486
  }),
25481
- style: mode === "json" ? styles$c.controlSelected : styles$c.control
25487
+ style: mode === "json" ? styles$m.controlSelected : styles$m.control
25482
25488
  }, "JSON")), /*#__PURE__*/React__namespace.createElement("span", {
25483
- style: styles$c.controls
25489
+ style: styles$m.controls
25484
25490
  }, "Screen:", " ", /*#__PURE__*/React__namespace.createElement("span", {
25485
25491
  onClick: () => this.setState({
25486
25492
  screen: "phone"
25487
25493
  }),
25488
- style: screen === "phone" ? styles$c.controlSelected : styles$c.control
25494
+ style: screen === "phone" ? styles$m.controlSelected : styles$m.control
25489
25495
  }, "PHONE"), " | ", /*#__PURE__*/React__namespace.createElement("span", {
25490
25496
  onClick: () => this.setState({
25491
25497
  screen: "tablet"
25492
25498
  }),
25493
- style: screen === "tablet" ? styles$c.controlSelected : styles$c.control
25499
+ style: screen === "tablet" ? styles$m.controlSelected : styles$m.control
25494
25500
  }, "TABLET"), " | ", /*#__PURE__*/React__namespace.createElement("span", {
25495
25501
  onClick: () => this.setState({
25496
25502
  screen: "desktop"
25497
25503
  }),
25498
- style: screen === "desktop" ? styles$c.controlSelected : styles$c.control
25504
+ style: screen === "desktop" ? styles$m.controlSelected : styles$m.control
25499
25505
  }, "DESKTOP"))), /*#__PURE__*/React__namespace.createElement("div", {
25500
- style: styles$c.editor
25506
+ style: styles$m.editor
25501
25507
  }, /*#__PURE__*/React__namespace.createElement(ArticleEditor, this.state)));
25502
25508
  }
25503
25509
  });
25504
- const styles$c = {
25510
+ const styles$m = {
25505
25511
  controlBar: {
25506
25512
  marginBottom: 25,
25507
25513
  marginTop: 5
@@ -27039,10 +27045,10 @@ class GradedGroupEditor extends React__namespace.Component {
27039
27045
  }, /*#__PURE__*/React__namespace.createElement("div", {
27040
27046
  className: "perseus-widget-row"
27041
27047
  }, /*#__PURE__*/React__namespace.createElement("label", {
27042
- className: aphrodite.css(styles$b.title)
27048
+ className: aphrodite.css(styles$l.title)
27043
27049
  }, "Title:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$6, {
27044
27050
  value: this.props.title,
27045
- className: aphrodite.css(styles$b.input)
27051
+ className: aphrodite.css(styles$l.input)
27046
27052
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
27047
27053
  ,
27048
27054
  onChange: this.change("title")
@@ -27067,7 +27073,7 @@ class GradedGroupEditor extends React__namespace.Component {
27067
27073
  }, /*#__PURE__*/React__namespace.createElement(InlineIcon$4, iconPlus$1), " Add a hint"), this.props.hint && /*#__PURE__*/React__namespace.createElement("div", {
27068
27074
  className: "perseus-hint-editor"
27069
27075
  }, /*#__PURE__*/React__namespace.createElement("div", {
27070
- className: aphrodite.css(styles$b.hintsTitle)
27076
+ className: aphrodite.css(styles$l.hintsTitle)
27071
27077
  }, "Hint"), /*#__PURE__*/React__namespace.createElement(Editor, {
27072
27078
  ref: this.hintEditor,
27073
27079
  content: this.props.hint ? this.props.hint.content : "",
@@ -27099,7 +27105,7 @@ class GradedGroupEditor extends React__namespace.Component {
27099
27105
  };
27100
27106
  };
27101
27107
  }
27102
- const styles$b = aphrodite.StyleSheet.create({
27108
+ const styles$l = aphrodite.StyleSheet.create({
27103
27109
  title: {
27104
27110
  fontSize: 18,
27105
27111
  fontWeight: "bold"
@@ -28462,13 +28468,13 @@ function MathquillInput(props) {
28462
28468
  }
28463
28469
  });
28464
28470
  return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
28465
- style: styles$a.outerWrapper
28471
+ style: styles$k.outerWrapper
28466
28472
  }, /*#__PURE__*/React__namespace.createElement("span", {
28467
28473
  ref: mathFieldWrapperRef,
28468
28474
  className: "perseus-math-input mq-editable-field mq-math-mode"
28469
28475
  }));
28470
28476
  }
28471
- const styles$a = aphrodite.StyleSheet.create({
28477
+ const styles$k = aphrodite.StyleSheet.create({
28472
28478
  outerWrapper: {
28473
28479
  display: "inline-block",
28474
28480
  borderStyle: "solid",
@@ -29546,48 +29552,113 @@ const GraphPointsCountSelector = _ref => {
29546
29552
  numPoints = 1,
29547
29553
  onChange
29548
29554
  } = _ref;
29549
- return /*#__PURE__*/React__namespace.createElement("select", {
29550
- value: numPoints,
29551
- onChange: e => {
29552
- onChange(parsePointCount(e.target.value));
29555
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
29556
+ selectedValue: `${numPoints}`,
29557
+ onChange: newValue => {
29558
+ onChange(parsePointCount(newValue));
29553
29559
  }
29554
- }, [...Array(7).keys()].map(n => /*#__PURE__*/React__namespace.createElement("option", {
29560
+ // Never uses placeholder, always has value
29561
+ ,
29562
+ placeholder: "",
29563
+ style: styles$j.singleSelectShort
29564
+ }, [...[...Array(7).keys()].map(n => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29555
29565
  key: n,
29556
- value: n
29557
- }, `${n} point${n > 1 ? "s" : ""}`)), /*#__PURE__*/React__namespace.createElement("option", {
29558
- value: UNLIMITED
29559
- }, "unlimited"));
29566
+ value: `${n}`,
29567
+ label: `${n} point${n > 1 ? "s" : ""}`
29568
+ })), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29569
+ value: UNLIMITED,
29570
+ label: "unlimited"
29571
+ })]);
29560
29572
  };
29573
+ const styles$j = aphrodite.StyleSheet.create({
29574
+ singleSelectShort: {
29575
+ // Non-standard spacing, but it's the smallest we can go
29576
+ // without running into styling issues with the dropdown.
29577
+ height: 26
29578
+ }
29579
+ });
29561
29580
 
29562
29581
  const GraphTypeSelector = props => {
29563
- return /*#__PURE__*/React__namespace.createElement("select", {
29564
- value: props.graphType,
29565
- onChange: e => {
29566
- const type = e.target.value;
29567
- props.onChange(type);
29568
- }
29569
- }, /*#__PURE__*/React__namespace.createElement("option", {
29570
- value: "linear"
29571
- }, "Linear function"), /*#__PURE__*/React__namespace.createElement("option", {
29572
- value: "quadratic"
29573
- }, "Quadratic function"), /*#__PURE__*/React__namespace.createElement("option", {
29574
- value: "sinusoid"
29575
- }, "Sinusoid function"), /*#__PURE__*/React__namespace.createElement("option", {
29576
- value: "circle"
29577
- }, "Circle"), /*#__PURE__*/React__namespace.createElement("option", {
29578
- value: "point"
29579
- }, "Point(s)"), /*#__PURE__*/React__namespace.createElement("option", {
29580
- value: "linear-system"
29581
- }, "Linear System"), /*#__PURE__*/React__namespace.createElement("option", {
29582
- value: "polygon"
29583
- }, "Polygon"), /*#__PURE__*/React__namespace.createElement("option", {
29584
- value: "segment"
29585
- }, "Line Segment(s)"), /*#__PURE__*/React__namespace.createElement("option", {
29586
- value: "ray"
29587
- }, "Ray"), /*#__PURE__*/React__namespace.createElement("option", {
29588
- value: "angle"
29589
- }, "Angle"));
29582
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
29583
+ selectedValue: props.graphType,
29584
+ onChange: props.onChange,
29585
+ placeholder: "Select a graph type",
29586
+ style: styles$i.singleSelectShort
29587
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29588
+ value: "linear",
29589
+ label: "Linear function"
29590
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29591
+ value: "quadratic",
29592
+ label: "Quadratic function"
29593
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29594
+ value: "sinusoid",
29595
+ label: "Sinusoid function"
29596
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29597
+ value: "circle",
29598
+ label: "Circle"
29599
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29600
+ value: "point",
29601
+ label: "Point(s)"
29602
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29603
+ value: "linear-system",
29604
+ label: "Linear System"
29605
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29606
+ value: "polygon",
29607
+ label: "Polygon"
29608
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29609
+ value: "segment",
29610
+ label: "Line Segment(s)"
29611
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29612
+ value: "ray",
29613
+ label: "Ray"
29614
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
29615
+ value: "angle",
29616
+ label: "Angle"
29617
+ }));
29618
+ };
29619
+ const styles$i = aphrodite.StyleSheet.create({
29620
+ singleSelectShort: {
29621
+ // Non-standard spacing, but it's the smallest we can go
29622
+ // without running into styling issues with the dropdown.
29623
+ height: 26
29624
+ }
29625
+ });
29626
+
29627
+ // Renders the given children in a View laid out horizontally.
29628
+ const LabeledRow = props => {
29629
+ const {
29630
+ children,
29631
+ label,
29632
+ labelSide = "left",
29633
+ style
29634
+ } = props;
29635
+ return /*#__PURE__*/React__namespace.createElement("label", {
29636
+ className: aphrodite.css(styles$h.label)
29637
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
29638
+ style: [styles$h.row, style]
29639
+ }, labelSide === "start" || /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
29640
+ style: styles$h.spaceEnd
29641
+ }, label), children, labelSide === "end" && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
29642
+ style: styles$h.spaceStart
29643
+ }, label)));
29590
29644
  };
29645
+ const styles$h = aphrodite.StyleSheet.create({
29646
+ label: {
29647
+ width: "fit-content"
29648
+ },
29649
+ row: {
29650
+ flexDirection: "row",
29651
+ marginTop: wonderBlocksTokens.spacing.xSmall_8,
29652
+ alignItems: "center",
29653
+ width: "fit-content"
29654
+ },
29655
+ spaceStart: {
29656
+ marginInlineStart: wonderBlocksTokens.spacing.xSmall_8
29657
+ },
29658
+ spaceEnd: {
29659
+ marginInlineEnd: wonderBlocksTokens.spacing.xSmall_8
29660
+ }
29661
+ });
29591
29662
 
29592
29663
  /* eslint-disable react/forbid-prop-types, react/no-unsafe */
29593
29664
  const {
@@ -29908,75 +29979,70 @@ class InteractiveGraphSettings extends React__namespace.Component {
29908
29979
  className: "perseus-widget-row"
29909
29980
  }, /*#__PURE__*/React__namespace.createElement("div", {
29910
29981
  className: "perseus-widget-left-col"
29911
- }, /*#__PURE__*/React__namespace.createElement("label", {
29912
- htmlFor: "labels-x"
29913
- }, "x Label"), /*#__PURE__*/React__namespace.createElement("input", {
29914
- id: "labels-x",
29982
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
29983
+ label: "x Label"
29984
+ }, /*#__PURE__*/React__namespace.createElement("input", {
29915
29985
  type: "text",
29916
29986
  className: "graph-settings-axis-label",
29917
29987
  ref: this.labelXRef,
29918
29988
  onChange: e => this.changeLabel(0, e),
29919
29989
  value: this.state.labelsTextbox[0] || ""
29920
- })), /*#__PURE__*/React__namespace.createElement("div", {
29990
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
29921
29991
  className: "perseus-widget-right-col"
29922
- }, /*#__PURE__*/React__namespace.createElement("label", {
29923
- htmlFor: "labels-y"
29924
- }, "y Label"), /*#__PURE__*/React__namespace.createElement("input", {
29925
- id: "labels-y",
29992
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
29993
+ label: "y Label"
29994
+ }, /*#__PURE__*/React__namespace.createElement("input", {
29926
29995
  type: "text",
29927
29996
  className: "graph-settings-axis-label",
29928
29997
  ref: this.labelYRef,
29929
29998
  onChange: e => this.changeLabel(1, e),
29930
29999
  value: this.state.labelsTextbox[1] || ""
29931
- }))), /*#__PURE__*/React__namespace.createElement("div", {
30000
+ })))), /*#__PURE__*/React__namespace.createElement("div", {
29932
30001
  className: "perseus-widget-row"
29933
30002
  }, /*#__PURE__*/React__namespace.createElement("div", {
29934
30003
  className: "perseus-widget-left-col"
29935
- }, /*#__PURE__*/React__namespace.createElement("label", {
29936
- htmlFor: "range-x"
29937
- }, "x Range"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29938
- id: "range-x",
30004
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30005
+ label: "x Range"
30006
+ }, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29939
30007
  value: this.state.rangeTextbox[0],
29940
30008
  onChange: vals => this.changeRange(0, vals)
29941
- })), /*#__PURE__*/React__namespace.createElement("div", {
30009
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
29942
30010
  className: "perseus-widget-right-col"
29943
- }, /*#__PURE__*/React__namespace.createElement("label", {
29944
- htmlFor: "range-y"
29945
- }, "y Range"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29946
- id: "range-y",
30011
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30012
+ label: "y Range"
30013
+ }, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29947
30014
  value: this.state.rangeTextbox[1],
29948
30015
  onChange: vals => this.changeRange(1, vals)
29949
- }))), /*#__PURE__*/React__namespace.createElement("div", {
30016
+ })))), /*#__PURE__*/React__namespace.createElement("div", {
29950
30017
  className: "perseus-widget-row"
29951
30018
  }, /*#__PURE__*/React__namespace.createElement("div", {
29952
30019
  className: "perseus-widget-left-col"
29953
- }, /*#__PURE__*/React__namespace.createElement("label", {
29954
- htmlFor: "tick-step"
29955
- }, "Tick Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29956
- id: "tick-step",
30020
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30021
+ label: "Tick Step"
30022
+ }, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29957
30023
  value: this.state.stepTextbox,
29958
30024
  onChange: this.changeStep
29959
- })), /*#__PURE__*/React__namespace.createElement("div", {
30025
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
29960
30026
  className: "perseus-widget-right-col"
29961
- }, /*#__PURE__*/React__namespace.createElement("label", {
29962
- htmlFor: "grid-step"
29963
- }, "Grid Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29964
- id: "grid-step",
30027
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30028
+ label: "Grid Step"
30029
+ }, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29965
30030
  value: this.state.gridStepTextbox,
29966
30031
  onChange: this.changeGridStep
29967
- }))), /*#__PURE__*/React__namespace.createElement("div", {
30032
+ })))), /*#__PURE__*/React__namespace.createElement("div", {
29968
30033
  className: "perseus-widget-row"
29969
30034
  }, /*#__PURE__*/React__namespace.createElement("div", {
29970
30035
  className: "perseus-widget-left-col"
29971
- }, /*#__PURE__*/React__namespace.createElement("label", {
29972
- htmlFor: "snap-step"
29973
- }, "Snap Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29974
- id: "snap-step",
30036
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30037
+ label: "Snap Step"
30038
+ }, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29975
30039
  value: this.state.snapStepTextbox,
29976
30040
  onChange: this.changeSnapStep
29977
- }))), /*#__PURE__*/React__namespace.createElement("div", {
30041
+ })))), /*#__PURE__*/React__namespace.createElement("div", {
29978
30042
  className: "perseus-widget-row"
29979
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Markings: "), /*#__PURE__*/React__namespace.createElement(ButtonGroup$2, {
30043
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30044
+ label: "Markings:"
30045
+ }, /*#__PURE__*/React__namespace.createElement(ButtonGroup$2, {
29980
30046
  value: this.props.markings,
29981
30047
  allowEmpty: false,
29982
30048
  buttons: [{
@@ -29990,24 +30056,25 @@ class InteractiveGraphSettings extends React__namespace.Component {
29990
30056
  content: "None"
29991
30057
  }],
29992
30058
  onChange: this.change("markings")
29993
- })), /*#__PURE__*/React__namespace.createElement("div", {
30059
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
29994
30060
  className: "perseus-widget-left-col"
29995
30061
  }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$7, {
29996
30062
  label: "Show tooltips",
29997
30063
  showTooltips: this.props.showTooltips,
29998
30064
  onChange: this.change
29999
- }))), /*#__PURE__*/React__namespace.createElement("div", {
30000
- className: "image-settings"
30001
- }, /*#__PURE__*/React__namespace.createElement("div", null, "Background image:"), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", {
30002
- htmlFor: "bg-url"
30003
- }, "Url:"), /*#__PURE__*/React__namespace.createElement("input", {
30004
- id: "bg-url",
30065
+ }))), /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30066
+ label: "Background image URL:",
30067
+ style: styles$g.resetSpaceTop
30068
+ }, /*#__PURE__*/React__namespace.createElement("input", {
30005
30069
  type: "text",
30006
- className: "graph-settings-background-url",
30070
+ className: aphrodite.css(styles$g.backgroundUrlInput),
30007
30071
  ref: this.bgUrlRef,
30008
30072
  value: this.state.backgroundImage.url || "",
30009
30073
  onChange: e => {
30010
- const image = ___default["default"].clone(this.props.backgroundImage);
30074
+ // Shallow-copied clone
30075
+ const image = {
30076
+ ...this.props.backgroundImage
30077
+ };
30011
30078
  image.url = e.target.value;
30012
30079
  this.setState({
30013
30080
  backgroundImage: image
@@ -30015,60 +30082,452 @@ class InteractiveGraphSettings extends React__namespace.Component {
30015
30082
  },
30016
30083
  onKeyPress: this.changeBackgroundUrl,
30017
30084
  onBlur: this.changeBackgroundUrl
30018
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$c, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background.")))), /*#__PURE__*/React__namespace.createElement("div", {
30019
- className: "misc-settings"
30020
- }, /*#__PURE__*/React__namespace.createElement("div", {
30021
- className: "perseus-widget-row"
30022
- }, /*#__PURE__*/React__namespace.createElement("div", {
30023
- className: "perseus-widget-left-col"
30085
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$c, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background."))), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30086
+ style: styles$g.rulerSection
30087
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30088
+ style: styles$g.checkboxRow
30024
30089
  }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$7, {
30025
30090
  label: "Show ruler",
30026
30091
  showRuler: this.props.showRuler,
30027
- onChange: this.change
30028
- })), /*#__PURE__*/React__namespace.createElement("div", {
30029
- className: "perseus-widget-right-col"
30030
- }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$7, {
30092
+ onChange: this.change,
30093
+ style: styles$g.resetSpaceTop
30094
+ }), /*#__PURE__*/React__namespace.createElement(PropCheckBox$7, {
30031
30095
  label: "Show protractor",
30032
30096
  showProtractor: this.props.showProtractor,
30033
- onChange: this.change
30034
- }))), this.props.showRuler && /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Ruler label:", " ", /*#__PURE__*/React__namespace.createElement("select", {
30035
- onChange: this.changeRulerLabel,
30036
- value: this.props.rulerLabel
30037
- }, /*#__PURE__*/React__namespace.createElement("option", {
30038
- value: ""
30039
- }, "None"), /*#__PURE__*/React__namespace.createElement("optgroup", {
30040
- label: "Metric"
30041
- }, this.renderLabelChoices([["milimeters", "mm"], ["centimeters", "cm"], ["meters", "m"], ["kilometers", "km"]])), /*#__PURE__*/React__namespace.createElement("optgroup", {
30042
- label: "Imperial"
30043
- }, this.renderLabelChoices([["inches", "in"], ["feet", "ft"], ["yards", "yd"], ["miles", "mi"]]))))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Ruler ticks:", " ", /*#__PURE__*/React__namespace.createElement("select", {
30044
- onChange: this.changeRulerTicks,
30045
- value: this.props.rulerTicks
30046
- }, ___default["default"].map([1, 2, 4, 8, 10, 16], function (n) {
30047
- return /*#__PURE__*/React__namespace.createElement("option", {
30048
- key: `ruler-tick-${n}`,
30049
- value: n
30050
- }, n);
30097
+ onChange: this.change,
30098
+ style: styles$g.resetSpaceTop
30099
+ })), this.props.showRuler && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30100
+ style: styles$g.spaceTop
30101
+ }, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30102
+ label: "Ruler label:",
30103
+ style: styles$g.resetSpaceTop
30104
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
30105
+ id: "ruler-label-select",
30106
+ selectedValue: this.props.rulerLabel,
30107
+ onChange: newValue => {
30108
+ this.change({
30109
+ rulerLabel: newValue
30110
+ });
30111
+ },
30112
+ placeholder: "None",
30113
+ style: styles$g.singleSelectShort
30114
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30115
+ value: "",
30116
+ label: "None",
30117
+ horizontalRule: "full-width"
30118
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30119
+ value: "mm",
30120
+ label: "Milimeters"
30121
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30122
+ value: "cm",
30123
+ label: "Centimeters"
30124
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30125
+ value: "m",
30126
+ label: "Meters"
30127
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30128
+ value: "km",
30129
+ label: "Kilometers",
30130
+ horizontalRule: "full-width"
30131
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30132
+ value: "in",
30133
+ label: "Inches"
30134
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30135
+ value: "ft",
30136
+ label: "Feet"
30137
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30138
+ value: "yd",
30139
+ label: "Yards"
30140
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30141
+ value: "mi",
30142
+ label: "Miles"
30143
+ }))), /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30144
+ label: "Ruler ticks:"
30145
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
30146
+ id: "ruler-ticks-select",
30147
+ selectedValue: `${this.props.rulerTicks}`,
30148
+ onChange: newValue => {
30149
+ this.change({
30150
+ rulerTicks: newValue
30151
+ });
30152
+ },
30153
+ placeholder: "10",
30154
+ style: styles$g.singleSelectShort
30155
+ }, [1, 2, 4, 8, 10, 16].map(value => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30156
+ key: value,
30157
+ value: `${value}`,
30158
+ label: `${value}`
30051
30159
  })))))));
30052
30160
  }
30053
30161
  }
30162
+ const styles$g = aphrodite.StyleSheet.create({
30163
+ resetSpaceTop: {
30164
+ marginTop: 0
30165
+ },
30166
+ spaceTop: {
30167
+ marginTop: wonderBlocksTokens.spacing.xSmall_8
30168
+ },
30169
+ singleSelectShort: {
30170
+ // Non-standard spacing, but it's the smallest we can go
30171
+ // without running into styling issues with the dropdown.
30172
+ height: 26
30173
+ },
30174
+ backgroundUrlInput: {
30175
+ border: `1px solid ${wonderBlocksTokens.color.offBlack32}`,
30176
+ borderRadius: wonderBlocksTokens.spacing.xxxSmall_4,
30177
+ padding: wonderBlocksTokens.spacing.xxxSmall_4
30178
+ },
30179
+ checkboxRow: {
30180
+ flexDirection: "row",
30181
+ alignItems: "center",
30182
+ justifyContent: "space-between"
30183
+ },
30184
+ rulerSection: {
30185
+ marginTop: wonderBlocksTokens.spacing.xSmall_8,
30186
+ borderTop: `1px solid ${wonderBlocksTokens.color.offBlack16}`,
30187
+ paddingTop: wonderBlocksTokens.spacing.xSmall_8,
30188
+ paddingBottom: wonderBlocksTokens.spacing.xSmall_8,
30189
+ borderBottom: `1px solid ${wonderBlocksTokens.color.offBlack16}`
30190
+ }
30191
+ });
30192
+
30193
+ /**
30194
+ * Dropdown for selecting a locked figure to add to an interactive graph.
30195
+ * Locked figures are elements (points, segmeents, etc.) that are not
30196
+ * interactive, just present in the graph's background.
30197
+ *
30198
+ * Used in the interactive graph editor's locked figures section.
30199
+ */
30200
+ const LockedFigureSelect = props => {
30201
+ const {
30202
+ id,
30203
+ onChange
30204
+ } = props;
30205
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30206
+ style: styles$f.container
30207
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.ActionMenu, {
30208
+ menuText: "Add element",
30209
+ style: styles$f.addElementSelect
30210
+ }, [/*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.ActionItem, {
30211
+ key: `${id}-point`,
30212
+ label: "Point",
30213
+ onClick: () => onChange("point")
30214
+ }, "Point")]));
30215
+ };
30216
+ const styles$f = aphrodite.StyleSheet.create({
30217
+ container: {
30218
+ marginTop: wonderBlocksTokens.spacing.medium_16
30219
+ },
30220
+ addElementSelect: {
30221
+ backgroundColor: wonderBlocksTokens.color.fadedBlue16,
30222
+ borderRadius: wonderBlocksTokens.spacing.xxxSmall_4
30223
+ }
30224
+ });
30225
+
30226
+ const mediaDefaultSpecLargeMarginWidth = wonderBlocksTokens.spacing.large_24;
30227
+ const MEDIA_DEFAULT_SPEC = {
30228
+ small: {
30229
+ query: "(max-width: 767px)",
30230
+ totalColumns: 4,
30231
+ gutterWidth: wonderBlocksTokens.spacing.medium_16,
30232
+ marginWidth: wonderBlocksTokens.spacing.medium_16
30233
+ },
30234
+ medium: {
30235
+ query: "(min-width: 768px) and (max-width: 1023px)",
30236
+ totalColumns: 8,
30237
+ gutterWidth: wonderBlocksTokens.spacing.xLarge_32,
30238
+ marginWidth: wonderBlocksTokens.spacing.large_24
30239
+ },
30240
+ large: {
30241
+ query: "(min-width: 1024px)",
30242
+ totalColumns: 12,
30243
+ gutterWidth: wonderBlocksTokens.spacing.xLarge_32,
30244
+ marginWidth: mediaDefaultSpecLargeMarginWidth,
30245
+ maxWidth: 1120 + mediaDefaultSpecLargeMarginWidth * 2
30246
+ }
30247
+ };
30248
+ ({
30249
+ large: {
30250
+ query: "(min-width: 1px)",
30251
+ totalColumns: 12,
30252
+ gutterWidth: wonderBlocksTokens.spacing.xLarge_32,
30253
+ marginWidth: wonderBlocksTokens.spacing.medium_16
30254
+ }
30255
+ });
30256
+ ({
30257
+ small: {
30258
+ query: "(max-width: 767px)",
30259
+ totalColumns: 4,
30260
+ gutterWidth: wonderBlocksTokens.spacing.medium_16,
30261
+ marginWidth: wonderBlocksTokens.spacing.medium_16
30262
+ },
30263
+ large: {
30264
+ query: "(min-width: 768px)",
30265
+ totalColumns: 12,
30266
+ gutterWidth: wonderBlocksTokens.spacing.xLarge_32,
30267
+ marginWidth: wonderBlocksTokens.spacing.xxLarge_48
30268
+ }
30269
+ });
30270
+
30271
+ const defaultContext = {
30272
+ ssrSize: "large",
30273
+ mediaSpec: MEDIA_DEFAULT_SPEC
30274
+ };
30275
+ const MediaLayoutContext = React__namespace.createContext(defaultContext);
30276
+ MediaLayoutContext.displayName = "MediaLayoutContext";
30277
+
30278
+ class Spring extends React__namespace.Component {
30279
+ render() {
30280
+ const {
30281
+ style
30282
+ } = this.props;
30283
+ return React__namespace.createElement(wonderBlocksCore.View, {
30284
+ "aria-hidden": "true",
30285
+ style: [styles$e.grow, style]
30286
+ });
30287
+ }
30288
+ }
30289
+ const styles$e = aphrodite.StyleSheet.create({
30290
+ grow: {
30291
+ flexGrow: 1
30292
+ }
30293
+ });
30294
+
30295
+ function focusWithChromeStickyFocusBugWorkaround(element) {
30296
+ // NOTE(marksandstrom) Chrome sticky focus bug.
30297
+ //
30298
+ // There is a bug in Chrome related to sticky positioning and
30299
+ // focus: When a child of an element with sticky positioning is
30300
+ // focused with the focus() method, the scrollable area
30301
+ // containing that element will scroll to the top (even though
30302
+ // the element is already visble on the page). For a dropdown
30303
+ // this means that the area will be scrolled to the top when
30304
+ // the user interacts with the dropdown (since we actively
30305
+ // manage dropdown header and option focus for keyboard users).
30306
+ //
30307
+ // To work around this bug the `preventScroll` focus option is
30308
+ // used.
30309
+ //
30310
+ // Using `focusOptions` is an experimental browser feature
30311
+ // "that should not be used in production code". However, since
30312
+ // Chrome is the only browser we support that exhibits this
30313
+ // buggy behavior and using `focusOptions` works around the
30314
+ // bug, it is perfectly reasonable to use the feature in this
30315
+ // case. We are not relying on the effect of the
30316
+ // `preventScroll` option otherwise.
30317
+ //
30318
+ // focusOptions documentation:
30319
+ //
30320
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
30321
+ //
30322
+ // Note that there could be cases where we want default focus() behavior.
30323
+ // One that comes to mind is a dropdown with a long list of options that
30324
+ // might be rendered off screen when opened. With this workaround the
30325
+ // selected option would not be scrolled into view if the option is near
30326
+ // the end of the list. We're not aware of any uses of the dropdown where
30327
+ // this is an issue, however, so there isn't currently a way to out of the
30328
+ // `preventScroll` behavior.
30329
+
30330
+ // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
30331
+ element.focus({
30332
+ preventScroll: true
30333
+ });
30334
+ }
30335
+ function getValidNumberFromString(value) {
30336
+ const parsed = parseInt(value);
30337
+ // If the value is not a number, return 0.
30338
+ return isNaN(parsed) ? 0 : parsed;
30339
+ }
30340
+ function getDefaultFigureForFigureType(type) {
30341
+ switch (type) {
30342
+ case "point":
30343
+ return {
30344
+ type: "point",
30345
+ coord: [0, 0]
30346
+ };
30347
+ }
30348
+ }
30349
+
30350
+ /**
30351
+ * LockedPointSettings is a component that allows the user to edit the
30352
+ * settings of specifically a locked point on the graph.
30353
+ *
30354
+ * Used in the interactive graph editor's locked figures section.
30355
+ */
30356
+ const LockedPointSettings = props => {
30357
+ const {
30358
+ coord,
30359
+ onRemove,
30360
+ onChangeCoord
30361
+ } = props;
30362
+ const [coordState, setCoordState] = React__namespace.useState([
30363
+ // Using strings to make it easier to work with the text fields.
30364
+ coord[0].toString(), coord[1].toString()]);
30365
+
30366
+ // Generate unique IDs so that the programmatic labels can be associated
30367
+ // with their respective text fields.
30368
+ const ids = wonderBlocksCore.useUniqueIdWithMock();
30369
+ const xCoordId = ids.get("x-coord");
30370
+ const yCoordId = ids.get("y-coord");
30371
+ function handleBlur() {
30372
+ const validCoord = [getValidNumberFromString(coordState[0]), getValidNumberFromString(coordState[1])];
30373
+
30374
+ // Make the text field only show valid numbers after blur.
30375
+ setCoordState([validCoord[0].toString(), validCoord[1].toString()]);
30376
+ // Update the graph with the new coordinates.
30377
+ onChangeCoord(validCoord);
30378
+ }
30379
+ function handleChange(newValue, coordIndex) {
30380
+ const newCoord = [...coordState];
30381
+ newCoord[coordIndex] = newValue;
30382
+ setCoordState(newCoord);
30383
+ }
30384
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30385
+ style: styles$d.container
30386
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30387
+ style: styles$d.row
30388
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, "Point"), /*#__PURE__*/React__namespace.createElement(Spring, null), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
30389
+ icon: trashIcon__default["default"],
30390
+ "aria-label": `Delete locked point at ${coordState[0]}, ${coordState[1]}`,
30391
+ onClick: onRemove
30392
+ })), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30393
+ style: styles$d.row
30394
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
30395
+ htmlFor: xCoordId,
30396
+ style: styles$d.label,
30397
+ tag: "label"
30398
+ }, "x Coordinate"), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
30399
+ id: xCoordId,
30400
+ value: coordState[0],
30401
+ onChange: newValue => handleChange(newValue, 0),
30402
+ onBlur: handleBlur,
30403
+ style: styles$d.textField
30404
+ })), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30405
+ style: styles$d.row
30406
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
30407
+ htmlFor: yCoordId,
30408
+ style: styles$d.label,
30409
+ tag: "label"
30410
+ }, "y Coordinate"), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
30411
+ id: yCoordId,
30412
+ value: coordState[1],
30413
+ onChange: newValue => handleChange(newValue, 1),
30414
+ onBlur: handleBlur,
30415
+ style: styles$d.textField
30416
+ }))));
30417
+ };
30418
+ const styles$d = aphrodite.StyleSheet.create({
30419
+ container: {
30420
+ backgroundColor: wonderBlocksTokens.color.fadedBlue8,
30421
+ marginBottom: wonderBlocksTokens.spacing.xSmall_8,
30422
+ padding: wonderBlocksTokens.spacing.medium_16,
30423
+ borderRadius: wonderBlocksTokens.spacing.xSmall_8
30424
+ },
30425
+ row: {
30426
+ flexDirection: "row",
30427
+ alignItems: "center",
30428
+ marginBottom: wonderBlocksTokens.spacing.xSmall_8
30429
+ },
30430
+ label: {
30431
+ marginInlineEnd: wonderBlocksTokens.spacing.xSmall_8
30432
+ },
30433
+ textField: {
30434
+ width: wonderBlocksTokens.spacing.xxxLarge_64
30435
+ }
30436
+ });
30437
+
30438
+ /**
30439
+ * LockedFigureSettings takes in a figure and renders the
30440
+ * respective settings for that figure type.
30441
+ *
30442
+ * Used in the interactive graph editor's locked figures section.
30443
+ */
30444
+
30445
+ // Union this type with other locked figure types when they are added.
30446
+
30447
+ const LockedFigureSettings = props => {
30448
+ switch (props.type) {
30449
+ case "point":
30450
+ return /*#__PURE__*/React__namespace.createElement(LockedPointSettings, props);
30451
+ }
30452
+ return null;
30453
+ };
30454
+
30455
+ const LockedFiguresSection = props => {
30456
+ const uniqueId = wonderBlocksCore.useUniqueIdWithMock().get("locked-figures-section");
30457
+ const {
30458
+ figures,
30459
+ onChange
30460
+ } = props;
30461
+ function addLockedFigure(newFigure) {
30462
+ const lockedFigures = figures || [];
30463
+ const newProps = {
30464
+ lockedFigures: [...lockedFigures, getDefaultFigureForFigureType(newFigure)]
30465
+ };
30466
+ onChange(newProps);
30467
+ }
30468
+ function removeLockedFigure(index) {
30469
+ const lockedFigures = figures || [];
30470
+ onChange({
30471
+ lockedFigures: [...lockedFigures.slice(0, index), ...lockedFigures.slice(index + 1)]
30472
+ });
30473
+ }
30474
+ function changeCoord(index, coord) {
30475
+ const lockedFigures = figures || [];
30476
+ const newProps = {
30477
+ lockedFigures: [...lockedFigures.slice(0, index), {
30478
+ ...lockedFigures[index],
30479
+ coord
30480
+ }, ...lockedFigures.slice(index + 1)]
30481
+ };
30482
+ onChange(newProps);
30483
+ }
30484
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30485
+ style: styles$c.container
30486
+ }, figures?.map((figure, index) => /*#__PURE__*/React__namespace.createElement(LockedFigureSettings, _extends({
30487
+ key: `${uniqueId}-locked-${figure}-${index}`
30488
+ }, figure, {
30489
+ onRemove: () => removeLockedFigure(index),
30490
+ onChangeCoord: coord => changeCoord(index, coord)
30491
+ }))), /*#__PURE__*/React__namespace.createElement(LockedFigureSelect, {
30492
+ id: `${uniqueId}-select`,
30493
+ onChange: addLockedFigure
30494
+ }));
30495
+ };
30496
+ const styles$c = aphrodite.StyleSheet.create({
30497
+ container: {
30498
+ paddingTop: wonderBlocksTokens.spacing.large_24
30499
+ }
30500
+ });
30054
30501
 
30055
30502
  const SegmentCountSelector = _ref => {
30056
30503
  let {
30057
30504
  numSegments = 1,
30058
30505
  onChange
30059
30506
  } = _ref;
30060
- return /*#__PURE__*/React__namespace.createElement("select", {
30507
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
30061
30508
  key: "segment-select",
30062
- value: numSegments,
30063
- onChange: e => {
30064
- const num = +e.target.value;
30509
+ selectedValue: `${numSegments}`
30510
+ // Never uses placeholder, always has value
30511
+ ,
30512
+ placeholder: "",
30513
+ onChange: newValue => {
30514
+ const num = +newValue;
30065
30515
  onChange(num);
30066
- }
30067
- }, ___default["default"].range(1, 7).map(n => /*#__PURE__*/React__namespace.createElement("option", {
30516
+ },
30517
+ style: styles$b.singleSelectShort
30518
+ }, ___default["default"].range(1, 7).map(n => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30068
30519
  key: n,
30069
- value: n
30070
- }, `${n} segment${n > 1 ? "s" : ""}`)));
30520
+ value: `${n}`,
30521
+ label: `${n} segment${n > 1 ? "s" : ""}`
30522
+ })));
30071
30523
  };
30524
+ const styles$b = aphrodite.StyleSheet.create({
30525
+ singleSelectShort: {
30526
+ // Non-standard spacing, but it's the smallest we can go
30527
+ // without running into styling issues with the dropdown.
30528
+ height: 26
30529
+ }
30530
+ });
30072
30531
 
30073
30532
  const {
30074
30533
  InfoTip: InfoTip$b
@@ -30089,27 +30548,13 @@ const deprecatedProps = {
30089
30548
  };
30090
30549
  }
30091
30550
  };
30092
- // Renders the given children in a View laid out horizontally.
30093
- const Row = props => {
30094
- const {
30095
- children,
30096
- style
30097
- } = props;
30098
- return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30099
- style: {
30100
- ...style,
30101
- flexDirection: "row",
30102
- marginTop: Spacing__default["default"].xSmall_8
30103
- }
30104
- }, children);
30105
- };
30106
- const FieldLabel = props => {
30107
- return /*#__PURE__*/React__namespace.createElement(Typography__namespace.LabelSmall, {
30108
- style: {
30109
- marginRight: Spacing__default["default"].xSmall_8
30110
- }
30111
- }, props.children);
30112
- };
30551
+ const POLYGON_SIDES = ___default["default"].map(___default["default"].range(3, 13), function (value) {
30552
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30553
+ key: `polygon-sides-${value}`,
30554
+ value: `${value}`,
30555
+ label: `${value} sides`
30556
+ });
30557
+ });
30113
30558
  /**
30114
30559
  * An editor for the InteractiveGraph widget, which allows the user to
30115
30560
  * specify the graph's properties and the correct answer.
@@ -30162,6 +30607,7 @@ class InteractiveGraphEditor extends React__namespace.Component {
30162
30607
  showTooltips: this.props.showTooltips,
30163
30608
  rulerLabel: this.props.rulerLabel,
30164
30609
  rulerTicks: this.props.rulerTicks,
30610
+ lockedFigures: this.props.lockedFigures,
30165
30611
  trackInteraction: function () {},
30166
30612
  onChange: newProps => {
30167
30613
  let correct = this.props.correct;
@@ -30199,7 +30645,9 @@ class InteractiveGraphEditor extends React__namespace.Component {
30199
30645
  className: "perseus-error"
30200
30646
  }, this.props.valid);
30201
30647
  }
30202
- return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(FieldLabel, null, "Type of Graph:"), /*#__PURE__*/React__namespace.createElement(GraphTypeSelector, {
30648
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30649
+ label: "Type of Graph:"
30650
+ }, /*#__PURE__*/React__namespace.createElement(GraphTypeSelector, {
30203
30651
  graphType: this.props.graph?.type ?? InteractiveGraph.defaultProps.graph.type,
30204
30652
  onChange: type => {
30205
30653
  this.props.onChange({
@@ -30211,7 +30659,9 @@ class InteractiveGraphEditor extends React__namespace.Component {
30211
30659
  }
30212
30660
  });
30213
30661
  }
30214
- })), this.props.correct?.type === "point" && /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(FieldLabel, null, "Number of Points:"), /*#__PURE__*/React__namespace.createElement(GraphPointsCountSelector, {
30662
+ })), this.props.correct?.type === "point" && /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30663
+ label: "Number of Points:"
30664
+ }, /*#__PURE__*/React__namespace.createElement(GraphPointsCountSelector, {
30215
30665
  numPoints: this.props.correct?.numPoints,
30216
30666
  onChange: points => {
30217
30667
  this.props.onChange({
@@ -30221,13 +30671,16 @@ class InteractiveGraphEditor extends React__namespace.Component {
30221
30671
  }
30222
30672
  });
30223
30673
  }
30224
- })), this.props.correct?.type === "polygon" && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(FieldLabel, null, "Number of sides:"), /*#__PURE__*/React__namespace.createElement("select", {
30674
+ })), this.props.correct?.type === "polygon" && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30675
+ label: "Number of sides:"
30676
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
30225
30677
  key: "polygon-select",
30226
- value: this.props.correct?.numSides || 3,
30227
- onChange: e => {
30678
+ selectedValue: this.props.correct?.numSides ? `${this.props.correct.numSides}` : "3",
30679
+ placeholder: "",
30680
+ onChange: newValue => {
30228
30681
  const graph = {
30229
30682
  ...this.props.correct,
30230
- numSides: parsePointCount(e.target.value),
30683
+ numSides: parsePointCount(newValue),
30231
30684
  coords: null,
30232
30685
  // reset the snap for UNLIMITED, which
30233
30686
  // only supports "grid"
@@ -30237,38 +30690,45 @@ class InteractiveGraphEditor extends React__namespace.Component {
30237
30690
  this.props.onChange({
30238
30691
  correct: graph
30239
30692
  });
30240
- }
30241
- }, ___default["default"].map(___default["default"].range(3, 13), function (n) {
30242
- return /*#__PURE__*/React__namespace.createElement("option", {
30243
- key: n,
30244
- value: n
30245
- }, `${n} sides`);
30246
- }), /*#__PURE__*/React__namespace.createElement("option", {
30247
- value: "unlimited"
30248
- }, "unlimited sides"))), /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(FieldLabel, null, "Snap to:"), /*#__PURE__*/React__namespace.createElement("select", {
30249
- key: "polygon-snap",
30250
- value: this.props.correct?.snapTo,
30251
- onChange: e => {
30693
+ },
30694
+ style: styles$a.singleSelectShort
30695
+ }, [...POLYGON_SIDES, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30696
+ value: "unlimited",
30697
+ label: "unlimited sides"
30698
+ })])), /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30699
+ label: "Snap to:"
30700
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
30701
+ selectedValue: this.props.correct?.snapTo || "grid"
30702
+ // Never uses placeholder, always has value
30703
+ ,
30704
+ placeholder: "",
30705
+ onChange: newValue => {
30252
30706
  const graph = {
30253
30707
  ...this.props.correct,
30254
- snapTo: e.target.value,
30708
+ snapTo: newValue,
30255
30709
  coords: null
30256
30710
  };
30257
30711
  this.props.onChange({
30258
30712
  correct: graph
30259
30713
  });
30260
- }
30261
- }, /*#__PURE__*/React__namespace.createElement("option", {
30262
- value: "grid"
30263
- }, "grid"), this.props.correct?.numSides !== "unlimited" && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("option", {
30264
- value: "angles"
30265
- }, "interior angles"), /*#__PURE__*/React__namespace.createElement("option", {
30266
- value: "sides"
30267
- }, "side measures"))), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "These options affect the movement of the vertex points. The grid option will guide the points to the nearest half step along the grid."), /*#__PURE__*/React__namespace.createElement("p", null, "The interior angle and side measure options guide the points to the nearest whole angle or side"), " ", "measure respectively.")), /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(Typography__namespace.LabelSmall, {
30268
- tag: "label"
30269
- }, "Show angle measures:", " ", /*#__PURE__*/React__namespace.createElement("input", {
30270
- type: "checkbox",
30271
- checked: this.props.correct?.showAngles,
30714
+ },
30715
+ style: styles$a.singleSelectShort
30716
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30717
+ value: "grid",
30718
+ label: "grid"
30719
+ }), this.props.correct?.numSides !== "unlimited" && /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30720
+ value: "angles",
30721
+ label: "interior angles"
30722
+ }), this.props.correct?.numSides !== "unlimited" && /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30723
+ value: "sides",
30724
+ label: "side measures"
30725
+ })), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "These options affect the movement of the vertex points. The grid option will guide the points to the nearest half step along the grid."), /*#__PURE__*/React__namespace.createElement("p", null, "The interior angle and side measure options guide the points to the nearest whole angle or side"), " ", "measure respectively.")), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30726
+ style: styles$a.row
30727
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
30728
+ label: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, null, "Show angle measures"),
30729
+ checked:
30730
+ // Don't show indeterminate checkbox state
30731
+ !!this.props.correct?.showAngles,
30272
30732
  onChange: () => {
30273
30733
  this.props.onChange({
30274
30734
  correct: {
@@ -30277,11 +30737,13 @@ class InteractiveGraphEditor extends React__namespace.Component {
30277
30737
  }
30278
30738
  });
30279
30739
  }
30280
- })), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Displays the interior angle measures."))), /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(Typography__namespace.LabelSmall, {
30281
- tag: "label"
30282
- }, "Show side measures:", " ", /*#__PURE__*/React__namespace.createElement("input", {
30283
- type: "checkbox",
30284
- checked: this.props.correct?.showSides,
30740
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Displays the interior angle measures."))), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
30741
+ style: styles$a.row
30742
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
30743
+ label: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, null, "Show side measures"),
30744
+ checked:
30745
+ // Don't show indeterminate checkbox state
30746
+ !!this.props.correct?.showSides,
30285
30747
  onChange: () => {
30286
30748
  this.props.onChange({
30287
30749
  correct: {
@@ -30290,7 +30752,9 @@ class InteractiveGraphEditor extends React__namespace.Component {
30290
30752
  }
30291
30753
  });
30292
30754
  }
30293
- })), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Displays the side lengths.")))), this.props.correct?.type === "segment" && /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(FieldLabel, null, "Number of segments: "), /*#__PURE__*/React__namespace.createElement(SegmentCountSelector, {
30755
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Displays the side lengths.")))), this.props.correct?.type === "segment" && /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30756
+ label: "Number of segments:"
30757
+ }, /*#__PURE__*/React__namespace.createElement(SegmentCountSelector, {
30294
30758
  numSegments: this.props.correct?.numSegments,
30295
30759
  onChange: sides => {
30296
30760
  this.props.onChange({
@@ -30301,16 +30765,7 @@ class InteractiveGraphEditor extends React__namespace.Component {
30301
30765
  }
30302
30766
  });
30303
30767
  }
30304
- })), /*#__PURE__*/React__namespace.createElement(Row, null, /*#__PURE__*/React__namespace.createElement(FieldLabel, null, "Correct answer:"), /*#__PURE__*/React__namespace.createElement(Typography__namespace.BodyMonospace, {
30305
- style: {
30306
- fontSize: 12,
30307
- backgroundColor: "#eee",
30308
- paddingInline: Spacing__default["default"].xxSmall_6,
30309
- borderColor: "#ccc",
30310
- borderStyle: "solid",
30311
- borderWidth: 1
30312
- }
30313
- }, equationString), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."))), /*#__PURE__*/React__namespace.createElement(InteractiveGraphSettings, {
30768
+ })), /*#__PURE__*/React__namespace.createElement(InteractiveGraphSettings, {
30314
30769
  box: getInteractiveBoxFromSizeClass(sizeClass),
30315
30770
  range: this.props.range,
30316
30771
  labels: this.props.labels,
@@ -30326,40 +30781,72 @@ class InteractiveGraphEditor extends React__namespace.Component {
30326
30781
  rulerLabel: this.props.rulerLabel,
30327
30782
  rulerTicks: this.props.rulerTicks,
30328
30783
  onChange: this.props.onChange
30329
- }), this.props.correct.type === "polygon" && /*#__PURE__*/React__namespace.createElement("div", {
30330
- className: "type-settings"
30331
- }, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Student answer must", " ", /*#__PURE__*/React__namespace.createElement("select", {
30332
- value: this.props.correct.match,
30784
+ }), this.props.correct.type === "polygon" && /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30785
+ label: "Student answer must"
30786
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
30787
+ selectedValue: this.props.correct.match || "exact",
30333
30788
  onChange: this.changeMatchType
30334
- }, /*#__PURE__*/React__namespace.createElement("option", {
30335
- value: "exact"
30336
- }, "match exactly"), /*#__PURE__*/React__namespace.createElement("option", {
30337
- value: "congruent"
30338
- }, "be congruent"), /*#__PURE__*/React__namespace.createElement("option", {
30339
- value: "approx"
30340
- }, "be approximately congruent"), /*#__PURE__*/React__namespace.createElement("option", {
30341
- value: "similar"
30342
- }, "be similar"))), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("ul", null, /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Match Exactly:"), " Match exactly in size, orientation, and location on the grid even if it is not shown in the background.")), /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Be Congruent:"), " Be congruent in size and shape, but can be located anywhere on the grid.")), /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Be Approximately Congruent:"), " Be exactly similar, and congruent in size and shape to within 0.1 units, but can be located anywhere on the grid.", " ", /*#__PURE__*/React__namespace.createElement("em", null, "Use this with snapping to angle measure."))), /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Be Similar:"), " Be similar with matching interior angles, and side measures that are matching or a multiple of the correct side measures. The figure can be located anywhere on the grid."))))), this.props.correct.type === "angle" && /*#__PURE__*/React__namespace.createElement("div", {
30343
- className: "type-settings"
30344
- }, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Student answer must", " ", /*#__PURE__*/React__namespace.createElement("select", {
30345
- value: this.props.correct.match,
30789
+ // Never uses placeholder, always has value
30790
+ ,
30791
+ placeholder: "",
30792
+ style: styles$a.singleSelectShort
30793
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30794
+ value: "exact",
30795
+ label: "match exactly"
30796
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30797
+ value: "congruent",
30798
+ label: "be congruent"
30799
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30800
+ value: "approx",
30801
+ label: "be approximately congruent"
30802
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30803
+ value: "similar",
30804
+ label: "be similar"
30805
+ })), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("ul", null, /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Match Exactly:"), " Match exactly in size, orientation, and location on the grid even if it is not shown in the background.")), /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Be Congruent:"), " Be congruent in size and shape, but can be located anywhere on the grid.")), /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Be Approximately Congruent:"), " Be exactly similar, and congruent in size and shape to within 0.1 units, but can be located anywhere on the grid.", " ", /*#__PURE__*/React__namespace.createElement("em", null, "Use this with snapping to angle measure."))), /*#__PURE__*/React__namespace.createElement("li", null, /*#__PURE__*/React__namespace.createElement("p", null, /*#__PURE__*/React__namespace.createElement("b", null, "Be Similar:"), " Be similar with matching interior angles, and side measures that are matching or a multiple of the correct side measures. The figure can be located anywhere on the grid."))))), this.props.correct.type === "angle" && /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30806
+ label: "Student answer must"
30807
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
30808
+ selectedValue: this.props.correct.match || "exact",
30346
30809
  onChange: this.changeMatchType
30347
- }, /*#__PURE__*/React__namespace.createElement("option", {
30348
- value: "exact"
30349
- }, "match exactly"), /*#__PURE__*/React__namespace.createElement("option", {
30350
- value: "congruent"
30351
- }, "be congruent"))), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Congruency requires only that the angle measures are the same. An exact match implies congruency, but also requires that the angles have the same orientation and that the vertices are in the same position.")))), graph);
30352
- }
30353
- changeMatchType(e) {
30354
- const correct = ___default["default"].extend({}, this.props.correct, {
30355
- match: e.target.value
30356
- });
30810
+ // Never uses placeholder, always has value
30811
+ ,
30812
+ placeholder: "",
30813
+ style: styles$a.singleSelectShort
30814
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30815
+ value: "exact",
30816
+ label: "match exactly"
30817
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
30818
+ value: "congruent",
30819
+ label: "be congruent"
30820
+ })), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Congruency requires only that the angle measures are the same. An exact match implies congruency, but also requires that the angles have the same orientation and that the vertices are in the same position."))), /*#__PURE__*/React__namespace.createElement(LabeledRow, {
30821
+ label: "Correct answer:"
30822
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.BodyMonospace, {
30823
+ style: {
30824
+ fontSize: 12,
30825
+ backgroundColor: "#eee",
30826
+ paddingInline: Spacing__default["default"].xxSmall_6,
30827
+ borderColor: "#ccc",
30828
+ borderStyle: "solid",
30829
+ borderWidth: 1
30830
+ }
30831
+ }, equationString), /*#__PURE__*/React__namespace.createElement(InfoTip$b, null, /*#__PURE__*/React__namespace.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."))), graph,
30832
+ // Only show the "Add element" dropdown if the graph is
30833
+ // using Mafs.
30834
+ this.props.graph && this.props.apiOptions?.flags?.["mafs"]?.[this.props.graph.type] && /*#__PURE__*/React__namespace.createElement(LockedFiguresSection, {
30835
+ figures: this.props.lockedFigures,
30836
+ onChange: this.props.onChange
30837
+ }));
30838
+ }
30839
+ changeMatchType = newValue => {
30840
+ const correct = {
30841
+ ...this.props.correct,
30842
+ match: newValue
30843
+ };
30357
30844
  this.props.onChange({
30358
30845
  correct: correct
30359
30846
  });
30360
- }
30847
+ };
30361
30848
  serialize() {
30362
- const json = ___default["default"].pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showRuler", "showTooltips", "rulerLabel", "rulerTicks", "range", "gridStep", "snapStep");
30849
+ const json = ___default["default"].pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showRuler", "showTooltips", "rulerLabel", "rulerTicks", "range", "gridStep", "snapStep", "lockedFigures");
30363
30850
 
30364
30851
  // eslint-disable-next-line react/no-string-refs
30365
30852
  const graph = this.refs.graph;
@@ -30383,6 +30870,18 @@ class InteractiveGraphEditor extends React__namespace.Component {
30383
30870
  return json;
30384
30871
  }
30385
30872
  }
30873
+ const styles$a = aphrodite.StyleSheet.create({
30874
+ singleSelectShort: {
30875
+ // Non-standard spacing, but it's the smallest we can go
30876
+ // without running into styling issues with the dropdown.
30877
+ height: 26
30878
+ },
30879
+ row: {
30880
+ flexDirection: "row",
30881
+ marginTop: Spacing__default["default"].xSmall_8,
30882
+ alignItems: "center"
30883
+ }
30884
+ });
30386
30885
 
30387
30886
  class FormWrappedTextField extends React__namespace.Component {
30388
30887
  state = {
@@ -31123,47 +31622,6 @@ const styles$5 = aphrodite.StyleSheet.create({
31123
31622
  }
31124
31623
  });
31125
31624
 
31126
- function focusWithChromeStickyFocusBugWorkaround(element) {
31127
- // NOTE(marksandstrom) Chrome sticky focus bug.
31128
- //
31129
- // There is a bug in Chrome related to sticky positioning and
31130
- // focus: When a child of an element with sticky positioning is
31131
- // focused with the focus() method, the scrollable area
31132
- // containing that element will scroll to the top (even though
31133
- // the element is already visble on the page). For a dropdown
31134
- // this means that the area will be scrolled to the top when
31135
- // the user interacts with the dropdown (since we actively
31136
- // manage dropdown header and option focus for keyboard users).
31137
- //
31138
- // To work around this bug the `preventScroll` focus option is
31139
- // used.
31140
- //
31141
- // Using `focusOptions` is an experimental browser feature
31142
- // "that should not be used in production code". However, since
31143
- // Chrome is the only browser we support that exhibits this
31144
- // buggy behavior and using `focusOptions` works around the
31145
- // bug, it is perfectly reasonable to use the feature in this
31146
- // case. We are not relying on the effect of the
31147
- // `preventScroll` option otherwise.
31148
- //
31149
- // focusOptions documentation:
31150
- //
31151
- // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
31152
- //
31153
- // Note that there could be cases where we want default focus() behavior.
31154
- // One that comes to mind is a dropdown with a long list of options that
31155
- // might be rendered off screen when opened. With this workaround the
31156
- // selected option would not be scrolled into view if the option is near
31157
- // the end of the list. We're not aware of any uses of the dropdown where
31158
- // this is an issue, however, so there isn't currently a way to out of the
31159
- // `preventScroll` behavior.
31160
-
31161
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
31162
- element.focus({
31163
- preventScroll: true
31164
- });
31165
- }
31166
-
31167
31625
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
31168
31626
  const {
31169
31627
  Icon