@khanacademy/perseus-editor 35.2.2 → 35.3.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/es/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
2
2
  import * as React from 'react';
3
- import React__default, { useState, useId, createElement, useRef, useEffect } from 'react';
3
+ import React__default, { useId, useContext, useState, createElement, useRef, useEffect } from 'react';
4
4
  import { PerseusMarkdown, Util, Widgets, excludeDenylistKeys, ApiOptions, Log, preprocessTex, components, Dependencies, ClassNames, usePerseusI18n, UserInputManager, Renderer, Categorizer as Categorizer$1, Changeable, EditorJsonify, Expression, interactiveSizes, GrapherWidget, GrapherUtil, containerSizeClass, getInteractiveBoxFromSizeClass, iconChevronDown, iconTrash, KhanColors, mathOnlyParser, getLogarithmCoords, getAngleCoords, getPolygonCoords, getPointCoords, getQuadraticCoords, getTangentCoords, getExponentialCoords, getSinusoidCoords, getCircleCoords, getLinearSystemCoords, getSegmentCoords, getVectorCoords, getLineCoords, getAbsoluteValueCoords, InteractiveGraphWidget, MatrixWidget, PlotterWidget, TableWidget, widgets } from '@khanacademy/perseus';
5
5
  export { widgets } from '@khanacademy/perseus';
6
6
  import { generateImageWidget, generateImageOptions, isSuccess, CoreWidgetRegistry, applyDefaultsToWidget, getWidgetIdsFromContent, PerseusError, Errors, parseAndMigratePerseusArticle, getDefaultAnswerArea, ItemExtras, isFeatureOn, parseAndMigratePerseusItem, categorizerLogic, csProgramLogic, definitionLogic, dropdownLogic, explanationLogic, expressionLogic, deriveExtraKeys, PerseusExpressionAnswerFormConsidered, freeResponseLogic, gradedGroupLogic, gradedGroupSetLogic, grapherLogic, GrapherUtil as GrapherUtil$1, groupLogic, iframeLogic, imageLogic, numericInputLogic, interactionLogic, lockedFigureColors, lockedFigureFillStyles, getDefaultFigureForType, interactiveGraphLogic, labelImageLogic, matcherLogic, matrixLogic, getMatrixSize, measurerLogic, numberLineLogic, ordererLogic, phetSimulationLogic, makeSafeUrl, plotterLogic, plotterPlotTypes, pythonProgramLogic, radioLogic, deriveNumCorrect, sorterLogic, tableLogic, videoLogic } from '@khanacademy/perseus-core';
@@ -34,9 +34,9 @@ import katex from 'katex';
34
34
  import classNames from 'classnames';
35
35
  import invariant from 'tiny-invariant';
36
36
  import { Checkbox as Checkbox$1, RadioGroup, Choice, TextField, LabeledTextField, TextArea } from '@khanacademy/wonder-blocks-form';
37
- import * as axeCore from 'axe-core';
38
37
  import { StatefulKeypadContextProvider, KeypadContext } from '@khanacademy/keypad-context';
39
38
  import { MobileKeypad, useMathInputI18n, createMathField } from '@khanacademy/math-input';
39
+ import { useActionScheduler } from '@khanacademy/wonder-blocks-timing';
40
40
  import PropTypes from 'prop-types';
41
41
  import ReactDOM from 'react-dom';
42
42
  import * as KAS from '@khanacademy/kas';
@@ -65,7 +65,7 @@ import minusCircle from '@phosphor-icons/core/regular/minus-circle.svg';
65
65
  import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
66
66
  import minusCircleIcon from '@phosphor-icons/core/bold/minus-circle-bold.svg';
67
67
 
68
- const libName="@khanacademy/perseus-editor";const libVersion="35.2.2";addLibraryVersionToPerseusDebug(libName,libVersion);
68
+ const libName="@khanacademy/perseus-editor";const libVersion="35.3.0";addLibraryVersionToPerseusDebug(libName,libVersion);
69
69
 
70
70
  var jsxRuntime = {exports: {}};
71
71
 
@@ -1415,6 +1415,8 @@ const devices={PHONE:"phone",TABLET:"tablet",DESKTOP:"desktop"};const lintGutter
1415
1415
 
1416
1416
  const SCREEN_SIZES={phone:{width:320,height:480,framedWidth:320},tablet:{width:750,height:920,framedWidth:525},desktop:{width:688,height:600,framedWidth:688}};const DeviceFramer=({children,deviceType="phone",nochrome})=>{const scale=React.useMemo(()=>SCREEN_SIZES[deviceType].framedWidth/SCREEN_SIZES[deviceType].width,[deviceType]);const withChromeStyle=React.useMemo(()=>({backgroundColor:"white",color:"black",textAlign:"left",width:SCREEN_SIZES[deviceType].width,height:SCREEN_SIZES[deviceType].height,border:"solid 1px #CCC",margin:8,zoom:scale}),[deviceType,scale]);if(nochrome){return jsxRuntimeExports.jsx("div",{style:{width:SCREEN_SIZES[deviceType].framedWidth+2*perseusFrameBorderWidth+lintGutterWidth},children:jsxRuntimeExports.jsx("div",{children:children})},"screen")}return jsxRuntimeExports.jsx("div",{className:"screen",style:{...withChromeStyle,textAlign:"start"},children:children},"screen")};
1417
1417
 
1418
+ function createA11yContextValue(overrides={}){return {setIssueHighlight:()=>{},a11yScanningEnabled:false,setA11yScanningEnabled:()=>{},highlightInstanceIds:[],onA11yReport:()=>{},axeCoreIssues:[],...overrides}}const A11yContext=React.createContext(null);
1419
+
1418
1420
  const IMAGE_MARKDOWN_REGEX=/!\[[^\]]*\]\([^)]+\)/g;function getFirstAvailableWidgetIndex(widgetType,widgets){const widgetNames=Object.keys(widgets);for(let i=1;i<=widgetNames.length+1;i++){if(!widgetNames.includes(`${widgetType} ${i}`)){return i}}return 1}async function convertImageMarkdownToImageWidget(question,onEditorChange){const{content,widgets}=question;const newWidgets={...widgets};const matches=Array.from(content.matchAll(IMAGE_MARKDOWN_REGEX));if(matches.length===0){return}const replacements=[];for(const match of matches){const imageIndex=getFirstAvailableWidgetIndex("image",newWidgets);const imageNode=PerseusMarkdown.parse(match[0],{});const imageUrl=imageNode[0].content[0].target;const imageAlt=imageNode[0].content[0].alt;const imageSize=await Util.getImageSizeModern(imageUrl);const[width,height]=imageSize;newWidgets[`image ${imageIndex}`]=generateImageWidget({options:generateImageOptions({backgroundImage:{url:imageUrl,width,height},alt:imageAlt})});replacements.push({original:match[0],replacement:`[[☃ image ${imageIndex}]]`});}let newContent=content;for(const{original,replacement}of replacements){newContent=newContent.replace(original,replacement);}onEditorChange({content:newContent,widgets:newWidgets});}function getCtaForIssueId(issueId,question,onEditorChange){switch(issueId){case "image-markdown":return {label:"Convert all image markdown to widget",onClick:()=>convertImageMarkdownToImageWidget(question,onEditorChange)};default:return null}}
