@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/index.js CHANGED
@@ -19,12 +19,12 @@ var caretRight = require('@phosphor-icons/core/bold/caret-right-bold.svg');
19
19
  var classNames = require('classnames');
20
20
  var wonderBlocksForm = require('@khanacademy/wonder-blocks-form');
21
21
  var ReactDOM = require('react-dom');
22
- var kmath = require('@khanacademy/kmath');
23
22
  var KAS = require('@khanacademy/kas');
24
23
  var Button = require('@khanacademy/wonder-blocks-button');
25
24
  var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
26
25
  var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
27
26
  var mathInput = require('@khanacademy/math-input');
27
+ var kmath = require('@khanacademy/kmath');
28
28
  var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
29
29
  var wonderBlocksAccordion = require('@khanacademy/wonder-blocks-accordion');
30
30
  var IconButton = require('@khanacademy/wonder-blocks-icon-button');
@@ -91,7 +91,7 @@ var arrowCounterClockwise__default = /*#__PURE__*/_interopDefaultLegacy(arrowCou
91
91
 
92
92
  // This file is processed by a Rollup plugin (replace) to inject the production
93
93
  const libName = "@khanacademy/perseus-editor";
94
- const libVersion = "13.0.1";
94
+ const libVersion = "14.0.0";
95
95
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
96
96
 
97
97
  function _extends() {
@@ -188,16 +188,6 @@ const JsonEditor = createReactClass__default["default"]({
188
188
  this.setState(this.getInitialState());
189
189
  }
190
190
  },
191
- render: function () {
192
- const classes = "perseus-json-editor " + (this.state.valid ? "valid" : "invalid");
193
- return /*#__PURE__*/React__namespace.createElement("textarea", {
194
- className: classes,
195
- value: this.state.currentValue,
196
- onChange: this.handleChange,
197
- onKeyDown: this.handleKeyDown,
198
- onBlur: this.handleBlur
199
- });
200
- },
201
191
  handleKeyDown: function (e) {
202
192
  // This handler allows the tab character to be entered by pressing
203
193
  // tab, instead of jumping to the next (non-existant) field
@@ -264,6 +254,16 @@ const JsonEditor = createReactClass__default["default"]({
264
254
  valid: true
265
255
  });
266
256
  }
257
+ },
258
+ render: function () {
259
+ const classes = "perseus-json-editor " + (this.state.valid ? "valid" : "invalid");
260
+ return /*#__PURE__*/React__namespace.createElement("textarea", {
261
+ className: classes,
262
+ value: this.state.currentValue,
263
+ onChange: this.handleChange,
264
+ onKeyDown: this.handleKeyDown,
265
+ onBlur: this.handleBlur
266
+ });
267
267
  }
268
268
  });
269
269
 
@@ -25549,7 +25549,7 @@ const styles$N = aphrodite.StyleSheet.create({
25549
25549
  }
25550
25550
  });
25551
25551
 
25552
- /* eslint-disable react/no-unsafe, react/sort-comp */
25552
+ /* eslint-disable react/no-unsafe */
25553
25553
 
