@khanacademy/perseus-editor 5.0.3 → 5.1.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
@@ -9,7 +9,7 @@ import Clickable from '@khanacademy/wonder-blocks-clickable';
9
9
  import Color from '@khanacademy/wonder-blocks-color';
10
10
  import { StyleSheet, css } from 'aphrodite';
11
11
  import $ from 'jquery';
12
- import { View } from '@khanacademy/wonder-blocks-core';
12
+ import { View, useUniqueIdWithMock } from '@khanacademy/wonder-blocks-core';
13
13
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
14
14
  import caretRight from '@phosphor-icons/core/bold/caret-right-bold.svg';
15
15
  import classNames from 'classnames';
@@ -18,17 +18,19 @@ import { point, number } from '@khanacademy/kmath';
18
18
  import * as KAS from '@khanacademy/kas';
19
19
  import { isTruthy } from '@khanacademy/wonder-stuff-core';
20
20
  import { createMathField } from '@khanacademy/math-input';
21
- import { SingleSelect, OptionItem } from '@khanacademy/wonder-blocks-dropdown';
22
- import { Checkbox as Checkbox$1 } from '@khanacademy/wonder-blocks-form';
21
+ import { SingleSelect, OptionItem, ActionMenu, ActionItem } from '@khanacademy/wonder-blocks-dropdown';
22
+ import { TextField, Checkbox as Checkbox$1 } from '@khanacademy/wonder-blocks-form';
23
23
  import Spacing from '@khanacademy/wonder-blocks-spacing';
24
- import { LabelSmall, BodyMonospace } from '@khanacademy/wonder-blocks-typography';
24
+ import { LabelSmall, LabelLarge, LabelMedium, BodyMonospace } from '@khanacademy/wonder-blocks-typography';
25
25
  import { spacing, color } from '@khanacademy/wonder-blocks-tokens';
26
+ import IconButton from '@khanacademy/wonder-blocks-icon-button';
27
+ import trashIcon from '@phosphor-icons/core/bold/trash-bold.svg';
26
28
  import Button from '@khanacademy/wonder-blocks-button';
27
29
  import * as i18n$1 from '@khanacademy/wonder-blocks-i18n';
28
30
 
29
31
  // This file is processed by a Rollup plugin (replace) to inject the production
30
32
  const libName = "@khanacademy/perseus-editor";
31
- const libVersion = "5.0.3";
33
+ const libVersion = "5.1.1";
32
34
  addLibraryVersionToPerseusDebug(libName, libVersion);
33
35
 
34
36
  function _extends() {
@@ -224,7 +226,7 @@ class SectionControlButton extends React.Component {
224
226
  role: "button",
225
227
  hideDefaultFocusRing: true,
226
228
  "aria-label": title,
227
- style: styles$m.button
229
+ style: styles$q.button
228
230
  }, ({
229
231
  hovered,
230
232
  focused,
@@ -232,7 +234,7 @@ class SectionControlButton extends React.Component {
232
234
  }) => /*#__PURE__*/React.createElement(InlineIcon$b, icon));
233
235
  }
234
236
  }
