@khanacademy/perseus-editor 4.2.7 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -64,7 +64,7 @@ var i18n__namespace = /*#__PURE__*/_interopNamespace(i18n$1);
64
64
 
65
65
  // This file is processed by a Rollup plugin (replace) to inject the production
66
66
  const libName = "@khanacademy/perseus-editor";
67
- const libVersion = "4.2.7";
67
+ const libVersion = "4.3.0";
68
68
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
69
69
 
70
70
  function _extends() {
@@ -22087,7 +22087,7 @@ class ArticleEditor extends React__namespace.Component {
22087
22087
  * Renders three buttons: "Phone", "Tablet", and "Desktop".
22088
22088
  */
22089
22089
  const {
22090
- ButtonGroup: ButtonGroup$4,
22090
+ ButtonGroup: ButtonGroup$5,
22091
22091
  InlineIcon: InlineIcon$9
22092
22092
  } = perseus.components;
22093
22093
  const {
@@ -22117,7 +22117,7 @@ class ViewportResizer extends React__namespace.Component {
22117
22117
  // TODO(david): Allow input of custom viewport sizes.
22118
22118
  return /*#__PURE__*/React__namespace.createElement("span", {
22119
22119
  className: "viewport-resizer"
22120
- }, "Viewport:", " ", /*#__PURE__*/React__namespace.createElement(ButtonGroup$4, {
22120
+ }, "Viewport:", " ", /*#__PURE__*/React__namespace.createElement(ButtonGroup$5, {
22121
22121
  value: this.props.deviceType,
22122
22122
  allowEmpty: false,
22123
22123
  buttons: [{
@@ -22135,8 +22135,6 @@ class ViewportResizer extends React__namespace.Component {
22135
22135
  }
22136
22136
  }
22137
22137
 
22138
- var jsdiff$1 = {exports: {}};
22139
-
22140
22138
  /*
22141
22139
  Software License Agreement (BSD License)
22142
22140
 
@@ -22171,382 +22169,374 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISI
22171
22169
  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22172
22170
  */
22173
22171
 
22174
- (function (module) {
22175
- /*
22176
- * Text diff implementation.
22177
- *
22178
- * This library supports the following APIS:
22179
- * JsDiff.diffChars: Character by character diff
22180
- * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
22181
- * JsDiff.diffLines: Line based diff
22182
- *
22183
- * JsDiff.diffCss: Diff targeted at CSS content
22184
- *
22185
- * These methods are based on the implementation proposed in
22186
- * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
22187
- * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
22188
- */
22189
- var JsDiff = function () {
22190
- /*jshint maxparams: 5*/
22191
- function clonePath(path) {
22192
- return {
22193
- newPos: path.newPos,
22194
- components: path.components.slice(0)
22195
- };
22196
- }
22197
- function removeEmpty(array) {
22198
- var ret = [];
22199
- for (var i = 0; i < array.length; i++) {
22200
- if (array[i]) {
22201
- ret.push(array[i]);
22202
- }
22203
- }
22204
- return ret;
22205
- }
22206
- function escapeHTML(s) {
22207
- var n = s;
22208
- n = n.replace(/&/g, '&amp;');
22209
- n = n.replace(/</g, '&lt;');
22210
- n = n.replace(/>/g, '&gt;');
22211
- n = n.replace(/"/g, '&quot;');
22212
- return n;
22213
- }
22214
- var Diff = function (ignoreWhitespace) {
22215
- this.ignoreWhitespace = ignoreWhitespace;
22216
- };
22217
- Diff.prototype = {
22218
- diff: function (oldString, newString) {
22219
- // Handle the identity case (this is due to unrolling editLength == 0
22220
- if (newString === oldString) {
22221
- return [{
22222
- value: newString
22223
- }];
22224
- }
22225
- if (!newString) {
22226
- return [{
22227
- value: oldString,
22228
- removed: true
22229
- }];
22230
- }
22231
- if (!oldString) {
22232
- return [{
22233
- value: newString,
22234
- added: true
22235
- }];
22236
- }
22237
- newString = this.tokenize(newString);
22238
- oldString = this.tokenize(oldString);
22239
- var newLen = newString.length,
22240
- oldLen = oldString.length;
22241
- var maxEditLength = newLen + oldLen;
22242
- var bestPath = [{
22243
- newPos: -1,
22244
- components: []
22245
- }];
22172
+ /*
22173
+ * Text diff implementation.
22174
+ *
22175
+ * This library supports the following APIS:
22176
+ * JsDiff.diffChars: Character by character diff
22177
+ * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
22178
+ * JsDiff.diffLines: Line based diff
22179
+ *
22180
+ * JsDiff.diffCss: Diff targeted at CSS content
22181
+ *
22182
+ * These methods are based on the implementation proposed in
22183
+ * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
22184
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
22185
+ */
22246
22186
 
22247
- // Seed editLength = 0
22248
- var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
22249
- if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
22250
- return bestPath[0].components;
22251
- }
22252
- for (var editLength = 1; editLength <= maxEditLength; editLength++) {
22253
- for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
22254
- var basePath;
22255
- var addPath = bestPath[diagonalPath - 1],
22256
- removePath = bestPath[diagonalPath + 1];
22257
- oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
22258
- if (addPath) {
22259
- // No one else is going to attempt to use this value, clear it
22260
- bestPath[diagonalPath - 1] = undefined;
22261
- }
22262
- var canAdd = addPath && addPath.newPos + 1 < newLen;
22263
- var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
22264
- if (!canAdd && !canRemove) {
22265
- bestPath[diagonalPath] = undefined;
22266
- continue;
22267
- }
22187
+ /*jshint maxparams: 5*/
22188
+ function clonePath(path) {
22189
+ return {
22190
+ newPos: path.newPos,
22191
+ components: path.components.slice(0)
22192
+ };
22193
+ }
22194
+ function removeEmpty(array) {
22195
+ var ret = [];
22196
+ for (var i = 0; i < array.length; i++) {
22197
+ if (array[i]) {
22198
+ ret.push(array[i]);
22199
+ }
22200
+ }
22201
+ return ret;
22202
+ }
22203
+ function escapeHTML(s) {
22204
+ var n = s;
22205
+ n = n.replace(/&/g, '&amp;');
22206
+ n = n.replace(/</g, '&lt;');
22207
+ n = n.replace(/>/g, '&gt;');
22208
+ n = n.replace(/"/g, '&quot;');
22209
+ return n;
22210
+ }
22211
+ var Diff = function (ignoreWhitespace) {
22212
+ this.ignoreWhitespace = ignoreWhitespace;
22213
+ };
22214
+ Diff.prototype = {
22215
+ diff: function (oldString, newString) {
22216
+ // Handle the identity case (this is due to unrolling editLength == 0
22217
+ if (newString === oldString) {
22218
+ return [{
22219
+ value: newString
22220
+ }];
22221
+ }
22222
+ if (!newString) {
22223
+ return [{
22224
+ value: oldString,
22225
+ removed: true
22226
+ }];
22227
+ }
22228
+ if (!oldString) {
22229
+ return [{
22230
+ value: newString,
22231
+ added: true
22232
+ }];
22233
+ }
22234
+ newString = this.tokenize(newString);
22235
+ oldString = this.tokenize(oldString);
22236
+ var newLen = newString.length,
22237
+ oldLen = oldString.length;
22238
+ var maxEditLength = newLen + oldLen;
22239
+ var bestPath = [{
22240
+ newPos: -1,
22241
+ components: []
22242
+ }];
22268
22243
 
22269
- // Select the diagonal that we want to branch from. We select the prior
22270
- // path whose position in the new string is the farthest from the origin
22271
- // and does not pass the bounds of the diff graph
22272
- if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
22273
- basePath = clonePath(removePath);
22274
- this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
22275
- } else {
22276
- basePath = clonePath(addPath);
22277
- basePath.newPos++;
22278
- this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
22279
- }
22280
- var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
22281
- if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
22282
- return basePath.components;
22283
- } else {
22284
- bestPath[diagonalPath] = basePath;
22285
- }
22286
- }
22287
- }
22288
- },
22289
- pushComponent: function (components, value, added, removed) {
22290
- var last = components[components.length - 1];
22291
- if (last && last.added === added && last.removed === removed) {
22292
- // We need to clone here as the component clone operation is just
22293
- // as shallow array clone
22294
- components[components.length - 1] = {
22295
- value: this.join(last.value, value),
22296
- added: added,
22297
- removed: removed
22298
- };
22299
- } else {
22300
- components.push({
22301
- value: value,
22302
- added: added,
22303
- removed: removed
22304
- });
22305
- }
22306
- },
22307
- extractCommon: function (basePath, newString, oldString, diagonalPath) {
22308
- var newLen = newString.length,
22309
- oldLen = oldString.length,
22310
- newPos = basePath.newPos,
22311
- oldPos = newPos - diagonalPath;
22312
- while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
22313
- newPos++;
22314
- oldPos++;
22315
- this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
22316
- }
22317
- basePath.newPos = newPos;
22318
- return oldPos;
22319
- },
22320
- equals: function (left, right) {
22321
- var reWhitespace = /\S/;
22322
- if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
22323
- return true;
22324
- } else {
22325
- return left === right;
22326
- }
22327
- },
22328
- join: function (left, right) {
22329
- return left + right;
22330
- },
22331
- tokenize: function (value) {
22332
- return value;
22333
- }
22334
- };
22335
- var CharDiff = new Diff();
22336
- var WordDiff = new Diff(true);
22337
- var WordWithSpaceDiff = new Diff();
22338
- WordDiff.tokenize = WordWithSpaceDiff.tokenize = function (value) {
22339
- return removeEmpty(value.split(/(\s+|\b)/));
22340
- };
22341
- var CssDiff = new Diff(true);
22342
- CssDiff.tokenize = function (value) {
22343
- return removeEmpty(value.split(/([{}:;,]|\s+)/));
22344
- };
22345
- var LineDiff = new Diff();
22346
- LineDiff.tokenize = function (value) {
22347
- var retLines = [],
22348
- lines = value.split(/^/m);
22349
- for (var i = 0; i < lines.length; i++) {
22350
- var line = lines[i],
22351
- lastLine = lines[i - 1];
22352
-
22353
- // Merge lines that may contain windows new lines
22354
- if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
22355
- retLines[retLines.length - 1] += '\n';
22356
- } else if (line) {
22357
- retLines.push(line);
22358
- }
22359
- }
22360
- return retLines;
22361
- };
22362
- return {
22363
- Diff: Diff,
22364
- diffChars: function (oldStr, newStr) {
22365
- return CharDiff.diff(oldStr, newStr);
22366
- },
22367
- diffWords: function (oldStr, newStr) {
22368
- return WordDiff.diff(oldStr, newStr);
22369
- },
22370
- diffWordsWithSpace: function (oldStr, newStr) {
22371
- return WordWithSpaceDiff.diff(oldStr, newStr);
22372
- },
22373
- diffLines: function (oldStr, newStr) {
22374
- return LineDiff.diff(oldStr, newStr);
22375
- },
22376
- diffCss: function (oldStr, newStr) {
22377
- return CssDiff.diff(oldStr, newStr);
22378
- },
22379
- createPatch: function (fileName, oldStr, newStr, oldHeader, newHeader) {
22380
- var ret = [];
22381
- ret.push('Index: ' + fileName);
22382
- ret.push('===================================================================');
22383
- ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
22384
- ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
22385
- var diff = LineDiff.diff(oldStr, newStr);
22386
- if (!diff[diff.length - 1].value) {
22387
- diff.pop(); // Remove trailing newline add
22388
- }
22244
+ // Seed editLength = 0
22245
+ var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
22246
+ if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
22247
+ return bestPath[0].components;
22248
+ }
22249
+ for (var editLength = 1; editLength <= maxEditLength; editLength++) {
22250
+ for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
22251
+ var basePath;
22252
+ var addPath = bestPath[diagonalPath - 1],
22253
+ removePath = bestPath[diagonalPath + 1];
22254
+ oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
22255
+ if (addPath) {
22256
+ // No one else is going to attempt to use this value, clear it
22257
+ bestPath[diagonalPath - 1] = undefined;
22258
+ }
22259
+ var canAdd = addPath && addPath.newPos + 1 < newLen;
22260
+ var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
22261
+ if (!canAdd && !canRemove) {
22262
+ bestPath[diagonalPath] = undefined;
22263
+ continue;
22264
+ }
22389
22265
 
22390
- diff.push({
22391
- value: '',
22392
- lines: []
22393
- }); // Append an empty value to make cleanup easier
22266
+ // Select the diagonal that we want to branch from. We select the prior
22267
+ // path whose position in the new string is the farthest from the origin
22268
+ // and does not pass the bounds of the diff graph
22269
+ if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
22270
+ basePath = clonePath(removePath);
22271
+ this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
22272
+ } else {
22273
+ basePath = clonePath(addPath);
22274
+ basePath.newPos++;
22275
+ this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
22276
+ }
22277
+ var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
22278
+ if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
22279
+ return basePath.components;
22280
+ } else {
22281
+ bestPath[diagonalPath] = basePath;
22282
+ }
22283
+ }
22284
+ }
22285
+ },
22286
+ pushComponent: function (components, value, added, removed) {
22287
+ var last = components[components.length - 1];
22288
+ if (last && last.added === added && last.removed === removed) {
22289
+ // We need to clone here as the component clone operation is just
22290
+ // as shallow array clone
22291
+ components[components.length - 1] = {
22292
+ value: this.join(last.value, value),
22293
+ added: added,
22294
+ removed: removed
22295
+ };
22296
+ } else {
22297
+ components.push({
22298
+ value: value,
22299
+ added: added,
22300
+ removed: removed
22301
+ });
22302
+ }
22303
+ },
22304
+ extractCommon: function (basePath, newString, oldString, diagonalPath) {
22305
+ var newLen = newString.length,
22306
+ oldLen = oldString.length,
22307
+ newPos = basePath.newPos,
22308
+ oldPos = newPos - diagonalPath;
22309
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
22310
+ newPos++;
22311
+ oldPos++;
22312
+ this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
22313
+ }
22314
+ basePath.newPos = newPos;
22315
+ return oldPos;
22316
+ },
22317
+ equals: function (left, right) {
22318
+ var reWhitespace = /\S/;
22319
+ if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
22320
+ return true;
22321
+ } else {
22322
+ return left === right;
22323
+ }
22324
+ },
22325
+ join: function (left, right) {
22326
+ return left + right;
22327
+ },
22328
+ tokenize: function (value) {
22329
+ return value;
22330
+ }
22331
+ };
22332
+ var CharDiff = new Diff();
22333
+ var WordDiff = new Diff(true);
22334
+ var WordWithSpaceDiff = new Diff();
22335
+ WordDiff.tokenize = WordWithSpaceDiff.tokenize = function (value) {
22336
+ return removeEmpty(value.split(/(\s+|\b)/));
22337
+ };
22338
+ var CssDiff = new Diff(true);
22339
+ CssDiff.tokenize = function (value) {
22340
+ return removeEmpty(value.split(/([{}:;,]|\s+)/));
22341
+ };
22342
+ var LineDiff = new Diff();
22343
+ LineDiff.tokenize = function (value) {
22344
+ var retLines = [],
22345
+ lines = value.split(/^/m);
22346
+ for (var i = 0; i < lines.length; i++) {
22347
+ var line = lines[i],
22348
+ lastLine = lines[i - 1];
22349
+
22350
+ // Merge lines that may contain windows new lines
22351
+ if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
22352
+ retLines[retLines.length - 1] += '\n';
22353
+ } else if (line) {
22354
+ retLines.push(line);
22355
+ }
22356
+ }
22357
+ return retLines;
22358
+ };
22359
+ const JSDiff = {
22360
+ Diff: Diff,
22361
+ diffChars: function (oldStr, newStr) {
22362
+ return CharDiff.diff(oldStr, newStr);
22363
+ },
22364
+ diffWords: function (oldStr, newStr) {
22365
+ return WordDiff.diff(oldStr, newStr);
22366
+ },
22367
+ diffWordsWithSpace: function (oldStr, newStr) {
22368
+ return WordWithSpaceDiff.diff(oldStr, newStr);
22369
+ },
22370
+ diffLines: function (oldStr, newStr) {
22371
+ return LineDiff.diff(oldStr, newStr);
22372
+ },
22373
+ diffCss: function (oldStr, newStr) {
22374
+ return CssDiff.diff(oldStr, newStr);
22375
+ },
22376
+ createPatch: function (fileName, oldStr, newStr, oldHeader, newHeader) {
22377
+ var ret = [];
22378
+ ret.push('Index: ' + fileName);
22379
+ ret.push('===================================================================');
22380
+ ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
22381
+ ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
22382
+ var diff = LineDiff.diff(oldStr, newStr);
22383
+ if (!diff[diff.length - 1].value) {
22384
+ diff.pop(); // Remove trailing newline add
22385
+ }
22394
22386
 
22395
- function contextLines(lines) {
22396
- return lines.map(function (entry) {
22397
- return ' ' + entry;
22398
- });
22399
- }
22400
- function eofNL(curRange, i, current) {
22401
- var last = diff[diff.length - 2],
22402
- isLast = i === diff.length - 2,
22403
- isLastOfType = i === diff.length - 3 && (current.added !== last.added || current.removed !== last.removed);
22404
-
22405
- // Figure out if this is the last line for the given file and missing NL
22406
- if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
22407
- curRange.push('\');
22408
- }
22409
- }
22410
- var oldRangeStart = 0,
22411
- newRangeStart = 0,
22412
- curRange = [],
22413
- oldLine = 1,
22414
- newLine = 1;
22415
- for (var i = 0; i < diff.length; i++) {
22416
- var current = diff[i],
22417
- lines = current.lines || current.value.replace(/\n$/, '').split('\n');
22418
- current.lines = lines;
22419
- if (current.added || current.removed) {
22420
- if (!oldRangeStart) {
22421
- var prev = diff[i - 1];
22422
- oldRangeStart = oldLine;
22423
- newRangeStart = newLine;
22424
- if (prev) {
22425
- curRange = contextLines(prev.lines.slice(-4));
22426
- oldRangeStart -= curRange.length;
22427
- newRangeStart -= curRange.length;
22428
- }
22429
- }
22430
- curRange.push.apply(curRange, lines.map(function (entry) {
22431
- return (current.added ? '+' : '-') + entry;
22432
- }));
22433
- eofNL(curRange, i, current);
22434
- if (current.added) {
22435
- newLine += lines.length;
22436
- } else {
22437
- oldLine += lines.length;
22438
- }
22439
- } else {
22440
- if (oldRangeStart) {
22441
- // Close out any changes that have been output (or join overlapping)
22442
- if (lines.length <= 8 && i < diff.length - 2) {
22443
- // Overlapping
22444
- curRange.push.apply(curRange, contextLines(lines));
22445
- } else {
22446
- // end the range and output
22447
- var contextSize = Math.min(lines.length, 4);
22448
- ret.push('@@ -' + oldRangeStart + ',' + (oldLine - oldRangeStart + contextSize) + ' +' + newRangeStart + ',' + (newLine - newRangeStart + contextSize) + ' @@');
22449
- ret.push.apply(ret, curRange);
22450
- ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
22451
- if (lines.length <= 4) {
22452
- eofNL(ret, i, current);
22453
- }
22454
- oldRangeStart = 0;
22455
- newRangeStart = 0;
22456
- curRange = [];
22457
- }
22458
- }
22459
- oldLine += lines.length;
22460
- newLine += lines.length;
22461
- }
22462
- }
22463
- return ret.join('\n') + '\n';
22464
- },
22465
- applyPatch: function (oldStr, uniDiff) {
22466
- var diffstr = uniDiff.split('\n');
22467
- var diff = [];
22468
- var remEOFNL = false,
22469
- addEOFNL = false;
22470
- for (var i = diffstr[0][0] === 'I' ? 4 : 0; i < diffstr.length; i++) {
22471
- if (diffstr[i][0] === '@') {
22472
- var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
22473
- diff.unshift({
22474
- start: meh[3],
22475
- oldlength: meh[2],
22476
- oldlines: [],
22477
- newlength: meh[4],
22478
- newlines: []
22479
- });
22480
- } else if (diffstr[i][0] === '+') {
22481
- diff[0].newlines.push(diffstr[i].substr(1));
22482
- } else if (diffstr[i][0] === '-') {
22483
- diff[0].oldlines.push(diffstr[i].substr(1));
22484
- } else if (diffstr[i][0] === ' ') {
22485
- diff[0].newlines.push(diffstr[i].substr(1));
22486
- diff[0].oldlines.push(diffstr[i].substr(1));
22487
- } else if (diffstr[i][0] === '\\') {
22488
- if (diffstr[i - 1][0] === '+') {
22489
- remEOFNL = true;
22490
- } else if (diffstr[i - 1][0] === '-') {
22491
- addEOFNL = true;
22492
- }
22493
- }
22494
- }
22495
- var str = oldStr.split('\n');
22496
- for (var i = diff.length - 1; i >= 0; i--) {
22497
- var d = diff[i];
22498
- for (var j = 0; j < d.oldlength; j++) {
22499
- if (str[d.start - 1 + j] !== d.oldlines[j]) {
22500
- return false;
22501
- }
22502
- }
22503
- Array.prototype.splice.apply(str, [d.start - 1, +d.oldlength].concat(d.newlines));
22504
- }
22505
- if (remEOFNL) {
22506
- while (!str[str.length - 1]) {
22507
- str.pop();
22508
- }
22509
- } else if (addEOFNL) {
22510
- str.push('');
22511
- }
22512
- return str.join('\n');
22513
- },
22514
- convertChangesToXML: function (changes) {
22515
- var ret = [];
22516
- for (var i = 0; i < changes.length; i++) {
22517
- var change = changes[i];
22518
- if (change.added) {
22519
- ret.push('<ins>');
22520
- } else if (change.removed) {
22521
- ret.push('<del>');
22522
- }
22523
- ret.push(escapeHTML(change.value));
22524
- if (change.added) {
22525
- ret.push('</ins>');
22526
- } else if (change.removed) {
22527
- ret.push('</del>');
22528
- }
22529
- }
22530
- return ret.join('');
22531
- },
22532
- // See: http://code.google.com/p/google-diff-match-patch/wiki/API
22533
- convertChangesToDMP: function (changes) {
22534
- var ret = [],
22535
- change;
22536
- for (var i = 0; i < changes.length; i++) {
22537
- change = changes[i];
22538
- ret.push([change.added ? 1 : change.removed ? -1 : 0, change.value]);
22539
- }
22540
- return ret;
22541
- }
22542
- };
22543
- }();
22544
- {
22545
- module.exports = JsDiff;
22546
- }
22547
- } (jsdiff$1));
22387
+ diff.push({
22388
+ value: '',
22389
+ lines: []
22390
+ }); // Append an empty value to make cleanup easier
22548
22391
 