25554
25554
  /* Renders an EditorPage (or an ArticleEditor) as a non-controlled component.
25555
25555
  *
@@ -25568,10 +25568,6 @@ const StatefulEditorPage = createReactClass__default["default"]({
25568
25568
  componentClass: EditorPage
25569
25569
  };
25570
25570
  },
25571
- render: function () {
25572
- const Component = this.props.componentClass;
25573
- return /*#__PURE__*/React__namespace.createElement(Component, this.state);
25574
- },
25575
25571
  getInitialState: function () {
25576
25572
  return ___default["default"]({}).extend(___default["default"].omit(this.props, "componentClass"), {
25577
25573
  onChange: this.handleChange,
@@ -25581,9 +25577,6 @@ const StatefulEditorPage = createReactClass__default["default"]({
25581
25577
  componentDidMount: function () {
25582
25578
  this._isMounted = true;
25583
25579
  },
25584
- componentWillUnmount: function () {
25585
- this._isMounted = false;
25586
- },
25587
25580
  // getInitialState isn't called if the react component is re-rendered
25588
25581
  // in-place on the dom, in which case this is called instead, so we
25589
25582
  // need to update the state here.
@@ -25591,6 +25584,9 @@ const StatefulEditorPage = createReactClass__default["default"]({
25591
25584
  UNSAFE_componentWillReceiveProps: function (nextProps) {
25592
25585
  this.setState(___default["default"](nextProps).pick("apiOptions", "imageUploader", "developerMode", "problemNum", "previewDevice", "frameSource"));
25593
25586
  },
25587
+ componentWillUnmount: function () {
25588
+ this._isMounted = false;
25589
+ },
25594
25590
  getSaveWarnings: function () {
25595
25591
  // eslint-disable-next-line react/no-string-refs
25596
25592
  return this.refs.editor.getSaveWarnings();
@@ -25607,6 +25603,10 @@ const StatefulEditorPage = createReactClass__default["default"]({
25607
25603
  scorePreview: function () {
25608
25604
  // eslint-disable-next-line react/no-string-refs
25609
25605
  return this.refs.editor.scorePreview();
25606
+ },
25607
+ render: function () {
25608
+ const Component = this.props.componentClass;
25609
+ return /*#__PURE__*/React__namespace.createElement(Component, this.state);
25610
25610
  }
25611
25611
  });
25612
25612
 
@@ -25955,7 +25955,7 @@ class CSProgramEditor extends React__namespace.Component {
25955
25955
 
25956
25956
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
25957
25957
  const {
25958
- TextInput: TextInput$8
25958
+ TextInput: TextInput$7
25959
25959
  } = perseus.components;
25960
25960
  class DefinitionEditor extends React__namespace.Component {
25961
25961
  static propTypes = {
@@ -25989,7 +25989,7 @@ class DefinitionEditor extends React__namespace.Component {
25989
25989
  target: "_blank"
25990
25990
  }, "Definition style guide"), /*#__PURE__*/React__namespace.createElement("div", {
25991
25991
  className: "perseus-widget-row"
25992
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Word to be defined:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$8, {
25992
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Word to be defined:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$7, {
25993
25993
  value: this.props.togglePrompt
25994
25994
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
25995
25995
  ,
@@ -26170,236 +26170,9 @@ class DropdownEditor extends React__namespace.Component {
26170
26170
  }
26171
26171
  }
26172
26172
 
26173
- /* eslint-disable @typescript-eslint/no-unused-vars, react/forbid-prop-types, react/sort-comp */
26174
- const {
26175
- Graphie
26176
- } = perseus.components;
26177
-
26178
- // @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
26179
- const MovablePoint = Graphie.MovablePoint;
26180
- /**
26181
- * This is the widget's renderer. It shows up in the right column
26182
- * in the demo, and is what is visible to users, and where
26183
- * users enter their answers.
26184
- */
26185
- class ExampleGraphieWidget$1 extends React__namespace.Component {
26186
- static defaultProps = {
26187
- // We want to allow our coord to be null to test if the
26188
- // user has interacted with this widget yet when grading it
26189
- coord: null,
26190
- graph: {
26191
- box: [400, 400],
26192
- labels: ["x", "y"],
26193
- range: [[-10, 10], [-10, 10]],
26194
- step: [1, 1],
26195
- gridStep: [1, 1],
26196
- valid: true,
26197
- backgroundImage: null,
26198
- markings: "grid",
26199
- showProtractor: false
26200
- }
26201
- };
26202
-
26203
- /**
26204
- * This is the widget's grading function
26205
- */
26206
- static validate(state, rubric) {
26207
- if (state.coord == null) {
26208
- return {
26209
- type: "invalid",
26210
- message: null
26211
- };
26212
- }
26213
- if (kmath.point.equal(state.coord, rubric.correct)) {
26214
- return {
26215
- type: "points",
26216
- earned: 1,
26217
- total: 1,
26218
- message: null
26219
- };
26220
- }
26221
- return {
26222
- type: "points",
26223
- earned: 0,
26224
- total: 1,
26225
- message: null
26226
- };
26227
- }
26228
- getUserInput = () => {
26229
- return perseus.WidgetJsonifyDeprecated.getUserInput.call(this);
26230
- };
26231
- render() {
26232
- return /*#__PURE__*/React__namespace.createElement(Graphie
26233
- // eslint-disable-next-line react/no-string-refs
26234
- , {
26235
- ref: "graphie",
26236
- box: this.props.graph.box,
26237
- range: this.props.graph.range,
26238
- options: this.props.graph,
26239
- setup: this.setupGraphie,
26240
- setDrawingAreaAvailable: this.props.apiOptions?.setDrawingAreaAvailable
26241
- }, /*#__PURE__*/React__namespace.createElement(MovablePoint, {
26242
- pointSize: 5,
26243
- coord: this.props.coord || [0, 0],
26244
- constraints: [MovablePoint.constraints.snap(), MovablePoint.constraints.bound()],
26245
- onMove: this.movePoint
26246
- }));
26247
- }
26248
- change = (() => {
26249
- var _this = this;
26250
- return function () {
26251
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
26252
- args[_key] = arguments[_key];
26253
- }
26254
- return perseus.Changeable.change.apply(_this, args);
26255
- };
26256
- })();
26257
- movePoint = newCoord => {
26258
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26259
- this.change({
26260
- coord: newCoord
26261
- });
26262
- };
26263
- _getGridConfig = options => {
26264
- return ___default["default"].map(options.step, function (step, i) {
26265
- return perseus.Util.gridDimensionConfig(step, options.range[i], options.box[i], options.gridStep[i]);
26266
- });
26267
- };
26268
- setupGraphie = (graphie, options) => {
26269
- const gridConfig = this._getGridConfig(options);
26270
- graphie.graphInit({
26271
- range: options.range,
26272
- scale: ___default["default"].pluck(gridConfig, "scale"),
26273
- axisArrows: "<->",
26274
- labelFormat: function (s) {
26275
- return "\\small{" + s + "}";
26276
- },
26277
- gridStep: options.gridStep,
26278
- tickStep: ___default["default"].pluck(gridConfig, "tickStep"),
26279
- labelStep: 1,
26280
- unityLabels: ___default["default"].pluck(gridConfig, "unityLabel")
26281
- });
26282
- graphie.label([0, options.range[1][1]], options.labels[1], "above");
26283
- };
26284
- simpleValidate = rubric => {
26285
- return ExampleGraphieWidget$1.validate(this.getUserInput(), rubric);
26286
- };
26287
- }
26288
-
26289
- /**
26290
- * For this widget to work, we must export it.
26291
- * We also must import this file in src/all-widgets.js
26292
- */
26293
- var ExampleGraphieWidget$2 = {
26294
- name: "example-graphie-widget",
26295
- displayName: "Example Graphie Widget",
26296
- hidden: true,
26297
- // Hides this widget from the Perseus.Editor widget select
26298
- widget: ExampleGraphieWidget$1
26299
- };
26300
-
26301
- const ExampleGraphieWidget = ExampleGraphieWidget$2.widget;
26302
- /**
26303
- * This is the widget's editor. This is what shows up on the left side
26304
- * of the screen in the demo page. Only the question writer sees this.
26305
- */
26306
- class ExampleGraphieWidgetEditor extends React__namespace.Component {
26307
- static propTypes = {
26308
- ...perseus.Changeable.propTypes
26309
- };
26310
- static widgetName = "example-graphie-widget";
26311
- static defaultProps = {
26312
- correct: [4, 4],
26313
- graph: {
26314
- box: [340, 340],
26315
- labels: ["x", "y"],
26316
- range: [[-10, 10], [-10, 10]],
26317
- step: [1, 1],
26318
- gridStep: [1, 1],
26319
- valid: true,
26320
- backgroundImage: null,
26321
- markings: "grid",
26322
- showProtractor: false
26323
- }
26324
- };
26325
- change = (() => {
26326
- var _this = this;
26327
- return function () {
26328
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
26329
- args[_key] = arguments[_key];
26330
- }
26331
- return perseus.Changeable.change.apply(_this, args);
26332
- };
26333
- })();
26334
- handleChange = newProps => {
26335
- if (newProps.coord) {
26336
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26337
- this.change({
26338
- correct: newProps.coord
26339
- });
26340
- }
26341
- };
26342
- serialize = () => {
26343
- return perseus.EditorJsonify.serialize.call(this);
26344
- };
26345
- render() {
26346
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(ExampleGraphieWidget, {
26347
- graph: this.props.graph,
26348
- coord: this.props.correct,
26349
- onChange: this.handleChange,
26350
- apiOptions: this.props.apiOptions
26351
- }));
26352
- }
26353
- }
26354
-
26355
- /* eslint-disable react/sort-comp */
26356
- /**
26357
- * This is the widget's editor. This is what shows up on the left side
26358
- * of the screen in the demo. Only the question writer sees this.
26359
- */
26360
- class ExampleWidgetEditor extends React__namespace.Component {
26361
- static propTypes = {
26362
- ...perseus.Changeable.propTypes
26363
- };
26364
- static widgetName = "example-widget";
26365
- static defaultProps = {
26366
- correct: ""
26367
- };
26368
- input = /*#__PURE__*/React__namespace.createRef();
26369
- handleAnswerChange = event => {
26370
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26371
- this.change({
26372
- correct: event.target.value
26373
- });
26374
- };
26375
- render() {
26376
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Correct answer:", /*#__PURE__*/React__namespace.createElement("input", {
26377
- value: this.props.correct,
26378
- onChange: this.handleAnswerChange,
26379
- ref: this.input
26380
- })));
26381
- }
26382
- change = (() => {
26383
- var _this = this;
26384
- return function () {
26385
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
26386
- args[_key] = arguments[_key];
26387
- }
26388
- return perseus.Changeable.change.apply(_this, args);
26389
- };
26390
- })();
26391
- focus = () => {
26392
- this.input.current?.focus();
26393
- return true;
26394
- };
26395
- serialize = () => {
26396
- return perseus.EditorJsonify.serialize.call(this);
26397
- };
26398
- }
26399
-
26400
26173
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
26401
26174
  const {
26402
- TextInput: TextInput$7
26175
+ TextInput: TextInput$6
26403
26176
  } = perseus.components;
26404
26177
  const defaultExplanationProps = {
26405
26178
  showPrompt: "Explain",
@@ -26436,14 +26209,14 @@ class ExplanationEditor extends React__namespace.Component {
26436
26209
  className: "perseus-widget-explanation-editor"
26437
26210
  }, /*#__PURE__*/React__namespace.createElement("div", {
26438
26211
  className: "perseus-widget-row"
26439
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Prompt to show explanation:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$7, {
26212
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Prompt to show explanation:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$6, {
26440
26213
  value: this.props.showPrompt
26441
26214
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26442
26215
  ,
26443
26216
  onChange: this.change("showPrompt")
26444
26217
  }))), /*#__PURE__*/React__namespace.createElement("div", {
26445
26218
  className: "perseus-widget-row"
26446
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Prompt to hide explanation:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$7, {
26219
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Prompt to hide explanation:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$6, {
26447
26220
  value: this.props.hidePrompt
26448
26221
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
26449
26222
  ,
@@ -26718,101 +26491,6 @@ class ExpressionEditor extends React__namespace.Component {
26718
26491
  }
26719
26492
  return perseus.Changeable.change.apply(this, args);
26720
26493
  }
26721
- render() {
26722
- const answerOptions = this.props.answerForms.map(ans => {
26723
- const key = parseAnswerKey(ans);
26724
- const expressionProps = {
26725
- // note we're using
26726
- // *this.props*.{times,functions,buttonSets} since each
26727
- // answer area has the same settings for those
26728
- times: this.props.times,
26729
- functions: this.props.functions,
26730
- buttonSets: this.props.buttonSets,
26731
- buttonsVisible: "focused",
26732
- form: ans.form,
26733
- simplify: ans.simplify,
26734
- value: ans.value,
26735
- onChange: props => this.updateForm(key, props),
26736
- trackInteraction: () => {},
26737
- widgetId: this.props.widgetId + "-" + ans.key
26738
- };
26739
- return lens(ans).merge([], {
26740
- key,
26741
- draggable: true,
26742
- onChange: props => this.updateForm(Number.parseInt(ans.key ?? ""), props),
26743
- onDelete: () => this.handleRemoveForm(key),
26744
- expressionProps: expressionProps
26745
- }).freeze();
26746
- }).map(obj => /*#__PURE__*/React__namespace.createElement(AnswerOption, _extends({
26747
- key: obj.key
26748
- }, obj)));
26749
- const sortable = /*#__PURE__*/React__namespace.createElement(SortableArea, {
26750
- components: answerOptions,
26751
- onReorder: this.handleReorder
26752
- });
26753
-
26754
- // checkboxes to choose which sets of input buttons are shown
26755
- const buttonSetChoices = buttonSetsList.map(name => {
26756
- // The first one gets special cased to always be checked, disabled,
26757
- // and float left.
26758
- const isBasic = name === "basic";
26759
- const checked = this.props.buttonSets.includes(name) || isBasic;
26760
- return /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
26761
- key: name,
26762
- label: name,
26763
- checked: checked,
26764
- disabled: isBasic,
26765
- onChange: () => this.handleButtonSet(name)
26766
- });
26767
- });
26768
- buttonSetChoices.unshift( /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
26769
- key: "show \xF7 button",
26770
- label: "show \xF7 button",
26771
- checked: this.props.buttonSets.includes("basic+div"),
26772
- onChange: this.handleToggleDiv
26773
- }));
26774
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.HeadingSmall, null, "Global Options"), /*#__PURE__*/React__namespace.createElement("div", {
26775
- className: aphrodite.css(styles$L.paddedY)
26776
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
26777
- label: "Visible label",
26778
- value: this.props.visibleLabel || "",
26779
- onChange: this.change("visibleLabel")
26780
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."))), /*#__PURE__*/React__namespace.createElement("div", {
26781
- className: aphrodite.css(styles$L.paddedY)
26782
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
26783
- label: "Aria label",
26784
- value: this.props.ariaLabel || "",
26785
- onChange: this.change("ariaLabel")
26786
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see", " ", /*#__PURE__*/React__namespace.createElement("a", {
26787
- href: "https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",
26788
- target: "_blank"
26789
- }, "this article.")))), /*#__PURE__*/React__namespace.createElement("div", {
26790
- className: aphrodite.css(styles$L.paddedY)
26791
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
26792
- label: "Function variables",
26793
- value: this.state.functionsInternal,
26794
- onChange: this.handleFunctions
26795
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means \"f of x\" and not \"f times x\"."))), /*#__PURE__*/React__namespace.createElement("div", {
26796
- className: aphrodite.css(styles$L.paddedY)
26797
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
26798
- label: "Use \xD7 instead of \u22C5 for multiplication",
26799
- checked: this.props.times,
26800
- onChange: value => {
26801
- this.props.onChange({
26802
- times: value
26803
- });
26804
- }
26805
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."))), /*#__PURE__*/React__namespace.createElement("div", {
26806
- className: aphrodite.css(styles$L.paddedY)
26807
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.HeadingXSmall, null, "Button Sets"), buttonSetChoices), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.HeadingSmall, null, "Answers"), /*#__PURE__*/React__namespace.createElement("p", {
26808
- style: {
26809
- margin: "4px 0"
26810
- }
26811
- }, "student responses area matched against these from top to bottom"), sortable, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
26812
- size: "small",
26813
- onClick: this.newAnswer
26814
- }, "Add new answer")));
26815
- }
26816
26494
  serialize = () => {
26817
26495
  const formSerializables = ["value", "form", "simplify", "considered",
26818
26496
  // it's a little weird to serialize the react key, but saves some
@@ -26953,6 +26631,101 @@ class ExpressionEditor extends React__namespace.Component {
26953
26631
  newProps.functions = value.split(/[ ,]+/).filter(wonderStuffCore.isTruthy);
26954
26632
  this.props.onChange(newProps);
26955
26633
  };
26634
+ render() {
26635
+ const answerOptions = this.props.answerForms.map(ans => {
26636
+ const key = parseAnswerKey(ans);
26637
+ const expressionProps = {
26638
+ // note we're using
26639
+ // *this.props*.{times,functions,buttonSets} since each
26640
+ // answer area has the same settings for those
26641
+ times: this.props.times,
26642
+ functions: this.props.functions,
26643
+ buttonSets: this.props.buttonSets,
26644
+ buttonsVisible: "focused",
26645
+ form: ans.form,
26646
+ simplify: ans.simplify,
26647
+ value: ans.value,
26648
+ onChange: props => this.updateForm(key, props),
26649
+ trackInteraction: () => {},
26650
+ widgetId: this.props.widgetId + "-" + ans.key
26651
+ };
26652
+ return lens(ans).merge([], {
26653
+ key,
26654
+ draggable: true,
26655
+ onChange: props => this.updateForm(Number.parseInt(ans.key ?? ""), props),
26656
+ onDelete: () => this.handleRemoveForm(key),
26657
+ expressionProps: expressionProps
26658
+ }).freeze();
26659
+ }).map(obj => /*#__PURE__*/React__namespace.createElement(AnswerOption, _extends({
26660
+ key: obj.key
26661
+ }, obj)));
26662
+ const sortable = /*#__PURE__*/React__namespace.createElement(SortableArea, {
26663
+ components: answerOptions,
26664
+ onReorder: this.handleReorder
26665
+ });
26666
+
26667
+ // checkboxes to choose which sets of input buttons are shown
26668
+ const buttonSetChoices = buttonSetsList.map(name => {
26669
+ // The first one gets special cased to always be checked, disabled,
26670
+ // and float left.
26671
+ const isBasic = name === "basic";
26672
+ const checked = this.props.buttonSets.includes(name) || isBasic;
26673
+ return /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
26674
+ key: name,
26675
+ label: name,
26676
+ checked: checked,
26677
+ disabled: isBasic,
26678
+ onChange: () => this.handleButtonSet(name)
26679
+ });
26680
+ });
26681
+ buttonSetChoices.unshift( /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
26682
+ key: "show \xF7 button",
26683
+ label: "show \xF7 button",
26684
+ checked: this.props.buttonSets.includes("basic+div"),
26685
+ onChange: this.handleToggleDiv
26686
+ }));
26687
+ return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.HeadingSmall, null, "Global Options"), /*#__PURE__*/React__namespace.createElement("div", {
26688
+ className: aphrodite.css(styles$L.paddedY)
26689
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
26690
+ label: "Visible label",
26691
+ value: this.props.visibleLabel || "",
26692
+ onChange: this.change("visibleLabel")
26693
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."))), /*#__PURE__*/React__namespace.createElement("div", {
26694
+ className: aphrodite.css(styles$L.paddedY)
26695
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
26696
+ label: "Aria label",
26697
+ value: this.props.ariaLabel || "",
26698
+ onChange: this.change("ariaLabel")
26699
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see", " ", /*#__PURE__*/React__namespace.createElement("a", {
26700
+ href: "https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",
26701
+ target: "_blank"
26702
+ }, "this article.")))), /*#__PURE__*/React__namespace.createElement("div", {
26703
+ className: aphrodite.css(styles$L.paddedY)
26704
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
26705
+ label: "Function variables",
26706
+ value: this.state.functionsInternal,
26707
+ onChange: this.handleFunctions
26708
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means \"f of x\" and not \"f times x\"."))), /*#__PURE__*/React__namespace.createElement("div", {
26709
+ className: aphrodite.css(styles$L.paddedY)
26710
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
26711
+ label: "Use \xD7 instead of \u22C5 for multiplication",
26712
+ checked: this.props.times,
26713
+ onChange: value => {
26714
+ this.props.onChange({
26715
+ times: value
26716
+ });
26717
+ }
26718
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."))), /*#__PURE__*/React__namespace.createElement("div", {
26719
+ className: aphrodite.css(styles$L.paddedY)
26720
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.HeadingXSmall, null, "Button Sets"), buttonSetChoices), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.HeadingSmall, null, "Answers"), /*#__PURE__*/React__namespace.createElement("p", {
26721
+ style: {
26722
+ margin: "4px 0"
26723
+ }
26724
+ }, "student responses area matched against these from top to bottom"), sortable, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
26725
+ size: "small",
26726
+ onClick: this.newAnswer
26727
+ }, "Add new answer")));
26728
+ }
26956
26729
  }
26957
26730
 
26958
26731
  // Find the next element in arr after val, wrapping around to the first.
@@ -26974,6 +26747,25 @@ class AnswerOption extends React__namespace.Component {
26974
26747
  return perseus.Changeable.change.apply(_this, args);
26975
26748
  };
26976
26749
  })();
26750
+ handleImSure = () => {
26751
+ this.props.onDelete();
26752
+ };
26753
+ handleCancelDelete = () => {
26754
+ this.setState({
26755
+ deleteFocused: false
26756
+ });
26757
+ };
26758
+ handleDelete = () => {
26759
+ this.setState({
26760
+ deleteFocused: true
26761
+ });
26762
+ };
26763
+ toggleConsidered = () => {
26764
+ const newVal = findNextIn(perseus.PerseusExpressionAnswerFormConsidered, this.props.considered);
26765
+ this.change({
26766
+ considered: newVal
26767
+ });
26768
+ };
26977
26769
  render() {
26978
26770
  const removeButton = this.state.deleteFocused ? /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
26979
26771
  size: "small",
@@ -27025,25 +26817,6 @@ class AnswerOption extends React__namespace.Component {
27025
26817
  className: aphrodite.css(styles$L.buttonRow, styles$L.paddedY)
27026
26818
  }, removeButton)));
27027
26819
  }
27028
- handleImSure = () => {
27029
- this.props.onDelete();
27030
- };
27031
- handleCancelDelete = () => {
27032
- this.setState({
27033
- deleteFocused: false
27034
- });
27035
- };
27036
- handleDelete = () => {
27037
- this.setState({
27038
- deleteFocused: true
27039
- });
27040
- };
27041
- toggleConsidered = () => {
27042
- const newVal = findNextIn(perseus.PerseusExpressionAnswerFormConsidered, this.props.considered);
27043
- this.change({
27044
- considered: newVal
27045
- });
27046
- };
27047
26820
  }
