@khanacademy/perseus-core 3.5.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.
package/dist/index.js CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var perseusCore = require('@khanacademy/perseus-core');
6
+
5
7
  /**
6
8
  * Adds the given perseus library version information to the __perseus_debug__
7
9
  * object and ensures that the object is attached to `globalThis` (`window` in
@@ -821,7 +823,7 @@ function times(n, iteratee, context) {
821
823
  }
822
824
 
823
825
  // Return a random integer between `min` and `max` (inclusive).
824
- function random(min, max) {
826
+ function random$1(min, max) {
825
827
  if (max == null) {
826
828
  max = min;
827
829
  min = 0;
@@ -1564,14 +1566,14 @@ function toArray(obj) {
1564
1566
  function sample(obj, n, guard) {
1565
1567
  if (n == null || guard) {
1566
1568
  if (!isArrayLike(obj)) obj = values(obj);
1567
- return obj[random(obj.length - 1)];
1569
+ return obj[random$1(obj.length - 1)];
1568
1570
  }
1569
1571
  var sample = toArray(obj);
1570
1572
  var length = getLength(sample);
1571
1573
  n = Math.max(Math.min(n, length), 0);
1572
1574
  var last = length - 1;
1573
1575
  for (var index = 0; index < n; index++) {
1574
- var rand = random(index, last);
1576
+ var rand = random$1(index, last);
1575
1577
  var temp = sample[index];
1576
1578
  sample[index] = sample[rand];
1577
1579
  sample[rand] = temp;
@@ -1580,7 +1582,7 @@ function sample(obj, n, guard) {
1580
1582
  }
1581
1583
 
1582
1584
  // Shuffle a collection.
1583
- function shuffle(obj) {
1585
+ function shuffle$1(obj) {
1584
1586
  return sample(obj, Infinity);
1585
1587
  }
1586
1588
 
@@ -1966,7 +1968,7 @@ var allExports = /*#__PURE__*/Object.freeze({
1966
1968
  matcher: matcher,
1967
1969
  matches: matcher,
1968
1970
  times: times,
1969
- random: random,
1971
+ random: random$1,
1970
1972
  now: now,
1971
1973
  escape: escape,
1972
1974
  unescape: unescape,
@@ -2023,7 +2025,7 @@ var allExports = /*#__PURE__*/Object.freeze({
2023
2025
  where: where,
2024
2026
  max: max,
2025
2027
  min: min,
2026
- shuffle: shuffle,
2028
+ shuffle: shuffle$1,
2027
2029
  sample: sample,
2028
2030
  sortBy: sortBy,
2029
2031
  groupBy: groupBy,
@@ -3075,7 +3077,7 @@ function parseWidget(parseType, parseOptions) {
3075
3077
  graded: optional(boolean),
3076
3078
  alignment: optional(string),
3077
3079
  options: parseOptions,
3078
- key: optional(number),
3080
+ key: optional(nullable(number)),
3079
3081
  version: optional(object({
3080
3082
  major: number,
3081
3083
  minor: number
@@ -3155,6 +3157,13 @@ function convert(f) {
3155
3157
  return (rawValue, ctx) => ctx.success(f(rawValue));
3156
3158
  }
3157
3159
 
3160
+ const parseLegacyButtonSet = enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations", "scientific");
3161
+ const parseLegacyButtonSets = defaulted(array(parseLegacyButtonSet),
3162
+ // NOTE(benchristel): I copied the default buttonSets from
3163
+ // expression.tsx. See the parse-perseus-json/README.md for
3164
+ // an explanation of why we want to duplicate the default here.
3165
+ () => ["basic", "trig", "prealgebra", "logarithms"]);
3166
+
3158
3167
  /**
3159
3168
  * Creates a parser for a widget options type with multiple major versions. Old
3160
3169
  * versions are migrated to the latest version. The parse fails if the input
@@ -3244,11 +3253,6 @@ function removeInvalidAnswerForms(possiblyInvalid) {
3244
3253
  }
3245
3254
  return valid;
3246
3255
  }
3247
-
3248
- // NOTE(benchristel): I copied the default buttonSets from
3249
- // expression.tsx. See the parse-perseus-json/README.md for
3250
- // an explanation of why we want to duplicate the default here.
3251
- const parseButtonSets = defaulted(array(enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations")), () => ["basic", "trig", "prealgebra", "logarithms"]);
3252
3256
  const version1 = object({
3253
3257
  major: constant(1),
3254
3258
  minor: number
@@ -3259,7 +3263,7 @@ const parseExpressionWidgetV1 = parseWidgetWithVersion(version1, constant("expre
3259
3263
  times: boolean,
3260
3264
  visibleLabel: optional(string),
3261
3265
  ariaLabel: optional(string),
3262
- buttonSets: parseButtonSets,
3266
+ buttonSets: parseLegacyButtonSets,
3263
3267
  buttonsVisible: optional(enumeration("always", "never", "focused"))
3264
3268
  }));
3265
3269
  const version0 = optional(object({
@@ -3274,7 +3278,7 @@ const parseExpressionWidgetV0 = parseWidgetWithVersion(version0, constant("expre
3274
3278
  form: boolean,
3275
3279
  simplify: boolean,
3276
3280
  value: string,
3277
- buttonSets: parseButtonSets,
3281
+ buttonSets: parseLegacyButtonSets,
3278
3282
  buttonsVisible: optional(enumeration("always", "never", "focused"))
3279
3283
  }));
3280
3284
  function migrateV0ToV1(widget) {
@@ -3461,14 +3465,15 @@ const imageDimensionToNumber = pipeParsers(union(number).or(string).parser)
3461
3465
  // string parses to either NaN (using parseInt) or 0 (using unary +) and
3462
3466
  // CSS will treat NaN as invalid and default to 0 instead.
3463
3467
  .then(convert(emptyToZero)).then(stringToNumber).parser;
3468
+ const dimensionOrUndefined = defaulted(imageDimensionToNumber, () => undefined);
3464
3469
  const parsePerseusImageBackground = object({
3465
3470
  url: optional(nullable(string)),
3466
- width: optional(imageDimensionToNumber),
3467
- height: optional(imageDimensionToNumber),
3468
- top: optional(imageDimensionToNumber),
3469
- left: optional(imageDimensionToNumber),
3470
- bottom: optional(imageDimensionToNumber),
3471
- scale: optional(imageDimensionToNumber)
3471
+ width: dimensionOrUndefined,
3472
+ height: dimensionOrUndefined,
3473
+ top: dimensionOrUndefined,
3474
+ left: dimensionOrUndefined,
3475
+ bottom: dimensionOrUndefined,
3476
+ scale: dimensionOrUndefined
3472
3477
  });
3473
3478
 
3474
3479
  const pairOfNumbers$2 = pair(number, number);
@@ -4209,7 +4214,7 @@ const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
4209
4214
  // the data, simplify this.
4210
4215
  value: optional(nullable(number)),
4211
4216
  status: string,
4212
- answerForms: optional(array(parseMathFormat)),
4217
+ answerForms: defaulted(array(parseMathFormat), () => undefined),
4213
4218
  strict: boolean,
4214
4219
  maxError: optional(nullable(number)),
4215
4220
  // TODO(benchristel): simplify should never be a boolean, but we
@@ -4307,7 +4312,7 @@ const parseRadioWidget = parseWidget(constant("radio"), object({
4307
4312
  // There is an import cycle between radio-widget.ts and
4308
4313
  // widgets-map.ts. The anonymous function below ensures that we
4309
4314
  // don't refer to parseWidgetsMap before it's defined.
4310
- widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
4315
+ widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => undefined)
4311
4316
  })),
4312
4317
  hasNoneOfTheAbove: optional(boolean),
4313
4318
  countChoices: optional(boolean),
@@ -4461,13 +4466,17 @@ const parseDeprecatedWidget = parseWidget(
4461
4466
  (_, ctx) => ctx.success("deprecated-standin"),
4462
4467
  // Allow any widget options
4463
4468
  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);
4469
+ const parseStringToNonNegativeInt = (rawValue, ctx) => {
4470
+ // The article renderer seems to allow the numeric part of a widget ID to
4471
+ // be 0, at least for image widgets. However, if widget IDs in an exercise
4472
+ // contain 0, the exercise renderer will blow up. We allow 0 here for
4473
+ // compatibility with articles.
4474
+ if (typeof rawValue !== "string" || !/^(0|[1-9][0-9]*)$/.test(rawValue)) {
4475
+ return ctx.failure("a string representing a non-negative integer", rawValue);
4467
4476
  }
4468
4477
  return ctx.success(+rawValue);
4469
4478
  };
4470
- const parseWidgetIdComponents = pair(string, parseStringToPositiveInt);
4479
+ const parseWidgetIdComponents = pair(string, parseStringToNonNegativeInt);
4471
4480
 
4472
4481
  const parsePerseusRenderer = defaulted(object({
4473
4482
  // TODO(benchristel): content is also defaulted to empty string in
@@ -4478,8 +4487,9 @@ const parsePerseusRenderer = defaulted(object({
4478
4487
  // The anonymous function below ensures that we don't try to access
4479
4488
  // parseWidgetsMap before it's defined.
4480
4489
  widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => ({})),
4481
- metadata: optional(array(string)),
4482
- images: parseImages
4490
+ images: parseImages,
4491
+ // deprecated
4492
+ metadata: any
4483
4493
  }),
4484
4494
  // Default value
4485
4495
  () => ({
@@ -4494,14 +4504,44 @@ const parseHint = object({
4494
4504
  replace: optional(boolean),
4495
4505
  content: string,
4496
4506
  widgets: defaulted(parseWidgetsMap, () => ({})),
4497
- metadata: optional(array(string)),
4498
- images: parseImages
4507
+ images: parseImages,
4508
+ // deprecated
4509
+ metadata: any
4499
4510
  });
4500
4511
 
4512
+ const parsePerseusAnswerArea = pipeParsers(defaulted(object({}), () => ({}))).then(convert(toAnswerArea)).parser;
4513
+
4514
+ // Some answerAreas have extra, bogus fields, like:
4515
+ //
4516
+ // "answerArea": {
4517
+ // "type": "multiple",
4518
+ // "options": {},
4519
+ // "version": null,
4520
+ // "static": false,
4521
+ // "graded": false,
4522
+ // "alignment": "",
4523
+ // }
4524
+ //
4525
+ // This function filters the fields of an answerArea object, keeping only the
4526
+ // known ones, and converts `undefined` and `null` values to `false`.
4527
+ function toAnswerArea(raw) {
4528
+ return {
4529
+ zTable: !!raw.zTable,
4530
+ calculator: !!raw.calculator,
4531
+ chi2Table: !!raw.chi2Table,
4532
+ financialCalculatorMonthlyPayment: !!raw.financialCalculatorMonthlyPayment,
4533
+ financialCalculatorTotalAmount: !!raw.financialCalculatorTotalAmount,
4534
+ financialCalculatorTimeToPayOff: !!raw.financialCalculatorTimeToPayOff,
4535
+ periodicTable: !!raw.periodicTable,
4536
+ periodicTableWithKey: !!raw.periodicTableWithKey,
4537
+ tTable: !!raw.tTable
4538
+ };
4539
+ }
4540
+
4501
4541
  const parsePerseusItem$1 = object({
4502
4542
  question: parsePerseusRenderer,
4503
4543
  hints: defaulted(array(parseHint), () => []),
4504
- answerArea: pipeParsers(defaulted(object({}), () => ({}))).then(migrateAnswerArea).then(record(enumeration(...ItemExtras), boolean)).parser,
4544
+ answerArea: parsePerseusAnswerArea,
4505
4545
  itemDataVersion: optional(object({
4506
4546
  major: number,
4507
4547
  minor: number
@@ -4510,28 +4550,6 @@ const parsePerseusItem$1 = object({
4510
4550
  answer: any
4511
4551
  });
4512
4552
 
4513
- // Some answerAreas have extra fields, like:
4514
- //
4515
- // "answerArea": {
4516
- // "type": "multiple",
4517
- // "options": {
4518
- // "content": "",
4519
- // "images": {},
4520
- // "widgets": {}
4521
- // }
4522
- // }
4523
- //
4524
- // The "type" and "options" fields don't seem to be used anywhere. This
4525
- // migration function removes them.
4526
- function migrateAnswerArea(rawValue, ctx) {
4527
- const {
4528
- type: _,
4529
- options: __,
4530
- ...rest
4531
- } = rawValue;
4532
- return ctx.success(rest);
4533
- }
4534
-
4535
4553
  /**
4536
4554
  * Helper to parse PerseusItem JSON
4537
4555
  * Why not just use JSON.parse? We want:
@@ -4606,7 +4624,7 @@ function throwErrorIfCheatingDetected() {
4606
4624
 
4607
4625
  // This file is processed by a Rollup plugin (replace) to inject the production
4608
4626
  const libName = "@khanacademy/perseus-core";
4609
- const libVersion = "3.5.0";
4627
+ const libVersion = "3.7.0";
4610
4628
  addLibraryVersionToPerseusDebug(libName, libVersion);
4611
4629
 
4612
4630
  /**
@@ -4705,6 +4723,24 @@ const mapObject = function (obj, lambda) {
4705
4723
  return result;
4706
4724
  };
4707
4725
 
4726
+ /**
4727
+ * For details on the individual options, see the
4728
+ * PerseusCategorizerWidgetOptions type
4729
+ */
4730
+
4731
+ /**
4732
+ * Given a PerseusCategorizerWidgetOptions object, return a new object with only
4733
+ * the public options that should be exposed to the client.
4734
+ */
4735
+ function getCategorizerPublicWidgetOptions(options) {
4736
+ return {
4737
+ items: options.items,
4738
+ categories: options.categories,
4739
+ randomizeItems: options.randomizeItems,
4740
+ static: options.static
4741
+ };
4742
+ }
4743
+
4708
4744
  const defaultWidgetOptions$v = {
4709
4745
  items: [],
4710
4746
  categories: [],
@@ -4713,9 +4749,14 @@ const defaultWidgetOptions$v = {
4713
4749
  };
4714
4750
  const categorizerWidgetLogic = {
4715
4751
  name: "categorizer",
4716
- defaultWidgetOptions: defaultWidgetOptions$v
4752
+ defaultWidgetOptions: defaultWidgetOptions$v,
4753
+ getPublicWidgetOptions: getCategorizerPublicWidgetOptions
4717
4754
  };
4718
4755
 
4756
+ function getCSProgramPublicWidgetOptions(options) {
4757
+ return options;
4758
+ }
4759
+
4719
4760
  const DEFAULT_HEIGHT = 400;
4720
4761
  const defaultWidgetOptions$u = {
4721
4762
  programID: "",
@@ -4731,7 +4772,8 @@ const defaultWidgetOptions$u = {
4731
4772
  const csProgramWidgetLogic = {
4732
4773
  name: "cs-program",
4733
4774
  defaultWidgetOptions: defaultWidgetOptions$u,
4734
- supportedAlignments: ["block", "full-width"]
4775
+ supportedAlignments: ["block", "full-width"],
4776
+ getPublicWidgetOptions: getCSProgramPublicWidgetOptions
4735
4777
  };
4736
4778
 
4737
4779
  const defaultWidgetOptions$t = {
@@ -4744,6 +4786,27 @@ const definitionWidgetLogic = {
4744
4786
  defaultAlignment: "inline"
4745
4787
  };
4746
4788
 
4789
+ /**
4790
+ * For details on the individual options, see the
4791
+ * PerseusDropdownWidgetOptions type
4792
+ */
4793
+
4794
+ /**
4795
+ * Given a PerseusDropdownWidgetOptions object, return a new object with only
4796
+ * the public options that should be exposed to the client.
4797
+ */
4798
+ function getDropdownPublicWidgetOptions(options) {
4799
+ return {
4800
+ choices: options.choices.map(choice => ({
4801
+ content: choice.content
4802
+ })),
4803
+ placeholder: options.placeholder,
4804
+ static: options.static,
4805
+ visibleLabel: options.visibleLabel,
4806
+ ariaLabel: options.ariaLabel
4807
+ };
4808
+ }
4809
+
4747
4810
  const defaultWidgetOptions$s = {
4748
4811
  placeholder: "",
4749
4812
  choices: [{
@@ -4754,7 +4817,8 @@ const defaultWidgetOptions$s = {
4754
4817
  const dropdownWidgetLogic = {
4755
4818
  name: "definition",
4756
4819
  defaultWidgetOptions: defaultWidgetOptions$s,
4757
- defaultAlignment: "inline-block"
4820
+ defaultAlignment: "inline-block",
4821
+ getPublicWidgetOptions: getDropdownPublicWidgetOptions
4758
4822
  };
4759
4823
 
4760
4824
  const defaultWidgetOptions$r = {
@@ -4796,12 +4860,33 @@ const defaultWidgetOptions$q = {
4796
4860
  functions: ["f", "g", "h"]
4797
4861
  };
4798
4862
 
4863
+ /**
4864
+ * For details on the individual options, see the
4865
+ * PerseusExpressionWidgetOptions type
4866
+ */
4867
+
4868
+ /**
4869
+ * Given a PerseusExpressionWidgetOptions object, return a new object with only
4870
+ * the public options that should be exposed to the client.
4871
+ */
4872
+ function getExpressionPublicWidgetOptions(options) {
4873
+ return {
4874
+ buttonSets: options.buttonSets,
4875
+ functions: options.functions,
4876
+ times: options.times,
4877
+ visibleLabel: options.visibleLabel,
4878
+ ariaLabel: options.ariaLabel,
4879
+ buttonsVisible: options.buttonsVisible
4880
+ };
4881
+ }
4882
+
4799
4883
  const expressionWidgetLogic = {
4800
4884
  name: "expression",
4801
4885
  version: currentVersion$3,
4802
4886
  widgetOptionsUpgrades: widgetOptionsUpgrades$2,
4803
4887
  defaultWidgetOptions: defaultWidgetOptions$q,
4804
- defaultAlignment: "inline-block"
4888
+ defaultAlignment: "inline-block",
4889
+ getPublicWidgetOptions: getExpressionPublicWidgetOptions
4805
4890
  };
4806
4891
 
4807
4892
  const defaultWidgetOptions$p = {
@@ -4824,6 +4909,14 @@ const gradedGroupSetWidgetLogic = {
4824
4909
  defaultWidgetOptions: defaultWidgetOptions$o
4825
4910
  };
4826
4911
 
4912
+ function getGrapherPublicWidgetOptions(options) {
4913
+ const {
4914
+ correct: _,
4915
+ ...publicOptions
4916
+ } = options;
4917
+ return publicOptions;
4918
+ }
4919
+
4827
4920
  const defaultWidgetOptions$n = {
4828
4921
  graph: {
4829
4922
  labels: ["x", "y"],
@@ -4846,22 +4939,24 @@ const defaultWidgetOptions$n = {
4846
4939
  };
4847
4940
  const grapherWidgetLogic = {
4848
4941
  name: "grapher",
4849
- defaultWidgetOptions: defaultWidgetOptions$n
4942
+ defaultWidgetOptions: defaultWidgetOptions$n,
4943
+ getPublicWidgetOptions: getGrapherPublicWidgetOptions
4850
4944
  };
4851
4945
 
4852
4946
  const defaultWidgetOptions$m = {
4853
4947
  content: "",
4854
4948
  widgets: {},
4855
- images: {},
4856
- // `undefined` instead of `null` so that getDefaultProps works for
4857
- // `the GroupMetadataEditor`
4858
- metadata: undefined
4949
+ images: {}
4859
4950
  };
4860
4951
  const groupWidgetLogic = {
4861
4952
  name: "group",
4862
4953
  defaultWidgetOptions: defaultWidgetOptions$m
4863
4954
  };
4864
4955
 
4956
+ function getIFramePublicWidgetOptions(options) {
4957
+ return options;
4958
+ }
4959
+
4865
4960
  const defaultWidgetOptions$l = {
4866
4961
  url: "",
4867
4962
  settings: [{
@@ -4875,7 +4970,8 @@ const defaultWidgetOptions$l = {
4875
4970
  };
4876
4971
  const iframeWidgetLogic = {
4877
4972
  name: "iframe",
4878
- defaultWidgetOptions: defaultWidgetOptions$l
4973
+ defaultWidgetOptions: defaultWidgetOptions$l,
4974
+ getPublicWidgetOptions: getIFramePublicWidgetOptions
4879
4975
  };
4880
4976
 
4881
4977
  const defaultWidgetOptions$k = {
@@ -4929,6 +5025,14 @@ const interactionWidgetLogic = {
4929
5025
  defaultWidgetOptions: defaultWidgetOptions$i
4930
5026
  };
4931
5027
 
5028
+ function getInteractiveGraphPublicWidgetOptions(options) {
5029
+ const {
5030
+ correct: _,
5031
+ ...publicOptions
5032
+ } = options;
5033
+ return publicOptions;
5034
+ }
5035
+
4932
5036
  const defaultWidgetOptions$h = {
4933
5037
  labels: ["x", "y"],
4934
5038
  range: [[-10, 10], [-10, 10]],
@@ -4949,9 +5053,29 @@ const defaultWidgetOptions$h = {
4949
5053
  };
4950
5054
  const interactiveGraphWidgetLogic = {
4951
5055
  name: "interactive-graph",
4952
- defaultWidgetOptions: defaultWidgetOptions$h
5056
+ defaultWidgetOptions: defaultWidgetOptions$h,
5057
+ getPublicWidgetOptions: getInteractiveGraphPublicWidgetOptions
4953
5058
  };
4954
5059
 
5060
+ /**
5061
+ * For details on the individual options, see the
5062
+ * PerseusLabelImageWidgetOptions type
5063
+ */
5064
+
5065
+ function getLabelImagePublicWidgetOptions(options) {
5066
+ return {
5067
+ ...options,
5068
+ markers: options.markers.map(getLabelImageMarkerPublicData)
5069
+ };
5070
+ }
5071
+ function getLabelImageMarkerPublicData(marker) {
5072
+ const {
5073
+ answers: _,
5074
+ ...publicData
5075
+ } = marker;
5076
+ return publicData;
5077
+ }
5078
+
4955
5079
  const defaultWidgetOptions$g = {
4956
5080
  choices: [],
4957
5081
  imageAlt: "",
@@ -4964,9 +5088,68 @@ const defaultWidgetOptions$g = {
4964
5088
  };
4965
5089
  const labelImageWidgetLogic = {
4966
5090
  name: "label-image",
4967
- defaultWidgetOptions: defaultWidgetOptions$g
5091
+ defaultWidgetOptions: defaultWidgetOptions$g,
5092
+ getPublicWidgetOptions: getLabelImagePublicWidgetOptions
5093
+ };
5094
+
5095
+ // TODO(LEMS-2841): Should be able to remove once getPublicWidgetOptions is hooked up
5096
+
5097
+ // TODO(LEMS-2841): Should be able to remove once getPublicWidgetOptions is hooked up
5098
+ const shuffleMatcher = props => {
5099
+ // Use the same random() function to shuffle both columns sequentially
5100
+ const rng = perseusCore.seededRNG(props.problemNum);
5101
+ let left;
5102
+ if (!props.orderMatters) {
5103
+ // If the order doesn't matter, don't shuffle the left column
5104
+ left = props.left;
5105
+ } else {
5106
+ left = perseusCore.shuffle(props.left, rng, /* ensurePermuted */true);
5107
+ }
5108
+ const right = perseusCore.shuffle(props.right, rng, /* ensurePermuted */true);
5109
+ return {
5110
+ left,
5111
+ right
5112
+ };
4968
5113
  };
4969
5114
 
5115
+ // TODO(LEMS-2841): Can shorten to shuffleMatcher after above function removed
5116
+ function shuffleMatcherWithRandom(data) {
5117
+ // Use the same random() function to shuffle both columns sequentially
5118
+ let left;
5119
+ if (!data.orderMatters) {
5120
+ // If the order doesn't matter, don't shuffle the left column
5121
+ left = data.left;
5122
+ } else {
5123
+ left = perseusCore.shuffle(data.left, Math.random, /* ensurePermuted */true);
5124
+ }
5125
+ const right = perseusCore.shuffle(data.right, Math.random, /* ensurePermuted */true);
5126
+ return {
5127
+ left,
5128
+ right
5129
+ };
5130
+ }
5131
+
5132
+ /**
5133
+ * For details on the individual options, see the
5134
+ * PerseusMatcherWidgetOptions type
5135
+ */
5136
+
5137
+ /**
5138
+ * Given a PerseusMatcherWidgetOptions object, return a new object with only
5139
+ * the public options that should be exposed to the client.
5140
+ */
5141
+ function getMatcherPublicWidgetOptions(options) {
5142
+ const {
5143
+ left,
5144
+ right
5145
+ } = shuffleMatcherWithRandom(options);
5146
+ return {
5147
+ ...options,
5148
+ left: left,
5149
+ right: right
5150
+ };
5151
+ }
5152
+
4970
5153
  const defaultWidgetOptions$f = {
4971
5154
  left: ["$x$", "$y$", "$z$"],
4972
5155
  right: ["$1$", "$2$", "$3$"],
@@ -4976,9 +5159,18 @@ const defaultWidgetOptions$f = {
4976
5159
  };
4977
5160
  const matcherWidgetLogic = {
4978
5161
  name: "matcher",
4979
- defaultWidgetOptions: defaultWidgetOptions$f
5162
+ defaultWidgetOptions: defaultWidgetOptions$f,
5163
+ getPublicWidgetOptions: getMatcherPublicWidgetOptions
4980
5164
  };
4981
5165
 
5166
+ function getMatrixPublicWidgetOptions(options) {
5167
+ const {
5168
+ answers: _,
5169
+ ...publicOptions
5170
+ } = options;
5171
+ return publicOptions;
5172
+ }
5173
+
4982
5174
  const defaultWidgetOptions$e = {
4983
5175
  matrixBoardSize: [3, 3],
4984
5176
  answers: [[]],
@@ -4988,7 +5180,8 @@ const defaultWidgetOptions$e = {
4988
5180
  };
4989
5181
  const matrixWidgetLogic = {
4990
5182
  name: "matrix",
4991
- defaultWidgetOptions: defaultWidgetOptions$e
5183
+ defaultWidgetOptions: defaultWidgetOptions$e,
5184
+ getPublicWidgetOptions: getMatrixPublicWidgetOptions
4992
5185
  };
4993
5186
 
4994
5187
  const currentVersion$2 = {
@@ -5031,6 +5224,15 @@ const measurerWidgetLogic = {
5031
5224
  defaultWidgetOptions: defaultWidgetOptions$d
5032
5225
  };
5033
5226
 
5227
+ function getNumberLinePublicWidgetOptions(options) {
5228
+ const {
5229
+ correctX: _,
5230
+ correctRel: __,
5231
+ ...publicOptions
5232
+ } = options;
5233
+ return publicOptions;
5234
+ }
5235
+
5034
5236
  const defaultWidgetOptions$c = {
5035
5237
  range: [0, 10],
5036
5238
  labelRange: [null, null],
@@ -5047,9 +5249,27 @@ const defaultWidgetOptions$c = {
5047
5249
  };
5048
5250
  const numberLineWidgetLogic = {
5049
5251
  name: "number-line",
5050
- defaultWidgetOptions: defaultWidgetOptions$c
5252
+ defaultWidgetOptions: defaultWidgetOptions$c,
5253
+ getPublicWidgetOptions: getNumberLinePublicWidgetOptions
5051
5254
  };
5052
5255
 
5256
+ /**
5257
+ * For details on the individual options, see the
5258
+ * PerseusNumericInputWidgetOptions type
5259
+ */
5260
+
5261
+ /**
5262
+ * Given a PerseusNumericInputWidgetOptions object, return a new object with only
5263
+ * the public options that should be exposed to the client.
5264
+ */
5265
+ function getNumericInputPublicWidgetOptions(options) {
5266
+ const {
5267
+ answers: _,
5268
+ ...publicWidgetOptions
5269
+ } = options;
5270
+ return publicWidgetOptions;
5271
+ }
5272
+
5053
5273
  const defaultWidgetOptions$b = {
5054
5274
  answers: [{
5055
5275
  value: null,
@@ -5068,9 +5288,27 @@ const defaultWidgetOptions$b = {
5068
5288
  const numericInputWidgetLogic = {
5069
5289
  name: "numeric-input",
5070
5290
  defaultWidgetOptions: defaultWidgetOptions$b,
5071
- defaultAlignment: "inline-block"
5291
+ defaultAlignment: "inline-block",
5292
+ getPublicWidgetOptions: getNumericInputPublicWidgetOptions
5072
5293
  };
5073
5294
 
5295
+ /**
5296
+ * For details on the individual options, see the
5297
+ * PerseusOrdererWidgetOptions type
5298
+ */
5299
+
5300
+ /**
5301
+ * Given a PerseusOrdererWidgetOptions object, return a new object with only
5302
+ * the public options that should be exposed to the client.
5303
+ */
5304
+ function getOrdererPublicWidgetOptions(options) {
5305
+ return {
5306
+ options: options.options,
5307
+ height: options.height,
5308
+ layout: options.layout
5309
+ };
5310
+ }
5311
+
5074
5312
  const defaultWidgetOptions$a = {
5075
5313
  correctOptions: [{
5076
5314
  content: "$x$"
@@ -5083,7 +5321,8 @@ const defaultWidgetOptions$a = {
5083
5321
  };
5084
5322
  const ordererWidgetLogic = {
5085
5323
  name: "orderer",
5086
- defaultWidgetOptions: defaultWidgetOptions$a
5324
+ defaultWidgetOptions: defaultWidgetOptions$a,
5325
+ getPublicWidgetOptions: getOrdererPublicWidgetOptions
5087
5326
  };
5088
5327
 
5089
5328
  const defaultWidgetOptions$9 = {
@@ -5132,6 +5371,23 @@ const phetSimulationWidgetLogic = {
5132
5371
  defaultWidgetOptions: defaultWidgetOptions$6
5133
5372
  };
5134
5373
 
5374
+ /**
5375
+ * For details on the individual options, see the
5376
+ * PerseusPlotterWidgetOptions type
5377
+ */
5378
+
5379
+ /**
5380
+ * Given a PerseusPlotterWidgetOptions object, return a new object with only
5381
+ * the public options that should be exposed to the client.
5382
+ */
5383
+ function getPlotterPublicWidgetOptions(options) {
5384
+ const {
5385
+ correct: _,
5386
+ ...publicOptions
5387
+ } = options;
5388
+ return publicOptions;
5389
+ }
5390
+
5135
5391
  const defaultWidgetOptions$5 = {
5136
5392
  scaleY: 1,
5137
5393
  maxY: 10,
@@ -5149,7 +5405,8 @@ const defaultWidgetOptions$5 = {
5149
5405
  };
5150
5406
  const plotterWidgetLogic = {
5151
5407
  name: "plotter",
5152
- defaultWidgetOptions: defaultWidgetOptions$5
5408
+ defaultWidgetOptions: defaultWidgetOptions$5,
5409
+ getPublicWidgetOptions: getPlotterPublicWidgetOptions
5153
5410
  };
5154
5411
 
5155
5412
  const defaultWidgetOptions$4 = {
@@ -5190,27 +5447,98 @@ const defaultWidgetOptions$3 = {
5190
5447
  deselectEnabled: false
5191
5448
  };
5192
5449
 
5193
- const radioWidgetLogic = {
5194
- name: "radio",
5195
- version: currentVersion,
5196
- widgetOptionsUpgrades: widgetOptionsUpgrades,
5197
- defaultWidgetOptions: defaultWidgetOptions$3
5198
- };
5199
-
5200
- const defaultWidgetOptions$2 = {
5201
- correct: ["$x$", "$y$", "$z$"],
5202
- layout: "horizontal",
5203
- padding: true
5204
- };
5205
- const sorterWidgetLogic = {
5206
- name: "sorter",
5207
- defaultWidgetOptions: defaultWidgetOptions$2
5208
- };
5450
+ /**
5451
+ * For details on the individual options, see the
5452
+ * PerseusRadioWidgetOptions type
5453
+ */
5209
5454
 
5210
- const defaultRows = 4;
5211
- const defaultColumns = 1;
5455
+ /**
5456
+ * Only the options from each Radio choice that should be exposed to the client.
5457
+ */
5212
5458
 
5213
- // initialize a 2D array
5459
+ /**
5460
+ * Given a PerseusRadioChoice object, return a new object with only the public
5461
+ * data that should be included in the Radio public widget options.
5462
+ */
5463
+ function getRadioChoicePublicData(choice) {
5464
+ const {
5465
+ content,
5466
+ isNoneOfTheAbove,
5467
+ widgets
5468
+ } = choice;
5469
+ return {
5470
+ content,
5471
+ isNoneOfTheAbove,
5472
+ widgets
5473
+ };
5474
+ }
5475
+
5476
+ /**
5477
+ * Given a PerseusRadioWidgetOptions object, return a new object with only
5478
+ * the public options that should be exposed to the client.
5479
+ */
5480
+ function getRadioPublicWidgetOptions(options) {
5481
+ return {
5482
+ ...options,
5483
+ choices: options.choices.map(getRadioChoicePublicData)
5484
+ };
5485
+ }
5486
+
5487
+ const radioWidgetLogic = {
5488
+ name: "radio",
5489
+ version: currentVersion,
5490
+ widgetOptionsUpgrades: widgetOptionsUpgrades,
5491
+ defaultWidgetOptions: defaultWidgetOptions$3,
5492
+ getPublicWidgetOptions: getRadioPublicWidgetOptions
5493
+ };
5494
+
5495
+ /**
5496
+ * For details on the individual options, see the
5497
+ * PerseusSorterWidgetOptions type
5498
+ */
5499
+
5500
+ /**
5501
+ * Given a PerseusSorterWidgetOptions object, return a new object with only
5502
+ * the public options that should be exposed to the client.
5503
+ */
5504
+ function getSorterPublicWidgetOptions(options) {
5505
+ const shuffledCorrect = perseusCore.shuffle(options.correct, Math.random, /* ensurePermuted */true);
5506
+ return {
5507
+ ...options,
5508
+ // Note(Tamara): This does not provide correct answer information any longer.
5509
+ // To maintain compatibility with the original widget options, we are
5510
+ // keeping the key the same. Represents initial state of the cards here.
5511
+ correct: shuffledCorrect,
5512
+ // Note(Tamara): This new key is only added here with "true". There isn't
5513
+ // a place where it is set to false. It indicates that the correct field
5514
+ // has been shuffled and no longer contains correct answer info.
5515
+ isCorrectShuffled: true
5516
+ };
5517
+ }
5518
+
5519
+ const defaultWidgetOptions$2 = {
5520
+ correct: ["$x$", "$y$", "$z$"],
5521
+ layout: "horizontal",
5522
+ padding: true
5523
+ };
5524
+ const sorterWidgetLogic = {
5525
+ name: "sorter",
5526
+ defaultWidgetOptions: defaultWidgetOptions$2,
5527
+ getPublicWidgetOptions: getSorterPublicWidgetOptions
5528
+ };
5529
+
5530
+ function getTablePublicWidgetOptions(options) {
5531
+ const {
5532
+ answers: _,
5533
+ ...publicOptions
5534
+ } = options;
5535
+ return publicOptions;
5536
+ }
5537
+
5538
+ const defaultRows = 4;
5539
+ const defaultColumns = 1;
5540
+
5541
+ // initialize a 2D array
5214
5542
  // (defaultRows x defaultColumns) of empty strings
5215
5543
  const answers = new Array(defaultRows).fill(0).map(() => new Array(defaultColumns).fill(""));
5216
5544
  const defaultWidgetOptions$1 = {
@@ -5221,7 +5549,8 @@ const defaultWidgetOptions$1 = {
5221
5549
  };
5222
5550
  const tableWidgetLogic = {
5223
5551
  name: "table",
5224
- defaultWidgetOptions: defaultWidgetOptions$1
5552
+ defaultWidgetOptions: defaultWidgetOptions$1,
5553
+ getPublicWidgetOptions: getTablePublicWidgetOptions
5225
5554
  };
5226
5555
 
5227
5556
  const defaultWidgetOptions = {
@@ -5249,6 +5578,12 @@ function getCurrentVersion(type) {
5249
5578
  minor: 0
5250
5579
  };
5251
5580
  }
5581
+
5582
+ // TODO(LEMS-2870): getPublicWidgetOptionsFunction/PublicWidgetOptionsFunction
5583
+ // need better types
5584
+ const getPublicWidgetOptionsFunction = name => {
5585
+ return widgets[name]?.getPublicWidgetOptions ?? (i => i);
5586
+ };
5252
5587
  function getWidgetOptionsUpgrades(type) {
5253
5588
  const widgetLogic = widgets[type];
5254
5589
  return widgetLogic?.widgetOptionsUpgrades || {};
@@ -5333,6 +5668,7 @@ var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
5333
5668
  __proto__: null,
5334
5669
  isWidgetRegistered: isWidgetRegistered,
5335
5670
  getCurrentVersion: getCurrentVersion,
5671
+ getPublicWidgetOptionsFunction: getPublicWidgetOptionsFunction,
5336
5672
  getWidgetOptionsUpgrades: getWidgetOptionsUpgrades,
5337
5673
  getDefaultWidgetOptions: getDefaultWidgetOptions,
5338
5674
  getSupportedAlignments: getSupportedAlignments,
@@ -5465,240 +5801,77 @@ function getUpgradedWidgetOptions(oldWidgetOptions) {
5465
5801
  });
5466
5802
  }
5467
5803
 
5468
- /**
5469
- * For details on the individual options, see the
5470
- * PerseusOrdererWidgetOptions type
5471
- */
5472
-
5473
- /**
5474
- * Given a PerseusOrdererWidgetOptions object, return a new object with only
5475
- * the public options that should be exposed to the client.
5476
- */
5477
- function getOrdererPublicWidgetOptions(options) {
5478
- return {
5479
- options: options.options,
5480
- height: options.height,
5481
- layout: options.layout
5482
- };
5483
- }
5484
-
5485
- /**
5486
- * For details on the individual options, see the
5487
- * PerseusCategorizerWidgetOptions type
5488
- */
5489
-
5490
- /**
5491
- * Given a PerseusCategorizerWidgetOptions object, return a new object with only
5492
- * the public options that should be exposed to the client.
5493
- */
5494
- function getCategorizerPublicWidgetOptions(options) {
5495
- return {
5496
- items: options.items,
5497
- categories: options.categories,
5498
- randomizeItems: options.randomizeItems,
5499
- static: options.static
5500
- };
5501
- }
5502
-
5503
- function getCSProgramPublicWidgetOptions(options) {
5504
- return options;
5505
- }
5506
-
5507
- /**
5508
- * For details on the individual options, see the
5509
- * PerseusExpressionWidgetOptions type
5510
- */
5511
-
5512
- /**
5513
- * Given a PerseusExpressionWidgetOptions object, return a new object with only
5514
- * the public options that should be exposed to the client.
5515
- */
5516
- function getExpressionPublicWidgetOptions(options) {
5517
- return {
5518
- buttonSets: options.buttonSets,
5519
- functions: options.functions,
5520
- times: options.times,
5521
- visibleLabel: options.visibleLabel,
5522
- ariaLabel: options.ariaLabel,
5523
- buttonsVisible: options.buttonsVisible
5524
- };
5525
- }
5526
-
5527
- function getGrapherPublicWidgetOptions(options) {
5528
- const {
5529
- correct: _,
5530
- ...publicOptions
5531
- } = options;
5532
- return publicOptions;
5533
- }
5534
-
5535
- function getInteractiveGraphPublicWidgetOptions(options) {
5536
- const {
5537
- correct: _,
5538
- ...publicOptions
5539
- } = options;
5540
- return publicOptions;
5541
- }
5542
-
5543
- /**
5544
- * For details on the individual options, see the
5545
- * PerseusLabelImageWidgetOptions type
5546
- */
5547
-
5548
- function getLabelImagePublicWidgetOptions(options) {
5549
- return {
5550
- ...options,
5551
- markers: options.markers.map(getLabelImageMarkerPublicData)
5552
- };
5553
- }
5554
- function getLabelImageMarkerPublicData(marker) {
5555
- const {
5556
- answers: _,
5557
- ...publicData
5558
- } = marker;
5559
- return publicData;
5560
- }
5561
-
5562
- /**
5563
- * For details on the individual options, see the
5564
- * PerseusSorterWidgetOptions type
5565
- */
5566
-
5567
- /**
5568
- * Given a PerseusSorterWidgetOptions object, return a new object with only
5569
- * the public options that should be exposed to the client.
5570
- */
5571
- function getSorterPublicWidgetOptions(options) {
5572
- return {
5573
- // Note(Tamara): This does not provide correct answer information any longer.
5574
- // To maintain compatibility with the original widget options, we are
5575
- // keeping the key the same. Represents initial state of the cards here.
5576
- correct: options.correct.slice().sort(),
5577
- padding: options.padding,
5578
- layout: options.layout
5579
- };
5580
- }
5581
-
5582
- /**
5583
- * For details on the individual options, see the
5584
- * PerseusDropdownWidgetOptions type
5585
- */
5586
-
5587
- /**
5588
- * Given a PerseusDropdownWidgetOptions object, return a new object with only
5589
- * the public options that should be exposed to the client.
5590
- */
5591
- function getDropdownPublicWidgetOptions(options) {
5592
- return {
5593
- choices: options.choices.map(choice => ({
5594
- content: choice.content
5595
- })),
5596
- placeholder: options.placeholder,
5597
- static: options.static,
5598
- visibleLabel: options.visibleLabel,
5599
- ariaLabel: options.ariaLabel
5600
- };
5601
- }
5602
-
5603
- /**
5604
- * For details on the individual options, see the
5605
- * PerseusNumericInputWidgetOptions type
5606
- */
5607
-
5608
- /**
5609
- * Given a PerseusNumericInputWidgetOptions object, return a new object with only
5610
- * the public options that should be exposed to the client.
5611
- */
5612
- function getNumericInputPublicWidgetOptions(options) {
5613
- const {
5614
- answers: _,
5615
- ...publicWidgetOptions
5616
- } = options;
5617
- return publicWidgetOptions;
5618
- }
5619
-
5620
- function getNumberLinePublicWidgetOptions(options) {
5621
- const {
5622
- correctX: _,
5623
- correctRel: __,
5624
- ...publicOptions
5625
- } = options;
5626
- return publicOptions;
5627
- }
5628
-
5629
- /**
5630
- * For details on the individual options, see the
5631
- * PerseusRadioWidgetOptions type
5632
- */
5633
-
5634
- /**
5635
- * Only the options from each Radio choice that should be exposed to the client.
5636
- */
5637
-
5638
- /**
5639
- * Given a PerseusRadioChoice object, return a new object with only the public
5640
- * data that should be included in the Radio public widget options.
5641
- */
5642
- function getRadioChoicePublicData(choice) {
5643
- const {
5644
- content,
5645
- isNoneOfTheAbove,
5646
- widgets
5647
- } = choice;
5804
+ function splitPerseusItem(originalItem) {
5805
+ const item = _.clone(originalItem);
5806
+ const originalWidgets = item.widgets ?? {};
5807
+ const upgradedWidgets = getUpgradedWidgetOptions(originalWidgets);
5808
+ const splitWidgets = {};
5809
+ for (const [id, widget] of Object.entries(upgradedWidgets)) {
5810
+ const publicWidgetOptionsFun = getPublicWidgetOptionsFunction(widget.type);
5811
+ splitWidgets[id] = {
5812
+ ...widget,
5813
+ options: publicWidgetOptionsFun(widget.options)
5814
+ };
5815
+ }
5648
5816
  return {
5649
- content,
5650
- isNoneOfTheAbove,
5651
- widgets
5817
+ ...item,
5818
+ widgets: splitWidgets
5652
5819
  };
5653
5820
  }
5654
5821
 
5655
- /**
5656
- * Given a PerseusRadioWidgetOptions object, return a new object with only
5657
- * the public options that should be exposed to the client.
5658
- */
5659
- function getRadioPublicWidgetOptions(options) {
5660
- return {
5661
- ...options,
5662
- choices: options.choices.map(getRadioChoicePublicData)
5822
+ /* Note(tamara): Brought over from the perseus package packages/perseus/src/util.ts file.
5823
+ May be useful to bring other perseus package utilities here. Contains utility functions
5824
+ and types used across multiple widgets for randomization and shuffling. */
5825
+ const seededRNG = function (seed) {
5826
+ let randomSeed = seed;
5827
+ return function () {
5828
+ // Robert Jenkins' 32 bit integer hash function.
5829
+ let seed = randomSeed;
5830
+ seed = seed + 0x7ed55d16 + (seed << 12) & 0xffffffff;
5831
+ seed = (seed ^ 0xc761c23c ^ seed >>> 19) & 0xffffffff;
5832
+ seed = seed + 0x165667b1 + (seed << 5) & 0xffffffff;
5833
+ seed = (seed + 0xd3a2646c ^ seed << 9) & 0xffffffff;
5834
+ seed = seed + 0xfd7046c5 + (seed << 3) & 0xffffffff;
5835
+ seed = (seed ^ 0xb55a4f09 ^ seed >>> 16) & 0xffffffff;
5836
+ return (randomSeed = seed & 0xfffffff) / 0x10000000;
5663
5837
  };
5664
- }
5665
-
5666
- function getTablePublicWidgetOptions(options) {
5667
- const {
5668
- answers: _,
5669
- ...publicOptions
5670
- } = options;
5671
- return publicOptions;
5672
- }
5673
-
5674
- function getIFramePublicWidgetOptions(options) {
5675
- return options;
5676
- }
5677
-
5678
- function getMatrixPublicWidgetOptions(options) {
5679
- const {
5680
- answers: _,
5681
- ...publicOptions
5682
- } = options;
5683
- return publicOptions;
5684
- }
5685
-
5686
- /**
5687
- * For details on the individual options, see the
5688
- * PerseusPlotterWidgetOptions type
5689
- */
5838
+ };
5690
5839
 
5691
- /**
5692
- * Given a PerseusPlotterWidgetOptions object, return a new object with only
5693
- * the public options that should be exposed to the client.
5694
- */
5695
- function getPlotterPublicWidgetOptions(options) {
5696
- const {
5697
- correct: _,
5698
- ...publicOptions
5699
- } = options;
5700
- return publicOptions;
5840
+ // Shuffle an array using a given random seed or function.
5841
+ // If `ensurePermuted` is true, the input and output are guaranteed to be
5842
+ // distinct permutations.
5843
+ function shuffle(array, randomSeed) {
5844
+ let ensurePermuted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
5845
+ // Always return a copy of the input array
5846
+ const shuffled = _.clone(array);
5847
+
5848
+ // Handle edge cases (input array is empty or uniform)
5849
+ if (!shuffled.length || _.all(shuffled, function (value) {
5850
+ return _.isEqual(value, shuffled[0]);
5851
+ })) {
5852
+ return shuffled;
5853
+ }
5854
+ let random;
5855
+ if (typeof randomSeed === "function") {
5856
+ random = randomSeed;
5857
+ } else {
5858
+ random = seededRNG(randomSeed);
5859
+ }
5860
+ do {
5861
+ // Fischer-Yates shuffle
5862
+ for (let top = shuffled.length; top > 0; top--) {
5863
+ const newEnd = Math.floor(random() * top);
5864
+ const temp = shuffled[newEnd];
5865
+
5866
+ // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
5867
+ shuffled[newEnd] = shuffled[top - 1];
5868
+ // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
5869
+ shuffled[top - 1] = temp;
5870
+ }
5871
+ } while (ensurePermuted && _.isEqual(array, shuffled));
5872
+ return shuffled;
5701
5873
  }
5874
+ const random = seededRNG(new Date().getTime() & 0xffffffff);
5702
5875
 
5703
5876
  exports.CoreWidgetRegistry = coreWidgetRegistry;
5704
5877
  exports.Errors = Errors;
@@ -5726,6 +5899,7 @@ exports.getGrapherPublicWidgetOptions = getGrapherPublicWidgetOptions;
5726
5899
  exports.getIFramePublicWidgetOptions = getIFramePublicWidgetOptions;
5727
5900
  exports.getInteractiveGraphPublicWidgetOptions = getInteractiveGraphPublicWidgetOptions;
5728
5901
  exports.getLabelImagePublicWidgetOptions = getLabelImagePublicWidgetOptions;
5902
+ exports.getMatcherPublicWidgetOptions = getMatcherPublicWidgetOptions;
5729
5903
  exports.getMatrixPublicWidgetOptions = getMatrixPublicWidgetOptions;
5730
5904
  exports.getMatrixSize = getMatrixSize;
5731
5905
  exports.getNumberLinePublicWidgetOptions = getNumberLinePublicWidgetOptions;
@@ -5773,7 +5947,12 @@ exports.plotterPlotTypes = plotterPlotTypes;
5773
5947
  exports.pluck = pluck;
5774
5948
  exports.pythonProgramLogic = pythonProgramWidgetLogic;
5775
5949
  exports.radioLogic = radioWidgetLogic;
5950
+ exports.random = random;
5951
+ exports.seededRNG = seededRNG;
5952
+ exports.shuffle = shuffle;
5953
+ exports.shuffleMatcher = shuffleMatcher;
5776
5954
  exports.sorterLogic = sorterWidgetLogic;
5955
+ exports.splitPerseusItem = splitPerseusItem;
5777
5956
  exports.tableLogic = tableWidgetLogic;
5778
5957
  exports.upgradeWidgetInfoToLatestVersion = upgradeWidgetInfoToLatestVersion;
5779
5958
  exports.videoLogic = videoWidgetLogic;