22549
- var jsdiff = jsdiff$1.exports;
22392
+ function contextLines(lines) {
22393
+ return lines.map(function (entry) {
22394
+ return ' ' + entry;
22395
+ });
22396
+ }
22397
+ function eofNL(curRange, i, current) {
22398
+ var last = diff[diff.length - 2],
22399
+ isLast = i === diff.length - 2,
22400
+ isLastOfType = i === diff.length - 3 && (current.added !== last.added || current.removed !== last.removed);
22401
+
22402
+ // Figure out if this is the last line for the given file and missing NL
22403
+ if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
22404
+ curRange.push('\');
22405
+ }
22406
+ }
22407
+ var oldRangeStart = 0,
22408
+ newRangeStart = 0,
22409
+ curRange = [],
22410
+ oldLine = 1,
22411
+ newLine = 1;
22412
+ for (var i = 0; i < diff.length; i++) {
22413
+ var current = diff[i],
22414
+ lines = current.lines || current.value.replace(/\n$/, '').split('\n');
22415
+ current.lines = lines;
22416
+ if (current.added || current.removed) {
22417
+ if (!oldRangeStart) {
22418
+ var prev = diff[i - 1];
22419
+ oldRangeStart = oldLine;
22420
+ newRangeStart = newLine;
22421
+ if (prev) {
22422
+ curRange = contextLines(prev.lines.slice(-4));
22423
+ oldRangeStart -= curRange.length;
22424
+ newRangeStart -= curRange.length;
22425
+ }
22426
+ }
22427
+ curRange.push.apply(curRange, lines.map(function (entry) {
22428
+ return (current.added ? '+' : '-') + entry;
22429
+ }));
22430
+ eofNL(curRange, i, current);
22431
+ if (current.added) {
22432
+ newLine += lines.length;
22433
+ } else {
22434
+ oldLine += lines.length;
22435
+ }
22436
+ } else {
22437
+ if (oldRangeStart) {
22438
+ // Close out any changes that have been output (or join overlapping)
22439
+ if (lines.length <= 8 && i < diff.length - 2) {
22440
+ // Overlapping
22441
+ curRange.push.apply(curRange, contextLines(lines));
22442
+ } else {
22443
+ // end the range and output
22444
+ var contextSize = Math.min(lines.length, 4);
22445
+ ret.push('@@ -' + oldRangeStart + ',' + (oldLine - oldRangeStart + contextSize) + ' +' + newRangeStart + ',' + (newLine - newRangeStart + contextSize) + ' @@');
22446
+ ret.push.apply(ret, curRange);
22447
+ ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
22448
+ if (lines.length <= 4) {
22449
+ eofNL(ret, i, current);
22450
+ }
22451
+ oldRangeStart = 0;
22452
+ newRangeStart = 0;
22453
+ curRange = [];
22454
+ }
22455
+ }
22456
+ oldLine += lines.length;
22457
+ newLine += lines.length;
22458
+ }
22459
+ }
22460
+ return ret.join('\n') + '\n';
22461
+ },
22462
+ applyPatch: function (oldStr, uniDiff) {
22463
+ var diffstr = uniDiff.split('\n');
22464
+ var diff = [];
22465
+ var remEOFNL = false,
22466
+ addEOFNL = false;
22467
+ for (var i = diffstr[0][0] === 'I' ? 4 : 0; i < diffstr.length; i++) {
22468
+ if (diffstr[i][0] === '@') {
22469
+ var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
22470
+ diff.unshift({
22471
+ start: meh[3],
22472
+ oldlength: meh[2],
22473
+ oldlines: [],
22474
+ newlength: meh[4],
22475
+ newlines: []
22476
+ });
22477
+ } else if (diffstr[i][0] === '+') {
22478
+ diff[0].newlines.push(diffstr[i].substr(1));
22479
+ } else if (diffstr[i][0] === '-') {
22480
+ diff[0].oldlines.push(diffstr[i].substr(1));
22481
+ } else if (diffstr[i][0] === ' ') {
22482
+ diff[0].newlines.push(diffstr[i].substr(1));
22483
+ diff[0].oldlines.push(diffstr[i].substr(1));
22484
+ } else if (diffstr[i][0] === '\\') {
22485
+ if (diffstr[i - 1][0] === '+') {
22486
+ remEOFNL = true;
22487
+ } else if (diffstr[i - 1][0] === '-') {
22488
+ addEOFNL = true;
22489
+ }
22490
+ }
22491
+ }
22492
+ var str = oldStr.split('\n');
22493
+ for (var i = diff.length - 1; i >= 0; i--) {
22494
+ var d = diff[i];
22495
+ for (var j = 0; j < d.oldlength; j++) {
22496
+ if (str[d.start - 1 + j] !== d.oldlines[j]) {
22497
+ return false;
22498
+ }
22499
+ }
22500
+ Array.prototype.splice.apply(str, [d.start - 1, +d.oldlength].concat(d.newlines));
22501
+ }
22502
+ if (remEOFNL) {
22503
+ while (!str[str.length - 1]) {
22504
+ str.pop();
22505
+ }
22506
+ } else if (addEOFNL) {
22507
+ str.push('');
22508
+ }
22509
+ return str.join('\n');
22510
+ },
22511
+ convertChangesToXML: function (changes) {
22512
+ var ret = [];
22513
+ for (var i = 0; i < changes.length; i++) {
22514
+ var change = changes[i];
22515
+ if (change.added) {
22516
+ ret.push('<ins>');
22517
+ } else if (change.removed) {
22518
+ ret.push('<del>');
22519
+ }
22520
+ ret.push(escapeHTML(change.value));
22521
+ if (change.added) {
22522
+ ret.push('</ins>');
22523
+ } else if (change.removed) {
22524
+ ret.push('</del>');
22525
+ }
22526
+ }
22527
+ return ret.join('');
22528
+ },
22529
+ // See: http://code.google.com/p/google-diff-match-patch/wiki/API
22530
+ convertChangesToDMP: function (changes) {
22531
+ var ret = [],
22532
+ change;
22533
+ for (var i = 0; i < changes.length; i++) {
22534
+ change = changes[i];
22535
+ ret.push([change.added ? 1 : change.removed ? -1 : 0, change.value]);
22536
+ }
22537
+ return ret;
22538
+ }
22539
+ };
22550
22540
 