27048
26821
  const styles$L = aphrodite.StyleSheet.create({
27049
26822
  paddedX: {
@@ -27092,7 +26865,7 @@ const styles$L = aphrodite.StyleSheet.create({
27092
26865
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
27093
26866
  const {
27094
26867
  InlineIcon: InlineIcon$3,
27095
- TextInput: TextInput$6
26868
+ TextInput: TextInput$5
27096
26869
  } = perseus.components;
27097
26870
  const {
27098
26871
  iconPlus: iconPlus$1,
@@ -27141,6 +26914,16 @@ class GradedGroupEditor extends React__namespace.Component {
27141
26914
  hint: null
27142
26915
  });
27143
26916
  };
26917
+ getSaveWarnings = () => {
26918
+ return this.editor.current?.getSaveWarnings();
26919
+ };
26920
+ serialize = () => {
26921
+ return {
26922
+ title: this.props.title,
26923
+ ...this.editor.current?.serialize(),
26924
+ hint: this.hintEditor.current?.serialize()
26925
+ };
26926
+ };
27144
26927
  render() {
27145
26928
  return /*#__PURE__*/React__namespace.createElement("div", {
27146
26929
  className: "perseus-group-editor"
@@ -27148,7 +26931,7 @@ class GradedGroupEditor extends React__namespace.Component {
27148
26931
  className: "perseus-widget-row"
27149
26932
  }, /*#__PURE__*/React__namespace.createElement("label", {
27150
26933
  className: aphrodite.css(styles$K.title)
27151
- }, "Title:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$6, {
26934
+ }, "Title:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$5, {
27152
26935
  value: this.props.title,
27153
26936
  className: aphrodite.css(styles$K.input)
27154
26937
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
@@ -27196,16 +26979,6 @@ class GradedGroupEditor extends React__namespace.Component {
27196
26979
  onClick: this.handleRemoveHint
27197
26980
  }, /*#__PURE__*/React__namespace.createElement(InlineIcon$3, iconTrash$2), " Remove this hint")));
27198
26981
  }
27199
- getSaveWarnings = () => {
27200
- return this.editor.current?.getSaveWarnings();
27201
- };
27202
- serialize = () => {
27203
- return {
27204
- title: this.props.title,
27205
- ...this.editor.current?.serialize(),
27206
- hint: this.hintEditor.current?.serialize()
27207
- };
27208
- };
27209
26982
  }
27210
26983
  const styles$K = aphrodite.StyleSheet.create({
27211
26984
  title: {
@@ -27839,6 +27612,26 @@ class GrapherEditor extends React__namespace.Component {
27839
27612
  return perseus.Changeable.change.apply(_this, args);
27840
27613
  };
27841
27614
  })();
27615
+ handleAvailableTypesChange = newAvailableTypes => {
27616
+ let correct = this.props.correct;
27617
+
27618
+ // If the currently 'correct' type is removed from the list of types,
27619
+ // we need to change it to avoid impossible questions.
27620
+ if (!___default["default"].contains(newAvailableTypes, this.props.correct.type)) {
27621
+ const graph = this.props.graph;
27622
+ const newType = chooseType(newAvailableTypes);
27623
+ correct = defaultPlotProps(newType, graph);
27624
+ }
27625
+ this.props.onChange({
27626
+ availableTypes: newAvailableTypes,
27627
+ correct: correct
27628
+ });
27629
+ };
27630
+ serialize = () => {
27631
+ return ___default["default"].chain(this.props).pick("correct", "availableTypes").extend({
27632
+ graph: ___default["default"].omit(this.props.graph, "box")
27633
+ }).value();
27634
+ };
27842
27635
  render() {
27843
27636
  const sizeClass = containerSizeClass$1.SMALL;
27844
27637
  let equationString;
@@ -27904,26 +27697,6 @@ class GrapherEditor extends React__namespace.Component {
27904
27697
  onChange: this.handleAvailableTypesChange
27905
27698
  })), graph);
27906
27699
  }
27907
- handleAvailableTypesChange = newAvailableTypes => {
27908
- let correct = this.props.correct;
27909
-
27910
- // If the currently 'correct' type is removed from the list of types,
27911
- // we need to change it to avoid impossible questions.
27912
- if (!___default["default"].contains(newAvailableTypes, this.props.correct.type)) {
27913
- const graph = this.props.graph;
27914
- const newType = chooseType(newAvailableTypes);
27915
- correct = defaultPlotProps(newType, graph);
27916
- }
27917
- this.props.onChange({
27918
- availableTypes: newAvailableTypes,
27919
- correct: correct
27920
- });
27921
- };
27922
- serialize = () => {
27923
- return ___default["default"].chain(this.props).pick("correct", "availableTypes").extend({
27924
- graph: ___default["default"].omit(this.props.graph, "box")
27925
- }).value();
27926
- };
27927
27700
  }
27928
27701
 
27929
27702
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
@@ -27946,20 +27719,6 @@ class GroupEditor extends React__namespace.Component {
27946
27719
  metadata: undefined
27947
27720
  };
27948
27721
  editor = /*#__PURE__*/React__namespace.createRef();
27949
- render() {
27950
- return /*#__PURE__*/React__namespace.createElement("div", {
27951
- className: "perseus-group-editor"
27952
- }, /*#__PURE__*/React__namespace.createElement("div", null, this._renderMetadataEditor()), /*#__PURE__*/React__namespace.createElement(Editor, {
27953
- ref: this.editor,
27954
- content: this.props.content,
27955
- widgets: this.props.widgets,
27956
- apiOptions: this.props.apiOptions,
27957
- images: this.props.images,
27958
- widgetEnabled: true,
27959
- immutableWidgets: false,
27960
- onChange: this.props.onChange
27961
- }));
27962
- }
27963
27722
  _renderMetadataEditor = () => {
27964
27723
  const GroupMetadataEditor = this.props.apiOptions.GroupMetadataEditor;
27965
27724
  return /*#__PURE__*/React__namespace.createElement(GroupMetadataEditor, {
@@ -27986,6 +27745,20 @@ class GroupEditor extends React__namespace.Component {
27986
27745
  metadata: this.props.metadata
27987
27746
  });
27988
27747
  };
27748
+ render() {
27749
+ return /*#__PURE__*/React__namespace.createElement("div", {
27750
+ className: "perseus-group-editor"
27751
+ }, /*#__PURE__*/React__namespace.createElement("div", null, this._renderMetadataEditor()), /*#__PURE__*/React__namespace.createElement(Editor, {
27752
+ ref: this.editor,
27753
+ content: this.props.content,
27754
+ widgets: this.props.widgets,
27755
+ apiOptions: this.props.apiOptions,
27756
+ images: this.props.images,
27757
+ widgetEnabled: true,
27758
+ immutableWidgets: false,
27759
+ onChange: this.props.onChange
27760
+ }));
27761
+ }
27989
27762
  }
27990
27763
 
27991
27764
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
@@ -28011,6 +27784,9 @@ class PairEditor extends React__namespace.Component {
28011
27784
  return perseus.Changeable.change.apply(_this, args);
28012
27785
  };
28013
27786
  })();
27787
+ serialize = () => {
27788
+ return perseus.EditorJsonify.serialize.call(this);
27789
+ };
28014
27790
  render() {
28015
27791
  return /*#__PURE__*/React__namespace.createElement("fieldset", null, /*#__PURE__*/React__namespace.createElement("label", null, "Name:", /*#__PURE__*/React__namespace.createElement(BlurInput, {
28016
27792
  value: this.props.name,
@@ -28020,9 +27796,6 @@ class PairEditor extends React__namespace.Component {
28020
27796
  onChange: this.change("value")
28021
27797
  })));
28022
27798
  }
28023
- serialize = () => {
28024
- return perseus.EditorJsonify.serialize.call(this);
28025
- };
28026
27799
  }
28027
27800
  /**
28028
27801
  * This is used for editing a set of name/value pairs.
@@ -28035,19 +27808,6 @@ class PairsEditor extends React__namespace.Component {
28035
27808
  value: PropTypes__default["default"].string
28036
27809
  })).isRequired
28037
27810
  };
28038
- render() {
28039
- const editors = ___default["default"].map(this.props.pairs, (pair, i) => {
28040
- return /*#__PURE__*/React__namespace.createElement(PairEditor, {
28041
- key: i,
28042
- name: pair.name,
28043
- value: pair.value
28044
- // eslint-disable-next-line react/jsx-no-bind
28045
- ,
28046
- onChange: this.handlePairChange.bind(this, i)
28047
- });
28048
- });
28049
- return /*#__PURE__*/React__namespace.createElement("div", null, editors);
28050
- }
28051
27811
  change = (() => {
28052
27812
  var _this2 = this;
28053
27813
  return function () {
@@ -28073,6 +27833,19 @@ class PairsEditor extends React__namespace.Component {
28073
27833
  serialize = () => {
28074
27834
  return perseus.EditorJsonify.serialize.call(this);
28075
27835
  };
27836
+ render() {
27837
+ const editors = ___default["default"].map(this.props.pairs, (pair, i) => {
27838
+ return /*#__PURE__*/React__namespace.createElement(PairEditor, {
27839
+ key: i,
27840
+ name: pair.name,
27841
+ value: pair.value
27842
+ // eslint-disable-next-line react/jsx-no-bind
27843
+ ,
27844
+ onChange: this.handlePairChange.bind(this, i)
27845
+ });
27846
+ });
27847
+ return /*#__PURE__*/React__namespace.createElement("div", null, editors);
27848
+ }
28076
27849
  }
28077
27850
  /**
28078
27851
  * This is the main editor for this widget, to specify all the options.
@@ -28102,6 +27875,15 @@ class IframeEditor extends React__namespace.Component {
28102
27875
  return perseus.Changeable.change.apply(_this3, args);
28103
27876
  };
28104
27877
  })();
27878
+ handleSettingsChange = settings => {
27879
+ // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
27880
+ this.change({
27881
+ settings: settings.pairs
27882
+ });
27883
+ };
27884
+ serialize = () => {
27885
+ return perseus.EditorJsonify.serialize.call(this);
27886
+ };
28105
27887
  render() {
28106
27888
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
28107
27889
  style: {
@@ -28145,18 +27927,9 @@ class IframeEditor extends React__namespace.Component {
28145
27927
  }
28146
27928
  }));
28147
27929
  }
28148
- handleSettingsChange = settings => {
28149
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
28150
- this.change({
28151
- settings: settings.pairs
28152
- });
28153
- };
28154
- serialize = () => {
28155
- return perseus.EditorJsonify.serialize.call(this);
28156
- };
28157
27930
  }
28158
27931
 
28159
- /* eslint-disable jsx-a11y/anchor-is-valid, react/sort-comp */
27932
+ /* eslint-disable jsx-a11y/anchor-is-valid */
28160
27933
  const {
28161
27934
  InfoTip: InfoTip$f,
28162
27935
  InlineIcon: InlineIcon$2,
@@ -28182,9 +27955,9 @@ const INTERNALLY_HOSTED_URL_RE = new RegExp("^(https?|web\\+graphie)://[^/]*" +
28182
27955
  */
28183
27956
  const captionAlignments = ["center", "above", "above right", "right", "below right", "below", "below left", "left", "above left"];
28184
27957
  class ImageEditor extends React__namespace.Component {
28185
- _isMounted = false;
28186
27958
  static displayName = "ImageEditor";
28187
27959
  static widgetName = "image";
27960
+ _isMounted = false;
28188
27961
  static defaultProps = {
28189
27962
  title: "",
28190
27963
  range: [defaultRange, defaultRange],
@@ -28205,48 +27978,6 @@ class ImageEditor extends React__namespace.Component {
28205
27978
  componentWillUnmount() {
28206
27979
  this._isMounted = false;
28207
27980
  }
28208
- render() {
28209
- const backgroundImage = this.props.backgroundImage;
28210
- const imageSettings = /*#__PURE__*/React__namespace.createElement("div", {
28211
- className: "image-settings"
28212
- }, !perseus.Util.isLabeledSVG(backgroundImage.url) && /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Preview:"), /*#__PURE__*/React__namespace.createElement("img", {
28213
- alt: "Editor preview of image",
28214
- src: backgroundImage.url,
28215
- style: {
28216
- width: "100%"
28217
- }
28218
- }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Dimensions:"), /*#__PURE__*/React__namespace.createElement("p", null, backgroundImage.width, "x", backgroundImage.height))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Alt text:", /*#__PURE__*/React__namespace.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__namespace.createElement(Editor, {
28219
- apiOptions: this.props.apiOptions,
28220
- content: this.props.alt,
28221
- onChange: props => {
28222
- if (props.content != null) {
28223
- this.change("alt", props.content);
28224
- }
28225
- },
28226
- widgetEnabled: false
28227
- }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Caption:"), /*#__PURE__*/React__namespace.createElement(Editor, {
28228
- apiOptions: this.props.apiOptions,
28229
- content: this.props.caption,
28230
- onChange: props => {
28231
- if (props.content != null) {
28232
- this.change("caption", props.content);
28233
- }
28234
- },
28235
- widgetEnabled: false
28236
- }))));
28237
- const backgroundImageErrorText = /*#__PURE__*/React__namespace.createElement("div", {
28238
- className: "renderer-widget-error"
28239
- }, this.state.backgroundImageError);
28240
- return /*#__PURE__*/React__namespace.createElement("div", {
28241
- className: "perseus-image-editor"
28242
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Image url:", /*#__PURE__*/React__namespace.createElement(InfoTip$f, null, "Paste an image or graphie image URL."), this.state.backgroundImageError && backgroundImageErrorText, /*#__PURE__*/React__namespace.createElement(BlurInput, {
28243
- value: backgroundImage.url || "",
28244
- style: {
28245
- width: 332
28246
- },
28247
- onChange: url => this.onUrlChange(url, false)
28248
- })), backgroundImage.url && imageSettings);
28249
- }
28250
27981
  _renderRowForLabel(label, i) {
28251
27982
  return /*#__PURE__*/React__namespace.createElement("tr", {
28252
27983
  key: i
@@ -28391,9 +28122,50 @@ class ImageEditor extends React__namespace.Component {
28391
28122
  serialize() {
28392
28123
  return perseus.EditorJsonify.serialize.call(this);
28393
28124
  }
28125
+ render() {
28126
+ const backgroundImage = this.props.backgroundImage;
28127
+ const imageSettings = /*#__PURE__*/React__namespace.createElement("div", {
28128
+ className: "image-settings"
28129
+ }, !perseus.Util.isLabeledSVG(backgroundImage.url) && /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Preview:"), /*#__PURE__*/React__namespace.createElement("img", {
28130
+ alt: "Editor preview of image",
28131
+ src: backgroundImage.url,
28132
+ style: {
28133
+ width: "100%"
28134
+ }
28135
+ }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Dimensions:"), /*#__PURE__*/React__namespace.createElement("p", null, backgroundImage.width, "x", backgroundImage.height))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Alt text:", /*#__PURE__*/React__namespace.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__namespace.createElement(Editor, {
28136
+ apiOptions: this.props.apiOptions,
28137
+ content: this.props.alt,
28138
+ onChange: props => {
28139
+ if (props.content != null) {
28140
+ this.change("alt", props.content);
28141
+ }
28142
+ },
28143
+ widgetEnabled: false
28144
+ }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("div", null, "Caption:"), /*#__PURE__*/React__namespace.createElement(Editor, {
28145
+ apiOptions: this.props.apiOptions,
28146
+ content: this.props.caption,
28147
+ onChange: props => {
28148
+ if (props.content != null) {
28149
+ this.change("caption", props.content);
28150
+ }
28151
+ },
28152
+ widgetEnabled: false
28153
+ }))));
28154
+ const backgroundImageErrorText = /*#__PURE__*/React__namespace.createElement("div", {
28155
+ className: "renderer-widget-error"
28156
+ }, this.state.backgroundImageError);
28157
+ return /*#__PURE__*/React__namespace.createElement("div", {
28158
+ className: "perseus-image-editor"
28159
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Image url:", /*#__PURE__*/React__namespace.createElement(InfoTip$f, null, "Paste an image or graphie image URL."), this.state.backgroundImageError && backgroundImageErrorText, /*#__PURE__*/React__namespace.createElement(BlurInput, {
28160
+ value: backgroundImage.url || "",
28161
+ style: {
28162
+ width: 332
28163
+ },
28164
+ onChange: url => this.onUrlChange(url, false)
28165
+ })), backgroundImage.url && imageSettings);
28166
+ }
28394
28167
  }
28395
28168
 
28396
- /* eslint-disable react/sort-comp */
28397
28169
  const {
28398
28170
  InfoTip: InfoTip$e
28399
28171
  } = perseus.components;
@@ -28450,6 +28222,19 @@ class InputNumberEditor extends React__namespace.Component {
28450
28222
  value: value
28451
28223
  });
