@khanacademy/perseus-editor 14.3.0 → 14.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
@@ -35,6 +35,7 @@ import trashIcon from '@phosphor-icons/core/bold/trash-bold.svg';
35
35
  import copyIcon from '@phosphor-icons/core/assets/regular/copy.svg';
36
36
  import autoPasteIcon from '@phosphor-icons/core/assets/regular/note-pencil.svg';
37
37
  import plusCircle from '@phosphor-icons/core/regular/plus-circle.svg';
38
+ import { vec } from 'mafs';
38
39
  import arrowFatDown from '@phosphor-icons/core/regular/arrow-fat-down.svg';
39
40
  import arrowFatLeft from '@phosphor-icons/core/regular/arrow-fat-left.svg';
40
41
  import arrowFatRight from '@phosphor-icons/core/regular/arrow-fat-right.svg';
@@ -44,7 +45,7 @@ import arrowCounterClockwise from '@phosphor-icons/core/bold/arrow-counter-clock
44
45
 
45
46
  // This file is processed by a Rollup plugin (replace) to inject the production
46
47
  const libName = "@khanacademy/perseus-editor";
47
- const libVersion = "14.3.0";
48
+ const libVersion = "14.4.0";
48
49
  addLibraryVersionToPerseusDebug(libName, libVersion);
49
50
 
50
51
  function _extends() {
@@ -229,7 +230,7 @@ class SectionControlButton extends React.Component {
229
230
  role: "button",
230
231
  hideDefaultFocusRing: true,
231
232
  "aria-label": title,
232
- style: styles$U.button
233
+ style: styles$T.button
233
234
  }, ({
234
235
  hovered,
235
236
  focused,
@@ -237,7 +238,7 @@ class SectionControlButton extends React.Component {
237
238
  }) => /*#__PURE__*/React.createElement(InlineIcon$b, icon));
238
239
  }
239
240
  }
