@khanacademy/perseus 78.0.0 → 78.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -1413,7 +1413,7 @@ var a11y = StyleSheet.create({srOnly:{border:0,clip:"rect(0,0,0,0)",height:1,mar
1413
1413
 
1414
1414
  const debounce=(func,delay)=>{let timer=null;return (...args)=>{if(timer){clearTimeout(timer);}timer=window.setTimeout(()=>{func(...args);},delay);}};
1415
1415
 
1416
- class InnerMathInput extends React.Component{componentDidMount(){this.mathField()?.latex(this.props.value);}componentDidUpdate(prevProps){if(prevProps.value!==this.props.value){if(this.state.focused){return}const field=this.mathField();if(!field){return}const current=field.latex();if(this.props.value!==current){field.latex(this.props.value);}}}openKeypad(){if(this.props.buttonsVisible==="never"){return}this.setState({keypadOpen:true});}closeKeypad(){this.setState({keypadOpen:false});}render(){let className=classNames$2({"perseus-math-input":true,"mq-editable-field":true,"mq-math-mode":true});const popoverContentUniqueId=v4().slice(0,8);if(this.props.className){className=className+" "+this.props.className;}return jsxRuntimeExports.jsx(View,{style:[styles$D.outerWrapper,this.state.focused&&styles$D.wrapperFocused],children:jsxRuntimeExports.jsxs("div",{style:{display:"flex",padding:1},onClick:e=>{e.stopPropagation();const mathField=this.mathField();if(!mathField){return}this.setState({cursorContext:getCursorContext(mathField)});},children:[jsxRuntimeExports.jsx("span",{className:className,ref:ref=>this.__mathFieldWrapperRef=ref,onFocus:()=>this.focus(),onBlur:()=>this.blur()}),jsxRuntimeExports.jsx(Popover,{opened:this.state.keypadOpen,dismissEnabled:true,rootBoundary:"document","aria-label":this.context.strings.mathInputTitle,"aria-describedby":`popover-content-${popoverContentUniqueId}`,onClose:()=>this.closeKeypad(),content:()=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{size:"large",id:`popover-content-${popoverContentUniqueId}`,style:a11y.srOnly,children:this.context.strings.mathInputDescription}),jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$D.popoverContent,children:jsxRuntimeExports.jsx(DesktopKeypad,{onAnalyticsEvent:this.props.onAnalyticsEvent,extraKeys:this.props.extraKeys,onClickKey:this.handleKeypadPress,cursorContext:this.state.cursorContext,convertDotToTimes:this.props.convertDotToTimes,...this.props.keypadButtonSets??mapButtonSets(this.props?.buttonSets),showDismiss:true})})]}),children:this.props.buttonsVisible==="never"?jsxRuntimeExports.jsx(MathInputIcon,{hovered:false,focused:false,active:false}):jsxRuntimeExports.jsx(Clickable,{"aria-label":this.state.keypadOpen?this.context.strings.closeKeypad:this.context.strings.openKeypad,role:"button",onClick:()=>this.state.keypadOpen?this.closeKeypad():this.openKeypad(),children:props=>jsxRuntimeExports.jsx(MathInputIcon,{active:this.state.keypadOpen,...props})})})]})})}constructor(...args){super(...args),this.__mathFieldWrapperRef=null,this.__mathField=null,this.state={focused:false,keypadOpen:this.props.buttonsVisible==="always"?true:false,cursorContext:CursorContext.NONE},this.insert=value=>{const input=this.mathField();const{locale}=this.context;const customKeyTranslator={...getKeyTranslator(locale,this.context.strings),FRAC:mathQuill=>{const contents=mathQuill.latex();mathQuill.typedText("/");if(mathQuill.latex()===contents){mathQuill.cmd("\\frac");}}};const inputModifier=customKeyTranslator[value];if(inputModifier){inputModifier(input,value);input?.focus();return}if(_(value).isFunction()){value(input);}else if(value[0]==="\\"){input?.cmd(value).focus();}else {input?.write(value).focus();}input?.focus();},this.mathField=()=>{if(!this.__mathField&&this.__mathFieldWrapperRef){const{locale}=this.context;this.__mathField=createMathField(this.__mathFieldWrapperRef,locale,this.props.mathInputStrings,baseConfig=>({...baseConfig,handlers:{edit:debounce(mathField=>{let value=mathField.latex();value=value.replace(/<>/g,"\\ne");if(convertDotToTimesByLocale(locale,this.props.convertDotToTimes)){value=value.replace(/\\cdot/g,"\\times");const left=mathField.cursor()[mathQuillInstance.L];if(left&&left.ctrlSeq==="\\cdot "){mathField.controller().backspace();mathField.cmd("\\times");}}else {value=value.replace(/\\times/g,"\\cdot");}if(this.props.value!==value){this.props.onChange(value);}this.setState({cursorContext:getCursorContext(mathField)});},100),enter:()=>{if(this.__mathFieldWrapperRef){$(this.__mathFieldWrapperRef).submit();}},upOutOf:mathField=>{mathField.typedText("^");}}}));}this.__mathField?.setAriaLabel(this.props.ariaLabel);return this.__mathField},this.focus=()=>{this.mathField()?.focus();this.setState({focused:true});},this.blur=()=>this.setState({focused:false}),this.handleKeypadPress=(key,e)=>{if(key==="DISMISS"){this.closeKeypad();return}const{locale}=this.context;const translator=getKeyTranslator(locale,this.context.strings)[key];const mathField=this.mathField();if(mathField){if(translator){translator(mathField,key);}this.setState({cursorContext:getCursorContext(mathField)});}if(e?.type==="click"){this.focus();}};}}InnerMathInput.contextType=PerseusI18nContext;InnerMathInput.defaultProps={value:"",convertDotToTimes:false};class MathInput extends React.Component{blur(){this.inputRef.current?.blur();}focus(){this.inputRef.current?.focus();}insert(value){this.inputRef.current?.insert(value);}render(){return jsxRuntimeExports.jsx(InnerMathInput,{...this.props,ref:this.inputRef,mathInputStrings:this.context.strings})}constructor(...args){super(...args),this.inputRef=React.createRef();}}MathInput.contextType=MathInputI18nContext;MathInput.defaultProps={ariaLabel:"Math input"};const MathInputIcon=({hovered,focused,active})=>{let fillColor;switch(true){case focused||active:fillColor=semanticColor.action.primary.progressive.default.foreground;break;case hovered:fillColor=semanticColor.action.primary.progressive.hover.background;break;default:fillColor=semanticColor.core.foreground.neutral.strong;break}const dynamicClass=active||focused?styles$D.iconActive:styles$D.iconInactive;return jsxRuntimeExports.jsx(View,{style:[styles$D.iconContainer,dynamicClass],children:jsxRuntimeExports.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",fill:fillColor,viewBox:"0 0 256 256",children:jsxRuntimeExports.jsx("path",{d:"M112,72a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16h64A8,8,0,0,1,112,72Zm-8,104H80V152a8,8,0,0,0-16,0v24H40a8,8,0,0,0,0,16H64v24a8,8,0,0,0,16,0V192h24a8,8,0,0,0,0-16Zm48,0h64a8,8,0,0,0,0-16H152a8,8,0,0,0,0,16Zm64,16H152a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm-61.66-90.34a8,8,0,0,0,11.32,0L184,83.31l18.34,18.35a8,8,0,0,0,11.32-11.32L195.31,72l18.35-18.34a8,8,0,0,0-11.32-11.32L184,60.69,165.66,42.34a8,8,0,0,0-11.32,11.32L172.69,72,154.34,90.34A8,8,0,0,0,154.34,101.66Z"})})})};const mapButtonSets=buttonSets=>{const keypadButtonSets={};if(!buttonSets){return keypadButtonSets}buttonSets.forEach(buttonSet=>{switch(buttonSet){case "advanced relations":keypadButtonSets.advancedRelations=true;break;case "basic relations":keypadButtonSets.basicRelations=true;break;case "basic+div":keypadButtonSets.divisionKey=true;break;case "logarithms":keypadButtonSets.logarithms=true;break;case "prealgebra":keypadButtonSets.preAlgebra=true;break;case "trig":keypadButtonSets.trigonometry=true;break;case "scientific":keypadButtonSets.scientific=true;break;}});return keypadButtonSets};const inputFocused={borderWidth:2,borderColor:semanticColor.core.border.instructive.default,margin:-1};const styles$D=StyleSheet.create({iconContainer:{display:"flex",justifyContent:"center",height:"100%",padding:sizing.size_040,borderRadius:1},iconInactive:{border:"2px solid transparent",backgroundColor:semanticColor.core.background.neutral.subtle},iconActive:{border:`2px solid ${semanticColor.core.border.knockout.default}`,backgroundColor:semanticColor.core.background.neutral.default},outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:semanticColor.core.border.neutral.default,borderRadius:3,background:semanticColor.core.background.base.default,":hover":inputFocused},wrapperFocused:inputFocused,popoverContent:{padding:0,paddingBottom:sizing.size_060,maxWidth:"initial"}});
1416
+ class InnerMathInput extends React.Component{componentDidMount(){this.mathField()?.latex(this.props.value);}componentDidUpdate(prevProps){if(prevProps.value!==this.props.value){if(this.state.focused){return}const field=this.mathField();if(!field){return}const current=field.latex();if(this.props.value!==current){field.latex(this.props.value);}}}openKeypad(){if(this.props.buttonsVisible==="never"){return}this.setState({keypadOpen:true});}closeKeypad(){this.setState({keypadOpen:false});}render(){let className=classNames$2({"perseus-math-input":true,"mq-editable-field":true,"mq-math-mode":true});const popoverContentUniqueId=v4().slice(0,8);if(this.props.className){className=className+" "+this.props.className;}return jsxRuntimeExports.jsx(View,{style:[styles$E.outerWrapper,this.state.focused&&styles$E.wrapperFocused],children:jsxRuntimeExports.jsxs("div",{style:{display:"flex",padding:1},onClick:e=>{e.stopPropagation();const mathField=this.mathField();if(!mathField){return}this.setState({cursorContext:getCursorContext(mathField)});},children:[jsxRuntimeExports.jsx("span",{className:className,ref:ref=>this.__mathFieldWrapperRef=ref,onFocus:()=>this.focus(),onBlur:()=>this.blur()}),jsxRuntimeExports.jsx(Popover,{opened:this.state.keypadOpen,dismissEnabled:true,rootBoundary:"document","aria-label":this.context.strings.mathInputTitle,"aria-describedby":`popover-content-${popoverContentUniqueId}`,onClose:()=>this.closeKeypad(),content:()=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{size:"large",id:`popover-content-${popoverContentUniqueId}`,style:a11y.srOnly,children:this.context.strings.mathInputDescription}),jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$E.popoverContent,children:jsxRuntimeExports.jsx(DesktopKeypad,{onAnalyticsEvent:this.props.onAnalyticsEvent,extraKeys:this.props.extraKeys,onClickKey:this.handleKeypadPress,cursorContext:this.state.cursorContext,convertDotToTimes:this.props.convertDotToTimes,...this.props.keypadButtonSets??mapButtonSets(this.props?.buttonSets),showDismiss:true})})]}),children:this.props.buttonsVisible==="never"?jsxRuntimeExports.jsx(MathInputIcon,{hovered:false,focused:false,active:false}):jsxRuntimeExports.jsx(Clickable,{"aria-label":this.state.keypadOpen?this.context.strings.closeKeypad:this.context.strings.openKeypad,role:"button",onClick:()=>this.state.keypadOpen?this.closeKeypad():this.openKeypad(),children:props=>jsxRuntimeExports.jsx(MathInputIcon,{active:this.state.keypadOpen,...props})})})]})})}constructor(...args){super(...args),this.__mathFieldWrapperRef=null,this.__mathField=null,this.state={focused:false,keypadOpen:this.props.buttonsVisible==="always"?true:false,cursorContext:CursorContext.NONE},this.insert=value=>{const input=this.mathField();const{locale}=this.context;const customKeyTranslator={...getKeyTranslator(locale,this.context.strings),FRAC:mathQuill=>{const contents=mathQuill.latex();mathQuill.typedText("/");if(mathQuill.latex()===contents){mathQuill.cmd("\\frac");}}};const inputModifier=customKeyTranslator[value];if(inputModifier){inputModifier(input,value);input?.focus();return}if(_(value).isFunction()){value(input);}else if(value[0]==="\\"){input?.cmd(value).focus();}else {input?.write(value).focus();}input?.focus();},this.mathField=()=>{if(!this.__mathField&&this.__mathFieldWrapperRef){const{locale}=this.context;this.__mathField=createMathField(this.__mathFieldWrapperRef,locale,this.props.mathInputStrings,baseConfig=>({...baseConfig,handlers:{edit:debounce(mathField=>{let value=mathField.latex();value=value.replace(/<>/g,"\\ne");if(convertDotToTimesByLocale(locale,this.props.convertDotToTimes)){value=value.replace(/\\cdot/g,"\\times");const left=mathField.cursor()[mathQuillInstance.L];if(left&&left.ctrlSeq==="\\cdot "){mathField.controller().backspace();mathField.cmd("\\times");}}else {value=value.replace(/\\times/g,"\\cdot");}if(this.props.value!==value){this.props.onChange(value);}this.setState({cursorContext:getCursorContext(mathField)});},100),enter:()=>{if(this.__mathFieldWrapperRef){$(this.__mathFieldWrapperRef).submit();}},upOutOf:mathField=>{mathField.typedText("^");}}}));}this.__mathField?.setAriaLabel(this.props.ariaLabel);return this.__mathField},this.focus=()=>{this.mathField()?.focus();this.setState({focused:true});},this.blur=()=>this.setState({focused:false}),this.handleKeypadPress=(key,e)=>{if(key==="DISMISS"){this.closeKeypad();return}const{locale}=this.context;const translator=getKeyTranslator(locale,this.context.strings)[key];const mathField=this.mathField();if(mathField){if(translator){translator(mathField,key);}this.setState({cursorContext:getCursorContext(mathField)});}if(e?.type==="click"){this.focus();}};}}InnerMathInput.contextType=PerseusI18nContext;InnerMathInput.defaultProps={value:"",convertDotToTimes:false};class MathInput extends React.Component{blur(){this.inputRef.current?.blur();}focus(){this.inputRef.current?.focus();}insert(value){this.inputRef.current?.insert(value);}render(){return jsxRuntimeExports.jsx(InnerMathInput,{...this.props,ref:this.inputRef,mathInputStrings:this.context.strings})}constructor(...args){super(...args),this.inputRef=React.createRef();}}MathInput.contextType=MathInputI18nContext;MathInput.defaultProps={ariaLabel:"Math input"};const MathInputIcon=({hovered,focused,active})=>{let fillColor;switch(true){case focused||active:fillColor=semanticColor.action.primary.progressive.default.foreground;break;case hovered:fillColor=semanticColor.action.primary.progressive.hover.background;break;default:fillColor=semanticColor.core.foreground.neutral.strong;break}const dynamicClass=active||focused?styles$E.iconActive:styles$E.iconInactive;return jsxRuntimeExports.jsx(View,{style:[styles$E.iconContainer,dynamicClass],children:jsxRuntimeExports.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",fill:fillColor,viewBox:"0 0 256 256",children:jsxRuntimeExports.jsx("path",{d:"M112,72a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16h64A8,8,0,0,1,112,72Zm-8,104H80V152a8,8,0,0,0-16,0v24H40a8,8,0,0,0,0,16H64v24a8,8,0,0,0,16,0V192h24a8,8,0,0,0,0-16Zm48,0h64a8,8,0,0,0,0-16H152a8,8,0,0,0,0,16Zm64,16H152a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm-61.66-90.34a8,8,0,0,0,11.32,0L184,83.31l18.34,18.35a8,8,0,0,0,11.32-11.32L195.31,72l18.35-18.34a8,8,0,0,0-11.32-11.32L184,60.69,165.66,42.34a8,8,0,0,0-11.32,11.32L172.69,72,154.34,90.34A8,8,0,0,0,154.34,101.66Z"})})})};const mapButtonSets=buttonSets=>{const keypadButtonSets={};if(!buttonSets){return keypadButtonSets}buttonSets.forEach(buttonSet=>{switch(buttonSet){case "advanced relations":keypadButtonSets.advancedRelations=true;break;case "basic relations":keypadButtonSets.basicRelations=true;break;case "basic+div":keypadButtonSets.divisionKey=true;break;case "logarithms":keypadButtonSets.logarithms=true;break;case "prealgebra":keypadButtonSets.preAlgebra=true;break;case "trig":keypadButtonSets.trigonometry=true;break;case "scientific":keypadButtonSets.scientific=true;break;}});return keypadButtonSets};const inputFocused={borderWidth:2,borderColor:semanticColor.core.border.instructive.default,margin:-1};const styles$E=StyleSheet.create({iconContainer:{display:"flex",justifyContent:"center",height:"100%",padding:sizing.size_040,borderRadius:1},iconInactive:{border:"2px solid transparent",backgroundColor:semanticColor.core.background.neutral.subtle},iconActive:{border:`2px solid ${semanticColor.core.border.knockout.default}`,backgroundColor:semanticColor.core.background.neutral.default},outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:semanticColor.core.border.neutral.default,borderRadius:3,background:semanticColor.core.background.base.default,":hover":inputFocused},wrapperFocused:inputFocused,popoverContent:{padding:0,paddingBottom:sizing.size_060,maxWidth:"initial"}});
1417
1417
 
1418
1418
  let _dependencies=null;const setDependencies=dependencies=>{_dependencies=dependencies;};const getDependencies=()=>{if(_dependencies){return _dependencies}throw new Error(["Perseus has not been provided required dependencies.","setDependencies(dependencies) must be called first.","Make sure Perseus is being imported from javascript/perseus/perseus.js."].join("\n"))};const DependenciesContext=React.createContext({analytics:{onAnalyticsEvent:async()=>{}},generateUrl:()=>{throw new Error("generateUrl dependency not provided in Perseus dependencies")},useVideo:()=>{throw new Error("useVideo dependency not provided in Perseus dependencies")}});const useDependencies=()=>{const deps=React.useContext(DependenciesContext);return deps};
1419
1419
 
@@ -1429,7 +1429,7 @@ const ApiOptions={propTypes:PropTypes.shape({isArticle:PropTypes.bool.isRequired
1429
1429
 
1430
1430
  const getPromptJSON$r=(label,userInput)=>{return {type:"expression",label,userInput:{value:userInput}}};
1431
1431
 
1432
- 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)};const defaultButtonSets=["basic","trig","prealgebra","logarithms"];const defaultOnFocus=()=>{};const defaultOnBlur=()=>{};const KeypadInputWithInterface=React.forwardRef(function KeypadInputWithInterface(props,ref){const keypadInputRef=React.useRef(null);const noopKeypadActivation=_keypadActive=>{};React.useImperativeHandle(ref,()=>({focus:(cb=noopKeypadActivation)=>keypadInputRef.current?.focus(cb),blur:()=>keypadInputRef.current?.blur(),insert:val=>{keypadInputRef.current?.mathField?.pressKey?.(val);}}));return jsxRuntimeExports.jsx(KeypadInput,{ref:keypadInputRef,...props})});const Expression=forwardRef(function Expression({apiOptions=ApiOptions.defaults,buttonSets=defaultButtonSets,times=false,onFocus=defaultOnFocus,onBlur=defaultOnBlur,userInput="",visibleLabel,ariaLabel,keypadElement,extraKeys,handleUserInput,trackInteraction,widgetId,answerForms,...rest},ref){const{strings}=usePerseusI18n();const{analytics}=useDependencies();const{setKeypadActive}=React.useContext(KeypadContext);const textareaId=useId();const inputRef=useRef(null);const rootRef=useRef(null);useEffect(()=>{analytics?.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"expression",widgetId}});if(rootRef.current){const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=rootRef.current.querySelector(selector);if(inputElement instanceof HTMLElement){inputElement.setAttribute("id",textareaId);}}},[]);const handleFocus=()=>{analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});onFocus([]);};const handleBlur=()=>{onBlur([]);};const changeAndTrack=(value,cb)=>{const normalized=normalizeTex(value);handleUserInput(normalized,cb);trackInteraction();};const mobileHandleFocus=()=>{keypadElement?.configure(getKeypadConfiguration(),()=>{if(rootRef.current){handleFocus();}});};const getKeypadConfiguration=useCallback(()=>{return {keypadType:"EXPRESSION",extraKeys:extraKeys,times:times}},[extraKeys,times]);const getFocusTarget=useCallback(()=>{if(!rootRef.current){return null}const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const element=rootRef.current.querySelector(selector);return element instanceof HTMLElement?element:null},[apiOptions.customKeypad]);useImperativeHandle(ref,()=>({focus:()=>{const targetBefore=getFocusTarget();inputRef.current?.focus?.(setKeypadActive);const targetAfter=getFocusTarget()??targetBefore??(document.activeElement instanceof HTMLElement?document.activeElement:null);if(!targetAfter){return false}if(document.activeElement!==targetAfter){targetAfter.focus();}return document.activeElement===targetAfter},focusInputPath:path=>{inputRef.current?.focus?.(setKeypadActive);},blurInputPath:path=>{if(typeof inputRef.current?.blur==="function"){inputRef.current?.blur();}},insert:keyPressed=>{inputRef.current?.insert?.(keyPressed);},getInputPaths:()=>[[]],getUserInput:()=>{return normalizeTex(userInput)},getKeypadConfiguration,getPromptJSON:()=>{return getPromptJSON$r(visibleLabel,normalizeTex(userInput))},getSerializedState:()=>{return {...rest,value:userInput,keypadConfiguration:getKeypadConfiguration(),times,buttonSets}}}),[userInput,setKeypadActive,getKeypadConfiguration,getFocusTarget,rest,visibleLabel,buttonSets,times]);const keypadConfiguration=getKeypadConfiguration();if(apiOptions.customKeypad){return jsxRuntimeExports.jsxs(View,{ref:rootRef,style:styles$C.mobileLabelInputWrapper,children:[!!visibleLabel&&jsxRuntimeExports.jsx(BodyText,{size:"small",htmlFor:textareaId,tag:"label",children:visibleLabel}),jsxRuntimeExports.jsx(KeypadInputWithInterface,{ref:inputRef,ariaLabel:ariaLabel||strings.mathInputBox,value:userInput,keypadElement:keypadElement,onChange:changeAndTrack,onFocus:mobileHandleFocus,onBlur:handleBlur})]})}return jsxRuntimeExports.jsxs(View,{ref:rootRef,style:styles$C.desktopLabelInputWrapper,children:[!!visibleLabel&&jsxRuntimeExports.jsx(BodyText,{size:"small",htmlFor:textareaId,tag:"label",children:visibleLabel}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-expression",children:jsxRuntimeExports.jsx(MathInput,{ref:inputRef,value:userInput,onChange:changeAndTrack,convertDotToTimes:times,buttonSets:buttonSets,onFocus:handleFocus,onBlur:handleBlur,ariaLabel:ariaLabel||strings.mathInputBox,extraKeys:keypadConfiguration.extraKeys,onAnalyticsEvent:analytics?.onAnalyticsEvent??(async()=>{})})})]})});const styles$C=StyleSheet.create({mobileLabelInputWrapper:{padding:"15px 4px 0"},desktopLabelInputWrapper:{margin:"5px 5px 0"}});function getUserInputFromSerializedState$i(serializedState){return normalizeTex(serializedState.value)}function getStartUserInput$j(){return ""}function getOneCorrectAnswerFromRubric$1(rubric){const correctAnswers=(rubric.answerForms||[]).filter(answerForm=>answerForm.considered==="correct");if(correctAnswers.length===0){return}return correctAnswers[0].value}function getCorrectUserInput$a(options){for(const form of options.answerForms){if(form.considered==="correct"){return form.value}}return ""}var Expression$1 = {name:"expression",displayName:"Expression / Equation",widget:Expression,version:expressionLogic.version,isLintable:true,getOneCorrectAnswerFromRubric: getOneCorrectAnswerFromRubric$1,getStartUserInput: getStartUserInput$j,getCorrectUserInput: getCorrectUserInput$a,getUserInputFromSerializedState: getUserInputFromSerializedState$i};
1432
+ 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)};const defaultButtonSets=["basic","trig","prealgebra","logarithms"];const defaultOnFocus=()=>{};const defaultOnBlur=()=>{};const KeypadInputWithInterface=React.forwardRef(function KeypadInputWithInterface(props,ref){const keypadInputRef=React.useRef(null);const noopKeypadActivation=_keypadActive=>{};React.useImperativeHandle(ref,()=>({focus:(cb=noopKeypadActivation)=>keypadInputRef.current?.focus(cb),blur:()=>keypadInputRef.current?.blur(),insert:val=>{keypadInputRef.current?.mathField?.pressKey?.(val);}}));return jsxRuntimeExports.jsx(KeypadInput,{ref:keypadInputRef,...props})});const Expression=forwardRef(function Expression({apiOptions=ApiOptions.defaults,buttonSets=defaultButtonSets,times=false,onFocus=defaultOnFocus,onBlur=defaultOnBlur,userInput="",visibleLabel,ariaLabel,keypadElement,extraKeys,handleUserInput,trackInteraction,widgetId,answerForms,...rest},ref){const{strings}=usePerseusI18n();const{analytics}=useDependencies();const{setKeypadActive}=React.useContext(KeypadContext);const textareaId=useId();const inputRef=useRef(null);const rootRef=useRef(null);useEffect(()=>{analytics?.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"expression",widgetId}});if(rootRef.current){const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=rootRef.current.querySelector(selector);if(inputElement instanceof HTMLElement){inputElement.setAttribute("id",textareaId);}}},[]);const handleFocus=()=>{analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});onFocus([]);};const handleBlur=()=>{onBlur([]);};const changeAndTrack=(value,cb)=>{const normalized=normalizeTex(value);handleUserInput(normalized,cb);trackInteraction();};const mobileHandleFocus=()=>{keypadElement?.configure(getKeypadConfiguration(),()=>{if(rootRef.current){handleFocus();}});};const getKeypadConfiguration=useCallback(()=>{return {keypadType:"EXPRESSION",extraKeys:extraKeys,times:times}},[extraKeys,times]);const getFocusTarget=useCallback(()=>{if(!rootRef.current){return null}const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const element=rootRef.current.querySelector(selector);return element instanceof HTMLElement?element:null},[apiOptions.customKeypad]);useImperativeHandle(ref,()=>({focus:()=>{const targetBefore=getFocusTarget();inputRef.current?.focus?.(setKeypadActive);const targetAfter=getFocusTarget()??targetBefore??(document.activeElement instanceof HTMLElement?document.activeElement:null);if(!targetAfter){return false}if(document.activeElement!==targetAfter){targetAfter.focus();}return document.activeElement===targetAfter},focusInputPath:path=>{inputRef.current?.focus?.(setKeypadActive);},blurInputPath:path=>{if(typeof inputRef.current?.blur==="function"){inputRef.current?.blur();}},insert:keyPressed=>{inputRef.current?.insert?.(keyPressed);},getInputPaths:()=>[[]],getUserInput:()=>{return normalizeTex(userInput)},getKeypadConfiguration,getPromptJSON:()=>{return getPromptJSON$r(visibleLabel,normalizeTex(userInput))},getSerializedState:()=>{return {...rest,value:userInput,keypadConfiguration:getKeypadConfiguration(),times,buttonSets}}}),[userInput,setKeypadActive,getKeypadConfiguration,getFocusTarget,rest,visibleLabel,buttonSets,times]);const keypadConfiguration=getKeypadConfiguration();if(apiOptions.customKeypad){return jsxRuntimeExports.jsxs(View,{ref:rootRef,style:styles$D.mobileLabelInputWrapper,children:[!!visibleLabel&&jsxRuntimeExports.jsx(BodyText,{size:"small",htmlFor:textareaId,tag:"label",children:visibleLabel}),jsxRuntimeExports.jsx(KeypadInputWithInterface,{ref:inputRef,ariaLabel:ariaLabel||strings.mathInputBox,value:userInput,keypadElement:keypadElement,onChange:changeAndTrack,onFocus:mobileHandleFocus,onBlur:handleBlur})]})}return jsxRuntimeExports.jsxs(View,{ref:rootRef,style:styles$D.desktopLabelInputWrapper,children:[!!visibleLabel&&jsxRuntimeExports.jsx(BodyText,{size:"small",htmlFor:textareaId,tag:"label",children:visibleLabel}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-expression",children:jsxRuntimeExports.jsx(MathInput,{ref:inputRef,value:userInput,onChange:changeAndTrack,convertDotToTimes:times,buttonSets:buttonSets,onFocus:handleFocus,onBlur:handleBlur,ariaLabel:ariaLabel||strings.mathInputBox,extraKeys:keypadConfiguration.extraKeys,onAnalyticsEvent:analytics?.onAnalyticsEvent??(async()=>{})})})]})});const styles$D=StyleSheet.create({mobileLabelInputWrapper:{padding:"15px 4px 0"},desktopLabelInputWrapper:{margin:"5px 5px 0"}});function getUserInputFromSerializedState$i(serializedState){return normalizeTex(serializedState.value)}function getStartUserInput$j(){return ""}function getOneCorrectAnswerFromRubric$1(rubric){const correctAnswers=(rubric.answerForms||[]).filter(answerForm=>answerForm.considered==="correct");if(correctAnswers.length===0){return}return correctAnswers[0].value}function getCorrectUserInput$a(options){for(const form of options.answerForms){if(form.considered==="correct"){return form.value}}return ""}var Expression$1 = {name:"expression",displayName:"Expression / Equation",widget:Expression,version:expressionLogic.version,isLintable:true,getOneCorrectAnswerFromRubric: getOneCorrectAnswerFromRubric$1,getStartUserInput: getStartUserInput$j,getCorrectUserInput: getCorrectUserInput$a,getUserInputFromSerializedState: getUserInputFromSerializedState$i};
1433
1433
 
1434
1434
  class SimpleKeypadInput extends React.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(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.createRef();}}SimpleKeypadInput.contextType=KeypadContext;SimpleKeypadInput.propTypes={keypadElement:keypadElementPropType,onFocus:PropTypes.func,value:PropTypes.oneOfType([PropTypes.string,PropTypes.number])};
1435
1435
 
@@ -1561,7 +1561,7 @@ const reactRootCache=new WeakMap;function render(element,container){const childr
1561
1561
 
1562
1562
  function findChildOrAdd(elem,className){const $child=$(elem).find("."+className);if($child.length===0){return $("<span>").addClass(className).appendTo($(elem))}return $child}var Tex$1 = {processMath:async function(elem,text,force,callback){const $elem=$(elem);if($elem.attr("data-math-formula")==null||force){const $texHolder=findChildOrAdd($elem,"tex-holder");if(text==null&&$elem.attr("data-math-formula")){text=$elem.attr("data-math-formula");}text=text!=null?text+"":"";text=KhanMath.cleanMath(text);$elem.attr("data-math-formula",text);const{TeX}=await getDependencies();render(React.createElement(TeX,{children:text,onRender:callback}),$texHolder[0]);}}};
1563
1563
 
1564
- const{processMath: processMath$1}=Tex$1;function polar$2(r,th){if(typeof r==="number"){r=[r,r];}th=th*Math.PI/180;return [r[0]*Math.cos(th),r[1]*Math.sin(th)]}var _bounds=/*#__PURE__*/_class_private_field_loose_key("_bounds"),_drawingTransform=/*#__PURE__*/_class_private_field_loose_key("_drawingTransform"),_labelElements=/*#__PURE__*/_class_private_field_loose_key("_labelElements"),_resizeObserver=/*#__PURE__*/_class_private_field_loose_key("_resizeObserver");let Graphie$1 = class Graphie{init(options){let scale=options.scale||[40,40];scale=typeof scale==="number"?[scale,scale]:scale;if(options.range==null){throw new PerseusError("range should be specified in graph init",Errors.Internal)}_class_private_field_loose_base(this,_bounds)[_bounds]=new GraphBounds(...options.range);_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]=new DrawingTransform(this.raphael,scale,this.bounds());const[w,h]=this.drawingTransform().canvasDimensions();$(this.el).css({width:w,height:h});this.range=options.range;this.scale=scale;this.dimensions=[w,h];this.xpixels=w;this.ypixels=h;this.isMobile=options.isMobile??false;return this}graphInit(options){options=options||{};for(const[prop,val]of entries(options)){if(!prop.match(/.*Opacity$/)&&prop!=="range"&&typeof val==="number"){options[prop]=[val,val];}if(prop==="range"||prop==="gridRange"){options[prop]=normalizeRange(options[prop]);}}const range=normalizeRange(options.range||[[-10,10],[-10,10]]);const gridRange=normalizeRange(options.gridRange||range);const scale=options.scale||[20,20];const grid=options.grid!=null?options.grid:true;const gridOpacity=options.gridOpacity||.1;const gridStep=toPair(options.gridStep||[1,1]);const axes=options.axes!=null?options.axes:true;const axisArrows=options.axisArrows||"";const axisOpacity=options.axisOpacity||1;const axisCenter=options.axisCenter||[Math.min(Math.max(range[0][0],0),range[0][1]),Math.min(Math.max(range[1][0],0),range[1][1])];const axisLabels=options.axisLabels!=null?options.axisLabels:false;const ticks=options.ticks!=null?options.ticks:true;const tickStep=options.tickStep||[2,2];const tickLen=options.tickLen||[5,5];const tickOpacity=options.tickOpacity||1;const labels=options.labels||options.labelStep||false;const labelStep=options.labelStep||[1,1];const labelOpacity=options.labelOpacity||1;let unityLabels=options.unityLabels||false;const labelFormat=options.labelFormat||function(a){return a};let xLabelFormat=options.xLabelFormat||labelFormat;let yLabelFormat=options.yLabelFormat||labelFormat;const realRange=[[range[0][0]-(range[0][0]>0?1:0),range[0][1]+(range[0][1]<0?1:0)],[range[1][0]-(range[1][0]>0?1:0),range[1][1]+(range[1][1]<0?1:0)]];if(!Array.isArray(unityLabels)){unityLabels=[unityLabels,unityLabels];}const minusIgnorer=function(lf){return function(a){return (lf(a)+"").replace(/-(\d)/g,"\\llap{-}$1")}};xLabelFormat=minusIgnorer(xLabelFormat);yLabelFormat=minusIgnorer(yLabelFormat);this.init({range:realRange,scale:scale,isMobile:options.isMobile});if(grid){this.grid(gridRange[0],gridRange[1],{stroke:options.isMobile?KhanColors.GRAY_C:"#000000",opacity:options.isMobile?1:gridOpacity,step:gridStep,strokeWidth:options.isMobile?1:2});}if(axes){if(axisArrows==="<->"||axisArrows===true){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:axisOpacity,strokeWidth:options.isMobile?1:2,arrows:"->"},function(){if(range[1][0]<0&&range[1][1]>0){thisGraphie.path([axisCenter,[gridRange[0][0],axisCenter[1]]]);thisGraphie.path([axisCenter,[gridRange[0][1],axisCenter[1]]]);}if(range[0][0]<0&&range[0][1]>0){thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][0]]]);thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][1]]]);}});}else if(axisArrows==="->"||axisArrows===""){const thisGraphie=this;this.style({stroke:"#000000",opacity:axisOpacity,strokeWidth:2,arrows:axisArrows},function(){thisGraphie.path([[gridRange[0][0],axisCenter[1]],[gridRange[0][1],axisCenter[1]]]);thisGraphie.path([[axisCenter[0],gridRange[1][0]],[axisCenter[0],gridRange[1][1]]]);});}if(axisLabels&&axisLabels.length===2){this.label([gridRange[0][1],axisCenter[1]],axisLabels[0],"right");this.label([axisCenter[0],gridRange[1][1]],axisLabels[1],"above");}}if(ticks){const halfWidthTicks=options.isMobile;const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:tickOpacity,strokeWidth:1},()=>{let step=gridStep[0]*tickStep[0];let len=tickLen[0]/scale[1];let start=gridRange[0][0];let stop=gridRange[0][1];if(range[1][0]<0&&range[1][1]>0){for(let x=step+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}for(let x=-step+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}}step=gridStep[1]*tickStep[1];len=tickLen[1]/scale[0];start=gridRange[1][0];stop=gridRange[1][1];if(range[0][0]<0&&range[0][1]>0){for(let y=step+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}for(let y=-step+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}}});}if(labels){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:labelOpacity},function(){let step=gridStep[0]*tickStep[0]*labelStep[0];let start=gridRange[0][0];let stop=gridRange[0][1];const xAxisPosition=axisCenter[0]<0?"above":"below";const yAxisPosition=axisCenter[0]<0?"right":"left";const xShowZero=axisCenter[0]===0&&axisCenter[1]!==0;const yShowZero=axisCenter[0]!==0&&axisCenter[1]===0;const axisOffCenter=axisCenter[0]!==0||axisCenter[1]!==0;const showUnityX=unityLabels[0]||axisOffCenter;const showUnityY=unityLabels[1]||axisOffCenter;for(let x=(xShowZero?0:step)+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}for(let x=-step*(showUnityX?1:2)+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}step=gridStep[1]*tickStep[1]*labelStep[1];start=gridRange[1][0];stop=gridRange[1][1];for(let y=(yShowZero?0:step)+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}for(let y=-step*(showUnityY?1:2)+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}});}}drawingTransform(){if(_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]==null){throw new Error("Can't get drawingTransform of an uninitialized Graphie")}return _class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]}bounds(){if(_class_private_field_loose_base(this,_bounds)[_bounds]==null){throw new Error("Can't get bounds of an uninitialized Graphie")}return _class_private_field_loose_base(this,_bounds)[_bounds]}style(attrs,fn){const processed=this.processAttributes(attrs);if(typeof fn==="function"){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...processed};const result=fn.call(this);this.currentStyle=oldStyle;return result}Object.assign(this.currentStyle,processed);}grid(xr,yr,style){return this.withStyle(style,()=>{const step=this.currentStyle.step||[1,1];const set=this.raphael.set();let x=step[0]*Math.ceil(xr[0]/step[0]);for(;x<=xr[1];x+=step[0]){set.push(this.line([x,yr[0]],[x,yr[1]]));}let y=step[1]*Math.ceil(yr[0]/step[1]);for(;y<=yr[1];y+=step[1]){set.push(this.line([xr[0],y],[xr[1],y]));}return set})}arc(center,radius,startAngle,endAngle,sector,style){return this.withStyle(style,()=>{startAngle=(startAngle%360+360)%360;endAngle=(endAngle%360+360)%360;const cent=this.scalePoint(center);const radii=this.scaleVector(radius);const startVector=polar$2(radius,startAngle);const endVector=polar$2(radius,endAngle);const round=x=>number.round(x,6);const startPoint=this.scalePoint([round(center[0]+startVector[0]),round(center[1]+startVector[1])]);const endPoint=this.scalePoint([round(center[0]+endVector[0]),round(center[1]+endVector[1])]);const largeAngle=((endAngle-startAngle)%360+360)%360>180;return this.raphael.path("M"+startPoint.join(" ")+"A"+radii.join(" ")+" 0 "+(largeAngle?1:0)+" 0 "+endPoint.join(" ")+(sector?"L"+cent.join(" ")+"z":""))})}circle(center,radius,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center),...this.scaleVector([radius,radius])))}rect(x,y,width,height,style){return this.withStyle(style,()=>{const corner=this.scalePoint([x,y+height]);const dims=this.scaleVector([width,height]);const elem=this.raphael.rect(...corner.concat(dims));if(this.isMobile){elem.node.style.shapeRendering="crispEdges";}return elem})}ellipse(center,radii,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center).concat(this.scaleVector(radii))))}fixedEllipse(center,radii,maxScale,padding,style){return this.withStyle(style,()=>{const scaledPoint=this.scalePoint(center);const scaledRadii=this.scaleVector(radii);const width=2*scaledRadii[0]*maxScale+padding;const height=2*scaledRadii[1]*maxScale+padding;const left=scaledPoint[0]-width/2;const top=scaledPoint[1]-height/2;const wrapper=document.createElement("div");$(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px"});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.ellipse(width/2,height/2,scaledRadii[0],scaledRadii[1]);return {wrapper:wrapper,visibleShape:visibleShape}})}unstyledPath(points){const p=this.raphael.path(this.svgPath(points));p.graphiePath=points;return p}path(points,style){return this.withStyle(style,()=>{return this.unstyledPath(points)})}fixedPath(points,center,createPath){points=points.map(this.scalePoint);center=center?this.scalePoint(center):null;createPath=createPath||this.svgPath;const xs=points.map(p=>p[0]);const ys=points.map(p=>p[1]);const pathLeft=Math.min(...xs);const pathRight=Math.max(...xs);const pathTop=Math.min(...ys);const pathBottom=Math.max(...ys);const padding=[4,4];const topLeftOfBoundingBox=[pathLeft,pathTop];points=points.map(function(point){return vector$3.add(vector$3.subtract(point,topLeftOfBoundingBox),vector$3.scale(padding,.5))});const width=pathRight-pathLeft+padding[0];const height=pathBottom-pathTop+padding[1];const left=topLeftOfBoundingBox[0]-padding[0]/2;const top=topLeftOfBoundingBox[1]-padding[1]/2;const wrapper=document.createElement("div");$(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:center?width/2+center[0]+"px "+(height/2+center[1])+"px":null});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.path(createPath(points));return {wrapper:wrapper,visibleShape:visibleShape}}scaledPath(points,style){return this.withStyle(style,()=>{const p=this.raphael.path(this.svgPath(points,true));p.graphiePath=points;return p})}line(start,end,style){return this.withStyle(style,()=>{const l=this.unstyledPath([start,end]);if(this.isMobile){l.node.style.shapeRendering="crispEdges";}return l})}parabola(a,b,c,style){return this.withStyle(style,()=>this.raphael.path(this.svgParabolaPath(a,b,c)))}fixedLine(start,end,thickness){const padding=[thickness,thickness];start=this.scalePoint(start);end=this.scalePoint(end);const extraOffset=[Math.min(start[0],end[0]),Math.min(start[1],end[1])];start=vector$3.add(vector$3.subtract(start,extraOffset),vector$3.scale(padding,.5));end=vector$3.add(vector$3.subtract(end,extraOffset),vector$3.scale(padding,.5));const left=extraOffset[0]-padding[0]/2;const top=extraOffset[1]-padding[1]/2;const width=Math.abs(start[0]-end[0])+padding[0];const height=Math.abs(start[1]-end[1])+padding[1];const wrapper=document.createElement("div");$(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:start[0]+"px "+start[1]+"px"});const localRaphael=Raphael$1(wrapper,width,height);const path="M"+start[0]+" "+start[1]+" "+"L"+end[0]+" "+end[1];const visibleShape=localRaphael.path(path);visibleShape.graphiePath=[start,end];return {wrapper:wrapper,visibleShape:visibleShape}}sinusoid(a,b,c,d,style){return this.withStyle(style,()=>this.raphael.path(this.svgSinusoidPath(a,b,c,d)))}plotParametric(fn,range,style){return this.withStyle(style,()=>{const clip=xy=>{if(Math.abs(xy[1])>5e5){return [xy[0],Math.min(Math.max(xy[1],-5e5),5e5)]}return xy};const clippedFn=x=>clip(fn(x));const min=range[0];const max=range[1];let step=(max-min)/(this.currentStyle["plot-points"]||800);if(step===0){step=1;}const paths=this.raphael.set();let points=[];let lastY=clippedFn(min)[1];for(let t=min;t<=max;t+=step){const point=clippedFn(t);const y=point[1];if(y>0!==lastY>0&&Math.abs(y-lastY)>2*this.drawingTransform().pixelsPerUnitY()||isNaN(y)){paths.push(this.unstyledPath(points));points=[];}else {points.push(point);}lastY=y;}paths.push(this.unstyledPath(points));return paths})}plot(fn,range,style){return this.withStyle(style,()=>{const min=range[0];const max=range[1];if(!this.currentStyle["plot-points"]){this.currentStyle["plot-points"]=2*(max-min)*this.drawingTransform().pixelsPerUnitX();}const parametricFn=x=>[x,fn(x)];return this.plotParametric(parametricFn,range)})}withStyle(style,fn){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...this.processAttributes(style)};const result=this.postprocessDrawingResult(fn());this.currentStyle=oldStyle;return result}postprocessDrawingResult(result){const type=result.constructor.prototype;if(type===Raphael$1.el||type===Raphael$1.st){result.attr(this.currentStyle);if(this.currentStyle.arrows){result=this.addArrowheads(result);}}else if(result instanceof $){result.css({...this.currentStyle,...SVG_SPECIFIC_STYLE_MASK});}return result}addArrowheads(path){const type=path.constructor.prototype;if(type===Raphael$1.el){if(path.type==="path"&&typeof path.arrowheadsDrawn==="undefined"){const w=path.attr("stroke-width");const s=.6+.4*w;const l=path.getTotalLength();const set=this.raphael.set();const head=this.raphael.path(this.isMobile?"M-4,4 C-4,4 -0.25,0 -0.25,0 C-0.25,0 -4,-4 -4,-4":"M-3 4 C-2.75 2.5 0 0.25 0.75 0C0 -0.25 -2.75 -2.5 -3 -4");const end=path.getPointAtLength(l-.4);const almostTheEnd=path.getPointAtLength(l-.75*s);const angle=Math.atan2(end.y-almostTheEnd.y,end.x-almostTheEnd.x)*180/Math.PI;const attrs=path.attr();delete attrs.path;let subpath=path.getSubpath(0,l-.75*s);subpath=this.raphael.path(subpath).attr(attrs);subpath.arrowheadsDrawn=true;path.remove();head.rotate(angle,this.isMobile?1e-5:.75,0).scale(s,s,.75,0).translate(almostTheEnd.x,almostTheEnd.y).attr(attrs).attr({"stroke-linejoin":"round","stroke-linecap":"round"});head.arrowheadsDrawn=true;set.push(subpath);set.push(head);return set}}else if(type===Raphael$1.st){for(let i=0,l=path.items.length;i<l;i++){this.addArrowheads(path.items[i]);}}return path}processAttributes(attrs){const transformers={scale:scale=>{this.drawingTransform().setScale(scale);},clipRect:pair=>{const point=pair[0];const size=pair[1];point[1]+=size[1];return {"clip-rect":this.scalePoint(point).concat(this.scaleVector(size)).join(" ")}},strokeWidth:function(val){return {"stroke-width":parseFloat(val)}},rx:val=>{return {rx:this.scaleVector([val,0])[0]}},ry:val=>{return {ry:this.scaleVector([0,val])[1]}},r:val=>{const scaled=this.scaleVector([val,val]);return {rx:scaled[0],ry:scaled[1]}}};const processed={};Object.entries(attrs||{}).forEach(function([key,value]){const transformer=transformers[key];if(typeof transformer==="function"){Object.assign(processed,transformer(value));}else {const dasherized=String(key).replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase();processed[dasherized]=value;}});return processed}addMouseLayer(options){const localOptions={allowScratchpad:false,...options};const mouselayerZIndex=2;this.mouselayer=Raphael$1(this.el,this.xpixels,this.ypixels);$(this.mouselayer.canvas).css("z-index",mouselayerZIndex);if(localOptions.onClick||localOptions.onMouseDown||localOptions.onMouseMove||localOptions.onMouseOver||localOptions.onMouseOut){const canvasClickTarget=this.mouselayer.rect(0,0,this.xpixels,this.ypixels).attr({fill:"#000",opacity:0});let isClickingCanvas=false;$(this.mouselayer.canvas).on("vmousedown",e=>{if(e.target===canvasClickTarget[0]){if(localOptions.onMouseDown){localOptions.onMouseDown(this.getMouseCoord(e));}isClickingCanvas=true;if(localOptions.onMouseMove){const handler=localOptions.onMouseMove;$(document).bind("vmousemove.mouseLayer",e=>{if(isClickingCanvas){e.preventDefault();handler(this.getMouseCoord(e));}});}$(document).bind("vmouseup.mouseLayer",e=>{$(document).unbind(".mouseLayer");if(isClickingCanvas&&localOptions.onClick){localOptions.onClick(this.getMouseCoord(e));}isClickingCanvas=false;});}});if(localOptions.onMouseOver){const handler=localOptions.onMouseOver;$(this.mouselayer.canvas).on("vmouseover",e=>{handler(this.getMouseCoord(e));});}if(localOptions.onMouseOut){const handler=localOptions.onMouseOut;$(this.mouselayer.canvas).on("vmouseout",e=>{handler(this.getMouseCoord(e));});}}this._mouselayerWrapper=document.createElement("div");$(this._mouselayerWrapper).css({position:"absolute",left:0,top:0,zIndex:mouselayerZIndex});this._visiblelayerWrapper=document.createElement("div");$(this._visiblelayerWrapper).css({position:"absolute",left:0,top:0});const el=this.el;el.appendChild(this._visiblelayerWrapper);el.appendChild(this._mouselayerWrapper);this.addToMouseLayerWrapper=el=>{this._mouselayerWrapper?.appendChild(el);};this.addToVisibleLayerWrapper=el=>{this._visiblelayerWrapper?.appendChild(el);};}addToMouseLayerWrapper(el){throw new Error("addToMouseLayerWrapper is not ready. Call addMouseLayer() first.")}addToVisibleLayerWrapper(el){throw new Error("addToVisibleLayerWrapper is not ready. Call addMouseLayer() first.")}getMousePx(event){const offset=$(this.el).offset();const mouseX=event.pageX-offset.left;const mouseY=event.pageY-offset.top;return [mouseX,mouseY]}getMouseCoord(event){return this.unscalePoint(this.getMousePx(event))}_ensureResizeObserver(){if(_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]!=null||typeof ResizeObserver==="undefined"){return}_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=new ResizeObserver(()=>{this._recalculateLabels();});_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver].observe(this.el);}_recalculateLabels(){_class_private_field_loose_base(this,_labelElements)[_labelElements].forEach(span=>{const originalSize=$(span).data("originalLabelSize");if(originalSize!=null){setLabelMargins(span,originalSize);}});}cleanup(){_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]?.disconnect();_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;_class_private_field_loose_base(this,_labelElements)[_labelElements].clear();}constructor(el){Object.defineProperty(this,_bounds,{writable:true,value:void 0});Object.defineProperty(this,_drawingTransform,{writable:true,value:void 0});Object.defineProperty(this,_labelElements,{writable:true,value:void 0});Object.defineProperty(this,_resizeObserver,{writable:true,value:void 0});_class_private_field_loose_base(this,_labelElements)[_labelElements]=new Set;_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;this.isMobile=false;this.currentStyle={"stroke-width":2,fill:"none"};this.label=(point,text,direction,arg4,arg5)=>{const style=typeof arg4==="object"?arg4:arg5;const latex=typeof arg4==="boolean"?arg4:true;return this.withStyle(style,()=>{const $span=$("<span>").addClass("graphie-label");const pad=this.currentStyle["label-distance"];$span.css({position:"absolute",padding:(pad!=null?pad:7)+"px",color:"black"}).data("labelDirection",direction).appendTo(this.el);$span.setPosition=point=>{const scaledPoint=this.scalePoint(point);$span.css({left:scaledPoint[0],top:scaledPoint[1]});};$span.setPosition(point);$span.css({"font-size":this.currentStyle["font-size"]});const span=$span[0];_class_private_field_loose_base(this,_labelElements)[_labelElements].add(span);$span.processMath=function(math,force){processMath$1(span,math,force,function(){const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);});};$span.processText=function(text){$span.html(text);const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);};if(latex){$span.processMath(text,false);}else {$span.processText(text);}this._ensureResizeObserver();return $span})};this.svgPath=(points,alreadyScaled)=>{return points.map((point,i)=>{if(point===true){return "z"}const scaled=alreadyScaled?point:this.scalePoint(point);return (i===0?"M":"L")+KhanMath.bound(scaled[0])+" "+KhanMath.bound(scaled[1])}).join("")};this.svgParabolaPath=(a,b,c)=>{const computeParabola=function(x){return (a*x+b)*x+c};if(a===0){const points=[[this.bounds().xMin,computeParabola(this.bounds().xMin)],[this.bounds().xMax,computeParabola(this.bounds().xMax)]];return this.svgPath(points)}const xVertex=-b/(2*a);const distToEdge=Math.max(Math.abs(xVertex-this.bounds().xMin),Math.abs(xVertex-this.bounds().xMax));const xPoint=xVertex+distToEdge;const vertex=[xVertex,computeParabola(xVertex)];const point=[xPoint,computeParabola(xPoint)];const control=[vertex[0],vertex[1]-(point[1]-vertex[1])];const dx=Math.abs(vertex[0]-point[0]);const left=[vertex[0]-dx,point[1]];const right=[vertex[0]+dx,point[1]];const points=[left,control,right].map(this.scalePoint);const values=points.flat().map(KhanMath.bound);return "M"+values[0]+","+values[1]+" Q"+values[2]+","+values[3]+" "+values[4]+","+values[5]};this.svgSinusoidPath=(a,b,c,d)=>{const quarterPeriod=Math.abs(Math.PI/(2*b));const computeSine=function(x){return a*Math.sin(b*x-c)+d};const computeDerivative=function(x){return a*b*Math.cos(c-b*x)};const coordsForOffset=(initial,i)=>{const x0=initial+quarterPeriod*i;const x1=x0+quarterPeriod;const xCoords=[x0,x0*2/3+x1*1/3,x0*1/3+x1*2/3,x1];const yCoords=[computeSine(x0),computeSine(x0)+computeDerivative(x0)*(x1-x0)/3,computeSine(x1)-computeDerivative(x1)*(x1-x0)/3,computeSine(x1)];const points=vector$3.zip(xCoords,yCoords);return points.map(this.scalePoint)};const extent=this.bounds().width();const numQuarterPeriods=Math.ceil(extent/quarterPeriod)+1;let initial=c/b;const distToEdge=initial-this.bounds().xMin;initial-=quarterPeriod*Math.ceil(distToEdge/quarterPeriod);let coords=coordsForOffset(initial,0);let path="M"+coords[0][0]+","+coords[0][1]+" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];for(let i=1;i<numQuarterPeriods;i++){coords=coordsForOffset(initial,i);path+=" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];}return path};this.scalePoint=point=>{return this.drawingTransform().scalePoint(point)};this.scaleVector=point=>{return this.drawingTransform().scaleVector(point)};this.unscalePoint=point=>{return this.drawingTransform().unscalePoint(point)};this.unscaleVector=point=>{return this.drawingTransform().unscaleVector(point)};this.el=el;$(el).css("position","relative");this.raphael=Raphael$1(el);$(el).attr("aria-hidden","true");$(el).children("div").css("position","absolute");}};const labelDirections={center:[-0.5,-0.5],above:[-0.5,-1],"above right":[0,-1],right:[0,-0.5],"below right":[0,0],below:[-0.5,0],"below left":[-1,0],left:[-1,-0.5],"above left":[-1,-1]};function normalizeRange(range){function normalizeInterval(magnitude){if(typeof magnitude==="number"){return [-magnitude,magnitude]}else {return magnitude}}function getXAndYRanges(range){if(Array.isArray(range)){return range}else {return [range,range]}}if(range==null){return range}const[xRange,yRange]=getXAndYRanges(range);return [normalizeInterval(xRange),normalizeInterval(yRange)]}function toPair(x){if(Array.isArray(x)){return x}return [x,x]}const SVG_SPECIFIC_STYLE_MASK={"stroke-width":null};const setLabelMargins=function(span,size){if(document.fonts?.status==="loading"){document.fonts.ready.then(()=>setLabelMargins(span,size));return}const $span=$(span);const direction=$span.data("labelDirection");let[width,height]=size;if(width===0&&height===0){[width,height]=[1,1];Log.log("Label size was 0x0 in graphie.js; using 1x1 instead");}$span.css("visibility","");if(typeof direction==="number"){const x=Math.cos(direction);const y=Math.sin(direction);const scale=Math.min(width/2/Math.abs(x),height/2/Math.abs(y));$span.css({marginLeft:-width/2+x*scale,marginTop:-height/2-y*scale});if($span.data("originalLabelSize")==null){$span.data("originalLabelSize",[width,height]);}}else {const $svgImage=$span.closest(".svg-image");const $graphie=$span.closest(".graphie");const $container=$svgImage.length>0?$svgImage:$graphie;$container.css("line-height","normal");if($span.data("originalLabelSize")==null){height=span.scrollHeight;$span.data("originalLabelSize",[width,height]);}const widthValues=$container.css(["max-width","width"])??{"max-width":"0px"};const expectedWidth=widthValues["max-width"]!=="none"?widthValues["max-width"]:widthValues["width"];let scale=($container.width()??0)/parseInt(expectedWidth.replace(/px$/,""));if(isNaN(scale)){scale=1;}else if(scale===0){scale=1;}let rawPadding;const storedPadding=$span.data("originalPadding");if(storedPadding!=null){rawPadding=storedPadding;}else {const padding=$span.css("padding")??"0px";const currentPadding=padding!=="none"?padding:"0px";rawPadding=parseInt(currentPadding.replace(/px$/,""));$span.data("originalPadding",rawPadding);}let normalizedWidth=width;let normalizedHeight=height;const imageScale=Number($container.attr("data-scale"));const hasValidImageScale=!Number.isNaN(imageScale)&&imageScale>=0;if(hasValidImageScale){scale=scale*imageScale;const totalPadding=2*rawPadding;normalizedWidth=(width-totalPadding)/imageScale+totalPadding;normalizedHeight=(height-totalPadding)/imageScale+totalPadding;}const newPadding=rawPadding*scale;const multipliers=labelDirections[direction||"center"];const styling={marginLeft:normalizedWidth*multipliers[0]*scale,marginTop:normalizedHeight*multipliers[1]*scale,padding:`${newPadding}px`,fontSize:`${scale*100}%`};$span.css(styling);}};const GraphUtils={Graphie: Graphie$1,createGraphie:function(el){return new Graphie$1(el)},unscaledSvgPath:function(points){if(points[0]===true){return ""}return points.map(function(point,i){if(point===true){return "z"}return (i===0?"M":"L")+point[0]+" "+point[1]}).join("")},getDistance:function(point1,point2){return point.distanceToPoint(point1,point2)},findAngleDeprecated:function(point1,point2,vertex){if(vertex===undefined){const x=point1[0]-point2[0];const y=point1[1]-point2[1];if(!x&&!y){return 0}return (180+Math.atan2(-y,-x)*180/Math.PI+360)%360}return GraphUtils.findAngleDeprecated(point1,vertex)-GraphUtils.findAngleDeprecated(point2,vertex)},graphs:{}};
1564
+ const{processMath: processMath$1}=Tex$1;function polar$2(r,th){if(typeof r==="number"){r=[r,r];}th=th*Math.PI/180;return [r[0]*Math.cos(th),r[1]*Math.sin(th)]}var _bounds=/*#__PURE__*/_class_private_field_loose_key("_bounds"),_drawingTransform=/*#__PURE__*/_class_private_field_loose_key("_drawingTransform"),_labelElements=/*#__PURE__*/_class_private_field_loose_key("_labelElements"),_resizeObserver=/*#__PURE__*/_class_private_field_loose_key("_resizeObserver");let Graphie$1 = class Graphie{init(options){let scale=options.scale||[40,40];scale=typeof scale==="number"?[scale,scale]:scale;if(options.range==null){throw new PerseusError("range should be specified in graph init",Errors.Internal)}_class_private_field_loose_base(this,_bounds)[_bounds]=new GraphBounds(...options.range);_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]=new DrawingTransform(this.raphael,scale,this.bounds());const[w,h]=this.drawingTransform().canvasDimensions();$(this.el).css({width:w,height:h});this.range=options.range;this.scale=scale;this.dimensions=[w,h];this.xpixels=w;this.ypixels=h;this.isMobile=options.isMobile??false;return this}graphInit(options){options=options||{};for(const[prop,val]of entries(options)){if(!prop.match(/.*Opacity$/)&&prop!=="range"&&typeof val==="number"){options[prop]=[val,val];}if(prop==="range"||prop==="gridRange"){options[prop]=normalizeRange(options[prop]);}}const range=normalizeRange(options.range||[[-10,10],[-10,10]]);const gridRange=normalizeRange(options.gridRange||range);const scale=options.scale||[20,20];const grid=options.grid!=null?options.grid:true;const gridOpacity=options.gridOpacity||.1;const gridStep=toPair(options.gridStep||[1,1]);const axes=options.axes!=null?options.axes:true;const axisArrows=options.axisArrows||"";const axisOpacity=options.axisOpacity||1;const axisCenter=options.axisCenter||[Math.min(Math.max(range[0][0],0),range[0][1]),Math.min(Math.max(range[1][0],0),range[1][1])];const axisLabels=options.axisLabels!=null?options.axisLabels:false;const ticks=options.ticks!=null?options.ticks:true;const tickStep=options.tickStep||[2,2];const tickLen=options.tickLen||[5,5];const tickOpacity=options.tickOpacity||1;const labels=options.labels||options.labelStep||false;const labelStep=options.labelStep||[1,1];const labelOpacity=options.labelOpacity||1;let unityLabels=options.unityLabels||false;const labelFormat=options.labelFormat||function(a){return a};let xLabelFormat=options.xLabelFormat||labelFormat;let yLabelFormat=options.yLabelFormat||labelFormat;const realRange=[[range[0][0]-(range[0][0]>0?1:0),range[0][1]+(range[0][1]<0?1:0)],[range[1][0]-(range[1][0]>0?1:0),range[1][1]+(range[1][1]<0?1:0)]];if(!Array.isArray(unityLabels)){unityLabels=[unityLabels,unityLabels];}const minusIgnorer=function(lf){return function(a){return (lf(a)+"").replace(/-(\d)/g,"\\llap{-}$1")}};xLabelFormat=minusIgnorer(xLabelFormat);yLabelFormat=minusIgnorer(yLabelFormat);this.init({range:realRange,scale:scale,isMobile:options.isMobile});if(grid){this.grid(gridRange[0],gridRange[1],{stroke:options.isMobile?KhanColors.GRAY_C:"#000000",opacity:options.isMobile?1:gridOpacity,step:gridStep,strokeWidth:options.isMobile?1:2});}if(axes){if(axisArrows==="<->"||axisArrows===true){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:axisOpacity,strokeWidth:options.isMobile?1:2,arrows:"->"},function(){if(range[1][0]<0&&range[1][1]>0){thisGraphie.path([axisCenter,[gridRange[0][0],axisCenter[1]]]);thisGraphie.path([axisCenter,[gridRange[0][1],axisCenter[1]]]);}if(range[0][0]<0&&range[0][1]>0){thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][0]]]);thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][1]]]);}});}else if(axisArrows==="->"||axisArrows===""){const thisGraphie=this;this.style({stroke:"#000000",opacity:axisOpacity,strokeWidth:2,arrows:axisArrows},function(){thisGraphie.path([[gridRange[0][0],axisCenter[1]],[gridRange[0][1],axisCenter[1]]]);thisGraphie.path([[axisCenter[0],gridRange[1][0]],[axisCenter[0],gridRange[1][1]]]);});}if(axisLabels&&axisLabels.length===2){this.label([gridRange[0][1],axisCenter[1]],axisLabels[0],"right");this.label([axisCenter[0],gridRange[1][1]],axisLabels[1],"above");}}if(ticks){const halfWidthTicks=options.isMobile;const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:tickOpacity,strokeWidth:1},()=>{let step=gridStep[0]*tickStep[0];let len=tickLen[0]/scale[1];let start=gridRange[0][0];let stop=gridRange[0][1];if(range[1][0]<0&&range[1][1]>0){for(let x=step+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}for(let x=-step+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}}step=gridStep[1]*tickStep[1];len=tickLen[1]/scale[0];start=gridRange[1][0];stop=gridRange[1][1];if(range[0][0]<0&&range[0][1]>0){for(let y=step+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}for(let y=-step+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}}});}if(labels){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:labelOpacity},function(){let step=gridStep[0]*tickStep[0]*labelStep[0];let start=gridRange[0][0];let stop=gridRange[0][1];const xAxisPosition=axisCenter[0]<0?"above":"below";const yAxisPosition=axisCenter[0]<0?"right":"left";const xShowZero=axisCenter[0]===0&&axisCenter[1]!==0;const yShowZero=axisCenter[0]!==0&&axisCenter[1]===0;const axisOffCenter=axisCenter[0]!==0||axisCenter[1]!==0;const showUnityX=unityLabels[0]||axisOffCenter;const showUnityY=unityLabels[1]||axisOffCenter;for(let x=(xShowZero?0:step)+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}for(let x=-step*(showUnityX?1:2)+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}step=gridStep[1]*tickStep[1]*labelStep[1];start=gridRange[1][0];stop=gridRange[1][1];for(let y=(yShowZero?0:step)+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}for(let y=-step*(showUnityY?1:2)+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}});}}drawingTransform(){if(_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]==null){throw new Error("Can't get drawingTransform of an uninitialized Graphie")}return _class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]}bounds(){if(_class_private_field_loose_base(this,_bounds)[_bounds]==null){throw new Error("Can't get bounds of an uninitialized Graphie")}return _class_private_field_loose_base(this,_bounds)[_bounds]}style(attrs,fn){const processed=this.processAttributes(attrs);if(typeof fn==="function"){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...processed};const result=fn.call(this);this.currentStyle=oldStyle;return result}Object.assign(this.currentStyle,processed);}grid(xr,yr,style){return this.withStyle(style,()=>{const step=this.currentStyle.step||[1,1];const set=this.raphael.set();let x=step[0]*Math.ceil(xr[0]/step[0]);for(;x<=xr[1];x+=step[0]){set.push(this.line([x,yr[0]],[x,yr[1]]));}let y=step[1]*Math.ceil(yr[0]/step[1]);for(;y<=yr[1];y+=step[1]){set.push(this.line([xr[0],y],[xr[1],y]));}return set})}arc(center,radius,startAngle,endAngle,sector,style){return this.withStyle(style,()=>{startAngle=(startAngle%360+360)%360;endAngle=(endAngle%360+360)%360;const cent=this.scalePoint(center);const radii=this.scaleVector(radius);const startVector=polar$2(radius,startAngle);const endVector=polar$2(radius,endAngle);const round=x=>number.round(x,6);const startPoint=this.scalePoint([round(center[0]+startVector[0]),round(center[1]+startVector[1])]);const endPoint=this.scalePoint([round(center[0]+endVector[0]),round(center[1]+endVector[1])]);const largeAngle=((endAngle-startAngle)%360+360)%360>180;return this.raphael.path("M"+startPoint.join(" ")+"A"+radii.join(" ")+" 0 "+(largeAngle?1:0)+" 0 "+endPoint.join(" ")+(sector?"L"+cent.join(" ")+"z":""))})}circle(center,radius,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center),...this.scaleVector([radius,radius])))}rect(x,y,width,height,style){return this.withStyle(style,()=>{const corner=this.scalePoint([x,y+height]);const dims=this.scaleVector([width,height]);const elem=this.raphael.rect(...corner.concat(dims));if(this.isMobile){elem.node.style.shapeRendering="crispEdges";}return elem})}ellipse(center,radii,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center).concat(this.scaleVector(radii))))}fixedEllipse(center,radii,maxScale,padding,style){return this.withStyle(style,()=>{const scaledPoint=this.scalePoint(center);const scaledRadii=this.scaleVector(radii);const width=2*scaledRadii[0]*maxScale+padding;const height=2*scaledRadii[1]*maxScale+padding;const left=scaledPoint[0]-width/2;const top=scaledPoint[1]-height/2;const wrapper=document.createElement("div");$(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px"});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.ellipse(width/2,height/2,scaledRadii[0],scaledRadii[1]);return {wrapper:wrapper,visibleShape:visibleShape}})}unstyledPath(points){const p=this.raphael.path(this.svgPath(points));p.graphiePath=points;return p}path(points,style){return this.withStyle(style,()=>{return this.unstyledPath(points)})}fixedPath(points,center,createPath){points=points.map(this.scalePoint);center=center?this.scalePoint(center):null;createPath=createPath||this.svgPath;const xs=points.map(p=>p[0]);const ys=points.map(p=>p[1]);const pathLeft=Math.min(...xs);const pathRight=Math.max(...xs);const pathTop=Math.min(...ys);const pathBottom=Math.max(...ys);const padding=[4,4];const topLeftOfBoundingBox=[pathLeft,pathTop];points=points.map(function(point){return vector$3.add(vector$3.subtract(point,topLeftOfBoundingBox),vector$3.scale(padding,.5))});const width=pathRight-pathLeft+padding[0];const height=pathBottom-pathTop+padding[1];const left=topLeftOfBoundingBox[0]-padding[0]/2;const top=topLeftOfBoundingBox[1]-padding[1]/2;const wrapper=document.createElement("div");$(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:center?width/2+center[0]+"px "+(height/2+center[1])+"px":null});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.path(createPath(points));return {wrapper:wrapper,visibleShape:visibleShape}}scaledPath(points,style){return this.withStyle(style,()=>{const p=this.raphael.path(this.svgPath(points,true));p.graphiePath=points;return p})}line(start,end,style){return this.withStyle(style,()=>{const l=this.unstyledPath([start,end]);if(this.isMobile){l.node.style.shapeRendering="crispEdges";}return l})}parabola(a,b,c,style){return this.withStyle(style,()=>this.raphael.path(this.svgParabolaPath(a,b,c)))}fixedLine(start,end,thickness){const padding=[thickness,thickness];start=this.scalePoint(start);end=this.scalePoint(end);const extraOffset=[Math.min(start[0],end[0]),Math.min(start[1],end[1])];start=vector$3.add(vector$3.subtract(start,extraOffset),vector$3.scale(padding,.5));end=vector$3.add(vector$3.subtract(end,extraOffset),vector$3.scale(padding,.5));const left=extraOffset[0]-padding[0]/2;const top=extraOffset[1]-padding[1]/2;const width=Math.abs(start[0]-end[0])+padding[0];const height=Math.abs(start[1]-end[1])+padding[1];const wrapper=document.createElement("div");$(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:start[0]+"px "+start[1]+"px"});const localRaphael=Raphael$1(wrapper,width,height);const path="M"+start[0]+" "+start[1]+" "+"L"+end[0]+" "+end[1];const visibleShape=localRaphael.path(path);visibleShape.graphiePath=[start,end];return {wrapper:wrapper,visibleShape:visibleShape}}sinusoid(a,b,c,d,style){return this.withStyle(style,()=>this.raphael.path(this.svgSinusoidPath(a,b,c,d)))}plotParametric(fn,range,style){return this.withStyle(style,()=>{const clip=xy=>{if(Math.abs(xy[1])>5e5){return [xy[0],Math.min(Math.max(xy[1],-5e5),5e5)]}return xy};const clippedFn=x=>clip(fn(x));const min=range[0];const max=range[1];let step=(max-min)/(this.currentStyle["plot-points"]||800);if(step===0){step=1;}const paths=this.raphael.set();let points=[];let lastY=clippedFn(min)[1];for(let t=min;t<=max;t+=step){const point=clippedFn(t);const y=point[1];if(y>0!==lastY>0&&Math.abs(y-lastY)>2*this.drawingTransform().pixelsPerUnitY()||isNaN(y)){paths.push(this.unstyledPath(points));points=[];}else {points.push(point);}lastY=y;}paths.push(this.unstyledPath(points));return paths})}plot(fn,range,style){return this.withStyle(style,()=>{const min=range[0];const max=range[1];if(!this.currentStyle["plot-points"]){this.currentStyle["plot-points"]=2*(max-min)*this.drawingTransform().pixelsPerUnitX();}const parametricFn=x=>[x,fn(x)];return this.plotParametric(parametricFn,range)})}withStyle(style,fn){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...this.processAttributes(style)};const result=this.postprocessDrawingResult(fn());this.currentStyle=oldStyle;return result}postprocessDrawingResult(result){const type=result.constructor.prototype;if(type===Raphael$1.el||type===Raphael$1.st){result.attr(this.currentStyle);if(this.currentStyle.arrows){result=this.addArrowheads(result);}}else if(result instanceof $){result.css({...this.currentStyle,...SVG_SPECIFIC_STYLE_MASK});}return result}addArrowheads(path){const type=path.constructor.prototype;if(type===Raphael$1.el){if(path.type==="path"&&typeof path.arrowheadsDrawn==="undefined"){const w=path.attr("stroke-width");const s=.6+.4*w;const l=path.getTotalLength();const set=this.raphael.set();const head=this.raphael.path(this.isMobile?"M-4,4 C-4,4 -0.25,0 -0.25,0 C-0.25,0 -4,-4 -4,-4":"M-3 4 C-2.75 2.5 0 0.25 0.75 0C0 -0.25 -2.75 -2.5 -3 -4");const end=path.getPointAtLength(l-.4);const almostTheEnd=path.getPointAtLength(l-.75*s);const angle=Math.atan2(end.y-almostTheEnd.y,end.x-almostTheEnd.x)*180/Math.PI;const attrs=path.attr();delete attrs.path;let subpath=path.getSubpath(0,l-.75*s);subpath=this.raphael.path(subpath).attr(attrs);subpath.arrowheadsDrawn=true;path.remove();head.rotate(angle,this.isMobile?1e-5:.75,0).scale(s,s,.75,0).translate(almostTheEnd.x,almostTheEnd.y).attr(attrs).attr({"stroke-linejoin":"round","stroke-linecap":"round"});head.arrowheadsDrawn=true;set.push(subpath);set.push(head);return set}}else if(type===Raphael$1.st){for(let i=0,l=path.items.length;i<l;i++){this.addArrowheads(path.items[i]);}}return path}processAttributes(attrs){const transformers={scale:scale=>{this.drawingTransform().setScale(scale);},clipRect:pair=>{const point=pair[0];const size=pair[1];point[1]+=size[1];return {"clip-rect":this.scalePoint(point).concat(this.scaleVector(size)).join(" ")}},strokeWidth:function(val){return {"stroke-width":parseFloat(val)}},rx:val=>{return {rx:this.scaleVector([val,0])[0]}},ry:val=>{return {ry:this.scaleVector([0,val])[1]}},r:val=>{const scaled=this.scaleVector([val,val]);return {rx:scaled[0],ry:scaled[1]}}};const processed={};Object.entries(attrs||{}).forEach(function([key,value]){const transformer=transformers[key];if(typeof transformer==="function"){Object.assign(processed,transformer(value));}else {const dasherized=String(key).replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase();processed[dasherized]=value;}});return processed}addMouseLayer(options){const localOptions={allowScratchpad:false,...options};const mouselayerZIndex=2;this.mouselayer=Raphael$1(this.el,this.xpixels,this.ypixels);$(this.mouselayer.canvas).css("z-index",mouselayerZIndex);if(localOptions.onClick||localOptions.onMouseDown||localOptions.onMouseMove||localOptions.onMouseOver||localOptions.onMouseOut){const canvasClickTarget=this.mouselayer.rect(0,0,this.xpixels,this.ypixels).attr({fill:"#000",opacity:0});let isClickingCanvas=false;$(this.mouselayer.canvas).on("vmousedown",e=>{if(e.target===canvasClickTarget[0]){if(localOptions.onMouseDown){localOptions.onMouseDown(this.getMouseCoord(e));}isClickingCanvas=true;if(localOptions.onMouseMove){const handler=localOptions.onMouseMove;$(document).bind("vmousemove.mouseLayer",e=>{if(isClickingCanvas){e.preventDefault();handler(this.getMouseCoord(e));}});}$(document).bind("vmouseup.mouseLayer",e=>{$(document).unbind(".mouseLayer");if(isClickingCanvas&&localOptions.onClick){localOptions.onClick(this.getMouseCoord(e));}isClickingCanvas=false;});}});if(localOptions.onMouseOver){const handler=localOptions.onMouseOver;$(this.mouselayer.canvas).on("vmouseover",e=>{handler(this.getMouseCoord(e));});}if(localOptions.onMouseOut){const handler=localOptions.onMouseOut;$(this.mouselayer.canvas).on("vmouseout",e=>{handler(this.getMouseCoord(e));});}}this._mouselayerWrapper=document.createElement("div");$(this._mouselayerWrapper).css({position:"absolute",left:0,top:0,zIndex:mouselayerZIndex});this._visiblelayerWrapper=document.createElement("div");$(this._visiblelayerWrapper).css({position:"absolute",left:0,top:0});const el=this.el;el.appendChild(this._visiblelayerWrapper);el.appendChild(this._mouselayerWrapper);this.addToMouseLayerWrapper=el=>{this._mouselayerWrapper?.appendChild(el);};this.addToVisibleLayerWrapper=el=>{this._visiblelayerWrapper?.appendChild(el);};}addToMouseLayerWrapper(el){throw new Error("addToMouseLayerWrapper is not ready. Call addMouseLayer() first.")}addToVisibleLayerWrapper(el){throw new Error("addToVisibleLayerWrapper is not ready. Call addMouseLayer() first.")}getMousePx(event){const offset=$(this.el).offset();const mouseX=event.pageX-offset.left;const mouseY=event.pageY-offset.top;return [mouseX,mouseY]}getMouseCoord(event){return this.unscalePoint(this.getMousePx(event))}_ensureResizeObserver(){if(_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]!=null||typeof ResizeObserver==="undefined"){return}_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=new ResizeObserver(()=>{this._recalculateLabels();});_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver].observe(this.el);}_recalculateLabels(){_class_private_field_loose_base(this,_labelElements)[_labelElements].forEach(span=>{const originalSize=$(span).data("originalLabelSize");if(originalSize!=null){setLabelMargins(span,originalSize);}});}cleanup(){_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]?.disconnect();_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;_class_private_field_loose_base(this,_labelElements)[_labelElements].clear();}constructor(el){Object.defineProperty(this,_bounds,{writable:true,value:void 0});Object.defineProperty(this,_drawingTransform,{writable:true,value:void 0});Object.defineProperty(this,_labelElements,{writable:true,value:void 0});Object.defineProperty(this,_resizeObserver,{writable:true,value:void 0});_class_private_field_loose_base(this,_labelElements)[_labelElements]=new Set;_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;this.isMobile=false;this.currentStyle={"stroke-width":2,fill:"none"};this.label=(point,text,direction,arg4,arg5)=>{const style=typeof arg4==="object"?arg4:arg5;const latex=typeof arg4==="boolean"?arg4:true;return this.withStyle(style,()=>{const $span=$("<span>").addClass("graphie-label");const pad=this.currentStyle["label-distance"];$span.css({position:"absolute",padding:(pad!=null?pad:7)+"px",color:"black"}).data("labelDirection",direction).appendTo(this.el);$span.setPosition=point=>{const scaledPoint=this.scalePoint(point);$span.css({left:scaledPoint[0],top:scaledPoint[1]});};$span.setPosition(point);$span.css({"font-size":this.currentStyle["font-size"]});const span=$span[0];_class_private_field_loose_base(this,_labelElements)[_labelElements].add(span);$span.processMath=function(math,force){processMath$1(span,math,force,function(){const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);});};$span.processText=function(text){$span.html(text);const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);};if(latex){$span.processMath(text,false);}else {$span.processText(text);}this._ensureResizeObserver();return $span})};this.svgPath=(points,alreadyScaled)=>{return points.map((point,i)=>{if(point===true){return "z"}const scaled=alreadyScaled?point:this.scalePoint(point);return (i===0?"M":"L")+KhanMath.bound(scaled[0])+" "+KhanMath.bound(scaled[1])}).join("")};this.svgParabolaPath=(a,b,c)=>{const computeParabola=function(x){return (a*x+b)*x+c};if(a===0){const points=[[this.bounds().xMin,computeParabola(this.bounds().xMin)],[this.bounds().xMax,computeParabola(this.bounds().xMax)]];return this.svgPath(points)}const xVertex=-b/(2*a);const distToEdge=Math.max(Math.abs(xVertex-this.bounds().xMin),Math.abs(xVertex-this.bounds().xMax));const xPoint=xVertex+distToEdge;const vertex=[xVertex,computeParabola(xVertex)];const point=[xPoint,computeParabola(xPoint)];const control=[vertex[0],vertex[1]-(point[1]-vertex[1])];const dx=Math.abs(vertex[0]-point[0]);const left=[vertex[0]-dx,point[1]];const right=[vertex[0]+dx,point[1]];const points=[left,control,right].map(this.scalePoint);const values=points.flat().map(KhanMath.bound);return "M"+values[0]+","+values[1]+" Q"+values[2]+","+values[3]+" "+values[4]+","+values[5]};this.svgSinusoidPath=(a,b,c,d)=>{const quarterPeriod=Math.abs(Math.PI/(2*b));const computeSine=function(x){return a*Math.sin(b*x-c)+d};const computeDerivative=function(x){return a*b*Math.cos(c-b*x)};const coordsForOffset=(initial,i)=>{const x0=initial+quarterPeriod*i;const x1=x0+quarterPeriod;const xCoords=[x0,x0*2/3+x1*1/3,x0*1/3+x1*2/3,x1];const yCoords=[computeSine(x0),computeSine(x0)+computeDerivative(x0)*(x1-x0)/3,computeSine(x1)-computeDerivative(x1)*(x1-x0)/3,computeSine(x1)];const points=vector$3.zip(xCoords,yCoords);return points.map(this.scalePoint)};const extent=this.bounds().width();const numQuarterPeriods=Math.ceil(extent/quarterPeriod)+1;let initial=c/b;const distToEdge=initial-this.bounds().xMin;initial-=quarterPeriod*Math.ceil(distToEdge/quarterPeriod);let coords=coordsForOffset(initial,0);let path="M"+coords[0][0]+","+coords[0][1]+" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];for(let i=1;i<numQuarterPeriods;i++){coords=coordsForOffset(initial,i);path+=" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];}return path};this.scalePoint=point=>{return this.drawingTransform().scalePoint(point)};this.scaleVector=point=>{return this.drawingTransform().scaleVector(point)};this.unscalePoint=point=>{return this.drawingTransform().unscalePoint(point)};this.unscaleVector=point=>{return this.drawingTransform().unscaleVector(point)};this.el=el;$(el).css("position","relative");this.raphael=Raphael$1(el);$(el).attr("aria-hidden","true");$(el).children("div").css("position","absolute");}};const labelDirections={center:[-0.5,-0.5],above:[-0.5,-1],"above right":[0,-1],right:[0,-0.5],"below right":[0,0],below:[-0.5,0],"below left":[-1,0],left:[-1,-0.5],"above left":[-1,-1]};function normalizeRange(range){function normalizeInterval(magnitude){if(typeof magnitude==="number"){return [-magnitude,magnitude]}else {return magnitude}}function getXAndYRanges(range){if(Array.isArray(range)){return range}else {return [range,range]}}if(range==null){return range}const[xRange,yRange]=getXAndYRanges(range);return [normalizeInterval(xRange),normalizeInterval(yRange)]}function toPair(x){if(Array.isArray(x)){return x}return [x,x]}const SVG_SPECIFIC_STYLE_MASK={"stroke-width":null};const setLabelMargins=function(span,size){if(document.fonts?.status==="loading"){document.fonts.ready.then(()=>applyLabelMargins(span,size));return}applyLabelMargins(span,size);};const applyLabelMargins=function(span,size){const $span=$(span);const direction=$span.data("labelDirection");let[width,height]=size;if(width===0&&height===0){[width,height]=[1,1];Log.log("Label size was 0x0 in graphie.js; using 1x1 instead");}$span.css("visibility","");if(typeof direction==="number"){const x=Math.cos(direction);const y=Math.sin(direction);const scale=Math.min(width/2/Math.abs(x),height/2/Math.abs(y));$span.css({marginLeft:-width/2+x*scale,marginTop:-height/2-y*scale});if($span.data("originalLabelSize")==null){$span.data("originalLabelSize",[width,height]);}}else {const $svgImage=$span.closest(".svg-image");const $graphie=$span.closest(".graphie");const $container=$svgImage.length>0?$svgImage:$graphie;$container.css("line-height","normal");if($span.data("originalLabelSize")==null){height=span.scrollHeight;$span.data("originalLabelSize",[width,height]);}const widthValues=$container.css(["max-width","width"])??{"max-width":"0px"};const expectedWidth=widthValues["max-width"]!=="none"?widthValues["max-width"]:widthValues["width"];let scale=($container.width()??0)/parseInt(expectedWidth.replace(/px$/,""));if(isNaN(scale)){scale=1;}else if(scale===0){scale=1;}let rawPadding;const storedPadding=$span.data("originalPadding");if(storedPadding!=null){rawPadding=storedPadding;}else {const padding=$span.css("padding")??"0px";const currentPadding=padding!=="none"?padding:"0px";rawPadding=parseInt(currentPadding.replace(/px$/,""));$span.data("originalPadding",rawPadding);}let normalizedWidth=width;let normalizedHeight=height;const imageScale=Number($container.attr("data-scale"));const hasValidImageScale=!Number.isNaN(imageScale)&&imageScale>=0;if(hasValidImageScale){scale=scale*imageScale;const totalPadding=2*rawPadding;normalizedWidth=(width-totalPadding)/imageScale+totalPadding;normalizedHeight=(height-totalPadding)/imageScale+totalPadding;}const newPadding=rawPadding*scale;const multipliers=labelDirections[direction||"center"];const styling={marginLeft:normalizedWidth*multipliers[0]*scale,marginTop:normalizedHeight*multipliers[1]*scale,padding:`${newPadding}px`,fontSize:`${scale*100}%`};$span.css(styling);}};const GraphUtils={Graphie: Graphie$1,createGraphie:function(el){return new Graphie$1(el)},unscaledSvgPath:function(points){if(points[0]===true){return ""}return points.map(function(point,i){if(point===true){return "z"}return (i===0?"M":"L")+point[0]+" "+point[1]}).join("")},getDistance:function(point1,point2){return point.distanceToPoint(point1,point2)},findAngleDeprecated:function(point1,point2,vertex){if(vertex===undefined){const x=point1[0]-point2[0];const y=point1[1]-point2[1];if(!x&&!y){return 0}return (180+Math.atan2(-y,-x)*180/Math.PI+360)%360}return GraphUtils.findAngleDeprecated(point1,vertex)-GraphUtils.findAngleDeprecated(point2,vertex)},graphs:{}};
1565
1565
 
1566
1566
  (function($,window1,document1,undefined$1){if(typeof $==="undefined"){return}var dataPropertyName="virtualMouseBindings",touchTargetPropertyName="virtualTouchID",virtualEventNames="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),touchEventProps="clientX clientY pageX pageY screenX screenY".split(" "),mouseHookProps=$.event.mouseHooks?$.event.mouseHooks.props:[],mouseEventProps=$.event.props.concat(mouseHookProps),activeDocHandlers={},resetTimerID=0,startX=0,startY=0,didScroll=false,clickBlockList=[],blockMouseTriggers=false,blockTouchTriggers=false,eventCaptureSupported="addEventListener"in document1,$document=$(document1),nextTouchID=1,lastTouchID=0;$.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500};function getNativeEvent(event){while(event&&typeof event.originalEvent!=="undefined"){event=event.originalEvent;}return event}function createVirtualEvent(event,eventType){var t=event.type,oe,props,ne,prop,ct,touch,i,j,len;event=$.Event(event);event.type=eventType;oe=event.originalEvent;props=$.event.props;if(t.search(/mouse/)>-1){props=mouseEventProps;}if(oe){for(i=props.length,prop;i;){prop=props[--i];event[prop]=oe[prop];}}if(t.search(/mouse(down|up)|click/)>-1&&!event.which){event.which=1;}if(t.search(/^touch/)!==-1){ne=getNativeEvent(oe);t=ne.touches;ct=ne.changedTouches;touch=t&&t.length?t[0]:ct&&ct.length?ct[0]:undefined$1;if(touch){for(j=0,len=touchEventProps.length;j<len;j++){prop=touchEventProps[j];event[prop]=touch[prop];}}}return event}function getVirtualBindingFlags(element){var flags={},b,k;while(element){b=$.data(element,dataPropertyName);for(k in b){if(b[k]){flags[k]=flags.hasVirtualBinding=true;}}element=element.parentNode;}return flags}function getClosestElementWithVirtualBinding(element,eventType){var b;while(element){b=$.data(element,dataPropertyName);if(b&&(!eventType||b[eventType])){return element}element=element.parentNode;}return null}function enableTouchBindings(){blockTouchTriggers=false;}function disableTouchBindings(){blockTouchTriggers=true;}function enableMouseBindings(){lastTouchID=0;clickBlockList.length=0;blockMouseTriggers=false;disableTouchBindings();}function disableMouseBindings(){enableTouchBindings();}function startResetTimer(){clearResetTimer();resetTimerID=setTimeout(function(){resetTimerID=0;enableMouseBindings();},$.vmouse.resetTimerDuration);}function clearResetTimer(){if(resetTimerID){clearTimeout(resetTimerID);resetTimerID=0;}}function triggerVirtualEvent(eventType,event,flags){var ve;if(flags&&flags[eventType]||!flags&&getClosestElementWithVirtualBinding(event.target,eventType)){ve=createVirtualEvent(event,eventType);$(event.target).trigger(ve);}return ve}function mouseEventCallback(event){var touchID=$.data(event.target,touchTargetPropertyName);if(!blockMouseTriggers&&(!lastTouchID||lastTouchID!==touchID)){var ve=triggerVirtualEvent("v"+event.type,event);if(ve){if(ve.isDefaultPrevented()){event.preventDefault();}if(ve.isPropagationStopped()){event.stopPropagation();}if(ve.isImmediatePropagationStopped()){event.stopImmediatePropagation();}}}}function handleTouchStart(event){var touches=getNativeEvent(event).touches,target,flags;if(touches&&touches.length===1){target=event.target;flags=getVirtualBindingFlags(target);if(flags.hasVirtualBinding){lastTouchID=nextTouchID++;$.data(target,touchTargetPropertyName,lastTouchID);clearResetTimer();disableMouseBindings();didScroll=false;var t=getNativeEvent(event).touches[0];startX=t.pageX;startY=t.pageY;triggerVirtualEvent("vmouseover",event,flags);triggerVirtualEvent("vmousedown",event,flags);}}}function handleScroll(event){if(blockTouchTriggers){return}if(!didScroll){triggerVirtualEvent("vmousecancel",event,getVirtualBindingFlags(event.target));}didScroll=true;startResetTimer();}function handleTouchMove(event){if(blockTouchTriggers){return}var t=getNativeEvent(event).touches[0],didCancel=didScroll,moveThreshold=$.vmouse.moveDistanceThreshold,didScroll=didScroll||Math.abs(t.pageX-startX)>moveThreshold||Math.abs(t.pageY-startY)>moveThreshold,flags=getVirtualBindingFlags(event.target);if(didScroll&&!didCancel){triggerVirtualEvent("vmousecancel",event,flags);}triggerVirtualEvent("vmousemove",event,flags);startResetTimer();}function handleTouchEnd(event){if(blockTouchTriggers){return}disableTouchBindings();var flags=getVirtualBindingFlags(event.target),t;triggerVirtualEvent("vmouseup",event,flags);if(!didScroll){var ve=triggerVirtualEvent("vclick",event,flags);if(ve&&ve.isDefaultPrevented()){t=getNativeEvent(event).changedTouches[0];clickBlockList.push({touchID:lastTouchID,x:t.clientX,y:t.clientY});blockMouseTriggers=true;}}triggerVirtualEvent("vmouseout",event,flags);didScroll=false;startResetTimer();}function hasVirtualBindings(ele){var bindings=$.data(ele,dataPropertyName),k;if(bindings){for(k in bindings){if(bindings[k]){return true}}}return false}function dummyMouseHandler(){}function getSpecialEventObject(eventType){var realType=eventType.substr(1);return {setup:function(data,namespace){if(!hasVirtualBindings(this)){$.data(this,dataPropertyName,{});}var bindings=$.data(this,dataPropertyName);bindings[eventType]=true;activeDocHandlers[eventType]=(activeDocHandlers[eventType]||0)+1;if(activeDocHandlers[eventType]===1){$document.bind(realType,mouseEventCallback);}$(this).bind(realType,dummyMouseHandler);if(eventCaptureSupported){activeDocHandlers["touchstart"]=(activeDocHandlers["touchstart"]||0)+1;if(activeDocHandlers["touchstart"]===1){$document.bind("touchstart",handleTouchStart).bind("touchend",handleTouchEnd).bind("touchmove",handleTouchMove).bind("scroll",handleScroll);}}},teardown:function(data,namespace){--activeDocHandlers[eventType];if(!activeDocHandlers[eventType]){$document.unbind(realType,mouseEventCallback);}if(eventCaptureSupported){--activeDocHandlers["touchstart"];if(!activeDocHandlers["touchstart"]){$document.unbind("touchstart",handleTouchStart).unbind("touchmove",handleTouchMove).unbind("touchend",handleTouchEnd).unbind("scroll",handleScroll);}}var $this=$(this),bindings=$.data(this,dataPropertyName);if(bindings){bindings[eventType]=false;}$this.unbind(realType,dummyMouseHandler);if(!hasVirtualBindings(this)){$this.removeData(dataPropertyName);}}}}for(var i=0;i<virtualEventNames.length;i++){$.event.special[virtualEventNames[i]]=getSpecialEventObject(virtualEventNames[i]);}if(eventCaptureSupported){document1.addEventListener("click",function(e){var cnt=clickBlockList.length,target=e.target,x,y,ele,i,o;if(cnt){x=e.clientX;y=e.clientY;threshold=$.vmouse.clickDistanceThreshold;ele=target;while(ele){for(i=0;i<cnt;i++){o=clickBlockList[i];if(ele===target&&Math.abs(o.x-x)<threshold&&Math.abs(o.y-y)<threshold||$.data(ele,touchTargetPropertyName)===o.touchID){e.preventDefault();e.stopPropagation();return}}ele=ele.parentNode;}}},true);}})($,window,document);
1567
1567
 
@@ -1609,9 +1609,9 @@ const Status={PENDING:"pending",LOADING:"loading",LOADED:"loaded",FAILED:"failed
1609
1609
 
1610
1610
  function isGif(url){return url.endsWith(".gif")}function isSvg(url){const hasSvgExtension=url.endsWith(".svg");const hasGraphieUrl=isLabeledSVG(url);return hasSvgExtension||hasGraphieUrl}
1611
1611
 
1612
- var styles$B = {"contentWrapper":"perseus_NqTCZY3N","imageContainer":"perseus_Ctn3miye"};
1612
+ var styles$C = {"contentWrapper":"perseus_NqTCZY3N","imageContainer":"perseus_Ctn3miye"};
1613
1613
 
1614
- const WB_MODAL_PADDING_TOTAL=64;const ZoomedImageView=props=>{const i18n=usePerseusI18n();const{initialFocusId,onClose,...svgProps}=props;const width=props.width;const height=props.height;const contentScale=props.scale;const imageIsSvg=isSvg(props.src);const scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);const maxAvailableWidth=window.innerWidth-WB_MODAL_PADDING_TOTAL;const maxAvailableHeight=window.innerHeight-WB_MODAL_PADDING_TOTAL;const scaleWidth=maxAvailableWidth/(width*scale);const scaleHeight=maxAvailableHeight/(height*scale);const fitRatio=Math.min(scaleWidth,scaleHeight,1);const constrainedDisplayWidth=width*fitRatio*scale;return jsxRuntimeExports.jsx(ModalDialog,{"aria-labelledby":"",style:wbStyles$2.dialog,children:jsxRuntimeExports.jsx(ModalPanel,{closeButtonVisible:false,content:jsxRuntimeExports.jsxs("div",{className:styles$B.contentWrapper,children:[jsxRuntimeExports.jsx("div",{className:styles$B.imageContainer,style:{width:constrainedDisplayWidth},children:jsxRuntimeExports.jsx("div",{className:"framework-perseus",tabIndex:0,id:initialFocusId,children:jsxRuntimeExports.jsx(SvgImage,{...svgProps,allowZoom:false,width:width,height:height,scale:scale})})}),jsxRuntimeExports.jsx(IconButton,{icon:closeIcon,onClick:onClose,"aria-label":i18n.strings.imageResetZoomAriaLabel,kind:"primary",style:wbStyles$2.closeButton})]})})})};const wbStyles$2=StyleSheet.create({dialog:{width:"auto",height:"auto",margin:sizing.size_320,"@media (max-width: 767px)":{margin:0}},closeButton:{position:"absolute",top:border$1.width.medium,right:border$1.width.medium,opacity:0,":hover":{opacity:1},":focus":{opacity:1}}});
1614
+ const WB_MODAL_PADDING_TOTAL=64;const ZoomedImageView=props=>{const i18n=usePerseusI18n();const{initialFocusId,onClose,...svgProps}=props;const width=props.width;const height=props.height;const contentScale=props.scale;const imageIsSvg=isSvg(props.src);const scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);const maxAvailableWidth=window.innerWidth-WB_MODAL_PADDING_TOTAL;const maxAvailableHeight=window.innerHeight-WB_MODAL_PADDING_TOTAL;const scaleWidth=maxAvailableWidth/(width*scale);const scaleHeight=maxAvailableHeight/(height*scale);const fitRatio=Math.min(scaleWidth,scaleHeight,1);const constrainedDisplayWidth=width*fitRatio*scale;return jsxRuntimeExports.jsx(ModalDialog,{"aria-labelledby":"",style:wbStyles$2.dialog,children:jsxRuntimeExports.jsx(ModalPanel,{closeButtonVisible:false,content:jsxRuntimeExports.jsxs("div",{className:styles$C.contentWrapper,children:[jsxRuntimeExports.jsx("div",{className:styles$C.imageContainer,style:{width:constrainedDisplayWidth},children:jsxRuntimeExports.jsx("div",{className:"framework-perseus",tabIndex:0,id:initialFocusId,children:jsxRuntimeExports.jsx(SvgImage,{...svgProps,allowZoom:false,width:width,height:height,scale:scale})})}),jsxRuntimeExports.jsx(IconButton,{icon:closeIcon,onClick:onClose,"aria-label":i18n.strings.imageResetZoomAriaLabel,kind:"primary",style:wbStyles$2.closeButton})]})})})};const wbStyles$2=StyleSheet.create({dialog:{width:"auto",height:"auto",margin:sizing.size_320,"@media (max-width: 767px)":{margin:0}},closeButton:{position:"absolute",top:border$1.width.medium,right:border$1.width.medium,opacity:0,":hover":{opacity:1},":focus":{opacity:1}}});
1615
1615
 
1616
1616
  const ZoomImageButton=props=>{const{imgSrc}=props;const i18n=usePerseusI18n();const uniqueId=React.useId().replace(/:/g,"");const zoomedImageUniqueId=`zoomed-image-${uniqueId}`;const handleClick=(event,openModal)=>{const mouseEvent=event;if(mouseEvent.metaKey||mouseEvent.ctrlKey){window.open(imgSrc,"_blank");}else {openModal();}};return jsxRuntimeExports.jsx(ModalLauncher,{initialFocusId:zoomedImageUniqueId,modal:({closeModal})=>jsxRuntimeExports.jsx(ZoomedImageView,{...props,initialFocusId:zoomedImageUniqueId,onClose:closeModal}),children:({openModal})=>jsxRuntimeExports.jsx(Clickable,{"aria-label":i18n.strings.imageZoomAriaLabel,onClick:event=>handleClick(event,openModal),style:{position:"absolute",width:"100%",height:"100%",overflow:"hidden",cursor:"zoom-in"},children:()=>{return jsxRuntimeExports.jsx(React.Fragment,{})}})})};
1617
1617
 
@@ -1633,7 +1633,7 @@ const arrayRules={fence:{match:SimpleMarkdown.defaultRules.fence.match,order:1,p
1633
1633
 
1634
1634
  const denylist=["key","ref","containerSizeClass","widgetId","onChange","problemNum","apiOptions","widgetIsOpen","findWidgets","onRemove","id","onBlur","onFocus","trackInteraction","keypadElement","linterContext","handleUserInput","analytics","showSolutions","reviewMode","widgetIndex","graded"];function excludeDenylistKeys(obj){if(obj==null){return obj}const rv={};for(const k of Object.keys(obj)){if(!denylist.includes(k)){rv[k]=obj[k];}}return rv}
1635
1635
 
1636
- const exclamationIcon={path:"M6 11a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0-9a1 1 0 0 1 1 1v4a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1z",height:12,width:12};class Lint extends React.Component{componentDidMount(){this._positionTimeout=window.setTimeout(this.getPosition);}componentWillUnmount(){window.clearTimeout(this._positionTimeout);}render(){const{children,inline,blockHighlight,insideTable}=this.props;if(insideTable){if(inline){return jsxRuntimeExports.jsx("span",{"data-lint-inside-table":"true",children:children})}return jsxRuntimeExports.jsx("div",{"data-lint-inside-table":"true",children:children})}if(blockHighlight){return jsxRuntimeExports.jsxs("span",{className:css(styles$A.lintContainer,styles$A.lintContainerBlock),children:[this.renderLink(styles$A.radioWidgetHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}if(inline){return jsxRuntimeExports.jsxs("span",{className:css(styles$A.lintContainer),children:[this.renderLink(styles$A.inlineHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}return jsxRuntimeExports.jsxs("div",{className:css(styles$A.lintContainer),children:[this.renderLink(styles$A.hoverTarget),jsxRuntimeExports.jsx("div",{children:children})]})}constructor(...args){super(...args),this.state={tooltipAbove:true},this.getPosition=()=>{const rect=ReactDOM__default.findDOMNode(this).getBoundingClientRect();this.setState({tooltipAbove:rect.top>100});},this.renderLink=style=>{const tooltipAbove=this.state.tooltipAbove;let severityStyle;let warningText;let warningTextStyle;if(this.props.severity===1){severityStyle=styles$A.indicatorError;warningText="Error";warningTextStyle=styles$A.publishBlockingError;}else if(this.props.severity===2){severityStyle=styles$A.indicatorWarning;warningText="Warning";warningTextStyle=styles$A.warning;}else {severityStyle=styles$A.indicatorGuideline;warningText="Recommendation";warningTextStyle=styles$A.warning;}return jsxRuntimeExports.jsxs("a",{href:`https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,target:"lint-help-window",className:css(style),children:[jsxRuntimeExports.jsx("span",{className:css(styles$A.indicator,severityStyle),children:this.props.severity===1&&jsxRuntimeExports.jsx(InlineIcon,{...exclamationIcon})}),jsxRuntimeExports.jsxs("div",{className:css(styles$A.tooltip,tooltipAbove&&styles$A.tooltipAbove),children:[this.props.message.split("\n\n").map((m,i)=>jsxRuntimeExports.jsxs("p",{className:css(styles$A.tooltipParagraph),children:[jsxRuntimeExports.jsxs("span",{className:css(warningTextStyle),children:[warningText,":"," "]}),m]},i)),jsxRuntimeExports.jsx("div",{className:css(styles$A.tail,tooltipAbove&&styles$A.tailAbove)})]})]})};}}const styles$A=StyleSheet.create({lintContainer:{position:"relative"},lintContainerBlock:{display:"block"},hoverTarget:{position:"absolute",top:0,right:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ div":{outline:"1px solid "+warningColor},":hover ~ div div[data-lint-inside-table]":{outline:"1px solid "+warningColor},":hover ~ div span[data-lint-inside-table]":{backgroundColor:warningColor,color:white}},inlineHoverTarget:{float:"right",position:"relative",marginRight:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ span":{backgroundColor:warningColor,color:white}},radioWidgetHoverTarget:{position:"absolute",left:-40,display:"block",width:24,height:24,minWidth:264,":hover > span":{backgroundColor:warningColorHover},":hover > div":{display:"block",padding:8,width:280},":hover > div > div":{left:8},":hover ~ span":{backgroundColor:warningColor,color:white}},indicator:{alignItems:"center",borderRadius:4,color:"white",display:"flex",fontSize:12,height:8,justifyContent:"center",margin:8,width:8},indicatorError:{backgroundColor:"#be2612",borderRadius:8,height:16,width:16},indicatorWarning:{backgroundColor:"#f86700"},indicatorGuideline:{backgroundColor:"#ffbe26"},tooltip:{position:"absolute",right:-12,display:"none",zIndex:1e3,color:white,backgroundColor:gray17,opacity:.9,fontFamily:baseFontFamily,fontSize:"12px",lineHeight:"15px",width:"320px",borderRadius:"4px"},tooltipAbove:{bottom:32},tail:{position:"absolute",top:-12,right:16,width:0,height:0,borderLeft:"8px solid transparent",borderRight:"8px solid transparent",borderBottom:"12px solid "+gray17},tailAbove:{bottom:-12,borderBottom:"none",borderTop:"12px solid "+gray17,top:"auto"},tooltipParagraph:{margin:12},warning:{color:warningColor,fontFamily:boldFontFamily},publishBlockingError:{color:publishBlockingErrorColor}});
1636
+ const exclamationIcon={path:"M6 11a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0-9a1 1 0 0 1 1 1v4a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1z",height:12,width:12};class Lint extends React.Component{componentDidMount(){this._positionTimeout=window.setTimeout(this.getPosition);}componentWillUnmount(){window.clearTimeout(this._positionTimeout);}render(){const{children,inline,blockHighlight,insideTable}=this.props;if(insideTable){if(inline){return jsxRuntimeExports.jsx("span",{"data-lint-inside-table":"true",children:children})}return jsxRuntimeExports.jsx("div",{"data-lint-inside-table":"true",children:children})}if(blockHighlight){return jsxRuntimeExports.jsxs("span",{className:css(styles$B.lintContainer,styles$B.lintContainerBlock),children:[this.renderLink(styles$B.radioWidgetHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}if(inline){return jsxRuntimeExports.jsxs("span",{className:css(styles$B.lintContainer),children:[this.renderLink(styles$B.inlineHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}return jsxRuntimeExports.jsxs("div",{className:css(styles$B.lintContainer),children:[this.renderLink(styles$B.hoverTarget),jsxRuntimeExports.jsx("div",{children:children})]})}constructor(...args){super(...args),this.state={tooltipAbove:true},this.getPosition=()=>{const rect=ReactDOM__default.findDOMNode(this).getBoundingClientRect();this.setState({tooltipAbove:rect.top>100});},this.renderLink=style=>{const tooltipAbove=this.state.tooltipAbove;let severityStyle;let warningText;let warningTextStyle;if(this.props.severity===1){severityStyle=styles$B.indicatorError;warningText="Error";warningTextStyle=styles$B.publishBlockingError;}else if(this.props.severity===2){severityStyle=styles$B.indicatorWarning;warningText="Warning";warningTextStyle=styles$B.warning;}else {severityStyle=styles$B.indicatorGuideline;warningText="Recommendation";warningTextStyle=styles$B.warning;}return jsxRuntimeExports.jsxs("a",{href:`https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,target:"lint-help-window",className:css(style),children:[jsxRuntimeExports.jsx("span",{className:css(styles$B.indicator,severityStyle),children:this.props.severity===1&&jsxRuntimeExports.jsx(InlineIcon,{...exclamationIcon})}),jsxRuntimeExports.jsxs("div",{className:css(styles$B.tooltip,tooltipAbove&&styles$B.tooltipAbove),children:[this.props.message.split("\n\n").map((m,i)=>jsxRuntimeExports.jsxs("p",{className:css(styles$B.tooltipParagraph),children:[jsxRuntimeExports.jsxs("span",{className:css(warningTextStyle),children:[warningText,":"," "]}),m]},i)),jsxRuntimeExports.jsx("div",{className:css(styles$B.tail,tooltipAbove&&styles$B.tailAbove)})]})]})};}}const styles$B=StyleSheet.create({lintContainer:{position:"relative"},lintContainerBlock:{display:"block"},hoverTarget:{position:"absolute",top:0,right:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ div":{outline:"1px solid "+warningColor},":hover ~ div div[data-lint-inside-table]":{outline:"1px solid "+warningColor},":hover ~ div span[data-lint-inside-table]":{backgroundColor:warningColor,color:white}},inlineHoverTarget:{float:"right",position:"relative",marginRight:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ span":{backgroundColor:warningColor,color:white}},radioWidgetHoverTarget:{position:"absolute",left:-40,display:"block",width:24,height:24,minWidth:264,":hover > span":{backgroundColor:warningColorHover},":hover > div":{display:"block",padding:8,width:280},":hover > div > div":{left:8},":hover ~ span":{backgroundColor:warningColor,color:white}},indicator:{alignItems:"center",borderRadius:4,color:"white",display:"flex",fontSize:12,height:8,justifyContent:"center",margin:8,width:8},indicatorError:{backgroundColor:"#be2612",borderRadius:8,height:16,width:16},indicatorWarning:{backgroundColor:"#f86700"},indicatorGuideline:{backgroundColor:"#ffbe26"},tooltip:{position:"absolute",right:-12,display:"none",zIndex:1e3,color:white,backgroundColor:gray17,opacity:.9,fontFamily:baseFontFamily,fontSize:"12px",lineHeight:"15px",width:"320px",borderRadius:"4px"},tooltipAbove:{bottom:32},tail:{position:"absolute",top:-12,right:16,width:0,height:0,borderLeft:"8px solid transparent",borderRight:"8px solid transparent",borderBottom:"12px solid "+gray17},tailAbove:{bottom:-12,borderBottom:"none",borderTop:"12px solid "+gray17,top:"auto"},tooltipParagraph:{margin:12},warning:{color:warningColor,fontFamily:boldFontFamily},publishBlockingError:{color:publishBlockingErrorColor}});
1637
1637
 
1638
1638
  const rules={...pureMarkdownRules,columns:{...pureMarkdownRules.columns,react:(node,output,state)=>{return jsxRuntimeExports.jsxs("div",{className:"perseus-two-columns",children:[jsxRuntimeExports.jsx("div",{className:"perseus-column",children:jsxRuntimeExports.jsx("div",{className:"perseus-column-content",children:output(node.col1,state)})}),jsxRuntimeExports.jsx("div",{className:"perseus-column",children:jsxRuntimeExports.jsx("div",{className:"perseus-column-content",children:output(node.col2,state)})})]},state.key)}},crowdinId:{...pureMarkdownRules.crowdinId,react:(node,output,state)=>node.id},table:{...pureMarkdownRules.table,react:function(node,output,state){const table=SimpleMarkdown.defaultRules.table.react(node,output,state);if(!state.isMobile){return table}return React.cloneElement(table,{tabIndex:0})}},titledTable:{...pureMarkdownRules.titledTable,react:(node,output,state)=>{let contents;if(!node.table){contents="//invalid table//";}else if(node.table.type==="lint"){if(node.table.content?.type==="table"){contents=rules.lint.react({...node.table,content:{...node,table:node.table.content}},output,{...state,unwrapTitledTableContents:true});}else {contents=rules.lint.react(node.table,output,state);}}else {const tableOutput=SimpleMarkdown.defaultRules.table.react(node.table,output,state);const caption=jsxRuntimeExports.jsx("caption",{className:"perseus-table-title",children:output(node.title,state)},"caption");contents=React.cloneElement(tableOutput,null,[caption,...tableOutput.props.children]);}if(state.unwrapTitledTableContents){return contents}return jsxRuntimeExports.jsx("div",{className:"perseus-titled-table",children:contents},state.key)}},widget:{...pureMarkdownRules.widget,react:(node,output,state)=>{return jsxRuntimeExports.jsx("em",{children:`[Widget: ${node.id}]`},state.key)}},blockMath:{...pureMarkdownRules.blockMath,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},math:{...pureMarkdownRules.math,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},unescapedDollar:{...pureMarkdownRules.unescapedDollar,react:(node,output,state)=>{return "$"}},link:{...pureMarkdownRules.link,react:function(node,output,state){const link=SimpleMarkdown.defaultRules.link.react(node,output,state);const href=link.props.href;let rel=null;const isKAUrl=href?href.match(/https?:\/\/[^/]*khanacademy.org|^\//):false;if(!isKAUrl){rel="noopener noreferrer";}const newProps={...link.props,target:"_blank",href,rel};if(state.baseElements&&state.baseElements.Link){return state.baseElements.Link(newProps)}return React.cloneElement(link,newProps)}},codeBlock:{...pureMarkdownRules.codeBlock,react:(node,output,state)=>{if(node.lang==="alt"){return jsxRuntimeExports.jsx("div",{className:"perseus-markdown-alt perseus-sr-only",children:output(node.content,state)},state.key)}return SimpleMarkdown.defaultRules.codeBlock.react(node,output,state)}},lint:{...pureMarkdownRules.lint,react:(node,output,state)=>{return jsxRuntimeExports.jsx(Lint,{message:node.message,ruleName:node.ruleName,inline:isInline(node.content),blockHighlight:node.blockHighlight,insideTable:node.insideTable,severity:node.severity,children:output(node.content,state)})}}};function isInline(node){return !!(node&&node.type&&inlineNodeTypes.hasOwnProperty(node.type))}const inlineNodeTypes={text:true,math:true,unescapedDollar:true,link:true,img:true,strong:true,u:true,em:true,del:true,code:true};const builtParser=SimpleMarkdown.parserFor(rules);const parse$2=(source,state)=>{const paragraphedSource=source+"\n\n";return builtParser(paragraphedSource,{...state,inline:false})};const inlineParser=(source,state)=>{return builtParser(source,{...state,inline:true})};const getContent=ast=>{if(_.isArray(ast)){return _.flatten(_.map(ast,getContent))}if(ast.content&&_.isString(ast.content)){if(ast.type.toLowerCase().indexOf("code")!==-1){return ["",ast.content,""]}return [ast.content.replace(/\s+/g," ")]}const children=_.chain(ast).values().flatten().filter(object=>object!=null&&_.has(object,"type")).value();if(!children.length){return []}const nestedContent=getContent(children);if(ast.type==="paragraph"&&nestedContent.length){nestedContent[0]=nestedContent[0].replace(/^\s+/,"");const last=nestedContent.length-1;nestedContent[last]=nestedContent[last].replace(/\s+$/,"");}return nestedContent};const characterCount=source=>{const ast=parse$2(source);const content=getContent(ast).join("");return content.length};var PerseusMarkdown = {characterCount:characterCount,traverseContent:traverseContent,parse:parse$2,parseInline:inlineParser,reactFor:SimpleMarkdown.reactFor,ruleOutput:SimpleMarkdown.ruleOutput(rules,"react"),basicOutput:SimpleMarkdown.reactFor(SimpleMarkdown.ruleOutput(rules,"react")),sanitizeUrl:SimpleMarkdown.sanitizeUrl};
1639
1639
 
@@ -1673,7 +1673,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
1673
1673
 
1674
1674
  class WidgetContainer extends React.Component{componentDidMount(){if(this.props.widgetProps.apiOptions.isMobile){const containerWidth=ReactDOM__default.findDOMNode(this).offsetWidth;this.setState({sizeClass:getClassFromWidth(containerWidth)});}}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.type!==nextProps.type){throw new Error("WidgetContainer can't change widget type; set a different "+"key instead to recreate the container.")}}render(){let className=classNames$2({"perseus-widget-container":true,"perseus-widget__definition":this.props.type==="definition"});const type=this.props.type;const userAgent=navigator.userAgent;const WidgetType=getWidget(type);if(WidgetType==null){console.warn(`Widget type '${type}' not found!`);return jsxRuntimeExports.jsx("div",{className:className})}const subType=getWidgetSubType(type,this.props.widgetProps)??"null";let alignment=this.props.widgetProps.alignment;if(alignment==="default"){alignment=CoreWidgetRegistry.getDefaultAlignment(type);}className+=CoreWidgetRegistry.getAlignmentClassName(type,alignment);const apiOptions=this.props.widgetProps.apiOptions;const isStatic=this.props.widgetProps.static||apiOptions.readOnly;const staticContainerStyles={position:"relative",overflow:"visible"};const staticOverlayStyles={width:"100%",height:"100%",position:"absolute",top:0,left:0,zIndex:3};const linterContext=isLintable(type)?this.props.linterContext:{...this.props.linterContext,highlightLint:false};return jsxRuntimeExports.jsx("div",{className:className,style:isStatic?staticContainerStyles:{},children:jsxRuntimeExports.jsx(DependenciesContext.Consumer,{children:({analytics})=>jsxRuntimeExports.jsxs(ErrorBoundary,{metadata:{widget_type:type,widget_id:this.props.id},onError:error=>{analytics.onAnalyticsEvent({type:"perseus:widget-rendering-error:ti",payload:{widgetSubType:subType,widgetType:type,widgetId:this.props.id,message:error.message,stack:error.stack??"No stack trace available",userAgent:userAgent}});},children:[jsxRuntimeExports.jsx(WidgetType,{...this.props.widgetProps,linterContext:linterContext,containerSizeClass:this.state.sizeClass,ref:this.widgetRef}),isStatic&&jsxRuntimeExports.jsx("div",{style:staticOverlayStyles})]})})})}constructor(...args){super(...args),this.widgetRef=React.createRef(),this.state={sizeClass:containerSizeClass.MEDIUM},this.getWidget=()=>{return this.widgetRef.current};}}WidgetContainer.defaultProps={linterContext:linterContextDefault};
1675
1675
 
1676
- const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return _.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return _.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion(propsA,propsB){function makeItem(props){return splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!_.isEqual(makeItem(propsA),makeItem(propsB))}class Renderer extends React.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!_.isEqual(this.state,nextState);const propsChanged=!_.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput&&!_.isEqual(this.props.userInput,prevProps.userInput)){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_isAnswerable(){if(this.props.userInput){return this.emptyWidgets().length===0}return false}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];if(!this._interactionTrackers){this._interactionTrackers={};}let interactionTracker=this._interactionTrackers[widgetId];if(!interactionTracker){interactionTracker=this._interactionTrackers[widgetId]=new InteractionTracker(apiOptions.trackInteraction,widgetInfo&&widgetInfo.type,widgetId,getTracking(widgetInfo&&widgetInfo.type));}return {...widgetProps,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,graded:widgetInfo?.graded,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,showSolutions:this.props.showSolutions,onFocus:_.partial(this._onWidgetFocus,widgetId),onBlur:_.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.apiOptions?.interactionCallback?.(updatedUserInput);},trackInteraction:interactionTracker.track}}getSerializedState(){return mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}getPromptJSON(){const{content}=this.props;const widgetJSON={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);widgetJSON[id]=widget?.getPromptJSON?.()||{};});return {content,widgets:widgetJSON}}score(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();const content=this.getContent(this.props,this.state);this.widgetIds=[];if(this.shouldRenderJiptPlaceholder(this.props,this.state)){if(!this.translationIndex){this.translationIndex=getDependencies().rendererTranslationComponents.addComponent(this);}if(!apiOptions.isArticle){return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{"data-perseus-component-index":this.translationIndex,children:content})})}}this._isTwoColumn=false;const parsedMarkdown=this.props.inline?PerseusMarkdown.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown.parse(content,{isJipt:this.translationIndex!=null});if(this.props.linterContext.highlightLint){const fullLinterContext={content:this.props.content,widgets:this.props.widgets,...this.props.linterContext};PerseusLinter.runLinter(parsedMarkdown,fullLinterContext,true);this._translationLinter.applyLintErrors(parsedMarkdown,[...this.state.translationLintErrors,...this.props.legacyPerseusLint||[]]);}const markdownContents=this.outputMarkdown(parsedMarkdown,{baseElements:apiOptions.baseElements});const className=classNames$2({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},this._getDefaultWidgetInfo=widgetId=>{const widgetIdParts=Util.rTypeFromWidgetId.exec(widgetId);if(widgetIdParts==null){return {}}return {type:widgetIdParts[1],graded:true,options:{}}},this._getWidgetInfo=widgetId=>{return this.state.widgetInfo[widgetId]||this._getDefaultWidgetInfo(widgetId)},this.renderWidget=(impliedType,id,state)=>{const widgetInfo=this.state.widgetInfo[id];if(widgetInfo&&widgetInfo.alignment==="full-width"){state.foundFullWidth=true;}if(widgetInfo){const type=widgetInfo&&widgetInfo.type||impliedType;return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,widgetProps:this.getWidgetProps(id),linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},this.findInternalWidgets=filterCriterion=>{let filterFunc;if(typeof filterCriterion==="string"){if(filterCriterion.indexOf(" ")!==-1){const widgetId=filterCriterion;filterFunc=(id,widgetInfo,widget)=>id===widgetId;}else {const widgetType=filterCriterion;filterFunc=(id,widgetInfo,widget)=>{return widgetInfo.type===widgetType};}}else {filterFunc=filterCriterion;}const results=this.widgetIds.filter(id=>{const widgetInfo=this._getWidgetInfo(id);const widget=this.getWidgetInstance(id);return filterFunc(id,widgetInfo,widget)}).map(this.getWidgetInstance);return results},this.findWidgets=filterCriterion=>{return [...this.findInternalWidgets(filterCriterion),...this.props.findExternalWidgets(filterCriterion)]},this.getWidgetInstance=id=>{const ref=this._widgetContainers.get(makeContainerId(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!_.isArray(focusPath)){throw new PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!_.isEqual(fullPath,blurringFocusPath)){return}_.defer(()=>{if(_.isEqual(this._currentFocus,blurringFocusPath)){this._setCurrentFocus(null);}});},this.getContent=(props,state)=>{return state.jiptContent||props.content},this.shouldRenderJiptPlaceholder=(props,state)=>{return getDependencies().JIPT.useJIPT&&state.jiptContent==null&&props.content.indexOf("crwdns")!==-1},this.replaceJiptContent=(content,paragraphIndex)=>{if(paragraphIndex==null){this.setState({jiptContent:content});}else {const codeFenceRegex=/^\s*(`{3,}|~{3,})\s*(\S+)?\s*\n([\s\S]+?)\s*\1\s*$/;if(codeFenceRegex.test(content));else if(/\S\n\s*\n\S/.test(content)){content="$\\large{\\red{\\text{Please translate each "+"paragraph to a single paragraph.}}}$";}else if(/^\s*$/.test(content)){content="$\\large{\\red{\\text{Translated paragraph is "+"currently empty}}}$";}const allContent=this.getContent(this.props,this.state);const paragraphs=JiptParagraphs.parseToArray(allContent);paragraphs[paragraphIndex]=content;this.setState({jiptContent:JiptParagraphs.joinFromArray(paragraphs)});}},this.outputMarkdown=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;state.paragraphIndex=i;const nodeOut=this.outputMarkdown(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}this._foundTextNodes=false;state.foundFullWidth=false;const output=this.outputNested(ast,state);let className;if(this.translationIndex!=null){className=null;}else {className=classNames$2({"perseus-paragraph-centered":!this._foundTextNodes,"perseus-paragraph-full-width":state.foundFullWidth&&ast.content.length===1});}return jsxRuntimeExports.jsx(QuestionParagraph,{className:className,translationIndex:this.translationIndex,paragraphIndex:state.paragraphIndex,inline:this.props.inline,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:output})},state.key)},this.outputNested=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;const nodeOut=this.outputNested(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}return this.outputNode(ast,this.outputNested,state)},this.outputNode=(node,nestedOutput,state)=>{const apiOptions=this.getApiOptions();const imagePlaceholder=apiOptions.imagePlaceholder;if(node.type==="widget"){const widgetPlaceholder=apiOptions.widgetPlaceholder;if(widgetPlaceholder){return widgetPlaceholder}this._foundTextNodes=true;if(this.widgetIds.includes(node.id)){return jsxRuntimeExports.jsx("span",{className:"renderer-widget-error",children:["Widget [[","☃"," ",node.id,"]] already exists."].join("")},state.key)}this.widgetIds.push(node.id);return this.renderWidget(node.widgetType,node.id,state)}if(node.type==="blockMath"){const content=preprocessTex(node.content);const innerStyle={overflowX:"auto",overflowY:"hidden",paddingTop:10,paddingBottom:10,marginTop:-10,marginBottom:-10};if(apiOptions.isMobile){const margin=16;const outerStyle={marginLeft:-16,marginRight:-16};const horizontalPadding={paddingLeft:margin,paddingRight:margin};const mobileInnerStyle={...innerStyle,...styles$z.mobileZoomableParentFix};return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",style:outerStyle,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:{...mobileInnerStyle,...horizontalPadding},children:jsxRuntimeExports.jsx(ZoomableTeX,{children:content})})})},state.key)}return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:innerStyle,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{setAssetStatus:setAssetStatus,children:content})})})})},state.key)}if(node.type==="math"){const tex=node.content;return jsxRuntimeExports.jsx("span",{style:{whiteSpace:"nowrap"},children:jsxRuntimeExports.jsxs(ErrorBoundary,{children:[jsxRuntimeExports.jsx("span",{}),jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{onRender:this.props.onRender,setAssetStatus:setAssetStatus,children:tex})}),jsxRuntimeExports.jsx("span",{})]})},state.key)}if(node.type==="image"){if(imagePlaceholder){return imagePlaceholder}const extraAttrs=_.has(this.props.images,node.target)?this.props.images[node.target]:null;const responsive=!state.inTable;return jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{allowZoom:true,setAssetStatus:setAssetStatus,src:PerseusMarkdown.sanitizeUrl(node.target),alt:node.alt,title:node.title,responsive:responsive,onUpdate:this.props.onRender,zoomToFullSizeOnMobile:apiOptions.isMobile&&apiOptions.isArticle,...extraAttrs})})},state.key)}if(node.type==="columns"){this._isTwoColumn=true;return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown.ruleOutput(node,nestedOutput,{...state,isMobile:apiOptions.isMobile,inTable:true});if(!apiOptions.isMobile){return output}const outerStyle={marginLeft:-16,marginRight:-16};const innerStyle={paddingLeft:0,paddingRight:0};const mobileInnerStyle={...innerStyle,...styles$z.mobileZoomableParentFix};const wrappedOutput=jsxRuntimeExports.jsx("div",{style:{...mobileInnerStyle,overflowX:"auto"},children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(Zoomable,{animateHeight:true,children:output})})});return jsxRuntimeExports.jsx("div",{style:outerStyle,children:wrappedOutput})}return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender||oldOnRender!==noopOnRender){const $images=$(ReactDOM__default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender){$images.off("load",oldOnRender);}if(onRender!==noopOnRender){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix(path,this._currentFocus)){const prevFocus=this._currentFocus;if(prevFocus){this.blurPath(prevFocus);}this._currentFocus=path;apiOptions.onFocusChange(this._currentFocus,prevFocus);}},this.focus=()=>{let id;let focusResult;for(let i=0;i<this.widgetIds.length;i++){const widgetId=this.widgetIds[i];const widget=this.getWidgetInstance(widgetId);const widgetFocusResult=widget?.focus?.();if(widgetFocusResult){id=widgetId;focusResult=widgetFocusResult;break}}if(id){let path;if(typeof focusResult==="object"){path=[id].concat(focusResult.path||[]);Log.error("Renderer received a focus result of type 'object' "+"instead of the expected type 'boolean'",Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){const container=this._widgetContainers.get(makeContainerId(widgetId));if(container){return ReactDOM__default.findDOMNode(container)}return ReactDOM__default.findDOMNode(widget)}},this.getInputPaths=()=>{const inputPaths=[];this.widgetIds.forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getInputPaths){const widgetInputPaths=widget.getInputPaths();widgetInputPaths.forEach(inputPath=>{const relativeInputPath=[widgetId].concat(inputPath);inputPaths.push(relativeInputPath);});}});return inputPaths},this.focusPath=path=>{if(_.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!_.isEqual(this._currentFocus,path)){return}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget){const blurWidget=this.getWidgetInstance(widgetId);blurWidget?.blurInputPath?.(interWidgetPath);}},this.blur=()=>{if(this._currentFocus){this.blurPath(this._currentFocus);}},this.serialize=()=>{const state={};_.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!_.isEmpty(s)){state[id]=s;}},this);return state},this.getWidgetIds=()=>{return this.widgetIds},this.handletranslationLintErrors=lintErrors=>{if(!this._isMounted){return}this.setState({translationLintErrors:lintErrors});};this._translationLinter=new TranslationLinter;this.state={jiptContent:null,translationLintErrors:[],...this._getInitialWidgetState(props)};}}Renderer.contextType=PerseusI18nContext;Renderer.defaultProps={content:"",widgets:{},images:{},showSolutions:"none",onRender:noopOnRender,findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter.linterContextDefault};const styles$z={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
1676
+ const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return _.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return _.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion(propsA,propsB){function makeItem(props){return splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!_.isEqual(makeItem(propsA),makeItem(propsB))}class Renderer extends React.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!_.isEqual(this.state,nextState);const propsChanged=!_.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput&&!_.isEqual(this.props.userInput,prevProps.userInput)){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_isAnswerable(){if(this.props.userInput){return this.emptyWidgets().length===0}return false}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];if(!this._interactionTrackers){this._interactionTrackers={};}let interactionTracker=this._interactionTrackers[widgetId];if(!interactionTracker){interactionTracker=this._interactionTrackers[widgetId]=new InteractionTracker(apiOptions.trackInteraction,widgetInfo&&widgetInfo.type,widgetId,getTracking(widgetInfo&&widgetInfo.type));}return {...widgetProps,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,graded:widgetInfo?.graded,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,showSolutions:this.props.showSolutions,onFocus:_.partial(this._onWidgetFocus,widgetId),onBlur:_.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.apiOptions?.interactionCallback?.(updatedUserInput);},trackInteraction:interactionTracker.track}}getSerializedState(){return mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}getPromptJSON(){const{content}=this.props;const widgetJSON={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);widgetJSON[id]=widget?.getPromptJSON?.()||{};});return {content,widgets:widgetJSON}}score(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();const content=this.getContent(this.props,this.state);this.widgetIds=[];if(this.shouldRenderJiptPlaceholder(this.props,this.state)){if(!this.translationIndex){this.translationIndex=getDependencies().rendererTranslationComponents.addComponent(this);}if(!apiOptions.isArticle){return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{"data-perseus-component-index":this.translationIndex,children:content})})}}this._isTwoColumn=false;const parsedMarkdown=this.props.inline?PerseusMarkdown.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown.parse(content,{isJipt:this.translationIndex!=null});if(this.props.linterContext.highlightLint){const fullLinterContext={content:this.props.content,widgets:this.props.widgets,...this.props.linterContext};PerseusLinter.runLinter(parsedMarkdown,fullLinterContext,true);this._translationLinter.applyLintErrors(parsedMarkdown,[...this.state.translationLintErrors,...this.props.legacyPerseusLint||[]]);}const markdownContents=this.outputMarkdown(parsedMarkdown,{baseElements:apiOptions.baseElements});const className=classNames$2({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},this._getDefaultWidgetInfo=widgetId=>{const widgetIdParts=Util.rTypeFromWidgetId.exec(widgetId);if(widgetIdParts==null){return {}}return {type:widgetIdParts[1],graded:true,options:{}}},this._getWidgetInfo=widgetId=>{return this.state.widgetInfo[widgetId]||this._getDefaultWidgetInfo(widgetId)},this.renderWidget=(impliedType,id,state)=>{const widgetInfo=this.state.widgetInfo[id];if(widgetInfo&&widgetInfo.alignment==="full-width"){state.foundFullWidth=true;}if(widgetInfo){const type=widgetInfo&&widgetInfo.type||impliedType;return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,widgetProps:this.getWidgetProps(id),linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},this.findInternalWidgets=filterCriterion=>{let filterFunc;if(typeof filterCriterion==="string"){if(filterCriterion.indexOf(" ")!==-1){const widgetId=filterCriterion;filterFunc=(id,widgetInfo,widget)=>id===widgetId;}else {const widgetType=filterCriterion;filterFunc=(id,widgetInfo,widget)=>{return widgetInfo.type===widgetType};}}else {filterFunc=filterCriterion;}const results=this.widgetIds.filter(id=>{const widgetInfo=this._getWidgetInfo(id);const widget=this.getWidgetInstance(id);return filterFunc(id,widgetInfo,widget)}).map(this.getWidgetInstance);return results},this.findWidgets=filterCriterion=>{return [...this.findInternalWidgets(filterCriterion),...this.props.findExternalWidgets(filterCriterion)]},this.getWidgetInstance=id=>{const ref=this._widgetContainers.get(makeContainerId(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!_.isArray(focusPath)){throw new PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!_.isEqual(fullPath,blurringFocusPath)){return}_.defer(()=>{if(_.isEqual(this._currentFocus,blurringFocusPath)){this._setCurrentFocus(null);}});},this.getContent=(props,state)=>{return state.jiptContent||props.content},this.shouldRenderJiptPlaceholder=(props,state)=>{return getDependencies().JIPT.useJIPT&&state.jiptContent==null&&props.content.indexOf("crwdns")!==-1},this.replaceJiptContent=(content,paragraphIndex)=>{if(paragraphIndex==null){this.setState({jiptContent:content});}else {const codeFenceRegex=/^\s*(`{3,}|~{3,})\s*(\S+)?\s*\n([\s\S]+?)\s*\1\s*$/;if(codeFenceRegex.test(content));else if(/\S\n\s*\n\S/.test(content)){content="$\\large{\\red{\\text{Please translate each "+"paragraph to a single paragraph.}}}$";}else if(/^\s*$/.test(content)){content="$\\large{\\red{\\text{Translated paragraph is "+"currently empty}}}$";}const allContent=this.getContent(this.props,this.state);const paragraphs=JiptParagraphs.parseToArray(allContent);paragraphs[paragraphIndex]=content;this.setState({jiptContent:JiptParagraphs.joinFromArray(paragraphs)});}},this.outputMarkdown=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;state.paragraphIndex=i;const nodeOut=this.outputMarkdown(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}this._foundTextNodes=false;state.foundFullWidth=false;const output=this.outputNested(ast,state);let className;if(this.translationIndex!=null){className=null;}else {className=classNames$2({"perseus-paragraph-centered":!this._foundTextNodes,"perseus-paragraph-full-width":state.foundFullWidth&&ast.content.length===1});}return jsxRuntimeExports.jsx(QuestionParagraph,{className:className,translationIndex:this.translationIndex,paragraphIndex:state.paragraphIndex,inline:this.props.inline,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:output})},state.key)},this.outputNested=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;const nodeOut=this.outputNested(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}return this.outputNode(ast,this.outputNested,state)},this.outputNode=(node,nestedOutput,state)=>{const apiOptions=this.getApiOptions();const imagePlaceholder=apiOptions.imagePlaceholder;if(node.type==="widget"){const widgetPlaceholder=apiOptions.widgetPlaceholder;if(widgetPlaceholder){return widgetPlaceholder}this._foundTextNodes=true;if(this.widgetIds.includes(node.id)){return jsxRuntimeExports.jsx("span",{className:"renderer-widget-error",children:["Widget [[","☃"," ",node.id,"]] already exists."].join("")},state.key)}this.widgetIds.push(node.id);return this.renderWidget(node.widgetType,node.id,state)}if(node.type==="blockMath"){const content=preprocessTex(node.content);const innerStyle={overflowX:"auto",overflowY:"hidden",paddingTop:10,paddingBottom:10,marginTop:-10,marginBottom:-10};if(apiOptions.isMobile){const margin=16;const outerStyle={marginLeft:-16,marginRight:-16};const horizontalPadding={paddingLeft:margin,paddingRight:margin};const mobileInnerStyle={...innerStyle,...styles$A.mobileZoomableParentFix};return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",style:outerStyle,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:{...mobileInnerStyle,...horizontalPadding},children:jsxRuntimeExports.jsx(ZoomableTeX,{children:content})})})},state.key)}return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:innerStyle,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{setAssetStatus:setAssetStatus,children:content})})})})},state.key)}if(node.type==="math"){const tex=node.content;return jsxRuntimeExports.jsx("span",{style:{whiteSpace:"nowrap"},children:jsxRuntimeExports.jsxs(ErrorBoundary,{children:[jsxRuntimeExports.jsx("span",{}),jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{onRender:this.props.onRender,setAssetStatus:setAssetStatus,children:tex})}),jsxRuntimeExports.jsx("span",{})]})},state.key)}if(node.type==="image"){if(imagePlaceholder){return imagePlaceholder}const extraAttrs=_.has(this.props.images,node.target)?this.props.images[node.target]:null;const responsive=!state.inTable;return jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{allowZoom:true,setAssetStatus:setAssetStatus,src:PerseusMarkdown.sanitizeUrl(node.target),alt:node.alt,title:node.title,responsive:responsive,onUpdate:this.props.onRender,zoomToFullSizeOnMobile:apiOptions.isMobile&&apiOptions.isArticle,...extraAttrs})})},state.key)}if(node.type==="columns"){this._isTwoColumn=true;return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown.ruleOutput(node,nestedOutput,{...state,isMobile:apiOptions.isMobile,inTable:true});if(!apiOptions.isMobile){return output}const outerStyle={marginLeft:-16,marginRight:-16};const innerStyle={paddingLeft:0,paddingRight:0};const mobileInnerStyle={...innerStyle,...styles$A.mobileZoomableParentFix};const wrappedOutput=jsxRuntimeExports.jsx("div",{style:{...mobileInnerStyle,overflowX:"auto"},children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(Zoomable,{animateHeight:true,children:output})})});return jsxRuntimeExports.jsx("div",{style:outerStyle,children:wrappedOutput})}return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender||oldOnRender!==noopOnRender){const $images=$(ReactDOM__default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender){$images.off("load",oldOnRender);}if(onRender!==noopOnRender){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix(path,this._currentFocus)){const prevFocus=this._currentFocus;if(prevFocus){this.blurPath(prevFocus);}this._currentFocus=path;apiOptions.onFocusChange(this._currentFocus,prevFocus);}},this.focus=()=>{let id;let focusResult;for(let i=0;i<this.widgetIds.length;i++){const widgetId=this.widgetIds[i];const widget=this.getWidgetInstance(widgetId);const widgetFocusResult=widget?.focus?.();if(widgetFocusResult){id=widgetId;focusResult=widgetFocusResult;break}}if(id){let path;if(typeof focusResult==="object"){path=[id].concat(focusResult.path||[]);Log.error("Renderer received a focus result of type 'object' "+"instead of the expected type 'boolean'",Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){const container=this._widgetContainers.get(makeContainerId(widgetId));if(container){return ReactDOM__default.findDOMNode(container)}return ReactDOM__default.findDOMNode(widget)}},this.getInputPaths=()=>{const inputPaths=[];this.widgetIds.forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getInputPaths){const widgetInputPaths=widget.getInputPaths();widgetInputPaths.forEach(inputPath=>{const relativeInputPath=[widgetId].concat(inputPath);inputPaths.push(relativeInputPath);});}});return inputPaths},this.focusPath=path=>{if(_.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!_.isEqual(this._currentFocus,path)){return}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget){const blurWidget=this.getWidgetInstance(widgetId);blurWidget?.blurInputPath?.(interWidgetPath);}},this.blur=()=>{if(this._currentFocus){this.blurPath(this._currentFocus);}},this.serialize=()=>{const state={};_.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!_.isEmpty(s)){state[id]=s;}},this);return state},this.getWidgetIds=()=>{return this.widgetIds},this.handletranslationLintErrors=lintErrors=>{if(!this._isMounted){return}this.setState({translationLintErrors:lintErrors});};this._translationLinter=new TranslationLinter;this.state={jiptContent:null,translationLintErrors:[],...this._getInitialWidgetState(props)};}}Renderer.contextType=PerseusI18nContext;Renderer.defaultProps={content:"",widgets:{},images:{},showSolutions:"none",onRender:noopOnRender,findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter.linterContextDefault};const styles$A={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
1677
1677
 
1678
1678
  const{captureScratchpadTouchStart: captureScratchpadTouchStart$1}=Util;const InputWithExamples=forwardRef(function InputWithExamples({shouldShowExamples=true,onFocus=()=>{},onBlur=()=>{},disabled=false,linterContext=PerseusLinter.linterContextDefault,className="",...props},ref){const context=React.useContext(PerseusI18nContext);const inputRef=React.useRef(null);const[inputFocused,setInputFocused]=React.useState(false);const id=useId();const ariaId=`aria-for-${id}`;useImperativeHandle(ref,()=>({current:inputRef.current,focus:()=>{if(inputRef.current){inputRef.current.focus();}},blur:()=>{if(inputRef.current){inputRef.current.blur();}}}));const getInputClassName=()=>{let inputClassName=ClassNames.INPUT;if(inputFocused){inputClassName+=" "+ClassNames.FOCUSED;}if(className){inputClassName+=" "+className;}return inputClassName};const handleFocus=()=>{onFocus();setInputFocused(true);};const handleBlur=()=>{onBlur();setInputFocused(false);};const renderInput=()=>{const examplesAria=shouldShowExamples?`${props.examples[0]}
1679
1679
  ${props.examples.slice(1).join(", or\n")}`.replace(/\*/g,"").replace(/\$/g,"").replace(/\\ \\text{pi}/g," pi").replace(/\\ /g," 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$1,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(TooltipContent,{children:jsxRuntimeExports.jsx("div",{id:id,className:"input-with-examples-tooltip",children:jsxRuntimeExports.jsx(Renderer,{content:examplesContent,linterContext:PerseusLinter.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}
@@ -1681,41 +1681,41 @@ const{captureScratchpadTouchStart: captureScratchpadTouchStart$1}=Util;const Inp
1681
1681
 
1682
1682
  const getPromptJSON$p=widgetData=>{return {type:"numeric-input",label:widgetData.labelText,userInput:{value:widgetData.userInput.currentValue}}};
1683
1683
 
1684
- var styles$y = {"inputWithExamples":"perseus_QUlWSKE-","isFocused":"perseus_8i8MUC5K","rightAlign":"perseus_9cRSmuw9","sizeSmall":"perseus_LbMErCm0"};
1684
+ var styles$z = {"inputWithExamples":"perseus_QUlWSKE-","isFocused":"perseus_8i8MUC5K","rightAlign":"perseus_9cRSmuw9","sizeSmall":"perseus_LbMErCm0"};
1685
1685
 
1686
- const styles$x={inputWithExamples:{borderRadius:"0.3rem",borderWidth:"var(--wb-border-width-thin)",direction:"ltr",display:"inline-block",fontFamily:'Symbola, "Times New Roman", serif',fontSize:"1.8rem",height:"3.2rem",lineHeight:"1.8rem",padding:"0.4rem 0.5rem",textAlign:"left",width:"8rem"},isFocused:{borderWidth:"var(--wb-border-width-medium)",padding:"0.4rem"},rightAlign:{textAlign:"right"},sizeSmall:{width:"4rem"}};
1686
+ const styles$y={inputWithExamples:{borderRadius:"0.3rem",borderWidth:"var(--wb-border-width-thin)",direction:"ltr",display:"inline-block",fontFamily:'Symbola, "Times New Roman", serif',fontSize:"1.8rem",height:"3.2rem",lineHeight:"1.8rem",padding:"0.4rem 0.5rem",textAlign:"left",width:"8rem"},isFocused:{borderWidth:"var(--wb-border-width-medium)",padding:"0.4rem"},rightAlign:{textAlign:"right"},sizeSmall:{width:"4rem"}};
1687
1687
 
1688
1688
  const NumericExampleStrings={integer:(form,strings)=>strings.integerExample,proper:(form,strings)=>form.simplify==="optional"?strings.properExample:strings.simplifiedProperExample,improper:(form,strings)=>form.simplify==="optional"?strings.improperExample:strings.simplifiedImproperExample,mixed:(form,strings)=>strings.mixedExample,decimal:(form,strings)=>strings.decimalExample,percent:(form,strings)=>strings.percentExample,pi:(form,strings)=>strings.piExample};const generateExamples=(answerForms,strings)=>{if(answerForms.length===0){return []}const uniqueForms=getUniqueAnswerForms(answerForms);const examples=uniqueForms.map(form=>{return NumericExampleStrings[form.name](form,strings)});return [strings.yourAnswer].concat(examples)};const shouldShowExamples=answerForms=>{if(answerForms.length===0){return false}const answerFormNames=getUniqueAnswerForms(answerForms).map(form=>form.name);const allFormsAccepted=answerFormNames.length>=Object.keys(NumericExampleStrings).length;return !allFormsAccepted};const getUniqueAnswerForms=function(list){const foundForms=new Set;return list.filter(form=>{if(foundForms.has(form.name)){return false}foundForms.add(form.name);return true})};const unionAnswerForms=function(answerFormsList){const allForms=answerFormsList.flat();const uniqueForms=getUniqueAnswerForms(allForms);const formExampleKeys=Object.keys(NumericExampleStrings);return uniqueForms.sort((a,b)=>{return formExampleKeys.indexOf(a.name)-formExampleKeys.indexOf(b.name)})};function normalizeCorrectAnswerForms(answers){if(answers==null){return []}return unionAnswerForms(answers.filter(answer=>answer.status==="correct").map(answer=>{return (answer.answerForms||[]).map(form=>{return {simplify:answer.simplify,name:form}})}))}
1689
1689
 
1690
- const NumericInputComponent=forwardRef(function NumericInputComponent(props,ref){const{analytics}=useDependencies();const context=useContext(PerseusI18nContext);const inputRef=useRef(null);const[isFocused,setIsFocused]=useState(false);useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"numeric-input",widgetId:props.widgetId}});});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 legacyStylesToUse={...styles$x.inputWithExamples,...isFocused?styles$x.isFocused:{},...props.rightAlign?styles$x.rightAlign:{},...props.size==="small"?styles$x.sizeSmall:{}};const classesToUse=[styles$y.inputWithExamples];if(isFocused){classesToUse.push(styles$y.isFocused);}if(props.rightAlign){classesToUse.push(styles$y.rightAlign);}if(props.size==="small"){classesToUse.push(styles$y.sizeSmall);}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||context.strings.yourAnswerLabel,examples:generateExamples(props.answerForms,context.strings),shouldShowExamples:shouldShowExamples(props.answerForms),onFocus:handleFocus,onBlur:handleBlur,id:props.widgetId,disabled:props.apiOptions.readOnly,style:legacyStylesToUse,className:classesToUse.join(" ")})});
1690
+ const NumericInputComponent=forwardRef(function NumericInputComponent(props,ref){const{analytics}=useDependencies();const context=useContext(PerseusI18nContext);const inputRef=useRef(null);const[isFocused,setIsFocused]=useState(false);useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"numeric-input",widgetId:props.widgetId}});});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 legacyStylesToUse={...styles$y.inputWithExamples,...isFocused?styles$y.isFocused:{},...props.rightAlign?styles$y.rightAlign:{},...props.size==="small"?styles$y.sizeSmall:{}};const classesToUse=[styles$z.inputWithExamples];if(isFocused){classesToUse.push(styles$z.isFocused);}if(props.rightAlign){classesToUse.push(styles$z.rightAlign);}if(props.size==="small"){classesToUse.push(styles$z.sizeSmall);}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||context.strings.yourAnswerLabel,examples:generateExamples(props.answerForms,context.strings),shouldShowExamples:shouldShowExamples(props.answerForms),onFocus:handleFocus,onBlur:handleBlur,id:props.widgetId,disabled:props.apiOptions.readOnly,style:legacyStylesToUse,className:classesToUse.join(" ")})});
1691
1691
 
1692
1692
  class NumericInput extends React.Component{getPromptJSON(){return getPromptJSON$p(this.props)}getSerializedState(){const{userInput,answers:_,...rest}=this.props;return {...rest,currentValue:userInput.currentValue}}render(){return jsxRuntimeExports.jsx(NumericInputComponent,{...this.props,answerForms:normalizeCorrectAnswerForms(this.props.answers),ref:this.inputRef})}constructor(...args){super(...args),this.inputRef=React.createRef(),this.focus=()=>{this.inputRef.current?.focus();return true},this.blur=()=>{this.inputRef.current?.blur();},this.focusInputPath=()=>{this.inputRef.current?.focus();},this.blurInputPath=()=>{this.inputRef.current?.blur();},this.getInputPaths=()=>{return [[]]};}}NumericInput.defaultProps={size:"normal",rightAlign:false,apiOptions:ApiOptions.defaults,coefficient:false,answerForms:[],labelText:"",linterContext:linterContextDefault,userInput:{currentValue:""}};function getStartUserInput$i(){return {currentValue:""}}function getUserInputFromSerializedState$h(serializedState){return {currentValue:serializedState.currentValue}}function findPrecision(value){for(let i=0;i<10;i++){if(value===+value.toFixed(i)){return i}}return 10}function findCommonFractions(value){const whole=Math.floor(value);if(value===whole){return}const decimal=value-whole;const precision=findPrecision(decimal);for(let num=1;num<100;num++){for(let denom=2;denom<100;denom++){if(+(num/denom).toFixed(precision)===decimal){return {num:num+whole*denom,denom}}}}}function getCorrectUserInput$9(options){for(const answer of options.answers){if(answer.status==="correct"&&answer.value!=null){if(answer.answerForms?.includes("decimal")){return {currentValue:answer.value.toString()}}if(answer.answerForms?.includes("improper")){const frac=findCommonFractions(answer.value);if(frac){return {currentValue:`${frac.num}/${frac.denom}`}}}if(answer.answerForms?.includes("proper")){const frac=findCommonFractions(answer.value);if(frac){const{num,denom}=frac;if(num>denom){const whole=Math.floor(num/denom);const remainder=num-whole*denom;return {currentValue:`${whole} ${remainder}/${denom}`}}else {return {currentValue:`${num}/${denom}`}}}}return {currentValue:answer.value.toString()}}}return {currentValue:""}}var NumericInput$1 = {name:"numeric-input",displayName:"Numeric input",widget:NumericInput,isLintable:true,getCorrectUserInput: getCorrectUserInput$9,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=KhanMath.toNumericString(answer.value,format);if(answer.maxError){answerString+=" ± "+KhanMath.toNumericString(answer.maxError,format);}return answerString});if(answerStrings.length===0){return}return answerStrings[0]},getStartUserInput: getStartUserInput$i,getUserInputFromSerializedState: getUserInputFromSerializedState$h};
1693
1693
 
1694
- 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.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"input-number",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$q(this.props)}examples(){const{strings}=this.context;const type=this.props.answerType;const forms=inputNumberAnswerTypes[type].forms.split(/\s*,\s*/);const examples=forms.map(form=>formExamples[form](this.props,strings));return [strings.yourAnswer].concat(examples)}getSerializedState(){return {alignment:this.props.alignment,static:this.props.static,simplify:this.props.simplify,size:this.props.size,answerType:this.props.answerType,rightAlign:this.props.rightAlign,currentValue:this.props.userInput.currentValue}}render(){if(isFeatureOn(this.props,"input-number-to-numeric-input")){const numericInputOptions=convertInputNumberOptionsToNumericInput(this.props);return jsxRuntimeExports.jsx(NumericInput,{...this.props,...numericInputOptions,labelText:"",ref:this.handleInputRef})}if(this.props.apiOptions.customKeypad){const input=jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:this.handleInputRef,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$w.default,this.props.size==="small"?styles$w.small:null,this.props.rightAlign?styles$w.rightAlign:styles$w.leftAlign];if(this.props.reviewMode&&!this.props.userInput.currentValue){inputStyles.push(styles$w.answerStateUnanswered);}return jsxRuntimeExports.jsx(InputWithExamples,{ref:this.handleInputRef,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.inputRef={current:null},this.handleInputRef=instance=>{this.inputRef.current=instance;},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.inputRef.current?.focus();return true},this.focusInputPath=()=>{this.inputRef.current?.focus();},this.blurInputPath=()=>{this.inputRef.current?.blur();},this.getInputPaths=()=>{return [[]]};}}InputNumber.contextType=PerseusI18nContext;InputNumber.defaultProps={size:"normal",answerType:"number",rightAlign:false,apiOptions:ApiOptions.defaults,linterContext:linterContextDefault,userInput:{currentValue:""}};const styles$w=StyleSheet.create({default:{width:80,height:"auto",direction:"ltr"},small:{width:40},leftAlign:{paddingLeft:spacing.xxxSmall_4,paddingRight:0},rightAlign:{textAlign:"right",paddingLeft:0,paddingRight:spacing.xxxSmall_4},answerStateUnanswered:{backgroundColor:"#eee",border:"solid 1px #999"}});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}}function getStartUserInput$h(){return {currentValue:""}}function getCorrectUserInput$8(options){return {currentValue:options.value.toString()}}const WrappedInputNumber=withDependencies(InputNumber);var InputNumber$1 = {name:"input-number",displayName:"Input number (deprecated - use numeric input instead)",hidden:true,widget:WrappedInputNumber,isLintable:true,getOneCorrectAnswerFromRubric,getStartUserInput: getStartUserInput$h,getCorrectUserInput: getCorrectUserInput$8,getUserInputFromSerializedState: getUserInputFromSerializedState$g};
1694
+ 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.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"input-number",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$q(this.props)}examples(){const{strings}=this.context;const type=this.props.answerType;const forms=inputNumberAnswerTypes[type].forms.split(/\s*,\s*/);const examples=forms.map(form=>formExamples[form](this.props,strings));return [strings.yourAnswer].concat(examples)}getSerializedState(){return {alignment:this.props.alignment,static:this.props.static,simplify:this.props.simplify,size:this.props.size,answerType:this.props.answerType,rightAlign:this.props.rightAlign,currentValue:this.props.userInput.currentValue}}render(){if(isFeatureOn(this.props,"input-number-to-numeric-input")){const numericInputOptions=convertInputNumberOptionsToNumericInput(this.props);return jsxRuntimeExports.jsx(NumericInput,{...this.props,...numericInputOptions,labelText:"",ref:this.handleInputRef})}if(this.props.apiOptions.customKeypad){const input=jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:this.handleInputRef,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$x.default,this.props.size==="small"?styles$x.small:null,this.props.rightAlign?styles$x.rightAlign:styles$x.leftAlign];if(this.props.reviewMode&&!this.props.userInput.currentValue){inputStyles.push(styles$x.answerStateUnanswered);}return jsxRuntimeExports.jsx(InputWithExamples,{ref:this.handleInputRef,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.inputRef={current:null},this.handleInputRef=instance=>{this.inputRef.current=instance;},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.inputRef.current?.focus();return true},this.focusInputPath=()=>{this.inputRef.current?.focus();},this.blurInputPath=()=>{this.inputRef.current?.blur();},this.getInputPaths=()=>{return [[]]};}}InputNumber.contextType=PerseusI18nContext;InputNumber.defaultProps={size:"normal",answerType:"number",rightAlign:false,apiOptions:ApiOptions.defaults,linterContext:linterContextDefault,userInput:{currentValue:""}};const styles$x=StyleSheet.create({default:{width:80,height:"auto",direction:"ltr"},small:{width:40},leftAlign:{paddingLeft:spacing.xxxSmall_4,paddingRight:0},rightAlign:{textAlign:"right",paddingLeft:0,paddingRight:spacing.xxxSmall_4},answerStateUnanswered:{backgroundColor:"#eee",border:"solid 1px #999"}});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}}function getStartUserInput$h(){return {currentValue:""}}function getCorrectUserInput$8(options){return {currentValue:options.value.toString()}}const WrappedInputNumber=withDependencies(InputNumber);var InputNumber$1 = {name:"input-number",displayName:"Input number (deprecated - use numeric input instead)",hidden:true,widget:WrappedInputNumber,isLintable:true,getOneCorrectAnswerFromRubric,getStartUserInput: getStartUserInput$h,getCorrectUserInput: getCorrectUserInput$8,getUserInputFromSerializedState: getUserInputFromSerializedState$g};
1695
1695
 
1696
1696
  const MathRenderingContext=React.createContext({shouldAddAriaLabels:false});
1697
1697
 
1698
1698
  const getPromptJSON$o=(widgetData,userInput)=>{const choices=widgetData.choices||[];const options=choices.map(choice=>{const option={value:choice.content,id:choice.id};if(choice.rationale){option.rationale=choice.rationale;}return option});const hasNoneOfTheAbove=choices.some(choice=>choice.isNoneOfTheAbove);return {type:"radio",hasNoneOfTheAbove,options,userInput:{selectedOptions:userInput?.selectedChoiceIds??[]}}};
1699
1699
 
1700
- var styles$v = {"scrollButtonsContainer":"perseus_kjDHiWdD"};
1700
+ var styles$w = {"scrollButtonsContainer":"perseus_kjDHiWdD"};
1701
1701
 
1702
- const SCROLL_DISTANCE=100;const scrollInstances=new Map;function ScrollableArea({overflowX,overflowY,children,className,scrollDescription,style,role="group",id:providedId,...additionalProps}){const{strings}=usePerseusI18n();const containerRef=useRef(null);const[isScrollable,setIsScrollable]=useState(false);const[isScrolling,setIsScrolling]=useState(false);const generatedId=React.useId();const id=providedId||generatedId;const scrollableThreshold=React.useMemo(()=>{return window.innerWidth<=767?8:5},[]);const scroll=React.useCallback(direction=>{if(!containerRef.current||isScrolling){return}setIsScrolling(true);const contentIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const scrollNegative=contentIsRtl&&direction==="end"||!contentIsRtl&&direction==="start";const scrollAmount=scrollNegative?-100:SCROLL_DISTANCE;containerRef.current.scrollBy({left:scrollAmount,behavior:"smooth"});setTimeout(()=>{setIsScrolling(false);},150);},[isScrolling]);const updateScrollState=React.useCallback(()=>{if(!containerRef.current){return}const{scrollLeft,scrollWidth,clientWidth}=containerRef.current;const newIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const newIsScrollable=scrollWidth>clientWidth+scrollableThreshold;setIsScrollable(newIsScrollable);let newCanScrollStart;let newCanScrollEnd;if(newIsRtl){newCanScrollStart=scrollLeft<-scrollableThreshold;newCanScrollEnd=Math.abs(scrollLeft)<scrollWidth-clientWidth-scrollableThreshold;}else {newCanScrollStart=scrollLeft>scrollableThreshold;newCanScrollEnd=scrollLeft+clientWidth<scrollWidth-scrollableThreshold;}const scrollState={isScrollable:newIsScrollable,canScrollStart:newCanScrollStart,canScrollEnd:newCanScrollEnd,isRTL:newIsRtl,scroll,scrollDescription:scrollDescription||strings.scrollAnswers};scrollInstances.set(id,scrollState);},[id,scrollableThreshold,scrollDescription,strings.scrollAnswers,scroll]);useEffect(()=>{const container=containerRef.current;if(!container){return}updateScrollState();container.addEventListener("scroll",updateScrollState);window.addEventListener("resize",updateScrollState);return ()=>{container.removeEventListener("scroll",updateScrollState);window.removeEventListener("resize",updateScrollState);scrollInstances.delete(id);}},[children,updateScrollState,id]);const mergeStyle={overflowX:isScrollable&&overflowX==="auto"?"scroll":overflowX,overflowY:isScrollable&&overflowY==="auto"?"scroll":overflowY,scrollbarWidth:"thin",...style};return jsxRuntimeExports.jsx("div",{...additionalProps,id:id,role:role,className:className,style:mergeStyle,ref:containerRef,children:children})}function ScrollControls({target,scrollDescription:overrideDescription}){const{strings}=usePerseusI18n();const[scrollState,setScrollState]=useState(null);useEffect(()=>{if(!target){return}const checkForScrollState=()=>{const state=scrollInstances.get(target);if(state){setScrollState(state);}};checkForScrollState();const interval=setInterval(checkForScrollState,100);return ()=>{clearInterval(interval);}},[target]);if(!scrollState||!scrollState.isScrollable){return null}const description=overrideDescription||scrollState.scrollDescription;return jsxRuntimeExports.jsxs("div",{className:styles$v.scrollButtonsContainer,"aria-live":"polite",role:"group","aria-label":description,children:[jsxRuntimeExports.jsx(IconButton,{icon:scrollState.isRTL?caretRightIcon:caretLeftIcon,actionType:"neutral",kind:"secondary",size:"small",onClick:()=>scrollState.scroll("start"),"aria-label":strings.scrollStart,disabled:!scrollState.canScrollStart}),jsxRuntimeExports.jsx(IconButton,{icon:scrollState.isRTL?caretLeftIcon:caretRightIcon,actionType:"neutral",kind:"secondary",size:"small",onClick:()=>scrollState.scroll("end"),"aria-label":strings.scrollEnd,disabled:!scrollState.canScrollEnd}),jsxRuntimeExports.jsx(BodyText,{size:"small",children:description})]})}const ScrollableView=ScrollableArea;ScrollableView.Controls=ScrollControls;
1702
+ const SCROLL_DISTANCE=100;const scrollInstances=new Map;function ScrollableArea({overflowX,overflowY,children,className,scrollDescription,style,role="group",id:providedId,...additionalProps}){const{strings}=usePerseusI18n();const containerRef=useRef(null);const[isScrollable,setIsScrollable]=useState(false);const[isScrolling,setIsScrolling]=useState(false);const generatedId=React.useId();const id=providedId||generatedId;const scrollableThreshold=React.useMemo(()=>{return window.innerWidth<=767?8:5},[]);const scroll=React.useCallback(direction=>{if(!containerRef.current||isScrolling){return}setIsScrolling(true);const contentIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const scrollNegative=contentIsRtl&&direction==="end"||!contentIsRtl&&direction==="start";const scrollAmount=scrollNegative?-100:SCROLL_DISTANCE;containerRef.current.scrollBy({left:scrollAmount,behavior:"smooth"});setTimeout(()=>{setIsScrolling(false);},150);},[isScrolling]);const updateScrollState=React.useCallback(()=>{if(!containerRef.current){return}const{scrollLeft,scrollWidth,clientWidth}=containerRef.current;const newIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const newIsScrollable=scrollWidth>clientWidth+scrollableThreshold;setIsScrollable(newIsScrollable);let newCanScrollStart;let newCanScrollEnd;if(newIsRtl){newCanScrollStart=scrollLeft<-scrollableThreshold;newCanScrollEnd=Math.abs(scrollLeft)<scrollWidth-clientWidth-scrollableThreshold;}else {newCanScrollStart=scrollLeft>scrollableThreshold;newCanScrollEnd=scrollLeft+clientWidth<scrollWidth-scrollableThreshold;}const scrollState={isScrollable:newIsScrollable,canScrollStart:newCanScrollStart,canScrollEnd:newCanScrollEnd,isRTL:newIsRtl,scroll,scrollDescription:scrollDescription||strings.scrollAnswers};scrollInstances.set(id,scrollState);},[id,scrollableThreshold,scrollDescription,strings.scrollAnswers,scroll]);useEffect(()=>{const container=containerRef.current;if(!container){return}updateScrollState();container.addEventListener("scroll",updateScrollState);window.addEventListener("resize",updateScrollState);return ()=>{container.removeEventListener("scroll",updateScrollState);window.removeEventListener("resize",updateScrollState);scrollInstances.delete(id);}},[children,updateScrollState,id]);const mergeStyle={overflowX:isScrollable&&overflowX==="auto"?"scroll":overflowX,overflowY:isScrollable&&overflowY==="auto"?"scroll":overflowY,scrollbarWidth:"thin",...style};return jsxRuntimeExports.jsx("div",{...additionalProps,id:id,role:role,className:className,style:mergeStyle,ref:containerRef,children:children})}function ScrollControls({target,scrollDescription:overrideDescription}){const{strings}=usePerseusI18n();const[scrollState,setScrollState]=useState(null);useEffect(()=>{if(!target){return}const checkForScrollState=()=>{const state=scrollInstances.get(target);if(state){setScrollState(state);}};checkForScrollState();const interval=setInterval(checkForScrollState,100);return ()=>{clearInterval(interval);}},[target]);if(!scrollState||!scrollState.isScrollable){return null}const description=overrideDescription||scrollState.scrollDescription;return jsxRuntimeExports.jsxs("div",{className:styles$w.scrollButtonsContainer,"aria-live":"polite",role:"group","aria-label":description,children:[jsxRuntimeExports.jsx(IconButton,{icon:scrollState.isRTL?caretRightIcon:caretLeftIcon,actionType:"neutral",kind:"secondary",size:"small",onClick:()=>scrollState.scroll("start"),"aria-label":strings.scrollStart,disabled:!scrollState.canScrollStart}),jsxRuntimeExports.jsx(IconButton,{icon:scrollState.isRTL?caretLeftIcon:caretRightIcon,actionType:"neutral",kind:"secondary",size:"small",onClick:()=>scrollState.scroll("end"),"aria-label":strings.scrollEnd,disabled:!scrollState.canScrollEnd}),jsxRuntimeExports.jsx(BodyText,{size:"small",children:description})]})}const ScrollableView=ScrollableArea;ScrollableView.Controls=ScrollControls;
1703
1703
 
1704
- var styles$u = {"base":"perseus_C4cWo-dY","is-correct":"perseus_vWc7XkhJ","isCorrect":"perseus_vWc7XkhJ","is-wrong":"perseus_yVmsF9sA","isWrong":"perseus_yVmsF9sA","icon":"perseus_brEUCVvd","circle-shape":"perseus_irgRpkgB","circleShape":"perseus_irgRpkgB","square-shape":"perseus_JsUZt48D","squareShape":"perseus_JsUZt48D"};
1704
+ var styles$v = {"base":"perseus_C4cWo-dY","is-correct":"perseus_vWc7XkhJ","isCorrect":"perseus_vWc7XkhJ","is-wrong":"perseus_yVmsF9sA","isWrong":"perseus_yVmsF9sA","icon":"perseus_brEUCVvd","circle-shape":"perseus_irgRpkgB","circleShape":"perseus_irgRpkgB","square-shape":"perseus_JsUZt48D","squareShape":"perseus_JsUZt48D"};
1705
1705
 
1706
- const Indicator=props=>{const{checked,content,showCorrectness}=props;const indicatorId=useId();const ariaLabelledby=content.labelledBy?`${indicatorId} ${content.labelledBy}`:undefined;const ariaDisabled=showCorrectness?"true":"false";const iconImage=checked&&showCorrectness==="correct"?checkIcon:checked&&showCorrectness==="wrong"?minusIcon:undefined;const icon=iconImage?jsxRuntimeExports.jsx(PhosphorIcon,{"aria-hidden":true,className:styles$u.icon,icon:iconImage}):undefined;const classes=[styles$u.base,styles$u[props.shape+"-shape"]];if(showCorrectness){classes.push(styles$u["is-"+showCorrectness]);}const handleClick=showCorrectness?undefined:event=>{event.stopPropagation();props.updateChecked(!checked);};return jsxRuntimeExports.jsxs("button",{"aria-describedby":content.describedBy,"aria-disabled":ariaDisabled,"aria-pressed":checked,"aria-label":content.screenReader,"aria-labelledby":ariaLabelledby,className:classes.join(" "),id:indicatorId,type:"button",ref:props.buttonRef,onClick:handleClick,children:[icon,jsxRuntimeExports.jsx("span",{children:content.visible})]})};
1706
+ const Indicator=props=>{const{checked,content,showCorrectness}=props;const indicatorId=useId();const ariaLabelledby=content.labelledBy?`${indicatorId} ${content.labelledBy}`:undefined;const ariaDisabled=showCorrectness?"true":"false";const iconImage=checked&&showCorrectness==="correct"?checkIcon:checked&&showCorrectness==="wrong"?minusIcon:undefined;const icon=iconImage?jsxRuntimeExports.jsx(PhosphorIcon,{"aria-hidden":true,className:styles$v.icon,icon:iconImage}):undefined;const classes=[styles$v.base,styles$v[props.shape+"-shape"]];if(showCorrectness){classes.push(styles$v["is-"+showCorrectness]);}const handleClick=showCorrectness?undefined:event=>{event.stopPropagation();props.updateChecked(!checked);};return jsxRuntimeExports.jsxs("button",{"aria-describedby":content.describedBy,"aria-disabled":ariaDisabled,"aria-pressed":checked,"aria-label":content.screenReader,"aria-labelledby":ariaLabelledby,className:classes.join(" "),id:indicatorId,type:"button",ref:props.buttonRef,onClick:handleClick,children:[icon,jsxRuntimeExports.jsx("span",{children:content.visible})]})};
1707
1707
 
1708
- var styles$t = {"choice":"perseus_hm3uu-sq","is-correct":"perseus_qpU2z5U7","isCorrect":"perseus_qpU2z5U7","is-wrong":"perseus_dUXUrBDI","isWrong":"perseus_dUXUrBDI"};
1708
+ var styles$u = {"choice":"perseus_hm3uu-sq","is-correct":"perseus_qpU2z5U7","isCorrect":"perseus_qpU2z5U7","is-wrong":"perseus_dUXUrBDI","isWrong":"perseus_dUXUrBDI"};
1709
1709
 
1710
- const Choice=props=>{const showCorrectness=props.showCorrectness;const buttonRef=useRef(null);const indicatorShape=props.isMultiSelect?"square":"circle";const clickHandler=showCorrectness?undefined:()=>{buttonRef.current?.click();};const classes=[styles$t.choice].concat(showCorrectness?[styles$t["is-"+showCorrectness]]:[]).join(" ");return jsxRuntimeExports.jsxs("li",{className:classes,onClick:clickHandler,role:"listitem",children:[jsxRuntimeExports.jsx(Indicator,{buttonRef:buttonRef,checked:props.checked,content:props.indicatorContent,shape:indicatorShape,showCorrectness:showCorrectness,updateChecked:props.updateChecked}),props.children]})};
1710
+ const Choice=props=>{const showCorrectness=props.showCorrectness;const buttonRef=useRef(null);const indicatorShape=props.isMultiSelect?"square":"circle";const clickHandler=showCorrectness?undefined:()=>{buttonRef.current?.click();};const classes=[styles$u.choice].concat(showCorrectness?[styles$u["is-"+showCorrectness]]:[]).join(" ");return jsxRuntimeExports.jsxs("li",{className:classes,onClick:clickHandler,role:"listitem",children:[jsxRuntimeExports.jsx(Indicator,{buttonRef:buttonRef,checked:props.checked,content:props.indicatorContent,shape:indicatorShape,showCorrectness:showCorrectness,updateChecked:props.updateChecked}),props.children]})};
1711
1711
 
1712
- var styles$s = {"container":"perseus_yewUvpCl","choiceList":"perseus_ejJezW-c","content":"perseus_zAWs4E3G","instructions":"perseus_WyGpYl3q","rationale":"perseus_6vMrWVz0","isCorrect":"perseus_Zv66BVdg","reviewAnswers":"perseus_hJzSXKwq"};
1712
+ var styles$t = {"container":"perseus_yewUvpCl","choiceList":"perseus_ejJezW-c","content":"perseus_zAWs4E3G","instructions":"perseus_WyGpYl3q","rationale":"perseus_6vMrWVz0","isCorrect":"perseus_Zv66BVdg","reviewAnswers":"perseus_hJzSXKwq"};
1713
1713
 
1714
1714
  function getChoiceLetter(pos,strings){const lettersString=strings.letters;const letters=lettersString.split(" ");if(pos<letters.length){return letters[pos]}return " "}function hasChoiceData(state){return state!=null&&typeof state==="object"&&"choiceStates"in state&&"choices"in state&&Array.isArray(state.choiceStates)&&Array.isArray(state.choices)}function getUserInputFromSerializedState$f(serializedState){const selectedChoiceIds=[];if(hasChoiceData(serializedState)){const{choiceStates,choices}=serializedState;for(let i=0;i<choiceStates.length;i++){const choiceState=choiceStates[i];const choice=choices[i];if(choiceState?.selected&&choice?.id){selectedChoiceIds.push(choice.id);}}}return {selectedChoiceIds}}function moveNoneOfTheAboveToEnd(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}function enforceOrdering(choices,strings){const ReversedChoices=[[strings.false,strings.true],[strings.no,strings.yes]];const content=choices.map(c=>c.content);if(ReversedChoices.some(reversed=>_.isEqual(content,reversed))){return [choices[1],choices[0]]}return choices}function choiceTransform(choices,randomize,strings,seed){const choicesWithMetadata=choices.map((choice,i)=>{return {...choice,originalIndex:i,correct:Boolean(choice.correct)}});return moveNoneOfTheAboveToEnd(enforceOrdering(randomize?shuffle(choicesWithMetadata,seed):choicesWithMetadata,strings))}
1715
1715
 
1716
1716
  const getInstructionsText=({multipleSelect,countChoices,numCorrect,strings})=>{if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer};
1717
1717
 
1718
- const RadioComponent=({choices,countChoices,multipleSelect=false,numCorrect,onChoiceChange,reviewMode})=>{const{strings}=usePerseusI18n();const legendId=useId();const containerRef=useRef(null);const[backgroundColor,setBackgroundColor]=useState("transparent");useEffect(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},[]);useTimeout(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},100);const instructions=getInstructionsText({multipleSelect,countChoices,numCorrect,strings});const choiceListClasses=reviewMode?`${styles$s.choiceList} ${styles$s.reviewAnswers}`:styles$s.choiceList;const cssVariableDeclaration=backgroundColor!=="transparent"?{"--perseus-widget-background-color":backgroundColor}:undefined;const scrollId=useId()+"-scroll";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("fieldset",{className:styles$s.container,ref:containerRef,style:cssVariableDeclaration,children:[jsxRuntimeExports.jsx("legend",{id:legendId,"aria-hidden":"true",className:styles$s.instructions,children:instructions}),jsxRuntimeExports.jsx(ScrollableView,{id:scrollId,overflowX:"auto",children:jsxRuntimeExports.jsx("ul",{"data-widget":"radio","aria-labelledby":legendId,className:choiceListClasses,role:"list",children:jsxRuntimeExports.jsx(ChoiceListItems,{choices:choices,i18nStrings:strings,onChoiceChange:onChoiceChange,reviewMode:reviewMode,multipleSelect:multipleSelect})})})]}),jsxRuntimeExports.jsx(ScrollableView.Controls,{target:scrollId})]})};const ChoiceListItems=props=>{const{choices,i18nStrings,multipleSelect,onChoiceChange,reviewMode}=props;const listId=useId();const items=choices.map((choice,i)=>{const updateChecked=isChecked=>{onChoiceChange(choice.id,isChecked);};const contentId=`${listId}-choice-${i+1}`;const choiceLetter=getChoiceLetter(i,i18nStrings);const srContent=reviewMode&&choice.correct?i18nStrings.choiceCorrect:i18nStrings.choice;const indicatorContent={visible:choiceLetter,screenReader:srContent({letter:choiceLetter}),labelledBy:contentId};const showCorrectness=reviewMode?choice.correct?"correct":"wrong":undefined;const content=choice.isNoneOfTheAbove?i18nStrings.noneOfTheAbove:choice.content;let rationale;if(reviewMode&&choice.hasRationale){const rationaleId=`${contentId}-rationale`;indicatorContent.describedBy=rationaleId;const rationaleClasses=showCorrectness==="correct"?`${styles$s.rationale} ${styles$s.isCorrect}`:styles$s.rationale;rationale=jsxRuntimeExports.jsx("div",{id:rationaleId,className:rationaleClasses,children:choice.rationale});}return jsxRuntimeExports.jsx(Choice,{checked:choice.checked,indicatorContent:indicatorContent,isMultiSelect:multipleSelect,showCorrectness:showCorrectness,updateChecked:updateChecked,children:jsxRuntimeExports.jsxs("div",{className:styles$s.content,children:[jsxRuntimeExports.jsx("div",{id:contentId,children:content}),rationale]})},choice.id)});return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:items})};
1718
+ const RadioComponent=({choices,countChoices,multipleSelect=false,numCorrect,onChoiceChange,reviewMode})=>{const{strings}=usePerseusI18n();const legendId=useId();const containerRef=useRef(null);const[backgroundColor,setBackgroundColor]=useState("transparent");useEffect(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},[]);useTimeout(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},100);const instructions=getInstructionsText({multipleSelect,countChoices,numCorrect,strings});const choiceListClasses=reviewMode?`${styles$t.choiceList} ${styles$t.reviewAnswers}`:styles$t.choiceList;const cssVariableDeclaration=backgroundColor!=="transparent"?{"--perseus-widget-background-color":backgroundColor}:undefined;const scrollId=useId()+"-scroll";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("fieldset",{className:styles$t.container,ref:containerRef,style:cssVariableDeclaration,children:[jsxRuntimeExports.jsx("legend",{id:legendId,"aria-hidden":"true",className:styles$t.instructions,children:instructions}),jsxRuntimeExports.jsx(ScrollableView,{id:scrollId,overflowX:"auto",children:jsxRuntimeExports.jsx("ul",{"data-widget":"radio","aria-labelledby":legendId,className:choiceListClasses,role:"list",children:jsxRuntimeExports.jsx(ChoiceListItems,{choices:choices,i18nStrings:strings,onChoiceChange:onChoiceChange,reviewMode:reviewMode,multipleSelect:multipleSelect})})})]}),jsxRuntimeExports.jsx(ScrollableView.Controls,{target:scrollId})]})};const ChoiceListItems=props=>{const{choices,i18nStrings,multipleSelect,onChoiceChange,reviewMode}=props;const listId=useId();const items=choices.map((choice,i)=>{const updateChecked=isChecked=>{onChoiceChange(choice.id,isChecked);};const contentId=`${listId}-choice-${i+1}`;const choiceLetter=getChoiceLetter(i,i18nStrings);const srContent=reviewMode&&choice.correct?i18nStrings.choiceCorrect:i18nStrings.choice;const indicatorContent={visible:choiceLetter,screenReader:srContent({letter:choiceLetter}),labelledBy:contentId};const showCorrectness=reviewMode?choice.correct?"correct":"wrong":undefined;const content=choice.isNoneOfTheAbove?i18nStrings.noneOfTheAbove:choice.content;let rationale;if(reviewMode&&choice.hasRationale){const rationaleId=`${contentId}-rationale`;indicatorContent.describedBy=rationaleId;const rationaleClasses=showCorrectness==="correct"?`${styles$t.rationale} ${styles$t.isCorrect}`:styles$t.rationale;rationale=jsxRuntimeExports.jsx("div",{id:rationaleId,className:rationaleClasses,children:choice.rationale});}return jsxRuntimeExports.jsx(Choice,{checked:choice.checked,indicatorContent:indicatorContent,isMultiSelect:multipleSelect,showCorrectness:showCorrectness,updateChecked:updateChecked,children:jsxRuntimeExports.jsxs("div",{className:styles$t.content,children:[jsxRuntimeExports.jsx("div",{id:contentId,children:content}),rationale]})},choice.id)});return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:items})};
1719
1719
 
1720
1720
  const getChoiceStates=({choices,showSolutions,choiceStates,reviewMode})=>{if(showSolutions==="all"||reviewMode){return choices.map(choice=>({selected:!!choice.correct}))}if(choiceStates){return choiceStates}return choices.map(()=>({selected:false}))};
1721
1721
 
@@ -1731,7 +1731,7 @@ const{radioBorderColor,checkedColor,circleSize,radioMarginWidth}=constants;var s
1731
1731
 
1732
1732
  const getPromptJSON$n=widgetData=>{return {type:"categorizer",options:{items:widgetData.items,categories:widgetData.categories},userInput:{itemToCategoryMapping:widgetData.userInput.values}}};
1733
1733
 
1734
- class Categorizer extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"categorizer",widgetId:this.props.widgetId}});}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,values:userInput.values}}getPromptJSON(){return getPromptJSON$n(this.props)}_handleUserInput(itemNum,catNum){const values=[...this.props.userInput.values];values[itemNum]=catNum;this.props.handleUserInput({values});this.props.trackInteraction();}render(){const self=this;const isMobile=this.props.apiOptions.isMobile;let indexedItems=this.props.items.map((item,n)=>[item,n]);if(this.props.randomizeItems){indexedItems=shuffle(indexedItems,this.props.problemNum);}const table=jsxRuntimeExports.jsxs("table",{className:"categorizer-table "+css(styles$r.mobileTable),children:[jsxRuntimeExports.jsx("thead",{children:jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{className:css(styles$r.emptyHeaderCell)}),this.props.categories.map((category,i)=>{return jsxRuntimeExports.jsx("th",{className:css(styles$r.header),children:jsxRuntimeExports.jsx(Renderer,{content:category,linterContext:this.props.linterContext,strings:this.context.strings})},i)})]})}),jsxRuntimeExports.jsx("tbody",{children:indexedItems.map(indexedItem=>{const item=indexedItem[0];const itemNum=indexedItem[1];const uniqueId=self.state.uniqueId+"_"+itemNum;return jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{children:jsxRuntimeExports.jsx(Renderer,{content:item,linterContext:this.props.linterContext,strings:this.context.strings})}),self.props.categories.map((catName,catNum)=>{const selected=self.props.userInput.values[itemNum]===catNum;return jsxRuntimeExports.jsx("td",{className:"category "+css(styles$r.cell),children:jsxRuntimeExports.jsxs("div",{role:"button","aria-label":catName,onClick:()=>this._handleUserInput(itemNum,catNum),children:[isMobile&&jsxRuntimeExports.jsx("input",{type:"radio",name:uniqueId,className:css(sharedStyles.responsiveInput,sharedStyles.responsiveRadioInput),checked:selected,onChange:()=>this._handleUserInput(itemNum,catNum),onClick:e=>e.stopPropagation()}),!isMobile&&jsxRuntimeExports.jsx("span",{className:css(styles$r.radioSpan,selected&&styles$r.checkedRadioSpan,this.props.static&&selected&&styles$r.staticCheckedRadioSpan),children:selected?jsxRuntimeExports.jsx(InlineIcon,{...iconCircle}):jsxRuntimeExports.jsx(InlineIcon,{...iconCircleThin})})]})},catNum)})]},itemNum)})})]});const extraClassNames=classNames$2({"categorizer-container":true,"static-mode":this.props.static});const inlineStyles=this.props.apiOptions.isMobile?[styles$r.fullBleedContainer]:[];return jsxRuntimeExports.jsx("div",{className:extraClassNames+" "+css(...inlineStyles),children:table})}constructor(...args){super(...args),this.state={uniqueId:_.uniqueId("perseus_radio_")};}}Categorizer.contextType=PerseusI18nContext;Categorizer.defaultProps={items:[],categories:[],linterContext:linterContextDefault,userInput:{values:[]}};const styles$r=StyleSheet.create({mobileTable:{[mediaQueries.smOrSmaller]:{minWidth:"auto"}},fullBleedContainer:{[mediaQueries.mdOrSmaller]:{marginLeft:-16,marginRight:-16,overflowX:"auto"}},header:{textAlign:"center",verticalAlign:"bottom"},cell:{textAlign:"center",padding:0,color:"#ccc",verticalAlign:"middle"},emptyHeaderCell:{backgroundColor:"inherit",borderBottom:"2px solid #ccc"},radioSpan:{fontSize:30,paddingRight:3,":hover":{color:"#999"}},checkedRadioSpan:{color:"#333"},staticCheckedRadioSpan:{color:"#888"}});function getUserInputFromSerializedState$e(serializedState){return {values:serializedState.values}}function getCorrectUserInput$7(options){return {values:options.values}}function getStartUserInput$f(){return {values:[]}}const WrappedCategorizer=withDependencies(Categorizer);var Categorizer$1 = {name:"categorizer",displayName:"Categorizer",hidden:true,widget:WrappedCategorizer,getUserInputFromSerializedState: getUserInputFromSerializedState$e,getCorrectUserInput: getCorrectUserInput$7,getStartUserInput: getStartUserInput$f,isLintable:true};
1734
+ class Categorizer extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"categorizer",widgetId:this.props.widgetId}});}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,values:userInput.values}}getPromptJSON(){return getPromptJSON$n(this.props)}_handleUserInput(itemNum,catNum){const values=[...this.props.userInput.values];values[itemNum]=catNum;this.props.handleUserInput({values});this.props.trackInteraction();}render(){const self=this;const isMobile=this.props.apiOptions.isMobile;let indexedItems=this.props.items.map((item,n)=>[item,n]);if(this.props.randomizeItems){indexedItems=shuffle(indexedItems,this.props.problemNum);}const table=jsxRuntimeExports.jsxs("table",{className:"categorizer-table "+css(styles$s.mobileTable),children:[jsxRuntimeExports.jsx("thead",{children:jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{className:css(styles$s.emptyHeaderCell)}),this.props.categories.map((category,i)=>{return jsxRuntimeExports.jsx("th",{className:css(styles$s.header),children:jsxRuntimeExports.jsx(Renderer,{content:category,linterContext:this.props.linterContext,strings:this.context.strings})},i)})]})}),jsxRuntimeExports.jsx("tbody",{children:indexedItems.map(indexedItem=>{const item=indexedItem[0];const itemNum=indexedItem[1];const uniqueId=self.state.uniqueId+"_"+itemNum;return jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{children:jsxRuntimeExports.jsx(Renderer,{content:item,linterContext:this.props.linterContext,strings:this.context.strings})}),self.props.categories.map((catName,catNum)=>{const selected=self.props.userInput.values[itemNum]===catNum;return jsxRuntimeExports.jsx("td",{className:"category "+css(styles$s.cell),children:jsxRuntimeExports.jsxs("div",{role:"button","aria-label":catName,onClick:()=>this._handleUserInput(itemNum,catNum),children:[isMobile&&jsxRuntimeExports.jsx("input",{type:"radio",name:uniqueId,className:css(sharedStyles.responsiveInput,sharedStyles.responsiveRadioInput),checked:selected,onChange:()=>this._handleUserInput(itemNum,catNum),onClick:e=>e.stopPropagation()}),!isMobile&&jsxRuntimeExports.jsx("span",{className:css(styles$s.radioSpan,selected&&styles$s.checkedRadioSpan,this.props.static&&selected&&styles$s.staticCheckedRadioSpan),children:selected?jsxRuntimeExports.jsx(InlineIcon,{...iconCircle}):jsxRuntimeExports.jsx(InlineIcon,{...iconCircleThin})})]})},catNum)})]},itemNum)})})]});const extraClassNames=classNames$2({"categorizer-container":true,"static-mode":this.props.static});const inlineStyles=this.props.apiOptions.isMobile?[styles$s.fullBleedContainer]:[];return jsxRuntimeExports.jsx("div",{className:extraClassNames+" "+css(...inlineStyles),children:table})}constructor(...args){super(...args),this.state={uniqueId:_.uniqueId("perseus_radio_")};}}Categorizer.contextType=PerseusI18nContext;Categorizer.defaultProps={items:[],categories:[],linterContext:linterContextDefault,userInput:{values:[]}};const styles$s=StyleSheet.create({mobileTable:{[mediaQueries.smOrSmaller]:{minWidth:"auto"}},fullBleedContainer:{[mediaQueries.mdOrSmaller]:{marginLeft:-16,marginRight:-16,overflowX:"auto"}},header:{textAlign:"center",verticalAlign:"bottom"},cell:{textAlign:"center",padding:0,color:"#ccc",verticalAlign:"middle"},emptyHeaderCell:{backgroundColor:"inherit",borderBottom:"2px solid #ccc"},radioSpan:{fontSize:30,paddingRight:3,":hover":{color:"#999"}},checkedRadioSpan:{color:"#333"},staticCheckedRadioSpan:{color:"#888"}});function getUserInputFromSerializedState$e(serializedState){return {values:serializedState.values}}function getCorrectUserInput$7(options){return {values:options.values}}function getStartUserInput$f(){return {values:[]}}const WrappedCategorizer=withDependencies(Categorizer);var Categorizer$1 = {name:"categorizer",displayName:"Categorizer",hidden:true,widget:WrappedCategorizer,getUserInputFromSerializedState: getUserInputFromSerializedState$e,getCorrectUserInput: getCorrectUserInput$7,getStartUserInput: getStartUserInput$f,isLintable:true};
1735
1735
 
1736
1736
  const isFileProtocol=protocol=>{if(protocol&&protocol.toLowerCase()==="file:"){return true}return false};
1737
1737
 
@@ -1741,15 +1741,15 @@ const getUnsupportedPromptJSON=(widgetType,message="")=>{return {type:widgetType
1741
1741
 
1742
1742
  const getPromptJSON$m=()=>{return getUnsupportedPromptJSON("cs-program")};
1743
1743
 
1744
- const{updateQueryString: updateQueryString$1}=Util;function getUrlFromProgramID$1(programID){const{InitialRequestUrl}=getDependencies();const path="/computer-programming/program/"+`${programID}/embedded?embed=yes&author=no`;if(isFileProtocol(InitialRequestUrl.protocol)){return `https://khanacademy.org${path}`}return toAbsoluteUrl(path)}class CSProgram extends React.Component{componentDidMount(){$(window).on("message",this.handleMessageEvent);}componentWillUnmount(){$(window).off("message",this.handleMessageEvent);}getPromptJSON(){return getPromptJSON$m()}getSerializedState(){const{userInput:_,alignment:__,...rest}=this.props;return {...rest,programType:rest.programType||null}}render(){if(!this.props.programID){return jsxRuntimeExports.jsx("div",{})}let styleContainer=false;let url=getUrlFromProgramID$1(this.props.programID);let className;const style={height:this.props.height,width:"100%"};if(this.props.showEditor){url+="&editor=yes";className="perseus-scratchpad-editor";}else {url+=`&editor=no&width=${articleMaxWidthInPx}`;className="perseus-scratchpad";if(this.props.programType!=="webpage"){styleContainer=true;}}if(this.props.showButtons){url+="&buttons=yes";style.height+=67;}else {url+="&buttons=no";}if(this.props.settings){const settings={};_.each(this.props.settings,function(setting){if(setting.name&&setting.value){settings[setting.name]=setting.value;}});url=updateQueryString$1(url,"settings",JSON.stringify(settings));}if(this.context?.locale){url=updateQueryString$1(url,"lang",this.context.locale);}const sandboxOptions=["allow-popups","allow-same-origin","allow-scripts","allow-top-navigation"].join(" ");return jsxRuntimeExports.jsx("div",{className:css(styleContainer&&styles$q.container),children:jsxRuntimeExports.jsx("iframe",{title:this.context.strings.computerScienceProgram,sandbox:sandboxOptions,src:url,style:style,className:className,allowFullScreen:true})})}constructor(...args){super(...args),this.handleMessageEvent=e=>{let data={};try{data=JSON.parse(e.originalEvent.data);}catch{return}if(_.isUndefined(data.testsPassed)){return}const status=data.testsPassed?"correct":"incorrect";this.props.handleUserInput({status:status,message:data.message});};}}CSProgram.contextType=PerseusI18nContext;CSProgram.defaultProps={showEditor:false,showButtons:false,userInput:{status:"incomplete",message:null}};const styles$q=StyleSheet.create({container:{margin:"auto"}});function getUserInputFromSerializedState$d(serializedState){return {status:serializedState.status,message:serializedState.message}}function getStartUserInput$e(){return {status:"incomplete",message:null}}var CSProgram$1 = {name:"cs-program",displayName:"CS Program",widget:CSProgram,hidden:true,getStartUserInput: getStartUserInput$e,getUserInputFromSerializedState: getUserInputFromSerializedState$d};
1744
+ const{updateQueryString: updateQueryString$1}=Util;function getUrlFromProgramID$1(programID){const{InitialRequestUrl}=getDependencies();const path="/computer-programming/program/"+`${programID}/embedded?embed=yes&author=no`;if(isFileProtocol(InitialRequestUrl.protocol)){return `https://khanacademy.org${path}`}return toAbsoluteUrl(path)}class CSProgram extends React.Component{componentDidMount(){$(window).on("message",this.handleMessageEvent);}componentWillUnmount(){$(window).off("message",this.handleMessageEvent);}getPromptJSON(){return getPromptJSON$m()}getSerializedState(){const{userInput:_,alignment:__,...rest}=this.props;return {...rest,programType:rest.programType||null}}render(){if(!this.props.programID){return jsxRuntimeExports.jsx("div",{})}let styleContainer=false;let url=getUrlFromProgramID$1(this.props.programID);let className;const style={height:this.props.height,width:"100%"};if(this.props.showEditor){url+="&editor=yes";className="perseus-scratchpad-editor";}else {url+=`&editor=no&width=${articleMaxWidthInPx}`;className="perseus-scratchpad";if(this.props.programType!=="webpage"){styleContainer=true;}}if(this.props.showButtons){url+="&buttons=yes";style.height+=67;}else {url+="&buttons=no";}if(this.props.settings){const settings={};_.each(this.props.settings,function(setting){if(setting.name&&setting.value){settings[setting.name]=setting.value;}});url=updateQueryString$1(url,"settings",JSON.stringify(settings));}if(this.context?.locale){url=updateQueryString$1(url,"lang",this.context.locale);}const sandboxOptions=["allow-popups","allow-same-origin","allow-scripts","allow-top-navigation"].join(" ");return jsxRuntimeExports.jsx("div",{className:css(styleContainer&&styles$r.container),children:jsxRuntimeExports.jsx("iframe",{title:this.context.strings.computerScienceProgram,sandbox:sandboxOptions,src:url,style:style,className:className,allowFullScreen:true})})}constructor(...args){super(...args),this.handleMessageEvent=e=>{let data={};try{data=JSON.parse(e.originalEvent.data);}catch{return}if(_.isUndefined(data.testsPassed)){return}const status=data.testsPassed?"correct":"incorrect";this.props.handleUserInput({status:status,message:data.message});};}}CSProgram.contextType=PerseusI18nContext;CSProgram.defaultProps={showEditor:false,showButtons:false,userInput:{status:"incomplete",message:null}};const styles$r=StyleSheet.create({container:{margin:"auto"}});function getUserInputFromSerializedState$d(serializedState){return {status:serializedState.status,message:serializedState.message}}function getStartUserInput$e(){return {status:"incomplete",message:null}}var CSProgram$1 = {name:"cs-program",displayName:"CS Program",widget:CSProgram,hidden:true,getStartUserInput: getStartUserInput$e,getUserInputFromSerializedState: getUserInputFromSerializedState$d};
1745
1745
 
1746
1746
  const getPromptJSON$l=widgetData=>{return {type:"definition",definition:widgetData.definition,togglePrompt:widgetData.togglePrompt}};
1747
1747
 
1748
- var styles$p = {"definition":"perseus_5CDFHduT"};
1748
+ var styles$q = {"definition":"perseus_5CDFHduT"};
1749
1749
 
1750
- const styles$o={tooltipBody:{color:"var(--wb-semanticColor-core-foreground-neutral-strong)",fontSize:"var(--wb-font-body-size-medium)",fontWeight:"var(--wb-font-weight-medium)",lineHeight:"var(--wb-font-body-lineHeight-medium)"}};
1750
+ const styles$p={tooltipBody:{color:"var(--wb-semanticColor-core-foreground-neutral-strong)",fontSize:"var(--wb-font-body-size-medium)",fontWeight:"var(--wb-font-weight-medium)",lineHeight:"var(--wb-font-body-lineHeight-medium)"}};
1751
1751
 
1752
- class Definition extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"definition",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$l(this.props)}render(){return jsxRuntimeExports.jsx(DefinitionConsumer,{children:({activeDefinitionId,setActiveDefinitionId})=>jsxRuntimeExports.jsx(Popover,{dismissEnabled:true,content:jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$o.tooltipBody,closeButtonVisible:true,children:jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.definition,widgets:this.props.widgets,strings:this.context.strings})}),opened:activeDefinitionId===this.props.widgetId,onClose:()=>setActiveDefinitionId(null),placement:"top",children:jsxRuntimeExports.jsx(Clickable,{onClick:()=>{this.props.trackInteraction();setActiveDefinitionId(this.props.widgetId);},"aria-label":this.context.strings.definitionIdentifier({word:this.props.togglePrompt}),children:()=>jsxRuntimeExports.jsx("span",{className:styles$p.definition,children:this.props.togglePrompt})})})})}constructor(...args){super(...args),this.isWidget=true;}}Definition.contextType=PerseusI18nContext;Definition.defaultProps={togglePrompt:"define me",definition:"definition goes here"};const WrappedDefinition=withDependencies(Definition);var Definition$1 = {name:"definition",displayName:"Definition",widget:WrappedDefinition};
1752
+ class Definition extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"definition",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$l(this.props)}render(){return jsxRuntimeExports.jsx(DefinitionConsumer,{children:({activeDefinitionId,setActiveDefinitionId})=>jsxRuntimeExports.jsx(Popover,{dismissEnabled:true,content:jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$p.tooltipBody,closeButtonVisible:true,children:jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.definition,widgets:this.props.widgets,strings:this.context.strings})}),opened:activeDefinitionId===this.props.widgetId,onClose:()=>setActiveDefinitionId(null),placement:"top",children:jsxRuntimeExports.jsx(Clickable,{onClick:()=>{this.props.trackInteraction();setActiveDefinitionId(this.props.widgetId);},"aria-label":this.context.strings.definitionIdentifier({word:this.props.togglePrompt}),children:()=>jsxRuntimeExports.jsx("span",{className:styles$q.definition,children:this.props.togglePrompt})})})})}constructor(...args){super(...args),this.isWidget=true;}}Definition.contextType=PerseusI18nContext;Definition.defaultProps={togglePrompt:"define me",definition:"definition goes here"};const WrappedDefinition=withDependencies(Definition);var Definition$1 = {name:"definition",displayName:"Definition",widget:WrappedDefinition};
1753
1753
 
1754
1754
  class DeprecatedStandin extends React__default.Component{render(){return jsxRuntimeExports.jsx("div",{style:{paddingTop:8,paddingBottom:8},children:jsxRuntimeExports.jsx(Banner,{text:this.context.strings.deprecatedStandin,kind:"info"})})}constructor(...args){super(...args),this.isWidget=true;}}DeprecatedStandin.contextType=PerseusI18nContext;var DeprecatedStandin$1 = {name:"deprecated-standin",displayName:"Deprecated Standin",widget:DeprecatedStandin,hidden:true};
1755
1755
 
@@ -1761,25 +1761,25 @@ function sharedInitializeUserInput(widgetOptions,problemNum){const startUserInpu
1761
1761
 
1762
1762
  const getPromptJSON$j=widgetData=>{return {type:"explanation",showPrompt:widgetData.showPrompt,explanation:widgetData.explanation}};
1763
1763
 
1764
- var styles$n = {"content":"perseus_HDIlPzEz","contentCollapsed":"perseus_NkFQFgcZ","contentExpanded":"perseus_XhV-9haB","contentWrapper":"perseus_WEJESS6h","transitionCollapsed":"perseus_sbBrAODD","transitionExpanded":"perseus_Wp72j6qk"};
1764
+ var styles$o = {"content":"perseus_HDIlPzEz","contentCollapsed":"perseus_NkFQFgcZ","contentExpanded":"perseus_XhV-9haB","contentWrapper":"perseus_WEJESS6h","transitionCollapsed":"perseus_sbBrAODD","transitionExpanded":"perseus_Wp72j6qk"};
1765
1765
 
1766
- const styles$m={buttonStyleOverrides:{height:"auto",lineHeight:"inherit",marginLeft:"-0.2rem",marginRight:"0.2rem",paddingLeft:"0.2rem"},content:{borderLeft:"0px solid #ccc",display:"inline-grid",position:"relative"},contentCollapsed:{gridTemplateColumns:"0fr",gridTemplateRows:"0fr",marginBottom:"0",marginTop:"0",minWidth:"0",paddingBottom:"0",visibility:"hidden"},contentExpanded:{borderLeftWidth:"5px",gridTemplateColumns:"1fr",gridTemplateRows:"1fr",marginBottom:"1.4rem",marginLeft:"-2.3rem",marginTop:"1.4rem",minWidth:"100%",paddingBottom:"1rem",paddingLeft:"2.3rem",visibility:"visible"},contentWrapper:{overflow:"hidden"},labelStyle:{fontSize:"var(--wb-font-heading-size-medium)",lineHeight:"inherit",marginRight:"-0.6rem",textAlign:"left",whiteSpace:"normal"},transitionCollapsed:{transition:"all 0.25s step-end, grid-template-rows 0.25s, margin-top 0.25s, margin-bottom 0.25s, padding-bottom 0.25s"},transitionExpanded:{transition:"grid-template-rows 0.5s, margin-top 0.5s, margin-bottom 0.5s, padding-bottom 0.5s"}};
1766
+ const styles$n={buttonStyleOverrides:{height:"auto",lineHeight:"inherit",marginLeft:"-0.2rem",marginRight:"0.2rem",paddingLeft:"0.2rem"},content:{borderLeft:"0px solid #ccc",display:"inline-grid",position:"relative"},contentCollapsed:{gridTemplateColumns:"0fr",gridTemplateRows:"0fr",marginBottom:"0",marginTop:"0",minWidth:"0",paddingBottom:"0",visibility:"hidden"},contentExpanded:{borderLeftWidth:"5px",gridTemplateColumns:"1fr",gridTemplateRows:"1fr",marginBottom:"1.4rem",marginLeft:"-2.3rem",marginTop:"1.4rem",minWidth:"100%",paddingBottom:"1rem",paddingLeft:"2.3rem",visibility:"visible"},contentWrapper:{overflow:"hidden"},labelStyle:{fontSize:"var(--wb-font-heading-size-medium)",lineHeight:"inherit",marginRight:"-0.6rem",textAlign:"left",whiteSpace:"normal"},transitionCollapsed:{transition:"all 0.25s step-end, grid-template-rows 0.25s, margin-top 0.25s, margin-bottom 0.25s, padding-bottom 0.25s"},transitionExpanded:{transition:"grid-template-rows 0.5s, margin-top 0.5s, margin-bottom 0.5s, padding-bottom 0.5s"}};
1767
1767
 
1768
- function mediaQueryIsMatched(mediaQuery){if(typeof window.matchMedia!=="function"){return false}return window.matchMedia(mediaQuery).matches}class Explanation extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"explanation",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$j(this.props)}render(){const promptText=this.state.expanded?this.props.hidePrompt:this.props.showPrompt;const caretIcon=this.state.expanded?caretUp:caretDown;const legacyContentStyling=[styles$m.content,this.state.expanded?styles$m.contentExpanded:styles$m.contentCollapsed,mediaQueryIsMatched("(prefers-reduced-motion: no-preference)")&&(this.state.expanded?styles$m.transitionExpanded:styles$m.transitionCollapsed)];const contentClasses=[styles$n.content,this.state.expanded?styles$n.contentExpanded:styles$n.contentCollapsed,this.state.expanded?styles$n.transitionExpanded:styles$n.transitionCollapsed];return jsxRuntimeExports.jsx(Id,{children:contentId=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{"aria-expanded":this.state.expanded,"aria-controls":contentId,endIcon:caretIcon,kind:"tertiary",labelStyle:styles$m.labelStyle,onClick:this._onClick,size:"small",style:styles$m.buttonStyleOverrides,children:promptText}),jsxRuntimeExports.jsx(View,{id:contentId,style:legacyContentStyling,className:contentClasses.join(" "),"aria-hidden":!this.state.expanded,testId:"content-container",children:jsxRuntimeExports.jsx(View,{className:styles$n.contentWrapper,style:styles$m.contentWrapper,children:jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>{return jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.explanation,widgets:this.props.widgets,linterContext:this.props.linterContext,strings:this.context.strings,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput})}})})})]})})}constructor(...args){super(...args),this.isWidget=true,this.state={expanded:false},this._onClick=()=>{this.setState({expanded:!this.state.expanded});this.props.trackInteraction();};}}Explanation.contextType=PerseusI18nContext;Explanation.defaultProps={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{},linterContext:linterContextDefault};const WrappedExplanation=withDependencies(Explanation);var Explanation$1 = {name:"explanation",displayName:"Explanation",widget:WrappedExplanation,isLintable:true};
1768
+ function mediaQueryIsMatched(mediaQuery){if(typeof window.matchMedia!=="function"){return false}return window.matchMedia(mediaQuery).matches}class Explanation extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"explanation",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$j(this.props)}render(){const promptText=this.state.expanded?this.props.hidePrompt:this.props.showPrompt;const caretIcon=this.state.expanded?caretUp:caretDown;const legacyContentStyling=[styles$n.content,this.state.expanded?styles$n.contentExpanded:styles$n.contentCollapsed,mediaQueryIsMatched("(prefers-reduced-motion: no-preference)")&&(this.state.expanded?styles$n.transitionExpanded:styles$n.transitionCollapsed)];const contentClasses=[styles$o.content,this.state.expanded?styles$o.contentExpanded:styles$o.contentCollapsed,this.state.expanded?styles$o.transitionExpanded:styles$o.transitionCollapsed];return jsxRuntimeExports.jsx(Id,{children:contentId=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{"aria-expanded":this.state.expanded,"aria-controls":contentId,endIcon:caretIcon,kind:"tertiary",labelStyle:styles$n.labelStyle,onClick:this._onClick,size:"small",style:styles$n.buttonStyleOverrides,children:promptText}),jsxRuntimeExports.jsx(View,{id:contentId,style:legacyContentStyling,className:contentClasses.join(" "),"aria-hidden":!this.state.expanded,testId:"content-container",children:jsxRuntimeExports.jsx(View,{className:styles$o.contentWrapper,style:styles$n.contentWrapper,children:jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>{return jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.explanation,widgets:this.props.widgets,linterContext:this.props.linterContext,strings:this.context.strings,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput})}})})})]})})}constructor(...args){super(...args),this.isWidget=true,this.state={expanded:false},this._onClick=()=>{this.setState({expanded:!this.state.expanded});this.props.trackInteraction();};}}Explanation.contextType=PerseusI18nContext;Explanation.defaultProps={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{},linterContext:linterContextDefault};const WrappedExplanation=withDependencies(Explanation);var Explanation$1 = {name:"explanation",displayName:"Explanation",widget:WrappedExplanation,isLintable:true};
1769
1769
 
1770
- class FreeResponse extends React.Component{isOverLimit(){return !this.props.allowUnlimitedCharacters&&this.characterCount()>this.props.characterLimit}render(){const isOverLimit=this.isOverLimit();const characterCountText=this.props.allowUnlimitedCharacters?undefined:this.context.strings.characterCount({used:this.characterCount(),num:this.props.characterLimit});if(characterCountText){this.announceCharacterCount(characterCountText,isOverLimit);}return jsxRuntimeExports.jsx(View,{style:styles$l.container,className:"free-response",children:jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(View,{className:"free-response-question",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.question,strings:this.context.strings})}),field:jsxRuntimeExports.jsx(TextArea,{error:isOverLimit,onChange:this._handleUserInput,placeholder:this.props.placeholder,style:styles$l.textarea,value:this.props.userInput.currentValue}),additionalHelperMessage:jsxRuntimeExports.jsxs("p",{className:css(styles$l.characterCountText,isOverLimit?styles$l.overCharacterLimit:undefined),children:[isOverLimit&&jsxRuntimeExports.jsx(PhosphorIcon,{"aria-label":"Error:",icon:warningCircleIcon,size:"small",style:styles$l.warningCircleIcon}),characterCountText]})})})}constructor(...args){super(...args),this.isWidget=true,this.announceCharacterCount=(message,isOverLimit)=>{const level=isOverLimit?"assertive":"polite";announceMessage({message,level,debounceThreshold:750});},this.characterCount=()=>{return this.props.userInput.currentValue.replace(/\n/g,"").length},this._handleUserInput=newValue=>{this.props.handleUserInput({currentValue:newValue});};}}FreeResponse.contextType=PerseusI18nContext;FreeResponse.defaultProps={userInput:{currentValue:""}};function getStartUserInput$c(){return {currentValue:""}}var FreeResponse$1 = {name:"free-response",accessible:true,displayName:"Free Response (Assessments only)",widget:FreeResponse,hidden:false,getUserInputFromSerializedState:getStartUserInput$c,getStartUserInput: getStartUserInput$c};const styles$l=StyleSheet.create({container:{gap:spacing.xSmall_8},characterCountText:{color:semanticColor.core.foreground.neutral.default,fontSize:font.body.size.small,margin:0},overCharacterLimit:{color:semanticColor.core.foreground.critical.default},textarea:{padding:spacing.medium_16},warningCircleIcon:{marginInlineEnd:spacing.xSmall_8}});
1770
+ class FreeResponse extends React.Component{isOverLimit(){return !this.props.allowUnlimitedCharacters&&this.characterCount()>this.props.characterLimit}render(){const isOverLimit=this.isOverLimit();const characterCountText=this.props.allowUnlimitedCharacters?undefined:this.context.strings.characterCount({used:this.characterCount(),num:this.props.characterLimit});if(characterCountText){this.announceCharacterCount(characterCountText,isOverLimit);}return jsxRuntimeExports.jsx(View,{style:styles$m.container,className:"free-response",children:jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(View,{className:"free-response-question",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.question,strings:this.context.strings})}),field:jsxRuntimeExports.jsx(TextArea,{error:isOverLimit,onChange:this._handleUserInput,placeholder:this.props.placeholder,style:styles$m.textarea,value:this.props.userInput.currentValue}),additionalHelperMessage:jsxRuntimeExports.jsxs("p",{className:css(styles$m.characterCountText,isOverLimit?styles$m.overCharacterLimit:undefined),children:[isOverLimit&&jsxRuntimeExports.jsx(PhosphorIcon,{"aria-label":"Error:",icon:warningCircleIcon,size:"small",style:styles$m.warningCircleIcon}),characterCountText]})})})}constructor(...args){super(...args),this.isWidget=true,this.announceCharacterCount=(message,isOverLimit)=>{const level=isOverLimit?"assertive":"polite";announceMessage({message,level,debounceThreshold:750});},this.characterCount=()=>{return this.props.userInput.currentValue.replace(/\n/g,"").length},this._handleUserInput=newValue=>{this.props.handleUserInput({currentValue:newValue});};}}FreeResponse.contextType=PerseusI18nContext;FreeResponse.defaultProps={userInput:{currentValue:""}};function getStartUserInput$c(){return {currentValue:""}}var FreeResponse$1 = {name:"free-response",accessible:true,displayName:"Free Response (Assessments only)",widget:FreeResponse,hidden:false,getUserInputFromSerializedState:getStartUserInput$c,getStartUserInput: getStartUserInput$c};const styles$m=StyleSheet.create({container:{gap:spacing.xSmall_8},characterCountText:{color:semanticColor.core.foreground.neutral.default,fontSize:font.body.size.small,margin:0},overCharacterLimit:{color:semanticColor.core.foreground.critical.default},textarea:{padding:spacing.medium_16},warningCircleIcon:{marginInlineEnd:spacing.xSmall_8}});
1771
1771
 
1772
1772
  const getPromptJSON$i=(title,rendererJSON,hintRendererJSON)=>{if(!rendererJSON){return {type:"graded-group",title,content:"",widgets:{},hint:hintRendererJSON}}return {...rendererJSON,title,type:"graded-group",hint:hintRendererJSON}};
1773
1773
 
1774
- class GradedGroupAnswerBar extends React.Component{render(){const{apiOptions,answerBarState,onCheckAnswer,onNextQuestion}=this.props;const{keepTrying,tryAgain,check,correctExcited,nextQuestion}=this.context.strings;const answerBarStyle={...styles$k.answerBar,backgroundColor:answerBarState==="CORRECT"?semanticColor.core.background.base.subtle:semanticColor.core.background.base.default,justifyContent:answerBarState==="CORRECT"&&!onNextQuestion?"center":"space-between"};const message=answerBarState==="INCORRECT"?jsxRuntimeExports.jsxs("span",{style:styles$k.text,children:[jsxRuntimeExports.jsx("span",{style:styles$k.tryAgainIcon,children:jsxRuntimeExports.jsx(InlineIcon,{...iconTryAgain})}),jsxRuntimeExports.jsx("span",{style:{marginLeft:8},children:keepTrying})]}):jsxRuntimeExports.jsx("span",{});if(answerBarState!=="CORRECT"){const buttonLabel=answerBarState==="INCORRECT"?tryAgain:check;return jsxRuntimeExports.jsxs("div",{style:answerBarStyle,children:[message,jsxRuntimeExports.jsx(Button,{disabled:apiOptions.readOnly||answerBarState!=="ACTIVE",onClick:onCheckAnswer,children:buttonLabel})]})}return jsxRuntimeExports.jsxs("div",{style:answerBarStyle,children:[jsxRuntimeExports.jsxs("span",{style:styles$k.text,children:[jsxRuntimeExports.jsx("span",{style:{fontSize:28,color:semanticColor.core.foreground.success.default},children:jsxRuntimeExports.jsx(InlineIcon,{...iconStar,style:{marginBottom:5}})}),jsxRuntimeExports.jsx("span",{role:"alert","aria-label":correctExcited,style:{marginLeft:8},children:correctExcited})]}),onNextQuestion&&jsxRuntimeExports.jsx(Button,{onClick:onNextQuestion,children:nextQuestion})]})}}GradedGroupAnswerBar.contextType=PerseusI18nContext;const fontSize$1=17;const styles$k={answerBar:{display:"flex",alignItems:"center",height:68,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,marginBottom:negativePhoneMargin,marginTop:phoneMargin,paddingLeft:phoneMargin,paddingRight:10,borderTop:`1px solid ${semanticColor.core.border.neutral.default}`},tryAgainIcon:{fontSize:28,color:"#63D9EA",transform:"scale(-1,1) rotate(-268deg)"},text:{display:"flex",flexDirection:"row",alignItems:"center",fontWeight:"bold",fontSize:fontSize$1}};
1774
+ class GradedGroupAnswerBar extends React.Component{render(){const{apiOptions,answerBarState,onCheckAnswer,onNextQuestion}=this.props;const{keepTrying,tryAgain,check,correctExcited,nextQuestion}=this.context.strings;const answerBarStyle={...styles$l.answerBar,backgroundColor:answerBarState==="CORRECT"?semanticColor.core.background.base.subtle:semanticColor.core.background.base.default,justifyContent:answerBarState==="CORRECT"&&!onNextQuestion?"center":"space-between"};const message=answerBarState==="INCORRECT"?jsxRuntimeExports.jsxs("span",{style:styles$l.text,children:[jsxRuntimeExports.jsx("span",{style:styles$l.tryAgainIcon,children:jsxRuntimeExports.jsx(InlineIcon,{...iconTryAgain})}),jsxRuntimeExports.jsx("span",{style:{marginLeft:8},children:keepTrying})]}):jsxRuntimeExports.jsx("span",{});if(answerBarState!=="CORRECT"){const buttonLabel=answerBarState==="INCORRECT"?tryAgain:check;return jsxRuntimeExports.jsxs("div",{style:answerBarStyle,children:[message,jsxRuntimeExports.jsx(Button,{disabled:apiOptions.readOnly||answerBarState!=="ACTIVE",onClick:onCheckAnswer,children:buttonLabel})]})}return jsxRuntimeExports.jsxs("div",{style:answerBarStyle,children:[jsxRuntimeExports.jsxs("span",{style:styles$l.text,children:[jsxRuntimeExports.jsx("span",{style:{fontSize:28,color:semanticColor.core.foreground.success.default},children:jsxRuntimeExports.jsx(InlineIcon,{...iconStar,style:{marginBottom:5}})}),jsxRuntimeExports.jsx("span",{role:"alert","aria-label":correctExcited,style:{marginLeft:8},children:correctExcited})]}),onNextQuestion&&jsxRuntimeExports.jsx(Button,{onClick:onNextQuestion,children:nextQuestion})]})}}GradedGroupAnswerBar.contextType=PerseusI18nContext;const fontSize$1=17;const styles$l={answerBar:{display:"flex",alignItems:"center",height:68,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,marginBottom:negativePhoneMargin,marginTop:phoneMargin,paddingLeft:phoneMargin,paddingRight:10,borderTop:`1px solid ${semanticColor.core.border.neutral.default}`},tryAgainIcon:{fontSize:28,color:"#63D9EA",transform:"scale(-1,1) rotate(-268deg)"},text:{display:"flex",flexDirection:"row",alignItems:"center",fontWeight:"bold",fontSize:fontSize$1}};
1775
1775
 
1776
- const GRADING_STATUSES={ungraded:"ungraded",correct:"correct",incorrect:"incorrect",invalid:"invalid"};const getNextState=(currentState,answerable)=>{switch(currentState){case "ACTIVE":return !answerable?"INACTIVE":currentState;case "INACTIVE":return answerable?"ACTIVE":currentState;case "INCORRECT":return answerable?"ACTIVE":"INACTIVE";default:return currentState}};class GradedGroup extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"graded-group",widgetSubType:"null",widgetId:this.props.widgetId}});}shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}_handleUserInput(_userInput,widgetsEmpty){this.setState({status:GRADING_STATUSES.ungraded,message:""});const answerable=!widgetsEmpty;const answerBarState=this.state.answerBarState;const nextState=getNextState(answerBarState,answerable);this.setState({answerBarState:nextState});}getPromptJSON(){const hint=this.hintRendererRef.current?.getPromptJSON()||{content:this.props.hint?.content||"",widgets:{}};return getPromptJSON$i(this.props.title,this.rendererRef.current?.getPromptJSON(),hint)}render(){const apiOptions=_.extend({},ApiOptions.defaults,this.props.apiOptions,{onFocusChange:(newFocus,oldFocus)=>{if(oldFocus){this.props.onBlur(oldFocus);}if(newFocus){this.props.onFocus(newFocus);}}});let gradeStatus=null;let icon=null;if(this.state.status===GRADING_STATUSES.correct){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconOk,style:{color:"#526f03"}});gradeStatus=this.context.strings.correct;}else if(this.state.status===GRADING_STATUSES.incorrect){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconRemove,style:{color:"#ff5454"}});gradeStatus=this.context.strings.incorrect;}const mobileClass=this.props.inGradedGroupSet?css(styles$j.gradedGroupInSet):css(styles$j.gradedGroup);const classes=classNames$2({[mobileClass]:apiOptions.isMobile,"perseus-graded-group":true,"answer-correct":apiOptions.isMobile?false:this.state.status===GRADING_STATUSES.correct,"answer-incorrect":apiOptions.isMobile?false:this.state.status===GRADING_STATUSES.incorrect});const{answerBarState}=this.state;const isCorrect=answerBarState==="CORRECT";const readOnly=apiOptions.readOnly||apiOptions.isMobile&&isCorrect;const showSolutions=isCorrect?"all":"none";return jsxRuntimeExports.jsxs("div",{className:classes,children:[!!this.props.title&&jsxRuntimeExports.jsx("div",{className:css(styles$j.title),children:this.props.title}),jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.widgets,handleUserInput:(userInput,widgetsEmpty)=>this._handleUserInput(userInput,widgetsEmpty),problemNum:0,children:({userInput,handleUserInput})=>jsxRuntimeExports.jsx(Renderer,{content:this.props.content,widgets:this.props.widgets,images:this.props.images,userInput:userInput,handleUserInput:handleUserInput,problemNum:0,ref:this.rendererRef,keypadElement:this.props.keypadElement,apiOptions:{...apiOptions,readOnly},showSolutions:showSolutions,linterContext:this.props.linterContext,strings:this.context.strings})}),!apiOptions.isMobile&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[icon!=null&&jsxRuntimeExports.jsx("div",{className:"group-icon",children:icon}),gradeStatus&&jsxRuntimeExports.jsx("div",{className:css(a11y.srOnly),role:"alert","aria-label":gradeStatus,children:gradeStatus}),jsxRuntimeExports.jsx("div",{role:"status","aria-live":"polite",children:jsxRuntimeExports.jsx(Renderer,{content:this.state.message,strings:this.context.strings})}),jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:this.props.apiOptions.readOnly,onClick:this._checkAnswer,children:this.context.strings.check}),isCorrect&&this.props.onNextQuestion&&jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:this.props.apiOptions.readOnly,onClick:this.props.onNextQuestion,style:{marginLeft:5},children:this.context.strings.nextQuestion})]}),this.props.hint?.content&&(this.state.showHint?jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("button",{tabIndex:"0",className:css(styles$j.explanationTitle),onClick:()=>this.setState({showHint:false}),onKeyPress:e=>{e.preventDefault();this.setState({showHint:false});},children:this.context.strings.hideExplanation}),jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.hint.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>{const{content,widgets,images}=this.props.hint;return jsxRuntimeExports.jsx(Renderer,{content:content,widgets:widgets,images:images,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,ref:this.hintRendererRef,apiOptions:apiOptions,linterContext:this.props.linterContext,strings:this.context.strings,showSolutions:showSolutions})}})]}):jsxRuntimeExports.jsx("button",{tabIndex:"0",onClick:()=>this.setState({showHint:true}),onKeyPress:e=>{e.preventDefault();this.setState({showHint:true});},className:css(styles$j.showHintLink),children:this.context.strings.explain})),apiOptions.isMobile&&jsxRuntimeExports.jsx(GradedGroupAnswerBar,{apiOptions:apiOptions,answerBarState:answerBarState,onCheckAnswer:this._checkAnswer,onNextQuestion:this.props.onNextQuestion})]})}constructor(...args){super(...args),this.state={status:GRADING_STATUSES.ungraded,showHint:false,message:"",answerBarState:"INACTIVE"},this.rendererRef=React.createRef(),this.hintRendererRef=React.createRef(),this._checkAnswer=()=>{const score=this.rendererRef.current?.score()||{type:"invalid"};const{INVALID_MESSAGE_PREFIX,DEFAULT_INVALID_MESSAGE_1,DEFAULT_INVALID_MESSAGE_2}=this.context.strings;const status=score.type==="points"?score.total===score.earned?GRADING_STATUSES.correct:GRADING_STATUSES.incorrect:GRADING_STATUSES.invalid;const message=score.type==="points"?score.message||"":score.message?`${INVALID_MESSAGE_PREFIX} ${mapErrorToString(score.message,this.context.strings)}`:`${INVALID_MESSAGE_PREFIX} ${DEFAULT_INVALID_MESSAGE_1}${DEFAULT_INVALID_MESSAGE_2}`;this.setState({status:status,message:message,answerBarState:status==="correct"?"CORRECT":"INCORRECT"});this.props.trackInteraction({status:status});},this.getInputPaths=()=>{return this.rendererRef.current?.getInputPaths()||[]},this.focus=()=>{return !!this.rendererRef.current?.focus()},this.focusInputPath=path=>{this.rendererRef.current?.focusPath(path);},this.blurInputPath=path=>{this.rendererRef.current?.blurPath(path);};}}GradedGroup.contextType=PerseusI18nContext;GradedGroup.defaultProps={title:"",content:"",widgets:{},images:{},hint:null,hasHint:false,linterContext:linterContextDefault};const styles$j=StyleSheet.create({gradedGroupInSet:{marginLeft:0,paddingLeft:0},gradedGroup:{borderTop:`1px solid ${gray76}`,borderBottom:`1px solid ${gray76}`,backgroundColor:tableBackgroundAccent,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"},showHintLink:{backgroundColor:"unset",fontSize:14,padding:0,border:"none",marginTop:20,color:semanticColor.core.foreground.instructive.default,cursor:"pointer",display:"block",clear:"both"},explanationTitle:{backgroundColor:"unset",marginTop:20,color:semanticColor.core.foreground.instructive.default,marginBottom:10,cursor:"pointer",fontSize:14,padding:0,border:"none",display:"block",clear:"both"},title:{fontSize:12,color:gray68,textTransform:"uppercase",marginBottom:11,letterSpacing:.8}});const WrappedGradedGroup=withDependencies(GradedGroup);var GradedGroup$1 = {name:"graded-group",displayName:"Graded group (articles only)",widget:WrappedGradedGroup,hidden:false,tracking:"all",isLintable:true};
1776
+ const GRADING_STATUSES={ungraded:"ungraded",correct:"correct",incorrect:"incorrect",invalid:"invalid"};const getNextState=(currentState,answerable)=>{switch(currentState){case "ACTIVE":return !answerable?"INACTIVE":currentState;case "INACTIVE":return answerable?"ACTIVE":currentState;case "INCORRECT":return answerable?"ACTIVE":"INACTIVE";default:return currentState}};class GradedGroup extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"graded-group",widgetSubType:"null",widgetId:this.props.widgetId}});}shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}_handleUserInput(_userInput,widgetsEmpty){this.setState({status:GRADING_STATUSES.ungraded,message:""});const answerable=!widgetsEmpty;const answerBarState=this.state.answerBarState;const nextState=getNextState(answerBarState,answerable);this.setState({answerBarState:nextState});}getPromptJSON(){const hint=this.hintRendererRef.current?.getPromptJSON()||{content:this.props.hint?.content||"",widgets:{}};return getPromptJSON$i(this.props.title,this.rendererRef.current?.getPromptJSON(),hint)}render(){const apiOptions=_.extend({},ApiOptions.defaults,this.props.apiOptions,{onFocusChange:(newFocus,oldFocus)=>{if(oldFocus){this.props.onBlur(oldFocus);}if(newFocus){this.props.onFocus(newFocus);}}});let gradeStatus=null;let icon=null;if(this.state.status===GRADING_STATUSES.correct){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconOk,style:{color:"#526f03"}});gradeStatus=this.context.strings.correct;}else if(this.state.status===GRADING_STATUSES.incorrect){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconRemove,style:{color:"#ff5454"}});gradeStatus=this.context.strings.incorrect;}const mobileClass=this.props.inGradedGroupSet?css(styles$k.gradedGroupInSet):css(styles$k.gradedGroup);const classes=classNames$2({[mobileClass]:apiOptions.isMobile,"perseus-graded-group":true,"answer-correct":apiOptions.isMobile?false:this.state.status===GRADING_STATUSES.correct,"answer-incorrect":apiOptions.isMobile?false:this.state.status===GRADING_STATUSES.incorrect});const{answerBarState}=this.state;const isCorrect=answerBarState==="CORRECT";const readOnly=apiOptions.readOnly||apiOptions.isMobile&&isCorrect;const showSolutions=isCorrect?"all":"none";return jsxRuntimeExports.jsxs("div",{className:classes,children:[!!this.props.title&&jsxRuntimeExports.jsx("div",{className:css(styles$k.title),children:this.props.title}),jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.widgets,handleUserInput:(userInput,widgetsEmpty)=>this._handleUserInput(userInput,widgetsEmpty),problemNum:0,children:({userInput,handleUserInput})=>jsxRuntimeExports.jsx(Renderer,{content:this.props.content,widgets:this.props.widgets,images:this.props.images,userInput:userInput,handleUserInput:handleUserInput,problemNum:0,ref:this.rendererRef,keypadElement:this.props.keypadElement,apiOptions:{...apiOptions,readOnly},showSolutions:showSolutions,linterContext:this.props.linterContext,strings:this.context.strings})}),!apiOptions.isMobile&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[icon!=null&&jsxRuntimeExports.jsx("div",{className:"group-icon",children:icon}),gradeStatus&&jsxRuntimeExports.jsx("div",{className:css(a11y.srOnly),role:"alert","aria-label":gradeStatus,children:gradeStatus}),jsxRuntimeExports.jsx("div",{role:"status","aria-live":"polite",children:jsxRuntimeExports.jsx(Renderer,{content:this.state.message,strings:this.context.strings})}),jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:this.props.apiOptions.readOnly,onClick:this._checkAnswer,children:this.context.strings.check}),isCorrect&&this.props.onNextQuestion&&jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:this.props.apiOptions.readOnly,onClick:this.props.onNextQuestion,style:{marginLeft:5},children:this.context.strings.nextQuestion})]}),this.props.hint?.content&&(this.state.showHint?jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("button",{tabIndex:"0",className:css(styles$k.explanationTitle),onClick:()=>this.setState({showHint:false}),onKeyPress:e=>{e.preventDefault();this.setState({showHint:false});},children:this.context.strings.hideExplanation}),jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.hint.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>{const{content,widgets,images}=this.props.hint;return jsxRuntimeExports.jsx(Renderer,{content:content,widgets:widgets,images:images,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,ref:this.hintRendererRef,apiOptions:apiOptions,linterContext:this.props.linterContext,strings:this.context.strings,showSolutions:showSolutions})}})]}):jsxRuntimeExports.jsx("button",{tabIndex:"0",onClick:()=>this.setState({showHint:true}),onKeyPress:e=>{e.preventDefault();this.setState({showHint:true});},className:css(styles$k.showHintLink),children:this.context.strings.explain})),apiOptions.isMobile&&jsxRuntimeExports.jsx(GradedGroupAnswerBar,{apiOptions:apiOptions,answerBarState:answerBarState,onCheckAnswer:this._checkAnswer,onNextQuestion:this.props.onNextQuestion})]})}constructor(...args){super(...args),this.state={status:GRADING_STATUSES.ungraded,showHint:false,message:"",answerBarState:"INACTIVE"},this.rendererRef=React.createRef(),this.hintRendererRef=React.createRef(),this._checkAnswer=()=>{const score=this.rendererRef.current?.score()||{type:"invalid"};const{INVALID_MESSAGE_PREFIX,DEFAULT_INVALID_MESSAGE_1,DEFAULT_INVALID_MESSAGE_2}=this.context.strings;const status=score.type==="points"?score.total===score.earned?GRADING_STATUSES.correct:GRADING_STATUSES.incorrect:GRADING_STATUSES.invalid;const message=score.type==="points"?score.message||"":score.message?`${INVALID_MESSAGE_PREFIX} ${mapErrorToString(score.message,this.context.strings)}`:`${INVALID_MESSAGE_PREFIX} ${DEFAULT_INVALID_MESSAGE_1}${DEFAULT_INVALID_MESSAGE_2}`;this.setState({status:status,message:message,answerBarState:status==="correct"?"CORRECT":"INCORRECT"});this.props.trackInteraction({status:status});},this.getInputPaths=()=>{return this.rendererRef.current?.getInputPaths()||[]},this.focus=()=>{return !!this.rendererRef.current?.focus()},this.focusInputPath=path=>{this.rendererRef.current?.focusPath(path);},this.blurInputPath=path=>{this.rendererRef.current?.blurPath(path);};}}GradedGroup.contextType=PerseusI18nContext;GradedGroup.defaultProps={title:"",content:"",widgets:{},images:{},hint:null,hasHint:false,linterContext:linterContextDefault};const styles$k=StyleSheet.create({gradedGroupInSet:{marginLeft:0,paddingLeft:0},gradedGroup:{borderTop:`1px solid ${gray76}`,borderBottom:`1px solid ${gray76}`,backgroundColor:tableBackgroundAccent,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"},showHintLink:{backgroundColor:"unset",fontSize:14,padding:0,border:"none",marginTop:20,color:semanticColor.core.foreground.instructive.default,cursor:"pointer",display:"block",clear:"both"},explanationTitle:{backgroundColor:"unset",marginTop:20,color:semanticColor.core.foreground.instructive.default,marginBottom:10,cursor:"pointer",fontSize:14,padding:0,border:"none",display:"block",clear:"both"},title:{fontSize:12,color:gray68,textTransform:"uppercase",marginBottom:11,letterSpacing:.8}});const WrappedGradedGroup=withDependencies(GradedGroup);var GradedGroup$1 = {name:"graded-group",displayName:"Graded group (articles only)",widget:WrappedGradedGroup,hidden:false,tracking:"all",isLintable:true};
1777
1777
 
1778
1778
  const getPromptJSON$h=(widgetData,activeGroupJSON)=>{return {type:"graded-group-set",options:{groupCount:widgetData.gradedGroups.length,currentGroup:activeGroupJSON}}};
1779
1779
 
1780
- class Indicators extends React.Component{render(){return jsxRuntimeExports.jsx("ul",{role:"list",className:classNames$2(css(styles$i.indicatorContainer),"indicatorContainer"),children:this.props.gradedGroups.map(({title},i)=>jsxRuntimeExports.jsx("li",{className:css(styles$i.indicator),children:jsxRuntimeExports.jsx(Clickable,{role:"button","aria-label":title,"aria-current":i===this.props.currentGroup,style:styles$i.indicatorButton,onClick:()=>this.props.onChangeCurrentGroup(i),onKeyDown:e=>this.handleKeyDown(e,i),children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(View,{style:[styles$i.indicatorDot,(hovered||focused||pressed)&&styles$i.indicatorDotFocused],children:i===this.props.currentGroup&&jsxRuntimeExports.jsx(View,{style:styles$i.indicatorDotActive})})})},i))})}constructor(...args){super(...args),this.handleKeyDown=(e,i)=>{if(e.key==="Enter"||e.key===" "){this.props.onChangeCurrentGroup(i);}};}}Indicators.contextType=PerseusI18nContext;class GradedGroupSet extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"graded-group-set",widgetSubType:"null",widgetId:this.props.widgetId}});}shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}getPromptJSON(){const activeGroupPromptJSON=this._childGroup.getPromptJSON();return getPromptJSON$h(this.props,activeGroupPromptJSON)}render(){const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.props.gradedGroups.length>1){return jsxRuntimeExports.jsx("div",{className:css(styles$i.container),children:this.props.gradedGroups.map((gradedGroup,i)=>{return jsxRuntimeExports.jsx(GradedGroup,{...this.props,...gradedGroup,inGradedGroupSet:false,linterContext:this.props.linterContext},i)})})}const currentGroup=this.props.gradedGroups[this.state.currentGroup];if(!currentGroup){return jsxRuntimeExports.jsx("span",{children:"No current group..."})}const numGroups=this.props.gradedGroups.length;const handleNextQuestion=this.state.currentGroup<numGroups-1?this.handleNextQuestion:null;return jsxRuntimeExports.jsxs("div",{className:css(styles$i.container),children:[jsxRuntimeExports.jsxs("div",{className:css(styles$i.top),children:[jsxRuntimeExports.jsx("div",{className:css(styles$i.title),children:currentGroup.title}),jsxRuntimeExports.jsx("div",{className:css(styles$i.spacer)}),jsxRuntimeExports.jsx(Indicators,{currentGroup:this.state.currentGroup,gradedGroups:this.props.gradedGroups,onChangeCurrentGroup:currentGroup=>this.setState({currentGroup})})]}),jsxRuntimeExports.jsx(GradedGroup,{ref:comp=>this._childGroup=comp,...this.props,...currentGroup,inGradedGroupSet:true,title:null,onNextQuestion:handleNextQuestion,linterContext:this.props.linterContext},this.state.currentGroup)]})}constructor(...args){super(...args),this.state={currentGroup:0},this.getInputPaths=()=>{return this._childGroup.getInputPaths()},this.focus=()=>{return this._childGroup.focus()},this.focusInputPath=path=>{this._childGroup.focusInputPath(path);},this.blurInputPath=path=>{this._childGroup.blurInputPath(path);},this.handleNextQuestion=()=>{const{currentGroup}=this.state;const numGroups=this.props.gradedGroups.length;if(currentGroup<numGroups-1){this.setState({currentGroup:currentGroup+1});}};}}GradedGroupSet.defaultProps={gradedGroups:[],linterContext:linterContextDefault};const WrappedGradedGroupSet=withDependencies(GradedGroupSet);var GradedGroupSet$1 = {name:"graded-group-set",displayName:"Graded group set (articles only)",widget:WrappedGradedGroupSet,hidden:false,tracking:"all",isLintable:true};const styles$i=StyleSheet.create({top:{display:"flex",flexDirection:"row"},spacer:{flex:1},title:{fontSize:12,color:semanticColor.core.foreground.neutral.subtle,textTransform:"uppercase",marginBottom:11,letterSpacing:.8},indicatorContainer:{display:"flex",flexDirection:"row",listStyleType:"none",margin:"unset",paddingInlineStart:"unset",flexWrap:"wrap"},indicator:{width:24,height:24},indicatorButton:{width:"100%",height:"100%",display:"flex",flexWrap:"wrap",placeContent:"center",cursor:"pointer",":focus":{outline:"none"}},indicatorDot:{boxSizing:"content-box",width:10,height:10,borderRadius:"100%",borderWidth:2,borderColor:semanticColor.core.border.instructive.default,borderStyle:"solid"},indicatorDotFocused:{borderWidth:5,borderStyle:"double"},indicatorDotActive:{backgroundColor:semanticColor.core.background.instructive.default,width:"100%",height:"100%"},container:{borderTop:`1px solid ${gray76}`,borderBottom:`1px solid ${gray76}`,backgroundColor:tableBackgroundAccent,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"}});
1780
+ class Indicators extends React.Component{render(){return jsxRuntimeExports.jsx("ul",{role:"list",className:classNames$2(css(styles$j.indicatorContainer),"indicatorContainer"),children:this.props.gradedGroups.map(({title},i)=>jsxRuntimeExports.jsx("li",{className:css(styles$j.indicator),children:jsxRuntimeExports.jsx(Clickable,{role:"button","aria-label":title,"aria-current":i===this.props.currentGroup,style:styles$j.indicatorButton,onClick:()=>this.props.onChangeCurrentGroup(i),onKeyDown:e=>this.handleKeyDown(e,i),children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(View,{style:[styles$j.indicatorDot,(hovered||focused||pressed)&&styles$j.indicatorDotFocused],children:i===this.props.currentGroup&&jsxRuntimeExports.jsx(View,{style:styles$j.indicatorDotActive})})})},i))})}constructor(...args){super(...args),this.handleKeyDown=(e,i)=>{if(e.key==="Enter"||e.key===" "){this.props.onChangeCurrentGroup(i);}};}}Indicators.contextType=PerseusI18nContext;class GradedGroupSet extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"graded-group-set",widgetSubType:"null",widgetId:this.props.widgetId}});}shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}getPromptJSON(){const activeGroupPromptJSON=this._childGroup.getPromptJSON();return getPromptJSON$h(this.props,activeGroupPromptJSON)}render(){const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.props.gradedGroups.length>1){return jsxRuntimeExports.jsx("div",{className:css(styles$j.container),children:this.props.gradedGroups.map((gradedGroup,i)=>{return jsxRuntimeExports.jsx(GradedGroup,{...this.props,...gradedGroup,inGradedGroupSet:false,linterContext:this.props.linterContext},i)})})}const currentGroup=this.props.gradedGroups[this.state.currentGroup];if(!currentGroup){return jsxRuntimeExports.jsx("span",{children:"No current group..."})}const numGroups=this.props.gradedGroups.length;const handleNextQuestion=this.state.currentGroup<numGroups-1?this.handleNextQuestion:null;return jsxRuntimeExports.jsxs("div",{className:css(styles$j.container),children:[jsxRuntimeExports.jsxs("div",{className:css(styles$j.top),children:[jsxRuntimeExports.jsx("div",{className:css(styles$j.title),children:currentGroup.title}),jsxRuntimeExports.jsx("div",{className:css(styles$j.spacer)}),jsxRuntimeExports.jsx(Indicators,{currentGroup:this.state.currentGroup,gradedGroups:this.props.gradedGroups,onChangeCurrentGroup:currentGroup=>this.setState({currentGroup})})]}),jsxRuntimeExports.jsx(GradedGroup,{ref:comp=>this._childGroup=comp,...this.props,...currentGroup,inGradedGroupSet:true,title:null,onNextQuestion:handleNextQuestion,linterContext:this.props.linterContext},this.state.currentGroup)]})}constructor(...args){super(...args),this.state={currentGroup:0},this.getInputPaths=()=>{return this._childGroup.getInputPaths()},this.focus=()=>{return this._childGroup.focus()},this.focusInputPath=path=>{this._childGroup.focusInputPath(path);},this.blurInputPath=path=>{this._childGroup.blurInputPath(path);},this.handleNextQuestion=()=>{const{currentGroup}=this.state;const numGroups=this.props.gradedGroups.length;if(currentGroup<numGroups-1){this.setState({currentGroup:currentGroup+1});}};}}GradedGroupSet.defaultProps={gradedGroups:[],linterContext:linterContextDefault};const WrappedGradedGroupSet=withDependencies(GradedGroupSet);var GradedGroupSet$1 = {name:"graded-group-set",displayName:"Graded group set (articles only)",widget:WrappedGradedGroupSet,hidden:false,tracking:"all",isLintable:true};const styles$j=StyleSheet.create({top:{display:"flex",flexDirection:"row"},spacer:{flex:1},title:{fontSize:12,color:semanticColor.core.foreground.neutral.subtle,textTransform:"uppercase",marginBottom:11,letterSpacing:.8},indicatorContainer:{display:"flex",flexDirection:"row",listStyleType:"none",margin:"unset",paddingInlineStart:"unset",flexWrap:"wrap"},indicator:{width:24,height:24},indicatorButton:{width:"100%",height:"100%",display:"flex",flexWrap:"wrap",placeContent:"center",cursor:"pointer",":focus":{outline:"none"}},indicatorDot:{boxSizing:"content-box",width:10,height:10,borderRadius:"100%",borderWidth:2,borderColor:semanticColor.core.border.instructive.default,borderStyle:"solid"},indicatorDotFocused:{borderWidth:5,borderStyle:"double"},indicatorDotActive:{backgroundColor:semanticColor.core.background.instructive.default,width:"100%",height:"100%"},container:{borderTop:`1px solid ${gray76}`,borderBottom:`1px solid ${gray76}`,backgroundColor:tableBackgroundAccent,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"}});
1781
1781
 
1782
- class ButtonGroup extends React.Component{componentWillUnmount(){this.container=null;}focus(){if(this.container){this.container.focus();return true}}toggleSelect(newValue){const value=this.props.value;if(this.props.allowEmpty){this.props.onChange(value!==newValue?newValue:null);}else {this.props.onChange(newValue);}}render(){const value=this.props.value;const buttons=this.props.buttons.map((button,i)=>{return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",ref:"button"+i,className:css(styles$h.buttonStyle,button.value===value&&styles$h.selectedStyle,button.value===value&&this.props.selectedButtonStyle),onClick:()=>this.toggleSelect(button.value),children:button.content||""+button.value},""+i)});const outerStyle={display:"inline-block"};return jsxRuntimeExports.jsx("div",{style:outerStyle,ref:node=>this.container=node,children:buttons})}}ButtonGroup.defaultProps={value:null,allowEmpty:true};const styles$h=StyleSheet.create({buttonStyle:{backgroundColor:"white",border:"1px solid #ccc",borderLeft:"0",cursor:"pointer",margin:"0",padding:"5px 10px",position:"relative",":first-child":{borderLeft:"1px solid #ccc",borderTopLeftRadius:"3px",borderBottomLeftRadius:"3px"},":last-child":{borderRight:"1px solid #ccc",borderTopRightRadius:"3px",borderBottomRightRadius:"3px"},":hover":{backgroundColor:"#ccc"},":focus":{zIndex:2}},selectedStyle:{backgroundColor:"#ddd"}});
1782
+ class ButtonGroup extends React.Component{componentWillUnmount(){this.container=null;}focus(){if(this.container){this.container.focus();return true}}toggleSelect(newValue){const value=this.props.value;if(this.props.allowEmpty){this.props.onChange(value!==newValue?newValue:null);}else {this.props.onChange(newValue);}}render(){const value=this.props.value;const buttons=this.props.buttons.map((button,i)=>{return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",ref:"button"+i,className:css(styles$i.buttonStyle,button.value===value&&styles$i.selectedStyle,button.value===value&&this.props.selectedButtonStyle),onClick:()=>this.toggleSelect(button.value),children:button.content||""+button.value},""+i)});const outerStyle={display:"inline-block"};return jsxRuntimeExports.jsx("div",{style:outerStyle,ref:node=>this.container=node,children:buttons})}}ButtonGroup.defaultProps={value:null,allowEmpty:true};const styles$i=StyleSheet.create({buttonStyle:{backgroundColor:"white",border:"1px solid #ccc",borderLeft:"0",cursor:"pointer",margin:"0",padding:"5px 10px",position:"relative",":first-child":{borderLeft:"1px solid #ccc",borderTopLeftRadius:"3px",borderBottomLeftRadius:"3px"},":last-child":{borderRight:"1px solid #ccc",borderTopRightRadius:"3px",borderBottomRightRadius:"3px"},":hover":{backgroundColor:"#ccc"},":focus":{zIndex:2}},selectedStyle:{backgroundColor:"#ddd"}});
1783
1783
 
1784
1784
  const getPromptJSON$g=widgetData=>{const{userInput}=widgetData;const{type,coords}=userInput;const input={type,coords};if(userInput.type==="logarithm"||userInput.type==="exponential"){input["asymptote"]=userInput.asymptote;}return {type:"grapher",options:{availableTypes:widgetData.availableTypes,range:widgetData.graph.range,labels:widgetData.graph.labels,tickStep:widgetData.graph.step,gridStep:widgetData.graph.gridStep,snapStep:widgetData.graph.snapStep,backgroundImageUrl:widgetData.graph.backgroundImage.url},userInput:input}};
1785
1785
 
@@ -1797,19 +1797,19 @@ const{updateQueryString}=Util;class Iframe extends React.Component{componentDidM
1797
1797
 
1798
1798
  const getPromptJSON$d=widgetData=>{return {type:"image",options:{altText:widgetData.alt,title:widgetData.title,caption:widgetData.caption,imageUrl:widgetData.backgroundImage.url}}};
1799
1799
 
1800
- var styles$g = {"titleContainer":"perseus_aAJy9Er3","infoAreaContainer":"perseus_a7ZnxMAZ","modalContainer":"perseus_-p2ghr1-","modalTitleContainer":"perseus_YxnjOOa7","modalPanelContainer":"perseus_ryDvI8uD","modalImageContainer":"perseus_yCoMyk8e","modalDescriptionContainer":"perseus_femvuTvR","modalCaptionContainer":"perseus_y4DO7MoR","spacerHorizontal":"perseus_fBhKbquh","spacerVertical":"perseus_9XgZ2QXH"};
1800
+ var styles$h = {"titleContainer":"perseus_aAJy9Er3","infoAreaContainer":"perseus_a7ZnxMAZ","modalContainer":"perseus_-p2ghr1-","modalTitleContainer":"perseus_YxnjOOa7","modalPanelContainer":"perseus_ryDvI8uD","modalImageContainer":"perseus_yCoMyk8e","modalDescriptionContainer":"perseus_femvuTvR","modalCaptionContainer":"perseus_y4DO7MoR","spacerHorizontal":"perseus_fBhKbquh","spacerVertical":"perseus_9XgZ2QXH"};
1801
1801
 
1802
1802
  function ExploreImageButton({hasCaption,onClick}){const context=React.useContext(PerseusI18nContext);if(!hasCaption){return jsxRuntimeExports.jsx(Button,{"aria-label":context.strings.imageExploreButtonAriaLabel,kind:"secondary",startIcon:infoIconBold,onClick:onClick,children:context.strings.imageExploreButton})}return jsxRuntimeExports.jsx(IconButton,{"aria-label":context.strings.imageExploreButtonAriaLabel,icon:infoIconBold,kind:"secondary",onClick:onClick,style:{flexShrink:0}})}
1803
1803
 
1804
- const VisibleIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",className:css(styles$f.icon),children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsx("path",{id:"a",d:"M7.401 10.035c-1.424.748-2.599 1.905-3.544 "+"3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 "+"12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 "+"1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-"+"3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 "+"0 0 0 0 6z"})}),jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[jsxRuntimeExports.jsx("path",{fill:"none",d:"M0 0h24v24H0z"}),jsxRuntimeExports.jsx("mask",{id:"b",fill:"#fff",children:jsxRuntimeExports.jsx("use",{href:"#a"})}),jsxRuntimeExports.jsx("use",{fill:"#fff",fillRule:"nonzero",href:"#a"}),jsxRuntimeExports.jsx("g",{fill:"#fff",mask:"url(#b)",children:jsxRuntimeExports.jsx("path",{d:"M0 0h24v24H0z"})})]})]});const HiddenIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",className:css(styles$f.icon),children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsx("path",{id:"a",d:"M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 "+"7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 "+"1.028c-.945-1.574-2.12-2.73-3.544-3.48.258."+"604.401 1.268.401 1.966 0 1.02-.305 "+"1.967-.828 2.757l2.535 2.536a1 1 0 0 "+"1-1.414 1.414l-12-12a1 1 0 0 1 "+"1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 "+"0-4.001-4.001l4 4.001zM6.072 8.486l2.976 "+"2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 "+"0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 "+"3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 "+"2.363-3.085 3.929-4z"})}),jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[jsxRuntimeExports.jsx("path",{fill:"none",d:"M0 0h24v24H0z"}),jsxRuntimeExports.jsx("mask",{id:"b",fill:"#fff",children:jsxRuntimeExports.jsx("use",{href:"#a"})}),jsxRuntimeExports.jsx("use",{fill:"#fff",fillRule:"nonzero",href:"#a"}),jsxRuntimeExports.jsx("g",{fill:"#fff",mask:"url(#b)",children:jsxRuntimeExports.jsx("path",{d:"M0 0h24v24H0z"})})]})]});const HUD=({message,enabled,onClick,fixedPosition=true})=>{let state;let icon;if(enabled){state=styles$f.enabled;icon=jsxRuntimeExports.jsx(VisibleIcon,{});}else {state=styles$f.disabled;icon=jsxRuntimeExports.jsx(HiddenIcon,{});}return jsxRuntimeExports.jsxs("button",{className:css(styles$f.hud,fixedPosition&&styles$f.hudFixedPosition,state),onClick:e=>{onClick();},children:[icon,message]})};const styles$f=StyleSheet.create({hud:{boxSizing:"border-box",height:36,padding:"9px 16px",borderRadius:18,fontFamily:boldFontFamily,fontSize:"15px",lineHeight:"18px",color:white,userSelect:"none",borderWidth:0},hudFixedPosition:{bottom:20,position:"fixed",right:20,zIndex:1},icon:{width:24,height:24,marginRight:8,marginTop:-3,verticalAlign:"middle"},enabled:{backgroundColor:warningColor,":hover":{backgroundColor:warningColorHover},":active":{backgroundColor:warningColorActive}},disabled:{backgroundColor:gray76,":hover":{backgroundColor:"#a1a5a9"},":active":{backgroundColor:gray68}}});
1804
+ const VisibleIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",className:css(styles$g.icon),children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsx("path",{id:"a",d:"M7.401 10.035c-1.424.748-2.599 1.905-3.544 "+"3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 "+"12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 "+"1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-"+"3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 "+"0 0 0 0 6z"})}),jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[jsxRuntimeExports.jsx("path",{fill:"none",d:"M0 0h24v24H0z"}),jsxRuntimeExports.jsx("mask",{id:"b",fill:"#fff",children:jsxRuntimeExports.jsx("use",{href:"#a"})}),jsxRuntimeExports.jsx("use",{fill:"#fff",fillRule:"nonzero",href:"#a"}),jsxRuntimeExports.jsx("g",{fill:"#fff",mask:"url(#b)",children:jsxRuntimeExports.jsx("path",{d:"M0 0h24v24H0z"})})]})]});const HiddenIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",className:css(styles$g.icon),children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsx("path",{id:"a",d:"M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 "+"7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 "+"1.028c-.945-1.574-2.12-2.73-3.544-3.48.258."+"604.401 1.268.401 1.966 0 1.02-.305 "+"1.967-.828 2.757l2.535 2.536a1 1 0 0 "+"1-1.414 1.414l-12-12a1 1 0 0 1 "+"1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 "+"0-4.001-4.001l4 4.001zM6.072 8.486l2.976 "+"2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 "+"0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 "+"3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 "+"2.363-3.085 3.929-4z"})}),jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[jsxRuntimeExports.jsx("path",{fill:"none",d:"M0 0h24v24H0z"}),jsxRuntimeExports.jsx("mask",{id:"b",fill:"#fff",children:jsxRuntimeExports.jsx("use",{href:"#a"})}),jsxRuntimeExports.jsx("use",{fill:"#fff",fillRule:"nonzero",href:"#a"}),jsxRuntimeExports.jsx("g",{fill:"#fff",mask:"url(#b)",children:jsxRuntimeExports.jsx("path",{d:"M0 0h24v24H0z"})})]})]});const HUD=({message,enabled,onClick,fixedPosition=true})=>{let state;let icon;if(enabled){state=styles$g.enabled;icon=jsxRuntimeExports.jsx(VisibleIcon,{});}else {state=styles$g.disabled;icon=jsxRuntimeExports.jsx(HiddenIcon,{});}return jsxRuntimeExports.jsxs("button",{className:css(styles$g.hud,fixedPosition&&styles$g.hudFixedPosition,state),onClick:e=>{onClick();},children:[icon,message]})};const styles$g=StyleSheet.create({hud:{boxSizing:"border-box",height:36,padding:"9px 16px",borderRadius:18,fontFamily:boldFontFamily,fontSize:"15px",lineHeight:"18px",color:white,userSelect:"none",borderWidth:0},hudFixedPosition:{bottom:20,position:"fixed",right:20,zIndex:1},icon:{width:24,height:24,marginRight:8,marginTop:-3,verticalAlign:"middle"},enabled:{backgroundColor:warningColor,":hover":{backgroundColor:warningColorHover},":active":{backgroundColor:warningColorActive}},disabled:{backgroundColor:gray76,":hover":{backgroundColor:"#a1a5a9"},":active":{backgroundColor:gray68}}});
1805
1805
 
1806
1806
  const BASE_ICON_SIZE=10;class Icon extends React.Component{render(){const{color,pathClassName,className,title,style,alt}=this.props;let{icon,size}=this.props;let units="";if(typeof icon==="string"){icon={path:icon,width:BASE_ICON_SIZE,height:BASE_ICON_SIZE};}if(typeof size!=="number"){size=1;units="em";}const height=size;const width=height/icon.height*icon.width;const xMin=0;const yMin=0;const focusable=!!this.props.focusable;return jsxRuntimeExports.jsxs("svg",{role:"img",alt:alt,"aria-label":title,"aria-hidden":title?null:true,className:className,style:style,focusable:focusable.toString(),width:width+units,height:height+units,viewBox:`${xMin} ${yMin} ${icon.width} ${icon.height}`,children:[!!title&&jsxRuntimeExports.jsx("title",{children:title}),jsxRuntimeExports.jsx("path",{className:pathClassName,fill:color,d:icon.path})]})}}Icon.defaultProps={color:"currentColor"};
1807
1807
 
1808
- const InfoTipBase=props=>{return jsxRuntimeExports.jsx(Tooltip,{content:jsxRuntimeExports.jsx(BodyText,{style:styles$e.body,children:props.children}),placement:"right",children:jsxRuntimeExports.jsx(PhosphorIcon,{size:"small",icon:questionIcon,style:styles$e.spacingLeft})})};const styles$e=StyleSheet.create({spacingLeft:{marginInlineStart:spacing.xxxSmall_4},body:{padding:spacing.medium_16}});
1808
+ const InfoTipBase=props=>{return jsxRuntimeExports.jsx(Tooltip,{content:jsxRuntimeExports.jsx(BodyText,{style:styles$f.body,children:props.children}),placement:"right",children:jsxRuntimeExports.jsx(PhosphorIcon,{size:"small",icon:questionIcon,style:styles$f.spacingLeft})})};const styles$f=StyleSheet.create({spacingLeft:{marginInlineStart:spacing.xxxSmall_4},body:{padding:spacing.medium_16}});
1809
1809
 
1810
1810
  class InfoTip extends React.Component{componentDidMount(){this.setState({didMount:true});}render(){if(this.state.didMount){return jsxRuntimeExports.jsx(InfoTipBase,{...this.props})}return jsxRuntimeExports.jsx("div",{})}constructor(...args){super(...args),this.state={didMount:false};}}
1811
1811
 
1812
- class MultiButtonGroup extends React.Component{focus(){this.buttonContainerRef.current?.focus();return true}render(){const values=this.props.values||[];const buttons=this.props.buttons.map((button,i)=>{const selected=values.indexOf(button.value)>=0;return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",id:""+i,ref:"button"+i,className:css(styles$d.buttonStyle,selected&&styles$d.selectedStyle),onClick:()=>this.toggleSelect(button.value),children:button.content||""+button.value},""+i)});const outerStyle={display:"inline-block"};return jsxRuntimeExports.jsx("div",{style:outerStyle,ref:this.buttonContainerRef,children:buttons})}constructor(...args){super(...args),this.buttonContainerRef=React.createRef(),this.toggleSelect=newValue=>{const values=(this.props.values||[]).slice(0);const allowEmpty=this.props.allowEmpty;if(values.indexOf(newValue)>=0&&(values.length>1||allowEmpty)){values.splice(values.indexOf(newValue),1);}else {if(values.indexOf(newValue)<0){values.push(newValue);}}this.props.onChange(values);};}}MultiButtonGroup.defaultProps={values:[],allowEmpty:true};const styles$d=StyleSheet.create({buttonStyle:{backgroundColor:"white",border:"1px solid #ccc",borderLeft:"0",cursor:"pointer",margin:"0",padding:"5px 10px",position:"relative",":first-child":{borderLeft:"1px solid #ccc",borderTopLeftRadius:"3px",borderBottomLeftRadius:"3px"},":last-child":{borderRight:"1px solid #ccc",borderTopRightRadius:"3px",borderBottomRightRadius:"3px"},":hover":{backgroundColor:"#ccc"},":focus":{zIndex:2}},selectedStyle:{backgroundColor:"#ddd"}});
1812
+ class MultiButtonGroup extends React.Component{focus(){this.buttonContainerRef.current?.focus();return true}render(){const values=this.props.values||[];const buttons=this.props.buttons.map((button,i)=>{const selected=values.indexOf(button.value)>=0;return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",id:""+i,ref:"button"+i,className:css(styles$e.buttonStyle,selected&&styles$e.selectedStyle),onClick:()=>this.toggleSelect(button.value),children:button.content||""+button.value},""+i)});const outerStyle={display:"inline-block"};return jsxRuntimeExports.jsx("div",{style:outerStyle,ref:this.buttonContainerRef,children:buttons})}constructor(...args){super(...args),this.buttonContainerRef=React.createRef(),this.toggleSelect=newValue=>{const values=(this.props.values||[]).slice(0);const allowEmpty=this.props.allowEmpty;if(values.indexOf(newValue)>=0&&(values.length>1||allowEmpty)){values.splice(values.indexOf(newValue),1);}else {if(values.indexOf(newValue)<0){values.push(newValue);}}this.props.onChange(values);};}}MultiButtonGroup.defaultProps={values:[],allowEmpty:true};const styles$e=StyleSheet.create({buttonStyle:{backgroundColor:"white",border:"1px solid #ccc",borderLeft:"0",cursor:"pointer",margin:"0",padding:"5px 10px",position:"relative",":first-child":{borderLeft:"1px solid #ccc",borderTopLeftRadius:"3px",borderBottomLeftRadius:"3px"},":last-child":{borderRight:"1px solid #ccc",borderTopRightRadius:"3px",borderBottomRightRadius:"3px"},":hover":{backgroundColor:"#ccc"},":focus":{zIndex:2}},selectedStyle:{backgroundColor:"#ddd"}});
1813
1813
 
1814
1814
  function isPiMultiple(value){if(Number.isInteger(value)){return false}return value%Math.PI===0||value%(Math.PI/2)===0||value%(Math.PI/3)===0||value%(Math.PI/4)===0||value%(Math.PI/6)===0}
1815
1815
 
@@ -1838,15 +1838,15 @@ var components = /*#__PURE__*/Object.freeze({
1838
1838
 
1839
1839
  const GifControlsButton=({isPlaying,onToggle})=>{const strings=usePerseusI18n().strings;return jsxRuntimeExports.jsx(Button,{"aria-label":isPlaying?strings.gifPauseButtonLabel:strings.gifPlayButtonLabel,kind:"secondary",startIcon:isPlaying?pauseIcon:playIcon,onClick:onToggle,style:{width:"fit-content"},children:isPlaying?strings.gifPauseButtonLabel:strings.gifPlayButtonLabel})};
1840
1840
 
1841
- const MODAL_HEIGHT=568;function ExploreImageModalContent({backgroundImage,scale:contentScale,caption,alt,longDescription,linterContext,apiOptions,box,labels,range,captionId,longDescId}){const[isGifPlaying,setIsGifPlaying]=React.useState(false);const context=React.useContext(PerseusI18nContext);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);const imageIsSvg=isSvg(backgroundImage.url);let scale=1;if(backgroundImage.width&&backgroundImage.height){scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);}let height=backgroundImage.height;let width=backgroundImage.width;if(backgroundImage.height&&backgroundImage.width){width=backgroundImage.width;height=backgroundImage.height;const maxScale=MODAL_HEIGHT/backgroundImage.height;scale=Math.min(scale,maxScale);}return jsxRuntimeExports.jsxs("div",{className:styles$g.modalPanelContainer,children:[jsxRuntimeExports.jsx("div",{className:styles$g.modalImageContainer,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:backgroundImage.url,allowZoom:false,alt:caption===alt?"":alt,width:width,height:height,scale:scale,extraGraphie:{box:box,range:range,labels:labels??[]},zoomToFullSizeOnMobile:apiOptions.isMobile,constrainHeight:apiOptions.isMobile,allowFullBleed:apiOptions.isMobile,setAssetStatus:setAssetStatus,isGifPlaying:imageIsGif?isGifPlaying:undefined,onGifLoop:imageIsGif?()=>setIsGifPlaying(false):undefined})})}),jsxRuntimeExports.jsxs("div",{className:`perseus-image-modal-description ${styles$g.modalDescriptionContainer}`,children:[imageIsGif&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(GifControlsButton,{isPlaying:isGifPlaying,onToggle:()=>setIsGifPlaying(!isGifPlaying)}),jsxRuntimeExports.jsx("div",{className:styles$g.spacerVertical})]}),caption&&jsxRuntimeExports.jsx("div",{id:captionId,className:styles$g.modalCaptionContainer,children:jsxRuntimeExports.jsx(Renderer,{content:caption,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})}),jsxRuntimeExports.jsx(Heading,{size:"large",tag:"h2",style:wbStyles$1.descriptionHeading,children:context.strings.imageDescriptionLabel}),jsxRuntimeExports.jsx("div",{id:longDescId,children:jsxRuntimeExports.jsx(Renderer,{content:longDescription,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})})]})]})}const wbStyles$1={descriptionHeading:{marginBlockEnd:sizing.size_160}};
1841
+ const MODAL_HEIGHT=568;function ExploreImageModalContent({backgroundImage,scale:contentScale,caption,alt,longDescription,linterContext,apiOptions,box,labels,range,captionId,longDescId}){const[isGifPlaying,setIsGifPlaying]=React.useState(false);const context=React.useContext(PerseusI18nContext);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);const imageIsSvg=isSvg(backgroundImage.url);let scale=1;if(backgroundImage.width&&backgroundImage.height){scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);}let height=backgroundImage.height;let width=backgroundImage.width;if(backgroundImage.height&&backgroundImage.width){width=backgroundImage.width;height=backgroundImage.height;const maxScale=MODAL_HEIGHT/backgroundImage.height;scale=Math.min(scale,maxScale);}return jsxRuntimeExports.jsxs("div",{className:styles$h.modalPanelContainer,children:[jsxRuntimeExports.jsx("div",{className:styles$h.modalImageContainer,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:backgroundImage.url,allowZoom:false,alt:caption===alt?"":alt,width:width,height:height,scale:scale,extraGraphie:{box:box,range:range,labels:labels??[]},zoomToFullSizeOnMobile:apiOptions.isMobile,constrainHeight:apiOptions.isMobile,allowFullBleed:apiOptions.isMobile,setAssetStatus:setAssetStatus,isGifPlaying:imageIsGif?isGifPlaying:undefined,onGifLoop:imageIsGif?()=>setIsGifPlaying(false):undefined})})}),jsxRuntimeExports.jsxs("div",{className:`perseus-image-modal-description ${styles$h.modalDescriptionContainer}`,children:[imageIsGif&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(GifControlsButton,{isPlaying:isGifPlaying,onToggle:()=>setIsGifPlaying(!isGifPlaying)}),jsxRuntimeExports.jsx("div",{className:styles$h.spacerVertical})]}),caption&&jsxRuntimeExports.jsx("div",{id:captionId,className:styles$h.modalCaptionContainer,children:jsxRuntimeExports.jsx(Renderer,{content:caption,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})}),jsxRuntimeExports.jsx(Heading,{size:"large",tag:"h2",style:wbStyles$1.descriptionHeading,children:context.strings.imageDescriptionLabel}),jsxRuntimeExports.jsx("div",{id:longDescId,children:jsxRuntimeExports.jsx(Renderer,{content:longDescription,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})})]})]})}const wbStyles$1={descriptionHeading:{marginBlockEnd:sizing.size_160}};
1842
1842
 
1843
- const ExploreImageModal=props=>{const context=React__default.useContext(PerseusI18nContext);const uniqueId=React__default.useId();const captionId=`${uniqueId}-caption`;const longDescId=`${uniqueId}-long-desc`;const titleText=props.title||context.strings.imageAlternativeTitle;const title=jsxRuntimeExports.jsx("h1",{className:`perseus-image-modal-title ${styles$g.modalTitleContainer}`,children:jsxRuntimeExports.jsx(Renderer,{content:titleText,apiOptions:props.apiOptions,linterContext:props.linterContext,strings:context.strings})});return jsxRuntimeExports.jsx("div",{className:`framework-perseus ${styles$g.modalContainer}`,children:jsxRuntimeExports.jsx(FlexibleDialog,{title:title,content:jsxRuntimeExports.jsx(ExploreImageModalContent,{...props,captionId:captionId,longDescId:longDescId}),"aria-describedby":props.caption?`${captionId} ${longDescId}`:longDescId,styles:{root:wbStyles.root}})})};const wbStyles={root:{borderRadius:sizing.size_120,maxWidth:"100%"}};
1843
+ const ExploreImageModal=props=>{const context=React__default.useContext(PerseusI18nContext);const uniqueId=React__default.useId();const captionId=`${uniqueId}-caption`;const longDescId=`${uniqueId}-long-desc`;const titleText=props.title||context.strings.imageAlternativeTitle;const title=jsxRuntimeExports.jsx("h1",{className:`perseus-image-modal-title ${styles$h.modalTitleContainer}`,children:jsxRuntimeExports.jsx(Renderer,{content:titleText,apiOptions:props.apiOptions,linterContext:props.linterContext,strings:context.strings})});return jsxRuntimeExports.jsx("div",{className:`framework-perseus ${styles$h.modalContainer}`,children:jsxRuntimeExports.jsx(FlexibleDialog,{title:title,content:jsxRuntimeExports.jsx(ExploreImageModalContent,{...props,captionId:captionId,longDescId:longDescId}),"aria-describedby":props.caption?`${captionId} ${longDescId}`:longDescId,styles:{root:wbStyles.root}})})};const wbStyles={root:{borderRadius:sizing.size_120,maxWidth:"100%"}};
1844
1844
 
1845
1845
  const GifControlsIcon=({isPlaying,onToggle})=>{const strings=usePerseusI18n().strings;return jsxRuntimeExports.jsx(IconButton,{icon:isPlaying?pauseIcon:playIcon,kind:"secondary","aria-label":isPlaying?strings.gifPauseButtonLabel:strings.gifPlayButtonLabel,onClick:onToggle,style:{flexShrink:0}})};
1846
1846
 
1847
- const ImageInfoArea=props=>{const{backgroundImage,caption,longDescription,apiOptions,linterContext,isGifPlaying,setIsGifPlaying}=props;const context=React.useContext(PerseusI18nContext);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);return jsxRuntimeExports.jsxs("div",{className:styles$g.infoAreaContainer,children:[imageIsGif&&jsxRuntimeExports.jsx(GifControlsIcon,{isPlaying:isGifPlaying,onToggle:()=>setIsGifPlaying(!isGifPlaying)}),imageIsGif&&longDescription&&jsxRuntimeExports.jsx("div",{className:styles$g.spacerHorizontal}),longDescription&&jsxRuntimeExports.jsx(ModalLauncher,{modal:jsxRuntimeExports.jsx(ExploreImageModal,{...props}),children:({openModal})=>jsxRuntimeExports.jsx(ExploreImageButton,{hasCaption:!!caption,onClick:openModal})}),caption&&jsxRuntimeExports.jsx("figcaption",{className:"perseus-image-caption",children:jsxRuntimeExports.jsx(Renderer,{content:caption,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})})]})};
1847
+ const ImageInfoArea=props=>{const{backgroundImage,caption,longDescription,apiOptions,linterContext,isGifPlaying,setIsGifPlaying}=props;const context=React.useContext(PerseusI18nContext);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);return jsxRuntimeExports.jsxs("div",{className:styles$h.infoAreaContainer,children:[imageIsGif&&jsxRuntimeExports.jsx(GifControlsIcon,{isPlaying:isGifPlaying,onToggle:()=>setIsGifPlaying(!isGifPlaying)}),imageIsGif&&longDescription&&jsxRuntimeExports.jsx("div",{className:styles$h.spacerHorizontal}),longDescription&&jsxRuntimeExports.jsx(ModalLauncher,{modal:jsxRuntimeExports.jsx(ExploreImageModal,{...props}),children:({openModal})=>jsxRuntimeExports.jsx(ExploreImageButton,{hasCaption:!!caption,onClick:openModal})}),caption&&jsxRuntimeExports.jsx("figcaption",{className:"perseus-image-caption",children:jsxRuntimeExports.jsx(Renderer,{content:caption,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})})]})};
1848
1848
 
1849
- const ImageComponent=props=>{const{apiOptions,alt,backgroundImage,box,caption,longDescription,decorative,linterContext,labels,range,title,trackInteraction,widgetId}=props;const context=React.useContext(PerseusI18nContext);const{analytics}=useDependencies();const[isGifPlaying,setIsGifPlaying]=React.useState(false);useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"image",widgetId:widgetId}});});React.useEffect(()=>{setIsGifPlaying(false);},[backgroundImage.url]);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);let scale=props.scale;if(scale<=0||scale===Infinity||scale===-Infinity){scale=1;}const svgImage=jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:backgroundImage.url,apiOptions:apiOptions,width:backgroundImage.width,height:backgroundImage.height,scale:scale,extraGraphie:{box:box,range:range,labels:labels},trackInteraction:trackInteraction,zoomToFullSizeOnMobile:apiOptions.isMobile,constrainHeight:apiOptions.isMobile,allowFullBleed:apiOptions.isMobile,allowZoom:!decorative&&!imageIsGif,alt:decorative||caption===alt?"":alt,setAssetStatus:setAssetStatus,isGifPlaying:imageIsGif?isGifPlaying:undefined,onGifLoop:imageIsGif?()=>setIsGifPlaying(false):undefined})});const maxWidth=backgroundImage.width?backgroundImage.width*scale:undefined;const width=maxWidth?undefined:"fit-content";if(decorative){return jsxRuntimeExports.jsx("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:svgImage})}return jsxRuntimeExports.jsxs("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:[title&&jsxRuntimeExports.jsx("div",{className:`perseus-image-title ${styles$g.titleContainer}`,children:jsxRuntimeExports.jsx(Renderer,{content:title,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})}),svgImage,(imageIsGif||caption||longDescription)&&jsxRuntimeExports.jsx(ImageInfoArea,{isGifPlaying:isGifPlaying,setIsGifPlaying:setIsGifPlaying,...props})]})};
1849
+ const ImageComponent=props=>{const{apiOptions,alt,backgroundImage,box,caption,longDescription,decorative,linterContext,labels,range,title,trackInteraction,widgetId}=props;const context=React.useContext(PerseusI18nContext);const{analytics}=useDependencies();const[isGifPlaying,setIsGifPlaying]=React.useState(false);useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"image",widgetId:widgetId}});});React.useEffect(()=>{setIsGifPlaying(false);},[backgroundImage.url]);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);let scale=props.scale;if(scale<=0||scale===Infinity||scale===-Infinity){scale=1;}const svgImage=jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:backgroundImage.url,apiOptions:apiOptions,width:backgroundImage.width,height:backgroundImage.height,scale:scale,extraGraphie:{box:box,range:range,labels:labels},trackInteraction:trackInteraction,zoomToFullSizeOnMobile:apiOptions.isMobile,constrainHeight:apiOptions.isMobile,allowFullBleed:apiOptions.isMobile,allowZoom:!decorative&&!imageIsGif,alt:decorative||caption===alt?"":alt,setAssetStatus:setAssetStatus,isGifPlaying:imageIsGif?isGifPlaying:undefined,onGifLoop:imageIsGif?()=>setIsGifPlaying(false):undefined})});const maxWidth=backgroundImage.width?backgroundImage.width*scale:undefined;const width=maxWidth?undefined:"fit-content";if(decorative){return jsxRuntimeExports.jsx("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:svgImage})}return jsxRuntimeExports.jsxs("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:[title&&jsxRuntimeExports.jsx("div",{className:`perseus-image-title ${styles$h.titleContainer}`,children:jsxRuntimeExports.jsx(Renderer,{content:title,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})}),svgImage,(imageIsGif||caption||longDescription)&&jsxRuntimeExports.jsx(ImageInfoArea,{isGifPlaying:isGifPlaying,setIsGifPlaying:setIsGifPlaying,...props})]})};
1850
1850
 
1851
1851
  const defaultBoxSize=400;const defaultRange=[0,10];const defaultBackgroundImage$1={url:null,width:0,height:0};class ImageWidget extends React.Component{getPromptJSON(){return getPromptJSON$d(this.props)}render(){return jsxRuntimeExports.jsx(ImageComponent,{...this.props})}constructor(...args){super(...args),this.isWidget=true;}}ImageWidget.contextType=PerseusI18nContext;ImageWidget.defaultProps={alignment:"block",title:"",range:[defaultRange,defaultRange],box:[defaultBoxSize,defaultBoxSize],backgroundImage:defaultBackgroundImage$1,scale:1,labels:[],alt:"",longDescription:"",decorative:false,caption:"",linterContext:linterContextDefault};var Image$1 = {name:"image",displayName:"Image",widget:ImageWidget,isLintable:true};
1852
1852
 
@@ -1998,13 +1998,13 @@ const{calculateAngleInDegrees: calculateAngleInDegrees$1}=angles;const LINE_PULL
1998
1998
 
1999
1999
  const{calculateAngleInDegrees,convertDegreesToRadians}=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]=useState(initialCenter);const[rotationHandleOffset,setRotationHandleOffset]=useState(centerToRotationHandle);const draggableRef=useRef(null);const{dragging}=useDraggable({gestureTarget:draggableRef,onMove:point=>setCenter(bound$1({snapStep,range,point})),point:center,constrainKeyboardMovement:point=>bound$1({snapStep,range,point})});const rotationHandleRef=useRef(null);useDraggablePx({gestureTarget:rotationHandleRef,onMove:setRotationHandleOffset,point:rotationHandleOffset,constrain:constrainToCircle});const[centerPx]=useTransformVectorsToPixels(center);const topLeftPx=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=vec.mag(centerToRotationHandle);function constrainToCircle(edgePoint){return vec.withMag(edgePoint,protractorRadius)}function useDraggablePx(args){const{gestureTarget:target,onMove,point,constrain=p=>p}=args;const pickupPx=React.useRef([0,0]);useDrag(state=>{const{event,first,movement:pixelMovement}=state;event?.stopPropagation();if(first){pickupPx.current=point;}if(vec.mag(pixelMovement)===0){return}onMove?.(constrain(vec.add(pickupPx.current,pixelMovement)));},{target,eventOptions:{passive:false}});}
2000
2000
 
2001
- const GRAPH_LEFT_MARGIN=20;const MafsGraph=props=>{const{state,dispatch,labels,labelLocation,readOnly,fullGraphAriaLabel,fullGraphAriaDescription,widgetId}=props;const{type}=state;const[width,height]=props.box;const tickStep=props.step;const uniqueId=React.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.useRef(null);const{analytics}=useDependencies();const i18n=usePerseusI18n();const{strings}=i18n;const interactionPrompt=isUnlimitedGraphState(state)&&state.showKeyboardInteractionInvitation;useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:type,widgetType:"interactive-graph",widgetId:widgetId}});});const{graph,interactiveElementsDescription}=renderGraphElements({state,dispatch,i18n,markings:props.markings});const disableInteraction=readOnly||!!props.static;const graphInfo={range:state.range,width,height};const[xAxisLabelLocation,yAxisLabelLocation]=getLabelPosition(graphInfo,labelLocation,tickStep);const needsExtraMargin=labelLocation==="alongEdge"&&yAxisLabelLocation[0]<-14*fontSizeYAxisLabelMultiplier;const marginLabelDiff=GRAPH_LEFT_MARGIN-fontSize*fontSizeYAxisLabelMultiplier;const marginWithExtraOffset=-1*(yAxisLabelLocation[X]-marginLabelDiff);const showsAxisLabels=props.markings==="graph"||props.markings==="axes";const hasXAxisLabel=!!(labels[0]&&labels[0].trim());const graphMarginBottom=getGraphBottomMargin(xAxisLabelLocation[Y],height,hasXAxisLabel,showsAxisLabels);return jsxRuntimeExports.jsx(GraphConfigContext.Provider,{value:{range:state.range,snapStep:state.snapStep,markings:props.markings,tickStep:tickStep,gridStep:props.gridStep,showTooltips:!!props.showTooltips,showAxisArrows:props.showAxisArrows,showAxisTicks:props.showAxisTicks,graphDimensionsInPixels:props.box,width,height,labels,labelLocation,disableKeyboardInteraction:disableInteraction,interactiveColor:disableInteraction?"var(--static-gray)":"var(--mafs-blue)"},children:jsxRuntimeExports.jsxs(View,{className:"mafs-graph-container",children:[jsxRuntimeExports.jsxs(View,{className:"mafs-graph",role:"figure",style:{position:"relative",padding:"25px 25px 0 0",boxSizing:"content-box",marginLeft:needsExtraMargin?`${marginWithExtraOffset}px`:`${GRAPH_LEFT_MARGIN}px`,marginBottom:graphMarginBottom,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(View,{id:descriptionId,tabIndex:-1,className:"mafs-sr-only",children:fullGraphAriaDescription}),interactiveElementsDescription&&jsxRuntimeExports.jsx(View,{id:interactiveElementsDescriptionId,tabIndex:-1,className:"mafs-sr-only",children:interactiveElementsDescription}),state.type!=="none"&&jsxRuntimeExports.jsx(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(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,xAxisLabelLocation:xAxisLabelLocation,yAxisLabelLocation:yAxisLabelLocation})}),jsxRuntimeExports.jsx(View,{"aria-hidden":props.lockedFigures.length===0,children:jsxRuntimeExports.jsxs(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(ClipToGraphBounds,{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(ClipToGraphBounds,{children:jsxRuntimeExports.jsx(GraphLockedLayer,{lockedFigures:props.lockedFigures,range:state.range})})]})}),jsxRuntimeExports.jsx(GraphLockedLabelsLayer,{lockedFigures:props.lockedFigures}),jsxRuntimeExports.jsx(View,{style:{position:"absolute"},children:jsxRuntimeExports.jsxs(Mafs,{preserveAspectRatio:false,viewBox:{x:state.range[X],y:state.range[Y],padding:0},pan:false,zoom:false,width:width,height:height,children:[props.showProtractor&&jsxRuntimeExports.jsx(ClipToGraphBounds,{children:jsxRuntimeExports.jsx(Protractor,{})}),graph]})})]}),interactionPrompt&&jsxRuntimeExports.jsx(View,{style:{display:interactionPrompt?undefined:"hidden",textAlign:"center",backgroundColor:semanticColor.core.background.base.default,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,padding:"16px 0",boxShadow:"0px 8px 8px 0px #21242C14",top:"50%",transform:"translateY(-50%)"},children:jsxRuntimeExports.jsx(BodyText,{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(View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button,{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,{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,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},tabIndex:0,onClick:()=>{props.dispatch(actions.polygon.openPolygon());},children:perseusStrings.openPolygon}):jsxRuntimeExports.jsx(Button,{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(View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button,{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,{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 "exponential":return renderExponentialGraph(state,dispatch,i18n);case "none":return {graph:null,interactiveElementsDescription:null};case "absolute-value":return renderAbsoluteValueGraph(state,dispatch,i18n);case "tangent":return renderTangentGraph(state,dispatch,i18n);case "logarithm":return renderLogarithmGraph(state,dispatch,i18n);case "vector":return renderVectorGraph(state,dispatch,i18n);default:throw new UnreachableCaseError(type)}};function describedByIds(...args){return args.filter(Boolean).join(" ")||undefined}
2001
+ const GRAPH_LEFT_MARGIN=20;const MafsGraph=props=>{const{state,dispatch,labels,labelLocation,readOnly,fullGraphAriaLabel,fullGraphAriaDescription,widgetId}=props;const{type}=state;const[width,height]=props.box;const tickStep=props.step;const uniqueId=React.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.useRef(null);const{analytics}=useDependencies();const i18n=usePerseusI18n();const{strings}=i18n;const interactionPrompt=isUnlimitedGraphState(state)&&state.showKeyboardInteractionInvitation;useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:type,widgetType:"interactive-graph",widgetId:widgetId}});});const{graph,interactiveElementsDescription}=renderGraphElements({state,dispatch,i18n,markings:props.markings});const disableInteraction=readOnly||!!props.static;const graphInfo={range:state.range,width,height};const[xAxisLabelLocation,yAxisLabelLocation]=getLabelPosition(graphInfo,labelLocation,tickStep);const needsExtraMargin=labelLocation==="alongEdge"&&yAxisLabelLocation[0]<-14*fontSizeYAxisLabelMultiplier;const marginLabelDiff=GRAPH_LEFT_MARGIN-fontSize*fontSizeYAxisLabelMultiplier;const marginWithExtraOffset=-1*(yAxisLabelLocation[X]-marginLabelDiff);const showsAxisLabels=props.markings==="graph"||props.markings==="axes";const hasXAxisLabel=!!(labels[0]&&labels[0].trim());const graphMarginBottom=getGraphBottomMargin(xAxisLabelLocation[Y],height,hasXAxisLabel,showsAxisLabels);return jsxRuntimeExports.jsx(GraphConfigContext.Provider,{value:{range:state.range,snapStep:state.snapStep,markings:props.markings,tickStep:tickStep,gridStep:props.gridStep,showTooltips:!!props.showTooltips,showAxisArrows:props.showAxisArrows,showAxisTicks:props.showAxisTicks,graphDimensionsInPixels:props.box,width,height,labels,labelLocation,disableKeyboardInteraction:disableInteraction,interactiveColor:disableInteraction?"var(--static-gray)":"var(--mafs-blue)"},children:jsxRuntimeExports.jsxs(View,{className:"mafs-graph-container",children:[jsxRuntimeExports.jsxs(View,{className:"mafs-graph",role:"figure",style:{position:"relative",padding:"25px 25px 0 0",boxSizing:"content-box",marginLeft:needsExtraMargin?`${marginWithExtraOffset}px`:`${GRAPH_LEFT_MARGIN}px`,marginBottom:graphMarginBottom,pointerEvents:props.static?"none":"auto",userSelect:"none",width,height},onKeyUp:event=>{handleKeyboardEvent(event,state,dispatch);},"aria-label":fullGraphAriaLabel,"aria-describedby":describedByIds(state.type!=="none"&&!disableInteraction&&instructionsId,fullGraphAriaDescription&&descriptionId,interactiveElementsDescription&&interactiveElementsDescriptionId,isUnlimitedGraphState(state)&&unlimitedGraphKeyboardPromptId),ref:graphRef,tabIndex:0,onFocus:event=>{handleFocusEvent(event,state,dispatch);},onBlur:event=>{handleBlurEvent(event,state,dispatch);},children:[state.type!=="none"&&jsxRuntimeExports.jsx(View,{id:instructionsId,tabIndex:-1,className:"mafs-sr-only",children:isUnlimitedGraphState(state)?strings.srUnlimitedGraphInstructions:strings.srGraphInstructions}),fullGraphAriaDescription&&jsxRuntimeExports.jsx(View,{id:descriptionId,tabIndex:-1,className:"mafs-sr-only",children:fullGraphAriaDescription}),interactiveElementsDescription&&jsxRuntimeExports.jsx(View,{id:interactiveElementsDescriptionId,tabIndex:-1,className:"mafs-sr-only",children:interactiveElementsDescription}),jsxRuntimeExports.jsx(LegacyGrid,{box:props.box,backgroundImage:props.backgroundImage}),jsxRuntimeExports.jsxs(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,xAxisLabelLocation:xAxisLabelLocation,yAxisLabelLocation:yAxisLabelLocation})}),jsxRuntimeExports.jsx(View,{"aria-hidden":props.lockedFigures.length===0,children:jsxRuntimeExports.jsxs(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(ClipToGraphBounds,{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(ClipToGraphBounds,{children:jsxRuntimeExports.jsx(GraphLockedLayer,{lockedFigures:props.lockedFigures,range:state.range})})]})}),jsxRuntimeExports.jsx(GraphLockedLabelsLayer,{lockedFigures:props.lockedFigures}),jsxRuntimeExports.jsx(View,{style:{position:"absolute"},children:jsxRuntimeExports.jsxs(Mafs,{preserveAspectRatio:false,viewBox:{x:state.range[X],y:state.range[Y],padding:0},pan:false,zoom:false,width:width,height:height,children:[props.showProtractor&&jsxRuntimeExports.jsx(ClipToGraphBounds,{children:jsxRuntimeExports.jsx(Protractor,{})}),graph]})})]}),interactionPrompt&&jsxRuntimeExports.jsx(View,{style:{display:interactionPrompt?undefined:"hidden",textAlign:"center",backgroundColor:semanticColor.core.background.base.default,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,padding:"16px 0",boxShadow:"0px 8px 8px 0px #21242C14",top:"50%",transform:"translateY(-50%)"},children:jsxRuntimeExports.jsx(BodyText,{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(View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button,{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,{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,{kind:"secondary",style:{width:"100%",marginLeft:"20px"},tabIndex:0,onClick:()=>{props.dispatch(actions.polygon.openPolygon());},children:perseusStrings.openPolygon}):jsxRuntimeExports.jsx(Button,{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(View,{style:{flexDirection:"row",width:props.width},children:[interactionMode==="keyboard"&&jsxRuntimeExports.jsx(Button,{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,{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 "exponential":return renderExponentialGraph(state,dispatch,i18n);case "none":return {graph:null,interactiveElementsDescription:null};case "absolute-value":return renderAbsoluteValueGraph(state,dispatch,i18n);case "tangent":return renderTangentGraph(state,dispatch,i18n);case "logarithm":return renderLogarithmGraph(state,dispatch,i18n);case "vector":return renderVectorGraph(state,dispatch,i18n);default:throw new UnreachableCaseError(type)}};function describedByIds(...args){return args.filter(Boolean).join(" ")||undefined}
2002
2002
 
2003
2003
  function mafsStateToInteractiveGraph(state,originalGraph){switch(state.type){case "angle":invariant(originalGraph.type==="angle");return {...originalGraph,coords:state.coords};case "quadratic":invariant(originalGraph.type==="quadratic");return {...originalGraph,coords:state.coords};case "circle":invariant(originalGraph.type==="circle");return {...originalGraph,center:state.center,radius:getRadius(state)};case "linear":invariant(originalGraph.type==="linear");return {...originalGraph,coords:state.coords};case "ray":invariant(originalGraph.type==="ray");return {...originalGraph,coords:state.coords};case "sinusoid":invariant(originalGraph.type==="sinusoid");return {...originalGraph,coords:state.coords};case "segment":invariant(originalGraph.type==="segment");return {...originalGraph,coords:state.coords};case "linear-system":invariant(originalGraph.type==="linear-system");return {...originalGraph,coords:state.coords};case "polygon":invariant(originalGraph.type==="polygon");return {...originalGraph,coords:state.coords};case "point":invariant(originalGraph.type==="point");return {...originalGraph,coords:state.coords};case "exponential":invariant(originalGraph.type==="exponential");return {...originalGraph,coords:state.coords,asymptote:state.asymptote};case "none":invariant(originalGraph.type==="none");return {...originalGraph};case "absolute-value":invariant(originalGraph.type==="absolute-value");return {...originalGraph,coords:state.coords};case "tangent":invariant(originalGraph.type==="tangent");return {...originalGraph,coords:state.coords};case "logarithm":invariant(originalGraph.type==="logarithm");return {...originalGraph,coords:state.coords,asymptote:state.asymptote};case "vector":invariant(originalGraph.type==="vector");return {...originalGraph,coords:state.coords};default:throw new UnreachableCaseError(state)}}
2004
2004
 
2005
2005
  const StatefulMafsGraph=React.forwardRef(function StatefulMafsGraphWithRef(props,ref){const{onChange,graph}=props;const{strings,locale}=usePerseusI18n();const[state,dispatch]=React.useReducer(interactiveGraphReducer,props,initializeGraphState);useImperativeHandle(ref,()=>({getUserInput:()=>getGradableGraph(state,graph)}));const prevState=useRef(state);useEffect(()=>{if(prevState.current!==state){onChange(mafsStateToInteractiveGraph(state,graph));}prevState.current=state;},[onChange,state,graph]);useEffect(()=>{if(!state.stateAnnouncement){return}announceMessage({message:getAnnouncementText(state.stateAnnouncement,strings,locale)});},[state.stateAnnouncement,strings,locale]);const[xSnap,ySnap]=props.snapStep;useEffect(()=>{dispatch(changeSnapStep([xSnap,ySnap]));},[dispatch,xSnap,ySnap]);const[[xMinRange,xMaxRange],[yMinRange,yMaxRange]]=props.range;useEffect(()=>{dispatch(changeRange([[xMinRange,xMaxRange],[yMinRange,yMaxRange]]));},[dispatch,xMinRange,xMaxRange,yMinRange,yMaxRange]);const numSegments=graph.type==="segment"?graph.numSegments:null;const numPoints=graph.type==="point"?graph.numPoints:null;const numSides=graph.type==="polygon"?graph.numSides:null;const snapTo=graph.type==="polygon"?graph.snapTo:null;const showAngles=graph.type==="polygon"||graph.type==="angle"?graph.showAngles:null;const allowReflexAngles=graph.type==="angle"?graph.allowReflexAngles:null;const showSides=graph.type==="polygon"?graph.showSides:null;const startCoords="startCoords"in graph?graph.startCoords:undefined;const pointLabels="pointLabels"in graph?graph.pointLabels:undefined;const originalPropsRef=useRef(props);const latestPropsRef=useLatestRef(props);useEffect(()=>{if(latestPropsRef.current!==originalPropsRef.current){dispatch(reinitialize(latestPropsRef.current));}},[graph.type,numPoints,numSegments,numSides,snapTo,showAngles,showSides,latestPropsRef,startCoords,allowReflexAngles,pointLabels]);if(props.static&&props.correct&&props.graded!==false){return jsxRuntimeExports.jsx(MafsGraph,{...props,state:initializeGraphState({...props,graph:props.correct}),dispatch:dispatch})}return jsxRuntimeExports.jsx(MafsGraph,{...props,state:state,dispatch:dispatch})});
2006
2006
 
2007
- const defaultBackgroundImage={url:null};class InteractiveGraph extends React.Component{static getEquationString(props){return getEquationString(props)}getUserInput(){if(this.mafsRef.current?.getUserInput){return this.mafsRef.current.getUserInput()}throw new PerseusError("Cannot getUserInput from a graph that has never rendered",Errors.NotAllowed)}getPromptJSON(){return getPromptJSON$b(this.props,this.getUserInput())}getSerializedState(){const{userInput:_,...rest}=this.props;return {...rest,graph:this.props.userInput}}render(){const box=getInteractiveBoxFromSizeClass(this.props.containerSizeClass);const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,box[0]);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const mafsProps={...this.props,graph:this.props.userInput,onChange:()=>this.props.handleUserInput(this.mafsRef.current?.getUserInput())};const showUngradedText=this.props.graded===false&&this.props.graph.type!=="none";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[showUngradedText&&jsxRuntimeExports.jsx("p",{children:this.context.strings.ungradedInteractiveGraph}),jsxRuntimeExports.jsx(StatefulMafsGraph,{...mafsProps,ref:this.mafsRef,gridStep:gridStep,snapStep:snapStep,box:box,showTooltips:!!this.props.showTooltips,readOnly:this.props.apiOptions?.readOnly,widgetId:this.props.widgetId,graded:this.props.graded})]})}constructor(...args){super(...args),this.mafsRef=React.createRef();}}InteractiveGraph.contextType=PerseusI18nContext;InteractiveGraph.defaultProps={labels:["$x$","$y$"],labelLocation:"onAxis",range:[[-10,10],[-10,10]],showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true},showAxisTicks:{x:true,y:true},step:[1,1],backgroundImage:defaultBackgroundImage,markings:"graph",showTooltips:false,showProtractor:false,userInput:{type:"linear"}};function getUserInputFromSerializedState$8(serializedState){return serializedState.graph}function getStartUserInput$8(options){return options.graph}function getCorrectUserInput$4(options){return options.correct}var InteractiveGraph$1 = {name:"interactive-graph",displayName:"Interactive graph",widget:InteractiveGraph,getStartUserInput: getStartUserInput$8,getCorrectUserInput: getCorrectUserInput$4,getUserInputFromSerializedState: getUserInputFromSerializedState$8,supportsUngraded:true};
2007
+ const defaultBackgroundImage={url:null};class InteractiveGraph extends React.Component{static getEquationString(props){return getEquationString(props)}getUserInput(){if(this.mafsRef.current?.getUserInput){return this.mafsRef.current.getUserInput()}throw new PerseusError("Cannot getUserInput from a graph that has never rendered",Errors.NotAllowed)}getPromptJSON(){return getPromptJSON$b(this.props,this.getUserInput())}getSerializedState(){const{userInput:_,...rest}=this.props;return {...rest,graph:this.props.userInput}}render(){const box=getInteractiveBoxFromSizeClass(this.props.containerSizeClass);const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,box[0]);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const mafsProps={...this.props,graph:this.props.userInput,onChange:()=>this.props.handleUserInput(this.mafsRef.current?.getUserInput())};const showUngradedText=this.props.graded===false&&this.props.graph.type!=="none";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[showUngradedText&&jsxRuntimeExports.jsx("p",{children:this.context.strings.ungradedInteractiveGraph}),jsxRuntimeExports.jsx(StatefulMafsGraph,{...mafsProps,ref:this.mafsRef,gridStep:gridStep,snapStep:snapStep,box:box,showTooltips:!!this.props.showTooltips,readOnly:this.props.apiOptions?.readOnly,widgetId:this.props.widgetId,graded:this.props.graded})]})}constructor(...args){super(...args),this.mafsRef=React.createRef();}}InteractiveGraph.contextType=PerseusI18nContext;InteractiveGraph.defaultProps={labels:["$x$","$y$"],labelLocation:"onAxis",range:[[-10,10],[-10,10]],showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true},showAxisTicks:{x:true,y:true},step:[1,1],backgroundImage:defaultBackgroundImage,markings:"graph",showTooltips:false,showProtractor:false,userInput:{type:"none"}};function getUserInputFromSerializedState$8(serializedState){return serializedState.graph}function getStartUserInput$8(options){return options.graph}function getCorrectUserInput$4(options){return options.correct}var InteractiveGraph$1 = {name:"interactive-graph",displayName:"Interactive graph",widget:InteractiveGraph,getStartUserInput: getStartUserInput$8,getCorrectUserInput: getCorrectUserInput$4,getUserInputFromSerializedState: getUserInputFromSerializedState$8,supportsUngraded:true};
2008
2008
 
2009
2009
  const bodyXsmallBold={fontFamily:"inherit",fontSize:15,fontWeight:"bold",lineHeight:"22px"};
2010
2010
 
@@ -2012,19 +2012,19 @@ const getPromptJSON$a=widgetData=>{const propMarkers=widgetData.markers.map(mark
2012
2012
 
2013
2013
  const AnswerChoices=props=>{const{strings}=usePerseusI18n();const onAnswerChange=selected=>{const{choices,onChange}=props;onChange(choices.map(choice=>selected.includes(choice.content)));};const AnswerItems=choices=>choices.map(({content})=>jsxRuntimeExports.jsx(OptionItem,{value:content,label:jsxRuntimeExports.jsx(Renderer,{content:content,strings:strings,inline:true})},content));const selectedValues=props.choices.filter(choice=>choice.checked).map(choice=>choice.content);const{opener,onToggle,disabled}=props;const args={style:{zIndex:"unset"},children:AnswerItems(props.choices),opener,onToggle,disabled};return props.multipleSelect?jsxRuntimeExports.jsx(MultiSelect,{...args,selectedValues:selectedValues,onChange:selected=>onAnswerChange(selected)}):jsxRuntimeExports.jsx(SingleSelect,{...args,selectedValue:selectedValues[0],onChange:selected=>onAnswerChange([selected]),placeholder:props.choices[0].content})};
2014
2014
 
2015
- const HideAnswersToggle=props=>{const switchId=useId();const labelId=useId();const{strings}=usePerseusI18n();return jsxRuntimeExports.jsxs(View,{style:styles$c.switchWrapper,children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:props.areAnswersHidden,onChange:props.onChange,"aria-labelledby":labelId}),jsxRuntimeExports.jsx(BodyText,{id:labelId,htmlFor:switchId,tag:"label",children:strings.hideAnswersToggleLabel})]})};const styles$c=StyleSheet.create({switchWrapper:{display:"flex",flexDirection:"row",flexWrap:"wrap-reverse",alignItems:"center",gap:"0.5em",marginTop:"1em"}});
2015
+ const HideAnswersToggle=props=>{const switchId=useId();const labelId=useId();const{strings}=usePerseusI18n();return jsxRuntimeExports.jsxs(View,{style:styles$d.switchWrapper,children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:props.areAnswersHidden,onChange:props.onChange,"aria-labelledby":labelId}),jsxRuntimeExports.jsx(BodyText,{id:labelId,htmlFor:switchId,tag:"label",children:strings.hideAnswersToggleLabel})]})};const styles$d=StyleSheet.create({switchWrapper:{display:"flex",flexDirection:"row",flexWrap:"wrap-reverse",alignItems:"center",gap:"0.5em",marginTop:"1em"}});
2016
2016
 
2017
- const BringToFront={boxShadow:`0 8px 8px ${semanticColor.core.border.neutral.default}`,zIndex:1e3};const AnswerPill=props=>{const{selectedAnswers,showCorrectness,markerRef,side,onClick,style,focused,hovered}=props;const pillId=useId();const{strings}=usePerseusI18n();const answerString=selectedAnswers.length>1?strings.answers({num:selectedAnswers.length}):selectedAnswers[0];const correct=showCorrectness==="correct";const incorrect=showCorrectness==="incorrect";return jsxRuntimeExports.jsx(Popper,{placement:side,referenceElement:markerRef,modifiers:[{name:"preventOverflow",options:{rootBoundary:"viewport"}}],children:({ref,style:popperStyle})=>jsxRuntimeExports.jsx(Pill,{size:"large",kind:"accent",id:pillId,onClick:correct?undefined:onClick,ref:ref,style:[style,popperStyle,styles$b.pill,correct&&styles$b.correct,incorrect&&styles$b.incorrect,(focused||hovered)&&BringToFront],children:jsxRuntimeExports.jsx(Renderer,{content:answerString,strings:strings,inline:true})})})};const styles$b=StyleSheet.create({correct:{backgroundColor:semanticColor.core.background.success.strong},incorrect:{backgroundColor:semanticColor.core.background.neutral.default},pill:{height:"auto"}});
2017
+ const BringToFront={boxShadow:`0 8px 8px ${semanticColor.core.border.neutral.default}`,zIndex:1e3};const AnswerPill=props=>{const{selectedAnswers,showCorrectness,markerRef,side,onClick,style,focused,hovered}=props;const pillId=useId();const{strings}=usePerseusI18n();const answerString=selectedAnswers.length>1?strings.answers({num:selectedAnswers.length}):selectedAnswers[0];const correct=showCorrectness==="correct";const incorrect=showCorrectness==="incorrect";return jsxRuntimeExports.jsx(Popper,{placement:side,referenceElement:markerRef,modifiers:[{name:"preventOverflow",options:{rootBoundary:"viewport"}}],children:({ref,style:popperStyle})=>jsxRuntimeExports.jsx(Pill,{size:"large",kind:"accent",id:pillId,onClick:correct?undefined:onClick,ref:ref,style:[style,popperStyle,styles$c.pill,correct&&styles$c.correct,incorrect&&styles$c.incorrect,(focused||hovered)&&BringToFront],children:jsxRuntimeExports.jsx(Renderer,{content:answerString,strings:strings,inline:true})})})};const styles$c=StyleSheet.create({correct:{backgroundColor:semanticColor.core.background.success.strong},incorrect:{backgroundColor:semanticColor.core.background.neutral.default},pill:{height:"auto"}});
2018
2018
 
2019
- function shouldReduceMotion(){if(typeof window.matchMedia!=="function"){return true}const mediaQuery=window.matchMedia("(prefers-reduced-motion: reduce)");return !mediaQuery||mediaQuery.matches}const MARKER_SIZE=24;class Marker extends React.Component{componentDidMount(){this._mounted=true;}componentWillUnmount(){this._mounted=false;}renderIcon(){const{selected,showCorrectness,showSelected,showPulsate}=this.props;const isOpen=showSelected;const selectedAnswers=selected;let iconStyles;const iconNull={path:"",height:1,width:1};let args={size:MARKER_SIZE,color:semanticColor.core.foreground.knockout.default,icon:iconNull};if(showCorrectness){iconStyles=[styles$a.markerGraded,showCorrectness==="correct"?styles$a.markerCorrect:styles$a.markerIncorrect,isOpen&&styles$a.markerSelected];args={...args,icon:showCorrectness==="correct"?iconCheck:iconMinus};}else if(selectedAnswers&&selectedAnswers.length>0){iconStyles=[styles$a.markerFilled,isOpen&&styles$a.markerSelected];}else if(isOpen){iconStyles=[styles$a.markerSelected];args={...args,icon:iconChevronDown,size:8};}else if(showPulsate){iconStyles=[styles$a.markerPulsateBase,this._mounted&&shouldReduceMotion()?showPulsate&&styles$a.markerUnfilledPulsateOnce:showPulsate&&styles$a.markerUnfilledPulsateInfinite];}return jsxRuntimeExports.jsx(View,{style:[styles$a.markerIcon,iconStyles],ref:node=>this._icon=node,children:jsxRuntimeExports.jsx(Icon,{...args})})}render(){const{showCorrectness,selected,showAnswer,answerSide,answerStyles,hovered,focused,label}=this.props;const markerDisabled=showCorrectness==="correct";const active=hovered||focused;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(View,{style:[styles$a.marker,active&&!markerDisabled&&styles$a.markerActive],"aria-label":markerDisabled?this.context.strings.correctExcited:label,children:this.renderIcon()}),!!selected&&showAnswer&&jsxRuntimeExports.jsx(AnswerPill,{selectedAnswers:selected,showCorrectness:showCorrectness,side:answerSide,style:answerStyles,markerRef:this._icon??undefined,hovered:hovered,focused:focused})]})}constructor(...args){super(...args),this._mounted=false;}}Marker.contextType=PerseusI18nContext;Marker.defaultProps={selected:[]};const styles$a=StyleSheet.create({marker:{position:"absolute",backgroundColor:semanticColor.core.background.base.default,borderRadius:MARKER_SIZE,width:MARKER_SIZE,height:MARKER_SIZE,marginLeft:MARKER_SIZE/-2,marginTop:MARKER_SIZE/-2,boxShadow:boxShadow.mid},markerIcon:{display:"flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",width:MARKER_SIZE,height:MARKER_SIZE,border:`2px solid ${semanticColor.core.border.neutral.default}`,borderRadius:MARKER_SIZE},markerPulsateBase:{animationName:{"0%":{transform:"scale(1)",backgroundColor:semanticColor.core.background.instructive.default},"100%":{transform:"scale(1.3)",backgroundColor:semanticColor.core.background.instructive.default}},animationDirection:"alternate",animationDuration:"0.8s",animationTimingFunction:"ease-in",transformOrigin:"50% 50%",animationIterationCount:"0"},markerUnfilledPulsateInfinite:{animationIterationCount:"infinite"},markerUnfilledPulsateOnce:{animationIterationCount:"2"},markerActive:{outline:`2px solid ${semanticColor.core.border.instructive.default}`,outlineOffset:2},markerSelected:{boxShadow:boxShadow.mid,border:`solid 4px ${semanticColor.core.border.knockout.default}`,backgroundColor:semanticColor.core.background.instructive.default,borderRadius:MARKER_SIZE,transform:"rotate(180deg)"},markerFilled:{backgroundColor:semanticColor.core.background.instructive.subtle,border:`4px solid ${semanticColor.core.border.instructive.default}`},markerGraded:{width:MARKER_SIZE,height:MARKER_SIZE,justifyContent:"center",alignItems:"center",border:`2px solid ${semanticColor.core.border.knockout.default}`},markerCorrect:{background:semanticColor.core.background.success.strong},markerIncorrect:{background:semanticColor.core.background.neutral.default}});
2019
+ function shouldReduceMotion(){if(typeof window.matchMedia!=="function"){return true}const mediaQuery=window.matchMedia("(prefers-reduced-motion: reduce)");return !mediaQuery||mediaQuery.matches}const MARKER_SIZE=24;class Marker extends React.Component{componentDidMount(){this._mounted=true;}componentWillUnmount(){this._mounted=false;}renderIcon(){const{selected,showCorrectness,showSelected,showPulsate}=this.props;const isOpen=showSelected;const selectedAnswers=selected;let iconStyles;const iconNull={path:"",height:1,width:1};let args={size:MARKER_SIZE,color:semanticColor.core.foreground.knockout.default,icon:iconNull};if(showCorrectness){iconStyles=[styles$b.markerGraded,showCorrectness==="correct"?styles$b.markerCorrect:styles$b.markerIncorrect,isOpen&&styles$b.markerSelected];args={...args,icon:showCorrectness==="correct"?iconCheck:iconMinus};}else if(selectedAnswers&&selectedAnswers.length>0){iconStyles=[styles$b.markerFilled,isOpen&&styles$b.markerSelected];}else if(isOpen){iconStyles=[styles$b.markerSelected];args={...args,icon:iconChevronDown,size:8};}else if(showPulsate){iconStyles=[styles$b.markerPulsateBase,this._mounted&&shouldReduceMotion()?showPulsate&&styles$b.markerUnfilledPulsateOnce:showPulsate&&styles$b.markerUnfilledPulsateInfinite];}return jsxRuntimeExports.jsx(View,{style:[styles$b.markerIcon,iconStyles],ref:node=>this._icon=node,children:jsxRuntimeExports.jsx(Icon,{...args})})}render(){const{showCorrectness,selected,showAnswer,answerSide,answerStyles,hovered,focused,label}=this.props;const markerDisabled=showCorrectness==="correct";const active=hovered||focused;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(View,{style:[styles$b.marker,active&&!markerDisabled&&styles$b.markerActive],"aria-label":markerDisabled?this.context.strings.correctExcited:label,children:this.renderIcon()}),!!selected&&showAnswer&&jsxRuntimeExports.jsx(AnswerPill,{selectedAnswers:selected,showCorrectness:showCorrectness,side:answerSide,style:answerStyles,markerRef:this._icon??undefined,hovered:hovered,focused:focused})]})}constructor(...args){super(...args),this._mounted=false;}}Marker.contextType=PerseusI18nContext;Marker.defaultProps={selected:[]};const styles$b=StyleSheet.create({marker:{position:"absolute",backgroundColor:semanticColor.core.background.base.default,borderRadius:MARKER_SIZE,width:MARKER_SIZE,height:MARKER_SIZE,marginLeft:MARKER_SIZE/-2,marginTop:MARKER_SIZE/-2,boxShadow:boxShadow.mid},markerIcon:{display:"flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",width:MARKER_SIZE,height:MARKER_SIZE,border:`2px solid ${semanticColor.core.border.neutral.default}`,borderRadius:MARKER_SIZE},markerPulsateBase:{animationName:{"0%":{transform:"scale(1)",backgroundColor:semanticColor.core.background.instructive.default},"100%":{transform:"scale(1.3)",backgroundColor:semanticColor.core.background.instructive.default}},animationDirection:"alternate",animationDuration:"0.8s",animationTimingFunction:"ease-in",transformOrigin:"50% 50%",animationIterationCount:"0"},markerUnfilledPulsateInfinite:{animationIterationCount:"infinite"},markerUnfilledPulsateOnce:{animationIterationCount:"2"},markerActive:{outline:`2px solid ${semanticColor.core.border.instructive.default}`,outlineOffset:2},markerSelected:{boxShadow:boxShadow.mid,border:`solid 4px ${semanticColor.core.border.knockout.default}`,backgroundColor:semanticColor.core.background.instructive.default,borderRadius:MARKER_SIZE,transform:"rotate(180deg)"},markerFilled:{backgroundColor:semanticColor.core.background.instructive.subtle,border:`4px solid ${semanticColor.core.border.instructive.default}`},markerGraded:{width:MARKER_SIZE,height:MARKER_SIZE,justifyContent:"center",alignItems:"center",border:`2px solid ${semanticColor.core.border.knockout.default}`},markerCorrect:{background:semanticColor.core.background.success.strong},markerIncorrect:{background:semanticColor.core.background.neutral.default}});
2020
2020
 
2021
- function isAnswerful(marker){return marker.answers!=null}function getComputedSelectedState(marker,userInputMarker,reviewMode,showSolutions){const shouldShowFeedback=showSolutions==="all"||reviewMode;if(!shouldShowFeedback){return userInputMarker}if(isAnswerful(marker)){return {...userInputMarker,selected:marker.answers}}else {return {...userInputMarker,selected:undefined}}}class LabelImage extends React.Component{static pointInTriangle(p,a,b,c){const sign=(p1,p2,p3)=>(p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y);const b1=sign(p,a,b)<0;const b2=sign(p,b,c)<0;const b3=sign(p,c,a)<0;return b1===b2&&b2===b3}static imageSideForMarkerPosition(x,y,preferredDirection){if(preferredDirection&&preferredDirection!=="NONE"){if(preferredDirection==="LEFT"&&x>20){return "right"}else if(preferredDirection==="RIGHT"&&x<80){return "left"}else if(preferredDirection==="UP"&&y>20){return "bottom"}else if(preferredDirection==="DOWN"&&y<80){return "top"}}if(x<20){return "left"}if(x>80){return "right"}const tl={x:20,y:0};const tr={x:80,y:0};const br={x:80,y:100};const bl={x:20,y:100};const cp={x:50,y:50};const sides=["top","right","bottom","left"];const triangles={top:[tl,tr,cp],right:[cp,tr,br],bottom:[bl,cp,br],left:[tl,cp,bl]};const p={x,y};for(const side of sides){const corners=triangles[side];if(LabelImage.pointInTriangle(p,...corners)){return side}}return "center"}static navigateToMarkerIndex(navigateDirection,markers,thisIndex){const thisMarker=markers[thisIndex];const sortedMarkers=markers.map((otherMarker,index)=>{const x=otherMarker.x-thisMarker.x;const y=otherMarker.y-thisMarker.y;const dist=Math.sqrt(x**2+y**2);return {index,dist,dir:{x:dist!==0?x/dist:0,y:dist!==0?y/dist:0}}}).filter(marker=>{if(marker.index===thisIndex){return false}return markers[marker.index].showCorrectness!=="correct"}).sort((a,b)=>{const distA=Math.round(a.dist*(navigateDirection.x*a.dir.x+navigateDirection.y*a.dir.y));const distB=Math.round(b.dist*(navigateDirection.x*b.dir.x+navigateDirection.y*b.dir.y));let dirA;let dirB;if(navigateDirection.x>0){dirA=a.dir.x>0&&distA!==0;dirB=b.dir.x>0&&distB!==0;}else if(navigateDirection.x<0){dirA=a.dir.x<0&&distA!==0;dirB=b.dir.x<0&&distB!==0;}else if(navigateDirection.y>0){dirA=a.dir.y>0&&distA!==0;dirB=b.dir.y>0&&distB!==0;}else if(navigateDirection.y<0){dirA=a.dir.y<0&&distA!==0;dirB=b.dir.y<0&&distB!==0;}if(dirA!==dirB){if(dirA){return -1}return 1}return distA-distB});return sortedMarkers.length>0?sortedMarkers[0].index:thisIndex}componentDidMount(){this.props.analytics?.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"label-image",widgetId:this.props.widgetId}});this._mounted=true;}componentWillUnmount(){this._mounted=false;}getPromptJSON(){return getPromptJSON$a(this.props)}handleMarkerChange(index,marker){const{userInput,handleUserInput}=this.props;const updatedUserInput=[...userInput.markers.slice(0,index),{label:marker.label,selected:marker.selected},...userInput.markers.slice(index+1)];handleUserInput({markers:updatedUserInput});}activateMarker(index,opened){this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:marker-interacted-with",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:marker-interacted-with:ti",payload:null});const{activeMarkerIndex}=this.state;if(activeMarkerIndex!==index&&opened){this.setState({activeMarkerIndex:index,markersInteracted:true});}else {this.setState({activeMarkerIndex:-1});}}handleMarkerKeyDown(index,e){const{markers}=this.props;if(markers.length<2){return}const directions={ArrowUp:{x:0,y:-1},ArrowRight:{x:1,y:0},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0}};if(!(e.key in directions)){return}const navigateDirection=directions[e.key];e.preventDefault();const marker=this._markers[LabelImage.navigateToMarkerIndex(navigateDirection,markers,index)];if(marker){ReactDOM.findDOMNode(marker).focus();}}handleAnswerChoicesChangeForMarker(index,selection){const{choices,markers}=this.props;const selected=choices.filter((_,index)=>selection[index]);this.handleMarkerChange(index,{...markers[index],selected:selected.length>0?selected:undefined});}renderMarkers(){const{markers,preferredPopoverDirection,userInput}=this.props;const{markersInteracted,activeMarkerIndex}=this.state;const isNarrowPage=this._mounted&&window.matchMedia(mediaQueries.xsOrSmaller.replace("@media ","")).matches;const isWideImage=this.props.imageWidth/2>this.props.imageHeight;return markers.map((marker,index)=>{const userInputMarker=userInput.markers[index];let side;let markerPosition;if(isNarrowPage||isWideImage){side=marker.y>50?"top":"bottom";markerPosition=marker.y>50?"bottom":"top";}else {markerPosition=LabelImage.imageSideForMarkerPosition(marker.x,marker.y,preferredPopoverDirection);if(markerPosition==="center"){markerPosition="bottom";}side=({left:"right",top:"bottom",right:"left",bottom:"top"})[markerPosition];}const computedSelectedState=getComputedSelectedState(marker,userInputMarker,this.props.reviewMode,this.props.showSolutions);let score;if(isAnswerful(marker)){score=scoreLabelImageMarker(computedSelectedState.selected,marker.answers);}else {score={hasAnswers:false,isCorrect:false};}const shouldShowFeedback=this.props.showSolutions==="all"||this.props.reviewMode;const showCorrectness=shouldShowFeedback&&score.isCorrect?"correct":marker.showCorrectness;const disabled=shouldShowFeedback;const isActiveAnswerChoice=activeMarkerIndex===index;const showAnswerChoice=computedSelectedState.selected&&!this.state.hideAnswers&&!isActiveAnswerChoice;const adjustPillDistance={[`margin${markerPosition.charAt(0).toUpperCase()+markerPosition.slice(1)}`]:10};return jsxRuntimeExports.jsx(View,{style:{position:"absolute",left:`${marker.x}%`,top:`${marker.y}%`,zIndex:"unset"},children:jsxRuntimeExports.jsx(AnswerChoices,{choices:this.props.choices.map(choice=>({content:choice,checked:computedSelectedState.selected?computedSelectedState.selected.includes(choice):false})),multipleSelect:this.props.multipleAnswers,onChange:selection=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:choiced-interacted-with",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:choiced-interacted-with:ti",payload:null});this.handleAnswerChoicesChangeForMarker(index,selection);},onToggle:opened=>this.activateMarker(index,opened),disabled:disabled,opener:({opened})=>jsxRuntimeExports.jsx(Clickable,{role:"button","aria-expanded":opened,children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(Marker,{label:marker.label,showCorrectness:showCorrectness,showSelected:opened,showPulsate:!markersInteracted,ref:node=>this._markers[index]=node,showAnswer:showAnswerChoice,answerSide:side,answerStyles:adjustPillDistance,focused:focused||pressed,hovered:hovered,selected:computedSelectedState.selected})},`marker-${marker.x}.${marker.y}`)},`answers-${marker.x}.${marker.y}`)},index)})}renderInstructions(){const{apiOptions:{isMobile},choices,multipleAnswers,hideChoicesFromInstructions:hideChoices}=this.props;const{strings}=this.context;const promptString=isMobile?multipleAnswers?strings.tapMultiple:strings.tapSingle:multipleAnswers?strings.clickMultiple:strings.clickSingle;const choicesString=strings.choices;return jsxRuntimeExports.jsxs("div",{className:classNames$2("perseus-label-image-widget-instructions",css(styles$9.instructions)),children:[jsxRuntimeExports.jsxs("div",{className:css(styles$9.instructionsCaption),children:[promptString," ",!hideChoices&&choicesString]}),!hideChoices&&jsxRuntimeExports.jsx("div",{className:css(styles$9.instructionsChoices),children:choices.map((choice,index)=>jsxRuntimeExports.jsx("div",{className:css(styles$9.instructionsChoice),children:jsxRuntimeExports.jsx(Renderer,{content:choice,strings:strings})},index))})]})}getSerializedState(){const{userInput,markers,...rest}=this.props;return {...rest,markers:markers.map((marker,index)=>({...marker,selected:userInput.markers[index].selected}))}}render(){const{imageAlt,imageUrl,imageWidth,imageHeight}=this.props;const{activeMarkerIndex}=this.state;return jsxRuntimeExports.jsxs("div",{children:[this.renderInstructions(),jsxRuntimeExports.jsxs("div",{className:css(styles$9.markersCanvas),style:{maxWidth:imageWidth,maxHeight:imageHeight},children:[jsxRuntimeExports.jsx("div",{className:css(styles$9.imageContainer,activeMarkerIndex!==-1&&styles$9.imageInteractionDisabled),children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{alt:imageAlt,src:imageUrl,width:imageWidth,height:imageHeight,setAssetStatus:setAssetStatus,allowZoom:true})})}),this.renderMarkers()]}),jsxRuntimeExports.jsx(HideAnswersToggle,{areAnswersHidden:this.state.hideAnswers,onChange:hideAnswers=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:toggle-answers-hidden",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:toggle-answers-hidden:ti",payload:null});this.setState({hideAnswers});}})]})}constructor(props){super(props),this._mounted=false;this._markers=[];this.state={activeMarkerIndex:-1,markersInteracted:false,hideAnswers:false};}}LabelImage.contextType=PerseusI18nContext;const LabelImageWithDependencies=React.forwardRef((props,ref)=>{const deps=useDependencies();return jsxRuntimeExports.jsx(LabelImage,{ref:ref,analytics:deps.analytics,...props})});function getStartUserInput$7(options){return {markers:options.markers.map(m=>({label:m.label}))}}function getUserInputFromSerializedState$7(serializedState){return {markers:serializedState.markers.map(m=>({label:m.label,selected:m.selected}))}}function getCorrectUserInput$3(options){return {markers:options.markers.map(marker=>({label:marker.label,selected:marker.answers}))}}var LabelImage$1 = {name:"label-image",displayName:"Label Image",widget:LabelImageWithDependencies,isLintable:true,getStartUserInput: getStartUserInput$7,getCorrectUserInput: getCorrectUserInput$3,getUserInputFromSerializedState: getUserInputFromSerializedState$7};const styles$9=StyleSheet.create({instructions:{paddingBottom:16},instructionsCaption:{...bodyXsmallBold,paddingBottom:16},instructionsChoices:{display:"flex",flexWrap:"wrap",margin:"-8px 0"},instructionsChoice:{display:"flex",alignItems:"center",margin:"8px 0",":not(:last-child)":{"::after":{content:"''",display:"inline-block",position:"relative",width:2,height:2,marginLeft:5,marginRight:5,background:semanticColor.core.border.neutral.default,borderRadius:2}}},markersCanvas:{position:"relative"},imageContainer:{display:"flex"},imageInteractionDisabled:{pointerEvents:"none"}});
2021
+ function isAnswerful(marker){return marker.answers!=null}function getComputedSelectedState(marker,userInputMarker,reviewMode,showSolutions){const shouldShowFeedback=showSolutions==="all"||reviewMode;if(!shouldShowFeedback){return userInputMarker}if(isAnswerful(marker)){return {...userInputMarker,selected:marker.answers}}else {return {...userInputMarker,selected:undefined}}}class LabelImage extends React.Component{static pointInTriangle(p,a,b,c){const sign=(p1,p2,p3)=>(p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y);const b1=sign(p,a,b)<0;const b2=sign(p,b,c)<0;const b3=sign(p,c,a)<0;return b1===b2&&b2===b3}static imageSideForMarkerPosition(x,y,preferredDirection){if(preferredDirection&&preferredDirection!=="NONE"){if(preferredDirection==="LEFT"&&x>20){return "right"}else if(preferredDirection==="RIGHT"&&x<80){return "left"}else if(preferredDirection==="UP"&&y>20){return "bottom"}else if(preferredDirection==="DOWN"&&y<80){return "top"}}if(x<20){return "left"}if(x>80){return "right"}const tl={x:20,y:0};const tr={x:80,y:0};const br={x:80,y:100};const bl={x:20,y:100};const cp={x:50,y:50};const sides=["top","right","bottom","left"];const triangles={top:[tl,tr,cp],right:[cp,tr,br],bottom:[bl,cp,br],left:[tl,cp,bl]};const p={x,y};for(const side of sides){const corners=triangles[side];if(LabelImage.pointInTriangle(p,...corners)){return side}}return "center"}static navigateToMarkerIndex(navigateDirection,markers,thisIndex){const thisMarker=markers[thisIndex];const sortedMarkers=markers.map((otherMarker,index)=>{const x=otherMarker.x-thisMarker.x;const y=otherMarker.y-thisMarker.y;const dist=Math.sqrt(x**2+y**2);return {index,dist,dir:{x:dist!==0?x/dist:0,y:dist!==0?y/dist:0}}}).filter(marker=>{if(marker.index===thisIndex){return false}return markers[marker.index].showCorrectness!=="correct"}).sort((a,b)=>{const distA=Math.round(a.dist*(navigateDirection.x*a.dir.x+navigateDirection.y*a.dir.y));const distB=Math.round(b.dist*(navigateDirection.x*b.dir.x+navigateDirection.y*b.dir.y));let dirA;let dirB;if(navigateDirection.x>0){dirA=a.dir.x>0&&distA!==0;dirB=b.dir.x>0&&distB!==0;}else if(navigateDirection.x<0){dirA=a.dir.x<0&&distA!==0;dirB=b.dir.x<0&&distB!==0;}else if(navigateDirection.y>0){dirA=a.dir.y>0&&distA!==0;dirB=b.dir.y>0&&distB!==0;}else if(navigateDirection.y<0){dirA=a.dir.y<0&&distA!==0;dirB=b.dir.y<0&&distB!==0;}if(dirA!==dirB){if(dirA){return -1}return 1}return distA-distB});return sortedMarkers.length>0?sortedMarkers[0].index:thisIndex}componentDidMount(){this.props.analytics?.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"label-image",widgetId:this.props.widgetId}});this._mounted=true;}componentWillUnmount(){this._mounted=false;}getPromptJSON(){return getPromptJSON$a(this.props)}handleMarkerChange(index,marker){const{userInput,handleUserInput}=this.props;const updatedUserInput=[...userInput.markers.slice(0,index),{label:marker.label,selected:marker.selected},...userInput.markers.slice(index+1)];handleUserInput({markers:updatedUserInput});}activateMarker(index,opened){this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:marker-interacted-with",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:marker-interacted-with:ti",payload:null});const{activeMarkerIndex}=this.state;if(activeMarkerIndex!==index&&opened){this.setState({activeMarkerIndex:index,markersInteracted:true});}else {this.setState({activeMarkerIndex:-1});}}handleMarkerKeyDown(index,e){const{markers}=this.props;if(markers.length<2){return}const directions={ArrowUp:{x:0,y:-1},ArrowRight:{x:1,y:0},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0}};if(!(e.key in directions)){return}const navigateDirection=directions[e.key];e.preventDefault();const marker=this._markers[LabelImage.navigateToMarkerIndex(navigateDirection,markers,index)];if(marker){ReactDOM.findDOMNode(marker).focus();}}handleAnswerChoicesChangeForMarker(index,selection){const{choices,markers}=this.props;const selected=choices.filter((_,index)=>selection[index]);this.handleMarkerChange(index,{...markers[index],selected:selected.length>0?selected:undefined});}renderMarkers(){const{markers,preferredPopoverDirection,userInput}=this.props;const{markersInteracted,activeMarkerIndex}=this.state;const isNarrowPage=this._mounted&&window.matchMedia(mediaQueries.xsOrSmaller.replace("@media ","")).matches;const isWideImage=this.props.imageWidth/2>this.props.imageHeight;return markers.map((marker,index)=>{const userInputMarker=userInput.markers[index];let side;let markerPosition;if(isNarrowPage||isWideImage){side=marker.y>50?"top":"bottom";markerPosition=marker.y>50?"bottom":"top";}else {markerPosition=LabelImage.imageSideForMarkerPosition(marker.x,marker.y,preferredPopoverDirection);if(markerPosition==="center"){markerPosition="bottom";}side=({left:"right",top:"bottom",right:"left",bottom:"top"})[markerPosition];}const computedSelectedState=getComputedSelectedState(marker,userInputMarker,this.props.reviewMode,this.props.showSolutions);let score;if(isAnswerful(marker)){score=scoreLabelImageMarker(computedSelectedState.selected,marker.answers);}else {score={hasAnswers:false,isCorrect:false};}const shouldShowFeedback=this.props.showSolutions==="all"||this.props.reviewMode;const showCorrectness=shouldShowFeedback&&score.isCorrect?"correct":marker.showCorrectness;const disabled=shouldShowFeedback;const isActiveAnswerChoice=activeMarkerIndex===index;const showAnswerChoice=computedSelectedState.selected&&!this.state.hideAnswers&&!isActiveAnswerChoice;const adjustPillDistance={[`margin${markerPosition.charAt(0).toUpperCase()+markerPosition.slice(1)}`]:10};return jsxRuntimeExports.jsx(View,{style:{position:"absolute",left:`${marker.x}%`,top:`${marker.y}%`,zIndex:"unset"},children:jsxRuntimeExports.jsx(AnswerChoices,{choices:this.props.choices.map(choice=>({content:choice,checked:computedSelectedState.selected?computedSelectedState.selected.includes(choice):false})),multipleSelect:this.props.multipleAnswers,onChange:selection=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:choiced-interacted-with",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:choiced-interacted-with:ti",payload:null});this.handleAnswerChoicesChangeForMarker(index,selection);},onToggle:opened=>this.activateMarker(index,opened),disabled:disabled,opener:({opened})=>jsxRuntimeExports.jsx(Clickable,{role:"button","aria-expanded":opened,children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(Marker,{label:marker.label,showCorrectness:showCorrectness,showSelected:opened,showPulsate:!markersInteracted,ref:node=>this._markers[index]=node,showAnswer:showAnswerChoice,answerSide:side,answerStyles:adjustPillDistance,focused:focused||pressed,hovered:hovered,selected:computedSelectedState.selected})},`marker-${marker.x}.${marker.y}`)},`answers-${marker.x}.${marker.y}`)},index)})}renderInstructions(){const{apiOptions:{isMobile},choices,multipleAnswers,hideChoicesFromInstructions:hideChoices}=this.props;const{strings}=this.context;const promptString=isMobile?multipleAnswers?strings.tapMultiple:strings.tapSingle:multipleAnswers?strings.clickMultiple:strings.clickSingle;const choicesString=strings.choices;return jsxRuntimeExports.jsxs("div",{className:classNames$2("perseus-label-image-widget-instructions",css(styles$a.instructions)),children:[jsxRuntimeExports.jsxs("div",{className:css(styles$a.instructionsCaption),children:[promptString," ",!hideChoices&&choicesString]}),!hideChoices&&jsxRuntimeExports.jsx("div",{className:css(styles$a.instructionsChoices),children:choices.map((choice,index)=>jsxRuntimeExports.jsx("div",{className:css(styles$a.instructionsChoice),children:jsxRuntimeExports.jsx(Renderer,{content:choice,strings:strings})},index))})]})}getSerializedState(){const{userInput,markers,...rest}=this.props;return {...rest,markers:markers.map((marker,index)=>({...marker,selected:userInput.markers[index].selected}))}}render(){const{imageAlt,imageUrl,imageWidth,imageHeight}=this.props;const{activeMarkerIndex}=this.state;return jsxRuntimeExports.jsxs("div",{children:[this.renderInstructions(),jsxRuntimeExports.jsxs("div",{className:css(styles$a.markersCanvas),style:{maxWidth:imageWidth,maxHeight:imageHeight},children:[jsxRuntimeExports.jsx("div",{className:css(styles$a.imageContainer,activeMarkerIndex!==-1&&styles$a.imageInteractionDisabled),children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{alt:imageAlt,src:imageUrl,width:imageWidth,height:imageHeight,setAssetStatus:setAssetStatus,allowZoom:true})})}),this.renderMarkers()]}),jsxRuntimeExports.jsx(HideAnswersToggle,{areAnswersHidden:this.state.hideAnswers,onChange:hideAnswers=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:toggle-answers-hidden",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:toggle-answers-hidden:ti",payload:null});this.setState({hideAnswers});}})]})}constructor(props){super(props),this._mounted=false;this._markers=[];this.state={activeMarkerIndex:-1,markersInteracted:false,hideAnswers:false};}}LabelImage.contextType=PerseusI18nContext;const LabelImageWithDependencies=React.forwardRef((props,ref)=>{const deps=useDependencies();return jsxRuntimeExports.jsx(LabelImage,{ref:ref,analytics:deps.analytics,...props})});function getStartUserInput$7(options){return {markers:options.markers.map(m=>({label:m.label}))}}function getUserInputFromSerializedState$7(serializedState){return {markers:serializedState.markers.map(m=>({label:m.label,selected:m.selected}))}}function getCorrectUserInput$3(options){return {markers:options.markers.map(marker=>({label:marker.label,selected:marker.answers}))}}var LabelImage$1 = {name:"label-image",displayName:"Label Image",widget:LabelImageWithDependencies,isLintable:true,getStartUserInput: getStartUserInput$7,getCorrectUserInput: getCorrectUserInput$3,getUserInputFromSerializedState: getUserInputFromSerializedState$7};const styles$a=StyleSheet.create({instructions:{paddingBottom:16},instructionsCaption:{...bodyXsmallBold,paddingBottom:16},instructionsChoices:{display:"flex",flexWrap:"wrap",margin:"-8px 0"},instructionsChoice:{display:"flex",alignItems:"center",margin:"8px 0",":not(:last-child)":{"::after":{content:"''",display:"inline-block",position:"relative",width:2,height:2,marginLeft:5,marginRight:5,background:semanticColor.core.border.neutral.default,borderRadius:2}}},markersCanvas:{position:"relative"},imageContainer:{display:"flex"},imageInteractionDisabled:{pointerEvents:"none"}});
2022
2022
 
2023
- const addOffsetParentScroll=($el,position)=>{const $offsetParent=$el.offsetParent();return {top:position.top+$offsetParent.scrollTop(),left:position.left+$offsetParent.scrollLeft()}};class Placeholder extends React.Component{render(){const{layout}=this.props;const className=css(styles$8.card,styles$8.placeholder,layout==="horizontal"&&styles$8.horizontalCard);const style={width:this.props.width,height:this.props.height};if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style})}}class Draggable extends React.Component{componentDidMount(){this._mounted=true;this.isMouseMoveUpBound=false;document.addEventListener("touchmove",this.onMouseMove,Util.supportsPassiveEvents()?{passive:false}:false);}componentDidUpdate(prevProps){if(this.props.state===prevProps.state){return}if(this.props.state==="animating"&&this.props.endPosition){const current=this.getCurrentPosition();const duration=15*Math.sqrt(Math.sqrt(Math.pow(this.props.endPosition.left-current.left,2)+Math.pow(this.props.endPosition.top-current.top,2)));$(ReactDOM__default.findDOMNode(this)).animate(this.props.endPosition,{duration:Math.max(duration,1),complete:this.props.onAnimationEnd});}else if(this.props.state==="static"){$(ReactDOM__default.findDOMNode(this)).finish();}}componentWillUnmount(){this._mounted=false;if(this.isMouseMoveUpBound){this.unbindMouseMoveUp();}if(this.animationFrameRequest){cancelAnimationFrame(this.animationFrameRequest);}document.removeEventListener("touchmove",this.onMouseMove);}render(){const{includePadding,layout,state:type}=this.props;let className=css(styles$8.card,styles$8.draggable,layout==="horizontal"&&styles$8.horizontalCard,layout==="vertical"&&styles$8.verticalCard,type==="dragging"&&styles$8.dragging,type==="disabled"&&styles$8.disabled,!includePadding&&styles$8.unpaddedCard)+" "+"perseus-sortable-draggable";if(!includePadding){className+=" perseus-sortable-draggable-unpadded";}const style={position:"static"};if(this.props.state==="dragging"||this.props.state==="animating"){_.extend(style,{position:"absolute"},this.getCurrentPosition());}if(this.props.width){style.width=this.props.width+1;}if(this.props.height){style.height=this.props.height;}if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style,onMouseDown:this.onMouseDown,onTouchStart:this.onMouseDown,onTouchMove:this.onMouseMove,onTouchEnd:this.onMouseUp,onTouchCancel:this.onMouseUp,children:jsxRuntimeExports.jsx(Renderer,{content:this.props.content,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"draggable"),onRender:this.props.onRender,strings:this.context.strings})})}constructor(...args){super(...args),this.animationFrameRequest=null,this.state={startPosition:{left:0,top:0},startMouse:{left:0,top:0},mouse:{left:0,top:0},dragging:false},this.getCurrentPosition=()=>{return {left:this.state.startPosition.left+this.state.mouse.left-this.state.startMouse.left,top:this.state.startPosition.top+this.state.mouse.top-this.state.startMouse.top}},this.bindMouseMoveUp=()=>{this.isMouseMoveUpBound=true;$(document).on("mousemove",this.onMouseMove);$(document).on("mouseup",this.onMouseUp);},this.unbindMouseMoveUp=()=>{this.isMouseMoveUpBound=false;$(document).off("mousemove",this.onMouseMove);$(document).off("mouseup",this.onMouseUp);},this.onMouseDown=event=>{if(this.props.state!=="static"){return}if(!(event.button===0||event.touches!=null&&event.touches.length===1)){return}event.preventDefault();const loc=Util.extractPointerLocation(event);this.animationFrameRequest=requestAnimationFrame(()=>{const $el=$(ReactDOM__default.findDOMNode(this));const position=$el.position();const startPosition=addOffsetParentScroll($el,position);if(loc&&this._mounted){this.setState({startPosition,startMouse:loc,mouse:loc,dragging:true},function(){this.bindMouseMoveUp();this.props.onMouseDown();});}});},this.onMouseMove=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.animationFrameRequest=requestAnimationFrame(()=>{this.setState({mouse:loc},this.props.onMouseMove);});}},this.onMouseUp=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.setState({dragging:false});this.unbindMouseMoveUp();this.props.onMouseUp();}};}}Draggable.contextType=PerseusI18nContext;Draggable.defaultProps={includePadding:true,type:"static",linterContext:PerseusLinter.linterContextDefault};class Sortable extends React.Component{static itemsFromProps(props){const state=props.disabled?"disabled":"static";return props.options.map((option,i)=>{return {option:option,key:i,state,width:0,height:0}})}static clearItemMeasurements(items){return items.map(item=>{return {...item,width:0,height:0}})}UNSAFE_componentWillReceiveProps(nextProps){const prevProps=this.props;if(!_.isEqual(nextProps.options,prevProps.options)){this.setState({items:Sortable.itemsFromProps(nextProps)});}else if(nextProps.layout!==prevProps.layout||nextProps.padding!==prevProps.padding||nextProps.disabled!==prevProps.disabled||!_.isEqual(nextProps.constraints,prevProps.constraints)){this.setState({items:Sortable.clearItemMeasurements(this.state.items)});}}componentDidUpdate(){if(this.state.items.length&&!this.state.items[0].width&&!this.state.items[0].height){setTimeout(()=>{this.measureItems();},0);}}measureItems(){let items=[...this.state.items];const $items=_.map(items,function(item){return $(ReactDOM__default.findDOMNode(this.refs[item.key]))},this);const widths=_.invoke($items,"outerWidth");const heights=_.invoke($items,"outerHeight");const{constraints,layout}=this.props;let syncWidth=null;if(constraints?.width){syncWidth=_.max(widths.concat(constraints.width));}else if(layout==="vertical"){syncWidth=_.max(widths);}let syncHeight=null;if(constraints?.height){syncHeight=_.max(heights.concat(constraints.height));}else if(layout==="horizontal"){syncHeight=_.max(heights);}items=_.map(items,function(item,i){item.width=syncWidth||widths[i];item.height=syncHeight||heights[i];return item});this.setState({items},()=>{this.props.onMeasure?.({widths:widths,heights:heights});});}onMouseDown(key){const items=_.map(this.state.items,function(item){if(item.key===key){item.state="dragging";}return item});this.setState({items:items});}moveOptionToIndex(option,index){const{items}=this.state;if(index<0||index>items.length){throw new Error(`index ${index} out of bounds`)}const nextItems=_.clone(items);const item=items.filter(item=>{return item.option===option})[0];if(item==null){throw new Error(`option ${option} not found`)}const currentIndex=items.findIndex(i=>{return i.key===item.key});nextItems.splice(currentIndex,1);nextItems.splice(index,0,item);this.setState({items:nextItems},()=>{this.props.onChange?.({});});}onMouseMove(key){const $draggable=$(ReactDOM__default.findDOMNode(this.refs[key]));const $sortable=$(ReactDOM__default.findDOMNode(this));const items=_.clone(this.state.items);const item=_.findWhere(this.state.items,{key:key});const margin=this.props.margin||0;const currentIndex=_.indexOf(items,item);let newIndex=0;items.splice(currentIndex,1);if(this.props.layout==="horizontal"){const midWidth=$draggable.offset().left-$sortable.offset().left;let sumWidth=0;let cardWidth;_.each(items,function(item){cardWidth=item.width;if(midWidth>sumWidth+cardWidth/2){newIndex+=1;}sumWidth+=cardWidth+margin;});}else {const midHeight=$draggable.offset().top-$sortable.offset().top;let sumHeight=0;let cardHeight;_.each(items,function(item){cardHeight=item.height;if(midHeight>sumHeight+cardHeight/2){newIndex+=1;}sumHeight+=cardHeight+margin;});}if(newIndex!==currentIndex){items.splice(newIndex,0,item);this.setState({items:items});}}onMouseUp(key){const nextAnimationFrame=requestAnimationFrame(()=>{const items=_.map(this.state.items,function(item){if(item.key===key){item.state="animating";const $placeholder=$(ReactDOM__default.findDOMNode(this.refs["placeholder_"+key]));const position=$placeholder.position();const endPosition=addOffsetParentScroll($placeholder,position);item.endPosition=endPosition;}return item},this);this.setState({items:items},()=>{this.props.onChange?.({});});});this.animationFrameRequest=nextAnimationFrame;}onAnimationEnd(key){const items=_.map(this.state.items,function(item){if(item.key===key){item.state="static";}return item});this.setState({items:items});}getOptions(){return _.pluck(this.state.items,"option")}render(){if(this.props.waitForTexRendererToLoad&&!this.state.texRendererLoaded){const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CircularSpinner,{}),jsxRuntimeExports.jsx("div",{style:{display:"none"},children:jsxRuntimeExports.jsx(TeX,{onRender:()=>this.setState({texRendererLoaded:true}),children:"1"})})]})}const cards=[];const{layout}=this.props;const className=css(styles$8.sortable)+" perseus-sortable";const syncWidth=this.props.constraints?.width||layout==="vertical";const syncHeight=this.props.constraints?.height||layout==="horizontal";_.each(this.state.items,function(item,i,items){const isLast=i===items.length-1;const isStatic=item.state==="static"||item.state==="disabled";let margin;if(this.props.layout==="horizontal"){margin="0 "+this.props.margin+"px 0 0";}else if(this.props.layout==="vertical"){margin="0 0 "+this.props.margin+"px 0";}cards.push(jsxRuntimeExports.jsx(Draggable,{content:item.option,state:item.state,ref:item.key,width:syncWidth?item.width:undefined,height:syncHeight?item.height:undefined,layout:layout,includePadding:this.props.padding,margin:isLast&&isStatic?0:margin,endPosition:item.endPosition,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"sortable"),onRender:this.remeasureItems,onMouseDown:this.onMouseDown.bind(this,item.key),onMouseMove:this.onMouseMove.bind(this,item.key),onMouseUp:this.onMouseUp.bind(this,item.key),onTouchMove:this.onMouseMove.bind(this,item.key),onTouchEnd:this.onMouseUp.bind(this,item.key),onTouchCancel:this.onMouseUp.bind(this,item.key),onAnimationEnd:this.onAnimationEnd.bind(this,item.key)},item.key));if(item.state==="dragging"||item.state==="animating"){cards.push(jsxRuntimeExports.jsx(Placeholder,{ref:"placeholder_"+item.key,width:item.width,height:item.height,layout:layout,margin:isLast?0:margin},"placeholder_"+item.key));}},this);return jsxRuntimeExports.jsx("ul",{className:className,children:cards})}constructor(props){super(props),this.remeasureItems=_.debounce(()=>{this.setState({items:Sortable.clearItemMeasurements(this.state.items)});},20);this.state={items:Sortable.itemsFromProps(this.props),texRendererLoaded:false};}}Sortable.defaultProps={layout:"horizontal",padding:true,disabled:false,constraints:{},onMeasure:function(){},margin:5,onChange:function(){},linterContext:PerseusLinter.linterContextDefault,waitForTexRendererToLoad:true};const styles$8=StyleSheet.create({sortable:{boxSizing:"border-box",float:"left",padding:0,margin:0},card:{boxSizing:"border-box",background:semanticColor.core.background.base.default,border:`${border$1.width.thin} solid ${semanticColor.core.border.neutral.subtle}`,borderRadius:4,cursor:"pointer",minWidth:25,minHeight:44,padding:10,listStyleType:"none",userSelect:"none",touchAction:"none"},placeholder:{background:semanticColor.core.background.neutral.subtle,border:`${border$1.width.thin} solid ${semanticColor.core.border.neutral.subtle}`},draggable:{textAlign:"center"},horizontalCard:{float:"left",cursor:"ew-resize"},verticalCard:{maxWidth:"100%",cursor:"ns-resize"},unpaddedCard:{padding:0},dragging:{background:semanticColor.core.background.instructive.subtle,border:`${border$1.width.thin} solid ${semanticColor.core.border.instructive.default}`,opacity:.8},disabled:{backgroundColor:"inherit",border:`${border$1.width.thin} solid ${semanticColor.core.border.disabled.subtle}`,cursor:"default"}});
2023
+ const addOffsetParentScroll=($el,position)=>{const $offsetParent=$el.offsetParent();return {top:position.top+$offsetParent.scrollTop(),left:position.left+$offsetParent.scrollLeft()}};class Placeholder extends React.Component{render(){const{layout}=this.props;const className=css(styles$9.card,styles$9.placeholder,layout==="horizontal"&&styles$9.horizontalCard);const style={width:this.props.width,height:this.props.height};if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style})}}class Draggable extends React.Component{componentDidMount(){this._mounted=true;this.isMouseMoveUpBound=false;document.addEventListener("touchmove",this.onMouseMove,Util.supportsPassiveEvents()?{passive:false}:false);}componentDidUpdate(prevProps){if(this.props.state===prevProps.state){return}if(this.props.state==="animating"&&this.props.endPosition){const current=this.getCurrentPosition();const duration=15*Math.sqrt(Math.sqrt(Math.pow(this.props.endPosition.left-current.left,2)+Math.pow(this.props.endPosition.top-current.top,2)));$(ReactDOM__default.findDOMNode(this)).animate(this.props.endPosition,{duration:Math.max(duration,1),complete:this.props.onAnimationEnd});}else if(this.props.state==="static"){$(ReactDOM__default.findDOMNode(this)).finish();}}componentWillUnmount(){this._mounted=false;if(this.isMouseMoveUpBound){this.unbindMouseMoveUp();}if(this.animationFrameRequest){cancelAnimationFrame(this.animationFrameRequest);}document.removeEventListener("touchmove",this.onMouseMove);}render(){const{includePadding,layout,state:type}=this.props;let className=css(styles$9.card,styles$9.draggable,layout==="horizontal"&&styles$9.horizontalCard,layout==="vertical"&&styles$9.verticalCard,type==="dragging"&&styles$9.dragging,type==="disabled"&&styles$9.disabled,!includePadding&&styles$9.unpaddedCard)+" "+"perseus-sortable-draggable";if(!includePadding){className+=" perseus-sortable-draggable-unpadded";}const style={position:"static"};if(this.props.state==="dragging"||this.props.state==="animating"){_.extend(style,{position:"absolute"},this.getCurrentPosition());}if(this.props.width){style.width=this.props.width+1;}if(this.props.height){style.height=this.props.height;}if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style,onMouseDown:this.onMouseDown,onTouchStart:this.onMouseDown,onTouchMove:this.onMouseMove,onTouchEnd:this.onMouseUp,onTouchCancel:this.onMouseUp,children:jsxRuntimeExports.jsx(Renderer,{content:this.props.content,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"draggable"),onRender:this.props.onRender,strings:this.context.strings})})}constructor(...args){super(...args),this.animationFrameRequest=null,this.state={startPosition:{left:0,top:0},startMouse:{left:0,top:0},mouse:{left:0,top:0},dragging:false},this.getCurrentPosition=()=>{return {left:this.state.startPosition.left+this.state.mouse.left-this.state.startMouse.left,top:this.state.startPosition.top+this.state.mouse.top-this.state.startMouse.top}},this.bindMouseMoveUp=()=>{this.isMouseMoveUpBound=true;$(document).on("mousemove",this.onMouseMove);$(document).on("mouseup",this.onMouseUp);},this.unbindMouseMoveUp=()=>{this.isMouseMoveUpBound=false;$(document).off("mousemove",this.onMouseMove);$(document).off("mouseup",this.onMouseUp);},this.onMouseDown=event=>{if(this.props.state!=="static"){return}if(!(event.button===0||event.touches!=null&&event.touches.length===1)){return}event.preventDefault();const loc=Util.extractPointerLocation(event);this.animationFrameRequest=requestAnimationFrame(()=>{const $el=$(ReactDOM__default.findDOMNode(this));const position=$el.position();const startPosition=addOffsetParentScroll($el,position);if(loc&&this._mounted){this.setState({startPosition,startMouse:loc,mouse:loc,dragging:true},function(){this.bindMouseMoveUp();this.props.onMouseDown();});}});},this.onMouseMove=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.animationFrameRequest=requestAnimationFrame(()=>{this.setState({mouse:loc},this.props.onMouseMove);});}},this.onMouseUp=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.setState({dragging:false});this.unbindMouseMoveUp();this.props.onMouseUp();}};}}Draggable.contextType=PerseusI18nContext;Draggable.defaultProps={includePadding:true,type:"static",linterContext:PerseusLinter.linterContextDefault};class Sortable extends React.Component{static itemsFromProps(props){const state=props.disabled?"disabled":"static";return props.options.map((option,i)=>{return {option:option,key:i,state,width:0,height:0}})}static clearItemMeasurements(items){return items.map(item=>{return {...item,width:0,height:0}})}UNSAFE_componentWillReceiveProps(nextProps){const prevProps=this.props;if(!_.isEqual(nextProps.options,prevProps.options)){this.setState({items:Sortable.itemsFromProps(nextProps)});}else if(nextProps.layout!==prevProps.layout||nextProps.padding!==prevProps.padding||nextProps.disabled!==prevProps.disabled||!_.isEqual(nextProps.constraints,prevProps.constraints)){this.setState({items:Sortable.clearItemMeasurements(this.state.items)});}}componentDidUpdate(){if(this.state.items.length&&!this.state.items[0].width&&!this.state.items[0].height){setTimeout(()=>{this.measureItems();},0);}}measureItems(){let items=[...this.state.items];const $items=_.map(items,function(item){return $(ReactDOM__default.findDOMNode(this.refs[item.key]))},this);const widths=_.invoke($items,"outerWidth");const heights=_.invoke($items,"outerHeight");const{constraints,layout}=this.props;let syncWidth=null;if(constraints?.width){syncWidth=_.max(widths.concat(constraints.width));}else if(layout==="vertical"){syncWidth=_.max(widths);}let syncHeight=null;if(constraints?.height){syncHeight=_.max(heights.concat(constraints.height));}else if(layout==="horizontal"){syncHeight=_.max(heights);}items=_.map(items,function(item,i){item.width=syncWidth||widths[i];item.height=syncHeight||heights[i];return item});this.setState({items},()=>{this.props.onMeasure?.({widths:widths,heights:heights});});}onMouseDown(key){const items=_.map(this.state.items,function(item){if(item.key===key){item.state="dragging";}return item});this.setState({items:items});}moveOptionToIndex(option,index){const{items}=this.state;if(index<0||index>items.length){throw new Error(`index ${index} out of bounds`)}const nextItems=_.clone(items);const item=items.filter(item=>{return item.option===option})[0];if(item==null){throw new Error(`option ${option} not found`)}const currentIndex=items.findIndex(i=>{return i.key===item.key});nextItems.splice(currentIndex,1);nextItems.splice(index,0,item);this.setState({items:nextItems},()=>{this.props.onChange?.({});});}onMouseMove(key){const $draggable=$(ReactDOM__default.findDOMNode(this.refs[key]));const $sortable=$(ReactDOM__default.findDOMNode(this));const items=_.clone(this.state.items);const item=_.findWhere(this.state.items,{key:key});const margin=this.props.margin||0;const currentIndex=_.indexOf(items,item);let newIndex=0;items.splice(currentIndex,1);if(this.props.layout==="horizontal"){const midWidth=$draggable.offset().left-$sortable.offset().left;let sumWidth=0;let cardWidth;_.each(items,function(item){cardWidth=item.width;if(midWidth>sumWidth+cardWidth/2){newIndex+=1;}sumWidth+=cardWidth+margin;});}else {const midHeight=$draggable.offset().top-$sortable.offset().top;let sumHeight=0;let cardHeight;_.each(items,function(item){cardHeight=item.height;if(midHeight>sumHeight+cardHeight/2){newIndex+=1;}sumHeight+=cardHeight+margin;});}if(newIndex!==currentIndex){items.splice(newIndex,0,item);this.setState({items:items});}}onMouseUp(key){const nextAnimationFrame=requestAnimationFrame(()=>{const items=_.map(this.state.items,function(item){if(item.key===key){item.state="animating";const $placeholder=$(ReactDOM__default.findDOMNode(this.refs["placeholder_"+key]));const position=$placeholder.position();const endPosition=addOffsetParentScroll($placeholder,position);item.endPosition=endPosition;}return item},this);this.setState({items:items},()=>{this.props.onChange?.({});});});this.animationFrameRequest=nextAnimationFrame;}onAnimationEnd(key){const items=_.map(this.state.items,function(item){if(item.key===key){item.state="static";}return item});this.setState({items:items});}getOptions(){return _.pluck(this.state.items,"option")}render(){if(this.props.waitForTexRendererToLoad&&!this.state.texRendererLoaded){const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CircularSpinner,{}),jsxRuntimeExports.jsx("div",{style:{display:"none"},children:jsxRuntimeExports.jsx(TeX,{onRender:()=>this.setState({texRendererLoaded:true}),children:"1"})})]})}const cards=[];const{layout}=this.props;const className=css(styles$9.sortable)+" perseus-sortable";const syncWidth=this.props.constraints?.width||layout==="vertical";const syncHeight=this.props.constraints?.height||layout==="horizontal";_.each(this.state.items,function(item,i,items){const isLast=i===items.length-1;const isStatic=item.state==="static"||item.state==="disabled";let margin;if(this.props.layout==="horizontal"){margin="0 "+this.props.margin+"px 0 0";}else if(this.props.layout==="vertical"){margin="0 0 "+this.props.margin+"px 0";}cards.push(jsxRuntimeExports.jsx(Draggable,{content:item.option,state:item.state,ref:item.key,width:syncWidth?item.width:undefined,height:syncHeight?item.height:undefined,layout:layout,includePadding:this.props.padding,margin:isLast&&isStatic?0:margin,endPosition:item.endPosition,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"sortable"),onRender:this.remeasureItems,onMouseDown:this.onMouseDown.bind(this,item.key),onMouseMove:this.onMouseMove.bind(this,item.key),onMouseUp:this.onMouseUp.bind(this,item.key),onTouchMove:this.onMouseMove.bind(this,item.key),onTouchEnd:this.onMouseUp.bind(this,item.key),onTouchCancel:this.onMouseUp.bind(this,item.key),onAnimationEnd:this.onAnimationEnd.bind(this,item.key)},item.key));if(item.state==="dragging"||item.state==="animating"){cards.push(jsxRuntimeExports.jsx(Placeholder,{ref:"placeholder_"+item.key,width:item.width,height:item.height,layout:layout,margin:isLast?0:margin},"placeholder_"+item.key));}},this);return jsxRuntimeExports.jsx("ul",{className:className,children:cards})}constructor(props){super(props),this.remeasureItems=_.debounce(()=>{this.setState({items:Sortable.clearItemMeasurements(this.state.items)});},20);this.state={items:Sortable.itemsFromProps(this.props),texRendererLoaded:false};}}Sortable.defaultProps={layout:"horizontal",padding:true,disabled:false,constraints:{},onMeasure:function(){},margin:5,onChange:function(){},linterContext:PerseusLinter.linterContextDefault,waitForTexRendererToLoad:true};const styles$9=StyleSheet.create({sortable:{boxSizing:"border-box",float:"left",padding:0,margin:0},card:{boxSizing:"border-box",background:semanticColor.core.background.base.default,border:`${border$1.width.thin} solid ${semanticColor.core.border.neutral.subtle}`,borderRadius:4,cursor:"pointer",minWidth:25,minHeight:44,padding:10,listStyleType:"none",userSelect:"none",touchAction:"none"},placeholder:{background:semanticColor.core.background.neutral.subtle,border:`${border$1.width.thin} solid ${semanticColor.core.border.neutral.subtle}`},draggable:{textAlign:"center"},horizontalCard:{float:"left",cursor:"ew-resize"},verticalCard:{maxWidth:"100%",cursor:"ns-resize"},unpaddedCard:{padding:0},dragging:{background:semanticColor.core.background.instructive.subtle,border:`${border$1.width.thin} solid ${semanticColor.core.border.instructive.default}`,opacity:.8},disabled:{backgroundColor:"inherit",border:`${border$1.width.thin} solid ${semanticColor.core.border.disabled.subtle}`,cursor:"default"}});
2024
2024
 
2025
2025
  const getPromptJSON$9=widgetData=>{const{userInput}=widgetData;return {type:"matcher",options:{labels:widgetData.labels,left:widgetData.left,right:widgetData.right,orderMatters:widgetData.orderMatters},userInput:{left:userInput.left,right:userInput.right}}};
2026
2026
 
2027
- const HACKY_CSS_CLASSNAME="perseus-widget-matcher";class Matcher extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"matcher",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$9(this.props)}render(){if(!this.state.texRendererLoaded){const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CircularSpinner,{}),jsxRuntimeExports.jsx("div",{style:{display:"none"},children:jsxRuntimeExports.jsx(TeX,{onRender:()=>{this.setState({texRendererLoaded:true});},children:"1"})})]})}const showLabels=_.any(this.props.labels);const constraints={height:_.max([this.state.leftHeight,this.state.rightHeight])};const cellMarginPx=this.props.apiOptions.isMobile?8:5;return jsxRuntimeExports.jsx("table",{className:css(styles$7.widget)+" "+HACKY_CSS_CLASSNAME,children:jsxRuntimeExports.jsxs("tbody",{children:[showLabels&&jsxRuntimeExports.jsxs("tr",{className:css(styles$7.row),children:[jsxRuntimeExports.jsx("th",{className:css(styles$7.column,styles$7.columnLabel),children:jsxRuntimeExports.jsx(Renderer,{content:this.props.labels[0]||"...",linterContext:this.props.linterContext,strings:this.context.strings})}),jsxRuntimeExports.jsx("th",{className:css(styles$7.column,styles$7.columnRight,styles$7.columnLabel),children:jsxRuntimeExports.jsx(Renderer,{content:this.props.labels[1]||"...",linterContext:this.props.linterContext,strings:this.context.strings})})]}),jsxRuntimeExports.jsxs("tr",{className:css(styles$7.row),children:[jsxRuntimeExports.jsx("td",{className:css(styles$7.column),children:jsxRuntimeExports.jsx(Sortable,{options:this.props.userInput.left,layout:"vertical",padding:this.props.padding,disabled:!this.props.orderMatters,constraints:constraints,onMeasure:this.onMeasureLeft,onChange:this.changeAndTrack,margin:cellMarginPx,linterContext:this.props.linterContext,ref:"left"})}),jsxRuntimeExports.jsx("td",{className:css(styles$7.column,styles$7.columnRight),children:jsxRuntimeExports.jsx(Sortable,{options:this.props.userInput.right,layout:"vertical",padding:this.props.padding,constraints:constraints,onMeasure:this.onMeasureRight,onChange:this.changeAndTrack,margin:cellMarginPx,linterContext:this.props.linterContext,ref:"right"})})]})]})})}constructor(...args){super(...args),this.state={leftHeight:0,rightHeight:0,texRendererLoaded:false},this.changeAndTrack=()=>{const nextUserInput=this._getUserInputFromSortable();this.props.handleUserInput(nextUserInput);this.props.trackInteraction();},this.onMeasureLeft=dimensions=>{const height=_.max(dimensions.heights);this.setState({leftHeight:height});},this.onMeasureRight=dimensions=>{const height=_.max(dimensions.heights);this.setState({rightHeight:height});},this._getUserInputFromSortable=()=>{if(!this.state.texRendererLoaded){return {left:[],right:[]}}return {left:this.refs.left.getOptions(),right:this.refs.right.getOptions()}},this.moveLeftOptionToIndex=(option,index)=>{this.refs.left.moveOptionToIndex(option,index);},this.moveRightOptionToIndex=(option,index)=>{this.refs.right.moveOptionToIndex(option,index);};}}Matcher.contextType=PerseusI18nContext;Matcher.defaultProps={labels:["",""],orderMatters:false,padding:true,problemNum:0,linterContext:linterContextDefault,userInput:{left:[],right:[]}};function getStartUserInput$6(options,problemNum){const shuffled=shuffleMatcher(options,problemNum);return shuffled}function getUserInputFromSerializedState$6(serializedState){return {left:serializedState.left,right:serializedState.right}}const WrappedMatcher=withDependencies(Matcher);var Matcher$1 = {name:"matcher",displayName:"Matcher (two column)",widget:WrappedMatcher,isLintable:true,getStartUserInput: getStartUserInput$6,getUserInputFromSerializedState: getUserInputFromSerializedState$6};const padding=5;const border=`var(--wb-border-width-thin) solid var(--wb-semanticColor-core-border-neutral-strong)`;const styles$7=StyleSheet.create({widget:{paddingTop:padding,maxWidth:"100%",minWidth:"auto"},row:{border:0},column:{padding:0,border:0},columnRight:{borderLeft:border},columnLabel:{fontWeight:"inherit",borderBottom:border,padding:`0 ${padding}px ${padding}px ${padding}px`,textAlign:"center"}});
2027
+ const HACKY_CSS_CLASSNAME="perseus-widget-matcher";class Matcher extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"matcher",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$9(this.props)}render(){if(!this.state.texRendererLoaded){const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CircularSpinner,{}),jsxRuntimeExports.jsx("div",{style:{display:"none"},children:jsxRuntimeExports.jsx(TeX,{onRender:()=>{this.setState({texRendererLoaded:true});},children:"1"})})]})}const showLabels=_.any(this.props.labels);const constraints={height:_.max([this.state.leftHeight,this.state.rightHeight])};const cellMarginPx=this.props.apiOptions.isMobile?8:5;return jsxRuntimeExports.jsx("table",{className:css(styles$8.widget)+" "+HACKY_CSS_CLASSNAME,children:jsxRuntimeExports.jsxs("tbody",{children:[showLabels&&jsxRuntimeExports.jsxs("tr",{className:css(styles$8.row),children:[jsxRuntimeExports.jsx("th",{className:css(styles$8.column,styles$8.columnLabel),children:jsxRuntimeExports.jsx(Renderer,{content:this.props.labels[0]||"...",linterContext:this.props.linterContext,strings:this.context.strings})}),jsxRuntimeExports.jsx("th",{className:css(styles$8.column,styles$8.columnRight,styles$8.columnLabel),children:jsxRuntimeExports.jsx(Renderer,{content:this.props.labels[1]||"...",linterContext:this.props.linterContext,strings:this.context.strings})})]}),jsxRuntimeExports.jsxs("tr",{className:css(styles$8.row),children:[jsxRuntimeExports.jsx("td",{className:css(styles$8.column),children:jsxRuntimeExports.jsx(Sortable,{options:this.props.userInput.left,layout:"vertical",padding:this.props.padding,disabled:!this.props.orderMatters,constraints:constraints,onMeasure:this.onMeasureLeft,onChange:this.changeAndTrack,margin:cellMarginPx,linterContext:this.props.linterContext,ref:"left"})}),jsxRuntimeExports.jsx("td",{className:css(styles$8.column,styles$8.columnRight),children:jsxRuntimeExports.jsx(Sortable,{options:this.props.userInput.right,layout:"vertical",padding:this.props.padding,constraints:constraints,onMeasure:this.onMeasureRight,onChange:this.changeAndTrack,margin:cellMarginPx,linterContext:this.props.linterContext,ref:"right"})})]})]})})}constructor(...args){super(...args),this.state={leftHeight:0,rightHeight:0,texRendererLoaded:false},this.changeAndTrack=()=>{const nextUserInput=this._getUserInputFromSortable();this.props.handleUserInput(nextUserInput);this.props.trackInteraction();},this.onMeasureLeft=dimensions=>{const height=_.max(dimensions.heights);this.setState({leftHeight:height});},this.onMeasureRight=dimensions=>{const height=_.max(dimensions.heights);this.setState({rightHeight:height});},this._getUserInputFromSortable=()=>{if(!this.state.texRendererLoaded){return {left:[],right:[]}}return {left:this.refs.left.getOptions(),right:this.refs.right.getOptions()}},this.moveLeftOptionToIndex=(option,index)=>{this.refs.left.moveOptionToIndex(option,index);},this.moveRightOptionToIndex=(option,index)=>{this.refs.right.moveOptionToIndex(option,index);};}}Matcher.contextType=PerseusI18nContext;Matcher.defaultProps={labels:["",""],orderMatters:false,padding:true,problemNum:0,linterContext:linterContextDefault,userInput:{left:[],right:[]}};function getStartUserInput$6(options,problemNum){const shuffled=shuffleMatcher(options,problemNum);return shuffled}function getUserInputFromSerializedState$6(serializedState){return {left:serializedState.left,right:serializedState.right}}const WrappedMatcher=withDependencies(Matcher);var Matcher$1 = {name:"matcher",displayName:"Matcher (two column)",widget:WrappedMatcher,isLintable:true,getStartUserInput: getStartUserInput$6,getUserInputFromSerializedState: getUserInputFromSerializedState$6};const padding=5;const border=`var(--wb-border-width-thin) solid var(--wb-semanticColor-core-border-neutral-strong)`;const styles$8=StyleSheet.create({widget:{paddingTop:padding,maxWidth:"100%",minWidth:"auto"},row:{border:0},column:{padding:0,border:0},columnRight:{borderLeft:border},columnLabel:{fontWeight:"inherit",borderBottom:border,padding:`0 ${padding}px ${padding}px ${padding}px`,textAlign:"center"}});
2028
2028
 
2029
2029
  const getPromptJSON$8=widgetData=>{return {type:"matrix",options:{height:widgetData.matrixBoardSize[0],width:widgetData.matrixBoardSize[1]},userInput:{answerRows:widgetData.userInput.answers}}};
2030
2030
 
@@ -2034,7 +2034,7 @@ const getPromptJSON$7=()=>{return getUnsupportedPromptJSON("measurer")};
2034
2034
 
2035
2035
  const defaultImage={url:null,top:0,left:0};class Measurer extends React.Component{componentDidMount(){this.setupGraphie();}componentDidUpdate(prevProps){const shouldSetupGraphie=_.any(["box","showProtractor","showRuler","rulerLabel","rulerTicks","rulerPixels","rulerLength"],prop=>{return prevProps[prop]!==this.props[prop]},this);if(shouldSetupGraphie){this.setupGraphie();}}setupGraphie(){const graphieDiv=ReactDOM__default.findDOMNode(this.refs.graphieDiv);$(graphieDiv).empty();const graphie=this.graphie=GraphUtils.createGraphie(graphieDiv);const scale=[40,40];const range=[[0,this.props.box[0]/scale[0]],[0,this.props.box[1]/scale[1]]];graphie.init({range:range,scale:scale});graphie.addMouseLayer({allowScratchpad:true});if(this.protractor){this.protractor.remove();}if(this.props.showProtractor){this.protractor=graphie.protractor([this.props.protractorX,this.props.protractorY]);}if(this.ruler){this.ruler.remove();}if(this.props.showRuler){this.ruler=graphie.ruler({center:[(range[0][0]+range[0][1])/2,(range[1][0]+range[1][1])/2],label:this.props.rulerLabel,pixelsPerUnit:this.props.rulerPixels,ticksPerUnit:this.props.rulerTicks,units:this.props.rulerLength});}}getPromptJSON(){return getPromptJSON$7()}render(){const image=_.extend({},defaultImage,this.props.image);return jsxRuntimeExports.jsxs("div",{className:"perseus-widget perseus-widget-measurer "+"graphie-container blank-background",style:{width:this.props.box[0],height:this.props.box[1]},children:[image.url&&jsxRuntimeExports.jsx("div",{style:{position:"relative",top:image.top,left:image.left},children:jsxRuntimeExports.jsx(SvgImage,{src:image.url,allowZoom:false})}),jsxRuntimeExports.jsx("div",{className:"graphie",ref:"graphieDiv"})]})}constructor(...args){super(...args),this.isWidget=true,this.state={};}}Measurer.defaultProps={box:[480,480],image:defaultImage,showProtractor:true,protractorX:7.5,protractorY:.5,showRuler:false,rulerLabel:"",rulerTicks:10,rulerPixels:40,rulerLength:10};var Measurer$1 = {name:"measurer",displayName:"Measurer",hidden:true,widget:Measurer,version:measurerLogic.version};
2036
2036
 
2037
- function drawText(ctx,item){if(item.value===null){return}ctx.fillStyle=styles$6.fgColor;ctx.font=styles$6.font;ctx.fillText(item.value,item.pos[0]-styles$6.fontSizePx/2+1,item.pos[1]+styles$6.fontSizePx/2);}function drawDoubleLine(ctx,item){let path=new Path2D;ctx.lineWidth=5*styles$6.lineWidth;ctx.strokeStyle=styles$6.fgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);path=new Path2D;ctx.lineWidth=3*styles$6.lineWidth;ctx.strokeStyle=styles$6.bgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);}function drawTripleLine(ctx,item){let path=new Path2D;ctx.lineWidth=7*styles$6.lineWidth;ctx.strokeStyle=styles$6.fgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);path=new Path2D;ctx.lineWidth=5*styles$6.lineWidth;ctx.strokeStyle=styles$6.bgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);drawLine(ctx,item);}function drawLine(ctx,item){const path=new Path2D;ctx.lineWidth=styles$6.lineWidth;ctx.strokeStyle=styles$6.fgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);}const drawingFuncs={text:drawText,"line:single":drawLine,"line:double":drawDoubleLine,"line:triple":drawTripleLine};function drawItem(ctx){return function(item){drawingFuncs[item.type](ctx,item);}}const ordering={"line:single":0,"line:double":0,"line:triple":0,text:1};function compareElements(item0,item1){return ordering[item0.type]-ordering[item1.type]}function draw(ctx,items){items.sort(compareElements).forEach(drawItem(ctx));}const styles$6={bgColor:"rgb(255, 255, 255)",fgColor:"rgb(0, 0, 0)",fontSizePx:12,lineWidth:1,font:"12px sans"};
2037
+ function drawText(ctx,item){if(item.value===null){return}ctx.fillStyle=styles$7.fgColor;ctx.font=styles$7.font;ctx.fillText(item.value,item.pos[0]-styles$7.fontSizePx/2+1,item.pos[1]+styles$7.fontSizePx/2);}function drawDoubleLine(ctx,item){let path=new Path2D;ctx.lineWidth=5*styles$7.lineWidth;ctx.strokeStyle=styles$7.fgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);path=new Path2D;ctx.lineWidth=3*styles$7.lineWidth;ctx.strokeStyle=styles$7.bgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);}function drawTripleLine(ctx,item){let path=new Path2D;ctx.lineWidth=7*styles$7.lineWidth;ctx.strokeStyle=styles$7.fgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);path=new Path2D;ctx.lineWidth=5*styles$7.lineWidth;ctx.strokeStyle=styles$7.bgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);drawLine(ctx,item);}function drawLine(ctx,item){const path=new Path2D;ctx.lineWidth=styles$7.lineWidth;ctx.strokeStyle=styles$7.fgColor;path.moveTo(item.startPos[0],item.startPos[1]);path.lineTo(item.endPos[0],item.endPos[1]);ctx.stroke(path);}const drawingFuncs={text:drawText,"line:single":drawLine,"line:double":drawDoubleLine,"line:triple":drawTripleLine};function drawItem(ctx){return function(item){drawingFuncs[item.type](ctx,item);}}const ordering={"line:single":0,"line:double":0,"line:triple":0,text:1};function compareElements(item0,item1){return ordering[item0.type]-ordering[item1.type]}function draw(ctx,items){items.sort(compareElements).forEach(drawItem(ctx));}const styles$7={bgColor:"rgb(255, 255, 255)",fgColor:"rgb(0, 0, 0)",fontSizePx:12,lineWidth:1,font:"12px sans"};
2038
2038
 
2039
2039
  const bondLength=30;function polarAdd(origin,angle,length){const x=origin[0];const y=origin[1];return [x+Math.cos(angle*2*Math.PI/360)*length,y+-1*Math.sin(angle*2*Math.PI/360)*length]}function atomLayout(atom,atoms,bonds,rotationAngle){let textValue=atom.symbol;if(textValue==="C"&&Object.keys(atoms).length!==1){textValue=null;}if(atom.idx==="1,0"){const pos=[0,0];atom.pos=pos;atom.baseAngle=-30+rotationAngle;return {type:"text",value:textValue,pos:pos,idx:atom.idx}}const prevPositionedAtom=atoms[atom.connections.find(function(c){return atoms[c].pos})];const myIndex=prevPositionedAtom.connections.indexOf(atom.idx);let baseAngleIncrement=60;let angleIncrement=120;if(prevPositionedAtom.connections.length===4){angleIncrement=90;baseAngleIncrement=90;}else if(bonds.find(bond=>bond.bondType==="triple"&&bond.to===atom.idx)||bonds.find(bond=>bond.bondType==="triple"&&bond.to===prevPositionedAtom.idx)){angleIncrement=0;baseAngleIncrement=0;}let angle=0;const idxPath=prevPositionedAtom.idx.split(":");const lastAtomIdx=idxPath[idxPath.length-1].split(",")[0];if(parseInt(lastAtomIdx)%2!==0){angle=prevPositionedAtom.baseAngle-(baseAngleIncrement-angleIncrement*myIndex);}else {angle=prevPositionedAtom.baseAngle+(baseAngleIncrement-angleIncrement*myIndex);}const pos=polarAdd(prevPositionedAtom.pos,angle,bondLength);atom.pos=pos;atom.baseAngle=angle;return {type:"text",value:textValue,pos:pos,idx:atom.idx}}function maybeShrinkLines(fromAtom,toAtom){const shrinkFactor=.25;let fromPos=[fromAtom.pos[0],fromAtom.pos[1]];let toPos=[toAtom.pos[0],toAtom.pos[1]];if(fromAtom.symbol!=="C"){fromPos=[toAtom.pos[0]-(1-shrinkFactor)*(toAtom.pos[0]-fromAtom.pos[0]),toAtom.pos[1]-(1-shrinkFactor)*(toAtom.pos[1]-fromAtom.pos[1])];}if(toAtom.symbol!=="C"){toPos=[fromAtom.pos[0]-(1-shrinkFactor)*(fromAtom.pos[0]-toAtom.pos[0]),fromAtom.pos[1]-(1-shrinkFactor)*(fromAtom.pos[1]-toAtom.pos[1])];}return [fromPos,toPos]}function bondLayout(bond,atoms){const fromAtom=atoms[bond.from];const toAtom=atoms[bond.to];const startAndEndPos=maybeShrinkLines(fromAtom,toAtom);return {type:"line:"+bond.bondType,startPos:startAndEndPos[0],endPos:startAndEndPos[1]}}function idxString(idx){return idx.join(":")}function convertTree(atoms,bonds,tree){if(tree===null){return [atoms,bonds]}if(tree.type==="atom"){const treeIdx=idxString(tree.idx);atoms[treeIdx]={idx:treeIdx,symbol:tree.symbol,connections:[]};if(tree.bonds){tree.bonds.forEach(function(b){const toIdx=idxString(b.to.idx);atoms[treeIdx].connections.push(toIdx);bonds.push({from:treeIdx,to:toIdx,bondType:b.bondType});convertTree(atoms,bonds,b.to);atoms[toIdx].connections.push(treeIdx);});}}return [atoms,bonds]}function atomLayoutHelper(outputs,atomProcessingQueue,atoms,bonds,rotationAngle){if(atomProcessingQueue.length===0){return outputs}const queuedAtomIdx=atomProcessingQueue.shift();const atom=atoms[queuedAtomIdx];atom.connections.forEach(function(c){if(!atoms[c].pos){atomProcessingQueue.push(c);}});return atomLayoutHelper(outputs.concat(atomLayout(atom,atoms,bonds,rotationAngle)),atomProcessingQueue,atoms,bonds,rotationAngle)}function bondLayoutHelper(outputs,atoms,bonds){if(bonds.length===0){return outputs}return bondLayoutHelper(outputs.concat(bondLayout(bonds[0],atoms)),atoms,bonds.slice(1))}function layout$1(tree,rotationAngle){const converted=convertTree({},[],tree);const atoms=converted[0];const bonds=converted[1];const outputs=atomLayoutHelper([],["1,0"],atoms,bonds,rotationAngle);return bondLayoutHelper(outputs,atoms,bonds)}var MoleculeLayout = {layout:layout$1};
2040
2040
 
@@ -2052,7 +2052,7 @@ class PlaceholderCard extends React.Component{render(){return jsxRuntimeExports.
2052
2052
 
2053
2053
  const getPromptJSON$4=()=>{return getUnsupportedPromptJSON("phet-simulation")};
2054
2054
 
2055
- const MOBILE_APP_BOTTOM_BAR_HEIGHT=66;class PhetSimulation extends React.Component{async componentDidMount(){await this.updateSimState(this.props.url);}async componentDidUpdate(prevProps){if(prevProps.url!==this.props.url){await this.updateSimState(this.props.url);}}getLocale(){switch(this.context.locale){case "pt-pt":return "pt";case "zh-hans":return "zh_CN";case "zh-hant":return "zh_TW";case "fa-af":return "fa_DA";default:return this.context.locale}}getPromptJSON(){return getPromptJSON$4()}async updateSimState(urlString){const url=makeSafeUrl(urlString,this.getLocale(),"https://phet.colorado.edu");if(url===null){this.displayLoadFailure();return}const response=await fetch(url);if(!response.ok){this.displayLoadFailure();return}const showLocaleWarning=await this.showLocaleWarning(url);this.setState({url:url,banner:showLocaleWarning?{message:this.context.strings.simulationLocaleWarning,kind:"warning"}:null});}async showLocaleWarning(url){if(!url){return false}const phetRegex=/https:\/\/phet\.colorado\.edu\/sims\/html\/([a-zA-Z0-9-]+)\/.*/g;const match=phetRegex.exec(url.toString());if(match===null){return false}const simName=match[1];const response=await fetch(`https://phet.colorado.edu/sims/html/${simName}/latest/string-map.json`);if(!response.ok){return false}let responseJson;try{responseJson=await response.json();}catch{return false}const locales=Object.keys(responseJson);const baseLocale=this.getLocale().split("_")[0];for(const l of locales){if(baseLocale===l.split("_")[0]){return false}}return true}render(){const{isFullScreen,banner,url}=this.state;const{isMobileApp}=this.props.apiOptions;const isMobileAppFullscreen=isFullScreen&&isMobileApp;const containerStyle=isMobileAppFullscreen?{...styles$5.appFullScreenWidgetContainer}:styles$5.widgetContainer;const iframeContainerStyle=isMobileAppFullscreen?styles$5.appFullScreenIframeContainer:styles$5.iframeContainer;const sandboxProperties="allow-same-origin allow-scripts";return jsxRuntimeExports.jsxs(View,{style:containerStyle,children:[banner!==null&&jsxRuntimeExports.jsx(View,{style:{marginBottom:phoneMargin},children:jsxRuntimeExports.jsx(Banner,{kind:banner.kind,text:banner.message})}),isMobileAppFullscreen&&jsxRuntimeExports.jsx(View,{style:styles$5.closeButtonContainer,children:jsxRuntimeExports.jsx(IconButton,{icon:xIcon,onClick:this.toggleFullScreen,kind:"tertiary",actionType:"neutral","aria-label":"Exit fullscreen",style:styles$5.closeButton})}),jsxRuntimeExports.jsx(View,{style:iframeContainerStyle,children:jsxRuntimeExports.jsx("iframe",{ref:this.iframeRef,title:this.props.description,sandbox:sandboxProperties,className:css(styles$5.iframeResponsive),src:url?.toString(),allow:"fullscreen"})}),url!==null&&!isMobileAppFullscreen&&jsxRuntimeExports.jsx(IconButton,{icon:cornersOutIcon,onClick:isMobileApp?this.toggleFullScreen:()=>{this.iframeRef.current?.requestFullscreen();},kind:"tertiary",actionType:"neutral","aria-label":"Fullscreen",style:{marginTop:5,marginBottom:5,alignSelf:"flex-end"}})]})}constructor(...args){super(...args),this.iframeRef=React.createRef(),this.isWidget=true,this.state={url:null,banner:null,isFullScreen:false},this.displayLoadFailure=()=>{this.setState({url:null,banner:{message:this.context.strings.simulationLoadFail,kind:"critical"}});},this.toggleFullScreen=()=>{this.setState(prevState=>({isFullScreen:!prevState.isFullScreen}));};}}PhetSimulation.contextType=PerseusI18nContext;const styles$5=StyleSheet.create({widgetContainer:{borderRadius:6,borderWidth:1,borderColor:"#CCC",padding:spacing.medium_16,paddingBottom:0},iframeContainer:{position:"relative",overflow:"hidden",width:"100%",paddingTop:"56.25%"},iframeResponsive:{borderWidth:0,position:"absolute",top:0,left:0,bottom:0,right:0,width:"100%",height:"100%"},appFullScreenWidgetContainer:{position:"fixed",top:0,left:0,right:0,bottom:MOBILE_APP_BOTTOM_BAR_HEIGHT,width:"100%",height:"auto",zIndex:1e3,backgroundColor:"white",display:"flex",flexDirection:"column"},appFullScreenIframeContainer:{position:"relative",overflow:"hidden",width:"100%",flex:1},closeButtonContainer:{position:"absolute",top:spacing.xSmall_8,right:spacing.xSmall_8,zIndex:1001},closeButton:{backgroundColor:"rgba(255, 255, 255, 0.8)",borderRadius:"50%"}});var PhetSimulation$1 = {name:"phet-simulation",displayName:"PhET Simulation",widget:PhetSimulation,isLintable:true};
2055
+ const MOBILE_APP_BOTTOM_BAR_HEIGHT=66;class PhetSimulation extends React.Component{async componentDidMount(){await this.updateSimState(this.props.url);}async componentDidUpdate(prevProps){if(prevProps.url!==this.props.url){await this.updateSimState(this.props.url);}}getLocale(){switch(this.context.locale){case "pt-pt":return "pt";case "zh-hans":return "zh_CN";case "zh-hant":return "zh_TW";case "fa-af":return "fa_DA";default:return this.context.locale}}getPromptJSON(){return getPromptJSON$4()}async updateSimState(urlString){const url=makeSafeUrl(urlString,this.getLocale(),"https://phet.colorado.edu");if(url===null){this.displayLoadFailure();return}const response=await fetch(url);if(!response.ok){this.displayLoadFailure();return}const showLocaleWarning=await this.showLocaleWarning(url);this.setState({url:url,banner:showLocaleWarning?{message:this.context.strings.simulationLocaleWarning,kind:"warning"}:null});}async showLocaleWarning(url){if(!url){return false}const phetRegex=/https:\/\/phet\.colorado\.edu\/sims\/html\/([a-zA-Z0-9-]+)\/.*/g;const match=phetRegex.exec(url.toString());if(match===null){return false}const simName=match[1];const response=await fetch(`https://phet.colorado.edu/sims/html/${simName}/latest/string-map.json`);if(!response.ok){return false}let responseJson;try{responseJson=await response.json();}catch{return false}const locales=Object.keys(responseJson);const baseLocale=this.getLocale().split("_")[0];for(const l of locales){if(baseLocale===l.split("_")[0]){return false}}return true}render(){const{isFullScreen,banner,url}=this.state;const{isMobileApp}=this.props.apiOptions;const isMobileAppFullscreen=isFullScreen&&isMobileApp;const containerStyle=isMobileAppFullscreen?{...styles$6.appFullScreenWidgetContainer}:styles$6.widgetContainer;const iframeContainerStyle=isMobileAppFullscreen?styles$6.appFullScreenIframeContainer:styles$6.iframeContainer;const sandboxProperties="allow-same-origin allow-scripts";return jsxRuntimeExports.jsxs(View,{style:containerStyle,children:[banner!==null&&jsxRuntimeExports.jsx(View,{style:{marginBottom:phoneMargin},children:jsxRuntimeExports.jsx(Banner,{kind:banner.kind,text:banner.message})}),isMobileAppFullscreen&&jsxRuntimeExports.jsx(View,{style:styles$6.closeButtonContainer,children:jsxRuntimeExports.jsx(IconButton,{icon:xIcon,onClick:this.toggleFullScreen,kind:"tertiary",actionType:"neutral","aria-label":"Exit fullscreen",style:styles$6.closeButton})}),jsxRuntimeExports.jsx(View,{style:iframeContainerStyle,children:jsxRuntimeExports.jsx("iframe",{ref:this.iframeRef,title:this.props.description,sandbox:sandboxProperties,className:css(styles$6.iframeResponsive),src:url?.toString(),allow:"fullscreen"})}),url!==null&&!isMobileAppFullscreen&&jsxRuntimeExports.jsx(IconButton,{icon:cornersOutIcon,onClick:isMobileApp?this.toggleFullScreen:()=>{this.iframeRef.current?.requestFullscreen();},kind:"tertiary",actionType:"neutral","aria-label":"Fullscreen",style:{marginTop:5,marginBottom:5,alignSelf:"flex-end"}})]})}constructor(...args){super(...args),this.iframeRef=React.createRef(),this.isWidget=true,this.state={url:null,banner:null,isFullScreen:false},this.displayLoadFailure=()=>{this.setState({url:null,banner:{message:this.context.strings.simulationLoadFail,kind:"critical"}});},this.toggleFullScreen=()=>{this.setState(prevState=>({isFullScreen:!prevState.isFullScreen}));};}}PhetSimulation.contextType=PerseusI18nContext;const styles$6=StyleSheet.create({widgetContainer:{borderRadius:6,borderWidth:1,borderColor:"#CCC",padding:spacing.medium_16,paddingBottom:0},iframeContainer:{position:"relative",overflow:"hidden",width:"100%",paddingTop:"56.25%"},iframeResponsive:{borderWidth:0,position:"absolute",top:0,left:0,bottom:0,right:0,width:"100%",height:"100%"},appFullScreenWidgetContainer:{position:"fixed",top:0,left:0,right:0,bottom:MOBILE_APP_BOTTOM_BAR_HEIGHT,width:"100%",height:"auto",zIndex:1e3,backgroundColor:"white",display:"flex",flexDirection:"column"},appFullScreenIframeContainer:{position:"relative",overflow:"hidden",width:"100%",flex:1},closeButtonContainer:{position:"absolute",top:spacing.xSmall_8,right:spacing.xSmall_8,zIndex:1001},closeButton:{backgroundColor:"rgba(255, 255, 255, 0.8)",borderRadius:"50%"}});var PhetSimulation$1 = {name:"phet-simulation",displayName:"PhET Simulation",widget:PhetSimulation,isLintable:true};
2056
2056
 
2057
2057
  const getPromptJSON$3=()=>{return getUnsupportedPromptJSON("plotter")};
2058
2058
 
@@ -2060,7 +2060,7 @@ const plotterDefaults=CoreWidgetRegistry.getDefaultWidgetOptions("plotter");clas
2060
2060
 
2061
2061
  const getPromptJSON$2=()=>{return getUnsupportedPromptJSON("python-program")};
2062
2062
 
2063
- function getUrlFromProgramID(programID){return `/python-program/${programID}/embedded`}class PythonProgram extends React.Component{getPromptJSON(){return getPromptJSON$2()}render(){let url=getUrlFromProgramID(this.props.programID);url=this.props.dependencies.generateUrl({url,context:"python_program:program_url",kaLocale:this.context?.locale});const iframeStyle={height:this.props.height,width:"100%"};const sandboxOptions=["allow-popups","allow-same-origin","allow-scripts","allow-top-navigation"].join(" ");return jsxRuntimeExports.jsx(View,{style:styles$4.container,children:jsxRuntimeExports.jsx("iframe",{title:this.context.strings.pythonProgram,sandbox:sandboxOptions,src:url,style:iframeStyle,allowFullScreen:true})})}}PythonProgram.contextType=PerseusI18nContext;PythonProgram.defaultProps={height:400};const styles$4=StyleSheet.create({container:{margin:"auto",width:"100%"}});const WrappedPythonProgram=withDependencies(PythonProgram);var PythonProgram$1 = {name:"python-program",displayName:"Python Program",widget:WrappedPythonProgram};
2063
+ function getUrlFromProgramID(programID){return `/python-program/${programID}/embedded`}class PythonProgram extends React.Component{getPromptJSON(){return getPromptJSON$2()}render(){let url=getUrlFromProgramID(this.props.programID);url=this.props.dependencies.generateUrl({url,context:"python_program:program_url",kaLocale:this.context?.locale});const iframeStyle={height:this.props.height,width:"100%"};const sandboxOptions=["allow-popups","allow-same-origin","allow-scripts","allow-top-navigation"].join(" ");return jsxRuntimeExports.jsx(View,{style:styles$5.container,children:jsxRuntimeExports.jsx("iframe",{title:this.context.strings.pythonProgram,sandbox:sandboxOptions,src:url,style:iframeStyle,allowFullScreen:true})})}}PythonProgram.contextType=PerseusI18nContext;PythonProgram.defaultProps={height:400};const styles$5=StyleSheet.create({container:{margin:"auto",width:"100%"}});const WrappedPythonProgram=withDependencies(PythonProgram);var PythonProgram$1 = {name:"python-program",displayName:"Python Program",widget:WrappedPythonProgram};
2064
2064
 
2065
2065
  const getPromptJSON$1=userInput=>{return {type:"sorter",userInput:{values:userInput.options,changed:userInput.changed}}};
2066
2066
 
@@ -2070,15 +2070,17 @@ const{assert}=InteractiveUtil;function getInputPath(row,column){return [""+row,"
2070
2070
 
2071
2071
  const getPromptJSON=()=>{return getUnsupportedPromptJSON("video")};
2072
2072
 
2073
- const IS_URL$1=/^https?:\/\//;const getYoutubeId=url=>{const regExp=/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;const match=url.match(regExp);if(match&&match[7].length===11){return match[7]}return "videoNotFound"};const VideoTranscriptLink=props=>{const{location}=props;const{useVideo}=useDependencies();const[id,kind]=IS_URL$1.test(location)?[getYoutubeId(location),"YOUTUBE_ID"]:[location,"READABLE_ID"];const result=useVideo(id,kind);const{strings}=usePerseusI18n();switch(result.status){case "loading":return jsxRuntimeExports.jsx(View,{children:strings.loading});case "success":{const video=result.data?.video;return jsxRuntimeExports.jsxs(View,{style:styles$3.transcriptLink,children:[jsxRuntimeExports.jsx(Text$2,{children:video?.title}),jsxRuntimeExports.jsx(Strut,{size:10}),jsxRuntimeExports.jsx(Link,{href:"/transcript/"+(video?.contentId||"videoNotFound"),target:"_blank",className:"visited-no-recolor",children:strings.videoTranscript})]})}case "error":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});case "aborted":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});default:return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong})}};const styles$3=StyleSheet.create({transcriptLink:{flexDirection:"row",width:"100%",justifyContent:"center"}});
2073
+ const IS_URL$1=/^https?:\/\//;const getYoutubeId=url=>{const regExp=/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;const match=url.match(regExp);if(match&&match[7].length===11){return match[7]}return "videoNotFound"};const VideoTranscriptLink=props=>{const{location}=props;const{useVideo}=useDependencies();const[id,kind]=IS_URL$1.test(location)?[getYoutubeId(location),"YOUTUBE_ID"]:[location,"READABLE_ID"];const result=useVideo(id,kind);const{strings}=usePerseusI18n();switch(result.status){case "loading":return jsxRuntimeExports.jsx(View,{children:strings.loading});case "success":{const video=result.data?.video;return jsxRuntimeExports.jsxs(View,{style:styles$4.transcriptLink,children:[jsxRuntimeExports.jsx(Text$2,{children:video?.title}),jsxRuntimeExports.jsx(Strut,{size:10}),jsxRuntimeExports.jsx(Link,{href:"/transcript/"+(video?.contentId||"videoNotFound"),target:"_blank",className:"visited-no-recolor",children:strings.videoTranscript})]})}case "error":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});case "aborted":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});default:return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong})}};const styles$4=StyleSheet.create({transcriptLink:{flexDirection:"row",width:"100%",justifyContent:"center"}});
2074
2074
 
2075
- const DEFAULT_WIDTH=1280;const DEFAULT_HEIGHT=720;const KA_EMBED="{host}/embed_video?slug={slug}"+"&internal_video_only=1";const IS_URL=/^https?:\/\//;const IS_KA_SITE=/(khanacademy\.org|localhost)/;const IS_VIMEO=/(vimeo\.com)/;class Video extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"video",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON()}render(){const{InitialRequestUrl}=getDependencies();const location=this.props.location;if(!location){return jsxRuntimeExports.jsx("div",{})}let url;if(IS_URL.test(location)){url=location;if(IS_VIMEO.test(url)){if(url.indexOf("?")===-1){url+="?dnt=1";}else {url+="&dnt=1";}}}else {url=KA_EMBED.replace("{slug}",location);let embedHostname="https://www.khanacademy.org";if(IS_KA_SITE.test(InitialRequestUrl.host)){embedHostname=InitialRequestUrl.origin;}url=url.replace("{host}",embedHostname);}url=this.props.dependencies.generateUrl({url,context:"video:video_url",kaLocale:this.context.locale});return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(FixedToResponsive,{width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,children:jsxRuntimeExports.jsx("iframe",{title:this.context.strings.videoWrapper,className:"perseus-video-widget",sandbox:"allow-same-origin allow-scripts",width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,src:url,allowFullScreen:true,allow:"autoplay"})},location+this.props.alignment),jsxRuntimeExports.jsx(VideoTranscriptLink,{location:location})]})}constructor(...args){super(...args),this.isWidget=true;}}Video.contextType=PerseusI18nContext;const WrappedVideo=withDependencies(Video);var Video$1 = {name:"video",displayName:"Video",widget:WrappedVideo};
2075
+ var styles$3 = {"perseusVideoWidget":"perseus_gxXDcWBe","perseusVideoFixedToResponsive":"perseus_5hjlD7xq"};
2076
+
2077
+ const DEFAULT_WIDTH=1280;const DEFAULT_HEIGHT=720;const KA_EMBED="{host}/embed_video?slug={slug}"+"&internal_video_only=1";const IS_URL=/^https?:\/\//;const IS_KA_SITE=/(khanacademy\.org|localhost)/;const IS_VIMEO=/(vimeo\.com)/;class Video extends React.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"video",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON()}render(){const{InitialRequestUrl}=getDependencies();const location=this.props.location;if(!location){return jsxRuntimeExports.jsx("div",{})}let url;if(IS_URL.test(location)){url=location;if(IS_VIMEO.test(url)){if(url.indexOf("?")===-1){url+="?dnt=1";}else {url+="&dnt=1";}}}else {url=KA_EMBED.replace("{slug}",location);let embedHostname="https://www.khanacademy.org";if(IS_KA_SITE.test(InitialRequestUrl.host)){embedHostname=InitialRequestUrl.origin;}url=url.replace("{host}",embedHostname);}url=this.props.dependencies.generateUrl({url,context:"video:video_url",kaLocale:this.context.locale});return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(FixedToResponsive,{className:styles$3.perseusVideoFixedToResponsive,width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,children:jsxRuntimeExports.jsx("iframe",{title:this.context.strings.videoWrapper,className:styles$3.perseusVideoWidget,sandbox:"allow-same-origin allow-scripts",width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,src:url,allowFullScreen:true,allow:"autoplay"})},location),jsxRuntimeExports.jsx(VideoTranscriptLink,{location:location})]})}constructor(...args){super(...args),this.isWidget=true;}}Video.contextType=PerseusI18nContext;const WrappedVideo=withDependencies(Video);var Video$1 = {name:"video",displayName:"Video",widget:WrappedVideo};
2076
2078
 
2077
2079
  var extraWidgets = [CSProgram$1,Categorizer$1,Definition$1,DeprecatedStandin$1,Dropdown$1,Explanation$1,FreeResponse$1,GradedGroup$1,GradedGroupSet$1,Grapher$1,Group$1,Iframe$1,Image$1,Interactive,InteractiveGraph$1,LabelImage$1,Matcher$1,Matrix$1,Measurer$1,Molecule$1,NumberLine$1,Orderer$1,PhetSimulation$1,Plotter$1,PythonProgram$1,Sorter$1,Table$1,Video$1];
2078
2080
 
2079
2081
  const init=function(){registerWidgets(basicWidgets);registerWidgets(extraWidgets);replaceDeprecatedWidgets();};
2080
2082
 
2081
- const libName="@khanacademy/perseus";const libVersion="78.0.0";addLibraryVersionToPerseusDebug(libName,libVersion);
2083
+ const libName="@khanacademy/perseus";const libVersion="78.0.1";addLibraryVersionToPerseusDebug(libName,libVersion);
2082
2084
 
2083
2085
  const apiVersion={major:12,minor:0};
2084
2086