@khanacademy/perseus-editor 6.2.3 → 6.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -22,14 +22,14 @@ import { SingleSelect, OptionItem, ActionMenu, ActionItem } from '@khanacademy/w
22
22
  import { TextField, Checkbox as Checkbox$1 } from '@khanacademy/wonder-blocks-form';
23
23
  import { LabelSmall, LabelMedium, LabelLarge, BodyMonospace } from '@khanacademy/wonder-blocks-typography';
24
24
  import Banner from '@khanacademy/wonder-blocks-banner';
25
- import { AccordionSection } from '@khanacademy/wonder-blocks-accordion';
26
25
  import Button from '@khanacademy/wonder-blocks-button';
27
- import trashIcon from '@phosphor-icons/core/bold/trash-bold.svg';
28
26
  import Switch from '@khanacademy/wonder-blocks-switch';
27
+ import { AccordionSection } from '@khanacademy/wonder-blocks-accordion';
28
+ import trashIcon from '@phosphor-icons/core/bold/trash-bold.svg';
29
29
 
30
30
  // This file is processed by a Rollup plugin (replace) to inject the production
31
31
  const libName = "@khanacademy/perseus-editor";
32
- const libVersion = "6.2.3";
32
+ const libVersion = "6.4.1";
33
33
  addLibraryVersionToPerseusDebug(libName, libVersion);
34
34
 
35
35
  function _extends() {
@@ -219,7 +219,7 @@ class SectionControlButton extends React.Component {
219
219
  role: "button",
220
220
  hideDefaultFocusRing: true,
221
221
  "aria-label": title,
222
- style: styles$u.button
222
+ style: styles$y.button
223
223
  }, ({
224
224
  hovered,
225
225
  focused,
@@ -227,7 +227,7 @@ class SectionControlButton extends React.Component {
227
227
  }) => /*#__PURE__*/React.createElement(InlineIcon$b, icon));
228
228
  }
229
229
  }