28452
28224
  };
28225
+ focus = () => {
28226
+ this.input.current?.focus();
28227
+ return true;
28228
+ };
28229
+ serialize = () => ({
28230
+ value: this.props.value,
28231
+ simplify: this.props.simplify,
28232
+ size: this.props.size,
28233
+ inexact: this.props.inexact,
28234
+ maxError: this.props.maxError,
28235
+ answerType: this.props.answerType,
28236
+ rightAlign: this.props.rightAlign
28237
+ });
28453
28238
  render() {
28454
28239
  const answerTypeOptions = ___default["default"].map(answerTypes, function (v, k) {
28455
28240
  return /*#__PURE__*/React__namespace.createElement("option", {
@@ -28533,19 +28318,6 @@ class InputNumberEditor extends React__namespace.Component {
28533
28318
  }
28534
28319
  }), " ", "Right alignment")));
28535
28320
  }
28536
- focus = () => {
28537
- this.input.current?.focus();
28538
- return true;
28539
- };
28540
- serialize = () => ({
28541
- value: this.props.value,
28542
- simplify: this.props.simplify,
28543
- size: this.props.size,
28544
- inexact: this.props.inexact,
28545
- maxError: this.props.maxError,
28546
- answerType: this.props.answerType,
28547
- rightAlign: this.props.rightAlign
28548
- });
28549
28321
  }
28550
28322
 
