@khanacademy/perseus-core 11.0.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -35,6 +35,8 @@ export { default as expressionLogic } from "./widgets/expression";
35
35
  export type { ExpressionDefaultWidgetOptions } from "./widgets/expression";
36
36
  export { default as deriveExtraKeys } from "./widgets/expression/derive-extra-keys";
37
37
  export { default as gradedGroupLogic } from "./widgets/graded-group";
38
+ export { default as freeResponseLogic } from "./widgets/free-response";
39
+ export type { FreeResponseDefaultWidgetOptions } from "./widgets/free-response";
38
40
  export type { GradedGroupDefaultWidgetOptions } from "./widgets/graded-group";
39
41
  export { default as gradedGroupSetLogic } from "./widgets/graded-group-set";
40
42
  export type { GradedGroupSetDefaultWidgetOptions } from "./widgets/graded-group-set";
@@ -97,6 +99,7 @@ export { default as getCategorizerPublicWidgetOptions } from "./widgets/categori
97
99
  export type { CategorizerPublicWidgetOptions } from "./widgets/categorizer/categorizer-util";
98
100
  export { default as getCSProgramPublicWidgetOptions } from "./widgets/cs-program/cs-program-util";
99
101
  export { default as getExpressionPublicWidgetOptions } from "./widgets/expression/expression-util";
102
+ export { default as getFreeResponsePublicWidgetOptions } from "./widgets/free-response/free-response-util";
100
103
  export type { ExpressionPublicWidgetOptions } from "./widgets/expression/expression-util";
101
104
  export { default as getGrapherPublicWidgetOptions } from "./widgets/grapher/grapher-util";
102
105
  export type { GrapherPublicWidgetOptions } from "./widgets/grapher/grapher-util";
