@khanacademy/perseus 65.4.0 → 65.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1471,7 +1471,7 @@ const ApiOptions={propTypes:PropTypes__default.default.shape({isArticle:PropType
1471
1471
 
1472
1472
  const getPromptJSON$t=(renderProps,userInput)=>{return {type:"expression",label:renderProps.visibleLabel,userInput:{value:userInput}}};
1473
1473
 
1474
- const englishOperators={arctg:"arctan",cosec:"csc",cossec:"csc",cotg:"cot",ctg:"cot",sen:"sin",tg:"tan"};const anglicizeOperators=tex=>{return tex.replace(/\\operatorname{([a-z]+)}/g,(_,op)=>`\\${englishOperators[op]??op} `)};const normalizeTex=tex=>{return anglicizeOperators(tex)};class Expression extends React__namespace.Component{getUserInput(){return normalizeTex(this.props.userInput)}getPromptJSON(){return getPromptJSON$t(this.props,this.getUserInput())}focusInputPath(inputPath){this.refs.input.focus();}blurInputPath(inputPath){if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}}insert(keyPressed){this.refs.input.insert(keyPressed);}setInputValue(path,newValue,cb){this.props.handleUserInput(newValue,cb);}getSerializedState(){const{userInput:_,...rest}=this.props;return {...rest,value:this.props.userInput}}render(){if(this.props.apiOptions.customKeypad){return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:aphrodite.css(styles$I.mobileLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsx(mathInput.KeypadInput,{ref:"input",ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,value:this.props.userInput,keypadElement:this.props.keypadElement,onChange:this.changeAndTrack,onFocus:()=>{this.props.keypadElement?.configure(this.props.keypadConfiguration,()=>{if(this._isMounted){this._handleFocus();}});},onBlur:this._handleBlur})]})}const className=classNames__default.default({"perseus-widget-expression":true,"show-error-tooltip":this.state.showErrorTooltip});const{ERROR_MESSAGE,ERROR_TITLE}=this.context.strings;return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:aphrodite.css(styles$I.desktopLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsxs("div",{className:className,onBlur:()=>this.state.invalid&&this.setState({showErrorTooltip:true,showErrorStyle:true}),onFocus:()=>this.setState({showErrorTooltip:false}),children:[jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:a11y.srOnly,role:"alert",children:this.state.showErrorTooltip&&ERROR_TITLE+" "+ERROR_MESSAGE}),jsxRuntimeExports.jsx(Tooltip__default.default,{forceAnchorFocusivity:false,opened:this.state.showErrorTooltip,title:ERROR_TITLE,content:ERROR_MESSAGE,children:jsxRuntimeExports.jsx(MathInput,{ref:"input",value:this.props.userInput,onChange:this.changeAndTrack,convertDotToTimes:this.props.times,buttonSets:this.props.buttonSets,onFocus:this._handleFocus,onBlur:this._handleBlur,hasError:this.state.showErrorStyle,ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,extraKeys:this.props.keypadConfiguration?.extraKeys,onAnalyticsEvent:this.props.analytics?.onAnalyticsEvent??(async()=>{})})})]})]})}constructor(...args){super(...args),this._textareaId=`expression_textarea_${Date.now()}`,this._isMounted=false,this.displayName="Expression",this.state={invalid:false,showErrorTooltip:false,showErrorStyle:false},this.componentDidMount=()=>{document.addEventListener("mousedown",this._handleMouseDown);this._isMounted=true;if(this.refs.input){const isMobile=this.props.apiOptions.customKeypad;const container=ReactDOM__namespace.default.findDOMNode(this.refs.input);const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=container.querySelector(selector);inputElement?.setAttribute("id",this._textareaId);}},this.componentDidUpdate=prevProps=>{if(!___default.default.isEqual(this.props.userInput,prevProps.userInput)||!___default.default.isEqual(this.props.functions,prevProps.functions)){this.setState({invalid:false,showErrorTooltip:false,showErrorStyle:false});if(!this.parse(this.props.userInput,this.props).parsed){this.setState({invalid:true});}}},this.componentWillUnmount=()=>{this._isMounted=false;},this._handleMouseDown=()=>{if(this._isMounted&&this.state.showErrorTooltip){this.setState({showErrorTooltip:false});}},this.parse=(value,props)=>{const options=___default.default.pick(props||this.props,"functions");___default.default.extend(options,{decimal_separator:perseusCore.getDecimalSeparator(this.context.locale)});return KAS__namespace.parse(normalizeTex(value),options)},this.changeAndTrack=(userInput,cb)=>{this.props.handleUserInput(normalizeTex(userInput),cb);this.props.trackInteraction();},this._handleFocus=()=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{if(this.props.apiOptions.customKeypad){this.refs.input.focus();}return true},this.getInputPaths=()=>{return [[]]};}}Expression.contextType=PerseusI18nContext;Expression.defaultProps={times:false,functions:[],buttonSets:["basic","trig","prealgebra","logarithms"],onFocus:()=>{},onBlur:()=>{},apiOptions:ApiOptions.defaults,linterContext:PerseusLinter.linterContextDefault,userInput:""};const styles$I=aphrodite.StyleSheet.create({mobileLabelInputWrapper:{padding:"15px 4px 0"},desktopLabelInputWrapper:{margin:"5px 5px 0"}});const ExpressionWithDependencies=React__namespace.forwardRef((props,ref)=>{const deps=useDependencies();return jsxRuntimeExports.jsx(Expression,{ref:ref,analytics:deps.analytics,...props})});function getUserInputFromSerializedState$g(serializedState){return normalizeTex(serializedState.value)}var Expression$1 = {name:"expression",displayName:"Expression / Equation",widget:ExpressionWithDependencies,transform:widgetOptions=>{const{times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel,extraKeys}=widgetOptions;return {keypadConfiguration:{keypadType:"EXPRESSION",extraKeys,times},times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel}},version:perseusCore.expressionLogic.version,isLintable:true,getOneCorrectAnswerFromRubric(rubric){const correctAnswers=(rubric.answerForms||[]).filter(answerForm=>answerForm.considered==="correct");if(correctAnswers.length===0){return}return correctAnswers[0].value},getUserInputFromSerializedState: getUserInputFromSerializedState$g};
1474
+ const englishOperators={arctg:"arctan",cosec:"csc",cossec:"csc",cotg:"cot",ctg:"cot",sen:"sin",tg:"tan"};const anglicizeOperators=tex=>{return tex.replace(/\\operatorname{([a-z]+)}/g,(_,op)=>`\\${englishOperators[op]??op} `)};const normalizeTex=tex=>{return anglicizeOperators(tex)};class Expression extends React__namespace.Component{getUserInput(){return normalizeTex(this.props.userInput)}getPromptJSON(){return getPromptJSON$t(this.props,this.getUserInput())}focusInputPath(inputPath){this.refs.input.focus();}blurInputPath(inputPath){if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}}insert(keyPressed){this.refs.input.insert(keyPressed);}setInputValue(path,newValue,cb){this.props.handleUserInput(newValue,cb);}getSerializedState(){const{userInput:_,...rest}=this.props;return {...rest,value:this.props.userInput}}render(){if(this.props.apiOptions.customKeypad){return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:aphrodite.css(styles$I.mobileLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsx(mathInput.KeypadInput,{ref:"input",ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,value:this.props.userInput,keypadElement:this.props.keypadElement,onChange:this.changeAndTrack,onFocus:()=>{this.props.keypadElement?.configure(this.props.keypadConfiguration,()=>{if(this._isMounted){this._handleFocus();}});},onBlur:this._handleBlur})]})}const className=classNames__default.default({"perseus-widget-expression":true,"show-error-tooltip":this.state.showErrorTooltip});const{ERROR_MESSAGE,ERROR_TITLE}=this.context.strings;return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:aphrodite.css(styles$I.desktopLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsxs("div",{className:className,onBlur:()=>this.state.invalid&&this.setState({showErrorTooltip:true,showErrorStyle:true}),onFocus:()=>this.setState({showErrorTooltip:false}),children:[jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:a11y.srOnly,role:"alert",children:this.state.showErrorTooltip&&ERROR_TITLE+" "+ERROR_MESSAGE}),jsxRuntimeExports.jsx(Tooltip__default.default,{forceAnchorFocusivity:false,opened:this.state.showErrorTooltip,title:ERROR_TITLE,content:ERROR_MESSAGE,children:jsxRuntimeExports.jsx(MathInput,{ref:"input",value:this.props.userInput,onChange:this.changeAndTrack,convertDotToTimes:this.props.times,buttonSets:this.props.buttonSets,onFocus:this._handleFocus,onBlur:this._handleBlur,hasError:this.state.showErrorStyle,ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,extraKeys:this.props.keypadConfiguration?.extraKeys,onAnalyticsEvent:this.props.analytics?.onAnalyticsEvent??(async()=>{})})})]})]})}constructor(...args){super(...args),this._textareaId=`expression_textarea_${Date.now()}`,this._isMounted=false,this.displayName="Expression",this.state={invalid:false,showErrorTooltip:false,showErrorStyle:false},this.componentDidMount=()=>{document.addEventListener("mousedown",this._handleMouseDown);this._isMounted=true;if(this.refs.input){const isMobile=this.props.apiOptions.customKeypad;const container=ReactDOM__namespace.default.findDOMNode(this.refs.input);const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=container.querySelector(selector);inputElement?.setAttribute("id",this._textareaId);}},this.componentDidUpdate=prevProps=>{if(!___default.default.isEqual(this.props.userInput,prevProps.userInput)||!___default.default.isEqual(this.props.functions,prevProps.functions)){this.setState({invalid:false,showErrorTooltip:false,showErrorStyle:false});if(!this.parse(this.props.userInput,this.props).parsed){this.setState({invalid:true});}}},this.componentWillUnmount=()=>{this._isMounted=false;},this._handleMouseDown=()=>{if(this._isMounted&&this.state.showErrorTooltip){this.setState({showErrorTooltip:false});}},this.parse=(value,props)=>{const options=___default.default.pick(props||this.props,"functions");___default.default.extend(options,{decimal_separator:perseusCore.getDecimalSeparator(this.context.locale)});return KAS__namespace.parse(normalizeTex(value),options)},this.changeAndTrack=(userInput,cb)=>{this.props.handleUserInput(normalizeTex(userInput),cb);this.props.trackInteraction();},this._handleFocus=()=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{if(this.props.apiOptions.customKeypad){this.refs.input.focus();}return true},this.getInputPaths=()=>{return [[]]};}}Expression.contextType=PerseusI18nContext;Expression.defaultProps={times:false,functions:[],buttonSets:["basic","trig","prealgebra","logarithms"],onFocus:()=>{},onBlur:()=>{},apiOptions:ApiOptions.defaults,linterContext:PerseusLinter.linterContextDefault,userInput:""};const styles$I=aphrodite.StyleSheet.create({mobileLabelInputWrapper:{padding:"15px 4px 0"},desktopLabelInputWrapper:{margin:"5px 5px 0"}});const ExpressionWithDependencies=React__namespace.forwardRef((props,ref)=>{const deps=useDependencies();return jsxRuntimeExports.jsx(Expression,{ref:ref,analytics:deps.analytics,...props})});function getUserInputFromSerializedState$h(serializedState){return normalizeTex(serializedState.value)}var Expression$1 = {name:"expression",displayName:"Expression / Equation",widget:ExpressionWithDependencies,transform:widgetOptions=>{const{times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel,extraKeys}=widgetOptions;return {keypadConfiguration:{keypadType:"EXPRESSION",extraKeys,times},times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel}},version:perseusCore.expressionLogic.version,isLintable:true,getOneCorrectAnswerFromRubric(rubric){const correctAnswers=(rubric.answerForms||[]).filter(answerForm=>answerForm.considered==="correct");if(correctAnswers.length===0){return}return correctAnswers[0].value},getUserInputFromSerializedState: getUserInputFromSerializedState$h};
1475
1475
 
1476
1476
  class SimpleKeypadInput extends React__namespace.Component{componentDidMount(){this._isMounted=true;}componentWillUnmount(){this._isMounted=false;}focus(){this.inputRef.current?.focus(this.context.setKeypadActive);}blur(){this.inputRef.current?.blur();}getValue(){return this.props.value}render(){const _this=this;const{keypadElement,onFocus,value,...rest}=_this.props;return jsxRuntimeExports.jsx(mathInput.KeypadInput,{ref:this.inputRef,keypadElement:keypadElement,onFocus:()=>{if(keypadElement){keypadElement.configure({keypadType:"FRACTION"},()=>{if(_this._isMounted){onFocus?.();}});}else {onFocus?.();}},value:value==null?"":""+value,...rest})}constructor(...args){super(...args),this._isMounted=false,this.inputRef=React__namespace.createRef();}}SimpleKeypadInput.contextType=keypadContext.KeypadContext;SimpleKeypadInput.propTypes={keypadElement:mathInput.keypadElementPropType,onFocus:PropTypes__default.default.func,value:PropTypes__default.default.oneOfType([PropTypes__default.default.string,PropTypes__default.default.number])};
1477
1477
 
