@doenet/v06-to-v07 0.7.20-dev.307 → 0.7.20-dev.309

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.
@@ -10899,6 +10899,50 @@ function answerSugar(node) {
10899
10899
  node.children = [answerElement, videoCreditMessage, callActionElement];
10900
10900
  }
10901
10901
  }
10902
+ const SCORED_SECTION_COMPONENT_TYPES = [
10903
+ "document",
10904
+ "section",
10905
+ "subsection",
10906
+ "subsubsection",
10907
+ "paragraphs",
10908
+ "aside",
10909
+ "objectives",
10910
+ "problem",
10911
+ "exercise",
10912
+ "question",
10913
+ "activity",
10914
+ "example",
10915
+ "definition",
10916
+ "note",
10917
+ "theorem",
10918
+ "part",
10919
+ "task",
10920
+ "proof",
10921
+ "problems",
10922
+ "exercises",
10923
+ "standinForFutureLayoutTag",
10924
+ "externalContent",
10925
+ "cascade",
10926
+ "div",
10927
+ "span",
10928
+ "ol",
10929
+ "ul",
10930
+ "li",
10931
+ "p"
10932
+ ];
10933
+ function renamedScoredSectionAttribute(oldName, newName) {
10934
+ const rule = {
10935
+ to: newName,
10936
+ warningMessage: `[deprecation] Attribute \`${oldName}\` is deprecated; use \`${newName}\` instead.`,
10937
+ conflictWarningMessage: `[deprecation] Attribute \`${oldName}\` is deprecated and ignored because \`${newName}\` is also specified.`
10938
+ };
10939
+ return Object.fromEntries(
10940
+ SCORED_SECTION_COMPONENT_TYPES.map((comp) => [
10941
+ comp,
10942
+ { [oldName]: rule }
10943
+ ])
10944
+ );
10945
+ }
10902
10946
  function ignoredAttributes(componentName, attributeNames) {
10903
10947
  return Object.fromEntries(
10904
10948
  attributeNames.map((attributeName) => [
@@ -10909,9 +10953,19 @@ function ignoredAttributes(componentName, attributeNames) {
10909
10953
  ])
10910
10954
  );
10911
10955
  }
10956
+ const SCORED_SECTION_COLORING_RENAMES = renamedScoredSectionAttribute(
10957
+ "forceIndividualAnswerColoring",
10958
+ "colorAnswersSeparately"
10959
+ );
10912
10960
  const DEPRECATION_REGISTRY = {
10913
10961
  attributeRenames: {
10962
+ // Merge per-component rules, spreading scored-section rename rules
10963
+ // first so component-specific rules take precedence on conflict.
10964
+ ...SCORED_SECTION_COLORING_RENAMES,
10914
10965
  document: {
10966
+ // document already has a scored-section rename (spread above) plus
10967
+ // its own documentWideCheckWork rename.
10968
+ ...SCORED_SECTION_COLORING_RENAMES["document"],
10915
10969
  documentWideCheckWork: {
10916
10970
  to: "sectionWideCheckWork",
10917
10971
  warningMessage: "[deprecation] Attribute `documentWideCheckWork` on `<document>` is deprecated; use `sectionWideCheckWork` instead.",
@@ -40909,7 +40963,7 @@ async function cidFromArrayBuffer(data) {
40909
40963
  await crypto.subtle.digest("SHA-256", new Uint8Array());
40910
40964
  digest = (data2) => crypto.subtle.digest("SHA-256", data2);
40911
40965
  } catch (e22) {
40912
- const sha256 = (await import("./sha256-C0vj3HDn-ILc8kzpi-tZRzzwtP.js").then((n2) => n2.s)).default;
40966
+ const sha256 = (await import("./sha256-C0vj3HDn-Dy8iD4h--1Hj5Gcpr.js").then((n2) => n2.s)).default;
40913
40967
  digest = (data2) => sha256(data2, {
40914
40968
  asBytes: true
40915
40969
  });
@@ -49562,6 +49616,54 @@ const PRIMITIVE_TO_COMPONENT_TYPE = {
49562
49616
  stringArray: "textList",
49563
49617
  numberArray: "numberList"
49564
49618
  };
49619
+ const SHARED_STATE_VARIABLE_DEFINITIONS = /* @__PURE__ */ Symbol(
49620
+ "sharedStateVariableDefinitions"
49621
+ );
49622
+ const classStateVariableDefinitionsCache = /* @__PURE__ */ new WeakMap();
49623
+ function getClassStateVariableDefinitions(core2, componentClass) {
49624
+ let perCore = classStateVariableDefinitionsCache.get(core2);
49625
+ if (!perCore) {
49626
+ perCore = /* @__PURE__ */ new Map();
49627
+ classStateVariableDefinitionsCache.set(core2, perCore);
49628
+ }
49629
+ let entry = perCore.get(componentClass);
49630
+ if (!entry) {
49631
+ const combined = {};
49632
+ createAttributeStateVariableDefinitions({
49633
+ core: core2,
49634
+ stateVariableDefinitions: combined,
49635
+ componentClass
49636
+ });
49637
+ const normalized = componentClass.returnNormalizedStateVariableDefinitions(
49638
+ core2.numerics
49639
+ );
49640
+ Object.assign(combined, normalized);
49641
+ combined[SHARED_STATE_VARIABLE_DEFINITIONS] = true;
49642
+ entry = { combined, normalized };
49643
+ perCore.set(componentClass, entry);
49644
+ }
49645
+ return entry;
49646
+ }
49647
+ function cloneStateVariableDefinition(def) {
49648
+ const clone2 = Object.assign({}, def);
49649
+ if (clone2.shadowingInstructions) {
49650
+ clone2.shadowingInstructions = Object.assign(
49651
+ {},
49652
+ clone2.shadowingInstructions
49653
+ );
49654
+ }
49655
+ if (clone2.additionalStateVariablesDefined) {
49656
+ clone2.additionalStateVariablesDefined = [
49657
+ ...clone2.additionalStateVariablesDefined
49658
+ ];
49659
+ }
49660
+ if (clone2.stateVariablesDeterminingDependencies) {
49661
+ clone2.stateVariablesDeterminingDependencies = [
49662
+ ...clone2.stateVariablesDeterminingDependencies
49663
+ ];
49664
+ }
49665
+ return clone2;
49666
+ }
49565
49667
  async function createStateVariableDefinitions({
49566
49668
  core: core2,
49567
49669
  componentClass,
@@ -49605,32 +49707,33 @@ async function createStateVariableDefinitions({
49605
49707
  }
49606
49708
  }
49607
49709
  }
49608
- let stateVariableDefinitions = {};
49710
+ const classDefinitions = getClassStateVariableDefinitions(
49711
+ core2,
49712
+ componentClass
49713
+ );
49609
49714
  if (!redefineDependencies) {
49610
- createAttributeStateVariableDefinitions({
49715
+ return classDefinitions.combined;
49716
+ }
49717
+ let stateVariableDefinitions = {};
49718
+ for (const varName in classDefinitions.normalized) {
49719
+ stateVariableDefinitions[varName] = cloneStateVariableDefinition(
49720
+ classDefinitions.normalized[varName]
49721
+ );
49722
+ }
49723
+ if (redefineDependencies.linkSource === "adapter") {
49724
+ createAdapterStateVariableDefinitions({
49611
49725
  core: core2,
49726
+ redefineDependencies,
49727
+ stateVariableDefinitions,
49728
+ componentClass
49729
+ });
49730
+ } else {
49731
+ await createReferenceShadowStateVariableDefinitions({
49732
+ core: core2,
49733
+ redefineDependencies,
49612
49734
  stateVariableDefinitions,
49613
49735
  componentClass
49614
49736
  });
49615
- }
49616
- let newDefinitions = componentClass.returnNormalizedStateVariableDefinitions(core2.numerics);
49617
- Object.assign(stateVariableDefinitions, newDefinitions);
49618
- if (redefineDependencies) {
49619
- if (redefineDependencies.linkSource === "adapter") {
49620
- createAdapterStateVariableDefinitions({
49621
- core: core2,
49622
- redefineDependencies,
49623
- stateVariableDefinitions,
49624
- componentClass
49625
- });
49626
- } else {
49627
- await createReferenceShadowStateVariableDefinitions({
49628
- core: core2,
49629
- redefineDependencies,
49630
- stateVariableDefinitions,
49631
- componentClass
49632
- });
49633
- }
49634
49737
  }
49635
49738
  return stateVariableDefinitions;
49636
49739
  }
@@ -52957,6 +53060,7 @@ function cloneChangeMetadataIfNeeded({
52957
53060
  }) {
52958
53061
  return consumeChanges ? changeMetadata : deepClone(changeMetadata);
52959
53062
  }
53063
+ const INITIAL_CHANGE_RECORD = Object.freeze({ changed: true });
52960
53064
  const _Dependency = class _Dependency2 {
52961
53065
  constructor({
52962
53066
  component,
@@ -52971,7 +53075,7 @@ const _Dependency = class _Dependency2 {
52971
53075
  this.dependencyHandler = dependencyHandler;
52972
53076
  this.upstreamComponentIdx = component.componentIdx;
52973
53077
  this.upstreamVariableNames = allStateVariablesAffected;
52974
- this.definition = Object.assign({}, dependencyDefinition);
53078
+ this.definition = dependencyDefinition;
52975
53079
  this.representativeStateVariable = stateVariable;
52976
53080
  if (dependencyDefinition.doNotProxy) {
52977
53081
  this.doNotProxy = true;
@@ -53127,6 +53231,9 @@ const _Dependency = class _Dependency2 {
53127
53231
  }
53128
53232
  let downVarNames = mappedVarNames;
53129
53233
  if (originalVarNames.length > 0 || this.originalVariablesByComponent) {
53234
+ mappedVarNames = this.dependencyHandler.internVariableNameList(
53235
+ mappedVarNames
53236
+ );
53130
53237
  this.mappedDownstreamVariableNamesByComponent.splice(
53131
53238
  index2,
53132
53239
  0,
@@ -53134,7 +53241,7 @@ const _Dependency = class _Dependency2 {
53134
53241
  );
53135
53242
  let valsChanged = {};
53136
53243
  for (let downVar of mappedVarNames) {
53137
- valsChanged[downVar] = { changed: true };
53244
+ valsChanged[downVar] = INITIAL_CHANGE_RECORD;
53138
53245
  }
53139
53246
  this.valuesChanged.splice(index2, 0, valsChanged);
53140
53247
  if (this.variablesOptional) {
@@ -53234,9 +53341,10 @@ const _Dependency = class _Dependency2 {
53234
53341
  );
53235
53342
  this.valuesChanged.splice(indexToRemove, 1);
53236
53343
  if (this.variablesOptional) {
53237
- affectedDownstreamVariableNames.push(
53344
+ affectedDownstreamVariableNames = [
53345
+ ...affectedDownstreamVariableNames,
53238
53346
  this.downstreamVariableNameIfNoVariables
53239
- );
53347
+ ];
53240
53348
  }
53241
53349
  }
53242
53350
  for (let vName of affectedDownstreamVariableNames) {
@@ -53457,7 +53565,7 @@ const _Dependency = class _Dependency2 {
53457
53565
  if (!mappedStateVarObj.deferred) {
53458
53566
  componentObj.stateValues[nameForOutput] = await mappedStateVarObj.value;
53459
53567
  let valueChanged = this.valuesChanged[componentInd][mappedVarName];
53460
- if (valueChanged.changed) {
53568
+ if (valueChanged?.changed) {
53461
53569
  if (!changes.valuesChanged) {
53462
53570
  changes.valuesChanged = {};
53463
53571
  }
@@ -53470,7 +53578,7 @@ const _Dependency = class _Dependency2 {
53470
53578
  });
53471
53579
  }
53472
53580
  if (consumeChanges) {
53473
- this.valuesChanged[componentInd][mappedVarName] = {};
53581
+ delete this.valuesChanged[componentInd][mappedVarName];
53474
53582
  }
53475
53583
  if (mappedStateVarObj.usedDefault) {
53476
53584
  usedDefaultObj[nameForOutput] = true;
@@ -54039,7 +54147,7 @@ const _StateVariableComponentTypeDependency = class _StateVariableComponentTypeD
54039
54147
  }
54040
54148
  }
54041
54149
  let valueChanged0 = this.valuesChanged[0][mappedVarName];
54042
- if (valueChanged0.changed) {
54150
+ if (valueChanged0?.changed) {
54043
54151
  if (!changes.valuesChanged) {
54044
54152
  changes.valuesChanged = {};
54045
54153
  }
@@ -54052,7 +54160,7 @@ const _StateVariableComponentTypeDependency = class _StateVariableComponentTypeD
54052
54160
  });
54053
54161
  }
54054
54162
  if (consumeChanges) {
54055
- this.valuesChanged[0][mappedVarName] = {};
54163
+ delete this.valuesChanged[0][mappedVarName];
54056
54164
  }
54057
54165
  let hasVariableComponentType = stateVarObj.shadowingInstructions?.hasVariableComponentType;
54058
54166
  if (!hasVariableComponentType && stateVarObj.isArrayEntry) {
@@ -57252,6 +57360,30 @@ const _UnlinkedCopySourceDependency = class _UnlinkedCopySourceDependency2 exten
57252
57360
  };
57253
57361
  _UnlinkedCopySourceDependency.dependencyType = "unlinkedCopySource";
57254
57362
  let UnlinkedCopySourceDependency = _UnlinkedCopySourceDependency;
57363
+ const _ShadowInfoDependency = class _ShadowInfoDependency2 extends Dependency {
57364
+ setUpParameters() {
57365
+ if (this.definition.componentIdx != void 0) {
57366
+ this.componentIdx = this.definition.componentIdx;
57367
+ } else {
57368
+ this.componentIdx = this.upstreamComponentIdx;
57369
+ }
57370
+ }
57371
+ async getValue() {
57372
+ const component = this.dependencyHandler._components[this.componentIdx];
57373
+ if (!component?.shadows) {
57374
+ return { value: null, changes: {} };
57375
+ }
57376
+ return {
57377
+ value: {
57378
+ componentIdx: component.shadows.componentIdx,
57379
+ propVariable: component.shadows.propVariable ?? null
57380
+ },
57381
+ changes: {}
57382
+ };
57383
+ }
57384
+ };
57385
+ _ShadowInfoDependency.dependencyType = "shadowInfo";
57386
+ let ShadowInfoDependency = _ShadowInfoDependency;
57255
57387
  const _PrimaryShadowDependency = class _PrimaryShadowDependency2 extends Dependency {
57256
57388
  setUpParameters() {
57257
57389
  if (this.definition.componentIdx != void 0) {
@@ -58400,6 +58532,7 @@ const dependencyTypeClasses = [
58400
58532
  ShadowSourceDependency,
58401
58533
  UnlinkedCopySourceDependency,
58402
58534
  PrimaryShadowDependency,
58535
+ ShadowInfoDependency,
58403
58536
  AdapterSourceStateVariableDependency,
58404
58537
  AdapterSourceDependency,
58405
58538
  CountAmongSiblingsDependency,
@@ -58416,6 +58549,7 @@ const dependencyTypeClasses = [
58416
58549
  DetermineDependenciesDependency,
58417
58550
  FileDependency
58418
58551
  ];
58552
+ const EMPTY_BLOCKERS = Object.freeze({});
58419
58553
  class DependencyHandler {
58420
58554
  constructor({
58421
58555
  _components,
@@ -58450,6 +58584,16 @@ class DependencyHandler {
58450
58584
  resolveBlockedBy: {}
58451
58585
  };
58452
58586
  this.attributeRefResolutionDependenciesByReferenced = {};
58587
+ this._internedVariableNameLists = /* @__PURE__ */ new Map();
58588
+ }
58589
+ internVariableNameList(names) {
58590
+ const key = names.join("\n");
58591
+ let interned = this._internedVariableNameLists.get(key);
58592
+ if (!interned) {
58593
+ interned = Object.freeze(names);
58594
+ this._internedVariableNameLists.set(key, interned);
58595
+ }
58596
+ return interned;
58453
58597
  }
58454
58598
  async setUpComponentDependencies(component) {
58455
58599
  if (this.downstreamDependencies[component.componentIdx]) {
@@ -59165,26 +59309,11 @@ class DependencyHandler {
59165
59309
  let ind = upDep.downstreamComponentIndices.indexOf(componentIdx);
59166
59310
  let upValuesChanged = upDep.valuesChanged[ind][varName];
59167
59311
  if (!upValuesChanged) {
59168
- if (component.stateVarAliases) {
59169
- for (let alias in component.stateVarAliases) {
59170
- if (component.stateVarAliases[alias] === varName && // @ts-expect-error see "Note (dated July 20, 2023)" above:
59171
- // `upValuesChangedSub` is undefined; keeping the
59172
- // reference verbatim so behavior matches the JS source.
59173
- alias in upValuesChangedSub) {
59174
- upValuesChanged = // @ts-expect-error same as above
59175
- upValuesChangedSub[alias];
59176
- }
59177
- }
59178
- }
59179
- }
59180
- if (!upValuesChanged) {
59181
- if (!component.state[varName].isArrayEntry) {
59182
- throw Error(
59183
- `Something is wrong, as a variable ${varName} of ${component.componentIdx} actually changed, but wasn't marked with a potential change`
59184
- );
59185
- }
59186
- upValuesChanged = // @ts-expect-error same as above
59187
- upValuesChangedSub[varName] = { changed: {} };
59312
+ upValuesChanged = upDep.valuesChanged[ind][varName] = {};
59313
+ } else if (Object.isFrozen(upValuesChanged)) {
59314
+ upValuesChanged = upDep.valuesChanged[ind][varName] = {
59315
+ changed: upValuesChanged.changed
59316
+ };
59188
59317
  }
59189
59318
  if (component.state[varName] && component.state[varName].isArray) {
59190
59319
  if (upValuesChanged.changed === void 0) {
@@ -59302,6 +59431,45 @@ class DependencyHandler {
59302
59431
  finishedPropagation: parentResult.finishedPropagation
59303
59432
  };
59304
59433
  }
59434
+ /**
59435
+ * Non-creating variant of `getNeededToResolve`: returns the nested entry
59436
+ * if it exists, else `EMPTY_BLOCKERS`, without materializing intermediate
59437
+ * levels. `getNeededToResolve` creates the whole nested chain on every
59438
+ * lookup, and read-only callers used to leave tens of thousands of empty
59439
+ * `{cIdx: {type: {stateVariable: {}}}}` chains behind — the bulk of
59440
+ * `resolveBlockers`' retained memory.
59441
+ */
59442
+ peekNeededToResolve({
59443
+ componentIdx,
59444
+ type,
59445
+ stateVariable,
59446
+ dependency
59447
+ }) {
59448
+ let neededToResolve = this.resolveBlockers.neededToResolve[componentIdx]?.[type];
59449
+ if (neededToResolve && stateVariable) {
59450
+ neededToResolve = neededToResolve[stateVariable];
59451
+ if (neededToResolve && dependency) {
59452
+ neededToResolve = neededToResolve[dependency];
59453
+ }
59454
+ }
59455
+ return neededToResolve ?? EMPTY_BLOCKERS;
59456
+ }
59457
+ /** Non-creating variant of `getResolveBlockedBy`; see `peekNeededToResolve`. */
59458
+ peekResolveBlockedBy({
59459
+ componentIdx,
59460
+ type,
59461
+ stateVariable,
59462
+ dependency
59463
+ }) {
59464
+ let resolveBlockedBy = this.resolveBlockers.resolveBlockedBy[componentIdx]?.[type];
59465
+ if (resolveBlockedBy && stateVariable) {
59466
+ resolveBlockedBy = resolveBlockedBy[stateVariable];
59467
+ if (resolveBlockedBy && dependency) {
59468
+ resolveBlockedBy = resolveBlockedBy[dependency];
59469
+ }
59470
+ }
59471
+ return resolveBlockedBy ?? EMPTY_BLOCKERS;
59472
+ }
59305
59473
  getNeededToResolve({ componentIdx, type, stateVariable, dependency }) {
59306
59474
  let neededToResolveForComponent = this.resolveBlockers.neededToResolve[componentIdx];
59307
59475
  if (!neededToResolveForComponent) {
@@ -59811,7 +59979,7 @@ class DependencyHandler {
59811
59979
  } catch (e32) {
59812
59980
  }
59813
59981
  if (dep) {
59814
- let neededForItem = this.getNeededToResolve({
59982
+ let neededForItem = this.peekNeededToResolve({
59815
59983
  componentIdx: componentIdxNewlyResolved,
59816
59984
  type: "stateVariable",
59817
59985
  stateVariable: stateVariableNewlyResolved
@@ -59902,7 +60070,7 @@ class DependencyHandler {
59902
60070
  );
59903
60071
  }
59904
60072
  }
59905
- let resolveBlockedByNewlyResolved = this.getResolveBlockedBy({
60073
+ let resolveBlockedByNewlyResolved = this.peekResolveBlockedBy({
59906
60074
  componentIdx: componentIdxNewlyResolved,
59907
60075
  type: typeNewlyResolved,
59908
60076
  stateVariable: stateVariableNewlyResolved,
@@ -60004,7 +60172,7 @@ class DependencyHandler {
60004
60172
  expandComposites = true,
60005
60173
  numPreviouslyNeeded
60006
60174
  }) {
60007
- let neededForItem = this.getNeededToResolve({
60175
+ let neededForItem = this.peekNeededToResolve({
60008
60176
  componentIdx,
60009
60177
  type,
60010
60178
  stateVariable,
@@ -60046,7 +60214,7 @@ class DependencyHandler {
60046
60214
  break;
60047
60215
  }
60048
60216
  if (nFailures > 0) {
60049
- neededForItem = this.getNeededToResolve({
60217
+ neededForItem = this.peekNeededToResolve({
60050
60218
  componentIdx,
60051
60219
  type,
60052
60220
  stateVariable,
@@ -60086,7 +60254,7 @@ class DependencyHandler {
60086
60254
  }
60087
60255
  }
60088
60256
  if (nFailures > 0) {
60089
- neededForItem = this.getNeededToResolve({
60257
+ neededForItem = this.peekNeededToResolve({
60090
60258
  componentIdx,
60091
60259
  type,
60092
60260
  stateVariable,
@@ -60134,7 +60302,7 @@ class DependencyHandler {
60134
60302
  expandComposites
60135
60303
  });
60136
60304
  if (!finalResult.success) {
60137
- let stillNeededForItem = this.getNeededToResolve({
60305
+ let stillNeededForItem = this.peekNeededToResolve({
60138
60306
  componentIdx,
60139
60307
  type,
60140
60308
  stateVariable,
@@ -60186,7 +60354,7 @@ class DependencyHandler {
60186
60354
  }
60187
60355
  if (!this.circularResolveBlockedCheckPassed[identifier]) {
60188
60356
  this.circularResolveBlockedCheckPassed[identifier] = true;
60189
- let neededForItem = this.getNeededToResolve({
60357
+ let neededForItem = this.peekNeededToResolve({
60190
60358
  componentIdx,
60191
60359
  type,
60192
60360
  stateVariable,
@@ -60301,7 +60469,7 @@ class DependencyHandler {
60301
60469
  let identifier = code + "|" + type;
60302
60470
  if (this.circularResolveBlockedCheckPassed[identifier]) {
60303
60471
  delete this.circularResolveBlockedCheckPassed[identifier];
60304
- let resolveBlockedBy = this.getResolveBlockedBy({
60472
+ let resolveBlockedBy = this.peekResolveBlockedBy({
60305
60473
  componentIdx,
60306
60474
  type,
60307
60475
  stateVariable,
@@ -63755,12 +63923,13 @@ class StalenessPropagator {
63755
63923
  if (!upDep.valuesChanged[componentInd]) {
63756
63924
  upDep.valuesChanged[componentInd] = {};
63757
63925
  }
63758
- if (!upDep.valuesChanged[componentInd][varName]) {
63759
- upDep.valuesChanged[componentInd][varName] = {};
63926
+ let changeRecord = upDep.valuesChanged[componentInd][varName];
63927
+ if (!changeRecord || Object.isFrozen(changeRecord)) {
63928
+ changeRecord = upDep.valuesChanged[componentInd][varName] = changeRecord ? { changed: changeRecord.changed } : {};
63760
63929
  }
63761
- upDep.valuesChanged[componentInd][varName].potentialChange = true;
63930
+ changeRecord.potentialChange = true;
63762
63931
  if (freshnessInfo) {
63763
- upDep.valuesChanged[componentInd][varName].freshnessInfo = freshnessInfo;
63932
+ changeRecord.freshnessInfo = freshnessInfo;
63764
63933
  }
63765
63934
  foundVarChange = true;
63766
63935
  } else if (varName === upDep.downstreamVariableNameIfNoVariables) {
@@ -68386,11 +68555,52 @@ class BaseComponent {
68386
68555
  this.refResolution = refResolution;
68387
68556
  }
68388
68557
  this.state = {};
68389
- for (let stateVariable in stateVariableDefinitions) {
68390
- this.state[stateVariable] = Object.assign(
68391
- {},
68392
- stateVariableDefinitions[stateVariable]
68393
- );
68558
+ if (stateVariableDefinitions[SHARED_STATE_VARIABLE_DEFINITIONS]) {
68559
+ for (let stateVariable in stateVariableDefinitions) {
68560
+ let def = Object.create(
68561
+ stateVariableDefinitions[stateVariable]
68562
+ );
68563
+ if (def.shadowingInstructions) {
68564
+ def.shadowingInstructions = Object.assign(
68565
+ {},
68566
+ def.shadowingInstructions
68567
+ );
68568
+ }
68569
+ if (def.additionalStateVariablesDefined) {
68570
+ def.additionalStateVariablesDefined = [
68571
+ ...def.additionalStateVariablesDefined
68572
+ ];
68573
+ }
68574
+ if (def.stateVariablesDeterminingDependencies) {
68575
+ def.stateVariablesDeterminingDependencies = [
68576
+ ...def.stateVariablesDeterminingDependencies
68577
+ ];
68578
+ }
68579
+ this.state[stateVariable] = def;
68580
+ }
68581
+ } else {
68582
+ for (let stateVariable in stateVariableDefinitions) {
68583
+ this.state[stateVariable] = stateVariableDefinitions[stateVariable];
68584
+ }
68585
+ }
68586
+ let workspaceAssigned = /* @__PURE__ */ new Set();
68587
+ for (let stateVariable in this.state) {
68588
+ let def = this.state[stateVariable];
68589
+ if (!def.createWorkspace || workspaceAssigned.has(stateVariable)) {
68590
+ continue;
68591
+ }
68592
+ let workspace = {};
68593
+ def.workspace = workspace;
68594
+ workspaceAssigned.add(stateVariable);
68595
+ if (def.additionalStateVariablesDefined) {
68596
+ for (let otherVar of def.additionalStateVariablesDefined) {
68597
+ let otherDef = this.state[otherVar];
68598
+ if (otherDef?.createWorkspace) {
68599
+ otherDef.workspace = workspace;
68600
+ workspaceAssigned.add(otherVar);
68601
+ }
68602
+ }
68603
+ }
68394
68604
  }
68395
68605
  this.stateValues = new Proxy(this.state, createStateProxyHandler());
68396
68606
  this.essentialState = {};
@@ -74964,12 +75174,12 @@ function returnScoredSectionAttributes() {
74964
75174
  groupName: "scoring",
74965
75175
  description: "Whether to color-code the answers it contains based on correctness."
74966
75176
  },
74967
- forceIndividualAnswerColoring: {
75177
+ colorAnswersSeparately: {
74968
75178
  createComponentOfType: "boolean",
74969
- createStateVariable: "forceIndividualAnswerColoring",
75179
+ createStateVariable: "colorAnswersSeparately",
74970
75180
  defaultValue: false,
74971
75181
  groupName: "scoring",
74972
- description: "Whether to force per-answer color-correctness even when section-wide check work is enabled."
75182
+ description: "When section-wide check work is enabled, color each answer based on its own correctness rather than the section's overall credit."
74973
75183
  },
74974
75184
  submitLabel: {
74975
75185
  createComponentOfType: "text",
@@ -75415,9 +75625,9 @@ function returnScoredSectionStateVariableDefinition() {
75415
75625
  dependencyType: "stateVariable",
75416
75626
  variableName: "sectionWideCheckWork"
75417
75627
  },
75418
- forceIndividualAnswerColoring: {
75628
+ colorAnswersSeparately: {
75419
75629
  dependencyType: "stateVariable",
75420
- variableName: "forceIndividualAnswerColoring"
75630
+ variableName: "colorAnswersSeparately"
75421
75631
  },
75422
75632
  ancestorDeterminingSubmit: {
75423
75633
  dependencyType: "ancestor",
@@ -75437,7 +75647,7 @@ function returnScoredSectionStateVariableDefinition() {
75437
75647
  } else if (dependencyValues.sectionWideCheckWork) {
75438
75648
  createSubmitAllButton = true;
75439
75649
  suppressAnswerSubmitButtons = true;
75440
- if (!dependencyValues.forceIndividualAnswerColoring) {
75650
+ if (!dependencyValues.colorAnswersSeparately) {
75441
75651
  descendantColorCorrectnessBasedOnIdx = componentIdx;
75442
75652
  }
75443
75653
  }
@@ -111064,7 +111274,8 @@ class Input extends InlineComponent {
111064
111274
  "nextCreditFactor",
111065
111275
  "forceFullCheckWorkButton",
111066
111276
  "forceSmallCheckWorkButton",
111067
- "labelsForAnswer"
111277
+ "labelsForAnswer",
111278
+ "colorInputsSeparately"
111068
111279
  ]
111069
111280
  }
111070
111281
  }),
@@ -111151,7 +111362,8 @@ class Input extends InlineComponent {
111151
111362
  "justSubmitted",
111152
111363
  "creditAchieved",
111153
111364
  "showCorrectness",
111154
- "colorCorrectness"
111365
+ "colorCorrectness",
111366
+ "colorInputsSeparately"
111155
111367
  ],
111156
111368
  variablesOptional: true
111157
111369
  };
@@ -111236,18 +111448,63 @@ class Input extends InlineComponent {
111236
111448
  return { setValue: { colorCorrectness } };
111237
111449
  }
111238
111450
  };
111451
+ const variableForImplicitProp = this.variableForImplicitProp ?? "value";
111239
111452
  stateVariableDefinitions.creditAchieved = {
111240
111453
  forRenderer: true,
111241
- returnDependencies: () => ({
111242
- componentDeterminingDisplayedCorrectness: {
111243
- dependencyType: "stateVariable",
111244
- variableName: "componentDeterminingDisplayedCorrectness"
111454
+ stateVariablesDeterminingDependencies: [
111455
+ "answerAncestor",
111456
+ "answerSpecifiedInForAnswer"
111457
+ ],
111458
+ returnDependencies({ stateValues }) {
111459
+ const deps = {
111460
+ componentDeterminingDisplayedCorrectness: {
111461
+ dependencyType: "stateVariable",
111462
+ variableName: "componentDeterminingDisplayedCorrectness"
111463
+ }
111464
+ };
111465
+ if (stateValues.answerAncestor?.stateValues.colorInputsSeparately) {
111466
+ deps.answerCreditAchievedPerInput = {
111467
+ dependencyType: "ancestor",
111468
+ componentType: "answer",
111469
+ variableNames: ["creditAchievedPerInput"]
111470
+ };
111471
+ } else if (stateValues.answerSpecifiedInForAnswer !== null) {
111472
+ deps.answerColoringState = {
111473
+ dependencyType: "multipleStateVariables",
111474
+ componentIdx: stateValues.answerSpecifiedInForAnswer,
111475
+ variableNames: [
111476
+ "colorInputsSeparately",
111477
+ "creditAchievedPerInput"
111478
+ ],
111479
+ variablesOptional: true
111480
+ };
111245
111481
  }
111246
- }),
111247
- definition: function({ dependencyValues }) {
111482
+ return deps;
111483
+ },
111484
+ definition: function({ dependencyValues, componentIdx }) {
111248
111485
  let creditAchieved = 0;
111249
- if (dependencyValues.componentDeterminingDisplayedCorrectness) {
111250
- creditAchieved = dependencyValues.componentDeterminingDisplayedCorrectness.stateValues.creditAchieved;
111486
+ const comp = dependencyValues.componentDeterminingDisplayedCorrectness;
111487
+ if (comp) {
111488
+ const overallCredit = comp.stateValues.creditAchieved ?? 0;
111489
+ const creditAchievedPerInput = dependencyValues.answerCreditAchievedPerInput?.stateValues.creditAchievedPerInput ?? (dependencyValues.answerColoringState?.stateValues?.colorInputsSeparately ? dependencyValues.answerColoringState.stateValues.creditAchievedPerInput : void 0);
111490
+ if (comp.stateValues.colorInputsSeparately && creditAchievedPerInput) {
111491
+ const key = `${componentIdx}/${variableForImplicitProp}`;
111492
+ let perInputCredit = creditAchievedPerInput[key];
111493
+ if (perInputCredit === void 0 && variableForImplicitProp !== "value") {
111494
+ const keyPrefix = `${componentIdx}/`;
111495
+ const candidateCredits = Object.entries(
111496
+ creditAchievedPerInput
111497
+ ).filter(
111498
+ ([entryKey]) => entryKey.startsWith(keyPrefix)
111499
+ ).map(([, credit]) => credit);
111500
+ if (candidateCredits.length > 0) {
111501
+ perInputCredit = Math.max(...candidateCredits);
111502
+ }
111503
+ }
111504
+ creditAchieved = perInputCredit !== void 0 ? perInputCredit : overallCredit;
111505
+ } else {
111506
+ creditAchieved = overallCredit;
111507
+ }
111251
111508
  }
111252
111509
  return {
111253
111510
  setValue: { creditAchieved }
@@ -115698,6 +115955,88 @@ class FractionInput extends Input {
115698
115955
  }
115699
115956
  })
115700
115957
  };
115958
+ stateVariableDefinitions.componentIdx = {
115959
+ returnDependencies: () => ({}),
115960
+ definition({ componentIdx }) {
115961
+ return { setValue: { componentIdx } };
115962
+ }
115963
+ };
115964
+ stateVariableDefinitions.colorInputsSeparately = {
115965
+ stateVariablesDeterminingDependencies: [
115966
+ "answerSpecifiedInForAnswer"
115967
+ ],
115968
+ returnDependencies({ stateValues }) {
115969
+ const deps = {
115970
+ answerAncestor: {
115971
+ dependencyType: "stateVariable",
115972
+ variableName: "answerAncestor"
115973
+ }
115974
+ };
115975
+ if (stateValues.answerSpecifiedInForAnswer !== null) {
115976
+ deps.forAnswerColorInputsSeparately = {
115977
+ dependencyType: "stateVariable",
115978
+ componentIdx: stateValues.answerSpecifiedInForAnswer,
115979
+ variableName: "colorInputsSeparately",
115980
+ variablesOptional: true
115981
+ };
115982
+ }
115983
+ return deps;
115984
+ },
115985
+ definition({ dependencyValues }) {
115986
+ if (dependencyValues.answerAncestor) {
115987
+ return {
115988
+ setValue: {
115989
+ colorInputsSeparately: dependencyValues.answerAncestor.stateValues.colorInputsSeparately ?? false
115990
+ }
115991
+ };
115992
+ }
115993
+ return {
115994
+ setValue: {
115995
+ colorInputsSeparately: dependencyValues.forAnswerColorInputsSeparately ?? false
115996
+ }
115997
+ };
115998
+ }
115999
+ };
116000
+ stateVariableDefinitions.creditAchievedPerInput = {
116001
+ stateVariablesDeterminingDependencies: [
116002
+ "colorInputsSeparately",
116003
+ "answerAncestor",
116004
+ "answerSpecifiedInForAnswer"
116005
+ ],
116006
+ returnDependencies({ stateValues }) {
116007
+ if (!stateValues.colorInputsSeparately) {
116008
+ return {};
116009
+ }
116010
+ if (stateValues.answerAncestor) {
116011
+ return {
116012
+ answerCreditAchievedPerInput: {
116013
+ dependencyType: "ancestor",
116014
+ componentType: "answer",
116015
+ variableNames: ["creditAchievedPerInput"]
116016
+ }
116017
+ };
116018
+ }
116019
+ if (stateValues.answerSpecifiedInForAnswer !== null) {
116020
+ return {
116021
+ answerCreditAchievedPerInput: {
116022
+ dependencyType: "stateVariable",
116023
+ componentIdx: stateValues.answerSpecifiedInForAnswer,
116024
+ variableName: "creditAchievedPerInput",
116025
+ returnAsComponentObject: true,
116026
+ variablesOptional: true
116027
+ }
116028
+ };
116029
+ }
116030
+ return {};
116031
+ },
116032
+ definition({ dependencyValues }) {
116033
+ return {
116034
+ setValue: {
116035
+ creditAchievedPerInput: dependencyValues.answerCreditAchievedPerInput?.stateValues?.creditAchievedPerInput ?? {}
116036
+ }
116037
+ };
116038
+ }
116039
+ };
115701
116040
  return stateVariableDefinitions;
115702
116041
  }
115703
116042
  static adapters = [
@@ -115834,18 +116173,49 @@ class FractionComponentInput extends BaseComponent {
115834
116173
  };
115835
116174
  stateVariableDefinitions.creditAchieved = {
115836
116175
  forRenderer: true,
115837
- returnDependencies: () => ({
115838
- parentCreditAchieved: {
116176
+ stateVariablesDeterminingDependencies: ["part"],
116177
+ returnDependencies({ stateValues }) {
116178
+ const deps = {
116179
+ parentCreditAchieved: {
116180
+ dependencyType: "parentStateVariable",
116181
+ parentComponentType: "fractionInput",
116182
+ variableName: "creditAchieved"
116183
+ },
116184
+ parentColorInputsSeparately: {
116185
+ dependencyType: "parentStateVariable",
116186
+ parentComponentType: "fractionInput",
116187
+ variableName: "colorInputsSeparately"
116188
+ }
116189
+ };
116190
+ deps.parentCreditAchievedPerInput = {
115839
116191
  dependencyType: "parentStateVariable",
115840
116192
  parentComponentType: "fractionInput",
115841
- variableName: "creditAchieved"
115842
- }
115843
- }),
116193
+ variableName: "creditAchievedPerInput"
116194
+ };
116195
+ deps.parentComponentIdx = {
116196
+ dependencyType: "parentStateVariable",
116197
+ parentComponentType: "fractionInput",
116198
+ variableName: "componentIdx"
116199
+ };
116200
+ deps.part = {
116201
+ dependencyType: "stateVariable",
116202
+ variableName: "part"
116203
+ };
116204
+ return deps;
116205
+ },
115844
116206
  definition({ dependencyValues }) {
116207
+ const fallback = dependencyValues.parentCreditAchieved ?? 0;
116208
+ if (dependencyValues.parentColorInputsSeparately && dependencyValues.parentCreditAchievedPerInput && dependencyValues.parentComponentIdx !== void 0 && dependencyValues.part) {
116209
+ const key = `${dependencyValues.parentComponentIdx}/${dependencyValues.part}`;
116210
+ const perPartCredit = dependencyValues.parentCreditAchievedPerInput[key];
116211
+ return {
116212
+ setValue: {
116213
+ creditAchieved: perPartCredit !== void 0 ? perPartCredit : fallback
116214
+ }
116215
+ };
116216
+ }
115845
116217
  return {
115846
- setValue: {
115847
- creditAchieved: dependencyValues.parentCreditAchieved ?? 0
115848
- }
116218
+ setValue: { creditAchieved: fallback }
115849
116219
  };
115850
116220
  }
115851
116221
  };
@@ -135761,6 +136131,13 @@ class Answer extends InlineComponent {
135761
136131
  public: true,
135762
136132
  description: "Maximum number of matching awards whose credits are summed."
135763
136133
  };
136134
+ attributes.colorInputsSeparately = {
136135
+ createComponentOfType: "boolean",
136136
+ createStateVariable: "colorInputsSeparately",
136137
+ defaultValue: false,
136138
+ public: true,
136139
+ description: "Attempt to color each input separately based on the awards that reference it, rather than all inputs sharing the same overall credit color."
136140
+ };
135764
136141
  attributes.allowedErrorInNumbers = {
135765
136142
  createComponentOfType: "number",
135766
136143
  createStateVariable: "allowedErrorInNumbers",
@@ -136584,6 +136961,35 @@ class Answer extends InlineComponent {
136584
136961
  return { setValue: { inputChildWithValues } };
136585
136962
  }
136586
136963
  };
136964
+ stateVariableDefinitions.allInputComponentIdxs = {
136965
+ stateVariablesDeterminingDependencies: [
136966
+ "inputChildRelativeIndices"
136967
+ ],
136968
+ returnDependencies: ({ stateValues }) => ({
136969
+ inputChildren: {
136970
+ dependencyType: "child",
136971
+ childGroups: ["inputs"],
136972
+ childIndices: stateValues.inputChildRelativeIndices
136973
+ },
136974
+ inputsForAnswer: {
136975
+ dependencyType: "stateVariable",
136976
+ variableName: "inputsForAnswer"
136977
+ }
136978
+ }),
136979
+ definition({ dependencyValues }) {
136980
+ const allInputComponentIdxs = /* @__PURE__ */ new Set([
136981
+ ...dependencyValues.inputChildren.map(
136982
+ (c2) => c2.componentIdx
136983
+ ),
136984
+ ...dependencyValues.inputsForAnswer.map(
136985
+ (c2) => c2.componentIdx
136986
+ )
136987
+ ]);
136988
+ return {
136989
+ setValue: { allInputComponentIdxs }
136990
+ };
136991
+ }
136992
+ };
136587
136993
  stateVariableDefinitions.inputComponentIdxForLabel = {
136588
136994
  stateVariablesDeterminingDependencies: ["inputChildrenWithValues"],
136589
136995
  additionalStateVariablesDefined: [
@@ -137414,6 +137820,50 @@ class Answer extends InlineComponent {
137414
137820
  };
137415
137821
  }
137416
137822
  };
137823
+ stateVariableDefinitions.creditAchievedPerInput = {
137824
+ returnDependencies: () => ({
137825
+ awardChildren: {
137826
+ dependencyType: "child",
137827
+ childGroups: ["awards"],
137828
+ variableNames: [
137829
+ "awarded",
137830
+ "creditAchieved",
137831
+ "credit",
137832
+ "referencedInputStateVars"
137833
+ ]
137834
+ }
137835
+ }),
137836
+ definition({ dependencyValues }) {
137837
+ const maxCreditByKey = {};
137838
+ const actualCreditByKey = {};
137839
+ for (const award of dependencyValues.awardChildren) {
137840
+ const referencedInputStateVars = award.stateValues.referencedInputStateVars;
137841
+ const credit = award.stateValues.credit;
137842
+ const awarded = award.stateValues.awarded;
137843
+ const creditAchieved = award.stateValues.creditAchieved;
137844
+ for (const {
137845
+ componentIdx,
137846
+ propVariable
137847
+ } of referencedInputStateVars) {
137848
+ const key = `${componentIdx}/${propVariable}`;
137849
+ if (maxCreditByKey[key] === void 0 || credit > maxCreditByKey[key]) {
137850
+ maxCreditByKey[key] = credit;
137851
+ }
137852
+ if (awarded && (actualCreditByKey[key] === void 0 || creditAchieved > actualCreditByKey[key])) {
137853
+ actualCreditByKey[key] = creditAchieved;
137854
+ }
137855
+ }
137856
+ }
137857
+ const creditAchievedPerInput = {};
137858
+ for (const key of Object.keys(maxCreditByKey)) {
137859
+ const maxCredit = maxCreditByKey[key];
137860
+ if (maxCredit > 0) {
137861
+ creditAchievedPerInput[key] = (actualCreditByKey[key] ?? 0) / maxCredit;
137862
+ }
137863
+ }
137864
+ return { setValue: { creditAchievedPerInput } };
137865
+ }
137866
+ };
137417
137867
  stateVariableDefinitions.numPreviousIncorrectSubmissions = {
137418
137868
  defaultValue: 0,
137419
137869
  hasEssential: true,
@@ -138490,6 +138940,60 @@ class Award extends BaseComponent {
138490
138940
  targetVariableName: "feedback1",
138491
138941
  description: "The first feedback message produced by this award."
138492
138942
  };
138943
+ stateVariableDefinitions.colorInputsSeparatelyFromAnswer = {
138944
+ returnDependencies: () => ({
138945
+ colorInputsSeparately: {
138946
+ dependencyType: "parentStateVariable",
138947
+ variableName: "colorInputsSeparately"
138948
+ }
138949
+ }),
138950
+ definition({ dependencyValues }) {
138951
+ return {
138952
+ setValue: {
138953
+ colorInputsSeparatelyFromAnswer: dependencyValues.colorInputsSeparately ?? false
138954
+ }
138955
+ };
138956
+ }
138957
+ };
138958
+ stateVariableDefinitions.referencedInputStateVars = {
138959
+ stateVariablesDeterminingDependencies: [
138960
+ "colorInputsSeparatelyFromAnswer"
138961
+ ],
138962
+ returnDependencies({ stateValues }) {
138963
+ const deps = {
138964
+ colorInputsSeparatelyFromAnswer: {
138965
+ dependencyType: "parentStateVariable",
138966
+ variableName: "colorInputsSeparately"
138967
+ }
138968
+ };
138969
+ if (stateValues.colorInputsSeparatelyFromAnswer) {
138970
+ deps.allInputComponentIdxs = {
138971
+ dependencyType: "parentStateVariable",
138972
+ variableName: "allInputComponentIdxs"
138973
+ };
138974
+ deps.whenChild = {
138975
+ dependencyType: "child",
138976
+ childGroups: ["whens"],
138977
+ variableNames: ["referencedStateVars"]
138978
+ };
138979
+ }
138980
+ return deps;
138981
+ },
138982
+ definition({ dependencyValues }) {
138983
+ if (!dependencyValues.colorInputsSeparatelyFromAnswer) {
138984
+ return { setValue: { referencedInputStateVars: [] } };
138985
+ }
138986
+ const allInputComponentIdxs = dependencyValues.allInputComponentIdxs ?? /* @__PURE__ */ new Set();
138987
+ const referencedStateVars = dependencyValues.whenChild?.[0]?.stateValues.referencedStateVars ?? [];
138988
+ return {
138989
+ setValue: {
138990
+ referencedInputStateVars: referencedStateVars.filter(
138991
+ (ref) => allInputComponentIdxs.has(ref.componentIdx)
138992
+ )
138993
+ }
138994
+ };
138995
+ }
138996
+ };
138493
138997
  return stateVariableDefinitions;
138494
138998
  }
138495
138999
  static standardizedFeedback = {
@@ -138721,6 +139225,43 @@ class When extends BooleanComponent {
138721
139225
  };
138722
139226
  }
138723
139227
  };
139228
+ stateVariableDefinitions._descendantIdxs = {
139229
+ returnDependencies: () => ({
139230
+ allDescendants: {
139231
+ dependencyType: "descendant",
139232
+ componentTypes: ["_base"]
139233
+ }
139234
+ }),
139235
+ definition({ dependencyValues }) {
139236
+ return {
139237
+ setValue: {
139238
+ _descendantIdxs: (dependencyValues.allDescendants ?? []).map((d2) => d2.componentIdx)
139239
+ }
139240
+ };
139241
+ }
139242
+ };
139243
+ stateVariableDefinitions.referencedStateVars = {
139244
+ stateVariablesDeterminingDependencies: ["_descendantIdxs"],
139245
+ returnDependencies({ stateValues }) {
139246
+ const deps = {};
139247
+ for (const idx of stateValues._descendantIdxs ?? []) {
139248
+ deps[`shadowInfo_${idx}`] = {
139249
+ dependencyType: "shadowInfo",
139250
+ componentIdx: idx
139251
+ };
139252
+ }
139253
+ return deps;
139254
+ },
139255
+ definition({ dependencyValues }) {
139256
+ const referencedStateVars = [];
139257
+ for (const [key, value] of Object.entries(dependencyValues)) {
139258
+ if (key.startsWith("shadowInfo_") && value !== null) {
139259
+ referencedStateVars.push(value);
139260
+ }
139261
+ }
139262
+ return { setValue: { referencedStateVars } };
139263
+ }
139264
+ };
138724
139265
  return stateVariableDefinitions;
138725
139266
  }
138726
139267
  // "when" does not adapt to "text", even though boolean does
@@ -228313,4 +228854,4 @@ export {
228313
228854
  getDefaultExportFromCjs as g,
228314
228855
  updateSyntaxFromV06toV07 as u
228315
228856
  };
228316
- //# sourceMappingURL=index-C0ofSjwe.js.map
228857
+ //# sourceMappingURL=index-BH7K9foM.js.map