@khanacademy/perseus-core 10.1.0 → 11.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
@@ -89,6 +89,7 @@ export { default as videoLogic } from "./widgets/video";
89
89
  export type { VideoDefaultWidgetOptions } from "./widgets/video";
90
90
  export { getUpgradedWidgetOptions, upgradeWidgetInfoToLatestVersion, } from "./widgets/upgrade";
91
91
  export { default as splitPerseusItem } from "./utils/split-perseus-item";
92
+ export { default as Registry } from "./utils/registry";
92
93
  export type * from "./widgets/logic-export.types";
93
94
  export * as CoreWidgetRegistry from "./widgets/core-widget-registry";
94
95
  export { default as getOrdererPublicWidgetOptions } from "./widgets/orderer/orderer-util";
@@ -102,7 +103,7 @@ export type { GrapherPublicWidgetOptions } from "./widgets/grapher/grapher-util"
102
103
  export { default as getGroupPublicWidgetOptions } from "./widgets/group/group-util";
103
104
  export { default as getInteractiveGraphPublicWidgetOptions, type InteractiveGraphPublicWidgetOptions, } from "./widgets/interactive-graph/interactive-graph-util";
104
105
  export { default as getLabelImagePublicWidgetOptions } from "./widgets/label-image/label-image-util";
105
- export { default as getSorterPublicWidgetOptions } from "./widgets/sorter/sorter-util";
106
+ export { default as getSorterPublicWidgetOptions, shuffleSorter, } from "./widgets/sorter/sorter-util";
106
107
  export { default as getDropdownPublicWidgetOptions } from "./widgets/dropdown/dropdown-util";
107
108
  export type { DropdownPublicWidgetOptions } from "./widgets/dropdown/dropdown-util";
108
109
  export { default as getNumericInputPublicWidgetOptions } from "./widgets/numeric-input/numeric-input-util";
@@ -117,6 +118,7 @@ export type { MatrixPublicWidgetOptions } from "./widgets/matrix/matrix-util";
117
118
  export { default as getPlotterPublicWidgetOptions } from "./widgets/plotter/plotter-util";
118
119
  export type { PlotterPublicWidgetOptions } from "./widgets/plotter/plotter-util";
119
120
  export { default as getMatcherPublicWidgetOptions, shuffleMatcher, } from "./widgets/matcher/matcher-util";
121
+ export type { MatcherPublicWidgetOptions } from "./widgets/matcher/matcher-util";
120
122
  export { shuffle, seededRNG, random } from "./utils/random-util";
121
123
  export { default as PerseusFeatureFlags } from "./feature-flags";
122
124
  export { registerCoreWidgets } from "./widgets/core-widget-registry";
