@khanacademy/perseus-editor 34.2.1 → 35.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/article-editor.d.ts +39 -3
- package/dist/editor-page.d.ts +3 -2
- package/dist/es/index.js +26 -24
- package/dist/es/index.js.map +1 -1
- package/dist/hint-editor.d.ts +1 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +27 -24
- package/dist/index.js.map +1 -1
- package/dist/item-editor.d.ts +11 -4
- package/dist/preview/message-types.d.ts +43 -15
- package/dist/preview/preview-data-sanitizer.d.ts +0 -5
- package/dist/preview/sanitize-api-options.d.ts +14 -1
- package/dist/preview/use-preview-presenter.d.ts +6 -6
- package/dist/preview-with-iframe.d.ts +3 -2
- package/dist/testing/preview/exercise-preview-page.d.ts +2 -4
- package/dist/testing/preview/preview-renderer.d.ts +4 -2
- package/package.json +38 -38
package/dist/es/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import arrowCircleDownIcon from '@phosphor-icons/core/bold/arrow-circle-down-bol
|
|
|
10
10
|
import arrowCircleUpIcon from '@phosphor-icons/core/bold/arrow-circle-up-bold.svg';
|
|
11
11
|
import plusIcon from '@phosphor-icons/core/bold/plus-bold.svg';
|
|
12
12
|
import trashIcon from '@phosphor-icons/core/bold/trash-bold.svg';
|
|
13
|
-
import _ from 'underscore';
|
|
14
13
|
import { View, Id } from '@khanacademy/wonder-blocks-core';
|
|
15
14
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
16
15
|
import { sizing, spacing, semanticColor, font, border } from '@khanacademy/wonder-blocks-tokens';
|
|
@@ -23,10 +22,12 @@ import { StyleSheet, css } from 'aphrodite';
|
|
|
23
22
|
import Switch from '@khanacademy/wonder-blocks-switch';
|
|
24
23
|
import { Strut, Spring } from '@khanacademy/wonder-blocks-layout';
|
|
25
24
|
import caretRight from '@phosphor-icons/core/bold/caret-right-bold.svg';
|
|
25
|
+
import _ from 'underscore';
|
|
26
26
|
import IconButton from '@khanacademy/wonder-blocks-icon-button';
|
|
27
27
|
import $ from 'jquery';
|
|
28
28
|
import Link from '@khanacademy/wonder-blocks-link';
|
|
29
29
|
import { SingleSelect, OptionItem, ActionMenu, ActionItem } from '@khanacademy/wonder-blocks-dropdown';
|
|
30
|
+
import { UnreachableCaseError, isTruthy } from '@khanacademy/wonder-stuff-core';
|
|
30
31
|
import katex from 'katex';
|
|
31
32
|
import classNames from 'classnames';
|
|
32
33
|
import invariant from 'tiny-invariant';
|
|
@@ -34,7 +35,6 @@ import { Checkbox as Checkbox$1, TextField, LabeledTextField, TextArea } from '@
|
|
|
34
35
|
import * as axeCore from 'axe-core';
|
|
35
36
|
import { StatefulKeypadContextProvider, KeypadContext } from '@khanacademy/keypad-context';
|
|
36
37
|
import { MobileKeypad, useMathInputI18n, createMathField } from '@khanacademy/math-input';
|
|
37
|
-
import { UnreachableCaseError, isTruthy } from '@khanacademy/wonder-stuff-core';
|
|
38
38
|
import PropTypes from 'prop-types';
|
|
39
39
|
import ReactDOM from 'react-dom';
|
|
40
40
|
import * as KAS from '@khanacademy/kas';
|
|
@@ -63,7 +63,7 @@ import minusCircle from '@phosphor-icons/core/regular/minus-circle.svg';
|
|
|
63
63
|
import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
|
|
64
64
|
import minusCircleIcon from '@phosphor-icons/core/bold/minus-circle-bold.svg';
|
|
65
65
|
|
|
66
|
-
const libName="@khanacademy/perseus-editor";const libVersion="
|
|
66
|
+
const libName="@khanacademy/perseus-editor";const libVersion="35.0.0";addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
67
67
|
|
|
68
68
|
var jsxRuntime = {exports: {}};
|
|
69
69
|
|
|
@@ -1451,19 +1451,29 @@ function setPerseusClipboardData({text,widgets}){const dummyElement=document.cre
|
|
|
1451
1451
|
|
|
1452
1452
|
const widgetPlaceholder="[[☃ {id}]]";const widgetRegExp="(\\[\\[☃ {id}\\]\\])";const rWidgetSplit=new RegExp(widgetRegExp.replace("{id}","[a-z-]+ [0-9]+"),"g");const shortcutRegexp=/^\[\[([a-z-]+)$/;const ENDS_WITH_A_PARAGRAPH=/(?:\n{2,}|^\n*)$/;const TRAILING_NEWLINES=/(\n*)$/;const LEADING_NEWLINES=/^(\n*)/;const commafyInteger=n=>{let str=n.toString();if(str.length>=5){str=str.replace(/(\d)(?=(\d{3})+$)/g,"$1{,}");}return str};const makeEndWithAParagraphIfNecessary=content=>{if(!ENDS_WITH_A_PARAGRAPH.test(content)){const match=TRAILING_NEWLINES.exec(content);if(match){const newlines=match[1];return content+"\n\n".slice(0,2-newlines.length)}}return content};const makeStartWithAParagraphAlways=content=>{const match=LEADING_NEWLINES.exec(content);if(!match){return content}const newlines=match[1];return "\n\n".slice(0,2-newlines.length)+content};const IMAGE_REGEX$1=/!\[[^\]]*\]\(([^\s)]+)[^)]*\)/g;const allMatches=function(regex,str){const result=[];while(true){const match=regex.exec(str);if(!match){break}result.push(match);}return result};const imageUrlsFromContent=function(content){return allMatches(IMAGE_REGEX$1,content).map(capture=>capture[1])};class Editor extends React.Component{static getDerivedStateFromProps(props,state){return {textAreaValue:props.content,rememberedWidgetsForUndo:{...state.rememberedWidgetsForUndo,...props.widgets}}}componentDidMount(){this.lastUserValue=null;this._sizeImages(this.props);$(this.textarea.current).on("copy cut",this._maybeCopyWidgets).on("paste",this._maybePasteWidgets);}componentDidUpdate(prevProps){const textarea=this.textarea.current;if(this.lastUserValue!=null&&textarea){textarea.focus();textarea.value=this.lastUserValue;textarea.selectionStart=0;textarea.setSelectionRange(0,prevProps.content.length);document.execCommand("insertText",false,this.props.content);this.lastUserValue=null;}if(this._pendingCursorPos!=null&&textarea){Util.textarea.moveCursor(textarea,this._pendingCursorPos);this._pendingCursorPos=null;}if(this.props.content!==prevProps.content){this._sizeImages(this.props);}}getWidgetEditor(id,type){if(!Widgets.getEditor(type)){return}return createElement(WidgetEditor,{...this.props.widgets[id],ref:id,id:id,key:id,onChange:this._handleWidgetEditorChange.bind(this,id),onRemove:this._handleWidgetEditorRemove.bind(this,id),apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}getWidgetsReferencedIn(content){const referencedWidgetIds=getWidgetIdsFromContent(content);const allWidgets={...this.state.rememberedWidgetsForUndo,...this.props.widgets};const referencedWidgets={};for(const id of referencedWidgetIds){if(allWidgets[id]!=null){referencedWidgets[id]=allWidgets[id];}}return referencedWidgets}serialize(){const widgets={};const widgetIds=_.intersection(this.widgetIds,_.keys(this.refs));_.each(widgetIds,id=>{widgets[id]=this.refs[id].serialize();});return {content:this.props.content,images:this.props.images,widgets}}render(){let pieces;let widgets;let underlayPieces;let templatesDropDown;let widgetsAndTemplates;let wordCountDisplay;if(this.props.showWordCount){const numChars=PerseusMarkdown.characterCount(this.props.content);const numWords=Math.floor(numChars/6);wordCountDisplay=jsxRuntimeExports.jsx("span",{className:"perseus-editor-word-count",title:"~"+commafyInteger(numWords)+" words ("+commafyInteger(numChars)+" characters)",children:commafyInteger(numWords)});}if(this.props.widgetEnabled){pieces=this.props.content.split(rWidgetSplit);widgets={};underlayPieces=[];for(let i=0;i<pieces.length;i++){if(i%2===0){underlayPieces.push(pieces[i]);}else {const match=Util.rWidgetParts.exec(pieces[i]);if(match!=null){const id=match[1];const type=match[2];const duplicate=id in widgets;widgets[id]=this.getWidgetEditor(id,type);const classes=(duplicate||!widgets[id]?"error ":"")+("");const key=duplicate?i:id;underlayPieces.push(jsxRuntimeExports.jsx("b",{className:classes,children:pieces[i]},key));}}}this.widgetIds=Object.keys(widgets);const insertTemplateString="Insert template…";templatesDropDown=jsxRuntimeExports.jsxs("select",{onChange:this.addTemplate,"data-testid":"editor__template-select",children:[jsxRuntimeExports.jsx("option",{value:"",children:insertTemplateString}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"table",children:"Table"}),jsxRuntimeExports.jsx("option",{value:"titledTable",children:"Titled table"}),jsxRuntimeExports.jsx("option",{value:"alignment",children:"Aligned equations"}),jsxRuntimeExports.jsx("option",{value:"piecewise",children:"Piecewise function"}),Object.keys(this.props.additionalTemplates).length>0&&jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),Object.entries(this.props.additionalTemplates).map(([key])=>jsxRuntimeExports.jsx("option",{value:key,children:key},key)),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"allWidgets",children:"All widgets (for testing)"})]});if(!this.props.immutableWidgets){const widgetNodes=Object.values(widgets);widgetsAndTemplates=jsxRuntimeExports.jsxs("div",{className:"perseus-editor-widgets",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-widgets-selectors",children:[jsxRuntimeExports.jsx(WidgetSelect,{onChange:this._addWidget}),templatesDropDown,wordCountDisplay]}),widgetNodes]});wordCountDisplay=null;}}else {underlayPieces=[this.props.content];}underlayPieces.push(jsxRuntimeExports.jsx("br",{},"end"));const completeTextarea=[jsxRuntimeExports.jsx("div",{className:"perseus-textarea-underlay",ref:this.underlay,children:underlayPieces},"underlay"),jsxRuntimeExports.jsx("textarea",{ref:this.textarea,"aria-label":"Markdown content",onChange:this.handleChange,onKeyDown:this._handleKeyDown,placeholder:this.props.placeholder,disabled:this.props.disabled,value:this.state.textAreaValue},"textarea")];let textareaWrapper;if(this.props.imageUploader){textareaWrapper=jsxRuntimeExports.jsx(DragTarget,{onDrop:this.handleDrop,className:"perseus-textarea-pair",children:completeTextarea});}else {textareaWrapper=jsxRuntimeExports.jsx("div",{className:"perseus-textarea-pair",children:completeTextarea});}const contentWithoutWidgets=this.props.content.replace(/\[\[\u2603 (([a-z-]+) ([0-9]+))\]\]/g,"");const noPrompt=contentWithoutWidgets.trim().length===0;const noWidgets=!/\[\[\u2603 (([a-z-]+) ([0-9]+))\]\]/g.test(this.props.content);const warningStyle={borderTop:"none",padding:4,backgroundColor:"pink"};const editingDisabled=this.props.apiOptions.editingDisabled;return jsxRuntimeExports.jsxs("div",{"data-testid":"perseus-single-editor",className:"perseus-single-editor "+(this.props.className||"")+(editingDisabled?" perseus-editor-disabled":""),children:[textareaWrapper,this.props.warnNoPrompt&&noPrompt&&jsxRuntimeExports.jsx("div",{style:warningStyle,children:"Graded Groups should contain a prompt"}),this.props.warnNoWidgets&&noWidgets&&jsxRuntimeExports.jsx("div",{style:warningStyle,children:"Graded Groups should contain at least one widget"}),wordCountDisplay,widgetsAndTemplates]})}constructor(...args){super(...args),this._pendingCursorPos=null,this.underlay=React.createRef(),this.textarea=React.createRef(),this.state={textAreaValue:this.props.content,rememberedWidgetsForUndo:{}},this._handleWidgetEditorChange=(id,newWidgetInfo)=>{const widgets=Object.assign({},this.props.widgets);widgets[id]=Object.assign({},widgets[id],newWidgetInfo);this.props.onChange({widgets});},this._handleWidgetEditorRemove=id=>{if(!confirm("Are you sure you want to delete this item?")){return}const textarea=this.textarea.current;const re=new RegExp(widgetRegExp.replace("{id}",id),"gm");this.props.onChange({content:textarea?.value.replace(re,"")});},this._sizeImages=props=>{const imageUrls=imageUrlsFromContent(props.content);const images=_.pick(props.images,imageUrls);const newImageUrls=_.filter(imageUrls,url=>!images[url]);_.each(newImageUrls,url=>{Util.getImageSize(url,(width,height)=>{images[url]={width:width,height:height};props.onChange({images:_.clone(images)});});});},this.handleDrop=e=>{const{imageUploader}=this.props;let content=this.state.textAreaValue||"";const dataTransfer="dataTransfer"in e?e.dataTransfer:null;if(!dataTransfer||!imageUploader){return}const files=dataTransfer.files;if(files.length===0){const imageUrl=dataTransfer.getData("URL");if(imageUrl){const newContent=content+"\n\n";this.lastUserValue=this.props.content;this.props.onChange({content:newContent});}return}const origContent=this.state.textAreaValue;_(files).chain().map(function(file){if(!file.type.match("image.*")){return null}const sentinel="☃ "+_.uniqueId("image_");content+="\n\n";return {file:file,sentinel:sentinel}}).reject(_.isNull).tap(()=>{this.lastUserValue=origContent;this.props.onChange({content:content});}).each(fileAndSentinel=>{imageUploader(fileAndSentinel.file,url=>{this.lastUserValue=origContent;this.props.onChange({content:this.state.textAreaValue.replace(fileAndSentinel.sentinel,url)});});});},this.handleChange=e=>{const newValue=e.currentTarget.value;this.setState({textAreaValue:newValue});const widgets=this.getWidgetsReferencedIn(newValue);if(newValue!==this.props.content){this.props.onChange({content:newValue,widgets});}},this._handleKeyDown=e=>{e.stopPropagation();if(e.key==="Tab"){const textarea=this.textarea.current;const word=Util.textarea.getWordBeforeCursor(textarea);const matches=word.string.toLowerCase().match(shortcutRegexp);if(matches!=null){const text=matches[1];const widgets=Widgets.getAllWidgetTypes();const matchingWidgets=widgets.filter(name=>{return name.substring(0,text.length)===text});if(matchingWidgets.length===1){const widgetType=matchingWidgets[0];this._addWidgetToContent(this.props.content,[word.pos.start,word.pos.end+1],widgetType);}e.preventDefault();}}},this._maybeCopyWidgets=e=>{const textarea=e.currentTarget;const selectedText=textarea.value.substring(textarea.selectionStart,textarea.selectionEnd);const widgetIds=_.map(selectedText.match(rWidgetSplit),syntax=>{return Util.rWidgetParts.exec(syntax)[1]});const widgetData=_.pick(this.serialize().widgets,widgetIds);setPerseusClipboardData({text:selectedText,widgets:widgetData}).catch(err=>Log.error("failed to copy data to clipboard","Internal",{cause:err}));},this._maybePasteWidgets=async e=>{e.preventDefault();const{widgets,text:textToBePasted}=await getPerseusClipboardData();const safeWidgetMapping=this._safeWidgetNameMapping(widgets);const safeWidgetData={};for(const[key,data]of Object.entries(widgets)){safeWidgetData[safeWidgetMapping[key]]=data;}const safeText=textToBePasted.replace(rWidgetSplit,syntax=>{const match=Util.rWidgetParts.exec(syntax);const completeWidget=match[0];const widget=match[1];return completeWidget.replace(widget,safeWidgetMapping[widget])});const textarea=e.currentTarget;const selectionStart=textarea.selectionStart;const newContent=this.state.textAreaValue.substr(0,selectionStart)+safeText+this.state.textAreaValue.substr(textarea.selectionEnd);this.lastUserValue=this.state.textAreaValue;this._pendingCursorPos=selectionStart+safeText.length;this.props.onChange({content:newContent,widgets:{...safeWidgetData,...this.getWidgetsReferencedIn(newContent)}});},this._safeWidgetNameMapping=widgetData=>{const widgets=_.keys(widgetData).map(name=>name.split(" "));const widgetTypes=_.uniq(widgets.map(widget=>widget[0]));const existingWidgets=_.keys(this.props.widgets).map(name=>name.split(" "));const safeWidgetNums={};_.each(widgetTypes,type=>{safeWidgetNums[type]=_.chain(existingWidgets).filter(existingWidget=>existingWidget[0]===type).map(existingWidget=>+existingWidget[1]+1).max().value();safeWidgetNums[type]=Math.max(safeWidgetNums[type],1);});const safeWidgetMapping={};_.each(widgets,widget=>{const widgetName=widget.join(" ");const widgetType=widget[0];safeWidgetMapping[widgetName]=`${widgetType} ${safeWidgetNums[widgetType]}`;safeWidgetNums[widgetType]++;});return safeWidgetMapping},this._addWidgetToContent=(oldContent,cursorRange,widgetType)=>{const allWidgetIds=_.map(oldContent.match(rWidgetSplit),syntax=>{const match=Util.rWidgetParts.exec(syntax);const type=match[2];const num=+match[3];return [type,num]});const widgetNum=_.reduce(allWidgetIds,(currentNum,otherId)=>{const[otherType,otherNum]=otherId;if(otherType===widgetType){return Math.max(otherNum+1,currentNum)}return currentNum},1);const id=widgetType+" "+widgetNum;const widgetContent=widgetPlaceholder.replace("{id}",id);const isBlock=CoreWidgetRegistry.getDefaultAlignment(widgetType)==="block";const selectedText=oldContent.slice(cursorRange[0],cursorRange[1]);const prelude=oldContent.slice(0,cursorRange[0]);const postlude=oldContent.slice(cursorRange[1]);const newPrelude=isBlock?makeEndWithAParagraphIfNecessary(prelude):prelude;const newPostlude=isBlock?makeStartWithAParagraphAlways(postlude):postlude;const newContent=newPrelude+widgetContent+newPostlude;const newWidgets={...this.props.widgets};const widgetEditor=Widgets.getEditor(widgetType);const initializeWidgetOptionsParams={selectedText};const startWidgetOptions=widgetEditor?.initializeWidgetOptions?.(initializeWidgetOptionsParams);const defaultProps=widgetEditor?.defaultProps;newWidgets[id]={options:startWidgetOptions||defaultProps,type:widgetType,version:CoreWidgetRegistry.getCurrentVersion(widgetType)};this.lastUserValue=this.props.content;this._pendingCursorPos=newContent.length-postlude.length;this.props.onChange({content:newContent,widgets:newWidgets});},this._addWidget=widgetType=>{const textarea=this.textarea.current;if(!textarea){return}this._addWidgetToContent(this.props.content,[textarea.selectionStart,textarea.selectionEnd],widgetType);textarea.focus();},this.addTemplate=e=>{const templateType=e.currentTarget.value;if(templateType===""){return}e.currentTarget.value="";let oldContent=this.props.content;oldContent=oldContent.replace(/\n*$/,"\n\n");let template;if(templateType==="table"){template="header 1 | header 2 | header 3\n"+"- | - | -\n"+"data 1 | data 2 | data 3\n"+"data 4 | data 5 | data 6\n"+"data 7 | data 8 | data 9";}else if(templateType==="titledTable"){template="|| **Table title** ||\n"+"header 1 | header 2 | header 3\n"+"- | - | -\n"+"data 1 | data 2 | data 3\n"+"data 4 | data 5 | data 6\n"+"data 7 | data 8 | data 9";}else if(templateType==="alignment"){template="$\\begin{align} \n"+"\\\\\\\\\n"+"\\end{align}$";}else if(templateType==="piecewise"){template="$f(x) = \\begin{cases}\n"+"7 & \\text{if }x=1 \\\\\n"+"f(x-1)+5 & \\text{if }x > 1\n"+"\\end{cases}$";}else if(templateType==="allWidgets"){template=Widgets.getAllWidgetTypes().map(type=>`[[${Util.snowman} ${type} 1]]`).join("\n\n");}else if(templateType in this.props.additionalTemplates){template=this.props.additionalTemplates[templateType];}else {throw new PerseusError("Invalid template type: "+templateType,Errors.InvalidInput,{metadata:{templateType}})}const newContent=oldContent+template;this.lastUserValue=this.props.content;this.props.onChange({content:newContent});},this.getSaveWarnings=()=>{const widgetIds=_.intersection(this.widgetIds,_.keys(this.refs));const warnings=_(widgetIds).chain().map(id=>{const issuesFunc=this.refs[id].getSaveWarnings;const issues=issuesFunc?issuesFunc():[];return _.map(issues,issue=>id+": "+issue)}).flatten(true).value();return warnings},this.focus=()=>{const textarea=this.textarea.current;if(textarea){textarea.focus();}},this.focusAndMoveToEnd=()=>{this.focus();const textarea=this.textarea.current;if(textarea){textarea.selectionStart=textarea.value.length;textarea.selectionEnd=textarea.value.length;}};}}Editor.defaultProps={content:"",placeholder:"",widgets:{},images:{},disabled:false,widgetEnabled:true,immutableWidgets:false,showWordCount:false,warnNoPrompt:false,warnNoWidgets:false,additionalTemplates:{},apiOptions:ApiOptions.defaults};
|
|
1453
1453
|
|
|
1454
|
-
let nextIframeID=0;const requestIframeData={};const updateIframeHeight={};window.iframeDataStore={};window.addEventListener("message",event=>{if(typeof event.data==="string"){const callback=requestIframeData[event.data];if(callback){callback();}}else if(event.data.id){if(event.data.height!==undefined){updateIframeHeight[event.data.id](event.data.height);}else if(event.data.lintWarnings){Log.log("LINTER REPORT",{lintWarnings:JSON.stringify(event.data.lintWarnings)});}}});class IframeContentRenderer extends React.Component{componentDidMount(){this._isMounted=true;this.iframeID=nextIframeID;nextIframeID++;this._prepareFrame();requestIframeData[this.iframeID]=()=>{this.sendNewData(this._lastData);};updateIframeHeight[this.iframeID]=height=>{this._lastHeight=height;if(this._isMounted&&this.props.seamless&&this.container.current){this.container.current.style.height=height+"px";}};}shouldComponentUpdate(nextProps){return nextProps.datasetValue!==this.props.datasetValue||nextProps.seamless!==this.props.seamless}componentDidUpdate(prevProps){if(this.container.current){if(!this.props.seamless){this.container.current.style.height="100%";}else {this.container.current.style.height=this._lastHeight+"px";}}if(prevProps.datasetValue!==this.props.datasetValue){this._prepareFrame();}}componentWillUnmount(){requestIframeData[this.iframeID]=null;updateIframeHeight[this.iframeID]=null;this._isMounted=false;}_prepareFrame(){if(this._frame){this.container.current?.removeChild(this._frame);}const frame=document.createElement("iframe");frame.style.width="100%";frame.style.height="100%";frame.dataset.name="content-preview";frame.src=this.props.url;frame.onload=()=>{const iframeDoc=frame.contentDocument||frame.contentWindow?.document;if(iframeDoc){const axeCoreScriptElement=iframeDoc.createElement("script");axeCoreScriptElement.src="https://unpkg.com/axe-core@4.11.0/axe.js";iframeDoc.body.appendChild(axeCoreScriptElement);}else {console.warn("Unable to add axe-core to iframe document");}};if(this.props.datasetKey){frame.dataset[this.props.datasetKey]=this.props.datasetValue;}frame.dataset.id=String(this.iframeID);if(this.props.seamless){frame.dataset.lintGutter="true";}this.container.current?.appendChild(frame);this._frame=frame;}sendNewData(data){const frame=this._frame;if(this._isMounted&&data&&frame?.contentWindow){this._lastData=data;window.iframeDataStore[this.iframeID]=data;frame.contentWindow.postMessage(this.iframeID,"*");}}render(){return jsxRuntimeExports.jsx("div",{ref:this.container,style:{width:"100%",height:"100%"}})}constructor(...args){super(...args),this.container=React.createRef();}}
|
|
1455
|
-
|
|
1456
1454
|
const SEVERITY_ERROR=1;const SEVERITY_WARNING=2;const SEVERITY_GUIDELINE=3;const SEVERITY_MAP={[SEVERITY_ERROR]:"high",[SEVERITY_WARNING]:"medium",[SEVERITY_GUIDELINE]:"low"};const WARNINGS={inaccessibleWidget:(widgetType,widgetId)=>({id:`${widgetId} inaccessible`,description:`This ${widgetType} widget (${widgetId}) is inaccessible. Consider using an alternative to support all learners. Please check out the following documentation on compliant widget options.`,helpUrl:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/1909489691/Widget+Fundamentals",help:"Widget Fundamentals",impact:"medium",message:"Selecting inaccessible widgets for a practice item will result in this exercise being hidden from users with 'Hide visually dependant content' setting set to true. Please select another widget or create an alternative practice item."}),genericLinterWarning:(rule,message,severity)=>({id:rule,description:message,help:"Learn more about best practices for authoring items",helpUrl:"https://docs.google.com/document/d/1N13f4sY-7EXWDwQ04ivA9vJBVvPPd60qjBT73B4NHuM/edit?tab=t.0",impact:SEVERITY_MAP[severity??SEVERITY_GUIDELINE],message:message}),texError:(math,errorMessage,index)=>({id:`tex-debug-info-${index+1}`,description:"If your math doesn't display correctly, these errors might help you troubleshoot. Message #content-kitchen for help.",help:"Learn more about TeX syntax",helpUrl:"https://khan.github.io/KaTeX/",impact:"medium",message:`Error in: ${math}
|
|
1457
1455
|
|
|
1458
1456
|
${errorMessage}`})};
|
|
1459
1457
|
|
|
1458
|
+
const PREVIEW_MESSAGE_SOURCE="perseus-preview";function createPreviewIframeReadyMessage(){return {source:PREVIEW_MESSAGE_SOURCE,type:"iframe-ready"}}
|
|
1459
|
+
|
|
1460
|
+
function isIframeToParentMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&typeof message.source==="string"&&message.source===PREVIEW_MESSAGE_SOURCE}function isParentToIframeMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&typeof message.source==="string"&&message.source===PREVIEW_MESSAGE_SOURCE}
|
|
1461
|
+
|
|
1462
|
+
function sanitizeApiOptions(apiOptions){const{onFocusChange:_,answerableCallback:__,getAnotherHint:___,interactionCallback:____,trackInteraction:_____,baseElements:_______,imagePlaceholder:_________,widgetPlaceholder:__________,...serializableOptions}=apiOptions;return serializableOptions}
|
|
1463
|
+
|
|
1464
|
+
function sanitizePreviewData(content){if(content.data.apiOptions==null){return content}const sanitizedApiOptions=sanitizeApiOptions(content.data.apiOptions);switch(content.type){case "question":return {type:content.type,data:{...content.data,apiOptions:sanitizedApiOptions}};case "hint":return {type:content.type,data:{...content.data,apiOptions:sanitizedApiOptions}};case "article-section":return {type:content.type,data:{...content.data,apiOptions:sanitizedApiOptions}};case "article-all":return {type:content.type,data:{...content.data,apiOptions:sanitizedApiOptions}};case "exercise":return {type:content.type,data:{...content.data,apiOptions:sanitizedApiOptions}};default:throw new UnreachableCaseError(content)}}
|
|
1465
|
+
|
|
1466
|
+
function usePreviewController(iframeRef){const[height,setHeight]=React.useState(null);const[isIframeReady,setIsIframeReady]=React.useState(false);const pendingDataRef=React.useRef(null);React.useEffect(()=>{const handleMessage=event=>{if(iframeRef.current?.contentWindow==null||event.source!==iframeRef.current?.contentWindow){return}const message=event.data;if(!isIframeToParentMessage(message)){return}switch(message.type){case "iframe-ready":{if(pendingDataRef.current){const sanitizedData=sanitizePreviewData(pendingDataRef.current);const msg={source:PREVIEW_MESSAGE_SOURCE,type:"content-data",content:sanitizedData};iframeRef.current.contentWindow.postMessage(msg,"/");pendingDataRef.current=null;}setIsIframeReady(true);break}case "height-update":setHeight(message.height);break;default:throw new UnreachableCaseError(message)}};window.addEventListener("message",handleMessage);return ()=>{window.removeEventListener("message",handleMessage);}},[iframeRef]);const sendData=React.useCallback(data=>{if(!isIframeReady){pendingDataRef.current=data;return}const contentWindow=iframeRef.current?.contentWindow;if(!contentWindow){return}const sanitizedData=sanitizePreviewData(data);const message={source:PREVIEW_MESSAGE_SOURCE,type:"content-data",content:sanitizedData};contentWindow.postMessage(message,"/");},[iframeRef,isIframeReady]);return {sendData,height}}
|
|
1467
|
+
|
|
1468
|
+
function PreviewWithIframe(props){const iframeRef=React.useRef(null);const{sendData,height}=usePreviewController(iframeRef);React.useEffect(()=>{if(props.content!=null){sendData(props.content);}},[sendData,props.content]);const containerHeight=props.seamless&&height!=null?`${height}px`:"100%";return jsxRuntimeExports.jsx("iframe",{ref:iframeRef,title:`perseus-preview`,"data-mobile":String(props.isMobile),"data-lint-gutter":String(props.seamless),style:{width:"100%",height:containerHeight},src:props.url})}PreviewWithIframe.displayName="PreviewWithIframe";
|
|
1469
|
+
|
|
1460
1470
|
const chemParse=function(tokens,stateMachine){let str="";let expectedLoc=tokens[tokens.length-1].loc.start;for(let i=tokens.length-1;i>=0;i--){if(tokens[i].loc.start>expectedLoc){str+=" ";expectedLoc=tokens[i].loc.start;}str+=tokens[i].text;expectedLoc+=tokens[i].text.length;}const tex=texify.go(mhchemParser.go(str,stateMachine));return tex};var mhchemParser={go:function(input,stateMachine){if(!input){return []}if(stateMachine===undefined){stateMachine="ce";}let state="0";const buffer={};buffer["parenthesisLevel"]=0;input=input.replace(/\n/g," ");input=input.replace(/[\u2212\u2013\u2014\u2010]/g,"-");input=input.replace(/[\u2026]/g,"...");let lastInput;let watchdog=10;const output=[];while(true){if(lastInput!==input){watchdog=10;lastInput=input;}else {watchdog--;}const machine=mhchemParser.stateMachines[stateMachine];const t=machine.transitions[state]||machine.transitions["*"];iterateTransitions:for(let i=0;i<t.length;i++){const matches=mhchemParser.patterns.match_(t[i].pattern,input);if(matches){const task=t[i].task;for(let iA=0;iA<task.action_.length;iA++){var o;if(machine.actions[task.action_[iA].type_]){o=machine.actions[task.action_[iA].type_](buffer,matches.match_,task.action_[iA].option);}else if(mhchemParser.actions[task.action_[iA].type_]){o=mhchemParser.actions[task.action_[iA].type_](buffer,matches.match_,task.action_[iA].option);}else {throw ["MhchemBugA","mhchem bug A. Please report. ("+task.action_[iA].type_+")"]}mhchemParser.concatArray(output,o);}state=task.nextState||state;if(input.length>0){if(!task.revisit){input=matches.remainder;}if(!task.toContinue){break iterateTransitions}}else {return output}}}if(watchdog<=0){throw ["MhchemBugU","mhchem bug U. Please report."]}}},concatArray:function(a,b){if(b){if(Array.isArray(b)){for(let iB=0;iB<b.length;iB++){a.push(b[iB]);}}else {a.push(b);}}},patterns:{patterns:{empty:/^$/,else:/^./,else2:/^./,space:/^\s/,"space A":/^\s(?=[A-Z\\$])/,space$:/^\s$/,"a-z":/^[a-z]/,x:/^x/,x$:/^x$/,i$:/^i$/,letters:/^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/,"\\greek":/^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/,"one lowercase latin letter $":/^(?:([a-z])(?:$|[^a-zA-Z]))$/,"$one lowercase latin letter$ $":/^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,"one lowercase greek letter $":/^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/,digits:/^[0-9]+/,"-9.,9":/^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,"-9.,9 no missing 0":/^[+\-]?[0-9]+(?:[.,][0-9]+)?/,"(-)(9.,9)(e)(99)":function(input){const m=input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:([eE]|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/);if(m&&m[0]){return {match_:m.splice(1),remainder:input.substr(m[0].length)}}return null},"(-)(9)^(-9)":function(input){const m=input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);if(m&&m[0]){return {match_:m.splice(1),remainder:input.substr(m[0].length)}}return null},"state of aggregation $":function(input){const a=mhchemParser.patterns.findObserveGroups(input,"",/^\([a-z]{1,3}(?=[\),])/,")","");if(a&&a.remainder.match(/^($|[\s,;\)\]\}])/)){return a}const m=input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/);if(m){return {match_:m[0],remainder:input.substr(m[0].length)}}return null},"_{(state of aggregation)}$":/^_\{(\([a-z]{1,3}\))\}/,"{[(":/^(?:\\\{|\[|\()/,")]}":/^(?:\)|\]|\\\})/,", ":/^[,;]\s*/,",":/^[,;]/,".":/^[.]/,". ":/^([.\u22C5\u00B7\u2022])\s*/,"...":/^\.\.\.(?=$|[^.])/,"* ":/^([*])\s*/,"^{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^{","","","}")},"^($...$)":function(input){return mhchemParser.patterns.findObserveGroups(input,"^","$","$","")},"^a":/^\^([0-9]+|[^\\_])/,"^\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"^\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^",/^\\[a-zA-Z]+\{/,"}","")},"^\\x":/^\^(\\[a-zA-Z]+)\s*/,"^(-1)":/^\^(-?\d+)/,"'":/^'/,"_{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_{","","","}")},"_($...$)":function(input){return mhchemParser.patterns.findObserveGroups(input,"_","$","$","")},_9:/^_([+\-]?[0-9]+|[^\\])/,"_\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"_\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_",/^\\[a-zA-Z]+\{/,"}","")},"_\\x":/^_(\\[a-zA-Z]+)\s*/,"^_":/^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,"{}":/^\{\}/,"{...}":function(input){return mhchemParser.patterns.findObserveGroups(input,"","{","}","")},"{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"{","","","}")},"$...$":function(input){return mhchemParser.patterns.findObserveGroups(input,"","$","$","")},"${(...)}$":function(input){return mhchemParser.patterns.findObserveGroups(input,"${","","","}$")},"$(...)$":function(input){return mhchemParser.patterns.findObserveGroups(input,"$","","","$")},"=<>":/^[=<>]/,"#":/^[#\u2261]/,"+":/^\+/,"-$":/^-(?=[\s_},;\]/]|$|\([a-z]+\))/,"-9":/^-(?=[0-9])/,"- orbital overlap":/^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,"-":/^-/,"pm-operator":/^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,operator:/^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,arrowUpDown:/^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,"\\bond{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\bond{","","","}")},"->":/^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,CMT:/^[CMT](?=\[)/,"[(...)]":function(input){return mhchemParser.patterns.findObserveGroups(input,"[","","","]")},"1st-level escape":/^(&|\\\\|\\hline)\s*/,"\\,":/^(?:\\[,\ ;:])/,"\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"",/^\\[a-zA-Z]+\{/,"}","")},"\\ca":/^\\ca(?:\s+|(?![a-zA-Z]))/,"\\x":/^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,orbital:/^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,others:/^[\/~|]/,"\\frac{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\frac{","","","}","{","","","}")},"\\overset{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\overset{","","","}","{","","","}")},"\\underset{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\underset{","","","}","{","","","}")},"\\underbrace{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\underbrace{","","","}_","{","","","}")},"\\color{(...)}0":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color{","","","}")},"\\color{(...)}{(...)}1":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color{","","","}","{","","","}")},"\\color(...){(...)}2":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color","\\","",/^(?=\{)/,"{","","","}")},"\\ce{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\ce{","","","}")},oxidation$:/^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"d-oxidation$":/^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"roman numeral":/^[IVX]+/,"1/2$":/^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,amount:function(input){let match;match=input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}const a=mhchemParser.patterns.findObserveGroups(input,"","$","$","");if(a){match=a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}}return null},amount2:function(input){return this["amount"](input)},"(KV letters),":/^(?:[A-Z][a-z]{0,2}|i)(?=,)/,formula$:function(input){if(input.match(/^\([a-z]+\)$/)){return null}const match=input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}return null},uprightEntities:/^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,"/":/^\s*(\/)\s*/,"//":/^\s*(\/\/)\s*/,"*":/^\s*[*.]\s*/},findObserveGroups:function(input,begExcl,begIncl,endIncl,endExcl,beg2Excl,beg2Incl,end2Incl,end2Excl,combine){const _match=function(input,pattern){if(typeof pattern==="string"){if(input.indexOf(pattern)!==0){return null}return pattern}const match=input.match(pattern);if(!match){return null}return match[0]};const _findObserveGroups=function(input,i,endChars){let braces=0;while(i<input.length){const a=input.charAt(i);const match=_match(input.substr(i),endChars);if(match!==null&&braces===0){return {endMatchBegin:i,endMatchEnd:i+match.length}}if(a==="{"){braces++;}else if(a==="}"){if(braces===0){throw ["ExtraCloseMissingOpen","Extra close brace or missing open brace"]}else {braces--;}}i++;}if(braces>0){return null}return null};let match=_match(input,begExcl);if(match===null){return null}input=input.substr(match.length);match=_match(input,begIncl);if(match===null){return null}const e=_findObserveGroups(input,match.length,endIncl||endExcl);if(e===null){return null}const match1=input.substring(0,endIncl?e.endMatchEnd:e.endMatchBegin);if(!(beg2Excl||beg2Incl)){return {match_:match1,remainder:input.substr(e.endMatchEnd)}}const group2=this.findObserveGroups(input.substr(e.endMatchEnd),beg2Excl,beg2Incl,end2Incl,end2Excl);if(group2===null){return null}const matchRet=[match1,group2.match_];return {match_:combine?matchRet.join(""):matchRet,remainder:group2.remainder}},match_:function(m,input){const pattern=mhchemParser.patterns.patterns[m];if(pattern===undefined){throw ["MhchemBugP","mhchem bug P. Please report. ("+m+")"]}else if(typeof pattern==="function"){return mhchemParser.patterns.patterns[m](input)}else {const match=input.match(pattern);if(match){let mm;if(match[2]){mm=[match[1],match[2]];}else if(match[1]){mm=match[1];}else {mm=match[0];}return {match_:mm,remainder:input.substr(match[0].length)}}return null}}},actions:{"a=":function(buffer,m){buffer.a=(buffer.a||"")+m;},"b=":function(buffer,m){buffer.b=(buffer.b||"")+m;},"p=":function(buffer,m){buffer.p=(buffer.p||"")+m;},"o=":function(buffer,m){buffer.o=(buffer.o||"")+m;},"q=":function(buffer,m){buffer.q=(buffer.q||"")+m;},"d=":function(buffer,m){buffer.d=(buffer.d||"")+m;},"rm=":function(buffer,m){buffer.rm=(buffer.rm||"")+m;},"text=":function(buffer,m){buffer.text_=(buffer.text_||"")+m;},insert:function(buffer,m,a){return {type_:a}},"insert+p1":function(buffer,m,a){return {type_:a,p1:m}},"insert+p1+p2":function(buffer,m,a){return {type_:a,p1:m[0],p2:m[1]}},copy:function(buffer,m){return m},rm:function(buffer,m){return {type_:"rm",p1:m||""}},text:function(buffer,m){return mhchemParser.go(m,"text")},"{text}":function(buffer,m){const ret=["{"];mhchemParser.concatArray(ret,mhchemParser.go(m,"text"));ret.push("}");return ret},"tex-math":function(buffer,m){return mhchemParser.go(m,"tex-math")},"tex-math tight":function(buffer,m){return mhchemParser.go(m,"tex-math tight")},bond:function(buffer,m,k){return {type_:"bond",kind_:k||m}},"color0-output":function(buffer,m){return {type_:"color0",color:m[0]}},ce:function(buffer,m){return mhchemParser.go(m)},"1/2":function(buffer,m){const ret=[];if(m.match(/^[+\-]/)){ret.push(m.substr(0,1));m=m.substr(1);}const n=m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);n[1]=n[1].replace(/\$/g,"");ret.push({type_:"frac",p1:n[1],p2:n[2]});if(n[3]){n[3]=n[3].replace(/\$/g,"");ret.push({type_:"tex-math",p1:n[3]});}return ret},"9,9":function(buffer,m){return mhchemParser.go(m,"9,9")}},createTransitions:function(o){let pattern;let state;let stateArray;let i;const transitions={};for(pattern in o){for(state in o[pattern]){stateArray=state.split("|");o[pattern][state].stateArray=stateArray;for(i=0;i<stateArray.length;i++){transitions[stateArray[i]]=[];}}}for(pattern in o){for(state in o[pattern]){stateArray=o[pattern][state].stateArray||[];for(i=0;i<stateArray.length;i++){const p=o[pattern][state];if(p.action_){p.action_=[].concat(p.action_);for(let k=0;k<p.action_.length;k++){if(typeof p.action_[k]==="string"){p.action_[k]={type_:p.action_[k]};}}}else {p.action_=[];}const patternArray=pattern.split("|");for(let j=0;j<patternArray.length;j++){if(stateArray[i]==="*"){for(const t in transitions){transitions[t].push({pattern:patternArray[j],task:p});}}else {transitions[stateArray[i]].push({pattern:patternArray[j],task:p});}}}}}return transitions},stateMachines:{}};mhchemParser.stateMachines={ce:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},else:{"0|1|2":{action_:"beginsWithBond=false",revisit:true,toContinue:true}},oxidation$:{0:{action_:"oxidation-output"}},CMT:{r:{action_:"rdt=",nextState:"rt"},rd:{action_:"rqt=",nextState:"rdt"}},arrowUpDown:{"0|1|2|as":{action_:["sb=false","output","operator"],nextState:"1"}},uprightEntities:{"0|1|2":{action_:["o=","output"],nextState:"1"}},orbital:{"0|1|2|3":{action_:"o=",nextState:"o"}},"->":{"0|1|2|3":{action_:"r=",nextState:"r"},"a|as":{action_:["output","r="],nextState:"r"},"*":{action_:["output","r="],nextState:"r"}},"+":{o:{action_:"d= kv",nextState:"d"},"d|D":{action_:"d=",nextState:"d"},q:{action_:"d=",nextState:"qd"},"qd|qD":{action_:"d=",nextState:"qd"},dq:{action_:["output","d="],nextState:"d"},3:{action_:["sb=false","output","operator"],nextState:"0"}},amount:{"0|2":{action_:"a=",nextState:"a"}},"pm-operator":{"0|1|2|a|as":{action_:["sb=false","output",{type_:"operator",option:"\\pm"}],nextState:"0"}},operator:{"0|1|2|a|as":{action_:["sb=false","output","operator"],nextState:"0"}},"-$":{"o|q":{action_:["charge or bond","output"],nextState:"qd"},d:{action_:"d=",nextState:"d"},D:{action_:["output",{type_:"bond",option:"-"}],nextState:"3"},q:{action_:"d=",nextState:"qd"},qd:{action_:"d=",nextState:"qd"},"qD|dq":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},"-9":{"3|o":{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"3"}},"- orbital overlap":{o:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},d:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"}},"-":{"0|1|2":{action_:[{type_:"output",option:1},"beginsWithBond=true",{type_:"bond",option:"-"}],nextState:"3"},3:{action_:{type_:"bond",option:"-"}},a:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},as:{action_:[{type_:"output",option:2},{type_:"bond",option:"-"}],nextState:"3"},b:{action_:"b="},o:{action_:{type_:"- after o/d",option:false},nextState:"2"},q:{action_:{type_:"- after o/d",option:false},nextState:"2"},"d|qd|dq":{action_:{type_:"- after o/d",option:true},nextState:"2"},"D|qD|p":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},amount2:{"1|3":{action_:"a=",nextState:"a"}},letters:{"0|1|2|3|a|as|b|p|bp|o":{action_:"o=",nextState:"o"},"q|dq":{action_:["output","o="],nextState:"o"},"d|D|qd|qD":{action_:"o after d",nextState:"o"}},digits:{o:{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},q:{action_:["output","o="],nextState:"o"},a:{action_:"o=",nextState:"o"}},"space A":{"b|p|bp":{}},space:{a:{nextState:"as"},0:{action_:"sb=false"},"1|2":{action_:"sb=true"},"r|rt|rd|rdt|rdq":{action_:"output",nextState:"0"},"*":{action_:["output","sb=true"],nextState:"1"}},"1st-level escape":{"1|2":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}]},"*":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}],nextState:"0"}},"[(...)]":{"r|rt":{action_:"rd=",nextState:"rd"},"rd|rdt":{action_:"rq=",nextState:"rdq"}},"...":{"o|d|D|dq|qd|qD":{action_:["output",{type_:"bond",option:"..."}],nextState:"3"},"*":{action_:[{type_:"output",option:1},{type_:"insert",option:"ellipsis"}],nextState:"1"}},". |* ":{"*":{action_:["output",{type_:"insert",option:"addition compound"}],nextState:"1"}},"state of aggregation $":{"*":{action_:["output","state of aggregation"],nextState:"1"}},"{[(":{"a|as|o":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"0|1|2|3":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"*":{action_:["output","o=","output","parenthesisLevel++"],nextState:"2"}},")]}":{"0|1|2|3|b|p|bp|o":{action_:["o=","parenthesisLevel--"],nextState:"o"},"a|as|d|D|q|qd|qD|dq":{action_:["output","o=","parenthesisLevel--"],nextState:"o"}},", ":{"*":{action_:["output","comma"],nextState:"0"}},"^_":{"*":{}},"^{(...)}|^($...$)":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"D"},q:{action_:"d=",nextState:"qD"},"d|D|qd|qD|dq":{action_:["output","d="],nextState:"D"}},"^a|^\\x{}{}|^\\x{}|^\\x|'":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"d"},q:{action_:"d=",nextState:"qd"},"d|qd|D|qD":{action_:"d="},dq:{action_:["output","d="],nextState:"d"}},"_{(state of aggregation)}$":{"d|D|q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x":{"0|1|2|as":{action_:"p=",nextState:"p"},b:{action_:"p=",nextState:"bp"},"3|o":{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},"q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"=<>":{"0|1|2|3|a|as|o|q|d|D|qd|qD|dq":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"#":{"0|1|2|3|a|as|o":{action_:[{type_:"output",option:2},{type_:"bond",option:"#"}],nextState:"3"}},"{}":{"*":{action_:{type_:"output",option:1},nextState:"1"}},"{...}":{"0|1|2|3|a|as|b|p|bp":{action_:"o=",nextState:"o"},"o|d|D|q|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"$...$":{a:{action_:"a="},"0|1|2|3|as|b|p|bp|o":{action_:"o=",nextState:"o"},"as|o":{action_:"o="},"q|d|D|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"\\bond{(...)}":{"*":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"\\frac{(...)}":{"*":{action_:[{type_:"output",option:1},"frac-output"],nextState:"3"}},"\\overset{(...)}":{"*":{action_:[{type_:"output",option:2},"overset-output"],nextState:"3"}},"\\underset{(...)}":{"*":{action_:[{type_:"output",option:2},"underset-output"],nextState:"3"}},"\\underbrace{(...)}":{"*":{action_:[{type_:"output",option:2},"underbrace-output"],nextState:"3"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:[{type_:"output",option:2},"color-output"],nextState:"3"}},"\\color{(...)}0":{"*":{action_:[{type_:"output",option:2},"color0-output"]}},"\\ce{(...)}":{"*":{action_:[{type_:"output",option:2},"ce"],nextState:"3"}},"\\,":{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"1"}},"\\x{}{}|\\x{}|\\x":{"0|1|2|3|a|as|b|p|bp|o|c0":{action_:["o=","output"],nextState:"3"},"*":{action_:["output","o=","output"],nextState:"3"}},others:{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"3"}},else2:{a:{action_:"a to o",nextState:"o",revisit:true},as:{action_:["output","sb=true"],nextState:"1",revisit:true},"r|rt|rd|rdt|rdq":{action_:["output"],nextState:"0",revisit:true},"*":{action_:["output","copy"],nextState:"3"}}}),actions:{"o after d":function(buffer,m){let ret;if((buffer.d||"").match(/^[0-9]+$/)){const tmp=buffer.d;buffer.d=undefined;ret=this["output"](buffer);buffer.b=tmp;}else {ret=this["output"](buffer);}mhchemParser.actions["o="](buffer,m);return ret},"d= kv":function(buffer,m){buffer.d=m;buffer.dType="kv";},"charge or bond":function(buffer,m){if(buffer["beginsWithBond"]){const ret=[];mhchemParser.concatArray(ret,this["output"](buffer));mhchemParser.concatArray(ret,mhchemParser.actions["bond"](buffer,m,"-"));return ret}buffer.d=m;},"- after o/d":function(buffer,m,isAfterD){let c1=mhchemParser.patterns.match_("orbital",buffer.o||"");const c2=mhchemParser.patterns.match_("one lowercase greek letter $",buffer.o||"");const c3=mhchemParser.patterns.match_("one lowercase latin letter $",buffer.o||"");const c4=mhchemParser.patterns.match_("$one lowercase latin letter$ $",buffer.o||"");const hyphenFollows=m==="-"&&(c1&&c1.remainder===""||c2||c3||c4);if(hyphenFollows&&!buffer.a&&!buffer.b&&!buffer.p&&!buffer.d&&!buffer.q&&!c1&&c3){buffer.o="$"+buffer.o+"$";}const ret=[];if(hyphenFollows){mhchemParser.concatArray(ret,this["output"](buffer));ret.push({type_:"hyphen"});}else {c1=mhchemParser.patterns.match_("digits",buffer.d||"");if(isAfterD&&c1&&c1.remainder===""){mhchemParser.concatArray(ret,mhchemParser.actions["d="](buffer,m));mhchemParser.concatArray(ret,this["output"](buffer));}else {mhchemParser.concatArray(ret,this["output"](buffer));mhchemParser.concatArray(ret,mhchemParser.actions["bond"](buffer,m,"-"));}}return ret},"a to o":function(buffer){buffer.o=buffer.a;buffer.a=undefined;},"sb=true":function(buffer){buffer.sb=true;},"sb=false":function(buffer){buffer.sb=false;},"beginsWithBond=true":function(buffer){buffer["beginsWithBond"]=true;},"beginsWithBond=false":function(buffer){buffer["beginsWithBond"]=false;},"parenthesisLevel++":function(buffer){buffer["parenthesisLevel"]++;},"parenthesisLevel--":function(buffer){buffer["parenthesisLevel"]--;},"state of aggregation":function(buffer,m){return {type_:"state of aggregation",p1:mhchemParser.go(m,"o")}},comma:function(buffer,m){const a=m.replace(/\s*$/,"");const withSpace=a!==m;if(withSpace&&buffer["parenthesisLevel"]===0){return {type_:"comma enumeration L",p1:a}}return {type_:"comma enumeration M",p1:a}},output:function(buffer,m,entityFollows){let ret;if(!buffer.r){ret=[];if(!buffer.a&&!buffer.b&&!buffer.p&&!buffer.o&&!buffer.q&&!buffer.d&&!entityFollows);else {if(buffer.sb){ret.push({type_:"entitySkip"});}if(!buffer.o&&!buffer.q&&!buffer.d&&!buffer.b&&!buffer.p&&entityFollows!==2){buffer.o=buffer.a;buffer.a=undefined;}else if(!buffer.o&&!buffer.q&&!buffer.d&&(buffer.b||buffer.p)){buffer.o=buffer.a;buffer.d=buffer.b;buffer.q=buffer.p;buffer.a=buffer.b=buffer.p=undefined;}else {if(buffer.o&&buffer.dType==="kv"&&mhchemParser.patterns.match_("d-oxidation$",buffer.d||"")){buffer.dType="oxidation";}else if(buffer.o&&buffer.dType==="kv"&&!buffer.q){buffer.dType=undefined;}}ret.push({type_:"chemfive",a:mhchemParser.go(buffer.a,"a"),b:mhchemParser.go(buffer.b,"bd"),p:mhchemParser.go(buffer.p,"pq"),o:mhchemParser.go(buffer.o,"o"),q:mhchemParser.go(buffer.q,"pq"),d:mhchemParser.go(buffer.d,buffer.dType==="oxidation"?"oxidation":"bd"),dType:buffer.dType});}}else {let rd;if(buffer.rdt==="M"){rd=mhchemParser.go(buffer.rd,"tex-math");}else if(buffer.rdt==="T"){rd=[{type_:"text",p1:buffer.rd||""}];}else {rd=mhchemParser.go(buffer.rd);}let rq;if(buffer.rqt==="M"){rq=mhchemParser.go(buffer.rq,"tex-math");}else if(buffer.rqt==="T"){rq=[{type_:"text",p1:buffer.rq||""}];}else {rq=mhchemParser.go(buffer.rq);}ret={type_:"arrow",r:buffer.r,rd:rd,rq:rq};}for(const p in buffer){if(p!=="parenthesisLevel"&&p!=="beginsWithBond"){delete buffer[p];}}return ret},"oxidation-output":function(buffer,m){const ret=["{"];mhchemParser.concatArray(ret,mhchemParser.go(m,"oxidation"));ret.push("}");return ret},"frac-output":function(buffer,m){return {type_:"frac-ce",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"overset-output":function(buffer,m){return {type_:"overset",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"underset-output":function(buffer,m){return {type_:"underset",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"underbrace-output":function(buffer,m){return {type_:"underbrace",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1])}},"r=":function(buffer,m){buffer.r=m;},"rdt=":function(buffer,m){buffer.rdt=m;},"rd=":function(buffer,m){buffer.rd=m;},"rqt=":function(buffer,m){buffer.rqt=m;},"rq=":function(buffer,m){buffer.rq=m;},operator:function(buffer,m,p1){return {type_:"operator",kind_:p1||m}}}},a:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:true}},"$(...)$":{"*":{action_:"tex-math tight",nextState:"1"}},",":{"*":{action_:{type_:"insert",option:"commaDecimal"}}},else2:{"*":{action_:"copy"}}}),actions:{}},o:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:true}},letters:{"*":{action_:"rm"}},"\\ca":{"*":{action_:{type_:"insert",option:"circa"}}},"\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"{text}"}},else2:{"*":{action_:"copy"}}}),actions:{}},text:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"{...}":{"*":{action_:"text="}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"\\greek":{"*":{action_:["output","rm"]}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:["output","copy"]}},else:{"*":{action_:"text="}}}),actions:{output:function(buffer){if(buffer.text_){const ret={type_:"text",p1:buffer.text_};for(const p in buffer){delete buffer[p];}return ret}}}},pq:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"state of aggregation $":{"*":{action_:"state of aggregation"}},i$:{0:{nextState:"!f",revisit:true}},"(KV letters),":{0:{action_:"rm",nextState:"0"}},formula$:{0:{nextState:"f",revisit:true}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"!f",revisit:true}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"a-z":{f:{action_:"tex-math"}},letters:{"*":{action_:"rm"}},"-9.,9":{"*":{action_:"9,9"}},",":{"*":{action_:{type_:"insert+p1",option:"comma enumeration S"}}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"state of aggregation":function(buffer,m){return {type_:"state of aggregation subscript",p1:mhchemParser.go(m,"o")}},"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1],"pq")}}}},bd:{transitions:mhchemParser.createTransitions({empty:{"*":{}},x$:{0:{nextState:"!f",revisit:true}},formula$:{0:{nextState:"f",revisit:true}},else:{0:{nextState:"!f",revisit:true}},"-9.,9 no missing 0":{"*":{action_:"9,9"}},".":{"*":{action_:{type_:"insert",option:"electron dot"}}},"a-z":{f:{action_:"tex-math"}},x:{"*":{action_:{type_:"insert",option:"KV x"}}},letters:{"*":{action_:"rm"}},"'":{"*":{action_:{type_:"insert",option:"prime"}}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1],"bd")}}}},oxidation:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"roman numeral":{"*":{action_:"roman-numeral"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},else:{"*":{action_:"copy"}}}),actions:{"roman-numeral":function(buffer,m){return {type_:"roman numeral",p1:m||""}}}},"tex-math":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},else:{"*":{action_:"o="}}}),actions:{output:function(buffer){if(buffer.o){const ret={type_:"tex-math",p1:buffer.o};for(const p in buffer){delete buffer[p];}return ret}}}},"tex-math tight":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},"-|+":{"*":{action_:"tight operator"}},else:{"*":{action_:"o="}}}),actions:{"tight operator":function(buffer,m){buffer.o=(buffer.o||"")+"{"+m+"}";},output:function(buffer){if(buffer.o){const ret={type_:"tex-math",p1:buffer.o};for(const p in buffer){delete buffer[p];}return ret}}}},"9,9":{transitions:mhchemParser.createTransitions({empty:{"*":{}},",":{"*":{action_:"comma"}},else:{"*":{action_:"copy"}}}),actions:{comma:function(){return {type_:"commaDecimal"}}}},pu:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},space$:{"*":{action_:["output","space"]}},"{[(|)]}":{"0|a":{action_:"copy"}},"(-)(9)^(-9)":{0:{action_:"number^",nextState:"a"}},"(-)(9.,9)(e)(99)":{0:{action_:"enumber",nextState:"a"}},space:{"0|a":{}},"pm-operator":{"0|a":{action_:{type_:"operator",option:"\\pm"},nextState:"0"}},operator:{"0|a":{action_:"copy",nextState:"0"}},"//":{d:{action_:"o=",nextState:"/"}},"/":{d:{action_:"o=",nextState:"/"}},"{...}|else":{"0|d":{action_:"d=",nextState:"d"},a:{action_:["space","d="],nextState:"d"},"/|q":{action_:"q=",nextState:"q"}}}),actions:{enumber:function(buffer,m){const ret=[];if(m[0]==="+-"||m[0]==="+/-"){ret.push("\\pm ");}else if(m[0]){ret.push(m[0]);}if(m[1]){mhchemParser.concatArray(ret,mhchemParser.go(m[1],"pu-9,9"));if(m[2]){if(m[2].match(/[,.]/)){mhchemParser.concatArray(ret,mhchemParser.go(m[2],"pu-9,9"));}else {ret.push(m[2]);}}m[3]=m[4]||m[3];if(m[3]){m[3]=m[3].trim();if(m[3]==="e"||m[3].substr(0,1)==="*"){ret.push({type_:"cdot"});}else {ret.push({type_:"times"});}}}if(m[3]){ret.push("10^{"+m[5]+"}");}return ret},"number^":function(buffer,m){const ret=[];if(m[0]==="+-"||m[0]==="+/-"){ret.push("\\pm ");}else if(m[0]){ret.push(m[0]);}mhchemParser.concatArray(ret,mhchemParser.go(m[1],"pu-9,9"));ret.push("^{"+m[2]+"}");return ret},operator:function(buffer,m,p1){return {type_:"operator",kind_:p1||m}},space:function(){return {type_:"pu-space-1"}},output:function(buffer){let ret;const md=mhchemParser.patterns.match_("{(...)}",buffer.d||"");if(md&&md.remainder===""){buffer.d=md.match_;}const mq=mhchemParser.patterns.match_("{(...)}",buffer.q||"");if(mq&&mq.remainder===""){buffer.q=mq.match_;}if(buffer.d){buffer.d=buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C");buffer.d=buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");}if(buffer.q){buffer.q=buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C");buffer.q=buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");const b5={d:mhchemParser.go(buffer.d,"pu"),q:mhchemParser.go(buffer.q,"pu")};if(buffer.o==="//"){ret={type_:"pu-frac",p1:b5.d,p2:b5.q};}else {ret=b5.d;if(b5.d.length>1||b5.q.length>1){ret.push({type_:" / "});}else {ret.push({type_:"/"});}mhchemParser.concatArray(ret,b5.q);}}else {ret=mhchemParser.go(buffer.d,"pu-2");}for(const p in buffer){delete buffer[p];}return ret}}},"pu-2":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"*":{"*":{action_:["output","cdot"],nextState:"0"}},"\\x":{"*":{action_:"rm="}},space:{"*":{action_:["output","space"],nextState:"0"}},"^{(...)}|^(-1)":{1:{action_:"^(-1)"}},"-9.,9":{0:{action_:"rm=",nextState:"0"},1:{action_:"^(-1)",nextState:"0"}},"{...}|else":{"*":{action_:"rm=",nextState:"1"}}}),actions:{cdot:function(){return {type_:"tight cdot"}},"^(-1)":function(buffer,m){buffer.rm+="^{"+m+"}";},space:function(){return {type_:"pu-space-2"}},output:function(buffer){let ret=[];if(buffer.rm){const mrm=mhchemParser.patterns.match_("{(...)}",buffer.rm||"");if(mrm&&mrm.remainder===""){ret=mhchemParser.go(mrm.match_,"pu");}else {ret={type_:"rm",p1:buffer.rm};}}for(const p in buffer){delete buffer[p];}return ret}}},"pu-9,9":{transitions:mhchemParser.createTransitions({empty:{0:{action_:"output-0"},o:{action_:"output-o"}},",":{0:{action_:["output-0","comma"],nextState:"o"}},".":{0:{action_:["output-0","copy"],nextState:"o"}},else:{"*":{action_:"text="}}}),actions:{comma:function(){return {type_:"commaDecimal"}},"output-0":function(buffer){const ret=[];buffer.text_=buffer.text_||"";if(buffer.text_.length>4){let a=buffer.text_.length%3;if(a===0){a=3;}for(let i=buffer.text_.length-3;i>0;i-=3){ret.push(buffer.text_.substr(i,3));ret.push({type_:"1000 separator"});}ret.push(buffer.text_.substr(0,a));ret.reverse();}else {ret.push(buffer.text_);}for(const p in buffer){delete buffer[p];}return ret},"output-o":function(buffer){const ret=[];buffer.text_=buffer.text_||"";if(buffer.text_.length>4){const a=buffer.text_.length-3;for(var i=0;i<a;i+=3){ret.push(buffer.text_.substr(i,3));ret.push({type_:"1000 separator"});}ret.push(buffer.text_.substr(i));}else {ret.push(buffer.text_);}for(const p in buffer){delete buffer[p];}return ret}}}};var texify={go:function(input,isInner){if(!input){return ""}let res="";let cee=false;for(let i=0;i<input.length;i++){const inputi=input[i];if(typeof inputi==="string"){res+=inputi;}else {res+=texify._go2(inputi);if(inputi.type_==="1st-level escape"){cee=true;}}}if(!isInner&&!cee&&res){res="{"+res+"}";}return res},_goInner:function(input){if(!input){return input}return texify.go(input,true)},_go2:function(buf){let res;switch(buf.type_){case "chemfive":res="";var b5={a:texify._goInner(buf.a),b:texify._goInner(buf.b),p:texify._goInner(buf.p),o:texify._goInner(buf.o),q:texify._goInner(buf.q),d:texify._goInner(buf.d)};if(b5.a){if(b5.a.match(/^[+\-]/)){b5.a="{"+b5.a+"}";}res+=b5.a+"\\,";}if(b5.b||b5.p){res+="{\\vphantom{X}}";res+="^{\\hphantom{"+(b5.b||"")+"}}_{\\hphantom{"+(b5.p||"")+"}}";res+="{\\vphantom{X}}";res+="^{\\smash[t]{\\vphantom{2}}\\mathllap{"+(b5.b||"")+"}}";res+="_{\\vphantom{2}\\mathllap{\\smash[t]{"+(b5.p||"")+"}}}";}if(b5.o){if(b5.o.match(/^[+\-]/)){b5.o="{"+b5.o+"}";}res+=b5.o;}if(buf.dType==="kv"){if(b5.d||b5.q){res+="{\\vphantom{X}}";}if(b5.d){res+="^{"+b5.d+"}";}if(b5.q){res+="_{\\smash[t]{"+b5.q+"}}";}}else if(buf.dType==="oxidation"){if(b5.d){res+="{\\vphantom{X}}";res+="^{"+b5.d+"}";}if(b5.q){res+="{\\vphantom{X}}";res+="_{\\smash[t]{"+b5.q+"}}";}}else {if(b5.q){res+="{\\vphantom{X}}";res+="_{\\smash[t]{"+b5.q+"}}";}if(b5.d){res+="{\\vphantom{X}}";res+="^{"+b5.d+"}";}}break;case "rm":res="\\mathrm{"+buf.p1+"}";break;case "text":if(buf.p1.match(/[\^_]/)){buf.p1=buf.p1.replace(" ","~").replace("-","\\text{-}");res="\\mathrm{"+buf.p1+"}";}else {res="\\text{"+buf.p1+"}";}break;case "roman numeral":res="\\mathrm{"+buf.p1+"}";break;case "state of aggregation":res="\\mskip2mu "+texify._goInner(buf.p1);break;case "state of aggregation subscript":res="\\mskip1mu "+texify._goInner(buf.p1);break;case "bond":res=texify._getBond(buf.kind_);if(!res){throw ["MhchemErrorBond","mhchem Error. Unknown bond type ("+buf.kind_+")"]}break;case "frac":var c="\\frac{"+buf.p1+"}{"+buf.p2+"}";res="\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}";break;case "pu-frac":var d="\\frac{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";res="\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}";break;case "tex-math":res=buf.p1+" ";break;case "frac-ce":res="\\frac{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "overset":res="\\overset{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "underset":res="\\underset{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "underbrace":res="\\underbrace{"+texify._goInner(buf.p1)+"}_{"+texify._goInner(buf.p2)+"}";break;case "color":res="{\\color{"+buf.color1+"}{"+texify._goInner(buf.color2)+"}}";break;case "color0":res="\\color{"+buf.color+"}";break;case "arrow":var b6={rd:texify._goInner(buf.rd),rq:texify._goInner(buf.rq)};var arrow="\\x"+texify._getArrow(buf.r);if(b6.rq){arrow+="[{"+b6.rq+"}]";}if(b6.rd){arrow+="{"+b6.rd+"}";}else {arrow+="{}";}res=arrow;break;case "operator":res=texify._getOperator(buf.kind_);break;case "1st-level escape":res=buf.p1+" ";break;case "space":res=" ";break;case "entitySkip":res="~";break;case "pu-space-1":res="~";break;case "pu-space-2":res="\\mkern3mu ";break;case "1000 separator":res="\\mkern2mu ";break;case "commaDecimal":res="{,}";break;case "comma enumeration L":res="{"+buf.p1+"}\\mkern6mu ";break;case "comma enumeration M":res="{"+buf.p1+"}\\mkern3mu ";break;case "comma enumeration S":res="{"+buf.p1+"}\\mkern1mu ";break;case "hyphen":res="\\text{-}";break;case "addition compound":res="\\,{\\cdot}\\,";break;case "electron dot":res="\\mkern1mu \\bullet\\mkern1mu ";break;case "KV x":res="{\\times}";break;case "prime":res="\\prime ";break;case "cdot":res="\\cdot ";break;case "tight cdot":res="\\mkern1mu{\\cdot}\\mkern1mu ";break;case "times":res="\\times ";break;case "circa":res="{\\sim}";break;case "^":res="uparrow";break;case "v":res="downarrow";break;case "ellipsis":res="\\ldots ";break;case "/":res="/";break;case " / ":res="\\,/\\,";break;default:throw ["MhchemBugT","mhchem bug T. Please report."]}return res},_getArrow:function(a){switch(a){case "->":return "rightarrow";case "→":return "rightarrow";case "⟶":return "rightarrow";case "<-":return "leftarrow";case "<->":return "leftrightarrow";case "<-->":return "rightleftarrows";case "<=>":return "rightleftharpoons";case "⇌":return "rightleftharpoons";case "<=>>":return "rightequilibrium";case "<<=>":return "leftequilibrium";default:throw ["MhchemBugT","mhchem bug T. Please report."]}},_getBond:function(a){switch(a){case "-":return "{-}";case "1":return "{-}";case "=":return "{=}";case "2":return "{=}";case "#":return "{\\equiv}";case "3":return "{\\equiv}";case "~":return "{\\tripledash}";case "~-":return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";case "~=":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";case "~--":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";case "-~-":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";case "...":return "{{\\cdot}{\\cdot}{\\cdot}}";case "....":return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";case "->":return "{\\rightarrow}";case "<-":return "{\\leftarrow}";case "<":return "{<}";case ">":return "{>}";default:throw ["MhchemBugT","mhchem bug T. Please report."]}},_getOperator:function(a){switch(a){case "+":return " {}+{} ";case "-":return " {}-{} ";case "=":return " {}={} ";case "<":return " {}<{} ";case ">":return " {}>{} ";case "<<":return " {}\\ll{} ";case ">>":return " {}\\gg{} ";case "\\pm":return " {}\\pm{} ";case "\\approx":return " {}\\approx{} ";case "$\\approx$":return " {}\\approx{} ";case "v":return " \\downarrow{} ";case "(v)":return " \\downarrow{} ";case "^":return " \\uparrow{} ";case "(^)":return " \\uparrow{} ";default:throw ["MhchemBugT","mhchem bug T. Please report."]}}};
|
|
1461
1471
|
|
|
1462
1472
|
katex.__defineMacro("\\ce",function(context){return chemParse(context.consumeArgs(1)[0],"ce")});katex.__defineMacro("\\pu",function(context){return chemParse(context.consumeArgs(1)[0],"pu")});katex.__defineMacro("\\tripledash","{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu"+"\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}");
|
|
1463
1473
|
|
|
1464
1474
|
function detectTexErrors(content){const errors=[];const ast=PerseusMarkdown.parse(content,{});PerseusMarkdown.traverseContent(ast,node=>{if(node.type==="math"||node.type==="blockMath"){const texContent=preprocessTex(node.content);try{katex.renderToString(texContent,{colorIsTextColor:true});}catch(e){errors.push({math:texContent,message:e.message});}}});return errors}
|
|
1465
1475
|
|
|
1466
|
-
const{HUD: HUD$1}=components;class ArticleEditor extends React.Component{componentDidMount(){this._updateIssues();
|
|
1476
|
+
const{HUD: HUD$1}=components;class ArticleEditor extends React.Component{componentDidMount(){this._updateIssues();}componentDidUpdate(prevProps){if(prevProps.json!==this.props.json){this._updateIssues();}}_updateIssues(){const issues=this._sections().map(section=>{const parsed=PerseusMarkdown.parse(section.content??"",{});const linterContext={content:section.content,widgets:section.widgets,stack:[]};const sectionIssues=PerseusLinter.runLinter(parsed,linterContext,false)?.map(linterWarning=>{if(linterWarning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(linterWarning.metadata?.widgetType??"unknown",linterWarning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(linterWarning.rule,linterWarning.message,linterWarning.severity)})??[];const texErrors=detectTexErrors(section.content??"");const texIssues=texErrors.map((error,index)=>WARNINGS.texError(error.math,error.message,index));return [...texIssues,...sectionIssues]});this.setState({issues});}_previewDataForSection(section,sectionIndex){const editor=this.refs[`editor${sectionIndex}`];return {article:section,apiOptions:this._apiOptionsForPreview(),linterContext:{contentType:"article",highlightLint:this.state.highlightLint},legacyPerseusLint:editor?.getSaveWarnings()??[]}}_apiOptionsForPreview(){return {...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true}}_sections(){const json=this.props.json;return json instanceof Array?json:[json]}_renderEditor(){const{imageUploader,sectionImageUploadGenerator}=this.props;const apiOptions={...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true};const sections=this._sections();const editingDisabled=this.props.apiOptions?.editingDisabled??false;const isMobile=this._isMobilePreview();return jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[sections.map((section,i)=>{return [jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsxs("fieldset",{disabled:editingDisabled,children:[jsxRuntimeExports.jsx(IssuesPanel,{issues:this.state.issues[i]}),jsxRuntimeExports.jsxs("div",{className:"pod-title",children:["Section ",i+1,jsxRuntimeExports.jsxs("div",{style:{display:"inline-block",float:"right"},children:[sectionImageUploadGenerator(i),jsxRuntimeExports.jsx(SectionControlButton,{icon:plusIcon,disabled:editingDisabled,onClick:()=>{this._handleAddSectionAfter(i);},title:"Add a new section after this one"}),i+1<sections.length&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleDownIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionLater(i);},title:"Move this section down"}),i>0&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleUpIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionEarlier(i);},title:"Move this section up"}),jsxRuntimeExports.jsx(SectionControlButton,{icon:trashIcon,disabled:editingDisabled,onClick:()=>{const msg="Are you sure you "+"want to delete section "+(i+1)+"?";if(confirm(msg)){this._handleRemoveSection(i);}},title:"Delete this section"})]})]}),jsxRuntimeExports.jsx(Editor,{...section,apiOptions:apiOptions,imageUploader:imageUploader,onChange:newProps=>this._handleEditorChange(i,newProps),placeholder:"Type your section text here...",ref:"editor"+i})]})}),jsxRuntimeExports.jsx("div",{className:"editor-preview",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.screen,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:{type:"article-section",data:this._previewDataForSection(section,i)}},`${String(i)}-${this.props.screen}`)})})]},i)]}),this._renderAddSection(editingDisabled),this._renderLinterHUD()]})}_renderAddSection(editingDisabled){return jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,disabled:editingDisabled,kind:"tertiary","aria-label":"Add a section",onClick:()=>{this._handleAddSectionAfter(this._sections().length-1);},children:"Add a section"})})})}_renderLinterHUD(){return jsxRuntimeExports.jsx(HUD$1,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})}_renderPreviewMode(){return jsxRuntimeExports.jsx("div",{className:"standalone-preview",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.screen,nochrome:false,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:this._isMobilePreview(),seamless:false,url:this.props.previewURL,content:{type:"article-all",data:{article:this._sections(),apiOptions:this._apiOptionsForPreview()}}},`all-${this.props.screen}`)})})}_isMobilePreview(){return this.props.screen==="phone"||this.props.screen==="tablet"}_handleMoveSectionEarlier(i){if(i===0){return}const sections=[...this._sections()];const section=sections[i];sections.splice(i,1);sections.splice(i-1,0,section);this.props.onChange({json:sections});}_handleMoveSectionLater(i){const sections=[...this._sections()];if(i+1===sections.length){return}const section=sections[i];sections.splice(i,1);sections.splice(i+1,0,section);this.props.onChange({json:sections});}_handleAddSectionAfter(i){const clonedArticle=this.serialize();const sections=clonedArticle instanceof Array?clonedArticle:[clonedArticle];const newSection={content:"",images:{},widgets:i>=0?sections[i].widgets:{}};sections.splice(i+1,0,newSection);this.props.onChange({json:sections});}_handleRemoveSection(i){const sections=[...this._sections()];sections.splice(i,1);this.props.onChange({json:sections});}serialize(){if(this.props.mode==="edit"){return this._sections().map((section,i)=>{return this.refs["editor"+i].serialize()})}if(this.props.mode==="preview"||this.props.mode==="json"){return this.props.json}throw new PerseusError("Could not serialize; mode "+this.props.mode+" not found",Errors.Internal)}getSaveWarnings(){if(this.props.mode!=="edit"){throw new PerseusError("Can only get save warnings in edit mode.",Errors.NotAllowed)}return this._sections().map((section,i)=>{return this.refs["editor"+i].getSaveWarnings()})}render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:"framework-perseus perseus-article-editor",children:[this.props.mode==="edit"&&this._renderEditor(),this.props.mode==="preview"&&this._renderPreviewMode(),this.props.mode==="json"&&jsxRuntimeExports.jsxs("div",{className:"json-editor",children:[jsxRuntimeExports.jsx("div",{className:"json-editor-warning",children:jsxRuntimeExports.jsx("span",{children:"Warning: Editing in this mode can lead to broken articles!"})}),jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,onChange:this._handleJsonChange,value:this.props.json,parser:parseAndMigratePerseusArticle,editingDisabled:editingDisabled})]})]})})}constructor(...args){super(...args),this.state={highlightLint:true,issues:[]},this._handleJsonChange=newJson=>{this.props.onChange({json:newJson});},this._handleEditorChange=(i,newProps)=>{const sections=[...this._sections()];sections[i]={...sections[i],...newProps};this.props.onChange({json:sections});};}}ArticleEditor.defaultProps={json:[{content:"",widgets:{},images:{}}],mode:"edit",screen:"desktop",sectionImageUploadGenerator:()=>jsxRuntimeExports.jsx("span",{})};
|
|
1467
1477
|
|
|
1468
1478
|
const iconChevronRight={path:"M62.808 49.728q0 3.36-2.352 5.88l-41.72 41.664q-2.352 2.408-5.768 2.408t-5.768-2.408l-4.872-4.76q-2.352-2.52-2.352-5.88t2.352-5.712l31.08-31.136-31.08-31.024q-2.352-2.52-2.352-5.88t2.352-5.712l4.872-4.76q2.296-2.408 5.768-2.408t5.768 2.408l41.72 41.664q2.352 2.296 2.352 5.656z",width:63.034,height:100};const iconCircleArrowDown={path:"M50.046 83.676q1.767 0 2.907-1.14l29.526-29.526q1.197-1.197 1.197-2.907t-1.197-2.964l-5.928-5.928q-1.197-1.14-2.964-1.14t-2.907 1.14l-12.312 12.312l0-32.661q0-1.71-1.254-2.964t-2.907-1.254l-8.322 0q-1.71 0-2.964 1.254t-1.254 2.964l0 32.661l-12.312-12.312q-1.197-1.254-2.907-1.254t-2.907 1.254l-5.928 5.928q-1.197 1.197-1.197 2.964t1.197 2.907l29.469 29.526q1.197 1.14 2.964 1.14zm49.989-33.63q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",width:100,height:100};const iconCircleArrowUp={path:"M54.207 83.391q1.653 0 2.907-1.254t1.254-2.907l0-32.718l12.312 12.312q1.254 1.254 2.964 1.254t2.907-1.254l5.928-5.928q1.197-1.197 1.14-2.964 0-1.767-1.14-2.907l-29.526-29.526q-1.197-1.14-2.907-1.14t-2.964 1.14l-29.469 29.526q-1.197 1.254-1.197 2.964t1.197 2.907l5.928 5.928q1.197 1.197 2.907 1.197t2.907-1.197l12.312-12.312l0 32.718q0 1.653 1.254 2.907t2.964 1.254l8.322 0zm45.828-33.345q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",width:100,height:100};const iconDesktop={path:"M94.208 52.119l0-43.746q0-.69-.506-1.15t-1.196-.506l-84.088 0q-.69 0-1.196.506t-.506 1.15l0 43.746q0 .69.506 1.196t1.196.506l84.088 0q.69 0 1.196-.506t.506-1.196zm6.716-43.746l0 57.224q0 3.45-2.484 5.934t-5.934 2.484l-28.566 0q0 3.128 2.53 7.774.828 1.61.828 2.622t-1.012 2.07q-1.012 1.012-2.346.966l-26.91 0q-1.38 0-2.392-1.012t-1.012-2.024q0-1.058 1.656-4.14t1.748-6.256l-28.612 0q-3.45 0-5.934-2.484t-2.484-5.934l0-57.224q0-3.45 2.484-5.934t5.934-2.438l84.088 0q3.45 0 5.98 2.438 2.438 2.484 2.438 5.934z",width:100,height:86.648};const iconMobilePhone={path:"M36.04 89.557q0-2.584-1.836-4.42t-4.42-1.836-4.352 1.836q-1.836 1.836-1.836 4.42t1.836 4.352 4.42 1.836q2.652-.068 4.42-1.836t1.768-4.352zm16.184-12.444l0-54.74q0-1.088-.748-1.768t-1.768-.68l-39.78 0q-1.088 0-1.768.748t-.68 1.7l0 54.74q0 1.02.748 1.768t1.7.68l39.78 0q1.02-.068 1.768-.748t.748-1.7zm-14.892-65.892q0-1.224-1.292-1.292l-12.444 0q-1.224.068-1.224 1.292t1.224 1.224l12.444 0q1.292 0 1.292-1.224zm22.372-1.292l0 79.628q0 3.944-2.992 6.936t-7.004 2.992l-39.78 0q-4.012 0-7.004-2.924-2.924-2.924-2.924-7.004l0-79.628q0-4.012 2.924-6.936t7.004-2.992l39.78 0q4.012-.068 7.004 2.924t2.992 7.004z",width:60.013,height:100};const iconPlus={path:"M99.758 43.09l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-29.45 0l0 29.45q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-29.45l-29.45 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l29.45 0l0-29.45q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836l0 29.45l29.45 0q2.852 0 4.836 1.984t1.984 4.836z",width:100,height:100};const iconTablet={path:"M45.322 90.706q0-1.86-1.302-3.224-1.364-1.364-3.224-1.364t-3.224 1.364-1.302 3.224q0 1.86 1.364 3.224 1.302 1.364 3.162 1.302 1.86.062 3.224-1.302t1.302-3.224zm27.218-11.346l0-68.014q0-.93-.682-1.612t-1.55-.682l-58.962 0q-.93 0-1.612.682t-.682 1.612l0 68.014q0 .93.682 1.612t1.612.62l58.962 0q.992-.062 1.612-.682t.62-1.55zm9.114-68.014l0 77.066q0 4.65-3.348 7.998t-7.998 3.348l-58.962 0q-4.65 0-7.998-3.348t-3.348-7.998l0-77.066q0-4.65 3.348-7.998t7.998-3.348l58.962 0q4.65 0 7.998 3.348t3.348 7.998z",width:81.852,height:100};
|
|
1469
1479
|
|
|
@@ -1493,11 +1503,11 @@ class AnswerAreaDiff extends React.Component{render(){const{after,before,title}=
|
|
|
1493
1503
|
|
|
1494
1504
|
class ItemDiff extends React.Component{render(){const{before,after}=this.props;const hintCount=Math.max(before.hints.length,after.hints.length);const question=jsxRuntimeExports.jsx(RendererDiff,{before:before.question,after:after.question,title:"Question",showAlignmentOptions:false,showSeparator:true});const extras=jsxRuntimeExports.jsx(AnswerAreaDiff,{before:before.answerArea?before.answerArea:undefined,after:after.answerArea?after.answerArea:undefined,title:"Question extras"});const hints=_.times(hintCount,function(n){return jsxRuntimeExports.jsx(RendererDiff,{before:n<before.hints.length?before.hints[n]:undefined,after:n<after.hints.length?after.hints[n]:undefined,title:`Hint ${n+1}`,showAlignmentOptions:false,showSeparator:n<hintCount-1},n)});return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:"framework-perseus",children:[question,extras,hints.length>0&&jsxRuntimeExports.jsx("div",{className:"diff-separator"}),hints]})})}}
|
|
1495
1505
|
|
|
1496
|
-
const{InfoTip: InfoTip$o,InlineIcon: InlineIcon$2}=components;class HintEditor extends React.Component{serialize(){invariant(this.editor.current,"cannot serialize HintEditor with no Editor");return {...this.editor.current.serialize(),replace:this.props.replace??undefined}}render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor "+this.props.className,children:[this.props.showTitle&&jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,apiOptions:this.props.apiOptions,widgets:this.props.widgets||undefined,content:this.props.content||undefined,images:this.props.images,placeholder:"Type your hint here...",imageUploader:this.props.imageUploader,onChange:this.props.onChange,widgetIsOpen:this.props.widgetIsOpen},this.props.itemId),jsxRuntimeExports.jsxs("div",{className:"hint-controls-container clearfix",children:[this.props.showMoveButtons&&jsxRuntimeExports.jsxs("span",{className:"reorder-hints",children:[jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isLast?"hidden":"",onClick:_.partial(this.props.onMove,1),children:jsxRuntimeExports.jsx(InlineIcon$2,{...iconCircleArrowDown})})," ",jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isFirst?"hidden":"",onClick:_.partial(this.props.onMove,-1),children:jsxRuntimeExports.jsx(InlineIcon$2,{...iconCircleArrowUp})})," ",this.props.isLast&&jsxRuntimeExports.jsx(InfoTip$o,{children:jsxRuntimeExports.jsx("p",{children:"The last hint is automatically bolded."})})]}),jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.replace,onChange:this.handleReplaceChanged}),"Replace previous hint",this.props.showRemoveButton&&jsxRuntimeExports.jsxs("button",{type:"button",className:"remove-hint simple-button orange",onClick:this.props.onRemove,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconTrash}),"Remove this hint"," "]})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.handleReplaceChanged=e=>{this.props.onChange({replace:e.target.checked});},this.focus=()=>{this.editor.current?.focus();},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()};}}HintEditor.defaultProps={className:"",content:"",replace:false,showMoveButtons:true,showTitle:true,showRemoveButton:true};class CombinedHintEditor extends React.Component{
|
|
1506
|
+
const{InfoTip: InfoTip$o,InlineIcon: InlineIcon$2}=components;class HintEditor extends React.Component{serialize(){invariant(this.editor.current,"cannot serialize HintEditor with no Editor");return {...this.editor.current.serialize(),replace:this.props.replace??undefined}}render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor "+this.props.className,children:[this.props.showTitle&&jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,apiOptions:this.props.apiOptions,widgets:this.props.widgets||undefined,content:this.props.content||undefined,images:this.props.images,placeholder:"Type your hint here...",imageUploader:this.props.imageUploader,onChange:this.props.onChange,widgetIsOpen:this.props.widgetIsOpen},this.props.itemId),jsxRuntimeExports.jsxs("div",{className:"hint-controls-container clearfix",children:[this.props.showMoveButtons&&jsxRuntimeExports.jsxs("span",{className:"reorder-hints",children:[jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isLast?"hidden":"",onClick:_.partial(this.props.onMove,1),children:jsxRuntimeExports.jsx(InlineIcon$2,{...iconCircleArrowDown})})," ",jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isFirst?"hidden":"",onClick:_.partial(this.props.onMove,-1),children:jsxRuntimeExports.jsx(InlineIcon$2,{...iconCircleArrowUp})})," ",this.props.isLast&&jsxRuntimeExports.jsx(InfoTip$o,{children:jsxRuntimeExports.jsx("p",{children:"The last hint is automatically bolded."})})]}),jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.replace,onChange:this.handleReplaceChanged}),"Replace previous hint",this.props.showRemoveButton&&jsxRuntimeExports.jsxs("button",{type:"button",className:"remove-hint simple-button orange",onClick:this.props.onRemove,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconTrash}),"Remove this hint"," "]})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.handleReplaceChanged=e=>{this.props.onChange({replace:e.target.checked});},this.focus=()=>{this.editor.current?.focus();},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()};}}HintEditor.defaultProps={className:"",content:"",replace:false,showMoveButtons:true,showTitle:true,showRemoveButton:true};class CombinedHintEditor extends React.Component{serialize(){invariant(this.editor.current,"cannot serialize CombinedHintEditor with no HintEditor");return this.editor.current.serialize()}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";return jsxRuntimeExports.jsxs("div",{className:"perseus-combined-hint-editor "+"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(HintEditor,{ref:this.editor,itemId:this.props.itemId,isFirst:this.props.isFirst,isLast:this.props.isLast,widgets:this.props.hint.widgets,content:this.props.hint.content,images:this.props.hint.images,replace:this.props.hint.replace,imageUploader:this.props.imageUploader,onChange:this.props.onChange,onRemove:this.props.onRemove,onMove:this.props.onMove,apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:{type:"hint",data:{hint:this.props.hint,pos:this.props.pos,apiOptions:this.props.apiOptions||ApiOptions.defaults,linterContext:{contentType:"hint",highlightLint:this.props.highlightLint}}}})})})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.focus=()=>{this.editor.current?.focus();};}}class CombinedHintsEditor extends React.Component{handleHintChange(i,newProps){const hints=[...this.props.hints];hints[i]=_.extend({},this.serializeHint(i),newProps);this.props.onChange({hints:hints});}handleHintRemove(i){if(!confirm("Are you sure you want to delete this hint?")){return}const hints=[...this.props.hints];hints.splice(i,1);this.props.onChange({hints:hints});}handleHintMove(i,dir){const hints=[...this.props.hints];const hint=hints.splice(i,1)[0];hints.splice(i+dir,0,hint);this.props.onChange({hints:hints});}serialize(){return this.props.hints.map((_,i)=>this.serializeHint(i))}serializeHint(index){return this.refs["hintEditor"+index].serialize()}render(){const{itemId,hints}=this.props;const editingDisabled=this.props.apiOptions?.editingDisabled??false;const hintElems=_.map(hints,(hint,i)=>{return jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(CombinedHintEditor,{ref:"hintEditor"+i,isFirst:i===0,isLast:i+1===hints.length,itemId:itemId,hint:hint,pos:i,imageUploader:this.props.imageUploader,onChange:this.handleHintChange.bind(this,i),onRemove:this.handleHintRemove.bind(this,i),onMove:this.handleHintMove.bind(this,i),deviceType:this.props.deviceType,apiOptions:this.props.apiOptions,highlightLint:this.props.highlightLint,previewURL:this.props.previewURL,widgetIsOpen:this.props.widgetIsOpen})},"hintEditor"+i)},this);return jsxRuntimeExports.jsxs("div",{className:"perseus-hints-editor perseus-editor-table",children:[hintElems,jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"add-hint-container perseus-editor-left-cell",children:jsxRuntimeExports.jsxs("button",{type:"button",className:"add-hint simple-button orange",disabled:editingDisabled,onClick:this.addHint,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconPlus})," Add a hint"]})})})]})}constructor(...args){super(...args),this.addHint=()=>{const hint={content:"",images:{},widgets:{}};const hints=[...this.props.hints,hint];this.props.onChange({hints:hints});},this.getSaveWarnings=()=>{return _.chain(this.props.hints).map((hint,i)=>{return _.map(this.refs["hintEditor"+i].getSaveWarnings(),issue=>"Hint "+(i+1)+": "+issue)}).flatten(true).value()};}}CombinedHintsEditor.HintEditor=HintEditor;CombinedHintsEditor.defaultProps={hints:[],onChange:()=>{}};
|
|
1497
1507
|
|
|
1498
1508
|
const calculatorVariants=[{label:"Scientific calculator",tip:"Provides the student with a scientific calculator.",variant:"scientific"},{label:"Graphing calculator",tip:"Provides the student with a graphing calculator.",variant:"graphing"},{label:"Four-function calculator",tip:"Provides the student with a four-function calculator.",variant:"four_function"}];const{InfoTip: InfoTip$n}=components;class ItemExtrasEditor extends React.Component{shouldShowCalculatorVariants(){return this.props.calculatorVariant!==undefined}shouldShowFinancialCalculatorOptions(){return this.props.financialCalculatorMonthlyPayment||this.props.financialCalculatorTotalAmount||this.props.financialCalculatorTimeToPayOff}serialize(){const data={...ItemExtrasEditor.defaultProps};for(const key of ItemExtras){data[key]=!!this.props[key];}data.calculatorVariant=this.props.calculatorVariant;return data}render(){const{editingDisabled}=this.props;return jsxRuntimeExports.jsx("div",{className:"perseus-answer-editor",children:jsxRuntimeExports.jsxs("div",{className:"perseus-answer-options",children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show calculator",disabled:editingDisabled,infoTip:"Use the calculator when completing difficult calculations is NOT the intent of the question. DON’T use the calculator when testing the student’s ability to complete different types of computations.",checked:this.shouldShowCalculatorVariants(),onChange:newCheckedState=>{this.props.onChange({calculator:newCheckedState,calculatorVariant:newCheckedState?"scientific":undefined});}}),isFeatureOn(this.props,"desmos-calculator")&&this.shouldShowCalculatorVariants()&&calculatorVariants.map(calcVariant=>jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:calcVariant.label,disabled:editingDisabled,infoTip:calcVariant.tip,checked:this.props.calculatorVariant===calcVariant.variant,onChange:()=>{this.props.onChange({calculatorVariant:calcVariant.variant});},indent:true},calcVariant.variant)),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show financial calculator",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a financial calculator, e.g., for answering financial questions. Once checked, requires at least one of the three options below to be checked.",checked:this.shouldShowFinancialCalculatorOptions(),onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState,financialCalculatorTotalAmount:newCheckedState,financialCalculatorTimeToPayOff:newCheckedState});}}),this.shouldShowFinancialCalculatorOptions()&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include monthly payment",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a monthly payment calculator; e.g., given a loan amount, interest rate, and term, what is the monthly payment?",checked:this.props.financialCalculatorMonthlyPayment,onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include total amount",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a total amount calculator; e.g., given a monthly payment, interest rate, and term, what is the total amount to be paid?",checked:this.props.financialCalculatorTotalAmount,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTotalAmount:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include time-to-pay-off",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a time to pay off calculator; e.g., given a loan amount, interest rate, and monthly payment, how long will it take to pay off the loan?",checked:this.props.financialCalculatorTimeToPayOff,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTimeToPayOff:newCheckedState});},indent:true})]}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show periodic table",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a periodic table of the elements, e.g., for answering chemistry questions.",checked:this.props.periodicTable,onChange:newCheckedState=>{this.props.onChange({periodicTable:newCheckedState,periodicTableWithKey:false});}}),this.props.periodicTable&&jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include key/legend with periodic table",disabled:editingDisabled,infoTip:"Include a key for HS courses; omit for AP chemistry.",checked:this.props.periodicTableWithKey,onChange:newCheckedState=>{this.props.onChange({periodicTableWithKey:newCheckedState});},indent:true})]})})}}ItemExtrasEditor.defaultProps=getDefaultAnswerArea();const ItemExtraCheckbox=props=>jsxRuntimeExports.jsx(View,{style:[styles$O.checkbox,props.indent?styles$O.indented:undefined],children:jsxRuntimeExports.jsx(Checkbox$1,{disabled:props.disabled,label:jsxRuntimeExports.jsxs(View,{style:{flexDirection:"row"},children:[props.label," ",jsxRuntimeExports.jsx(InfoTip$n,{children:props.infoTip})]}),checked:props.checked,onChange:newCheckedState=>props.onChange(newCheckedState)})});const styles$O=StyleSheet.create({indented:{marginInlineStart:spacing.large_24}});
|
|
1499
1509
|
|
|
1500
|
-
class ItemEditor extends React.Component{serialize(){invariant(this.questionEditor.current,"cannot serialize ItemEditor without Editor");invariant(this.itemExtrasEditor.current,"cannot serialize ItemEditor without ItemExtrasEditor");return {question:this.questionEditor.current.serialize(),answerArea:this.itemExtrasEditor.current.serialize()}}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-question-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question"}),jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(Editor,{ref:this.questionEditor,placeholder:"Type your question here...",className:"perseus-question-editor",imageUploader:this.props.imageUploader,onChange:this.handleEditorChange,apiOptions:this.props.apiOptions,showWordCount:true,widgetIsOpen:this.props.widgetIsOpen,additionalTemplates:this.props.additionalTemplates,...this.props.question},this.props.itemId)})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx("div",{id:"problemarea",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(
|
|
1510
|
+
class ItemEditor extends React.Component{serialize(){invariant(this.questionEditor.current,"cannot serialize ItemEditor without Editor");invariant(this.itemExtrasEditor.current,"cannot serialize ItemEditor without ItemExtrasEditor");return {question:this.questionEditor.current.serialize(),answerArea:this.itemExtrasEditor.current.serialize()}}_derivePreviewContent(){const question=this.props.question;if(!question){return null}return {type:"question",data:{question,apiOptions:{...ApiOptions.defaults,...this.props.apiOptions,customKeypad:this.props.deviceType==="phone"||this.props.deviceType==="tablet"},linterContext:{contentType:"exercise",highlightLint:this.props.highlightLint},reviewMode:true,legacyPerseusLint:this.getSaveWarnings(),problemNum:this.props.problemNum}}}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-question-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question"}),jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(Editor,{ref:this.questionEditor,placeholder:"Type your question here...",className:"perseus-question-editor",imageUploader:this.props.imageUploader,onChange:this.handleEditorChange,apiOptions:this.props.apiOptions,showWordCount:true,widgetIsOpen:this.props.widgetIsOpen,additionalTemplates:this.props.additionalTemplates,...this.props.question},this.props.itemId)})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx("div",{id:"problemarea",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:this._derivePreviewContent()},this.props.deviceType)})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-answer-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question extras"}),jsxRuntimeExports.jsx(ItemExtrasEditor,{ref:this.itemExtrasEditor,apiOptions:this.props.apiOptions,onChange:this.handleItemExtrasChange,editingDisabled:editingDisabled,...this.props.answerArea})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell"})]})]})})}constructor(...args){super(...args),this.questionEditor=React.createRef(),this.itemExtrasEditor=React.createRef(),this.updateProps=newProps=>{const props=_(this.props).pick("question","answerArea");this.props.onChange(_(props).extend(newProps));},this.handleEditorChange=newProps=>{const question=_.extend({},this.props.question,newProps);this.updateProps({question});},this.handleItemExtrasChange=newProps=>{const answerArea=_.extend({},this.props.answerArea,newProps);this.updateProps({answerArea});},this.getSaveWarnings=()=>{return this.questionEditor.current?.getSaveWarnings()};}}ItemEditor.defaultProps={onChange:()=>{},question:{},answerArea:{}};
|
|
1501
1511
|
|
|
1502
1512
|
var issuesList = {"axe-core":{"user-fixable":["aria-input-field-name","aria-meter-name","aria-toggle-field-name","image-alt","input-image-alt","label","link-name","list","role-img-alt","select-name","summary-name","svg-img-alt","video-caption"]}};
|
|
1503
1513
|
|
|
@@ -1505,21 +1515,13 @@ const assistanceNeededMessage="Developer assistance needed - Please send this ex
|
|
|
1505
1515
|
|
|
1506
1516
|
function lintRenderer(content,widgets){const parsed=PerseusMarkdown.parse(content,{});const linterContext={content,widgets,stack:[]};const linterIssues=(PerseusLinter.runLinter(parsed,linterContext,false)??[]).map(warning=>{if(warning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(warning.metadata?.widgetType??"unknown",warning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(warning.rule,warning.message,warning.severity)});const texIssues=detectTexErrors(content).map((error,i)=>WARNINGS.texError(error.math,error.message,i));return [...linterIssues,...texIssues]}function gatherLinterIssues(question,hints,hostIssues){const questionIssues=lintRenderer(question?.content??"",question?.widgets);const hintIssues=hints.flatMap((hint,i)=>lintRenderer(hint.content??"",hint.widgets??undefined).map(issue=>({...issue,id:`hint-${i+1}-${issue.id}`,message:`Hint ${i+1}: ${issue.message}`})));return [...hostIssues??[],...questionIssues,...hintIssues]}
|
|
1507
1517
|
|
|
1508
|
-
const{HUD}=components;class EditorPage extends React.Component{componentDidMount(){this.
|
|
1509
|
-
|
|
1510
|
-
function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice,reviewMode}){const i18n=usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(View,{className:`framework-perseus ${className}`,style:[styles$N.container,!seamless?styles$N.gutter:undefined],children:jsxRuntimeExports.jsx(StatefulKeypadContextProvider,{children:jsxRuntimeExports.jsx(KeypadContext.Consumer,{children:({setKeypadActive,keypadElement,setKeypadElement})=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(UserInputManager,{widgets:question?.widgets||{},problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,reviewMode:reviewMode,...question})}),jsxRuntimeExports.jsx(MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$N=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginRight:lintGutterWidth}});
|
|
1511
|
-
|
|
1512
|
-
const PREVIEW_MESSAGE_SOURCE="perseus-preview";function createPreviewIframeReadyMessage(){return {source:PREVIEW_MESSAGE_SOURCE,type:"iframe-ready"}}
|
|
1513
|
-
|
|
1514
|
-
function isIframeToParentMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&typeof message.source==="string"&&message.source===PREVIEW_MESSAGE_SOURCE}function isParentToIframeMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&typeof message.source==="string"&&message.source===PREVIEW_MESSAGE_SOURCE}
|
|
1515
|
-
|
|
1516
|
-
function sanitizeApiOptions(apiOptions){if(apiOptions==null){return null}const{onFocusChange:_,answerableCallback:__,getAnotherHint:___,interactionCallback:____,trackInteraction:_____,baseElements:_______,imagePlaceholder:_________,widgetPlaceholder:__________,...serializableOptions}=apiOptions;return serializableOptions}
|
|
1518
|
+
const{HUD}=components;class EditorPage extends React.Component{componentDidMount(){this.setState({issues:gatherLinterIssues(this.props.question,this.props.hints,this.props.issues)});}getSnapshotBeforeUpdate(prevProps,prevState){if(!prevProps.jsonMode&&this.props.jsonMode){return {...this.itemEditor.current?.serialize()??{},hints:this.hintsEditor.current?.serialize()}}return null}componentDidUpdate(previousProps,prevState,snapshot){if(snapshot){this.setState({json:snapshot});return}if(!_.isEqual(previousProps.question,this.props.question)||!_.isEqual(previousProps.answerArea,this.props.answerArea)||!_.isEqual(previousProps.hints,this.props.hints)){this.syncJsonStateFromProps();}const questionOrHintsChanged=previousProps.question?.content!==this.props.question?.content||previousProps.question?.widgets!==this.props.question?.widgets||!_.isEqual(previousProps.hints,this.props.hints);if(questionOrHintsChanged){this.setState({issues:gatherLinterIssues(this.props.question,this.props.hints,this.props.issues)});this.a11yCheckerTimeoutId=runAxeCoreOnUpdate(this.a11yCheckerTimeoutId,axeCoreIssues=>this.setState({axeCoreIssues}),this.state.showAxeCoreIssues);}}componentWillUnmount(){clearTimeout(this.a11yCheckerTimeoutId);}syncJsonStateFromProps(){this.setState({json:{question:this.props.question,answerArea:this.props.answerArea,hints:this.props.hints}});}getApiOptions(){return {...ApiOptions.defaults,...this.props.apiOptions}}getSaveWarnings(){const issues1=this.itemEditor.current?.getSaveWarnings();const issues2=this.hintsEditor.current?.getSaveWarnings();return issues1.concat(issues2)}serialize(){if(this.props.jsonMode){return this.state.json}invariant(this.itemEditor.current,"cannot serialize EditorPage without ItemEditor");invariant(this.hintsEditor.current,"cannot serialize EditorPage without HintsEditor");return {...this.itemEditor.current.serialize(),hints:this.hintsEditor.current.serialize()}}render(){let className="framework-perseus";const editingDisabled=this.props.apiOptions?.editingDisabled??false;const touch=this.props.previewDevice==="phone"||this.props.previewDevice==="tablet";const deviceBasedApiOptions={...this.getApiOptions(),customKeypad:touch,isMobile:touch};const showEditor=!this.props.developerMode||!this.props.jsonMode;if(deviceBasedApiOptions.isMobile){className+=" "+ClassNames.MOBILE;}return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{id:"perseus",className:className,children:[jsxRuntimeExports.jsxs("div",{style:{marginBottom:10},children:[this.props.developerMode&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Developer JSON Mode:"," ",jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.jsonMode,disabled:this.props.apiOptions?.editingDisabled,onChange:this.toggleJsonMode})]})," "]}),!this.props.jsonMode&&jsxRuntimeExports.jsx(ViewportResizer,{deviceType:this.props.previewDevice,onViewportSizeChanged:this.props.onPreviewDeviceChange}),!this.props.jsonMode&&jsxRuntimeExports.jsx(HUD,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})]}),this.props.developerMode&&this.props.jsonMode&&jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,value:this.state.json,parser:parseAndMigratePerseusItem,onChange:this.changeJSON,editingDisabled:editingDisabled})}),showEditor&&jsxRuntimeExports.jsx("div",{className:"perseus-editor-table",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(IssuesPanel,{issues:this.state.issues.concat(this.state.showAxeCoreIssues?this.state.axeCoreIssues:[]),a11yCheck:{callback:()=>this.setState({showAxeCoreIssues:!this.state.showAxeCoreIssues}),isChecked:this.state.showAxeCoreIssues}})})})}),showEditor&&jsxRuntimeExports.jsx(ItemEditor,{ref:this.itemEditor,itemId:this.props.itemId,question:this.props.question,answerArea:this.props.answerArea,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,widgetIsOpen:this.state.widgetsAreOpen,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,additionalTemplates:this.props.additionalTemplates,highlightLint:this.state.highlightLint,problemNum:this.props.problemNum}),showEditor&&jsxRuntimeExports.jsx(CombinedHintsEditor,{ref:this.hintsEditor,itemId:this.props.itemId,hints:this.props.hints,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,highlightLint:this.state.highlightLint,widgetIsOpen:this.state.widgetsAreOpen})]})})}constructor(props){super(props),this.itemEditor=React.createRef(),this.hintsEditor=React.createRef(),this.toggleJsonMode=()=>{this.setState({json:this.serialize()},()=>{this.props.onChange({jsonMode:!this.props.jsonMode});});},this.handleChange=toChange=>{const newProps=_(this.props).pick("question","hints","answerArea");_(newProps).extend(toChange);this.props.onChange(newProps);},this.changeJSON=newJson=>{this.setState({json:newJson});this.props.onChange(newJson);};this.state={json:_.pick(this.props,"question","answerArea","hints"),highlightLint:true,widgetsAreOpen:this.props.widgetsAreOpen??true,issues:[],axeCoreIssues:[],showAxeCoreIssues:false};}}EditorPage.defaultProps={answerArea:getDefaultAnswerArea(),developerMode:false,hints:[],jsonMode:false,onChange:()=>{}};
|
|
1517
1519
|
|
|
1518
|
-
|
|
1520
|
+
let nextIframeID=0;const requestIframeData={};const updateIframeHeight={};window.iframeDataStore={};window.addEventListener("message",event=>{if(typeof event.data==="string"){const callback=requestIframeData[event.data];if(callback){callback();}}else if(event.data.id){if(event.data.height!==undefined){updateIframeHeight[event.data.id](event.data.height);}else if(event.data.lintWarnings){Log.log("LINTER REPORT",{lintWarnings:JSON.stringify(event.data.lintWarnings)});}}});class IframeContentRenderer extends React.Component{componentDidMount(){this._isMounted=true;this.iframeID=nextIframeID;nextIframeID++;this._prepareFrame();requestIframeData[this.iframeID]=()=>{this.sendNewData(this._lastData);};updateIframeHeight[this.iframeID]=height=>{this._lastHeight=height;if(this._isMounted&&this.props.seamless&&this.container.current){this.container.current.style.height=height+"px";}};}shouldComponentUpdate(nextProps){return nextProps.datasetValue!==this.props.datasetValue||nextProps.seamless!==this.props.seamless}componentDidUpdate(prevProps){if(this.container.current){if(!this.props.seamless){this.container.current.style.height="100%";}else {this.container.current.style.height=this._lastHeight+"px";}}if(prevProps.datasetValue!==this.props.datasetValue){this._prepareFrame();}}componentWillUnmount(){requestIframeData[this.iframeID]=null;updateIframeHeight[this.iframeID]=null;this._isMounted=false;}_prepareFrame(){if(this._frame){this.container.current?.removeChild(this._frame);}const frame=document.createElement("iframe");frame.style.width="100%";frame.style.height="100%";frame.dataset.name="content-preview";frame.src=this.props.url;frame.onload=()=>{const iframeDoc=frame.contentDocument||frame.contentWindow?.document;if(iframeDoc){const axeCoreScriptElement=iframeDoc.createElement("script");axeCoreScriptElement.src="https://unpkg.com/axe-core@4.11.0/axe.js";iframeDoc.body.appendChild(axeCoreScriptElement);}else {console.warn("Unable to add axe-core to iframe document");}};if(this.props.datasetKey){frame.dataset[this.props.datasetKey]=this.props.datasetValue;}frame.dataset.id=String(this.iframeID);if(this.props.seamless){frame.dataset.lintGutter="true";}this.container.current?.appendChild(frame);this._frame=frame;}sendNewData(data){const frame=this._frame;if(this._isMounted&&data&&frame?.contentWindow){this._lastData=data;window.iframeDataStore[this.iframeID]=data;frame.contentWindow.postMessage(this.iframeID,"*");}}render(){return jsxRuntimeExports.jsx("div",{ref:this.container,style:{width:"100%",height:"100%"}})}constructor(...args){super(...args),this.container=React.createRef();}}
|
|
1519
1521
|
|
|
1520
|
-
function
|
|
1522
|
+
function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice,reviewMode}){const i18n=usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(View,{className:`framework-perseus ${className}`,style:[styles$N.container,!seamless?styles$N.gutter:undefined],children:jsxRuntimeExports.jsx(StatefulKeypadContextProvider,{children:jsxRuntimeExports.jsx(KeypadContext.Consumer,{children:({setKeypadActive,keypadElement,setKeypadElement})=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(UserInputManager,{widgets:question?.widgets||{},problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,reviewMode:reviewMode,...question})}),jsxRuntimeExports.jsx(MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$N=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginRight:lintGutterWidth}});
|
|
1521
1523
|
|
|
1522
|
-
function usePreviewPresenter(){const[
|
|
1524
|
+
function usePreviewPresenter(){const[content,setContent]=React.useState(null);const iframe=window.frameElement;if(iframe==null){throw new Error("usePreviewPresenter must be used within an iframe")}React.useEffect(()=>{const handleMessage=event=>{if(event.source!==window.parent){return}const message=event.data;if(!isParentToIframeMessage(message)){return}switch(message.type){case "content-data":setContent(message.content);break;default:throw new UnreachableCaseError(message.type)}};window.addEventListener("message",handleMessage);window.parent.postMessage(createPreviewIframeReadyMessage(),"/");return ()=>{window.removeEventListener("message",handleMessage);}},[]);const reportHeight=React.useCallback(height=>{if(window.parent==null){return}const message={source:PREVIEW_MESSAGE_SOURCE,type:"height-update",height};window.parent.postMessage(message,"/");},[]);return {content,isMobile:iframe.dataset.mobile==="true",hasLintGutter:iframe.dataset.lintGutter==="true",reportHeight}}
|
|
1523
1525
|
|
|
1524
1526
|
const{TextListEditor: TextListEditor$4}=components;const Categorizer=Categorizer$1.widget;class CategorizerEditor extends React.Component{render(){const categorizerProps={items:this.props.items,categories:this.props.categories,userInput:{values:this.props.values},handleUserInput:userInput=>{this.props.onChange({values:userInput.values});},apiOptions:this.props.apiOptions,trackInteraction:function(){}};return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Randomize item order",checked:this.props.randomizeItems,onChange:value=>{this.props.onChange({randomizeItems:value});}})}),"Categories:",jsxRuntimeExports.jsx(TextListEditor$4,{options:this.props.categories,onChange:cat=>{this.change("categories",cat);},layout:"horizontal"}),"Items:",jsxRuntimeExports.jsx(TextListEditor$4,{options:this.props.items,onChange:items=>{this.change({items:items,values:_.first(this.props.values,items.length)});},layout:"vertical"}),jsxRuntimeExports.jsx(Categorizer,{...categorizerProps})]})}constructor(...args){super(...args),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}CategorizerEditor.propTypes={...Changeable.propTypes,apiOptions:ApiOptions.propTypes,items:PropTypes.arrayOf(PropTypes.string),categories:PropTypes.arrayOf(PropTypes.string),values:PropTypes.arrayOf(PropTypes.number),randomizeItems:PropTypes.bool};CategorizerEditor.widgetName="categorizer";CategorizerEditor.defaultProps=categorizerLogic.defaultWidgetOptions;
|
|
1525
1527
|
|
|
@@ -1538,9 +1540,9 @@ const{TextInput: TextInput$5}=components;class ExplanationEditor extends React.C
|
|
|
1538
1540
|
var styles$M = {"paddedX":"perseus_xyIPJvSm","paddedY":"perseus_6B-8VzAW","answerOption":"perseus_SHUAvRqo","buttonRow":"perseus_yBc0LCPb","buttonSets":"perseus_h0zeeqNR","answersSubtitle":"perseus_xbG0OWq1","answersGroup":"perseus_XphVr0Eg","answersList":"perseus_-z--eTDm","deleteButton":"perseus_UuEVVICK"};
|
|
1539
1541
|
|
|
1540
1542
|
const{ButtonGroup: ButtonGroup$7,InfoTip: InfoTip$k}=components;const buttonSetsList=["basic","trig","prealgebra","logarithms","scientific","basic relations","advanced relations"];class ExpressionEditor extends React.Component{serialize(){const{answerForms,buttonSets,functions,times,visibleLabel,ariaLabel}=this.props;return {answerForms,buttonSets,functions,times,visibleLabel,ariaLabel,extraKeys:deriveExtraKeys(this.props)}}updateAnswerForm(index,answerFormProps){const answerForms=this.props.answerForms.slice();answerForms[index]=answerFormProps;const{extraKeys:_,...restProps}=this.props;const extraKeys=deriveExtraKeys({...restProps,answerForms});this.props.onChange({answerForms,extraKeys});}changeSimplify(index,simplify){const answerForm={...this.props.answerForms[index],simplify};this.updateAnswerForm(index,answerForm);}changeForm(index,form){const answerForm={...this.props.answerForms[index],form};this.updateAnswerForm(index,answerForm);}changeConsidered(index,considered){const answerForm={...this.props.answerForms[index],considered};this.updateAnswerForm(index,answerForm);}changeTimes(times){this.props.onChange({times:times});}render(){const editingDisabled=this.props.apiOptions.editingDisabled??false;const answerOptions=this.props.answerForms.map((ans,index)=>{const expressionProps={times:this.props.times,functions:this.props.functions,buttonSets:this.props.buttonSets,buttonsVisible:"focused",userInput:ans.value,handleUserInput:input=>this.changeExpressionWidget(index,input),trackInteraction:()=>{},widgetId:this.props.widgetId+"-"+ans.key,visibleLabel:this.props.visibleLabel,ariaLabel:this.props.ariaLabel};return jsxRuntimeExports.jsx(AnswerOption,{considered:ans.considered,editingDisabled:editingDisabled,expressionProps:expressionProps,form:ans.form,simplify:ans.simplify,onDelete:()=>this.handleRemoveForm(index),onChangeSimplify:simplify=>this.changeSimplify(index,simplify),onChangeForm:form=>this.changeForm(index,form),onChangeConsidered:considered=>this.changeConsidered(index,considered)},ans.key)});const buttonSetChoices=buttonSetsList.map(name=>{const isBasic=name==="basic";const checked=this.props.buttonSets.includes(name)||isBasic;return jsxRuntimeExports.jsx(Checkbox$1,{label:name,checked:checked,disabled:isBasic,onChange:()=>this.handleButtonSet(name)},name)});buttonSetChoices.unshift(jsxRuntimeExports.jsx(Checkbox$1,{label:"show ÷ button",checked:this.props.buttonSets.includes("basic+div"),onChange:this.handleToggleDiv},"show ÷ button"));return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Heading$1,{size:"medium",children:"Global Options"}),jsxRuntimeExports.jsx("div",{className:styles$M.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Visible label",jsxRuntimeExports.jsx(InfoTip$k,{children:"Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."})]}),value:this.props.visibleLabel||"",onChange:this.handleVisibleLabel})}),jsxRuntimeExports.jsx("div",{className:styles$M.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Aria label",jsxRuntimeExports.jsxs(InfoTip$k,{children:["Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see"," ",jsxRuntimeExports.jsx("a",{href:"https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",target:"_blank",rel:"noreferrer",children:"this article."})]})]}),value:this.props.ariaLabel||"",onChange:this.handleAriaLabel})}),jsxRuntimeExports.jsx("div",{className:styles$M.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Function variables",jsxRuntimeExports.jsx(InfoTip$k,{children:'Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means "f of x" and not "f times x".'})]}),value:this.state.functionsInternal,onChange:this.handleFunctions})}),jsxRuntimeExports.jsx("div",{className:styles$M.paddedY,children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Use × instead of ⋅ for multiplication",jsxRuntimeExports.jsx(InfoTip$k,{children:"For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."})]}),checked:this.props.times,onChange:newCheckedState=>{this.changeTimes(newCheckedState);}})}),jsxRuntimeExports.jsxs("div",{className:styles$M.paddedY,children:[jsxRuntimeExports.jsx(Heading$1,{size:"small",className:styles$M.buttonSets,children:"Button Sets"}),buttonSetChoices]}),jsxRuntimeExports.jsx(Heading$1,{size:"medium",children:"Answers"}),jsxRuntimeExports.jsx(BodyText,{size:"small",className:styles$M.answersSubtitle,children:"student responses area matched against these from top to bottom"}),jsxRuntimeExports.jsxs(View,{className:styles$M.answersGroup,children:[jsxRuntimeExports.jsx(View,{className:styles$M.answersList,children:answerOptions}),jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.newAnswer,children:"Add new answer"})]})]})}constructor(props){super(props),this.getSaveWarnings=()=>{const issues=[];if(this.props.answerForms.length===0){issues.push("No answers specified");}else {const hasCorrect=this.props.answerForms.some(form=>{return form.considered==="correct"});if(!hasCorrect){issues.push("No correct answer specified");}_(this.props.answerForms).each((form,ix)=>{if(this.props.value===""){issues.push(`Answer ${ix+1} is empty`);}else {const expression=KAS.parse(form.value,{functions:this.props.functions});if(!expression.parsed){issues.push(`Couldn't parse ${form.value}`);}else if(form.simplify&&!expression.expr.isSimplified()){issues.push(`${form.value} isn't simplified, but is required" +
|
|
1541
|
-
" to be`);}}});}return issues},this.newAnswer=()=>{const answerForms=this.props.answerForms.slice();const newKey=crypto.randomUUID();const newAnswerForm={considered:"correct",form:false,key:`${newKey}`,simplify:false,value:""};answerForms.push(newAnswerForm);this.props.onChange({answerForms});},this.handleRemoveForm=i=>{const updatedAnswerForms=this.props.answerForms.slice();updatedAnswerForms.splice(i,1);this.props.onChange({answerForms:updatedAnswerForms});},this.handleButtonSet=changingName=>{const buttonSetNames=buttonSetsList;const buttonSets=buttonSetNames.filter(set=>{return this.props.buttonSets.includes(set)!==(set===changingName)});this.props.onChange({buttonSets});},this.handleToggleDiv=()=>{let keep;let remove;if(this.props.buttonSets.includes("basic+div")){keep="basic";remove="basic+div";}else {keep="basic+div";remove="basic";}const buttonSets=this.props.buttonSets.filter(set=>set!==remove).concat(keep);this.props.onChange({buttonSets});},this.handleTexInsert=str=>{this.refs.expression.insert(str);},this.handleFunctions=value=>{this.setState({functionsInternal:value});const newProps={};newProps.functions=value.split(/[ ,]+/).filter(isTruthy);this.props.onChange(newProps);},this.handleVisibleLabel=visibleLabel=>{this.props.onChange({visibleLabel});},this.handleAriaLabel=ariaLabel=>{this.props.onChange({ariaLabel});},this.changeExpressionWidget=(index,input)=>{const answerForm={...this.props.answerForms[index],value:input};this.updateAnswerForm(index,answerForm);};this.state={functionsInternal:this.props.functions.join(" ")};}}ExpressionEditor.widgetName="expression";ExpressionEditor.defaultProps={...expressionLogic.defaultWidgetOptions
|
|
1543
|
+
" to be`);}}});}return issues},this.newAnswer=()=>{const answerForms=this.props.answerForms.slice();const newKey=crypto.randomUUID();const newAnswerForm={considered:"correct",form:false,key:`${newKey}`,simplify:false,value:""};answerForms.push(newAnswerForm);this.props.onChange({answerForms});},this.handleRemoveForm=i=>{const updatedAnswerForms=this.props.answerForms.slice();updatedAnswerForms.splice(i,1);this.props.onChange({answerForms:updatedAnswerForms});},this.handleButtonSet=changingName=>{const buttonSetNames=buttonSetsList;const buttonSets=buttonSetNames.filter(set=>{return this.props.buttonSets.includes(set)!==(set===changingName)});this.props.onChange({buttonSets});},this.handleToggleDiv=()=>{let keep;let remove;if(this.props.buttonSets.includes("basic+div")){keep="basic";remove="basic+div";}else {keep="basic+div";remove="basic";}const buttonSets=this.props.buttonSets.filter(set=>set!==remove).concat(keep);this.props.onChange({buttonSets});},this.handleTexInsert=str=>{this.refs.expression.insert(str);},this.handleFunctions=value=>{this.setState({functionsInternal:value});const newProps={};newProps.functions=value.split(/[ ,]+/).filter(isTruthy);this.props.onChange(newProps);},this.handleVisibleLabel=visibleLabel=>{this.props.onChange({visibleLabel});},this.handleAriaLabel=ariaLabel=>{this.props.onChange({ariaLabel});},this.changeExpressionWidget=(index,input)=>{const answerForm={...this.props.answerForms[index],value:input};this.updateAnswerForm(index,answerForm);};this.state={functionsInternal:this.props.functions.join(" ")};}}ExpressionEditor.widgetName="expression";ExpressionEditor.defaultProps={...expressionLogic.defaultWidgetOptions};const findNextIn=function(arr,val){let ix=arr.indexOf(val);ix=(ix+1)%arr.length;return arr[ix]};class AnswerOption extends React.Component{render(){const{editingDisabled}=this.props;const removeButton=this.state.deleteFocused?jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleImSure,actionType:"destructive",children:"I'm sure!"}),jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleCancelDelete,kind:"secondary",children:"Cancel"})]}):jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleDelete,actionType:"destructive",kind:"tertiary",className:styles$M.deleteButton,children:"Delete"});return jsxRuntimeExports.jsxs("div",{className:styles$M.answerOption,children:[jsxRuntimeExports.jsx(ButtonGroup$7,{onChange:this.toggleConsidered,allowEmpty:false,disabled:editingDisabled,value:this.props.considered,selectedButtonStyle:consideredButtonStyles[this.props.considered],buttons:PerseusExpressionAnswerFormConsidered.map(c=>({value:c,content:c,title:`This answer will be considered ${c}`}))}),jsxRuntimeExports.jsx(Expression,{...this.props.expressionProps}),jsxRuntimeExports.jsx("div",{className:`${styles$M.paddedY} ${styles$M.paddedX}`,children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must have the same form.",jsxRuntimeExports.jsx(InfoTip$k,{children:"The student's answer must be in the same form. Commutativity and excess negative signs are ignored."})]}),checked:this.props.form,onChange:this.props.onChangeForm})}),jsxRuntimeExports.jsx("div",{className:`${styles$M.paddedY} ${styles$M.paddedX}`,children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must be fully expanded and simplified.",jsxRuntimeExports.jsx(InfoTip$k,{children:'The student\'s answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response "Your answer is not fully expanded and simplified."'})]}),checked:this.props.simplify,onChange:this.props.onChangeSimplify})}),jsxRuntimeExports.jsx("div",{className:`${styles$M.buttonRow} ${styles$M.paddedY}`,children:removeButton})]})}constructor(...args){super(...args),this.state={deleteFocused:false},this.handleImSure=()=>{this.props.onDelete();this.handleCancelDelete();},this.handleCancelDelete=()=>{this.setState({deleteFocused:false});},this.handleDelete=()=>{this.setState({deleteFocused:true});},this.toggleConsidered=()=>{const newVal=findNextIn(PerseusExpressionAnswerFormConsidered,this.props.considered);this.props.onChangeConsidered(newVal);};}}const wbStyles$1=StyleSheet.create({answerStatusWrong:{backgroundColor:semanticColor.core.background.critical.subtle},answerStatusCorrect:{backgroundColor:semanticColor.core.background.success.subtle},answerStatusUngraded:{backgroundColor:semanticColor.core.background.instructive.subtle}});const consideredButtonStyles={wrong:wbStyles$1.answerStatusWrong,correct:wbStyles$1.answerStatusCorrect,ungraded:wbStyles$1.answerStatusUngraded};
|
|
1542
1544
|
|
|
1543
|
-
class FreeResponseEditor extends React.Component{render(){const editingDisabled=this.props.apiOptions.editingDisabled??false;return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Question",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.question,onChange:newValue=>this.props.onChange({question:newValue})}),styles:{root:styles$L.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Placeholder",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.placeholder,onChange:newValue=>this.props.onChange({placeholder:newValue})}),styles:{root:styles$L.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Allow unlimited characters",field:jsxRuntimeExports.jsx(Checkbox$1,{checked:this.props.allowUnlimitedCharacters,onChange:val=>this.props.onChange({allowUnlimitedCharacters:val})}),styles:{root:styles$L.labeledInputField}}),!this.props.allowUnlimitedCharacters&&jsxRuntimeExports.jsx(LabeledField,{label:"Character limit",field:jsxRuntimeExports.jsx(TextField,{type:"number",min:1,value:String(this.props.characterLimit),onChange:this.handleUpdateCharacterLimit}),styles:{root:styles$L.labeledInputField}}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsxs(View,{style:styles$L.criteriaList,tag:"fieldset",children:[jsxRuntimeExports.jsx(BodyText,{tag:"legend",children:"Scoring criteria"}),this.renderCriteriaList(editingDisabled)]}),jsxRuntimeExports.jsx(View,{children:jsxRuntimeExports.jsx(Button,{onClick:this.handleAddCriterion,startIcon:plusCircle,disabled:editingDisabled,children:"Add an item"})})]})]})}constructor(...args){super(...args),this.serialize=()=>{return {allowUnlimitedCharacters:this.props.allowUnlimitedCharacters,characterLimit:this.props.characterLimit,placeholder:this.props.placeholder,question:this.props.question,scoringCriteria:this.props.scoringCriteria}},this.getSaveWarnings=()=>{const warnings=[];if(!this.props.question){warnings.push("The question is empty");}if(this.props.question.match(Util.rWidgetRule)!=null){warnings.push("The question contains a widget");}return warnings},this.handleUpdateCharacterLimit=newValue=>{const val=parseInt(newValue);if(isNaN(val)){return}this.props.onChange({characterLimit:Math.max(1,val)});},this.handleUpdateCriterion=(index,criterion)=>{const newCriteria=this.props.scoringCriteria.map((c,i)=>{if(i===index){return criterion}return c});this.props.onChange({scoringCriteria:newCriteria});},this.handleDeleteCriterion=index=>{this.props.onChange({scoringCriteria:this.props.scoringCriteria.filter((_,i)=>i!==index)});},this.handleAddCriterion=()=>{this.props.onChange({scoringCriteria:[...this.props.scoringCriteria,{text:""}]});},this.renderCriteriaList=editingDisabled=>{const isDeletable=this.props.scoringCriteria.length>1;return this.props.scoringCriteria.map((criterion,index)=>{return jsxRuntimeExports.jsx(CriterionEditor,{criterion:criterion,index:index,isDeletable:isDeletable,editingDisabled:editingDisabled,onChange:this.handleUpdateCriterion,onDelete:this.handleDeleteCriterion},index)})};}}FreeResponseEditor.defaultProps={...freeResponseLogic.defaultWidgetOptions
|
|
1545
|
+
class FreeResponseEditor extends React.Component{render(){const editingDisabled=this.props.apiOptions.editingDisabled??false;return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Question",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.question,onChange:newValue=>this.props.onChange({question:newValue})}),styles:{root:styles$L.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Placeholder",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.placeholder,onChange:newValue=>this.props.onChange({placeholder:newValue})}),styles:{root:styles$L.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Allow unlimited characters",field:jsxRuntimeExports.jsx(Checkbox$1,{checked:this.props.allowUnlimitedCharacters,onChange:val=>this.props.onChange({allowUnlimitedCharacters:val})}),styles:{root:styles$L.labeledInputField}}),!this.props.allowUnlimitedCharacters&&jsxRuntimeExports.jsx(LabeledField,{label:"Character limit",field:jsxRuntimeExports.jsx(TextField,{type:"number",min:1,value:String(this.props.characterLimit),onChange:this.handleUpdateCharacterLimit}),styles:{root:styles$L.labeledInputField}}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsxs(View,{style:styles$L.criteriaList,tag:"fieldset",children:[jsxRuntimeExports.jsx(BodyText,{tag:"legend",children:"Scoring criteria"}),this.renderCriteriaList(editingDisabled)]}),jsxRuntimeExports.jsx(View,{children:jsxRuntimeExports.jsx(Button,{onClick:this.handleAddCriterion,startIcon:plusCircle,disabled:editingDisabled,children:"Add an item"})})]})]})}constructor(...args){super(...args),this.serialize=()=>{return {allowUnlimitedCharacters:this.props.allowUnlimitedCharacters,characterLimit:this.props.characterLimit,placeholder:this.props.placeholder,question:this.props.question,scoringCriteria:this.props.scoringCriteria}},this.getSaveWarnings=()=>{const warnings=[];if(!this.props.question){warnings.push("The question is empty");}if(this.props.question.match(Util.rWidgetRule)!=null){warnings.push("The question contains a widget");}return warnings},this.handleUpdateCharacterLimit=newValue=>{const val=parseInt(newValue);if(isNaN(val)){return}this.props.onChange({characterLimit:Math.max(1,val)});},this.handleUpdateCriterion=(index,criterion)=>{const newCriteria=this.props.scoringCriteria.map((c,i)=>{if(i===index){return criterion}return c});this.props.onChange({scoringCriteria:newCriteria});},this.handleDeleteCriterion=index=>{this.props.onChange({scoringCriteria:this.props.scoringCriteria.filter((_,i)=>i!==index)});},this.handleAddCriterion=()=>{this.props.onChange({scoringCriteria:[...this.props.scoringCriteria,{text:""}]});},this.renderCriteriaList=editingDisabled=>{const isDeletable=this.props.scoringCriteria.length>1;return this.props.scoringCriteria.map((criterion,index)=>{return jsxRuntimeExports.jsx(CriterionEditor,{criterion:criterion,index:index,isDeletable:isDeletable,editingDisabled:editingDisabled,onChange:this.handleUpdateCriterion,onDelete:this.handleDeleteCriterion},index)})};}}FreeResponseEditor.defaultProps={...freeResponseLogic.defaultWidgetOptions};FreeResponseEditor.widgetName="free-response";const CriterionEditor=function(props){return jsxRuntimeExports.jsxs(View,{style:styles$L.criterionContainer,children:[jsxRuntimeExports.jsx("textarea",{"aria-label":`Criterion ${props.index+1}`,onChange:e=>props.onChange(props.index,{text:e.target.value}),value:props.criterion.text}),props.isDeletable&&jsxRuntimeExports.jsx(View,{style:styles$L.deleteButtonContainer,children:jsxRuntimeExports.jsx(Button,{"aria-label":`Delete criterion ${props.index+1}`,actionType:"destructive",disabled:!props.isDeletable||props.editingDisabled,kind:"tertiary",onClick:()=>props.onDelete(props.index),size:"small",startIcon:trashIcon$1,children:"Delete"})})]})};const styles$L=StyleSheet.create({criteriaList:{gap:spacing.small_12},criterionContainer:{paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,borderBottom:`1px solid ${semanticColor.core.border.neutral.subtle}`,":last-child":{borderBottom:"none"}},deleteButtonContainer:{display:"flex",flexDirection:"row",justifyContent:"flex-end"},labeledInputField:{paddingBottom:spacing.large_24}});
|
|
1544
1546
|
|
|
1545
1547
|
var styles$K = {"title":"perseus_az1kQinp","input":"perseus_khxW0hEz","hintsTitle":"perseus_UPlDqNry","addHintButton":"perseus_2aajvB7Y"};
|
|
1546
1548
|
|
|
@@ -1584,7 +1586,7 @@ function ToggleButton({selected,onClick,disabled=false,role="radio",children,sty
|
|
|
1584
1586
|
|
|
1585
1587
|
var styles$F = {"field":"perseus_JbwuUF5N","labelRow":"perseus_aHiPdK--","inlineField":"perseus_dNMdOiQI"};
|
|
1586
1588
|
|
|
1587
|
-
const{InfoTip: InfoTip$g,NumberInput: NumberInput$c,TextInput: TextInput$3}=components;const{firstNumericalParse}=Util;const answerFormButtons=[{title:"Integers",value:"integer",content:"6"},{title:"Decimals",value:"decimal",content:"0.75"},{title:"Proper fractions",value:"proper",content:"⅗"},{title:"Improper fractions",value:"improper",content:"⁷⁄₄"},{title:"Mixed numbers",value:"mixed",content:"1¾"},{title:"Numbers with π",value:"pi",content:"π"}];const initAnswer=status=>{return {value:null,status:status,message:"",simplify:"required",answerForms:[],strict:false,maxError:null}};class NumericInputEditor extends React.Component{render(){const answers=this.props.answers;const editingDisabled=this.props.apiOptions.editingDisabled;const unsimplifiedAnswers=i=>jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[answers[i]["status"]!=="correct"&&jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are irrelevant for this status"}),answers[i]["status"]==="correct"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are"}),jsxRuntimeExports.jsxs(InfoTip$g,{children:[jsxRuntimeExports.jsx("p",{children:'Normally select "ungraded". This will give the user a message saying the answer is correct but not simplified. The user will then have to simplify it and re-enter, but will not be penalized. (5th grade and after)'}),jsxRuntimeExports.jsx("p",{children:'Select "accepted" only if the user is not expected to know how to simplify fractions yet. (Anything prior to 5th grade)'}),jsxRuntimeExports.jsxs("p",{children:['Select "wrong" ',jsxRuntimeExports.jsx("em",{children:"only"})," if we are specifically assessing the ability to simplify."]})]})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Unsimplified answers are",disabled:editingDisabled,selectedValue:answers[i]["simplify"],onChange:value=>this.updateAnswer(i,{simplify:value}),options:[{value:"required",label:"Ungraded"},{value:"optional",label:"Accepted"},{value:"enforced",label:"Wrong"}]})]})]});const suggestedAnswerTypes=i=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Possible answer formats"}),jsxRuntimeExports.jsxs(InfoTip$g,{children:[jsxRuntimeExports.jsx("p",{children:'Formats will be autoselected for you based on the given answer; to show no suggested formats and accept all types, simply have a decimal/integer be the answer. Values with π will have format "pi", and values that are fractions will have some subset (mixed will be "mixed" and "proper"; improper/proper will both be "improper" and "proper"). If you would like to specify that it is only a proper fraction (or only a mixed/improper fraction), deselect the other format. Except for specific cases, you should not need to change the autoselected formats.'}),jsxRuntimeExports.jsxs("p",{children:["To restrict the answer to ",jsxRuntimeExports.jsx("em",{children:"only"}),' an improper fraction (i.e. 7/4), select the improper fraction and toggle "strict" to true. This ',jsxRuntimeExports.jsx("b",{children:"will not"})," accept 1.75 as an answer."," "]}),jsxRuntimeExports.jsx("p",{children:"Unless you are testing that specific skill, please do not restrict the answer format."})]})]}),jsxRuntimeExports.jsx(ToggleButtonGroup,{"aria-label":"Possible answer formats",disabled:editingDisabled,selectedValues:answers[i]["answerForms"]??[],onToggle:value=>this.onToggleAnswerForm(i,value),options:answerFormButtons.map(format=>({value:format.value,label:format.content,ariaLabel:format.title}))})]}),jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer formats are"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Answer formats are",disabled:editingDisabled,selectedValue:answers[i]["strict"]?"required":"suggested",onChange:value=>this.updateAnswer(i,{strict:value==="required"}),options:[{value:"suggested",label:"Suggested"},{value:"required",label:"Required"}]})]})]});const inputSize=jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Width"}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:'Use size "Normal" for all text boxes, unless there are multiple text boxes in one line and the answer area is too narrow to fit them.'})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Width",disabled:editingDisabled,selectedValue:this.props.size,onChange:value=>this.change("size")(value),options:[{value:"normal",label:"Normal (80px)"},{value:"small",label:"Small (40px)"}]})]});const labelText=jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer Field Aria label"}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:"Text to describe the Answer Field for screenreader users."})})]}),jsxRuntimeExports.jsx(TextInput$3,{labelText:"aria label",value:this.props.labelText,onChange:this.change("labelText")})]});const coefficientCheck=jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Number style"}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:"A coefficient style number allows the student to use - for -1 and an empty string to mean 1."})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Number style",disabled:editingDisabled,selectedValue:this.props.coefficient?"coefficient":"standard",onChange:value=>this.props.onChange({coefficient:value==="coefficient"}),options:[{value:"standard",label:"Standard"},{value:"coefficient",label:"Coefficient"}]})]});const instructions={wrong:"(address the mistake/misconception)",ungraded:"(explain in detail to avoid confusion)",correct:"(reinforce the user's understanding)"};const generateInputAnswerEditors=()=>answers.map((answer,i)=>{const editor=jsxRuntimeExports.jsx(Editor,{apiOptions:this.props.apiOptions,content:answer.message||"",placeholder:"Why is this answer "+answer.status+"? "+instructions[answer.status],widgetEnabled:false,onChange:newProps=>{if("content"in newProps){this.updateAnswer(i,{message:newProps.content});}}});const statusProper=answer.status.charAt(0).toUpperCase()+answer.status.slice(1);const answerFormat=(answer.answerForms||[]).at(-1);const answerString=KhanMath.toNumericString(answer.value??0,answerFormat);const answerRangeText=answer.maxError?`\xb1 ${KhanMath.toNumericString(answer.maxError,answerFormat)}`:"";const answerHeading=answer.value===null?"New Answer":`${statusProper} answer: ${answerString} ${answerRangeText}`;return jsxRuntimeExports.jsx("div",{className:"perseus-widget-row answer-option",children:jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:this.state.showAnswerDetails[i],onToggle:()=>{this.onToggleAnswers(i);},header:jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:answerHeading}),children:[jsxRuntimeExports.jsxs("div",{className:"input-answer-editor-value-container"+(answer.maxError?" with-max-error":""),children:[jsxRuntimeExports.jsxs(View,{tag:"label",className:styles$F.inlineField,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"User input"}),jsxRuntimeExports.jsx(NumberInput$c,{value:answer.value,className:"numeric-input-value",placeholder:"answer",format:_.last(answer.answerForms||[]),onFormatChange:(newValue,format)=>{let forms;if(format==="pi"){forms=["pi"];}else if(format==="mixed"){forms=["proper","mixed"];}else if(format==="proper"||format==="improper"){forms=["proper","improper"];}this.updateAnswer(i,{value:firstNumericalParse(newValue),answerForms:forms});},onChange:newValue=>{this.updateAnswer(i,{value:firstNumericalParse(newValue)});}})]}),jsxRuntimeExports.jsx("span",{className:"max-error-plusmn",children:"±"}),jsxRuntimeExports.jsx(NumberInput$c,{className:"max-error-input-value",placeholder:0,value:answers[i]["maxError"],format:_.last(answer.answerForms||[]),onChange:this.updateAnswer(i,"maxError")})]}),jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Status"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Status",disabled:editingDisabled,selectedValue:answers[i]["status"],onChange:value=>this.onEvaluationChange(i,value),options:[{value:"correct",label:"Correct"},{value:"wrong",label:"Wrong"},{value:"ungraded",label:"Ungraded"}]})]}),unsimplifiedAnswers(i),jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"(Articles only) Message shown to user"}),editor]}),suggestedAnswerTypes(i),jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,"aria-label":`Delete ${answerHeading}`,className:"delete-item-button",disabled:editingDisabled,onClick:()=>{this.onTrashAnswer(i);},kind:"tertiary",children:"Delete"})]})},i)});return jsxRuntimeExports.jsxs("div",{className:"perseus-input-number-editor",children:[jsxRuntimeExports.jsx(Heading,{title:"General Settings",isCollapsible:true,isOpen:this.state.showSettings,onToggle:this.onToggleHeading("Settings")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showSettings?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[inputSize,jsxRuntimeExports.jsxs("label",{children:["Text alignment",jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.textAlign,onChange:value=>{this.props.onChange({textAlign:value});},placeholder:"Select text alignment",children:[jsxRuntimeExports.jsx(OptionItem,{value:"left",label:"Left"}),jsxRuntimeExports.jsx(OptionItem,{value:"center",label:"Center"}),jsxRuntimeExports.jsx(OptionItem,{value:"right",label:"Right"})]})]}),coefficientCheck,labelText]})}),jsxRuntimeExports.jsx(Heading,{title:"Answers",isCollapsible:true,isOpen:this.state.showAnswers,onToggle:this.onToggleHeading("Answers")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showAnswers?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[generateInputAnswerEditors(),jsxRuntimeExports.jsx(Button,{kind:"tertiary",disabled:editingDisabled,onClick:this.addAnswer,children:"Add new answer"})]})})]})}constructor(props){super(props),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.onToggleAnswers=answerIndex=>{const showAnswerDetails=this.state.showAnswerDetails.slice();showAnswerDetails[answerIndex]=!showAnswerDetails[answerIndex];this.setState({showAnswerDetails:showAnswerDetails});},this.onToggleAnswerForm=(answerIndex,answerForm)=>{let answerForms=[...this.props.answers[answerIndex]["answerForms"]??[]];const formSelected=answerForms.includes(answerForm);if(!formSelected){answerForms.push(answerForm);}else {answerForms=answerForms.filter(form=>form!==answerForm);}const updateFn=this.updateAnswer(answerIndex,"answerForms");if(updateFn){updateFn(answerForms);}},this.onToggleHeading=accordionName=>{return ()=>{const toggleName=`show${accordionName}`;const newState={...this.state};newState[toggleName]=!newState[toggleName];this.setState(newState);}},this.onTrashAnswer=choiceIndex=>{if(choiceIndex>=0&&choiceIndex<this.props.answers.length){const answers=this.props.answers.slice(0);answers.splice(choiceIndex,1);this.props.onChange({answers:answers});}},this.onSpace=(e,callback,...args)=>{if(e.key===" "){e.preventDefault();callback.apply(this,args);}},this.onStatusChange=choiceIndex=>{const statuses=["wrong","ungraded","correct"];const answers=this.props.answers;const i=statuses.indexOf(answers[choiceIndex].status);const newStatus=statuses[(i+1)%statuses.length];this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.onEvaluationChange=(choiceIndex,newStatus)=>{this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.updateAnswer=(choiceIndex,update)=>{if(!_.isObject(update)){return _.partial((choiceIndex,key,value)=>{const update={};update[key]=value;this.updateAnswer(choiceIndex,update);},choiceIndex,update)}let answers=[...this.props.answers];if(choiceIndex===answers.length){const lastAnswer=initAnswer(this.state.lastStatus);answers=answers.concat(lastAnswer);}answers[choiceIndex]=_.extend({},answers[choiceIndex],update);this.props.onChange({answers:answers});},this.addAnswer=()=>{const lastAnswer=initAnswer(this.state.lastStatus);const answers=this.props.answers.concat(lastAnswer);const showAnswerDetails=this.state.showAnswerDetails.concat(true);this.setState({showAnswerDetails:showAnswerDetails});this.props.onChange({answers:answers});},this.getSaveWarnings=()=>{const warnings=[];if(_.contains(_.pluck(this.props.answers,"value"),"")){warnings.push("One or more answers is empty");}this.props.answers.forEach((answer,i)=>{const formatError=answer.strict&&(!answer.answerForms||answer.answerForms.length===0);if(formatError){warnings.push(`Answer ${i+1} is set to string format `+"matching, but no format was selected");}});return warnings},this.serialize=()=>{return EditorJsonify.serialize.call(this)};this.state={lastStatus:"wrong",showAnswerDetails:Array(this.props.answers.length).fill(true),showSettings:true,showAnswers:true};}}NumericInputEditor.widgetName="numeric-input";NumericInputEditor.displayName="NumericInputEditor";NumericInputEditor.defaultProps={...numericInputLogic.defaultWidgetOptions,apiOptions:ApiOptions.defaults};
|
|
1589
|
+
const{InfoTip: InfoTip$g,NumberInput: NumberInput$c,TextInput: TextInput$3}=components;const{firstNumericalParse}=Util;const answerFormButtons=[{title:"Integers",value:"integer",content:"6"},{title:"Decimals",value:"decimal",content:"0.75"},{title:"Proper fractions",value:"proper",content:"⅗"},{title:"Improper fractions",value:"improper",content:"⁷⁄₄"},{title:"Mixed numbers",value:"mixed",content:"1¾"},{title:"Numbers with π",value:"pi",content:"π"}];const initAnswer=status=>{return {value:null,status:status,message:"",simplify:"required",answerForms:[],strict:false,maxError:null}};class NumericInputEditor extends React.Component{render(){const answers=this.props.answers;const editingDisabled=this.props.apiOptions.editingDisabled;const unsimplifiedAnswers=i=>jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[answers[i]["status"]!=="correct"&&jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are irrelevant for this status"}),answers[i]["status"]==="correct"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are"}),jsxRuntimeExports.jsxs(InfoTip$g,{children:[jsxRuntimeExports.jsx("p",{children:'Normally select "ungraded". This will give the user a message saying the answer is correct but not simplified. The user will then have to simplify it and re-enter, but will not be penalized. (5th grade and after)'}),jsxRuntimeExports.jsx("p",{children:'Select "accepted" only if the user is not expected to know how to simplify fractions yet. (Anything prior to 5th grade)'}),jsxRuntimeExports.jsxs("p",{children:['Select "wrong" ',jsxRuntimeExports.jsx("em",{children:"only"})," if we are specifically assessing the ability to simplify."]})]})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Unsimplified answers are",disabled:editingDisabled,selectedValue:answers[i]["simplify"],onChange:value=>this.updateAnswer(i,{simplify:value}),options:[{value:"required",label:"Ungraded"},{value:"optional",label:"Accepted"},{value:"enforced",label:"Wrong"}]})]})]});const suggestedAnswerTypes=i=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Possible answer formats"}),jsxRuntimeExports.jsxs(InfoTip$g,{children:[jsxRuntimeExports.jsx("p",{children:'Formats will be autoselected for you based on the given answer; to show no suggested formats and accept all types, simply have a decimal/integer be the answer. Values with π will have format "pi", and values that are fractions will have some subset (mixed will be "mixed" and "proper"; improper/proper will both be "improper" and "proper"). If you would like to specify that it is only a proper fraction (or only a mixed/improper fraction), deselect the other format. Except for specific cases, you should not need to change the autoselected formats.'}),jsxRuntimeExports.jsxs("p",{children:["To restrict the answer to ",jsxRuntimeExports.jsx("em",{children:"only"}),' an improper fraction (i.e. 7/4), select the improper fraction and toggle "strict" to true. This ',jsxRuntimeExports.jsx("b",{children:"will not"})," accept 1.75 as an answer."," "]}),jsxRuntimeExports.jsx("p",{children:"Unless you are testing that specific skill, please do not restrict the answer format."})]})]}),jsxRuntimeExports.jsx(ToggleButtonGroup,{"aria-label":"Possible answer formats",disabled:editingDisabled,selectedValues:answers[i]["answerForms"]??[],onToggle:value=>this.onToggleAnswerForm(i,value),options:answerFormButtons.map(format=>({value:format.value,label:format.content,ariaLabel:format.title}))})]}),jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer formats are"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Answer formats are",disabled:editingDisabled,selectedValue:answers[i]["strict"]?"required":"suggested",onChange:value=>this.updateAnswer(i,{strict:value==="required"}),options:[{value:"suggested",label:"Suggested"},{value:"required",label:"Required"}]})]})]});const inputSize=jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Width"}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:'Use size "Normal" for all text boxes, unless there are multiple text boxes in one line and the answer area is too narrow to fit them.'})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Width",disabled:editingDisabled,selectedValue:this.props.size,onChange:value=>this.change("size")(value),options:[{value:"normal",label:"Normal (80px)"},{value:"small",label:"Small (40px)"}]})]});const labelText=jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer Field Aria label"}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:"Text to describe the Answer Field for screenreader users."})})]}),jsxRuntimeExports.jsx(TextInput$3,{labelText:"aria label",value:this.props.labelText,onChange:this.change("labelText")})]});const coefficientCheck=jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$F.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Number style"}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:"A coefficient style number allows the student to use - for -1 and an empty string to mean 1."})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Number style",disabled:editingDisabled,selectedValue:this.props.coefficient?"coefficient":"standard",onChange:value=>this.props.onChange({coefficient:value==="coefficient"}),options:[{value:"standard",label:"Standard"},{value:"coefficient",label:"Coefficient"}]})]});const instructions={wrong:"(address the mistake/misconception)",ungraded:"(explain in detail to avoid confusion)",correct:"(reinforce the user's understanding)"};const generateInputAnswerEditors=()=>answers.map((answer,i)=>{const editor=jsxRuntimeExports.jsx(Editor,{apiOptions:this.props.apiOptions,content:answer.message||"",placeholder:"Why is this answer "+answer.status+"? "+instructions[answer.status],widgetEnabled:false,onChange:newProps=>{if("content"in newProps){this.updateAnswer(i,{message:newProps.content});}}});const statusProper=answer.status.charAt(0).toUpperCase()+answer.status.slice(1);const answerFormat=(answer.answerForms||[]).at(-1);const answerString=KhanMath.toNumericString(answer.value??0,answerFormat);const answerRangeText=answer.maxError?`\xb1 ${KhanMath.toNumericString(answer.maxError,answerFormat)}`:"";const answerHeading=answer.value===null?"New Answer":`${statusProper} answer: ${answerString} ${answerRangeText}`;return jsxRuntimeExports.jsx("div",{className:"perseus-widget-row answer-option",children:jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:this.state.showAnswerDetails[i],onToggle:()=>{this.onToggleAnswers(i);},header:jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:answerHeading}),children:[jsxRuntimeExports.jsxs("div",{className:"input-answer-editor-value-container"+(answer.maxError?" with-max-error":""),children:[jsxRuntimeExports.jsxs(View,{tag:"label",className:styles$F.inlineField,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"User input"}),jsxRuntimeExports.jsx(NumberInput$c,{value:answer.value,className:"numeric-input-value",placeholder:"answer",format:_.last(answer.answerForms||[]),onFormatChange:(newValue,format)=>{let forms;if(format==="pi"){forms=["pi"];}else if(format==="mixed"){forms=["proper","mixed"];}else if(format==="proper"||format==="improper"){forms=["proper","improper"];}this.updateAnswer(i,{value:firstNumericalParse(newValue),answerForms:forms});},onChange:newValue=>{this.updateAnswer(i,{value:firstNumericalParse(newValue)});}})]}),jsxRuntimeExports.jsx("span",{className:"max-error-plusmn",children:"±"}),jsxRuntimeExports.jsx(NumberInput$c,{className:"max-error-input-value",placeholder:0,value:answers[i]["maxError"],format:_.last(answer.answerForms||[]),onChange:this.updateAnswer(i,"maxError")})]}),jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Status"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Status",disabled:editingDisabled,selectedValue:answers[i]["status"],onChange:value=>this.onEvaluationChange(i,value),options:[{value:"correct",label:"Correct"},{value:"wrong",label:"Wrong"},{value:"ungraded",label:"Ungraded"}]})]}),unsimplifiedAnswers(i),jsxRuntimeExports.jsxs(View,{className:styles$F.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"(Articles only) Message shown to user"}),editor]}),suggestedAnswerTypes(i),jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,"aria-label":`Delete ${answerHeading}`,className:"delete-item-button",disabled:editingDisabled,onClick:()=>{this.onTrashAnswer(i);},kind:"tertiary",children:"Delete"})]})},i)});return jsxRuntimeExports.jsxs("div",{className:"perseus-input-number-editor",children:[jsxRuntimeExports.jsx(Heading,{title:"General Settings",isCollapsible:true,isOpen:this.state.showSettings,onToggle:this.onToggleHeading("Settings")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showSettings?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[inputSize,jsxRuntimeExports.jsxs("label",{children:["Text alignment",jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.textAlign,onChange:value=>{this.props.onChange({textAlign:value});},placeholder:"Select text alignment",children:[jsxRuntimeExports.jsx(OptionItem,{value:"left",label:"Left"}),jsxRuntimeExports.jsx(OptionItem,{value:"center",label:"Center"}),jsxRuntimeExports.jsx(OptionItem,{value:"right",label:"Right"})]})]}),coefficientCheck,labelText]})}),jsxRuntimeExports.jsx(Heading,{title:"Answers",isCollapsible:true,isOpen:this.state.showAnswers,onToggle:this.onToggleHeading("Answers")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showAnswers?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[generateInputAnswerEditors(),jsxRuntimeExports.jsx(Button,{kind:"tertiary",disabled:editingDisabled,onClick:this.addAnswer,children:"Add new answer"})]})})]})}constructor(props){super(props),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.onToggleAnswers=answerIndex=>{const showAnswerDetails=this.state.showAnswerDetails.slice();showAnswerDetails[answerIndex]=!showAnswerDetails[answerIndex];this.setState({showAnswerDetails:showAnswerDetails});},this.onToggleAnswerForm=(answerIndex,answerForm)=>{let answerForms=[...this.props.answers[answerIndex]["answerForms"]??[]];const formSelected=answerForms.includes(answerForm);if(!formSelected){answerForms.push(answerForm);}else {answerForms=answerForms.filter(form=>form!==answerForm);}const updateFn=this.updateAnswer(answerIndex,"answerForms");if(updateFn){updateFn(answerForms);}},this.onToggleHeading=accordionName=>{return ()=>{const toggleName=`show${accordionName}`;const newState={...this.state};newState[toggleName]=!newState[toggleName];this.setState(newState);}},this.onTrashAnswer=choiceIndex=>{if(choiceIndex>=0&&choiceIndex<this.props.answers.length){const answers=this.props.answers.slice(0);answers.splice(choiceIndex,1);this.props.onChange({answers:answers});}},this.onSpace=(e,callback,...args)=>{if(e.key===" "){e.preventDefault();callback.apply(this,args);}},this.onStatusChange=choiceIndex=>{const statuses=["wrong","ungraded","correct"];const answers=this.props.answers;const i=statuses.indexOf(answers[choiceIndex].status);const newStatus=statuses[(i+1)%statuses.length];this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.onEvaluationChange=(choiceIndex,newStatus)=>{this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.updateAnswer=(choiceIndex,update)=>{if(!_.isObject(update)){return _.partial((choiceIndex,key,value)=>{const update={};update[key]=value;this.updateAnswer(choiceIndex,update);},choiceIndex,update)}let answers=[...this.props.answers];if(choiceIndex===answers.length){const lastAnswer=initAnswer(this.state.lastStatus);answers=answers.concat(lastAnswer);}answers[choiceIndex]=_.extend({},answers[choiceIndex],update);this.props.onChange({answers:answers});},this.addAnswer=()=>{const lastAnswer=initAnswer(this.state.lastStatus);const answers=this.props.answers.concat(lastAnswer);const showAnswerDetails=this.state.showAnswerDetails.concat(true);this.setState({showAnswerDetails:showAnswerDetails});this.props.onChange({answers:answers});},this.getSaveWarnings=()=>{const warnings=[];if(_.contains(_.pluck(this.props.answers,"value"),"")){warnings.push("One or more answers is empty");}this.props.answers.forEach((answer,i)=>{const formatError=answer.strict&&(!answer.answerForms||answer.answerForms.length===0);if(formatError){warnings.push(`Answer ${i+1} is set to string format `+"matching, but no format was selected");}});return warnings},this.serialize=()=>{return EditorJsonify.serialize.call(this)};this.state={lastStatus:"wrong",showAnswerDetails:Array(this.props.answers.length).fill(true),showSettings:true,showAnswers:true};}}NumericInputEditor.widgetName="numeric-input";NumericInputEditor.displayName="NumericInputEditor";NumericInputEditor.defaultProps={...numericInputLogic.defaultWidgetOptions};
|
|
1588
1590
|
|
|
1589
1591
|
class InputNumberEditor extends NumericInputEditor{}InputNumberEditor.widgetName="input-number";
|
|
1590
1592
|
|
|
@@ -1855,5 +1857,5 @@ var AllEditors = [CategorizerEditor,CSProgramEditor,DefinitionEditor,DropdownEdi
|
|
|
1855
1857
|
|
|
1856
1858
|
Widgets.registerEditors(AllEditors);Widgets.registerWidgets(widgets);Widgets.replaceDeprecatedWidgets();Widgets.replaceDeprecatedEditors();
|
|
1857
1859
|
|
|
1858
|
-
export { AllEditors, ArticleDiff, ArticleEditor, ContentPreview, DeviceFramer, Editor, EditorPage, IframeContentRenderer, IssuesPanel, ItemDiff, ViewportResizer, libVersion, usePreviewController, usePreviewPresenter };
|
|
1860
|
+
export { AllEditors, ArticleDiff, ArticleEditor, ContentPreview, DeviceFramer, Editor, EditorPage, IframeContentRenderer, IssuesPanel, ItemDiff, PreviewWithIframe, ViewportResizer, libVersion, usePreviewController, usePreviewPresenter };
|
|
1859
1861
|
//# sourceMappingURL=index.js.map
|