235
- const styles$m = StyleSheet.create({
237
+ const styles$q = StyleSheet.create({
236
238
  button: {
237
239
  backgroundColor: Color.gold,
238
240
  margin: 2,
@@ -20754,19 +20756,19 @@ class TexErrorView extends React.Component {
20754
20756
  const {
20755
20757
  showErrors
20756
20758
  } = this.state;
20757
- const iconStyle = showErrors ? styles$l.iconExpanded : styles$l.iconCollapsed;
20759
+ const iconStyle = showErrors ? styles$p.iconExpanded : styles$p.iconCollapsed;
20758
20760
  return /*#__PURE__*/React.createElement(View, {
20759
- style: styles$l.errorContainer
20761
+ style: styles$p.errorContainer
20760
20762
  }, /*#__PURE__*/React.createElement(View, {
20761
- style: styles$l.title,
20763
+ style: styles$p.title,
20762
20764
  onClick: this.handleToggleTexErrors
20763
20765
  }, /*#__PURE__*/React.createElement(PhosphorIcon, {
20764
20766
  icon: caretRight,
20765
20767
  style: iconStyle
20766
20768
  }), "\xA0 TeX Errors (", errorList.length, ")"), showErrors && /*#__PURE__*/React.createElement(View, {
20767
- style: styles$l.errorExplanation
20769
+ style: styles$p.errorExplanation
20768
20770
  }, "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, {
20769
- style: styles$l.error,
20771
+ style: styles$p.error,
20770
20772
  key: index
20771
20773
  }, /*#__PURE__*/React.createElement(View, {
20772
20774
  style: {
@@ -20775,7 +20777,7 @@ class TexErrorView extends React.Component {
20775
20777
  }, e.math), /*#__PURE__*/React.createElement(View, null, e.message))));
20776
20778
  }
20777
20779
  }
20778
- const styles$l = StyleSheet.create({
20780
+ const styles$p = StyleSheet.create({
20779
20781
  title: {
20780
20782
  backgroundColor: "#eee",
20781
20783
  fontSize: "1.25em",
@@ -24606,7 +24608,7 @@ class SimpleButton extends React.Component {
24606
24608
  } = _this$props,
24607
24609
  otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
24608
24610
  return /*#__PURE__*/React.createElement("div", _extends({
24609
- className: css(styles$k.baseButton, color === "green" && styles$k.green, color === "orange" && styles$k.orange),
24611
+ className: css(styles$o.baseButton, color === "green" && styles$o.green, color === "orange" && styles$o.orange),
24610
24612
  onClick: onClick
24611
24613
  }, otherProps), children);
24612
24614
  }
@@ -24621,7 +24623,7 @@ SimpleButton.defaultProps = {
24621
24623
  color: "green",
24622
24624
  onClick: () => {}
24623
24625
  };
24624
- const styles$k = StyleSheet.create({
24626
+ const styles$o = StyleSheet.create({
24625
24627
  baseButton: {
24626
24628
  top: "0",
24627
24629
  fontSize: "11px",
@@ -24841,23 +24843,23 @@ const LeafContainer = ({
24841
24843
  }) => {
24842
24844
  const hasPreviewHeading = shape.type === "content" || shape.type === "hint";
24843
24845
  const previewHeading = hasPreviewHeading && /*#__PURE__*/React.createElement("div", {
24844
- className: css(styles$j.containerHeader)
24846
+ className: css(styles$n.containerHeader)
24845
24847
  }, /*#__PURE__*/React.createElement(Header, {
24846
24848
  depth: path.length,
24847
- className: css(styles$j.containerTitle)
24849
+ className: css(styles$n.containerTitle)
24848
24850
  }, capitalize(name)));
24849
24851
  return /*#__PURE__*/React.createElement("div", {
24850
- className: css(styles$j.container)
24852
+ className: css(styles$n.container)
24851
24853
  }, /*#__PURE__*/React.createElement("span", {
24852
- className: css(styles$j.row, styles$j.rowHeading)
24854
+ className: css(styles$n.row, styles$n.rowHeading)
24853
24855
  }, /*#__PURE__*/React.createElement("div", {
24854
- className: css(styles$j.columnLeft)
24856
+ className: css(styles$n.columnLeft)
24855
24857
  }, /*#__PURE__*/React.createElement("div", {
24856
- className: "pod-title " + css(styles$j.containerHeader)
24858
+ className: "pod-title " + css(styles$n.containerHeader)
24857
24859
  }, /*#__PURE__*/React.createElement("div", {
24858
- className: css(styles$j.containerTitle)
24860
+ className: css(styles$n.containerTitle)
24859
24861
  }, capitalize(name)), controls)), /*#__PURE__*/React.createElement("div", {
24860
- className: css(styles$j.columnRight)
24862
+ className: css(styles$n.columnRight)
24861
24863
  }, previewHeading)), children);
24862
24864
  };
24863
24865
  const ArrayContainer = props => {
@@ -24870,11 +24872,11 @@ const ArrayContainer = props => {
24870
24872
  actions
24871
24873
  } = props;
24872
24874
  return /*#__PURE__*/React.createElement("div", {
24873
- className: css(styles$j.container)
24875
+ className: css(styles$n.container)
24874
24876
  }, controls && /*#__PURE__*/React.createElement("div", {
24875
- className: css(styles$j.columnLeft, styles$j.containerHeader)
24877
+ className: css(styles$n.columnLeft, styles$n.containerHeader)
24876
24878
  }, controls), /*#__PURE__*/React.createElement("div", null, children), /*#__PURE__*/React.createElement("div", {
24877
- className: css(styles$j.columnLeft)
24879
+ className: css(styles$n.columnLeft)
24878
24880
  }, /*#__PURE__*/React.createElement("a", {
24879
24881
  href: "javascript:void 0",
24880
24882
  onClick: () => actions.addArrayElement(path, shape.elementShape)
@@ -24887,28 +24889,28 @@ const ObjectContainer = ({
24887
24889
  path
24888
24890
  }) => {
24889
24891
  const headingEditor = /*#__PURE__*/React.createElement("div", {
24890
- className: css(styles$j.containerHeader)
24892
+ className: css(styles$n.containerHeader)
24891
24893
  }, /*#__PURE__*/React.createElement(Header, {
24892
24894
  depth: path.length,
24893
- className: css(styles$j.containerTitle)
24895
+ className: css(styles$n.containerTitle)
24894
24896
  }, capitalize(name)), controls);
24895
24897
  const headingPreview = (name || controls) && /*#__PURE__*/React.createElement("div", {
24896
- className: css(styles$j.containerHeader, styles$j.previewCollectionHeader)
24898
+ className: css(styles$n.containerHeader, styles$n.previewCollectionHeader)
24897
24899
  }, /*#__PURE__*/React.createElement(Header, {
24898
24900
  depth: path.length,
24899
- className: css(styles$j.containerTitle)
24901
+ className: css(styles$n.containerTitle)
24900
24902
  }, capitalize(name)));
24901
24903
  const hasBothHeadings = headingEditor && headingPreview;
24902
24904
  return /*#__PURE__*/React.createElement("div", {
24903
- className: css(styles$j.container)
24905
+ className: css(styles$n.container)
24904
24906
  }, hasBothHeadings && /*#__PURE__*/React.createElement("span", {
24905
- className: css(styles$j.row)
24907
+ className: css(styles$n.row)
24906
24908
  }, /*#__PURE__*/React.createElement("div", {
24907
- className: css(styles$j.columnLeft)
24909
+ className: css(styles$n.columnLeft)
24908
24910
  }, headingEditor), /*#__PURE__*/React.createElement("div", {
24909
- className: css(styles$j.columnRight)
24911
+ className: css(styles$n.columnRight)
24910
24912
  }, headingPreview)), /*#__PURE__*/React.createElement("div", {
24911
- className: css(path.length > 0 && styles$j.contentIndent)
24913
+ className: css(path.length > 0 && styles$n.contentIndent)
24912
24914
  }, children));
24913
24915
  };
24914
24916
 
@@ -25031,11 +25033,11 @@ const ItemNodeContent = withStickiness(props => {
25031
25033
  className: "framework-perseus"
25032
25034
  }, lens(renderers).get(path));
25033
25035
  return /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("div", {
25034
- className: css(styles$j.row)
25036
+ className: css(styles$n.row)
25035
25037
  }, /*#__PURE__*/React.createElement("div", {
25036
- className: css(styles$j.columnLeft)
25038
+ className: css(styles$n.columnLeft)
25037
25039
  }, /*#__PURE__*/React.createElement("div", {
25038
- className: css(sticky && styles$j.sticky)
25040
+ className: css(sticky && styles$n.sticky)
25039
25041
  },
25040
25042
  /*#__PURE__*/
25041
25043
  // @ts-expect-error - TS2769 - No overload matches this call.
@@ -25043,9 +25045,9 @@ const ItemNodeContent = withStickiness(props => {
25043
25045
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25044
25046
  apiOptions: apiOptions
25045
25047
  })))), /*#__PURE__*/React.createElement("div", {
25046
- className: css(styles$j.columnRight)
25048
+ className: css(styles$n.columnRight)
25047
25049
  }, /*#__PURE__*/React.createElement("div", {
25048
- className: css(sticky && styles$j.sticky)
25050
+ className: css(sticky && styles$n.sticky)
25049
25051
  }, preview))));
25050
25052
  });
25051
25053
  const HintNodeContent = withStickiness(props => {
@@ -25061,13 +25063,13 @@ const HintNodeContent = withStickiness(props => {
25061
25063
  className: "framework-perseus"
25062
25064
  }, lens(renderers).get(path));
25063
25065
  return /*#__PURE__*/React.createElement("div", {
25064
- className: css(styles$j.row)
25066
+ className: css(styles$n.row)
25065
25067
  }, /*#__PURE__*/React.createElement("div", {
25066
- className: css(styles$j.columnLeft)
25068
+ className: css(styles$n.columnLeft)
25067
25069
  }, /*#__PURE__*/React.createElement("div", {
25068
- className: css(sticky && styles$j.sticky)
25070
+ className: css(sticky && styles$n.sticky)
25069
25071
  }, /*#__PURE__*/React.createElement(HintEditor, _extends({}, data, {
25070
- className: css(styles$j.hintEditor),
25072
+ className: css(styles$n.hintEditor),
25071
25073
  onChange: newVal => actions.mergeValueAtPath(path, newVal),
25072
25074
  apiOptions: apiOptions,
25073
25075
  showTitle: false,
@@ -25082,9 +25084,9 @@ const HintNodeContent = withStickiness(props => {
25082
25084
  isFirst: true,
25083
25085
  isLast: true
25084
25086
  })))), /*#__PURE__*/React.createElement("div", {
25085
- className: css(styles$j.columnRight)
25087
+ className: css(styles$n.columnRight)
25086
25088
  }, /*#__PURE__*/React.createElement("div", {
25087
- className: css(sticky && styles$j.sticky)
25089
+ className: css(sticky && styles$n.sticky)
25088
25090
  }, preview)));
25089
25091
  });
25090
25092
  const TagsNodeContent = props => {
@@ -25101,9 +25103,9 @@ const TagsNodeContent = props => {
25101
25103
  return null;
25102
25104
  }
25103
25105
  return /*#__PURE__*/React.createElement("div", {
25104
- className: css(styles$j.columnLeft)
25106
+ className: css(styles$n.columnLeft)
25105
25107
  }, /*#__PURE__*/React.createElement("div", {
25106
- className: css(styles$j.tagsEditor)
25108
+ className: css(styles$n.tagsEditor)
25107
25109
  }, /*#__PURE__*/React.createElement(GroupMetadataEditor, {
25108
25110
  value: data,
25109
25111
  onChange: newVal => actions.setValueAtPath(path, newVal),
@@ -25134,23 +25136,23 @@ const ArrayNodeContent = props => {
25134
25136
  const subpath = path.concat(i);
25135
25137
  const controls = [i > 0 && /*#__PURE__*/React.createElement("div", {
25136
25138
  key: "moveArrayElementUp",
25137
- className: css(styles$j.control)
25139
+ className: css(styles$n.control)
25138
25140
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25139
25141
  color: "orange",
25140
25142
  title: "Move up",
25141
25143
  onClick: () => actions.moveArrayElementUp(subpath)
25142
25144
  }, /*#__PURE__*/React.createElement("div", {
25143
- className: css(styles$j.verticalFlip)
25145
+ className: css(styles$n.verticalFlip)
25144
25146
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconChevronDown)))), i < data.length - 1 && /*#__PURE__*/React.createElement("div", {
25145
25147
  key: "moveArrayElementDown",
25146
- className: css(styles$j.control)
25148
+ className: css(styles$n.control)
25147
25149
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25148
25150
  color: "orange",
25149
25151
  title: "Move down",
25150
25152
  onClick: () => actions.moveArrayElementDown(subpath)
25151
25153
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconChevronDown))), /*#__PURE__*/React.createElement("div", {
25152
25154
  key: "removeArrayElement",
25153
- className: css(styles$j.control)
25155
+ className: css(styles$n.control)
25154
25156
  }, /*#__PURE__*/React.createElement(SimpleButton, {
25155
25157
  color: "orange",
25156
25158
  title: "Delete",
@@ -25158,7 +25160,7 @@ const ArrayNodeContent = props => {
25158
25160
  }, /*#__PURE__*/React.createElement(InlineIcon$6, iconTrash$4)))];
25159
25161
  return /*#__PURE__*/React.createElement("div", {
25160
25162
  key: i,
25161
- className: css(styles$j.arrayElement, !elementIsLeaf && styles$j.arrayElementAndNotLeaf)
25163
+ className: css(styles$n.arrayElement, !elementIsLeaf && styles$n.arrayElementAndNotLeaf)
25162
25164
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25163
25165
  key: i,
25164
25166
  shape: shape.elementShape,
@@ -25184,7 +25186,7 @@ const ObjectNodeContent = props => {
25184
25186
  // made sense to the shape's author is the order in which we'll iterate :)
25185
25187
  const children = Object.keys(shape.shape).map(subkey => /*#__PURE__*/React.createElement("div", {
25186
25188
  key: subkey,
25187
- className: css(styles$j.objectElement)
25189
+ className: css(styles$n.objectElement)
25188
25190
  }, /*#__PURE__*/React.createElement(NodeContainer, _extends({}, otherProps, {
25189
25191
  shape: shape.shape[subkey],
25190
25192
  data: data[subkey],
@@ -25351,7 +25353,7 @@ class MultiRendererEditor extends React.Component {
25351
25353
  }, this._renderContent());
25352
25354
  }
25353
25355
  }
25354
- const styles$j = StyleSheet.create({
25356
+ const styles$n = StyleSheet.create({
25355
25357
  // This is used in a number of places throughout this file.
25356
25358
  container: {},
25357
25359
  // eslint-disable-next-line react-native/no-unused-styles
@@ -25503,47 +25505,47 @@ const StatefulArticleEditor = createReactClass({
25503
25505
  screen
25504
25506
  } = this.state;
25505
25507
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
25506
- style: styles$i.controlBar
25508
+ style: styles$m.controlBar
25507
25509
  }, /*#__PURE__*/React.createElement("span", {
25508
- style: styles$i.controls
25510
+ style: styles$m.controls
25509
25511
  }, "Mode:", " ", /*#__PURE__*/React.createElement("span", {
25510
25512
  onClick: () => this.setState({
25511
25513
  mode: "edit"
25512
25514
  }),
25513
- style: mode === "edit" ? styles$i.controlSelected : styles$i.control
25515
+ style: mode === "edit" ? styles$m.controlSelected : styles$m.control
25514
25516
  }, "EDIT"), " | ", /*#__PURE__*/React.createElement("span", {
25515
25517
  onClick: () => this.setState({
25516
25518
  mode: "preview"
25517
25519
  }),
25518
- style: mode === "preview" ? styles$i.controlSelected : styles$i.control
25520
+ style: mode === "preview" ? styles$m.controlSelected : styles$m.control
25519
25521
  }, "PREVIEW"), " | ", /*#__PURE__*/React.createElement("span", {
25520
25522
  onClick: () => this.setState({
25521
25523
  mode: "json"
25522
25524
  }),
25523
- style: mode === "json" ? styles$i.controlSelected : styles$i.control
25525
+ style: mode === "json" ? styles$m.controlSelected : styles$m.control
25524
25526
  }, "JSON")), /*#__PURE__*/React.createElement("span", {
25525
- style: styles$i.controls
25527
+ style: styles$m.controls
25526
25528
  }, "Screen:", " ", /*#__PURE__*/React.createElement("span", {
25527
25529
  onClick: () => this.setState({
25528
25530
  screen: "phone"
25529
25531
  }),
25530
- style: screen === "phone" ? styles$i.controlSelected : styles$i.control
25532
+ style: screen === "phone" ? styles$m.controlSelected : styles$m.control
25531
25533
  }, "PHONE"), " | ", /*#__PURE__*/React.createElement("span", {
25532
25534
  onClick: () => this.setState({
25533
25535
  screen: "tablet"
25534
25536
  }),
25535
- style: screen === "tablet" ? styles$i.controlSelected : styles$i.control
25537
+ style: screen === "tablet" ? styles$m.controlSelected : styles$m.control
25536
25538
  }, "TABLET"), " | ", /*#__PURE__*/React.createElement("span", {
25537
25539
  onClick: () => this.setState({
25538
25540
  screen: "desktop"
25539
25541
  }),
25540
- style: screen === "desktop" ? styles$i.controlSelected : styles$i.control
25542
+ style: screen === "desktop" ? styles$m.controlSelected : styles$m.control
25541
25543
  }, "DESKTOP"))), /*#__PURE__*/React.createElement("div", {
25542
- style: styles$i.editor
25544
+ style: styles$m.editor
25543
25545
  }, /*#__PURE__*/React.createElement(ArticleEditor, this.state)));
25544
25546
  }
25545
25547
  });
25546
- const styles$i = {
25548
+ const styles$m = {
25547
25549
  controlBar: {
25548
25550
  marginBottom: 25,
25549
25551
  marginTop: 5
@@ -27032,10 +27034,10 @@ class GradedGroupEditor extends React.Component {
27032
27034
  }, /*#__PURE__*/React.createElement("div", {
27033
27035
  className: "perseus-widget-row"
27034
27036
  }, /*#__PURE__*/React.createElement("label", {
27035
- className: css(styles$h.title)
27037
+ className: css(styles$l.title)
27036
27038
  }, "Title:", " ", /*#__PURE__*/React.createElement(TextInput$6, {
27037
27039
  value: this.props.title,
27038
- className: css(styles$h.input)
27040
+ className: css(styles$l.input)
27039
27041
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
27040
27042
  ,
27041
27043
  onChange: this.change("title")
@@ -27060,7 +27062,7 @@ class GradedGroupEditor extends React.Component {
27060
27062
  }, /*#__PURE__*/React.createElement(InlineIcon$4, iconPlus$1), " Add a hint"), this.props.hint && /*#__PURE__*/React.createElement("div", {
27061
27063
  className: "perseus-hint-editor"
27062
27064
  }, /*#__PURE__*/React.createElement("div", {
27063
- className: css(styles$h.hintsTitle)
27065
+ className: css(styles$l.hintsTitle)
27064
27066
  }, "Hint"), /*#__PURE__*/React.createElement(Editor, {
27065
27067
  ref: this.hintEditor,
27066
27068
  content: this.props.hint ? this.props.hint.content : "",
@@ -27097,7 +27099,7 @@ GradedGroupEditor.defaultProps = {
27097
27099
  images: {},
27098
27100
  hint: null
27099
27101
  };
27100
- const styles$h = StyleSheet.create({
27102
+ const styles$l = StyleSheet.create({
27101
27103
  title: {
27102
27104
  fontSize: 18,
27103
27105
  fontWeight: "bold"
@@ -28429,13 +28431,13 @@ function MathquillInput(props) {
28429
28431
  }
28430
28432
  });
28431
28433
  return /*#__PURE__*/React.createElement(View, {
28432
- style: styles$g.outerWrapper
28434
+ style: styles$k.outerWrapper
28433
28435
  }, /*#__PURE__*/React.createElement("span", {
28434
28436
  ref: mathFieldWrapperRef,
28435
28437
  className: "perseus-math-input mq-editable-field mq-math-mode"
28436
28438
  }));
28437
28439
  }
28438
- const styles$g = StyleSheet.create({
28440
+ const styles$k = StyleSheet.create({
28439
28441
  outerWrapper: {
28440
28442
  display: "inline-block",
28441
28443
  borderStyle: "solid",
@@ -29496,7 +29498,7 @@ const GraphPointsCountSelector = ({
29496
29498
  // Never uses placeholder, always has value
29497
29499
  ,
29498
29500
  placeholder: "",
29499
- style: styles$f.singleSelectShort
29501
+ style: styles$j.singleSelectShort
29500
29502
  }, [...[...Array(7).keys()].map(n => /*#__PURE__*/React.createElement(OptionItem, {
29501
29503
  key: n,
29502
29504
  value: `${n}`,
@@ -29506,7 +29508,7 @@ const GraphPointsCountSelector = ({
29506
29508
  label: "unlimited"
29507
29509
  })]);
29508
29510
  };
29509
- const styles$f = StyleSheet.create({
29511
+ const styles$j = StyleSheet.create({
29510
29512
  singleSelectShort: {
29511
29513
  // Non-standard spacing, but it's the smallest we can go
29512
29514
  // without running into styling issues with the dropdown.
@@ -29519,7 +29521,7 @@ const GraphTypeSelector = props => {
29519
29521
  selectedValue: props.graphType,
29520
29522
  onChange: props.onChange,
29521
29523
  placeholder: "Select a graph type",
29522
- style: styles$e.singleSelectShort
29524
+ style: styles$i.singleSelectShort
29523
29525
  }, /*#__PURE__*/React.createElement(OptionItem, {
29524
29526
  value: "linear",
29525
29527
  label: "Linear function"
@@ -29552,7 +29554,7 @@ const GraphTypeSelector = props => {
29552
29554
  label: "Angle"
29553
29555
  }));
29554
29556
  };
29555
- const styles$e = StyleSheet.create({
29557
+ const styles$i = StyleSheet.create({
29556
29558
  singleSelectShort: {
29557
29559
  // Non-standard spacing, but it's the smallest we can go
29558
29560
  // without running into styling issues with the dropdown.
@@ -29568,19 +29570,25 @@ const LabeledRow = props => {
29568
29570
  labelSide = "left",
29569
29571
  style
29570
29572
  } = props;
29571
- return /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement(View, {
29572
- style: [styles$d.row, style]
29573
+ return /*#__PURE__*/React.createElement("label", {
29574
+ className: css(styles$h.label)
29575
+ }, /*#__PURE__*/React.createElement(View, {
29576
+ style: [styles$h.row, style]
29573
29577
  }, labelSide === "start" || /*#__PURE__*/React.createElement(LabelSmall, {
29574
- style: styles$d.spaceEnd
29578
+ style: styles$h.spaceEnd
29575
29579
  }, label), children, labelSide === "end" && /*#__PURE__*/React.createElement(LabelSmall, {
29576
- style: styles$d.spaceStart
29580
+ style: styles$h.spaceStart
29577
29581
  }, label)));
29578
29582
  };
29579
- const styles$d = StyleSheet.create({
29583
+ const styles$h = StyleSheet.create({
29584
+ label: {
29585
+ width: "fit-content"
29586
+ },
29580
29587
  row: {
29581
29588
  flexDirection: "row",
29582
29589
  marginTop: spacing.xSmall_8,
29583
- alignItems: "center"
29590
+ alignItems: "center",
29591
+ width: "fit-content"
29584
29592
  },
29585
29593
  spaceStart: {
29586
29594
  marginInlineStart: spacing.xSmall_8
@@ -29966,10 +29974,10 @@ class InteractiveGraphSettings extends React.Component {
29966
29974
  onChange: this.change
29967
29975
  }))), /*#__PURE__*/React.createElement(LabeledRow, {
29968
29976
  label: "Background image URL:",
29969
- style: styles$c.resetSpaceTop
29977
+ style: styles$g.resetSpaceTop
29970
29978
  }, /*#__PURE__*/React.createElement("input", {
29971
29979
  type: "text",
29972
- className: css(styles$c.backgroundUrlInput),
29980
+ className: css(styles$g.backgroundUrlInput),
29973
29981
  ref: this.bgUrlRef,
29974
29982
  value: this.state.backgroundImage.url || "",
29975
29983
  onChange: e => {
@@ -29983,24 +29991,24 @@ class InteractiveGraphSettings extends React.Component {
29983
29991
  onKeyPress: this.changeBackgroundUrl,
29984
29992
  onBlur: this.changeBackgroundUrl
29985
29993
  }), /*#__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, {
29986
- style: styles$c.rulerSection
29994
+ style: styles$g.rulerSection
29987
29995
  }, /*#__PURE__*/React.createElement(View, {
29988
- style: styles$c.checkboxRow
29996
+ style: styles$g.checkboxRow
29989
29997
  }, /*#__PURE__*/React.createElement(PropCheckBox$7, {
29990
29998
  label: "Show ruler",
29991
29999
  showRuler: this.props.showRuler,
29992
30000
  onChange: this.change,
29993
- style: styles$c.resetSpaceTop
30001
+ style: styles$g.resetSpaceTop
29994
30002
  }), /*#__PURE__*/React.createElement(PropCheckBox$7, {
29995
30003
  label: "Show protractor",
29996
30004
  showProtractor: this.props.showProtractor,
29997
30005
  onChange: this.change,
29998
- style: styles$c.resetSpaceTop
30006
+ style: styles$g.resetSpaceTop
29999
30007
  })), this.props.showRuler && /*#__PURE__*/React.createElement(View, {
30000
- style: styles$c.spaceTop
30008
+ style: styles$g.spaceTop
30001
30009
  }, /*#__PURE__*/React.createElement(LabeledRow, {
30002
30010
  label: "Ruler label:",
30003
- style: styles$c.resetSpaceTop
30011
+ style: styles$g.resetSpaceTop
30004
30012
  }, /*#__PURE__*/React.createElement(SingleSelect, {
30005
30013
  id: "ruler-label-select",
30006
30014
  selectedValue: this.props.rulerLabel,
@@ -30010,7 +30018,7 @@ class InteractiveGraphSettings extends React.Component {
30010
30018
  });
30011
30019
  },
30012
30020
  placeholder: "None",
30013
- style: styles$c.singleSelectShort
30021
+ style: styles$g.singleSelectShort
30014
30022
  }, /*#__PURE__*/React.createElement(OptionItem, {
30015
30023
  value: "",
30016
30024
  label: "None",
@@ -30051,7 +30059,7 @@ class InteractiveGraphSettings extends React.Component {
30051
30059
  });
30052
30060
  },
30053
30061
  placeholder: "10",
30054
- style: styles$c.singleSelectShort
30062
+ style: styles$g.singleSelectShort
30055
30063
  }, [1, 2, 4, 8, 10, 16].map(value => /*#__PURE__*/React.createElement(OptionItem, {
30056
30064
  key: value,
30057
30065
  value: `${value}`,
@@ -30075,7 +30083,7 @@ InteractiveGraphSettings.defaultProps = {
30075
30083
  rulerLabel: "",
30076
30084
  rulerTicks: 10
30077
30085
  };
30078
- const styles$c = StyleSheet.create({
30086
+ const styles$g = StyleSheet.create({
30079
30087
  resetSpaceTop: {
30080
30088
  marginTop: 0
30081
30089
  },
@@ -30106,6 +30114,314 @@ const styles$c = StyleSheet.create({
30106
30114
  }
30107
30115
  });
30108
30116
 
30117
+ /**
30118
+ * Dropdown for selecting a locked figure to add to an interactive graph.
30119
+ * Locked figures are elements (points, segmeents, etc.) that are not
30120
+ * interactive, just present in the graph's background.
30121
+ *
30122
+ * Used in the interactive graph editor's locked figures section.
30123
+ */
30124
+ const LockedFigureSelect = props => {
30125
+ const {
30126
+ id,
30127
+ onChange
30128
+ } = props;
30129
+ return /*#__PURE__*/React.createElement(View, {
30130
+ style: styles$f.container
30131
+ }, /*#__PURE__*/React.createElement(ActionMenu, {
30132
+ menuText: "Add element",
30133
+ style: styles$f.addElementSelect
30134
+ }, [/*#__PURE__*/React.createElement(ActionItem, {
30135
+ key: `${id}-point`,
30136
+ label: "Point",
30137
+ onClick: () => onChange("point")
30138
+ }, "Point")]));
30139
+ };
30140
+ const styles$f = StyleSheet.create({
30141
+ container: {
30142
+ marginTop: spacing.medium_16
30143
+ },
30144
+ addElementSelect: {
30145
+ backgroundColor: color.fadedBlue16,
30146
+ borderRadius: spacing.xxxSmall_4
30147
+ }
30148
+ });
30149
+
30150
+ const mediaDefaultSpecLargeMarginWidth = spacing.large_24;
30151
+ const MEDIA_DEFAULT_SPEC = {
30152
+ small: {
30153
+ query: "(max-width: 767px)",
30154
+ totalColumns: 4,
30155
+ gutterWidth: spacing.medium_16,
30156
+ marginWidth: spacing.medium_16
30157
+ },
30158
+ medium: {
30159
+ query: "(min-width: 768px) and (max-width: 1023px)",
30160
+ totalColumns: 8,
30161
+ gutterWidth: spacing.xLarge_32,
30162
+ marginWidth: spacing.large_24
30163
+ },
30164
+ large: {
30165
+ query: "(min-width: 1024px)",
30166
+ totalColumns: 12,
30167
+ gutterWidth: spacing.xLarge_32,
30168
+ marginWidth: mediaDefaultSpecLargeMarginWidth,
30169
+ maxWidth: 1120 + mediaDefaultSpecLargeMarginWidth * 2
30170
+ }
30171
+ };
30172
+ ({
30173
+ large: {
30174
+ query: "(min-width: 1px)",
30175
+ totalColumns: 12,
30176
+ gutterWidth: spacing.xLarge_32,
30177
+ marginWidth: spacing.medium_16
30178
+ }
30179
+ });
30180
+ ({
30181
+ small: {
30182
+ query: "(max-width: 767px)",
30183
+ totalColumns: 4,
30184
+ gutterWidth: spacing.medium_16,
30185
+ marginWidth: spacing.medium_16
30186
+ },
30187
+ large: {
30188
+ query: "(min-width: 768px)",
30189
+ totalColumns: 12,
30190
+ gutterWidth: spacing.xLarge_32,
30191
+ marginWidth: spacing.xxLarge_48
30192
+ }
30193
+ });
30194
+
30195
+ const defaultContext = {
30196
+ ssrSize: "large",
30197
+ mediaSpec: MEDIA_DEFAULT_SPEC
30198
+ };
30199
+ const MediaLayoutContext = React.createContext(defaultContext);
30200
+ MediaLayoutContext.displayName = "MediaLayoutContext";
30201
+
30202
+ class Spring extends React.Component {
30203
+ render() {
30204
+ const {
30205
+ style
30206
+ } = this.props;
30207
+ return React.createElement(View, {
30208
+ "aria-hidden": "true",
30209
+ style: [styles$e.grow, style]
30210
+ });
30211
+ }
30212
+ }
30213
+ const styles$e = StyleSheet.create({
30214
+ grow: {
30215
+ flexGrow: 1
30216
+ }
30217
+ });
30218
+
30219
+ function focusWithChromeStickyFocusBugWorkaround(element) {
30220
+ // NOTE(marksandstrom) Chrome sticky focus bug.
30221
+ //
30222
+ // There is a bug in Chrome related to sticky positioning and
30223
+ // focus: When a child of an element with sticky positioning is
30224
+ // focused with the focus() method, the scrollable area
30225
+ // containing that element will scroll to the top (even though
30226
+ // the element is already visble on the page). For a dropdown
30227
+ // this means that the area will be scrolled to the top when
30228
+ // the user interacts with the dropdown (since we actively
30229
+ // manage dropdown header and option focus for keyboard users).
30230
+ //
30231
+ // To work around this bug the `preventScroll` focus option is
30232
+ // used.
30233
+ //
30234
+ // Using `focusOptions` is an experimental browser feature
30235
+ // "that should not be used in production code". However, since
30236
+ // Chrome is the only browser we support that exhibits this
30237
+ // buggy behavior and using `focusOptions` works around the
30238
+ // bug, it is perfectly reasonable to use the feature in this
30239
+ // case. We are not relying on the effect of the
30240
+ // `preventScroll` option otherwise.
30241
+ //
30242
+ // focusOptions documentation:
30243
+ //
30244
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
30245
+ //
30246
+ // Note that there could be cases where we want default focus() behavior.
30247
+ // One that comes to mind is a dropdown with a long list of options that
30248
+ // might be rendered off screen when opened. With this workaround the
30249
+ // selected option would not be scrolled into view if the option is near
30250
+ // the end of the list. We're not aware of any uses of the dropdown where
30251
+ // this is an issue, however, so there isn't currently a way to out of the
30252
+ // `preventScroll` behavior.
30253
+
30254
+ // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
30255
+ element.focus({
30256
+ preventScroll: true
30257
+ });
30258
+ }
30259
+ function getValidNumberFromString(value) {
30260
+ const parsed = parseInt(value);
30261
+ // If the value is not a number, return 0.
30262
+ return isNaN(parsed) ? 0 : parsed;
30263
+ }
30264
+ function getDefaultFigureForFigureType(type) {
30265
+ switch (type) {
30266
+ case "point":
30267
+ return {
30268
+ type: "point",
30269
+ coord: [0, 0]
30270
+ };
30271
+ }
30272
+ }
30273
+
30274
+ /**
30275
+ * LockedPointSettings is a component that allows the user to edit the
30276
+ * settings of specifically a locked point on the graph.
30277
+ *
30278
+ * Used in the interactive graph editor's locked figures section.
30279
+ */
30280
+ const LockedPointSettings = props => {
30281
+ const {
30282
+ coord,
30283
+ onRemove,
30284
+ onChangeCoord
30285
+ } = props;
30286
+ const [coordState, setCoordState] = React.useState([
30287
+ // Using strings to make it easier to work with the text fields.
30288
+ coord[0].toString(), coord[1].toString()]);
30289
+
30290
+ // Generate unique IDs so that the programmatic labels can be associated
30291
+ // with their respective text fields.
30292
+ const ids = useUniqueIdWithMock();
30293
+ const xCoordId = ids.get("x-coord");
30294
+ const yCoordId = ids.get("y-coord");
30295
+ function handleBlur() {
30296
+ const validCoord = [getValidNumberFromString(coordState[0]), getValidNumberFromString(coordState[1])];
30297
+
30298
+ // Make the text field only show valid numbers after blur.
30299
+ setCoordState([validCoord[0].toString(), validCoord[1].toString()]);
30300
+ // Update the graph with the new coordinates.
30301
+ onChangeCoord(validCoord);
30302
+ }
30303
+ function handleChange(newValue, coordIndex) {
30304
+ const newCoord = [...coordState];
30305
+ newCoord[coordIndex] = newValue;
30306
+ setCoordState(newCoord);
30307
+ }
30308
+ return /*#__PURE__*/React.createElement(View, {
30309
+ style: styles$d.container
30310
+ }, /*#__PURE__*/React.createElement(View, {
30311
+ style: styles$d.row
30312
+ }, /*#__PURE__*/React.createElement(LabelLarge, null, "Point"), /*#__PURE__*/React.createElement(Spring, null), /*#__PURE__*/React.createElement(IconButton, {
30313
+ icon: trashIcon,
30314
+ "aria-label": `Delete locked point at ${coordState[0]}, ${coordState[1]}`,
30315
+ onClick: onRemove
30316
+ })), /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(View, {
30317
+ style: styles$d.row
30318
+ }, /*#__PURE__*/React.createElement(LabelMedium, {
30319
+ htmlFor: xCoordId,
30320
+ style: styles$d.label,
30321
+ tag: "label"
30322
+ }, "x Coordinate"), /*#__PURE__*/React.createElement(TextField, {
30323
+ id: xCoordId,
30324
+ value: coordState[0],
30325
+ onChange: newValue => handleChange(newValue, 0),
30326
+ onBlur: handleBlur,
30327
+ style: styles$d.textField
30328
+ })), /*#__PURE__*/React.createElement(View, {
30329
+ style: styles$d.row
30330
+ }, /*#__PURE__*/React.createElement(LabelMedium, {
30331
+ htmlFor: yCoordId,
30332
+ style: styles$d.label,
30333
+ tag: "label"
30334
+ }, "y Coordinate"), /*#__PURE__*/React.createElement(TextField, {
30335
+ id: yCoordId,
30336
+ value: coordState[1],
30337
+ onChange: newValue => handleChange(newValue, 1),
30338
+ onBlur: handleBlur,
30339
+ style: styles$d.textField
30340
+ }))));
30341
+ };
30342
+ const styles$d = StyleSheet.create({
30343
+ container: {
30344
+ backgroundColor: color.fadedBlue8,
30345
+ marginBottom: spacing.xSmall_8,
30346
+ padding: spacing.medium_16,
30347
+ borderRadius: spacing.xSmall_8
30348
+ },
30349
+ row: {
30350
+ flexDirection: "row",
30351
+ alignItems: "center",
30352
+ marginBottom: spacing.xSmall_8
30353
+ },
30354
+ label: {
30355
+ marginInlineEnd: spacing.xSmall_8
30356
+ },
30357
+ textField: {
30358
+ width: spacing.xxxLarge_64
30359
+ }
30360
+ });
30361
+
30362
+ /**
30363
+ * LockedFigureSettings takes in a figure and renders the
30364
+ * respective settings for that figure type.
30365
+ *
30366
+ * Used in the interactive graph editor's locked figures section.
30367
+ */
30368
+
30369
+ // Union this type with other locked figure types when they are added.
30370
+
30371
+ const LockedFigureSettings = props => {
30372
+ switch (props.type) {
30373
+ case "point":
30374
+ return /*#__PURE__*/React.createElement(LockedPointSettings, props);
30375
+ }
30376
+ return null;
30377
+ };
30378
+
30379
+ const LockedFiguresSection = props => {
30380
+ const uniqueId = useUniqueIdWithMock().get("locked-figures-section");
30381
+ const {
30382
+ figures,
30383
+ onChange
30384
+ } = props;
30385
+ function addLockedFigure(newFigure) {
30386
+ const lockedFigures = figures || [];
30387
+ const newProps = {
30388
+ lockedFigures: [...lockedFigures, getDefaultFigureForFigureType(newFigure)]
30389
+ };
30390
+ onChange(newProps);
30391
+ }
30392
+ function removeLockedFigure(index) {
30393
+ const lockedFigures = figures || [];
30394
+ onChange({
30395
+ lockedFigures: [...lockedFigures.slice(0, index), ...lockedFigures.slice(index + 1)]
30396
+ });
30397
+ }
30398
+ function changeCoord(index, coord) {
30399
+ const lockedFigures = figures || [];
30400
+ const newProps = {
30401
+ lockedFigures: [...lockedFigures.slice(0, index), _extends({}, lockedFigures[index], {
30402
+ coord
30403
+ }), ...lockedFigures.slice(index + 1)]
30404
+ };
30405
+ onChange(newProps);
30406
+ }
30407
+ return /*#__PURE__*/React.createElement(View, {
30408
+ style: styles$c.container
30409
+ }, figures == null ? void 0 : figures.map((figure, index) => /*#__PURE__*/React.createElement(LockedFigureSettings, _extends({
30410
+ key: `${uniqueId}-locked-${figure}-${index}`
30411
+ }, figure, {
30412
+ onRemove: () => removeLockedFigure(index),
30413
+ onChangeCoord: coord => changeCoord(index, coord)
30414
+ }))), /*#__PURE__*/React.createElement(LockedFigureSelect, {
30415
+ id: `${uniqueId}-select`,
30416
+ onChange: addLockedFigure
30417
+ }));
30418
+ };
30419
+ const styles$c = StyleSheet.create({
30420
+ container: {
30421
+ paddingTop: spacing.large_24
30422
+ }
30423
+ });
30424
+
30109
30425
  const SegmentCountSelector = ({
30110
30426
  numSegments: _numSegments = 1,
30111
30427
  onChange
@@ -30186,7 +30502,7 @@ class InteractiveGraphEditor extends React.Component {
30186
30502
  DeprecationMixin.UNSAFE_componentWillMount.call(this);
30187
30503
  }
30188
30504
  render() {
30189
- var _this$props$graph$typ, _this$props$graph, _this$props$correct, _this$props$correct2, _this$props$correct3, _this$props$correct4, _this$props$correct5, _this$props$correct6, _this$props$correct7, _this$props$correct8, _this$props$correct9, _this$props$correct10, _this$props$correct11;
30505
+ var _this$props$graph$typ, _this$props$graph, _this$props$correct, _this$props$correct2, _this$props$correct3, _this$props$correct4, _this$props$correct5, _this$props$correct6, _this$props$correct7, _this$props$correct8, _this$props$correct9, _this$props$correct10, _this$props$correct11, _this$props$apiOption;
30190
30506
  let graph;
30191
30507
  let equationString;
30192
30508
  const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, interactiveSizes.defaultBoxSize);
@@ -30210,6 +30526,7 @@ class InteractiveGraphEditor extends React.Component {
30210
30526
  showTooltips: this.props.showTooltips,
30211
30527
  rulerLabel: this.props.rulerLabel,
30212
30528
  rulerTicks: this.props.rulerTicks,
30529
+ lockedFigures: this.props.lockedFigures,
30213
30530
  trackInteraction: function () {},
30214
30531
  onChange: newProps => {
30215
30532
  let correct = this.props.correct;
@@ -30425,10 +30742,16 @@ class InteractiveGraphEditor extends React.Component {
30425
30742
  borderStyle: "solid",
30426
30743
  borderWidth: 1
30427
30744
  }
30428
- }, equationString), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."))), graph);
30745
+ }, equationString), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."))), graph,
30746
+ // Only show the "Add element" dropdown if the graph is
30747
+ // using Mafs.
30748
+ this.props.graph && ((_this$props$apiOption = this.props.apiOptions) == null || (_this$props$apiOption = _this$props$apiOption.flags) == null || (_this$props$apiOption = _this$props$apiOption["mafs"]) == null ? void 0 : _this$props$apiOption[this.props.graph.type]) && /*#__PURE__*/React.createElement(LockedFiguresSection, {
30749
+ figures: this.props.lockedFigures,
30750
+ onChange: this.props.onChange
30751
+ }));
30429
30752
  }
30430
30753
  serialize() {
30431
- const json = _.pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showRuler", "showTooltips", "rulerLabel", "rulerTicks", "range", "gridStep", "snapStep");
30754
+ const json = _.pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showRuler", "showTooltips", "rulerLabel", "rulerTicks", "range", "gridStep", "snapStep", "lockedFigures");
30432
30755
 
30433
30756
  // eslint-disable-next-line react/no-string-refs
30434
30757
  const graph = this.refs.graph;
@@ -31188,47 +31511,6 @@ const styles$5 = StyleSheet.create({
31188
31511
  })
31189
31512
  });
31190
31513
 
31191
- function focusWithChromeStickyFocusBugWorkaround(element) {
31192
- // NOTE(marksandstrom) Chrome sticky focus bug.
31193
- //
31194
- // There is a bug in Chrome related to sticky positioning and
31195
- // focus: When a child of an element with sticky positioning is
31196
- // focused with the focus() method, the scrollable area
31197
- // containing that element will scroll to the top (even though
31198
- // the element is already visble on the page). For a dropdown
31199
- // this means that the area will be scrolled to the top when
31200
- // the user interacts with the dropdown (since we actively
31201
- // manage dropdown header and option focus for keyboard users).
31202
- //
31203
- // To work around this bug the `preventScroll` focus option is
31204
- // used.
31205
- //
31206
- // Using `focusOptions` is an experimental browser feature
31207
- // "that should not be used in production code". However, since
31208
- // Chrome is the only browser we support that exhibits this
31209
- // buggy behavior and using `focusOptions` works around the
31210
- // bug, it is perfectly reasonable to use the feature in this
31211
- // case. We are not relying on the effect of the
31212
- // `preventScroll` option otherwise.
31213
- //
31214
- // focusOptions documentation:
31215
- //
31216
- // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
31217
- //
31218
- // Note that there could be cases where we want default focus() behavior.
31219
- // One that comes to mind is a dropdown with a long list of options that
31220
- // might be rendered off screen when opened. With this workaround the
31221
- // selected option would not be scrolled into view if the option is near
31222
- // the end of the list. We're not aware of any uses of the dropdown where
31223
- // this is an issue, however, so there isn't currently a way to out of the
31224
- // `preventScroll` behavior.
31225
-
31226
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
31227
- element.focus({
31228
- preventScroll: true
31229
- });
31230
- }
31231
-
31232
31514
  const {
31233
31515
  Icon
31234
31516
  } = components;