28551
28323
  /**
@@ -28681,7 +28453,7 @@ class FunctionEditor extends React__namespace.Component {
28681
28453
  }
28682
28454
 
28683
28455
  const {
28684
- TextInput: TextInput$5
28456
+ TextInput: TextInput$4
28685
28457
  } = perseus.components;
28686
28458
  const {
28687
28459
  getDependencies: getDependencies$7
@@ -28715,7 +28487,7 @@ class LabelEditor extends React__namespace.Component {
28715
28487
  className: "graph-settings"
28716
28488
  }, /*#__PURE__*/React__namespace.createElement("div", {
28717
28489
  className: "perseus-widget-row"
28718
- }, /*#__PURE__*/React__namespace.createElement(TextInput$5, {
28490
+ }, /*#__PURE__*/React__namespace.createElement(TextInput$4, {
28719
28491
  value: this.props.label,
28720
28492
  onChange: this.change("label"),
28721
28493
  style: {
@@ -32831,9 +32603,9 @@ const POLYGON_SIDES = ___default["default"].map(___default["default"].range(3, 1
32831
32603
  * Used in the exercise editor.
32832
32604
  */
32833
32605
  class InteractiveGraphEditor extends React__namespace.Component {
32606
+ static widgetName = "interactive-graph";
32834
32607
  displayName = "InteractiveGraphEditor";
32835
32608
  className = "perseus-widget-interactive-graph";
32836
- static widgetName = "interactive-graph";
32837
32609
  static defaultProps = {
32838
32610
  ...InteractiveGraph.defaultProps,
32839
32611
  valid: true,
@@ -32852,6 +32624,68 @@ class InteractiveGraphEditor extends React__namespace.Component {
32852
32624
  UNSAFE_componentWillMount() {
32853
32625
  DeprecationMixin.UNSAFE_componentWillMount.call(this);
32854
32626
  }
32627
+ changeMatchType = newValue => {
32628
+ const correct = {
32629
+ ...this.props.correct,
32630
+ match: newValue
32631
+ };
32632
+ this.props.onChange({
32633
+ correct: correct
32634
+ });
32635
+ };
32636
+ changeStartCoords = coords => {
32637
+ if (!this.props.graph?.type) {
32638
+ return;
32639
+ }
32640
+ const graph = {
32641
+ ...this.props.graph,
32642
+ startCoords: coords
32643
+ };
32644
+ this.props.onChange({
32645
+ graph: graph
32646
+ });
32647
+ };
32648
+
32649
+ // serialize() is what makes copy/paste work. All the properties included
32650
+ // in the serialization json are included when, for example, a graph
32651
+ // is copied from the question editor and pasted into the hint editor
32652
+ // (double brackets in the markdown).
32653
+ serialize() {
32654
+ const json = ___default["default"].pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showTooltips", "range", "gridStep", "snapStep", "lockedFigures");
32655
+
32656
+ // eslint-disable-next-line react/no-string-refs
32657
+ const graph = this.refs.graph;
32658
+ if (graph) {
32659
+ // @ts-expect-error TS2339 Property 'getUserInput' does not exist on type 'ReactInstance'. Property 'getUserInput' does not exist on type 'Component<any, {}, any>'.
32660
+ const correct = graph && graph.getUserInput();
32661
+ ___default["default"].extend(json, {
32662
+ graph: {
32663
+ type: correct.type,
32664
+ startCoords: this.props.graph?.startCoords
32665
+ },
32666
+ correct: correct
32667
+ });
32668
+ ___default["default"].each(["allowReflexAngles", "angleOffsetDeg", "numPoints", "numSides", "numSegments", "showAngles", "showSides", "snapTo", "snapDegrees"], function (key) {
32669
+ if (___default["default"].has(correct, key)) {
32670
+ // @ts-expect-error - TS2339 - Property 'graph' does not exist on type 'Pick<any, "step" | "range" | "backgroundImage" | "snapStep" | "labels" | "showTooltips" | "markings" | "gridStep" | "showProtractor">'.
32671
+ json.graph[key] = correct[key];
32672
+ }
32673
+ });
32674
+ }
32675
+ // @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
32676
+ return json;
32677
+ }
32678
+ getSaveWarnings = () => {
32679
+ const issues = [];
32680
+
32681
+ // A locked line on the graph cannot have length 0.
32682
+ for (const figure of this.props.lockedFigures ?? []) {
32683
+ if (figure.type === "line" && kmath.vector.equal(figure.points[0].coord, figure.points[1].coord)) {
32684
+ issues.push("The line cannot have length 0.");
32685
+ }
32686
+ }
32687
+ return issues;
32688
+ };
32855
32689
  render() {
32856
32690
  let graph;
32857
32691
  let equationString;
@@ -33127,68 +32961,6 @@ class InteractiveGraphEditor extends React__namespace.Component {
33127
32961
  onChange: this.props.onChange
33128
32962
  }));
33129
32963
  }
33130
- changeMatchType = newValue => {
33131
- const correct = {
33132
- ...this.props.correct,
33133
- match: newValue
33134
- };
33135
- this.props.onChange({
33136
- correct: correct
33137
- });
33138
- };
33139
- changeStartCoords = coords => {
33140
- if (!this.props.graph?.type) {
33141
- return;
33142
- }
33143
- const graph = {
33144
- ...this.props.graph,
33145
- startCoords: coords
33146
- };
33147
- this.props.onChange({
33148
- graph: graph
33149
- });
33150
- };
33151
-
33152
- // serialize() is what makes copy/paste work. All the properties included
33153
- // in the serialization json are included when, for example, a graph
33154
- // is copied from the question editor and pasted into the hint editor
33155
- // (double brackets in the markdown).
33156
- serialize() {
33157
- const json = ___default["default"].pick(this.props, "step", "backgroundImage", "markings", "labels", "showProtractor", "showTooltips", "range", "gridStep", "snapStep", "lockedFigures");
33158
-
33159
- // eslint-disable-next-line react/no-string-refs
33160
- const graph = this.refs.graph;
33161
- if (graph) {
33162
- // @ts-expect-error TS2339 Property 'getUserInput' does not exist on type 'ReactInstance'. Property 'getUserInput' does not exist on type 'Component<any, {}, any>'.
33163
- const correct = graph && graph.getUserInput();
33164
- ___default["default"].extend(json, {
33165
- graph: {
33166
- type: correct.type,
33167
- startCoords: this.props.graph?.startCoords
33168
- },
33169
- correct: correct
33170
- });
33171
- ___default["default"].each(["allowReflexAngles", "angleOffsetDeg", "numPoints", "numSides", "numSegments", "showAngles", "showSides", "snapTo", "snapDegrees"], function (key) {
33172
- if (___default["default"].has(correct, key)) {
33173
- // @ts-expect-error - TS2339 - Property 'graph' does not exist on type 'Pick<any, "step" | "range" | "backgroundImage" | "snapStep" | "labels" | "showTooltips" | "markings" | "gridStep" | "showProtractor">'.
33174
- json.graph[key] = correct[key];
33175
- }
33176
- });
33177
- }
33178
- // @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
33179
- return json;
33180
- }
33181
- getSaveWarnings = () => {
33182
- const issues = [];
33183
-
33184
- // A locked line on the graph cannot have length 0.
33185
- for (const figure of this.props.lockedFigures ?? []) {
33186
- if (figure.type === "line" && kmath.vector.equal(figure.points[0].coord, figure.points[1].coord)) {
33187
- issues.push("The line cannot have length 0.");
33188
- }
33189
- }
33190
- return issues;
33191
- };
33192
32964
  }
33193
32965
  const styles$a = aphrodite.StyleSheet.create({
33194
32966
  singleSelectShort: {
@@ -33637,8 +33409,55 @@ const editorStyles = aphrodite.StyleSheet.create({
33637
33409
  }
33638
33410
  });
33639
33411
 
33640
- /* eslint-disable react/sort-comp */
33412
+ /**
33413
+ * Add hover behavior to another component.
33414
+ *
33415
+ * This component provides hover and focus status updates in a consistent way
33416
+ * across desktop and mobile.
33417
+ *
33418
+ * For advice on when to use this component instead of Button, see README.md.
33419
+ *
33420
+ * Many mobile browsers treat :hover as sticky which results in buttons looking
33421
+ * pressed even when the user has lifted their finger. This component ensures
33422
+ * that when user lifts their finger the hover state is removed.
33423
+ *
33424
+ * We also chnage how the focus state works. Browsers immediately set the
33425
+ * focus state as soon as you click on a button. This component only sets the
33426
+ * focus state when a user starts navigating between elements via keybaord.
33427
+ *
33428
+ * HoverBehavior accepts a function as 'children' which is passed state and
33429
+ * an object containing event handlers. The 'children' function should return
33430
+ * an React Element of some sort.
33431
+ *
33432
+ * Example:
33433
+ *
33434
+ * class MyButtonLikeComponent extends React.Component {
33435
+ * render(): React.Node {
33436
+ * return <HoverBehavior
33437
+ * disabled={this.props.disabled}
33438
+ * onClick={this.handleClick}
33439
+ * >
33440
+ * {({hovered}, handlers) =>
33441
+ * <RoundRect
33442
+ * textcolor='white'
33443
+ * backgroundColor={hovered ? 'red' : 'blue'}/>}
33444
+ * {...handlers}
33445
+ * >
33446
+ * {this.props.children}
33447
+ * </RoundRect>
33448
+ * }
33449
+ * </HoverBehavior>
33450
+ * }
33451
+ * }
33452
+ *
33453
+ * This follows a pattern call 'Function as Child Components':
33454
+ * https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9#.sw0jiio8b
33455
+ */
33641
33456
  class HoverBehavior extends React__namespace.Component {
33457
+ // @ts-expect-error - TS2564 - Property 'focusFlag' has no initializer and is not definitely assigned in the constructor.
33458
+ focusFlag;
33459
+ // @ts-expect-error - TS2564 - Property 'waitingForClick' has no initializer and is not definitely assigned in the constructor.
33460
+ waitingForClick;
33642
33461
  static defaultProps = {
33643
33462
  startHovered: false,
33644
33463
  shouldUpdate: () => true
@@ -33650,11 +33469,6 @@ class HoverBehavior extends React__namespace.Component {
33650
33469
  hovered: props.startHovered
33651
33470
  };
33652
33471
  }
33653
-
33654
- // @ts-expect-error - TS2564 - Property 'focusFlag' has no initializer and is not definitely assigned in the constructor.
33655
- focusFlag;
33656
- // @ts-expect-error - TS2564 - Property 'waitingForClick' has no initializer and is not definitely assigned in the constructor.
33657
- waitingForClick;
33658
33472
  handleClick = e => {
33659
33473
  if (!this.props.disabled) {
33660
33474
  if (this.props.shouldUpdate()) {
@@ -34688,7 +34502,7 @@ const styles = aphrodite.StyleSheet.create({
34688
34502
  }
34689
34503
  });
34690
34504
 
34691
- /* eslint-disable react/forbid-prop-types, react/sort-comp */
34505
+ /* eslint-disable react/forbid-prop-types */
34692
34506
  const {
34693
34507
  InfoTip: InfoTip$a,
34694
34508
  TextListEditor: TextListEditor$3
@@ -34709,6 +34523,22 @@ class MatcherEditor extends React__namespace.Component {
34709
34523
  orderMatters: false,
34710
34524
  padding: true
34711
34525
  };
34526
+ onLabelChange = (index, e) => {
34527
+ const labels = ___default["default"].clone(this.props.labels);
34528
+ labels[index] = e.target.value;
34529
+ this.props.onChange({
34530
+ labels: labels
34531
+ });
34532
+ };
34533
+ getSaveWarnings = () => {
34534
+ if (this.props.left.length !== this.props.right.length) {
34535
+ return ["The two halves of the matcher have different numbers" + " of cards."];
34536
+ }
34537
+ return [];
34538
+ };
34539
+ serialize = () => {
34540
+ return ___default["default"].pick(this.props, "left", "right", "labels", "orderMatters", "padding");
34541
+ };
34712
34542
  render() {
34713
34543
  return /*#__PURE__*/React__namespace.createElement("div", {
34714
34544
  className: "perseus-matcher-editor"
@@ -34760,25 +34590,8 @@ class MatcherEditor extends React__namespace.Component {
34760
34590
  }
34761
34591
  }), /*#__PURE__*/React__namespace.createElement(InfoTip$a, null, /*#__PURE__*/React__namespace.createElement("p", null, "Padding is good for text, but not needed for images."))));
34762
34592
  }
34763
- onLabelChange = (index, e) => {
34764
- const labels = ___default["default"].clone(this.props.labels);
34765
- labels[index] = e.target.value;
34766
- this.props.onChange({
34767
- labels: labels
34768
- });
34769
- };
34770
- getSaveWarnings = () => {
34771
- if (this.props.left.length !== this.props.right.length) {
34772
- return ["The two halves of the matcher have different numbers" + " of cards."];
34773
- }
34774
- return [];
34775
- };
34776
- serialize = () => {
34777
- return ___default["default"].pick(this.props, "left", "right", "labels", "orderMatters", "padding");
34778
- };
34779
34593
  }
34780
34594
 
34781
- /* eslint-disable react/sort-comp */
34782
34595
  const {
34783
34596
  RangeInput: RangeInput$3
34784
34597
  } = perseus.components;
@@ -34827,6 +34640,33 @@ class MatrixEditor extends React__namespace.Component {
34827
34640
  suffix: "",
34828
34641
  cursorPosition: [0, 0]
34829
34642
  };
34643
+ change = (() => {
34644
+ var _this = this;
34645
+ return function () {
34646
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
34647
+ args[_key] = arguments[_key];
34648
+ }
34649
+ return perseus.Changeable.change.apply(_this, args);
34650
+ };
34651
+ })();
34652
+ onMatrixBoardSizeChange = range => {
34653
+ const matrixSize = getMatrixSize(this.props.answers);
34654
+ if (range[0] !== null && range[1] !== null) {
34655
+ range = [Math.round(Math.min(Math.max(range[0], 1), MAX_BOARD_SIZE)), Math.round(Math.min(Math.max(range[1], 1), MAX_BOARD_SIZE))];
34656
+ const answers = ___default["default"](Math.min(range[0], matrixSize[0])).times(row => {
34657
+ return ___default["default"](Math.min(range[1], matrixSize[1])).times(col => {
34658
+ return this.props.answers[row][col];
34659
+ });
34660
+ });
34661
+ this.props.onChange({
34662
+ matrixBoardSize: range,
34663
+ answers: answers
34664
+ });
34665
+ }
34666
+ };
34667
+ serialize = () => {
34668
+ return perseus.EditorJsonify.serialize.call(this);
34669
+ };
34830
34670
  render() {
34831
34671
  const matrixProps = ___default["default"].extend({
34832
34672
  numericInput: true,
@@ -34877,33 +34717,6 @@ class MatrixEditor extends React__namespace.Component {
34877
34717
  }
34878
34718
  })));
34879
34719
  }
34880
- change = (() => {
34881
- var _this = this;
34882
- return function () {
34883
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
34884
- args[_key] = arguments[_key];
34885
- }
34886
- return perseus.Changeable.change.apply(_this, args);
34887
- };
34888
- })();
34889
- onMatrixBoardSizeChange = range => {
34890
- const matrixSize = getMatrixSize(this.props.answers);
34891
- if (range[0] !== null && range[1] !== null) {
34892
- range = [Math.round(Math.min(Math.max(range[0], 1), MAX_BOARD_SIZE)), Math.round(Math.min(Math.max(range[1], 1), MAX_BOARD_SIZE))];
34893
- const answers = ___default["default"](Math.min(range[0], matrixSize[0])).times(row => {
34894
- return ___default["default"](Math.min(range[1], matrixSize[1])).times(col => {
34895
- return this.props.answers[row][col];
34896
- });
34897
- });
34898
- this.props.onChange({
34899
- matrixBoardSize: range,
34900
- answers: answers
34901
- });
34902
- }
34903
- };
34904
- serialize = () => {
34905
- return perseus.EditorJsonify.serialize.call(this);
34906
- };
34907
34720
  }
34908
34721
 
34909
34722
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
@@ -34945,6 +34758,42 @@ class MeasurerEditor extends React__namespace.Component {
34945
34758
  rulerLength: 10
34946
34759
  };
34947
34760
  className = "perseus-widget-measurer";
34761
+ change = (() => {
34762
+ var _this = this;
34763
+ return function () {
34764
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
34765
+ args[_key] = arguments[_key];
34766
+ }
34767
+ return perseus.Changeable.change.apply(_this, args);
34768
+ };
34769
+ })();
34770
+ _changeUrl = e => {
34771
+ this._changeImage("url", e.target.value);
34772
+ };
34773
+ _changeTop = newTop => {
34774
+ this._changeImage("top", newTop);
34775
+ };
34776
+ _changeLeft = newLeft => {
34777
+ this._changeImage("left", newLeft);
34778
+ };
34779
+ _changeImage = (subProp, newValue) => {
34780
+ const image = ___default["default"].clone(this.props.image);
34781
+ image[subProp] = newValue;
34782
+ // @ts-expect-error - TS2554 - Expected 3 arguments, but got 2.
34783
+ this.change("image", image);
34784
+ };
34785
+ renderLabelChoices = choices => {
34786
+ return ___default["default"].map(choices, function (nameAndValue) {
34787
+ const [name, value] = nameAndValue;
34788
+ return /*#__PURE__*/React__namespace.createElement("option", {
34789
+ key: value,
34790
+ value: value
34791
+ }, name);
34792
+ });
34793
+ };
34794
+ serialize = () => {
34795
+ return perseus.EditorJsonify.serialize.call(this);
34796
+ };
34948
34797
  render() {
34949
34798
  const image = ___default["default"].extend({}, defaultImage, this.props.image);
34950
34799
  return /*#__PURE__*/React__namespace.createElement("div", {
@@ -35038,47 +34887,11 @@ class MeasurerEditor extends React__namespace.Component {
35038
34887
  useArrowKeys: true
35039
34888
  })))));
35040
34889
  }
35041
- change = (() => {
35042
- var _this = this;
35043
- return function () {
35044
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
35045
- args[_key] = arguments[_key];
35046
- }
35047
- return perseus.Changeable.change.apply(_this, args);
35048
- };
35049
- })();
35050
- _changeUrl = e => {
35051
- this._changeImage("url", e.target.value);
35052
- };
35053
- _changeTop = newTop => {
35054
- this._changeImage("top", newTop);
35055
- };
35056
- _changeLeft = newLeft => {
35057
- this._changeImage("left", newLeft);
35058
- };
35059
- _changeImage = (subProp, newValue) => {
35060
- const image = ___default["default"].clone(this.props.image);
35061
- image[subProp] = newValue;
35062
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 2.
35063
- this.change("image", image);
35064
- };
35065
- renderLabelChoices = choices => {
35066
- return ___default["default"].map(choices, function (nameAndValue) {
35067
- const [name, value] = nameAndValue;
35068
- return /*#__PURE__*/React__namespace.createElement("option", {
35069
- key: value,
35070
- value: value
35071
- }, name);
35072
- });
35073
- };
35074
- serialize = () => {
35075
- return perseus.EditorJsonify.serialize.call(this);
35076
- };
35077
34890
  }
35078
34891
 
35079
34892
  const {
35080
34893
  NumberInput: NumberInput$6,
35081
- TextInput: TextInput$4
34894
+ TextInput: TextInput$3
35082
34895
  } = perseus.components;