@@ -1717,7 +1717,7 @@ const{captureScratchpadTouchStart: captureScratchpadTouchStart$3}=Util;const Inp
1717
1717
  ${props.examples.slice(1).join(", or\n")}`.replaceAll("*","").replaceAll("$","").replaceAll("\\ \\text{pi}"," pi").replaceAll("\\ "," and "):"";const inputProps={id:id,"aria-describedby":shouldShowExamples?ariaId:undefined,ref:inputRef,className:getInputClassName(),labelText:props.labelText,value:props.value,onFocus:handleFocus,onBlur:handleBlur,disabled:disabled,style:props.style,onChange:props.onChange,onTouchStart:captureScratchpadTouchStart$3,autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:"false"};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(TextInput,{...inputProps}),jsxRuntimeExports.jsx("span",{id:ariaId,style:{display:"none"},children:examplesAria})]})};const renderTooltipContent=()=>{return jsxRuntimeExports.jsx(Tooltip.TooltipContent,{children:jsxRuntimeExports.jsx("div",{id:id,className:"input-with-examples-tooltip",children:jsxRuntimeExports.jsx(Renderer,{content:examplesContent,linterContext:PerseusLinter__namespace.pushContextStack(linterContext,"input-with-examples"),strings:context.strings})})})};const examplesContent=props.examples.length<=2?props.examples.join(" "):props.examples.map((example,index)=>{return index===0&&example.startsWith("**")?`${example}