1419
1421
 
1420
1422
  const defaultItemEditorContext={question:{content:"",widgets:{},images:{}},onEditorChange:()=>{}};const ItemEditorContext=React.createContext(defaultItemEditorContext);function useItemEditorContext(){return React.useContext(ItemEditorContext)}
@@ -1423,15 +1425,15 @@ const IssueCta=({issue})=>{const{question,onEditorChange}=useItemEditorContext()
1423
1425
 
1424
1426
  const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,headerStyle,onToggle}=props;return jsxRuntimeExports.jsx(View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$V.container,containerStyle],headerStyle:[styles$V.accordionHeader,headerStyle],header:header,children:jsxRuntimeExports.jsx(View,{style:[styles$V.accordionPanel,panelStyle],children:children})})})};const styles$V=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.instructive.subtle,marginTop:spacing.xSmall_8},accordionHeader:{padding:spacing.small_12,paddingInlineEnd:0,height:spacing.xxLarge_48},accordionPanel:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxxSmall_4,paddingLeft:spacing.small_12,paddingRight:spacing.small_12}});
1425
1427
 
1426
- const ShowMe=({elements})=>{const[showMe,setShowMe]=useState(false);if(!elements||elements.length===0){return null}const getIssueBoundary=element=>{const iframeBoundary=element.ownerDocument.defaultView?.frameElement?.getBoundingClientRect();const elementBoundary=element.getBoundingClientRect();return {top:elementBoundary.top+(iframeBoundary?.top||0),left:elementBoundary.left+(iframeBoundary?.left||0),height:elementBoundary.height,width:elementBoundary.width}};const showMeStyle={marginTop:"1em",display:"flex",alignItems:"center"};const getOutlineStyle=issueBoundary=>showMe&&issueBoundary.width!==0?{display:"block",border:"2px solid red",borderRadius:"4px",position:"fixed",height:issueBoundary.height+8,width:issueBoundary.width+8,top:issueBoundary.top-4,left:issueBoundary.left-4}:{display:"none"};const elementOutlines=elements?.map((element,index)=>{const issueBoundary=getIssueBoundary(element);const outlineStyle=getOutlineStyle(issueBoundary);return jsxRuntimeExports.jsx("div",{style:outlineStyle},index)});const showMeToggle=jsxRuntimeExports.jsxs(BodyText,{size:"small",tag:"span",weight:"bold",style:showMeStyle,children:[jsxRuntimeExports.jsx("span",{style:{marginInlineEnd:"1em"},children:"Show Me"}),jsxRuntimeExports.jsx(Switch,{checked:showMe,onChange:setShowMe}),elementOutlines]});const showMeUnavailable=jsxRuntimeExports.jsx("div",{children:"Unable to find the offending element. Please ask a developer for help fixing this."});return Array.isArray(elementOutlines)&&elementOutlines.length>0?showMeToggle:showMeUnavailable};
1428
+ const showMeStyle={marginBlockStart:"1em",display:"flex",alignItems:"center"};const ShowMe=({instanceId})=>{const[showMe,setShowMe]=React.useState(false);const context=React.useContext(A11yContext);React.useEffect(()=>{return ()=>{if(instanceId!=null){context?.setIssueHighlight(instanceId,false);}}},[]);if(instanceId==null||context==null){return jsxRuntimeExports.jsx("div",{children:"Unable to find the offending element. Please ask a developer for help fixing this."})}const handleChange=checked=>{setShowMe(checked);context.setIssueHighlight(instanceId,checked);};return jsxRuntimeExports.jsxs(BodyText,{size:"small",tag:"span",weight:"bold",style:showMeStyle,children:[jsxRuntimeExports.jsx("span",{style:{marginInlineEnd:"1em"},children:"Show Me"}),jsxRuntimeExports.jsx(Switch,{checked:showMe,onChange:handleChange,"aria-label":"Show Me"})]})};
1427
1429
 
1428
- const impactStringMap={high:"Error",medium:"Warning",low:"Guideline"};const IssueDetails=({issue})=>{const[expanded,setExpanded]=React.useState(false);const toggleVisibility=()=>setExpanded(!expanded);const accordionColor=issue.impact==="high"?semanticColor.feedback.critical.subtle.background:semanticColor.feedback.warning.subtle.background;const messageStyling={whiteSpace:"pre-line",color:semanticColor.core.foreground.critical.default};return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:expanded,onToggle:toggleVisibility,containerStyle:{backgroundColor:accordionColor},panelStyle:{backgroundColor:"white"},header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",style:{textOverflow:"ellipsis",maxWidth:"100%",overflow:"hidden",whiteSpace:"nowrap"},children:`${impactStringMap[issue.impact]}: ${issue.id}`}),children:[jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",children:"Description:"}),jsxRuntimeExports.jsx("span",{children:issue.description}),jsxRuntimeExports.jsx("a",{href:issue.helpUrl,target:"_blank",rel:"noreferrer",children:issue.help}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",style:{marginTop:"1em"},children:"Impact:"}),jsxRuntimeExports.jsxs("span",{style:{fontWeight:"initial"},children:[" ",issue.impact]}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",style:{marginTop:"1em"},children:"Issue:"}),jsxRuntimeExports.jsx("span",{style:messageStyling,children:issue.message}),jsxRuntimeExports.jsx(ShowMe,{elements:issue.elements}),jsxRuntimeExports.jsx(IssueCta,{issue:issue})]})};
1430
+ const impactStringMap={high:"Error",medium:"Warning",low:"Guideline"};const IssueDetails=({issue})=>{const[expanded,setExpanded]=React.useState(false);const toggleVisibility=()=>setExpanded(!expanded);const accordionColor=issue.impact==="high"?semanticColor.feedback.critical.subtle.background:semanticColor.feedback.warning.subtle.background;const messageStyling={whiteSpace:"pre-line",color:semanticColor.core.foreground.critical.default};return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:expanded,onToggle:toggleVisibility,containerStyle:{backgroundColor:accordionColor},panelStyle:{backgroundColor:"white"},header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",style:{textOverflow:"ellipsis",maxWidth:"100%",overflow:"hidden",whiteSpace:"nowrap"},children:`${impactStringMap[issue.impact]}: ${issue.id}`}),children:[jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",children:"Description:"}),jsxRuntimeExports.jsx("span",{children:issue.description}),jsxRuntimeExports.jsx("a",{href:issue.helpUrl,target:"_blank",rel:"noreferrer",children:issue.help}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",style:{marginTop:"1em"},children:"Impact:"}),jsxRuntimeExports.jsxs("span",{style:{fontWeight:"initial"},children:[" ",issue.impact]}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",style:{marginTop:"1em"},children:"Issue:"}),jsxRuntimeExports.jsx("span",{style:messageStyling,children:issue.message}),jsxRuntimeExports.jsx(ShowMe,{instanceId:issue.source==="a11y"?issue.instanceId:undefined}),jsxRuntimeExports.jsx(IssueCta,{issue:issue})]})};
1429
1431
 