35083
34896
  class MoleculeWidgetEditor extends React__namespace.Component {
35084
34897
  static propTypes = {
@@ -35112,7 +34925,7 @@ class MoleculeWidgetEditor extends React__namespace.Component {
35112
34925
  return perseus.EditorJsonify.serialize.call(this);
35113
34926
  };
35114
34927
  render() {
35115
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "SMILES:\xA0", /*#__PURE__*/React__namespace.createElement(TextInput$4, {
34928
+ return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "SMILES:\xA0", /*#__PURE__*/React__namespace.createElement(TextInput$3, {
35116
34929
  onChange: this.updateMolecule,
35117
34930
  value: this.props.smiles
35118
34931
  }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Rotation (deg):\xA0", /*#__PURE__*/React__namespace.createElement(NumberInput$6, {
@@ -35437,14 +35250,14 @@ class NumberLineEditor extends React__namespace.Component {
35437
35250
  }
35438
35251
  }
35439
35252
 
35440
- /* eslint-disable jsx-a11y/anchor-is-valid, react/sort-comp */
35253
+ /* eslint-disable jsx-a11y/anchor-is-valid */
35441
35254
  const {
35442
35255
  ButtonGroup,
35443
35256
  InfoTip: InfoTip$7,
35444
35257
  InlineIcon: InlineIcon$1,
35445
35258
  MultiButtonGroup,
35446
35259
  NumberInput: NumberInput$4,
35447
- TextInput: TextInput$3
35260
+ TextInput: TextInput$2
35448
35261
  } = perseus.components;
35449
35262
  const {
35450
35263
  iconGear,
@@ -35510,6 +35323,106 @@ class NumericInputEditor extends React__namespace.Component {
35510
35323
  showOptions: ___default["default"].map(this.props.answers, () => false)
35511
35324
  };
35512
35325
  }
35326
+ change = (() => {
35327
+ var _this = this;
35328
+ return function () {
35329
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
35330
+ args[_key] = arguments[_key];
35331
+ }
35332
+ return perseus.Changeable.change.apply(_this, args);
35333
+ };
35334
+ })();
35335
+ onToggleOptions = choiceIndex => {
35336
+ const showOptions = this.state.showOptions.slice();
35337
+ showOptions[choiceIndex] = !showOptions[choiceIndex];
35338
+ this.setState({
35339
+ showOptions: showOptions
35340
+ });
35341
+ };
35342
+ onTrashAnswer = choiceIndex => {
35343
+ if (choiceIndex >= 0 && choiceIndex < this.props.answers.length) {
35344
+ const answers = this.props.answers.slice(0);
35345
+ answers.splice(choiceIndex, 1);
35346
+ this.props.onChange({
35347
+ answers: answers
35348
+ });
35349
+ }
35350
+ };
35351
+ onSpace = (() => {
35352
+ var _this2 = this;
35353
+ return function (e, callback) {
35354
+ if (e.key === " ") {
35355
+ e.preventDefault(); // prevent page shifting
35356
+ for (var _len2 = arguments.length, args = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
35357
+ args[_key2 - 2] = arguments[_key2];
35358
+ }
35359
+ callback.apply(_this2, args);
35360
+ }
35361
+ };
35362
+ })();
35363
+ onStatusChange = choiceIndex => {
35364
+ const statuses = ["wrong", "ungraded", "correct"];
35365
+ const answers = this.props.answers;
35366
+ const i = ___default["default"].indexOf(statuses, answers[choiceIndex].status);
35367
+ const newStatus = statuses[(i + 1) % statuses.length];
35368
+ this.updateAnswer(choiceIndex, {
35369
+ status: newStatus,
35370
+ simplify: newStatus === "correct" ? "required" : "accepted"
35371
+ });
35372
+ };
35373
+ updateAnswer = (choiceIndex, update) => {
35374
+ if (!___default["default"].isObject(update)) {
35375
+ return ___default["default"].partial((choiceIndex, key, value) => {
35376
+ const update = {};
35377
+ update[key] = value;
35378
+ this.updateAnswer(choiceIndex, update);
35379
+ }, choiceIndex, update);
35380
+ }
35381
+ let answers = [
35382
+ // Have to do this to remove the `readonly` state from the prop
35383
+ ...this.props.answers];
35384
+
35385
+ // Don't bother to make a new answer box unless we are editing the last
35386
+ // one.
35387
+ // TODO(oliver): This might not be necessary anymore.
35388
+ if (choiceIndex === answers.length) {
35389
+ const lastAnswer = initAnswer(this.state.lastStatus);
35390
+ answers = answers.concat(lastAnswer);
35391
+ }
35392
+ answers[choiceIndex] = ___default["default"].extend({}, answers[choiceIndex], update);
35393
+ this.props.onChange({
35394
+ answers: answers
35395
+ });
35396
+ };
35397
+ addAnswer = () => {
35398
+ const lastAnswer = initAnswer(this.state.lastStatus);
35399
+ const answers = this.props.answers.concat(lastAnswer);
35400
+ this.props.onChange({
35401
+ answers: answers
35402
+ });
35403
+ };
35404
+ getSaveWarnings = () => {
35405
+ // Filter out all the empty answers
35406
+ const warnings = [];
35407
+ // TODO(emily): This doesn't actually work, because the value is either
35408
+ // null or undefined when undefined, probably.
35409
+ if (___default["default"].contains(___default["default"].pluck(this.props.answers, "value"), "")) {
35410
+ // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'.
35411
+ warnings.push("One or more answers is empty");
35412
+ }
35413
+ this.props.answers.forEach((answer, i) => {
35414
+ const formatError = answer.strict && (!answer.answerForms || answer.answerForms.length === 0);
35415
+ if (formatError) {
35416
+ warnings.push(
35417
+ // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'.
35418
+ `Answer ${i + 1} is set to string format ` + "matching, but no format was selected");
35419
+ }
35420
+ });
35421
+ return warnings;
35422
+ };
35423
+ serialize = () => {
35424
+ return perseus.EditorJsonify.serialize.call(this);
35425
+ };
35513
35426
  render() {
35514
35427
  const answers = this.props.answers;
35515
35428
  const unsimplifiedAnswers = i => /*#__PURE__*/React__namespace.createElement("div", {
@@ -35581,7 +35494,7 @@ class NumericInputEditor extends React__namespace.Component {
35581
35494
  }));
35582
35495
  const labelText = /*#__PURE__*/React__namespace.createElement("div", {
35583
35496
  className: "perseus-widget-row"
35584
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Aria label", /*#__PURE__*/React__namespace.createElement(TextInput$3, {
35497
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Aria label", /*#__PURE__*/React__namespace.createElement(TextInput$2, {
35585
35498
  value: this.props.labelText,
35586
35499
  onChange: this.change("labelText")
35587
35500
  })), /*#__PURE__*/React__namespace.createElement(InfoTip$7, null, /*#__PURE__*/React__namespace.createElement("p", null, "Text to describe this input. This will be shown to users using screenreaders.")));
@@ -35731,106 +35644,6 @@ class NumericInputEditor extends React__namespace.Component {
35731
35644
  className: "msg-title"
35732
35645
  }, "Message shown to user on attempt"), generateInputAnswerEditors(), addAnswerButton, inputSize, rightAlign, coefficientCheck, labelText);
35733
35646
  }
35734
- change = (() => {
35735
- var _this = this;
35736
- return function () {
35737
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
35738
- args[_key] = arguments[_key];
35739
- }
35740
- return perseus.Changeable.change.apply(_this, args);
35741
- };
35742
- })();
35743
- onToggleOptions = choiceIndex => {
35744
- const showOptions = this.state.showOptions.slice();
35745
- showOptions[choiceIndex] = !showOptions[choiceIndex];
35746
- this.setState({
35747
- showOptions: showOptions
35748
- });
35749
- };
35750
- onTrashAnswer = choiceIndex => {
35751
- if (choiceIndex >= 0 && choiceIndex < this.props.answers.length) {
35752
- const answers = this.props.answers.slice(0);
35753
- answers.splice(choiceIndex, 1);
35754
- this.props.onChange({
35755
- answers: answers
35756
- });
35757
- }
35758
- };
35759
- onSpace = (() => {
35760
- var _this2 = this;
35761
- return function (e, callback) {
35762
- if (e.key === " ") {
35763
- e.preventDefault(); // prevent page shifting
35764
- for (var _len2 = arguments.length, args = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
35765
- args[_key2 - 2] = arguments[_key2];
35766
- }
35767
- callback.apply(_this2, args);
35768
- }
35769
- };
35770
- })();
35771
- onStatusChange = choiceIndex => {
35772
- const statuses = ["wrong", "ungraded", "correct"];
35773
- const answers = this.props.answers;
35774
- const i = ___default["default"].indexOf(statuses, answers[choiceIndex].status);
35775
- const newStatus = statuses[(i + 1) % statuses.length];
35776
- this.updateAnswer(choiceIndex, {
35777
- status: newStatus,
35778
- simplify: newStatus === "correct" ? "required" : "accepted"
35779
- });
35780
- };
35781
- updateAnswer = (choiceIndex, update) => {
35782
- if (!___default["default"].isObject(update)) {
35783
- return ___default["default"].partial((choiceIndex, key, value) => {
35784
- const update = {};
35785
- update[key] = value;
35786
- this.updateAnswer(choiceIndex, update);
35787
- }, choiceIndex, update);
35788
- }
35789
- let answers = [
35790
- // Have to do this to remove the `readonly` state from the prop
35791
- ...this.props.answers];
35792
-
35793
- // Don't bother to make a new answer box unless we are editing the last
35794
- // one.
35795
- // TODO(oliver): This might not be necessary anymore.
35796
- if (choiceIndex === answers.length) {
35797
- const lastAnswer = initAnswer(this.state.lastStatus);
35798
- answers = answers.concat(lastAnswer);
35799
- }
35800
- answers[choiceIndex] = ___default["default"].extend({}, answers[choiceIndex], update);
35801
- this.props.onChange({
35802
- answers: answers
35803
- });
35804
- };
35805
- addAnswer = () => {
35806
- const lastAnswer = initAnswer(this.state.lastStatus);
35807
- const answers = this.props.answers.concat(lastAnswer);
35808
- this.props.onChange({
35809
- answers: answers
35810
- });
35811
- };
35812
- getSaveWarnings = () => {
35813
- // Filter out all the empty answers
35814
- const warnings = [];
35815
- // TODO(emily): This doesn't actually work, because the value is either
35816
- // null or undefined when undefined, probably.
35817
- if (___default["default"].contains(___default["default"].pluck(this.props.answers, "value"), "")) {
35818
- // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'.
35819
- warnings.push("One or more answers is empty");
35820
- }
35821
- this.props.answers.forEach((answer, i) => {
35822
- const formatError = answer.strict && (!answer.answerForms || answer.answerForms.length === 0);
35823
- if (formatError) {
35824
- warnings.push(
35825
- // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'.
35826
- `Answer ${i + 1} is set to string format ` + "matching, but no format was selected");
35827
- }
35828
- });
35829
- return warnings;
35830
- };
35831
- serialize = () => {
35832
- return perseus.EditorJsonify.serialize.call(this);
35833
- };
35834
35647
  }
35835
35648
 
35836
35649
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
@@ -35861,41 +35674,6 @@ class OrdererEditor extends React__namespace.Component {
35861
35674
  height: NORMAL,
35862
35675
  layout: HORIZONTAL$1
35863
35676
  };
35864
- render() {
35865
- return /*#__PURE__*/React__namespace.createElement("div", {
35866
- className: "perseus-widget-orderer"
35867
- }, /*#__PURE__*/React__namespace.createElement("div", null, " ", "Correct answer:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Place the cards in the correct order. The same card can be used more than once in the answer but will only be displayed once at the top of a stack of identical cards."))), /*#__PURE__*/React__namespace.createElement(TextListEditor$2, {
35868
- options: ___default["default"].pluck(this.props.correctOptions, "content")
35869
- // eslint-disable-next-line react/jsx-no-bind
35870
- ,
35871
- onChange: this.onOptionsChange.bind(this, "correctOptions"),
35872
- layout: this.props.layout
35873
- }), /*#__PURE__*/React__namespace.createElement("div", null, " ", "Other cards:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create cards that are not part of the answer."))), /*#__PURE__*/React__namespace.createElement(TextListEditor$2, {
35874
- options: ___default["default"].pluck(this.props.otherOptions, "content")
35875
- // eslint-disable-next-line react/jsx-no-bind
35876
- ,
35877
- onChange: this.onOptionsChange.bind(this, "otherOptions"),
35878
- layout: this.props.layout
35879
- }), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Layout:", " ", /*#__PURE__*/React__namespace.createElement("select", {
35880
- value: this.props.layout
35881
- // @ts-expect-error - TS2322 - Type '(arg1: ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'ChangeEventHandler<HTMLSelectElement>'.
35882
- ,
35883
- onChange: this.onLayoutChange
35884
- }, /*#__PURE__*/React__namespace.createElement("option", {
35885
- value: HORIZONTAL$1
35886
- }, "Horizontal"), /*#__PURE__*/React__namespace.createElement("option", {
35887
- value: VERTICAL$1
35888
- }, "Vertical"))), /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use the horizontal layout for short text and small images. The vertical layout is best for longer text (e.g. proofs)."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Height:", " ", /*#__PURE__*/React__namespace.createElement("select", {
35889
- value: this.props.height
35890
- // @ts-expect-error - TS2322 - Type '(arg1: ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'ChangeEventHandler<HTMLSelectElement>'.
35891
- ,
35892
- onChange: this.onHeightChange
35893
- }, /*#__PURE__*/React__namespace.createElement("option", {
35894
- value: NORMAL
35895
- }, "Normal"), /*#__PURE__*/React__namespace.createElement("option", {
35896
- value: AUTO
35897
- }, "Automatic"))), /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use \"Normal\" for text, \"Automatic\" for images."))));
35898
- }
35899
35677
  onOptionsChange = (whichOptions, options, cb) => {
35900
35678
  const props = {};
35901
35679
  props[whichOptions] = ___default["default"].map(options, function (option) {
@@ -35942,6 +35720,41 @@ class OrdererEditor extends React__namespace.Component {
35942
35720
  layout: this.props.layout
35943
35721
  };
35944
35722
  };
35723
+ render() {
35724
+ return /*#__PURE__*/React__namespace.createElement("div", {
35725
+ className: "perseus-widget-orderer"
35726
+ }, /*#__PURE__*/React__namespace.createElement("div", null, " ", "Correct answer:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Place the cards in the correct order. The same card can be used more than once in the answer but will only be displayed once at the top of a stack of identical cards."))), /*#__PURE__*/React__namespace.createElement(TextListEditor$2, {
35727
+ options: ___default["default"].pluck(this.props.correctOptions, "content")
35728
+ // eslint-disable-next-line react/jsx-no-bind
35729
+ ,
35730
+ onChange: this.onOptionsChange.bind(this, "correctOptions"),
35731
+ layout: this.props.layout
35732
+ }), /*#__PURE__*/React__namespace.createElement("div", null, " ", "Other cards:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create cards that are not part of the answer."))), /*#__PURE__*/React__namespace.createElement(TextListEditor$2, {
35733
+ options: ___default["default"].pluck(this.props.otherOptions, "content")
35734
+ // eslint-disable-next-line react/jsx-no-bind
35735
+ ,
35736
+ onChange: this.onOptionsChange.bind(this, "otherOptions"),
35737
+ layout: this.props.layout
35738
+ }), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Layout:", " ", /*#__PURE__*/React__namespace.createElement("select", {
35739
+ value: this.props.layout
35740
+ // @ts-expect-error - TS2322 - Type '(arg1: ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'ChangeEventHandler<HTMLSelectElement>'.
35741
+ ,
35742
+ onChange: this.onLayoutChange
35743
+ }, /*#__PURE__*/React__namespace.createElement("option", {
35744
+ value: HORIZONTAL$1
35745
+ }, "Horizontal"), /*#__PURE__*/React__namespace.createElement("option", {
35746
+ value: VERTICAL$1
35747
+ }, "Vertical"))), /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use the horizontal layout for short text and small images. The vertical layout is best for longer text (e.g. proofs)."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Height:", " ", /*#__PURE__*/React__namespace.createElement("select", {
35748
+ value: this.props.height
35749
+ // @ts-expect-error - TS2322 - Type '(arg1: ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'ChangeEventHandler<HTMLSelectElement>'.
35750
+ ,
35751
+ onChange: this.onHeightChange
35752
+ }, /*#__PURE__*/React__namespace.createElement("option", {
35753
+ value: NORMAL
35754
+ }, "Normal"), /*#__PURE__*/React__namespace.createElement("option", {
35755
+ value: AUTO
35756
+ }, "Automatic"))), /*#__PURE__*/React__namespace.createElement(InfoTip$6, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use \"Normal\" for text, \"Automatic\" for images."))));
35757
+ }
35945
35758
  }