1718
1718
  `:`- ${example}`}).join("\n");const showExamplesTooltip=shouldShowExamples&&inputFocused;return jsxRuntimeExports.jsx(Tooltip__default.default,{content:renderTooltipContent(),opened:showExamplesTooltip,placement:"bottom",children:renderInput()})});
1719
1719
 
1720
- const formExamples={integer:function(_,strings){return strings.integerExample},proper:function(options,strings){if(options.simplify==="optional"){return strings.properExample}return strings.simplifiedProperExample},improper:function(options,strings){if(options.simplify==="optional"){return strings.improperExample}return strings.simplifiedImproperExample},mixed:function(_,strings){return strings.mixedExample},decimal:function(_,strings){return strings.decimalExample},percent:function(_,strings){return strings.percentExample},pi:function(_,strings){return strings.piExample}};class InputNumber extends React__namespace.Component{getUserInput(){return this.props.userInput}getPromptJSON(){return getPromptJSON$s(this.props,this.getUserInput())}examples(){const{strings}=this.context;const type=this.props.answerType;const forms=perseusScore.inputNumberAnswerTypes[type].forms.split(/\s*,\s*/);const examples=forms.map(form=>formExamples[form](this.props,strings));return [strings.yourAnswer].concat(examples)}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,currentValue:userInput.currentValue}}render(){if(this.props.apiOptions.customKeypad){const input=jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:"input",value:this.props.userInput.currentValue,keypadElement:this.props.keypadElement,onChange:this.handleChange,onFocus:this._handleFocus,onBlur:this._handleBlur});if(this.props.rightAlign){return jsxRuntimeExports.jsx("div",{className:"perseus-input-right-align",children:input})}return input}const inputStyles=[styles$F.default,this.props.size==="small"?styles$F.small:null,this.props.rightAlign?styles$F.rightAlign:styles$F.leftAlign];if(this.props.reviewMode&&!this.props.userInput.currentValue){inputStyles.push(styles$F.answerStateUnanswered);}return jsxRuntimeExports.jsx(InputWithExamples,{ref:"input",value:this.props.userInput.currentValue,onChange:this.handleChange,style:inputStyles,examples:this.examples(),shouldShowExamples:this.shouldShowExamples(),onFocus:this._handleFocus,onBlur:this._handleBlur,id:this.props.widgetId,disabled:this.props.apiOptions.readOnly,linterContext:this.props.linterContext})}constructor(...args){super(...args),this.shouldShowExamples=()=>{return this.props.answerType!=="number"},this.handleChange=(newValue,cb)=>{this.props.handleUserInput({currentValue:newValue},cb);},this._handleFocus=()=>{this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{this.refs.input.focus();return true},this.focusInputPath=inputPath=>{this.refs.input.focus();},this.blurInputPath=inputPath=>{if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}},this.getInputPaths=()=>{return [[]]},this.setInputValue=(path,newValue,cb)=>{this.props.handleUserInput({currentValue:newValue},cb);};}}InputNumber.contextType=PerseusI18nContext;InputNumber.defaultProps={size:"normal",answerType:"number",rightAlign:false,apiOptions:ApiOptions.defaults,linterContext:PerseusLinter.linterContextDefault,userInput:{currentValue:""}};const styles$F=aphrodite.StyleSheet.create({default:{width:80,height:"auto"},small:{width:40},leftAlign:{paddingLeft:wonderBlocksTokens.spacing.xxxSmall_4,paddingRight:0},rightAlign:{textAlign:"right",paddingLeft:0,paddingRight:wonderBlocksTokens.spacing.xxxSmall_4},answerStateUnanswered:{backgroundColor:"#eee",border:"solid 1px #999"}});function transform$6(widgetOptions){const{simplify,size,answerType,rightAlign}=widgetOptions;return {simplify,size,answerType,rightAlign}}function getOneCorrectAnswerFromRubric(rubric){if(rubric.value==null){return}let answerString=String(rubric.value);if(rubric.inexact&&rubric.maxError){answerString+=" ± "+rubric.maxError;}return answerString}function getUserInputFromSerializedState$f(serializedState){return {currentValue:serializedState.currentValue}}var InputNumber$1 = {name:"input-number",displayName:"Input number (deprecated - use numeric input instead)",hidden:true,widget:InputNumber,isLintable:true,transform: transform$6,getOneCorrectAnswerFromRubric,getUserInputFromSerializedState: getUserInputFromSerializedState$f};
1720
+ const formExamples={integer:function(_,strings){return strings.integerExample},proper:function(options,strings){if(options.simplify==="optional"){return strings.properExample}return strings.simplifiedProperExample},improper:function(options,strings){if(options.simplify==="optional"){return strings.improperExample}return strings.simplifiedImproperExample},mixed:function(_,strings){return strings.mixedExample},decimal:function(_,strings){return strings.decimalExample},percent:function(_,strings){return strings.percentExample},pi:function(_,strings){return strings.piExample}};class InputNumber extends React__namespace.Component{getUserInput(){return this.props.userInput}getPromptJSON(){return getPromptJSON$s(this.props,this.getUserInput())}examples(){const{strings}=this.context;const type=this.props.answerType;const forms=perseusScore.inputNumberAnswerTypes[type].forms.split(/\s*,\s*/);const examples=forms.map(form=>formExamples[form](this.props,strings));return [strings.yourAnswer].concat(examples)}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,currentValue:userInput.currentValue}}render(){if(this.props.apiOptions.customKeypad){const input=jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:"input",value:this.props.userInput.currentValue,keypadElement:this.props.keypadElement,onChange:this.handleChange,onFocus:this._handleFocus,onBlur:this._handleBlur});if(this.props.rightAlign){return jsxRuntimeExports.jsx("div",{className:"perseus-input-right-align",children:input})}return input}const inputStyles=[styles$F.default,this.props.size==="small"?styles$F.small:null,this.props.rightAlign?styles$F.rightAlign:styles$F.leftAlign];if(this.props.reviewMode&&!this.props.userInput.currentValue){inputStyles.push(styles$F.answerStateUnanswered);}return jsxRuntimeExports.jsx(InputWithExamples,{ref:"input",value:this.props.userInput.currentValue,onChange:this.handleChange,style:inputStyles,examples:this.examples(),shouldShowExamples:this.shouldShowExamples(),onFocus:this._handleFocus,onBlur:this._handleBlur,id:this.props.widgetId,disabled:this.props.apiOptions.readOnly,linterContext:this.props.linterContext})}constructor(...args){super(...args),this.shouldShowExamples=()=>{return this.props.answerType!=="number"},this.handleChange=(newValue,cb)=>{this.props.handleUserInput({currentValue:newValue},cb);},this._handleFocus=()=>{this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{this.refs.input.focus();return true},this.focusInputPath=inputPath=>{this.refs.input.focus();},this.blurInputPath=inputPath=>{if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}},this.getInputPaths=()=>{return [[]]},this.setInputValue=(path,newValue,cb)=>{this.props.handleUserInput({currentValue:newValue},cb);};}}InputNumber.contextType=PerseusI18nContext;InputNumber.defaultProps={size:"normal",answerType:"number",rightAlign:false,apiOptions:ApiOptions.defaults,linterContext:PerseusLinter.linterContextDefault,userInput:{currentValue:""}};const styles$F=aphrodite.StyleSheet.create({default:{width:80,height:"auto"},small:{width:40},leftAlign:{paddingLeft:wonderBlocksTokens.spacing.xxxSmall_4,paddingRight:0},rightAlign:{textAlign:"right",paddingLeft:0,paddingRight:wonderBlocksTokens.spacing.xxxSmall_4},answerStateUnanswered:{backgroundColor:"#eee",border:"solid 1px #999"}});function transform$6(widgetOptions){const{simplify,size,answerType,rightAlign}=widgetOptions;return {simplify,size,answerType,rightAlign}}function getOneCorrectAnswerFromRubric(rubric){if(rubric.value==null){return}let answerString=String(rubric.value);if(rubric.inexact&&rubric.maxError){answerString+=" ± "+rubric.maxError;}return answerString}function getUserInputFromSerializedState$g(serializedState){return {currentValue:serializedState.currentValue}}var InputNumber$1 = {name:"input-number",displayName:"Input number (deprecated - use numeric input instead)",hidden:true,widget:InputNumber,isLintable:true,transform: transform$6,getOneCorrectAnswerFromRubric,getUserInputFromSerializedState: getUserInputFromSerializedState$g};
1721
1721
 
1722
1722
  const getPromptJSON$r=(renderProps,userInput)=>{return {type:"numeric-input",label:renderProps.labelText,userInput:{value:userInput.currentValue}}};
1723
1723
 
@@ -1725,7 +1725,7 @@ const NumericExampleStrings={integer:(form,strings)=>strings.integerExample,prop
1725
1725
 
1726
1726
  const NumericInputComponent=React.forwardRef((props,ref)=>{const context=React.useContext(PerseusI18nContext);const inputRef=React.useRef(null);const[isFocused,setIsFocused]=React.useState(false);React.useImperativeHandle(ref,()=>({current:inputRef.current,focus:()=>{if(inputRef.current){inputRef.current?.focus();setIsFocused(true);}},blur:()=>{if(inputRef.current){inputRef.current?.blur();setIsFocused(false);}}}));const handleChange=newValue=>{props.handleUserInput({currentValue:newValue});props.trackInteraction();};const handleFocus=()=>{props.onFocus([]);setIsFocused(true);};const handleBlur=()=>{props.onBlur([]);setIsFocused(false);};const styles=aphrodite.StyleSheet.create({inputWithExamples:{borderRadius:"3px",borderWidth:isFocused?"2px":"1px",display:"inline-block",fontFamily:`Symbola, "Times New Roman", serif`,fontSize:"18px",height:"32px",lineHeight:"18px",padding:isFocused?"4px":"4px 5px",textAlign:props.rightAlign?"right":"left",width:props.size==="small"?40:80}});if(props.apiOptions.customKeypad){const alignmentClass=props.rightAlign?"perseus-input-right-align":undefined;return jsxRuntimeExports.jsx("div",{className:alignmentClass,children:jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:inputRef,value:props.userInput.currentValue,keypadElement:props.keypadElement,onChange:handleChange,onFocus:handleFocus,onBlur:handleBlur})})}return jsxRuntimeExports.jsx(InputWithExamples,{ref:inputRef,value:props.userInput.currentValue,onChange:handleChange,labelText:props.labelText,examples:generateExamples(props.answerForms,context.strings),shouldShowExamples:shouldShowExamples(props.answerForms),onFocus:handleFocus,onBlur:handleBlur,id:props.widgetId,disabled:props.apiOptions.readOnly,style:styles.inputWithExamples})});
1727
1727
 
1728
- class NumericInput extends React__namespace.Component{getUserInput(){return this.props.userInput}getPromptJSON(){return getPromptJSON$r(this.props,this.getUserInput())}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,currentValue:userInput.currentValue}}render(){return jsxRuntimeExports.jsx(NumericInputComponent,{...this.props,ref:this.inputRef})}constructor(...args){super(...args),this.inputRef=React__namespace.createRef(),this.focus=()=>{this.inputRef.current?.focus();return true},this.focusInputPath=()=>{this.inputRef.current?.focus();},this.blurInputPath=()=>{this.inputRef.current?.blur();},this.getInputPaths=()=>{return [[]]},this.setInputValue=(path,newValue,cb)=>{this.props.handleUserInput({currentValue:newValue},cb);};}}NumericInput.defaultProps={size:"normal",rightAlign:false,apiOptions:ApiOptions.defaults,coefficient:false,answerForms:[],labelText:"",linterContext:PerseusLinter.linterContextDefault,userInput:{currentValue:""}};const propsTransform=function(widgetOptions){const{answers:_,...rendererProps}={...widgetOptions,answerForms:unionAnswerForms(widgetOptions.answers.filter(answer=>answer.status==="correct").map(answer=>{return (answer.answerForms||[]).map(form=>{return {simplify:answer.simplify,name:form}})}))};return rendererProps};function getUserInputFromSerializedState$e(serializedState){return {currentValue:serializedState.currentValue}}var NumericInput$1 = {name:"numeric-input",displayName:"Numeric input",widget:NumericInput,transform:propsTransform,isLintable:true,getOneCorrectAnswerFromRubric(rubric){const correctAnswers=rubric.answers.filter(answer=>answer.status==="correct");const answerStrings=correctAnswers.map(answer=>{const format=answer.answerForms&&answer.answerForms[0]?answer.answerForms[0]:"decimal";let answerString=kmath.KhanMath.toNumericString(answer.value,format);if(answer.maxError){answerString+=" ± "+kmath.KhanMath.toNumericString(answer.maxError,format);}return answerString});if(answerStrings.length===0){return}return answerStrings[0]},getUserInputFromSerializedState: getUserInputFromSerializedState$e};
1728
+ class NumericInput extends React__namespace.Component{getUserInput(){return this.props.userInput}getPromptJSON(){return getPromptJSON$r(this.props,this.getUserInput())}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,currentValue:userInput.currentValue}}render(){return jsxRuntimeExports.jsx(NumericInputComponent,{...this.props,ref:this.inputRef})}constructor(...args){super(...args),this.inputRef=React__namespace.createRef(),this.focus=()=>{this.inputRef.current?.focus();return true},this.focusInputPath=()=>{this.inputRef.current?.focus();},this.blurInputPath=()=>{this.inputRef.current?.blur();},this.getInputPaths=()=>{return [[]]},this.setInputValue=(path,newValue,cb)=>{this.props.handleUserInput({currentValue:newValue},cb);};}}NumericInput.defaultProps={size:"normal",rightAlign:false,apiOptions:ApiOptions.defaults,coefficient:false,answerForms:[],labelText:"",linterContext:PerseusLinter.linterContextDefault,userInput:{currentValue:""}};const propsTransform=function(widgetOptions){const{answers:_,...rendererProps}={...widgetOptions,answerForms:unionAnswerForms(widgetOptions.answers.filter(answer=>answer.status==="correct").map(answer=>{return (answer.answerForms||[]).map(form=>{return {simplify:answer.simplify,name:form}})}))};return rendererProps};function getUserInputFromSerializedState$f(serializedState){return {currentValue:serializedState.currentValue}}var NumericInput$1 = {name:"numeric-input",displayName:"Numeric input",widget:NumericInput,transform:propsTransform,isLintable:true,getOneCorrectAnswerFromRubric(rubric){const correctAnswers=rubric.answers.filter(answer=>answer.status==="correct");const answerStrings=correctAnswers.map(answer=>{const format=answer.answerForms&&answer.answerForms[0]?answer.answerForms[0]:"decimal";let answerString=kmath.KhanMath.toNumericString(answer.value,format);if(answer.maxError){answerString+=" ± "+kmath.KhanMath.toNumericString(answer.maxError,format);}return answerString});if(answerStrings.length===0){return}return answerStrings[0]},getUserInputFromSerializedState: getUserInputFromSerializedState$f};
1729
1729
 
1730
1730
  const getPromptJSON$q=(renderProps,userInput)=>{const choices=renderProps.choices||[];const options=choices.map(choice=>{const option={value:choice.content};if(choice.rationale){option.rationale=choice.rationale;}return option});return {type:"radio",hasNoneOfTheAbove:!!renderProps.hasNoneOfTheAbove,options,userInput:{selectedOptions:userInput.choicesSelected.slice()}}};
1731
1731
 
@@ -1769,7 +1769,7 @@ function getA11yText$1(letter,checked,correct,showCorrectness,strings){if(showCo
1769
1769
 
1770
1770
  const FocusRing=function({visible=true,color=kaGreen,multipleSelect=false,children}){const borderColor=visible?color:"transparent";const borderRadius=multipleSelect?5:"50%";const style={borderColor,borderRadius};return jsxRuntimeExports.jsx("span",{"data-testid":"focus-ring",className:aphrodite.css(styles$A.ring),style:style,children:children})};const styles$A=aphrodite.StyleSheet.create({ring:{margin:"auto",display:"inline-block",borderWidth:2,padding:2,borderStyle:"solid"}});
1771
1771
 
1772
- function getChoiceLetter$1(pos,strings){const lettersString=strings.letters;const letters=lettersString.split(" ");if(pos<letters.length){return letters[pos]}return " "}
1772
+ function getChoiceLetter$1(pos,strings){const lettersString=strings.letters;const letters=lettersString.split(" ");if(pos<letters.length){return letters[pos]}return " "}function getUserInputFromSerializedState$e(props,unshuffle=true){if(props.choiceStates){const choiceStates=props.choiceStates;const choicesSelected=choiceStates.map(()=>false);for(let i=0;i<choicesSelected.length;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=choiceStates[i].selected;}return {choicesSelected}}const{values}=props;if(values){const choicesSelected=[...values];const valuesLength=values.length;for(let i=0;i<valuesLength;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=values[i];}return {choicesSelected}}return {choicesSelected:props.choices.map(()=>false)}}
1773
1773
 
1774
1774
  const CHOICE_ICON_SIZE$1=24;const styles$z=aphrodite.StyleSheet.create({iconWrapper:{display:"inline-block",position:"relative"}});
1775
1775
 
@@ -1783,7 +1783,7 @@ const ChoiceNoneAbove$1=function({content,forwardedRef,showContent=true,...rest}
1783
1783
 
1784
1784
  const{captureScratchpadTouchStart: captureScratchpadTouchStart$2}=Util;function getInstructionsText$1(multipleSelect,countChoices,numCorrect,strings){if(multipleSelect){if(perseusCore.usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer}const BaseRadio$1=function({apiOptions,reviewModeRubric,reviewMode,choices,editMode=false,multipleSelect=false,labelWrap,countChoices,numCorrect,isLastUsedWidget,onChange,registerFocusFunction}){const{strings}=usePerseusI18n();const prevReviewModeRubric=React.useRef();const choiceRefs=React.useRef([]);React.useEffect(()=>{if(apiOptions.canScrollPage&&isLastUsedWidget&&reviewModeRubric&&!prevReviewModeRubric.current){const checkedIndex=choices.findIndex(c=>c.checked);if(checkedIndex>=0){const ref=choiceRefs.current[checkedIndex];const anyNode=ReactDOM__namespace.default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){scrollElementIntoView(buttonNode);}}}prevReviewModeRubric.current=reviewModeRubric;},[apiOptions,choices,isLastUsedWidget,reviewModeRubric]);function updateChoice(choiceIndex,newValues){let newCheckedList;if(newValues.checked&&!multipleSelect){newCheckedList=choices.map(_=>false);}else {newCheckedList=choices.map(c=>c.checked);}newCheckedList[choiceIndex]=newValues.checked;onChange({checked:newCheckedList});}registerFocusFunction?.(choiceIndex=>{const ref=choiceRefs.current[choiceIndex||0];const anyNode=ReactDOM__namespace.default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){buttonNode.focus();}else {return false}return true});const isMobile=apiOptions.isMobile;const firstChoiceHighlighted=choices[0].highlighted;const lastChoiceHighlighted=choices[choices.length-1].highlighted;const className=classNames__default.default("perseus-widget-radio",!editMode&&"perseus-rendered-radio",aphrodite.css(styles$v.radio,styles$v.responsiveRadioContainer,firstChoiceHighlighted&&isMobile&&styles$v.radioContainerFirstHighlighted,lastChoiceHighlighted&&isMobile&&styles$v.radioContainerLastHighlighted));const instructionsClassName=classNames__default.default("instructions",aphrodite.css(styles$v.instructions,isMobile&&styles$v.instructionsMobile));const instructions=getInstructionsText$1(multipleSelect,countChoices,numCorrect,strings);const responsiveClassName=aphrodite.css(styles$v.responsiveFieldset);const fieldset=jsxRuntimeExports.jsxs("fieldset",{className:`perseus-widget-radio-fieldset ${responsiveClassName}`,children:[jsxRuntimeExports.jsx("legend",{className:"perseus-sr-only",children:instructions}),jsxRuntimeExports.jsx("div",{className:instructionsClassName,"aria-hidden":"true",children:instructions}),jsxRuntimeExports.jsx("ul",{className:className,style:{listStyle:"none"},children:choices.map((choice,i)=>{let Element=Choice$2;const ref=React__namespace.createRef();choiceRefs.current[i]=ref;const elementProps={apiOptions:apiOptions,multipleSelect:multipleSelect,checked:choice.checked,previouslyAnswered:choice.previouslyAnswered,reviewMode,correct:choice.correct,rationale:choice.rationale,content:choice.content,disabled:apiOptions.readOnly||choice.disabled,showCorrectness:reviewMode||!!choice.showCorrectness,showRationale:choice.hasRationale&&(reviewMode||choice.showRationale),pos:i,onChange:newValues=>{if(editMode){return}updateChoice(i,newValues);}};if(choice.isNoneOfTheAbove){Element=ChoiceNoneAbove$2;___default.default.extend(elementProps,{showContent:choice.revealNoneOfTheAbove});}const nextChoice=choices[i+1];const nextChoiceHighlighted=!!nextChoice&&nextChoice.highlighted;const aphroditeClassName=checked=>{return aphrodite.css(styles$v.item,styles$v.responsiveItem,checked&&styles$v.selectedItem,checked&&choice.highlighted&&styles$v.aboveBackdrop,checked&&choice.highlighted&&apiOptions.isMobile&&styles$v.aboveBackdropMobile,nextChoiceHighlighted&&apiOptions.isMobile&&styles$v.nextHighlighted)};aphroditeClassName(true);let correctnessClass;if(reviewMode&&reviewModeRubric){correctnessClass=reviewModeRubric.choices[i].correct?ClassNames.CORRECT:ClassNames.INCORRECT;}const className=classNames__default.default(aphroditeClassName(choice.checked),ClassNames.RADIO.OPTION,choice.checked&&ClassNames.RADIO.SELECTED,correctnessClass);let listElem=null;let clickHandler;if(editMode){clickHandler=e=>{let elem=e.target;while(elem&&elem!==listElem){if(elem.getAttribute("data-is-radio-icon")){updateChoice(i,{checked:!choice.checked});return}elem=elem.parentNode;}};}return jsxRuntimeExports.jsx("li",{ref:e=>listElem=e,className:className,onClick:clickHandler,onTouchStart:labelWrap?undefined:captureScratchpadTouchStart$2,children:jsxRuntimeExports.jsx(Element,{...elementProps,ref:ref})},i)})})]});return jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$v.responsiveContainer),children:fieldset})};const styles$v=aphrodite.StyleSheet.create({instructions:{display:"block",color:gray17,fontSize:14,lineHeight:1.25,fontFamily:"inherit",fontStyle:"normal",fontWeight:"bold",marginBottom:16},instructionsMobile:{fontSize:18,[mediaQueries.smOrSmaller]:{fontSize:16},[mediaQueries.xl]:{fontSize:20}},radio:{padding:0},responsiveRadioContainer:{borderBottom:`1px solid ${radioBorderColor$1}`,borderTop:`1px solid ${radioBorderColor$1}`,width:"auto",[mediaQueries.smOrSmaller]:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin}},radioContainerFirstHighlighted:{borderTop:`1px solid rgba(0, 0, 0, 0)`},radioContainerLastHighlighted:{borderBottom:`1px solid rgba(0, 0, 0, 0)`},item:{marginLeft:20},responsiveItem:{marginLeft:0,padding:0,":not(:last-child)":{borderBottom:`1px solid ${radioBorderColor$1}`}},selectedItem:{background:"white"},aboveBackdrop:{position:"relative",zIndex:1062},aboveBackdropMobile:{boxShadow:"0 0 4px 0 rgba(0, 0, 0, 0.2),"+"0 0 2px 0 rgba(0, 0, 0, 0.1)",":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},nextHighlighted:{":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},responsiveContainer:{overflow:"auto",marginLeft:negativePhoneMargin,paddingLeft:phoneMargin},responsiveFieldset:{paddingRight:phoneMargin,minWidth:"auto"}});
1785
1785
 
1786
- let Radio$3 = class Radio extends React__namespace.Component{static getUserInputFromProps(props,unshuffle=true){if(props.choiceStates){const choiceStates=props.choiceStates;const choicesSelected=choiceStates.map(()=>false);for(let i=0;i<choicesSelected.length;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=choiceStates[i].selected;}return {choicesSelected}}const{values}=props;if(values){const choicesSelected=[...values];const valuesLength=values.length;for(let i=0;i<valuesLength;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=values[i];}return {choicesSelected}}return {choicesSelected:props.choices.map(()=>false)}}focus(choiceIndex){if(this.focusFunction){return this.focusFunction(choiceIndex)}return false}registerFocusFunction(fun){this.focusFunction=fun;}getUserInput(){return Radio.getUserInputFromProps(this.props)}getPromptJSON(){const userInput=Radio.getUserInputFromProps(this.props,false);return getPromptJSON$q(this.props,userInput)}render(){const{choices}=this.props;const{strings}=this.context;let choiceStates;if(this.props.static){choiceStates=choices.map(choice=>({selected:!!choice.correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.showSolutions==="all"){choiceStates=choices.map(({correct})=>({selected:!!correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.choiceStates){choiceStates=this.props.choiceStates;}else if(this.props.values){choiceStates=this.props.values.map(val=>({selected:val,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}else {choiceStates=choices.map(()=>({selected:false,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}const choicesProp=choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];const reviewChoice=this.props.reviewModeRubric?.choices[i];return {content:this._renderRenderer(content),checked:selected,correct:choice.correct===undefined?!!reviewChoice&&!!reviewChoice.correct:choice.correct,disabled:readOnly,hasRationale:!!choice.rationale,rationale:this._renderRenderer(choice.rationale),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(this.props.questionCompleted&&selected),highlighted,previouslyAnswered:previouslyAnswered}});return jsxRuntimeExports.jsx(BaseRadio$1,{labelWrap:true,multipleSelect:this.props.multipleSelect,countChoices:this.props.countChoices,numCorrect:this.props.numCorrect,choices:choicesProp,onChange:this.updateChoices,reviewModeRubric:this.props.reviewModeRubric,reviewMode:this.props.reviewMode,deselectEnabled:this.props.deselectEnabled,apiOptions:this.props.apiOptions,isLastUsedWidget:this.props.isLastUsedWidget,registerFocusFunction:i=>this.registerFocusFunction(i)})}constructor(...args){super(...args),this._renderRenderer=(content="")=>{let nextPassageRefId=1;const widgets={};const modContent=content.replace(/\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,(match,passageNum,refNum,summaryText)=>{const widgetId="passage-ref "+nextPassageRefId;nextPassageRefId++;widgets[widgetId]={type:"passage-ref",graded:false,options:{passageNumber:parseInt(passageNum),referenceNumber:parseInt(refNum),summaryText:summaryText},version:PassageRef$1.version};return "[["+Util.snowman+" "+widgetId+"]]"});return jsxRuntimeExports.jsx(Renderer,{content:modContent,widgets:widgets,findExternalWidgets:this.props.findWidgets,alwaysUpdate:true,linterContext:{...this.props.linterContext,blockHighlight:true},strings:this.context.strings},"choiceContentRenderer")},this.updateChoices=newValueLists=>{const{choiceStates,choices}=this.props;const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{choiceState.selected=newValueLists.checked[i];});this.props.onChange({choiceStates:newChoiceStates});this.props.trackInteraction();};}};Radio$3.contextType=PerseusI18nContext;Radio$3.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:PerseusLinter.linterContextDefault,showSolutions:"none"};
1786
+ let Radio$3 = class Radio extends React__namespace.Component{focus(choiceIndex){if(this.focusFunction){return this.focusFunction(choiceIndex)}return false}registerFocusFunction(fun){this.focusFunction=fun;}getUserInput(){return this.props.userInput}getPromptJSON(){return getPromptJSON$q(this.props,this.props.userInput)}render(){const{choices}=this.props;const{strings}=this.context;let choiceStates;if(this.props.static){choiceStates=choices.map(choice=>({selected:!!choice.correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.showSolutions==="all"){choiceStates=choices.map(({correct})=>({selected:!!correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.choiceStates){choiceStates=this.props.choiceStates;}else if(this.props.values){choiceStates=this.props.values.map(val=>({selected:val,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}else {choiceStates=choices.map(()=>({selected:false,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}const choicesProp=choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];const reviewChoice=this.props.reviewModeRubric?.choices[i];return {content:this._renderRenderer(content),checked:selected,correct:choice.correct===undefined?!!reviewChoice&&!!reviewChoice.correct:choice.correct,disabled:readOnly,hasRationale:!!choice.rationale,rationale:this._renderRenderer(choice.rationale),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(this.props.questionCompleted&&selected),highlighted,previouslyAnswered:previouslyAnswered}});return jsxRuntimeExports.jsx(BaseRadio$1,{labelWrap:true,multipleSelect:this.props.multipleSelect,countChoices:this.props.countChoices,numCorrect:this.props.numCorrect,choices:choicesProp,onChange:this.updateChoices,reviewModeRubric:this.props.reviewModeRubric,reviewMode:this.props.reviewMode,deselectEnabled:this.props.deselectEnabled,apiOptions:this.props.apiOptions,isLastUsedWidget:this.props.isLastUsedWidget,registerFocusFunction:i=>this.registerFocusFunction(i)})}constructor(...args){super(...args),this._renderRenderer=(content="")=>{let nextPassageRefId=1;const widgets={};const modContent=content.replace(/\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,(match,passageNum,refNum,summaryText)=>{const widgetId="passage-ref "+nextPassageRefId;nextPassageRefId++;widgets[widgetId]={type:"passage-ref",graded:false,options:{passageNumber:parseInt(passageNum),referenceNumber:parseInt(refNum),summaryText:summaryText},version:PassageRef$1.version};return "[["+Util.snowman+" "+widgetId+"]]"});return jsxRuntimeExports.jsx(Renderer,{content:modContent,widgets:widgets,findExternalWidgets:this.props.findWidgets,alwaysUpdate:true,linterContext:{...this.props.linterContext,blockHighlight:true},strings:this.context.strings},"choiceContentRenderer")},this.updateChoices=newValueLists=>{const{choiceStates,choices}=this.props;const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{choiceState.selected=newValueLists.checked[i];});this.props.onChange({choiceStates:newChoiceStates});this.props.trackInteraction();};}};Radio$3.contextType=PerseusI18nContext;Radio$3.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:PerseusLinter.linterContextDefault,showSolutions:"none"};
1787
1787
 
1788
1788
  var styles$u = {"scrollButtonsContainer":"perseus_kjDHiWdD","scrollFade":"perseus_KB5rz4XY","scrollFadeLeft":"perseus_tP0ytdCp","scrollFadeRight":"perseus_t5yijnoR"};
1789
1789
 
@@ -1809,11 +1809,11 @@ const getChoiceStates=({choices,isStatic,showSolutions,choiceStates,values})=>{c
1809
1809
 
1810
1810
  const defaultProps={multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:PerseusLinter.linterContextDefault,showSolutions:"none"};const RadioComponent=({choices,multipleSelect=defaultProps.multipleSelect,countChoices=defaultProps.countChoices,deselectEnabled=defaultProps.deselectEnabled,linterContext=defaultProps.linterContext,showSolutions=defaultProps.showSolutions,static:isStatic,reviewModeRubric,reviewMode,apiOptions,isLastUsedWidget,questionCompleted,findWidgets,onChange,trackInteraction,numCorrect,choiceStates,values})=>{const{strings}=React.useContext(PerseusI18nContext);React.useEffect(()=>{console.log("New Radio Component");},[]);const renderRenderer=(content="")=>{const{parsedContent,extractedWidgets}=parseNestedWidgets(content);return jsxRuntimeExports.jsx(Renderer,{content:parsedContent,widgets:extractedWidgets,findExternalWidgets:findWidgets,alwaysUpdate:true,linterContext:{...linterContext,blockHighlight:true},strings:strings},"choiceContentRenderer")};const updateChoices=newValueLists=>{const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{choiceState.selected=newValueLists.checked[i];});onChange({choiceStates:newChoiceStates});trackInteraction();};const buildChoiceProps=(choices,choiceStates)=>{return choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];const reviewChoice=reviewModeRubric?.choices[i];return {content:renderRenderer(content),checked:selected,correct:choice.correct===undefined?!!reviewChoice&&!!reviewChoice.correct:choice.correct,disabled:readOnly,hasRationale:!!choice.rationale,rationale:renderRenderer(choice.rationale),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(questionCompleted&&selected),highlighted,previouslyAnswered}})};const updatedChoiceStates=getChoiceStates({choices,isStatic,showSolutions,choiceStates,values});const updatedChoicesProp=buildChoiceProps(choices,updatedChoiceStates);return jsxRuntimeExports.jsx(BaseRadio,{labelWrap:true,multipleSelect:multipleSelect,countChoices:countChoices,numCorrect:numCorrect,choices:updatedChoicesProp,onChange:updateChoices,reviewModeRubric:reviewModeRubric,reviewMode:reviewMode,deselectEnabled:deselectEnabled,apiOptions:apiOptions,isLastUsedWidget:isLastUsedWidget})};
1811
1811
 
1812
- let Radio$2 = class Radio extends React__namespace.Component{static getUserInputFromProps(props,unshuffle=true){if(props.choiceStates){const choiceStates=props.choiceStates;const choicesSelected=choiceStates.map(()=>false);for(let i=0;i<choicesSelected.length;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=choiceStates[i].selected;}return {choicesSelected}}const{values}=props;if(values){const choicesSelected=[...values];const valuesLength=values.length;for(let i=0;i<valuesLength;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=values[i];}return {choicesSelected}}return {choicesSelected:props.choices.map(()=>false)}}getUserInput(){return Radio.getUserInputFromProps(this.props)}getPromptJSON(){const userInput=Radio.getUserInputFromProps(this.props,false);return getPromptJSON$q(this.props,userInput)}render(){return jsxRuntimeExports.jsx(RadioComponent,{...this.props})}};Radio$2.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:PerseusLinter.linterContextDefault,showSolutions:"none"};
1812
+ let Radio$2 = class Radio extends React__namespace.Component{getUserInput(){return this.props.userInput}getPromptJSON(){return getPromptJSON$q(this.props,this.props.userInput)}render(){return jsxRuntimeExports.jsx(RadioComponent,{...this.props})}};Radio$2.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:PerseusLinter.linterContextDefault,showSolutions:"none"};
1813
1813
 
1814
- let Radio$1 = class Radio extends Radio$3{focus(choiceIndex){if(this.radioRef.current?.focus){return this.radioRef.current.focus(choiceIndex)}return false}render(){return this.ffIsOn?jsxRuntimeExports.jsx(Radio$2,{...this.props}):jsxRuntimeExports.jsx(Radio$3,{ref:this.radioRef,...this.props})}constructor(props){super(props),this.ffIsOn=false,this.radioRef=React__namespace.createRef();this.ffIsOn=props.apiOptions.flags?.["new-radio-widget"]??false;}};
1814
+ let Radio$1 = class Radio extends Radio$3{getSerializedState(){const{userInput:_,...rest}=this._mergePropsAndState();return {...rest}}_handleChange(arg){const newChoiceStates=arg.choiceStates;if(newChoiceStates){this.setState({choiceStates:newChoiceStates.map(choiceState=>{const{selected:_,...rest}=choiceState;return {...rest}})},()=>{const props=this._mergePropsAndState();const mergedProps={...props,choiceStates:perseusCore.deepClone(props.choiceStates||[]).map((choiceState,index)=>{return {...choiceState,selected:newChoiceStates[index].selected}})};const unshuffledUserInput=getUserInputFromSerializedState$e(mergedProps);this.props.handleUserInput(unshuffledUserInput);});}else {throw new Error("unhandled onChange call in Radio!")}}_mergePropsAndState(){return {...this.props,choiceStates:this.state.choiceStates?.map((choiceState,index)=>{const choice=this.props.choices[index];const selected=this.props.userInput.choicesSelected[choice.originalIndex];return {...choiceState,selected}}),onChange:arg=>this._handleChange(arg)}}focus(choiceIndex){if(this.radioRef.current?.focus){return this.radioRef.current.focus(choiceIndex)}return false}render(){const props=this._mergePropsAndState();return this.ffIsOn?jsxRuntimeExports.jsx(Radio$2,{...props}):jsxRuntimeExports.jsx(Radio$3,{ref:this.radioRef,...props})}constructor(props){super(props),this.ffIsOn=false,this.radioRef=React__namespace.createRef(),this.state={choiceStates:[]};this.ffIsOn=props.apiOptions.flags?.["new-radio-widget"]??false;this.state={choiceStates:props.choices.map(()=>({highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}))};}};
1815
1815
 
1816
- const _choiceTransform=(widgetOptions,strings,problemNum)=>{const _maybeRandomize=function(array){const randomSeed=problemNum===undefined?perseusCore.random:problemNum;return widgetOptions.randomize?perseusCore.shuffle(array,randomSeed??0):array};const _addNoneOfAbove=function(choices){let noneOfTheAbove=null;const newChoices=choices.filter((choice,index)=>{if(choice.isNoneOfTheAbove){noneOfTheAbove=choice;return false}return true});if(noneOfTheAbove){newChoices.push(noneOfTheAbove);}return newChoices};const enforceOrdering=choices=>{const ReversedChoices=[[strings.false,strings.true],[strings.no,strings.yes]];const content=choices.map(c=>c.content);if(ReversedChoices.some(reversed=>___default.default.isEqual(content,reversed))){return [choices[1],choices[0]]}return choices};const choices=widgetOptions.choices.map((choice,i)=>{return {...choice,originalIndex:i,correct:Boolean(choice.correct)}});return _addNoneOfAbove(enforceOrdering(_maybeRandomize(choices)))};const transform$5=(widgetOptions,strings,problemNum)=>{const choices=_choiceTransform(widgetOptions,strings,problemNum);const{hasNoneOfTheAbove,multipleSelect,countChoices,deselectEnabled,numCorrect}=widgetOptions;return {numCorrect:numCorrect,hasNoneOfTheAbove,multipleSelect,countChoices,deselectEnabled,choices,selectedChoices:___default.default.pluck(choices,"correct")}};var Radio = {name:"radio",displayName:"Radio / Multiple choice",widget:Radio$1,transform: transform$5,staticTransform:transform$5,version:perseusCore.radioLogic.version,isLintable:true,getUserInputFromSerializedState:Radio$1.getUserInputFromProps};
1816
+ const _choiceTransform=(widgetOptions,strings,problemNum)=>{const _maybeRandomize=function(array){const randomSeed=problemNum===undefined?perseusCore.random:problemNum;return widgetOptions.randomize?perseusCore.shuffle(array,randomSeed??0):array};const _addNoneOfAbove=function(choices){let noneOfTheAbove=null;const newChoices=choices.filter((choice,index)=>{if(choice.isNoneOfTheAbove){noneOfTheAbove=choice;return false}return true});if(noneOfTheAbove){newChoices.push(noneOfTheAbove);}return newChoices};const enforceOrdering=choices=>{const ReversedChoices=[[strings.false,strings.true],[strings.no,strings.yes]];const content=choices.map(c=>c.content);if(ReversedChoices.some(reversed=>___default.default.isEqual(content,reversed))){return [choices[1],choices[0]]}return choices};const choices=widgetOptions.choices.map((choice,i)=>{return {...choice,originalIndex:i,correct:Boolean(choice.correct)}});return _addNoneOfAbove(enforceOrdering(_maybeRandomize(choices)))};const transform$5=(widgetOptions,strings,problemNum)=>{const choices=_choiceTransform(widgetOptions,strings,problemNum);const{hasNoneOfTheAbove,multipleSelect,countChoices,deselectEnabled,numCorrect}=widgetOptions;return {numCorrect:numCorrect,hasNoneOfTheAbove,multipleSelect,countChoices,deselectEnabled,choices,selectedChoices:___default.default.pluck(choices,"correct")}};function getStartUserInput$8(options){return {choicesSelected:options.choices.map(()=>false)}}var Radio = {name:"radio",displayName:"Radio / Multiple choice",widget:Radio$1,transform: transform$5,staticTransform:transform$5,getStartUserInput: getStartUserInput$8,version:perseusCore.radioLogic.version,isLintable:true,getUserInputFromSerializedState: getUserInputFromSerializedState$e};
1817
1817
 
1818
1818
  var basicWidgets = [Radio,InputNumber$1,NumericInput$1,Expression$1];
1819
1819
 
@@ -1917,11 +1917,13 @@ const arrowPath=pathBuilder().move(-3,4).curve(-2.75,2.5,0,.25,.75,0).curve(0,-0
1917
1917
 
1918
1918
  function AxisArrows(){const{range:[[xMin,xMax],[yMin,yMax]]}=useGraphConfig();const axisColor="var(--mafs-fg)";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[!(yMin>0||yMax<0)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Arrowhead,{color:axisColor,tip:[xMin,0],angle:180}),jsxRuntimeExports.jsx(Arrowhead,{color:axisColor,tip:[xMax,0],angle:0})]}),!(xMin>0||xMax<0)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Arrowhead,{color:axisColor,tip:[0,yMin],angle:90}),jsxRuntimeExports.jsx(Arrowhead,{color:axisColor,tip:[0,yMax],angle:270})]})]})}
1919
1919
 
1920
- const TARGET_SIZE=44;const REMOVE_BUTTON_ID="perseus_mafs_remove_button";const normalizePoints=(range,step,coordsList,noSnap)=>coordsList.map(coords=>coords.map((coord,i)=>{const axisRange=range[i];if(noSnap){return axisRange[MIN]+size(axisRange)*coord}const axisStep=step[i];const nSteps=Math.floor(size(axisRange)/axisStep);const tick=Math.round(coord*nSteps);return axisRange[MIN]+axisStep*tick}));const normalizeCoords=(coordsList,ranges)=>coordsList.map(coords=>coords.map((coord,i)=>{return (coord+ranges[i][1])/size(ranges[i])}));function bound$1({snapStep,range,point}){const boundingBox=inset(snapStep,range);return clampToBox(boundingBox,point)}function isUnlimitedGraphState(state){return state.type==="point"&&state.numPoints==="unlimited"||state.type==="polygon"&&state.numSides==="unlimited"}const mathOnlyParser=SimpleMarkdown__default.default.parserFor({math:{...pureMarkdown.pureMarkdownRules.math,order:0},text:{order:1,match:SimpleMarkdown__default.default.anyScopeRegex(/^([^$\\{}]+)/),parse:capture=>({content:capture[0]})},specialCharacter:{order:2,match:SimpleMarkdown__default.default.anyScopeRegex(/^(\\[\S\s]|\$|\\$|{|})/),parse:capture=>({content:capture[0]})}},{inline:true});function replaceOutsideTeX(mathString){const parsed=mathOnlyParser(mathString);let result="";for(const piece of parsed){piece.type==="math"?result+="$"+piece.content+"$":piece.type==="specialCharacter"?result+=escapeIfUnescaped(piece.content):result+=piece.content;}return `\\text{${result}}`}function escapeIfUnescaped(character){if(character.length===1){return "\\"+character}else {return character}}
1920
+ const TARGET_SIZE=44;const REMOVE_BUTTON_ID="perseus_mafs_remove_button";const normalizePoints=(range,step,coordsList,noSnap)=>coordsList.map(coords=>coords.map((coord,i)=>{const axisRange=range[i];if(noSnap){return axisRange[MIN]+size(axisRange)*coord}const axisStep=step[i];const nSteps=Math.floor(size(axisRange)/axisStep);const tick=Math.round(coord*nSteps);return axisRange[MIN]+axisStep*tick}));const normalizeCoords=(coordsList,ranges)=>coordsList.map(coords=>coords.map((coord,i)=>{return (coord+ranges[i][1])/size(ranges[i])}));function bound$1({snapStep,range,point}){const boundingBox=inset(snapStep,range);return clampToBox(boundingBox,point)}function isUnlimitedGraphState(state){return state.type==="point"&&state.numPoints==="unlimited"||state.type==="polygon"&&state.numSides==="unlimited"}const mathOnlyParser=SimpleMarkdown__default.default.parserFor({math:{...pureMarkdown.pureMarkdownRules.math,order:0},text:{order:1,match:SimpleMarkdown__default.default.anyScopeRegex(/^([^$\\{}]+)/),parse:capture=>({content:capture[0]})},specialCharacter:{order:2,match:SimpleMarkdown__default.default.anyScopeRegex(/^(\\[\S\s]|\$|\\$|{|})/),parse:capture=>({content:capture[0]})}},{inline:true});function replaceOutsideTeX(mathString){const parsed=mathOnlyParser(mathString);let result="";for(const piece of parsed){piece.type==="math"?result+="$"+piece.content+"$":piece.type==="specialCharacter"?result+=escapeIfUnescaped(piece.content):result+=piece.content;}return `\\text{${result}}`}function escapeIfUnescaped(character){if(character.length===1){return "\\"+character}else {return character}}const getRangeDiff=range=>{const[min,max]=range;return Math.abs(max-min)};const calculateNestedSVGCoords=(range,width,height)=>{let viewboxX=0;const totalXRange=getRangeDiff(range[X]);const gridCellWidth=width/totalXRange;const minX=range[X][MIN];if(minX>0){viewboxX=gridCellWidth*Math.abs(minX);}if(minX<0){viewboxX=-gridCellWidth*Math.abs(minX);}let viewboxY=-height;const totalYRange=getRangeDiff(range[Y]);const gridCellHeight=height/totalYRange;const minY=range[Y][MIN];if(minY>0){viewboxY=-height-gridCellHeight*Math.abs(minY);}if(minY<0){viewboxY=gridCellHeight*Math.abs(minY)-height;}return {viewboxX,viewboxY}};
1921
1921
 
1922
- const fontSize=14;function AxisLabels({i18n}){const{range,labels,width,height,labelLocation}=useGraphConfig();const graphInfo={range,width,height};const[xAxisLabelLocation,yAxisLabelLocation]=getLabelPosition(graphInfo,labelLocation);const[xAxisLabelText,yAxisLabelText]=labels;const{xLabelTransform,yLabelTransform}=getLabelTransform(labelLocation);const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("span",{"aria-hidden":true,style:{position:"absolute",left:xAxisLabelLocation[X],top:xAxisLabelLocation[Y],fontSize:fontSize+"px",transform:xLabelTransform},children:jsxRuntimeExports.jsx(TeX,{children:replaceOutsideTeX(xAxisLabelText)})}),jsxRuntimeExports.jsx("span",{"aria-hidden":true,style:{position:"absolute",left:yAxisLabelLocation[X],top:yAxisLabelLocation[Y],fontSize:fontSize+"px",transform:yLabelTransform},children:jsxRuntimeExports.jsx(TeX,{children:replaceOutsideTeX(yAxisLabelText)})})]})}const getLabelTransform=labelLocation=>{const isOnAxis=labelLocation===undefined||labelLocation==="onAxis";const xLabelTransform=isOnAxis?"translate(7px, -50%)":"translate(-50%, -50%)";const yLabelTransform=isOnAxis?"translate(-50%, 0px)":"translate(-50%, 0px) rotate(-90deg)";return {xLabelTransform,yLabelTransform}};const clampLabelPosition=(labelPosition,graphInfo)=>{const x=Math.max(Math.min(labelPosition[X],graphInfo.width+fontSize*1.25),-14*1.5);const y=Math.max(Math.min(labelPosition[Y],graphInfo.height+fontSize*1.25),-14*2);return [x,y]};const getLabelPosition=(graphInfo,labelLocation)=>{if(labelLocation==="alongEdge"){const xAxisLabelOffset=graphInfo.range[Y][MIN]>=0?[0,fontSize*3]:[0,fontSize];const yAxisLabelOffset=graphInfo.range[X][MIN]>=0?[-14*3,-14]:[-14,-14];const xAxisLabelLocation=[(graphInfo.range[X][MIN]+graphInfo.range[X][MAX])/2,graphInfo.range[Y][MIN]];const yAxisLabelLocation=[graphInfo.range[X][MIN],(graphInfo.range[Y][MIN]+graphInfo.range[Y][MAX])/2];const xLabel=mafs.vec.add(pointToPixel(xAxisLabelLocation,graphInfo),xAxisLabelOffset);const yLabel=mafs.vec.add(pointToPixel(yAxisLabelLocation,graphInfo),yAxisLabelOffset);return [xLabel,yLabel]}const xLabelInitial=[graphInfo.range[X][MAX],0];const yLabelInitial=[0,graphInfo.range[Y][MAX]];const yLabelOffset=[0,-14*2];let xLabel=pointToPixel(xLabelInitial,graphInfo);let yLabel=mafs.vec.add(pointToPixel(yLabelInitial,graphInfo),yLabelOffset);xLabel=clampLabelPosition(xLabel,graphInfo);yLabel=clampLabelPosition(yLabel,graphInfo);return [xLabel,yLabel]};
1922
+ const fontSize=14;const clampLabelPosition=(labelPosition,graphInfo)=>{const x=Math.max(Math.min(labelPosition[X],graphInfo.width+fontSize*1.25),-14*1.5);const y=Math.max(Math.min(labelPosition[Y],graphInfo.height+fontSize*1.25),-14*2);return [x,y]};const getLabelTransform=labelLocation=>{const isOnAxis=labelLocation===undefined||labelLocation==="onAxis";const xLabelTransform=isOnAxis?"translate(7px, -50%)":"translate(-50%, -50%)";const yLabelTransform=isOnAxis?"translate(-50%, 0px)":"translate(-50%, 0px) rotate(-90deg)";return {xLabelTransform,yLabelTransform}};const calculateMaxDigitsInRange=(range,tickStep)=>{const maxDigitsInRange=Math.max(String(Math.abs(Math.floor(range[MIN]))).length,String(Math.abs(Math.ceil(range[MAX]))).length);const tickStepSigFigs=countSignificantDecimals(tickStep)+2;return Math.max(maxDigitsInRange,tickStepSigFigs)};const getLabelPosition=(graphInfo,labelLocation,tickStep)=>{if(labelLocation==="alongEdge"){const xAxisLabelOffset=graphInfo.range[Y][MIN]>=0?[0,fontSize*3]:[0,fontSize*1.5];const isRelativelyCloseToZero=graphInfo.range[X][MIN]<0&&Math.abs(graphInfo.range[X][MIN])<(graphInfo.range[X][MAX]-graphInfo.range[X][MIN])*.07;const needsExtraSpacing=graphInfo.range[X][MIN]>=0||isRelativelyCloseToZero;let paddingRequiredForTickLabels=0;if(needsExtraSpacing){const maxDigits=calculateMaxDigitsInRange(graphInfo.range[Y],tickStep[Y]);paddingRequiredForTickLabels=maxDigits*(fontSize*.75)+(graphInfo.range[Y][MIN]<0&&graphInfo.range[X][MIN]<=0?fontSize*.5:0);}const yAxisLabelOffset=[-14*1.25-paddingRequiredForTickLabels,-14];const xAxisLabelLocation=[(graphInfo.range[X][MIN]+graphInfo.range[X][MAX])/2,graphInfo.range[Y][MIN]];const yAxisLabelLocation=[graphInfo.range[X][MIN],(graphInfo.range[Y][MIN]+graphInfo.range[Y][MAX])/2];if(isRelativelyCloseToZero){yAxisLabelLocation[X]=yAxisLabelLocation[X]-graphInfo.range[X][MIN];}const xLabel=mafs.vec.add(pointToPixel(xAxisLabelLocation,graphInfo),xAxisLabelOffset);const yLabel=mafs.vec.add(pointToPixel(yAxisLabelLocation,graphInfo),yAxisLabelOffset);return [xLabel,yLabel]}const xLabelInitial=[graphInfo.range[X][MAX],0];const yLabelInitial=[0,graphInfo.range[Y][MAX]];const yLabelOffset=[0,-14*2];let xLabel=pointToPixel(xLabelInitial,graphInfo);let yLabel=mafs.vec.add(pointToPixel(yLabelInitial,graphInfo),yLabelOffset);xLabel=clampLabelPosition(xLabel,graphInfo);yLabel=clampLabelPosition(yLabel,graphInfo);return [xLabel,yLabel]};const shouldShowLabel=(currentTick,range,tickStep)=>{let showLabel=true;if(range[X][MIN]<-tickStep&&range[X][MAX]>0&&currentTick===-tickStep){showLabel=false;}return showLabel};function generateTickLocations(tickStep,min,max){const ticks=[];const decimalSigFigs=countSignificantDecimals(tickStep);const start=Math.max(min,0);for(let i=start+tickStep;i<max;i+=tickStep){ticks.push(parseFloat(i.toFixed(decimalSigFigs)));}let i=Math.min(max,0)-tickStep;for(i;i>min;i-=tickStep){ticks.push(i);}return ticks}const countSignificantDecimals=number=>{const numStr=number.toString();if(!numStr.includes(".")){return 0}return numStr.split(".")[1].length};function divideByAndShowPi(value){const dividedValue=value/Math.PI;switch(dividedValue){case 1:return "π";case -1:return "-π";case 0:return "0";default:return dividedValue+"π"}}
1923
1923
 
1924
- const tickSize=10;const tickLabelSize=14;const YGridTick=({y,range,tickStep,showPi})=>{let xPointOnAxis=0;if(range[X][MIN]>0){xPointOnAxis=range[X][MIN];}if(range[X][MAX]<0){xPointOnAxis=range[X][MAX];}const pointOnAxis=[xPointOnAxis,y];const[[xPosition,yPosition]]=useTransformVectorsToPixels(pointOnAxis);const x1=xPosition-tickSize/2;const y1=yPosition;const x2=xPosition+tickSize/2;const y2=yPosition;const xAdjustment=range[X][MAX]<=0?tickLabelSize*1.5:-14*1.1;const xPositionText=xPosition+xAdjustment;const yPositionText=yPosition+tickLabelSize*.25;const showLabel=shouldShowLabel(y,range,tickStep);const yLabel=showPi?divideByAndShowPi(y):y.toString();return jsxRuntimeExports.jsxs("g",{className:"tick","aria-hidden":true,children:[jsxRuntimeExports.jsx("line",{x1:x1,y1:y1,x2:x2,y2:y2,className:"axis-tick"}),showLabel&&jsxRuntimeExports.jsx("text",{className:"axis-tick-label",style:{fontSize:tickLabelSize},textAnchor:"end",x:xPositionText,y:yPositionText,children:yLabel})]})};const XGridTick=({x,range,showPi})=>{let yPointOnAxis=0;if(range[Y][MIN]>0){yPointOnAxis=range[Y][MIN];}if(range[Y][MAX]<0){yPointOnAxis=range[Y][MAX];}const pointOnAxis=[x,yPointOnAxis];const[[xPosition,yPosition]]=useTransformVectorsToPixels(pointOnAxis);const x1=xPosition;const y1=yPosition+tickSize/2;const x2=xPosition;const y2=yPosition-tickSize/2;const yAdjustment=range[Y][MAX]<0?-14:tickLabelSize*1.75;const xAdjustment=x<0?-2:0;const xPositionText=xPosition+xAdjustment;const yPositionText=yPosition+yAdjustment;const xLabel=showPi?divideByAndShowPi(x):x.toString();return jsxRuntimeExports.jsxs("g",{className:"tick","aria-hidden":true,children:[jsxRuntimeExports.jsx("line",{x1:x1,y1:y1,x2:x2,y2:y2,className:"axis-tick"}),jsxRuntimeExports.jsx("text",{className:"axis-tick-label",style:{fontSize:tickLabelSize},textAnchor:"middle",x:xPositionText,y:yPositionText,children:xLabel})]})};const shouldShowLabel=(currentTick,range,tickStep)=>{let showLabel=true;if(range[X][MIN]<-tickStep&&range[X][MAX]>0&&currentTick===-tickStep){showLabel=false;}return showLabel};function generateTickLocations(tickStep,min,max){const ticks=[];const decimalSigFigs=countSignificantDecimals(tickStep);const start=Math.max(min,0);for(let i=start+tickStep;i<max;i+=tickStep){ticks.push(parseFloat(i.toFixed(decimalSigFigs)));}let i=Math.min(max,0)-tickStep;for(i;i>min;i-=tickStep){ticks.push(i);}return ticks}const countSignificantDecimals=number=>{const numStr=number.toString();if(!numStr.includes(".")){return 0}return numStr.split(".")[1].length};function divideByAndShowPi(value){const dividedValue=value/Math.PI;switch(dividedValue){case 1:return "π";case -1:return "-π";case 0:return "0";default:return dividedValue+"π"}}const AxisTicks=()=>{const{tickStep,range}=useGraphConfig();const[[xMin,xMax],[yMin,yMax]]=range;const[xTickStep,yTickStep]=tickStep;const yGridTicks=generateTickLocations(yTickStep,yMin,yMax);const xGridTicks=generateTickLocations(xTickStep,xMin,xMax);return jsxRuntimeExports.jsxs("g",{className:"axis-ticks",role:"presentation",children:[jsxRuntimeExports.jsx("g",{className:"y-axis-ticks",children:yGridTicks.map(y=>{return jsxRuntimeExports.jsx(YGridTick,{y:y,range:range,tickStep:tickStep[Y],showPi:tickStep[Y]%Math.PI===0},`y-grid-tick-${y}`)})}),jsxRuntimeExports.jsx("g",{className:"x-axis-ticks",children:xGridTicks.map(x=>{return jsxRuntimeExports.jsx(XGridTick,{x:x,range:range,showPi:tickStep[X]%Math.PI===0},`x-grid-tick-${x}`)})})]})};
1924
+ function AxisLabels({i18n}){const{range,labels,width,height,labelLocation,tickStep}=useGraphConfig();const graphInfo={range,width,height};const[xAxisLabelLocation,yAxisLabelLocation]=getLabelPosition(graphInfo,labelLocation,tickStep);const[xAxisLabelText,yAxisLabelText]=labels;const{xLabelTransform,yLabelTransform}=getLabelTransform(labelLocation);const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("span",{"aria-hidden":true,style:{position:"absolute",left:xAxisLabelLocation[X],top:xAxisLabelLocation[Y],fontSize:fontSize+"px",transform:xLabelTransform},children:jsxRuntimeExports.jsx(TeX,{children:replaceOutsideTeX(xAxisLabelText)})}),jsxRuntimeExports.jsx("span",{"aria-hidden":true,style:{position:"absolute",left:yAxisLabelLocation[X],top:yAxisLabelLocation[Y],fontSize:fontSize+"px",transform:yLabelTransform},children:jsxRuntimeExports.jsx(TeX,{children:replaceOutsideTeX(yAxisLabelText)})})]})}
1925
+
1926
+ const tickSize=10;const tickLabelSize=14;const YGridTick=({y,range,tickStep,showPi})=>{let xPointOnAxis=0;if(range[X][MIN]>0){xPointOnAxis=range[X][MIN];}if(range[X][MAX]<0){xPointOnAxis=range[X][MAX];}const pointOnAxis=[xPointOnAxis,y];const[[xPosition,yPosition]]=useTransformVectorsToPixels(pointOnAxis);const x1=xPosition-tickSize/2;const y1=yPosition;const x2=xPosition+tickSize/2;const y2=yPosition;const xAdjustment=range[X][MAX]<=0?tickLabelSize*1.5:-14*1.1;const xPositionText=xPosition+xAdjustment;const yPositionText=yPosition+tickLabelSize*.25;const showLabel=shouldShowLabel(y,range,tickStep);const yLabel=showPi?divideByAndShowPi(y):y.toString();return jsxRuntimeExports.jsxs("g",{className:"tick","aria-hidden":true,children:[jsxRuntimeExports.jsx("line",{x1:x1,y1:y1,x2:x2,y2:y2,className:"axis-tick"}),showLabel&&jsxRuntimeExports.jsx("text",{className:"axis-tick-label",style:{fontSize:tickLabelSize},textAnchor:"end",x:xPositionText,y:yPositionText,children:yLabel})]})};const XGridTick=({x,range,showPi})=>{let yPointOnAxis=0;if(range[Y][MIN]>0){yPointOnAxis=range[Y][MIN];}if(range[Y][MAX]<0){yPointOnAxis=range[Y][MAX];}const pointOnAxis=[x,yPointOnAxis];const[[xPosition,yPosition]]=useTransformVectorsToPixels(pointOnAxis);const x1=xPosition;const y1=yPosition+tickSize/2;const x2=xPosition;const y2=yPosition-tickSize/2;const yAdjustment=range[Y][MAX]<0?-14:tickLabelSize*1.75;const xAdjustment=x<0?-2:0;const xPositionText=xPosition+xAdjustment;const yPositionText=yPosition+yAdjustment;const xLabel=showPi?divideByAndShowPi(x):x.toString();return jsxRuntimeExports.jsxs("g",{className:"tick","aria-hidden":true,children:[jsxRuntimeExports.jsx("line",{x1:x1,y1:y1,x2:x2,y2:y2,className:"axis-tick"}),jsxRuntimeExports.jsx("text",{className:"axis-tick-label",style:{fontSize:tickLabelSize},textAnchor:"middle",x:xPositionText,y:yPositionText,children:xLabel})]})};const AxisTicks=()=>{const{tickStep,range}=useGraphConfig();const[[xMin,xMax],[yMin,yMax]]=range;const[xTickStep,yTickStep]=tickStep;const yGridTicks=generateTickLocations(yTickStep,yMin,yMax);const xGridTicks=generateTickLocations(xTickStep,xMin,xMax);return jsxRuntimeExports.jsxs("g",{className:"axis-ticks",role:"presentation",children:[jsxRuntimeExports.jsx("g",{className:"y-axis-ticks",children:yGridTicks.map(y=>{return jsxRuntimeExports.jsx(YGridTick,{y:y,range:range,tickStep:tickStep[Y],showPi:tickStep[Y]%Math.PI===0},`y-grid-tick-${y}`)})}),jsxRuntimeExports.jsx("g",{className:"x-axis-ticks",children:xGridTicks.map(x=>{return jsxRuntimeExports.jsx(XGridTick,{x:x,range:range,showPi:tickStep[X]%Math.PI===0},`x-grid-tick-${x}`)})})]})};
1925
1927
 
1926
1928
  const axisOptions=(props,axisIndex)=>{const lines=props.markings==="axes"?false:props.gridStep[axisIndex];return {axis:props.markings==="graph"||props.markings==="axes",lines:lines,labels:false}};const Grid=props=>{return props.markings==="none"?null:jsxRuntimeExports.jsx(mafs.Coordinates.Cartesian,{xAxis:axisOptions(props,X),yAxis:axisOptions(props,Y)})};
1927
1929
 
@@ -2038,7 +2040,7 @@ function renderSinusoidGraph(state,dispatch,i18n){return {graph:jsxRuntimeExport
2038
2040
 
2039
2041
  const{calculateAngleInDegrees,convertDegreesToRadians}=kmath.angles;const protractorImage="https://cdn.kastatic.org/images/perseus/protractor.svg";const centerToTopLeft=[-195,-190];const centerToRotationHandle=[-201,-15];function Protractor(){const staticUrl=getDependencies().staticUrl;const{range,snapStep}=useGraphConfig();const[[xMin,xMax],[yMin,yMax]]=range;const initialCenter=[lerp(xMin,xMax,.5),lerp(yMin,yMax,.25)];const[center,setCenter]=React.useState(initialCenter);const[rotationHandleOffset,setRotationHandleOffset]=React.useState(centerToRotationHandle);const draggableRef=React.useRef(null);const{dragging}=useDraggable({gestureTarget:draggableRef,onMove:setCenter,point:center,constrainKeyboardMovement:point=>bound$1({snapStep,range,point})});const rotationHandleRef=React.useRef(null);useDraggablePx({gestureTarget:rotationHandleRef,onMove:setRotationHandleOffset,point:rotationHandleOffset,constrain:constrainToCircle});const[centerPx]=useTransformVectorsToPixels(center);const topLeftPx=mafs.vec.add(centerPx,centerToTopLeft);const angle=calculateAngleInDegrees(rotationHandleOffset)-calculateAngleInDegrees(centerToRotationHandle);return jsxRuntimeExports.jsxs("g",{ref:draggableRef,transform:`translate(${topLeftPx[X]}, ${topLeftPx[Y]}), rotate(${angle})`,style:{transformOrigin:`${-centerToTopLeft[X]}px ${-centerToTopLeft[Y]}px`,cursor:dragging?"grabbing":"grab"},children:[jsxRuntimeExports.jsx("image",{href:staticUrl(protractorImage)}),jsxRuntimeExports.jsx("g",{transform:`translate(5, ${-centerToTopLeft[1]})`,ref:rotationHandleRef,children:jsxRuntimeExports.jsx(RotationArrow,{})})]})}function RotationArrow(){const radius=175;const angleDeg=10;const angleRad=convertDegreesToRadians(angleDeg);const endX=radius*(1-Math.cos(angleRad));const endY=radius*-Math.sin(angleRad);const rotationArrow=pathBuilder().move(0,0).circularArc(radius,endX,endY,{sweep:true}).build();const arrowhead=pathBuilder().move(-8,0).line(0,10).line(8,0).build();const targetRadius=TARGET_SIZE/2;return jsxRuntimeExports.jsxs("g",{className:"protractor-rotation-handle",children:[jsxRuntimeExports.jsx("path",{className:"protractor-rotation-handle-arrow-arc",d:rotationArrow}),jsxRuntimeExports.jsx("path",{className:"protractor-rotation-handle-arrowhead",d:arrowhead}),jsxRuntimeExports.jsx("path",{className:"protractor-rotation-handle-arrowhead",d:arrowhead,transform:`translate(${endX}, ${endY}), rotate(${180+angleDeg})`}),jsxRuntimeExports.jsx("ellipse",{cx:"0px",cy:"-15px",rx:targetRadius,ry:targetRadius,fill:"none"})]})}const protractorRadius=mafs.vec.mag(centerToRotationHandle);function constrainToCircle(edgePoint){return mafs.vec.withMag(edgePoint,protractorRadius)}function useDraggablePx(args){const{gestureTarget:target,onMove,point,constrain=p=>p}=args;const pickupPx=React__namespace.useRef([0,0]);react.useDrag(state=>{const{event,first,movement:pixelMovement}=state;event?.stopPropagation();if(first){pickupPx.current=point;}if(mafs.vec.mag(pixelMovement)===0){return}onMove?.(constrain(mafs.vec.add(pickupPx.current,pixelMovement)));},{target,eventOptions:{passive:false}});}
2040
2042
 
2041
- const MafsGraph=props=>{const{state,dispatch,labels,labelLocation,readOnly,fullGraphAriaLabel,fullGraphAriaDescription}=props;const{type}=state;const[width,height]=props.box;const tickStep=props.step;const uniqueId=React__namespace.useId();const descriptionId=`interactive-graph-description-${uniqueId}`;const interactiveElementsDescriptionId=`interactive-graph-interactive-elements-description-${uniqueId}`;const unlimitedGraphKeyboardPromptId=`unlimited-graph-keyboard-prompt-${uniqueId}`;const instructionsId=`instructions-${uniqueId}`;const graphRef=React__namespace.useRef(null);const{analytics}=useDependencies();const{viewboxX,viewboxY}=calculateNestedSVGCoords(state.range,width,height);const viewBox=`${viewboxX} ${viewboxY} ${width} ${height}`;const nestedSVGAttributes={width,height,viewBox,preserveAspectRatio:"xMidYMin",x:viewboxX,y:viewboxY};const i18n=usePerseusI18n();const{strings}=i18n;const interactionPrompt=isUnlimitedGraphState(state)&&state.showKeyboardInteractionInvitation;wonderBlocksCore.useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:interactive-graph-widget:rendered",payload:{type,widgetType:"INTERACTIVE_GRAPH",widgetId:"interactive-graph"}});analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:type,widgetType:"INTERACTIVE_GRAPH",widgetId:"interactive-graph"}});});const{graph,interactiveElementsDescription}=renderGraphElements({state,dispatch,i18n,markings:props.markings});const disableInteraction=readOnly||!!props.static;return jsxRuntimeExports.jsx(GraphConfigContext.Provider,{value:{range:state.range,snapStep:state.snapStep,markings:props.markings,tickStep:tickStep,gridStep:props.gridStep,showTooltips:!!props.showTooltips,graphDimensionsInPixels:props.box,width,height,labels,labelLocation,disableKeyboardInteraction:disableInteraction,interactiveColor:disableInteraction?"var(--static-gray)":"var(--mafs-blue)"},children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:"mafs-graph-container",children:[jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:"mafs-graph",style:{position:"relative",padding:"25px 25px 0 0",boxSizing:"content-box",marginLeft:"20px",marginBottom:"30px",pointerEvents:props.static?"none":"auto",userSelect:"none",width,height},onKeyUp:event=>{handleKeyboardEvent(event,state,dispatch);},"aria-label":fullGraphAriaLabel,"aria-describedby":describedByIds(fullGraphAriaDescription&&descriptionId,interactiveElementsDescription&&interactiveElementsDescriptionId,isUnlimitedGraphState(state)&&unlimitedGraphKeyboardPromptId,state.type!=="none"&&!disableInteraction&&instructionsId),ref:graphRef,tabIndex:0,onFocus:event=>{handleFocusEvent(event,state,dispatch);},onBlur:event=>{handleBlurEvent(event,state,dispatch);},children:[fullGraphAriaDescription&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{id:descriptionId,tabIndex:-1,className:"mafs-sr-only",children:fullGraphAriaDescription}),interactiveElementsDescription&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{id:interactiveElementsDescriptionId,tabIndex:-1,className:"mafs-sr-only",children:interactiveElementsDescription}),state.type!=="none"&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{id:instructionsId,tabIndex:-1,className:"mafs-sr-only",children:isUnlimitedGraphState(state)?strings.srUnlimitedGraphInstructions:strings.srGraphInstructions}),jsxRuntimeExports.jsx(LegacyGrid,{box:props.box,backgroundImage:props.backgroundImage}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{position:"absolute",bottom:0,left:0},children:[(props.markings==="graph"||props.markings==="axes")&&jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:jsxRuntimeExports.jsx(AxisLabels,{i18n:i18n})}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{"aria-hidden":props.lockedFigures.length===0,children:jsxRuntimeExports.jsxs(mafs.Mafs,{preserveAspectRatio:false,viewBox:{x:state.range[X],y:state.range[Y],padding:0},pan:false,zoom:false,width:width,height:height,children:[jsxRuntimeExports.jsx(SvgDefs,{}),jsxRuntimeExports.jsx("svg",{...nestedSVGAttributes,children:jsxRuntimeExports.jsx(Grid,{gridStep:props.gridStep,range:state.range,containerSizeClass:props.containerSizeClass,markings:props.markings,width:width,height:height})}),(props.markings==="graph"||props.markings==="axes")&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(AxisTicks,{}),jsxRuntimeExports.jsx(AxisArrows,{})]}),props.lockedFigures.length>0&&jsxRuntimeExports.jsx("svg",{...nestedSVGAttributes,children:jsxRuntimeExports.jsx(GraphLockedLayer,{lockedFigures:props.lockedFigures,range:state.range})})]})}),jsxRuntimeExports.jsx(GraphLockedLabelsLayer,{lockedFigures:props.lockedFigures}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{position:"absolute"},children:jsxRuntimeExports.jsx(mafs.Mafs,{preserveAspectRatio:false,viewBox:{x:state.range[X],y:state.range[Y],padding:0},pan:false,zoom:false,width:width,height:height,children:jsxRuntimeExports.jsxs("svg",{...nestedSVGAttributes,children:[props.showProtractor&&jsxRuntimeExports.jsx(Protractor,{}),graph]})})})]}),interactionPrompt&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{display:interactionPrompt?undefined:"hidden",textAlign:"center",backgroundColor:"white",border:"1px solid #21242C52",padding:"16px 0",boxShadow:"0px 8px 8px 0px #21242C14",top:"50%",transform:"translateY(-50%)"},children:jsxRuntimeExports.jsx(wonderBlocksTypography.LabelMedium,{id:unlimitedGraphKeyboardPromptId,children:strings.graphKeyboardPrompt})})]}),renderGraphControls({state,dispatch,width,perseusStrings:strings})]})})};const renderPointGraphControls=props=>{const{interactionMode,showRemovePointButton,focusedPointIndex}=props.state;const{perseusStrings}=props;const shouldShowRemoveButton=showRemovePointButton&&focusedPointIndex!==null;return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},tabIndex:0,onClick:()=>{props.dispatch(actions.pointGraph.addPoint([0,0]));},children:perseusStrings.addPoint}),interactionMode==="mouse"&&jsxRuntimeExports.jsx(Button__default.default,{id:REMOVE_BUTTON_ID,kind:"secondary",actionType:"destructive",tabIndex:-1,style:{width:"100%",marginLeft:"20px",visibility:shouldShowRemoveButton?"visible":"hidden"},onClick:_event=>{props.dispatch(actions.pointGraph.removePoint(props.state.focusedPointIndex));},children:perseusStrings.removePoint})]})};const renderPolygonGraphControls=props=>{const{interactionMode,showRemovePointButton,focusedPointIndex,closedPolygon,coords}=props.state;const{perseusStrings}=props;const shouldShowRemoveButton=showRemovePointButton&&focusedPointIndex!==null;const disableCloseButton=getArrayWithoutDuplicates(coords).length<3;const polygonButton=closedPolygon?jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},tabIndex:0,onClick:()=>{props.dispatch(actions.polygon.openPolygon());},children:perseusStrings.openPolygon}):jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",disabled:disableCloseButton,style:{width:"100%",marginLeft:"20px"},tabIndex:disableCloseButton?-1:0,onClick:()=>{props.dispatch(actions.polygon.closePolygon());},children:perseusStrings.closePolygon});return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},disabled:closedPolygon,tabIndex:closedPolygon?-1:0,onClick:()=>{props.dispatch(actions.polygon.addPoint([0,0]));},children:perseusStrings.addPoint}),interactionMode==="mouse"&&jsxRuntimeExports.jsx(Button__default.default,{id:REMOVE_BUTTON_ID,kind:"secondary",actionType:"destructive",disabled:closedPolygon||!shouldShowRemoveButton,tabIndex:-1,style:{width:"100%",marginLeft:"20px"},onClick:_event=>{props.dispatch(actions.polygon.removePoint(props.state.focusedPointIndex));},children:perseusStrings.removePoint}),polygonButton]})})};const renderGraphControls=props=>{const{state,dispatch,width,perseusStrings}=props;const{type}=state;switch(type){case "point":if(state.numPoints==="unlimited"){return renderPointGraphControls({state,dispatch,width,perseusStrings})}return null;case "polygon":if(state.numSides==="unlimited"){return renderPolygonGraphControls({state,dispatch,width,perseusStrings})}return null;default:return null}};function handleFocusEvent(event,state,dispatch){if(isUnlimitedGraphState(state)){if(event.target.classList.contains("mafs-graph")&&state.interactionMode==="mouse"){dispatch(actions.global.changeKeyboardInvitationVisibility(true));}}}function handleBlurEvent(_event,state,dispatch){if(isUnlimitedGraphState(state)){dispatch(actions.global.changeKeyboardInvitationVisibility(false));}}function handleKeyboardEvent(event,state,dispatch){if(isUnlimitedGraphState(state)){if(event.key==="Backspace"||event.key==="Delete"){if(document.activeElement?.classList.contains("movable-point__focusable-handle")){if(state.type==="point"||state.type==="polygon"&&!state.closedPolygon){dispatch(actions.global.deleteIntent());}}document.activeElement.blur();}else if(event.shiftKey&&event.key==="Enter"){dispatch(actions.global.changeInteractionMode("keyboard"));}else if(state.interactionMode==="keyboard"&&event.key==="a"){dispatch(actions.pointGraph.addPoint([0,0]));}}}const getRangeDiff=range=>{const[min,max]=range;return Math.abs(max-min)};const calculateNestedSVGCoords=(range,width,height)=>{let viewboxX=0;const totalXRange=getRangeDiff(range[X]);const gridCellWidth=width/totalXRange;const minX=range[X][MIN];if(minX>0){viewboxX=gridCellWidth*Math.abs(minX);}if(minX<0){viewboxX=-gridCellWidth*Math.abs(minX);}let viewboxY=-height;const totalYRange=getRangeDiff(range[Y]);const gridCellHeight=height/totalYRange;const minY=range[Y][MIN];if(minY>0){viewboxY=-height-gridCellHeight*Math.abs(minY);}if(minY<0){viewboxY=gridCellHeight*Math.abs(minY)-height;}return {viewboxX,viewboxY}};const renderGraphElements=props=>{const{state,dispatch,i18n,markings}=props;const{type}=state;switch(type){case "angle":return renderAngleGraph(state,dispatch,i18n);case "segment":return renderSegmentGraph(state,dispatch,i18n);case "linear-system":return renderLinearSystemGraph(state,dispatch,i18n);case "linear":return renderLinearGraph(state,dispatch,i18n);case "ray":return renderRayGraph(state,dispatch,i18n);case "polygon":return renderPolygonGraph(state,dispatch,i18n,markings);case "point":return renderPointGraph(state,dispatch,i18n);case "circle":return renderCircleGraph(state,dispatch,i18n);case "quadratic":return renderQuadraticGraph(state,dispatch,i18n);case "sinusoid":return renderSinusoidGraph(state,dispatch,i18n);case "none":return {graph:null,interactiveElementsDescription:null};default:throw new wonderStuffCore.UnreachableCaseError(type)}};function describedByIds(...args){return args.filter(Boolean).join(" ")||undefined}
2043
+ const MafsGraph=props=>{const{state,dispatch,labels,labelLocation,readOnly,fullGraphAriaLabel,fullGraphAriaDescription}=props;const{type}=state;const[width,height]=props.box;const tickStep=props.step;const uniqueId=React__namespace.useId();const descriptionId=`interactive-graph-description-${uniqueId}`;const interactiveElementsDescriptionId=`interactive-graph-interactive-elements-description-${uniqueId}`;const unlimitedGraphKeyboardPromptId=`unlimited-graph-keyboard-prompt-${uniqueId}`;const instructionsId=`instructions-${uniqueId}`;const graphRef=React__namespace.useRef(null);const{analytics}=useDependencies();const{viewboxX,viewboxY}=calculateNestedSVGCoords(state.range,width,height);const viewBox=`${viewboxX} ${viewboxY} ${width} ${height}`;const nestedSVGAttributes={width,height,viewBox,preserveAspectRatio:"xMidYMin",x:viewboxX,y:viewboxY};const i18n=usePerseusI18n();const{strings}=i18n;const interactionPrompt=isUnlimitedGraphState(state)&&state.showKeyboardInteractionInvitation;wonderBlocksCore.useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:interactive-graph-widget:rendered",payload:{type,widgetType:"INTERACTIVE_GRAPH",widgetId:"interactive-graph"}});analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:type,widgetType:"INTERACTIVE_GRAPH",widgetId:"interactive-graph"}});});const{graph,interactiveElementsDescription}=renderGraphElements({state,dispatch,i18n,markings:props.markings});const disableInteraction=readOnly||!!props.static;return jsxRuntimeExports.jsx(GraphConfigContext.Provider,{value:{range:state.range,snapStep:state.snapStep,markings:props.markings,tickStep:tickStep,gridStep:props.gridStep,showTooltips:!!props.showTooltips,graphDimensionsInPixels:props.box,width,height,labels,labelLocation,disableKeyboardInteraction:disableInteraction,interactiveColor:disableInteraction?"var(--static-gray)":"var(--mafs-blue)"},children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:"mafs-graph-container",children:[jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:"mafs-graph",style:{position:"relative",padding:"25px 25px 0 0",boxSizing:"content-box",marginLeft:"20px",marginBottom:"30px",pointerEvents:props.static?"none":"auto",userSelect:"none",width,height},onKeyUp:event=>{handleKeyboardEvent(event,state,dispatch);},"aria-label":fullGraphAriaLabel,"aria-describedby":describedByIds(fullGraphAriaDescription&&descriptionId,interactiveElementsDescription&&interactiveElementsDescriptionId,isUnlimitedGraphState(state)&&unlimitedGraphKeyboardPromptId,state.type!=="none"&&!disableInteraction&&instructionsId),ref:graphRef,tabIndex:0,onFocus:event=>{handleFocusEvent(event,state,dispatch);},onBlur:event=>{handleBlurEvent(event,state,dispatch);},children:[fullGraphAriaDescription&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{id:descriptionId,tabIndex:-1,className:"mafs-sr-only",children:fullGraphAriaDescription}),interactiveElementsDescription&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{id:interactiveElementsDescriptionId,tabIndex:-1,className:"mafs-sr-only",children:interactiveElementsDescription}),state.type!=="none"&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{id:instructionsId,tabIndex:-1,className:"mafs-sr-only",children:isUnlimitedGraphState(state)?strings.srUnlimitedGraphInstructions:strings.srGraphInstructions}),jsxRuntimeExports.jsx(LegacyGrid,{box:props.box,backgroundImage:props.backgroundImage}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{position:"absolute",bottom:0,left:0},children:[(props.markings==="graph"||props.markings==="axes")&&jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:jsxRuntimeExports.jsx(AxisLabels,{i18n:i18n})}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{"aria-hidden":props.lockedFigures.length===0,children:jsxRuntimeExports.jsxs(mafs.Mafs,{preserveAspectRatio:false,viewBox:{x:state.range[X],y:state.range[Y],padding:0},pan:false,zoom:false,width:width,height:height,children:[jsxRuntimeExports.jsx(SvgDefs,{}),jsxRuntimeExports.jsx("svg",{...nestedSVGAttributes,children:jsxRuntimeExports.jsx(Grid,{gridStep:props.gridStep,range:state.range,containerSizeClass:props.containerSizeClass,markings:props.markings,width:width,height:height})}),(props.markings==="graph"||props.markings==="axes")&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(AxisTicks,{}),jsxRuntimeExports.jsx(AxisArrows,{})]}),props.lockedFigures.length>0&&jsxRuntimeExports.jsx("svg",{...nestedSVGAttributes,children:jsxRuntimeExports.jsx(GraphLockedLayer,{lockedFigures:props.lockedFigures,range:state.range})})]})}),jsxRuntimeExports.jsx(GraphLockedLabelsLayer,{lockedFigures:props.lockedFigures}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{position:"absolute"},children:jsxRuntimeExports.jsx(mafs.Mafs,{preserveAspectRatio:false,viewBox:{x:state.range[X],y:state.range[Y],padding:0},pan:false,zoom:false,width:width,height:height,children:jsxRuntimeExports.jsxs("svg",{...nestedSVGAttributes,children:[props.showProtractor&&jsxRuntimeExports.jsx(Protractor,{}),graph]})})})]}),interactionPrompt&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{display:interactionPrompt?undefined:"hidden",textAlign:"center",backgroundColor:"white",border:"1px solid #21242C52",padding:"16px 0",boxShadow:"0px 8px 8px 0px #21242C14",top:"50%",transform:"translateY(-50%)"},children:jsxRuntimeExports.jsx(wonderBlocksTypography.LabelMedium,{id:unlimitedGraphKeyboardPromptId,children:strings.graphKeyboardPrompt})})]}),renderGraphControls({state,dispatch,width,perseusStrings:strings})]})})};const renderPointGraphControls=props=>{const{interactionMode,showRemovePointButton,focusedPointIndex}=props.state;const{perseusStrings}=props;const shouldShowRemoveButton=showRemovePointButton&&focusedPointIndex!==null;return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},tabIndex:0,onClick:()=>{props.dispatch(actions.pointGraph.addPoint([0,0]));},children:perseusStrings.addPoint}),interactionMode==="mouse"&&jsxRuntimeExports.jsx(Button__default.default,{id:REMOVE_BUTTON_ID,kind:"secondary",actionType:"destructive",tabIndex:-1,style:{width:"100%",marginLeft:"20px",visibility:shouldShowRemoveButton?"visible":"hidden"},onClick:_event=>{props.dispatch(actions.pointGraph.removePoint(props.state.focusedPointIndex));},children:perseusStrings.removePoint})]})};const renderPolygonGraphControls=props=>{const{interactionMode,showRemovePointButton,focusedPointIndex,closedPolygon,coords}=props.state;const{perseusStrings}=props;const shouldShowRemoveButton=showRemovePointButton&&focusedPointIndex!==null;const disableCloseButton=getArrayWithoutDuplicates(coords).length<3;const polygonButton=closedPolygon?jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},tabIndex:0,onClick:()=>{props.dispatch(actions.polygon.openPolygon());},children:perseusStrings.openPolygon}):jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",disabled:disableCloseButton,style:{width:"100%",marginLeft:"20px"},tabIndex:disableCloseButton?-1:0,onClick:()=>{props.dispatch(actions.polygon.closePolygon());},children:perseusStrings.closePolygon});return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},disabled:closedPolygon,tabIndex:closedPolygon?-1:0,onClick:()=>{props.dispatch(actions.polygon.addPoint([0,0]));},children:perseusStrings.addPoint}),interactionMode==="mouse"&&jsxRuntimeExports.jsx(Button__default.default,{id:REMOVE_BUTTON_ID,kind:"secondary",actionType:"destructive",disabled:closedPolygon||!shouldShowRemoveButton,tabIndex:-1,style:{width:"100%",marginLeft:"20px"},onClick:_event=>{props.dispatch(actions.polygon.removePoint(props.state.focusedPointIndex));},children:perseusStrings.removePoint}),polygonButton]})})};const renderGraphControls=props=>{const{state,dispatch,width,perseusStrings}=props;const{type}=state;switch(type){case "point":if(state.numPoints==="unlimited"){return renderPointGraphControls({state,dispatch,width,perseusStrings})}return null;case "polygon":if(state.numSides==="unlimited"){return renderPolygonGraphControls({state,dispatch,width,perseusStrings})}return null;default:return null}};function handleFocusEvent(event,state,dispatch){if(isUnlimitedGraphState(state)){if(event.target.classList.contains("mafs-graph")&&state.interactionMode==="mouse"){dispatch(actions.global.changeKeyboardInvitationVisibility(true));}}}function handleBlurEvent(_event,state,dispatch){if(isUnlimitedGraphState(state)){dispatch(actions.global.changeKeyboardInvitationVisibility(false));}}function handleKeyboardEvent(event,state,dispatch){if(isUnlimitedGraphState(state)){if(event.key==="Backspace"||event.key==="Delete"){if(document.activeElement?.classList.contains("movable-point__focusable-handle")){if(state.type==="point"||state.type==="polygon"&&!state.closedPolygon){dispatch(actions.global.deleteIntent());}}document.activeElement.blur();}else if(event.shiftKey&&event.key==="Enter"){dispatch(actions.global.changeInteractionMode("keyboard"));}else if(state.interactionMode==="keyboard"&&event.key==="a"){dispatch(actions.pointGraph.addPoint([0,0]));}}}const renderGraphElements=props=>{const{state,dispatch,i18n,markings}=props;const{type}=state;switch(type){case "angle":return renderAngleGraph(state,dispatch,i18n);case "segment":return renderSegmentGraph(state,dispatch,i18n);case "linear-system":return renderLinearSystemGraph(state,dispatch,i18n);case "linear":return renderLinearGraph(state,dispatch,i18n);case "ray":return renderRayGraph(state,dispatch,i18n);case "polygon":return renderPolygonGraph(state,dispatch,i18n,markings);case "point":return renderPointGraph(state,dispatch,i18n);case "circle":return renderCircleGraph(state,dispatch,i18n);case "quadratic":return renderQuadraticGraph(state,dispatch,i18n);case "sinusoid":return renderSinusoidGraph(state,dispatch,i18n);case "none":return {graph:null,interactiveElementsDescription:null};default:throw new wonderStuffCore.UnreachableCaseError(type)}};function describedByIds(...args){return args.filter(Boolean).join(" ")||undefined}
2042
2044
 
2043
2045
  function mafsStateToInteractiveGraph(state,originalGraph){switch(state.type){case "angle":invariant__default.default(originalGraph.type==="angle");return {...originalGraph,coords:state.coords};case "quadratic":invariant__default.default(originalGraph.type==="quadratic");return {...originalGraph,coords:state.coords};case "circle":invariant__default.default(originalGraph.type==="circle");return {...originalGraph,center:state.center,radius:getRadius(state)};case "linear":invariant__default.default(originalGraph.type==="linear");return {...originalGraph,coords:state.coords};case "ray":invariant__default.default(originalGraph.type==="ray");return {...originalGraph,coords:state.coords};case "sinusoid":invariant__default.default(originalGraph.type==="sinusoid");return {...originalGraph,coords:state.coords};case "segment":invariant__default.default(originalGraph.type==="segment");return {...originalGraph,coords:state.coords};case "linear-system":invariant__default.default(originalGraph.type==="linear-system");return {...originalGraph,coords:state.coords};case "polygon":invariant__default.default(originalGraph.type==="polygon");return {...originalGraph,coords:state.coords};case "point":invariant__default.default(originalGraph.type==="point");return {...originalGraph,coords:state.coords};case "none":invariant__default.default(originalGraph.type==="none");return {...originalGraph};default:throw new wonderStuffCore.UnreachableCaseError(state)}}
2044
2046
 
@@ -2120,7 +2122,7 @@ var extraWidgets = [CSProgram$1,Categorizer$1,Definition$1,DeprecatedStandin$1,D
2120
2122
 
2121
2123
  const init=function(){registerWidgets(basicWidgets);registerWidgets(extraWidgets);replaceDeprecatedWidgets();};
2122
2124
 
2123
- const libName="@khanacademy/perseus";const libVersion="65.4.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
2125
+ const libName="@khanacademy/perseus";const libVersion="65.5.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
2124
2126
 
2125
2127
  const apiVersion={major:12,minor:0};
2126
2128