@khanacademy/perseus-editor 17.5.0 → 17.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -8,7 +8,7 @@ import Clickable from '@khanacademy/wonder-blocks-clickable';
8
8
  import { color, spacing, font } from '@khanacademy/wonder-blocks-tokens';
9
9
  import { StyleSheet, css } from 'aphrodite';
10
10
  import $ from 'jquery';
11
- import { View, addStyle } from '@khanacademy/wonder-blocks-core';
11
+ import { View, addStyle, Id } from '@khanacademy/wonder-blocks-core';
12
12
  import Switch from '@khanacademy/wonder-blocks-switch';
13
13
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
14
14
  import caretRight from '@phosphor-icons/core/bold/caret-right-bold.svg';
@@ -20,7 +20,7 @@ import ReactDOM from 'react-dom';
20
20
  import * as KAS from '@khanacademy/kas';
21
21
  import Button from '@khanacademy/wonder-blocks-button';
22
22
  import { isTruthy, UnreachableCaseError } from '@khanacademy/wonder-stuff-core';
23
- import { KhanMath, vector, angles, number } from '@khanacademy/kmath';
23
+ import { KhanMath, angles, vector, number } from '@khanacademy/kmath';
24
24
  import { inputNumberAnswerTypes } from '@khanacademy/perseus-score';
25
25
  import { useMathInputI18n, createMathField } from '@khanacademy/math-input';
26
26
  import { SingleSelect, OptionItem, ActionMenu, ActionItem } from '@khanacademy/wonder-blocks-dropdown';
@@ -47,7 +47,7 @@ import arrowCounterClockwise from '@phosphor-icons/core/bold/arrow-counter-clock
47
47
 
48
48
  // This file is processed by a Rollup plugin (replace) to inject the production
49
49
  const libName = "@khanacademy/perseus-editor";
50
- const libVersion = "17.5.0";
50
+ const libVersion = "17.6.0";
51
51
  addLibraryVersionToPerseusDebug(libName, libVersion);
52
52
 
53
53
  function _extends() {
@@ -20525,7 +20525,7 @@ function _objectWithoutPropertiesLoose(r, e) {
20525
20525
  if (null == r) return {};
20526
20526
  var t = {};
20527
20527
  for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
20528
- if (e.includes(n)) continue;
20528
+ if (-1 !== e.indexOf(n)) continue;
20529
20529
  t[n] = r[n];
20530
20530
  }
20531
20531
  return t;
@@ -28208,7 +28208,7 @@ const GraphTypeSelector = props => {
28208
28208
  onChange: props.onChange,
28209
28209
  placeholder: "Select an answer type",
28210
28210
  style: styles$J.singleSelectShort
28211
- }, props.showNoneOption && /*#__PURE__*/React.createElement(OptionItem, {
28211
+ }, /*#__PURE__*/React.createElement(OptionItem, {
28212
28212
  value: "none",
28213
28213
  label: "None"
28214
28214
  }), /*#__PURE__*/React.createElement(OptionItem, {
@@ -28302,7 +28302,9 @@ function InteractiveGraphCorrectAnswer(props) {
28302
28302
  title: "Correct Answer",
28303
28303
  isOpen: true,
28304
28304
  isCollapsible: false
28305
- }), /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(LabelXSmall, {
28305
+ }), /*#__PURE__*/React.createElement(View, {
28306
+ id: props.id
28307
+ }, /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(LabelXSmall, {
28306
28308
  style: {
28307
28309
  paddingTop: spacing.xxSmall_6,
28308
28310
  paddingBottom: spacing.xxSmall_6,
@@ -28864,10 +28866,14 @@ const styles$F = StyleSheet.create({
28864
28866
  }
28865
28867
  });
28866
28868
 
28867
- const StyledUL = addStyle("ul");
28869
+ const StyledUl = addStyle("ul");
28868
28870
  // Exported for testing
28869
- function getAccessibilityAttributes(container) {
28871
+ function getAccessibilityAttributes(graphId) {
28870
28872
  const elementArias = [];
28873
+
28874
+ // TODO(nisha): Change this to use ref after the graph has a non-string
28875
+ // ref and the InteractiveGraph component forwards refs.
28876
+ const container = document.getElementById(graphId);
28871
28877
  if (!container) {
28872
28878
  return elementArias;
28873
28879
  }
@@ -28937,7 +28943,7 @@ function SRTree(props) {
28937
28943
  size: "small",
28938
28944
  kind: "success",
28939
28945
  style: styles$E.smallSpaceRight
28940
- }, aria.roleOrTag), aria.className, /*#__PURE__*/React.createElement(StyledUL, {
28946
+ }, aria.roleOrTag), aria.className, /*#__PURE__*/React.createElement(StyledUl, {
28941
28947
  style: styles$E.indentListLeft
28942
28948
  }, aria.attributes.map((value, index) => /*#__PURE__*/React.createElement("li", {
28943
28949
  key: index
@@ -28948,27 +28954,26 @@ function SRTree(props) {
28948
28954
  }, value.name), value.value))))));
28949
28955
  }
28950
28956
  function InteractiveGraphSRTree({
28957
+ // The graph whos accessibility tree we want to display.
28958
+ // This is necessary when there are multiple graphs on the editor
28959
+ // page, such as when there are also hints.
28960
+ graphId,
28951
28961
  correct,
28952
28962
  fullGraphAriaLabel,
28953
28963
  fullGraphAriaDescription,
28954
28964
  lockedFigures
28955
28965
  }) {
28956
- var _document$getElements;
28957
28966
  const [isExpanded, setIsExpanded] = React.useState(true);
28958
28967
  const [showTags, setShowTags] = React.useState(false);
28959
28968
  const [elementArias, setElementArias] = React.useState([]);
28960
28969
  const switchId = React.useId();
28961
28970
 
28962
- // TODO(nisha): Change this to use ref after the graph has a non-string
28963
- // ref and the InteractiveGraph component forwards refs.
28964
- const mafsGraphContainer = (_document$getElements = document.getElementsByClassName("mafs-graph-container")) == null ? void 0 : _document$getElements[0];
28965
-
28966
28971
  // Update the tree when the graph is updated.
28967
28972
  React.useEffect(() => {
28968
- setElementArias(getAccessibilityAttributes(mafsGraphContainer));
28973
+ setElementArias(getAccessibilityAttributes(graphId));
28969
28974
  }, [
28970
28975
  // Update the tree when the "correct preview" graph is updated.
28971
- correct, fullGraphAriaLabel, fullGraphAriaDescription, lockedFigures, mafsGraphContainer]);
28976
+ correct, fullGraphAriaLabel, fullGraphAriaDescription, graphId, lockedFigures]);
28972
28977
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Heading, {
28973
28978
  title: "Screen reader tree",
28974
28979
  isOpen: isExpanded,
@@ -29135,59 +29140,16 @@ const ScrolllessNumberTextField = props => {
29135
29140
  }));
29136
29141
  };