1430
1432
  const LabeledSwitch=props=>{const{checked,label,labelSide="end",size="medium",style,disabled=false,onChange}=props;const switchId=useId();const labelElement=jsxRuntimeExports.jsx(BodyText,{size:size==="small"?"small":undefined,tag:"label",htmlFor:switchId,children:label});const strut=jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8});return jsxRuntimeExports.jsxs(View,{style:[styles$U.row,style],children:[labelSide==="start"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[labelElement,strut]}),jsxRuntimeExports.jsx(Switch,{id:switchId,checked:checked,disabled:disabled,onChange:onChange}),labelSide==="end"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[strut,labelElement]})]})};const styles$U=StyleSheet.create({row:{flexDirection:"row",alignItems:"center"}});
1431
1433
 
1432
1434
  function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$T.expanded:styles$T.collapsed;return jsxRuntimeExports.jsx(PhosphorIcon,{icon:caretRight,style:iconStyle})}const styles$T=StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
1433
1435
 
1434
- const IssuesPanel=props=>{const{issues=[]}=props;const a11yCheck=props.a11yCheck||{callback:()=>{},isChecked:false};const[showPanel,setShowPanel]=useState(false);const hasWarnings=issues.length>0;const hasErrors=issues.some(issue=>issue.impact==="high");const issuesCount=`${issues.length} issue${issues.length===1?"":"s"}`;const icon=hasErrors?iconAlert:hasWarnings?iconWarning:iconPass;const iconColor=hasErrors?semanticColor.feedback.critical.strong.icon:hasWarnings?semanticColor.feedback.warning.strong.icon:semanticColor.feedback.success.strong.icon;const impactOrder={high:3,medium:2,low:1};const sortedIssues=issues.sort((a,b)=>{if(impactOrder[b.impact]!==impactOrder[a.impact]){return impactOrder[b.impact]-impactOrder[a.impact]}return a.id.localeCompare(b.id)});return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:()=>setShowPanel(!showPanel),children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginRight:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-content",children:[sortedIssues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{issue:issue},issue.id)),issues.length===0&&jsxRuntimeExports.jsx("div",{children:"No issues found"}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Include axe-core scan",checked:a11yCheck.isChecked,onChange:()=>{a11yCheck.callback();},style:{marginBlockStart:"1rem"}})]})})]})};
1436
+ function getIssueKey(issue){return issue.instanceId??issue.id}const IssuesPanel=props=>{const{issues=[]}=props;const context=useContext(A11yContext);const[showPanel,setShowPanel]=useState(false);const axeCoreIssues=context?.a11yScanningEnabled?context.axeCoreIssues:[];const allIssues=[...issues,...axeCoreIssues];const hasWarnings=allIssues.length>0;const hasErrors=allIssues.some(issue=>issue.impact==="high");const issuesCount=`${allIssues.length} issue${allIssues.length===1?"":"s"}`;const icon=hasErrors?iconAlert:hasWarnings?iconWarning:iconPass;const iconColor=hasErrors?semanticColor.feedback.critical.strong.icon:hasWarnings?semanticColor.feedback.warning.strong.icon:semanticColor.feedback.success.strong.icon;const impactOrder={high:3,medium:2,low:1};const sortedIssues=[...allIssues].sort((a,b)=>{if(impactOrder[b.impact]!==impactOrder[a.impact]){return impactOrder[b.impact]-impactOrder[a.impact]}return a.id.localeCompare(b.id)});return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:()=>setShowPanel(!showPanel),children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginRight:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-content",children:[sortedIssues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{issue:issue},getIssueKey(issue))),allIssues.length===0&&jsxRuntimeExports.jsx("div",{children:"No issues found"}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Include axe-core scan",checked:context?.a11yScanningEnabled??false,onChange:enabled=>{context?.setA11yScanningEnabled(enabled);},style:{marginBlockStart:"1rem"}})]})})]})};
1435
1437
 
1436
1438
  class JsonEditor extends React.Component{getInitialState(){return {currentValue:JSON.stringify(this.props.value,null,4),valid:true}}componentDidUpdate(prevProps){if(!_.isEqual(prevProps.value,this.props.value)){const shouldReplaceContent=!this.state.valid||!_.isEqual(this.props.value,this.getCurrentValueAsJson());if(shouldReplaceContent){this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}}getCurrentValueAsJson(){try{return this.state.currentValue?this.typesafeParseOrThrow(this.state.currentValue):{}}catch{return null}}handleKeyDown(e){if(e.key==="Tab"){const textarea=e.currentTarget;const cursorPos=textarea.selectionStart;const v=textarea.value;const textBefore=v.substring(0,cursorPos);const textAfter=v.substring(cursorPos,v.length);textarea.value=textBefore+" "+textAfter;textarea.selectionStart=textBefore.length+4;textarea.selectionEnd=textBefore.length+4;e.preventDefault();this.processChange(textarea.value);}}handleChange(e){this.processChange(e.target.value);}processChange(nextString){try{const json=this.typesafeParseOrThrow(nextString);this.setState({currentValue:nextString,valid:true},()=>{this.props.onChange(json);});}catch{this.setState({currentValue:nextString,valid:false});}}handleBlur(e){const nextString=e.target.value;try{const json=this.typesafeParseOrThrow(nextString);this.setState({currentValue:JSON.stringify(json,null,4),valid:true},()=>{this.props.onChange(json);});}catch{this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}typesafeParseOrThrow(json){const parsed=this.props.parser(json);if(isSuccess(parsed)){return parsed.value}const parsedFromQuotedString=this.props.parser(JSON.parse(json));if(isSuccess(parsedFromQuotedString)){return parsedFromQuotedString.value}throw new TypeError("JsonEditor: parse failure")}render(){const classes="perseus-json-editor "+(this.state.valid?"valid":"invalid");return jsxRuntimeExports.jsx("textarea",{className:classes,value:this.state.currentValue,onChange:this.handleChange,onKeyDown:this.handleKeyDown,onBlur:this.handleBlur,disabled:this.props.editingDisabled})}constructor(props){super(props);this.state=this.getInitialState();this.handleBlur=this.handleBlur.bind(this);this.handleChange=this.handleChange.bind(this);this.handleKeyDown=this.handleKeyDown.bind(this);}}
1437
1439
 
@@ -1459,21 +1461,21 @@ function setPerseusClipboardData({text,widgets}){const dummyElement=document.cre
1459
1461
 
1460
1462
  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,Object.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)"})]});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]});}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"}),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![]("+imageUrl+")";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![]("+sentinel+")";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=Object.keys(widgetData).map(name=>name.split(" "));const widgetTypes=_.uniq(widgets.map(widget=>widget[0]));const existingWidgets=Object.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,Object.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,showWordCount:false,warnNoPrompt:false,warnNoWidgets:false,additionalTemplates:{},apiOptions:ApiOptions.defaults};
1461
1463
 
