@khanacademy/perseus-editor 13.0.1 → 14.0.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 (34) hide show
  1. package/dist/all-editors.d.ts +1 -4
  2. package/dist/components/hover-behavior.d.ts +2 -2
  3. package/dist/components/widget-editor.d.ts +1 -1
  4. package/dist/content-preview.d.ts +22 -0
  5. package/dist/es/index.js +202 -633
  6. package/dist/es/index.js.map +1 -1
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.js +748 -1197
  9. package/dist/index.js.map +1 -1
  10. package/dist/widgets/expression-editor.d.ts +1 -1
  11. package/dist/widgets/graded-group-editor.d.ts +1 -1
  12. package/dist/widgets/grapher-editor.d.ts +1 -1
  13. package/dist/widgets/group-editor.d.ts +1 -1
  14. package/dist/widgets/iframe-editor.d.ts +1 -1
  15. package/dist/widgets/image-editor.d.ts +2 -2
  16. package/dist/widgets/input-number-editor.d.ts +1 -1
  17. package/dist/widgets/interactive-graph-editor.d.ts +8 -114
  18. package/dist/widgets/matcher-editor.d.ts +1 -1
  19. package/dist/widgets/matrix-editor.d.ts +1 -1
  20. package/dist/widgets/measurer-editor.d.ts +1 -1
  21. package/dist/widgets/numeric-input-editor.d.ts +1 -1
  22. package/dist/widgets/orderer-editor.d.ts +1 -1
  23. package/dist/widgets/phet-simulation-editor.d.ts +2 -1
  24. package/dist/widgets/radio/editor.d.ts +1 -1
  25. package/dist/widgets/table-editor.d.ts +1 -1
  26. package/package.json +36 -35
  27. package/dist/all-widgets.d.ts +0 -22
  28. package/dist/testing-widgets.d.ts +0 -22
  29. package/dist/widgets/example-graphie-widget-editor.d.ts +0 -18
  30. package/dist/widgets/example-graphie-widget.d.ts +0 -61
  31. package/dist/widgets/example-widget-editor.d.ts +0 -20
  32. package/dist/widgets/example-widget.d.ts +0 -89
  33. package/dist/widgets/simple-markdown-tester-editor.d.ts +0 -21
  34. package/dist/widgets/simple-markdown-tester.d.ts +0 -54
package/dist/es/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { addLibraryVersionToPerseusDebug, PerseusError, Errors } from '@khanacademy/perseus-core';
2
- import { constants, components, Widgets, icons, WIDGET_PROP_DENYLIST, Util, Log, PerseusMarkdown, preprocessTex, ApiOptions, buildMapper, itemToTree, buildEmptyItemTreeForShape, shapes, ItemExtras, itemDataVersion, ClassNames, MultiItems, traverse, Categorizer as Categorizer$1, Changeable, EditorJsonify, Dependencies, WidgetJsonifyDeprecated, PerseusExpressionAnswerFormConsidered, Expression, interactiveSizes, KhanMath, GrapherWidget, GrapherUtil, SizingUtils, PerseusI18nContext, KhanColors, ColorPicker, DashPicker, ArrowPicker, ElementContainer, getAngleCoords, getPolygonCoords, getPointCoords, getQuadraticCoords, getSinusoidCoords, getCircleCoords, getLinearSystemCoords, getSegmentCoords, getLineCoords, lockedFigureColors, lockedFigureFillStyles, InteractiveGraphWidget, globalStyles, globalConstants, MatrixWidget, PlotterWidget, plotterPlotTypes, BaseRadio, TableWidget, widgets } from '@khanacademy/perseus';
2
+ import { constants, components, Widgets, icons, WIDGET_PROP_DENYLIST, Util, Log, PerseusMarkdown, preprocessTex, ApiOptions, buildMapper, itemToTree, buildEmptyItemTreeForShape, shapes, ItemExtras, itemDataVersion, ClassNames, MultiItems, traverse, Categorizer as Categorizer$1, Changeable, EditorJsonify, Dependencies, PerseusExpressionAnswerFormConsidered, Expression, interactiveSizes, KhanMath, GrapherWidget, GrapherUtil, SizingUtils, PerseusI18nContext, KhanColors, ColorPicker, DashPicker, ArrowPicker, ElementContainer, getAngleCoords, getPolygonCoords, getPointCoords, getQuadraticCoords, getSinusoidCoords, getCircleCoords, getLinearSystemCoords, getSegmentCoords, getLineCoords, lockedFigureColors, lockedFigureFillStyles, InteractiveGraphWidget, globalStyles, globalConstants, MatrixWidget, makeSafeUrl, PlotterWidget, plotterPlotTypes, BaseRadio, TableWidget, widgets } from '@khanacademy/perseus';
3
+ export { widgets } from '@khanacademy/perseus';
3
4
  import * as React from 'react';
4
5
  import { useRef, useEffect, useState } from 'react';
5
6
  import _ from 'underscore';
@@ -16,12 +17,12 @@ import caretRight from '@phosphor-icons/core/bold/caret-right-bold.svg';
16
17
  import classNames from 'classnames';
17
18
  import { Checkbox as Checkbox$1, LabeledTextField, TextField } from '@khanacademy/wonder-blocks-form';
18
19
  import ReactDOM from 'react-dom';
19
- import { point, vector, number } from '@khanacademy/kmath';
20
20
  import * as KAS from '@khanacademy/kas';
21
21
  import Button from '@khanacademy/wonder-blocks-button';
22
22
  import { HeadingSmall, HeadingXSmall, LabelSmall, LabelLarge, LabelMedium, LabelXSmall, BodyMonospace } from '@khanacademy/wonder-blocks-typography';
23
23
  import { isTruthy, UnreachableCaseError } from '@khanacademy/wonder-stuff-core';
24
24
  import { useMathInputI18n, createMathField } from '@khanacademy/math-input';
25
+ import { vector, number } from '@khanacademy/kmath';
25
26
  import { ActionMenu, ActionItem, SingleSelect, OptionItem } from '@khanacademy/wonder-blocks-dropdown';
26
27
  import { AccordionSection } from '@khanacademy/wonder-blocks-accordion';
27
28
  import IconButton from '@khanacademy/wonder-blocks-icon-button';
@@ -41,22 +42,17 @@ import arrowCounterClockwise from '@phosphor-icons/core/bold/arrow-counter-clock
41
42
 
42
43
  // This file is processed by a Rollup plugin (replace) to inject the production
43
44
  const libName = "@khanacademy/perseus-editor";
44
- const libVersion = "13.0.1";
45
+ const libVersion = "14.0.0";
45
46
  addLibraryVersionToPerseusDebug(libName, libVersion);
46
47
 
47
48
  function _extends() {
48
- _extends = Object.assign ? Object.assign.bind() : function (target) {
49
- for (var i = 1; i < arguments.length; i++) {
50
- var source = arguments[i];
51
- for (var key in source) {
52
- if (Object.prototype.hasOwnProperty.call(source, key)) {
53
- target[key] = source[key];
54
- }
55
- }
49
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
50
+ for (var e = 1; e < arguments.length; e++) {
51
+ var t = arguments[e];
52
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
56
53
  }
57
- return target;
58
- };
59
- return _extends.apply(this, arguments);
54
+ return n;
55
+ }, _extends.apply(null, arguments);
60
56
  }
61
57
 