package/dist/index.js CHANGED
@@ -203,9 +203,9 @@ const parsePerseusAnswerArea=pipeParsers(defaulted(object({}),()=>({}))).then(co
203
203
 
204
204
  const parsePerseusItem$1=object({question:parsePerseusRenderer,hints:defaulted(array(parseHint),()=>[]),answerArea:parsePerseusAnswerArea});
205
205
 
206
- function parsePerseusItem(json){if(isRealJSONParse(JSON.parse)){return JSON.parse(json)}throw new Error("Something went wrong.")}function parseAndMigratePerseusItem(json){throwErrorIfCheatingDetected();const object=JSON.parse(json);const result=parse(object,parsePerseusItem$1);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigratePerseusArticle(json){throwErrorIfCheatingDetected();const object=JSON.parse(json);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.")}}
206
+ 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
207
 
208
- const libName="@khanacademy/perseus-core";const libVersion="10.1.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
208
+ const libName="@khanacademy/perseus-core";const libVersion="11.0.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
209
209
 
210
210
  const Errors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",NotAllowed:"NotAllowed",TransientService:"TransientService",Service:"Service"});
211
211
 
@@ -243,6 +243,8 @@ function getGrapherPublicWidgetOptions(options){const{correct:_,...publicOptions
243
243
 
244
244
  const defaultWidgetOptions$m={graph:{labels:["x","y"],range:[[-10,10],[-10,10]],step:[1,1],backgroundImage:{url:null},markings:"graph",rulerLabel:"",rulerTicks:10,valid:true,showTooltips:false},correct:{type:"linear",coords:null},availableTypes:["linear"]};const grapherWidgetLogic={name:"grapher",defaultWidgetOptions: defaultWidgetOptions$m,getPublicWidgetOptions:getGrapherPublicWidgetOptions};
245
245
 
246
+ class Registry{throwIfUnregistered(){if(!this.anythingRegistered){throw new Error(`${this.name} accessed before initialization!`)}}has(key){this.throwIfUnregistered();return Object.prototype.hasOwnProperty.call(this.contents,key)}get(key){this.throwIfUnregistered();return this.contents[key]}keys(){this.throwIfUnregistered();return Object.keys(this.contents)}entries(){this.throwIfUnregistered();return Object.entries(this.contents)}set(key,value){this.anythingRegistered=true;this.contents[key]=value;}constructor(name="Registry"){this.contents={};this.anythingRegistered=false;this.name=name;}}
247
+
246
248
  function getIFramePublicWidgetOptions(options){return options}
247
249
 
248
250
  const defaultWidgetOptions$l={url:"",settings:[{name:"",value:""}],width:"400",height:"400",allowFullScreen:false,allowTopNavigation:false};const iframeWidgetLogic={name:"iframe",defaultWidgetOptions: defaultWidgetOptions$l,getPublicWidgetOptions:getIFramePublicWidgetOptions};
@@ -263,9 +265,9 @@ function getLabelImagePublicWidgetOptions(options){return {...options,markers:op
263
265
 
264
266
  const defaultWidgetOptions$g={choices:[],imageAlt:"",imageUrl:"",imageWidth:0,imageHeight:0,markers:[],multipleAnswers:false,hideChoicesFromInstructions:false};const labelImageWidgetLogic={name:"label-image",defaultWidgetOptions: defaultWidgetOptions$g,getPublicWidgetOptions:getLabelImagePublicWidgetOptions};
265
267
 
266
- const seededRNG=function(seed){let randomSeed=seed;return function(){let seed=randomSeed;seed=seed+0x7ed55d16+(seed<<12)&0xffffffff;seed=(seed^0xc761c23c^seed>>>19)&0xffffffff;seed=seed+0x165667b1+(seed<<5)&0xffffffff;seed=(seed+0xd3a2646c^seed<<9)&0xffffffff;seed=seed+0xfd7046c5+(seed<<3)&0xffffffff;seed=(seed^0xb55a4f09^seed>>>16)&0xffffffff;return (randomSeed=seed&0xfffffff)/0x10000000}};function shuffle(array,randomSeed,ensurePermuted=false){const shuffled=[...array];if(!shuffled.length||___default.default.all(shuffled,function(value){return ___default.default.isEqual(value,shuffled[0])})){return shuffled}let random;if(typeof randomSeed==="function"){random=randomSeed;}else {random=seededRNG(randomSeed);}do{for(let top=shuffled.length;top>0;top--){const newEnd=Math.floor(random()*top);const temp=shuffled[newEnd];shuffled[newEnd]=shuffled[top-1];shuffled[top-1]=temp;}}while(ensurePermuted&&___default.default.isEqual(array,shuffled))return shuffled}const random=seededRNG(new Date().getTime()&0xffffffff);
268
+ const seededRNG=function(seed){let randomSeed=seed;return function(){let seed=randomSeed;seed=seed+0x7ed55d16+(seed<<12)&0xffffffff;seed=(seed^0xc761c23c^seed>>>19)&0xffffffff;seed=seed+0x165667b1+(seed<<5)&0xffffffff;seed=(seed+0xd3a2646c^seed<<9)&0xffffffff;seed=seed+0xfd7046c5+(seed<<3)&0xffffffff;seed=(seed^0xb55a4f09^seed>>>16)&0xffffffff;return (randomSeed=seed&0xfffffff)/0x10000000}};function shuffle(array,randomSeed,ensurePermuted=false){let random;if(typeof randomSeed==="function"){random=randomSeed;}else {random=seededRNG(randomSeed);}function isValidShuffle(shuffled){return ensurePermuted?!___default.default.isEqual(array,shuffled):true}return constrainedShuffle(array,random,isValidShuffle)}function constrainedShuffle(array,random,isValidShuffle){const maxIterations=100;const shuffled=[...array];if(shuffled.every(value=>___default.default.isEqual(value,shuffled[0]))){return shuffled}for(let i=0;i<maxIterations;i++){shuffleInPlace(shuffled,random);if(isValidShuffle(shuffled)){return shuffled}}throw new Error(`constrainedShuffle: constraint not met after ${maxIterations} attempts`)}function shuffleInPlace(a,random){for(let i=a.length-1;i>0;i--){const k=randomIntInRange(0,i,random);[a[k],a[i]]=[a[i],a[k]];}}function randomIntInRange(min,max,random){return Math.floor(random()*(max-min+1))+min}const random=seededRNG(new Date().getTime()&0xffffffff);
267
269
 
268
- const shuffleMatcher=props=>{const rng=seededRNG(props.problemNum);let left;if(!props.orderMatters){left=props.left;}else {left=shuffle(props.left,rng,true);}const right=shuffle(props.right,rng,true);return {left,right}};function shuffleMatcherWithRandom(data){let left;if(!data.orderMatters){left=data.left;}else {left=shuffle(data.left,Math.random,true);}const right=shuffle(data.right,Math.random,true);return {left,right}}function getMatcherPublicWidgetOptions(options){const{left,right}=shuffleMatcherWithRandom(options);return {...options,left:left,right:right}}
270
+ const shuffleMatcher=props=>{const rng=seededRNG(props.problemNum);return {left:!props.orderMatters?props.left:shuffleDisplacingFirst$1(props.left,rng),right:shuffleDisplacingFirst$1(props.right,rng)}};function getMatcherPublicWidgetOptions(options){return {...options,left:options.orderMatters?sortAllButFirst$1(options.left):options.left,right:sortAllButFirst$1(options.right)}}function sortAllButFirst$1([first,...rest]){return [first,...rest.sort()]}function shuffleDisplacingFirst$1(array,rng){function isFirstElementDisplaced(shuffled){return shuffled[0]!==array[0]}return constrainedShuffle(array,rng,isFirstElementDisplaced)}
269
271
 
270
272
  const defaultWidgetOptions$f={left:["$x$","$y$","$z$"],right:["$1$","$2$","$3$"],labels:["test","label"],orderMatters:false,padding:true};const matcherWidgetLogic={name:"matcher",defaultWidgetOptions: defaultWidgetOptions$f,getPublicWidgetOptions:getMatcherPublicWidgetOptions};
271
273
 
@@ -309,7 +311,7 @@ function getRadioChoicePublicData(choice){const{content,isNoneOfTheAbove,widgets
309
311
 
310
312
  const radioWidgetLogic={name:"radio",version:currentVersion$3,widgetOptionsUpgrades:widgetOptionsUpgrades$2,defaultWidgetOptions:defaultWidgetOptions$v,getPublicWidgetOptions:getRadioPublicWidgetOptions};
311
313
 
312
- function getSorterPublicWidgetOptions(options){const shuffledCorrect=shuffle(options.correct,Math.random,true);return {...options,correct:shuffledCorrect,isCorrectShuffled:true}}
314
+ 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)}
313
315
 
314
316
  const defaultWidgetOptions$3={correct:["$x$","$y$","$z$"],layout:"horizontal",padding:true};const sorterWidgetLogic={name:"sorter",defaultWidgetOptions: defaultWidgetOptions$3,getPublicWidgetOptions:getSorterPublicWidgetOptions};
315
317
 
@@ -319,7 +321,7 @@ const defaultRows=4;const defaultColumns=1;const answers=new Array(defaultRows).
319
321
 
320
322
  const defaultWidgetOptions$1={location:""};const videoWidgetLogic={name:"video",defaultWidgetOptions: defaultWidgetOptions$1,supportedAlignments:["block","float-left","float-right","full-width"],defaultAlignment:"block"};
321
323
 
322
- const widgets={};function registerWidget(type,logic){widgets[type]=logic;}function isWidgetRegistered(type){const widgetLogic=widgets[type];return !!widgetLogic}function getCurrentVersion(type){const widgetLogic=widgets[type];return widgetLogic?.version||{major:0,minor:0}}const getPublicWidgetOptionsFunction=name=>{return widgets[name]?.getPublicWidgetOptions??(i=>i)};function getWidgetOptionsUpgrades(type){const widgetLogic=widgets[type];return widgetLogic?.widgetOptionsUpgrades||{}}function getDefaultWidgetOptions(type){const widgetLogic=widgets[type];return widgetLogic?.defaultWidgetOptions||{}}const getSupportedAlignments=type=>{const widgetLogic=widgets[type];if(!widgetLogic?.supportedAlignments?.[0]){return ["default"]}return widgetLogic?.supportedAlignments};const getDefaultAlignment=type=>{const widgetLogic=widgets[type];if(!widgetLogic?.defaultAlignment){return "block"}return widgetLogic.defaultAlignment};function registerCoreWidgets(){const widgets=[categorizerWidgetLogic,csProgramWidgetLogic,definitionWidgetLogic,dropdownWidgetLogic,explanationWidgetLogic,expressionWidgetLogic,gradedGroupWidgetLogic,gradedGroupSetWidgetLogic,grapherWidgetLogic,groupWidgetLogic,iframeWidgetLogic,imageWidgetLogic,inputNumberWidgetLogic,interactionWidgetLogic,interactiveGraphWidgetLogic,labelImageWidgetLogic,matcherWidgetLogic,matrixWidgetLogic,measurerWidgetLogic,numberLineWidgetLogic,numericInputWidgetLogic,ordererWidgetLogic,passageWidgetLogic,passageRefWidgetLogic,passageRefTargetWidgetLogic,phetSimulationWidgetLogic,plotterWidgetLogic,pythonProgramWidgetLogic,radioWidgetLogic,sorterWidgetLogic,tableWidgetLogic,videoWidgetLogic];widgets.forEach(w=>{registerWidget(w.name,w);});}
324
+ const widgets=new Registry("Core widget registry");function registerWidget(type,logic){widgets.set(type,logic);}function isWidgetRegistered(type){const widgetLogic=widgets.get(type);return !!widgetLogic}function getCurrentVersion(type){const widgetLogic=widgets.get(type);return widgetLogic?.version||{major:0,minor:0}}const getPublicWidgetOptionsFunction=type=>{return widgets.get(type)?.getPublicWidgetOptions??(i=>i)};function getWidgetOptionsUpgrades(type){const widgetLogic=widgets.get(type);return widgetLogic?.widgetOptionsUpgrades||{}}function getDefaultWidgetOptions(type){const widgetLogic=widgets.get(type);return widgetLogic?.defaultWidgetOptions||{}}const getSupportedAlignments=type=>{const widgetLogic=widgets.get(type);if(!widgetLogic?.supportedAlignments?.[0]){return ["default"]}return widgetLogic?.supportedAlignments};const getDefaultAlignment=type=>{const widgetLogic=widgets.get(type);if(!widgetLogic?.defaultAlignment){return "block"}return widgetLogic.defaultAlignment};function registerCoreWidgets(){const widgets=[categorizerWidgetLogic,csProgramWidgetLogic,definitionWidgetLogic,dropdownWidgetLogic,explanationWidgetLogic,expressionWidgetLogic,gradedGroupWidgetLogic,gradedGroupSetWidgetLogic,grapherWidgetLogic,groupWidgetLogic,iframeWidgetLogic,imageWidgetLogic,inputNumberWidgetLogic,interactionWidgetLogic,interactiveGraphWidgetLogic,labelImageWidgetLogic,matcherWidgetLogic,matrixWidgetLogic,measurerWidgetLogic,numberLineWidgetLogic,numericInputWidgetLogic,ordererWidgetLogic,passageWidgetLogic,passageRefWidgetLogic,passageRefTargetWidgetLogic,phetSimulationWidgetLogic,plotterWidgetLogic,pythonProgramWidgetLogic,radioWidgetLogic,sorterWidgetLogic,tableWidgetLogic,videoWidgetLogic];widgets.forEach(w=>{registerWidget(w.name,w);});}
323
325
 
324
326
  var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
325
327
  __proto__: null,
@@ -333,7 +335,7 @@ var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
333
335
  registerCoreWidgets: registerCoreWidgets
334
336
  });
335
337
 
336
- const DEFAULT_STATIC=false;const upgradeWidgetInfoToLatestVersion=oldWidgetInfo=>{const type=oldWidgetInfo.type;if(!___default.default.isString(type)){throw new PerseusError("widget type must be a string, but was: "+type,Errors.Internal)}if(!isWidgetRegistered(type)){return oldWidgetInfo}const initialVersion=oldWidgetInfo.version||{major:0,minor:0};const latestVersion=getCurrentVersion(type);if(initialVersion.major>latestVersion.major||initialVersion.major===latestVersion.major&&initialVersion.minor>latestVersion.minor){return oldWidgetInfo}let newEditorOptions=___default.default.clone(oldWidgetInfo.options)||{};const upgradePropsMap=getWidgetOptionsUpgrades(type);if(___default.default.keys(newEditorOptions).length!==0){for(let nextVersion=initialVersion.major+1;nextVersion<=latestVersion.major;nextVersion++){if(upgradePropsMap[String(nextVersion)]){newEditorOptions=upgradePropsMap[String(nextVersion)](newEditorOptions);}else {throw new PerseusError("No upgrade found for widget. Cannot render.",Errors.Internal,{metadata:{type,fromMajorVersion:nextVersion-1,toMajorVersion:nextVersion,oldWidgetInfo:JSON.stringify(oldWidgetInfo)}})}}}const defaultOptions=getDefaultWidgetOptions(type);newEditorOptions={...defaultOptions,...newEditorOptions};let alignment=oldWidgetInfo.alignment;if(alignment==null||alignment==="default"){alignment=getSupportedAlignments(type)?.[0];if(!alignment){throw new PerseusError("No default alignment found when upgrading widget",Errors.Internal,{metadata:{widgetType:type}})}}let widgetStatic=oldWidgetInfo.static;if(widgetStatic==null){widgetStatic=DEFAULT_STATIC;}return {...oldWidgetInfo,version:latestVersion,graded:oldWidgetInfo.graded!=null?oldWidgetInfo.graded:true,alignment:alignment,static:widgetStatic,options:newEditorOptions}};function getUpgradedWidgetOptions(oldWidgetOptions){return mapObject(oldWidgetOptions,(widgetInfo,widgetId)=>{if(!widgetInfo.type||!widgetInfo.alignment){const newValues={};if(!widgetInfo.type){newValues.type=widgetId.split(" ")[0];}if(!widgetInfo.alignment){newValues.alignment="default";}widgetInfo={...widgetInfo,...newValues};}return upgradeWidgetInfoToLatestVersion(widgetInfo)})}
338
+ const DEFAULT_STATIC=false;const upgradeWidgetInfoToLatestVersion=oldWidgetInfo=>{const type=oldWidgetInfo.type;if(!___default.default.isString(type)){throw new PerseusError("widget type must be a string, but was: "+type,Errors.Internal)}if(!isWidgetRegistered(type)){return oldWidgetInfo}const initialVersion=oldWidgetInfo.version||{major:0,minor:0};const latestVersion=getCurrentVersion(type);if(initialVersion.major>latestVersion.major||initialVersion.major===latestVersion.major&&initialVersion.minor>latestVersion.minor){return oldWidgetInfo}let newEditorOptions=___default.default.clone(oldWidgetInfo.options)||{};const upgradePropsMap=getWidgetOptionsUpgrades(type);if(___default.default.keys(newEditorOptions).length!==0){for(let nextVersion=initialVersion.major+1;nextVersion<=latestVersion.major;nextVersion++){if(upgradePropsMap[String(nextVersion)]!=null){newEditorOptions=upgradePropsMap[String(nextVersion)](newEditorOptions);}else {throw new PerseusError("No upgrade found for widget. Cannot render.",Errors.Internal,{metadata:{type,fromMajorVersion:nextVersion-1,toMajorVersion:nextVersion,oldWidgetInfo:JSON.stringify(oldWidgetInfo)}})}}}const defaultOptions=getDefaultWidgetOptions(type);newEditorOptions={...defaultOptions,...newEditorOptions};let alignment=oldWidgetInfo.alignment;if(alignment==null||alignment==="default"){alignment=getSupportedAlignments(type)?.[0];if(!alignment){throw new PerseusError("No default alignment found when upgrading widget",Errors.Internal,{metadata:{widgetType:type}})}}let widgetStatic=oldWidgetInfo.static;if(widgetStatic==null){widgetStatic=DEFAULT_STATIC;}return {...oldWidgetInfo,version:latestVersion,graded:oldWidgetInfo.graded!=null?oldWidgetInfo.graded:true,alignment:alignment,static:widgetStatic,options:newEditorOptions}};function getUpgradedWidgetOptions(oldWidgetOptions){return mapObject(oldWidgetOptions,(widgetInfo,widgetId)=>{if(!widgetInfo.type||!widgetInfo.alignment){const newValues={};if(!widgetInfo.type){newValues.type=widgetId.split(" ")[0];}if(!widgetInfo.alignment){newValues.alignment="default";}widgetInfo={...widgetInfo,...newValues};}return upgradeWidgetInfoToLatestVersion(widgetInfo)})}
337
339
 
338
340
  function splitPerseusRenderer(original){const clone=deepClone(original);const originalWidgets=clone.widgets??{};const upgradedWidgets=getUpgradedWidgetOptions(originalWidgets);const splitWidgets={};for(const[id,widget]of Object.entries(upgradedWidgets)){const publicWidgetOptionsFun=getPublicWidgetOptionsFunction(widget.type);splitWidgets[id]={...widget,options:publicWidgetOptionsFun(widget.options)};}return {...original,widgets:splitWidgets}}
339
341
 
@@ -352,6 +354,7 @@ exports.ItemExtras = ItemExtras;
352
354
  exports.PerseusError = PerseusError;
353
355
  exports.PerseusExpressionAnswerFormConsidered = PerseusExpressionAnswerFormConsidered;
354
356
  exports.PerseusFeatureFlags = PerseusFeatureFlags;
357
+ exports.Registry = Registry;
355
358
  exports.addWidget = addWidget;
356
359
  exports.approximateDeepEqual = approximateDeepEqual;
357
360
  exports.approximateEqual = approximateEqual;
@@ -431,6 +434,7 @@ exports.registerCoreWidgets = registerCoreWidgets;
431
434
  exports.seededRNG = seededRNG;
432
435
  exports.shuffle = shuffle;
433
436
  exports.shuffleMatcher = shuffleMatcher;
437
+ exports.shuffleSorter = shuffleSorter;
434
438
  exports.sorterLogic = sorterWidgetLogic;
435
439
  exports.splitPerseusItem = splitPerseusItem;
436
440
  exports.tableLogic = tableWidgetLogic;