1462
- 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}
1464
+ 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`,instanceId:`inaccessible-widget-${widgetId}`,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}
1463
1465
 
1464
1466
  ${errorMessage}`})};
1465
1467
 
1466
- const PREVIEW_MESSAGE_SOURCE="perseus-preview";function createPreviewIframeReadyMessage(){return {source:PREVIEW_MESSAGE_SOURCE,type:"iframe-ready"}}
1468
+ const PREVIEW_MESSAGE_SOURCE="perseus-preview";function createPreviewIframeInitMessage(content,a11yScanningEnabled,contentVersion){return {source:PREVIEW_MESSAGE_SOURCE,type:"iframe-init",content,a11yScanningEnabled,contentVersion}}function createPreviewSetA11yScanningEnabledMessage(enabled){return {source:PREVIEW_MESSAGE_SOURCE,type:"set-a11y-scanning-enabled",enabled}}function createPreviewHighlightIssuesMessage(instanceIds,contentVersion){return {source:PREVIEW_MESSAGE_SOURCE,type:"highlight-issues",instanceIds,contentVersion}}function createPreviewClearHighlightsMessage(){return {source:PREVIEW_MESSAGE_SOURCE,type:"clear-highlights"}}function createPreviewIframeReadyMessage(){return {source:PREVIEW_MESSAGE_SOURCE,type:"iframe-ready"}}function createPreviewA11yReportMessage(violations,needsReview,contentVersion){return {source:PREVIEW_MESSAGE_SOURCE,type:"a11y-report",violations,needsReview,contentVersion}}
1467
1469
 
1468
- 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}
1470
+ function isIframeToParentMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&message.source===PREVIEW_MESSAGE_SOURCE&&"type"in message&&typeof message.type==="string"}function isParentToIframeMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&message.source===PREVIEW_MESSAGE_SOURCE&&"type"in message&&typeof message.type==="string"}
1469
1471
 
1470
1472
  function sanitizeApiOptions(apiOptions){const{onFocusChange,answerableCallback,getAnotherHint,interactionCallback,trackInteraction,baseElements,imagePlaceholder,widgetPlaceholder,...serializableOptions}=apiOptions;return serializableOptions}
1471
1473
 
1472
1474
  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)}}
1473
1475
 
1474
- 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}}
1476
+ function usePreviewController(iframeRef){const[height,setHeight]=React.useState(null);const[isIframeReady,setIsIframeReady]=React.useState(false);const[a11yReport,setA11yReport]=React.useState(null);const currentContentRef=React.useRef(null);const currentA11yScanningEnabledRef=React.useRef(false);const postToIframe=React.useCallback(message=>{iframeRef.current?.contentWindow?.postMessage(message,"/");},[iframeRef]);const contentVersionRef=React.useRef(0);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":{postToIframe(createPreviewIframeInitMessage(currentContentRef.current?sanitizePreviewData(currentContentRef.current):null,currentA11yScanningEnabledRef.current,contentVersionRef.current));setIsIframeReady(true);break}case "height-update":setHeight(message.height);break;case "a11y-report":if(message.contentVersion!==contentVersionRef.current){break}setA11yReport({violations:message.violations,needsReview:message.needsReview});break;default:throw new UnreachableCaseError(message)}};window.addEventListener("message",handleMessage);return ()=>{window.removeEventListener("message",handleMessage);}},[iframeRef,postToIframe]);const sendData=React.useCallback(data=>{currentContentRef.current=data;contentVersionRef.current+=1;if(!isIframeReady){return}const message={source:PREVIEW_MESSAGE_SOURCE,type:"content-data",content:sanitizePreviewData(data),contentVersion:contentVersionRef.current};postToIframe(message);},[isIframeReady,postToIframe]);const setA11yScanningEnabled=React.useCallback(enabled=>{currentA11yScanningEnabledRef.current=enabled;if(!isIframeReady){return}postToIframe(createPreviewSetA11yScanningEnabledMessage(enabled));},[isIframeReady,postToIframe]);const highlightIssues=React.useCallback(instanceIds=>{postToIframe(createPreviewHighlightIssuesMessage(instanceIds,contentVersionRef.current));},[postToIframe]);const clearHighlights=React.useCallback(()=>{postToIframe(createPreviewClearHighlightsMessage());},[postToIframe]);return {sendData,height,setA11yScanningEnabled,highlightIssues,clearHighlights,a11yReport}}
1475
1477
 
1476
- 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";
1478
+ function PreviewWithIframe(props){const iframeRef=React.useRef(null);const{sendData,height,setA11yScanningEnabled,highlightIssues,clearHighlights,a11yReport}=usePreviewController(iframeRef);React.useEffect(()=>{if(props.content!=null){sendData(props.content);}},[sendData,props.content]);React.useEffect(()=>{setA11yScanningEnabled(props.a11yScanningEnabled??false);},[setA11yScanningEnabled,props.a11yScanningEnabled]);React.useEffect(()=>{if(props.highlightInstanceIds!=null&&props.highlightInstanceIds.length>0){highlightIssues(props.highlightInstanceIds);}else {clearHighlights();}},[highlightIssues,clearHighlights,props.highlightInstanceIds]);const{onA11yReport}=props;React.useEffect(()=>{onA11yReport?.(a11yReport);},[a11yReport,onA11yReport]);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";
1477
1479
 
1478
1480
  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."]}}};
1479
1481
 
@@ -1515,21 +1517,25 @@ class HintEditor extends React.Component{serialize(){invariant(this.editor.curre
1515
1517
 
1516
1518
  const calculatorVariants=[{label:"Scientific calculator",variant:"scientific"},{label:"Graphing calculator",variant:"graphing"},{label:"Four-function calculator",variant:"four_function"}];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,calculatorVariant}=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")&&calculatorVariant!==undefined&&jsxRuntimeExports.jsx(RadioGroup,{groupName:"calculator-variant",selectedValue:calculatorVariant,onChange:this.handleVariantChange,style:styles$P.indented,children:calculatorVariants.map((calcVariant,_)=>jsxRuntimeExports.jsx(Choice,{value:calcVariant.variant,label:calcVariant.label,disabled:editingDisabled,style:styles$P.calculatorChoice},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})]})})}constructor(...args){super(...args),this.handleVariantChange=newVariant=>{const selected=calculatorVariants.find(({variant})=>variant===newVariant);if(selected){this.props.onChange({calculatorVariant:selected.variant});}};}}ItemExtrasEditor.defaultProps=getDefaultAnswerArea();const ItemExtraCheckbox=props=>jsxRuntimeExports.jsx(View,{style:[styles$P.checkbox,props.indent?styles$P.indented:undefined],children:jsxRuntimeExports.jsx(Checkbox$1,{disabled:props.disabled,label:jsxRuntimeExports.jsxs(View,{style:{flexDirection:"row"},children:[props.label," ",jsxRuntimeExports.jsx(InfoTip,{children:props.infoTip})]}),checked:props.checked,onChange:newCheckedState=>props.onChange(newCheckedState)})});const styles$P=StyleSheet.create({indented:{marginInlineStart:spacing.large_24},calculatorChoice:{marginBlock:sizing.size_010}});
1517
1519
 
1518
- 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.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:{}};
1520
+ function legacyPerseusLintEqual(a,b){return a.length===b.length&&a.every((warning,i)=>warning===b[i])}function inputsEqual(a,b){return a.question===b.question&&a.apiOptions===b.apiOptions&&a.deviceType===b.deviceType&&a.highlightLint===b.highlightLint&&a.problemNum===b.problemNum&&legacyPerseusLintEqual(a.legacyPerseusLint,b.legacyPerseusLint)}function buildContent(inputs){return {type:"question",data:{question:inputs.question,apiOptions:{...ApiOptions.defaults,...inputs.apiOptions,customKeypad:inputs.deviceType==="phone"||inputs.deviceType==="tablet"},linterContext:{contentType:"exercise",highlightLint:inputs.highlightLint},reviewMode:true,legacyPerseusLint:inputs.legacyPerseusLint,problemNum:inputs.problemNum}}}function createPreviewContentDeriver(){let lastInputs=null;let lastContent=null;return inputs=>{if(!inputs.question){return null}if(lastInputs&&inputsEqual(inputs,lastInputs)){return lastContent}const content=buildContent(inputs);lastInputs=inputs;lastContent=content;return content}}
1519
1521
 
1520
- 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"]}};
1522
+ 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;const a11yScanningEnabled=this.context?.a11yScanningEnabled??false;const highlightInstanceIds=this.context?.highlightInstanceIds??[];return 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({question:this.props.question,apiOptions:this.props.apiOptions,deviceType:this.props.deviceType,highlightLint:this.props.highlightLint,problemNum:this.props.problemNum,legacyPerseusLint:this.getSaveWarnings()??[]}),a11yScanningEnabled:a11yScanningEnabled,highlightInstanceIds:highlightInstanceIds,onA11yReport:this.handleA11yReport},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.derivePreviewContent=createPreviewContentDeriver(),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()},this.handleA11yReport=report=>{this.context?.onA11yReport(report);};}}ItemEditor.contextType=A11yContext;ItemEditor.defaultProps={onChange:()=>{},question:{},answerArea:{}};
1521
1523
 
