@khanacademy/perseus-editor 2.15.6 → 2.16.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/components/blur-input.d.ts +2 -0
  3. package/dist/components/widget-editor.d.ts +1 -1
  4. package/dist/editor-page.d.ts +4 -1
  5. package/dist/editor.d.ts +3 -1
  6. package/dist/es/index.js +170 -260
  7. package/dist/es/index.js.map +1 -1
  8. package/dist/hint-editor.d.ts +2 -0
  9. package/dist/iframe-content-renderer.d.ts +1 -0
  10. package/dist/index.js +137 -256
  11. package/dist/index.js.map +1 -1
  12. package/dist/item-editor.d.ts +6 -0
  13. package/dist/widgets/example-widget-editor.d.ts +1 -0
  14. package/dist/widgets/example-widget.d.ts +7 -0
  15. package/dist/widgets/graded-group-editor.d.ts +3 -0
  16. package/dist/widgets/group-editor.d.ts +2 -0
  17. package/dist/widgets/input-number-editor.d.ts +2 -0
  18. package/dist/widgets/simple-markdown-tester-editor.d.ts +7 -0
  19. package/dist/widgets/table-editor.d.ts +2 -0
  20. package/package.json +13 -13
  21. package/src/components/__tests__/blur-input.test.tsx +67 -0
  22. package/src/components/blur-input.tsx +7 -0
  23. package/src/editor-page.tsx +11 -25
  24. package/src/editor.tsx +37 -65
  25. package/src/hint-editor.tsx +15 -27
  26. package/src/iframe-content-renderer.tsx +19 -20
  27. package/src/item-editor.tsx +11 -18
  28. package/src/util/register-all-widgets-and-editors-for-testing.test.ts +3 -1
  29. package/src/widgets/example-widget-editor.tsx +4 -5
  30. package/src/widgets/example-widget.tsx +8 -10
  31. package/src/widgets/graded-group-editor.tsx +9 -19
  32. package/src/widgets/group-editor.tsx +5 -8
  33. package/src/widgets/input-number-editor.tsx +4 -5
  34. package/src/widgets/simple-markdown-tester-editor.tsx +4 -5
  35. package/src/widgets/table-editor.tsx +4 -5
  36. package/tsconfig-build.tsbuildinfo +1 -1
package/dist/index.js CHANGED
@@ -12,11 +12,11 @@ var Clickable = require('@khanacademy/wonder-blocks-clickable');
12
12
  var Color = require('@khanacademy/wonder-blocks-color');
13
13
  var aphrodite = require('aphrodite');
14
14
  var $ = require('jquery');
15
- var ReactDOM = require('react-dom');
16
15
  var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
17
16
  var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
18
17
  var caretRight = require('@phosphor-icons/core/bold/caret-right-bold.svg');
19
18
  var classNames = require('classnames');
19
+ var ReactDOM = require('react-dom');
20
20
  var kmath = require('@khanacademy/kmath');
21
21
  var KAS = require('@khanacademy/kas');
22
22
  var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
@@ -53,10 +53,9 @@ var createReactClass__default = /*#__PURE__*/_interopDefaultLegacy(createReactCl
53
53
  var Clickable__default = /*#__PURE__*/_interopDefaultLegacy(Clickable);
54
54
  var Color__default = /*#__PURE__*/_interopDefaultLegacy(Color);
55
55
  var $__default = /*#__PURE__*/_interopDefaultLegacy($);
56
- var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
57
- var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
58
56
  var caretRight__default = /*#__PURE__*/_interopDefaultLegacy(caretRight);
59
57
  var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
58
+ var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
60
59
  var KAS__namespace = /*#__PURE__*/_interopNamespace(KAS);
61
60
  var Spacing__default = /*#__PURE__*/_interopDefaultLegacy(Spacing);
62
61
  var Typography__namespace = /*#__PURE__*/_interopNamespace(Typography);
@@ -65,7 +64,7 @@ var i18n__namespace = /*#__PURE__*/_interopNamespace(i18n$1);
65
64
 
66
65
  // This file is processed by a Rollup plugin (replace) to inject the production
67
66
  const libName = "@khanacademy/perseus-editor";
68
- const libVersion = "2.15.6";
67
+ const libVersion = "2.16.0";
69
68
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
70
69
 
71
70
  function _extends() {
@@ -20894,7 +20893,6 @@ const IMAGE_REGEX$1 = /!\[[^\]]*\]\(([^\s)]+)[^)]*\)/g;
20894
20893
  * ignores captures. If you don't need captures, use String::match
20895
20894
  */