29137
29142
 
29138
- function focusWithChromeStickyFocusBugWorkaround(element) {
29139
- // NOTE(marksandstrom) Chrome sticky focus bug.
29140
- //
29141
- // There is a bug in Chrome related to sticky positioning and
29142
- // focus: When a child of an element with sticky positioning is
29143
- // focused with the focus() method, the scrollable area
29144
- // containing that element will scroll to the top (even though
29145
- // the element is already visble on the page). For a dropdown
29146
- // this means that the area will be scrolled to the top when
29147
- // the user interacts with the dropdown (since we actively
29148
- // manage dropdown header and option focus for keyboard users).
29149
- //
29150
- // To work around this bug the `preventScroll` focus option is
29151
- // used.
29152
- //
29153
- // Using `focusOptions` is an experimental browser feature
29154
- // "that should not be used in production code". However, since
29155
- // Chrome is the only browser we support that exhibits this
29156
- // buggy behavior and using `focusOptions` works around the
29157
- // bug, it is perfectly reasonable to use the feature in this
29158
- // case. We are not relying on the effect of the
29159
- // `preventScroll` option otherwise.
29160
- //
29161
- // focusOptions documentation:
29162
- //
29163
- // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
29164
- //
29165
- // Note that there could be cases where we want default focus() behavior.
29166
- // One that comes to mind is a dropdown with a long list of options that
29167
- // might be rendered off screen when opened. With this workaround the
29168
- // selected option would not be scrolled into view if the option is near
29169
- // the end of the list. We're not aware of any uses of the dropdown where
29170
- // this is an issue, however, so there isn't currently a way to out of the
29171
- // `preventScroll` behavior.
29172
-
29173
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
29174
- element.focus({
29175
- preventScroll: true
29176
- });
29177
- }
29178
- function degreeToRadian(degrees) {
29179
- return degrees / 180 * Math.PI;
29180
- }
29181
- function radianToDegree(radians) {
29182
- return radians / Math.PI * 180;
29183
- }
29184
-
29143
+ const {
29144
+ convertDegreesToRadians,
29145
+ convertRadiansToDegrees: convertRadiansToDegrees$1
29146
+ } = angles;
29185
29147
  const AngleInput = props => {
29186
29148
  const {
29187
29149
  angle,
29188
29150
  onChange
29189
29151
  } = props;
29190
- const [angleInput, setAngleInput] = React.useState(radianToDegree(angle).toString());
29152
+ const [angleInput, setAngleInput] = React.useState(convertRadiansToDegrees$1(angle).toString());
29191
29153
  function handleAngleChange(newValue) {
29192
29154
  // Update the local state (update the input field value).
29193
29155
  setAngleInput(newValue);
@@ -29199,7 +29161,7 @@ const AngleInput = props => {
29199
29161
  }
29200
29162
 
29201
29163
  // Update the graph.
29202
- onChange(degreeToRadian(newValue));
29164
+ onChange(convertDegreesToRadians(newValue));
29203
29165
  }
29204
29166
  return /*#__PURE__*/React.createElement(LabelMedium, {
29205
29167
  tag: "label",
@@ -94296,6 +94258,9 @@ async function joinLabelsAsSpokenMath(labels) {
94296
94258
  return ` ${spokenLabels.join(", ")}`;
94297
94259
  }
94298
94260
 
94261
+ const {
94262
+ convertRadiansToDegrees
94263
+ } = angles;
94299
94264
  const {
94300
94265
  InfoTip: InfoTip$c
94301
94266
  } = components;
@@ -94325,7 +94290,7 @@ const LockedEllipseSettings = props => {
94325
94290
  const visiblelabel = await joinLabelsAsSpokenMath(labels);
94326
94291
  const spokenCenterX = await generateSpokenMathDetails(`$${center[0]}$`);
94327
94292
  const spokenCenterY = await generateSpokenMathDetails(`$${center[1]}$`);
94328
- const spokenRotation = await generateSpokenMathDetails(`$${radianToDegree(angle)}$`);
94293
+ const spokenRotation = await generateSpokenMathDetails(`$${convertRadiansToDegrees(angle)}$`);
94329
94294
  const isCircle = radius[0] === radius[1];
94330
94295
  let str = "";
94331
94296
  if (isCircle) {
@@ -96836,7 +96801,6 @@ class InteractiveGraphEditor extends React.Component {
96836
96801
  return json;
96837
96802
  }
96838
96803
  render() {
96839
- var _this$props$graph$typ, _this$props$graph3, _this$props$apiOption, _this$props$apiOption2, _this$props$fullGraph, _this$props$fullGraph2, _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$correct12, _this$props$correct13, _this$props$correct14, _this$props$graph12, _this$props$apiOption3;
96840
96804
  let graph;
96841
96805
  let equationString;
96842
96806
  const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, interactiveSizes.defaultBoxSize);
@@ -96903,264 +96867,232 @@ class InteractiveGraphEditor extends React.Component {
96903
96867
  className: "perseus-error"
96904
96868
  }, this.props.valid);
96905
96869
  }
96906
- return /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(LabeledRow, {
96907
- label: "Answer type:"
96908
- }, /*#__PURE__*/React.createElement(GraphTypeSelector, {
96909
- graphType: (_this$props$graph$typ = (_this$props$graph3 = this.props.graph) == null ? void 0 : _this$props$graph3.type) != null ? _this$props$graph$typ : InteractiveGraph.defaultProps.graph.type
96910
- // TODO(LEMS-2656): remove TS suppression
96911
- ,
96912
- onChange: type => {
96913
- this.props.onChange({
96914
- graph: {
96915
- type
96916
- },
96917
- correct: {
96918
- type
96919
- }
96920
- });
96921
- },
96922
- showNoneOption: (_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["none"]
96923
- })), this.props.graph && ((_this$props$apiOption2 = this.props.apiOptions) == null || (_this$props$apiOption2 = _this$props$apiOption2.flags) == null || (_this$props$apiOption2 = _this$props$apiOption2.mafs) == null ? void 0 : _this$props$apiOption2[this.props.graph.type]) && /*#__PURE__*/React.createElement(InteractiveGraphDescription, {
96924
- ariaLabelValue: (_this$props$fullGraph = this.props.fullGraphAriaLabel) != null ? _this$props$fullGraph : "",
96925
- ariaDescriptionValue: (_this$props$fullGraph2 = this.props.fullGraphAriaDescription) != null ? _this$props$fullGraph2 : "",
96926
- onChange: this.props.onChange
96927
- }), /*#__PURE__*/React.createElement(InteractiveGraphCorrectAnswer, {
96928
- equationString: equationString
96929
- }, graph), ((_this$props$correct = this.props.correct) == null ? void 0 : _this$props$correct.type) === "point" && /*#__PURE__*/React.createElement(LabeledRow, {
96930
- label: "Number of Points:"
96931
- }, /*#__PURE__*/React.createElement(GraphPointsCountSelector, {
96932
- numPoints: (_this$props$correct2 = this.props.correct) == null ? void 0 : _this$props$correct2.numPoints,
96933
- onChange: points => {
96934
- this.props.onChange({
96935
- correct: {
96936
- type: "point",
96937
- numPoints: points
96938
- },
96939
- graph: {
96940
- type: "point",
96941
- numPoints: points
96942
- }
96943
- });
96944
- }
96945
- })), ((_this$props$correct3 = this.props.correct) == null ? void 0 : _this$props$correct3.type) === "angle" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
96946
- style: styles$a.row
96947
- }, /*#__PURE__*/React.createElement(Checkbox$1, {
96948
- label: /*#__PURE__*/React.createElement(LabelSmall, null, "Show angle measures"),
96949
- checked:
96950
- // Don't show indeterminate checkbox state
96951
- !!((_this$props$correct4 = this.props.correct) != null && _this$props$correct4.showAngles),
96952
- onChange: newValue => {
96953
- var _this$props$graph4;
96954
- if (((_this$props$graph4 = this.props.graph) == null ? void 0 : _this$props$graph4.type) === "angle") {
96955
- invariant(this.props.correct.type === "angle", `Expected graph type to be angle, but got ${this.props.correct.type}`);
96870
+ return /*#__PURE__*/React.createElement(Id, null, graphId => {
96871
+ var _this$props$graph$typ, _this$props$graph3, _this$props$fullGraph, _this$props$fullGraph2, _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$correct12, _this$props$correct13, _this$props$correct14, _this$props$graph12;
96872
+ return /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(LabeledRow, {
96873
+ label: "Answer type:"
96874
+ }, /*#__PURE__*/React.createElement(GraphTypeSelector, {
96875
+ graphType: (_this$props$graph$typ = (_this$props$graph3 = this.props.graph) == null ? void 0 : _this$props$graph3.type) != null ? _this$props$graph$typ : InteractiveGraph.defaultProps.graph.type
96876
+ // TODO(LEMS-2656): remove TS suppression
96877
+ ,
96878
+ onChange: type => {
96956
96879
  this.props.onChange({
96957
- correct: _extends({}, this.props.correct, {
96958
- showAngles: newValue
96959
- }),
96960
- graph: _extends({}, this.props.graph, {
96961
- showAngles: newValue
96962
- })
96880
+ graph: {
96881
+ type
96882
+ },
96883
+ correct: {
96884
+ type
96885
+ }
96963
96886
  });
96964
96887
  }
96965
- }
96966
- }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Displays the interior angle measures."))), /*#__PURE__*/React.createElement(View, {
96967
- style: styles$a.row
96968
- }, /*#__PURE__*/React.createElement(Checkbox$1, {
96969
- label: /*#__PURE__*/React.createElement(LabelSmall, null, "Allow reflex angles"),
96970
- checked:
96971
- // Don't show indeterminate checkbox state
96972
- !!((_this$props$correct5 = this.props.correct) != null && _this$props$correct5.allowReflexAngles),
96973
- onChange: newValue => {
96974
- var _this$props$graph5, _this$props$graph6;
96975
- invariant(this.props.correct.type === "angle", `Expected graph type to be angle, but got ${this.props.correct.type}`);
96976
- invariant(((_this$props$graph5 = this.props.graph) == null ? void 0 : _this$props$graph5.type) === "angle", `Expected graph type to be angle, but got ${(_this$props$graph6 = this.props.graph) == null ? void 0 : _this$props$graph6.type}`);
96977
- const update = {
96978
- allowReflexAngles: newValue
96979
- };
96980
- this.props.onChange({
96981
- correct: _extends({}, this.props.correct, update),
96982
- graph: _extends({}, this.props.graph, update)
96983
- });
96984
- }
96985
- }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Allow students to be able to create reflex angles.")))), ((_this$props$correct6 = this.props.correct) == null ? void 0 : _this$props$correct6.type) === "polygon" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LabeledRow, {
96986
- label: "Number of sides:"
96987
- }, /*#__PURE__*/React.createElement(SingleSelect, {
96988
- key: "polygon-select",
96989
- selectedValue: (_this$props$correct7 = this.props.correct) != null && _this$props$correct7.numSides ? `${this.props.correct.numSides}` : "3",
96990
- placeholder: "",
96991
- onChange: newValue => {
96992
- var _this$props$graph7;
96993
- invariant(((_this$props$graph7 = this.props.graph) == null ? void 0 : _this$props$graph7.type) === "polygon");
96994
- const updates = {
96995
- numSides: parsePointCount(newValue),
96996
- coords: null,
96997
- // reset the snap for UNLIMITED, which
96998
- // only supports "grid"
96999
- // From: D6578
97000
- snapTo: "grid"
97001
- };
97002
- this.props.onChange({
97003
- correct: _extends({}, this.props.correct, updates),
97004
- graph: _extends({}, this.props.graph, updates)
97005
- });
97006
- },
97007
- style: styles$a.singleSelectShort
97008
- }, [...POLYGON_SIDES, /*#__PURE__*/React.createElement(OptionItem, {
97009
- key: "unlimited",
97010
- value: "unlimited",
97011
- label: "unlimited sides"
97012
- })])), /*#__PURE__*/React.createElement(LabeledRow, {
97013
- label: "Snap to:"
97014
- }, /*#__PURE__*/React.createElement(SingleSelect, {
97015
- selectedValue: ((_this$props$correct8 = this.props.correct) == null ? void 0 : _this$props$correct8.snapTo) || "grid"
97016
- // Never uses placeholder, always has value
97017
- ,
97018
- placeholder: "",
97019
- onChange: newValue => {
97020
- var _this$props$graph8, _this$props$graph9;
97021
- invariant(this.props.correct.type === "polygon", `Expected correct answer type to be polygon, but got ${this.props.correct.type}`);
97022
- invariant(((_this$props$graph8 = this.props.graph) == null ? void 0 : _this$props$graph8.type) === "polygon", `Expected graph type to be polygon, but got ${(_this$props$graph9 = this.props.graph) == null ? void 0 : _this$props$graph9.type}`);
97023
- const updates = {
97024
- snapTo: newValue,
97025
- coords: null
97026
- };
97027
- this.props.onChange({
97028
- correct: _extends({}, this.props.correct, updates),
97029
- graph: _extends({}, this.props.graph, updates)
97030
- });
97031
- },
97032
- style: styles$a.singleSelectShort
97033
- }, /*#__PURE__*/React.createElement(OptionItem, {
97034
- value: "grid",
97035
- label: "grid"
97036
- }), ((_this$props$correct9 = this.props.correct) == null ? void 0 : _this$props$correct9.numSides) !== "unlimited" && /*#__PURE__*/React.createElement(OptionItem, {
97037
- value: "angles",
97038
- label: "interior angles"
97039
- }), ((_this$props$correct10 = this.props.correct) == null ? void 0 : _this$props$correct10.numSides) !== "unlimited" && /*#__PURE__*/React.createElement(OptionItem, {
97040
- value: "sides",
97041
- label: "side measures"
97042
- })), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "These options affect the movement of the vertex points. The grid option will guide the points to the nearest half step along the grid."), /*#__PURE__*/React.createElement("p", null, "The interior angle and side measure options guide the points to the nearest whole angle or side measure respectively."))), /*#__PURE__*/React.createElement(View, {
97043
- style: styles$a.row
97044
- }, /*#__PURE__*/React.createElement(Checkbox$1, {
97045
- label: /*#__PURE__*/React.createElement(LabelSmall, null, "Show angle measures"),
97046
- checked:
97047
- // Don't show indeterminate checkbox state
97048
- !!((_this$props$correct11 = this.props.correct) != null && _this$props$correct11.showAngles),
97049
- onChange: () => {
97050
- var _this$props$graph10;
97051
- if (((_this$props$graph10 = this.props.graph) == null ? void 0 : _this$props$graph10.type) === "polygon") {
97052
- invariant(this.props.correct.type === "polygon", `Expected graph type to be polygon, but got ${this.props.correct.type}`);
96888
+ })), /*#__PURE__*/React.createElement(InteractiveGraphDescription, {
96889
+ ariaLabelValue: (_this$props$fullGraph = this.props.fullGraphAriaLabel) != null ? _this$props$fullGraph : "",
96890
+ ariaDescriptionValue: (_this$props$fullGraph2 = this.props.fullGraphAriaDescription) != null ? _this$props$fullGraph2 : "",
96891
+ onChange: this.props.onChange
96892
+ }), /*#__PURE__*/React.createElement(InteractiveGraphCorrectAnswer, {
96893
+ id: graphId,
96894
+ equationString: equationString
96895
+ }, graph), ((_this$props$correct = this.props.correct) == null ? void 0 : _this$props$correct.type) === "point" && /*#__PURE__*/React.createElement(LabeledRow, {
96896
+ label: "Number of Points:"
96897
+ }, /*#__PURE__*/React.createElement(GraphPointsCountSelector, {
96898
+ numPoints: (_this$props$correct2 = this.props.correct) == null ? void 0 : _this$props$correct2.numPoints,
96899
+ onChange: points => {
97053
96900
  this.props.onChange({
97054
- correct: _extends({}, this.props.correct, {
97055
- showAngles: !this.props.correct.showAngles
97056
- }),
97057
- graph: _extends({}, this.props.graph, {
97058
- showAngles: !this.props.graph.showAngles
97059
- })
96901
+ correct: {
96902
+ type: "point",
96903
+ numPoints: points
96904
+ },
96905
+ graph: {
96906
+ type: "point",
96907
+ numPoints: points
96908
+ }
97060
96909
  });
97061
96910
  }
97062
- }
97063
- }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Displays the interior angle measures."))), /*#__PURE__*/React.createElement(View, {
97064
- style: styles$a.row
97065
- }, /*#__PURE__*/React.createElement(Checkbox$1, {
97066
- label: /*#__PURE__*/React.createElement(LabelSmall, null, "Show side measures"),
97067
- checked:
97068
- // Don't show indeterminate checkbox state
97069
- !!((_this$props$correct12 = this.props.correct) != null && _this$props$correct12.showSides),
97070
- onChange: () => {
97071
- var _this$props$graph11;
97072
- if (((_this$props$graph11 = this.props.graph) == null ? void 0 : _this$props$graph11.type) === "polygon" && this.props.correct.type === "polygon") {
96911
+ })), ((_this$props$correct3 = this.props.correct) == null ? void 0 : _this$props$correct3.type) === "angle" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
96912
+ style: styles$a.row
96913
+ }, /*#__PURE__*/React.createElement(Checkbox$1, {
96914
+ label: /*#__PURE__*/React.createElement(LabelSmall, null, "Show angle measures"),
96915
+ checked:
96916
+ // Don't show indeterminate checkbox state
96917
+ !!((_this$props$correct4 = this.props.correct) != null && _this$props$correct4.showAngles),
96918
+ onChange: newValue => {
96919
+ var _this$props$graph4;
96920
+ if (((_this$props$graph4 = this.props.graph) == null ? void 0 : _this$props$graph4.type) === "angle") {
96921
+ invariant(this.props.correct.type === "angle", `Expected graph type to be angle, but got ${this.props.correct.type}`);
96922
+ this.props.onChange({
96923
+ correct: _extends({}, this.props.correct, {
96924
+ showAngles: newValue
96925
+ }),
96926
+ graph: _extends({}, this.props.graph, {
96927
+ showAngles: newValue
96928
+ })
96929
+ });
96930
+ }
96931
+ }
96932
+ }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Displays the interior angle measures."))), /*#__PURE__*/React.createElement(View, {
96933
+ style: styles$a.row
96934
+ }, /*#__PURE__*/React.createElement(Checkbox$1, {
96935
+ label: /*#__PURE__*/React.createElement(LabelSmall, null, "Allow reflex angles"),
96936
+ checked:
96937
+ // Don't show indeterminate checkbox state
96938
+ !!((_this$props$correct5 = this.props.correct) != null && _this$props$correct5.allowReflexAngles),
96939
+ onChange: newValue => {
96940
+ var _this$props$graph5, _this$props$graph6;
96941
+ invariant(this.props.correct.type === "angle", `Expected graph type to be angle, but got ${this.props.correct.type}`);
96942
+ invariant(((_this$props$graph5 = this.props.graph) == null ? void 0 : _this$props$graph5.type) === "angle", `Expected graph type to be angle, but got ${(_this$props$graph6 = this.props.graph) == null ? void 0 : _this$props$graph6.type}`);
96943
+ const update = {
96944
+ allowReflexAngles: newValue
96945
+ };
97073
96946
  this.props.onChange({
97074
- correct: _extends({}, this.props.correct, {
97075
- showSides: !this.props.correct.showSides
97076
- }),
97077
- graph: _extends({}, this.props.graph, {
97078
- showSides: !this.props.graph.showSides
97079
- })
96947
+ correct: _extends({}, this.props.correct, update),
96948
+ graph: _extends({}, this.props.graph, update)
97080
96949
  });
97081
96950
  }
97082
- }
97083
- }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Displays the side lengths.")))), ((_this$props$correct13 = this.props.correct) == null ? void 0 : _this$props$correct13.type) === "segment" && /*#__PURE__*/React.createElement(LabeledRow, {
97084
- label: "Number of segments:"
97085
- }, /*#__PURE__*/React.createElement(SegmentCountSelector, {
97086
- numSegments: (_this$props$correct14 = this.props.correct) == null ? void 0 : _this$props$correct14.numSegments,
97087
- onChange: sides => {
97088
- this.props.onChange({
97089
- correct: {
97090
- type: "segment",
97091
- numSegments: sides,
96951
+ }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Allow students to be able to create reflex angles.")))), ((_this$props$correct6 = this.props.correct) == null ? void 0 : _this$props$correct6.type) === "polygon" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LabeledRow, {
96952
+ label: "Number of sides:"
96953
+ }, /*#__PURE__*/React.createElement(SingleSelect, {
96954
+ key: "polygon-select",
96955
+ selectedValue: (_this$props$correct7 = this.props.correct) != null && _this$props$correct7.numSides ? `${this.props.correct.numSides}` : "3",
96956
+ placeholder: "",
96957
+ onChange: newValue => {
96958
+ var _this$props$graph7;
96959
+ invariant(((_this$props$graph7 = this.props.graph) == null ? void 0 : _this$props$graph7.type) === "polygon");
96960
+ const updates = {
96961
+ numSides: parsePointCount(newValue),
96962
+ coords: null,
96963
+ // reset the snap for UNLIMITED, which
96964
+ // only supports "grid"
96965
+ // From: D6578
96966
+ snapTo: "grid"
96967
+ };
96968
+ this.props.onChange({
96969
+ correct: _extends({}, this.props.correct, updates),
96970
+ graph: _extends({}, this.props.graph, updates)
96971
+ });
96972
+ },
96973
+ style: styles$a.singleSelectShort
96974
+ }, [...POLYGON_SIDES, /*#__PURE__*/React.createElement(OptionItem, {
96975
+ key: "unlimited",
96976
+ value: "unlimited",
96977
+ label: "unlimited sides"
96978
+ })])), /*#__PURE__*/React.createElement(LabeledRow, {
96979
+ label: "Snap to:"
96980
+ }, /*#__PURE__*/React.createElement(SingleSelect, {
96981
+ selectedValue: ((_this$props$correct8 = this.props.correct) == null ? void 0 : _this$props$correct8.snapTo) || "grid"
96982
+ // Never uses placeholder, always has value
96983
+ ,
96984
+ placeholder: "",
96985
+ onChange: newValue => {
96986
+ var _this$props$graph8, _this$props$graph9;
96987
+ invariant(this.props.correct.type === "polygon", `Expected correct answer type to be polygon, but got ${this.props.correct.type}`);
96988
+ invariant(((_this$props$graph8 = this.props.graph) == null ? void 0 : _this$props$graph8.type) === "polygon", `Expected graph type to be polygon, but got ${(_this$props$graph9 = this.props.graph) == null ? void 0 : _this$props$graph9.type}`);
96989
+ const updates = {
96990
+ snapTo: newValue,
97092
96991
  coords: null
97093
- },
97094
- graph: {
97095
- type: "segment",
97096
- numSegments: sides
96992
+ };
96993
+ this.props.onChange({
96994
+ correct: _extends({}, this.props.correct, updates),
96995
+ graph: _extends({}, this.props.graph, updates)
96996
+ });
96997
+ },
96998
+ style: styles$a.singleSelectShort
96999
+ }, /*#__PURE__*/React.createElement(OptionItem, {
97000
+ value: "grid",
97001
+ label: "grid"
97002
+ }), ((_this$props$correct9 = this.props.correct) == null ? void 0 : _this$props$correct9.numSides) !== "unlimited" && /*#__PURE__*/React.createElement(OptionItem, {
97003
+ value: "angles",
97004
+ label: "interior angles"
97005
+ }), ((_this$props$correct10 = this.props.correct) == null ? void 0 : _this$props$correct10.numSides) !== "unlimited" && /*#__PURE__*/React.createElement(OptionItem, {
97006
+ value: "sides",
97007
+ label: "side measures"
97008
+ })), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "These options affect the movement of the vertex points. The grid option will guide the points to the nearest half step along the grid."), /*#__PURE__*/React.createElement("p", null, "The interior angle and side measure options guide the points to the nearest whole angle or side measure respectively."))), /*#__PURE__*/React.createElement(View, {
97009
+ style: styles$a.row
97010
+ }, /*#__PURE__*/React.createElement(Checkbox$1, {
97011
+ label: /*#__PURE__*/React.createElement(LabelSmall, null, "Show angle measures"),
97012
+ checked:
97013
+ // Don't show indeterminate checkbox state
97014
+ !!((_this$props$correct11 = this.props.correct) != null && _this$props$correct11.showAngles),
97015
+ onChange: () => {
97016
+ var _this$props$graph10;
97017
+ if (((_this$props$graph10 = this.props.graph) == null ? void 0 : _this$props$graph10.type) === "polygon") {
97018
+ invariant(this.props.correct.type === "polygon", `Expected graph type to be polygon, but got ${this.props.correct.type}`);
97019
+ this.props.onChange({
97020
+ correct: _extends({}, this.props.correct, {
97021
+ showAngles: !this.props.correct.showAngles
97022
+ }),
97023
+ graph: _extends({}, this.props.graph, {
97024
+ showAngles: !this.props.graph.showAngles
97025
+ })
97026
+ });
97097
97027
  }
97098
- });
97099
- }
97100
- })), ((_this$props$graph12 = this.props.graph) == null ? void 0 : _this$props$graph12.type) && shouldShowStartCoordsUI(this.props.graph, this.props.static) && /*#__PURE__*/React.createElement(StartCoordsSettings, _extends({}, this.props.graph, {
97101
- range: this.props.range,
97102
- step: this.props.step,
97103
- onChange: this.changeStartCoords
97104
- })), /*#__PURE__*/React.createElement(InteractiveGraphSRTree, {
97105
- correct: this.props.correct,
97106
- fullGraphAriaLabel: this.props.fullGraphAriaLabel,
97107
- fullGraphAriaDescription: this.props.fullGraphAriaDescription,
97108
- lockedFigures: this.props.lockedFigures
97109
- }), /*#__PURE__*/React.createElement(InteractiveGraphSettings, {
97110
- box: getInteractiveBoxFromSizeClass(sizeClass),
97111
- range: this.props.range,
97112
- labels: this.props.labels,
97113
- step: this.props.step,
97114
- gridStep: gridStep,
97115
- snapStep: snapStep,
97116
- valid: this.props.valid,
97117
- backgroundImage: this.props.backgroundImage,
97118
- markings: this.props.markings,
97119
- showProtractor: this.props.showProtractor,
97120
- showTooltips: this.props.showTooltips,
97121
- onChange: this.props.onChange
97122
- }), this.props.correct.type === "polygon" && /*#__PURE__*/React.createElement(LabeledRow, {
97123
- label: "Student answer must"
97124
- }, /*#__PURE__*/React.createElement(SingleSelect, {
97125
- selectedValue: this.props.correct.match || "exact",
97126
- onChange: newValue => {
97127
- invariant(this.props.correct.type === "polygon", `Expected graph type to be polygon, but got ${this.props.correct.type}`);
97128
- const correct = _extends({}, this.props.correct, {
97129
- // TODO(benchristel): this cast is necessary
97130
- // because "exact" is not actually a valid
97131
- // value for `match`; a value of undefined
97132
- // means exact matching. The code happens
97133
- // to work because "exact" falls through
97134
- // to the correct else branch when scoring
97135
- match: newValue
97136
- });
97137
- this.props.onChange({
97138
- correct
97139
- });
97140
- }
97141
- // Never uses placeholder, always has value
97142
- ,
97143
- placeholder: "",
97144
- style: styles$a.singleSelectShort
97145
- }, /*#__PURE__*/React.createElement(OptionItem, {
97146
- value: "exact",
97147
- label: "match exactly"
97148
- }), /*#__PURE__*/React.createElement(OptionItem, {
97149
- value: "congruent",
97150
- label: "be congruent"
97151
- }), /*#__PURE__*/React.createElement(OptionItem, {
97152
- value: "approx",
97153
- label: "be approximately congruent"
97154
- }), /*#__PURE__*/React.createElement(OptionItem, {
97155
- value: "similar",
97156
- label: "be similar"
97157
- })), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("ul", null, /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Match Exactly:"), " Match exactly in size, orientation, and location on the grid even if it is not shown in the background.")), /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Be Congruent:"), " Be congruent in size and shape, but can be located anywhere on the grid.")), /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Be Approximately Congruent:"), " Be exactly similar, and congruent in size and shape to within 0.1 units, but can be located anywhere on the grid.", " ", /*#__PURE__*/React.createElement("em", null, "Use this with snapping to angle measure."))), /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Be Similar:"), " Be similar with matching interior angles, and side measures that are matching or a multiple of the correct side measures. The figure can be located anywhere on the grid."))))), this.props.correct.type === "angle" && /*#__PURE__*/React.createElement(LabeledRow, {
97158
- label: "Student answer must"
97159
- }, /*#__PURE__*/React.createElement(SingleSelect, {
97160
- selectedValue: this.props.correct.match || "exact",
97161
- onChange: newValue => {
97162
- this.props.onChange({
97163
- correct: _extends({}, this.props.correct, {
97028
+ }
97029
+ }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Displays the interior angle measures."))), /*#__PURE__*/React.createElement(View, {
97030
+ style: styles$a.row
97031
+ }, /*#__PURE__*/React.createElement(Checkbox$1, {
97032
+ label: /*#__PURE__*/React.createElement(LabelSmall, null, "Show side measures"),
97033
+ checked:
97034
+ // Don't show indeterminate checkbox state
97035
+ !!((_this$props$correct12 = this.props.correct) != null && _this$props$correct12.showSides),
97036
+ onChange: () => {
97037
+ var _this$props$graph11;
97038
+ if (((_this$props$graph11 = this.props.graph) == null ? void 0 : _this$props$graph11.type) === "polygon" && this.props.correct.type === "polygon") {
97039
+ this.props.onChange({
97040
+ correct: _extends({}, this.props.correct, {
97041
+ showSides: !this.props.correct.showSides
97042
+ }),
97043
+ graph: _extends({}, this.props.graph, {
97044
+ showSides: !this.props.graph.showSides
97045
+ })
97046
+ });
97047
+ }
97048
+ }
97049
+ }), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Displays the side lengths.")))), ((_this$props$correct13 = this.props.correct) == null ? void 0 : _this$props$correct13.type) === "segment" && /*#__PURE__*/React.createElement(LabeledRow, {
97050
+ label: "Number of segments:"
97051
+ }, /*#__PURE__*/React.createElement(SegmentCountSelector, {
97052
+ numSegments: (_this$props$correct14 = this.props.correct) == null ? void 0 : _this$props$correct14.numSegments,
97053
+ onChange: sides => {
97054
+ this.props.onChange({
97055
+ correct: {
97056
+ type: "segment",
97057
+ numSegments: sides,
97058
+ coords: null
97059
+ },
97060
+ graph: {
97061
+ type: "segment",
97062
+ numSegments: sides
97063
+ }
97064
+ });
97065
+ }
97066
+ })), ((_this$props$graph12 = this.props.graph) == null ? void 0 : _this$props$graph12.type) && shouldShowStartCoordsUI(this.props.graph, this.props.static) && /*#__PURE__*/React.createElement(StartCoordsSettings, _extends({}, this.props.graph, {
97067
+ range: this.props.range,
97068
+ step: this.props.step,
97069
+ onChange: this.changeStartCoords
97070
+ })), /*#__PURE__*/React.createElement(InteractiveGraphSRTree, {
97071
+ graphId: graphId,
97072
+ correct: this.props.correct,
97073
+ fullGraphAriaLabel: this.props.fullGraphAriaLabel,
97074
+ fullGraphAriaDescription: this.props.fullGraphAriaDescription,
97075
+ lockedFigures: this.props.lockedFigures
97076
+ }), /*#__PURE__*/React.createElement(InteractiveGraphSettings, {
97077
+ box: getInteractiveBoxFromSizeClass(sizeClass),
97078
+ range: this.props.range,
97079
+ labels: this.props.labels,
97080
+ step: this.props.step,
97081
+ gridStep: gridStep,
97082
+ snapStep: snapStep,
97083
+ valid: this.props.valid,
97084
+ backgroundImage: this.props.backgroundImage,
97085
+ markings: this.props.markings,
97086
+ showProtractor: this.props.showProtractor,
97087
+ showTooltips: this.props.showTooltips,
97088
+ onChange: this.props.onChange
97089
+ }), this.props.correct.type === "polygon" && /*#__PURE__*/React.createElement(LabeledRow, {
97090
+ label: "Student answer must"
97091
+ }, /*#__PURE__*/React.createElement(SingleSelect, {
97092
+ selectedValue: this.props.correct.match || "exact",
97093
+ onChange: newValue => {
97094
+ invariant(this.props.correct.type === "polygon", `Expected graph type to be polygon, but got ${this.props.correct.type}`);
97095
+ const correct = _extends({}, this.props.correct, {
97164
97096
  // TODO(benchristel): this cast is necessary
97165
97097
  // because "exact" is not actually a valid
97166
97098
  // value for `match`; a value of undefined
@@ -97168,26 +97100,59 @@ class InteractiveGraphEditor extends React.Component {
97168
97100
  // to work because "exact" falls through
97169
97101
  // to the correct else branch when scoring
97170
97102
  match: newValue
97171
- })
97172
- });
97173
- }
97174
- // Never uses placeholder, always has value
97175
- ,
97176
- placeholder: "",
97177
- style: styles$a.singleSelectShort
97178
- }, /*#__PURE__*/React.createElement(OptionItem, {
97179
- value: "exact",
97180
- label: "match exactly"
97181
- }), /*#__PURE__*/React.createElement(OptionItem, {
97182
- value: "congruent",
97183
- label: "be congruent"
97184
- })), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Congruency requires only that the angle measures are the same. An exact match implies congruency, but also requires that the angles have the same orientation and that the vertices are in the same position."))),
97185
- // Only show the "Add locked figure" dropdown if the graph
97186
- // is using Mafs.
97187
- this.props.graph && ((_this$props$apiOption3 = this.props.apiOptions) == null || (_this$props$apiOption3 = _this$props$apiOption3.flags) == null || (_this$props$apiOption3 = _this$props$apiOption3.mafs) == null ? void 0 : _this$props$apiOption3[this.props.graph.type]) && /*#__PURE__*/React.createElement(LockedFiguresSection, {
97188
- figures: this.props.lockedFigures,
97189
- onChange: this.props.onChange
97190
- }));
97103
+ });
97104
+ this.props.onChange({
97105
+ correct
97106
+ });
97107
+ }
97108
+ // Never uses placeholder, always has value
97109
+ ,
97110
+ placeholder: "",
97111
+ style: styles$a.singleSelectShort
97112
+ }, /*#__PURE__*/React.createElement(OptionItem, {
97113
+ value: "exact",
97114
+ label: "match exactly"
97115
+ }), /*#__PURE__*/React.createElement(OptionItem, {
97116
+ value: "congruent",
97117
+ label: "be congruent"
97118
+ }), /*#__PURE__*/React.createElement(OptionItem, {
97119
+ value: "approx",
97120
+ label: "be approximately congruent"
97121
+ }), /*#__PURE__*/React.createElement(OptionItem, {
97122
+ value: "similar",
97123
+ label: "be similar"
97124
+ })), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("ul", null, /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Match Exactly:"), " Match exactly in size, orientation, and location on the grid even if it is not shown in the background.")), /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Be Congruent:"), " Be congruent in size and shape, but can be located anywhere on the grid.")), /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Be Approximately Congruent:"), " ", "Be exactly similar, and congruent in size and shape to within 0.1 units, but can be located anywhere on the grid.", " ", /*#__PURE__*/React.createElement("em", null, "Use this with snapping to angle measure."))), /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("b", null, "Be Similar:"), " Be similar with matching interior angles, and side measures that are matching or a multiple of the correct side measures. The figure can be located anywhere on the grid."))))), this.props.correct.type === "angle" && /*#__PURE__*/React.createElement(LabeledRow, {
97125
+ label: "Student answer must"
97126
+ }, /*#__PURE__*/React.createElement(SingleSelect, {
97127
+ selectedValue: this.props.correct.match || "exact",
97128
+ onChange: newValue => {
97129
+ this.props.onChange({
97130
+ correct: _extends({}, this.props.correct, {
97131
+ // TODO(benchristel): this cast is necessary
97132
+ // because "exact" is not actually a valid
97133
+ // value for `match`; a value of undefined
97134
+ // means exact matching. The code happens
97135
+ // to work because "exact" falls through
97136
+ // to the correct else branch when scoring
97137
+ match: newValue
97138
+ })
97139
+ });
97140
+ }
97141
+ // Never uses placeholder, always has value
97142
+ ,
97143
+ placeholder: "",
97144
+ style: styles$a.singleSelectShort
97145
+ }, /*#__PURE__*/React.createElement(OptionItem, {
97146
+ value: "exact",
97147
+ label: "match exactly"
97148
+ }), /*#__PURE__*/React.createElement(OptionItem, {
97149
+ value: "congruent",
97150
+ label: "be congruent"
97151
+ })), /*#__PURE__*/React.createElement(InfoTip$b, null, /*#__PURE__*/React.createElement("p", null, "Congruency requires only that the angle measures are the same. An exact match implies congruency, but also requires that the angles have the same orientation and that the vertices are in the same position."))), /*#__PURE__*/React.createElement(LockedFiguresSection, {
97152
+ figures: this.props.lockedFigures,
97153
+ onChange: this.props.onChange
97154
+ }));
97155
+ });
97191
97156
  }