62
58
  const SCREEN_SIZES = {
@@ -133,16 +129,6 @@ const JsonEditor = createReactClass({
133
129
  this.setState(this.getInitialState());
134
130
  }
135
131
  },
136
- render: function () {
137
- const classes = "perseus-json-editor " + (this.state.valid ? "valid" : "invalid");
138
- return /*#__PURE__*/React.createElement("textarea", {
139
- className: classes,
140
- value: this.state.currentValue,
141
- onChange: this.handleChange,
142
- onKeyDown: this.handleKeyDown,
143
- onBlur: this.handleBlur
144
- });
145
- },
146
132
  handleKeyDown: function (e) {
147
133
  // This handler allows the tab character to be entered by pressing
148
134
  // tab, instead of jumping to the next (non-existant) field
@@ -209,6 +195,16 @@ const JsonEditor = createReactClass({
209
195
  valid: true
210
196
  });
211
197
  }
198
+ },
199
+ render: function () {
200
+ const classes = "perseus-json-editor " + (this.state.valid ? "valid" : "invalid");
201
+ return /*#__PURE__*/React.createElement("textarea", {
202
+ className: classes,
203
+ value: this.state.currentValue,
204
+ onChange: this.handleChange,
205
+ onKeyDown: this.handleKeyDown,
206
+ onBlur: this.handleBlur
207
+ });
212
208
  }
213
209
  });
214
210
 
@@ -20561,17 +20557,14 @@ const DragTarget = createReactClass({
20561
20557
  }
20562
20558
  });
20563
20559
 
20564
- function _objectWithoutPropertiesLoose(source, excluded) {
20565
- if (source == null) return {};
20566
- var target = {};
20567
- var sourceKeys = Object.keys(source);
20568
- var key, i;
20569
- for (i = 0; i < sourceKeys.length; i++) {
20570
- key = sourceKeys[i];
20571
- if (excluded.indexOf(key) >= 0) continue;
20572
- target[key] = source[key];
20573
- }
20574
- return target;
20560
+ function _objectWithoutPropertiesLoose(r, e) {
20561
+ if (null == r) return {};
20562
+ var t = {};
20563
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
20564
+ if (e.includes(n)) continue;
20565
+ t[n] = r[n];
20566
+ }
20567
+ return t;
20575
20568
  }
20576
20569
 
20577
20570
  const mediaDefaultSpecLargeMarginWidth = spacing.large_24;
@@ -25559,7 +25552,7 @@ const styles$N = StyleSheet.create({
25559
25552
  }
25560
25553
  });
25561
25554
 
25562
- /* eslint-disable react/no-unsafe, react/sort-comp */
25555
+ /* eslint-disable react/no-unsafe */
25563
25556
 