20896
20895
  const allMatches = function (regex, str) {
20897
- // @ts-expect-error - TS2702 - 'RegExp' only refers to a type, but is being used as a namespace here.
20898
20896
  const result = [];
20899
20897
  // eslint-disable-next-line no-constant-condition
20900
20898
  while (true) {
@@ -20912,10 +20910,12 @@ const allMatches = function (regex, str) {
20912
20910
  * markdown.
20913
20911
  */
20914
20912
  const imageUrlsFromContent = function (content) {
20915
- return ___default["default"].map(allMatches(IMAGE_REGEX$1, content), capture => capture[1]);
20913
+ return allMatches(IMAGE_REGEX$1, content).map(capture => capture[1]);
20916
20914
  };
20917
20915
  // eslint-disable-next-line react/no-unsafe
20918
20916
  class Editor extends React__namespace.Component {
20917
+ underlay = /*#__PURE__*/React__namespace.createRef();
20918
+ textarea = /*#__PURE__*/React__namespace.createRef();
20919
20919
  static defaultProps = {
20920
20920
  content: "",
20921
20921
  placeholder: "",
@@ -20940,11 +20940,15 @@ class Editor extends React__namespace.Component {
20940
20940
  // this.props.onChange during that, since it calls our parent's
20941
20941
  // setState
20942
20942
  this._sizeImages(this.props);
20943
- // eslint-disable-next-line react/no-string-refs
20944
- // @ts-expect-error - TS2769 - No overload matches this call.
20945
- $__default["default"](ReactDOM__namespace.findDOMNode(this.refs.textarea))
20943
+ // NOTE(jeremy): We use the non-null assertion here (!) because refs
20944
+ // are guaranteed to be up-to-date before componentDidMount or
20945
+ // componentDidUpdate fires.
20946
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20947
+ $__default["default"](this.textarea.current)
20946
20948
  // @ts-expect-error - TS2339 - Property 'on' does not exist on type 'JQueryStatic'.
20947
- .on("copy cut", this._maybeCopyWidgets).on("paste", this._maybePasteWidgets);
20949
+ .on("copy cut", this._maybeCopyWidgets)
20950
+ // @ts-expect-error - TS2769 - No overload matches this call.
20951
+ .on("paste", this._maybePasteWidgets);
20948
20952
  }
20949
20953
 
20950
20954
  // TODO(arun): This is a deprecated method, use the appropriate replacement
@@ -20957,9 +20961,7 @@ class Editor extends React__namespace.Component {
20957
20961
  }
20958
20962
  }
20959
20963
  componentDidUpdate(prevProps) {
20960
- // TODO(alpert): Maybe fix React so this isn't necessary
20961
- // eslint-disable-next-line react/no-string-refs
20962
- const textarea = ReactDOM__namespace.findDOMNode(this.refs.textarea);
20964
+ const textarea = this.textarea.current;
20963
20965
 
20964
20966
  // Slightly unorthodox method to ensure that programmatic text changes
20965
20967
  // are in the browser's undo stack.
@@ -20968,24 +20970,14 @@ class Editor extends React__namespace.Component {
20968
20970
  // will return false. However at least in Firefox setting `value` on a
20969
20971
  // textbox clears the undo stack so we don't get unexpected undo
20970
20972
  // behavior.
20971
- if (this.lastUserValue !== null && textarea) {
20972
- /**
20973
- * TODO(somewhatabstract, JIRA-XXXX):
20974
- * textarea should be refined with an instanceof check to
20975
- * HTMLTextAreaElement so that these props are available.
20976
- */
20977
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
20973
+ if (this.lastUserValue != null && textarea) {
20978
20974
  textarea.focus();
20979
- // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'Element | Text'.
20980
20975
  textarea.value = this.lastUserValue;
20981
- // @ts-expect-error - TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
20982
20976
  textarea.selectionStart = 0;
20983
- // @ts-expect-error - TS2339 - Property 'select' does not exist on type 'Element | Text'.
20984
- textarea.select(0, prevProps.content.length);
20977
+ textarea.setSelectionRange(0, prevProps.content.length);
20985
20978
  if (document.execCommand("insertText", false, this.props.content) === false) {
20986
20979
  // This command is not implemented. Fall back to setting `value`
20987
20980
  // directly.
20988
- // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'Element | Text'.
20989
20981
  textarea.value = this.props.content;
20990
20982
  }
20991
20983
  this.lastUserValue = null;
@@ -21032,12 +21024,10 @@ class Editor extends React__namespace.Component {
21032
21024
  }, cb, silent);
21033
21025
  };
21034
21026
  _handleWidgetEditorRemove = id => {
21035
- // eslint-disable-next-line react/no-string-refs
21036
- const textarea = this.refs.textarea;
21027
+ const textarea = this.textarea.current;
21037
21028
  const re = new RegExp(widgetRegExp.replace("{id}", id), "gm");
21038
- // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'ReactInstance'.
21039
21029
  this.props.onChange({
21040
- content: textarea.value.replace(re, "")
21030
+ content: textarea?.value.replace(re, "")
21041
21031
  });
21042
21032
  };
21043
21033
 
@@ -21185,11 +21175,11 @@ class Editor extends React__namespace.Component {
21185
21175
  // Tab-completion of widgets. For example, to insert an image:
21186
21176
  // type `[[im`, then tab.
21187
21177
  if (e.key === "Tab") {
21188
- // eslint-disable-next-line react/no-string-refs
21189
- const textarea = ReactDOM__namespace.findDOMNode(this.refs.textarea);
21190
-
21191
- // findDOMNode can also return Text, but we know it's an element.
21192
- // @ts-expect-error - TS2345 - Argument of type 'Element | Text | null' is not assignable to parameter of type 'HTMLTextAreaElement'.
21178
+ // We're in an event handler attached to the textarea, so the ref
21179
+ // can't be empty/undefined! (which is why its safe to use the
21180
+ // non-null-assertion here. aka the `!` suffix)
21181
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21182
+ const textarea = this.textarea.current;
21193
21183
  const word = perseus.Util.textarea.getWordBeforeCursor(textarea);
21194
21184
  const matches = word.string.toLowerCase().match(shortcutRegexp);
21195
21185
  if (matches != null) {
@@ -21322,9 +21312,6 @@ class Editor extends React__namespace.Component {
21322
21312
  return safeWidgetMapping;
21323
21313
  };
21324
21314
  _addWidgetToContent = (oldContent, cursorRange, widgetType) => {
21325
- // eslint-disable-next-line react/no-string-refs
21326
- const textarea = ReactDOM__namespace.findDOMNode(this.refs.textarea);
21327
-
21328
21315
  // Note: we have to use _.map here instead of Array::map
21329
21316
  // because the results of a .match might be null if no
21330
21317
  // widgets were found.
@@ -21371,23 +21358,22 @@ class Editor extends React__namespace.Component {
21371
21358
  this.props.onChange({
21372
21359
  content: newContent,
21373
21360
  widgets: newWidgets
21374
- }, function () {
21375
- perseus.Util.textarea.moveCursor(
21376
- // findDOMNode can return Text but we know this is Element
21377
- // @ts-expect-error - TS2345 - Argument of type 'Element | Text | null' is not assignable to parameter of type 'HTMLTextAreaElement'.
21378
- textarea,
21361
+ }, () => {
21362
+ if (!this.textarea.current) {
21363
+ return;
21364
+ }
21365
+ perseus.Util.textarea.moveCursor(this.textarea.current,
21379
21366
  // We want to put the cursor after the widget
21380
21367
  // and after any added newlines
21381
21368
  newContent.length - postlude.length);
21382
21369
  });
21383
21370
  };
21384
21371
  _addWidget = widgetType => {
21385
- // eslint-disable-next-line react/no-string-refs
21386
- const textarea = this.refs.textarea;
21387
- this._addWidgetToContent(this.props.content,
21388
- // @ts-expect-error - TS2339 - Property 'selectionStart' does not exist on type 'ReactInstance'. | TS2339 - Property 'selectionEnd' does not exist on type 'ReactInstance'.
21389
- [textarea.selectionStart, textarea.selectionEnd], widgetType);
21390
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
21372
+ const textarea = this.textarea.current;
21373
+ if (!textarea) {
21374
+ return;
21375
+ }
21376
+ this._addWidgetToContent(this.props.content, [textarea.selectionStart, textarea.selectionEnd], widgetType);
21391
21377
  textarea.focus();
21392
21378
  };
21393
21379
  addTemplate = e => {
@@ -21441,31 +21427,16 @@ class Editor extends React__namespace.Component {
21441
21427
  return warnings;
21442
21428
  };
21443
21429
  focus = () => {
21444
- // eslint-disable-next-line react/no-string-refs
21445
- const textarea = ReactDOM__namespace.findDOMNode(this.refs.textarea);
21430
+ const textarea = this.textarea.current;
21446
21431
  if (textarea) {
21447
- /**
21448
- * TODO(somewhatabstract, JIRA-XXXX):
21449
- * textarea should be refined with an instanceof check to
21450
- * HTMLTextAreaElement so that these props are available.
21451
- */
21452
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
21453
21432
  textarea.focus();
21454
21433
  }
21455
21434
  };
21456
21435
  focusAndMoveToEnd = () => {
21457
21436
  this.focus();
21458
- // eslint-disable-next-line react/no-string-refs
21459
- const textarea = ReactDOM__namespace.findDOMNode(this.refs.textarea);
21437
+ const textarea = this.textarea.current;
21460
21438
  if (textarea) {
21461
- /**
21462
- * TODO(somewhatabstract, JIRA-XXXX):
21463
- * textarea should be refined with an instanceof check to
21464
- * HTMLTextAreaElement so that these props are available.
21465
- */
21466
- // @ts-expect-error - TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
21467
21439
  textarea.selectionStart = textarea.value.length;
21468
- // @ts-expect-error - TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
21469
21440
  textarea.selectionEnd = textarea.value.length;
21470
21441
  }
21471
21442
  };
@@ -21589,10 +21560,7 @@ class Editor extends React__namespace.Component {
21589
21560
  onChange: this._addWidget
21590
21561
  });
21591
21562
  const insertTemplateString = "Insert template\u2026";
21592
- templatesDropDown =
21593
- /*#__PURE__*/
21594
- // @ts-expect-error - TS2322 - Type '(e: SyntheticEvent<HTMLTextAreaElement, Event>) => void' is not assignable to type 'ChangeEventHandler<HTMLSelectElement>'.
21595
- React__namespace.createElement("select", {
21563
+ templatesDropDown = /*#__PURE__*/React__namespace.createElement("select", {
21596
21564
  onChange: this.addTemplate
21597
21565
  }, /*#__PURE__*/React__namespace.createElement("option", {
21598
21566
  value: ""
@@ -21631,14 +21599,11 @@ class Editor extends React__namespace.Component {
21631
21599
  key: "end"
21632
21600
  }));
21633
21601
  const completeTextarea = [/*#__PURE__*/React__namespace.createElement("div", {
21634
- className: "perseus-textarea-underlay"
21635
- // eslint-disable-next-line react/no-string-refs
21636
- ,
21637
- ref: "underlay",
21602
+ className: "perseus-textarea-underlay",
21603
+ ref: this.underlay,
21638
21604
  key: "underlay"
21639
21605
  }, underlayPieces), /*#__PURE__*/React__namespace.createElement("textarea", {
21640
- // eslint-disable-next-line react/no-string-refs
21641
- ref: "textarea",
21606
+ ref: this.textarea,
21642
21607
  key: "textarea",
21643
21608
  onChange: this.handleChange,
21644
21609
  onKeyDown: this._handleKeyDown,
@@ -21725,6 +21690,8 @@ window.addEventListener("message", event => {
21725
21690
  }
21726
21691
  });
21727
21692
  class IframeContentRenderer extends React__namespace.Component {
21693
+ container = /*#__PURE__*/React__namespace.createRef();
21694
+
21728
21695
  // @ts-expect-error - TS2564 - Property '_isMounted' has no initializer and is not definitely assigned in the constructor.
21729
21696
 
21730
21697
  // @ts-expect-error - TS2564 - Property '_lastHeight' has no initializer and is not definitely assigned in the constructor.
@@ -21743,10 +21710,8 @@ class IframeContentRenderer extends React__namespace.Component {
21743
21710
  };
21744
21711
  updateIframeHeight[this.iframeID] = height => {
21745
21712
  this._lastHeight = height;
21746
- if (this._isMounted && this.props.seamless) {
21747
- // eslint-disable-next-line react/no-string-refs
21748
- // @ts-expect-error - TS2339 - Property 'style' does not exist on type 'ReactInstance'.
21749
- this.refs.container.style.height = height + "px";
21713
+ if (this._isMounted && this.props.seamless && this.container.current) {
21714
+ this.container.current.style.height = height + "px";
21750
21715
  }
21751
21716
  };
21752
21717
  }
@@ -21754,14 +21719,12 @@ class IframeContentRenderer extends React__namespace.Component {
21754
21719
  return nextProps.datasetValue !== this.props.datasetValue || nextProps.seamless !== this.props.seamless;
21755
21720
  }
21756
21721
  componentDidUpdate(prevProps) {
21757
- if (!this.props.seamless) {
21758
- // eslint-disable-next-line react/no-string-refs
21759
- // @ts-expect-error - TS2339 - Property 'style' does not exist on type 'ReactInstance'.
21760
- this.refs.container.style.height = "100%";
21761
- } else {
21762
- // eslint-disable-next-line react/no-string-refs
21763
- // @ts-expect-error - TS2339 - Property 'style' does not exist on type 'ReactInstance'.
21764
- this.refs.container.style.height = this._lastHeight + "px";
21722
+ if (this.container.current) {
21723
+ if (!this.props.seamless) {
21724
+ this.container.current.style.height = "100%";
21725
+ } else {
21726
+ this.container.current.style.height = this._lastHeight + "px";
21727
+ }
21765
21728
  }
21766
21729
  if (prevProps.datasetValue !== this.props.datasetValue) {
21767
21730
  // Not just a change in seamless
@@ -21776,9 +21739,7 @@ class IframeContentRenderer extends React__namespace.Component {
21776
21739
  _prepareFrame() {
21777
21740
  // Don't initialize the iframe until the page has loaded
21778
21741
  if (this._frame) {
21779
- // eslint-disable-next-line react/no-string-refs
21780
- // @ts-expect-error - TS2339 - Property 'removeChild' does not exist on type 'ReactInstance'.
21781
- this.refs.container.removeChild(this._frame);
21742
+ this.container.current?.removeChild(this._frame);
21782
21743
  }
21783
21744
  const frame = document.createElement("iframe");
21784
21745
  frame.style.width = "100%";
@@ -21800,10 +21761,7 @@ class IframeContentRenderer extends React__namespace.Component {
21800
21761
  // component inside the iframe
21801
21762
  frame.dataset.lintGutter = "true";
21802
21763
  }
21803
-
21804
- // eslint-disable-next-line react/no-string-refs
21805
- // @ts-expect-error - TS2339 - Property 'appendChild' does not exist on type 'ReactInstance'.
21806
- this.refs.container.appendChild(frame);
21764
+ this.container.current?.appendChild(frame);
21807
21765
  this._frame = frame;
21808
21766
  }
21809
21767
  sendNewData(data) {
@@ -21820,9 +21778,8 @@ class IframeContentRenderer extends React__namespace.Component {
21820
21778
  }
21821
21779
  }
21822
21780
  render() {
21823
- // eslint-disable-next-line react/no-string-refs
21824
21781
  return /*#__PURE__*/React__namespace.createElement("div", {
21825
- ref: "container",
21782
+ ref: this.container,
21826
21783
  style: {
21827
21784
  width: "100%",
21828
21785
  height: "100%"
@@ -23535,35 +23492,28 @@ class HintEditor extends React__namespace.Component {
23535
23492
  showTitle: true,
23536
23493
  showRemoveButton: true
23537
23494
  };
23495
+ editor = /*#__PURE__*/React__namespace.createRef();
23538
23496
  handleChange = e => {
23539
23497
  this.props.onChange({
23540
23498
  replace: e.target.checked
23541
23499
  });
23542
23500
  };
23543
23501
  focus = () => {
23544
- // eslint-disable-next-line react/no-string-refs
23545
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
23546
- this.refs.editor.focus();
23502
+ this.editor.current?.focus();
23547
23503
  };
23548
23504
  getSaveWarnings = () => {
23549
- // eslint-disable-next-line react/no-string-refs
23550
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
23551
- return this.refs.editor.getSaveWarnings();
23505
+ return this.editor.current?.getSaveWarnings();
23552
23506
  };
23553
23507
  serialize = options => {
23554
- // eslint-disable-next-line react/no-string-refs
23555
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
23556
- return this.refs.editor.serialize(options);
23508
+ return this.editor.current?.serialize(options);
23557
23509
  };
23558
23510
  render() {
23559
23511
  return /*#__PURE__*/React__namespace.createElement("div", {
23560
23512
  className: "perseus-hint-editor " + this.props.className
23561
23513
  }, this.props.showTitle && /*#__PURE__*/React__namespace.createElement("div", {
23562
23514
  className: "pod-title"
23563
- }, "Hint"), /*#__PURE__*/React__namespace.createElement(Editor
23564
- // eslint-disable-next-line react/no-string-refs
23565
- , {
23566
- ref: "editor"
23515
+ }, "Hint"), /*#__PURE__*/React__namespace.createElement(Editor, {
23516
+ ref: this.editor
23567
23517
  // Using the AssessmentItem content ID as the key
23568
23518
  // ensures that when the user navigates to another
23569
23519
  // item in the Sidebar, the question editor is
@@ -23608,6 +23558,8 @@ class CombinedHintEditor extends React__namespace.Component {
23608
23558
  static defaultProps = {
23609
23559
  highlightLint: false
23610
23560
  };
23561
+ editor = /*#__PURE__*/React__namespace.createRef();
23562
+ frame = /*#__PURE__*/React__namespace.createRef();
23611
23563
  componentDidMount() {
23612
23564
  this.updatePreview();
23613
23565
  }
@@ -23616,10 +23568,7 @@ class CombinedHintEditor extends React__namespace.Component {
23616
23568
  }
23617
23569
  updatePreview = () => {
23618
23570
  const shouldBold = this.props.isLast && !/\*\*/.test(this.props.hint.content);
23619
-
23620
- // eslint-disable-next-line react/no-string-refs
23621
- // @ts-expect-error - TS2339 - Property 'sendNewData' does not exist on type 'ReactInstance'.
23622
- this.refs.frame.sendNewData({
23571
+ this.frame.current?.sendNewData({
23623
23572
  type: "hint",
23624
23573
  data: {
23625
23574
  hint: this.props.hint,
@@ -23635,19 +23584,13 @@ class CombinedHintEditor extends React__namespace.Component {
23635
23584
  });
23636
23585
  };
23637
23586
  getSaveWarnings = () => {
23638
- // eslint-disable-next-line react/no-string-refs
23639
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
23640
- return this.refs.editor.getSaveWarnings();
23587
+ return this.editor.current?.getSaveWarnings();
23641
23588
  };
23642
23589
  serialize = options => {
23643
- // eslint-disable-next-line react/no-string-refs
23644
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
23645
- return this.refs.editor.serialize(options);
23590
+ return this.editor.current?.serialize(options);
23646
23591
  };
23647
23592
  focus = () => {
23648
- // eslint-disable-next-line react/no-string-refs
23649
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
23650
- this.refs.editor.focus();
23593
+ this.editor.current?.focus();
23651
23594
  };
23652
23595
  render() {
23653
23596
  const isMobile = this.props.deviceType === "phone" || this.props.deviceType === "tablet";
@@ -23655,10 +23598,8 @@ class CombinedHintEditor extends React__namespace.Component {
23655
23598
  className: "perseus-combined-hint-editor " + "perseus-editor-row"
23656
23599
  }, /*#__PURE__*/React__namespace.createElement("div", {
23657
23600
  className: "perseus-editor-left-cell"
23658
- }, /*#__PURE__*/React__namespace.createElement(HintEditor
23659
- // eslint-disable-next-line react/no-string-refs
23660
- , {
23661
- ref: "editor",
23601
+ }, /*#__PURE__*/React__namespace.createElement(HintEditor, {
23602
+ ref: this.editor,
23662
23603
  itemId: this.props.itemId,
23663
23604
  isFirst: this.props.isFirst,
23664
23605
  isLast: this.props.isLast,
@@ -23676,10 +23617,8 @@ class CombinedHintEditor extends React__namespace.Component {
23676
23617
  }, /*#__PURE__*/React__namespace.createElement(DeviceFramer, {
23677
23618
  deviceType: this.props.deviceType,
23678
23619
  nochrome: true
23679
- }, /*#__PURE__*/React__namespace.createElement(IframeContentRenderer
23680
- // eslint-disable-next-line react/no-string-refs
23681
- , {
23682
- ref: "frame",
23620
+ }, /*#__PURE__*/React__namespace.createElement(IframeContentRenderer, {
23621
+ ref: this.frame,
23683
23622
  datasetKey: "mobile",
23684
23623
  datasetValue: isMobile,
23685
23624
  seamless: true,
@@ -23998,6 +23937,9 @@ class ItemEditor extends React__namespace.Component {
23998
23937
  question: {},
23999
23938
  answerArea: {}
24000
23939
  };
23940
+ frame = /*#__PURE__*/React__namespace.createRef();
23941
+ questionEditor = /*#__PURE__*/React__namespace.createRef();
23942
+ itemExtrasEditor = /*#__PURE__*/React__namespace.createRef();
24001
23943
 
24002
23944
  // Notify the parent that the question or answer area has been updated.
24003
23945
  updateProps = (newProps, cb, silent) => {
@@ -24005,9 +23947,7 @@ class ItemEditor extends React__namespace.Component {
24005
23947
  this.props.onChange(___default["default"](props).extend(newProps), cb, silent);
24006
23948
  };
24007
23949
  triggerPreviewUpdate = newData => {
24008
- // eslint-disable-next-line react/no-string-refs
24009
- // @ts-expect-error - TS2339 - Property 'sendNewData' does not exist on type 'ReactInstance'.
24010
- this.refs.frame.sendNewData(newData);
23950
+ this.frame.current?.sendNewData(newData);
24011
23951
  };
24012
23952
  handleEditorChange = (newProps, cb, silent) => {
24013
23953
  const question = ___default["default"].extend({}, this.props.question, newProps);
@@ -24022,18 +23962,12 @@ class ItemEditor extends React__namespace.Component {
24022
23962
  }, cb, silent);
24023
23963
  };
24024
23964
  getSaveWarnings = () => {
24025
- // eslint-disable-next-line react/no-string-refs
24026
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
24027
- return this.refs.questionEditor.getSaveWarnings();
23965
+ return this.questionEditor.current?.getSaveWarnings();
24028
23966
  };
24029
23967
  serialize = options => {
24030
23968
  return {
24031
- // eslint-disable-next-line react/no-string-refs
24032
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
24033
- question: this.refs.questionEditor.serialize(options),
24034
- // eslint-disable-next-line react/no-string-refs
24035
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
24036
- answerArea: this.refs.itemExtrasEditor.serialize(options),
23969
+ question: this.questionEditor.current?.serialize(options),
23970
+ answerArea: this.itemExtrasEditor.current?.serialize(),
24037
23971
  itemDataVersion: ITEM_DATA_VERSION
24038
23972
  };
24039
23973
  };
@@ -24047,10 +23981,8 @@ class ItemEditor extends React__namespace.Component {
24047
23981
  className: "perseus-editor-left-cell"
24048
23982
  }, /*#__PURE__*/React__namespace.createElement("div", {
24049
23983
  className: "pod-title"
24050
- }, "Question"), /*#__PURE__*/React__namespace.createElement(Editor
24051
- // eslint-disable-next-line react/no-string-refs
24052
- , _extends({
24053
- ref: "questionEditor"
23984
+ }, "Question"), /*#__PURE__*/React__namespace.createElement(Editor, _extends({
23985
+ ref: this.questionEditor
24054
23986
  // Using the AssessmentItem content ID as the key
24055
23987
  // ensures that when the user navigates to another
24056
23988
  // item in the Sidebar, the question editor is
@@ -24070,10 +24002,8 @@ class ItemEditor extends React__namespace.Component {
24070
24002
  }, /*#__PURE__*/React__namespace.createElement(DeviceFramer, {
24071
24003
  deviceType: this.props.deviceType,
24072
24004
  nochrome: true
24073
- }, /*#__PURE__*/React__namespace.createElement(IframeContentRenderer
24074
- // eslint-disable-next-line react/no-string-refs
24075
- , {
24076
- ref: "frame",
24005
+ }, /*#__PURE__*/React__namespace.createElement(IframeContentRenderer, {
24006
+ ref: this.frame,
24077
24007
  key: this.props.deviceType,
24078
24008
  datasetKey: "mobile",
24079
24009
  datasetValue: isMobile,
@@ -24091,10 +24021,8 @@ class ItemEditor extends React__namespace.Component {
24091
24021
  className: "perseus-editor-left-cell"
24092
24022
  }, /*#__PURE__*/React__namespace.createElement("div", {
24093
24023
  className: "pod-title"
24094
- }, "Question extras"), /*#__PURE__*/React__namespace.createElement(ItemExtrasEditor
24095
- // eslint-disable-next-line react/no-string-refs
24096
- , _extends({
24097
- ref: "itemExtrasEditor",
24024
+ }, "Question extras"), /*#__PURE__*/React__namespace.createElement(ItemExtrasEditor, _extends({
24025
+ ref: this.itemExtrasEditor,
24098
24026
  onChange: this.handleItemExtrasChange
24099
24027
  }, this.props.answerArea))), /*#__PURE__*/React__namespace.createElement("div", {
24100
24028
  className: "perseus-editor-right-cell"
@@ -24108,8 +24036,8 @@ const {
24108
24036
  HUD
24109
24037
  } = perseus.components;
24110
24038
  class EditorPage extends React__namespace.Component {
24111
- // @ts-expect-error - TS2564 - Property 'rendererMountNode' has no initializer and is not definitely assigned in the constructor.
24112
-
24039
+ itemEditor = /*#__PURE__*/React__namespace.createRef();
24040
+ hintsEditor = /*#__PURE__*/React__namespace.createRef();
24113
24041
  static defaultProps = {
24114
24042
  developerMode: false,
24115
24043
  jsonMode: false,
@@ -24130,7 +24058,6 @@ class EditorPage extends React__namespace.Component {
24130
24058
  // TODO(scottgrant): This is a hack to remove the deprecated call to
24131
24059
  // this.isMounted() but is still considered an anti-pattern.
24132
24060
  this._isMounted = true;
24133
- this.rendererMountNode = document.createElement("div");
24134
24061
  this.updateRenderer();
24135
24062
  }
24136
24063
  componentDidUpdate() {
@@ -24173,10 +24100,7 @@ class EditorPage extends React__namespace.Component {
24173
24100
  customKeypad: touch,
24174
24101
  isMobile: touch
24175
24102
  };
24176
-
24177
- // eslint-disable-next-line react/no-string-refs
24178
- // @ts-expect-error - TS2339 - Property 'triggerPreviewUpdate' does not exist on type 'ReactInstance'.
24179
- this.refs.itemEditor.triggerPreviewUpdate({
24103
+ this.itemEditor.current?.triggerPreviewUpdate({
24180
24104
  type: "question",
24181
24105
  data: ___default["default"]({
24182
24106
  item: this.serialize(),
@@ -24190,9 +24114,7 @@ class EditorPage extends React__namespace.Component {
24190
24114
  paths: this.props.contentPaths || []
24191
24115
  },
24192
24116
  reviewMode: true,
24193
- // eslint-disable-next-line react/no-string-refs
24194
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
24195
- legacyPerseusLint: this.refs.itemEditor.getSaveWarnings()
24117
+ legacyPerseusLint: this.itemEditor.current?.getSaveWarnings()
24196
24118
  }).extend(___default["default"](this.props).pick("workAreaSelector", "solutionAreaSelector", "hintsAreaSelector", "problemNum"))
24197
24119
  });
24198
24120
  }
@@ -24203,24 +24125,16 @@ class EditorPage extends React__namespace.Component {
24203
24125
  };
24204
24126
  }
24205
24127
  getSaveWarnings() {
24206
- // eslint-disable-next-line react/no-string-refs
24207
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
24208
- const issues1 = this.refs.itemEditor.getSaveWarnings();
24209
- // eslint-disable-next-line react/no-string-refs
24210
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
24211
- const issues2 = this.refs.hintsEditor.getSaveWarnings();
24128
+ const issues1 = this.itemEditor.current?.getSaveWarnings();
24129
+ const issues2 = this.hintsEditor.current?.getSaveWarnings();
24212
24130
  return issues1.concat(issues2);
24213
24131
  }
24214
24132
  serialize(options) {
24215
24133
  if (this.props.jsonMode) {
24216
24134
  return this.state.json;
24217
24135
  }
24218
- // eslint-disable-next-line react/no-string-refs
24219
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
24220
- return ___default["default"].extend(this.refs.itemEditor.serialize(options), {
24221
- // eslint-disable-next-line react/no-string-refs
24222
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
24223
- hints: this.refs.hintsEditor.serialize(options)
24136
+ return ___default["default"].extend(this.itemEditor.current?.serialize(options), {
24137
+ hints: this.hintsEditor.current?.serialize(options)
24224
24138
  });
24225
24139
  }
24226
24140
  handleChange = (toChange, cb, silent) => {
@@ -24278,10 +24192,8 @@ class EditorPage extends React__namespace.Component {
24278
24192
  multiLine: true,
24279
24193
  value: this.state.json,
24280
24194
  onChange: this.changeJSON
24281
- })), (!this.props.developerMode || !this.props.jsonMode) && /*#__PURE__*/React__namespace.createElement(ItemEditor
24282
- // eslint-disable-next-line react/no-string-refs
24283
- , {
24284
- ref: "itemEditor",
24195
+ })), (!this.props.developerMode || !this.props.jsonMode) && /*#__PURE__*/React__namespace.createElement(ItemEditor, {
24196
+ ref: this.itemEditor,
24285
24197
  itemId: this.props.itemId,
24286
24198
  question: this.props.question,
24287
24199
  answerArea: this.props.answerArea,
@@ -24292,10 +24204,8 @@ class EditorPage extends React__namespace.Component {
24292
24204
  deviceType: this.props.previewDevice,
24293
24205
  apiOptions: deviceBasedApiOptions,
24294
24206
  previewURL: this.props.previewURL
24295
- }), (!this.props.developerMode || !this.props.jsonMode) && /*#__PURE__*/React__namespace.createElement(CombinedHintsEditor
24296
- // eslint-disable-next-line react/no-string-refs
24297
- , {
24298
- ref: "hintsEditor",
24207
+ }), (!this.props.developerMode || !this.props.jsonMode) && /*#__PURE__*/React__namespace.createElement(CombinedHintsEditor, {
24208
+ ref: this.hintsEditor,
24299
24209
  itemId: this.props.itemId,
24300
24210
  hints: this.props.hints,
24301
24211
  imageUploader: this.props.imageUploader,
@@ -25916,6 +25826,7 @@ class CategorizerEditor extends React__namespace.Component {
25916
25826
  * to its parent on blur.
25917
25827
  */ // eslint-disable-next-line react/no-unsafe
25918
25828
  class BlurInput extends React__namespace.Component {
25829
+ input = /*#__PURE__*/React__namespace.createRef();
25919
25830
  constructor(props) {
25920
25831
  super(props);
25921
25832
  this.state = {
@@ -25937,8 +25848,12 @@ class BlurInput extends React__namespace.Component {
25937
25848
  handleBlur = e => {
25938
25849
  this.props.onChange(e.target.value);
25939
25850
  };
25851
+ focus() {
25852
+ this.input.current?.focus();
25853
+ }
25940
25854
  render() {
25941
25855
  return /*#__PURE__*/React__namespace.createElement("input", {
25856
+ ref: this.input,
25942
25857
  className: this.props.className,
25943
25858
  style: this.props.style,
25944
25859
  type: "text",
@@ -26559,6 +26474,7 @@ class ExampleWidgetEditor extends React__namespace.Component {
26559
26474
  static defaultProps = {
26560
26475
  correct: ""
26561
26476
  };
26477
+ input = /*#__PURE__*/React__namespace.createRef();
26562
26478
  handleAnswerChange = event => {
26563
26479
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26564
26480
  this.change({
@@ -26568,10 +26484,8 @@ class ExampleWidgetEditor extends React__namespace.Component {
26568
26484
  render() {
26569
26485
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Correct answer:", /*#__PURE__*/React__namespace.createElement("input", {
26570
26486
  value: this.props.correct,
26571
- onChange: this.handleAnswerChange
26572
- // eslint-disable-next-line react/no-string-refs
26573
- ,
26574
- ref: "input"
26487
+ onChange: this.handleAnswerChange,
26488
+ ref: this.input
26575
26489
  })));
26576
26490
  }
26577
26491
  change = (() => {
@@ -26584,9 +26498,7 @@ class ExampleWidgetEditor extends React__namespace.Component {
26584
26498
  };
26585
26499
  })();
26586
26500
  focus = () => {
26587
- // eslint-disable-next-line react/no-string-refs
26588
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
26589
- this.refs.input.focus();
26501
+ this.input.current?.focus();
26590
26502
  return true;
26591
26503
  };
26592
26504
  serialize = () => {
@@ -27241,6 +27153,8 @@ class GradedGroupEditor extends React__namespace.Component {
27241
27153
  images: {},
27242
27154
  hint: null
27243
27155
  };
27156
+ editor = /*#__PURE__*/React__namespace.createRef();
27157
+ hintEditor = /*#__PURE__*/React__namespace.createRef();
27244
27158
  change = (() => {
27245
27159
  var _this = this;
27246
27160
  return function () {
@@ -27257,9 +27171,7 @@ class GradedGroupEditor extends React__namespace.Component {
27257
27171
  this.props.onChange({
27258
27172
  hint
27259
27173
  }, () => {
27260
- // eslint-disable-next-line react/no-string-refs
27261
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
27262
- this.refs["hint-editor"].focus();
27174
+ this.hintEditor.current?.focus();
27263
27175
  });
27264
27176
  };
27265
27177
  handleRemoveHint = e => {
@@ -27280,10 +27192,8 @@ class GradedGroupEditor extends React__namespace.Component {
27280
27192
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
27281
27193
  ,
27282
27194
  onChange: this.change("title")
27283
- }))), /*#__PURE__*/React__namespace.createElement(Editor
27284
- // eslint-disable-next-line react/no-string-refs
27285
- , {
27286
- ref: "editor",
27195
+ }))), /*#__PURE__*/React__namespace.createElement(Editor, {
27196
+ ref: this.editor,
27287
27197
  content: this.props.content,
27288
27198
  widgets: this.props.widgets,
27289
27199
  apiOptions: this.props.apiOptions,
@@ -27304,10 +27214,8 @@ class GradedGroupEditor extends React__namespace.Component {
27304
27214
  className: "perseus-hint-editor"
27305
27215
  }, /*#__PURE__*/React__namespace.createElement("div", {
27306
27216
  className: aphrodite.css(styles$b.hintsTitle)
27307
- }, "Hint"), /*#__PURE__*/React__namespace.createElement(Editor
27308
- // eslint-disable-next-line react/no-string-refs
27309
- , {
27310
- ref: "hint-editor",
27217
+ }, "Hint"), /*#__PURE__*/React__namespace.createElement(Editor, {
27218
+ ref: this.hintEditor,
27311
27219
  content: this.props.hint ? this.props.hint.content : "",
27312
27220
  widgets: this.props.hint ? this.props.hint.widgets : {},
27313
27221
  apiOptions: this.props.apiOptions,
@@ -27327,22 +27235,13 @@ class GradedGroupEditor extends React__namespace.Component {
27327
27235
  }, /*#__PURE__*/React__namespace.createElement(InlineIcon$5, iconTrash$3), " Remove this hint")));
27328
27236
  }
27329
27237
  getSaveWarnings = () => {
27330
- // eslint-disable-next-line react/no-string-refs
27331
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
27332
- return this.refs.editor.getSaveWarnings();
27238
+ return this.editor.current?.getSaveWarnings();
27333
27239
  };
27334
27240
  serialize = () => {
27335
27241
  return {
27336
27242
  title: this.props.title,
27337
- // eslint-disable-next-line react/no-string-refs
27338
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
27339
- ...this.refs.editor.serialize(),
27340
- hint:
27341
- // eslint-disable-next-line react/no-string-refs
27342
- this.refs["hint-editor"] &&
27343
- // eslint-disable-next-line react/no-string-refs
27344
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
27345
- this.refs["hint-editor"].serialize()
27243
+ ...this.editor.current?.serialize(),
27244
+ hint: this.hintEditor.current?.serialize()
27346
27245
  };
27347
27246
  };
27348
27247
  }
@@ -28046,13 +27945,12 @@ class GroupEditor extends React__namespace.Component {
28046
27945
  // `the GroupMetadataEditor`
28047
27946
  metadata: undefined
28048
27947
  };
27948
+ editor = /*#__PURE__*/React__namespace.createRef();
28049
27949
  render() {
28050
27950
  return /*#__PURE__*/React__namespace.createElement("div", {
28051
27951
  className: "perseus-group-editor"
28052
- }, /*#__PURE__*/React__namespace.createElement("div", null, this._renderMetadataEditor()), /*#__PURE__*/React__namespace.createElement(Editor
28053
- // eslint-disable-next-line react/no-string-refs
28054
- , {
28055
- ref: "editor",
27952
+ }, /*#__PURE__*/React__namespace.createElement("div", null, this._renderMetadataEditor()), /*#__PURE__*/React__namespace.createElement(Editor, {
27953
+ ref: this.editor,
28056
27954
  content: this.props.content,
28057
27955
  widgets: this.props.widgets,
28058
27956
  apiOptions: this.props.apiOptions,
@@ -28081,14 +27979,10 @@ class GroupEditor extends React__namespace.Component {
28081
27979
  };
28082
27980
  })();
28083
27981
  getSaveWarnings = () => {
28084
- // eslint-disable-next-line react/no-string-refs
28085
- // @ts-expect-error - TS2339 - Property 'getSaveWarnings' does not exist on type 'ReactInstance'.
28086
- return this.refs.editor.getSaveWarnings();
27982
+ return this.editor.current?.getSaveWarnings();
28087
27983
  };
28088
27984
  serialize = () => {
28089
- // eslint-disable-next-line react/no-string-refs
28090
- // @ts-expect-error - TS2339 - Property 'serialize' does not exist on type 'ReactInstance'.
28091
- return ___default["default"].extend({}, this.refs.editor.serialize(), {
27985
+ return ___default["default"].extend({}, this.editor.current?.serialize(), {
28092
27986
  metadata: this.props.metadata
28093
27987
  });
28094
27988
  };
@@ -28550,6 +28444,7 @@ class InputNumberEditor extends React__namespace.Component {
28550
28444
  answerType: "number",
28551
28445
  rightAlign: false
28552
28446
  };
28447
+ input = /*#__PURE__*/React__namespace.createRef();
28553
28448
  handleAnswerChange = str => {
28554
28449
  const value = perseus.Util.firstNumericalParse(str) || 0;
28555
28450
  this.props.onChange({
@@ -28565,10 +28460,8 @@ class InputNumberEditor extends React__namespace.Component {
28565
28460
  }, this);
28566
28461
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Correct answer:", " ", /*#__PURE__*/React__namespace.createElement(BlurInput, {
28567
28462
  value: "" + this.props.value,
28568
- onChange: this.handleAnswerChange
28569
- // eslint-disable-next-line react/no-string-refs
28570
- ,
28571
- ref: "input"
28463
+ onChange: this.handleAnswerChange,
28464
+ ref: this.input
28572
28465
  }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Unsimplified answers", " ", /*#__PURE__*/React__namespace.createElement("select", {
28573
28466
  value: this.props.simplify,
28574
28467
  onChange: e => {
@@ -28642,8 +28535,7 @@ class InputNumberEditor extends React__namespace.Component {
28642
28535
  }), " ", "Right alignment")));
28643
28536
  }
28644
28537
  focus = () => {
28645
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
28646
- ReactDOM__default["default"].findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
28538
+ this.input.current?.focus();
28647
28539
  return true;
28648
28540
  };
28649
28541
  serialize = () => ({
@@ -34132,15 +34024,14 @@ class SimpleMarkdownTesterEditor extends React__namespace.Component {
34132
34024
  static defaultProps = {
34133
34025
  value: ""
34134
34026
  };
34027
+ input = /*#__PURE__*/React__namespace.createRef();
34135
34028
  render() {
34136
34029
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Simple markdown contents:"), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(TextArea, {
34137
34030
  value: this.props.value
34138
34031
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
34139
34032
  ,
34140
- onChange: this.change("value")
34141
- // eslint-disable-next-line react/no-string-refs
34142
- ,
34143
- ref: "input"
34033
+ onChange: this.change("value"),
34034
+ ref: this.input
34144
34035
  }))));
34145
34036
  }
34146
34037
  change = (() => {
@@ -34153,9 +34044,7 @@ class SimpleMarkdownTesterEditor extends React__namespace.Component {
34153
34044
  };
34154
34045
  })();
34155
34046
  focus = () => {
34156
- // eslint-disable-next-line react/no-string-refs
34157
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
34158
- this.refs.input.focus();
34047
+ this.input.current?.focus();
34159
34048
  return true;
34160
34049
  };
34161
34050
  serialize = () => {
@@ -34324,11 +34213,10 @@ class TableEditor extends React__namespace.Component {
34324
34213
  answers: blankAnswers
34325
34214
  };
34326
34215
  }();
34216
+ numberOfColumns = /*#__PURE__*/React__namespace.createRef();
34327
34217
  focus = () => {
34328
- // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
34329
- ReactDOM__default["default"].findDOMNode(this.refs.numberOfColumns).focus(); // eslint-disable-line react/no-string-refs
34218
+ this.numberOfColumns.current?.focus();
34330
34219
  };
34331
-
34332
34220
  render() {
34333
34221
  const tableProps = ___default["default"].pick(this.props, "headers", "answers", "onChange", "apiOptions");
34334
34222
  ___default["default"].extend(tableProps, {
@@ -34340,10 +34228,8 @@ class TableEditor extends React__namespace.Component {
34340
34228
  });
34341
34229
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
34342
34230
  className: "perseus-widget-row"
34343
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Number of columns:", " ", /*#__PURE__*/React__namespace.createElement(NumberInput$1
34344
- // eslint-disable-next-line react/no-string-refs
34345
- , {
34346
- ref: "numberOfColumns",
34231
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Number of columns:", " ", /*#__PURE__*/React__namespace.createElement(NumberInput$1, {
34232
+ ref: this.numberOfColumns,
34347
34233
  value: this.props.columns,
34348
34234
  onChange: val => {
34349
34235
  if (val) {
@@ -35467,18 +35353,16 @@ var AllEditors = [CategorizerEditor, CSProgramEditor, DefinitionEditor, Dropdown
35467
35353
 
35468
35354
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
35469
35355
  class TextInput extends React__namespace.Component {
35356
+ input = /*#__PURE__*/React__namespace.createRef();
35470
35357
  render() {
35471
35358
  return /*#__PURE__*/React__namespace.createElement("input", {
35472
- // eslint-disable-next-line react/no-string-refs
35473
- ref: "input",
35359
+ ref: this.input,
35474
35360
  value: this.props.value || "",
35475
35361
  onChange: this.changeValue
35476
35362
  });
35477
35363
  }
35478
35364
  focus = () => {
35479
- // eslint-disable-next-line react/no-string-refs
35480
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
35481
- this.refs.input.focus();
35365
+ this.input.current?.focus();
35482
35366
  return true;
35483
35367
  };
35484
35368
  changeValue = e => {
@@ -35501,6 +35385,7 @@ class ExampleWidget extends React__namespace.Component {
35501
35385
  static defaultProps = {
35502
35386
  value: ""
35503
35387
  };
35388
+ input = /*#__PURE__*/React__namespace.createRef();
35504
35389
 
35505
35390
  /**
35506
35391
  * This is the widget's grading function. simpleValidate generally
@@ -35545,10 +35430,8 @@ class ExampleWidget extends React__namespace.Component {
35545
35430
  };
35546
35431
  })();
35547
35432
  render() {
35548
- return /*#__PURE__*/React__namespace.createElement(TextInput
35549
- // eslint-disable-next-line react/no-string-refs
35550
- , {
35551
- ref: "input",
35433
+ return /*#__PURE__*/React__namespace.createElement(TextInput, {
35434
+ ref: this.input,
35552
35435
  value: this.props.value
35553
35436
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
35554
35437
  ,
@@ -35565,9 +35448,7 @@ class ExampleWidget extends React__namespace.Component {
35565
35448
  * focused on page load.
35566
35449
  */
35567
35450
  focus = () => {
35568
- // eslint-disable-next-line react/no-string-refs
35569
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
35570
- this.refs.input.focus();
35451
+ this.input.current?.focus();
35571
35452
  return true;
35572
35453
  };
35573
35454