package/dist/index.js CHANGED
@@ -129,6 +129,8 @@ function versionedWidgetOptions(latestMajorVersion,parseLatest){return new Versi
129
129
 
130
130
  const stringOrNumberOrNullOrUndefined=union(string).or(number).or(constant(null)).or(constant(undefined)).parser;function numberOrNullToString(v){return typeof v==="number"||v===null?String(v):v}const parsePossiblyInvalidAnswerForm=object({value:optional(string),form:defaulted(boolean,()=>false),simplify:defaulted(boolean,()=>false),considered:enumeration("correct","wrong","ungraded"),key:pipeParsers(stringOrNumberOrNullOrUndefined).then(convert(numberOrNullToString)).parser});function removeInvalidAnswerForms(possiblyInvalid){return possiblyInvalid.flatMap(answerForm=>{const{value}=answerForm;if(value!=null){return [{...answerForm,value}]}return []})}const version2$1=object({major:constant(2),minor:number});const parseExpressionWidgetV2=parseWidgetWithVersion(version2$1,constant("expression"),object({answerForms:pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused")),extraKeys:optional(array(enumeration(...KeypadKeys)))}));const version1$1=object({major:constant(1),minor:number});const parseExpressionWidgetV1=parseWidgetWithVersion(version1$1,constant("expression"),object({answerForms:pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused"))}));function migrateV1ToV2$1(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{times:options.times,buttonSets:options.buttonSets,functions:options.functions,buttonsVisible:options.buttonsVisible,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,answerForms:options.answerForms,extraKeys:deriveExtraKeys(options)??[]}}}const version0$1=optional(object({major:constant(0),minor:number}));const parseExpressionWidgetV0=parseWidgetWithVersion(version0$1,constant("expression"),object({functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),form:boolean,simplify:boolean,value:string,buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused"))}));function migrateV0ToV1$1(widget){const{options}=widget;return {...widget,version:{major:1,minor:0},options:{times:options.times,buttonSets:options.buttonSets,functions:options.functions,buttonsVisible:options.buttonsVisible,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,answerForms:[{considered:"correct",form:options.form,simplify:options.simplify,value:options.value}]}}}const parseExpressionWidget=versionedWidgetOptions(2,parseExpressionWidgetV2).withMigrationFrom(1,parseExpressionWidgetV1,migrateV1ToV2$1).withMigrationFrom(0,parseExpressionWidgetV0,migrateV0ToV1$1).parser;
131
131
 
132
+ const parseFreeResponseWidget=parseWidget(constant("free-response"),object({allowUnlimitedCharacters:boolean,characterLimit:number,placeholder:string,question:string,scoringCriteria:array(object({text:string}))}));
133
+
132
134
  const falseToNull=pipeParsers(constant(false)).then(convert(()=>null)).parser;const parseGradedGroupWidgetOptions=object({title:defaulted(string,()=>""),hasHint:optional(nullable(boolean)),hint:union(falseToNull).or(constant(null)).or(constant(undefined)).or((rawVal,ctx)=>parsePerseusRenderer(rawVal,ctx)).parser,content:string,widgets:(rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),widgetEnabled:optional(nullable(boolean)),immutableWidgets:optional(nullable(boolean)),images:record(string,object({width:number,height:number}))});const parseGradedGroupWidget=parseWidget(constant("graded-group"),parseGradedGroupWidgetOptions);
133
135
 
134
136
  const parseGradedGroupSetWidget=parseWidget(constant("graded-group-set"),object({gradedGroups:array(parseGradedGroupWidgetOptions)}));
@@ -181,7 +183,7 @@ const parsePlotterWidget=parseWidget(constant("plotter"),object({labels:array(st
181
183
 
182
184
  const parsePythonProgramWidget=parseWidget(constant("python-program"),object({programID:string,height:number}));
183
185
 
184
- const currentVersion$3={major:2,minor:0};function deriveNumCorrect(options){const{choices,numCorrect}=options;return numCorrect??choices.filter(c=>c.correct).length}const widgetOptionsUpgrades$2={"2":v1props=>{const upgraded={...v1props,numCorrect:deriveNumCorrect(v1props)};return upgraded},"1":v0props=>{const{noneOfTheAbove,...rest}=v0props;if(noneOfTheAbove){throw new Error("radio widget v0 no longer supports auto noneOfTheAbove")}return {...rest,hasNoneOfTheAbove:false}}};const defaultWidgetOptions$v={choices:[{},{},{},{}],displayCount:null,randomize:false,hasNoneOfTheAbove:false,multipleSelect:false,countChoices:false,deselectEnabled:false};
186
+ const currentVersion$3={major:2,minor:0};function deriveNumCorrect(options){const{choices,numCorrect}=options;return numCorrect??choices.filter(c=>c.correct).length}const widgetOptionsUpgrades$2={"2":v1props=>{const upgraded={...v1props,numCorrect:deriveNumCorrect(v1props)};return upgraded},"1":v0props=>{const{noneOfTheAbove,...rest}=v0props;if(noneOfTheAbove){throw new Error("radio widget v0 no longer supports auto noneOfTheAbove")}return {...rest,hasNoneOfTheAbove:false}}};const defaultWidgetOptions$w={choices:[{},{},{},{}],displayCount:null,randomize:false,hasNoneOfTheAbove:false,multipleSelect:false,countChoices:false,deselectEnabled:false};
185
187
 
186
188
  const parseWidgetsMapOrUndefined=defaulted(optional((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx)),()=>undefined);const version2=optional(object({major:constant(2),minor:number}));const parseRadioWidgetV2=parseWidgetWithVersion(version2,constant("radio"),object({numCorrect:optional(number),choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));const version1=optional(object({major:constant(1),minor:number}));const parseRadioWidgetV1=parseWidgetWithVersion(version1,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV1ToV2(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{...options,numCorrect:deriveNumCorrect(options)}}}const version0=optional(object({major:constant(0),minor:number}));const parseRadioWidgetV0=parseWidgetWithVersion(version0,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV0ToV1(widget){const{options}=widget;const{noneOfTheAbove:_,...rest}=options;return {...widget,version:{major:1,minor:0},options:{...rest,hasNoneOfTheAbove:false,noneOfTheAbove:undefined}}}const parseRadioWidget=versionedWidgetOptions(2,parseRadioWidgetV2).withMigrationFrom(1,parseRadioWidgetV1,migrateV1ToV2).withMigrationFrom(0,parseRadioWidgetV0,migrateV0ToV1).parser;
187
189
 
@@ -191,7 +193,7 @@ const parseTableWidget=parseWidget(constant("table"),object({headers:array(strin
191
193
 
192
194
  const parseVideoWidget=parseWidget(constant("video"),object({location:string,static:optional(boolean)}));
193
195
 
194
- const parseWidgetsMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("PerseusWidgetsMap",rawValue)}const widgetsMap={};for(const key of Object.keys(rawValue)){const entryResult=parseWidgetsMapEntry([key,rawValue[key]],widgetsMap,ctx.forSubtree(key));if(isFailure(entryResult)){return entryResult}}return ctx.success(widgetsMap)};const parseWidgetsMapEntry=([id,widget],widgetMap,ctx)=>{const idComponentsResult=parseWidgetIdComponents(id.split(" "),ctx.forSubtree("(widget ID)"));if(isFailure(idComponentsResult)){return idComponentsResult}const[type,n]=idComponentsResult.value;function parseAndAssign(key,parse){const widgetResult=parse(widget,ctx);if(isFailure(widgetResult)){return widgetResult}widgetMap[key]=widgetResult.value;return ctx.success(undefined)}switch(type){case "categorizer":return parseAndAssign(`categorizer ${n}`,parseCategorizerWidget);case "cs-program":return parseAndAssign(`cs-program ${n}`,parseCSProgramWidget);case "definition":return parseAndAssign(`definition ${n}`,parseDefinitionWidget);case "dropdown":return parseAndAssign(`dropdown ${n}`,parseDropdownWidget);case "explanation":return parseAndAssign(`explanation ${n}`,parseExplanationWidget);case "expression":return parseAndAssign(`expression ${n}`,parseExpressionWidget);case "grapher":return parseAndAssign(`grapher ${n}`,parseGrapherWidget);case "group":return parseAndAssign(`group ${n}`,parseGroupWidget);case "graded-group":return parseAndAssign(`graded-group ${n}`,parseGradedGroupWidget);case "graded-group-set":return parseAndAssign(`graded-group-set ${n}`,parseGradedGroupSetWidget);case "iframe":return parseAndAssign(`iframe ${n}`,parseIframeWidget);case "image":return parseAndAssign(`image ${n}`,parseImageWidget);case "input-number":return parseAndAssign(`input-number ${n}`,parseInputNumberWidget);case "interaction":return parseAndAssign(`interaction ${n}`,parseInteractionWidget);case "interactive-graph":return parseAndAssign(`interactive-graph ${n}`,parseInteractiveGraphWidget);case "label-image":return parseAndAssign(`label-image ${n}`,parseLabelImageWidget);case "matcher":return parseAndAssign(`matcher ${n}`,parseMatcherWidget);case "matrix":return parseAndAssign(`matrix ${n}`,parseMatrixWidget);case "measurer":return parseAndAssign(`measurer ${n}`,parseMeasurerWidget);case "molecule-renderer":return parseAndAssign(`molecule-renderer ${n}`,parseMoleculeRendererWidget);case "number-line":return parseAndAssign(`number-line ${n}`,parseNumberLineWidget);case "numeric-input":return parseAndAssign(`numeric-input ${n}`,parseNumericInputWidget);case "orderer":return parseAndAssign(`orderer ${n}`,parseOrdererWidget);case "passage":return parseAndAssign(`passage ${n}`,parsePassageWidget);case "passage-ref":return parseAndAssign(`passage-ref ${n}`,parsePassageRefWidget);case "passage-ref-target":return parseAndAssign(`passage-ref-target ${n}`,any);case "phet-simulation":return parseAndAssign(`phet-simulation ${n}`,parsePhetSimulationWidget);case "plotter":return parseAndAssign(`plotter ${n}`,parsePlotterWidget);case "python-program":return parseAndAssign(`python-program ${n}`,parsePythonProgramWidget);case "radio":return parseAndAssign(`radio ${n}`,parseRadioWidget);case "sorter":return parseAndAssign(`sorter ${n}`,parseSorterWidget);case "table":return parseAndAssign(`table ${n}`,parseTableWidget);case "video":return parseAndAssign(`video ${n}`,parseVideoWidget);case "sequence":return parseAndAssign(`sequence ${n}`,parseDeprecatedWidget);case "lights-puzzle":return parseAndAssign(`lights-puzzle ${n}`,parseDeprecatedWidget);case "simulator":return parseAndAssign(`simulator ${n}`,parseDeprecatedWidget);case "transformer":return parseAndAssign(`transformer ${n}`,parseDeprecatedWidget);default:return parseAndAssign(`${type} ${n}`,parseWidget(constant(type),any))}};const parseDeprecatedWidget=parseWidget((_,ctx)=>ctx.success("deprecated-standin"),object({}));const parseStringToNonNegativeInt=(rawValue,ctx)=>{if(typeof rawValue!=="string"||!/^(0|[1-9][0-9]*)$/.test(rawValue)){return ctx.failure("a string representing a non-negative integer",rawValue)}return ctx.success(+rawValue)};const parseWidgetIdComponents=pair(string,parseStringToNonNegativeInt);
196
+ const parseWidgetsMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("PerseusWidgetsMap",rawValue)}const widgetsMap={};for(const key of Object.keys(rawValue)){const entryResult=parseWidgetsMapEntry([key,rawValue[key]],widgetsMap,ctx.forSubtree(key));if(isFailure(entryResult)){return entryResult}}return ctx.success(widgetsMap)};const parseWidgetsMapEntry=([id,widget],widgetMap,ctx)=>{const idComponentsResult=parseWidgetIdComponents(id.split(" "),ctx.forSubtree("(widget ID)"));if(isFailure(idComponentsResult)){return idComponentsResult}const[type,n]=idComponentsResult.value;function parseAndAssign(key,parse){const widgetResult=parse(widget,ctx);if(isFailure(widgetResult)){return widgetResult}widgetMap[key]=widgetResult.value;return ctx.success(undefined)}switch(type){case "categorizer":return parseAndAssign(`categorizer ${n}`,parseCategorizerWidget);case "cs-program":return parseAndAssign(`cs-program ${n}`,parseCSProgramWidget);case "definition":return parseAndAssign(`definition ${n}`,parseDefinitionWidget);case "dropdown":return parseAndAssign(`dropdown ${n}`,parseDropdownWidget);case "explanation":return parseAndAssign(`explanation ${n}`,parseExplanationWidget);case "expression":return parseAndAssign(`expression ${n}`,parseExpressionWidget);case "free-response":return parseAndAssign(`free-response ${n}`,parseFreeResponseWidget);case "grapher":return parseAndAssign(`grapher ${n}`,parseGrapherWidget);case "group":return parseAndAssign(`group ${n}`,parseGroupWidget);case "graded-group":return parseAndAssign(`graded-group ${n}`,parseGradedGroupWidget);case "graded-group-set":return parseAndAssign(`graded-group-set ${n}`,parseGradedGroupSetWidget);case "iframe":return parseAndAssign(`iframe ${n}`,parseIframeWidget);case "image":return parseAndAssign(`image ${n}`,parseImageWidget);case "input-number":return parseAndAssign(`input-number ${n}`,parseInputNumberWidget);case "interaction":return parseAndAssign(`interaction ${n}`,parseInteractionWidget);case "interactive-graph":return parseAndAssign(`interactive-graph ${n}`,parseInteractiveGraphWidget);case "label-image":return parseAndAssign(`label-image ${n}`,parseLabelImageWidget);case "matcher":return parseAndAssign(`matcher ${n}`,parseMatcherWidget);case "matrix":return parseAndAssign(`matrix ${n}`,parseMatrixWidget);case "measurer":return parseAndAssign(`measurer ${n}`,parseMeasurerWidget);case "molecule-renderer":return parseAndAssign(`molecule-renderer ${n}`,parseMoleculeRendererWidget);case "number-line":return parseAndAssign(`number-line ${n}`,parseNumberLineWidget);case "numeric-input":return parseAndAssign(`numeric-input ${n}`,parseNumericInputWidget);case "orderer":return parseAndAssign(`orderer ${n}`,parseOrdererWidget);case "passage":return parseAndAssign(`passage ${n}`,parsePassageWidget);case "passage-ref":return parseAndAssign(`passage-ref ${n}`,parsePassageRefWidget);case "passage-ref-target":return parseAndAssign(`passage-ref-target ${n}`,any);case "phet-simulation":return parseAndAssign(`phet-simulation ${n}`,parsePhetSimulationWidget);case "plotter":return parseAndAssign(`plotter ${n}`,parsePlotterWidget);case "python-program":return parseAndAssign(`python-program ${n}`,parsePythonProgramWidget);case "radio":return parseAndAssign(`radio ${n}`,parseRadioWidget);case "sorter":return parseAndAssign(`sorter ${n}`,parseSorterWidget);case "table":return parseAndAssign(`table ${n}`,parseTableWidget);case "video":return parseAndAssign(`video ${n}`,parseVideoWidget);case "sequence":return parseAndAssign(`sequence ${n}`,parseDeprecatedWidget);case "lights-puzzle":return parseAndAssign(`lights-puzzle ${n}`,parseDeprecatedWidget);case "simulator":return parseAndAssign(`simulator ${n}`,parseDeprecatedWidget);case "transformer":return parseAndAssign(`transformer ${n}`,parseDeprecatedWidget);default:return parseAndAssign(`${type} ${n}`,parseWidget(constant(type),any))}};const parseDeprecatedWidget=parseWidget((_,ctx)=>ctx.success("deprecated-standin"),object({}));const parseStringToNonNegativeInt=(rawValue,ctx)=>{if(typeof rawValue!=="string"||!/^(0|[1-9][0-9]*)$/.test(rawValue)){return ctx.failure("a string representing a non-negative integer",rawValue)}return ctx.success(+rawValue)};const parseWidgetIdComponents=pair(string,parseStringToNonNegativeInt);
195
197
 
196
198
  const parsePerseusRenderer=defaulted(object({content:defaulted(string,()=>""),widgets:defaulted((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),()=>({})),images:parseImages,metadata:any}),()=>({content:"",widgets:{},images:{}}));
197
199
 
@@ -205,7 +207,7 @@ const parsePerseusItem$1=object({question:parsePerseusRenderer,hints:defaulted(a
205
207
 
206
208
  function parsePerseusItem(json){if(isRealJSONParse(JSON.parse)){return JSON.parse(json)}throw new Error("Something went wrong.")}function parseAndMigratePerseusItem(data){throwErrorIfCheatingDetected();const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parsePerseusItem$1);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigratePerseusArticle(data){throwErrorIfCheatingDetected();const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parsePerseusArticle);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function throwErrorIfCheatingDetected(){if(!isRealJSONParse(JSON.parse)){throw new Error("Something went wrong.")}}
207
209
 
208
- const libName="@khanacademy/perseus-core";const libVersion="11.0.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
210
+ const libName="@khanacademy/perseus-core";const libVersion="12.0.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
209
211
 
210
212
  const Errors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",NotAllowed:"NotAllowed",TransientService:"TransientService",Service:"Service"});
211
213
 
@@ -215,27 +217,31 @@ const pluck=function(table,subKey){return ___default.default.object(___default.d
215
217
 
216
218
  function getCategorizerPublicWidgetOptions(options){return {items:options.items,categories:options.categories,randomizeItems:options.randomizeItems,static:options.static}}
217
219
 
218
- const defaultWidgetOptions$u={items:[],categories:[],values:[],randomizeItems:false};const categorizerWidgetLogic={name:"categorizer",defaultWidgetOptions: defaultWidgetOptions$u,getPublicWidgetOptions:getCategorizerPublicWidgetOptions};
220
+ const defaultWidgetOptions$v={items:[],categories:[],values:[],randomizeItems:false};const categorizerWidgetLogic={name:"categorizer",defaultWidgetOptions: defaultWidgetOptions$v,getPublicWidgetOptions:getCategorizerPublicWidgetOptions};
219
221
 
220
222
  function getCSProgramPublicWidgetOptions(options){return options}
221
223
 
222
- const DEFAULT_HEIGHT=400;const defaultWidgetOptions$t={programID:"",programType:null,settings:[{name:"",value:""}],showEditor:false,showButtons:false,height:DEFAULT_HEIGHT};const csProgramWidgetLogic={name:"cs-program",defaultWidgetOptions: defaultWidgetOptions$t,supportedAlignments:["block","full-width"],getPublicWidgetOptions:getCSProgramPublicWidgetOptions};
224
+ const DEFAULT_HEIGHT=400;const defaultWidgetOptions$u={programID:"",programType:null,settings:[{name:"",value:""}],showEditor:false,showButtons:false,height:DEFAULT_HEIGHT};const csProgramWidgetLogic={name:"cs-program",defaultWidgetOptions: defaultWidgetOptions$u,supportedAlignments:["block","full-width"],getPublicWidgetOptions:getCSProgramPublicWidgetOptions};
223
225
 
224
- const defaultWidgetOptions$s={togglePrompt:"",definition:""};const definitionWidgetLogic={name:"definition",defaultWidgetOptions: defaultWidgetOptions$s,defaultAlignment:"inline"};
226
+ const defaultWidgetOptions$t={togglePrompt:"",definition:""};const definitionWidgetLogic={name:"definition",defaultWidgetOptions: defaultWidgetOptions$t,defaultAlignment:"inline"};
225
227
 
226
228
  function getDropdownPublicWidgetOptions(options){return {choices:options.choices.map(choice=>({content:choice.content})),placeholder:options.placeholder,static:options.static,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel}}
227
229
 
228
- const defaultWidgetOptions$r={placeholder:"",choices:[{content:"",correct:false}]};const dropdownWidgetLogic={name:"dropdown",defaultWidgetOptions: defaultWidgetOptions$r,defaultAlignment:"inline-block",getPublicWidgetOptions:getDropdownPublicWidgetOptions};
230
+ const defaultWidgetOptions$s={placeholder:"",choices:[{content:"",correct:false}]};const dropdownWidgetLogic={name:"dropdown",defaultWidgetOptions: defaultWidgetOptions$s,defaultAlignment:"inline-block",getPublicWidgetOptions:getDropdownPublicWidgetOptions};
229
231
 
230
- const defaultWidgetOptions$q={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{}};const explanationWidgetLogic={name:"explanation",defaultWidgetOptions: defaultWidgetOptions$q,defaultAlignment:"inline"};
232
+ const defaultWidgetOptions$r={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{}};const explanationWidgetLogic={name:"explanation",defaultWidgetOptions: defaultWidgetOptions$r,defaultAlignment:"inline"};
231
233
 
232
- const currentVersion$2={major:2,minor:0};const widgetOptionsUpgrades$1={"2":v1options=>{return {times:v1options.times,buttonSets:v1options.buttonSets,functions:v1options.functions,buttonsVisible:v1options.buttonsVisible,visibleLabel:v1options.visibleLabel,ariaLabel:v1options.ariaLabel,answerForms:v1options.answerForms,extraKeys:v1options.extraKeys||deriveExtraKeys(v1options)}},"1":v0options=>{return {times:v0options.times,buttonSets:v0options.buttonSets,functions:v0options.functions,buttonsVisible:v0options.buttonsVisible,visibleLabel:v0options.visibleLabel,ariaLabel:v0options.ariaLabel,extraKeys:v0options.extraKeys,answerForms:[{considered:"correct",form:v0options.form,simplify:v0options.simplify,value:v0options.value}]}}};const defaultWidgetOptions$p={answerForms:[],times:false,buttonSets:["basic"],functions:["f","g","h"]};
234
+ const currentVersion$2={major:2,minor:0};const widgetOptionsUpgrades$1={"2":v1options=>{return {times:v1options.times,buttonSets:v1options.buttonSets,functions:v1options.functions,buttonsVisible:v1options.buttonsVisible,visibleLabel:v1options.visibleLabel,ariaLabel:v1options.ariaLabel,answerForms:v1options.answerForms,extraKeys:v1options.extraKeys||deriveExtraKeys(v1options)}},"1":v0options=>{return {times:v0options.times,buttonSets:v0options.buttonSets,functions:v0options.functions,buttonsVisible:v0options.buttonsVisible,visibleLabel:v0options.visibleLabel,ariaLabel:v0options.ariaLabel,extraKeys:v0options.extraKeys,answerForms:[{considered:"correct",form:v0options.form,simplify:v0options.simplify,value:v0options.value}]}}};const defaultWidgetOptions$q={answerForms:[],times:false,buttonSets:["basic"],functions:["f","g","h"]};
233
235
 
234
236
  function getExpressionPublicWidgetOptions(options){return {buttonSets:options.buttonSets,functions:options.functions,times:options.times,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,buttonsVisible:options.buttonsVisible,extraKeys:options.extraKeys}}
235
237
 
236
- const expressionWidgetLogic={name:"expression",version:currentVersion$2,widgetOptionsUpgrades:widgetOptionsUpgrades$1,defaultWidgetOptions:defaultWidgetOptions$p,defaultAlignment:"inline-block",getPublicWidgetOptions:getExpressionPublicWidgetOptions};
238
+ const expressionWidgetLogic={name:"expression",version:currentVersion$2,widgetOptionsUpgrades:widgetOptionsUpgrades$1,defaultWidgetOptions:defaultWidgetOptions$q,defaultAlignment:"inline-block",getPublicWidgetOptions:getExpressionPublicWidgetOptions};
239
+
240
+ const defaultWidgetOptions$p={title:"",content:"",widgets:{},images:{},hint:null};const gradedGroupWidgetLogic={name:"graded-group",defaultWidgetOptions: defaultWidgetOptions$p};
241
+
242
+ function getFreeResponsePublicWidgetOptions(options){return {allowUnlimitedCharacters:options.allowUnlimitedCharacters,characterLimit:options.characterLimit,placeholder:options.placeholder,question:options.question}}
237
243
 
238
- const defaultWidgetOptions$o={title:"",content:"",widgets:{},images:{},hint:null};const gradedGroupWidgetLogic={name:"graded-group",defaultWidgetOptions: defaultWidgetOptions$o};
244
+ const defaultWidgetOptions$o={allowUnlimitedCharacters:false,characterLimit:500,placeholder:"Please provide response here",question:"",scoringCriteria:[{text:""}]};const freeResponseWidgetLogic={name:"free-response",defaultWidgetOptions: defaultWidgetOptions$o,getPublicWidgetOptions:getFreeResponsePublicWidgetOptions};
239
245
 
240
246
  const defaultWidgetOptions$n={gradedGroups:[]};const gradedGroupSetWidgetLogic={name:"graded-group-set",defaultWidgetOptions: defaultWidgetOptions$n};
241
247
 
@@ -309,7 +315,7 @@ const defaultWidgetOptions$4={programID:"",height:400};const pythonProgramWidget
309
315
 
310
316
  function getRadioChoicePublicData(choice){const{content,isNoneOfTheAbove,widgets}=choice;return {content,isNoneOfTheAbove,widgets}}function usesNumCorrect(multipleSelect,countChoices,numCorrect){return multipleSelect&&countChoices&&numCorrect}function getRadioPublicWidgetOptions(options){const{numCorrect,choices,multipleSelect,countChoices}=options;return {...options,numCorrect:usesNumCorrect(multipleSelect,countChoices,numCorrect)?numCorrect:undefined,choices:choices.map(getRadioChoicePublicData)}}
311
317
 
312
- const radioWidgetLogic={name:"radio",version:currentVersion$3,widgetOptionsUpgrades:widgetOptionsUpgrades$2,defaultWidgetOptions:defaultWidgetOptions$v,getPublicWidgetOptions:getRadioPublicWidgetOptions};
318
+ const radioWidgetLogic={name:"radio",version:currentVersion$3,widgetOptionsUpgrades:widgetOptionsUpgrades$2,defaultWidgetOptions:defaultWidgetOptions$w,getPublicWidgetOptions:getRadioPublicWidgetOptions};
313
319
 
314
320
  function getSorterPublicWidgetOptions(options){return {...options,correct:sortAllButFirst(options.correct)}}function shuffleSorter(props){const{correct,problemNum}=props;const rng=seededRNG(problemNum??0);return shuffleDisplacingFirst(correct,rng)}function sortAllButFirst([first,...rest]){return [first,...rest.sort()]}function shuffleDisplacingFirst(array,rng){function isFirstElementDisplaced(shuffled){return shuffled[0]!==array[0]}return constrainedShuffle(array,rng,isFirstElementDisplaced)}
315
321
 
@@ -367,6 +373,7 @@ exports.deriveNumCorrect = deriveNumCorrect;
367
373
  exports.dropdownLogic = dropdownWidgetLogic;
368
374
  exports.explanationLogic = explanationWidgetLogic;
369
375
  exports.expressionLogic = expressionWidgetLogic;
376
+ exports.freeResponseLogic = freeResponseWidgetLogic;
370
377
  exports.generateTestPerseusItem = generateTestPerseusItem;
371
378
  exports.generateTestPerseusRenderer = generateTestPerseusRenderer;
372
379
  exports.getCSProgramPublicWidgetOptions = getCSProgramPublicWidgetOptions;
@@ -374,6 +381,7 @@ exports.getCategorizerPublicWidgetOptions = getCategorizerPublicWidgetOptions;
374
381
  exports.getDecimalSeparator = getDecimalSeparator;
375
382
  exports.getDropdownPublicWidgetOptions = getDropdownPublicWidgetOptions;
376
383
  exports.getExpressionPublicWidgetOptions = getExpressionPublicWidgetOptions;
384
+ exports.getFreeResponsePublicWidgetOptions = getFreeResponsePublicWidgetOptions;
377
385
  exports.getGrapherPublicWidgetOptions = getGrapherPublicWidgetOptions;
378
386
  exports.getGroupPublicWidgetOptions = getGroupPublicWidgetOptions;
379
387
  exports.getIFramePublicWidgetOptions = getIFramePublicWidgetOptions;