97192
97157
  }
97193
97158
 
@@ -98015,6 +97980,47 @@ const styles$5 = StyleSheet.create({
98015
97980
  }
98016
97981
  });
98017
97982
 
97983
+ function focusWithChromeStickyFocusBugWorkaround(element) {
97984
+ // NOTE(marksandstrom) Chrome sticky focus bug.
97985
+ //
97986
+ // There is a bug in Chrome related to sticky positioning and
97987
+ // focus: When a child of an element with sticky positioning is
97988
+ // focused with the focus() method, the scrollable area
97989
+ // containing that element will scroll to the top (even though
97990
+ // the element is already visble on the page). For a dropdown
97991
+ // this means that the area will be scrolled to the top when
97992
+ // the user interacts with the dropdown (since we actively
97993
+ // manage dropdown header and option focus for keyboard users).
97994
+ //
97995
+ // To work around this bug the `preventScroll` focus option is
97996
+ // used.
97997
+ //
97998
+ // Using `focusOptions` is an experimental browser feature
97999
+ // "that should not be used in production code". However, since
98000
+ // Chrome is the only browser we support that exhibits this
98001
+ // buggy behavior and using `focusOptions` works around the
98002
+ // bug, it is perfectly reasonable to use the feature in this
98003
+ // case. We are not relying on the effect of the
98004
+ // `preventScroll` option otherwise.
98005
+ //
98006
+ // focusOptions documentation:
98007
+ //
98008
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
98009
+ //
98010
+ // Note that there could be cases where we want default focus() behavior.
98011
+ // One that comes to mind is a dropdown with a long list of options that
98012
+ // might be rendered off screen when opened. With this workaround the
98013
+ // selected option would not be scrolled into view if the option is near
98014
+ // the end of the list. We're not aware of any uses of the dropdown where
98015
+ // this is an issue, however, so there isn't currently a way to out of the
98016
+ // `preventScroll` behavior.
98017
+
98018
+ // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
98019
+ element.focus({
98020
+ preventScroll: true
98021
+ });
98022
+ }
98023
+
98018
98024
  const {
98019
98025
  Icon
98020
98026
  } = components;