1522
- const assistanceNeededMessage="Developer assistance needed - Please send this exercise and warning info to the LEMS team for review.";const previewIframeSelector='.perseus-question-container iframe[data-name="content-preview"]';const axeCoreEditorOptions={include:"#page-container",exclude:'[target="lint-help-window"]'};const axeCoreStorybookOptions={include:{fromFrames:['iframe[data-name="content-preview"]',"#storybook-root > .framework-perseus"]},exclude:{fromFrames:['iframe[data-name="content-preview"]','[target="lint-help-window"]']}};const convertAxeImpactToIssueImpact=impact=>{switch(impact){case "critical":return "high";case "serious":return "high";case "moderate":return "medium";case "minor":return "low";default:return "low"}};const getIssueMessage=nodes=>{return nodes.flatMap(node=>{return node.all.concat(node.any,node.none).map(result=>result.message)}).filter((message,index,allMessages)=>allMessages.indexOf(message)===index).join(". ")};const getIssueElements=(nodes,iFrameElement)=>{return nodes.flatMap(node=>{return node.target.reduce((elements,target)=>{let element=null;if(elements.length>0&&elements[elements.length-1].tagName.toLowerCase()==="iframe"){elements[elements.length-1]=elements[elements.length-1].contentDocument.querySelector(target);}else if(iFrameElement){element=iFrameElement.contentDocument?.querySelector(target)||null;}else {element=document.querySelector(target);}if(element){elements.push(element);}return elements},[])})};const mapResultsToIssues=(results,type,iFrameElement)=>{return results.map(result=>{const isUserFixable=type==="Alert"&&issuesList["axe-core"]["user-fixable"].some(testId=>testId===result.id);const description=isUserFixable?"":assistanceNeededMessage;const issueInfo={id:result.id,description:description,elements:getIssueElements(result.nodes,iFrameElement),helpUrl:result.helpUrl,help:result.help,impact:convertAxeImpactToIssueImpact(result.impact),message:getIssueMessage(result.nodes),type:type};return issueInfo})};const runAxeCore=(updateIssuesFn,logToConsole=false)=>{const isInStorybook=!!document.getElementById("storybook-root");if(!isInStorybook){let frameHasLoaded=false;const frame=document.querySelector(previewIframeSelector);if(frame){const frameDocument=frame.contentDocument||frame.contentWindow?.document;frameHasLoaded=frameDocument?.readyState==="complete";}if(!frameHasLoaded){setTimeout(runAxeCore,100,updateIssuesFn);return}}const log=(...args)=>{if(logToConsole){console.log(...args);}};const options=isInStorybook?axeCoreStorybookOptions:axeCoreEditorOptions;log("Axe Core options: ",options);const previewWindow=document.querySelector(previewIframeSelector);const axeCoreProper=isInStorybook?axeCore:previewWindow?.contentWindow?.axe;axeCoreProper?.configure({reporter:"v2"});axeCoreProper?.run(options).then(results=>{log(`Accessibility Results: `,results);const violations=mapResultsToIssues(results.violations,"Alert",isInStorybook?null:previewWindow);const incompletes=mapResultsToIssues(results.incomplete,"Warning",isInStorybook?null:previewWindow);const issues=violations.concat(incompletes);log(` Issues: `,issues);if(violations.length===0&&incompletes.length===0&&results.passes.length===0){setTimeout(runAxeCore,1500,updateIssuesFn,logToConsole);}else {updateIssuesFn(issues);}},error=>{log(`*** Error: `,error);});};const runAxeCoreOnUpdate=(priorTimeoutId,setState,logToConsole)=>{clearTimeout(priorTimeoutId);return setTimeout(runAxeCore,1500,setState,logToConsole)};
1524
+ function buildDeviceApiOptions(inputs){return {...ApiOptions.defaults,...inputs.apiOptions,customKeypad:inputs.touch,isMobile:inputs.touch}}function createDeviceApiOptionsDeriver(){let lastInputs=null;let lastResult=null;return inputs=>{if(lastResult!=null&&lastInputs!=null&&lastInputs.apiOptions===inputs.apiOptions&&lastInputs.touch===inputs.touch){return lastResult}const result=buildDeviceApiOptions(inputs);lastInputs=inputs;lastResult=result;return result}}
1523
1525
 
