@khanacademy/perseus-core 3.6.0 → 3.7.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.
@@ -226,7 +226,14 @@ export type PerseusRenderer = {
226
226
  * field.
227
227
  */
228
228
  widgets: PerseusWidgetsMap;
229
- metadata?: ReadonlyArray<string>;
229
+ /**
230
+ * Formerly used in the PerseusGradedGroup widget. A list of "tags" that
231
+ * are keys that represent other content in the system. Not rendered to
232
+ * the user. NOTE: perseus_data.go says this is required even though it
233
+ * isn't necessary.
234
+ * @deprecated
235
+ */
236
+ metadata?: any;
230
237
  /**
231
238
  * A dictionary of {[imageUrl]: PerseusImageDetail}.
232
239
  */
@@ -258,7 +265,7 @@ export type WidgetOptions<Type extends string, Options> = {
258
265
  graded?: boolean;
259
266
  alignment?: string;
260
267
  options: Options;
261
- key?: number;
268
+ key?: number | null;
262
269
  version?: Version;
263
270
  };
264
271
  export type CategorizerWidget = WidgetOptions<'categorizer', PerseusCategorizerWidgetOptions>;
@@ -304,7 +311,7 @@ export type PerseusImageBackground = {
304
311
  height?: number;
305
312
  top?: number;
306
313
  left?: number;
307
- scale?: number | string;
314
+ scale?: number;
308
315
  bottom?: number;
309
316
  };
310
317
  /**
package/dist/es/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { seededRNG as seededRNG$1, shuffle as shuffle$2 } from '@khanacademy/perseus-core';
2
+
1
3
  /**
2
4
  * Adds the given perseus library version information to the __perseus_debug__
3
5
  * object and ensures that the object is attached to `globalThis` (`window` in
@@ -818,7 +820,7 @@ function times(n, iteratee, context) {
818
820
  }
819
821
 
820
822
  // Return a random integer between `min` and `max` (inclusive).
821
- function random(min, max) {
823
+ function random$1(min, max) {
822
824
  if (max == null) {
823
825
  max = min;
824
826
  min = 0;
@@ -1561,14 +1563,14 @@ function toArray(obj) {
1561
1563
  function sample(obj, n, guard) {
1562
1564
  if (n == null || guard) {
1563
1565
  if (!isArrayLike(obj)) obj = values(obj);
1564
- return obj[random(obj.length - 1)];
1566
+ return obj[random$1(obj.length - 1)];
1565
1567
  }
1566
1568
  var sample = toArray(obj);
1567
1569
  var length = getLength(sample);
1568
1570
  n = Math.max(Math.min(n, length), 0);
1569
1571
  var last = length - 1;
1570
1572
  for (var index = 0; index < n; index++) {
1571
- var rand = random(index, last);
1573
+ var rand = random$1(index, last);
1572
1574
  var temp = sample[index];
1573
1575
  sample[index] = sample[rand];
1574
1576
  sample[rand] = temp;
@@ -1577,7 +1579,7 @@ function sample(obj, n, guard) {
1577
1579
  }
1578
1580
 
1579
1581
  // Shuffle a collection.
1580
- function shuffle(obj) {
1582
+ function shuffle$1(obj) {
1581
1583
  return sample(obj, Infinity);
1582
1584
  }
1583
1585
 
@@ -1963,7 +1965,7 @@ var allExports = /*#__PURE__*/Object.freeze({
1963
1965
  matcher: matcher,
1964
1966
  matches: matcher,
1965
1967
  times: times,
1966
- random: random,
1968
+ random: random$1,
1967
1969
  now: now,
1968
1970
  escape: escape,
1969
1971
  unescape: unescape,
@@ -2020,7 +2022,7 @@ var allExports = /*#__PURE__*/Object.freeze({
2020
2022
  where: where,
2021
2023
  max: max,
2022
2024
  min: min,
2023
- shuffle: shuffle,
2025
+ shuffle: shuffle$1,
2024
2026
  sample: sample,
2025
2027
  sortBy: sortBy,
2026
2028
  groupBy: groupBy,
@@ -3076,7 +3078,7 @@ function parseWidget(parseType, parseOptions) {
3076
3078
  graded: optional(boolean),
3077
3079
  alignment: optional(string),
3078
3080
  options: parseOptions,
3079
- key: optional(number),
3081
+ key: optional(nullable(number)),
3080
3082
  version: optional(object({
3081
3083
  major: number,
3082
3084
  minor: number
@@ -3462,14 +3464,15 @@ const imageDimensionToNumber = pipeParsers(union(number).or(string).parser)
3462
3464
  // string parses to either NaN (using parseInt) or 0 (using unary +) and
3463
3465
  // CSS will treat NaN as invalid and default to 0 instead.
3464
3466
  .then(convert(emptyToZero)).then(stringToNumber).parser;
3467
+ const dimensionOrUndefined = defaulted(imageDimensionToNumber, () => undefined);
3465
3468
  const parsePerseusImageBackground = object({
3466
3469
  url: optional(nullable(string)),
3467
- width: optional(imageDimensionToNumber),
3468
- height: optional(imageDimensionToNumber),
3469
- top: optional(imageDimensionToNumber),
3470
- left: optional(imageDimensionToNumber),
3471
- bottom: optional(imageDimensionToNumber),
3472
- scale: optional(imageDimensionToNumber)
3470
+ width: dimensionOrUndefined,
3471
+ height: dimensionOrUndefined,
3472
+ top: dimensionOrUndefined,
3473
+ left: dimensionOrUndefined,
3474
+ bottom: dimensionOrUndefined,
3475
+ scale: dimensionOrUndefined
3473
3476
  });
3474
3477
 
3475
3478
  const pairOfNumbers$2 = pair(number, number);
@@ -4210,7 +4213,7 @@ const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
4210
4213
  // the data, simplify this.
4211
4214
  value: optional(nullable(number)),
4212
4215
  status: string,
4213
- answerForms: optional(array(parseMathFormat)),
4216
+ answerForms: defaulted(array(parseMathFormat), () => undefined),
4214
4217
  strict: boolean,
4215
4218
  maxError: optional(nullable(number)),
4216
4219
  // TODO(benchristel): simplify should never be a boolean, but we
@@ -4308,7 +4311,7 @@ const parseRadioWidget = parseWidget(constant("radio"), object({
4308
4311
  // There is an import cycle between radio-widget.ts and
4309
4312
  // widgets-map.ts. The anonymous function below ensures that we
4310
4313
  // don't refer to parseWidgetsMap before it's defined.
4311
- widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
4314
+ widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => undefined)
4312
4315
  })),
4313
4316
  hasNoneOfTheAbove: optional(boolean),
4314
4317
  countChoices: optional(boolean),
@@ -4461,13 +4464,17 @@ const parseDeprecatedWidget = parseWidget(
4461
4464
  (_, ctx) => ctx.success("deprecated-standin"),
4462
4465
  // Allow any widget options
4463
4466
  object({}));
4464
- const parseStringToPositiveInt = (rawValue, ctx) => {
4465
- if (typeof rawValue !== "string" || !/^[1-9][0-9]*$/.test(rawValue)) {
4466
- return ctx.failure("a string representing a positive integer", rawValue);
4467
+ const parseStringToNonNegativeInt = (rawValue, ctx) => {
4468
+ // The article renderer seems to allow the numeric part of a widget ID to
4469
+ // be 0, at least for image widgets. However, if widget IDs in an exercise
4470
+ // contain 0, the exercise renderer will blow up. We allow 0 here for
4471
+ // compatibility with articles.
4472
+ if (typeof rawValue !== "string" || !/^(0|[1-9][0-9]*)$/.test(rawValue)) {
4473
+ return ctx.failure("a string representing a non-negative integer", rawValue);
4467
4474
  }
4468
4475
  return ctx.success(+rawValue);
4469
4476
  };
4470
- const parseWidgetIdComponents = pair(string, parseStringToPositiveInt);
4477
+ const parseWidgetIdComponents = pair(string, parseStringToNonNegativeInt);
4471
4478
 
4472
4479
  const parsePerseusRenderer = defaulted(object({
4473
4480
  // TODO(benchristel): content is also defaulted to empty string in
@@ -4478,8 +4485,9 @@ const parsePerseusRenderer = defaulted(object({
4478
4485
  // The anonymous function below ensures that we don't try to access
4479
4486
  // parseWidgetsMap before it's defined.
4480
4487
  widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => ({})),
4481
- metadata: optional(array(string)),
4482
- images: parseImages
4488
+ images: parseImages,
4489
+ // deprecated
4490
+ metadata: any
4483
4491
  }),
4484
4492
  // Default value
4485
4493
  () => ({
@@ -4490,29 +4498,48 @@ const parsePerseusRenderer = defaulted(object({
4490
4498
 
4491
4499
  const parsePerseusArticle = union(parsePerseusRenderer).or(array(parsePerseusRenderer)).parser;
4492
4500
 
4493
- function _objectWithoutPropertiesLoose(r, e) {
4494
- if (null == r) return {};
4495
- var t = {};
4496
- for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
4497
- if (-1 !== e.indexOf(n)) continue;
4498
- t[n] = r[n];
4499
- }
4500
- return t;
4501
- }
4502
-
4503
4501
  const parseHint = object({
4504
4502
  replace: optional(boolean),
4505
4503
  content: string,
4506
4504
  widgets: defaulted(parseWidgetsMap, () => ({})),
4507
- metadata: optional(array(string)),
4508
- images: parseImages
4505
+ images: parseImages,
4506
+ // deprecated
4507
+ metadata: any
4509
4508
  });
4510
4509
 
4511
- const _excluded$a = ["type", "options"];
4510
+ const parsePerseusAnswerArea = pipeParsers(defaulted(object({}), () => ({}))).then(convert(toAnswerArea)).parser;
4511
+
4512
+ // Some answerAreas have extra, bogus fields, like:
4513
+ //
4514
+ // "answerArea": {
4515
+ // "type": "multiple",
4516
+ // "options": {},
4517
+ // "version": null,
4518
+ // "static": false,
4519
+ // "graded": false,
4520
+ // "alignment": "",
4521
+ // }
4522
+ //
4523
+ // This function filters the fields of an answerArea object, keeping only the
4524
+ // known ones, and converts `undefined` and `null` values to `false`.
4525
+ function toAnswerArea(raw) {
4526
+ return {
4527
+ zTable: !!raw.zTable,
4528
+ calculator: !!raw.calculator,
4529
+ chi2Table: !!raw.chi2Table,
4530
+ financialCalculatorMonthlyPayment: !!raw.financialCalculatorMonthlyPayment,
4531
+ financialCalculatorTotalAmount: !!raw.financialCalculatorTotalAmount,
4532
+ financialCalculatorTimeToPayOff: !!raw.financialCalculatorTimeToPayOff,
4533
+ periodicTable: !!raw.periodicTable,
4534
+ periodicTableWithKey: !!raw.periodicTableWithKey,
4535
+ tTable: !!raw.tTable
4536
+ };
4537
+ }
4538
+
4512
4539
  const parsePerseusItem$1 = object({
4513
4540
  question: parsePerseusRenderer,
4514
4541
  hints: defaulted(array(parseHint), () => []),
4515
- answerArea: pipeParsers(defaulted(object({}), () => ({}))).then(migrateAnswerArea).then(record(enumeration(...ItemExtras), boolean)).parser,
4542
+ answerArea: parsePerseusAnswerArea,
4516
4543
  itemDataVersion: optional(object({
4517
4544
  major: number,
4518
4545
  minor: number
@@ -4521,24 +4548,6 @@ const parsePerseusItem$1 = object({
4521
4548
  answer: any
4522
4549
  });
4523
4550
 
4524
- // Some answerAreas have extra fields, like:
4525
- //
4526
- // "answerArea": {
4527
- // "type": "multiple",
4528
- // "options": {
4529
- // "content": "",
4530
- // "images": {},
4531
- // "widgets": {}
4532
- // }
4533
- // }
4534
- //
4535
- // The "type" and "options" fields don't seem to be used anywhere. This
4536
- // migration function removes them.
4537
- function migrateAnswerArea(rawValue, ctx) {
4538
- const rest = _objectWithoutPropertiesLoose(rawValue, _excluded$a);
4539
- return ctx.success(rest);
4540
- }
4541
-
4542
4551
  /**
4543
4552
  * Helper to parse PerseusItem JSON
4544
4553
  * Why not just use JSON.parse? We want:
@@ -4613,7 +4622,7 @@ function throwErrorIfCheatingDetected() {
4613
4622
 
4614
4623
  // This file is processed by a Rollup plugin (replace) to inject the production
4615
4624
  const libName = "@khanacademy/perseus-core";
4616
- const libVersion = "3.6.0";
4625
+ const libVersion = "3.7.0";
4617
4626
  addLibraryVersionToPerseusDebug(libName, libVersion);
4618
4627
 
4619
4628
  /**
@@ -4898,6 +4907,16 @@ const gradedGroupSetWidgetLogic = {
4898
4907
  defaultWidgetOptions: defaultWidgetOptions$o
4899
4908
  };
4900
4909
 
4910
+ function _objectWithoutPropertiesLoose(r, e) {
4911
+ if (null == r) return {};
4912
+ var t = {};
4913
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
4914
+ if (-1 !== e.indexOf(n)) continue;
4915
+ t[n] = r[n];
4916
+ }
4917
+ return t;
4918
+ }
4919
+
4901
4920
  const _excluded$9 = ["correct"];
4902
4921
  function getGrapherPublicWidgetOptions(options) {
4903
4922
  const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$9);
@@ -4933,10 +4952,7 @@ const grapherWidgetLogic = {
4933
4952
  const defaultWidgetOptions$m = {
4934
4953
  content: "",
4935
4954
  widgets: {},
4936
- images: {},
4937
- // `undefined` instead of `null` so that getDefaultProps works for
4938
- // `the GroupMetadataEditor`
4939
- metadata: undefined
4955
+ images: {}
4940
4956
  };
4941
4957
  const groupWidgetLogic = {
4942
4958
  name: "group",
@@ -5077,6 +5093,63 @@ const labelImageWidgetLogic = {
5077
5093
  getPublicWidgetOptions: getLabelImagePublicWidgetOptions
5078
5094
  };
5079
5095
 
5096
+ // TODO(LEMS-2841): Should be able to remove once getPublicWidgetOptions is hooked up
5097
+
5098
+ // TODO(LEMS-2841): Should be able to remove once getPublicWidgetOptions is hooked up
5099
+ const shuffleMatcher = props => {
5100
+ // Use the same random() function to shuffle both columns sequentially
5101
+ const rng = seededRNG$1(props.problemNum);
5102
+ let left;
5103
+ if (!props.orderMatters) {
5104
+ // If the order doesn't matter, don't shuffle the left column
5105
+ left = props.left;
5106
+ } else {
5107
+ left = shuffle$2(props.left, rng, /* ensurePermuted */true);
5108
+ }
5109
+ const right = shuffle$2(props.right, rng, /* ensurePermuted */true);
5110
+ return {
5111
+ left,
5112
+ right
5113
+ };
5114
+ };
5115
+
5116
+ // TODO(LEMS-2841): Can shorten to shuffleMatcher after above function removed
5117
+ function shuffleMatcherWithRandom(data) {
5118
+ // Use the same random() function to shuffle both columns sequentially
5119
+ let left;
5120
+ if (!data.orderMatters) {
5121
+ // If the order doesn't matter, don't shuffle the left column
5122
+ left = data.left;
5123
+ } else {
5124
+ left = shuffle$2(data.left, Math.random, /* ensurePermuted */true);
5125
+ }
5126
+ const right = shuffle$2(data.right, Math.random, /* ensurePermuted */true);
5127
+ return {
5128
+ left,
5129
+ right
5130
+ };
5131
+ }
5132
+
5133
+ /**
5134
+ * For details on the individual options, see the
5135
+ * PerseusMatcherWidgetOptions type
5136
+ */
5137
+
5138
+ /**
5139
+ * Given a PerseusMatcherWidgetOptions object, return a new object with only
5140
+ * the public options that should be exposed to the client.
5141
+ */
5142
+ function getMatcherPublicWidgetOptions(options) {
5143
+ const {
5144
+ left,
5145
+ right
5146
+ } = shuffleMatcherWithRandom(options);
5147
+ return _extends({}, options, {
5148
+ left: left,
5149
+ right: right
5150
+ });
5151
+ }
5152
+
5080
5153
  const defaultWidgetOptions$f = {
5081
5154
  left: ["$x$", "$y$", "$z$"],
5082
5155
  right: ["$1$", "$2$", "$3$"],
@@ -5086,7 +5159,8 @@ const defaultWidgetOptions$f = {
5086
5159
  };
5087
5160
  const matcherWidgetLogic = {
5088
5161
  name: "matcher",
5089
- defaultWidgetOptions: defaultWidgetOptions$f
5162
+ defaultWidgetOptions: defaultWidgetOptions$f,
5163
+ getPublicWidgetOptions: getMatcherPublicWidgetOptions
5090
5164
  };
5091
5165
 
5092
5166
  const _excluded$6 = ["answers"];
@@ -5418,14 +5492,17 @@ const radioWidgetLogic = {
5418
5492
  * the public options that should be exposed to the client.
5419
5493
  */
5420
5494
  function getSorterPublicWidgetOptions(options) {
5421
- return {
5495
+ const shuffledCorrect = shuffle$2(options.correct, Math.random, /* ensurePermuted */true);
5496
+ return _extends({}, options, {
5422
5497
  // Note(Tamara): This does not provide correct answer information any longer.
5423
5498
  // To maintain compatibility with the original widget options, we are
5424
5499
  // keeping the key the same. Represents initial state of the cards here.
5425
- correct: options.correct.slice().sort(),
5426
- padding: options.padding,
5427
- layout: options.layout
5428
- };
5500
+ correct: shuffledCorrect,
5501
+ // Note(Tamara): This new key is only added here with "true". There isn't
5502
+ // a place where it is set to false. It indicates that the correct field
5503
+ // has been shuffled and no longer contains correct answer info.
5504
+ isCorrectShuffled: true
5505
+ });
5429
5506
  }
5430
5507
 
5431
5508
  const defaultWidgetOptions$2 = {
@@ -5724,5 +5801,58 @@ function splitPerseusItem(originalItem) {
5724
5801
  });
5725
5802
  }
5726
5803
 
5727
- export { coreWidgetRegistry as CoreWidgetRegistry, Errors, grapherUtil as GrapherUtil, ItemExtras, PerseusError, PerseusExpressionAnswerFormConsidered, addLibraryVersionToPerseusDebug, addWidget, approximateDeepEqual, approximateEqual, categorizerWidgetLogic as categorizerLogic, csProgramWidgetLogic as csProgramLogic, deepClone, definitionWidgetLogic as definitionLogic, dropdownWidgetLogic as dropdownLogic, explanationWidgetLogic as explanationLogic, expressionWidgetLogic as expressionLogic, getCSProgramPublicWidgetOptions, getCategorizerPublicWidgetOptions, getDecimalSeparator, getDropdownPublicWidgetOptions, getExpressionPublicWidgetOptions, getGrapherPublicWidgetOptions, getIFramePublicWidgetOptions, getInteractiveGraphPublicWidgetOptions, getLabelImagePublicWidgetOptions, getMatrixPublicWidgetOptions, getMatrixSize, getNumberLinePublicWidgetOptions, getNumericInputPublicWidgetOptions, getOrdererPublicWidgetOptions, getPlotterPublicWidgetOptions, getRadioPublicWidgetOptions, getSorterPublicWidgetOptions, getTablePublicWidgetOptions, getUpgradedWidgetOptions, getWidgetIdsFromContent, getWidgetIdsFromContentByType, gradedGroupWidgetLogic as gradedGroupLogic, gradedGroupSetWidgetLogic as gradedGroupSetLogic, grapherWidgetLogic as grapherLogic, groupWidgetLogic as groupLogic, iframeWidgetLogic as iframeLogic, imageWidgetLogic as imageLogic, inputNumberWidgetLogic as inputNumberLogic, interactionWidgetLogic as interactionLogic, interactiveGraphWidgetLogic as interactiveGraphLogic, isFailure, isSuccess, labelImageWidgetLogic as labelImageLogic, libVersion, lockedFigureColorNames, lockedFigureColors, lockedFigureFillStyles, mapObject, matcherWidgetLogic as matcherLogic, matrixWidgetLogic as matrixLogic, measurerWidgetLogic as measurerLogic, numberLineWidgetLogic as numberLineLogic, numericInputWidgetLogic as numericInputLogic, ordererWidgetLogic as ordererLogic, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem, passageWidgetLogic as passageLogic, passageRefWidgetLogic as passageRefLogic, passageRefTargetWidgetLogic as passageRefTargetLogic, phetSimulationWidgetLogic as phetSimulationLogic, plotterWidgetLogic as plotterLogic, plotterPlotTypes, pluck, pythonProgramWidgetLogic as pythonProgramLogic, radioWidgetLogic as radioLogic, sorterWidgetLogic as sorterLogic, splitPerseusItem, tableWidgetLogic as tableLogic, upgradeWidgetInfoToLatestVersion, videoWidgetLogic as videoLogic };
5804
+ /* Note(tamara): Brought over from the perseus package packages/perseus/src/util.ts file.
5805
+ May be useful to bring other perseus package utilities here. Contains utility functions
5806
+ and types used across multiple widgets for randomization and shuffling. */
5807
+ const seededRNG = function seededRNG(seed) {
5808
+ let randomSeed = seed;
5809
+ return function () {
5810
+ // Robert Jenkins' 32 bit integer hash function.
5811
+ let seed = randomSeed;
5812
+ seed = seed + 0x7ed55d16 + (seed << 12) & 0xffffffff;
5813
+ seed = (seed ^ 0xc761c23c ^ seed >>> 19) & 0xffffffff;
5814
+ seed = seed + 0x165667b1 + (seed << 5) & 0xffffffff;
5815
+ seed = (seed + 0xd3a2646c ^ seed << 9) & 0xffffffff;
5816
+ seed = seed + 0xfd7046c5 + (seed << 3) & 0xffffffff;
5817
+ seed = (seed ^ 0xb55a4f09 ^ seed >>> 16) & 0xffffffff;
5818
+ return (randomSeed = seed & 0xfffffff) / 0x10000000;
5819
+ };
5820
+ };
5821
+
5822
+ // Shuffle an array using a given random seed or function.
5823
+ // If `ensurePermuted` is true, the input and output are guaranteed to be
5824
+ // distinct permutations.
5825
+ function shuffle(array, randomSeed, ensurePermuted = false) {
5826
+ // Always return a copy of the input array
5827
+ const shuffled = _.clone(array);
5828
+
5829
+ // Handle edge cases (input array is empty or uniform)
5830
+ if (!shuffled.length || _.all(shuffled, function (value) {
5831
+ return _.isEqual(value, shuffled[0]);
5832
+ })) {
5833
+ return shuffled;
5834
+ }
5835
+ let random;
5836
+ if (typeof randomSeed === "function") {
5837
+ random = randomSeed;
5838
+ } else {
5839
+ random = seededRNG(randomSeed);
5840
+ }
5841
+ do {
5842
+ // Fischer-Yates shuffle
5843
+ for (let top = shuffled.length; top > 0; top--) {
5844
+ const newEnd = Math.floor(random() * top);
5845
+ const temp = shuffled[newEnd];
5846
+
5847
+ // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
5848
+ shuffled[newEnd] = shuffled[top - 1];
5849
+ // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
5850
+ shuffled[top - 1] = temp;
5851
+ }
5852
+ } while (ensurePermuted && _.isEqual(array, shuffled));
5853
+ return shuffled;
5854
+ }
5855
+ const random = seededRNG(new Date().getTime() & 0xffffffff);
5856
+
5857
+ export { coreWidgetRegistry as CoreWidgetRegistry, Errors, grapherUtil as GrapherUtil, ItemExtras, PerseusError, PerseusExpressionAnswerFormConsidered, addLibraryVersionToPerseusDebug, addWidget, approximateDeepEqual, approximateEqual, categorizerWidgetLogic as categorizerLogic, csProgramWidgetLogic as csProgramLogic, deepClone, definitionWidgetLogic as definitionLogic, dropdownWidgetLogic as dropdownLogic, explanationWidgetLogic as explanationLogic, expressionWidgetLogic as expressionLogic, getCSProgramPublicWidgetOptions, getCategorizerPublicWidgetOptions, getDecimalSeparator, getDropdownPublicWidgetOptions, getExpressionPublicWidgetOptions, getGrapherPublicWidgetOptions, getIFramePublicWidgetOptions, getInteractiveGraphPublicWidgetOptions, getLabelImagePublicWidgetOptions, getMatcherPublicWidgetOptions, getMatrixPublicWidgetOptions, getMatrixSize, getNumberLinePublicWidgetOptions, getNumericInputPublicWidgetOptions, getOrdererPublicWidgetOptions, getPlotterPublicWidgetOptions, getRadioPublicWidgetOptions, getSorterPublicWidgetOptions, getTablePublicWidgetOptions, getUpgradedWidgetOptions, getWidgetIdsFromContent, getWidgetIdsFromContentByType, gradedGroupWidgetLogic as gradedGroupLogic, gradedGroupSetWidgetLogic as gradedGroupSetLogic, grapherWidgetLogic as grapherLogic, groupWidgetLogic as groupLogic, iframeWidgetLogic as iframeLogic, imageWidgetLogic as imageLogic, inputNumberWidgetLogic as inputNumberLogic, interactionWidgetLogic as interactionLogic, interactiveGraphWidgetLogic as interactiveGraphLogic, isFailure, isSuccess, labelImageWidgetLogic as labelImageLogic, libVersion, lockedFigureColorNames, lockedFigureColors, lockedFigureFillStyles, mapObject, matcherWidgetLogic as matcherLogic, matrixWidgetLogic as matrixLogic, measurerWidgetLogic as measurerLogic, numberLineWidgetLogic as numberLineLogic, numericInputWidgetLogic as numericInputLogic, ordererWidgetLogic as ordererLogic, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem, passageWidgetLogic as passageLogic, passageRefWidgetLogic as passageRefLogic, passageRefTargetWidgetLogic as passageRefTargetLogic, phetSimulationWidgetLogic as phetSimulationLogic, plotterWidgetLogic as plotterLogic, plotterPlotTypes, pluck, pythonProgramWidgetLogic as pythonProgramLogic, radioWidgetLogic as radioLogic, random, seededRNG, shuffle, shuffleMatcher, sorterWidgetLogic as sorterLogic, splitPerseusItem, tableWidgetLogic as tableLogic, upgradeWidgetInfoToLatestVersion, videoWidgetLogic as videoLogic };
5728
5858
  //# sourceMappingURL=index.js.map