230
- const styles$u = StyleSheet.create({
230
+ const styles$y = StyleSheet.create({
231
231
  button: {
232
232
  backgroundColor: color.gold,
233
233
  margin: 2,
@@ -20749,19 +20749,19 @@ class TexErrorView extends React.Component {
20749
20749
  const {
20750
20750
  showErrors
20751
20751
  } = this.state;
20752
- const iconStyle = showErrors ? styles$t.iconExpanded : styles$t.iconCollapsed;
20752
+ const iconStyle = showErrors ? styles$x.iconExpanded : styles$x.iconCollapsed;
20753
20753
  return /*#__PURE__*/React.createElement(View, {
20754
- style: styles$t.errorContainer
20754
+ style: styles$x.errorContainer
20755
20755
  }, /*#__PURE__*/React.createElement(View, {
20756
- style: styles$t.title,
20756
+ style: styles$x.title,
20757
20757
  onClick: this.handleToggleTexErrors
20758
20758
  }, /*#__PURE__*/React.createElement(PhosphorIcon, {
20759
20759
  icon: caretRight,
20760
20760
  style: iconStyle
20761
20761
  }), "\xA0 TeX Errors (", errorList.length, ")"), showErrors && /*#__PURE__*/React.createElement(View, {
20762
- style: styles$t.errorExplanation
20762
+ style: styles$x.errorExplanation
20763
20763
  }, "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, {
20764
- style: styles$t.error,
20764
+ style: styles$x.error,
20765
20765
  key: index
20766
20766
  }, /*#__PURE__*/React.createElement(View, {
20767
20767
  style: {
@@ -20770,7 +20770,7 @@ class TexErrorView extends React.Component {
20770
20770
  }, e.math), /*#__PURE__*/React.createElement(View, null, e.message))));
20771
20771
  }
20772
20772
  }
20773
- const styles$t = StyleSheet.create({
20773
+ const styles$x = StyleSheet.create({
20774
20774
  title: {
20775
20775
  backgroundColor: "#eee",
20776
20776
  fontSize: "1.25em",
@@ -24571,7 +24571,7 @@ class SimpleButton extends React.Component {
24571
24571
  } = _this$props,
24572
24572
  otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
24573
24573
  return /*#__PURE__*/React.createElement("div", _extends({
24574
- className: css(styles$s.baseButton, color === "green" && styles$s.green, color === "orange" && styles$s.orange),
24574
+ className: css(styles$w.baseButton, color === "green" && styles$w.green, color === "orange" && styles$w.orange),
24575
24575
  onClick: onClick
24576
24576
  }, otherProps), children);
24577
24577
  }
@@ -24586,7 +24586,7 @@ SimpleButton.defaultProps = {
24586
24586
  color: "green",
24587
24587
  onClick: () => {}
24588
24588
  };
24589
- const styles$s = StyleSheet.create({
24589
+ const styles$w = StyleSheet.create({
24590
24590
  baseButton: {
24591
24591
  top: "0",
24592
24592
  fontSize: "11px",
@@ -24806,23 +24806,23 @@ const LeafContainer = ({
24806
24806
  }) => {
24807
24807
  const hasPreviewHeading = shape.type === "content" || shape.type === "hint";
24808
24808
  const previewHeading = hasPreviewHeading && /*#__PURE__*/React.createElement("div", {
24809
- className: css(styles$r.containerHeader)
24809
+ className: css(styles$v.containerHeader)
24810
24810
  }, /*#__PURE__*/React.createElement(Header, {
24811
24811
  depth: path.length,
24812
- className: css(styles$r.containerTitle)
24812
+ className: css(styles$v.containerTitle)
24813
24813
  }, capitalize(name)));
24814
24814
  return /*#__PURE__*/React.createElement("div", {
24815
- className: css(styles$r.container)
24815
+ className: css(styles$v.container)
24816
24816
  }, /*#__PURE__*/React.createElement("span", {
24817
- className: css(styles$r.row, styles$r.rowHeading)
24817
+ className: css(styles$v.row, styles$v.rowHeading)
24818
24818
  }, /*#__PURE__*/React.createElement("div", {
24819
- className: css(styles$r.columnLeft)
24819
+ className: css(styles$v.columnLeft)
24820
24820
  }, /*#__PURE__*/React.createElement("div", {
24821
- className: "pod-title " + css(styles$r.containerHeader)
24821
+ className: "pod-title " + css(styles$v.containerHeader)
24822
24822
  }, /*#__PURE__*/React.createElement("div", {
24823
- className: css(styles$r.containerTitle)
24823
+ className: css(styles$v.containerTitle)
24824
24824
  }, capitalize(name)), controls)), /*#__PURE__*/React.createElement("div", {
24825
- className: css(styles$r.columnRight)
24825
+ className: css(styles$v.columnRight)
24826
24826
  }, previewHeading)), children);
24827
24827
  };
24828
24828
  const ArrayContainer = props => {
@@ -24835,11 +24835,11 @@ const ArrayContainer = props => {
24835
24835
  actions
24836
24836
  } = props;
24837
24837
  return /*#__PURE__*/React.createElement("div", {
24838
- className: css(styles$r.container)
24838
+ className: css(styles$v.container)
24839
24839
  }, controls && /*#__PURE__*/React.createElement("div", {
24840
- className: css(styles$r.columnLeft, styles$r.containerHeader)
24840
+ className: css(styles$v.columnLeft, styles$v.containerHeader)
24841
24841
  }, controls), /*#__PURE__*/React.createElement("div", null, children), /*#__PURE__*/React.createElement("div", {
24842
- className: css(styles$r.columnLeft)
24842
+ className: css(styles$v.columnLeft)
24843
24843
  }, /*#__PURE__*/React.createElement("a", {
24844
24844
  href: "javascript:void 0",
24845
24845
  onClick: () => actions.addArrayElement(path, shape.elementShape)
@@ -24852,28 +24852,28 @@ const ObjectContainer = ({
24852
24852
  path
24853
24853
  }) => {
24854
24854
  const headingEditor = /*#__PURE__*/React.createElement("div", {
24855
- className: css(styles$r.containerHeader)
24855
+ className: css(styles$v.containerHeader)
24856
24856
  }, /*#__PURE__*/React.createElement(Header, {
24857
24857
  depth: path.length,
24858
- className: css(styles$r.containerTitle)
24858
+ className: css(styles$v.containerTitle)
24859
24859
  }, capitalize(name)), controls);
24860
24860
  const headingPreview = (name || controls) && /*#__PURE__*/React.createElement("div", {
24861
- className: css(styles$r.containerHeader, styles$r.previewCollectionHeader)
24861
+ className: css(styles$v.containerHeader, styles$v.previewCollectionHeader)
24862
24862
  }, /*#__PURE__*/React.createElement(Header, {
24863
24863
  depth: path.length,
24864
- className: css(styles$r.containerTitle)
24864
+ className: css(styles$v.containerTitle)
24865
24865
  }, capitalize(name)));
24866
24866
  const hasBothHeadings = headingEditor && headingPreview;
24867
24867
  return /*#__PURE__*/React.createElement("div", {
24868
- className: css(styles$r.container)
24868
+ className: css(styles$v.container)
24869
24869
  }, hasBothHeadings && /*#__PURE__*/React.createElement("span", {
24870
- className: css(styles$r.row)
24870
+ className: css(styles$v.row)
24871
24871
  }, /*#__PURE__*/React.createElement("div", {
24872
- className: css(styles$r.columnLeft)
24872
+ className: css(styles$v.columnLeft)
24873
24873
  }, headingEditor), /*#__PURE__*/React.createElement("div", {
24874
- className: css(styles$r.columnRight)
24874
+ className: css(styles$v.columnRight)
24875
24875
  }, headingPreview)), /*#__PURE__*/React.createElement("div", {
24876
- className: css(path.length > 0 && styles$r.contentIndent)
24876
+ className: css(path.length > 0 && styles$v.contentIndent)
24877
24877
  }, children));
24878
24878
  };
24879
24879
 
@@ -24996,11 +24996,11 @@ const ItemNodeContent = withStickiness(props => {
24996
24996
  className: "framework-perseus"
24997
24997
  }, lens(renderers).get(path));
24998
24998
  return /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("div", {
24999
- className: css(styles$r.row)
24999
+ className: css(styles$v.row)
25000
25000
  }, /*#__PURE__*/React.createElement("div", {
25001
- className: css(styles$r.columnLeft)
25001
+ className: css(styles$v.columnLeft)
25002
25002
  }, /*#__PURE__*/React.createElement("div", {
25003
- className: css(sticky && styles$r.sticky)
25003
+ className: css(sticky && styles$v.sticky)
25004
25004
  },
25005
25005
  /*#__PURE__*/
25006
25006
  // @ts-expect-error - TS2769 - No overload matches this call.
@@ -25008,9 +25008,9 @@ const ItemNodeContent = withStickiness(props => {
25008
25008
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25009
25009
  apiOptions: apiOptions
25010
25010
  })))), /*#__PURE__*/React.createElement("div", {
25011
- className: css(styles$r.columnRight)
25011
+ className: css(styles$v.columnRight)
25012
25012
  }, /*#__PURE__*/React.createElement("div", {
25013
- className: css(sticky && styles$r.sticky)
25013
+ className: css(sticky && styles$v.sticky)
25014
25014
  }, preview))));
25015
25015
  });
25016
25016
  const HintNodeContent = withStickiness(props => {
@@ -25026,13 +25026,13 @@ const HintNodeContent = withStickiness(props => {
25026
25026
  className: "framework-perseus"
25027
25027
  }, lens(renderers).get(path));
25028
25028
  return /*#__PURE__*/React.createElement("div", {
25029
- className: css(styles$r.row)
25029
+ className: css(styles$v.row)
25030
25030
  }, /*#__PURE__*/React.createElement("div", {
25031
- className: css(styles$r.columnLeft)
25031
+ className: css(styles$v.columnLeft)
25032
25032
  }, /*#__PURE__*/React.createElement("div", {
25033
- className: css(sticky && styles$r.sticky)
25033
+ className: css(sticky && styles$v.sticky)
25034
25034
  }, /*#__PURE__*/React.createElement(HintEditor, _extends({}, data, {
25035
- className: css(styles$r.hintEditor),
25035
+ className: css(styles$v.hintEditor),
25036
25036
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25037
25037
  apiOptions: apiOptions,
25038
25038
  showTitle: false,
@@ -25047,9 +25047,9 @@ const HintNodeContent = withStickiness(props => {
25047
25047
  isFirst: true,
25048
25048
  isLast: true
25049
25049
  })))), /*#__PURE__*/React.createElement("div", {
25050
- className: css(styles$r.columnRight)
25050
+ className: css(styles$v.columnRight)
25051
25051
  }, /*#__PURE__*/React.createElement("div", {
25052
- className: css(sticky && styles$r.sticky)
25052
+ className: css(sticky && styles$v.sticky)
25053
25053
  }, preview)));
25054
25054
  });
25055
25055
  const TagsNodeContent = props => {
@@ -25066,9 +25066,9 @@ const TagsNodeContent = props => {
25066
25066
  return null;
25067
25067
  }
25068
25068
  return /*#__PURE__*/React.createElement("div", {
25069
- className: css(styles$r.columnLeft)
25069
+ className: css(styles$v.columnLeft)
25070
25070
  }, /*#__PURE__*/React.createElement("div", {
25071
- className: css(styles$r.tagsEditor)
25071
+ className: css(styles$v.tagsEditor)
25072
25072
  }, /*#__PURE__*/React.createElement(GroupMetadataEditor, {
25073
25073
  value: data,
25074
25074
  onChange: newVal => actions.setValueAtPath(path, newVal),
@@ -25099,23 +25099,23 @@ const ArrayNodeContent = props => {
25099
25099
  const subpath = path.concat(i);
25100
25100
  const controls = [i > 0 && /*#__PURE__*/React.createElement("div", {
25101
25101
  key: "moveArrayElementUp",
25102
- className: css(styles$r.control)
25102
+ className: css(styles$v.control)
25103
25103
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25104
25104
  color: "orange",
25105
25105
  title: "Move up",
25106
25106
  onClick: () => actions.moveArrayElementUp(subpath)
25107
25107
  }, /*#__PURE__*/React.createElement("div", {
25108
- className: css(styles$r.verticalFlip)
25108
+ className: css(styles$v.verticalFlip)
25109
25109
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconChevronDown)))), i < data.length - 1 && /*#__PURE__*/React.createElement("div", {
25110
25110
  key: "moveArrayElementDown",
25111
- className: css(styles$r.control)
25111
+ className: css(styles$v.control)
25112
25112
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25113
25113
  color: "orange",
25114
25114
  title: "Move down",
25115
25115
  onClick: () => actions.moveArrayElementDown(subpath)
25116
25116
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconChevronDown))), /*#__PURE__*/React.createElement("div", {
25117
25117
  key: "removeArrayElement",
25118
- className: css(styles$r.control)
25118
+ className: css(styles$v.control)
25119
25119
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25120
25120
  color: "orange",
25121
25121
  title: "Delete",
@@ -25123,7 +25123,7 @@ const ArrayNodeContent = props => {
25123
25123
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconTrash$4)))];
25124
25124
  return /*#__PURE__*/React.createElement("div", {
25125
25125
  key: i,
25126
- className: css(styles$r.arrayElement, !elementIsLeaf && styles$r.arrayElementAndNotLeaf)
25126
+ className: css(styles$v.arrayElement, !elementIsLeaf && styles$v.arrayElementAndNotLeaf)
25127
25127
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25128
25128
  key: i,
25129
25129
  shape: shape.elementShape,
@@ -25149,7 +25149,7 @@ const ObjectNodeContent = props => {
25149
25149
  // made sense to the shape's author is the order in which we'll iterate :)
25150
25150
  const children = Object.keys(shape.shape).map(subkey => /*#__PURE__*/React.createElement("div", {
25151
25151
  key: subkey,
25152
- className: css(styles$r.objectElement)
25152
+ className: css(styles$v.objectElement)
25153
25153
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25154
25154
  shape: shape.shape[subkey],
25155
25155
  data: data[subkey],
@@ -25316,7 +25316,7 @@ class MultiRendererEditor extends React.Component {
25316
25316
  }, this._renderContent());
25317
25317
  }
25318
25318
  }
25319
- const styles$r = StyleSheet.create({
25319
+ const styles$v = StyleSheet.create({
25320
25320
  // This is used in a number of places throughout this file.
25321
25321
  container: {},
25322
25322
  // eslint-disable-next-line react-native/no-unused-styles
@@ -25468,47 +25468,47 @@ const StatefulArticleEditor = createReactClass({
25468
25468
  screen
25469
25469
  } = this.state;
25470
25470
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
25471
- style: styles$q.controlBar
25471
+ style: styles$u.controlBar
25472
25472
  }, /*#__PURE__*/React.createElement("span", {
25473
- style: styles$q.controls
25473
+ style: styles$u.controls
25474
25474
  }, "Mode:", " ", /*#__PURE__*/React.createElement("span", {
25475
25475
  onClick: () => this.setState({
25476
25476
  mode: "edit"
25477
25477
  }),
25478
- style: mode === "edit" ? styles$q.controlSelected : styles$q.control
25478
+ style: mode === "edit" ? styles$u.controlSelected : styles$u.control
25479
25479
  }, "EDIT"), " | ", /*#__PURE__*/React.createElement("span", {
25480
25480
  onClick: () => this.setState({
25481
25481
  mode: "preview"
25482
25482
  }),
25483
- style: mode === "preview" ? styles$q.controlSelected : styles$q.control
25483
+ style: mode === "preview" ? styles$u.controlSelected : styles$u.control
25484
25484
  }, "PREVIEW"), " | ", /*#__PURE__*/React.createElement("span", {
25485
25485
  onClick: () => this.setState({
25486
25486
  mode: "json"
25487
25487
  }),
25488
- style: mode === "json" ? styles$q.controlSelected : styles$q.control
25488
+ style: mode === "json" ? styles$u.controlSelected : styles$u.control
25489
25489
  }, "JSON")), /*#__PURE__*/React.createElement("span", {
25490
- style: styles$q.controls
25490
+ style: styles$u.controls
25491
25491
  }, "Screen:", " ", /*#__PURE__*/React.createElement("span", {
25492
25492
  onClick: () => this.setState({
25493
25493
  screen: "phone"
25494
25494
  }),
25495
- style: screen === "phone" ? styles$q.controlSelected : styles$q.control
25495
+ style: screen === "phone" ? styles$u.controlSelected : styles$u.control
25496
25496
  }, "PHONE"), " | ", /*#__PURE__*/React.createElement("span", {
25497
25497
  onClick: () => this.setState({
25498
25498
  screen: "tablet"
25499
25499
  }),
25500
- style: screen === "tablet" ? styles$q.controlSelected : styles$q.control
25500
+ style: screen === "tablet" ? styles$u.controlSelected : styles$u.control
25501
25501
  }, "TABLET"), " | ", /*#__PURE__*/React.createElement("span", {
25502
25502
  onClick: () => this.setState({
25503
25503
  screen: "desktop"
25504
25504
  }),
25505
- style: screen === "desktop" ? styles$q.controlSelected : styles$q.control
25505
+ style: screen === "desktop" ? styles$u.controlSelected : styles$u.control
25506
25506
  }, "DESKTOP"))), /*#__PURE__*/React.createElement("div", {
25507
- style: styles$q.editor
25507
+ style: styles$u.editor
25508
25508
  }, /*#__PURE__*/React.createElement(ArticleEditor, this.state)));
25509
25509
  }
25510
25510
  });
25511
- const styles$q = {
25511
+ const styles$u = {
25512
25512
  controlBar: {
25513
25513
  marginBottom: 25,
25514
25514
  marginTop: 5
@@ -26998,10 +26998,10 @@ class GradedGroupEditor extends React.Component {
26998
26998
  }, /*#__PURE__*/React.createElement("div", {
26999
26999
  className: "perseus-widget-row"
27000
27000
  }, /*#__PURE__*/React.createElement("label", {
27001
- className: css(styles$p.title)
27001
+ className: css(styles$t.title)
27002
27002
  }, "Title:", " ", /*#__PURE__*/React.createElement(TextInput$6, {
27003
27003
  value: this.props.title,
27004
- className: css(styles$p.input)
27004
+ className: css(styles$t.input)
27005
27005
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
27006
27006
  ,
27007
27007
  onChange: this.change("title")
@@ -27026,7 +27026,7 @@ class GradedGroupEditor extends React.Component {
27026
27026
  }, /*#__PURE__*/React.createElement(InlineIcon$4, iconPlus$1), " Add a hint"), this.props.hint && /*#__PURE__*/React.createElement("div", {
27027
27027
  className: "perseus-hint-editor"
27028
27028
  }, /*#__PURE__*/React.createElement("div", {
27029
- className: css(styles$p.hintsTitle)
27029
+ className: css(styles$t.hintsTitle)
27030
27030
  }, "Hint"), /*#__PURE__*/React.createElement(Editor, {
27031
27031
  ref: this.hintEditor,
27032
27032
  content: this.props.hint ? this.props.hint.content : "",
@@ -27063,7 +27063,7 @@ GradedGroupEditor.defaultProps = {
27063
27063
  images: {},
27064
27064
  hint: null
27065
27065
  };
27066
- const styles$p = StyleSheet.create({
27066
+ const styles$t = StyleSheet.create({
27067
27067
  title: {
27068
27068
  fontSize: 18,
27069
27069
  fontWeight: "bold"
@@ -28402,13 +28402,13 @@ function MathquillInput(props) {
28402
28402
  }
28403
28403
  });
28404
28404
  return /*#__PURE__*/React.createElement(View, {
28405
- style: styles$o.outerWrapper
28405
+ style: styles$s.outerWrapper
28406
28406
  }, /*#__PURE__*/React.createElement("span", {
28407
28407
  ref: mathFieldWrapperRef,
28408
28408
  className: "perseus-math-input mq-editable-field mq-math-mode"
28409
28409
  }));
28410
28410
  }
28411
- const styles$o = StyleSheet.create({
28411
+ const styles$s = StyleSheet.create({
28412
28412
  outerWrapper: {
28413
28413
  display: "inline-block",
28414
28414
  borderStyle: "solid",
@@ -29469,7 +29469,7 @@ const GraphPointsCountSelector = ({
29469
29469
  // Never uses placeholder, always has value
29470
29470
  ,
29471
29471
  placeholder: "",
29472
- style: styles$n.singleSelectShort
29472
+ style: styles$r.singleSelectShort
29473
29473
  }, [...[...Array(7).keys()].map(n => /*#__PURE__*/React.createElement(OptionItem, {
29474
29474
  key: n,
29475
29475
  value: `${n}`,
@@ -29480,7 +29480,7 @@ const GraphPointsCountSelector = ({
29480
29480
  label: "unlimited"
29481
29481
  })]);
29482
29482
  };
29483
- const styles$n = StyleSheet.create({
29483
+ const styles$r = StyleSheet.create({
29484
29484
  singleSelectShort: {
29485
29485
  // Non-standard spacing, but it's the smallest we can go
29486
29486
  // without running into styling issues with the dropdown.
@@ -29493,7 +29493,7 @@ const GraphTypeSelector = props => {
29493
29493
  selectedValue: props.graphType,
29494
29494
  onChange: props.onChange,
29495
29495
  placeholder: "Select a graph type",
29496
- style: styles$m.singleSelectShort
29496
+ style: styles$q.singleSelectShort
29497
29497
  }, /*#__PURE__*/React.createElement(OptionItem, {
29498
29498
  value: "linear",
29499
29499
  label: "Linear function"
@@ -29526,7 +29526,7 @@ const GraphTypeSelector = props => {
29526
29526
  label: "Angle"
29527
29527
  }));
29528
29528
  };
29529
- const styles$m = StyleSheet.create({
29529
+ const styles$q = StyleSheet.create({
29530
29530
  singleSelectShort: {
29531
29531
  // Non-standard spacing, but it's the smallest we can go
29532
29532
  // without running into styling issues with the dropdown.
@@ -29543,16 +29543,16 @@ const LabeledRow = props => {
29543
29543
  style
29544
29544
  } = props;
29545
29545
  return /*#__PURE__*/React.createElement("label", {
29546
- className: css(styles$l.label)
29546
+ className: css(styles$p.label)
29547
29547
  }, /*#__PURE__*/React.createElement(View, {
29548
- style: [styles$l.row, style]
29548
+ style: [styles$p.row, style]
29549
29549
  }, labelSide === "start" || /*#__PURE__*/React.createElement(LabelSmall, {
29550
- style: styles$l.spaceEnd
29550
+ style: styles$p.spaceEnd
29551
29551
  }, label), children, labelSide === "end" && /*#__PURE__*/React.createElement(LabelSmall, {
29552
- style: styles$l.spaceStart
29552
+ style: styles$p.spaceStart
29553
29553
  }, label)));
29554
29554
  };
29555
- const styles$l = StyleSheet.create({
29555
+ const styles$p = StyleSheet.create({
29556
29556
  label: {
29557
29557
  width: "fit-content"
29558
29558
  },
@@ -29946,10 +29946,10 @@ class InteractiveGraphSettings extends React.Component {
29946
29946
  onChange: this.change
29947
29947
  }))), /*#__PURE__*/React.createElement(LabeledRow, {
29948
29948
  label: "Background image URL:",
29949
- style: styles$k.resetSpaceTop
29949
+ style: styles$o.resetSpaceTop
29950
29950
  }, /*#__PURE__*/React.createElement("input", {
29951
29951
  type: "text",
29952
- className: css(styles$k.backgroundUrlInput),
29952
+ className: css(styles$o.backgroundUrlInput),
29953
29953
  ref: this.bgUrlRef,
29954
29954
  value: this.state.backgroundImage.url || "",
29955
29955
  onChange: e => {
@@ -29963,28 +29963,28 @@ class InteractiveGraphSettings extends React.Component {
29963
29963
  onKeyPress: this.changeBackgroundUrl,
29964
29964
  onBlur: this.changeBackgroundUrl
29965
29965
  }), /*#__PURE__*/React.createElement(InfoTip$c, 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, {
29966
- style: styles$k.rulerSection
29966
+ style: styles$o.rulerSection
29967
29967
  }, /*#__PURE__*/React.createElement(View, {
29968
- style: styles$k.checkboxRow
29968
+ style: styles$o.checkboxRow
29969
29969
  }, /*#__PURE__*/React.createElement(PropCheckBox$7, {
29970
29970
  label: "Show ruler",
29971
29971
  showRuler: this.props.showRuler,
29972
29972
  onChange: this.change,
29973
- style: styles$k.resetSpaceTop
29973
+ style: styles$o.resetSpaceTop
29974
29974
  }), /*#__PURE__*/React.createElement(PropCheckBox$7, {
29975
29975
  label: "Show protractor",
29976
29976
  showProtractor: this.props.showProtractor,
29977
29977
  onChange: this.change,
29978
- style: styles$k.resetSpaceTop
29978
+ style: styles$o.resetSpaceTop
29979
29979
  })), (this.props.showRuler || this.props.showProtractor) && /*#__PURE__*/React.createElement(Banner, {
29980
29980
  layout: "floating",
29981
29981
  text: "The ruler and protractor are not accessible. Please consider an alternate approach.",
29982
29982
  kind: "warning"
29983
29983
  }), this.props.showRuler && /*#__PURE__*/React.createElement(View, {
29984
- style: styles$k.spaceTop
29984
+ style: styles$o.spaceTop
29985
29985
  }, /*#__PURE__*/React.createElement(LabeledRow, {
29986
29986
  label: "Ruler label:",
29987
- style: styles$k.resetSpaceTop
29987
+ style: styles$o.resetSpaceTop
29988
29988
  }, /*#__PURE__*/React.createElement(SingleSelect, {
29989
29989
  id: "ruler-label-select",
29990
29990
  selectedValue: this.props.rulerLabel,
@@ -29994,7 +29994,7 @@ class InteractiveGraphSettings extends React.Component {
29994
29994
  });
29995
29995
  },
29996
29996
  placeholder: "None",
29997
- style: styles$k.singleSelectShort
29997
+ style: styles$o.singleSelectShort
29998
29998
  }, /*#__PURE__*/React.createElement(OptionItem, {
29999
29999
  value: "",
30000
30000
  label: "None",
@@ -30035,7 +30035,7 @@ class InteractiveGraphSettings extends React.Component {
30035
30035
  });
30036
30036
  },
30037
30037
  placeholder: "10",
30038
- style: styles$k.singleSelectShort
30038
+ style: styles$o.singleSelectShort
30039
30039
  }, [1, 2, 4, 8, 10, 16].map(value => /*#__PURE__*/React.createElement(OptionItem, {
30040
30040
  key: value,
30041
30041
  value: `${value}`,
@@ -30059,7 +30059,7 @@ InteractiveGraphSettings.defaultProps = {
30059
30059
  rulerLabel: "",
30060
30060
  rulerTicks: 10
30061
30061
  };
30062
- const styles$k = StyleSheet.create({
30062
+ const styles$o = StyleSheet.create({
30063
30063
  resetSpaceTop: {
30064
30064
  marginTop: 0
30065
30065
  },
@@ -30091,43 +30091,6 @@ const styles$k = StyleSheet.create({
30091
30091
  }
30092
30092
  });
30093
30093
 
30094
- /**
30095
- * Dropdown for selecting a locked figure to add to an interactive graph.
30096
- * Locked figures are elements (points, segmeents, etc.) that are not
30097
- * interactive, just present in the graph's background.
30098
- *
30099
- * Used in the interactive graph editor's locked figures section.
30100
- */
30101
- const LockedFigureSelect = props => {
30102
- const {
30103
- id,
30104
- onChange
30105
- } = props;
30106
- return /*#__PURE__*/React.createElement(View, {
30107
- style: styles$j.container
30108
- }, /*#__PURE__*/React.createElement(ActionMenu, {
30109
- menuText: "Add locked figure",
30110
- style: styles$j.addElementSelect
30111
- }, [/*#__PURE__*/React.createElement(ActionItem, {
30112
- key: `${id}-point`,
30113
- label: "Point",
30114
- onClick: () => onChange("point")
30115
- }, "Point"), /*#__PURE__*/React.createElement(ActionItem, {
30116
- key: `${id}-line`,
30117
- label: "Line",
30118
- onClick: () => onChange("line")
30119
- }, "Line")]));
30120
- };
30121
- const styles$j = StyleSheet.create({
30122
- container: {
30123
- marginTop: spacing.xSmall_8
30124
- },
30125
- addElementSelect: {
30126
- backgroundColor: color.fadedBlue8,
30127
- borderRadius: spacing.xxxSmall_4
30128
- }
30129
- });
30130
-
30131
30094
  const mediaDefaultSpecLargeMarginWidth = spacing.large_24;
30132
30095
  const MEDIA_DEFAULT_SPEC = {
30133
30096
  small: {
@@ -30208,6 +30171,43 @@ const strutStyle = size => {
30208
30171
  };
30209
30172
  };
30210
30173
 
30174
+ /**
30175
+ * Dropdown for selecting a locked figure to add to an interactive graph.
30176
+ * Locked figures are elements (points, segmeents, etc.) that are not
30177
+ * interactive, just present in the graph's background.
30178
+ *
30179
+ * Used in the interactive graph editor's locked figures section.
30180
+ */
30181
+ const LockedFigureSelect = props => {
30182
+ const {
30183
+ id,
30184
+ onChange
30185
+ } = props;
30186
+ return /*#__PURE__*/React.createElement(View, {
30187
+ style: styles$n.container
30188
+ }, /*#__PURE__*/React.createElement(ActionMenu, {
30189
+ menuText: "Add locked figure",
30190
+ style: styles$n.addElementSelect
30191
+ }, [/*#__PURE__*/React.createElement(ActionItem, {
30192
+ key: `${id}-point`,
30193
+ label: "Point",
30194
+ onClick: () => onChange("point")
30195
+ }, "Point"), /*#__PURE__*/React.createElement(ActionItem, {
30196
+ key: `${id}-line`,
30197
+ label: "Line",
30198
+ onClick: () => onChange("line")
30199
+ }, "Line")]));
30200
+ };
30201
+ const styles$n = StyleSheet.create({
30202
+ container: {
30203
+ marginTop: spacing.xSmall_8
30204
+ },
30205
+ addElementSelect: {
30206
+ backgroundColor: color.fadedBlue8,
30207
+ borderRadius: spacing.xxxSmall_4
30208
+ }
30209
+ });
30210
+
30211
30211
  const ColorSwatch = props => {
30212
30212
  const {
30213
30213
  color: color$1,
@@ -30217,14 +30217,14 @@ const ColorSwatch = props => {
30217
30217
  return /*#__PURE__*/React.createElement(View, {
30218
30218
  "aria-label":
30219
30219
  // Don't include an aria label for decorative circles.
30220
- !decorative ? `Color: ${color$1}, ${filled ? "filled" : "open"}` : undefined,
30221
- style: [styles$i.colorSwatch, {
30220
+ !decorative ? `${color$1}, ${filled ? "filled" : "open"}` : undefined,
30221
+ style: [styles$m.colorSwatch, {
30222
30222
  border: `4px solid ${lockedFigureColors[color$1]}`,
30223
30223
  backgroundColor: filled ? lockedFigureColors[color$1] : color.white
30224
30224
  }]
30225
30225
  });
30226
30226
  };
30227
- const styles$i = StyleSheet.create({
30227
+ const styles$m = StyleSheet.create({
30228
30228
  colorSwatch: {
30229
30229
  // Add a white outline so that the color swatch is visible when
30230
30230
  // the dropdown option is highlighted with its blue background.
@@ -30238,16 +30238,17 @@ const styles$i = StyleSheet.create({
30238
30238
  const possibleColors = Object.keys(lockedFigureColors);
30239
30239
  const ColorSelect = props => {
30240
30240
  const {
30241
- id,
30242
30241
  selectedValue,
30243
30242
  style,
30244
30243
  onChange
30245
30244
  } = props;
30245
+ const ids = useUniqueIdWithMock();
30246
+ const id = ids.get("color-select");
30246
30247
  return /*#__PURE__*/React.createElement(View, {
30247
- style: [styles$h.row, style]
30248
+ style: [styles$l.row, style]
30248
30249
  }, /*#__PURE__*/React.createElement(LabelMedium, {
30249
30250
  htmlFor: id,
30250
- style: styles$h.label,
30251
+ style: styles$l.label,
30251
30252
  tag: "label"
30252
30253
  }, "color"), /*#__PURE__*/React.createElement(SingleSelect, {
30253
30254
  id: id,
@@ -30266,7 +30267,7 @@ const ColorSelect = props => {
30266
30267
  })
30267
30268
  }, colorName))));
30268
30269
  };
30269
- const styles$h = StyleSheet.create({
30270
+ const styles$l = StyleSheet.create({
30270
30271
  row: {
30271
30272
  flexDirection: "row",
30272
30273
  alignItems: "center"
@@ -30276,12 +30277,121 @@ const styles$h = StyleSheet.create({
30276
30277
  }
30277
30278
  });
30278
30279
 
30280
+ const CoordinatePairInput = props => {
30281
+ const {
30282
+ coord,
30283
+ onChangeProps
30284
+ } = props;
30285
+
30286
+ // Keep track of the coordinates via state as the user is editing them,
30287
+ // before they are updated in the props as a valid number.
30288
+ const [coordState, setCoordState] = React.useState([
30289
+ // Using strings to make it easier to work with the text fields.
30290
+ coord[0].toString(), coord[1].toString()]);
30291
+
30292
+ // Generate unique IDs so that the programmatic labels can be associated
30293
+ // with their respective text fields.
30294
+ const ids = useUniqueIdWithMock();
30295
+ const xCoordId = ids.get("x-coord");
30296
+ const yCoordId = ids.get("y-coord");
30297
+ function handleCoordChange(newValue, coordIndex) {
30298
+ // Update the local state (update the input field value).
30299
+ const newCoordState = [...coordState];
30300
+ newCoordState[coordIndex] = newValue;
30301
+ setCoordState(newCoordState);
30302
+
30303
+ // If the new value is not a number, don't update the props.
30304
+ // If it's empty, keep the props the same value instead of setting to 0.
30305
+ if (isNaN(+newValue) || newValue === "") {
30306
+ return;
30307
+ }
30308
+
30309
+ // Update the props (update the graph).
30310
+ const newCoords = [...coord];
30311
+ newCoords[coordIndex] = +newValue;
30312
+ onChangeProps({
30313
+ coord: newCoords
30314
+ });
30315
+ }
30316
+ return /*#__PURE__*/React.createElement(View, {
30317
+ style: [styles$k.row, styles$k.spaceUnder]
30318
+ }, /*#__PURE__*/React.createElement(LabelMedium, {
30319
+ htmlFor: xCoordId,
30320
+ style: styles$k.label,
30321
+ tag: "label"
30322
+ }, "x coord"), /*#__PURE__*/React.createElement(TextField, {
30323
+ id: xCoordId,
30324
+ type: "number",
30325
+ value: coordState[0],
30326
+ onChange: newValue => handleCoordChange(newValue, 0),
30327
+ style: styles$k.textField
30328
+ }), /*#__PURE__*/React.createElement(Strut, {
30329
+ size: spacing.medium_16
30330
+ }), /*#__PURE__*/React.createElement(LabelMedium, {
30331
+ htmlFor: yCoordId,
30332
+ style: styles$k.label,
30333
+ tag: "label"
30334
+ }, "y coord"), /*#__PURE__*/React.createElement(TextField, {
30335
+ id: yCoordId,
30336
+ type: "number",
30337
+ value: coordState[1],
30338
+ onChange: newValue => handleCoordChange(newValue, 1),
30339
+ style: styles$k.textField
30340
+ }));
30341
+ };
30342
+ const styles$k = StyleSheet.create({
30343
+ row: {
30344
+ flexDirection: "row",
30345
+ alignItems: "center"
30346
+ },
30347
+ spaceUnder: {
30348
+ marginBottom: spacing.xSmall_8
30349
+ },
30350
+ label: {
30351
+ marginInlineEnd: spacing.xxSmall_6
30352
+ },
30353
+ textField: {
30354
+ width: spacing.xxxLarge_64
30355
+ }
30356
+ });
30357
+
30358
+ const LabeledSwitch = props => {
30359
+ const {
30360
+ checked,
30361
+ label,
30362
+ style,
30363
+ onChange
30364
+ } = props;
30365
+ const ids = useUniqueIdWithMock();
30366
+ const switchId = ids.get("switch");
30367
+ return /*#__PURE__*/React.createElement(View, {
30368
+ style: [styles$j.row, style]
30369
+ }, /*#__PURE__*/React.createElement(Switch, {
30370
+ id: switchId,
30371
+ checked: checked,
30372
+ onChange: onChange
30373
+ }), /*#__PURE__*/React.createElement(Strut, {
30374
+ size: spacing.xSmall_8
30375
+ }), /*#__PURE__*/React.createElement(LabelMedium, {
30376
+ tag: "label",
30377
+ htmlFor: switchId
30378
+ }, label));
30379
+ };
30380
+ const styles$j = StyleSheet.create({
30381
+ row: {
30382
+ flexDirection: "row",
30383
+ alignItems: "center"
30384
+ }
30385
+ });
30386
+
30279
30387
  const LockedFigureSettingsAccordion = props => {
30280
30388
  const {
30281
30389
  children,
30282
30390
  header,
30391
+ expanded,
30283
30392
  containerStyle,
30284
- panelStyle
30393
+ panelStyle,
30394
+ onToggle
30285
30395
  } = props;
30286
30396
  return /*#__PURE__*/React.createElement(View
30287
30397
  // More specificity so that we can override the default
@@ -30290,14 +30400,16 @@ const LockedFigureSettingsAccordion = props => {
30290
30400
  , {
30291
30401
  className: "locked-figure-accordion"
30292
30402
  }, /*#__PURE__*/React.createElement(AccordionSection, {
30293
- style: [styles$g.container, containerStyle],
30294
- headerStyle: styles$g.accordionHeader,
30403
+ expanded: expanded,
30404
+ onToggle: onToggle,
30405
+ style: [styles$i.container, containerStyle],
30406
+ headerStyle: styles$i.accordionHeader,
30295
30407
  header: header
30296
30408
  }, /*#__PURE__*/React.createElement(View, {
30297
- style: [styles$g.accordionPanel, panelStyle]
30409
+ style: [styles$i.accordionPanel, panelStyle]
30298
30410
  }, children)));
30299
30411
  };
30300
- const styles$g = StyleSheet.create({
30412
+ const styles$i = StyleSheet.create({
30301
30413
  container: {
30302
30414
  backgroundColor: color.fadedBlue8,
30303
30415
  marginTop: spacing.xSmall_8
@@ -30319,270 +30431,141 @@ const styles$g = StyleSheet.create({
30319
30431
  });
30320
30432
 
30321
30433
  /**
30322
- * The part of a locked figure settings panel that contains actions
30323
- * for this panel and its associated locked figure, including
30324
- * the delete button.
30434
+ * DefiningPointSettings is a component that allows the user to edit the
30435
+ * settings of a point that defines a locked figure (ex. line) on the graph.
30436
+ *
30437
+ * Used in the interactive graph editor's locked figures section.
30325
30438
  */
30326
- const LockedFigureSettingsActions = props => {
30439
+ const DefiningPointSettings = props => {
30327
30440
  const {
30328
- onRemove,
30329
- figureAriaLabel
30441
+ coord,
30442
+ color: pointColor,
30443
+ filled = true,
30444
+ label,
30445
+ showPoint = "false",
30446
+ onChangeProps,
30447
+ onTogglePoint
30330
30448
  } = props;
30331
- return /*#__PURE__*/React.createElement(View, {
30332
- style: styles$f.container
30333
- }, /*#__PURE__*/React.createElement(Button, {
30334
- startIcon: trashIcon,
30335
- "aria-label": `Delete ${figureAriaLabel}`,
30336
- onClick: onRemove,
30337
- kind: "tertiary",
30338
- style: styles$f.deleteButton
30339
- }, "Delete"));
30449
+ function handleColorChange(newValue) {
30450
+ onChangeProps({
30451
+ color: newValue
30452
+ });
30453
+ }
30454
+ return /*#__PURE__*/React.createElement(LockedFigureSettingsAccordion, {
30455
+ expanded: props.expanded,
30456
+ onToggle: props.onToggle,
30457
+ containerStyle: styles$h.container,
30458
+ panelStyle: styles$h.accordionPanel,
30459
+ header:
30460
+ /*#__PURE__*/
30461
+ // Summary: Point, coords, color (filled/open)
30462
+ React.createElement(View, {
30463
+ style: styles$h.row
30464
+ }, /*#__PURE__*/React.createElement(LabelLarge, null, `${label || "Point"} (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React.createElement(Strut, {
30465
+ size: spacing.xSmall_8
30466
+ }), showPoint && /*#__PURE__*/React.createElement(ColorSwatch, {
30467
+ color: pointColor,
30468
+ filled: filled
30469
+ }))
30470
+ }, /*#__PURE__*/React.createElement(CoordinatePairInput, {
30471
+ coord: coord,
30472
+ onChangeProps: onChangeProps
30473
+ }), onTogglePoint && /*#__PURE__*/React.createElement(LabeledSwitch, {
30474
+ label: "show point on graph",
30475
+ checked: !!showPoint,
30476
+ style: showPoint && styles$h.spaceUnder,
30477
+ onChange: onTogglePoint
30478
+ }), showPoint && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ColorSelect, {
30479
+ selectedValue: pointColor,
30480
+ onChange: handleColorChange,
30481
+ style: styles$h.spaceUnder
30482
+ }), /*#__PURE__*/React.createElement(LabeledSwitch, {
30483
+ label: "open point",
30484
+ checked: !filled,
30485
+ onChange: newValue => {
30486
+ onChangeProps({
30487
+ filled: !newValue
30488
+ });
30489
+ }
30490
+ })));
30340
30491
  };
30341
- const styles$f = StyleSheet.create({
30492
+ const styles$h = StyleSheet.create({
30342
30493
  container: {
30343
- width: "100%",
30494
+ marginTop: spacing.xSmall_8,
30495
+ marginBottom: 0,
30496
+ marginLeft: -spacing.xxxSmall_4,
30497
+ marginRight: -spacing.xxxSmall_4,
30498
+ backgroundColor: color.white
30499
+ },
30500
+ accordionPanel: {
30501
+ // Need more space since we don't have the actions' margins.
30502
+ paddingBottom: spacing.medium_16
30503
+ },
30504
+ row: {
30344
30505
  flexDirection: "row",
30345
- alignItems: "center",
30346
- marginTop: spacing.xxxSmall_4
30506
+ alignItems: "center"
30347
30507
  },
30348
- deleteButton: {
30349
- // Line up the delete icon with the rest of the content.
30350
- marginInlineStart: -spacing.xxxSmall_4
30508
+ spaceUnder: {
30509
+ marginBottom: spacing.xSmall_8
30351
30510
  }
30352
30511
  });
30353
30512
 
30354
- const LabeledSwitch = props => {
30513
+ const LineSwatch = props => {
30355
30514
  const {
30356
- checked,
30357
- label,
30358
- style,
30359
- onChange
30515
+ color,
30516
+ lineStyle
30360
30517
  } = props;
30361
- const ids = useUniqueIdWithMock();
30362
- const switchId = ids.get("switch");
30363
30518
  return /*#__PURE__*/React.createElement(View, {
30364
- style: [styles$e.row, style]
30365
- }, /*#__PURE__*/React.createElement(Switch, {
30366
- id: switchId,
30367
- checked: checked,
30368
- onChange: onChange
30369
- }), /*#__PURE__*/React.createElement(Strut, {
30370
- size: spacing.xSmall_8
30371
- }), /*#__PURE__*/React.createElement(LabelMedium, {
30372
- tag: "label",
30373
- htmlFor: switchId
30374
- }, label));
30519
+ style: styles$g.container
30520
+ }, /*#__PURE__*/React.createElement(View, {
30521
+ "aria-label": `${color}, ${lineStyle}`,
30522
+ style: [styles$g.lineSwatch, {
30523
+ border: `5px ${lineStyle} ${lockedFigureColors[color]}`
30524
+ }]
30525
+ }));
30375
30526
  };
30376
- const styles$e = StyleSheet.create({
30377
- row: {
30378
- flexDirection: "row",
30379
- alignItems: "center"
30527
+ const styles$g = StyleSheet.create({
30528
+ container: {
30529
+ backgroundColor: color.white,
30530
+ justifyContent: "center",
30531
+ padding: spacing.xSmall_8,
30532
+ borderRadius: spacing.xxxSmall_4
30533
+ },
30534
+ lineSwatch: {
30535
+ width: 40
30380
30536
  }
30381
30537
  });
30382
30538
 
30383
- function focusWithChromeStickyFocusBugWorkaround(element) {
30384
- // NOTE(marksandstrom) Chrome sticky focus bug.
30385
- //
30386
- // There is a bug in Chrome related to sticky positioning and
30387
- // focus: When a child of an element with sticky positioning is
30388
- // focused with the focus() method, the scrollable area
30389
- // containing that element will scroll to the top (even though
30390
- // the element is already visble on the page). For a dropdown
30391
- // this means that the area will be scrolled to the top when
30392
- // the user interacts with the dropdown (since we actively
30393
- // manage dropdown header and option focus for keyboard users).
30394
- //
30395
- // To work around this bug the `preventScroll` focus option is
30396
- // used.
30397
- //
30398
- // Using `focusOptions` is an experimental browser feature
30399
- // "that should not be used in production code". However, since
30400
- // Chrome is the only browser we support that exhibits this
30401
- // buggy behavior and using `focusOptions` works around the
30402
- // bug, it is perfectly reasonable to use the feature in this
30403
- // case. We are not relying on the effect of the
30404
- // `preventScroll` option otherwise.
30405
- //
30406
- // focusOptions documentation:
30407
- //
30408
- // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
30409
- //
30410
- // Note that there could be cases where we want default focus() behavior.
30411
- // One that comes to mind is a dropdown with a long list of options that
30412
- // might be rendered off screen when opened. With this workaround the
30413
- // selected option would not be scrolled into view if the option is near
30414
- // the end of the list. We're not aware of any uses of the dropdown where
30415
- // this is an issue, however, so there isn't currently a way to out of the
30416
- // `preventScroll` behavior.
30417
-
30418
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
30419
- element.focus({
30420
- preventScroll: true
30421
- });
30422
- }
30423
- function getValidNumberFromString(value) {
30424
- const parsed = parseFloat(value);
30425
- // If the value is not a number, return 0.
30426
- return isNaN(parsed) ? 0 : parsed;
30427
- }
30428
- const DEFAULT_COLOR = "grayH";
30429
- function getDefaultFigureForType(type) {
30430
- switch (type) {
30431
- case "point":
30432
- return {
30433
- type: "point",
30434
- coord: [0, 0],
30435
- color: DEFAULT_COLOR,
30436
- filled: true
30437
- };
30438
- case "line":
30439
- return {
30440
- type: "line",
30441
- kind: "line",
30442
- points: [getDefaultFigureForType("point"), _extends({}, getDefaultFigureForType("point"), {
30443
- coord: [2, 2]
30444
- })],
30445
- color: DEFAULT_COLOR,
30446
- lineStyle: "solid",
30447
- showStartPoint: false,
30448
- showEndPoint: false
30449
- };
30450
- default:
30451
- throw new UnreachableCaseError(type);
30452
- }
30453
- }
30454
-
30455
30539
  /**
30456
- * LockedPointSettings is a component that allows the user to edit the
30457
- * settings of specifically a locked point on the graph.
30458
- *
30459
- * Used in the interactive graph editor's locked figures section.
30540
+ * The part of a locked figure settings panel that contains actions
30541
+ * for this panel and its associated locked figure, including
30542
+ * the delete button.
30460
30543
  */
30461
- const LockedPointSettings = props => {
30544
+ const LockedFigureSettingsActions = props => {
30462
30545
  const {
30463
- coord,
30464
- color: pointColor,
30465
- filled = true,
30466
- label,
30467
- toggled = "true",
30468
- style,
30469
- onChangeProps,
30470
- onToggle,
30471
- onRemove
30546
+ onRemove,
30547
+ figureAriaLabel
30472
30548
  } = props;
30473
-
30474
- // Keep track of the coordinates via state as the user is editing them,
30475
- // before they are updated in the props on blur.
30476
- const [coordState, setCoordState] = React.useState([
30477
- // Using strings to make it easier to work with the text fields.
30478
- coord[0].toString(), coord[1].toString()]);
30479
-
30480
- // Generate unique IDs so that the programmatic labels can be associated
30481
- // with their respective text fields.
30482
- const ids = useUniqueIdWithMock();
30483
- const xCoordId = ids.get("x-coord");
30484
- const yCoordId = ids.get("y-coord");
30485
- const colorSelectId = ids.get("point-color-select");
30486
- function handleBlur() {
30487
- const validCoord = [getValidNumberFromString(coordState[0]), getValidNumberFromString(coordState[1])];
30488
-
30489
- // Make the text field only show valid numbers after blur.
30490
- setCoordState([validCoord[0].toString(), validCoord[1].toString()]);
30491
- // Update the graph with the new coordinates.
30492
- onChangeProps({
30493
- coord: validCoord
30494
- });
30495
- }
30496
- function handleCoordChange(newValue, coordIndex) {
30497
- const newCoord = [...coordState];
30498
- newCoord[coordIndex] = newValue;
30499
- setCoordState(newCoord);
30500
- }
30501
- function handleColorChange(newValue) {
30502
- onChangeProps({
30503
- color: newValue
30504
- });
30505
- }
30506
- return /*#__PURE__*/React.createElement(LockedFigureSettingsAccordion, {
30507
- containerStyle: style,
30508
- panelStyle: !onRemove && styles$d.accordionPanelWithoutActions,
30509
- header:
30510
- /*#__PURE__*/
30511
- // Summary: Point, coords, color (filled/open)
30512
- React.createElement(View, {
30513
- style: styles$d.row
30514
- }, /*#__PURE__*/React.createElement(LabelLarge, null, `${label || "Point"} (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React.createElement(Strut, {
30515
- size: spacing.xSmall_8
30516
- }), toggled && /*#__PURE__*/React.createElement(ColorSwatch, {
30517
- color: pointColor,
30518
- filled: filled
30519
- }))
30520
- }, /*#__PURE__*/React.createElement(View, {
30521
- style: [styles$d.row, styles$d.spaceUnder]
30522
- }, /*#__PURE__*/React.createElement(LabelMedium, {
30523
- htmlFor: xCoordId,
30524
- style: styles$d.label,
30525
- tag: "label"
30526
- }, "x coord"), /*#__PURE__*/React.createElement(TextField, {
30527
- id: xCoordId,
30528
- type: "number",
30529
- value: coordState[0],
30530
- onChange: newValue => handleCoordChange(newValue, 0),
30531
- onBlur: handleBlur,
30532
- style: styles$d.textField
30533
- }), /*#__PURE__*/React.createElement(Strut, {
30534
- size: spacing.medium_16
30535
- }), /*#__PURE__*/React.createElement(LabelMedium, {
30536
- htmlFor: yCoordId,
30537
- style: styles$d.label,
30538
- tag: "label"
30539
- }, "y coord"), /*#__PURE__*/React.createElement(TextField, {
30540
- id: yCoordId,
30541
- type: "number",
30542
- value: coordState[1],
30543
- onChange: newValue => handleCoordChange(newValue, 1),
30544
- onBlur: handleBlur,
30545
- style: styles$d.textField
30546
- })), onToggle && /*#__PURE__*/React.createElement(LabeledSwitch, {
30547
- label: "show point on graph",
30548
- checked: !!toggled,
30549
- style: toggled && styles$d.spaceUnder,
30550
- onChange: onToggle
30551
- }), toggled && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ColorSelect, {
30552
- id: colorSelectId,
30553
- selectedValue: pointColor,
30554
- onChange: handleColorChange,
30555
- style: styles$d.spaceUnder
30556
- }), /*#__PURE__*/React.createElement(LabeledSwitch, {
30557
- label: "open point",
30558
- checked: !filled,
30559
- onChange: newValue => {
30560
- onChangeProps({
30561
- filled: !newValue
30562
- });
30563
- }
30564
- })), onRemove && /*#__PURE__*/React.createElement(LockedFigureSettingsActions, {
30565
- onRemove: onRemove,
30566
- figureAriaLabel: `locked point at ${coordState[0]}, ${coordState[1]}`
30567
- }));
30549
+ return /*#__PURE__*/React.createElement(View, {
30550
+ style: styles$f.container
30551
+ }, /*#__PURE__*/React.createElement(Button, {
30552
+ startIcon: trashIcon,
30553
+ "aria-label": `Delete ${figureAriaLabel}`,
30554
+ onClick: onRemove,
30555
+ kind: "tertiary",
30556
+ style: styles$f.deleteButton
30557
+ }, "Delete"));
30568
30558
  };
30569
- const styles$d = StyleSheet.create({
30570
- accordionPanelWithoutActions: {
30571
- // Need more space since we don't have the actions' margins.
30572
- paddingBottom: spacing.medium_16
30573
- },
30574
- row: {
30559
+ const styles$f = StyleSheet.create({
30560
+ container: {
30561
+ width: "100%",
30575
30562
  flexDirection: "row",
30576
- alignItems: "center"
30577
- },
30578
- spaceUnder: {
30579
- marginBottom: spacing.xSmall_8
30580
- },
30581
- label: {
30582
- marginInlineEnd: spacing.xxSmall_6
30563
+ alignItems: "center",
30564
+ marginTop: spacing.xxxSmall_4
30583
30565
  },
30584
- textField: {
30585
- width: spacing.xxxLarge_64
30566
+ deleteButton: {
30567
+ // Line up the delete icon with the rest of the content.
30568
+ marginInlineStart: -spacing.xxxSmall_4
30586
30569
  }
30587
30570
  });
30588
30571
 
@@ -30592,21 +30575,21 @@ const LockedLineSettings = props => {
30592
30575
  points,
30593
30576
  color: lineColor,
30594
30577
  lineStyle = "solid",
30595
- showStartPoint,
30596
- showEndPoint,
30578
+ showPoint1,
30579
+ showPoint2,
30597
30580
  onChangeProps,
30598
30581
  onRemove
30599
30582
  } = props;
30600
- const [startPoint, endPoint] = points;
30583
+ const [point1, point2] = points;
30601
30584
 
30602
30585
  // Generate unique IDs so that the programmatic labels can be associated
30603
30586
  // with their respective text fields.
30604
30587
  const ids = useUniqueIdWithMock();
30605
30588
  const kindSelectId = ids.get("line-kind-select");
30606
- const colorSelectId = ids.get("line-color-select");
30607
30589
  const styleSelectId = ids.get("line-style-select");
30608
- const lineLabel = `Line (${startPoint.coord[0]}, ${startPoint.coord[1]}),
30609
- (${endPoint.coord[0]}, ${endPoint.coord[1]})`;
30590
+ const capitalizeKind = kind.charAt(0).toUpperCase() + kind.slice(1);
30591
+ const lineLabel = `${capitalizeKind} (${point1.coord[0]},
30592
+ ${point1.coord[1]}), (${point2.coord[0]}, ${point2.coord[1]})`;
30610
30593
  function handleChangePoint(newPointProps, index) {
30611
30594
  const newPoints = [...points];
30612
30595
  newPoints[index] = _extends({}, points[index], newPointProps);
@@ -30618,26 +30601,29 @@ const LockedLineSettings = props => {
30618
30601
  onChangeProps({
30619
30602
  color: newColor,
30620
30603
  // Keep the line's points' colors in sync with the line color.
30621
- points: [_extends({}, startPoint, {
30604
+ points: [_extends({}, point1, {
30622
30605
  color: newColor
30623
- }), _extends({}, endPoint, {
30606
+ }), _extends({}, point2, {
30624
30607
  color: newColor
30625
30608
  })]
30626
30609
  });
30627
30610
  }
30628
30611
  return /*#__PURE__*/React.createElement(LockedFigureSettingsAccordion, {
30612
+ expanded: props.expanded,
30613
+ onToggle: props.onToggle,
30629
30614
  header: /*#__PURE__*/React.createElement(View, {
30630
- style: styles$c.row
30615
+ style: styles$e.row
30631
30616
  }, /*#__PURE__*/React.createElement(LabelLarge, null, lineLabel), /*#__PURE__*/React.createElement(Strut, {
30632
30617
  size: spacing.xSmall_8
30633
- }), /*#__PURE__*/React.createElement(ColorSwatch, {
30634
- color: lineColor
30618
+ }), /*#__PURE__*/React.createElement(LineSwatch, {
30619
+ color: lineColor,
30620
+ lineStyle: lineStyle
30635
30621
  }))
30636
30622
  }, /*#__PURE__*/React.createElement(View, {
30637
- style: [styles$c.row, styles$c.spaceUnder]
30623
+ style: [styles$e.row, styles$e.spaceUnder]
30638
30624
  }, /*#__PURE__*/React.createElement(LabelMedium, {
30639
30625
  htmlFor: kindSelectId,
30640
- style: styles$c.label,
30626
+ style: styles$e.label,
30641
30627
  tag: "label"
30642
30628
  }, "kind"), /*#__PURE__*/React.createElement(SingleSelect, {
30643
30629
  id: kindSelectId,
@@ -30658,18 +30644,17 @@ const LockedLineSettings = props => {
30658
30644
  value: "ray",
30659
30645
  label: "ray"
30660
30646
  }))), /*#__PURE__*/React.createElement(View, {
30661
- style: [styles$c.row, styles$c.spaceUnder]
30647
+ style: [styles$e.row, styles$e.spaceUnder]
30662
30648
  }, /*#__PURE__*/React.createElement(ColorSelect, {
30663
- id: colorSelectId,
30664
30649
  selectedValue: lineColor,
30665
30650
  onChange: handleColorChange
30666
30651
  }), /*#__PURE__*/React.createElement(Strut, {
30667
30652
  size: spacing.small_12
30668
30653
  }), /*#__PURE__*/React.createElement(View, {
30669
- style: styles$c.row
30654
+ style: styles$e.row
30670
30655
  }, /*#__PURE__*/React.createElement(LabelMedium, {
30671
30656
  htmlFor: styleSelectId,
30672
- style: styles$c.label,
30657
+ style: styles$e.label,
30673
30658
  tag: "label"
30674
30659
  }, "style"), /*#__PURE__*/React.createElement(SingleSelect, {
30675
30660
  id: styleSelectId,
@@ -30680,46 +30665,37 @@ const LockedLineSettings = props => {
30680
30665
  // Placeholder is required, but never gets used.
30681
30666
  ,
30682
30667
  placeholder: "",
30683
- style: styles$c.selectMarginOffset
30668
+ style: styles$e.selectMarginOffset
30684
30669
  }, /*#__PURE__*/React.createElement(OptionItem, {
30685
30670
  value: "solid",
30686
30671
  label: "solid"
30687
30672
  }), /*#__PURE__*/React.createElement(OptionItem, {
30688
30673
  value: "dashed",
30689
30674
  label: "dashed"
30690
- })))), /*#__PURE__*/React.createElement(LockedPointSettings, _extends({
30691
- label: "Start point",
30692
- toggled: showStartPoint
30693
- }, startPoint, {
30694
- onToggle: newValue => onChangeProps({
30695
- showStartPoint: newValue
30675
+ })))), /*#__PURE__*/React.createElement(DefiningPointSettings, _extends({
30676
+ label: "Point 1",
30677
+ showPoint: showPoint1
30678
+ }, point1, {
30679
+ onTogglePoint: newValue => onChangeProps({
30680
+ showPoint1: newValue
30696
30681
  }),
30697
- onChangeProps: newProps => handleChangePoint(newProps, 0),
30698
- style: styles$c.lockedPointSettingsContainer
30699
- })), /*#__PURE__*/React.createElement(LockedPointSettings, _extends({
30700
- label: "End point",
30701
- toggled: showEndPoint
30702
- }, endPoint, {
30703
- onToggle: newValue => onChangeProps({
30704
- showEndPoint: newValue
30682
+ onChangeProps: newProps => handleChangePoint(newProps, 0)
30683
+ })), /*#__PURE__*/React.createElement(DefiningPointSettings, _extends({
30684
+ label: "Point 2",
30685
+ showPoint: showPoint2
30686
+ }, point2, {
30687
+ onTogglePoint: newValue => onChangeProps({
30688
+ showPoint2: newValue
30705
30689
  }),
30706
- onChangeProps: newProps => handleChangePoint(newProps, 1),
30707
- style: styles$c.lockedPointSettingsContainer
30690
+ onChangeProps: newProps => handleChangePoint(newProps, 1)
30708
30691
  })), /*#__PURE__*/React.createElement(LockedFigureSettingsActions, {
30709
30692
  onRemove: onRemove,
30710
30693
  figureAriaLabel: `locked line defined by
30711
- ${startPoint.coord[0]}, ${startPoint.coord[1]} and
30712
- ${endPoint.coord[0]}, ${endPoint.coord[1]}.`
30694
+ ${point1.coord[0]}, ${point1.coord[1]} and
30695
+ ${point2.coord[0]}, ${point2.coord[1]}.`
30713
30696
  }));
30714
30697
  };
30715
- const styles$c = StyleSheet.create({
30716
- lockedPointSettingsContainer: {
30717
- marginTop: spacing.xSmall_8,
30718
- marginBottom: 0,
30719
- marginLeft: -spacing.xxxSmall_4,
30720
- marginRight: -spacing.xxxSmall_4,
30721
- backgroundColor: color.white
30722
- },
30698
+ const styles$e = StyleSheet.create({
30723
30699
  row: {
30724
30700
  flexDirection: "row",
30725
30701
  alignItems: "center"
@@ -30736,6 +30712,69 @@ const styles$c = StyleSheet.create({
30736
30712
  }
30737
30713
  });
30738
30714
 
30715
+ /**
30716
+ * LockedPointSettings is a component that allows the user to edit the
30717
+ * settings of specifically a locked point on the graph.
30718
+ *
30719
+ * Used in the interactive graph editor's locked figures section.
30720
+ */
30721
+ const LockedPointSettings = props => {
30722
+ const {
30723
+ coord,
30724
+ color: pointColor,
30725
+ filled = true,
30726
+ onChangeProps,
30727
+ onRemove
30728
+ } = props;
30729
+ function handleColorChange(newValue) {
30730
+ onChangeProps({
30731
+ color: newValue
30732
+ });
30733
+ }
30734
+ return /*#__PURE__*/React.createElement(LockedFigureSettingsAccordion, {
30735
+ expanded: props.expanded,
30736
+ onToggle: props.onToggle,
30737
+ header:
30738
+ /*#__PURE__*/
30739
+ // Summary: Point, coords, color (filled/open)
30740
+ React.createElement(View, {
30741
+ style: styles$d.row
30742
+ }, /*#__PURE__*/React.createElement(LabelLarge, null, `Point (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React.createElement(Strut, {
30743
+ size: spacing.xSmall_8
30744
+ }), /*#__PURE__*/React.createElement(ColorSwatch, {
30745
+ color: pointColor,
30746
+ filled: filled
30747
+ }))
30748
+ }, /*#__PURE__*/React.createElement(CoordinatePairInput, {
30749
+ coord: coord,
30750
+ onChangeProps: onChangeProps
30751
+ }), /*#__PURE__*/React.createElement(ColorSelect, {
30752
+ selectedValue: pointColor,
30753
+ onChange: handleColorChange,
30754
+ style: styles$d.spaceUnder
30755
+ }), /*#__PURE__*/React.createElement(LabeledSwitch, {
30756
+ label: "open point",
30757
+ checked: !filled,
30758
+ onChange: newValue => {
30759
+ onChangeProps({
30760
+ filled: !newValue
30761
+ });
30762
+ }
30763
+ }), /*#__PURE__*/React.createElement(LockedFigureSettingsActions, {
30764
+ onRemove: onRemove,
30765
+ figureAriaLabel: `locked point at ${coord[0]}, ${coord[1]}`
30766
+ }));
30767
+ };
30768
+ const styles$d = StyleSheet.create({
30769
+ row: {
30770
+ flexDirection: "row",
30771
+ alignItems: "center"
30772
+ },
30773
+ spaceUnder: {
30774
+ marginBottom: spacing.xSmall_8
30775
+ }
30776
+ });
30777
+
30739
30778
  /**
30740
30779
  * LockedFigureSettings takes in a figure and renders the
30741
30780
  * respective settings for that figure type.
@@ -30755,7 +30794,78 @@ const LockedFigureSettings = props => {
30755
30794
  return null;
30756
30795
  };
30757
30796
 
30797
+ function focusWithChromeStickyFocusBugWorkaround(element) {
30798
+ // NOTE(marksandstrom) Chrome sticky focus bug.
30799
+ //
30800
+ // There is a bug in Chrome related to sticky positioning and
30801
+ // focus: When a child of an element with sticky positioning is
30802
+ // focused with the focus() method, the scrollable area
30803
+ // containing that element will scroll to the top (even though
30804
+ // the element is already visble on the page). For a dropdown
30805
+ // this means that the area will be scrolled to the top when
30806
+ // the user interacts with the dropdown (since we actively
30807
+ // manage dropdown header and option focus for keyboard users).
30808
+ //
30809
+ // To work around this bug the `preventScroll` focus option is
30810
+ // used.
30811
+ //
30812
+ // Using `focusOptions` is an experimental browser feature
30813
+ // "that should not be used in production code". However, since
30814
+ // Chrome is the only browser we support that exhibits this
30815
+ // buggy behavior and using `focusOptions` works around the
30816
+ // bug, it is perfectly reasonable to use the feature in this
30817
+ // case. We are not relying on the effect of the
30818
+ // `preventScroll` option otherwise.
30819
+ //
30820
+ // focusOptions documentation:
30821
+ //
30822
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
30823
+ //
30824
+ // Note that there could be cases where we want default focus() behavior.
30825
+ // One that comes to mind is a dropdown with a long list of options that
30826
+ // might be rendered off screen when opened. With this workaround the
30827
+ // selected option would not be scrolled into view if the option is near
30828
+ // the end of the list. We're not aware of any uses of the dropdown where
30829
+ // this is an issue, however, so there isn't currently a way to out of the
30830
+ // `preventScroll` behavior.
30831
+
30832
+ // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
30833
+ element.focus({
30834
+ preventScroll: true
30835
+ });
30836
+ }
30837
+ const DEFAULT_COLOR = "grayH";
30838
+ function getDefaultFigureForType(type) {
30839
+ switch (type) {
30840
+ case "point":
30841
+ return {
30842
+ type: "point",
30843
+ coord: [0, 0],
30844
+ color: DEFAULT_COLOR,
30845
+ filled: true
30846
+ };
30847
+ case "line":
30848
+ return {
30849
+ type: "line",
30850
+ kind: "line",
30851
+ points: [getDefaultFigureForType("point"), _extends({}, getDefaultFigureForType("point"), {
30852
+ coord: [2, 2]
30853
+ })],
30854
+ color: DEFAULT_COLOR,
30855
+ lineStyle: "solid",
30856
+ showPoint1: false,
30857
+ showPoint2: false
30858
+ };
30859
+ default:
30860
+ throw new UnreachableCaseError(type);
30861
+ }
30862
+ }
30863
+
30758
30864
  const LockedFiguresSection = props => {
30865
+ var _props$figures;
30866
+ // Keep track of all figures' accordions' expanded states for the
30867
+ // expand/collapse all button. Set the whole array to false initially.
30868
+ const [expandedStates, setExpandedStates] = React.useState(Array((_props$figures = props.figures) == null ? void 0 : _props$figures.length).fill(false));
30759
30869
  const uniqueId = useUniqueIdWithMock().get("locked-figures-section");
30760
30870
  const {
30761
30871
  figures,
@@ -30767,6 +30877,7 @@ const LockedFiguresSection = props => {
30767
30877
  lockedFigures: [...lockedFigures, getDefaultFigureForType(newFigure)]
30768
30878
  };
30769
30879
  onChange(newProps);
30880
+ setExpandedStates([...expandedStates, true]);
30770
30881
  }
30771
30882
  function removeLockedFigure(index) {
30772
30883
  // eslint-disable-next-line no-alert
@@ -30775,6 +30886,11 @@ const LockedFiguresSection = props => {
30775
30886
  onChange({
30776
30887
  lockedFigures: [...lockedFigures.slice(0, index), ...lockedFigures.slice(index + 1)]
30777
30888
  });
30889
+
30890
+ // Update expanded states
30891
+ const newExpandedStates = [...expandedStates];
30892
+ newExpandedStates.splice(index, 1);
30893
+ setExpandedStates(newExpandedStates);
30778
30894
  }
30779
30895
  }
30780
30896
  function changeProps(index,
@@ -30787,16 +30903,46 @@ const LockedFiguresSection = props => {
30787
30903
  };
30788
30904
  onChange(newFigures);
30789
30905
  }
30906
+ function toggleExpanded(newValue) {
30907
+ setExpandedStates(Array(figures == null ? void 0 : figures.length).fill(newValue));
30908
+ }
30909
+ const allCollapsed = expandedStates.every(value => !value);
30910
+ const buttonLabel = allCollapsed ? "Expand all" : "Collapse all";
30911
+ const showExpandButton = !!(figures != null && figures.length);
30790
30912
  return /*#__PURE__*/React.createElement(View, null, figures == null ? void 0 : figures.map((figure, index) => /*#__PURE__*/React.createElement(LockedFigureSettings, _extends({
30913
+ expanded: expandedStates[index],
30914
+ onToggle: newValue => {
30915
+ const newExpanded = [...expandedStates];
30916
+ newExpanded[index] = newValue;
30917
+ setExpandedStates(newExpanded);
30918
+ },
30791
30919
  key: `${uniqueId}-locked-${figure}-${index}`
30792
30920
  }, figure, {
30793
30921
  onChangeProps: newProps => changeProps(index, newProps),
30794
30922
  onRemove: () => removeLockedFigure(index)
30795
- }))), /*#__PURE__*/React.createElement(LockedFigureSelect, {
30923
+ }))), /*#__PURE__*/React.createElement(View, {
30924
+ style: styles$c.buttonContainer
30925
+ }, /*#__PURE__*/React.createElement(LockedFigureSelect, {
30796
30926
  id: `${uniqueId}-select`,
30797
30927
  onChange: addLockedFigure
30798
- }));
30928
+ }), /*#__PURE__*/React.createElement(Strut, {
30929
+ size: spacing.small_12
30930
+ }), showExpandButton && /*#__PURE__*/React.createElement(Button, {
30931
+ kind: "secondary",
30932
+ onClick: () => toggleExpanded(allCollapsed),
30933
+ style: styles$c.button
30934
+ }, buttonLabel)));
30799
30935
  };
30936
+ const styles$c = StyleSheet.create({
30937
+ buttonContainer: {
30938
+ flexDirection: "row",
30939
+ alignItems: "center"
30940
+ },
30941
+ button: {
30942
+ marginTop: spacing.xSmall_8,
30943
+ flexGrow: 1
30944
+ }
30945
+ });
30800
30946
 
30801
30947
  const SegmentCountSelector = ({
30802
30948
  numSegments: _numSegments = 1,