35946
35759
 
35947
35760
  const {
@@ -36035,7 +35848,7 @@ class PassageEditor extends React__namespace.Component {
36035
35848
  const {
36036
35849
  InfoTip: InfoTip$4,
36037
35850
  NumberInput: NumberInput$3,
36038
- TextInput: TextInput$2
35851
+ TextInput: TextInput$1
36039
35852
  } = perseus.components;
36040
35853
  class PassageRefEditor extends React__namespace.Component {
36041
35854
  static propTypes = {
@@ -36073,7 +35886,7 @@ class PassageRefEditor extends React__namespace.Component {
36073
35886
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
36074
35887
  ,
36075
35888
  onChange: this.change("referenceNumber")
36076
- }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Summary Text: ", /*#__PURE__*/React__namespace.createElement(TextInput$2, {
35889
+ }))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Summary Text: ", /*#__PURE__*/React__namespace.createElement(TextInput$1, {
36077
35890
  value: this.props.summaryText
36078
35891
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
36079
35892
  ,
@@ -36125,14 +35938,29 @@ class PhetSimulationEditor extends React__namespace.Component {
36125
35938
  description: ""
36126
35939
  };
36127
35940
  static widgetName = "phet-simulation";
35941
+ serialize() {
35942
+ return {
35943
+ url: this.props.url,
35944
+ description: this.props.description
35945
+ };
35946
+ }
35947
+ getSaveWarnings = () => {
35948
+ if (perseus.makeSafeUrl(this.props.url, "en") === null) {
35949
+ return ["Please enter a URL from the PhET domain."];
35950
+ }
35951
+ return [];
35952
+ };
36128
35953
  render() {
36129
35954
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
36130
35955
  label: "URL",
36131
35956
  value: this.props.url,
36132
35957
  onChange: url => this.props.onChange({
36133
35958
  url
36134
- })
36135
- }), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
35959
+ }),
35960
+ style: {
35961
+ marginBottom: wonderBlocksTokens.spacing.large_24
35962
+ }
35963
+ }), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.LabeledTextField, {
36136
35964
  label: "Description",
36137
35965
  value: this.props.description,
36138
35966
  onChange: description => this.props.onChange({
@@ -36140,12 +35968,6 @@ class PhetSimulationEditor extends React__namespace.Component {
36140
35968
  })
36141
35969
  }));
36142
35970
  }
36143
- serialize() {
36144
- return {
36145
- url: this.props.url,
36146
- description: this.props.description
36147
- };
36148
- }
36149
35971
  }
36150
35972
 
36151
35973
  const {
@@ -36463,7 +36285,7 @@ class PlotterEditor extends React__namespace.Component {
36463
36285
  */
36464
36286
  const {
36465
36287
  NumberInput: NumberInput$1,
36466
- TextInput: TextInput$1
36288
+ TextInput
36467
36289
  } = perseus.components;
36468
36290
  function validateOptions(height, programID) {
36469
36291
  const errors = [];
@@ -36505,7 +36327,7 @@ class PythonProgramEditor extends React__namespace.Component {
36505
36327
  return validateOptions(this.props.height, this.props.programID);
36506
36328
  };
36507
36329
  render() {
36508
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "User Program ID:", " ", /*#__PURE__*/React__namespace.createElement(TextInput$1, {
36330
+ return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "User Program ID:", " ", /*#__PURE__*/React__namespace.createElement(TextInput, {
36509
36331
  value: this.props.programID,
36510
36332
  onChange: this.change("programID"),
36511
36333
  placeholder: "123"
@@ -36517,7 +36339,7 @@ class PythonProgramEditor extends React__namespace.Component {
36517
36339
  }
36518
36340
  }
36519
36341
 
36520
- /* eslint-disable jsx-a11y/anchor-is-valid, react/forbid-prop-types, react/sort-comp */
36342
+ /* eslint-disable jsx-a11y/anchor-is-valid, react/forbid-prop-types */
36521
36343
  const {
36522
36344
  InlineIcon
36523
36345
  } = perseus.components;
@@ -36610,94 +36432,6 @@ class RadioEditor extends React__namespace.Component {
36610
36432
  countChoices: false,
36611
36433
  deselectEnabled: false
36612
36434
  };
36613
- render() {
36614
- const numCorrect = ___default["default"].reduce(this.props.choices, function (memo, choice) {
36615
- return choice.correct ? memo + 1 : memo;
36616
- }, 0);
36617
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
36618
- className: "perseus-widget-row"
36619
- }, /*#__PURE__*/React__namespace.createElement("a", {
36620
- href:
36621
- // This is an editor component, not user-facing.
36622
- "https://docs.google.com/document/d/1frZf7yrWVWb1n4tVjqlzqVUiv1pn4cZXbxgP62-JDBY/edit#heading=h.8ng1isya19nu",
36623
- target: "_blank"
36624
- }, "Multiple choice style guide"), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement("div", {
36625
- className: "perseus-widget-left-col"
36626
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
36627
- label: "Multiple selections",
36628
- checked: this.props.multipleSelect,
36629
- onChange: value => {
36630
- this.onMultipleSelectChange({
36631
- multipleSelect: value
36632
- });
36633
- }
36634
- })), /*#__PURE__*/React__namespace.createElement("div", {
36635
- className: "perseus-widget-right-col"
36636
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
36637
- label: "Randomize order",
36638
- checked: this.props.randomize,
36639
- onChange: value => {
36640
- this.props.onChange({
36641
- randomize: value
36642
- });
36643
- }
36644
- })), this.props.multipleSelect && /*#__PURE__*/React__namespace.createElement("div", {
36645
- className: "perseus-widget-left-col"
36646
- }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
36647
- label: "Specify number correct",
36648
- checked: this.props.countChoices,
36649
- onChange: value => {
36650
- this.onCountChoicesChange({
36651
- countChoices: value
36652
- });
36653
- }
36654
- }))), /*#__PURE__*/React__namespace.createElement(perseus.BaseRadio, {
36655
- multipleSelect: this.props.multipleSelect,
36656
- countChoices: this.props.countChoices,
36657
- numCorrect: numCorrect,
36658
- editMode: true,
36659
- labelWrap: false,
36660
- apiOptions: this.props.apiOptions,
36661
- choices: this.props.choices.map((choice, i) => {
36662
- return {
36663
- content: /*#__PURE__*/React__namespace.createElement(ChoiceEditor, {
36664
- ref: `choice-editor${i}`,
36665
- apiOptions: this.props.apiOptions,
36666
- choice: choice,
36667
- onContentChange: newProps => {
36668
- if ("content" in newProps) {
36669
- this.onContentChange(i, newProps.content);
36670
- }
36671
- },
36672
- onClueChange: newProps => {
36673
- if ("content" in newProps) {
36674
- this.onClueChange(i, newProps.content);
36675
- }
36676
- },
36677
- onDelete: () => this.onDelete(i),
36678
- showDelete: this.props.choices.length >= 2
36679
- }),
36680
- isNoneOfTheAbove: choice.isNoneOfTheAbove,
36681
- checked: choice.correct
36682
- };
36683
- }, this),
36684
- onChange: this.onChange
36685
- }), /*#__PURE__*/React__namespace.createElement("div", {
36686
- className: "add-choice-container"
36687
- }, /*#__PURE__*/React__namespace.createElement("a", {
36688
- className: "simple-button orange",
36689
- href: "#"
36690
- // eslint-disable-next-line react/jsx-no-bind
36691
- ,
36692
- onClick: this.addChoice.bind(this, false)
36693
- }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconPlus), " Add a choice", " "), !this.props.hasNoneOfTheAbove && /*#__PURE__*/React__namespace.createElement("a", {
36694
- className: "simple-button",
36695
- href: "#"
36696
- // eslint-disable-next-line react/jsx-no-bind
36697
- ,
36698
- onClick: this.addChoice.bind(this, true)
36699
- }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconPlus), " None of the above", " ")));
36700
- }
36701
36435
  change = (() => {
36702
36436
  var _this = this;
36703
36437
  return function () {
@@ -36816,64 +36550,94 @@ class RadioEditor extends React__namespace.Component {
36816
36550
  serialize = () => {
36817
36551
  return ___default["default"].pick(this.props, "choices", "randomize", "multipleSelect", "countChoices", "displayCount", "hasNoneOfTheAbove", "deselectEnabled");
36818
36552
  };
36819
- }
36820
-
36821
- /* eslint-disable @khanacademy/ts-no-error-suppressions */
36822
- class TextArea extends React__namespace.Component {
36823
- render() {
36824
- return /*#__PURE__*/React__namespace.createElement("textarea", {
36825
- // eslint-disable-next-line react/no-string-refs
36826
- ref: "input",
36827
- value: this.props.value || "",
36828
- onChange: this.changeValue
36829
- });
36830
- }
36831
- focus = () => {
36832
- // eslint-disable-next-line react/no-string-refs
36833
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
36834
- this.refs.input.focus();
36835
- return true;
36836
- };
36837
- changeValue = e => {
36838
- // Translating from the js event e to the value
36839
- // of the textbox to send to onChange
36840
- this.props.onChange(e.target.value);
36841
- };
36842
- }
36843
- class SimpleMarkdownTesterEditor extends React__namespace.Component {
36844
- static propTypes = {
36845
- ...perseus.Changeable.propTypes
36846
- };
36847
- static widgetName = "simple-markdown-tester";
36848
- static defaultProps = {
36849
- value: ""
36850
- };
36851
- input = /*#__PURE__*/React__namespace.createRef();
36852
36553
  render() {
36853
- 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, {
36854
- value: this.props.value
36855
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
36554
+ const numCorrect = ___default["default"].reduce(this.props.choices, function (memo, choice) {
36555
+ return choice.correct ? memo + 1 : memo;
36556
+ }, 0);
36557
+ return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
36558
+ className: "perseus-widget-row"
36559
+ }, /*#__PURE__*/React__namespace.createElement("a", {
36560
+ href:
36561
+ // This is an editor component, not user-facing.
36562
+ "https://docs.google.com/document/d/1frZf7yrWVWb1n4tVjqlzqVUiv1pn4cZXbxgP62-JDBY/edit#heading=h.8ng1isya19nu",
36563
+ target: "_blank"
36564
+ }, "Multiple choice style guide"), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement("div", {
36565
+ className: "perseus-widget-left-col"
36566
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
36567
+ label: "Multiple selections",
36568
+ checked: this.props.multipleSelect,
36569
+ onChange: value => {
36570
+ this.onMultipleSelectChange({
36571
+ multipleSelect: value
36572
+ });
36573
+ }
36574
+ })), /*#__PURE__*/React__namespace.createElement("div", {
36575
+ className: "perseus-widget-right-col"
36576
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
36577
+ label: "Randomize order",
36578
+ checked: this.props.randomize,
36579
+ onChange: value => {
36580
+ this.props.onChange({
36581
+ randomize: value
36582
+ });
36583
+ }
36584
+ })), this.props.multipleSelect && /*#__PURE__*/React__namespace.createElement("div", {
36585
+ className: "perseus-widget-left-col"
36586
+ }, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
36587
+ label: "Specify number correct",
36588
+ checked: this.props.countChoices,
36589
+ onChange: value => {
36590
+ this.onCountChoicesChange({
36591
+ countChoices: value
36592
+ });
36593
+ }
36594
+ }))), /*#__PURE__*/React__namespace.createElement(perseus.BaseRadio, {
36595
+ multipleSelect: this.props.multipleSelect,
36596
+ countChoices: this.props.countChoices,
36597
+ numCorrect: numCorrect,
36598
+ editMode: true,
36599
+ labelWrap: false,
36600
+ apiOptions: this.props.apiOptions,
36601
+ choices: this.props.choices.map((choice, i) => {
36602
+ return {
36603
+ content: /*#__PURE__*/React__namespace.createElement(ChoiceEditor, {
36604
+ ref: `choice-editor${i}`,
36605
+ apiOptions: this.props.apiOptions,
36606
+ choice: choice,
36607
+ onContentChange: newProps => {
36608
+ if ("content" in newProps) {
36609
+ this.onContentChange(i, newProps.content);
36610
+ }
36611
+ },
36612
+ onClueChange: newProps => {
36613
+ if ("content" in newProps) {
36614
+ this.onClueChange(i, newProps.content);
36615
+ }
36616
+ },
36617
+ onDelete: () => this.onDelete(i),
36618
+ showDelete: this.props.choices.length >= 2
36619
+ }),
36620
+ isNoneOfTheAbove: choice.isNoneOfTheAbove,
36621
+ checked: choice.correct
36622
+ };
36623
+ }, this),
36624
+ onChange: this.onChange
36625
+ }), /*#__PURE__*/React__namespace.createElement("div", {
36626
+ className: "add-choice-container"
36627
+ }, /*#__PURE__*/React__namespace.createElement("a", {
36628
+ className: "simple-button orange",
36629
+ href: "#"
36630
+ // eslint-disable-next-line react/jsx-no-bind
36856
36631
  ,
36857
- onChange: this.change("value"),
36858
- ref: this.input
36859
- }))));
36632
+ onClick: this.addChoice.bind(this, false)
36633
+ }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconPlus), " Add a choice", " "), !this.props.hasNoneOfTheAbove && /*#__PURE__*/React__namespace.createElement("a", {
36634
+ className: "simple-button",
36635
+ href: "#"
36636
+ // eslint-disable-next-line react/jsx-no-bind
36637
+ ,
36638
+ onClick: this.addChoice.bind(this, true)
36639
+ }, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconPlus), " None of the above", " ")));
36860
36640
  }