240
- const styles$U = StyleSheet.create({
241
+ const styles$T = StyleSheet.create({
241
242
  button: {
242
243
  backgroundColor: color.gold,
243
244
  margin: 2,
@@ -20628,11 +20629,11 @@ class Spring extends React.Component {
20628
20629
  } = this.props;
20629
20630
  return React.createElement(View, {
20630
20631
  "aria-hidden": "true",
20631
- style: [styles$T.grow, style]
20632
+ style: [styles$S.grow, style]
20632
20633
  });
20633
20634
  }
20634
20635
  }
20635
- const styles$T = StyleSheet.create({
20636
+ const styles$S = StyleSheet.create({
20636
20637
  grow: {
20637
20638
  flexGrow: 1
20638
20639
  }
@@ -20698,6 +20699,7 @@ const _upgradeWidgetInfo = props => {
20698
20699
  // eslint-disable-next-line react/no-unsafe
20699
20700
  class WidgetEditor extends React.Component {
20700
20701
  constructor(props) {
20702
+ var _props$widgetIsOpen;
20701
20703
  super(props);
20702
20704
  this.widget = void 0;
20703
20705
  this._toggleWidget = e => {
@@ -20751,7 +20753,7 @@ class WidgetEditor extends React.Component {
20751
20753
  };
20752
20754
  };
20753
20755
  this.state = {
20754
- showWidget: false,
20756
+ showWidget: (_props$widgetIsOpen = props.widgetIsOpen) != null ? _props$widgetIsOpen : true,
20755
20757
  widgetInfo: _upgradeWidgetInfo(props)
20756
20758
  };
20757
20759
  this.widget = /*#__PURE__*/React.createRef();
@@ -20762,6 +20764,12 @@ class WidgetEditor extends React.Component {
20762
20764
  this.setState({
20763
20765
  widgetInfo: _upgradeWidgetInfo(nextProps)
20764
20766
  });
20767
+ // user can update internal state while the widget is handled globally
20768
+ if (nextProps.widgetIsOpen != null && nextProps.widgetIsOpen !== this.props.widgetIsOpen) {
20769
+ this.setState({
20770
+ showWidget: nextProps.widgetIsOpen
20771
+ });
20772
+ }
20765
20773
  }
20766
20774
  render() {
20767
20775
  const widgetInfo = this.state.widgetInfo;
@@ -20869,13 +20877,13 @@ class WidgetSelect extends React.Component {
20869
20877
  * that collapse a region.
20870
20878
  */
20871
20879
  function ToggleableCaret(props) {
20872
- const iconStyle = props.isExpanded ? styles$S.expanded : styles$S.collapsed;
20880
+ const iconStyle = props.isExpanded ? styles$R.expanded : styles$R.collapsed;
20873
20881
  return /*#__PURE__*/React.createElement(PhosphorIcon, {
20874
20882
  icon: caretRight,
20875
20883
  style: iconStyle
20876
20884
  });
20877
20885
  }
20878
- const styles$S = StyleSheet.create({
20886
+ const styles$R = StyleSheet.create({
20879
20887
  collapsed: {
20880
20888
  transition: ".15s"
20881
20889
  },
@@ -20908,16 +20916,16 @@ class TexErrorView extends React.Component {
20908
20916
  showErrors
20909
20917
  } = this.state;
20910
20918
  return /*#__PURE__*/React.createElement(View, {
20911
- style: styles$R.errorContainer
20919
+ style: styles$Q.errorContainer
20912
20920
  }, /*#__PURE__*/React.createElement(View, {
20913
- style: styles$R.title,
20921
+ style: styles$Q.title,
20914
20922
  onClick: this.handleToggleTexErrors
20915
20923
  }, /*#__PURE__*/React.createElement(ToggleableCaret, {
20916
20924
  isExpanded: showErrors
20917
20925
  }), "\xA0 TeX Errors (", errorList.length, ")"), showErrors && /*#__PURE__*/React.createElement(View, {
20918
- style: styles$R.errorExplanation
20926
+ style: styles$Q.errorExplanation
20919
20927
  }, "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, {
20920
- style: styles$R.error,
20928
+ style: styles$Q.error,
20921
20929
  key: index
20922
20930
  }, /*#__PURE__*/React.createElement(View, {
20923
20931
  style: {
@@ -20926,7 +20934,7 @@ class TexErrorView extends React.Component {
20926
20934
  }, e.math), /*#__PURE__*/React.createElement(View, null, e.message))));
20927
20935
  }
20928
20936
  }
20929
- const styles$R = StyleSheet.create({
20937
+ const styles$Q = StyleSheet.create({
20930
20938
  title: {
20931
20939
  backgroundColor: "#eee",
20932
20940
  fontSize: "1.25em",
@@ -21574,7 +21582,8 @@ class Editor extends React.Component {
21574
21582
  // eslint-disable-next-line react/jsx-no-bind
21575
21583
  ,
21576
21584
  onRemove: this._handleWidgetEditorRemove.bind(this, id),
21577
- apiOptions: this.props.apiOptions
21585
+ apiOptions: this.props.apiOptions,
21586
+ widgetIsOpen: this.props.widgetIsOpen
21578
21587
  }, this.props.widgets[id]));
21579
21588
  }
21580
21589
  render() {
@@ -24039,7 +24048,7 @@ ItemExtrasEditor.defaultProps = {
24039
24048
  zTable: false
24040
24049
  };
24041
24050
  const ItemExtraCheckbox = props => /*#__PURE__*/React.createElement(View, {
24042
- style: [styles$Q.checkbox, props.indent ? styles$Q.indented : undefined]
24051
+ style: [styles$P.checkbox, props.indent ? styles$P.indented : undefined]
24043
24052
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
24044
24053
  label: /*#__PURE__*/React.createElement(View, {
24045
24054
  style: {
@@ -24049,7 +24058,7 @@ const ItemExtraCheckbox = props => /*#__PURE__*/React.createElement(View, {
24049
24058
  checked: props.checked,
24050
24059
  onChange: newCheckedState => props.onChange(newCheckedState)
24051
24060
  }));
24052
- const styles$Q = StyleSheet.create({
24061
+ const styles$P = StyleSheet.create({
24053
24062
  indented: {
24054
24063
  marginInlineStart: spacing.large_24
24055
24064
  }
@@ -24119,7 +24128,8 @@ class ItemEditor extends React.Component {
24119
24128
  imageUploader: this.props.imageUploader,
24120
24129
  onChange: this.handleEditorChange,
24121
24130
  apiOptions: this.props.apiOptions,
24122
- showWordCount: true
24131
+ showWordCount: true,
24132
+ widgetIsOpen: this.props.widgetIsOpen
24123
24133
  }, this.props.question))), /*#__PURE__*/React.createElement("div", {
24124
24134
  className: "perseus-editor-right-cell"
24125
24135
  }, /*#__PURE__*/React.createElement("div", {
@@ -24167,6 +24177,7 @@ const {
24167
24177
  } = components;
24168
24178
  class EditorPage extends React.Component {
24169
24179
  constructor(props) {
24180
+ var _this$props$widgetsAr;
24170
24181
  super(props);
24171
24182
  this._isMounted = void 0;
24172
24183
  this.renderer = void 0;
@@ -24199,7 +24210,8 @@ class EditorPage extends React.Component {
24199
24210
  json: _.pick(this.props, "question", "answerArea", "hints", "itemDataVersion"),
24200
24211
  gradeMessage: "",
24201
24212
  wasAnswered: false,
24202
- highlightLint: true
24213
+ highlightLint: true,
24214
+ widgetsAreOpen: (_this$props$widgetsAr = this.props.widgetsAreOpen) != null ? _this$props$widgetsAr : true
24203
24215
  };
24204
24216
  this._isMounted = false;
24205
24217
  }
@@ -24327,6 +24339,7 @@ class EditorPage extends React.Component {
24327
24339
  wasAnswered: this.state.wasAnswered,
24328
24340
  gradeMessage: this.state.gradeMessage,
24329
24341
  deviceType: this.props.previewDevice,
24342
+ widgetIsOpen: this.state.widgetsAreOpen,
24330
24343
  apiOptions: deviceBasedApiOptions,
24331
24344
  previewURL: this.props.previewURL
24332
24345
  }), (!this.props.developerMode || !this.props.jsonMode) && /*#__PURE__*/React.createElement(CombinedHintsEditor, {
@@ -24707,7 +24720,7 @@ class SimpleButton extends React.Component {
24707
24720
  } = _this$props,
24708
24721
  otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
24709
24722
  return /*#__PURE__*/React.createElement("div", _extends({
24710
- className: css(styles$P.baseButton, color === "green" && styles$P.green, color === "orange" && styles$P.orange),
24723
+ className: css(styles$O.baseButton, color === "green" && styles$O.green, color === "orange" && styles$O.orange),
24711
24724
  onClick: onClick
24712
24725
  }, otherProps), children);
24713
24726
  }
@@ -24722,7 +24735,7 @@ SimpleButton.defaultProps = {
24722
24735
  color: "green",
24723
24736
  onClick: () => {}
24724
24737
  };
24725
- const styles$P = StyleSheet.create({
24738
+ const styles$O = StyleSheet.create({
24726
24739
  baseButton: {
24727
24740
  top: "0",
24728
24741
  fontSize: "11px",
@@ -24942,23 +24955,23 @@ const LeafContainer = ({
24942
24955
  }) => {
24943
24956
  const hasPreviewHeading = shape.type === "content" || shape.type === "hint";
24944
24957
  const previewHeading = hasPreviewHeading && /*#__PURE__*/React.createElement("div", {
24945
- className: css(styles$O.containerHeader)
24958
+ className: css(styles$N.containerHeader)
24946
24959
  }, /*#__PURE__*/React.createElement(Header, {
24947
24960
  depth: path.length,
24948
- className: css(styles$O.containerTitle)
24961
+ className: css(styles$N.containerTitle)
24949
24962
  }, capitalize(name)));
24950
24963
  return /*#__PURE__*/React.createElement("div", {
24951
- className: css(styles$O.container)
24964
+ className: css(styles$N.container)
24952
24965
  }, /*#__PURE__*/React.createElement("span", {
24953
- className: css(styles$O.row, styles$O.rowHeading)
24966
+ className: css(styles$N.row, styles$N.rowHeading)
24954
24967
  }, /*#__PURE__*/React.createElement("div", {
24955
- className: css(styles$O.columnLeft)
24968
+ className: css(styles$N.columnLeft)
24956
24969
  }, /*#__PURE__*/React.createElement("div", {
24957
- className: "pod-title " + css(styles$O.containerHeader)
24970
+ className: "pod-title " + css(styles$N.containerHeader)
24958
24971
  }, /*#__PURE__*/React.createElement("div", {
24959
- className: css(styles$O.containerTitle)
24972
+ className: css(styles$N.containerTitle)
24960
24973
  }, capitalize(name)), controls)), /*#__PURE__*/React.createElement("div", {
24961
- className: css(styles$O.columnRight)
24974
+ className: css(styles$N.columnRight)
24962
24975
  }, previewHeading)), children);
24963
24976
  };
24964
24977
  const ArrayContainer = props => {
@@ -24971,11 +24984,11 @@ const ArrayContainer = props => {
24971
24984
  actions
24972
24985
  } = props;
24973
24986
  return /*#__PURE__*/React.createElement("div", {
24974
- className: css(styles$O.container)
24987
+ className: css(styles$N.container)
24975
24988
  }, controls && /*#__PURE__*/React.createElement("div", {
24976
- className: css(styles$O.columnLeft, styles$O.containerHeader)
24989
+ className: css(styles$N.columnLeft, styles$N.containerHeader)
24977
24990
  }, controls), /*#__PURE__*/React.createElement("div", null, children), /*#__PURE__*/React.createElement("div", {
24978
- className: css(styles$O.columnLeft)
24991
+ className: css(styles$N.columnLeft)
24979
24992
  }, /*#__PURE__*/React.createElement("a", {
24980
24993
  href: "javascript:void 0",
24981
24994
  onClick: () => actions.addArrayElement(path, shape.elementShape)
@@ -24988,28 +25001,28 @@ const ObjectContainer = ({
24988
25001
  path
24989
25002
  }) => {
24990
25003
  const headingEditor = /*#__PURE__*/React.createElement("div", {
24991
- className: css(styles$O.containerHeader)
25004
+ className: css(styles$N.containerHeader)
24992
25005
  }, /*#__PURE__*/React.createElement(Header, {
24993
25006
  depth: path.length,
24994
- className: css(styles$O.containerTitle)
25007
+ className: css(styles$N.containerTitle)
24995
25008
  }, capitalize(name)), controls);
24996
25009
  const headingPreview = (name || controls) && /*#__PURE__*/React.createElement("div", {
24997
- className: css(styles$O.containerHeader, styles$O.previewCollectionHeader)
25010
+ className: css(styles$N.containerHeader, styles$N.previewCollectionHeader)
24998
25011
  }, /*#__PURE__*/React.createElement(Header, {
24999
25012
  depth: path.length,
25000
- className: css(styles$O.containerTitle)
25013
+ className: css(styles$N.containerTitle)
25001
25014
  }, capitalize(name)));
25002
25015
  const hasBothHeadings = headingEditor && headingPreview;
25003
25016
  return /*#__PURE__*/React.createElement("div", {
25004
- className: css(styles$O.container)
25017
+ className: css(styles$N.container)
25005
25018
  }, hasBothHeadings && /*#__PURE__*/React.createElement("span", {
25006
- className: css(styles$O.row)
25019
+ className: css(styles$N.row)
25007
25020
  }, /*#__PURE__*/React.createElement("div", {
25008
- className: css(styles$O.columnLeft)
25021
+ className: css(styles$N.columnLeft)
25009
25022
  }, headingEditor), /*#__PURE__*/React.createElement("div", {
25010
- className: css(styles$O.columnRight)
25023
+ className: css(styles$N.columnRight)
25011
25024
  }, headingPreview)), /*#__PURE__*/React.createElement("div", {
25012
- className: css(path.length > 0 && styles$O.contentIndent)
25025
+ className: css(path.length > 0 && styles$N.contentIndent)
25013
25026
  }, children));
25014
25027
  };
25015
25028
 
@@ -25132,11 +25145,11 @@ const ItemNodeContent = withStickiness(props => {
25132
25145
  className: "framework-perseus"
25133
25146
  }, lens(renderers).get(path));
25134
25147
  return /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("div", {
25135
- className: css(styles$O.row)
25148
+ className: css(styles$N.row)
25136
25149
  }, /*#__PURE__*/React.createElement("div", {
25137
- className: css(styles$O.columnLeft)
25150
+ className: css(styles$N.columnLeft)
25138
25151
  }, /*#__PURE__*/React.createElement("div", {
25139
- className: css(sticky && styles$O.sticky)
25152
+ className: css(sticky && styles$N.sticky)
25140
25153
  },
25141
25154
  /*#__PURE__*/
25142
25155
  // @ts-expect-error - TS2769 - No overload matches this call.
@@ -25144,9 +25157,9 @@ const ItemNodeContent = withStickiness(props => {
25144
25157
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25145
25158
  apiOptions: apiOptions
25146
25159
  })))), /*#__PURE__*/React.createElement("div", {
25147
- className: css(styles$O.columnRight)
25160
+ className: css(styles$N.columnRight)
25148
25161
  }, /*#__PURE__*/React.createElement("div", {
25149
- className: css(sticky && styles$O.sticky)
25162
+ className: css(sticky && styles$N.sticky)
25150
25163
  }, preview))));
25151
25164
  });
25152
25165
  const HintNodeContent = withStickiness(props => {
@@ -25162,13 +25175,13 @@ const HintNodeContent = withStickiness(props => {
25162
25175
  className: "framework-perseus"
25163
25176
  }, lens(renderers).get(path));
25164
25177
  return /*#__PURE__*/React.createElement("div", {
25165
- className: css(styles$O.row)
25178
+ className: css(styles$N.row)
25166
25179
  }, /*#__PURE__*/React.createElement("div", {
25167
- className: css(styles$O.columnLeft)
25180
+ className: css(styles$N.columnLeft)
25168
25181
  }, /*#__PURE__*/React.createElement("div", {
25169
- className: css(sticky && styles$O.sticky)
25182
+ className: css(sticky && styles$N.sticky)
25170
25183
  }, /*#__PURE__*/React.createElement(HintEditor, _extends({}, data, {
25171
- className: css(styles$O.hintEditor),
25184
+ className: css(styles$N.hintEditor),
25172
25185
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25173
25186
  apiOptions: apiOptions,
25174
25187
  showTitle: false,
@@ -25183,9 +25196,9 @@ const HintNodeContent = withStickiness(props => {
25183
25196
  isFirst: true,
25184
25197
  isLast: true
25185
25198
  })))), /*#__PURE__*/React.createElement("div", {
25186
- className: css(styles$O.columnRight)
25199
+ className: css(styles$N.columnRight)
25187
25200
  }, /*#__PURE__*/React.createElement("div", {
25188
- className: css(sticky && styles$O.sticky)
25201
+ className: css(sticky && styles$N.sticky)
25189
25202
  }, preview)));
25190
25203
  });
25191
25204
  const TagsNodeContent = props => {
@@ -25202,9 +25215,9 @@ const TagsNodeContent = props => {
25202
25215
  return null;
25203
25216
  }
25204
25217
  return /*#__PURE__*/React.createElement("div", {
25205
- className: css(styles$O.columnLeft)
25218
+ className: css(styles$N.columnLeft)
25206
25219
  }, /*#__PURE__*/React.createElement("div", {
25207
- className: css(styles$O.tagsEditor)
25220
+ className: css(styles$N.tagsEditor)
25208
25221
  }, /*#__PURE__*/React.createElement(GroupMetadataEditor, {
25209
25222
  value: data,
25210
25223
  onChange: newVal => actions.setValueAtPath(path, newVal),
@@ -25235,23 +25248,23 @@ const ArrayNodeContent = props => {
25235
25248
  const subpath = path.concat(i);
25236
25249
  const controls = [i > 0 && /*#__PURE__*/React.createElement("div", {
25237
25250
  key: "moveArrayElementUp",
25238
- className: css(styles$O.control)
25251
+ className: css(styles$N.control)
25239
25252
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25240
25253
  color: "orange",
25241
25254
  title: "Move up",
25242
25255
  onClick: () => actions.moveArrayElementUp(subpath)
25243
25256
  }, /*#__PURE__*/React.createElement("div", {
25244
- className: css(styles$O.verticalFlip)
25257
+ className: css(styles$N.verticalFlip)
25245
25258
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconChevronDown)))), i < data.length - 1 && /*#__PURE__*/React.createElement("div", {
25246
25259
  key: "moveArrayElementDown",
25247
- className: css(styles$O.control)
25260
+ className: css(styles$N.control)
25248
25261
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25249
25262
  color: "orange",
25250
25263
  title: "Move down",
25251
25264
  onClick: () => actions.moveArrayElementDown(subpath)
25252
25265
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconChevronDown))), /*#__PURE__*/React.createElement("div", {
25253
25266
  key: "removeArrayElement",
25254
- className: css(styles$O.control)
25267
+ className: css(styles$N.control)
25255
25268
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25256
25269
  color: "orange",
25257
25270
  title: "Delete",
@@ -25259,7 +25272,7 @@ const ArrayNodeContent = props => {
25259
25272
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconTrash$4)))];
25260
25273
  return /*#__PURE__*/React.createElement("div", {
25261
25274
  key: i,
25262
- className: css(styles$O.arrayElement, !elementIsLeaf && styles$O.arrayElementAndNotLeaf)
25275
+ className: css(styles$N.arrayElement, !elementIsLeaf && styles$N.arrayElementAndNotLeaf)
25263
25276
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25264
25277
  key: i,
25265
25278
  shape: shape.elementShape,
@@ -25285,7 +25298,7 @@ const ObjectNodeContent = props => {
25285
25298
  // made sense to the shape's author is the order in which we'll iterate :)
25286
25299
  const children = Object.keys(shape.shape).map(subkey => /*#__PURE__*/React.createElement("div", {
25287
25300
  key: subkey,
25288
- className: css(styles$O.objectElement)
25301
+ className: css(styles$N.objectElement)
25289
25302
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25290
25303
  shape: shape.shape[subkey],
25291
25304
  data: data[subkey],
@@ -25452,7 +25465,7 @@ class MultiRendererEditor extends React.Component {
25452
25465
  }, this._renderContent());
25453
25466
  }
25454
25467
  }
25455
- const styles$O = StyleSheet.create({
25468
+ const styles$N = StyleSheet.create({
25456
25469
  // This is used in a number of places throughout this file.
25457
25470
  container: {},
25458
25471
  // eslint-disable-next-line react-native/no-unused-styles
@@ -26398,7 +26411,7 @@ const SortableItem = createReactClass({
26398
26411
  }
26399
26412
  return /*#__PURE__*/React.createElement("li", {
26400
26413
  draggable: this.props.draggable,
26401
- className: [dragState, css(styles$N.sortableListItem)].join(" "),
26414
+ className: [dragState, css(styles$M.sortableListItem)].join(" "),
26402
26415
  onDragStart: this.handleDragStart,
26403
26416
  onDrop: this.handleDrop,
26404
26417
  onDragEnter: this.handleDragEnter,
@@ -26406,7 +26419,7 @@ const SortableItem = createReactClass({
26406
26419
  }, this.props.component);
26407
26420
  }
26408
26421
  });
26409
- const styles$N = StyleSheet.create({
26422
+ const styles$M = StyleSheet.create({
26410
26423
  sortableListItem: {
26411
26424
  margin: "5px 0"
26412
26425
  }
@@ -26654,13 +26667,13 @@ class ExpressionEditor extends React.Component {
26654
26667
  onChange: this.handleToggleDiv
26655
26668
  }));
26656
26669
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(HeadingSmall, null, "Global Options"), /*#__PURE__*/React.createElement("div", {
26657
- className: css(styles$M.paddedY)
26670
+ className: css(styles$L.paddedY)
26658
26671
  }, /*#__PURE__*/React.createElement(LabeledTextField, {
26659
26672
  label: "Visible label",
26660
26673
  value: this.props.visibleLabel || "",
26661
26674
  onChange: this.change("visibleLabel")
26662
26675
  }), /*#__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", {
26663
- className: css(styles$M.paddedY)
26676
+ className: css(styles$L.paddedY)
26664
26677
  }, /*#__PURE__*/React.createElement(LabeledTextField, {
26665
26678
  label: "Aria label",
26666
26679
  value: this.props.ariaLabel || "",
@@ -26669,13 +26682,13 @@ class ExpressionEditor extends React.Component {
26669
26682
  href: "https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",
26670
26683
  target: "_blank"
26671
26684
  }, "this article.")))), /*#__PURE__*/React.createElement("div", {
26672
- className: css(styles$M.paddedY)
26685
+ className: css(styles$L.paddedY)
26673
26686
  }, /*#__PURE__*/React.createElement(LabeledTextField, {
26674
26687
  label: "Function variables",
26675
26688
  value: this.state.functionsInternal,
26676
26689
  onChange: this.handleFunctions
26677
26690
  }), /*#__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", {
26678
- className: css(styles$M.paddedY)
26691
+ className: css(styles$L.paddedY)
26679
26692
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
26680
26693
  label: "Use \xD7 instead of \u22C5 for multiplication",
26681
26694
  checked: this.props.times,
@@ -26685,7 +26698,7 @@ class ExpressionEditor extends React.Component {
26685
26698
  });
26686
26699
  }
26687
26700
  }), /*#__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", {
26688
- className: css(styles$M.paddedY)
26701
+ className: css(styles$L.paddedY)
26689
26702
  }, /*#__PURE__*/React.createElement(HeadingXSmall, null, "Button Sets"), buttonSetChoices), /*#__PURE__*/React.createElement(HeadingSmall, null, "Answers"), /*#__PURE__*/React.createElement("p", {
26690
26703
  style: {
26691
26704
  margin: "4px 0"
@@ -26756,18 +26769,18 @@ class AnswerOption extends React.Component {
26756
26769
  color: "destructive",
26757
26770
  light: true
26758
26771
  }, "Delete");
26759
- const answerStatusCss = css(styles$M.answerStatus, this.props.considered === "wrong" && styles$M.answerStatusWrong, this.props.considered === "correct" && styles$M.answerStatusCorrect, this.props.considered === "ungraded" && styles$M.answerStatusUngraded);
26772
+ const answerStatusCss = css(styles$L.answerStatus, this.props.considered === "wrong" && styles$L.answerStatusWrong, this.props.considered === "correct" && styles$L.answerStatusCorrect, this.props.considered === "ungraded" && styles$L.answerStatusUngraded);
26760
26773
  return /*#__PURE__*/React.createElement("div", {
26761
- className: css(styles$M.answerOption)
26774
+ className: css(styles$L.answerOption)
26762
26775
  }, /*#__PURE__*/React.createElement("div", {
26763
- className: css(styles$M.answerHandle)
26776
+ className: css(styles$L.answerHandle)
26764
26777
  }), /*#__PURE__*/React.createElement("div", {
26765
- className: css(styles$M.answerBody)
26778
+ className: css(styles$L.answerBody)
26766
26779
  }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
26767
26780
  onClick: this.toggleConsidered,
26768
26781
  className: answerStatusCss
26769
26782
  }, this.props.considered), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Expression, this.props.expressionProps))), /*#__PURE__*/React.createElement("div", {
26770
- className: css(styles$M.paddedY, styles$M.paddedX)
26783
+ className: css(styles$L.paddedY, styles$L.paddedX)
26771
26784
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
26772
26785
  label: "Answer expression must have the same form.",
26773
26786
  checked: this.props.form,
@@ -26777,7 +26790,7 @@ class AnswerOption extends React.Component {
26777
26790
  });
26778
26791
  }
26779
26792
  }), /*#__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", {
26780
- className: css(styles$M.paddedY, styles$M.paddedX)
26793
+ className: css(styles$L.paddedY, styles$L.paddedX)
26781
26794
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
26782
26795
  label: "Answer expression must be fully expanded and simplified.",
26783
26796
  checked: this.props.simplify,
@@ -26787,11 +26800,11 @@ class AnswerOption extends React.Component {
26787
26800
  });
26788
26801
  }
26789
26802
  }), /*#__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", {
26790
- className: css(styles$M.buttonRow, styles$M.paddedY)
26803
+ className: css(styles$L.buttonRow, styles$L.paddedY)
26791
26804
  }, removeButton)));
26792
26805
  }
26793
26806
  }
26794
- const styles$M = StyleSheet.create({
26807
+ const styles$L = StyleSheet.create({
26795
26808
  paddedX: {
26796
26809
  paddingLeft: spacing.xSmall_8,
26797
26810
  paddingRight: spacing.xSmall_8
@@ -26886,10 +26899,10 @@ class GradedGroupEditor extends React.Component {
26886
26899
  }, /*#__PURE__*/React.createElement("div", {
26887
26900
  className: "perseus-widget-row"
26888
26901
  }, /*#__PURE__*/React.createElement("label", {
26889
- className: css(styles$L.title)
26902
+ className: css(styles$K.title)
26890
26903
  }, "Title:", " ", /*#__PURE__*/React.createElement(TextInput$5, {
26891
26904
  value: this.props.title,
26892
- className: css(styles$L.input)
26905
+ className: css(styles$K.input)
26893
26906
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26894
26907
  ,
26895
26908
  onChange: this.change("title")
@@ -26914,7 +26927,7 @@ class GradedGroupEditor extends React.Component {
26914
26927
  }, /*#__PURE__*/React.createElement(InlineIcon$4, iconPlus$1), " Add a hint"), this.props.hint && /*#__PURE__*/React.createElement("div", {
26915
26928
  className: "perseus-hint-editor"
26916
26929
  }, /*#__PURE__*/React.createElement("div", {
26917
- className: css(styles$L.hintsTitle)
26930
+ className: css(styles$K.hintsTitle)
26918
26931
  }, "Hint"), /*#__PURE__*/React.createElement(Editor, {
26919
26932
  ref: this.hintEditor,
26920
26933
  content: this.props.hint ? this.props.hint.content : "",
@@ -26951,7 +26964,7 @@ GradedGroupEditor.defaultProps = {
26951
26964
  images: {},
26952
26965
  hint: null
26953
26966
  };
26954
- const styles$L = StyleSheet.create({
26967
+ const styles$K = StyleSheet.create({
26955
26968
  title: {
26956
26969
  fontSize: 18,
26957
26970
  fontWeight: "bold"
@@ -28410,13 +28423,13 @@ function MathquillInput(props) {
28410
28423
  }
28411
28424
  });
28412
28425
  return /*#__PURE__*/React.createElement(View, {
28413
- style: styles$K.outerWrapper
28426
+ style: styles$J.outerWrapper
28414
28427
  }, /*#__PURE__*/React.createElement("span", {
28415
28428
  ref: mathFieldWrapperRef,
28416
28429
  className: "perseus-math-input mq-editable-field mq-math-mode"
28417
28430
  }));
28418
28431
  }
28419
- const styles$K = StyleSheet.create({
28432
+ const styles$J = StyleSheet.create({
28420
28433
  outerWrapper: {
28421
28434
  display: "inline-block",
28422
28435
  borderStyle: "solid",
@@ -29520,7 +29533,7 @@ const GraphPointsCountSelector = ({
29520
29533
  // Never uses placeholder, always has value
29521
29534
  ,
29522
29535
  placeholder: "",
29523
- style: styles$J.singleSelectShort
29536
+ style: styles$I.singleSelectShort
29524
29537
  }, [...[...Array(7).keys()].map(n => /*#__PURE__*/React.createElement(OptionItem, {
29525
29538
  key: n,
29526
29539
  value: `${n}`,
@@ -29531,7 +29544,7 @@ const GraphPointsCountSelector = ({
29531
29544
  label: "unlimited"
29532
29545
  })]);
29533
29546
  };
29534
- const styles$J = StyleSheet.create({
29547
+ const styles$I = StyleSheet.create({
29535
29548
  singleSelectShort: {
29536
29549
  // Non-standard spacing, but it's the smallest we can go
29537
29550
  // without running into styling issues with the dropdown.
@@ -29544,7 +29557,7 @@ const GraphTypeSelector = props => {
29544
29557
  selectedValue: props.graphType,
29545
29558
  onChange: props.onChange,
29546
29559
  placeholder: "Select an answer type",
29547
- style: styles$I.singleSelectShort
29560
+ style: styles$H.singleSelectShort
29548
29561
  }, props.showNoneOption && /*#__PURE__*/React.createElement(OptionItem, {
29549
29562
  value: "none",
29550
29563
  label: "None"
@@ -29580,7 +29593,7 @@ const GraphTypeSelector = props => {
29580
29593
  label: "Angle"
29581
29594
  }));
29582
29595
  };
29583
- const styles$I = StyleSheet.create({
29596
+ const styles$H = StyleSheet.create({
29584
29597
  singleSelectShort: {
29585
29598
  // Non-standard spacing, but it's the smallest we can go
29586
29599
  // without running into styling issues with the dropdown.
@@ -29595,11 +29608,11 @@ function Heading({
29595
29608
  onToggle
29596
29609
  }) {
29597
29610
  return /*#__PURE__*/React.createElement(Clickable, {
29598
- style: [styles$H.container, !isCollapsible && styles$H.notClickable],
29611
+ style: [styles$G.container, !isCollapsible && styles$G.notClickable],
29599
29612
  disabled: !isCollapsible,
29600
29613
  onClick: () => isCollapsible && (onToggle == null ? void 0 : onToggle(!isOpen))
29601
29614
  }, () => /*#__PURE__*/React.createElement(View, {
29602
- style: styles$H.heading
29615
+ style: styles$G.heading
29603
29616
  }, /*#__PURE__*/React.createElement(LabelLarge, {
29604
29617
  style: {
29605
29618
  fontSize: 14,
@@ -29609,7 +29622,7 @@ function Heading({
29609
29622
  isExpanded: isOpen
29610
29623
  })));
29611
29624
  }
29612
- const styles$H = StyleSheet.create({
29625
+ const styles$G = StyleSheet.create({
29613
29626
  container: {
29614
29627
  marginTop: spacing.small_12,
29615
29628
  // NOTE(jeremy): This is the inverse of the @editorPadding CSS
@@ -29669,7 +29682,7 @@ function InteractiveGraphDescription(props) {
29669
29682
  isOpen: isOpen,
29670
29683
  onToggle: setIsOpen
29671
29684
  }), isOpen && /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(LabelXSmall, {
29672
- style: styles$G.caption
29685
+ style: styles$F.caption
29673
29686
  }, "Use these fields to describe the graph as a whole. These are used by screen readers to describe content to users who are visually impaired."), /*#__PURE__*/React.createElement(LabelLarge, {
29674
29687
  tag: "label"
29675
29688
  }, "Title", /*#__PURE__*/React.createElement(TextField, {
@@ -29677,7 +29690,7 @@ function InteractiveGraphDescription(props) {
29677
29690
  onChange: newValue => onChange({
29678
29691
  fullGraphAriaLabel: newValue
29679
29692
  }),
29680
- style: styles$G.spaceAbove
29693
+ style: styles$F.spaceAbove
29681
29694
  })), /*#__PURE__*/React.createElement(Strut, {
29682
29695
  size: spacing.small_12
29683
29696
  }), /*#__PURE__*/React.createElement(LabelLarge, {
@@ -29689,10 +29702,10 @@ function InteractiveGraphDescription(props) {
29689
29702
  onChange: newValue => onChange({
29690
29703
  fullGraphAriaDescription: newValue
29691
29704
  }),
29692
- style: styles$G.spaceAbove
29705
+ style: styles$F.spaceAbove
29693
29706
  }))));
29694
29707
  }
29695
- const styles$G = StyleSheet.create({
29708
+ const styles$F = StyleSheet.create({
29696
29709
  caption: {
29697
29710
  color: color.offBlack64,
29698
29711
  paddingTop: spacing.xxSmall_6,
@@ -29712,16 +29725,16 @@ const LabeledRow = props => {
29712
29725
  style
29713
29726
  } = props;
29714
29727
  return /*#__PURE__*/React.createElement("label", {
29715
- className: css(styles$F.label)
29728
+ className: css(styles$E.label)
29716
29729
  }, /*#__PURE__*/React.createElement(View, {
29717
- style: [styles$F.row, style]
29730
+ style: [styles$E.row, style]
29718
29731
  }, labelSide === "start" || /*#__PURE__*/React.createElement(LabelSmall, {
29719
- style: styles$F.spaceEnd
29732
+ style: styles$E.spaceEnd
29720
29733
  }, label), children, labelSide === "end" && /*#__PURE__*/React.createElement(LabelSmall, {
29721
- style: styles$F.spaceStart
29734
+ style: styles$E.spaceStart
29722
29735
  }, label)));
29723
29736
  };
29724
- const styles$F = StyleSheet.create({
29737
+ const styles$E = StyleSheet.create({
29725
29738
  label: {
29726
29739
  width: "fit-content"
29727
29740
  },
@@ -30115,10 +30128,10 @@ class InteractiveGraphSettings extends React.Component {
30115
30128
  }
30116
30129
  }))), /*#__PURE__*/React.createElement(LabeledRow, {
30117
30130
  label: "Background image URL:",
30118
- style: styles$E.resetSpaceTop
30131
+ style: styles$D.resetSpaceTop
30119
30132
  }, /*#__PURE__*/React.createElement("input", {
30120
30133
  type: "text",
30121
- className: css(styles$E.backgroundUrlInput),
30134
+ className: css(styles$D.backgroundUrlInput),
30122
30135
  ref: this.bgUrlRef,
30123
30136
  value: this.state.backgroundImage.url || "",
30124
30137
  onChange: e => {
@@ -30132,9 +30145,9 @@ class InteractiveGraphSettings extends React.Component {
30132
30145
  onKeyPress: this.changeBackgroundUrl,
30133
30146
  onBlur: this.changeBackgroundUrl
30134
30147
  }), /*#__PURE__*/React.createElement(InfoTip$d, null, /*#__PURE__*/React.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background."))), /*#__PURE__*/React.createElement(View, {
30135
- style: styles$E.protractorSection
30148
+ style: styles$D.protractorSection
30136
30149
  }, /*#__PURE__*/React.createElement(View, {
30137
- style: styles$E.checkboxRow
30150
+ style: styles$D.checkboxRow
30138
30151
  }, /*#__PURE__*/React.createElement(Checkbox$1, {
30139
30152
  label: "Show protractor",
30140
30153
  checked: this.props.showProtractor,
@@ -30143,7 +30156,7 @@ class InteractiveGraphSettings extends React.Component {
30143
30156
  showProtractor: value
30144
30157
  });
30145
30158
  },
30146
- style: styles$E.resetSpaceTop
30159
+ style: styles$D.resetSpaceTop
30147
30160
  })), this.props.showProtractor && /*#__PURE__*/React.createElement(Banner, {
30148
30161
  layout: "floating",
30149
30162
  text: "The protractor is not accessible. Please consider an alternate approach.",
@@ -30164,7 +30177,7 @@ InteractiveGraphSettings.defaultProps = {
30164
30177
  showProtractor: false,
30165
30178
  showTooltips: false
30166
30179
  };
30167
- const styles$E = StyleSheet.create({
30180
+ const styles$D = StyleSheet.create({
30168
30181
  resetSpaceTop: {
30169
30182
  marginTop: 0
30170
30183
  },
@@ -30201,13 +30214,13 @@ const SegmentCountSelector = ({
30201
30214
  const num = +newValue;
30202
30215
  onChange(num);
30203
30216
  },
30204
- style: styles$D.singleSelectShort
30217
+ style: styles$C.singleSelectShort
30205
30218
  }, _.range(1, 7).map(n => /*#__PURE__*/React.createElement(OptionItem, {
30206
30219
  key: n,
30207
30220
  value: `${n}`,
30208
30221
  label: `${n} segment${n > 1 ? "s" : ""}`
30209
30222
  })));
30210
- const styles$D = StyleSheet.create({
30223
+ const styles$C = StyleSheet.create({
30211
30224
  singleSelectShort: {
30212
30225
  // Non-standard spacing, but it's the smallest we can go
30213
30226
  // without running into styling issues with the dropdown.
@@ -30232,17 +30245,17 @@ const LockedFigureSelect = props => {
30232
30245
  figureTypes.push("label");
30233
30246
  }
30234
30247
  return /*#__PURE__*/React.createElement(View, {
30235
- style: styles$C.container
30248
+ style: styles$B.container
30236
30249
  }, /*#__PURE__*/React.createElement(ActionMenu, {
30237
30250
  menuText: "Add locked figure",
30238
- style: styles$C.addElementSelect
30251
+ style: styles$B.addElementSelect
30239
30252
  }, figureTypes.map(figureType => /*#__PURE__*/React.createElement(ActionItem, {
30240
30253
  key: `${id}-${figureType}`,
30241
30254
  label: figureType,
30242
30255
  onClick: () => onChange(figureType)
30243
30256
  }))));
30244
30257
  };
30245
- const styles$C = StyleSheet.create({
30258
+ const styles$B = StyleSheet.create({
30246
30259
  container: {
30247
30260
  marginTop: spacing.xSmall_8
30248
30261
  },
@@ -30359,18 +30372,18 @@ const AngleInput = props => {
30359
30372
  }
30360
30373
  return /*#__PURE__*/React.createElement(LabelMedium, {
30361
30374
  tag: "label",
30362
- style: styles$B.row
30375
+ style: styles$A.row
30363
30376
  }, "angle (degrees)", /*#__PURE__*/React.createElement(Strut, {
30364
30377
  size: spacing.xxSmall_6
30365
30378
  }), /*#__PURE__*/React.createElement(ScrolllessNumberTextField, {
30366
30379
  value: angleInput,
30367
30380
  onChange: handleAngleChange,
30368
- style: styles$B.textField
30381
+ style: styles$A.textField
30369
30382
  }), /*#__PURE__*/React.createElement(Strut, {
30370
30383
  size: spacing.xxSmall_6
30371
30384
  }));
30372
30385
  };
30373
- const styles$B = StyleSheet.create({
30386
+ const styles$A = StyleSheet.create({
30374
30387
  row: {
30375
30388
  display: "flex",
30376
30389
  flexDirection: "row",
@@ -30419,30 +30432,30 @@ const CoordinatePairInput = props => {
30419
30432
  onChange(newCoords);
30420
30433
  }
30421
30434
  return /*#__PURE__*/React.createElement(View, {
30422
- style: [styles$A.row, style]
30435
+ style: [styles$z.row, style]
30423
30436
  }, /*#__PURE__*/React.createElement(LabelMedium, {
30424
30437
  tag: "label",
30425
- style: styles$A.row
30438
+ style: styles$z.row
30426
30439
  }, labels ? labels[0] : "x coord", /*#__PURE__*/React.createElement(Strut, {
30427
30440
  size: spacing.xxSmall_6
30428
30441
  }), /*#__PURE__*/React.createElement(ScrolllessNumberTextField, {
30429
30442
  value: coordState[0],
30430
30443
  onChange: newValue => handleCoordChange(newValue, 0),
30431
- style: [styles$A.textField, error ? styles$A.errorField : undefined]
30444
+ style: [styles$z.textField, error ? styles$z.errorField : undefined]
30432
30445
  })), /*#__PURE__*/React.createElement(Strut, {
30433
30446
  size: spacing.medium_16
30434
30447
  }), /*#__PURE__*/React.createElement(LabelMedium, {
30435
30448
  tag: "label",
30436
- style: styles$A.row
30449
+ style: styles$z.row
30437
30450
  }, labels ? labels[1] : "y coord", /*#__PURE__*/React.createElement(Strut, {
30438
30451
  size: spacing.xxSmall_6
30439
30452
  }), /*#__PURE__*/React.createElement(ScrolllessNumberTextField, {
30440
30453
  value: coordState[1],
30441
30454
  onChange: newValue => handleCoordChange(newValue, 1),
30442
- style: [styles$A.textField, error ? styles$A.errorField : undefined]
30455
+ style: [styles$z.textField, error ? styles$z.errorField : undefined]
30443
30456
  })));
30444
30457
  };
30445
- const styles$A = StyleSheet.create({
30458
+ const styles$z = StyleSheet.create({
30446
30459
  row: {
30447
30460
  display: "flex",
30448
30461
  flexDirection: "row",
@@ -30475,14 +30488,14 @@ const PerseusEditorAccordion = props => {
30475
30488
  }, /*#__PURE__*/React.createElement(AccordionSection, {
30476
30489
  expanded: expanded,
30477
30490
  onToggle: onToggle,
30478
- style: [styles$z.container, containerStyle],
30479
- headerStyle: styles$z.accordionHeader,
30491
+ style: [styles$y.container, containerStyle],
30492
+ headerStyle: styles$y.accordionHeader,
30480
30493
  header: header
30481
30494
  }, /*#__PURE__*/React.createElement(View, {
30482
- style: [styles$z.accordionPanel, panelStyle]
30495
+ style: [styles$y.accordionPanel, panelStyle]
30483
30496
  }, children)));
30484
30497
  };
30485
- const styles$z = StyleSheet.create({
30498
+ const styles$y = StyleSheet.create({
30486
30499
  container: {
30487
30500
  backgroundColor: color.fadedBlue8,
30488
30501
  marginTop: spacing.xSmall_8
@@ -30513,13 +30526,13 @@ const ColorSwatch = props => {
30513
30526
  "aria-label":
30514
30527
  // Don't include an aria label for decorative circles.
30515
30528
  !decorative ? `${color$1}, ${filled ? "filled" : "open"}` : undefined,
30516
- style: [styles$y.colorSwatch, {
30529
+ style: [styles$x.colorSwatch, {
30517
30530
  border: `4px solid ${lockedFigureColors[color$1]}`,
30518
30531
  backgroundColor: filled ? lockedFigureColors[color$1] : color.white
30519
30532
  }]
30520
30533
  });
30521
30534
  };
30522
- const styles$y = StyleSheet.create({
30535
+ const styles$x = StyleSheet.create({
30523
30536
  colorSwatch: {
30524
30537
  // Add a white outline so that the color swatch is visible when
30525
30538
  // the dropdown option is highlighted with its blue background.
@@ -30538,10 +30551,10 @@ const ColorSelect = props => {
30538
30551
  onChange
30539
30552
  } = props;
30540
30553
  return /*#__PURE__*/React.createElement(View, {
30541
- style: [styles$x.row, style]
30554
+ style: [styles$w.row, style]
30542
30555
  }, /*#__PURE__*/React.createElement(LabelMedium, {
30543
30556
  tag: "label",
30544
- style: styles$x.row
30557
+ style: styles$w.row
30545
30558
  }, "color", /*#__PURE__*/React.createElement(Strut, {
30546
30559
  size: spacing.xxSmall_6
30547
30560
  }), /*#__PURE__*/React.createElement(SingleSelect, {
@@ -30560,7 +30573,7 @@ const ColorSelect = props => {
30560
30573
  })
30561
30574
  })))));
30562
30575
  };
30563
- const styles$x = StyleSheet.create({
30576
+ const styles$w = StyleSheet.create({
30564
30577
  row: {
30565
30578
  display: "flex",
30566
30579
  flexDirection: "row",
@@ -30579,17 +30592,17 @@ const EllipseSwatch = props => {
30579
30592
  } = props;
30580
30593
  return /*#__PURE__*/React.createElement(View, {
30581
30594
  "aria-label": `${color}, stroke ${strokeStyle}, fill ${fillStyle}`,
30582
- style: [styles$w.container, {
30595
+ style: [styles$v.container, {
30583
30596
  border: `4px ${strokeStyle} ${lockedFigureColors[color]}`
30584
30597
  }]
30585
30598
  }, /*#__PURE__*/React.createElement(View, {
30586
- style: [styles$w.innerCircle, {
30599
+ style: [styles$v.innerCircle, {
30587
30600
  backgroundColor: lockedFigureColors[color],
30588
30601
  opacity: fillStyle === "white" ? 0 : lockedFigureFillStyles[fillStyle]
30589
30602
  }]
30590
30603
  }));
30591
30604
  };
30592
- const styles$w = StyleSheet.create({
30605
+ const styles$v = StyleSheet.create({
30593
30606
  container: {
30594
30607
  // Add a white outline so that the color swatch is visible when
30595
30608
  // the dropdown option is highlighted with its blue background.
@@ -30615,7 +30628,7 @@ const LineStrokeSelect = props => {
30615
30628
  } = props;
30616
30629
  return /*#__PURE__*/React.createElement(LabelMedium, {
30617
30630
  tag: "label",
30618
- style: styles$v.lineStrokeSelect
30631
+ style: styles$u.lineStrokeSelect
30619
30632
  }, "stroke", /*#__PURE__*/React.createElement(Strut, {
30620
30633
  size: spacing.xxxSmall_4
30621
30634
  }), /*#__PURE__*/React.createElement(SingleSelect, {
@@ -30632,7 +30645,7 @@ const LineStrokeSelect = props => {
30632
30645
  label: "dashed"
30633
30646
  })));
30634
30647
  };
30635
- const styles$v = StyleSheet.create({
30648
+ const styles$u = StyleSheet.create({
30636
30649
  lineStrokeSelect: {
30637
30650
  display: "flex",
30638
30651
  flexDirection: "row",
@@ -30654,40 +30667,40 @@ const LockedFigureSettingsActions = props => {
30654
30667
  onRemove
30655
30668
  } = props;
30656
30669
  return /*#__PURE__*/React.createElement(View, {
30657
- style: styles$u.container
30670
+ style: styles$t.container
30658
30671
  }, /*#__PURE__*/React.createElement(Button, {
30659
30672
  startIcon: trashIcon,
30660
30673
  "aria-label": `Delete locked ${figureType}`,
30661
30674
  onClick: onRemove,
30662
30675
  kind: "tertiary",
30663
- style: styles$u.deleteButton
30676
+ style: styles$t.deleteButton
30664
30677
  }, "Delete"), onMove && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Spring, null), /*#__PURE__*/React.createElement(IconButton, {
30665
30678
  icon: caretDoubleUpIcon,
30666
30679
  size: "small",
30667
30680
  "aria-label": `Move locked ${figureType} to the back`,
30668
30681
  onClick: () => onMove("back"),
30669
- style: styles$u.iconButton
30682
+ style: styles$t.iconButton
30670
30683
  }), /*#__PURE__*/React.createElement(IconButton, {
30671
30684
  icon: caretUpIcon,
30672
30685
  size: "small",
30673
30686
  "aria-label": `Move locked ${figureType} backward`,
30674
30687
  onClick: () => onMove("backward"),
30675
- style: styles$u.iconButton
30688
+ style: styles$t.iconButton
30676
30689
  }), /*#__PURE__*/React.createElement(IconButton, {
30677
30690
  icon: caretDownIcon,
30678
30691
  size: "small",
30679
30692
  "aria-label": `Move locked ${figureType} forward`,
30680
30693
  onClick: () => onMove("forward"),
30681
- style: styles$u.iconButton
30694
+ style: styles$t.iconButton
30682
30695
  }), /*#__PURE__*/React.createElement(IconButton, {
30683
30696
  icon: caretDoubleDownIcon,
30684
30697
  size: "small",
30685
30698
  "aria-label": `Move locked ${figureType} to the front`,
30686
30699
  onClick: () => onMove("front"),
30687
- style: styles$u.iconButton
30700
+ style: styles$t.iconButton
30688
30701
  })));
30689
30702
  };
30690
- const styles$u = StyleSheet.create({
30703
+ const styles$t = StyleSheet.create({
30691
30704
  container: {
30692
30705
  width: "100%",
30693
30706
  flexDirection: "row",
@@ -30734,7 +30747,7 @@ const LockedEllipseSettings = props => {
30734
30747
  /*#__PURE__*/
30735
30748
  // Summary: Ellipse, center, radius, color (opacity, dashed)
30736
30749
  React.createElement(View, {
30737
- style: styles$t.row
30750
+ style: styles$s.row
30738
30751
  }, /*#__PURE__*/React.createElement(LabelLarge, null, `Ellipse (${center[0]}, ${center[1]}), radius ${radius[0]}, ${radius[1]}`), /*#__PURE__*/React.createElement(Strut, {
30739
30752
  size: spacing.xSmall_8
30740
30753
  }), /*#__PURE__*/React.createElement(EllipseSwatch, {
@@ -30743,19 +30756,19 @@ const LockedEllipseSettings = props => {
30743
30756
  strokeStyle: strokeStyle
30744
30757
  }))
30745
30758
  }, /*#__PURE__*/React.createElement(View, {
30746
- style: styles$t.row
30759
+ style: styles$s.row
30747
30760
  }, /*#__PURE__*/React.createElement(CoordinatePairInput, {
30748
30761
  coord: center,
30749
- style: styles$t.spaceUnder,
30762
+ style: styles$s.spaceUnder,
30750
30763
  onChange: newCoords => onChangeProps({
30751
30764
  center: newCoords
30752
30765
  })
30753
30766
  }), /*#__PURE__*/React.createElement(View, {
30754
- style: styles$t.spaceUnder
30767
+ style: styles$s.spaceUnder
30755
30768
  }, /*#__PURE__*/React.createElement(InfoTip$c, null, "The coordinates for the center of the ellipse."))), /*#__PURE__*/React.createElement(CoordinatePairInput, {
30756
30769
  coord: radius,
30757
30770
  labels: ["x radius", "y radius"],
30758
- style: styles$t.spaceUnder,
30771
+ style: styles$s.spaceUnder,
30759
30772
  onChange: newCoords => onChangeProps({
30760
30773
  radius: newCoords
30761
30774
  })
@@ -30767,7 +30780,7 @@ const LockedEllipseSettings = props => {
30767
30780
  }), /*#__PURE__*/React.createElement(Strut, {
30768
30781
  size: spacing.xSmall_8
30769
30782
  }), /*#__PURE__*/React.createElement(View, {
30770
- style: [styles$t.row, styles$t.spaceUnder]
30783
+ style: [styles$s.row, styles$s.spaceUnder]
30771
30784
  }, /*#__PURE__*/React.createElement(ColorSelect, {
30772
30785
  selectedValue: color,
30773
30786
  onChange: handleColorChange
@@ -30775,7 +30788,7 @@ const LockedEllipseSettings = props => {
30775
30788
  size: spacing.medium_16
30776
30789
  }), /*#__PURE__*/React.createElement(LabelMedium, {
30777
30790
  tag: "label",
30778
- style: [styles$t.row, styles$t.truncatedWidth]
30791
+ style: [styles$s.row, styles$s.truncatedWidth]
30779
30792
  }, "fill", /*#__PURE__*/React.createElement(Strut, {
30780
30793
  size: spacing.xxSmall_6
30781
30794
  }), /*#__PURE__*/React.createElement(SingleSelect, {
@@ -30801,7 +30814,7 @@ const LockedEllipseSettings = props => {
30801
30814
  onRemove: onRemove
30802
30815
  }));
30803
30816
  };
30804
- const styles$t = StyleSheet.create({
30817
+ const styles$s = StyleSheet.create({
30805
30818
  row: {
30806
30819
  display: "flex",
30807
30820
  flexDirection: "row",
@@ -30822,15 +30835,15 @@ const LineSwatch = props => {
30822
30835
  lineStyle
30823
30836
  } = props;
30824
30837
  return /*#__PURE__*/React.createElement(View, {
30825
- style: styles$s.container
30838
+ style: styles$r.container
30826
30839
  }, /*#__PURE__*/React.createElement(View, {
30827
30840
  "aria-label": `${color}, ${lineStyle}`,
30828
- style: [styles$s.lineSwatch, {
30841
+ style: [styles$r.lineSwatch, {
30829
30842
  border: `5px ${lineStyle} ${lockedFigureColors[color]}`
30830
30843
  }]
30831
30844
  }));
30832
30845
  };
30833
- const styles$s = StyleSheet.create({
30846
+ const styles$r = StyleSheet.create({
30834
30847
  container: {
30835
30848
  backgroundColor: color.white,
30836
30849
  justifyContent: "center",
@@ -30915,9 +30928,9 @@ const LockedFunctionSettings = props => {
30915
30928
  expanded: props.expanded,
30916
30929
  onToggle: props.onToggle,
30917
30930
  header: /*#__PURE__*/React.createElement(View, {
30918
- style: styles$r.row
30931
+ style: styles$q.row
30919
30932
  }, /*#__PURE__*/React.createElement(LabelLarge, {
30920
- style: styles$r.accordionHeader
30933
+ style: styles$q.accordionHeader
30921
30934
  }, lineLabel), /*#__PURE__*/React.createElement(Strut, {
30922
30935
  size: spacing.xSmall_8
30923
30936
  }), /*#__PURE__*/React.createElement(LineSwatch, {
@@ -30925,7 +30938,7 @@ const LockedFunctionSettings = props => {
30925
30938
  lineStyle: strokeStyle
30926
30939
  }))
30927
30940
  }, /*#__PURE__*/React.createElement(View, {
30928
- style: [styles$r.row, styles$r.spaceUnder]
30941
+ style: [styles$q.row, styles$q.spaceUnder]
30929
30942
  }, /*#__PURE__*/React.createElement(ColorSelect, {
30930
30943
  selectedValue: lineColor,
30931
30944
  onChange: newValue => {
@@ -30939,14 +30952,14 @@ const LockedFunctionSettings = props => {
30939
30952
  handlePropChange("strokeStyle", newValue);
30940
30953
  }
30941
30954
  })), /*#__PURE__*/React.createElement(View, {
30942
- style: [styles$r.row, styles$r.rowSpace]
30955
+ style: [styles$q.row, styles$q.rowSpace]
30943
30956
  }, /*#__PURE__*/React.createElement(SingleSelect, {
30944
30957
  selectedValue: directionalAxis,
30945
30958
  onChange: newValue => {
30946
30959
  handlePropChange("directionalAxis", newValue);
30947
30960
  },
30948
30961
  "aria-label": "equation prefix",
30949
- style: [styles$r.dropdownLabel, styles$r.axisMenu]
30962
+ style: [styles$q.dropdownLabel, styles$q.axisMenu]
30950
30963
  // Placeholder is required, but never gets used.
30951
30964
  ,
30952
30965
  placeholder: ""
@@ -30965,17 +30978,17 @@ const LockedFunctionSettings = props => {
30965
30978
  onChange: newValue => {
30966
30979
  handlePropChange("equation", newValue);
30967
30980
  },
30968
- style: [styles$r.textField]
30981
+ style: [styles$q.textField]
30969
30982
  })), /*#__PURE__*/React.createElement(View, {
30970
- style: [styles$r.row, styles$r.rowSpace]
30983
+ style: [styles$q.row, styles$q.rowSpace]
30971
30984
  }, /*#__PURE__*/React.createElement(LabelMedium, {
30972
30985
  tag: "label",
30973
- style: [styles$r.dropdownLabel, styles$r.domainMin]
30986
+ style: [styles$q.dropdownLabel, styles$q.domainMin]
30974
30987
  }, `${domainRangeText} min`, /*#__PURE__*/React.createElement(Strut, {
30975
30988
  size: spacing.xxSmall_6
30976
30989
  }), /*#__PURE__*/React.createElement(TextField, {
30977
30990
  type: "number",
30978
- style: styles$r.domainMinField,
30991
+ style: styles$q.domainMinField,
30979
30992
  value: domainEntries[0],
30980
30993
  onChange: newValue => {
30981
30994
  handleDomainChange(0, newValue);
@@ -30985,12 +30998,12 @@ const LockedFunctionSettings = props => {
30985
30998
  }), /*#__PURE__*/React.createElement(LabelMedium, {
30986
30999
  tag: "label",
30987
31000
  "aria-label": `${domainRangeText} max`,
30988
- style: [styles$r.dropdownLabel, styles$r.domainMax]
31001
+ style: [styles$q.dropdownLabel, styles$q.domainMax]
30989
31002
  }, "max", /*#__PURE__*/React.createElement(Strut, {
30990
31003
  size: spacing.xxSmall_6
30991
31004
  }), /*#__PURE__*/React.createElement(TextField, {
30992
31005
  type: "number",
30993
- style: styles$r.domainMaxField,
31006
+ style: styles$q.domainMaxField,
30994
31007
  value: domainEntries[1],
30995
31008
  onChange: newValue => {
30996
31009
  handleDomainChange(1, newValue);
@@ -30998,11 +31011,11 @@ const LockedFunctionSettings = props => {
30998
31011
  }))), /*#__PURE__*/React.createElement(PerseusEditorAccordion, {
30999
31012
  header: /*#__PURE__*/React.createElement(LabelLarge, null, "Example Functions"),
31000
31013
  expanded: false,
31001
- containerStyle: styles$r.exampleWorkspace,
31002
- panelStyle: styles$r.exampleAccordionPanel
31014
+ containerStyle: styles$q.exampleWorkspace,
31015
+ panelStyle: styles$q.exampleAccordionPanel
31003
31016
  }, /*#__PURE__*/React.createElement(LabelMedium, {
31004
31017
  tag: "label",
31005
- style: styles$r.dropdownLabel
31018
+ style: styles$q.dropdownLabel
31006
31019
  }, "Choose a category", /*#__PURE__*/React.createElement(Strut, {
31007
31020
  size: spacing.xxSmall_6
31008
31021
  }), /*#__PURE__*/React.createElement(SingleSelect, {
@@ -31016,7 +31029,7 @@ const LockedFunctionSettings = props => {
31016
31029
  label: category
31017
31030
  });
31018
31031
  }))), exampleCategorySelected && /*#__PURE__*/React.createElement("ul", {
31019
- className: css(styles$r.exampleContainer)
31032
+ className: css(styles$q.exampleContainer)
31020
31033
  }, exampleContent.map((example, index) => /*#__PURE__*/React.createElement(ExampleItem, {
31021
31034
  category: exampleCategory,
31022
31035
  example: example,
@@ -31038,29 +31051,29 @@ const ExampleItem = props => {
31038
31051
  const exampleId = useId();
31039
31052
  return /*#__PURE__*/React.createElement("li", {
31040
31053
  key: `${category}-${index}`,
31041
- className: css(styles$r.exampleRow)
31054
+ className: css(styles$q.exampleRow)
31042
31055
  }, /*#__PURE__*/React.createElement(IconButton, {
31043
31056
  icon: autoPasteIcon,
31044
31057
  "aria-label": "paste example",
31045
31058
  "aria-describedby": exampleId,
31046
31059
  onClick: () => pasteEquationFn("equation", example),
31047
31060
  size: "medium",
31048
- style: styles$r.copyPasteButton
31061
+ style: styles$q.copyPasteButton
31049
31062
  }), /*#__PURE__*/React.createElement(IconButton, {
31050
31063
  icon: copyIcon,
31051
31064
  "aria-label": "copy example",
31052
31065
  "aria-describedby": exampleId,
31053
31066
  onClick: () => navigator.clipboard.writeText(example),
31054
31067
  size: "medium",
31055
- style: styles$r.copyPasteButton
31068
+ style: styles$q.copyPasteButton
31056
31069
  }), /*#__PURE__*/React.createElement(Strut, {
31057
31070
  size: spacing.xxxSmall_4
31058
31071
  }), /*#__PURE__*/React.createElement(View, {
31059
- style: styles$r.exampleContent,
31072
+ style: styles$q.exampleContent,
31060
31073
  id: exampleId
31061
31074
  }, example));
31062
31075
  };
31063
- const styles$r = StyleSheet.create({
31076
+ const styles$q = StyleSheet.create({
31064
31077
  accordionHeader: {
31065
31078
  textOverflow: "ellipsis",
31066
31079
  // A maximum width needs to be specified in order for the ellipsis to work.
@@ -31172,22 +31185,23 @@ function LockedLabelSettings(props) {
31172
31185
  onChangeProps,
31173
31186
  onMove,
31174
31187
  onRemove,
31175
- onToggle
31188
+ onToggle,
31189
+ containerStyle
31176
31190
  } = props;
31177
31191
  return /*#__PURE__*/React.createElement(PerseusEditorAccordion, {
31178
31192
  expanded: expanded,
31179
31193
  onToggle: onToggle,
31180
31194
  header: /*#__PURE__*/React.createElement(View, {
31181
- style: [styles$q.row, styles$q.accordionHeaderContainer]
31195
+ style: [styles$p.row, styles$p.accordionHeaderContainer]
31182
31196
  }, /*#__PURE__*/React.createElement(LabelLarge, null, "Label (", coord[0], ", ", coord[1], ")"), /*#__PURE__*/React.createElement(Strut, {
31183
31197
  size: spacing.xSmall_8
31184
31198
  }), text !== "" && /*#__PURE__*/React.createElement(LabelLarge, {
31185
31199
  style: [{
31186
31200
  backgroundColor: color.white,
31187
31201
  color: lockedFigureColors[color$1]
31188
- }, styles$q.accordionHeader]
31202
+ }, styles$p.accordionHeader]
31189
31203
  }, text)),
31190
- containerStyle: !onMove && styles$q.innerLabelAccordionPanel
31204
+ containerStyle: containerStyle
31191
31205
  }, /*#__PURE__*/React.createElement(CoordinatePairInput, {
31192
31206
  coord: coord,
31193
31207
  onChange: newCoords => {
@@ -31195,10 +31209,10 @@ function LockedLabelSettings(props) {
31195
31209
  coord: newCoords
31196
31210
  });
31197
31211
  },
31198
- style: styles$q.spaceUnder
31212
+ style: styles$p.spaceUnder
31199
31213
  }), /*#__PURE__*/React.createElement(LabelMedium, {
31200
31214
  tag: "label",
31201
- style: [styles$q.row, styles$q.spaceUnder]
31215
+ style: [styles$p.row, styles$p.spaceUnder]
31202
31216
  }, "TeX", /*#__PURE__*/React.createElement(Strut, {
31203
31217
  size: spacing.xSmall_8
31204
31218
  }), /*#__PURE__*/React.createElement(TextField, {
@@ -31208,7 +31222,7 @@ function LockedLabelSettings(props) {
31208
31222
  text: newValue
31209
31223
  })
31210
31224
  })), /*#__PURE__*/React.createElement(View, {
31211
- style: styles$q.row
31225
+ style: styles$p.row
31212
31226
  }, onMove && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ColorSelect, {
31213
31227
  selectedValue: color$1,
31214
31228
  onChange: newColor => {
@@ -31216,12 +31230,12 @@ function LockedLabelSettings(props) {
31216
31230
  color: newColor
31217
31231
  });
31218
31232
  },
31219
- style: styles$q.spaceUnder
31233
+ style: styles$p.spaceUnder
31220
31234
  }), /*#__PURE__*/React.createElement(Strut, {
31221
31235
  size: spacing.medium_16
31222
31236
  })), /*#__PURE__*/React.createElement(LabelMedium, {
31223
31237
  tag: "label",
31224
- style: styles$q.row
31238
+ style: styles$p.row
31225
31239
  }, "size", /*#__PURE__*/React.createElement(Strut, {
31226
31240
  size: spacing.xSmall_8
31227
31241
  }), /*#__PURE__*/React.createElement(SingleSelect, {
@@ -31248,7 +31262,7 @@ function LockedLabelSettings(props) {
31248
31262
  onRemove: onRemove
31249
31263
  }));
31250
31264
  }
31251
- const styles$q = StyleSheet.create({
31265
+ const styles$p = StyleSheet.create({
31252
31266
  accordionHeaderContainer: {
31253
31267
  // Stop the label summary from wrapping.
31254
31268
  whiteSpace: "nowrap"
@@ -31269,9 +31283,6 @@ const styles$q = StyleSheet.create({
31269
31283
  },
31270
31284
  spaceUnder: {
31271
31285
  marginBottom: spacing.xSmall_8
31272
- },
31273
- innerLabelAccordionPanel: {
31274
- backgroundColor: color.white
31275
31286
  }
31276
31287
  });
31277
31288
 
@@ -31285,7 +31296,7 @@ const LabeledSwitch = props => {
31285
31296
  const ids = useUniqueIdWithMock();
31286
31297
  const switchId = ids.get("switch");
31287
31298
  return /*#__PURE__*/React.createElement(View, {
31288
- style: [styles$p.row, style]
31299
+ style: [styles$o.row, style]
31289
31300
  }, /*#__PURE__*/React.createElement(Switch, {
31290
31301
  id: switchId,
31291
31302
  checked: checked,
@@ -31297,71 +31308,168 @@ const LabeledSwitch = props => {
31297
31308
  htmlFor: switchId
31298
31309
  }, label));
31299
31310
  };
31300
- const styles$p = StyleSheet.create({
31311
+ const styles$o = StyleSheet.create({
31301
31312
  row: {
31302
31313
  flexDirection: "row",
31303
31314
  alignItems: "center"
31304
31315
  }
31305
31316
  });
31306
31317
 
31307
- /**
31308
- * DefiningPointSettings is a component that allows the user to edit the
31309
- * settings of a point that defines a locked figure (ex. line) on the graph.
31310
- *
31311
- * Used in the interactive graph editor's locked figures section.
31312
- */
31313
- const DefiningPointSettings = props => {
31318
+ const DEFAULT_COLOR = "grayH";
31319
+ function getDefaultFigureForType(type) {
31320
+ switch (type) {
31321
+ case "point":
31322
+ return {
31323
+ type: "point",
31324
+ coord: [0, 0],
31325
+ color: DEFAULT_COLOR,
31326
+ filled: true,
31327
+ labels: []
31328
+ };
31329
+ case "line":
31330
+ return {
31331
+ type: "line",
31332
+ kind: "line",
31333
+ points: [getDefaultFigureForType("point"), _extends({}, getDefaultFigureForType("point"), {
31334
+ coord: [2, 2]
31335
+ })],
31336
+ color: DEFAULT_COLOR,
31337
+ lineStyle: "solid",
31338
+ showPoint1: false,
31339
+ showPoint2: false,
31340
+ labels: []
31341
+ };
31342
+ case "vector":
31343
+ return {
31344
+ type: "vector",
31345
+ points: [[0, 0], [2, 2]],
31346
+ color: DEFAULT_COLOR
31347
+ };
31348
+ case "ellipse":
31349
+ return {
31350
+ type: "ellipse",
31351
+ center: [0, 0],
31352
+ radius: [1, 1],
31353
+ angle: 0,
31354
+ color: DEFAULT_COLOR,
31355
+ fillStyle: "none",
31356
+ strokeStyle: "solid"
31357
+ };
31358
+ case "polygon":
31359
+ return {
31360
+ type: "polygon",
31361
+ points: [[0, 2], [-1, 0], [1, 0]],
31362
+ color: DEFAULT_COLOR,
31363
+ showVertices: false,
31364
+ fillStyle: "none",
31365
+ strokeStyle: "solid"
31366
+ };
31367
+ case "function":
31368
+ return {
31369
+ type: "function",
31370
+ color: DEFAULT_COLOR,
31371
+ strokeStyle: "solid",
31372
+ equation: "x^2",
31373
+ directionalAxis: "x"
31374
+ };
31375
+ case "label":
31376
+ return {
31377
+ type: "label",
31378
+ coord: [0, 0],
31379
+ text: "",
31380
+ color: DEFAULT_COLOR,
31381
+ size: "medium"
31382
+ };
31383
+ default:
31384
+ throw new UnreachableCaseError(type);
31385
+ }
31386
+ }
31387
+
31388
+ const LockedPointSettings = props => {
31389
+ var _flags$mafs, _flags$mafs2;
31314
31390
  const {
31391
+ flags,
31392
+ headerLabel,
31315
31393
  coord,
31316
31394
  color: pointColor,
31317
31395
  filled = true,
31318
- label,
31319
- showPoint = "false",
31320
- error,
31396
+ labels,
31321
31397
  onChangeProps,
31322
- onTogglePoint,
31398
+ onMove,
31399
+ onRemove,
31400
+ // defining point props
31401
+ showPoint,
31323
31402
  expanded,
31403
+ onTogglePoint,
31324
31404
  onToggle
31325
31405
  } = props;
31406
+ const isDefiningPoint = !onMove && !onRemove;
31326
31407
  function handleColorChange(newValue) {
31327
- onChangeProps({
31408
+ const newProps = {
31328
31409
  color: newValue
31410
+ };
31411
+
31412
+ // Update the color of the all labels to match the point
31413
+ newProps.labels = labels.map(label => _extends({}, label, {
31414
+ color: newValue
31415
+ }));
31416
+ onChangeProps(newProps);
31417
+ }
31418
+ function handleCoordChange(newCoord) {
31419
+ const xOffset = newCoord[0] - coord[0];
31420
+ const yOffset = newCoord[1] - coord[1];
31421
+ const newProps = {
31422
+ coord: newCoord
31423
+ };
31424
+
31425
+ // Update the coord by the same amount as the point for all labels
31426
+ newProps.labels = labels.map(label => _extends({}, label, {
31427
+ coord: [label.coord[0] + xOffset, label.coord[1] + yOffset]
31428
+ }));
31429
+ onChangeProps(newProps);
31430
+ }
31431
+ function handleLabelChange(updatedLabel, labelIndex) {
31432
+ const updatedLabels = [...labels];
31433
+ updatedLabels[labelIndex] = _extends({}, labels[labelIndex], updatedLabel);
31434
+ onChangeProps({
31435
+ labels: updatedLabels
31436
+ });
31437
+ }
31438
+ function handleLabelRemove(labelIndex) {
31439
+ const updatedLabels = labels.filter((_, index) => index !== labelIndex);
31440
+ onChangeProps({
31441
+ labels: updatedLabels
31329
31442
  });
31330
31443
  }
31331
31444
  return /*#__PURE__*/React.createElement(PerseusEditorAccordion, {
31332
31445
  expanded: expanded,
31333
31446
  onToggle: onToggle,
31334
- containerStyle: styles$o.container,
31335
- panelStyle: styles$o.accordionPanel,
31447
+ containerStyle: isDefiningPoint ? styles$n.definingContainer : undefined,
31448
+ panelStyle: isDefiningPoint ? styles$n.definingPanel : undefined,
31336
31449
  header:
31337
31450
  /*#__PURE__*/
31338
31451
  // Summary: Point, coords, color (filled/open)
31339
31452
  React.createElement(View, {
31340
- style: styles$o.row
31341
- }, /*#__PURE__*/React.createElement(LabelLarge, null, `${label || "Point"} (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React.createElement(Strut, {
31453
+ style: styles$n.row
31454
+ }, /*#__PURE__*/React.createElement(LabelLarge, null, `${headerLabel || "Point"} (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React.createElement(Strut, {
31342
31455
  size: spacing.xSmall_8
31343
- }), showPoint && /*#__PURE__*/React.createElement(ColorSwatch, {
31456
+ }), /*#__PURE__*/React.createElement(ColorSwatch, {
31344
31457
  color: pointColor,
31345
31458
  filled: filled
31346
31459
  }))
31347
31460
  }, /*#__PURE__*/React.createElement(CoordinatePairInput, {
31348
31461
  coord: coord,
31349
- error: !!error,
31350
- style: styles$o.spaceUnder,
31351
- onChange: newCoords => {
31352
- onChangeProps({
31353
- coord: newCoords
31354
- });
31355
- }
31462
+ style: styles$n.spaceUnder,
31463
+ onChange: handleCoordChange
31356
31464
  }), onTogglePoint && /*#__PURE__*/React.createElement(LabeledSwitch, {
31357
31465
  label: "show point on graph",
31358
31466
  checked: !!showPoint,
31359
- style: showPoint && styles$o.spaceUnder,
31467
+ style: showPoint && styles$n.spaceUnder,
31360
31468
  onChange: onTogglePoint
31361
- }), showPoint && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ColorSelect, {
31469
+ }), (!isDefiningPoint || showPoint) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ColorSelect, {
31362
31470
  selectedValue: pointColor,
31363
31471
  onChange: handleColorChange,
31364
- style: styles$o.spaceUnder
31472
+ style: styles$n.spaceUnder
31365
31473
  }), /*#__PURE__*/React.createElement(LabeledSwitch, {
31366
31474
  label: "open point",
31367
31475
  checked: !filled,
@@ -31370,19 +31478,57 @@ const DefiningPointSettings = props => {
31370
31478
  filled: !newValue
31371
31479
  });
31372
31480
  }
31373
- })));
31481
+ })), (!isDefiningPoint && (flags == null || (_flags$mafs = flags["mafs"]) == null ? void 0 : _flags$mafs["locked-point-labels"]) || isDefiningPoint && (flags == null || (_flags$mafs2 = flags["mafs"]) == null ? void 0 : _flags$mafs2["locked-line-labels"])) && /*#__PURE__*/React.createElement(React.Fragment, null, labels.map((label, labelIndex) => /*#__PURE__*/React.createElement(LockedLabelSettings, _extends({}, label, {
31482
+ containerStyle: !isDefiningPoint && styles$n.lockedPointLabelContainer,
31483
+ expanded: true,
31484
+ onChangeProps: newLabel => {
31485
+ handleLabelChange(newLabel, labelIndex);
31486
+ },
31487
+ onRemove: () => {
31488
+ handleLabelRemove(labelIndex);
31489
+ }
31490
+ }))), /*#__PURE__*/React.createElement(Button, {
31491
+ kind: "tertiary",
31492
+ startIcon: plusCircle,
31493
+ onClick: () => {
31494
+ const newLabel = _extends({}, getDefaultFigureForType("label"), {
31495
+ // Place the label at the same position
31496
+ // as the point. Add a small offset to
31497
+ // avoid crowding.
31498
+ coord: [coord[0] + 0.5,
31499
+ // Additional offset for each label so
31500
+ // they don't overlap.
31501
+ coord[1] - 1 * (labels == null ? void 0 : labels.length)],
31502
+ // Default to the same color as the point
31503
+ color: pointColor
31504
+ });
31505
+ onChangeProps({
31506
+ labels: [...labels, newLabel]
31507
+ });
31508
+ },
31509
+ style: styles$n.addButton
31510
+ }, "Add visible label")), onRemove && /*#__PURE__*/React.createElement(LockedFigureSettingsActions, {
31511
+ figureType: props.type,
31512
+ onMove: onMove,
31513
+ onRemove: onRemove
31514
+ }));
31374
31515
  };
31375
- const styles$o = StyleSheet.create({
31376
- container: {
31516
+ const styles$n = StyleSheet.create({
31517
+ definingContainer: {
31377
31518
  marginTop: spacing.xSmall_8,
31378
31519
  marginBottom: 0,
31379
31520
  marginLeft: -spacing.xxxSmall_4,
31380
31521
  marginRight: -spacing.xxxSmall_4,
31381
31522
  backgroundColor: color.white
31382
31523
  },
31383
- accordionPanel: {
31524
+ definingPanel: {
31384
31525
  // Need more space since we don't have the actions' margins.
31385
- paddingBottom: spacing.medium_16
31526
+ paddingBottom: spacing.xxSmall_6
31527
+ },
31528
+ // A regular point (NOT a defining point) has label
31529
+ // accordions with white backgrounds.
31530
+ lockedPointLabelContainer: {
31531
+ backgroundColor: color.white
31386
31532
  },
31387
31533
  row: {
31388
31534
  flexDirection: "row",
@@ -31390,18 +31536,24 @@ const styles$o = StyleSheet.create({
31390
31536
  },
31391
31537
  spaceUnder: {
31392
31538
  marginBottom: spacing.xSmall_8
31539
+ },
31540
+ addButton: {
31541
+ alignSelf: "start"
31393
31542
  }
31394
31543
  });
31395
31544
 
31396
31545
  const lengthZeroStr = "The line cannot have length 0.";
31397
31546
  const LockedLineSettings = props => {
31547
+ var _flags$mafs;
31398
31548
  const {
31549
+ flags,
31399
31550
  kind,
31400
31551
  points,
31401
31552
  color: lineColor,
31402
31553
  lineStyle = "solid",
31403
31554
  showPoint1,
31404
31555
  showPoint2,
31556
+ labels,
31405
31557
  onChangeProps,
31406
31558
  onMove,
31407
31559
  onRemove
@@ -31416,26 +31568,60 @@ const LockedLineSettings = props => {
31416
31568
  function handleChangePoint(newPointProps, index) {
31417
31569
  const newPoints = [...points];
31418
31570
  newPoints[index] = _extends({}, points[index], newPointProps);
31571
+
31572
+ // Update labels to be centered between the two points,
31573
+ // retaining existing offset.
31574
+ const oldMidpoint = vec.midpoint(points[0].coord, points[1].coord);
31575
+ const newMidpoint = vec.midpoint(newPoints[0].coord, newPoints[1].coord);
31576
+ const offset = [newMidpoint[0] - oldMidpoint[0], newMidpoint[1] - oldMidpoint[1]];
31577
+ const newLabels = labels.map((label, labelIndex) => _extends({}, label, {
31578
+ coord: [label.coord[0] + offset[0], label.coord[1] + offset[1]]
31579
+ }));
31419
31580
  onChangeProps({
31420
- points: newPoints
31581
+ points: newPoints,
31582
+ labels: newLabels
31421
31583
  });
31422
31584
  }
31423
31585
  function handleColorChange(newColor) {
31586
+ const newLabels = labels.map(label => _extends({}, label, {
31587
+ color: newColor
31588
+ }));
31424
31589
  onChangeProps({
31425
31590
  color: newColor,
31426
31591
  // Keep the line's points' colors in sync with the line color.
31427
31592
  points: [_extends({}, point1, {
31428
- color: newColor
31593
+ color: newColor,
31594
+ labels: point1.labels.map(label => _extends({}, label, {
31595
+ color: newColor
31596
+ }))
31429
31597
  }), _extends({}, point2, {
31430
- color: newColor
31431
- })]
31598
+ color: newColor,
31599
+ labels: point2.labels.map(label => _extends({}, label, {
31600
+ color: newColor
31601
+ }))
31602
+ })],
31603
+ // Keep the line's labels' colors in sync with the line color.
31604
+ labels: newLabels
31605
+ });
31606
+ }
31607
+ function handleLabelChange(updatedLabel, labelIndex) {
31608
+ const updatedLabels = [...labels];
31609
+ updatedLabels[labelIndex] = _extends({}, labels[labelIndex], updatedLabel);
31610
+ onChangeProps({
31611
+ labels: updatedLabels
31612
+ });
31613
+ }
31614
+ function handleLabelRemove(labelIndex) {
31615
+ const updatedLabels = labels.filter((_, index) => index !== labelIndex);
31616
+ onChangeProps({
31617
+ labels: updatedLabels
31432
31618
  });
31433
31619
  }
31434
31620
  return /*#__PURE__*/React.createElement(PerseusEditorAccordion, {
31435
31621
  expanded: props.expanded,
31436
31622
  onToggle: props.onToggle,
31437
31623
  header: /*#__PURE__*/React.createElement(View, {
31438
- style: styles$n.row
31624
+ style: styles$m.row
31439
31625
  }, /*#__PURE__*/React.createElement(LabelLarge, null, lineLabel), /*#__PURE__*/React.createElement(Strut, {
31440
31626
  size: spacing.xSmall_8
31441
31627
  }), /*#__PURE__*/React.createElement(LineSwatch, {
@@ -31444,7 +31630,7 @@ const LockedLineSettings = props => {
31444
31630
  }))
31445
31631
  }, /*#__PURE__*/React.createElement(LabelMedium, {
31446
31632
  tag: "label",
31447
- style: [styles$n.row, styles$n.spaceUnder]
31633
+ style: [styles$m.row, styles$m.spaceUnder]
31448
31634
  }, "kind", /*#__PURE__*/React.createElement(Strut, {
31449
31635
  size: spacing.xxxSmall_4
31450
31636
  }), /*#__PURE__*/React.createElement(SingleSelect, {
@@ -31465,7 +31651,7 @@ const LockedLineSettings = props => {
31465
31651
  value: "segment",
31466
31652
  label: "segment"
31467
31653
  }))), /*#__PURE__*/React.createElement(View, {
31468
- style: styles$n.row
31654
+ style: styles$m.row
31469
31655
  }, /*#__PURE__*/React.createElement(ColorSelect, {
31470
31656
  selectedValue: lineColor,
31471
31657
  onChange: handleColorChange
@@ -31477,9 +31663,11 @@ const LockedLineSettings = props => {
31477
31663
  lineStyle: value
31478
31664
  })
31479
31665
  })), isInvalid && /*#__PURE__*/React.createElement(LabelMedium, {
31480
- style: styles$n.errorText
31481
- }, lengthZeroStr), /*#__PURE__*/React.createElement(DefiningPointSettings, _extends({
31482
- label: "Point 1",
31666
+ style: styles$m.errorText
31667
+ }, lengthZeroStr), /*#__PURE__*/React.createElement(LockedPointSettings, _extends({
31668
+ flags: flags,
31669
+ headerLabel: "Point 1",
31670
+ expanded: true,
31483
31671
  showPoint: showPoint1,
31484
31672
  error: isInvalid ? lengthZeroStr : null
31485
31673
  }, point1, {
@@ -31487,8 +31675,10 @@ const LockedLineSettings = props => {
31487
31675
  showPoint1: newValue
31488
31676
  }),
31489
31677
  onChangeProps: newProps => handleChangePoint(newProps, 0)
31490
- })), /*#__PURE__*/React.createElement(DefiningPointSettings, _extends({
31491
- label: "Point 2",
31678
+ })), /*#__PURE__*/React.createElement(LockedPointSettings, _extends({
31679
+ flags: flags,
31680
+ headerLabel: "Point 2",
31681
+ expanded: true,
31492
31682
  showPoint: showPoint2,
31493
31683
  error: isInvalid ? lengthZeroStr : null
31494
31684
  }, point2, {
@@ -31496,197 +31686,29 @@ const LockedLineSettings = props => {
31496
31686
  showPoint2: newValue
31497
31687
  }),
31498
31688
  onChangeProps: newProps => handleChangePoint(newProps, 1)
31499
- })), /*#__PURE__*/React.createElement(LockedFigureSettingsActions, {
31500
- figureType: props.type,
31501
- onMove: onMove,
31502
- onRemove: onRemove
31503
- }));
31504
- };
31505
- const styles$n = StyleSheet.create({
31506
- row: {
31507
- display: "flex",
31508
- flexDirection: "row",
31509
- alignItems: "center"
31510
- },
31511
- spaceUnder: {
31512
- marginBottom: spacing.xSmall_8
31513
- },
31514
- errorText: {
31515
- color: color.red
31516
- }
31517
- });
31518
-
31519
- const DEFAULT_COLOR = "grayH";
31520
- function getDefaultFigureForType(type) {
31521
- switch (type) {
31522
- case "point":
31523
- return {
31524
- type: "point",
31525
- coord: [0, 0],
31526
- color: DEFAULT_COLOR,
31527
- filled: true,
31528
- labels: []
31529
- };
31530
- case "line":
31531
- return {
31532
- type: "line",
31533
- kind: "line",
31534
- points: [getDefaultFigureForType("point"), _extends({}, getDefaultFigureForType("point"), {
31535
- coord: [2, 2]
31536
- })],
31537
- color: DEFAULT_COLOR,
31538
- lineStyle: "solid",
31539
- showPoint1: false,
31540
- showPoint2: false
31541
- };
31542
- case "vector":
31543
- return {
31544
- type: "vector",
31545
- points: [[0, 0], [2, 2]],
31546
- color: DEFAULT_COLOR
31547
- };
31548
- case "ellipse":
31549
- return {
31550
- type: "ellipse",
31551
- center: [0, 0],
31552
- radius: [1, 1],
31553
- angle: 0,
31554
- color: DEFAULT_COLOR,
31555
- fillStyle: "none",
31556
- strokeStyle: "solid"
31557
- };
31558
- case "polygon":
31559
- return {
31560
- type: "polygon",
31561
- points: [[0, 2], [-1, 0], [1, 0]],
31562
- color: DEFAULT_COLOR,
31563
- showVertices: false,
31564
- fillStyle: "none",
31565
- strokeStyle: "solid"
31566
- };
31567
- case "function":
31568
- return {
31569
- type: "function",
31570
- color: DEFAULT_COLOR,
31571
- strokeStyle: "solid",
31572
- equation: "x^2",
31573
- directionalAxis: "x"
31574
- };
31575
- case "label":
31576
- return {
31577
- type: "label",
31578
- coord: [0, 0],
31579
- text: "",
31580
- color: DEFAULT_COLOR,
31581
- size: "medium"
31582
- };
31583
- default:
31584
- throw new UnreachableCaseError(type);
31585
- }
31586
- }
31587
-
31588
- const LockedPointSettings = props => {
31589
- var _flags$mafs;
31590
- const {
31591
- flags,
31592
- coord,
31593
- color: pointColor,
31594
- filled = true,
31595
- labels,
31596
- onChangeProps,
31597
- onMove,
31598
- onRemove
31599
- } = props;
31600
- function handleColorChange(newValue) {
31601
- const newProps = {
31602
- color: newValue
31603
- };
31604
-
31605
- // Update the color of the all labels to match the point
31606
- newProps.labels = labels.map(label => _extends({}, label, {
31607
- color: newValue
31608
- }));
31609
- onChangeProps(newProps);
31610
- }
31611
- function handleCoordChange(newCoord) {
31612
- const xOffset = newCoord[0] - coord[0];
31613
- const yOffset = newCoord[1] - coord[1];
31614
- const newProps = {
31615
- coord: newCoord
31616
- };
31617
-
31618
- // Update the coord by the same amount as the point for all labels
31619
- newProps.labels = labels.map(label => _extends({}, label, {
31620
- coord: [label.coord[0] + xOffset, label.coord[1] + yOffset]
31621
- }));
31622
- onChangeProps(newProps);
31623
- }
31624
- function handleLabelChange(updatedLabel, labelIndex) {
31625
- const updatedLabels = [...labels];
31626
- updatedLabels[labelIndex] = _extends({}, labels[labelIndex], updatedLabel);
31627
- onChangeProps({
31628
- labels: updatedLabels
31629
- });
31630
- }
31631
- function handleLabelRemove(labelIndex) {
31632
- const updatedLabels = labels.filter((_, index) => index !== labelIndex);
31633
- onChangeProps({
31634
- labels: updatedLabels
31635
- });
31636
- }
31637
- return /*#__PURE__*/React.createElement(PerseusEditorAccordion, {
31638
- expanded: props.expanded,
31639
- onToggle: props.onToggle,
31640
- header:
31641
- /*#__PURE__*/
31642
- // Summary: Point, coords, color (filled/open)
31643
- React.createElement(View, {
31644
- style: styles$m.row
31645
- }, /*#__PURE__*/React.createElement(LabelLarge, null, `Point (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React.createElement(Strut, {
31646
- size: spacing.xSmall_8
31647
- }), /*#__PURE__*/React.createElement(ColorSwatch, {
31648
- color: pointColor,
31649
- filled: filled
31650
- }))
31651
- }, /*#__PURE__*/React.createElement(CoordinatePairInput, {
31652
- coord: coord,
31653
- style: styles$m.spaceUnder,
31654
- onChange: handleCoordChange
31655
- }), /*#__PURE__*/React.createElement(ColorSelect, {
31656
- selectedValue: pointColor,
31657
- onChange: handleColorChange,
31658
- style: styles$m.spaceUnder
31659
- }), /*#__PURE__*/React.createElement(LabeledSwitch, {
31660
- label: "open point",
31661
- checked: !filled,
31662
- onChange: newValue => {
31663
- onChangeProps({
31664
- filled: !newValue
31665
- });
31666
- },
31667
- style: styles$m.spaceUnder
31668
- }), (flags == null || (_flags$mafs = flags["mafs"]) == null ? void 0 : _flags$mafs["locked-point-labels"]) && /*#__PURE__*/React.createElement(React.Fragment, null, labels.map((label, labelIndex) => /*#__PURE__*/React.createElement(LockedLabelSettings, _extends({}, label, {
31689
+ })), (flags == null || (_flags$mafs = flags["mafs"]) == null ? void 0 : _flags$mafs["locked-line-labels"]) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
31690
+ style: styles$m.horizontalRule
31691
+ }), labels.map((label, labelIndex) => /*#__PURE__*/React.createElement(LockedLabelSettings, _extends({}, label, {
31669
31692
  expanded: true,
31670
31693
  onChangeProps: newLabel => {
31671
31694
  handleLabelChange(newLabel, labelIndex);
31672
31695
  },
31673
31696
  onRemove: () => {
31674
31697
  handleLabelRemove(labelIndex);
31675
- }
31698
+ },
31699
+ containerStyle: styles$m.labelContainer
31676
31700
  }))), /*#__PURE__*/React.createElement(Button, {
31677
31701
  kind: "tertiary",
31678
31702
  startIcon: plusCircle,
31679
31703
  onClick: () => {
31704
+ // Additional vertical offset for each label so
31705
+ // they don't overlap.
31706
+ const offsetPerLabel = [0, -1];
31707
+ const labelLocation = vec.add(vec.scale(offsetPerLabel, labels.length), vec.midpoint(points[0].coord, points[1].coord));
31680
31708
  const newLabel = _extends({}, getDefaultFigureForType("label"), {
31681
- // Place the label at the same position
31682
- // as the point. Add a small offset to
31683
- // avoid crowding.
31684
- coord: [coord[0] + 0.5,
31685
- // Additional offset for each label so
31686
- // they don't overlap.
31687
- coord[1] - 1 * (labels == null ? void 0 : labels.length)],
31709
+ coord: labelLocation,
31688
31710
  // Default to the same color as the point
31689
- color: pointColor
31711
+ color: lineColor
31690
31712
  });
31691
31713
  onChangeProps({
31692
31714
  labels: [...labels, newLabel]
@@ -31701,14 +31723,27 @@ const LockedPointSettings = props => {
31701
31723
  };
31702
31724
  const styles$m = StyleSheet.create({
31703
31725
  row: {
31726
+ display: "flex",
31704
31727
  flexDirection: "row",
31705
31728
  alignItems: "center"
31706
31729
  },
31707
31730
  spaceUnder: {
31708
31731
  marginBottom: spacing.xSmall_8
31709
31732
  },
31733
+ errorText: {
31734
+ color: color.red
31735
+ },
31710
31736
  addButton: {
31711
31737
  alignSelf: "start"
31738
+ },
31739
+ horizontalRule: {
31740
+ marginTop: spacing.small_12,
31741
+ marginBottom: spacing.xxxSmall_4,
31742
+ height: 1,
31743
+ backgroundColor: color.offBlack16
31744
+ },
31745
+ labelContainer: {
31746
+ backgroundColor: color.white
31712
31747
  }
31713
31748
  });
31714
31749