1524
- 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]}
1526
+ 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}`,instanceId:`hint-${i+1}-${getIssueKey(issue)}`,message:`Hint ${i+1}: ${issue.message}`})));return [...hostIssues??[],...questionIssues,...hintIssues]}
1525
1527
 
1526
- 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.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},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.handleEditorChange=newProps=>{this.handleChange({question:{...this.props.question,...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:()=>{}};
1528
+ 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)});}}syncJsonStateFromProps(){this.setState({json:{question:this.props.question,answerArea:this.props.answerArea,hints:this.props.hints}});}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.deriveDeviceApiOptions({apiOptions:this.props.apiOptions,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.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},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})}),jsxRuntimeExports.jsxs(A11yContext.Provider,{value:createA11yContextValue({setIssueHighlight:this.setIssueHighlight,a11yScanningEnabled:this.state.a11yScanningEnabled,setA11yScanningEnabled:this.setA11yScanningEnabled,highlightInstanceIds:this.state.highlightInstanceIds,onA11yReport:this.handleA11yReport,axeCoreIssues:this.state.axeCoreIssues}),children:[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})})})}),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.deriveDeviceApiOptions=createDeviceApiOptionsDeriver(),this.setIssueHighlight=(instanceId,highlighted)=>{this.setState(prevState=>{const current=prevState.highlightInstanceIds;if(highlighted===current.includes(instanceId)){return null}return {highlightInstanceIds:highlighted?[...current,instanceId]:current.filter(id=>id!==instanceId)}});},this.handleA11yReport=report=>{this.setState({axeCoreIssues:report?[...report.violations,...report.needsReview]:[]});},this.setA11yScanningEnabled=enabled=>{this.setState({a11yScanningEnabled:enabled});},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.handleEditorChange=newProps=>{this.handleChange({question:{...this.props.question,...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:[],a11yScanningEnabled:false,highlightInstanceIds:[]};}}EditorPage.defaultProps={answerArea:getDefaultAnswerArea(),developerMode:false,hints:[],jsonMode:false,onChange:()=>{}};
1527
1529
 
1528
1530
  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();}}
1529
1531
 
1530
1532
  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$O.container,!seamless?styles$O.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$O=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginRight:lintGutterWidth}});
1531
1533
 
1532
- 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}}
1534
+ 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"]}};
1535
+
1536
+ const assistanceNeededMessage="Developer assistance needed - Please send this exercise and warning info to the LEMS team for review.";const mapAxeResults=(results,type)=>{const prefix=type==="Alert"?"violation":"incomplete";const issues=[];const elementMap=new Map;results.forEach(result=>{const isUserFixable=type==="Alert"&&issuesList["axe-core"]["user-fixable"].some(testId=>testId===result.id);const instanceId=`${prefix}-${result.id}`;issues.push({source:"a11y",id:result.id,description:isUserFixable?"":assistanceNeededMessage,instanceId,helpUrl:result.helpUrl,help:result.help,impact:convertAxeImpactToIssueImpact(result.impact),message:getIssueMessage(result.nodes)});elementMap.set(instanceId,result.nodes.map(node=>node.element).filter(element=>element!=null));});return {issues,elementMap}};const getIssueMessage=nodes=>{return [...new Set(nodes.flatMap(node=>[...node.all,...node.any,...node.none].map(result=>result.message)))].join(". ")};const convertAxeImpactToIssueImpact=impact=>{switch(impact){case "critical":return "high";case "serious":return "high";case "moderate":return "medium";case "minor":return "low";default:return "low"}};
1537
+
1538
+ function usePreviewPresenter(options={}){const{contentContainerRef}=options;const[content,setContent]=React.useState(null);const[contentVersion,setContentVersion]=React.useState(0);const[a11yScanningEnabled,setA11yScanningEnabled]=React.useState(false);const[highlightTargets,setHighlightTargets]=React.useState([]);const schedule=useActionScheduler();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);setContentVersion(message.contentVersion);break;case "iframe-init":setContent(message.content);setA11yScanningEnabled(message.a11yScanningEnabled);setContentVersion(message.contentVersion);break;case "set-a11y-scanning-enabled":setA11yScanningEnabled(message.enabled);break;case "highlight-issues":if(message.contentVersion!==contentVersionRef.current){break}setHighlightTargets(message.instanceIds.flatMap(instanceId=>elementMapRef.current.get(instanceId)??[]));break;case "clear-highlights":setHighlightTargets([]);break;default:throw new UnreachableCaseError(message)}};window.addEventListener("message",handleMessage);window.parent.postMessage(createPreviewIframeReadyMessage(),"/");return ()=>{window.removeEventListener("message",handleMessage);}},[]);const a11yScanningEnabledRef=React.useRef(a11yScanningEnabled);React.useEffect(()=>{a11yScanningEnabledRef.current=a11yScanningEnabled;},[a11yScanningEnabled]);const contentVersionRef=React.useRef(contentVersion);React.useEffect(()=>{contentVersionRef.current=contentVersion;},[contentVersion]);React.useEffect(()=>{setHighlightTargets([]);},[contentVersion]);const scanPromiseRef=React.useRef(null);const rescanRequestedRef=React.useRef(false);const elementMapRef=React.useRef(new Map);const startScan=React.useCallback(()=>{const container=contentContainerRef?.current;if(!a11yScanningEnabledRef.current||container==null){return}if(scanPromiseRef.current!=null){rescanRequestedRef.current=true;return}const scannedVersion=contentVersionRef.current;scanPromiseRef.current=(async()=>{const axe=(await import('axe-core')).default;axe.configure({reporter:"v2"});const results=await axe.run({include:container,exclude:[['[target="lint-help-window"]']]},{elementRef:true});if(!a11yScanningEnabledRef.current){return}const{issues:violations,elementMap:violationMap}=mapAxeResults(results.violations,"Alert");const{issues:incompletes,elementMap:incompleteMap}=mapAxeResults(results.incomplete,"Warning");elementMapRef.current=new Map([...violationMap,...incompleteMap]);window.parent.postMessage(createPreviewA11yReportMessage(violations,incompletes,scannedVersion),"/");})().finally(()=>{scanPromiseRef.current=null;if(rescanRequestedRef.current){rescanRequestedRef.current=false;startScan();}});},[contentContainerRef]);React.useEffect(()=>{const container=contentContainerRef?.current;if(!a11yScanningEnabled||content==null||container==null){return}const scheduledScan=schedule.timeout(startScan,1500);return ()=>scheduledScan.clear()},[content,contentVersion,a11yScanningEnabled,contentContainerRef,schedule,startScan]);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,a11yScanningEnabled,highlightTargets}}
1533
1539
 
1534
1540
  const textWidthCache={};function getTextWidth(text){if(!textWidthCache[text]){const $test=$("<span>").text(text).appendTo("body");textWidthCache[text]=$test.width()+5;$test.remove();}return textWidthCache[text]}class TextListEditor extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({items:nextProps.options.concat("")});}render(){const className=["perseus-text-list-editor","perseus-clearfix","layout-"+this.props.layout].join(" ");const inputs=this.state.items.map((item,i)=>{return jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsx("input",{ref:"input_"+i,type:"text",value:item,onChange:this.onChange.bind(this,i),onKeyDown:this.onKeyDown.bind(this,i),style:{width:getTextWidth(item)}})},i)});return jsxRuntimeExports.jsx("ul",{className:className,children:inputs})}constructor(...args){super(...args),this.state={items:this.props.options.concat("")},this.onChange=(index,event)=>{let items=_.clone(this.state.items);items[index]=event.target.value;if(index===items.length-1){items=items.concat("");}this.setState({items:items});this.props.onChange(_.compact(items));},this.onKeyDown=(index,event)=>{const which=event.nativeEvent.keyCode;if(which===8&&this.state.items[index]===""){event.preventDefault();const items=_.clone(this.state.items);const focusIndex=index===0?0:index-1;if(index===items.length-1&&(index===0||items[focusIndex]!=="")){ReactDOM.findDOMNode(this.refs["input_"+focusIndex]).focus();}else {items.splice(index,1);this.setState({items:items},function(){ReactDOM.findDOMNode(this.refs["input_"+focusIndex]).focus();});}}else if(which===8&&this.state.items[index].length===1&&index===this.state.items.length-2){event.preventDefault();const items=_.clone(this.state.items);items.splice(index,1);this.setState({items:items});this.props.onChange(_.compact(items));}else if(which===13){event.preventDefault();const items=_.clone(this.state.items);const focusIndex=index+1;if(index===items.length-2){ReactDOM.findDOMNode(this.refs["input_"+focusIndex]).focus();}else {items.splice(focusIndex,0,"");this.setState({items:items},function(){ReactDOM.findDOMNode(this.refs["input_"+focusIndex]).focus();});}}};}}TextListEditor.propTypes={options:PropTypes.array,layout:PropTypes.oneOf(["horizontal","vertical"]),onChange:PropTypes.func.isRequired};TextListEditor.defaultProps={options:[],layout:"horizontal"};
1535
1541
 
@@ -1787,7 +1793,7 @@ const StartCoordsSettingsInner=props=>{const{type,range,step,allowReflexAngles,o
1787
1793
 
1788
1794
  function toTrio(pointLabels){return [pointLabels[0]??"",pointLabels[1]??"",pointLabels[2]??""]}function toPair(pointLabels){return [pointLabels[0]??"",pointLabels[1]??""]}function toArray(pointLabels){return [...pointLabels]}function reshapePointLabelsForGraphType(pointLabels,graph,correct){if(!graph?.type||!correct){return null}let nextGraph;let nextCorrect=correct;switch(graph.type){case "angle":case "quadratic":{const reshaped=toTrio(pointLabels);nextGraph={...graph,pointLabels:reshaped};if(correct.type===graph.type){nextCorrect={...correct,pointLabels:reshaped};}break}case "absolute-value":case "linear":case "ray":{const reshaped=toPair(pointLabels);nextGraph={...graph,pointLabels:reshaped};if(correct.type===graph.type){nextCorrect={...correct,pointLabels:reshaped};}break}case "circle":case "exponential":case "linear-system":case "logarithm":case "point":case "polygon":case "segment":case "sinusoid":case "tangent":{const reshaped=toArray(pointLabels);nextGraph={...graph,pointLabels:reshaped};if(correct.type===graph.type){nextCorrect={...correct,pointLabels:reshaped};}break}case "vector":case "none":return null}return {graph:nextGraph,correct:nextCorrect}}
1789
1795
 
1790
- const InteractiveGraph=InteractiveGraphWidget.widget;class InteractiveGraphEditor extends React.Component{serialize(){const json=_.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","showAxisArrows","showAxisTicks","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();_.extend(json,{graph:{type:correct.type,startCoords:this.props.graph&&getStartCoords(this.props.graph),...this.props.graph&&"pointLabels"in this.props.graph&&this.props.graph.pointLabels?{pointLabels:this.props.graph.pointLabels}:{},...this.props.graph&&"showPointLabels"in this.props.graph&&this.props.graph.showPointLabels?{showPointLabels:this.props.graph.showPointLabels}:{}},correct:correct});_.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(_.has(correct,key)){json.graph[key]=correct[key];}});}else {_.extend(json,{graph:this.props.graph,correct:this.props.correct});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const sizeClass=containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct.type===this.props.graph?.type?this.props.correct:this.props.graph;const graphProps={ref:"graph",box:this.props.box,range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,static:this.props.apiOptions?.editingDisabled??false,trackInteraction:function(){},userInput:this.props.static===true&&correct!=null&&"showPointLabels"in correct?{...correct,showPointLabels:false}:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant(newGraph!=null);if(this.props.static===true&&newGraph!=null&&"showPointLabels"in newGraph){newGraph={...newGraph,showPointLabels:"showPointLabels"in correct?correct.showPointLabels:undefined};}if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(Id,{children:graphId=>jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type",labelSize:"medium",children:jsxRuntimeExports.jsx(GraphTypeSelector,{disabled:this.props.apiOptions?.editingDisabled??false,graphType:this.props.graph?.type??InteractiveGraph.defaultProps.userInput.type,onChange:type=>{this.props.onChange({graph:{type},correct:{type}});}})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsx(AngleAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(GraphPointsCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsx(PolygonAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="vector"&&jsxRuntimeExports.jsx(VectorAnswerOptions,{correct:this.props.correct,onChange:this.props.onChange}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(SegmentCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),!this.props.static&&this.props.graph?.type&&this.props.graph.type!=="vector"&&this.props.graph.type!=="none"&&jsxRuntimeExports.jsx(ShowPointLabelsToggle,{showPointLabels:this.props.graph.showPointLabels===true,pointLabels:this.props.graph.pointLabels,onChange:this.changeShowPointLabels}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.changeStartCoords,onChangePointLabels:this.changePointLabels}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures,editingDisabled:this.props.apiOptions?.editingDisabled??false}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange,apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange,apiOptions:this.props.apiOptions})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.changePointLabels=pointLabels=>{const next=reshapePointLabelsForGraphType(pointLabels,this.props.graph,this.props.correct);if(next){this.props.onChange(next);}},this.changeShowPointLabels=showPointLabels=>{const{graph,correct}=this.props;if(graph===undefined||correct===undefined){return}const newGraph=withShowPointLabels(graph,showPointLabels);const newCorrect=withShowPointLabels(correct,showPointLabels);if(newGraph===undefined||newCorrect===undefined){return}this.props.onChange({graph:newGraph,correct:newCorrect});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}if(this.props.graph?.type==="exponential"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteY=asymptote;const minY=Math.min(coords[0][1],coords[1][1]);const maxY=Math.max(coords[0][1],coords[1][1]);if(asymptoteY>=minY&&asymptoteY<=maxY){issues.push("The exponential start asymptote must not fall between or on the curve's start points.");}}if(this.props.graph?.type==="logarithm"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteX=asymptote;const minX=Math.min(coords[0][0],coords[1][0]);const maxX=Math.max(coords[0][0],coords[1][0]);if(asymptoteX>=minX&&asymptoteX<=maxX){issues.push("The logarithm start asymptote must not fall between or on the curve's start points.");}}return issues};}}InteractiveGraphEditor.widgetName="interactive-graph";InteractiveGraphEditor.bestPractices={url:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/3295281289/Interactive+Graph+Widget#Adding-a-new-Interactive-Graph-Widget",label:"Interactive Graph best practices"};InteractiveGraphEditor.defaultProps={...interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant(b.type==="angle");return {...a,...b};case "circle":invariant(b.type==="circle");return {...a,...b};case "linear":invariant(b.type==="linear");return {...a,...b};case "linear-system":invariant(b.type==="linear-system");return {...a,...b};case "none":invariant(b.type==="none");return {...a,...b};case "point":invariant(b.type==="point");return {...a,...b};case "polygon":invariant(b.type==="polygon");return {...a,...b};case "quadratic":invariant(b.type==="quadratic");return {...a,...b};case "ray":invariant(b.type==="ray");return {...a,...b};case "segment":invariant(b.type==="segment");return {...a,...b};case "sinusoid":invariant(b.type==="sinusoid");return {...a,...b};case "absolute-value":invariant(b.type==="absolute-value");return {...a,...b};case "exponential":invariant(b.type==="exponential");return {...a,...b};case "tangent":invariant(b.type==="tangent");return {...a,...b};case "logarithm":invariant(b.type==="logarithm");return {...a,...b};case "vector":invariant(b.type==="vector");return {...a,...b};default:throw new UnreachableCaseError(a)}}function withShowPointLabels(graph,showPointLabels){switch(graph.type){case "absolute-value":case "angle":case "circle":case "exponential":case "linear":case "linear-system":case "logarithm":case "point":case "polygon":case "quadratic":case "ray":case "segment":case "sinusoid":case "tangent":return {...graph,showPointLabels};case "none":case "vector":return undefined;default:throw new UnreachableCaseError(graph)}}
1796
+ const InteractiveGraph=InteractiveGraphWidget.widget;class InteractiveGraphEditor extends React.Component{serialize(){const json=_.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","showAxisArrows","showAxisTicks","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();_.extend(json,{graph:{type:correct.type,startCoords:getStartCoords(this.props.graph),..."pointLabels"in this.props.graph&&this.props.graph.pointLabels?{pointLabels:this.props.graph.pointLabels}:{},..."showPointLabels"in this.props.graph&&this.props.graph.showPointLabels?{showPointLabels:this.props.graph.showPointLabels}:{}},correct:correct});_.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(_.has(correct,key)){json.graph[key]=correct[key];}});}else {_.extend(json,{graph:this.props.graph,correct:this.props.correct});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const sizeClass=containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct.type===this.props.graph?.type?this.props.correct:this.props.graph;const graphProps={ref:"graph",box:this.props.box,range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,static:this.props.apiOptions?.editingDisabled??false,trackInteraction:function(){},userInput:this.props.static===true&&correct!=null&&"showPointLabels"in correct?{...correct,showPointLabels:false}:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant(newGraph!=null);if(this.props.static===true&&newGraph!=null&&"showPointLabels"in newGraph){newGraph={...newGraph,showPointLabels:"showPointLabels"in correct?correct.showPointLabels:undefined};}if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(Id,{children:graphId=>jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type",labelSize:"medium",children:jsxRuntimeExports.jsx(GraphTypeSelector,{disabled:this.props.apiOptions?.editingDisabled??false,graphType:this.props.graph?.type??"none",onChange:type=>{this.props.onChange({graph:{type},correct:{type}});}})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsx(AngleAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(GraphPointsCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsx(PolygonAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="vector"&&jsxRuntimeExports.jsx(VectorAnswerOptions,{correct:this.props.correct,onChange:this.props.onChange}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(SegmentCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),!this.props.static&&this.props.graph?.type&&this.props.graph.type!=="vector"&&this.props.graph.type!=="none"&&jsxRuntimeExports.jsx(ShowPointLabelsToggle,{showPointLabels:this.props.graph.showPointLabels===true,pointLabels:this.props.graph.pointLabels,onChange:this.changeShowPointLabels}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.changeStartCoords,onChangePointLabels:this.changePointLabels}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures,editingDisabled:this.props.apiOptions?.editingDisabled??false}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange,apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange,apiOptions:this.props.apiOptions})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.changePointLabels=pointLabels=>{const next=reshapePointLabelsForGraphType(pointLabels,this.props.graph,this.props.correct);if(next){this.props.onChange(next);}},this.changeShowPointLabels=showPointLabels=>{const{graph,correct}=this.props;if(graph===undefined||correct===undefined){return}const newGraph=withShowPointLabels(graph,showPointLabels);const newCorrect=withShowPointLabels(correct,showPointLabels);if(newGraph===undefined||newCorrect===undefined){return}this.props.onChange({graph:newGraph,correct:newCorrect});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}if(this.props.graph?.type==="exponential"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteY=asymptote;const minY=Math.min(coords[0][1],coords[1][1]);const maxY=Math.max(coords[0][1],coords[1][1]);if(asymptoteY>=minY&&asymptoteY<=maxY){issues.push("The exponential start asymptote must not fall between or on the curve's start points.");}}if(this.props.graph?.type==="logarithm"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteX=asymptote;const minX=Math.min(coords[0][0],coords[1][0]);const maxX=Math.max(coords[0][0],coords[1][0]);if(asymptoteX>=minX&&asymptoteX<=maxX){issues.push("The logarithm start asymptote must not fall between or on the curve's start points.");}}return issues};}}InteractiveGraphEditor.widgetName="interactive-graph";InteractiveGraphEditor.bestPractices={url:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/3295281289/Interactive+Graph+Widget#Adding-a-new-Interactive-Graph-Widget",label:"Interactive Graph best practices"};InteractiveGraphEditor.defaultProps={...interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant(b.type==="angle");return {...a,...b};case "circle":invariant(b.type==="circle");return {...a,...b};case "linear":invariant(b.type==="linear");return {...a,...b};case "linear-system":invariant(b.type==="linear-system");return {...a,...b};case "none":invariant(b.type==="none");return {...a,...b};case "point":invariant(b.type==="point");return {...a,...b};case "polygon":invariant(b.type==="polygon");return {...a,...b};case "quadratic":invariant(b.type==="quadratic");return {...a,...b};case "ray":invariant(b.type==="ray");return {...a,...b};case "segment":invariant(b.type==="segment");return {...a,...b};case "sinusoid":invariant(b.type==="sinusoid");return {...a,...b};case "absolute-value":invariant(b.type==="absolute-value");return {...a,...b};case "exponential":invariant(b.type==="exponential");return {...a,...b};case "tangent":invariant(b.type==="tangent");return {...a,...b};case "logarithm":invariant(b.type==="logarithm");return {...a,...b};case "vector":invariant(b.type==="vector");return {...a,...b};default:throw new UnreachableCaseError(a)}}function withShowPointLabels(graph,showPointLabels){switch(graph.type){case "absolute-value":case "angle":case "circle":case "exponential":case "linear":case "linear-system":case "logarithm":case "point":case "polygon":case "quadratic":case "ray":case "segment":case "sinusoid":case "tangent":return {...graph,showPointLabels};case "none":case "vector":return undefined;default:throw new UnreachableCaseError(graph)}}
1791
1797
 
1792
1798
  const gray98="#FAFAFA";const gray95="#F0F1F2";const gray85="#D6D8DA";const gray76="#BABEC2";const gray68="#888D93";const gray41="#626569";const gray17="#21242C";
1793
1799