22551
22541
  // Split a word-wise diff generated by jsdiff into multiple lines, for the
22552
22542
  // purpose of breaking up the diffs into lines, so that modified lines can be
@@ -22609,7 +22599,7 @@ const mapcat = function (lst, fn) {
22609
22599
  // { "value": [2, 3] },
22610
22600
  // { "value": [4],
22611
22601
  // "added": true }]
22612
- const ArrayDiff = new jsdiff.Diff();
22602
+ const ArrayDiff = new JSDiff.Diff();
22613
22603
  ArrayDiff.tokenize = array => ___default["default"].map(array, elem => [elem]);
22614
22604
  // The default is `+` for string concatenation, which doesn't work for array
22615
22605
  // concatenation.
@@ -22708,7 +22698,7 @@ class TextDiff extends React__namespace.Component {
22708
22698
  });
22709
22699
  };
22710
22700
  render() {
22711
- const diffed = jsdiff.diffWords(this.props.before, this.props.after);
22701
+ const diffed = JSDiff.diffWords(this.props.before, this.props.after);
22712
22702
  const lines = splitDiff(diffed);
22713
22703
  const beforeImages = imagesInString(this.props.before);
22714
22704
  const afterImages = imagesInString(this.props.after);
@@ -23456,7 +23446,7 @@ class StructuredItemDiff extends React__namespace.Component {
23456
23446
 
23457
23447
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
23458
23448
  const {
23459
- InfoTip: InfoTip$m,
23449
+ InfoTip: InfoTip$n,
23460
23450
  InlineIcon: InlineIcon$8
23461
23451
  } = perseus.components;
23462
23452
  const {
@@ -23530,7 +23520,7 @@ class HintEditor extends React__namespace.Component {
23530
23520
  type: "button",
23531
23521
  className: this.props.isFirst ? "hidden" : "",
23532
23522
  onClick: ___default["default"].partial(this.props.onMove, -1)
23533
- }, /*#__PURE__*/React__namespace.createElement(InlineIcon$8, iconCircleArrowUp$1)), " ", this.props.isLast && /*#__PURE__*/React__namespace.createElement(InfoTip$m, null, /*#__PURE__*/React__namespace.createElement("p", null, "The last hint is automatically bolded."))), /*#__PURE__*/React__namespace.createElement("input", {
23523
+ }, /*#__PURE__*/React__namespace.createElement(InlineIcon$8, iconCircleArrowUp$1)), " ", this.props.isLast && /*#__PURE__*/React__namespace.createElement(InfoTip$n, null, /*#__PURE__*/React__namespace.createElement("p", null, "The last hint is automatically bolded."))), /*#__PURE__*/React__namespace.createElement("input", {
23534
23524
  type: "checkbox"
23535
23525
  // @ts-expect-error - TS2322 - Type 'boolean | null | undefined' is not assignable to type 'boolean | undefined'.
23536
23526
  ,
@@ -23765,7 +23755,7 @@ class CombinedHintsEditor extends React__namespace.Component {
23765
23755
  }
23766
23756
 
23767
23757
  const {
23768
- InfoTip: InfoTip$l
23758
+ InfoTip: InfoTip$m
23769
23759
  } = perseus.components;
23770
23760
  class ItemExtrasEditor extends React__namespace.Component {
23771
23761
  static defaultProps = {
@@ -23922,7 +23912,7 @@ const ItemExtraCheckbox = props => /*#__PURE__*/React__namespace.createElement("
23922
23912
  type: "checkbox",
23923
23913
  checked: props.checked,
23924
23914
  onChange: props.onChange
23925
- })), /*#__PURE__*/React__namespace.createElement(InfoTip$l, null, props.infoTip));
23915
+ })), /*#__PURE__*/React__namespace.createElement(InfoTip$m, null, props.infoTip));
23926
23916
 
23927
23917
  const ITEM_DATA_VERSION = perseus.itemDataVersion;
23928
23918
  class ItemEditor extends React__namespace.Component {
@@ -25581,7 +25571,7 @@ const StatefulEditorPage = createReactClass__default["default"]({
25581
25571
  });
25582
25572
 
25583
25573
  const {
25584
- PropCheckBox: PropCheckBox$c,
25574
+ PropCheckBox: PropCheckBox$d,
25585
25575
  TextListEditor: TextListEditor$4
25586
25576
  } = perseus.components;
25587
25577
  const Categorizer = perseus.Categorizer.widget;
@@ -25616,7 +25606,7 @@ class CategorizerEditor extends React__namespace.Component {
25616
25606
  render() {
25617
25607
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
25618
25608
  className: "perseus-widget-row"
25619
- }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$c, {
25609
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$d, {
25620
25610
  label: "Randomize item order",
25621
25611
  labelAlignment: "right",
25622
25612
  randomizeItems: this.props.randomizeItems,
@@ -25714,8 +25704,8 @@ class BlurInput extends React__namespace.Component {
25714
25704
 
25715
25705
  /* eslint-disable no-useless-escape */
25716
25706
  const {
25717
- InfoTip: InfoTip$k,
25718
- PropCheckBox: PropCheckBox$b
25707
+ InfoTip: InfoTip$l,
25708
+ PropCheckBox: PropCheckBox$c
25719
25709
  } = perseus.components;
25720
25710
  const DEFAULT_WIDTH = 400;
25721
25711
  const DEFAULT_HEIGHT = 400;
@@ -25898,11 +25888,11 @@ class CSProgramEditor extends React__namespace.Component {
25898
25888
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Url or Program ID:", " ", /*#__PURE__*/React__namespace.createElement(BlurInput, {
25899
25889
  value: this.props.programID,
25900
25890
  onChange: this._handleProgramIDChange
25901
- })), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement(PropCheckBox$b, {
25891
+ })), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement(PropCheckBox$c, {
25902
25892
  label: "Show Editor",
25903
25893
  showEditor: this.props.showEditor,
25904
25894
  onChange: this.props.onChange
25905
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$k, null, "If you show the editor, you should use the \"full-width\" alignment to make room for the width of the editor."), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement(PropCheckBox$b, {
25895
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$l, null, "If you show the editor, you should use the \"full-width\" alignment to make room for the width of the editor."), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement(PropCheckBox$c, {
25906
25896
  label: "Show Buttons",
25907
25897
  showButtons: this.props.showButtons,
25908
25898
  onChange: this.props.onChange
@@ -25910,7 +25900,7 @@ class CSProgramEditor extends React__namespace.Component {
25910
25900
  name: "settings",
25911
25901
  pairs: this.props.settings,
25912
25902
  onChange: this._handleSettingsChange
25913
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$k, null, "Settings that you add here are available to the program as an object returned by ", /*#__PURE__*/React__namespace.createElement("code", null, "Program.settings()"))));
25903
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$l, null, "Settings that you add here are available to the program as an object returned by ", /*#__PURE__*/React__namespace.createElement("code", null, "Program.settings()"))));
25914
25904
  }