25564
25557
  /* Renders an EditorPage (or an ArticleEditor) as a non-controlled component.
25565
25558
  *
@@ -25578,10 +25571,6 @@ const StatefulEditorPage = createReactClass({
25578
25571
  componentClass: EditorPage
25579
25572
  };
25580
25573
  },
25581
- render: function () {
25582
- const Component = this.props.componentClass;
25583
- return /*#__PURE__*/React.createElement(Component, this.state);
25584
- },
25585
25574
  getInitialState: function () {
25586
25575
  return _({}).extend(_.omit(this.props, "componentClass"), {
25587
25576
  onChange: this.handleChange,
@@ -25591,9 +25580,6 @@ const StatefulEditorPage = createReactClass({
25591
25580
  componentDidMount: function () {
25592
25581
  this._isMounted = true;
25593
25582
  },
25594
- componentWillUnmount: function () {
25595
- this._isMounted = false;
25596
- },
25597
25583
  // getInitialState isn't called if the react component is re-rendered
25598
25584
  // in-place on the dom, in which case this is called instead, so we
25599
25585
  // need to update the state here.
@@ -25601,6 +25587,9 @@ const StatefulEditorPage = createReactClass({
25601
25587
  UNSAFE_componentWillReceiveProps: function (nextProps) {
25602
25588
  this.setState(_(nextProps).pick("apiOptions", "imageUploader", "developerMode", "problemNum", "previewDevice", "frameSource"));
25603
25589
  },
25590
+ componentWillUnmount: function () {
25591
+ this._isMounted = false;
25592
+ },
25604
25593
  getSaveWarnings: function () {
25605
25594
  // eslint-disable-next-line react/no-string-refs
25606
25595
  return this.refs.editor.getSaveWarnings();
@@ -25617,6 +25606,10 @@ const StatefulEditorPage = createReactClass({
25617
25606
  scorePreview: function () {
25618
25607
  // eslint-disable-next-line react/no-string-refs
25619
25608
  return this.refs.editor.scorePreview();
25609
+ },
25610
+ render: function () {
25611
+ const Component = this.props.componentClass;
25612
+ return /*#__PURE__*/React.createElement(Component, this.state);
25620
25613
  }
25621
25614
  });
25622
25615
 
@@ -25947,7 +25940,7 @@ CSProgramEditor.defaultProps = {
25947
25940
  };
25948
25941
 
25949
25942
  const {
25950
- TextInput: TextInput$8
25943
+ TextInput: TextInput$7
25951
25944
  } = components;
25952
25945
  class DefinitionEditor extends React.Component {
25953
25946
  constructor(..._args) {
@@ -25967,7 +25960,7 @@ class DefinitionEditor extends React.Component {
25967
25960
  target: "_blank"
25968
25961
  }, "Definition style guide"), /*#__PURE__*/React.createElement("div", {
25969
25962
  className: "perseus-widget-row"
25970
- }, /*#__PURE__*/React.createElement("label", null, "Word to be defined:", " ", /*#__PURE__*/React.createElement(TextInput$8, {
25963
+ }, /*#__PURE__*/React.createElement("label", null, "Word to be defined:", " ", /*#__PURE__*/React.createElement(TextInput$7, {
25971
25964
  value: this.props.togglePrompt
25972
25965
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
25973
25966
  ,
@@ -26161,222 +26154,8 @@ DropdownEditor.defaultProps = {
26161
26154
  }]
26162
26155
  };
26163
26156
 
26164
- /* eslint-disable @typescript-eslint/no-unused-vars, react/forbid-prop-types, react/sort-comp */
26165
- const {
26166
- Graphie
26167
- } = components;
26168
-
26169
- // @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
26170
- const MovablePoint = Graphie.MovablePoint;
26171
- /**
26172
- * This is the widget's renderer. It shows up in the right column
26173
- * in the demo, and is what is visible to users, and where
26174
- * users enter their answers.
26175
- */
26176
- class ExampleGraphieWidget$1 extends React.Component {
26177
- constructor(..._args) {
26178
- super(..._args);
26179
- this.getUserInput = () => {
26180
- return WidgetJsonifyDeprecated.getUserInput.call(this);
26181
- };
26182
- this.change = (...args) => {
26183
- return Changeable.change.apply(this, args);
26184
- };
26185
- this.movePoint = newCoord => {
26186
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26187
- this.change({
26188
- coord: newCoord
26189
- });
26190
- };
26191
- this._getGridConfig = options => {
26192
- return _.map(options.step, function (step, i) {
26193
- return Util.gridDimensionConfig(step, options.range[i], options.box[i], options.gridStep[i]);
26194
- });
26195
- };
26196
- this.setupGraphie = (graphie, options) => {
26197
- const gridConfig = this._getGridConfig(options);
26198
- graphie.graphInit({
26199
- range: options.range,
26200
- scale: _.pluck(gridConfig, "scale"),
26201
- axisArrows: "<->",
26202
- labelFormat: function (s) {
26203
- return "\\small{" + s + "}";
26204
- },
26205
- gridStep: options.gridStep,
26206
- tickStep: _.pluck(gridConfig, "tickStep"),
26207
- labelStep: 1,
26208
- unityLabels: _.pluck(gridConfig, "unityLabel")
26209
- });
26210
- graphie.label([0, options.range[1][1]], options.labels[1], "above");
26211
- };
26212
- this.simpleValidate = rubric => {
26213
- return ExampleGraphieWidget$1.validate(this.getUserInput(), rubric);
26214
- };
26215
- }
26216
- /**
26217
- * This is the widget's grading function
26218
- */
26219
- static validate(state, rubric) {
26220
- if (state.coord == null) {
26221
- return {
26222
- type: "invalid",
26223
- message: null
26224
- };
26225
- }
26226
- if (point.equal(state.coord, rubric.correct)) {
26227
- return {
26228
- type: "points",
26229
- earned: 1,
26230
- total: 1,
26231
- message: null
26232
- };
26233
- }
26234
- return {
26235
- type: "points",
26236
- earned: 0,
26237
- total: 1,
26238
- message: null
26239
- };
26240
- }
26241
- render() {
26242
- var _this$props$apiOption;
26243
- return /*#__PURE__*/React.createElement(Graphie
26244
- // eslint-disable-next-line react/no-string-refs
26245
- , {
26246
- ref: "graphie",
26247
- box: this.props.graph.box,
26248
- range: this.props.graph.range,
26249
- options: this.props.graph,
26250
- setup: this.setupGraphie,
26251
- setDrawingAreaAvailable: (_this$props$apiOption = this.props.apiOptions) == null ? void 0 : _this$props$apiOption.setDrawingAreaAvailable
26252
- }, /*#__PURE__*/React.createElement(MovablePoint, {
26253
- pointSize: 5,
26254
- coord: this.props.coord || [0, 0],
26255
- constraints: [MovablePoint.constraints.snap(), MovablePoint.constraints.bound()],
26256
- onMove: this.movePoint
26257
- }));
26258
- }
26259
- }
26260
-
26261
- /**
26262
- * For this widget to work, we must export it.
26263
- * We also must import this file in src/all-widgets.js
26264
- */
26265
- ExampleGraphieWidget$1.defaultProps = {
26266
- // We want to allow our coord to be null to test if the
26267
- // user has interacted with this widget yet when grading it
26268
- coord: null,
26269
- graph: {
26270
- box: [400, 400],
26271
- labels: ["x", "y"],
26272
- range: [[-10, 10], [-10, 10]],
26273
- step: [1, 1],
26274
- gridStep: [1, 1],
26275
- valid: true,
26276
- backgroundImage: null,
26277
- markings: "grid",
26278
- showProtractor: false
26279
- }
26280
- };
26281
- var ExampleGraphieWidget$2 = {
26282
- name: "example-graphie-widget",
26283
- displayName: "Example Graphie Widget",
26284
- hidden: true,
26285
- // Hides this widget from the Perseus.Editor widget select
26286
- widget: ExampleGraphieWidget$1
26287
- };
26288
-
26289
- const ExampleGraphieWidget = ExampleGraphieWidget$2.widget;
26290
- /**
26291
- * This is the widget's editor. This is what shows up on the left side
26292
- * of the screen in the demo page. Only the question writer sees this.
26293
- */
26294
- class ExampleGraphieWidgetEditor extends React.Component {
26295
- constructor(..._args) {
26296
- super(..._args);
26297
- this.change = (...args) => {
26298
- return Changeable.change.apply(this, args);
26299
- };
26300
- this.handleChange = newProps => {
26301
- if (newProps.coord) {
26302
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26303
- this.change({
26304
- correct: newProps.coord
26305
- });
26306
- }
26307
- };
26308
- this.serialize = () => {
26309
- return EditorJsonify.serialize.call(this);
26310
- };
26311
- }
26312
- render() {
26313
- return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(ExampleGraphieWidget, {
26314
- graph: this.props.graph,
26315
- coord: this.props.correct,
26316
- onChange: this.handleChange,
26317
- apiOptions: this.props.apiOptions
26318
- }));
26319
- }
26320
- }
26321
- ExampleGraphieWidgetEditor.propTypes = _extends({}, Changeable.propTypes);
26322
- ExampleGraphieWidgetEditor.widgetName = "example-graphie-widget";
26323
- ExampleGraphieWidgetEditor.defaultProps = {
26324
- correct: [4, 4],
26325
- graph: {
26326
- box: [340, 340],
26327
- labels: ["x", "y"],
26328
- range: [[-10, 10], [-10, 10]],
26329
- step: [1, 1],
26330
- gridStep: [1, 1],
26331
- valid: true,
26332
- backgroundImage: null,
26333
- markings: "grid",
26334
- showProtractor: false
26335
- }
26336
- };
26337
-
26338
- /**
26339
- * This is the widget's editor. This is what shows up on the left side
26340
- * of the screen in the demo. Only the question writer sees this.
26341
- */
26342
- class ExampleWidgetEditor extends React.Component {
26343
- constructor(..._args) {
26344
- super(..._args);
26345
- this.input = /*#__PURE__*/React.createRef();
26346
- this.handleAnswerChange = event => {
26347
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26348
- this.change({
26349
- correct: event.target.value
26350
- });
26351
- };
26352
- this.change = (...args) => {
26353
- return Changeable.change.apply(this, args);
26354
- };
26355
- this.focus = () => {
26356
- var _this$input$current;
26357
- (_this$input$current = this.input.current) == null || _this$input$current.focus();
26358
- return true;
26359
- };
26360
- this.serialize = () => {
26361
- return EditorJsonify.serialize.call(this);
26362
- };
26363
- }
26364
- render() {
26365
- return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "Correct answer:", /*#__PURE__*/React.createElement("input", {
26366
- value: this.props.correct,
26367
- onChange: this.handleAnswerChange,
26368
- ref: this.input
26369
- })));
26370
- }
26371
- }
26372
- ExampleWidgetEditor.propTypes = _extends({}, Changeable.propTypes);
26373
- ExampleWidgetEditor.widgetName = "example-widget";
26374
- ExampleWidgetEditor.defaultProps = {
26375
- correct: ""
26376
- };
26377
-
26378
26157
  const {
26379
- TextInput: TextInput$7
26158
+ TextInput: TextInput$6
26380
26159
  } = components;
26381
26160
  const defaultExplanationProps = {
26382
26161
  showPrompt: "Explain",
@@ -26400,14 +26179,14 @@ class ExplanationEditor extends React.Component {
26400
26179
  className: "perseus-widget-explanation-editor"
26401
26180
  }, /*#__PURE__*/React.createElement("div", {
26402
26181
  className: "perseus-widget-row"
26403
- }, /*#__PURE__*/React.createElement("label", null, "Prompt to show explanation:", " ", /*#__PURE__*/React.createElement(TextInput$7, {
26182
+ }, /*#__PURE__*/React.createElement("label", null, "Prompt to show explanation:", " ", /*#__PURE__*/React.createElement(TextInput$6, {
26404
26183
  value: this.props.showPrompt
26405
26184
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26406
26185
  ,
26407
26186
  onChange: this.change("showPrompt")
26408
26187
  }))), /*#__PURE__*/React.createElement("div", {
26409
26188
  className: "perseus-widget-row"
26410
- }, /*#__PURE__*/React.createElement("label", null, "Prompt to hide explanation:", " ", /*#__PURE__*/React.createElement(TextInput$7, {
26189
+ }, /*#__PURE__*/React.createElement("label", null, "Prompt to hide explanation:", " ", /*#__PURE__*/React.createElement(TextInput$6, {
26411
26190
  value: this.props.hidePrompt
26412
26191
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26413
26192
  ,
@@ -27056,7 +26835,7 @@ const styles$L = StyleSheet.create({
27056
26835
 
27057
26836
  const {
27058
26837
  InlineIcon: InlineIcon$3,
27059
- TextInput: TextInput$6
26838
+ TextInput: TextInput$5
27060
26839
  } = components;
27061
26840
  const {
27062
26841
  iconPlus: iconPlus$1,
@@ -27106,7 +26885,7 @@ class GradedGroupEditor extends React.Component {
27106
26885
  className: "perseus-widget-row"
27107
26886
  }, /*#__PURE__*/React.createElement("label", {
27108
26887
  className: css(styles$K.title)
27109
- }, "Title:", " ", /*#__PURE__*/React.createElement(TextInput$6, {
26888
+ }, "Title:", " ", /*#__PURE__*/React.createElement(TextInput$5, {
27110
26889
  value: this.props.title,
27111
26890
  className: css(styles$K.input)
27112
26891
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
@@ -28084,7 +27863,7 @@ IframeEditor.defaultProps = {
28084
27863
  allowTopNavigation: false
28085
27864
  };
28086
27865
 
28087
- /* eslint-disable jsx-a11y/anchor-is-valid, react/sort-comp */
27866
+ /* eslint-disable jsx-a11y/anchor-is-valid */
28088
27867
  const {
28089
27868
  InfoTip: InfoTip$f,
28090
27869
  InlineIcon: InlineIcon$2,
@@ -28125,48 +27904,6 @@ class ImageEditor extends React.Component {
28125
27904
  componentWillUnmount() {
28126
27905
  this._isMounted = false;
28127
27906
  }
28128
- render() {
28129
- const backgroundImage = this.props.backgroundImage;
28130
- const imageSettings = /*#__PURE__*/React.createElement("div", {
28131
- className: "image-settings"
28132
- }, !Util.isLabeledSVG(backgroundImage.url) && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Preview:"), /*#__PURE__*/React.createElement("img", {
28133
- alt: "Editor preview of image",
28134
- src: backgroundImage.url,
28135
- style: {
28136
- width: "100%"
28137
- }
28138
- }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Dimensions:"), /*#__PURE__*/React.createElement("p", null, backgroundImage.width, "x", backgroundImage.height))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Alt text:", /*#__PURE__*/React.createElement(InfoTip$f, null, "This is important for screenreaders. The content of this alt text will be formatted as markdown (tables, emphasis, etc. are supported).")), /*#__PURE__*/React.createElement(Editor, {
28139
- apiOptions: this.props.apiOptions,
28140
- content: this.props.alt,
28141
- onChange: props => {
28142
- if (props.content != null) {
28143
- this.change("alt", props.content);
28144
- }
28145
- },
28146
- widgetEnabled: false
28147
- }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Caption:"), /*#__PURE__*/React.createElement(Editor, {
28148
- apiOptions: this.props.apiOptions,
28149
- content: this.props.caption,
28150
- onChange: props => {
28151
- if (props.content != null) {
28152
- this.change("caption", props.content);
28153
- }
28154
- },
28155
- widgetEnabled: false
28156
- }))));
28157
- const backgroundImageErrorText = /*#__PURE__*/React.createElement("div", {
28158
- className: "renderer-widget-error"
28159
- }, this.state.backgroundImageError);
28160
- return /*#__PURE__*/React.createElement("div", {
28161
- className: "perseus-image-editor"
28162
- }, /*#__PURE__*/React.createElement("label", null, "Image url:", /*#__PURE__*/React.createElement(InfoTip$f, null, "Paste an image or graphie image URL."), this.state.backgroundImageError && backgroundImageErrorText, /*#__PURE__*/React.createElement(BlurInput, {
28163
- value: backgroundImage.url || "",
28164
- style: {
28165
- width: 332
28166
- },
28167
- onChange: url => this.onUrlChange(url, false)
28168
- })), backgroundImage.url && imageSettings);
28169
- }
28170
27907
  _renderRowForLabel(label, i) {
28171
27908
  return /*#__PURE__*/React.createElement("tr", {
28172
27909
  key: i
@@ -28308,6 +28045,48 @@ class ImageEditor extends React.Component {
28308
28045
  serialize() {
28309
28046
  return EditorJsonify.serialize.call(this);
28310
28047
  }
28048
+ render() {
28049
+ const backgroundImage = this.props.backgroundImage;
28050
+ const imageSettings = /*#__PURE__*/React.createElement("div", {
28051
+ className: "image-settings"
28052
+ }, !Util.isLabeledSVG(backgroundImage.url) && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Preview:"), /*#__PURE__*/React.createElement("img", {
28053
+ alt: "Editor preview of image",
28054
+ src: backgroundImage.url,
28055
+ style: {
28056
+ width: "100%"
28057
+ }
28058
+ }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Dimensions:"), /*#__PURE__*/React.createElement("p", null, backgroundImage.width, "x", backgroundImage.height))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Alt text:", /*#__PURE__*/React.createElement(InfoTip$f, null, "This is important for screenreaders. The content of this alt text will be formatted as markdown (tables, emphasis, etc. are supported).")), /*#__PURE__*/React.createElement(Editor, {
28059
+ apiOptions: this.props.apiOptions,
28060
+ content: this.props.alt,
28061
+ onChange: props => {
28062
+ if (props.content != null) {
28063
+ this.change("alt", props.content);
28064
+ }
28065
+ },
28066
+ widgetEnabled: false
28067
+ }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Caption:"), /*#__PURE__*/React.createElement(Editor, {
28068
+ apiOptions: this.props.apiOptions,
28069
+ content: this.props.caption,
28070
+ onChange: props => {
28071
+ if (props.content != null) {
28072
+ this.change("caption", props.content);
28073
+ }
28074
+ },
28075
+ widgetEnabled: false
28076
+ }))));
28077
+ const backgroundImageErrorText = /*#__PURE__*/React.createElement("div", {
28078
+ className: "renderer-widget-error"
28079
+ }, this.state.backgroundImageError);
28080
+ return /*#__PURE__*/React.createElement("div", {
28081
+ className: "perseus-image-editor"
28082
+ }, /*#__PURE__*/React.createElement("label", null, "Image url:", /*#__PURE__*/React.createElement(InfoTip$f, null, "Paste an image or graphie image URL."), this.state.backgroundImageError && backgroundImageErrorText, /*#__PURE__*/React.createElement(BlurInput, {
28083
+ value: backgroundImage.url || "",
28084
+ style: {
28085
+ width: 332
28086
+ },
28087
+ onChange: url => this.onUrlChange(url, false)
28088
+ })), backgroundImage.url && imageSettings);
28089
+ }
28311
28090
  }
28312
28091
  ImageEditor.displayName = "ImageEditor";
28313
28092
  ImageEditor.widgetName = "image";
@@ -28321,7 +28100,6 @@ ImageEditor.defaultProps = {
28321
28100
  caption: ""
28322
28101
  };
28323
28102
 
28324
- /* eslint-disable react/sort-comp */
28325
28103
  const {
28326
28104
  InfoTip: InfoTip$e
28327
28105
  } = components;
@@ -28609,7 +28387,7 @@ FunctionEditor.defaultProps = {
28609
28387
  };
28610
28388
 
28611
28389
  const {
28612
- TextInput: TextInput$5
28390
+ TextInput: TextInput$4
28613
28391
  } = components;
28614
28392
  const {
28615
28393
  getDependencies: getDependencies$7
@@ -28634,7 +28412,7 @@ class LabelEditor extends React.Component {
28634
28412
  className: "graph-settings"
28635
28413
  }, /*#__PURE__*/React.createElement("div", {
28636
28414
  className: "perseus-widget-row"
28637
- }, /*#__PURE__*/React.createElement(TextInput$5, {
28415
+ }, /*#__PURE__*/React.createElement(TextInput$4, {
28638
28416
  value: this.props.label,
28639
28417
  onChange: this.change("label"),
28640
28418
  style: {
@@ -32734,8 +32512,38 @@ class InteractiveGraphEditor extends React.Component {
32734
32512
  UNSAFE_componentWillMount() {
32735
32513
  DeprecationMixin.UNSAFE_componentWillMount.call(this);
32736
32514
  }
32515
+ // serialize() is what makes copy/paste work. All the properties included
32516
+ // in the serialization json are included when, for example, a graph
32517
+ // is copied from the question editor and pasted into the hint editor
32518
+ // (double brackets in the markdown).
32519
+ serialize() {
32520
+ const json = _.pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showTooltips", "range", "gridStep", "snapStep", "lockedFigures");
32521
+
32522
+ // eslint-disable-next-line react/no-string-refs
32523
+ const graph = this.refs.graph;
32524
+ if (graph) {
32525
+ var _this$props$graph2;
32526
+ // @ts-expect-error TS2339 Property 'getUserInput' does not exist on type 'ReactInstance'. Property 'getUserInput' does not exist on type 'Component<any, {}, any>'.
32527
+ const correct = graph && graph.getUserInput();
32528
+ _.extend(json, {
32529
+ graph: {
32530
+ type: correct.type,
32531
+ startCoords: (_this$props$graph2 = this.props.graph) == null ? void 0 : _this$props$graph2.startCoords
32532
+ },
32533
+ correct: correct
32534
+ });
32535
+ _.each(["allowReflexAngles", "angleOffsetDeg", "numPoints", "numSides", "numSegments", "showAngles", "showSides", "snapTo", "snapDegrees"], function (key) {
32536
+ if (_.has(correct, key)) {
32537
+ // @ts-expect-error - TS2339 - Property 'graph' does not exist on type 'Pick<any, "step" | "range" | "backgroundImage" | "snapStep" | "labels" | "showTooltips" | "markings" | "gridStep" | "showProtractor">'.
32538
+ json.graph[key] = correct[key];
32539
+ }
32540
+ });
32541
+ }
32542
+ // @ts-expect-error TS2739 Type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "step" | "gridStep" | "snapStep" | "backgroundImage" | "markings" | "labels" | ... 5 more ... | "range">' is missing the following properties from type 'PerseusInteractiveGraphWidgetOptions': graph, correct
32543
+ return json;
32544
+ }
32737
32545
  render() {
32738
- var _this$props$graph$typ, _this$props$graph2, _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$graph5, _this$props$apiOption, _this$props$apiOption2, _this$props$apiOption3;
32546
+ var _this$props$graph$typ, _this$props$graph3, _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$graph6, _this$props$apiOption, _this$props$apiOption2, _this$props$apiOption3;
32739
32547
  let graph;
32740
32548
  let equationString;
32741
32549
  const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, interactiveSizes.defaultBoxSize);
@@ -32799,7 +32607,7 @@ class InteractiveGraphEditor extends React.Component {
32799
32607
  return /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(LabeledRow, {
32800
32608
  label: "Type of Graph:"
32801
32609
  }, /*#__PURE__*/React.createElement(GraphTypeSelector, {
32802
- graphType: (_this$props$graph$typ = (_this$props$graph2 = this.props.graph) == null ? void 0 : _this$props$graph2.type) != null ? _this$props$graph$typ : InteractiveGraph.defaultProps.graph.type,
32610
+ 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,
32803
32611
  onChange: type => {
32804
32612
  this.props.onChange({
32805
32613
  graph: {
@@ -32888,8 +32696,8 @@ class InteractiveGraphEditor extends React.Component {
32888
32696
  // Don't show indeterminate checkbox state
32889
32697
  !!((_this$props$correct8 = this.props.correct) != null && _this$props$correct8.showAngles),
32890
32698
  onChange: () => {
32891
- var _this$props$graph3;
32892
- if (((_this$props$graph3 = this.props.graph) == null ? void 0 : _this$props$graph3.type) === "polygon") {
32699
+ var _this$props$graph4;
32700
+ if (((_this$props$graph4 = this.props.graph) == null ? void 0 : _this$props$graph4.type) === "polygon") {
32893
32701
  this.props.onChange({
32894
32702
  correct: _extends({}, this.props.correct, {
32895
32703
  showAngles: !this.props.correct.showAngles
@@ -32908,8 +32716,8 @@ class InteractiveGraphEditor extends React.Component {
32908
32716
  // Don't show indeterminate checkbox state
32909
32717
  !!((_this$props$correct9 = this.props.correct) != null && _this$props$correct9.showSides),
32910
32718
  onChange: () => {
32911
- var _this$props$graph4;
32912
- if (((_this$props$graph4 = this.props.graph) == null ? void 0 : _this$props$graph4.type) === "polygon") {
32719
+ var _this$props$graph5;
32720
+ if (((_this$props$graph5 = this.props.graph) == null ? void 0 : _this$props$graph5.type) === "polygon") {
32913
32721
  this.props.onChange({
32914
32722
  correct: _extends({}, this.props.correct, {
32915
32723
  showSides: !this.props.correct.showSides
@@ -32937,7 +32745,7 @@ class InteractiveGraphEditor extends React.Component {
32937
32745
  }
32938
32746
  });
32939
32747
  }
32940
- })), ((_this$props$graph5 = this.props.graph) == null ? void 0 : _this$props$graph5.type) &&
32748
+ })), ((_this$props$graph6 = this.props.graph) == null ? void 0 : _this$props$graph6.type) &&
32941
32749
  // TODO(LEMS-2228): Remove flags once this is fully released
32942
32750
  shouldShowStartCoordsUI(this.props.apiOptions.flags, this.props.graph) && /*#__PURE__*/React.createElement(StartCoordsSettings, _extends({}, this.props.graph, {
32943
32751
  range: this.props.range,
@@ -33002,36 +32810,6 @@ class InteractiveGraphEditor extends React.Component {
33002
32810
  onChange: this.props.onChange
33003
32811
  }));
33004
32812
  }
33005
- // serialize() is what makes copy/paste work. All the properties included
33006
- // in the serialization json are included when, for example, a graph
33007
- // is copied from the question editor and pasted into the hint editor
33008
- // (double brackets in the markdown).
33009
- serialize() {
33010
- const json = _.pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showTooltips", "range", "gridStep", "snapStep", "lockedFigures");
33011
-
33012
- // eslint-disable-next-line react/no-string-refs
33013
- const graph = this.refs.graph;
33014
- if (graph) {
33015
- var _this$props$graph6;
33016
- // @ts-expect-error TS2339 Property 'getUserInput' does not exist on type 'ReactInstance'. Property 'getUserInput' does not exist on type 'Component<any, {}, any>'.
33017
- const correct = graph && graph.getUserInput();
33018
- _.extend(json, {
33019
- graph: {
33020
- type: correct.type,
33021
- startCoords: (_this$props$graph6 = this.props.graph) == null ? void 0 : _this$props$graph6.startCoords
33022
- },
33023
- correct: correct
33024
- });
33025
- _.each(["allowReflexAngles", "angleOffsetDeg", "numPoints", "numSides", "numSegments", "showAngles", "showSides", "snapTo", "snapDegrees"], function (key) {
33026
- if (_.has(correct, key)) {
33027
- // @ts-expect-error - TS2339 - Property 'graph' does not exist on type 'Pick<any, "step" | "range" | "backgroundImage" | "snapStep" | "labels" | "showTooltips" | "markings" | "gridStep" | "showProtractor">'.
33028
- json.graph[key] = correct[key];
33029
- }
33030
- });
33031
- }
33032
- // @ts-expect-error TS2739 Type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "step" | "gridStep" | "snapStep" | "backgroundImage" | "markings" | "labels" | ... 5 more ... | "range">' is missing the following properties from type 'PerseusInteractiveGraphWidgetOptions': graph, correct
33033
- return json;
33034
- }
33035
32813
  }
33036
32814
  InteractiveGraphEditor.widgetName = "interactive-graph";
33037
32815
  InteractiveGraphEditor.defaultProps = _extends({}, InteractiveGraph.defaultProps, {
@@ -33476,7 +33254,50 @@ const editorStyles = StyleSheet.create({
33476
33254
  }
33477
33255
  });
33478
33256
 
33479
- /* eslint-disable react/sort-comp */
33257
+ /**
33258
+ * Add hover behavior to another component.
33259
+ *
33260
+ * This component provides hover and focus status updates in a consistent way
33261
+ * across desktop and mobile.
33262
+ *
33263
+ * For advice on when to use this component instead of Button, see README.md.
33264
+ *
33265
+ * Many mobile browsers treat :hover as sticky which results in buttons looking
33266
+ * pressed even when the user has lifted their finger. This component ensures
33267
+ * that when user lifts their finger the hover state is removed.
33268
+ *
33269
+ * We also chnage how the focus state works. Browsers immediately set the
33270
+ * focus state as soon as you click on a button. This component only sets the
33271
+ * focus state when a user starts navigating between elements via keybaord.
33272
+ *
33273
+ * HoverBehavior accepts a function as 'children' which is passed state and
33274
+ * an object containing event handlers. The 'children' function should return
33275
+ * an React Element of some sort.
33276
+ *
33277
+ * Example:
33278
+ *
33279
+ * class MyButtonLikeComponent extends React.Component {
33280
+ * render(): React.Node {
33281
+ * return <HoverBehavior
33282
+ * disabled={this.props.disabled}
33283
+ * onClick={this.handleClick}
33284
+ * >
33285
+ * {({hovered}, handlers) =>
33286
+ * <RoundRect
33287
+ * textcolor='white'
33288
+ * backgroundColor={hovered ? 'red' : 'blue'}/>}
33289
+ * {...handlers}
33290
+ * >
33291
+ * {this.props.children}
33292
+ * </RoundRect>
33293
+ * }
33294
+ * </HoverBehavior>
33295
+ * }
33296
+ * }
33297
+ *
33298
+ * This follows a pattern call 'Function as Child Components':
33299
+ * https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9#.sw0jiio8b
33300
+ */
33480
33301
  class HoverBehavior extends React.Component {
33481
33302
  constructor(props) {
33482
33303
  super(props);
@@ -34513,7 +34334,7 @@ const styles = StyleSheet.create({
34513
34334
  }
34514
34335
  });
34515
34336
 
34516
- /* eslint-disable react/forbid-prop-types, react/sort-comp */
34337
+ /* eslint-disable react/forbid-prop-types */
34517
34338
  const {
34518
34339
  InfoTip: InfoTip$a,
34519
34340
  TextListEditor: TextListEditor$3
@@ -34896,7 +34717,7 @@ MeasurerEditor.defaultProps = {
34896
34717
 
34897
34718
  const {
34898
34719
  NumberInput: NumberInput$6,
34899
- TextInput: TextInput$4
34720
+ TextInput: TextInput$3
34900
34721
  } = components;
34901
34722
  class MoleculeWidgetEditor extends React.Component {
34902
34723
  constructor(..._args) {
@@ -34921,7 +34742,7 @@ class MoleculeWidgetEditor extends React.Component {
34921
34742
  };
34922
34743
  }
34923
34744
  render() {
34924
- return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "SMILES:\xA0", /*#__PURE__*/React.createElement(TextInput$4, {
34745
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "SMILES:\xA0", /*#__PURE__*/React.createElement(TextInput$3, {
34925
34746
  onChange: this.updateMolecule,
34926
34747
  value: this.props.smiles
34927
34748
  }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "Rotation (deg):\xA0", /*#__PURE__*/React.createElement(NumberInput$6, {
@@ -35254,14 +35075,14 @@ NumberLineEditor.defaultProps = {
35254
35075
  showTooltips: false
35255
35076
  };
35256
35077
 
35257
- /* eslint-disable jsx-a11y/anchor-is-valid, react/sort-comp */
35078
+ /* eslint-disable jsx-a11y/anchor-is-valid */
35258
35079
  const {
35259
35080
  ButtonGroup,
35260
35081
  InfoTip: InfoTip$7,
35261
35082
  InlineIcon: InlineIcon$1,
35262
35083
  MultiButtonGroup,
35263
35084
  NumberInput: NumberInput$4,
35264
- TextInput: TextInput$3
35085
+ TextInput: TextInput$2
35265
35086
  } = components;
35266
35087
  const {
35267
35088
  iconGear,
@@ -35476,7 +35297,7 @@ class NumericInputEditor extends React.Component {
35476
35297
  }));
35477
35298
  const labelText = /*#__PURE__*/React.createElement("div", {
35478
35299
  className: "perseus-widget-row"
35479
- }, /*#__PURE__*/React.createElement("label", null, "Aria label", /*#__PURE__*/React.createElement(TextInput$3, {
35300
+ }, /*#__PURE__*/React.createElement("label", null, "Aria label", /*#__PURE__*/React.createElement(TextInput$2, {
35480
35301
  value: this.props.labelText,
35481
35302
  onChange: this.change("labelText")
35482
35303
  })), /*#__PURE__*/React.createElement(InfoTip$7, null, /*#__PURE__*/React.createElement("p", null, "Text to describe this input. This will be shown to users using screenreaders.")));
@@ -35838,7 +35659,7 @@ PassageEditor.defaultProps = {
35838
35659
  const {
35839
35660
  InfoTip: InfoTip$4,
35840
35661
  NumberInput: NumberInput$3,
35841
- TextInput: TextInput$2
35662
+ TextInput: TextInput$1
35842
35663
  } = components;
35843
35664
  class PassageRefEditor extends React.Component {
35844
35665
  constructor(..._args) {
@@ -35861,7 +35682,7 @@ class PassageRefEditor extends React.Component {
35861
35682
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
35862
35683
  ,
35863
35684
  onChange: this.change("referenceNumber")
35864
- }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "Summary Text: ", /*#__PURE__*/React.createElement(TextInput$2, {
35685
+ }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "Summary Text: ", /*#__PURE__*/React.createElement(TextInput$1, {
35865
35686
  value: this.props.summaryText
35866
35687
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
35867
35688
  ,
@@ -35915,14 +35736,32 @@ PassageRefTargetEditor.defaultProps = {
35915
35736
 
35916
35737
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
35917
35738
  class PhetSimulationEditor extends React.Component {
35739
+ constructor(...args) {
35740
+ super(...args);
35741
+ this.getSaveWarnings = () => {
35742
+ if (makeSafeUrl(this.props.url, "en") === null) {
35743
+ return ["Please enter a URL from the PhET domain."];
35744
+ }
35745
+ return [];
35746
+ };
35747
+ }
35748
+ serialize() {
35749
+ return {
35750
+ url: this.props.url,
35751
+ description: this.props.description
35752
+ };
35753
+ }
35918
35754
  render() {
35919
35755
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(LabeledTextField, {
35920
35756
  label: "URL",
35921
35757
  value: this.props.url,
35922
35758
  onChange: url => this.props.onChange({
35923
35759
  url
35924
- })
35925
- }), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(LabeledTextField, {
35760
+ }),
35761
+ style: {
35762
+ marginBottom: spacing.large_24
35763
+ }
35764
+ }), /*#__PURE__*/React.createElement(LabeledTextField, {
35926
35765
  label: "Description",
35927
35766
  value: this.props.description,
35928
35767
  onChange: description => this.props.onChange({
@@ -35930,12 +35769,6 @@ class PhetSimulationEditor extends React.Component {
35930
35769
  })
35931
35770
  }));
35932
35771
  }
35933
- serialize() {
35934
- return {
35935
- url: this.props.url,
35936
- description: this.props.description
35937
- };
35938
- }
35939
35772
  }
35940
35773
  PhetSimulationEditor.defaultProps = {
35941
35774
  url: "",
@@ -36257,7 +36090,7 @@ PlotterEditor.defaultProps = _extends({}, editorDefaults, {
36257
36090
  */
36258
36091
  const {
36259
36092
  NumberInput: NumberInput$1,
36260
- TextInput: TextInput$1
36093
+ TextInput
36261
36094
  } = components;
36262
36095
  function validateOptions(height, programID) {
36263
36096
  const errors = [];
@@ -36291,7 +36124,7 @@ class PythonProgramEditor extends React.Component {
36291
36124
  };
36292
36125
  }
36293
36126
  render() {
36294
- return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "User Program ID:", " ", /*#__PURE__*/React.createElement(TextInput$1, {
36127
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, "User Program ID:", " ", /*#__PURE__*/React.createElement(TextInput, {
36295
36128
  value: this.props.programID,
36296
36129
  onChange: this.change("programID"),
36297
36130
  placeholder: "123"
@@ -36603,62 +36436,6 @@ RadioEditor.defaultProps = {
36603
36436
  deselectEnabled: false
36604
36437
  };
36605
36438
 
36606
- class TextArea extends React.Component {
36607
- constructor(...args) {
36608
- super(...args);
36609
- this.focus = () => {
36610
- // eslint-disable-next-line react/no-string-refs
36611
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
36612
- this.refs.input.focus();
36613
- return true;
36614
- };
36615
- this.changeValue = e => {
36616
- // Translating from the js event e to the value
36617
- // of the textbox to send to onChange
36618
- this.props.onChange(e.target.value);
36619
- };
36620
- }
36621
- render() {
36622
- return /*#__PURE__*/React.createElement("textarea", {
36623
- // eslint-disable-next-line react/no-string-refs
36624
- ref: "input",
36625
- value: this.props.value || "",
36626
- onChange: this.changeValue
36627
- });
36628
- }
36629
- }
36630
- class SimpleMarkdownTesterEditor extends React.Component {
36631
- constructor(..._args) {
36632
- super(..._args);
36633
- this.input = /*#__PURE__*/React.createRef();
36634
- this.change = (...args) => {
36635
- return Changeable.change.apply(this, args);
36636
- };
36637
- this.focus = () => {
36638
- var _this$input$current;
36639
- (_this$input$current = this.input.current) == null || _this$input$current.focus();
36640
- return true;
36641
- };
36642
- this.serialize = () => {
36643
- return EditorJsonify.serialize.call(this);
36644
- };
36645
- }
36646
- render() {
36647
- return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("div", null, "Simple markdown contents:"), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(TextArea, {
36648
- value: this.props.value
36649
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
36650
- ,
36651
- onChange: this.change("value"),
36652
- ref: this.input
36653
- }))));
36654
- }
36655
- }
36656
- SimpleMarkdownTesterEditor.propTypes = _extends({}, Changeable.propTypes);
36657
- SimpleMarkdownTesterEditor.widgetName = "simple-markdown-tester";
36658
- SimpleMarkdownTesterEditor.defaultProps = {
36659
- value: ""
36660
- };
36661
-
36662
36439
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
36663
36440
  const {
36664
36441
  InfoTip: InfoTip$2,
@@ -36722,7 +36499,6 @@ SorterEditor.defaultProps = {
36722
36499
  padding: true
36723
36500
  };
36724
36501
 
36725
- /* eslint-disable react/sort-comp */
36726
36502
  const {
36727
36503
  InfoTip: InfoTip$1,
36728
36504
  NumberInput
@@ -36889,219 +36665,12 @@ VideoEditor.defaultProps = {
36889
36665
  location: ""
36890
36666
  };
36891
36667
 
36892
- var AllEditors = [CategorizerEditor, CSProgramEditor, DefinitionEditor, DropdownEditor, ExampleGraphieWidgetEditor, ExampleWidgetEditor, ExplanationEditor, ExpressionEditor, GradedGroupEditor, GradedGroupSetEditor, GrapherEditor, GroupEditor, IframeEditor, ImageEditor, InputNumberEditor, InteractionEditor, InteractiveGraphEditor, LabelImageEditor, MatcherEditor, MatrixEditor, MeasurerEditor, MoleculeWidgetEditor, NumberLineEditor, NumericInputEditor, OrdererEditor, PassageEditor, PassageRefEditor, PassageRefTargetEditor, PhetSimulationEditor, PlotterEditor, PythonProgramEditor, SimpleMarkdownTesterEditor, SorterEditor, TableEditor, VideoEditor, RadioEditor, DeprecatedStandinEditor];
36893
-
36894
- /* eslint-disable @khanacademy/ts-no-error-suppressions */
36895
- class TextInput extends React.Component {
36896
- constructor(...args) {
36897
- super(...args);
36898
- this.input = /*#__PURE__*/React.createRef();
36899
- this.focus = () => {
36900
- var _this$input$current;
36901
- (_this$input$current = this.input.current) == null || _this$input$current.focus();
36902
- return true;
36903
- };
36904
- this.changeValue = e => {
36905
- // Translating from the js event e to the value
36906
- // of the textbox to send to onChange
36907
- this.props.onChange(e.target.value);
36908
- };
36909
- }
36910
- render() {
36911
- return /*#__PURE__*/React.createElement("input", {
36912
- ref: this.input,
36913
- value: this.props.value || "",
36914
- onChange: this.changeValue
36915
- });
36916
- }
36917
- }
36918
- /**
36919
- * This is the widget's renderer. It shows up in the right column
36920
- * in the demo, and is what is visible to users, and where
36921
- * users enter their answers.
36922
- */
36923
- class ExampleWidget extends React.Component {
36924
- constructor(..._args) {
36925
- super(..._args);
36926
- this.input = /*#__PURE__*/React.createRef();
36927
- /**
36928
- * Tell our parent to update our props.
36929
- */
36930
- this.change = (...args) => {
36931
- return Changeable.change.apply(this, args);
36932
- };
36933
- this.getUserInput = () => {
36934
- return this.props.value;
36935
- };
36936
- /**
36937
- * Widgets that are focusable should add a focus method that returns
36938
- * true if focusing succeeded. The first such widget found will be
36939
- * focused on page load.
36940
- */
36941
- this.focus = () => {
36942
- var _this$input$current2;
36943
- (_this$input$current2 = this.input.current) == null || _this$input$current2.focus();
36944
- return true;
36945
- };
36946
- /**
36947
- * simpleValidate is called for grading. Rubric is the result of calling
36948
- * getUserInput() on the editor that created this widget.
36949
- *
36950
- * Should return an object representing the grading result, such as
36951
- * {
36952
- * type: "points",
36953
- * earned: 1,
36954
- * total: 1,
36955
- * message: null
36956
- * }
36957
- */
36958
- this.simpleValidate = rubric => {
36959
- return ExampleWidget.validate(this.getUserInput(), rubric);
36960
- };
36961
- }
36962
- /**
36963
- * This is the widget's grading function. simpleValidate generally
36964
- * defers to this function.
36965
- *
36966
- * value is usually the result of getUserInput on the widget
36967
- * rubric is the result of calling serialize() on the editor
36968
- */
36969
- static validate(value, rubric) {
36970
- if (value === "") {
36971
- return {
36972
- type: "invalid",
36973
- message: "It looks like you haven't answered all of the " + "question yet."
36974
- };
36975
- }
36976
- if (value === rubric.correct) {
36977
- return {
36978
- type: "points",
36979
- earned: 1,
36980
- total: 1,
36981
- message: null
36982
- };
36983
- }
36984
- return {
36985
- type: "points",
36986
- earned: 0,
36987
- total: 1,
36988
- message: null
36989
- };
36990
- }
36991
- render() {
36992
- return /*#__PURE__*/React.createElement(TextInput, {
36993
- ref: this.input,
36994
- value: this.props.value
36995
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
36996
- ,
36997
- onChange: this.change("value")
36998
- });
36999
- }
37000
- }
37001
-
37002
- /**
37003
- * For this widget to work, we must import this file in src/all-widgets.js
37004
- */
37005
- ExampleWidget.defaultProps = {
37006
- value: ""
37007
- };
37008
- var ExampleWidget$1 = {
37009
- name: "example-widget",
37010
- displayName: "Example Widget",
37011
- // Tell the renderer what type of `display:` style we would like
37012
- // for the component wrapping this one.
37013
- defaultAlignment: "inline-block",
37014
- hidden: true,
37015
- // Hides this widget from the Perseus.Editor widget select
37016
- widget: ExampleWidget
37017
- };
37018
-
37019
- /* eslint-disable react/sort-comp */
37020
- const mdParse = PerseusMarkdown.parse;
37021
- const mdOutput = PerseusMarkdown.basicOutput;
37022
- class SimpleMarkdownTester extends React.Component {
37023
- constructor(..._args) {
37024
- super(..._args);
37025
- this.change = (...args) => {
37026
- return Changeable.change.apply(this, args);
37027
- };
37028
- this.toJSON = () => {
37029
- return {};
37030
- };
37031
- /**
37032
- * Widgets that are focusable should add a focus method that returns
37033
- * true if focusing succeeded. The first such widget found will be
37034
- * focused on page load.
37035
- */
37036
- this.focus = () => {
37037
- // eslint-disable-next-line react/no-string-refs
37038
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
37039
- this.refs.input.focus();
37040
- return true;
37041
- };
37042
- /**
37043
- * simpleValidate is called for grading. Rubric is the result of calling
37044
- * toJSON() on the editor that created this widget.
37045
- *
37046
- * Should return an object representing the grading result, such as
37047
- * {
37048
- * type: "points",
37049
- * earned: 1,
37050
- * total: 1,
37051
- * message: null
37052
- * }
37053
- */
37054
- this.simpleValidate = rubric => {
37055
- return SimpleMarkdownTester.validate(this.toJSON(), rubric);
37056
- };
37057
- }
37058
- /**
37059
- * This is the widget's grading function.
37060
- *
37061
- * simpleValidate generally defers to this function
37062
- *
37063
- * state is usually the result of toJSON on the widget
37064
- * rubric is the result of calling toJSON() on the editor
37065
- */
37066
- static validate(state, rubric) {
37067
- return {
37068
- type: "points",
37069
- earned: 0,
37070
- total: 0,
37071
- message: null
37072
- };
37073
- }
37074
- render() {
37075
- // @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
37076
- const parsed = mdParse(this.props.value);
37077
- const output = mdOutput(parsed);
37078
- return /*#__PURE__*/React.createElement("div", null, output);
37079
- }
37080
- }
37081
-
37082
- /**
37083
- * For this widget to work, we must import this file in src/all-widgets.js
37084
- */
37085
- SimpleMarkdownTester.defaultProps = {
37086
- value: ""
37087
- };
37088
- var SimpleMarkdownTester$1 = {
37089
- name: "simple-markdown-tester",
37090
- displayName: "Simple Markdown Tester",
37091
- hidden: true,
37092
- // Hides this widget from the Perseus.Editor widget select
37093
- widget: SimpleMarkdownTester,
37094
- transform: _.identity
37095
- };
37096
-
37097
- var testingWidgets = [ExampleGraphieWidget$2, ExampleWidget$1, SimpleMarkdownTester$1];
37098
-
37099
- var AllWidgets = [...widgets, ...testingWidgets];
36668
+ var AllEditors = [CategorizerEditor, CSProgramEditor, DefinitionEditor, DropdownEditor, ExplanationEditor, ExpressionEditor, GradedGroupEditor, GradedGroupSetEditor, GrapherEditor, GroupEditor, IframeEditor, ImageEditor, InputNumberEditor, InteractionEditor, InteractiveGraphEditor, LabelImageEditor, MatcherEditor, MatrixEditor, MeasurerEditor, MoleculeWidgetEditor, NumberLineEditor, NumericInputEditor, OrdererEditor, PassageEditor, PassageRefEditor, PassageRefTargetEditor, PhetSimulationEditor, PlotterEditor, PythonProgramEditor, SorterEditor, TableEditor, VideoEditor, RadioEditor, DeprecatedStandinEditor];
37100
36669
 
37101
36670
  Widgets.registerEditors(AllEditors);
37102
- Widgets.registerWidgets(AllWidgets);
36671
+ Widgets.registerWidgets(widgets);
37103
36672
  Widgets.replaceDeprecatedWidgets();
37104
36673
  Widgets.replaceDeprecatedEditors();
37105
36674
 
37106
- export { AllEditors, AllWidgets, ArticleDiff, ArticleEditor, DeviceFramer, Editor, EditorPage, IframeContentRenderer, ItemDiff, MultiRendererEditor, StatefulEditorPage, StructuredItemDiff, ViewportResizer, i18n, libVersion };
36675
+ export { AllEditors, ArticleDiff, ArticleEditor, DeviceFramer, Editor, EditorPage, IframeContentRenderer, ItemDiff, MultiRendererEditor, StatefulEditorPage, StructuredItemDiff, ViewportResizer, i18n, libVersion };
37107
36676
  //# sourceMappingURL=index.js.map