36861
- change = (() => {
36862
- var _this = this;
36863
- return function () {
36864
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
36865
- args[_key] = arguments[_key];
36866
- }
36867
- return perseus.Changeable.change.apply(_this, args);
36868
- };
36869
- })();
36870
- focus = () => {
36871
- this.input.current?.focus();
36872
- return true;
36873
- };
36874
- serialize = () => {
36875
- return perseus.EditorJsonify.serialize.call(this);
36876
- };
36877
36641
  }
36878
36642
 
36879
36643
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
@@ -36936,7 +36700,6 @@ class SorterEditor extends React__namespace.Component {
36936
36700
  }
36937
36701
  }
36938
36702
 
36939
- /* eslint-disable react/sort-comp */
36940
36703
  const {
36941
36704
  InfoTip: InfoTip$1,
36942
36705
  NumberInput
@@ -36967,41 +36730,6 @@ class TableEditor extends React__namespace.Component {
36967
36730
  focus = () => {
36968
36731
  this.numberOfColumns.current?.focus();
36969
36732
  };
36970
- render() {
36971
- const tableProps = ___default["default"].pick(this.props, "headers", "answers", "onChange", "apiOptions");
36972
- ___default["default"].extend(tableProps, {
36973
- editableHeaders: true,
36974
- Editor,
36975
- onFocus: () => {},
36976
- onBlur: () => {},
36977
- trackInteraction: () => {}
36978
- });
36979
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
36980
- className: "perseus-widget-row"
36981
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Number of columns:", " ", /*#__PURE__*/React__namespace.createElement(NumberInput, {
36982
- ref: this.numberOfColumns,
36983
- value: this.props.columns,
36984
- onChange: val => {
36985
- if (val) {
36986
- this.onSizeInput(this.props.rows, val);
36987
- }
36988
- },
36989
- useArrowKeys: true
36990
- }))), /*#__PURE__*/React__namespace.createElement("div", {
36991
- className: "perseus-widget-row"
36992
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Number of rows:", " ", /*#__PURE__*/React__namespace.createElement(NumberInput
36993
- // eslint-disable-next-line react/no-string-refs
36994
- , {
36995
- ref: "numberOfRows",
36996
- value: this.props.rows,
36997
- onChange: val => {
36998
- if (val) {
36999
- this.onSizeInput(val, this.props.columns);
37000
- }
37001
- },
37002
- useArrowKeys: true
37003
- }))), /*#__PURE__*/React__namespace.createElement("div", null, " ", "Table of answers:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$1, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student has to fill out all cells in the table. For partially filled tables create a table using the template, and insert text input boxes as desired."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(Table, tableProps)));
37004
- }
37005
36733
  onSizeInput = (numRawRows, numRawColumns) => {
37006
36734
  let rows = +numRawRows || 0;
37007
36735
  let columns = +numRawColumns || 0;
@@ -37044,6 +36772,41 @@ class TableEditor extends React__namespace.Component {
37044
36772
  answers: ___default["default"].map(this.props.answers, ___default["default"].clone)
37045
36773
  });
37046
36774
  };
36775
+ render() {
36776
+ const tableProps = ___default["default"].pick(this.props, "headers", "answers", "onChange", "apiOptions");
36777
+ ___default["default"].extend(tableProps, {
36778
+ editableHeaders: true,
36779
+ Editor,
36780
+ onFocus: () => {},
36781
+ onBlur: () => {},
36782
+ trackInteraction: () => {}
36783
+ });
36784
+ return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
36785
+ className: "perseus-widget-row"
36786
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Number of columns:", " ", /*#__PURE__*/React__namespace.createElement(NumberInput, {
36787
+ ref: this.numberOfColumns,
36788
+ value: this.props.columns,
36789
+ onChange: val => {
36790
+ if (val) {
36791
+ this.onSizeInput(this.props.rows, val);
36792
+ }
36793
+ },
36794
+ useArrowKeys: true
36795
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
36796
+ className: "perseus-widget-row"
36797
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Number of rows:", " ", /*#__PURE__*/React__namespace.createElement(NumberInput
36798
+ // eslint-disable-next-line react/no-string-refs
36799
+ , {
36800
+ ref: "numberOfRows",
36801
+ value: this.props.rows,
36802
+ onChange: val => {
36803
+ if (val) {
36804
+ this.onSizeInput(val, this.props.columns);
36805
+ }
36806
+ },
36807
+ useArrowKeys: true
36808
+ }))), /*#__PURE__*/React__namespace.createElement("div", null, " ", "Table of answers:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$1, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student has to fill out all cells in the table. For partially filled tables create a table using the template, and insert text input boxes as desired."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(Table, tableProps)));
36809
+ }
37047
36810
  }
37048
36811
 
37049
36812
  const {
@@ -37103,230 +36866,18 @@ class VideoEditor extends React__namespace.Component {
37103
36866
  }
37104
36867
  }
37105
36868
 
37106
- 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];
37107
-
37108
- /* eslint-disable @khanacademy/ts-no-error-suppressions */
37109
- class TextInput extends React__namespace.Component {
37110
- input = /*#__PURE__*/React__namespace.createRef();
37111
- render() {
37112
- return /*#__PURE__*/React__namespace.createElement("input", {
37113
- ref: this.input,
37114
- value: this.props.value || "",
37115
- onChange: this.changeValue
37116
- });
37117
- }
37118
- focus = () => {
37119
- this.input.current?.focus();
37120
- return true;
37121
- };
37122
- changeValue = e => {
37123
- // Translating from the js event e to the value
37124
- // of the textbox to send to onChange
37125
- this.props.onChange(e.target.value);
37126
- };
37127
- }
37128
- /**
37129
- * This is the widget's renderer. It shows up in the right column
37130
- * in the demo, and is what is visible to users, and where
37131
- * users enter their answers.
37132
- */
37133
- class ExampleWidget extends React__namespace.Component {
37134
- static defaultProps = {
37135
- value: ""
37136
- };
37137
- input = /*#__PURE__*/React__namespace.createRef();
37138
-
37139
- /**
37140
- * This is the widget's grading function. simpleValidate generally
37141
- * defers to this function.
37142
- *
37143
- * value is usually the result of getUserInput on the widget
37144
- * rubric is the result of calling serialize() on the editor
37145
- */
37146
- static validate(value, rubric) {
37147
- if (value === "") {
37148
- return {
37149
- type: "invalid",
37150
- message: "It looks like you haven't answered all of the " + "question yet."
37151
- };
37152
- }
37153
- if (value === rubric.correct) {
37154
- return {
37155
- type: "points",
37156
- earned: 1,
37157
- total: 1,
37158
- message: null
37159
- };
37160
- }
37161
- return {
37162
- type: "points",
37163
- earned: 0,
37164
- total: 1,
37165
- message: null
37166
- };
37167
- }
37168
-
37169
- /**
37170
- * Tell our parent to update our props.
37171
- */
37172
- change = (() => {
37173
- var _this = this;
37174
- return function () {
37175
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
37176
- args[_key] = arguments[_key];
37177
- }
37178
- return perseus.Changeable.change.apply(_this, args);
37179
- };
37180
- })();
37181
- render() {
37182
- return /*#__PURE__*/React__namespace.createElement(TextInput, {
37183
- ref: this.input,
37184
- value: this.props.value
37185
- // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
37186
- ,
37187
- onChange: this.change("value")
37188
- });
37189
- }
37190
- getUserInput = () => {
37191
- return this.props.value;
37192
- };
37193
-
37194
- /**
37195
- * Widgets that are focusable should add a focus method that returns
37196
- * true if focusing succeeded. The first such widget found will be
37197
- * focused on page load.
37198
- */
37199
- focus = () => {
37200
- this.input.current?.focus();
37201
- return true;
37202
- };
37203
-
37204
- /**
37205
- * simpleValidate is called for grading. Rubric is the result of calling
37206
- * getUserInput() on the editor that created this widget.
37207
- *
37208
- * Should return an object representing the grading result, such as
37209
- * {
37210
- * type: "points",
37211
- * earned: 1,
37212
- * total: 1,
37213
- * message: null
37214
- * }
37215
- */
37216
- simpleValidate = rubric => {
37217
- return ExampleWidget.validate(this.getUserInput(), rubric);
37218
- };
37219
- }
37220
-
37221
- /**
37222
- * For this widget to work, we must import this file in src/all-widgets.js
37223
- */
37224
- var ExampleWidget$1 = {
37225
- name: "example-widget",
37226
- displayName: "Example Widget",
37227
- // Tell the renderer what type of `display:` style we would like
37228
- // for the component wrapping this one.
37229
- defaultAlignment: "inline-block",
37230
- hidden: true,
37231
- // Hides this widget from the Perseus.Editor widget select
37232
- widget: ExampleWidget
37233
- };
37234
-
37235
- /* eslint-disable react/sort-comp */
37236
- const mdParse = perseus.PerseusMarkdown.parse;
37237
- const mdOutput = perseus.PerseusMarkdown.basicOutput;
37238
- class SimpleMarkdownTester extends React__namespace.Component {
37239
- static defaultProps = {
37240
- value: ""
37241
- };
37242
-
37243
- /**
37244
- * This is the widget's grading function.
37245
- *
37246
- * simpleValidate generally defers to this function
37247
- *
37248
- * state is usually the result of toJSON on the widget
37249
- * rubric is the result of calling toJSON() on the editor
37250
- */
37251
- static validate(state, rubric) {
37252
- return {
37253
- type: "points",
37254
- earned: 0,
37255
- total: 0,
37256
- message: null
37257
- };
37258
- }
37259
- change = (() => {
37260
- var _this = this;
37261
- return function () {
37262
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
37263
- args[_key] = arguments[_key];
37264
- }
37265
- return perseus.Changeable.change.apply(_this, args);
37266
- };
37267
- })();
37268
- toJSON = () => {
37269
- return {};
37270
- };
37271
- render() {
37272
- // @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
37273
- const parsed = mdParse(this.props.value);
37274
- const output = mdOutput(parsed);
37275
- return /*#__PURE__*/React__namespace.createElement("div", null, output);
37276
- }
37277
-
37278
- /**
37279
- * Widgets that are focusable should add a focus method that returns
37280
- * true if focusing succeeded. The first such widget found will be
37281
- * focused on page load.
37282
- */
37283
- focus = () => {
37284
- // eslint-disable-next-line react/no-string-refs
37285
- // @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
37286
- this.refs.input.focus();
37287
- return true;
37288
- };
37289
-
37290
- /**
37291
- * simpleValidate is called for grading. Rubric is the result of calling
37292
- * toJSON() on the editor that created this widget.
37293
- *
37294
- * Should return an object representing the grading result, such as
37295
- * {
37296
- * type: "points",
37297
- * earned: 1,
37298
- * total: 1,
37299
- * message: null
37300
- * }
37301
- */
37302
- simpleValidate = rubric => {
37303
- return SimpleMarkdownTester.validate(this.toJSON(), rubric);
37304
- };
37305
- }
37306
-
37307
- /**
37308
- * For this widget to work, we must import this file in src/all-widgets.js
37309
- */
37310
- var SimpleMarkdownTester$1 = {
37311
- name: "simple-markdown-tester",
37312
- displayName: "Simple Markdown Tester",
37313
- hidden: true,
37314
- // Hides this widget from the Perseus.Editor widget select
37315
- widget: SimpleMarkdownTester,
37316
- transform: ___default["default"].identity
37317
- };
37318
-
37319
- var testingWidgets = [ExampleGraphieWidget$2, ExampleWidget$1, SimpleMarkdownTester$1];
37320
-
37321
- var AllWidgets = [...perseus.widgets, ...testingWidgets];
36869
+ 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];
37322
36870
 
37323
36871
  perseus.Widgets.registerEditors(AllEditors);
37324
- perseus.Widgets.registerWidgets(AllWidgets);
36872
+ perseus.Widgets.registerWidgets(perseus.widgets);
37325
36873
  perseus.Widgets.replaceDeprecatedWidgets();
37326
36874
  perseus.Widgets.replaceDeprecatedEditors();
37327
36875
 
36876
+ Object.defineProperty(exports, 'widgets', {
36877
+ enumerable: true,
36878
+ get: function () { return perseus.widgets; }
36879
+ });
37328
36880
  exports.AllEditors = AllEditors;
37329
- exports.AllWidgets = AllWidgets;
37330
36881
  exports.ArticleDiff = ArticleDiff;
37331
36882
  exports.ArticleEditor = ArticleEditor;
37332
36883
  exports.DeviceFramer = DeviceFramer;