25915
25905
  }
25916
25906
 
@@ -25987,7 +25977,7 @@ class DeprecatedStandinEditor extends React__namespace.Component {
25987
25977
 
25988
25978
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
25989
25979
  const {
25990
- InfoTip: InfoTip$j,
25980
+ InfoTip: InfoTip$k,
25991
25981
  InlineIcon: InlineIcon$6
25992
25982
  } = perseus.components;
25993
25983
  const {
@@ -26068,14 +26058,14 @@ class DropdownEditor extends React__namespace.Component {
26068
26058
  className: "perseus-widget-dropdown"
26069
26059
  }, /*#__PURE__*/React__namespace.createElement("div", {
26070
26060
  className: "dropdown-info"
26071
- }, "Dropdown", /*#__PURE__*/React__namespace.createElement(InfoTip$j, null, /*#__PURE__*/React__namespace.createElement("p", null, "The drop down is useful for making inequalities in a custom format. We normally use the symbols ", "<", ",", " ", ">", ", \u2264, \u2265 (in that order) which you can copy into the choices. When possible, use the \"multiple choice\" answer type instead."))), /*#__PURE__*/React__namespace.createElement("div", {
26061
+ }, "Dropdown", /*#__PURE__*/React__namespace.createElement(InfoTip$k, null, /*#__PURE__*/React__namespace.createElement("p", null, "The drop down is useful for making inequalities in a custom format. We normally use the symbols ", "<", ",", " ", ">", ", \u2264, \u2265 (in that order) which you can copy into the choices. When possible, use the \"multiple choice\" answer type instead."))), /*#__PURE__*/React__namespace.createElement("div", {
26072
26062
  className: "dropdown-placeholder"
26073
26063
  }, /*#__PURE__*/React__namespace.createElement("input", {
26074
26064
  type: "text",
26075
26065
  placeholder: "Placeholder value",
26076
26066
  value: this.props.placeholder,
26077
26067
  onChange: this.onPlaceholderChange
26078
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$j, null, /*#__PURE__*/React__namespace.createElement("p", null, "This value will appear as the drop down default. It should give the user some indication of the values available in the drop down itself, e.g., Yes/No/Maybe."))), /*#__PURE__*/React__namespace.createElement("div", {
26068
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$k, null, /*#__PURE__*/React__namespace.createElement("p", null, "This value will appear as the drop down default. It should give the user some indication of the values available in the drop down itself, e.g., Yes/No/Maybe."))), /*#__PURE__*/React__namespace.createElement("div", {
26079
26069
  className: "clearfix"
26080
26070
  }), /*#__PURE__*/React__namespace.createElement("ul", {
26081
26071
  className: "dropdown-choices"
@@ -26615,8 +26605,8 @@ const SortableItem = createReactClass__default["default"]({
26615
26605
  });
26616
26606
 
26617
26607
  const {
26618
- InfoTip: InfoTip$i,
26619
- PropCheckBox: PropCheckBox$a
26608
+ InfoTip: InfoTip$j,
26609
+ PropCheckBox: PropCheckBox$b
26620
26610
  } = perseus.components;
26621
26611
 
26622
26612
  // types for iterables
@@ -26735,16 +26725,16 @@ class ExpressionEditor extends React__namespace.Component {
26735
26725
  className: "perseus-widget-expression-editor"
26736
26726
  }, /*#__PURE__*/React__namespace.createElement("h3", {
26737
26727
  className: "expression-editor-h3"
26738
- }, "Global Options"), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(PropCheckBox$a, {
26728
+ }, "Global Options"), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(PropCheckBox$b, {
26739
26729
  times: this.props.times,
26740
26730
  onChange: this.props.onChange,
26741
26731
  labelAlignment: "right",
26742
26732
  label: "Use \xD7 for rendering multiplication instead of a center dot."
26743
- }), /*#__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", null, /*#__PURE__*/React__namespace.createElement("label", null, "Function variables: ", /*#__PURE__*/React__namespace.createElement("input", {
26733
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$j, 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", null, /*#__PURE__*/React__namespace.createElement("label", null, "Function variables: ", /*#__PURE__*/React__namespace.createElement("input", {
26744
26734
  type: "text",
26745
26735
  defaultValue: this.props.functions.join(" "),
26746
26736
  onChange: this.handleFunctions
26747
- })), /*#__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", null, /*#__PURE__*/React__namespace.createElement("div", null, "Button sets:"), buttonSetChoices), /*#__PURE__*/React__namespace.createElement("h3", {
26737
+ })), /*#__PURE__*/React__namespace.createElement(InfoTip$j, 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", null, /*#__PURE__*/React__namespace.createElement("div", null, "Button sets:"), buttonSetChoices), /*#__PURE__*/React__namespace.createElement("h3", {
26748
26738
  className: "expression-editor-h3"
26749
26739
  }, "Answers"), /*#__PURE__*/React__namespace.createElement("p", {
26750
26740
  style: {
@@ -26953,19 +26943,19 @@ class AnswerOption extends React__namespace.Component {
26953
26943
  className: "answer-expression"
26954
26944
  }, /*#__PURE__*/React__namespace.createElement(perseus.Expression, this.props.expressionProps))), /*#__PURE__*/React__namespace.createElement("div", {
26955
26945
  className: "answer-option"
26956
- }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$a, {
26946
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$b, {
26957
26947
  form: this.props.form,
26958
26948
  onChange: this.props.onChange,
26959
26949
  labelAlignment: "right",
26960
26950
  label: "Answer expression must have the same form."
26961
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student's answer must be in the same form. Commutativity and excess negative signs are ignored."))), /*#__PURE__*/React__namespace.createElement("div", {
26951
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$j, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student's answer must be in the same form. Commutativity and excess negative signs are ignored."))), /*#__PURE__*/React__namespace.createElement("div", {
26962
26952
  className: "answer-option"
26963
- }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$a, {
26953
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$b, {
26964
26954
  simplify: this.props.simplify,
26965
26955
  onChange: this.props.onChange,
26966
26956
  labelAlignment: "right",
26967
26957
  label: "Answer expression must be fully expanded and simplified."
26968
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student's answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response \"Your answer is not fully expanded and simplified.\""))), /*#__PURE__*/React__namespace.createElement("div", {
26958
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$j, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student's answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response \"Your answer is not fully expanded and simplified.\""))), /*#__PURE__*/React__namespace.createElement("div", {
26969
26959
  className: "remove-container"
26970
26960
  }, removeButton)));
26971
26961
  }
@@ -27189,20 +27179,17 @@ const setArrayItem = (list, i, value) => [...list.slice(0, i), value, ...list.sl
27189
27179
 
27190
27180
  /* eslint-disable react/forbid-prop-types, react/no-unsafe */
27191
27181
  const {
27192
- ButtonGroup: ButtonGroup$3,
27193
- InfoTip: InfoTip$h,
27194
- PropCheckBox: PropCheckBox$9,
27195
- RangeInput: RangeInput$5
27182
+ ButtonGroup: ButtonGroup$4,
27183
+ InfoTip: InfoTip$i,
27184
+ PropCheckBox: PropCheckBox$a,
27185
+ RangeInput: RangeInput$6
27196
27186
  } = perseus.components;
27197
- const {
27198
- getDependencies: getDependencies$9
27199
- } = perseus.Dependencies;
27200
- const defaultBackgroundImage$2 = {
27187
+ const defaultBackgroundImage$3 = {
27201
27188
  url: null,
27202
27189
  width: 0,
27203
27190
  height: 0
27204
27191
  };
27205
- function numSteps(range, step) {
27192
+ function numSteps$1(range, step) {
27206
27193
  return Math.floor((range[1] - range[0]) / step);
27207
27194
  }
27208
27195
  const GraphSettings = createReactClass__default["default"]({
@@ -27235,7 +27222,7 @@ const GraphSettings = createReactClass__default["default"]({
27235
27222
  gridStep: [1, 1],
27236
27223
  snapStep: [1, 1],
27237
27224
  valid: true,
27238
- backgroundImage: defaultBackgroundImage$2,
27225
+ backgroundImage: defaultBackgroundImage$3,
27239
27226
  markings: "graph",
27240
27227
  showProtractor: false,
27241
27228
  showRuler: false,
@@ -27348,7 +27335,7 @@ const GraphSettings = createReactClass__default["default"]({
27348
27335
  if (!___default["default"].isFinite(step)) {
27349
27336
  return name + " must be a valid number";
27350
27337
  }
27351
- const nSteps = numSteps(range, step);
27338
+ const nSteps = numSteps$1(range, step);
27352
27339
  if (nSteps < minTicks) {
27353
27340
  return name + " is too large, there must be at least " + minTicks + " ticks.";
27354
27341
  }
@@ -27516,12 +27503,16 @@ const GraphSettings = createReactClass__default["default"]({
27516
27503
  const scale = [perseus.KhanMath.roundTo(2, perseus.Util.scaleFromExtent(this.props.range[0], this.props.box[0])), perseus.KhanMath.roundTo(2, perseus.Util.scaleFromExtent(this.props.range[1], this.props.box[1]))];
27517
27504
  const {
27518
27505
  TeX
27519
- } = getDependencies$9();
27506
+ } = perseus.Dependencies.getDependencies();
27507
+ this.props.box; // ?
27520
27508
  return /*#__PURE__*/React__namespace.createElement("div", null, ___default["default"].contains(this.props.editableSettings, "canvas") && /*#__PURE__*/React__namespace.createElement("div", {
27521
27509
  className: "graph-settings"
27522
27510
  }, /*#__PURE__*/React__namespace.createElement("div", {
27523
27511
  className: "perseus-widget-row"
27524
- }, "Canvas size (x,y pixels)", /*#__PURE__*/React__namespace.createElement(RangeInput$5, {
27512
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27513
+ htmlFor: "canvas-size"
27514
+ }, "Canvas size (x,y pixels)"), /*#__PURE__*/React__namespace.createElement(RangeInput$6, {
27515
+ id: "canvas-size",
27525
27516
  value: this.props.box,
27526
27517
  onChange: box => {
27527
27518
  this.change({
@@ -27536,7 +27527,10 @@ const GraphSettings = createReactClass__default["default"]({
27536
27527
  className: "perseus-widget-row"
27537
27528
  }, /*#__PURE__*/React__namespace.createElement("div", {
27538
27529
  className: "perseus-widget-left-col"
27539
- }, " ", "x Label", /*#__PURE__*/React__namespace.createElement("input", {
27530
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27531
+ htmlFor: "labels-x"
27532
+ }, "x Label"), /*#__PURE__*/React__namespace.createElement("input", {
27533
+ id: "labels-x",
27540
27534
  type: "text",
27541
27535
  className: "graph-settings-axis-label"
27542
27536
  // eslint-disable-next-line react/no-string-refs
@@ -27546,7 +27540,10 @@ const GraphSettings = createReactClass__default["default"]({
27546
27540
  value: this.state.labelsTextbox[0] || ""
27547
27541
  })), /*#__PURE__*/React__namespace.createElement("div", {
27548
27542
  className: "perseus-widget-right-col"
27549
- }, "y Label", /*#__PURE__*/React__namespace.createElement("input", {
27543
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27544
+ htmlFor: "labels-y"
27545
+ }, "y Label"), /*#__PURE__*/React__namespace.createElement("input", {
27546
+ id: "labels-y",
27550
27547
  type: "text",
27551
27548
  className: "graph-settings-axis-label"
27552
27549
  // eslint-disable-next-line react/no-string-refs
@@ -27558,36 +27555,51 @@ const GraphSettings = createReactClass__default["default"]({
27558
27555
  className: "perseus-widget-row"
27559
27556
  }, /*#__PURE__*/React__namespace.createElement("div", {
27560
27557
  className: "perseus-widget-left-col"
27561
- }, "x Range", /*#__PURE__*/React__namespace.createElement(RangeInput$5, {
27558
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27559
+ htmlFor: "range-x"
27560
+ }, "x Range"), /*#__PURE__*/React__namespace.createElement(RangeInput$6, {
27561
+ id: "range-x",
27562
27562
  value: this.state.rangeTextbox[0],
27563
27563
  onChange: vals => this.changeRange(0, vals)
27564
27564
  })), /*#__PURE__*/React__namespace.createElement("div", {
27565
27565
  className: "perseus-widget-right-col"
27566
- }, "y Range", /*#__PURE__*/React__namespace.createElement(RangeInput$5, {
27566
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27567
+ htmlFor: "range-y"
27568
+ }, "y Range"), /*#__PURE__*/React__namespace.createElement(RangeInput$6, {
27569
+ id: "range-y",
27567
27570
  value: this.state.rangeTextbox[1],
27568
27571
  onChange: vals => this.changeRange(1, vals)
27569
27572
  }))), /*#__PURE__*/React__namespace.createElement("div", {
27570
27573
  className: "perseus-widget-row"
27571
27574
  }, /*#__PURE__*/React__namespace.createElement("div", {
27572
27575
  className: "perseus-widget-left-col"
27573
- }, "Tick Step", /*#__PURE__*/React__namespace.createElement(RangeInput$5, {
27576
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27577
+ htmlFor: "tick-step"
27578
+ }, "Tick Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$6, {
27579
+ id: "tick-step",
27574
27580
  value: this.state.stepTextbox,
27575
27581
  onChange: this.changeStep
27576
27582
  })), /*#__PURE__*/React__namespace.createElement("div", {
27577
27583
  className: "perseus-widget-right-col"
27578
- }, "Grid Step", /*#__PURE__*/React__namespace.createElement(RangeInput$5, {
27584
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27585
+ htmlFor: "grid-step"
27586
+ }, "Grid Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$6, {
27587
+ id: "grid-step",
27579
27588
  value: this.state.gridStepTextbox,
27580
27589
  onChange: this.changeGridStep
27581
27590
  }))), ___default["default"].contains(this.props.editableSettings, "snap") && /*#__PURE__*/React__namespace.createElement("div", {
27582
27591
  className: "perseus-widget-row"
27583
27592
  }, /*#__PURE__*/React__namespace.createElement("div", {
27584
27593
  className: "perseus-widget-left-col"
27585
- }, "Snap Step", /*#__PURE__*/React__namespace.createElement(RangeInput$5, {
27594
+ }, /*#__PURE__*/React__namespace.createElement("label", {
27595
+ htmlFor: "snap-step"
27596
+ }, "Snap Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$6, {
27597
+ id: "snap-step",
27586
27598
  value: this.state.snapStepTextbox,
27587
27599
  onChange: this.changeSnapStep
27588
27600
  }))), /*#__PURE__*/React__namespace.createElement("div", {
27589
27601
  className: "perseus-widget-row"
27590
- }, /*#__PURE__*/React__namespace.createElement("label", null, "Markings: "), /*#__PURE__*/React__namespace.createElement(ButtonGroup$3, {
27602
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Markings: "), /*#__PURE__*/React__namespace.createElement(ButtonGroup$4, {
27591
27603
  value: this.props.markings,
27592
27604
  allowEmpty: false,
27593
27605
  buttons: [{
@@ -27603,13 +27615,16 @@ const GraphSettings = createReactClass__default["default"]({
27603
27615
  onChange: this.change("markings")
27604
27616
  })), /*#__PURE__*/React__namespace.createElement("div", {
27605
27617
  className: "perseus-widget-left-col"
27606
- }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$9, {
27618
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$a, {
27607
27619
  label: "Show tooltips",
27608
27620
  showTooltips: this.props.showTooltips,
27609
27621
  onChange: this.change
27610
27622
  }))), ___default["default"].contains(this.props.editableSettings, "image") && /*#__PURE__*/React__namespace.createElement("div", {
27611
27623
  className: "image-settings"
27612
- }, /*#__PURE__*/React__namespace.createElement("div", null, "Background image:"), /*#__PURE__*/React__namespace.createElement("div", null, "Url:", " ", /*#__PURE__*/React__namespace.createElement("input", {
27624
+ }, /*#__PURE__*/React__namespace.createElement("div", null, "Background image:"), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", {
27625
+ htmlFor: "bg-url"
27626
+ }, "Url:"), /*#__PURE__*/React__namespace.createElement("input", {
27627
+ id: "bg-url",
27613
27628
  type: "text",
27614
27629
  className: "graph-settings-background-url"
27615
27630
  // eslint-disable-next-line react/no-string-refs
@@ -27625,19 +27640,19 @@ const GraphSettings = createReactClass__default["default"]({
27625
27640
  },
27626
27641
  onKeyPress: this.changeBackgroundUrl,
27627
27642
  onBlur: this.changeBackgroundUrl
27628
- }), /*#__PURE__*/React__namespace.createElement(InfoTip$h, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background.")))), ___default["default"].contains(this.props.editableSettings, "measure") && /*#__PURE__*/React__namespace.createElement("div", {
27643
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$i, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background.")))), ___default["default"].contains(this.props.editableSettings, "measure") && /*#__PURE__*/React__namespace.createElement("div", {
27629
27644
  className: "misc-settings"
27630
27645
  }, /*#__PURE__*/React__namespace.createElement("div", {
27631
27646
  className: "perseus-widget-row"
27632
27647
  }, /*#__PURE__*/React__namespace.createElement("div", {
27633
27648
  className: "perseus-widget-left-col"
27634
- }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$9, {
27649
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$a, {
27635
27650
  label: "Show ruler",
27636
27651
  showRuler: this.props.showRuler,
27637
27652
  onChange: this.change
27638
27653
  })), /*#__PURE__*/React__namespace.createElement("div", {
27639
27654
  className: "perseus-widget-right-col"
27640
- }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$9, {
27655
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$a, {
27641
27656
  label: "Show protractor",
27642
27657
  showProtractor: this.props.showProtractor,
27643
27658
  onChange: this.change
@@ -27662,7 +27677,7 @@ const GraphSettings = createReactClass__default["default"]({
27662
27677
  });
27663
27678
 
27664
27679
  const {
27665
- InfoTip: InfoTip$g,
27680
+ InfoTip: InfoTip$h,
27666
27681
  MultiButtonGroup: MultiButtonGroup$1
27667
27682
  } = perseus.components;
27668
27683
  const {
@@ -27736,7 +27751,7 @@ class GrapherEditor extends React__namespace.Component {
27736
27751
  className: "perseus-error"
27737
27752
  }, this.props.graph.valid);
27738
27753
  }
27739
- return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", null, "Correct answer", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$g, null, /*#__PURE__*/React__namespace.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer.")), " ", ": ", equationString), /*#__PURE__*/React__namespace.createElement(GraphSettings, {
27754
+ return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", null, "Correct answer", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$h, null, /*#__PURE__*/React__namespace.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer.")), " ", ": ", equationString), /*#__PURE__*/React__namespace.createElement(GraphSettings, {
27740
27755
  editableSettings: ["graph", "snap", "image"],
27741
27756
  box: getInteractiveBoxFromSizeClass$1(sizeClass),
27742
27757
  range: this.props.graph.range,
@@ -27848,7 +27863,7 @@ class GroupEditor extends React__namespace.Component {
27848
27863
 
27849
27864
  /* eslint-disable @khanacademy/ts-no-error-suppressions */
27850
27865
  const {
27851
- PropCheckBox: PropCheckBox$8
27866
+ PropCheckBox: PropCheckBox$9
27852
27867
  } = perseus.components;
27853
27868
  /**
27854
27869
  * This is used for editing a name/value pair.
@@ -27988,11 +28003,11 @@ class IframeEditor extends React__namespace.Component {
27988
28003
  // @ts-expect-error - TS2554 - Expected 3 arguments, but got 1.
27989
28004
  ,
27990
28005
  onChange: this.change("height")
27991
- })), /*#__PURE__*/React__namespace.createElement(PropCheckBox$8, {
28006
+ })), /*#__PURE__*/React__namespace.createElement(PropCheckBox$9, {
27992
28007
  label: "Allow full screen",
27993
28008
  allowFullScreen: this.props.allowFullScreen,
27994
28009
  onChange: this.props.onChange
27995
- }), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement(PropCheckBox$8, {
28010
+ }), /*#__PURE__*/React__namespace.createElement("br", null), /*#__PURE__*/React__namespace.createElement(PropCheckBox$9, {
27996
28011
  label: "Allow iframe content to redirect the page",
27997
28012
  allowTopNavigation: this.props.allowTopNavigation,
27998
28013
  onChange: this.props.onChange
@@ -28011,13 +28026,13 @@ class IframeEditor extends React__namespace.Component {
28011
28026
 
28012
28027
  /* eslint-disable jsx-a11y/anchor-is-valid, react/sort-comp */
28013
28028
  const {
28014
- InfoTip: InfoTip$f,
28029
+ InfoTip: InfoTip$g,
28015
28030
  InlineIcon: InlineIcon$4,
28016
- RangeInput: RangeInput$4
28031
+ RangeInput: RangeInput$5
28017
28032
  } = perseus.components;
28018
28033
  const defaultBoxSize = 400;
28019
28034
  const defaultRange = [0, 10];
28020
- const defaultBackgroundImage$1 = {
28035
+ const defaultBackgroundImage$2 = {
28021
28036
  url: null,
28022
28037
  width: 0,
28023
28038
  height: 0
@@ -28042,7 +28057,7 @@ class ImageEditor extends React__namespace.Component {
28042
28057
  title: "",
28043
28058
  range: [defaultRange, defaultRange],
28044
28059
  box: [defaultBoxSize, defaultBoxSize],
28045
- backgroundImage: defaultBackgroundImage$1,
28060
+ backgroundImage: defaultBackgroundImage$2,
28046
28061
  labels: [],
28047
28062
  alt: "",
28048
28063
  caption: ""
@@ -28068,7 +28083,7 @@ class ImageEditor extends React__namespace.Component {
28068
28083
  style: {
28069
28084
  width: "100%"
28070
28085
  }
28071
- }))), /*#__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, {
28086
+ }))), /*#__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$g, 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, {
28072
28087
  apiOptions: this.props.apiOptions,
28073
28088
  content: this.props.alt,
28074
28089
  onChange: props => {
@@ -28092,7 +28107,7 @@ class ImageEditor extends React__namespace.Component {
28092
28107
  }, this.state.backgroundImageError);
28093
28108
  return /*#__PURE__*/React__namespace.createElement("div", {
28094
28109
  className: "perseus-image-editor"
28095
- }, /*#__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, {
28110
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Image url:", /*#__PURE__*/React__namespace.createElement(InfoTip$g, null, "Paste an image or graphie image URL."), this.state.backgroundImageError && backgroundImageErrorText, /*#__PURE__*/React__namespace.createElement(BlurInput, {
28096
28111
  value: backgroundImage.url || "",
28097
28112
  style: {
28098
28113
  width: 332
@@ -28103,7 +28118,7 @@ class ImageEditor extends React__namespace.Component {
28103
28118
  _renderRowForLabel(label, i) {
28104
28119
  return /*#__PURE__*/React__namespace.createElement("tr", {
28105
28120
  key: i
28106
- }, /*#__PURE__*/React__namespace.createElement("td", null, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
28121
+ }, /*#__PURE__*/React__namespace.createElement("td", null, /*#__PURE__*/React__namespace.createElement(RangeInput$5, {
28107
28122
  value: label.coordinates
28108
28123
  // eslint-disable-next-line react/jsx-no-bind
28109
28124
  ,
@@ -28248,7 +28263,7 @@ class ImageEditor extends React__namespace.Component {
28248
28263
 
28249
28264
  /* eslint-disable react/sort-comp */
28250
28265
  const {
28251
- InfoTip: InfoTip$e
28266
+ InfoTip: InfoTip$f
28252
28267
  } = perseus.components;
28253
28268
  const answerTypes = {
28254
28269
  number: {
@@ -28327,7 +28342,7 @@ class InputNumberEditor extends React__namespace.Component {
28327
28342
  value: "optional"
28328
28343
  }, "will be accepted"), /*#__PURE__*/React__namespace.createElement("option", {
28329
28344
  value: "enforced"
28330
- }, "will be marked wrong"))), /*#__PURE__*/React__namespace.createElement(InfoTip$e, null, /*#__PURE__*/React__namespace.createElement("p", null, "Normally select \"will not be graded\". This will give the user a message saying the answer is correct but not simplified. The user will then have to simplify it and re-enter, but will not be penalized. (5th grade and anything after)"), /*#__PURE__*/React__namespace.createElement("p", null, "Select \"will be accepted\" only if the user is not expected to know how to simplify fractions yet. (Anything prior to 5th grade)"), /*#__PURE__*/React__namespace.createElement("p", null, "Select \"will be marked wrong\" only if we are specifically assessing the ability to simplify."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("input", {
28345
+ }, "will be marked wrong"))), /*#__PURE__*/React__namespace.createElement(InfoTip$f, null, /*#__PURE__*/React__namespace.createElement("p", null, "Normally select \"will not be graded\". This will give the user a message saying the answer is correct but not simplified. The user will then have to simplify it and re-enter, but will not be penalized. (5th grade and anything after)"), /*#__PURE__*/React__namespace.createElement("p", null, "Select \"will be accepted\" only if the user is not expected to know how to simplify fractions yet. (Anything prior to 5th grade)"), /*#__PURE__*/React__namespace.createElement("p", null, "Select \"will be marked wrong\" only if we are specifically assessing the ability to simplify."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("input", {
28331
28346
  type: "checkbox",
28332
28347
  checked: this.props.inexact,
28333
28348
  onChange: e => {
@@ -28363,7 +28378,7 @@ class InputNumberEditor extends React__namespace.Component {
28363
28378
  });
28364
28379
  },
28365
28380
  "aria-label": "Answer type"
28366
- }, answerTypeOptions), /*#__PURE__*/React__namespace.createElement(InfoTip$e, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use the default \"Numbers\" unless the answer must be in a specific form (e.g., question is about converting decimals to fractions)."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Width", " ", /*#__PURE__*/React__namespace.createElement("select", {
28381
+ }, answerTypeOptions), /*#__PURE__*/React__namespace.createElement(InfoTip$f, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use the default \"Numbers\" unless the answer must be in a specific form (e.g., question is about converting decimals to fractions)."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, "Width", " ", /*#__PURE__*/React__namespace.createElement("select", {
28367
28382
  value: this.props.size,
28368
28383
  onChange: e => {
28369
28384
  // @ts-expect-error - TS2322 - Type 'string' is not assignable to type '"small" | "normal" | undefined'.
@@ -28375,7 +28390,7 @@ class InputNumberEditor extends React__namespace.Component {
28375
28390
  value: "normal"
28376
28391
  }, "Normal (80px)"), /*#__PURE__*/React__namespace.createElement("option", {
28377
28392
  value: "small"
28378
- }, "Small (40px)"))), /*#__PURE__*/React__namespace.createElement(InfoTip$e, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use size \"Normal\" for all text boxes, unless there are multiple text boxes in one line and the answer area is too narrow to fit them."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("input", {
28393
+ }, "Small (40px)"))), /*#__PURE__*/React__namespace.createElement(InfoTip$f, null, /*#__PURE__*/React__namespace.createElement("p", null, "Use size \"Normal\" for all text boxes, unless there are multiple text boxes in one line and the answer area is too narrow to fit them."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, /*#__PURE__*/React__namespace.createElement("input", {
28379
28394
  type: "checkbox",
28380
28395
  checked: this.props.rightAlign,
28381
28396
  onChange: e => {
@@ -28664,7 +28679,7 @@ class LineEditor extends React__namespace.Component {
28664
28679
  }
28665
28680
 
28666
28681
  const {
28667
- ButtonGroup: ButtonGroup$2,
28682
+ ButtonGroup: ButtonGroup$3,
28668
28683
  NumberInput: NumberInput$f
28669
28684
  } = perseus.components;
28670
28685
  class ConstraintEditor extends React__namespace.Component {
@@ -28686,7 +28701,7 @@ class ConstraintEditor extends React__namespace.Component {
28686
28701
  } = perseus.Dependencies.getDependencies();
28687
28702
  return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
28688
28703
  className: "perseus-widget-row"
28689
- }, "Constraint:", " ", /*#__PURE__*/React__namespace.createElement(ButtonGroup$2, {
28704
+ }, "Constraint:", " ", /*#__PURE__*/React__namespace.createElement(ButtonGroup$3, {
28690
28705
  value: this.props.constraint,
28691
28706
  allowEmpty: false,
28692
28707
  buttons: [{
@@ -29569,44 +29584,541 @@ const GraphTypeSelector = props => {
29569
29584
  }, "Angle"));
29570
29585
  };
29571
29586
 
29572
- const SegmentCountSelector = _ref => {
29573
- let {
29574
- numSegments = 1,
29575
- onChange
29576
- } = _ref;
29577
- return /*#__PURE__*/React__namespace.createElement("select", {
29578
- key: "segment-select",
29579
- value: numSegments,
29580
- onChange: e => {
29581
- const num = +e.target.value;
29582
- onChange(num);
29583
- }
29584
- }, ___default["default"].range(1, 7).map(n => /*#__PURE__*/React__namespace.createElement("option", {
29585
- key: n,
29586
- value: n
29587
- }, `${n} segment${n > 1 ? "s" : ""}`)));
29588
- };
29589
-
29587
+ /* eslint-disable react/forbid-prop-types, react/no-unsafe */
29590
29588
  const {
29591
- InfoTip: InfoTip$d
29589
+ ButtonGroup: ButtonGroup$2,
29590
+ InfoTip: InfoTip$e,
29591
+ PropCheckBox: PropCheckBox$8,
29592
+ RangeInput: RangeInput$4
29592
29593
  } = perseus.components;
29593
- const {
29594
- containerSizeClass,
29595
- getInteractiveBoxFromSizeClass
29596
- } = perseus.SizingUtils;
29597
- const DeprecationMixin = perseus.Util.DeprecationMixin;
29598
- const InteractiveGraph = perseus.InteractiveGraphWidget.widget;
29599
- const defaultBackgroundImage = {
29600
- url: null
29601
- };
29602
- const deprecatedProps = {
29603
- showGraph: function (props) {
29604
- return {
29605
- markings: props.showGraph ? "graph" : "none"
29606
- };
29607
- }
29594
+ const defaultBackgroundImage$1 = {
29595
+ url: null,
29596
+ width: 0,
29597
+ height: 0
29598
+ };
29599
+ function numSteps(range, step) {
29600
+ return Math.floor((range[1] - range[0]) / step);
29601
+ }
29602
+ const InteractiveGraphSettings = createReactClass__default["default"]({
29603
+ displayName: "InteractiveGraphSettings",
29604
+ propTypes: {
29605
+ ...perseus.Changeable.propTypes,
29606
+ editableSettings: PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOf(["canvas", "graph", "snap", "image", "measure"])),
29607
+ box: PropTypes__default["default"].arrayOf(PropTypes__default["default"].number),
29608
+ labels: PropTypes__default["default"].arrayOf(PropTypes__default["default"].string),
29609
+ range: PropTypes__default["default"].arrayOf(PropTypes__default["default"].arrayOf(PropTypes__default["default"].number)),
29610
+ step: PropTypes__default["default"].arrayOf(PropTypes__default["default"].number),
29611
+ gridStep: PropTypes__default["default"].arrayOf(PropTypes__default["default"].number),
29612
+ snapStep: PropTypes__default["default"].arrayOf(PropTypes__default["default"].number),
29613
+ valid: PropTypes__default["default"].oneOfType([PropTypes__default["default"].bool, PropTypes__default["default"].string]),
29614
+ backgroundImage: PropTypes__default["default"].object,
29615
+ markings: PropTypes__default["default"].oneOf(["graph", "grid", "none"]),
29616
+ showProtractor: PropTypes__default["default"].bool,
29617
+ showRuler: PropTypes__default["default"].bool,
29618
+ showTooltips: PropTypes__default["default"].bool,
29619
+ rulerLabel: PropTypes__default["default"].string,
29620
+ rulerTicks: PropTypes__default["default"].number
29621
+ },
29622
+ getDefaultProps: function () {
29623
+ return {
29624
+ editableSettings: ["graph", "snap", "image", "measure"],
29625
+ box: [perseus.interactiveSizes.defaultBoxSizeSmall, perseus.interactiveSizes.defaultBoxSizeSmall],
29626
+ labels: ["x", "y"],
29627
+ range: [[-10, 10], [-10, 10]],
29628
+ step: [1, 1],
29629
+ gridStep: [1, 1],
29630
+ snapStep: [1, 1],
29631
+ valid: true,
29632
+ backgroundImage: defaultBackgroundImage$1,
29633
+ markings: "graph",
29634
+ showProtractor: false,
29635
+ showRuler: false,
29636
+ showTooltips: false,
29637
+ rulerLabel: "",
29638
+ rulerTicks: 10
29639
+ };
29640
+ },
29641
+ getInitialState: function () {
29642
+ return this.stateFromProps(this.props);
29643
+ },
29644
+ componentDidMount: function () {
29645
+ // TODO(scottgrant): This is a hack to remove the deprecated call to
29646
+ // this.isMounted() but is still considered an anti-pattern.
29647
+ this._isMounted = true;
29648
+ this.changeGraph = ___default["default"].debounce(this.changeGraph, 300);
29649
+ },
29650
+ UNSAFE_componentWillReceiveProps: function (nextProps) {
29651
+ // Make sure that state updates when switching
29652
+ // between different items in a multi-item editor.
29653
+ if (!___default["default"].isEqual(this.props.labels, nextProps.labels) || !___default["default"].isEqual(this.props.gridStep, nextProps.gridStep) || !___default["default"].isEqual(this.props.snapStep, nextProps.snapStep) || !___default["default"].isEqual(this.props.step, nextProps.step) || !___default["default"].isEqual(this.props.range, nextProps.range) || !___default["default"].isEqual(this.props.backgroundImage, nextProps.backgroundImage)) {
29654
+ this.setState(this.stateFromProps(nextProps));
29655
+ }
29656
+ },
29657
+ componentWillUnmount: function () {
29658
+ this._isMounted = false;
29659
+ },
29660
+ stateFromProps: function (props) {
29661
+ return {
29662
+ labelsTextbox: props.labels,
29663
+ gridStepTextbox: props.gridStep,
29664
+ snapStepTextbox: props.snapStep,
29665
+ stepTextbox: props.step,
29666
+ rangeTextbox: props.range,
29667
+ backgroundImage: ___default["default"].clone(props.backgroundImage)
29668
+ };
29669
+ },
29670
+ change() {
29671
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
29672
+ args[_key] = arguments[_key];
29673
+ }
29674
+ return perseus.Changeable.change.apply(this, args);
29675
+ },
29676
+ // TODO(aria): Make either a wrapper for standard events to work
29677
+ // with this.change, or make these use some TextInput/NumberInput box
29678
+ changeRulerLabel: function (e) {
29679
+ this.change({
29680
+ rulerLabel: e.target.value
29681
+ });
29682
+ },
29683
+ changeRulerTicks: function (e) {
29684
+ this.change({
29685
+ rulerTicks: +e.target.value
29686
+ });
29687
+ },
29688
+ changeBackgroundUrl: function (e) {
29689
+ // Only continue on blur or "enter"
29690
+ if (e.type === "keypress" && e.key !== "Enter") {
29691
+ return;
29692
+ }
29693
+ const setUrl = (url, width, height) => {
29694
+ const image = ___default["default"].clone(this.props.backgroundImage);
29695
+ image.url = url;
29696
+ image.width = width;
29697
+ image.height = height;
29698
+ this.setState({
29699
+ backgroundImage: image
29700
+ }, this.changeGraph);
29701
+ };
29702
+
29703
+ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
29704
+ const url = ReactDOM__default["default"].findDOMNode(this.refs["bg-url"]).value; // eslint-disable-line react/no-string-refs
29705
+ if (url) {
29706
+ perseus.Util.getImageSize(url, (width, height) => {
29707
+ if (this._isMounted) {
29708
+ setUrl(url, width, height);
29709
+ }
29710
+ });
29711
+ } else {
29712
+ setUrl(null, 0, 0);
29713
+ }
29714
+ },
29715
+ renderLabelChoices: function (choices) {
29716
+ return ___default["default"].map(choices, function (nameAndValue) {
29717
+ return /*#__PURE__*/React__namespace.createElement("option", {
29718
+ value: nameAndValue[1]
29719
+ }, nameAndValue[0]);
29720
+ });
29721
+ },
29722
+ validRange: function (range) {
29723
+ const numbers = ___default["default"].every(range, function (num) {
29724
+ return ___default["default"].isFinite(num);
29725
+ });
29726
+ if (!numbers) {
29727
+ return "Range must be a valid number";
29728
+ }
29729
+ if (range[0] >= range[1]) {
29730
+ return "Range must have a higher number on the right";
29731
+ }
29732
+ return true;
29733
+ },
29734
+ validateStepValue: function (settings) {
29735
+ const {
29736
+ step,
29737
+ range,
29738
+ name,
29739
+ minTicks,
29740
+ maxTicks
29741
+ } = settings;
29742
+ if (!___default["default"].isFinite(step)) {
29743
+ return name + " must be a valid number";
29744
+ }
29745
+ const nSteps = numSteps(range, step);
29746
+ if (nSteps < minTicks) {
29747
+ return name + " is too large, there must be at least " + minTicks + " ticks.";
29748
+ }
29749
+ if (nSteps > maxTicks) {
29750
+ return name + " is too small, there can be at most " + maxTicks + " ticks.";
29751
+ }
29752
+ return true;
29753
+ },
29754
+ validSnapStep: function (step, range) {
29755
+ return this.validateStepValue({
29756
+ step: step,
29757
+ range: range,
29758
+ name: "Snap step",
29759
+ minTicks: 5,
29760
+ maxTicks: 60
29761
+ });
29762
+ },
29763
+ validGridStep: function (step, range) {
29764
+ return this.validateStepValue({
29765
+ step: step,
29766
+ range: range,
29767
+ name: "Grid step",
29768
+ minTicks: 3,
29769
+ maxTicks: 60
29770
+ });
29771
+ },
29772
+ validStep: function (step, range) {
29773
+ return this.validateStepValue({
29774
+ step: step,
29775
+ range: range,
29776
+ name: "Step",
29777
+ minTicks: 3,
29778
+ maxTicks: 20
29779
+ });
29780
+ },
29781
+ validBackgroundImageSize: function (image) {
29782
+ // Ignore empty images
29783
+ if (!image.url) {
29784
+ return true;
29785
+ }
29786
+ const validSize = image.width <= 450 && image.height <= 450;
29787
+ if (!validSize) {
29788
+ return "Image must be smaller than 450px x 450px.";
29789
+ }
29790
+ return true;
29791
+ },
29792
+ validateGraphSettings: function (range, step, gridStep, snapStep, image) {
29793
+ const self = this;
29794
+ let msg;
29795
+ const goodRange = ___default["default"].every(range, function (range) {
29796
+ msg = self.validRange(range);
29797
+ return msg === true;
29798
+ });
29799
+ if (!goodRange) {
29800
+ return msg;
29801
+ }
29802
+ const goodStep = ___default["default"].every(step, function (step, i) {
29803
+ msg = self.validStep(step, range[i]);
29804
+ return msg === true;
29805
+ });
29806
+ if (!goodStep) {
29807
+ return msg;
29808
+ }
29809
+ const goodGridStep = ___default["default"].every(gridStep, function (gridStep, i) {
29810
+ msg = self.validGridStep(gridStep, range[i]);
29811
+ return msg === true;
29812
+ });
29813
+ if (!goodGridStep) {
29814
+ return msg;
29815
+ }
29816
+ const goodSnapStep = ___default["default"].every(snapStep, function (snapStep, i) {
29817
+ msg = self.validSnapStep(snapStep, range[i]);
29818
+ return msg === true;
29819
+ });
29820
+ if (!goodSnapStep) {
29821
+ return msg;
29822
+ }
29823
+ const goodImageSize = this.validBackgroundImageSize(image);
29824
+ if (goodImageSize !== true) {
29825
+ msg = goodImageSize;
29826
+ return msg;
29827
+ }
29828
+ return true;
29829
+ },
29830
+ changeLabel: function (i, e) {
29831
+ const val = e.target.value;
29832
+ const labels = this.state.labelsTextbox.slice();
29833
+ labels[i] = val;
29834
+ this.setState({
29835
+ labelsTextbox: labels
29836
+ }, this.changeGraph);
29837
+ },
29838
+ changeRange: function (i, values) {
29839
+ const ranges = this.state.rangeTextbox.slice();
29840
+ ranges[i] = values;
29841
+ const step = this.state.stepTextbox.slice();
29842
+ const gridStep = this.state.gridStepTextbox.slice();
29843
+ const snapStep = this.state.snapStepTextbox.slice();
29844
+ const scale = perseus.Util.scaleFromExtent(ranges[i], this.props.box[i]);
29845
+ if (this.validRange(ranges[i]) === true) {
29846
+ step[i] = perseus.Util.tickStepFromExtent(ranges[i], this.props.box[i]);
29847
+ gridStep[i] = perseus.Util.gridStepFromTickStep(step[i], scale);
29848
+ snapStep[i] = gridStep[i] / 2;
29849
+ }
29850
+ this.setState({
29851
+ stepTextbox: step,
29852
+ gridStepTextbox: gridStep,
29853
+ snapStepTextbox: snapStep,
29854
+ rangeTextbox: ranges
29855
+ }, this.changeGraph);
29856
+ },
29857
+ changeStep: function (step) {
29858
+ this.setState({
29859
+ stepTextbox: step
29860
+ }, this.changeGraph);
29861
+ },
29862
+ changeSnapStep: function (snapStep) {
29863
+ this.setState({
29864
+ snapStepTextbox: snapStep
29865
+ }, this.changeGraph);
29866
+ },
29867
+ changeGridStep: function (gridStep) {
29868
+ this.setState({
29869
+ gridStepTextbox: gridStep,
29870
+ snapStepTextbox: ___default["default"].map(gridStep, function (step) {
29871
+ return step / 2;
29872
+ })
29873
+ }, this.changeGraph);
29874
+ },
29875
+ changeGraph: function () {
29876
+ const labels = this.state.labelsTextbox;
29877
+ const range = ___default["default"].map(this.state.rangeTextbox, function (range) {
29878
+ return ___default["default"].map(range, Number);
29879
+ });
29880
+ const step = ___default["default"].map(this.state.stepTextbox, Number);
29881
+ const gridStep = this.state.gridStepTextbox;
29882
+ const snapStep = this.state.snapStepTextbox;
29883
+ const image = this.state.backgroundImage;
29884
+
29885
+ // validationResult is either:
29886
+ // true -> the settings are valid
29887
+ // a string -> the settings are invalid, and the explanation
29888
+ // is contained in the string
29889
+ // TODO(aria): Refactor this to not be confusing
29890
+ const validationResult = this.validateGraphSettings(range, step, gridStep, snapStep, image);
29891
+ if (validationResult === true) {
29892
+ // either true or a string
29893
+ this.change({
29894
+ valid: true,
29895
+ labels: labels,
29896
+ range: range,
29897
+ step: step,
29898
+ gridStep: gridStep,
29899
+ snapStep: snapStep,
29900
+ backgroundImage: image
29901
+ });
29902
+ } else {
29903
+ this.change({
29904
+ valid: validationResult // a string message, not false
29905
+ });
29906
+ }
29907
+ },
29908
+
29909
+ render: function () {
29910
+ const scale = [perseus.KhanMath.roundTo(2, perseus.Util.scaleFromExtent(this.props.range[0], this.props.box[0])), perseus.KhanMath.roundTo(2, perseus.Util.scaleFromExtent(this.props.range[1], this.props.box[1]))];
29911
+ const {
29912
+ TeX
29913
+ } = perseus.Dependencies.getDependencies();
29914
+ return /*#__PURE__*/React__namespace.createElement("div", null, ___default["default"].contains(this.props.editableSettings, "canvas") && /*#__PURE__*/React__namespace.createElement("div", {
29915
+ className: "graph-settings"
29916
+ }, /*#__PURE__*/React__namespace.createElement("div", {
29917
+ className: "perseus-widget-row"
29918
+ }, /*#__PURE__*/React__namespace.createElement("label", {
29919
+ htmlFor: "canvas-size"
29920
+ }, "Canvas size (x,y pixels)"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29921
+ id: "canvas-size",
29922
+ value: this.props.box,
29923
+ onChange: box => {
29924
+ this.change({
29925
+ box: box
29926
+ });
29927
+ }
29928
+ })), /*#__PURE__*/React__namespace.createElement("div", {
29929
+ className: "perseus-widget-row"
29930
+ }, "Scale (px per div):", " ", /*#__PURE__*/React__namespace.createElement(TeX, null, "(" + scale[0] + ", " + scale[1] + ")"))), ___default["default"].contains(this.props.editableSettings, "graph") && /*#__PURE__*/React__namespace.createElement("div", {
29931
+ className: "graph-settings"
29932
+ }, /*#__PURE__*/React__namespace.createElement("div", {
29933
+ className: "perseus-widget-row"
29934
+ }, /*#__PURE__*/React__namespace.createElement("div", {
29935
+ className: "perseus-widget-left-col"
29936
+ }, /*#__PURE__*/React__namespace.createElement("label", {
29937
+ htmlFor: "labels-x"
29938
+ }, "x Label"), /*#__PURE__*/React__namespace.createElement("input", {
29939
+ id: "labels-x",
29940
+ type: "text",
29941
+ className: "graph-settings-axis-label"
29942
+ // eslint-disable-next-line react/no-string-refs
29943
+ ,
29944
+ ref: "labels-0",
29945
+ onChange: e => this.changeLabel(0, e),
29946
+ value: this.state.labelsTextbox[0] || ""
29947
+ })), /*#__PURE__*/React__namespace.createElement("div", {
29948
+ className: "perseus-widget-right-col"
29949
+ }, /*#__PURE__*/React__namespace.createElement("label", {
29950
+ htmlFor: "labels-y"
29951
+ }, "y Label"), /*#__PURE__*/React__namespace.createElement("input", {
29952
+ id: "labels-y",
29953
+ type: "text",
29954
+ className: "graph-settings-axis-label"
29955
+ // eslint-disable-next-line react/no-string-refs
29956
+ ,
29957
+ ref: "labels-1",
29958
+ onChange: e => this.changeLabel(1, e),
29959
+ value: this.state.labelsTextbox[1] || ""
29960
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
29961
+ className: "perseus-widget-row"
29962
+ }, /*#__PURE__*/React__namespace.createElement("div", {
29963
+ className: "perseus-widget-left-col"
29964
+ }, /*#__PURE__*/React__namespace.createElement("label", {
29965
+ htmlFor: "range-x"
29966
+ }, "x Range"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29967
+ id: "range-x",
29968
+ value: this.state.rangeTextbox[0],
29969
+ onChange: vals => this.changeRange(0, vals)
29970
+ })), /*#__PURE__*/React__namespace.createElement("div", {
29971
+ className: "perseus-widget-right-col"
29972
+ }, /*#__PURE__*/React__namespace.createElement("label", {
29973
+ htmlFor: "range-y"
29974
+ }, "y Range"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29975
+ id: "range-y",
29976
+ value: this.state.rangeTextbox[1],
29977
+ onChange: vals => this.changeRange(1, vals)
29978
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
29979
+ className: "perseus-widget-row"
29980
+ }, /*#__PURE__*/React__namespace.createElement("div", {
29981
+ className: "perseus-widget-left-col"
29982
+ }, /*#__PURE__*/React__namespace.createElement("label", {
29983
+ htmlFor: "tick-step"
29984
+ }, "Tick Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29985
+ id: "tick-step",
29986
+ value: this.state.stepTextbox,
29987
+ onChange: this.changeStep
29988
+ })), /*#__PURE__*/React__namespace.createElement("div", {
29989
+ className: "perseus-widget-right-col"
29990
+ }, /*#__PURE__*/React__namespace.createElement("label", {
29991
+ htmlFor: "grid-step"
29992
+ }, "Grid Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
29993
+ id: "grid-step",
29994
+ value: this.state.gridStepTextbox,
29995
+ onChange: this.changeGridStep
29996
+ }))), ___default["default"].contains(this.props.editableSettings, "snap") && /*#__PURE__*/React__namespace.createElement("div", {
29997
+ className: "perseus-widget-row"
29998
+ }, /*#__PURE__*/React__namespace.createElement("div", {
29999
+ className: "perseus-widget-left-col"
30000
+ }, /*#__PURE__*/React__namespace.createElement("label", {
30001
+ htmlFor: "snap-step"
30002
+ }, "Snap Step"), /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
30003
+ id: "snap-step",
30004
+ value: this.state.snapStepTextbox,
30005
+ onChange: this.changeSnapStep
30006
+ }))), /*#__PURE__*/React__namespace.createElement("div", {
30007
+ className: "perseus-widget-row"
30008
+ }, /*#__PURE__*/React__namespace.createElement("label", null, "Markings: "), /*#__PURE__*/React__namespace.createElement(ButtonGroup$2, {
30009
+ value: this.props.markings,
30010
+ allowEmpty: false,
30011
+ buttons: [{
30012
+ value: "graph",
30013
+ content: "Graph"
30014
+ }, {
30015
+ value: "grid",
30016
+ content: "Grid"
30017
+ }, {
30018
+ value: "none",
30019
+ content: "None"
30020
+ }],
30021
+ onChange: this.change("markings")
30022
+ })), /*#__PURE__*/React__namespace.createElement("div", {
30023
+ className: "perseus-widget-left-col"
30024
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$8, {
30025
+ label: "Show tooltips",
30026
+ showTooltips: this.props.showTooltips,
30027
+ onChange: this.change
30028
+ }))), ___default["default"].contains(this.props.editableSettings, "image") && /*#__PURE__*/React__namespace.createElement("div", {
30029
+ className: "image-settings"
30030
+ }, /*#__PURE__*/React__namespace.createElement("div", null, "Background image:"), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", {
30031
+ htmlFor: "bg-url"
30032
+ }, "Url:"), /*#__PURE__*/React__namespace.createElement("input", {
30033
+ id: "bg-url",
30034
+ type: "text",
30035
+ className: "graph-settings-background-url"
30036
+ // eslint-disable-next-line react/no-string-refs
30037
+ ,
30038
+ ref: "bg-url",
30039
+ value: this.state.backgroundImage.url || "",
30040
+ onChange: e => {
30041
+ const image = ___default["default"].clone(this.props.backgroundImage);
30042
+ image.url = e.target.value;
30043
+ this.setState({
30044
+ backgroundImage: image
30045
+ });
30046
+ },
30047
+ onKeyPress: this.changeBackgroundUrl,
30048
+ onBlur: this.changeBackgroundUrl
30049
+ }), /*#__PURE__*/React__namespace.createElement(InfoTip$e, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background.")))), ___default["default"].contains(this.props.editableSettings, "measure") && /*#__PURE__*/React__namespace.createElement("div", {
30050
+ className: "misc-settings"
30051
+ }, /*#__PURE__*/React__namespace.createElement("div", {
30052
+ className: "perseus-widget-row"
30053
+ }, /*#__PURE__*/React__namespace.createElement("div", {
30054
+ className: "perseus-widget-left-col"
30055
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$8, {
30056
+ label: "Show ruler",
30057
+ showRuler: this.props.showRuler,
30058
+ onChange: this.change
30059
+ })), /*#__PURE__*/React__namespace.createElement("div", {
30060
+ className: "perseus-widget-right-col"
30061
+ }, /*#__PURE__*/React__namespace.createElement(PropCheckBox$8, {
30062
+ label: "Show protractor",
30063
+ showProtractor: this.props.showProtractor,
30064
+ onChange: this.change
30065
+ }))), this.props.showRuler && /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Ruler label:", " ", /*#__PURE__*/React__namespace.createElement("select", {
30066
+ onChange: this.changeRulerLabel,
30067
+ value: this.props.rulerLabel
30068
+ }, /*#__PURE__*/React__namespace.createElement("option", {
30069
+ value: ""
30070
+ }, "None"), /*#__PURE__*/React__namespace.createElement("optgroup", {
30071
+ label: "Metric"
30072
+ }, this.renderLabelChoices([["milimeters", "mm"], ["centimeters", "cm"], ["meters", "m"], ["kilometers", "km"]])), /*#__PURE__*/React__namespace.createElement("optgroup", {
30073
+ label: "Imperial"
30074
+ }, this.renderLabelChoices([["inches", "in"], ["feet", "ft"], ["yards", "yd"], ["miles", "mi"]]))))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("label", null, " ", "Ruler ticks:", " ", /*#__PURE__*/React__namespace.createElement("select", {
30075
+ onChange: this.changeRulerTicks,
30076
+ value: this.props.rulerTicks
30077
+ }, ___default["default"].map([1, 2, 4, 8, 10, 16], function (n) {
30078
+ return /*#__PURE__*/React__namespace.createElement("option", {
30079
+ value: n
30080
+ }, n);
30081
+ })))))));
30082
+ }
30083
+ });
30084
+
30085
+ const SegmentCountSelector = _ref => {
30086
+ let {
30087
+ numSegments = 1,
30088
+ onChange
30089
+ } = _ref;
30090
+ return /*#__PURE__*/React__namespace.createElement("select", {
30091
+ key: "segment-select",
30092
+ value: numSegments,
30093
+ onChange: e => {
30094
+ const num = +e.target.value;
30095
+ onChange(num);
30096
+ }
30097
+ }, ___default["default"].range(1, 7).map(n => /*#__PURE__*/React__namespace.createElement("option", {
30098
+ key: n,
30099
+ value: n
30100
+ }, `${n} segment${n > 1 ? "s" : ""}`)));
30101
+ };
30102
+
30103
+ const {
30104
+ InfoTip: InfoTip$d
30105
+ } = perseus.components;
30106
+ const {
30107
+ containerSizeClass,
30108
+ getInteractiveBoxFromSizeClass
30109
+ } = perseus.SizingUtils;
30110
+ const DeprecationMixin = perseus.Util.DeprecationMixin;
30111
+ const InteractiveGraph = perseus.InteractiveGraphWidget.widget;
30112
+ const defaultBackgroundImage = {
30113
+ url: null
30114
+ };
30115
+ const deprecatedProps = {
30116
+ showGraph: function (props) {
30117
+ return {
30118
+ markings: props.showGraph ? "graph" : "none"
30119
+ };
30120
+ }
29608
30121
  };
29609
- // [min, max]
29610
30122
  // Renders the given children in a View laid out horizontally.
29611
30123
  const Row = props => {
29612
30124
  const {
@@ -29628,6 +30140,12 @@ const FieldLabel = props => {
29628
30140
  }
29629
30141
  }, props.children);
29630
30142
  };
30143
+ /**
30144
+ * An editor for the InteractiveGraph widget, which allows the user to
30145
+ * specify the graph's properties and the correct answer.
30146
+ *
30147
+ * Used in the exercise editor.
30148
+ */
29631
30149
  class InteractiveGraphEditor extends React__namespace.Component {
29632
30150
  displayName = "InteractiveGraphEditor";
29633
30151
  className = "perseus-widget-interactive-graph";
@@ -29821,7 +30339,7 @@ class InteractiveGraphEditor extends React__namespace.Component {
29821
30339
  borderStyle: "solid",
29822
30340
  borderWidth: 1
29823
30341
  }
29824
- }, equationString), /*#__PURE__*/React__namespace.createElement(InfoTip$d, null, /*#__PURE__*/React__namespace.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."))), /*#__PURE__*/React__namespace.createElement(GraphSettings, {
30342
+ }, equationString), /*#__PURE__*/React__namespace.createElement(InfoTip$d, null, /*#__PURE__*/React__namespace.createElement("p", null, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."))), /*#__PURE__*/React__namespace.createElement(InteractiveGraphSettings, {
29825
30343
  box: getInteractiveBoxFromSizeClass(sizeClass),
29826
30344
  range: this.props.range,
29827
30345
  labels: this.props.labels,