@khanacademy/perseus-editor 26.0.0 → 26.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
2
2
  import * as React from 'react';
3
3
  import React__default, { useId, createElement, useState, useRef, useEffect } from 'react';
4
- import { components, Widgets, iconTrash, excludeDenylistKeys, PerseusMarkdown, Util, preprocessTex, Log, ApiOptions, ClassNames, usePerseusI18n, Renderer, Categorizer as Categorizer$1, Changeable, EditorJsonify, Dependencies, Expression, interactiveSizes, GrapherWidget, GrapherUtil, containerSizeClass, getInteractiveBoxFromSizeClass, iconChevronDown, KhanColors, mathOnlyParser, getAngleCoords, getPolygonCoords, getPointCoords, getQuadraticCoords, getSinusoidCoords, getCircleCoords, getLinearSystemCoords, getSegmentCoords, getLineCoords, InteractiveGraphWidget, bodyXsmallBold, MatrixWidget, makeSafeUrl, PlotterWidget, BaseRadio, TableWidget, widgets } from '@khanacademy/perseus';
4
+ import { components, Widgets, iconTrash, excludeDenylistKeys, PerseusMarkdown, Util, preprocessTex, Log, ApiOptions, ClassNames, usePerseusI18n, Renderer, Categorizer as Categorizer$1, Changeable, EditorJsonify, Dependencies, Expression, interactiveSizes, GrapherWidget, GrapherUtil, containerSizeClass, getInteractiveBoxFromSizeClass, iconChevronDown, KhanColors, mathOnlyParser, getAngleCoords, getPolygonCoords, getPointCoords, getQuadraticCoords, getSinusoidCoords, getCircleCoords, getLinearSystemCoords, getSegmentCoords, getLineCoords, InteractiveGraphWidget, bodyXsmallBold, MatrixWidget, makeSafeUrl, PlotterWidget, TableWidget, widgets } from '@khanacademy/perseus';
5
5
  export { widgets } from '@khanacademy/perseus';
6
6
  import { CoreWidgetRegistry, applyDefaultsToWidget, PerseusError, Errors, ItemExtras, categorizerLogic, csProgramLogic, definitionLogic, dropdownLogic, explanationLogic, expressionLogic, deriveExtraKeys, PerseusExpressionAnswerFormConsidered, freeResponseLogic, gradedGroupLogic, gradedGroupSetLogic, grapherLogic, GrapherUtil as GrapherUtil$1, groupLogic, iframeLogic, imageLogic, inputNumberLogic, interactionLogic, lockedFigureColors, lockedFigureFillStyles, interactiveGraphLogic, labelImageLogic, matcherLogic, matrixLogic, getMatrixSize, measurerLogic, numberLineLogic, numericInputLogic, ordererLogic, passageLogic, passageRefLogic, passageRefTargetLogic, phetSimulationLogic, plotterLogic, plotterPlotTypes, pythonProgramLogic, radioLogic, deriveNumCorrect, sorterLogic, tableLogic, videoLogic } from '@khanacademy/perseus-core';
7
7
  import _ from 'underscore';
8
8
  import Clickable from '@khanacademy/wonder-blocks-clickable';
9
- import { color, spacing, sizing, semanticColor, font } from '@khanacademy/wonder-blocks-tokens';
9
+ import { color, spacing, semanticColor, sizing, font, border } from '@khanacademy/wonder-blocks-tokens';
10
10
  import { StyleSheet, css } from 'aphrodite';
11
11
  import $ from 'jquery';
12
12
  import katex from 'katex';
@@ -20,7 +20,7 @@ import classNames from 'classnames';
20
20
  import * as PerseusLinter from '@khanacademy/perseus-linter';
21
21
  import iconPass from '@phosphor-icons/core/fill/check-circle-fill.svg';
22
22
  import iconWarning from '@phosphor-icons/core/fill/warning-fill.svg';
23
- import { LabelSmall, LabelLarge, LabelMedium, HeadingSmall, HeadingXSmall, Caption, LabelXSmall, BodyMonospace } from '@khanacademy/wonder-blocks-typography';
23
+ import { LabelSmall, LabelLarge, LabelMedium, HeadingSmall, HeadingXSmall, Caption, LabelXSmall, BodyMonospace, Footnote } from '@khanacademy/wonder-blocks-typography';
24
24
  import { AccordionSection } from '@khanacademy/wonder-blocks-accordion';
25
25
  import { Checkbox as Checkbox$1, TextField, LabeledTextField, TextArea } from '@khanacademy/wonder-blocks-form';
26
26
  import { StatefulKeypadContextProvider, KeypadContext } from '@khanacademy/keypad-context';
@@ -57,8 +57,10 @@ import minusCircle from '@phosphor-icons/core/regular/minus-circle.svg';
57
57
  import arrowCounterClockwise from '@phosphor-icons/core/bold/arrow-counter-clockwise-bold.svg';
58
58
  import Link$1 from '@khanacademy/wonder-blocks-link';
59
59
  import plusIcon from '@phosphor-icons/core/bold/plus-bold.svg';
60
+ import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
61
+ import minusCircleIcon from '@phosphor-icons/core/bold/minus-circle-bold.svg';
60
62
 
61
- const libName="@khanacademy/perseus-editor";const libVersion="26.0.0";addLibraryVersionToPerseusDebug(libName,libVersion);
63
+ const libName="@khanacademy/perseus-editor";const libVersion="26.1.0";addLibraryVersionToPerseusDebug(libName,libVersion);
62
64
 
63
65
  var jsxRuntime = {exports: {}};
64
66
 
@@ -1410,7 +1412,7 @@ const SCREEN_SIZES={phone:{width:320,height:480,framedWidth:320},tablet:{width:7
1410
1412
 
1411
1413
  class JsonEditor extends React.Component{getInitialState(){return {currentValue:JSON.stringify(this.props.value,null,4),valid:true}}UNSAFE_componentWillReceiveProps(nextProps){const shouldReplaceContent=!this.state.valid||!_.isEqual(nextProps.value,JSON.parse(this.state.currentValue?this.state.currentValue:""));if(shouldReplaceContent){this.setState(this.getInitialState());}}handleKeyDown(e){if(e.key==="Tab"){const cursorPos=e.target.selectionStart;const v=e.target.value;const textBefore=v.substring(0,cursorPos);const textAfter=v.substring(cursorPos,v.length);e.target.value=textBefore+" "+textAfter;e.target.selectionStart=textBefore.length+4;e.target.selectionEnd=textBefore.length+4;e.preventDefault();this.handleChange(e);}}handleChange(e){const nextString=e.target.value;try{let json=JSON.parse(nextString);if(_.isString(json)){json=JSON.parse(json);}this.setState({currentValue:nextString,valid:true},function(){this.props.onChange(json);});}catch{this.setState({currentValue:nextString,valid:false});}}handleBlur(e){const nextString=e.target.value;try{let json=JSON.parse(nextString);if(_.isString(json)){json=JSON.parse(json);}this.setState({currentValue:JSON.stringify(json,null,4),valid:true},function(){this.props.onChange(json);});}catch{this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}render(){const classes="perseus-json-editor "+(this.state.valid?"valid":"invalid");return jsxRuntimeExports.jsx("textarea",{className:classes,value:this.state.currentValue,onChange:this.handleChange,onKeyDown:this.handleKeyDown,onBlur:this.handleBlur})}constructor(props){super(props);this.state=this.getInitialState();this.handleBlur=this.handleBlur.bind(this);this.handleChange=this.handleChange.bind(this);this.handleKeyDown=this.handleKeyDown.bind(this);}}JsonEditor.defaultProps={value:{}};
1412
1414
 
1413
- const{InlineIcon: InlineIcon$7}=components;class SectionControlButton extends React.Component{render(){const{icon,onClick,title}=this.props;return jsxRuntimeExports.jsx(Clickable,{className:"section-control-button "+"simple-button "+"simple-button--small ",onClick:e=>{e.preventDefault();onClick();},role:"button",hideDefaultFocusRing:true,"aria-label":title,style:styles$T.button,children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(InlineIcon$7,{...icon})})}}const styles$T=StyleSheet.create({button:{backgroundColor:color.gold,margin:2,paddingRight:10,paddingLeft:10,paddingBottom:2}});
1415
+ const{InlineIcon: InlineIcon$7}=components;class SectionControlButton extends React.Component{render(){const{icon,onClick,title}=this.props;return jsxRuntimeExports.jsx(Clickable,{className:"section-control-button "+"simple-button "+"simple-button--small ",onClick:e=>{e.preventDefault();onClick();},role:"button",hideDefaultFocusRing:true,"aria-label":title,style:styles$U.button,children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(InlineIcon$7,{...icon})})}}const styles$U=StyleSheet.create({button:{backgroundColor:color.gold,margin:2,paddingRight:10,paddingLeft:10,paddingBottom:2}});
1414
1416
 
1415
1417
  const chemParse=function(tokens,stateMachine){let str="";let expectedLoc=tokens[tokens.length-1].loc.start;for(let i=tokens.length-1;i>=0;i--){if(tokens[i].loc.start>expectedLoc){str+=" ";expectedLoc=tokens[i].loc.start;}str+=tokens[i].text;expectedLoc+=tokens[i].text.length;}const tex=texify.go(mhchemParser.go(str,stateMachine));return tex};var mhchemParser={go:function(input,stateMachine){if(!input){return []}if(stateMachine===undefined){stateMachine="ce";}let state="0";const buffer={};buffer["parenthesisLevel"]=0;input=input.replace(/\n/g," ");input=input.replace(/[\u2212\u2013\u2014\u2010]/g,"-");input=input.replace(/[\u2026]/g,"...");let lastInput;let watchdog=10;const output=[];while(true){if(lastInput!==input){watchdog=10;lastInput=input;}else {watchdog--;}const machine=mhchemParser.stateMachines[stateMachine];const t=machine.transitions[state]||machine.transitions["*"];iterateTransitions:for(let i=0;i<t.length;i++){const matches=mhchemParser.patterns.match_(t[i].pattern,input);if(matches){const task=t[i].task;for(let iA=0;iA<task.action_.length;iA++){var o;if(machine.actions[task.action_[iA].type_]){o=machine.actions[task.action_[iA].type_](buffer,matches.match_,task.action_[iA].option);}else if(mhchemParser.actions[task.action_[iA].type_]){o=mhchemParser.actions[task.action_[iA].type_](buffer,matches.match_,task.action_[iA].option);}else {throw ["MhchemBugA","mhchem bug A. Please report. ("+task.action_[iA].type_+")"]}mhchemParser.concatArray(output,o);}state=task.nextState||state;if(input.length>0){if(!task.revisit){input=matches.remainder;}if(!task.toContinue){break iterateTransitions}}else {return output}}}if(watchdog<=0){throw ["MhchemBugU","mhchem bug U. Please report."]}}},concatArray:function(a,b){if(b){if(Array.isArray(b)){for(let iB=0;iB<b.length;iB++){a.push(b[iB]);}}else {a.push(b);}}},patterns:{patterns:{empty:/^$/,else:/^./,else2:/^./,space:/^\s/,"space A":/^\s(?=[A-Z\\$])/,space$:/^\s$/,"a-z":/^[a-z]/,x:/^x/,x$:/^x$/,i$:/^i$/,letters:/^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/,"\\greek":/^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/,"one lowercase latin letter $":/^(?:([a-z])(?:$|[^a-zA-Z]))$/,"$one lowercase latin letter$ $":/^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,"one lowercase greek letter $":/^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/,digits:/^[0-9]+/,"-9.,9":/^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,"-9.,9 no missing 0":/^[+\-]?[0-9]+(?:[.,][0-9]+)?/,"(-)(9.,9)(e)(99)":function(input){const m=input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:([eE]|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/);if(m&&m[0]){return {match_:m.splice(1),remainder:input.substr(m[0].length)}}return null},"(-)(9)^(-9)":function(input){const m=input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);if(m&&m[0]){return {match_:m.splice(1),remainder:input.substr(m[0].length)}}return null},"state of aggregation $":function(input){const a=mhchemParser.patterns.findObserveGroups(input,"",/^\([a-z]{1,3}(?=[\),])/,")","");if(a&&a.remainder.match(/^($|[\s,;\)\]\}])/)){return a}const m=input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/);if(m){return {match_:m[0],remainder:input.substr(m[0].length)}}return null},"_{(state of aggregation)}$":/^_\{(\([a-z]{1,3}\))\}/,"{[(":/^(?:\\\{|\[|\()/,")]}":/^(?:\)|\]|\\\})/,", ":/^[,;]\s*/,",":/^[,;]/,".":/^[.]/,". ":/^([.\u22C5\u00B7\u2022])\s*/,"...":/^\.\.\.(?=$|[^.])/,"* ":/^([*])\s*/,"^{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^{","","","}")},"^($...$)":function(input){return mhchemParser.patterns.findObserveGroups(input,"^","$","$","")},"^a":/^\^([0-9]+|[^\\_])/,"^\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"^\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^",/^\\[a-zA-Z]+\{/,"}","")},"^\\x":/^\^(\\[a-zA-Z]+)\s*/,"^(-1)":/^\^(-?\d+)/,"'":/^'/,"_{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_{","","","}")},"_($...$)":function(input){return mhchemParser.patterns.findObserveGroups(input,"_","$","$","")},_9:/^_([+\-]?[0-9]+|[^\\])/,"_\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"_\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_",/^\\[a-zA-Z]+\{/,"}","")},"_\\x":/^_(\\[a-zA-Z]+)\s*/,"^_":/^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,"{}":/^\{\}/,"{...}":function(input){return mhchemParser.patterns.findObserveGroups(input,"","{","}","")},"{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"{","","","}")},"$...$":function(input){return mhchemParser.patterns.findObserveGroups(input,"","$","$","")},"${(...)}$":function(input){return mhchemParser.patterns.findObserveGroups(input,"${","","","}$")},"$(...)$":function(input){return mhchemParser.patterns.findObserveGroups(input,"$","","","$")},"=<>":/^[=<>]/,"#":/^[#\u2261]/,"+":/^\+/,"-$":/^-(?=[\s_},;\]/]|$|\([a-z]+\))/,"-9":/^-(?=[0-9])/,"- orbital overlap":/^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,"-":/^-/,"pm-operator":/^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,operator:/^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,arrowUpDown:/^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,"\\bond{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\bond{","","","}")},"->":/^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,CMT:/^[CMT](?=\[)/,"[(...)]":function(input){return mhchemParser.patterns.findObserveGroups(input,"[","","","]")},"1st-level escape":/^(&|\\\\|\\hline)\s*/,"\\,":/^(?:\\[,\ ;:])/,"\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"",/^\\[a-zA-Z]+\{/,"}","")},"\\ca":/^\\ca(?:\s+|(?![a-zA-Z]))/,"\\x":/^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,orbital:/^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,others:/^[\/~|]/,"\\frac{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\frac{","","","}","{","","","}")},"\\overset{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\overset{","","","}","{","","","}")},"\\underset{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\underset{","","","}","{","","","}")},"\\underbrace{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\underbrace{","","","}_","{","","","}")},"\\color{(...)}0":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color{","","","}")},"\\color{(...)}{(...)}1":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color{","","","}","{","","","}")},"\\color(...){(...)}2":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color","\\","",/^(?=\{)/,"{","","","}")},"\\ce{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\ce{","","","}")},oxidation$:/^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"d-oxidation$":/^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"roman numeral":/^[IVX]+/,"1/2$":/^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,amount:function(input){let match;match=input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}const a=mhchemParser.patterns.findObserveGroups(input,"","$","$","");if(a){match=a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}}return null},amount2:function(input){return this["amount"](input)},"(KV letters),":/^(?:[A-Z][a-z]{0,2}|i)(?=,)/,formula$:function(input){if(input.match(/^\([a-z]+\)$/)){return null}const match=input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}return null},uprightEntities:/^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,"/":/^\s*(\/)\s*/,"//":/^\s*(\/\/)\s*/,"*":/^\s*[*.]\s*/},findObserveGroups:function(input,begExcl,begIncl,endIncl,endExcl,beg2Excl,beg2Incl,end2Incl,end2Excl,combine){const _match=function(input,pattern){if(typeof pattern==="string"){if(input.indexOf(pattern)!==0){return null}return pattern}const match=input.match(pattern);if(!match){return null}return match[0]};const _findObserveGroups=function(input,i,endChars){let braces=0;while(i<input.length){const a=input.charAt(i);const match=_match(input.substr(i),endChars);if(match!==null&&braces===0){return {endMatchBegin:i,endMatchEnd:i+match.length}}if(a==="{"){braces++;}else if(a==="}"){if(braces===0){throw ["ExtraCloseMissingOpen","Extra close brace or missing open brace"]}else {braces--;}}i++;}if(braces>0){return null}return null};let match=_match(input,begExcl);if(match===null){return null}input=input.substr(match.length);match=_match(input,begIncl);if(match===null){return null}const e=_findObserveGroups(input,match.length,endIncl||endExcl);if(e===null){return null}const match1=input.substring(0,endIncl?e.endMatchEnd:e.endMatchBegin);if(!(beg2Excl||beg2Incl)){return {match_:match1,remainder:input.substr(e.endMatchEnd)}}const group2=this.findObserveGroups(input.substr(e.endMatchEnd),beg2Excl,beg2Incl,end2Incl,end2Excl);if(group2===null){return null}const matchRet=[match1,group2.match_];return {match_:combine?matchRet.join(""):matchRet,remainder:group2.remainder}},match_:function(m,input){const pattern=mhchemParser.patterns.patterns[m];if(pattern===undefined){throw ["MhchemBugP","mhchem bug P. Please report. ("+m+")"]}else if(typeof pattern==="function"){return mhchemParser.patterns.patterns[m](input)}else {const match=input.match(pattern);if(match){let mm;if(match[2]){mm=[match[1],match[2]];}else if(match[1]){mm=match[1];}else {mm=match[0];}return {match_:mm,remainder:input.substr(match[0].length)}}return null}}},actions:{"a=":function(buffer,m){buffer.a=(buffer.a||"")+m;},"b=":function(buffer,m){buffer.b=(buffer.b||"")+m;},"p=":function(buffer,m){buffer.p=(buffer.p||"")+m;},"o=":function(buffer,m){buffer.o=(buffer.o||"")+m;},"q=":function(buffer,m){buffer.q=(buffer.q||"")+m;},"d=":function(buffer,m){buffer.d=(buffer.d||"")+m;},"rm=":function(buffer,m){buffer.rm=(buffer.rm||"")+m;},"text=":function(buffer,m){buffer.text_=(buffer.text_||"")+m;},insert:function(buffer,m,a){return {type_:a}},"insert+p1":function(buffer,m,a){return {type_:a,p1:m}},"insert+p1+p2":function(buffer,m,a){return {type_:a,p1:m[0],p2:m[1]}},copy:function(buffer,m){return m},rm:function(buffer,m){return {type_:"rm",p1:m||""}},text:function(buffer,m){return mhchemParser.go(m,"text")},"{text}":function(buffer,m){const ret=["{"];mhchemParser.concatArray(ret,mhchemParser.go(m,"text"));ret.push("}");return ret},"tex-math":function(buffer,m){return mhchemParser.go(m,"tex-math")},"tex-math tight":function(buffer,m){return mhchemParser.go(m,"tex-math tight")},bond:function(buffer,m,k){return {type_:"bond",kind_:k||m}},"color0-output":function(buffer,m){return {type_:"color0",color:m[0]}},ce:function(buffer,m){return mhchemParser.go(m)},"1/2":function(buffer,m){const ret=[];if(m.match(/^[+\-]/)){ret.push(m.substr(0,1));m=m.substr(1);}const n=m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);n[1]=n[1].replace(/\$/g,"");ret.push({type_:"frac",p1:n[1],p2:n[2]});if(n[3]){n[3]=n[3].replace(/\$/g,"");ret.push({type_:"tex-math",p1:n[3]});}return ret},"9,9":function(buffer,m){return mhchemParser.go(m,"9,9")}},createTransitions:function(o){let pattern;let state;let stateArray;let i;const transitions={};for(pattern in o){for(state in o[pattern]){stateArray=state.split("|");o[pattern][state].stateArray=stateArray;for(i=0;i<stateArray.length;i++){transitions[stateArray[i]]=[];}}}for(pattern in o){for(state in o[pattern]){stateArray=o[pattern][state].stateArray||[];for(i=0;i<stateArray.length;i++){const p=o[pattern][state];if(p.action_){p.action_=[].concat(p.action_);for(let k=0;k<p.action_.length;k++){if(typeof p.action_[k]==="string"){p.action_[k]={type_:p.action_[k]};}}}else {p.action_=[];}const patternArray=pattern.split("|");for(let j=0;j<patternArray.length;j++){if(stateArray[i]==="*"){for(const t in transitions){transitions[t].push({pattern:patternArray[j],task:p});}}else {transitions[stateArray[i]].push({pattern:patternArray[j],task:p});}}}}}return transitions},stateMachines:{}};mhchemParser.stateMachines={ce:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},else:{"0|1|2":{action_:"beginsWithBond=false",revisit:true,toContinue:true}},oxidation$:{0:{action_:"oxidation-output"}},CMT:{r:{action_:"rdt=",nextState:"rt"},rd:{action_:"rqt=",nextState:"rdt"}},arrowUpDown:{"0|1|2|as":{action_:["sb=false","output","operator"],nextState:"1"}},uprightEntities:{"0|1|2":{action_:["o=","output"],nextState:"1"}},orbital:{"0|1|2|3":{action_:"o=",nextState:"o"}},"->":{"0|1|2|3":{action_:"r=",nextState:"r"},"a|as":{action_:["output","r="],nextState:"r"},"*":{action_:["output","r="],nextState:"r"}},"+":{o:{action_:"d= kv",nextState:"d"},"d|D":{action_:"d=",nextState:"d"},q:{action_:"d=",nextState:"qd"},"qd|qD":{action_:"d=",nextState:"qd"},dq:{action_:["output","d="],nextState:"d"},3:{action_:["sb=false","output","operator"],nextState:"0"}},amount:{"0|2":{action_:"a=",nextState:"a"}},"pm-operator":{"0|1|2|a|as":{action_:["sb=false","output",{type_:"operator",option:"\\pm"}],nextState:"0"}},operator:{"0|1|2|a|as":{action_:["sb=false","output","operator"],nextState:"0"}},"-$":{"o|q":{action_:["charge or bond","output"],nextState:"qd"},d:{action_:"d=",nextState:"d"},D:{action_:["output",{type_:"bond",option:"-"}],nextState:"3"},q:{action_:"d=",nextState:"qd"},qd:{action_:"d=",nextState:"qd"},"qD|dq":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},"-9":{"3|o":{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"3"}},"- orbital overlap":{o:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},d:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"}},"-":{"0|1|2":{action_:[{type_:"output",option:1},"beginsWithBond=true",{type_:"bond",option:"-"}],nextState:"3"},3:{action_:{type_:"bond",option:"-"}},a:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},as:{action_:[{type_:"output",option:2},{type_:"bond",option:"-"}],nextState:"3"},b:{action_:"b="},o:{action_:{type_:"- after o/d",option:false},nextState:"2"},q:{action_:{type_:"- after o/d",option:false},nextState:"2"},"d|qd|dq":{action_:{type_:"- after o/d",option:true},nextState:"2"},"D|qD|p":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},amount2:{"1|3":{action_:"a=",nextState:"a"}},letters:{"0|1|2|3|a|as|b|p|bp|o":{action_:"o=",nextState:"o"},"q|dq":{action_:["output","o="],nextState:"o"},"d|D|qd|qD":{action_:"o after d",nextState:"o"}},digits:{o:{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},q:{action_:["output","o="],nextState:"o"},a:{action_:"o=",nextState:"o"}},"space A":{"b|p|bp":{}},space:{a:{nextState:"as"},0:{action_:"sb=false"},"1|2":{action_:"sb=true"},"r|rt|rd|rdt|rdq":{action_:"output",nextState:"0"},"*":{action_:["output","sb=true"],nextState:"1"}},"1st-level escape":{"1|2":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}]},"*":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}],nextState:"0"}},"[(...)]":{"r|rt":{action_:"rd=",nextState:"rd"},"rd|rdt":{action_:"rq=",nextState:"rdq"}},"...":{"o|d|D|dq|qd|qD":{action_:["output",{type_:"bond",option:"..."}],nextState:"3"},"*":{action_:[{type_:"output",option:1},{type_:"insert",option:"ellipsis"}],nextState:"1"}},". |* ":{"*":{action_:["output",{type_:"insert",option:"addition compound"}],nextState:"1"}},"state of aggregation $":{"*":{action_:["output","state of aggregation"],nextState:"1"}},"{[(":{"a|as|o":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"0|1|2|3":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"*":{action_:["output","o=","output","parenthesisLevel++"],nextState:"2"}},")]}":{"0|1|2|3|b|p|bp|o":{action_:["o=","parenthesisLevel--"],nextState:"o"},"a|as|d|D|q|qd|qD|dq":{action_:["output","o=","parenthesisLevel--"],nextState:"o"}},", ":{"*":{action_:["output","comma"],nextState:"0"}},"^_":{"*":{}},"^{(...)}|^($...$)":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"D"},q:{action_:"d=",nextState:"qD"},"d|D|qd|qD|dq":{action_:["output","d="],nextState:"D"}},"^a|^\\x{}{}|^\\x{}|^\\x|'":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"d"},q:{action_:"d=",nextState:"qd"},"d|qd|D|qD":{action_:"d="},dq:{action_:["output","d="],nextState:"d"}},"_{(state of aggregation)}$":{"d|D|q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x":{"0|1|2|as":{action_:"p=",nextState:"p"},b:{action_:"p=",nextState:"bp"},"3|o":{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},"q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"=<>":{"0|1|2|3|a|as|o|q|d|D|qd|qD|dq":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"#":{"0|1|2|3|a|as|o":{action_:[{type_:"output",option:2},{type_:"bond",option:"#"}],nextState:"3"}},"{}":{"*":{action_:{type_:"output",option:1},nextState:"1"}},"{...}":{"0|1|2|3|a|as|b|p|bp":{action_:"o=",nextState:"o"},"o|d|D|q|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"$...$":{a:{action_:"a="},"0|1|2|3|as|b|p|bp|o":{action_:"o=",nextState:"o"},"as|o":{action_:"o="},"q|d|D|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"\\bond{(...)}":{"*":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"\\frac{(...)}":{"*":{action_:[{type_:"output",option:1},"frac-output"],nextState:"3"}},"\\overset{(...)}":{"*":{action_:[{type_:"output",option:2},"overset-output"],nextState:"3"}},"\\underset{(...)}":{"*":{action_:[{type_:"output",option:2},"underset-output"],nextState:"3"}},"\\underbrace{(...)}":{"*":{action_:[{type_:"output",option:2},"underbrace-output"],nextState:"3"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:[{type_:"output",option:2},"color-output"],nextState:"3"}},"\\color{(...)}0":{"*":{action_:[{type_:"output",option:2},"color0-output"]}},"\\ce{(...)}":{"*":{action_:[{type_:"output",option:2},"ce"],nextState:"3"}},"\\,":{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"1"}},"\\x{}{}|\\x{}|\\x":{"0|1|2|3|a|as|b|p|bp|o|c0":{action_:["o=","output"],nextState:"3"},"*":{action_:["output","o=","output"],nextState:"3"}},others:{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"3"}},else2:{a:{action_:"a to o",nextState:"o",revisit:true},as:{action_:["output","sb=true"],nextState:"1",revisit:true},"r|rt|rd|rdt|rdq":{action_:["output"],nextState:"0",revisit:true},"*":{action_:["output","copy"],nextState:"3"}}}),actions:{"o after d":function(buffer,m){let ret;if((buffer.d||"").match(/^[0-9]+$/)){const tmp=buffer.d;buffer.d=undefined;ret=this["output"](buffer);buffer.b=tmp;}else {ret=this["output"](buffer);}mhchemParser.actions["o="](buffer,m);return ret},"d= kv":function(buffer,m){buffer.d=m;buffer.dType="kv";},"charge or bond":function(buffer,m){if(buffer["beginsWithBond"]){const ret=[];mhchemParser.concatArray(ret,this["output"](buffer));mhchemParser.concatArray(ret,mhchemParser.actions["bond"](buffer,m,"-"));return ret}buffer.d=m;},"- after o/d":function(buffer,m,isAfterD){let c1=mhchemParser.patterns.match_("orbital",buffer.o||"");const c2=mhchemParser.patterns.match_("one lowercase greek letter $",buffer.o||"");const c3=mhchemParser.patterns.match_("one lowercase latin letter $",buffer.o||"");const c4=mhchemParser.patterns.match_("$one lowercase latin letter$ $",buffer.o||"");const hyphenFollows=m==="-"&&(c1&&c1.remainder===""||c2||c3||c4);if(hyphenFollows&&!buffer.a&&!buffer.b&&!buffer.p&&!buffer.d&&!buffer.q&&!c1&&c3){buffer.o="$"+buffer.o+"$";}const ret=[];if(hyphenFollows){mhchemParser.concatArray(ret,this["output"](buffer));ret.push({type_:"hyphen"});}else {c1=mhchemParser.patterns.match_("digits",buffer.d||"");if(isAfterD&&c1&&c1.remainder===""){mhchemParser.concatArray(ret,mhchemParser.actions["d="](buffer,m));mhchemParser.concatArray(ret,this["output"](buffer));}else {mhchemParser.concatArray(ret,this["output"](buffer));mhchemParser.concatArray(ret,mhchemParser.actions["bond"](buffer,m,"-"));}}return ret},"a to o":function(buffer){buffer.o=buffer.a;buffer.a=undefined;},"sb=true":function(buffer){buffer.sb=true;},"sb=false":function(buffer){buffer.sb=false;},"beginsWithBond=true":function(buffer){buffer["beginsWithBond"]=true;},"beginsWithBond=false":function(buffer){buffer["beginsWithBond"]=false;},"parenthesisLevel++":function(buffer){buffer["parenthesisLevel"]++;},"parenthesisLevel--":function(buffer){buffer["parenthesisLevel"]--;},"state of aggregation":function(buffer,m){return {type_:"state of aggregation",p1:mhchemParser.go(m,"o")}},comma:function(buffer,m){const a=m.replace(/\s*$/,"");const withSpace=a!==m;if(withSpace&&buffer["parenthesisLevel"]===0){return {type_:"comma enumeration L",p1:a}}return {type_:"comma enumeration M",p1:a}},output:function(buffer,m,entityFollows){let ret;if(!buffer.r){ret=[];if(!buffer.a&&!buffer.b&&!buffer.p&&!buffer.o&&!buffer.q&&!buffer.d&&!entityFollows);else {if(buffer.sb){ret.push({type_:"entitySkip"});}if(!buffer.o&&!buffer.q&&!buffer.d&&!buffer.b&&!buffer.p&&entityFollows!==2){buffer.o=buffer.a;buffer.a=undefined;}else if(!buffer.o&&!buffer.q&&!buffer.d&&(buffer.b||buffer.p)){buffer.o=buffer.a;buffer.d=buffer.b;buffer.q=buffer.p;buffer.a=buffer.b=buffer.p=undefined;}else {if(buffer.o&&buffer.dType==="kv"&&mhchemParser.patterns.match_("d-oxidation$",buffer.d||"")){buffer.dType="oxidation";}else if(buffer.o&&buffer.dType==="kv"&&!buffer.q){buffer.dType=undefined;}}ret.push({type_:"chemfive",a:mhchemParser.go(buffer.a,"a"),b:mhchemParser.go(buffer.b,"bd"),p:mhchemParser.go(buffer.p,"pq"),o:mhchemParser.go(buffer.o,"o"),q:mhchemParser.go(buffer.q,"pq"),d:mhchemParser.go(buffer.d,buffer.dType==="oxidation"?"oxidation":"bd"),dType:buffer.dType});}}else {let rd;if(buffer.rdt==="M"){rd=mhchemParser.go(buffer.rd,"tex-math");}else if(buffer.rdt==="T"){rd=[{type_:"text",p1:buffer.rd||""}];}else {rd=mhchemParser.go(buffer.rd);}let rq;if(buffer.rqt==="M"){rq=mhchemParser.go(buffer.rq,"tex-math");}else if(buffer.rqt==="T"){rq=[{type_:"text",p1:buffer.rq||""}];}else {rq=mhchemParser.go(buffer.rq);}ret={type_:"arrow",r:buffer.r,rd:rd,rq:rq};}for(const p in buffer){if(p!=="parenthesisLevel"&&p!=="beginsWithBond"){delete buffer[p];}}return ret},"oxidation-output":function(buffer,m){const ret=["{"];mhchemParser.concatArray(ret,mhchemParser.go(m,"oxidation"));ret.push("}");return ret},"frac-output":function(buffer,m){return {type_:"frac-ce",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"overset-output":function(buffer,m){return {type_:"overset",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"underset-output":function(buffer,m){return {type_:"underset",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"underbrace-output":function(buffer,m){return {type_:"underbrace",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1])}},"r=":function(buffer,m){buffer.r=m;},"rdt=":function(buffer,m){buffer.rdt=m;},"rd=":function(buffer,m){buffer.rd=m;},"rqt=":function(buffer,m){buffer.rqt=m;},"rq=":function(buffer,m){buffer.rq=m;},operator:function(buffer,m,p1){return {type_:"operator",kind_:p1||m}}}},a:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:true}},"$(...)$":{"*":{action_:"tex-math tight",nextState:"1"}},",":{"*":{action_:{type_:"insert",option:"commaDecimal"}}},else2:{"*":{action_:"copy"}}}),actions:{}},o:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:true}},letters:{"*":{action_:"rm"}},"\\ca":{"*":{action_:{type_:"insert",option:"circa"}}},"\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"{text}"}},else2:{"*":{action_:"copy"}}}),actions:{}},text:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"{...}":{"*":{action_:"text="}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"\\greek":{"*":{action_:["output","rm"]}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:["output","copy"]}},else:{"*":{action_:"text="}}}),actions:{output:function(buffer){if(buffer.text_){const ret={type_:"text",p1:buffer.text_};for(const p in buffer){delete buffer[p];}return ret}}}},pq:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"state of aggregation $":{"*":{action_:"state of aggregation"}},i$:{0:{nextState:"!f",revisit:true}},"(KV letters),":{0:{action_:"rm",nextState:"0"}},formula$:{0:{nextState:"f",revisit:true}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"!f",revisit:true}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"a-z":{f:{action_:"tex-math"}},letters:{"*":{action_:"rm"}},"-9.,9":{"*":{action_:"9,9"}},",":{"*":{action_:{type_:"insert+p1",option:"comma enumeration S"}}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"state of aggregation":function(buffer,m){return {type_:"state of aggregation subscript",p1:mhchemParser.go(m,"o")}},"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1],"pq")}}}},bd:{transitions:mhchemParser.createTransitions({empty:{"*":{}},x$:{0:{nextState:"!f",revisit:true}},formula$:{0:{nextState:"f",revisit:true}},else:{0:{nextState:"!f",revisit:true}},"-9.,9 no missing 0":{"*":{action_:"9,9"}},".":{"*":{action_:{type_:"insert",option:"electron dot"}}},"a-z":{f:{action_:"tex-math"}},x:{"*":{action_:{type_:"insert",option:"KV x"}}},letters:{"*":{action_:"rm"}},"'":{"*":{action_:{type_:"insert",option:"prime"}}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1],"bd")}}}},oxidation:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"roman numeral":{"*":{action_:"roman-numeral"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},else:{"*":{action_:"copy"}}}),actions:{"roman-numeral":function(buffer,m){return {type_:"roman numeral",p1:m||""}}}},"tex-math":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},else:{"*":{action_:"o="}}}),actions:{output:function(buffer){if(buffer.o){const ret={type_:"tex-math",p1:buffer.o};for(const p in buffer){delete buffer[p];}return ret}}}},"tex-math tight":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},"-|+":{"*":{action_:"tight operator"}},else:{"*":{action_:"o="}}}),actions:{"tight operator":function(buffer,m){buffer.o=(buffer.o||"")+"{"+m+"}";},output:function(buffer){if(buffer.o){const ret={type_:"tex-math",p1:buffer.o};for(const p in buffer){delete buffer[p];}return ret}}}},"9,9":{transitions:mhchemParser.createTransitions({empty:{"*":{}},",":{"*":{action_:"comma"}},else:{"*":{action_:"copy"}}}),actions:{comma:function(){return {type_:"commaDecimal"}}}},pu:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},space$:{"*":{action_:["output","space"]}},"{[(|)]}":{"0|a":{action_:"copy"}},"(-)(9)^(-9)":{0:{action_:"number^",nextState:"a"}},"(-)(9.,9)(e)(99)":{0:{action_:"enumber",nextState:"a"}},space:{"0|a":{}},"pm-operator":{"0|a":{action_:{type_:"operator",option:"\\pm"},nextState:"0"}},operator:{"0|a":{action_:"copy",nextState:"0"}},"//":{d:{action_:"o=",nextState:"/"}},"/":{d:{action_:"o=",nextState:"/"}},"{...}|else":{"0|d":{action_:"d=",nextState:"d"},a:{action_:["space","d="],nextState:"d"},"/|q":{action_:"q=",nextState:"q"}}}),actions:{enumber:function(buffer,m){const ret=[];if(m[0]==="+-"||m[0]==="+/-"){ret.push("\\pm ");}else if(m[0]){ret.push(m[0]);}if(m[1]){mhchemParser.concatArray(ret,mhchemParser.go(m[1],"pu-9,9"));if(m[2]){if(m[2].match(/[,.]/)){mhchemParser.concatArray(ret,mhchemParser.go(m[2],"pu-9,9"));}else {ret.push(m[2]);}}m[3]=m[4]||m[3];if(m[3]){m[3]=m[3].trim();if(m[3]==="e"||m[3].substr(0,1)==="*"){ret.push({type_:"cdot"});}else {ret.push({type_:"times"});}}}if(m[3]){ret.push("10^{"+m[5]+"}");}return ret},"number^":function(buffer,m){const ret=[];if(m[0]==="+-"||m[0]==="+/-"){ret.push("\\pm ");}else if(m[0]){ret.push(m[0]);}mhchemParser.concatArray(ret,mhchemParser.go(m[1],"pu-9,9"));ret.push("^{"+m[2]+"}");return ret},operator:function(buffer,m,p1){return {type_:"operator",kind_:p1||m}},space:function(){return {type_:"pu-space-1"}},output:function(buffer){let ret;const md=mhchemParser.patterns.match_("{(...)}",buffer.d||"");if(md&&md.remainder===""){buffer.d=md.match_;}const mq=mhchemParser.patterns.match_("{(...)}",buffer.q||"");if(mq&&mq.remainder===""){buffer.q=mq.match_;}if(buffer.d){buffer.d=buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C");buffer.d=buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");}if(buffer.q){buffer.q=buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C");buffer.q=buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");const b5={d:mhchemParser.go(buffer.d,"pu"),q:mhchemParser.go(buffer.q,"pu")};if(buffer.o==="//"){ret={type_:"pu-frac",p1:b5.d,p2:b5.q};}else {ret=b5.d;if(b5.d.length>1||b5.q.length>1){ret.push({type_:" / "});}else {ret.push({type_:"/"});}mhchemParser.concatArray(ret,b5.q);}}else {ret=mhchemParser.go(buffer.d,"pu-2");}for(const p in buffer){delete buffer[p];}return ret}}},"pu-2":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"*":{"*":{action_:["output","cdot"],nextState:"0"}},"\\x":{"*":{action_:"rm="}},space:{"*":{action_:["output","space"],nextState:"0"}},"^{(...)}|^(-1)":{1:{action_:"^(-1)"}},"-9.,9":{0:{action_:"rm=",nextState:"0"},1:{action_:"^(-1)",nextState:"0"}},"{...}|else":{"*":{action_:"rm=",nextState:"1"}}}),actions:{cdot:function(){return {type_:"tight cdot"}},"^(-1)":function(buffer,m){buffer.rm+="^{"+m+"}";},space:function(){return {type_:"pu-space-2"}},output:function(buffer){let ret=[];if(buffer.rm){const mrm=mhchemParser.patterns.match_("{(...)}",buffer.rm||"");if(mrm&&mrm.remainder===""){ret=mhchemParser.go(mrm.match_,"pu");}else {ret={type_:"rm",p1:buffer.rm};}}for(const p in buffer){delete buffer[p];}return ret}}},"pu-9,9":{transitions:mhchemParser.createTransitions({empty:{0:{action_:"output-0"},o:{action_:"output-o"}},",":{0:{action_:["output-0","comma"],nextState:"o"}},".":{0:{action_:["output-0","copy"],nextState:"o"}},else:{"*":{action_:"text="}}}),actions:{comma:function(){return {type_:"commaDecimal"}},"output-0":function(buffer){const ret=[];buffer.text_=buffer.text_||"";if(buffer.text_.length>4){let a=buffer.text_.length%3;if(a===0){a=3;}for(let i=buffer.text_.length-3;i>0;i-=3){ret.push(buffer.text_.substr(i,3));ret.push({type_:"1000 separator"});}ret.push(buffer.text_.substr(0,a));ret.reverse();}else {ret.push(buffer.text_);}for(const p in buffer){delete buffer[p];}return ret},"output-o":function(buffer){const ret=[];buffer.text_=buffer.text_||"";if(buffer.text_.length>4){const a=buffer.text_.length-3;for(var i=0;i<a;i+=3){ret.push(buffer.text_.substr(i,3));ret.push({type_:"1000 separator"});}ret.push(buffer.text_.substr(i));}else {ret.push(buffer.text_);}for(const p in buffer){delete buffer[p];}return ret}}}};var texify={go:function(input,isInner){if(!input){return ""}let res="";let cee=false;for(let i=0;i<input.length;i++){const inputi=input[i];if(typeof inputi==="string"){res+=inputi;}else {res+=texify._go2(inputi);if(inputi.type_==="1st-level escape"){cee=true;}}}if(!isInner&&!cee&&res){res="{"+res+"}";}return res},_goInner:function(input){if(!input){return input}return texify.go(input,true)},_go2:function(buf){let res;switch(buf.type_){case "chemfive":res="";var b5={a:texify._goInner(buf.a),b:texify._goInner(buf.b),p:texify._goInner(buf.p),o:texify._goInner(buf.o),q:texify._goInner(buf.q),d:texify._goInner(buf.d)};if(b5.a){if(b5.a.match(/^[+\-]/)){b5.a="{"+b5.a+"}";}res+=b5.a+"\\,";}if(b5.b||b5.p){res+="{\\vphantom{X}}";res+="^{\\hphantom{"+(b5.b||"")+"}}_{\\hphantom{"+(b5.p||"")+"}}";res+="{\\vphantom{X}}";res+="^{\\smash[t]{\\vphantom{2}}\\mathllap{"+(b5.b||"")+"}}";res+="_{\\vphantom{2}\\mathllap{\\smash[t]{"+(b5.p||"")+"}}}";}if(b5.o){if(b5.o.match(/^[+\-]/)){b5.o="{"+b5.o+"}";}res+=b5.o;}if(buf.dType==="kv"){if(b5.d||b5.q){res+="{\\vphantom{X}}";}if(b5.d){res+="^{"+b5.d+"}";}if(b5.q){res+="_{\\smash[t]{"+b5.q+"}}";}}else if(buf.dType==="oxidation"){if(b5.d){res+="{\\vphantom{X}}";res+="^{"+b5.d+"}";}if(b5.q){res+="{\\vphantom{X}}";res+="_{\\smash[t]{"+b5.q+"}}";}}else {if(b5.q){res+="{\\vphantom{X}}";res+="_{\\smash[t]{"+b5.q+"}}";}if(b5.d){res+="{\\vphantom{X}}";res+="^{"+b5.d+"}";}}break;case "rm":res="\\mathrm{"+buf.p1+"}";break;case "text":if(buf.p1.match(/[\^_]/)){buf.p1=buf.p1.replace(" ","~").replace("-","\\text{-}");res="\\mathrm{"+buf.p1+"}";}else {res="\\text{"+buf.p1+"}";}break;case "roman numeral":res="\\mathrm{"+buf.p1+"}";break;case "state of aggregation":res="\\mskip2mu "+texify._goInner(buf.p1);break;case "state of aggregation subscript":res="\\mskip1mu "+texify._goInner(buf.p1);break;case "bond":res=texify._getBond(buf.kind_);if(!res){throw ["MhchemErrorBond","mhchem Error. Unknown bond type ("+buf.kind_+")"]}break;case "frac":var c="\\frac{"+buf.p1+"}{"+buf.p2+"}";res="\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}";break;case "pu-frac":var d="\\frac{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";res="\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}";break;case "tex-math":res=buf.p1+" ";break;case "frac-ce":res="\\frac{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "overset":res="\\overset{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "underset":res="\\underset{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "underbrace":res="\\underbrace{"+texify._goInner(buf.p1)+"}_{"+texify._goInner(buf.p2)+"}";break;case "color":res="{\\color{"+buf.color1+"}{"+texify._goInner(buf.color2)+"}}";break;case "color0":res="\\color{"+buf.color+"}";break;case "arrow":var b6={rd:texify._goInner(buf.rd),rq:texify._goInner(buf.rq)};var arrow="\\x"+texify._getArrow(buf.r);if(b6.rq){arrow+="[{"+b6.rq+"}]";}if(b6.rd){arrow+="{"+b6.rd+"}";}else {arrow+="{}";}res=arrow;break;case "operator":res=texify._getOperator(buf.kind_);break;case "1st-level escape":res=buf.p1+" ";break;case "space":res=" ";break;case "entitySkip":res="~";break;case "pu-space-1":res="~";break;case "pu-space-2":res="\\mkern3mu ";break;case "1000 separator":res="\\mkern2mu ";break;case "commaDecimal":res="{,}";break;case "comma enumeration L":res="{"+buf.p1+"}\\mkern6mu ";break;case "comma enumeration M":res="{"+buf.p1+"}\\mkern3mu ";break;case "comma enumeration S":res="{"+buf.p1+"}\\mkern1mu ";break;case "hyphen":res="\\text{-}";break;case "addition compound":res="\\,{\\cdot}\\,";break;case "electron dot":res="\\mkern1mu \\bullet\\mkern1mu ";break;case "KV x":res="{\\times}";break;case "prime":res="\\prime ";break;case "cdot":res="\\cdot ";break;case "tight cdot":res="\\mkern1mu{\\cdot}\\mkern1mu ";break;case "times":res="\\times ";break;case "circa":res="{\\sim}";break;case "^":res="uparrow";break;case "v":res="downarrow";break;case "ellipsis":res="\\ldots ";break;case "/":res="/";break;case " / ":res="\\,/\\,";break;default:throw ["MhchemBugT","mhchem bug T. Please report."]}return res},_getArrow:function(a){switch(a){case "->":return "rightarrow";case "→":return "rightarrow";case "⟶":return "rightarrow";case "<-":return "leftarrow";case "<->":return "leftrightarrow";case "<-->":return "rightleftarrows";case "<=>":return "rightleftharpoons";case "⇌":return "rightleftharpoons";case "<=>>":return "rightequilibrium";case "<<=>":return "leftequilibrium";default:throw ["MhchemBugT","mhchem bug T. Please report."]}},_getBond:function(a){switch(a){case "-":return "{-}";case "1":return "{-}";case "=":return "{=}";case "2":return "{=}";case "#":return "{\\equiv}";case "3":return "{\\equiv}";case "~":return "{\\tripledash}";case "~-":return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";case "~=":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";case "~--":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";case "-~-":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";case "...":return "{{\\cdot}{\\cdot}{\\cdot}}";case "....":return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";case "->":return "{\\rightarrow}";case "<-":return "{\\leftarrow}";case "<":return "{<}";case ">":return "{>}";default:throw ["MhchemBugT","mhchem bug T. Please report."]}},_getOperator:function(a){switch(a){case "+":return " {}+{} ";case "-":return " {}-{} ";case "=":return " {}={} ";case "<":return " {}<{} ";case ">":return " {}>{} ";case "<<":return " {}\\ll{} ";case ">>":return " {}\\gg{} ";case "\\pm":return " {}\\pm{} ";case "\\approx":return " {}\\approx{} ";case "$\\approx$":return " {}\\approx{} ";case "v":return " \\downarrow{} ";case "(v)":return " \\downarrow{} ";case "^":return " \\uparrow{} ";case "(^)":return " \\uparrow{} ";default:throw ["MhchemBugT","mhchem bug T. Please report."]}}};
1416
1418
 
@@ -1418,13 +1420,13 @@ katex.__defineMacro("\\ce",function(context){return chemParse(context.consumeArg
1418
1420
 
1419
1421
  class DragTarget extends React.Component{handleDrop(e){e.stopPropagation();e.preventDefault();this.setState({dragHover:false});this.props.onDrop(e);}handleDragEnd(){this.setState({dragHover:false});}handleDragOver(e){e.preventDefault();}handleDragLeave(){this.setState({dragHover:false});}handleDragEnter(e){this.setState({dragHover:this.props.shouldDragHighlight(e)});}render(){const opacity=this.state.dragHover?{opacity:.3}:{};const{component:Component,shouldDragHighlight,...forwardProps}=this.props;return jsxRuntimeExports.jsx(Component,{...forwardProps,style:Object.assign({},this.props.style,opacity),onDrop:this.handleDrop,onDragEnd:this.handleDragEnd,onDragOver:this.handleDragOver,onDragEnter:this.handleDragEnter,onDragLeave:this.handleDragLeave})}constructor(props){super(props);this.state={dragHover:false};this.handleDrop=this.handleDrop.bind(this);this.handleDragEnd=this.handleDragEnd.bind(this);this.handleDragOver=this.handleDragOver.bind(this);this.handleDragLeave=this.handleDragLeave.bind(this);this.handleDragEnter=this.handleDragEnter.bind(this);}}DragTarget.defaultProps={component:"div",shouldDragHighlight:()=>true};
1420
1422
 
1421
- function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$S.expanded:styles$S.collapsed;return jsxRuntimeExports.jsx(PhosphorIcon,{icon:caretRight,style:iconStyle})}const styles$S=StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
1423
+ function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$T.expanded:styles$T.collapsed;return jsxRuntimeExports.jsx(PhosphorIcon,{icon:caretRight,style:iconStyle})}const styles$T=StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
1422
1424
 
1423
1425
  const _upgradeWidgetInfo=props=>{const filteredProps=excludeDenylistKeys(props);return applyDefaultsToWidget(filteredProps)};class WidgetEditor extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({widgetInfo:_upgradeWidgetInfo(nextProps)});if(nextProps.widgetIsOpen!=null&&nextProps.widgetIsOpen!==this.props.widgetIsOpen){this.setState({showWidget:nextProps.widgetIsOpen});}}render(){const widgetInfo=this.state.widgetInfo;const Ed=Widgets.getEditor(widgetInfo.type);let supportedAlignments;if(this.props.apiOptions.showAlignmentOptions){supportedAlignments=CoreWidgetRegistry.getSupportedAlignments(widgetInfo.type);}else {supportedAlignments=["default"];}const supportsStaticMode=Widgets.supportsStaticMode(widgetInfo.type);return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title "+(this.state.showWidget?"open":"closed"),children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:this._toggleWidget,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:this.state.showWidget}),jsxRuntimeExports.jsx("span",{children:this.props.id})]})}),supportsStaticMode&&jsxRuntimeExports.jsx(LabeledSwitch$1,{label:"Static",checked:!!widgetInfo.static,onChange:this._setStatic}),supportedAlignments.length>1&&jsxRuntimeExports.jsx("select",{className:"alignment",value:widgetInfo.alignment,onChange:this._handleAlignmentChange,children:supportedAlignments.map(alignment=>jsxRuntimeExports.jsx("option",{children:alignment},alignment))}),jsxRuntimeExports.jsx(SectionControlButton,{icon:iconTrash,onClick:()=>{this.props.onRemove();},title:"Remove image widget"})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-content "+(this.state.showWidget?"enter":"leave"),children:Ed&&jsxRuntimeExports.jsx(Ed,{ref:this.widget,onChange:this._handleWidgetChange,static:widgetInfo.static,apiOptions:this.props.apiOptions,...widgetInfo.options})})]})}constructor(props){super(props),this._toggleWidget=e=>{e.preventDefault();this.setState({showWidget:!this.state.showWidget});},this._handleWidgetChange=(newProps,cb,silent)=>{const newWidgetInfo={...this.state.widgetInfo,options:{...this.state.widgetInfo.options,...this.widget.current?.serialize()??{},...newProps}};this.props.onChange(newWidgetInfo,cb,silent);},this._setStatic=value=>{const newWidgetInfo={...this.state.widgetInfo,static:value};this.props.onChange(newWidgetInfo);},this._handleAlignmentChange=e=>{const newAlignment=e.currentTarget.value;const newWidgetInfo=Object.assign({},this.state.widgetInfo);newWidgetInfo.alignment=newAlignment;this.props.onChange(newWidgetInfo);},this.getSaveWarnings=()=>{const issuesFunc=this.widget.current?.getSaveWarnings;return issuesFunc?issuesFunc():[]},this.serialize=()=>{const widgetInfo=this.state.widgetInfo;return {type:widgetInfo.type,alignment:widgetInfo.alignment,static:widgetInfo.static,graded:widgetInfo.graded,options:this.widget.current.serialize(),version:widgetInfo.version}};this.state={showWidget:props.widgetIsOpen??true,widgetInfo:_upgradeWidgetInfo(props)};this.widget=React.createRef();}}function LabeledSwitch$1(props){const{label,...switchProps}=props;const id=useId();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("label",{htmlFor:id,children:label}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(Switch,{id:id,...switchProps})]})}
1424
1426
 
1425
1427
  class WidgetSelect extends React.Component{shouldComponentUpdate(){return false}render(){const widgets=Widgets.getPublicWidgets();const orderedWidgetNames=_.sortBy(_.keys(widgets),name=>{return widgets[name].displayName});const addWidgetString="Add a widget…";return jsxRuntimeExports.jsxs("select",{value:"",onChange:this.handleChange,"data-testid":"editor__widget-select",children:[jsxRuntimeExports.jsx("option",{value:"",children:addWidgetString}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),orderedWidgetNames.map(name=>{return jsxRuntimeExports.jsx("option",{value:name,children:widgets[name].displayName},name)})]})}constructor(...args){super(...args),this.handleChange=e=>{const widgetType=e.currentTarget.value;if(widgetType===""){return}if(this.props.onChange){this.props.onChange(widgetType);}};}}
1426
1428
 
1427
- class TexErrorView extends React.Component{render(){const{errorList}=this.props;const{showErrors}=this.state;return jsxRuntimeExports.jsxs(View,{style:styles$R.errorContainer,children:[jsxRuntimeExports.jsxs(View,{style:styles$R.title,onClick:this.handleToggleTexErrors,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showErrors}),"  TeX Errors (",errorList.length,")"]}),showErrors&&jsxRuntimeExports.jsx(View,{style:styles$R.errorExplanation,children:"If your math doesn't display correctly, these errors might help you troubleshoot. Message #content-kitchen for help."}),showErrors&&errorList.map((e,index)=>jsxRuntimeExports.jsxs(View,{style:styles$R.error,children:[jsxRuntimeExports.jsx(View,{style:{color:"red"},children:e.math}),jsxRuntimeExports.jsx(View,{children:e.message})]},index))]})}constructor(...args){super(...args),this.state={showErrors:false},this.handleToggleTexErrors=e=>{this.setState({showErrors:!this.state.showErrors});};}}const styles$R=StyleSheet.create({title:{backgroundColor:"#eee",fontSize:"1.25em",padding:"4px 10px",cursor:"pointer",display:"flex",flexDirection:"row",alignItems:"center"},errorContainer:{border:"1px solid #ddd",borderTop:"none"},errorExplanation:{padding:"4px 10px",backgroundColor:"pink"},error:{padding:"4px 10px"}});
1429
+ class TexErrorView extends React.Component{render(){const{errorList}=this.props;const{showErrors}=this.state;return jsxRuntimeExports.jsxs(View,{style:styles$S.errorContainer,children:[jsxRuntimeExports.jsxs(View,{style:styles$S.title,onClick:this.handleToggleTexErrors,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showErrors}),"  TeX Errors (",errorList.length,")"]}),showErrors&&jsxRuntimeExports.jsx(View,{style:styles$S.errorExplanation,children:"If your math doesn't display correctly, these errors might help you troubleshoot. Message #content-kitchen for help."}),showErrors&&errorList.map((e,index)=>jsxRuntimeExports.jsxs(View,{style:styles$S.error,children:[jsxRuntimeExports.jsx(View,{style:{color:"red"},children:e.math}),jsxRuntimeExports.jsx(View,{children:e.message})]},index))]})}constructor(...args){super(...args),this.state={showErrors:false},this.handleToggleTexErrors=e=>{this.setState({showErrors:!this.state.showErrors});};}}const styles$S=StyleSheet.create({title:{backgroundColor:"#eee",fontSize:"1.25em",padding:"4px 10px",cursor:"pointer",display:"flex",flexDirection:"row",alignItems:"center"},errorContainer:{border:"1px solid #ddd",borderTop:"none"},errorExplanation:{padding:"4px 10px",backgroundColor:"pink"},error:{padding:"4px 10px"}});
1428
1430
 
1429
1431
  const widgetPlaceholder="[[☃ {id}]]";const widgetRegExp="(\\[\\[☃ {id}\\]\\])";const rWidgetSplit=new RegExp(widgetRegExp.replace("{id}","[a-z-]+ [0-9]+"),"g");const shortcutRegexp=/^\[\[([a-z-]+)$/;const ENDS_WITH_A_PARAGRAPH=/(?:\n{2,}|^\n*)$/;const TRAILING_NEWLINES=/(\n*)$/;const LEADING_NEWLINES=/^(\n*)/;const commafyInteger=n=>{let str=n.toString();if(str.length>=5){str=str.replace(/(\d)(?=(\d{3})+$)/g,"$1{,}");}return str};const makeEndWithAParagraphIfNecessary=content=>{if(!ENDS_WITH_A_PARAGRAPH.test(content)){const match=TRAILING_NEWLINES.exec(content);if(match){const newlines=match[1];return content+"\n\n".slice(0,2-newlines.length)}}return content};const makeStartWithAParagraphAlways=content=>{const match=LEADING_NEWLINES.exec(content);if(!match){return content}const newlines=match[1];return "\n\n".slice(0,2-newlines.length)+content};const IMAGE_REGEX$1=/!\[[^\]]*\]\(([^\s)]+)[^)]*\)/g;const allMatches=function(regex,str){const result=[];while(true){const match=regex.exec(str);if(!match){break}result.push(match);}return result};const imageUrlsFromContent=function(content){return allMatches(IMAGE_REGEX$1,content).map(capture=>capture[1])};class Editor extends React.Component{componentDidMount(){this.lastUserValue=null;this._sizeImages(this.props);$(this.textarea.current).on("copy cut",this._maybeCopyWidgets).on("paste",this._maybePasteWidgets);}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.content!==nextProps.content){this.setState({textAreaValue:nextProps.content});}}componentDidUpdate(prevProps){const textarea=this.textarea.current;if(this.lastUserValue!=null&&textarea){textarea.focus();textarea.value=this.lastUserValue;textarea.selectionStart=0;textarea.setSelectionRange(0,prevProps.content.length);if(document.execCommand("insertText",false,this.props.content)===false){textarea.value=this.props.content;}this.lastUserValue=null;}if(this.props.content!==prevProps.content){this._sizeImages(this.props);}}componentWillUnmount(){clearTimeout(this.deferredChange);}getWidgetEditor(id,type){if(!Widgets.getEditor(type)){return}return createElement(WidgetEditor,{...this.props.widgets[id],ref:id,id:id,key:id,onChange:this._handleWidgetEditorChange.bind(this,id),onRemove:this._handleWidgetEditorRemove.bind(this,id),apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}render(){let pieces;let widgets;let underlayPieces;let widgetsDropDown;let templatesDropDown;let widgetsAndTemplates;let wordCountDisplay;const katexErrorList=[];if(this.props.showWordCount){const numChars=PerseusMarkdown.characterCount(this.props.content);const numWords=Math.floor(numChars/6);wordCountDisplay=jsxRuntimeExports.jsx("span",{className:"perseus-editor-word-count",title:"~"+commafyInteger(numWords)+" words ("+commafyInteger(numChars)+" characters)",children:commafyInteger(numWords)});}if(this.props.widgetEnabled){pieces=Util.split(this.props.content,rWidgetSplit);widgets={};underlayPieces=[];for(let i=0;i<pieces.length;i++){if(i%2===0){underlayPieces.push(pieces[i]);const ast=PerseusMarkdown.parse(pieces[i]);PerseusMarkdown.traverseContent(ast,node=>{if(node.type==="math"||node.type==="blockMath"){const content=preprocessTex(node.content);try{katex.renderToString(content,{colorIsTextColor:true});}catch(e){katexErrorList.push({math:content,message:e.message});}}});}else {const match=Util.rWidgetParts.exec(pieces[i]);if(match!=null){const id=match[1];const type=match[2];const duplicate=id in widgets;widgets[id]=this.getWidgetEditor(id,type);const classes=(duplicate||!widgets[id]?"error ":"")+("");const key=duplicate?i:id;underlayPieces.push(jsxRuntimeExports.jsx("b",{className:classes,children:pieces[i]},key));}}}this.widgetIds=_.keys(widgets);widgetsDropDown=jsxRuntimeExports.jsx(WidgetSelect,{onChange:this._addWidget});const insertTemplateString="Insert template…";templatesDropDown=jsxRuntimeExports.jsxs("select",{onChange:this.addTemplate,"data-testid":"editor__template-select",children:[jsxRuntimeExports.jsx("option",{value:"",children:insertTemplateString}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"table",children:"Table"}),jsxRuntimeExports.jsx("option",{value:"titledTable",children:"Titled table"}),jsxRuntimeExports.jsx("option",{value:"alignment",children:"Aligned equations"}),jsxRuntimeExports.jsx("option",{value:"piecewise",children:"Piecewise function"}),Object.keys(this.props.additionalTemplates).length>0&&jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),Object.entries(this.props.additionalTemplates).map(([key])=>jsxRuntimeExports.jsx("option",{value:key,children:key},key)),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"allWidgets",children:"All widgets (for testing)"})]});if(!this.props.immutableWidgets){const widgetNodes=Object.values(widgets);widgetsAndTemplates=jsxRuntimeExports.jsxs("div",{className:"perseus-editor-widgets",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-widgets-selectors",children:[widgetsDropDown,templatesDropDown,wordCountDisplay]}),widgetNodes]});wordCountDisplay=null;}}else {underlayPieces=[this.props.content];}underlayPieces.push(jsxRuntimeExports.jsx("br",{},"end"));const completeTextarea=[jsxRuntimeExports.jsx("div",{className:"perseus-textarea-underlay",ref:this.underlay,children:underlayPieces},"underlay"),jsxRuntimeExports.jsx("textarea",{ref:this.textarea,onChange:this.handleChange,onKeyDown:this._handleKeyDown,placeholder:this.props.placeholder,disabled:this.props.disabled,value:this.state.textAreaValue},"textarea")];let textareaWrapper;if(this.props.imageUploader){textareaWrapper=jsxRuntimeExports.jsx(DragTarget,{onDrop:this.handleDrop,className:"perseus-textarea-pair",children:completeTextarea});}else {textareaWrapper=jsxRuntimeExports.jsx("div",{className:"perseus-textarea-pair",children:completeTextarea});}const contentWithoutWidgets=this.props.content.replace(/\[\[\u2603 (([a-z-]+) ([0-9]+))\]\]/g,"");const noPrompt=contentWithoutWidgets.trim().length===0;const noWidgets=!/\[\[\u2603 (([a-z-]+) ([0-9]+))\]\]/g.test(this.props.content);const warningStyle={borderTop:"none",padding:4,backgroundColor:"pink"};return jsxRuntimeExports.jsxs("div",{className:"perseus-single-editor "+(this.props.className||""),children:[textareaWrapper,katexErrorList.length>0&&jsxRuntimeExports.jsx(TexErrorView,{errorList:katexErrorList}),this.props.warnNoPrompt&&noPrompt&&jsxRuntimeExports.jsx("div",{style:warningStyle,children:"Graded Groups should contain a prompt"}),this.props.warnNoWidgets&&noWidgets&&jsxRuntimeExports.jsx("div",{style:warningStyle,children:"Graded Groups should contain at least one widget"}),wordCountDisplay,widgetsAndTemplates]})}constructor(...args){super(...args),this.underlay=React.createRef(),this.textarea=React.createRef(),this.state={textAreaValue:this.props.content},this._handleWidgetEditorChange=(id,newWidgetInfo,cb,silent)=>{const widgets=Object.assign({},this.props.widgets);widgets[id]=Object.assign({},widgets[id],newWidgetInfo);this.props.onChange({widgets},cb,silent);},this._handleWidgetEditorRemove=id=>{if(!confirm("Are you sure you want to delete this item?")){return}const textarea=this.textarea.current;const re=new RegExp(widgetRegExp.replace("{id}",id),"gm");this.props.onChange({content:textarea?.value.replace(re,"")});},this._sizeImages=props=>{const imageUrls=imageUrlsFromContent(props.content);const images=_.pick(props.images,imageUrls);const newImageUrls=_.filter(imageUrls,url=>!images[url]);_.each(newImageUrls,url=>{Util.getImageSize(url,(width,height)=>{images[url]={width:width,height:height};props.onChange({images:_.clone(images)},null,true);});});},this.handleDrop=e=>{const{imageUploader}=this.props;let content=this.state.textAreaValue||"";const dataTransfer=e.dataTransfer;if(!dataTransfer||!imageUploader){return}const files=dataTransfer.files;if(files.length===0){const imageUrl=dataTransfer.getData("URL");if(imageUrl){const newContent=content+"\n\n![]("+imageUrl+")";this.lastUserValue=this.props.content;this.props.onChange({content:newContent});}return}const origContent=this.state.textAreaValue;_(files).chain().map(function(file){if(!file.type.match("image.*")){return null}const sentinel="☃ "+_.uniqueId("image_");content+="\n\n![]("+sentinel+")";return {file:file,sentinel:sentinel}}).reject(_.isNull).tap(()=>{this.lastUserValue=origContent;this.props.onChange({content:content});}).each(fileAndSentinel=>{imageUploader(fileAndSentinel.file,url=>{this.lastUserValue=origContent;this.props.onChange({content:this.state.textAreaValue.replace(fileAndSentinel.sentinel,url)});});});},this.handleChange=e=>{clearTimeout(this.deferredChange);this.setState({textAreaValue:e.currentTarget.value});this.deferredChange=setTimeout(()=>{if(this.state.textAreaValue!==this.props.content){this.props.onChange({content:this.state.textAreaValue});}},this.props.apiOptions.editorChangeDelay);},this._handleKeyDown=e=>{e.stopPropagation();if(e.key==="Tab"){const textarea=this.textarea.current;const word=Util.textarea.getWordBeforeCursor(textarea);const matches=word.string.toLowerCase().match(shortcutRegexp);if(matches!=null){const text=matches[1];const widgets=Widgets.getAllWidgetTypes();const matchingWidgets=widgets.filter(name=>{return name.substring(0,text.length)===text});if(matchingWidgets.length===1){const widgetType=matchingWidgets[0];this._addWidgetToContent(this.props.content,[word.pos.start,word.pos.end+1],widgetType);}e.preventDefault();}}},this._maybeCopyWidgets=e=>{const textarea=e.currentTarget;const selectedText=textarea.value.substring(textarea.selectionStart,textarea.selectionEnd);const widgetNames=_.map(selectedText.match(rWidgetSplit),syntax=>{return Util.rWidgetParts.exec(syntax)[1]});const widgetData=_.pick(this.serialize().widgets,widgetNames);localStorage.perseusLastCopiedText=selectedText;localStorage.perseusLastCopiedWidgets=JSON.stringify(widgetData);Log.log(`Widgets copied: ${localStorage.perseusLastCopiedWidgets}`);},this._maybePasteWidgets=e=>{const widgetJSON=localStorage.perseusLastCopiedWidgets;const lastCopiedText=localStorage.perseusLastCopiedText;const textToBePasted=e.originalEvent.clipboardData.getData("text");if(widgetJSON&&lastCopiedText===textToBePasted){e.preventDefault();const widgetData=JSON.parse(widgetJSON);const safeWidgetMapping=this._safeWidgetNameMapping(widgetData);const safeWidgetData={};for(const[key,data]of Object.entries(widgetData)){safeWidgetData[safeWidgetMapping[key]]=data;}const newWidgets=_.extend(safeWidgetData,this.props.widgets);const safeText=lastCopiedText.replace(rWidgetSplit,syntax=>{const match=Util.rWidgetParts.exec(syntax);const completeWidget=match[0];const widget=match[1];return completeWidget.replace(widget,safeWidgetMapping[widget])});const textarea=e.currentTarget;const selectionStart=textarea.selectionStart;const newContent=this.state.textAreaValue.substr(0,selectionStart)+safeText+this.state.textAreaValue.substr(textarea.selectionEnd);this.lastUserValue=this.state.textAreaValue;this.props.onChange({content:newContent,widgets:newWidgets},()=>{const expectedCursorPosition=selectionStart+safeText.length;Util.textarea.moveCursor(textarea,expectedCursorPosition);});}},this._safeWidgetNameMapping=widgetData=>{const widgets=_.keys(widgetData).map(name=>name.split(" "));const widgetTypes=_.uniq(widgets.map(widget=>widget[0]));const existingWidgets=_.keys(this.props.widgets).map(name=>name.split(" "));const safeWidgetNums={};_.each(widgetTypes,type=>{safeWidgetNums[type]=_.chain(existingWidgets).filter(existingWidget=>existingWidget[0]===type).map(existingWidget=>+existingWidget[1]+1).max().value();safeWidgetNums[type]=Math.max(safeWidgetNums[type],1);});const safeWidgetMapping={};_.each(widgets,widget=>{const widgetName=widget.join(" ");const widgetType=widget[0];safeWidgetMapping[widgetName]=`${widgetType} ${safeWidgetNums[widgetType]}`;safeWidgetNums[widgetType]++;});return safeWidgetMapping},this._addWidgetToContent=(oldContent,cursorRange,widgetType)=>{const allWidgetIds=_.map(oldContent.match(rWidgetSplit),syntax=>{const match=Util.rWidgetParts.exec(syntax);const type=match[2];const num=+match[3];return [type,num]});const widgetNum=_.reduce(allWidgetIds,(currentNum,otherId)=>{const[otherType,otherNum]=otherId;if(otherType===widgetType){return Math.max(otherNum+1,currentNum)}return currentNum},1);const id=widgetType+" "+widgetNum;const widgetContent=widgetPlaceholder.replace("{id}",id);const isBlock=CoreWidgetRegistry.getDefaultAlignment(widgetType)==="block";const prelude=oldContent.slice(0,cursorRange[0]);const postlude=oldContent.slice(cursorRange[1]);const newPrelude=isBlock?makeEndWithAParagraphIfNecessary(prelude):prelude;const newPostlude=isBlock?makeStartWithAParagraphAlways(postlude):postlude;const newContent=newPrelude+widgetContent+newPostlude;const newWidgets={...this.props.widgets};newWidgets[id]={options:Widgets.getEditor(widgetType)?.defaultProps,type:widgetType,version:Widgets.getVersion(widgetType)};this.lastUserValue=this.props.content;this.props.onChange({content:newContent,widgets:newWidgets},()=>{if(!this.textarea.current){return}Util.textarea.moveCursor(this.textarea.current,newContent.length-postlude.length);});},this._addWidget=widgetType=>{const textarea=this.textarea.current;if(!textarea){return}this._addWidgetToContent(this.props.content,[textarea.selectionStart,textarea.selectionEnd],widgetType);textarea.focus();},this.addTemplate=e=>{const templateType=e.currentTarget.value;if(templateType===""){return}e.currentTarget.value="";let oldContent=this.props.content;oldContent=oldContent.replace(/\n*$/,"\n\n");let template;if(templateType==="table"){template="header 1 | header 2 | header 3\n"+"- | - | -\n"+"data 1 | data 2 | data 3\n"+"data 4 | data 5 | data 6\n"+"data 7 | data 8 | data 9";}else if(templateType==="titledTable"){template="|| **Table title** ||\n"+"header 1 | header 2 | header 3\n"+"- | - | -\n"+"data 1 | data 2 | data 3\n"+"data 4 | data 5 | data 6\n"+"data 7 | data 8 | data 9";}else if(templateType==="alignment"){template="$\\begin{align} \n"+"\\\\\\\\\n"+"\\end{align}$";}else if(templateType==="piecewise"){template="$f(x) = \\begin{cases}\n"+"7 & \\text{if }x=1 \\\\\n"+"f(x-1)+5 & \\text{if }x > 1\n"+"\\end{cases}$";}else if(templateType==="allWidgets"){template=Widgets.getAllWidgetTypes().map(type=>`[[${Util.snowman} ${type} 1]]`).join("\n\n");}else if(templateType in this.props.additionalTemplates){template=this.props.additionalTemplates[templateType];}else {throw new PerseusError("Invalid template type: "+templateType,Errors.InvalidInput,{metadata:{templateType}})}const newContent=oldContent+template;this.lastUserValue=this.props.content;this.props.onChange({content:newContent},this.focusAndMoveToEnd);},this.getSaveWarnings=()=>{const widgetIds=_.intersection(this.widgetIds,_.keys(this.refs));const warnings=_(widgetIds).chain().map(id=>{const issuesFunc=this.refs[id].getSaveWarnings;const issues=issuesFunc?issuesFunc():[];return _.map(issues,issue=>id+": "+issue)}).flatten(true).value();return warnings},this.focus=()=>{const textarea=this.textarea.current;if(textarea){textarea.focus();}},this.focusAndMoveToEnd=()=>{this.focus();const textarea=this.textarea.current;if(textarea){textarea.selectionStart=textarea.value.length;textarea.selectionEnd=textarea.value.length;}},this.serialize=options=>{const widgets={};const widgetIds=_.intersection(this.widgetIds,_.keys(this.refs));_.each(widgetIds,id=>{widgets[id]=this.refs[id].serialize();});if(options&&options.keepDeletedWidgets){_.chain(this.props.widgets).keys().reject(id=>_.contains(widgetIds,id)).each(id=>{widgets[id]=this.props.widgets[id];});}return {replace:this.props.replace,content:this.props.content,images:this.props.images,widgets:widgets}};}}Editor.defaultProps={content:"",placeholder:"",widgets:{},images:{},disabled:false,widgetEnabled:true,immutableWidgets:false,showWordCount:false,warnNoPrompt:false,warnNoWidgets:false,additionalTemplates:{}};
1430
1432
 
@@ -1454,15 +1456,15 @@ const rendererProps=PropTypes.shape({content:PropTypes.string,images:PropTypes.o
1454
1456
 
1455
1457
  const itemProps=PropTypes.shape({question:PropTypes.shape({}).isRequired,answerArea:PropTypes.shape({}).isRequired,hints:PropTypes.arrayOf(PropTypes.any).isRequired});class ItemDiff extends React.Component{render(){const{before,after}=this.props;const hintCount=Math.max(before.hints.length,after.hints.length);const question=jsxRuntimeExports.jsx(RendererDiff,{before:before.question,after:after.question,title:"Question",showAlignmentOptions:false,showSeparator:true});const extras=jsxRuntimeExports.jsx(WidgetDiff,{before:before.answerArea,after:after.answerArea,title:"Question extras"});const hints=_.times(hintCount,function(n){return jsxRuntimeExports.jsx(RendererDiff,{before:n<before.hints.length?before.hints[n]:undefined,after:n<after.hints.length?after.hints[n]:undefined,title:`Hint ${n+1}`,showAlignmentOptions:false,showSeparator:n<hintCount-1},n)});return jsxRuntimeExports.jsxs("div",{className:"framework-perseus",children:[question,extras,hints&&jsxRuntimeExports.jsx("div",{className:"diff-separator"}),hints]})}}ItemDiff.propTypes={after:itemProps.isRequired,before:itemProps.isRequired};
1456
1458
 
1457
- const{InfoTip: InfoTip$p,InlineIcon: InlineIcon$4}=components;class HintEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor "+this.props.className,children:[this.props.showTitle&&jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,apiOptions:this.props.apiOptions,widgets:this.props.widgets||undefined,content:this.props.content||undefined,images:this.props.images,replace:this.props.replace,placeholder:"Type your hint here...",imageUploader:this.props.imageUploader,onChange:this.props.onChange,widgetIsOpen:this.props.widgetIsOpen},this.props.itemId),jsxRuntimeExports.jsxs("div",{className:"hint-controls-container clearfix",children:[this.props.showMoveButtons&&jsxRuntimeExports.jsxs("span",{className:"reorder-hints",children:[jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isLast?"hidden":"",onClick:_.partial(this.props.onMove,1),children:jsxRuntimeExports.jsx(InlineIcon$4,{...iconCircleArrowDown})})," ",jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isFirst?"hidden":"",onClick:_.partial(this.props.onMove,-1),children:jsxRuntimeExports.jsx(InlineIcon$4,{...iconCircleArrowUp})})," ",this.props.isLast&&jsxRuntimeExports.jsx(InfoTip$p,{children:jsxRuntimeExports.jsx("p",{children:"The last hint is automatically bolded."})})]}),jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.replace,onChange:this.handleChange}),"Replace previous hint",this.props.showRemoveButton&&jsxRuntimeExports.jsxs("button",{type:"button",className:"remove-hint simple-button orange",onClick:this.props.onRemove,children:[jsxRuntimeExports.jsx(InlineIcon$4,{...iconTrash}),"Remove this hint"," "]})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.handleChange=e=>{this.props.onChange({replace:e.target.checked});},this.focus=()=>{this.editor.current?.focus();},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=options=>{return this.editor.current?.serialize(options)};}}HintEditor.defaultProps={className:"",content:"",replace:false,showMoveButtons:true,showTitle:true,showRemoveButton:true};class CombinedHintEditor extends React.Component{componentDidMount(){this.updatePreview();}componentDidUpdate(){this.updatePreview();}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";return jsxRuntimeExports.jsxs("div",{className:"perseus-combined-hint-editor "+"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(HintEditor,{ref:this.editor,itemId:this.props.itemId,isFirst:this.props.isFirst,isLast:this.props.isLast,widgets:this.props.hint.widgets,content:this.props.hint.content,images:this.props.hint.images,replace:this.props.hint.replace,imageUploader:this.props.imageUploader,onChange:this.props.onChange,onRemove:this.props.onRemove,onMove:this.props.onMove,apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(IframeContentRenderer,{ref:this.frame,datasetKey:"mobile",datasetValue:isMobile,seamless:true,url:this.props.previewURL})})})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.frame=React.createRef(),this.updatePreview=()=>{const shouldBold=this.props.isLast&&!/\*\*/.test(this.props.hint.content);this.frame.current?.sendNewData({type:"hint",data:{hint:this.props.hint,bold:shouldBold,pos:this.props.pos,apiOptions:this.props.apiOptions,linterContext:{contentType:"hint",highlightLint:this.props.highlightLint,paths:this.props.contentPaths}}});},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=options=>{return this.editor.current?.serialize(options)},this.focus=()=>{this.editor.current?.focus();};}}CombinedHintEditor.defaultProps={highlightLint:false};class CombinedHintsEditor extends React.Component{render(){const{itemId,hints}=this.props;const hintElems=_.map(hints,function(hint,i){return jsxRuntimeExports.jsx(CombinedHintEditor,{ref:"hintEditor"+i,isFirst:i===0,isLast:i+1===hints.length,itemId:itemId,hint:hint,pos:i,imageUploader:this.props.imageUploader,onChange:this.handleHintChange.bind(this,i),onRemove:this.handleHintRemove.bind(this,i),onMove:this.handleHintMove.bind(this,i),deviceType:this.props.deviceType,apiOptions:this.props.apiOptions,highlightLint:this.props.highlightLint,previewURL:this.props.previewURL,contentPaths:[],widgetIsOpen:this.props.widgetIsOpen},"hintEditor"+i)},this);return jsxRuntimeExports.jsxs("div",{className:"perseus-hints-editor perseus-editor-table",children:[hintElems,jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"add-hint-container perseus-editor-left-cell",children:jsxRuntimeExports.jsxs("button",{type:"button",className:"add-hint simple-button orange",onClick:this.addHint,children:[jsxRuntimeExports.jsx(InlineIcon$4,{...iconPlus})," Add a hint"]})})})]})}constructor(...args){super(...args),this.handleHintChange=(i,newProps,cb,silent)=>{const hints=[...this.props.hints];hints[i]=_.extend({},this.serializeHint(i,{keepDeletedWidgets:true}),newProps);this.props.onChange({hints:hints},cb,silent);},this.handleHintRemove=i=>{if(!confirm("Are you sure you want to delete this hint?")){return}const hints=[...this.props.hints];hints.splice(i,1);this.props.onChange({hints:hints});},this.handleHintMove=(i,dir)=>{const hints=[...this.props.hints];const hint=hints.splice(i,1)[0];hints.splice(i+dir,0,hint);this.props.onChange({hints:hints},()=>{this.refs["hintEditor"+(i+dir)].focus();});},this.addHint=()=>{const hints=this.props.hints.concat([{content:"",images:{},widgets:{}}]);this.props.onChange({hints:hints},()=>{const i=hints.length-1;this.refs["hintEditor"+i].focus();});},this.getSaveWarnings=()=>{return _.chain(this.props.hints).map((hint,i)=>{return _.map(this.refs["hintEditor"+i].getSaveWarnings(),issue=>"Hint "+(i+1)+": "+issue)}).flatten(true).value()},this.serialize=options=>{return this.props.hints.map((hint,i)=>{return this.serializeHint(i,options)})},this.serializeHint=(index,options)=>{return this.refs["hintEditor"+index].serialize(options)};}}CombinedHintsEditor.HintEditor=HintEditor;CombinedHintsEditor.defaultProps={onChange:()=>{},hints:[],highlightLint:false};
1459
+ const{InfoTip: InfoTip$p,InlineIcon: InlineIcon$4}=components;class HintEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor "+this.props.className,children:[this.props.showTitle&&jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,apiOptions:this.props.apiOptions,widgets:this.props.widgets||undefined,content:this.props.content||undefined,images:this.props.images,replace:this.props.replace,placeholder:"Type your hint here...",imageUploader:this.props.imageUploader,onChange:this.props.onChange,widgetIsOpen:this.props.widgetIsOpen},this.props.itemId),jsxRuntimeExports.jsxs("div",{className:"hint-controls-container clearfix",children:[this.props.showMoveButtons&&jsxRuntimeExports.jsxs("span",{className:"reorder-hints",children:[jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isLast?"hidden":"",onClick:_.partial(this.props.onMove,1),children:jsxRuntimeExports.jsx(InlineIcon$4,{...iconCircleArrowDown})})," ",jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isFirst?"hidden":"",onClick:_.partial(this.props.onMove,-1),children:jsxRuntimeExports.jsx(InlineIcon$4,{...iconCircleArrowUp})})," ",this.props.isLast&&jsxRuntimeExports.jsx(InfoTip$p,{children:jsxRuntimeExports.jsx("p",{children:"The last hint is automatically bolded."})})]}),jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.replace,onChange:this.handleChange}),"Replace previous hint",this.props.showRemoveButton&&jsxRuntimeExports.jsxs("button",{type:"button",className:"remove-hint simple-button orange",onClick:this.props.onRemove,children:[jsxRuntimeExports.jsx(InlineIcon$4,{...iconTrash}),"Remove this hint"," "]})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.handleChange=e=>{this.props.onChange({replace:e.target.checked});},this.focus=()=>{this.editor.current?.focus();},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=options=>{return this.editor.current?.serialize(options)};}}HintEditor.defaultProps={className:"",content:"",replace:false,showMoveButtons:true,showTitle:true,showRemoveButton:true};class CombinedHintEditor extends React.Component{componentDidMount(){this.updatePreview();}componentDidUpdate(){this.updatePreview();}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";return jsxRuntimeExports.jsxs("div",{className:"perseus-combined-hint-editor "+"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(HintEditor,{ref:this.editor,itemId:this.props.itemId,isFirst:this.props.isFirst,isLast:this.props.isLast,widgets:this.props.hint.widgets,content:this.props.hint.content,images:this.props.hint.images,replace:this.props.hint.replace,imageUploader:this.props.imageUploader,onChange:this.props.onChange,onRemove:this.props.onRemove,onMove:this.props.onMove,apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(IframeContentRenderer,{ref:this.frame,datasetKey:"mobile",datasetValue:isMobile,seamless:true,url:this.props.previewURL})})})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.frame=React.createRef(),this.updatePreview=()=>{const shouldBold=this.props.isLast&&!/\*\*/.test(this.props.hint.content);this.frame.current?.sendNewData({type:"hint",data:{hint:this.props.hint,bold:shouldBold,pos:this.props.pos,apiOptions:this.props.apiOptions,linterContext:{contentType:"hint",highlightLint:this.props.highlightLint,paths:this.props.contentPaths}}});},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=options=>{return this.editor.current?.serialize(options)},this.focus=()=>{this.editor.current?.focus();};}}CombinedHintEditor.defaultProps={highlightLint:false};class CombinedHintsEditor extends React.Component{render(){const{itemId,hints}=this.props;const hintElems=_.map(hints,function(hint,i){return jsxRuntimeExports.jsx(CombinedHintEditor,{ref:"hintEditor"+i,isFirst:i===0,isLast:i+1===hints.length,itemId:itemId,hint:hint,pos:i,imageUploader:this.props.imageUploader,onChange:this.handleHintChange.bind(this,i),onRemove:this.handleHintRemove.bind(this,i),onMove:this.handleHintMove.bind(this,i),deviceType:this.props.deviceType,apiOptions:this.props.apiOptions,highlightLint:this.props.highlightLint,previewURL:this.props.previewURL,contentPaths:[],widgetIsOpen:this.props.widgetIsOpen},"hintEditor"+i)},this);return jsxRuntimeExports.jsxs("div",{className:"perseus-hints-editor perseus-editor-table",children:[hintElems,jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"add-hint-container perseus-editor-left-cell",children:jsxRuntimeExports.jsxs("button",{type:"button",className:"add-hint simple-button orange",onClick:this.addHint,children:[jsxRuntimeExports.jsx(InlineIcon$4,{...iconPlus})," Add a hint"]})})})]})}constructor(...args){super(...args),this.handleHintChange=(i,newProps,cb,silent)=>{const hints=[...this.props.hints];hints[i]=_.extend({},this.serializeHint(i,{keepDeletedWidgets:true}),newProps);this.props.onChange({hints:hints},cb,silent);},this.handleHintRemove=i=>{if(!confirm("Are you sure you want to delete this hint?")){return}const hints=[...this.props.hints];hints.splice(i,1);this.props.onChange({hints:hints});},this.handleHintMove=(i,dir)=>{const hints=[...this.props.hints];const hint=hints.splice(i,1)[0];hints.splice(i+dir,0,hint);this.props.onChange({hints:hints},()=>{this.refs["hintEditor"+(i+dir)].focus();});},this.addHint=()=>{const hint={content:"",images:{},widgets:{}};const hints=[...this.props.hints,hint];this.props.onChange({hints:hints},()=>{const i=hints.length-1;this.refs["hintEditor"+i].focus();});},this.getSaveWarnings=()=>{return _.chain(this.props.hints).map((hint,i)=>{return _.map(this.refs["hintEditor"+i].getSaveWarnings(),issue=>"Hint "+(i+1)+": "+issue)}).flatten(true).value()},this.serialize=options=>{return this.props.hints.map((hint,i)=>{return this.serializeHint(i,options)})},this.serializeHint=(index,options)=>{return this.refs["hintEditor"+index].serialize(options)};}}CombinedHintsEditor.HintEditor=HintEditor;CombinedHintsEditor.defaultProps={onChange:()=>{},hints:[],highlightLint:false};
1458
1460
 
1459
- const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,onToggle}=props;return jsxRuntimeExports.jsx(View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$Q.container,containerStyle],headerStyle:styles$Q.accordionHeader,header:header,children:jsxRuntimeExports.jsx(View,{style:[styles$Q.accordionPanel,panelStyle],children:children})})})};const styles$Q=StyleSheet.create({container:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8},accordionHeader:{padding:spacing.small_12,paddingInlineEnd:0,height:spacing.xxLarge_48},accordionPanel:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxxSmall_4,paddingLeft:spacing.small_12,paddingRight:spacing.small_12}});
1461
+ const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,onToggle}=props;return jsxRuntimeExports.jsx(View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$R.container,containerStyle],headerStyle:styles$R.accordionHeader,header:header,children:jsxRuntimeExports.jsx(View,{style:[styles$R.accordionPanel,panelStyle],children:children})})})};const styles$R=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.instructive.subtle,marginTop:spacing.xSmall_8},accordionHeader:{padding:spacing.small_12,paddingInlineEnd:0,height:spacing.xxLarge_48},accordionPanel:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxxSmall_4,paddingLeft:spacing.small_12,paddingRight:spacing.small_12}});
1460
1462
 
1461
1463
  const IssueDetails=({issue})=>{const[expanded,setExpanded]=React.useState(false);const toggleVisibility=()=>setExpanded(!expanded);return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:expanded,onToggle:toggleVisibility,containerStyle:{backgroundColor:color.fadedGold8},panelStyle:{backgroundColor:"white"},header:jsxRuntimeExports.jsx(LabelLarge,{style:{textOverflow:"ellipsis",maxWidth:"100%",overflow:"hidden",whiteSpace:"nowrap"},children:`Warning: ${issue.id}`}),children:[jsxRuntimeExports.jsx(LabelSmall,{style:{fontWeight:"bold"},children:"Description:"}),jsxRuntimeExports.jsx("span",{children:issue.description}),jsxRuntimeExports.jsx("a",{href:issue.helpUrl,target:"_blank",rel:"noreferrer",children:issue.help}),jsxRuntimeExports.jsx(LabelSmall,{style:{marginTop:"1em",fontWeight:"bold"},children:"Impact:"}),jsxRuntimeExports.jsxs("span",{style:{fontWeight:"initial"},children:[" ",issue.impact]}),jsxRuntimeExports.jsx(LabelSmall,{style:{marginTop:"1em",fontWeight:"bold"},children:"Issue:"}),jsxRuntimeExports.jsx("span",{children:issue.message})]})};
1462
1464
 
1463
1465
  const IssuesPanel=({issues=[]})=>{const[showPanel,setShowPanel]=useState(false);const hasWarnings=issues.length>0;const issuesCount=`${issues.length} issue${issues.length===1?"":"s"}`;const icon=hasWarnings?iconWarning:iconPass;const iconColor=hasWarnings?color.gold:color.green;const togglePanel=()=>{if(hasWarnings){setShowPanel(!showPanel);}};return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:togglePanel,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginRight:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-content",children:issues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{issue:issue},issue.id))})})]})};
1464
1466
 
1465
- const{InfoTip: InfoTip$o}=components;class ItemExtrasEditor extends React.Component{shouldShowFinancialCalculatorOptions(){return this.props.financialCalculatorMonthlyPayment||this.props.financialCalculatorTotalAmount||this.props.financialCalculatorTimeToPayOff}render(){return jsxRuntimeExports.jsx("div",{className:"perseus-answer-editor",children:jsxRuntimeExports.jsxs("div",{className:"perseus-answer-options",children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show calculator",infoTip:"Use the calculator when completing difficult calculations is NOT the intent of the question. DON’T use the calculator when testing the student’s ability to complete different types of computations.",checked:this.props.calculator,onChange:newCheckedState=>{this.props.onChange({calculator:newCheckedState});}}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show financial calculator",infoTip:"This provides the student with the ability to view a financial calculator, e.g., for answering financial questions. Once checked, requires at least one of the three options below to be checked.",checked:this.shouldShowFinancialCalculatorOptions(),onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState,financialCalculatorTotalAmount:newCheckedState,financialCalculatorTimeToPayOff:newCheckedState});}}),this.shouldShowFinancialCalculatorOptions()&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include monthly payment",infoTip:"This provides the student with the ability to view a monthly payment calculator; e.g., given a loan amount, interest rate, and term, what is the monthly payment?",checked:this.props.financialCalculatorMonthlyPayment,onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include total amount",infoTip:"This provides the student with the ability to view a total amount calculator; e.g., given a monthly payment, interest rate, and term, what is the total amount to be paid?",checked:this.props.financialCalculatorTotalAmount,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTotalAmount:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include time-to-pay-off",infoTip:"This provides the student with the ability to view a time to pay off calculator; e.g., given a loan amount, interest rate, and monthly payment, how long will it take to pay off the loan?",checked:this.props.financialCalculatorTimeToPayOff,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTimeToPayOff:newCheckedState});},indent:true})]}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show periodic table",infoTip:"This provides the student with the ability to view a periodic table of the elements, e.g., for answering chemistry questions.",checked:this.props.periodicTable,onChange:newCheckedState=>{this.props.onChange({periodicTable:newCheckedState,periodicTableWithKey:false});}}),this.props.periodicTable&&jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include key/legend with periodic table",infoTip:"Include a key for HS courses; omit for AP chemistry.",checked:this.props.periodicTableWithKey,onChange:newCheckedState=>{this.props.onChange({periodicTableWithKey:newCheckedState});},indent:true})]})})}constructor(...args){super(...args),this.serialize=()=>{const data={...ItemExtrasEditor.defaultProps};for(const key of ItemExtras){data[key]=!!this.props[key];}return data};}}ItemExtrasEditor.defaultProps={calculator:false,financialCalculatorMonthlyPayment:false,financialCalculatorTotalAmount:false,financialCalculatorTimeToPayOff:false,periodicTable:false,periodicTableWithKey:false};const ItemExtraCheckbox=props=>jsxRuntimeExports.jsx(View,{style:[styles$P.checkbox,props.indent?styles$P.indented:undefined],children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(View,{style:{flexDirection:"row"},children:[props.label," ",jsxRuntimeExports.jsx(InfoTip$o,{children:props.infoTip})]}),checked:props.checked,onChange:newCheckedState=>props.onChange(newCheckedState)})});const styles$P=StyleSheet.create({indented:{marginInlineStart:spacing.large_24}});
1467
+ const{InfoTip: InfoTip$o}=components;class ItemExtrasEditor extends React.Component{shouldShowFinancialCalculatorOptions(){return this.props.financialCalculatorMonthlyPayment||this.props.financialCalculatorTotalAmount||this.props.financialCalculatorTimeToPayOff}render(){return jsxRuntimeExports.jsx("div",{className:"perseus-answer-editor",children:jsxRuntimeExports.jsxs("div",{className:"perseus-answer-options",children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show calculator",infoTip:"Use the calculator when completing difficult calculations is NOT the intent of the question. DON’T use the calculator when testing the student’s ability to complete different types of computations.",checked:this.props.calculator,onChange:newCheckedState=>{this.props.onChange({calculator:newCheckedState});}}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show financial calculator",infoTip:"This provides the student with the ability to view a financial calculator, e.g., for answering financial questions. Once checked, requires at least one of the three options below to be checked.",checked:this.shouldShowFinancialCalculatorOptions(),onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState,financialCalculatorTotalAmount:newCheckedState,financialCalculatorTimeToPayOff:newCheckedState});}}),this.shouldShowFinancialCalculatorOptions()&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include monthly payment",infoTip:"This provides the student with the ability to view a monthly payment calculator; e.g., given a loan amount, interest rate, and term, what is the monthly payment?",checked:this.props.financialCalculatorMonthlyPayment,onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include total amount",infoTip:"This provides the student with the ability to view a total amount calculator; e.g., given a monthly payment, interest rate, and term, what is the total amount to be paid?",checked:this.props.financialCalculatorTotalAmount,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTotalAmount:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include time-to-pay-off",infoTip:"This provides the student with the ability to view a time to pay off calculator; e.g., given a loan amount, interest rate, and monthly payment, how long will it take to pay off the loan?",checked:this.props.financialCalculatorTimeToPayOff,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTimeToPayOff:newCheckedState});},indent:true})]}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show periodic table",infoTip:"This provides the student with the ability to view a periodic table of the elements, e.g., for answering chemistry questions.",checked:this.props.periodicTable,onChange:newCheckedState=>{this.props.onChange({periodicTable:newCheckedState,periodicTableWithKey:false});}}),this.props.periodicTable&&jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include key/legend with periodic table",infoTip:"Include a key for HS courses; omit for AP chemistry.",checked:this.props.periodicTableWithKey,onChange:newCheckedState=>{this.props.onChange({periodicTableWithKey:newCheckedState});},indent:true})]})})}constructor(...args){super(...args),this.serialize=()=>{const data={...ItemExtrasEditor.defaultProps};for(const key of ItemExtras){data[key]=!!this.props[key];}return data};}}ItemExtrasEditor.defaultProps={calculator:false,financialCalculatorMonthlyPayment:false,financialCalculatorTotalAmount:false,financialCalculatorTimeToPayOff:false,periodicTable:false,periodicTableWithKey:false};const ItemExtraCheckbox=props=>jsxRuntimeExports.jsx(View,{style:[styles$Q.checkbox,props.indent?styles$Q.indented:undefined],children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(View,{style:{flexDirection:"row"},children:[props.label," ",jsxRuntimeExports.jsx(InfoTip$o,{children:props.infoTip})]}),checked:props.checked,onChange:newCheckedState=>props.onChange(newCheckedState)})});const styles$Q=StyleSheet.create({indented:{marginInlineStart:spacing.large_24}});
1466
1468
 
1467
1469
  const WARNINGS={inaccessibleWidget:(widgetType,widgetId)=>({id:`${widgetId} inaccessible`,description:`This ${widgetType} widget (${widgetId}) is inaccessible. Consider using an alternative to support all learners. Please check out the following documentation on compliant widget options.`,helpUrl:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/1909489691/Widget+Fundamentals",help:"Widget Fundamentals",impact:"medium",message:"Selecting inaccessible widgets for a practice item will result in this exercise being hidden from users with 'Hide visually dependant content' setting set to true. Please select another widget or create an alternative practice item."}),genericLinterWarning:(rule,message)=>({id:rule,description:message,help:"Learn more about best practices for authoring items",helpUrl:"https://docs.google.com/document/d/1N13f4sY-7EXWDwQ04ivA9vJBVvPPd60qjBT73B4NHuM/edit?tab=t.0",impact:"low",message:message})};
1468
1470
 
@@ -1470,7 +1472,7 @@ class ItemEditor extends React.Component{static getDerivedStateFromProps(props){
1470
1472
 
1471
1473
  const{HUD}=components;class EditorPage extends React.Component{componentDidMount(){this._isMounted=true;this.updateRenderer();}componentDidUpdate(){setTimeout(()=>{this.updateRenderer();});}componentWillUnmount(){this._isMounted=false;}updateRenderer(){const hasEditor=!this.props.developerMode||!this.props.jsonMode;if(!this._isMounted||!hasEditor){return}const touch=this.props.previewDevice==="phone"||this.props.previewDevice==="tablet";const deviceBasedApiOptions={...this.getApiOptions(),customKeypad:touch,isMobile:touch};this.itemEditor.current?.triggerPreviewUpdate({type:"question",data:_({item:this.serialize(),apiOptions:deviceBasedApiOptions,initialHintsVisible:0,device:this.props.previewDevice,linterContext:{contentType:"exercise",highlightLint:this.state.highlightLint,paths:this.props.contentPaths||[]},reviewMode:true,legacyPerseusLint:this.itemEditor.current?.getSaveWarnings()}).extend(_(this.props).pick("problemNum"))});}getApiOptions(){return {...ApiOptions.defaults,...this.props.apiOptions}}getSaveWarnings(){const issues1=this.itemEditor.current?.getSaveWarnings();const issues2=this.hintsEditor.current?.getSaveWarnings();return issues1.concat(issues2)}serialize(options){if(this.props.jsonMode){return this.state.json}return _.extend(this.itemEditor.current?.serialize(options),{hints:this.hintsEditor.current?.serialize(options)})}render(){let className="framework-perseus";const touch=this.props.previewDevice==="phone"||this.props.previewDevice==="tablet";const deviceBasedApiOptions={...this.getApiOptions(),customKeypad:touch,isMobile:touch};if(deviceBasedApiOptions.isMobile){className+=" "+ClassNames.MOBILE;}return jsxRuntimeExports.jsxs("div",{id:"perseus",className:className,children:[jsxRuntimeExports.jsxs("div",{style:{marginBottom:10},children:[this.props.developerMode&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Developer JSON Mode:"," ",jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.jsonMode,onChange:this.toggleJsonMode})]})," "]}),!this.props.jsonMode&&jsxRuntimeExports.jsx(ViewportResizer,{deviceType:this.props.previewDevice,onViewportSizeChanged:this.props.onPreviewDeviceChange}),!this.props.jsonMode&&jsxRuntimeExports.jsx(HUD,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})]}),this.props.developerMode&&this.props.jsonMode&&jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,value:this.state.json,onChange:this.changeJSON})}),(!this.props.developerMode||!this.props.jsonMode)&&jsxRuntimeExports.jsx(ItemEditor,{ref:this.itemEditor,itemId:this.props.itemId,question:this.props.question,answerArea:this.props.answerArea,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,widgetIsOpen:this.state.widgetsAreOpen,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,issues:this.props.issues,additionalTemplates:this.props.additionalTemplates}),(!this.props.developerMode||!this.props.jsonMode)&&jsxRuntimeExports.jsx(CombinedHintsEditor,{ref:this.hintsEditor,itemId:this.props.itemId,hints:this.props.hints,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,highlightLint:this.state.highlightLint,widgetIsOpen:this.state.widgetsAreOpen})]})}constructor(props){super(props),this.itemEditor=React.createRef(),this.hintsEditor=React.createRef(),this.toggleJsonMode=()=>{this.setState({json:this.serialize({keepDeletedWidgets:true})},()=>{this.props.onChange({jsonMode:!this.props.jsonMode});});},this.handleChange=(toChange,cb,silent)=>{const newProps=_(this.props).pick("question","hints","answerArea");_(newProps).extend(toChange);this.props.onChange(newProps,cb,silent);},this.changeJSON=newJson=>{this.setState({json:newJson});this.props.onChange(newJson);};this.state={json:_.pick(this.props,"question","answerArea","hints"),gradeMessage:"",wasAnswered:false,highlightLint:true,widgetsAreOpen:this.props.widgetsAreOpen??true};this._isMounted=false;}}EditorPage.defaultProps={developerMode:false,jsonMode:false,onChange:()=>{}};
1472
1474
 
1473
- function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice}){const i18n=usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(View,{className:`framework-perseus ${className}`,style:[styles$O.container,!seamless?styles$O.gutter:undefined],children:jsxRuntimeExports.jsx(StatefulKeypadContextProvider,{children:jsxRuntimeExports.jsx(KeypadContext.Consumer,{children:({setKeypadActive,keypadElement,setKeypadElement})=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,...question}),jsxRuntimeExports.jsx(MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$O=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginRight:lintGutterWidth}});
1475
+ function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice}){const i18n=usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(View,{className:`framework-perseus ${className}`,style:[styles$P.container,!seamless?styles$P.gutter:undefined],children:jsxRuntimeExports.jsx(StatefulKeypadContextProvider,{children:jsxRuntimeExports.jsx(KeypadContext.Consumer,{children:({setKeypadActive,keypadElement,setKeypadElement})=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,...question}),jsxRuntimeExports.jsx(MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$P=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginRight:lintGutterWidth}});
1474
1476
 
1475
1477
  const{TextListEditor: TextListEditor$4}=components;const Categorizer=Categorizer$1.widget;class CategorizerEditor extends React.Component{render(){const categorizerProps={items:this.props.items,categories:this.props.categories,userInput:{values:this.props.values},handleUserInput:userInput=>{this.props.onChange({values:userInput.values});},apiOptions:this.props.apiOptions,trackInteraction:function(){}};return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Randomize item order",checked:this.props.randomizeItems,onChange:value=>{this.props.onChange({randomizeItems:value});}})}),"Categories:",jsxRuntimeExports.jsx(TextListEditor$4,{options:this.props.categories,onChange:cat=>{this.change("categories",cat);},layout:"horizontal"}),"Items:",jsxRuntimeExports.jsx(TextListEditor$4,{options:this.props.items,onChange:items=>{this.change({items:items,values:_.first(this.props.values,items.length)});},layout:"vertical"}),jsxRuntimeExports.jsx(Categorizer,{...categorizerProps})]})}constructor(...args){super(...args),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}CategorizerEditor.propTypes={...Changeable.propTypes,apiOptions:ApiOptions.propTypes,items:PropTypes.arrayOf(PropTypes.string),categories:PropTypes.arrayOf(PropTypes.string),values:PropTypes.arrayOf(PropTypes.number),randomizeItems:PropTypes.bool};CategorizerEditor.widgetName="categorizer";CategorizerEditor.defaultProps=categorizerLogic.defaultWidgetOptions;
1476
1478
 
@@ -1486,12 +1488,12 @@ const{InfoTip: InfoTip$m,InlineIcon: InlineIcon$3}=components;class DropdownEdit
1486
1488
 
1487
1489
  const{TextInput: TextInput$6}=components;class ExplanationEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-explanation-editor",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Prompt to show explanation:"," ",jsxRuntimeExports.jsx(TextInput$6,{value:this.props.showPrompt,onChange:this.change("showPrompt")})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Prompt to hide explanation:"," ",jsxRuntimeExports.jsx(TextInput$6,{value:this.props.hidePrompt,onChange:this.change("hidePrompt")})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(Editor,{apiOptions:this.props.apiOptions,content:this.props.explanation,widgets:this.props.widgets,widgetEnabled:true,immutableWidgets:false,onChange:props=>{const newProps={};if(_.has(props,"content")){newProps.explanation=props.content;}if(_.has(props,"widgets")){newProps.widgets=props.widgets;}this.change(newProps);}})})]})}constructor(...args){super(...args),this.state={},this.change=(...args)=>{return Changeable.change.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}ExplanationEditor.propTypes={...Changeable.propTypes,showPrompt:PropTypes.string,hidePrompt:PropTypes.string,explanation:PropTypes.string,widgets:PropTypes.object,apiOptions:PropTypes.any};ExplanationEditor.widgetName="explanation";ExplanationEditor.defaultProps=explanationLogic.defaultWidgetOptions;
1488
1490
 
1489
- const{ButtonGroup: ButtonGroup$7,InfoTip: InfoTip$l}=components;const buttonSetsList=["basic","trig","prealgebra","logarithms","scientific","basic relations","advanced relations"];class ExpressionEditor extends React.Component{serialize(){const{answerForms,buttonSets,functions,times,visibleLabel,ariaLabel}=this.props;return {answerForms,buttonSets,functions,times,visibleLabel,ariaLabel,extraKeys:deriveExtraKeys(this.props)}}updateAnswerForm(index,answerFormProps){const answerForms=this.props.answerForms.slice();answerForms[index]=answerFormProps;const{extraKeys:_,...restProps}=this.props;const extraKeys=deriveExtraKeys({...restProps,answerForms});this.props.onChange({answerForms,extraKeys});}changeSimplify(index,simplify){const answerForm={...this.props.answerForms[index],simplify};this.updateAnswerForm(index,answerForm);}changeForm(index,form){const answerForm={...this.props.answerForms[index],form};this.updateAnswerForm(index,answerForm);}changeConsidered(index,considered){const answerForm={...this.props.answerForms[index],considered};this.updateAnswerForm(index,answerForm);}changeTimes(times){this.props.onChange({times:times});}render(){const answerOptions=this.props.answerForms.map((ans,index)=>{const expressionProps={times:this.props.times,functions:this.props.functions,buttonSets:this.props.buttonSets,buttonsVisible:"focused",userInput:ans.value,handleUserInput:input=>this.changeExpressionWidget(index,input),trackInteraction:()=>{},widgetId:this.props.widgetId+"-"+ans.key,visibleLabel:this.props.visibleLabel,ariaLabel:this.props.ariaLabel};return jsxRuntimeExports.jsx(AnswerOption,{considered:ans.considered,expressionProps:expressionProps,form:ans.form,simplify:ans.simplify,onDelete:()=>this.handleRemoveForm(index),onChangeSimplify:simplify=>this.changeSimplify(index,simplify),onChangeForm:form=>this.changeForm(index,form),onChangeConsidered:considered=>this.changeConsidered(index,considered)},ans.key)});const buttonSetChoices=buttonSetsList.map(name=>{const isBasic=name==="basic";const checked=this.props.buttonSets.includes(name)||isBasic;return jsxRuntimeExports.jsx(Checkbox$1,{label:name,checked:checked,disabled:isBasic,onChange:()=>this.handleButtonSet(name)},name)});buttonSetChoices.unshift(jsxRuntimeExports.jsx(Checkbox$1,{label:"show ÷ button",checked:this.props.buttonSets.includes("basic+div"),onChange:this.handleToggleDiv},"show ÷ button"));return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(HeadingSmall,{children:"Global Options"}),jsxRuntimeExports.jsx("div",{className:css(styles$N.paddedY),children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Visible label",jsxRuntimeExports.jsx(InfoTip$l,{children:"Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."})]}),value:this.props.visibleLabel||"",onChange:this.handleVisibleLabel})}),jsxRuntimeExports.jsx("div",{className:css(styles$N.paddedY),children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Aria label",jsxRuntimeExports.jsxs(InfoTip$l,{children:["Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see"," ",jsxRuntimeExports.jsx("a",{href:"https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",target:"_blank",rel:"noreferrer",children:"this article."})]})]}),value:this.props.ariaLabel||"",onChange:this.handleAriaLabel})}),jsxRuntimeExports.jsx("div",{className:css(styles$N.paddedY),children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Function variables",jsxRuntimeExports.jsx(InfoTip$l,{children:'Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means "f of x" and not "f times x".'})]}),value:this.state.functionsInternal,onChange:this.handleFunctions})}),jsxRuntimeExports.jsx("div",{className:css(styles$N.paddedY),children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Use × instead of ⋅ for multiplication",jsxRuntimeExports.jsx(InfoTip$l,{children:"For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."})]}),checked:this.props.times,onChange:newCheckedState=>{this.changeTimes(newCheckedState);}})}),jsxRuntimeExports.jsxs("div",{className:css(styles$N.paddedY),children:[jsxRuntimeExports.jsx(HeadingXSmall,{children:"Button Sets"}),buttonSetChoices]}),jsxRuntimeExports.jsx(HeadingSmall,{children:"Answers"}),jsxRuntimeExports.jsx(Caption,{style:styles$N.answersSubtitle,children:"student responses area matched against these from top to bottom"}),jsxRuntimeExports.jsx(View,{style:{gap:spacing.xSmall_8},children:answerOptions}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.newAnswer,children:"Add new answer"})]})}constructor(props){super(props),this.getSaveWarnings=()=>{const issues=[];if(this.props.answerForms.length===0){issues.push("No answers specified");}else {const hasCorrect=this.props.answerForms.some(form=>{return form.considered==="correct"});if(!hasCorrect){issues.push("No correct answer specified");}_(this.props.answerForms).each((form,ix)=>{if(this.props.value===""){issues.push(`Answer ${ix+1} is empty`);}else {const expression=KAS.parse(form.value,{functions:this.props.functions});if(!expression.parsed){issues.push(`Couldn't parse ${form.value}`);}else if(form.simplify&&!expression.expr.isSimplified()){issues.push(`${form.value} isn't simplified, but is required" +
1490
- " to be`);}}});}return issues},this.newAnswer=()=>{const answerForms=this.props.answerForms.slice();const newKey=crypto.randomUUID();const newAnswerForm={considered:"correct",form:false,key:`${newKey}`,simplify:false,value:""};answerForms.push(newAnswerForm);this.props.onChange({answerForms});},this.handleRemoveForm=i=>{const updatedAnswerForms=this.props.answerForms.slice();updatedAnswerForms.splice(i,1);this.props.onChange({answerForms:updatedAnswerForms});},this.handleButtonSet=changingName=>{const buttonSetNames=buttonSetsList;const buttonSets=buttonSetNames.filter(set=>{return this.props.buttonSets.includes(set)!==(set===changingName)});this.props.onChange({buttonSets});},this.handleToggleDiv=()=>{let keep;let remove;if(this.props.buttonSets.includes("basic+div")){keep="basic";remove="basic+div";}else {keep="basic+div";remove="basic";}const buttonSets=this.props.buttonSets.filter(set=>set!==remove).concat(keep);this.props.onChange({buttonSets});},this.handleTexInsert=str=>{this.refs.expression.insert(str);},this.handleFunctions=value=>{this.setState({functionsInternal:value});const newProps={};newProps.functions=value.split(/[ ,]+/).filter(isTruthy);this.props.onChange(newProps);},this.handleVisibleLabel=visibleLabel=>{this.props.onChange({visibleLabel});},this.handleAriaLabel=ariaLabel=>{this.props.onChange({ariaLabel});},this.changeExpressionWidget=(index,input)=>{const answerForm={...this.props.answerForms[index],value:input};this.updateAnswerForm(index,answerForm);};this.state={functionsInternal:this.props.functions.join(" ")};}}ExpressionEditor.widgetName="expression";ExpressionEditor.defaultProps=expressionLogic.defaultWidgetOptions;const findNextIn=function(arr,val){let ix=arr.indexOf(val);ix=(ix+1)%arr.length;return arr[ix]};class AnswerOption extends React.Component{render(){const removeButton=this.state.deleteFocused?jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.handleImSure,actionType:"destructive",children:"I'm sure!"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.handleCancelDelete,kind:"secondary",children:"Cancel"})]}):jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.handleDelete,actionType:"destructive",kind:"tertiary",style:styles$N.deleteButton,children:"Delete"});return jsxRuntimeExports.jsxs("div",{className:css(styles$N.answerOption),children:[jsxRuntimeExports.jsx(ButtonGroup$7,{onChange:this.toggleConsidered,allowEmpty:false,value:this.props.considered,selectedButtonStyle:consideredButtonStyles[this.props.considered],buttons:PerseusExpressionAnswerFormConsidered.map(c=>({value:c,content:c,title:`This answer will be considered ${c}`}))}),jsxRuntimeExports.jsx(Expression,{...this.props.expressionProps}),jsxRuntimeExports.jsx("div",{className:css(styles$N.paddedY,styles$N.paddedX),children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must have the same form.",jsxRuntimeExports.jsx(InfoTip$l,{children:"The student's answer must be in the same form. Commutativity and excess negative signs are ignored."})]}),checked:this.props.form,onChange:this.props.onChangeForm})}),jsxRuntimeExports.jsx("div",{className:css(styles$N.paddedY,styles$N.paddedX),children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must be fully expanded and simplified.",jsxRuntimeExports.jsx(InfoTip$l,{children:'The student\'s answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response "Your answer is not fully expanded and simplified."'})]}),checked:this.props.simplify,onChange:this.props.onChangeSimplify})}),jsxRuntimeExports.jsx("div",{className:css(styles$N.buttonRow,styles$N.paddedY),children:removeButton})]})}constructor(...args){super(...args),this.state={deleteFocused:false},this.handleImSure=()=>{this.props.onDelete();this.handleCancelDelete();},this.handleCancelDelete=()=>{this.setState({deleteFocused:false});},this.handleDelete=()=>{this.setState({deleteFocused:true});},this.toggleConsidered=()=>{const newVal=findNextIn(PerseusExpressionAnswerFormConsidered,this.props.considered);this.props.onChangeConsidered(newVal);};}}const styles$N=StyleSheet.create({paddedX:{paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8},paddedY:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxSmall_6},answersSubtitle:{fontStyle:"italic"},answerOption:{border:"1px solid #ddd",borderRadius:"3px",display:"flex",flexDirection:"column"},answerStatusWrong:{backgroundColor:color.fadedRed16},answerStatusCorrect:{backgroundColor:color.fadedGreen16},answerStatusUngraded:{backgroundColor:color.fadedBlue16},buttonRow:{display:"flex"},deleteButton:{paddingInline:sizing.size_160}});const consideredButtonStyles={wrong:styles$N.answerStatusWrong,correct:styles$N.answerStatusCorrect,ungraded:styles$N.answerStatusUngraded};
1491
+ const{ButtonGroup: ButtonGroup$7,InfoTip: InfoTip$l}=components;const buttonSetsList=["basic","trig","prealgebra","logarithms","scientific","basic relations","advanced relations"];class ExpressionEditor extends React.Component{serialize(){const{answerForms,buttonSets,functions,times,visibleLabel,ariaLabel}=this.props;return {answerForms,buttonSets,functions,times,visibleLabel,ariaLabel,extraKeys:deriveExtraKeys(this.props)}}updateAnswerForm(index,answerFormProps){const answerForms=this.props.answerForms.slice();answerForms[index]=answerFormProps;const{extraKeys:_,...restProps}=this.props;const extraKeys=deriveExtraKeys({...restProps,answerForms});this.props.onChange({answerForms,extraKeys});}changeSimplify(index,simplify){const answerForm={...this.props.answerForms[index],simplify};this.updateAnswerForm(index,answerForm);}changeForm(index,form){const answerForm={...this.props.answerForms[index],form};this.updateAnswerForm(index,answerForm);}changeConsidered(index,considered){const answerForm={...this.props.answerForms[index],considered};this.updateAnswerForm(index,answerForm);}changeTimes(times){this.props.onChange({times:times});}render(){const answerOptions=this.props.answerForms.map((ans,index)=>{const expressionProps={times:this.props.times,functions:this.props.functions,buttonSets:this.props.buttonSets,buttonsVisible:"focused",userInput:ans.value,handleUserInput:input=>this.changeExpressionWidget(index,input),trackInteraction:()=>{},widgetId:this.props.widgetId+"-"+ans.key,visibleLabel:this.props.visibleLabel,ariaLabel:this.props.ariaLabel};return jsxRuntimeExports.jsx(AnswerOption,{considered:ans.considered,expressionProps:expressionProps,form:ans.form,simplify:ans.simplify,onDelete:()=>this.handleRemoveForm(index),onChangeSimplify:simplify=>this.changeSimplify(index,simplify),onChangeForm:form=>this.changeForm(index,form),onChangeConsidered:considered=>this.changeConsidered(index,considered)},ans.key)});const buttonSetChoices=buttonSetsList.map(name=>{const isBasic=name==="basic";const checked=this.props.buttonSets.includes(name)||isBasic;return jsxRuntimeExports.jsx(Checkbox$1,{label:name,checked:checked,disabled:isBasic,onChange:()=>this.handleButtonSet(name)},name)});buttonSetChoices.unshift(jsxRuntimeExports.jsx(Checkbox$1,{label:"show ÷ button",checked:this.props.buttonSets.includes("basic+div"),onChange:this.handleToggleDiv},"show ÷ button"));return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(HeadingSmall,{children:"Global Options"}),jsxRuntimeExports.jsx("div",{className:css(styles$O.paddedY),children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Visible label",jsxRuntimeExports.jsx(InfoTip$l,{children:"Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."})]}),value:this.props.visibleLabel||"",onChange:this.handleVisibleLabel})}),jsxRuntimeExports.jsx("div",{className:css(styles$O.paddedY),children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Aria label",jsxRuntimeExports.jsxs(InfoTip$l,{children:["Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see"," ",jsxRuntimeExports.jsx("a",{href:"https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",target:"_blank",rel:"noreferrer",children:"this article."})]})]}),value:this.props.ariaLabel||"",onChange:this.handleAriaLabel})}),jsxRuntimeExports.jsx("div",{className:css(styles$O.paddedY),children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Function variables",jsxRuntimeExports.jsx(InfoTip$l,{children:'Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means "f of x" and not "f times x".'})]}),value:this.state.functionsInternal,onChange:this.handleFunctions})}),jsxRuntimeExports.jsx("div",{className:css(styles$O.paddedY),children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Use × instead of ⋅ for multiplication",jsxRuntimeExports.jsx(InfoTip$l,{children:"For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."})]}),checked:this.props.times,onChange:newCheckedState=>{this.changeTimes(newCheckedState);}})}),jsxRuntimeExports.jsxs("div",{className:css(styles$O.paddedY),children:[jsxRuntimeExports.jsx(HeadingXSmall,{children:"Button Sets"}),buttonSetChoices]}),jsxRuntimeExports.jsx(HeadingSmall,{children:"Answers"}),jsxRuntimeExports.jsx(Caption,{style:styles$O.answersSubtitle,children:"student responses area matched against these from top to bottom"}),jsxRuntimeExports.jsx(View,{style:{gap:spacing.xSmall_8},children:answerOptions}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.newAnswer,children:"Add new answer"})]})}constructor(props){super(props),this.getSaveWarnings=()=>{const issues=[];if(this.props.answerForms.length===0){issues.push("No answers specified");}else {const hasCorrect=this.props.answerForms.some(form=>{return form.considered==="correct"});if(!hasCorrect){issues.push("No correct answer specified");}_(this.props.answerForms).each((form,ix)=>{if(this.props.value===""){issues.push(`Answer ${ix+1} is empty`);}else {const expression=KAS.parse(form.value,{functions:this.props.functions});if(!expression.parsed){issues.push(`Couldn't parse ${form.value}`);}else if(form.simplify&&!expression.expr.isSimplified()){issues.push(`${form.value} isn't simplified, but is required" +
1492
+ " to be`);}}});}return issues},this.newAnswer=()=>{const answerForms=this.props.answerForms.slice();const newKey=crypto.randomUUID();const newAnswerForm={considered:"correct",form:false,key:`${newKey}`,simplify:false,value:""};answerForms.push(newAnswerForm);this.props.onChange({answerForms});},this.handleRemoveForm=i=>{const updatedAnswerForms=this.props.answerForms.slice();updatedAnswerForms.splice(i,1);this.props.onChange({answerForms:updatedAnswerForms});},this.handleButtonSet=changingName=>{const buttonSetNames=buttonSetsList;const buttonSets=buttonSetNames.filter(set=>{return this.props.buttonSets.includes(set)!==(set===changingName)});this.props.onChange({buttonSets});},this.handleToggleDiv=()=>{let keep;let remove;if(this.props.buttonSets.includes("basic+div")){keep="basic";remove="basic+div";}else {keep="basic+div";remove="basic";}const buttonSets=this.props.buttonSets.filter(set=>set!==remove).concat(keep);this.props.onChange({buttonSets});},this.handleTexInsert=str=>{this.refs.expression.insert(str);},this.handleFunctions=value=>{this.setState({functionsInternal:value});const newProps={};newProps.functions=value.split(/[ ,]+/).filter(isTruthy);this.props.onChange(newProps);},this.handleVisibleLabel=visibleLabel=>{this.props.onChange({visibleLabel});},this.handleAriaLabel=ariaLabel=>{this.props.onChange({ariaLabel});},this.changeExpressionWidget=(index,input)=>{const answerForm={...this.props.answerForms[index],value:input};this.updateAnswerForm(index,answerForm);};this.state={functionsInternal:this.props.functions.join(" ")};}}ExpressionEditor.widgetName="expression";ExpressionEditor.defaultProps=expressionLogic.defaultWidgetOptions;const findNextIn=function(arr,val){let ix=arr.indexOf(val);ix=(ix+1)%arr.length;return arr[ix]};class AnswerOption extends React.Component{render(){const removeButton=this.state.deleteFocused?jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.handleImSure,actionType:"destructive",children:"I'm sure!"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.handleCancelDelete,kind:"secondary",children:"Cancel"})]}):jsxRuntimeExports.jsx(Button,{size:"small",onClick:this.handleDelete,actionType:"destructive",kind:"tertiary",style:styles$O.deleteButton,children:"Delete"});return jsxRuntimeExports.jsxs("div",{className:css(styles$O.answerOption),children:[jsxRuntimeExports.jsx(ButtonGroup$7,{onChange:this.toggleConsidered,allowEmpty:false,value:this.props.considered,selectedButtonStyle:consideredButtonStyles[this.props.considered],buttons:PerseusExpressionAnswerFormConsidered.map(c=>({value:c,content:c,title:`This answer will be considered ${c}`}))}),jsxRuntimeExports.jsx(Expression,{...this.props.expressionProps}),jsxRuntimeExports.jsx("div",{className:css(styles$O.paddedY,styles$O.paddedX),children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must have the same form.",jsxRuntimeExports.jsx(InfoTip$l,{children:"The student's answer must be in the same form. Commutativity and excess negative signs are ignored."})]}),checked:this.props.form,onChange:this.props.onChangeForm})}),jsxRuntimeExports.jsx("div",{className:css(styles$O.paddedY,styles$O.paddedX),children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must be fully expanded and simplified.",jsxRuntimeExports.jsx(InfoTip$l,{children:'The student\'s answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response "Your answer is not fully expanded and simplified."'})]}),checked:this.props.simplify,onChange:this.props.onChangeSimplify})}),jsxRuntimeExports.jsx("div",{className:css(styles$O.buttonRow,styles$O.paddedY),children:removeButton})]})}constructor(...args){super(...args),this.state={deleteFocused:false},this.handleImSure=()=>{this.props.onDelete();this.handleCancelDelete();},this.handleCancelDelete=()=>{this.setState({deleteFocused:false});},this.handleDelete=()=>{this.setState({deleteFocused:true});},this.toggleConsidered=()=>{const newVal=findNextIn(PerseusExpressionAnswerFormConsidered,this.props.considered);this.props.onChangeConsidered(newVal);};}}const styles$O=StyleSheet.create({paddedX:{paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8},paddedY:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxSmall_6},answersSubtitle:{fontStyle:"italic"},answerOption:{border:"1px solid #ddd",borderRadius:"3px",display:"flex",flexDirection:"column"},answerStatusWrong:{backgroundColor:color.fadedRed16},answerStatusCorrect:{backgroundColor:color.fadedGreen16},answerStatusUngraded:{backgroundColor:color.fadedBlue16},buttonRow:{display:"flex"},deleteButton:{paddingInline:sizing.size_160}});const consideredButtonStyles={wrong:styles$O.answerStatusWrong,correct:styles$O.answerStatusCorrect,ungraded:styles$O.answerStatusUngraded};
1491
1493
 
1492
- class FreeResponseEditor extends React.Component{render(){return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Question"}),field:jsxRuntimeExports.jsx("textarea",{value:this.props.question,onChange:e=>this.props.onChange({question:e.target.value})}),styles:{root:styles$M.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Placeholder"}),field:jsxRuntimeExports.jsx("textarea",{value:this.props.placeholder,onChange:e=>this.props.onChange({placeholder:e.target.value})}),styles:{root:styles$M.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Allow unlimited characters"}),field:jsxRuntimeExports.jsx(Checkbox$1,{checked:this.props.allowUnlimitedCharacters,onChange:val=>this.props.onChange({allowUnlimitedCharacters:val})}),styles:{root:styles$M.labeledInputField}}),!this.props.allowUnlimitedCharacters&&jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Character limit"}),field:jsxRuntimeExports.jsx("input",{type:"number",min:1,value:this.props.characterLimit,onChange:this.handleUpdateCharacterLimit}),styles:{root:styles$M.labeledInputField}}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(HeadingSmall,{children:"Scoring criteria"}),jsxRuntimeExports.jsx(View,{style:styles$M.criteriaList,children:this.renderCriteriaList()}),jsxRuntimeExports.jsx(View,{children:jsxRuntimeExports.jsx(Button,{onClick:this.handleAddCriterion,startIcon:plusCircle,children:"Add an item"})})]})]})}constructor(...args){super(...args),this.serialize=()=>{return {allowUnlimitedCharacters:this.props.allowUnlimitedCharacters,characterLimit:this.props.characterLimit,placeholder:this.props.placeholder,question:this.props.question,scoringCriteria:this.props.scoringCriteria}},this.getSaveWarnings=()=>{const warnings=[];if(!this.props.question){warnings.push("The question is empty");}if(this.props.question.match(Util.rWidgetRule)!=null){warnings.push("The question contains a widget");}return warnings},this.handleUpdateCharacterLimit=e=>{const val=parseInt(e.target.value);if(isNaN(val)){return}this.props.onChange({characterLimit:Math.max(1,val)});},this.handleUpdateCriterion=(index,criterion)=>{const newCriteria=this.props.scoringCriteria.map((c,i)=>{if(i===index){return criterion}return c});this.props.onChange({scoringCriteria:newCriteria});},this.handleDeleteCriterion=index=>{this.props.onChange({scoringCriteria:this.props.scoringCriteria.filter((_,i)=>i!==index)});},this.handleAddCriterion=()=>{this.props.onChange({scoringCriteria:[...this.props.scoringCriteria,{text:""}]});},this.renderCriteriaList=()=>{const isDeletable=this.props.scoringCriteria.length>1;return this.props.scoringCriteria.map((criterion,index)=>{return jsxRuntimeExports.jsx(CriterionEditor,{criterion:criterion,index:index,isDeletable:isDeletable,onChange:this.handleUpdateCriterion,onDelete:this.handleDeleteCriterion},index)})};}}FreeResponseEditor.defaultProps=freeResponseLogic.defaultWidgetOptions;FreeResponseEditor.widgetName="free-response";const CriterionEditor=function(props){return jsxRuntimeExports.jsxs(View,{style:styles$M.criterionContainer,children:[jsxRuntimeExports.jsx("textarea",{"aria-label":`Criterion ${props.index+1}`,onChange:e=>props.onChange(props.index,{text:e.target.value}),value:props.criterion.text}),props.isDeletable&&jsxRuntimeExports.jsx(View,{style:styles$M.deleteButtonContainer,children:jsxRuntimeExports.jsx(Button,{"aria-label":`Delete criterion ${props.index+1}`,actionType:"destructive",disabled:!props.isDeletable,kind:"tertiary",onClick:()=>props.onDelete(props.index),size:"small",startIcon:trashIcon,children:"Delete"})})]})};const styles$M=StyleSheet.create({criteriaList:{gap:spacing.small_12},criterionContainer:{paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,borderBottom:`1px solid ${semanticColor.core.border.neutral.subtle}`,":last-child":{borderBottom:"none"}},deleteButtonContainer:{display:"flex",flexDirection:"row",justifyContent:"flex-end"},labeledInputField:{paddingBottom:spacing.large_24}});
1494
+ class FreeResponseEditor extends React.Component{render(){return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Question"}),field:jsxRuntimeExports.jsx("textarea",{value:this.props.question,onChange:e=>this.props.onChange({question:e.target.value})}),styles:{root:styles$N.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Placeholder"}),field:jsxRuntimeExports.jsx("textarea",{value:this.props.placeholder,onChange:e=>this.props.onChange({placeholder:e.target.value})}),styles:{root:styles$N.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Allow unlimited characters"}),field:jsxRuntimeExports.jsx(Checkbox$1,{checked:this.props.allowUnlimitedCharacters,onChange:val=>this.props.onChange({allowUnlimitedCharacters:val})}),styles:{root:styles$N.labeledInputField}}),!this.props.allowUnlimitedCharacters&&jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(HeadingSmall,{children:"Character limit"}),field:jsxRuntimeExports.jsx("input",{type:"number",min:1,value:this.props.characterLimit,onChange:this.handleUpdateCharacterLimit}),styles:{root:styles$N.labeledInputField}}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(HeadingSmall,{children:"Scoring criteria"}),jsxRuntimeExports.jsx(View,{style:styles$N.criteriaList,children:this.renderCriteriaList()}),jsxRuntimeExports.jsx(View,{children:jsxRuntimeExports.jsx(Button,{onClick:this.handleAddCriterion,startIcon:plusCircle,children:"Add an item"})})]})]})}constructor(...args){super(...args),this.serialize=()=>{return {allowUnlimitedCharacters:this.props.allowUnlimitedCharacters,characterLimit:this.props.characterLimit,placeholder:this.props.placeholder,question:this.props.question,scoringCriteria:this.props.scoringCriteria}},this.getSaveWarnings=()=>{const warnings=[];if(!this.props.question){warnings.push("The question is empty");}if(this.props.question.match(Util.rWidgetRule)!=null){warnings.push("The question contains a widget");}return warnings},this.handleUpdateCharacterLimit=e=>{const val=parseInt(e.target.value);if(isNaN(val)){return}this.props.onChange({characterLimit:Math.max(1,val)});},this.handleUpdateCriterion=(index,criterion)=>{const newCriteria=this.props.scoringCriteria.map((c,i)=>{if(i===index){return criterion}return c});this.props.onChange({scoringCriteria:newCriteria});},this.handleDeleteCriterion=index=>{this.props.onChange({scoringCriteria:this.props.scoringCriteria.filter((_,i)=>i!==index)});},this.handleAddCriterion=()=>{this.props.onChange({scoringCriteria:[...this.props.scoringCriteria,{text:""}]});},this.renderCriteriaList=()=>{const isDeletable=this.props.scoringCriteria.length>1;return this.props.scoringCriteria.map((criterion,index)=>{return jsxRuntimeExports.jsx(CriterionEditor,{criterion:criterion,index:index,isDeletable:isDeletable,onChange:this.handleUpdateCriterion,onDelete:this.handleDeleteCriterion},index)})};}}FreeResponseEditor.defaultProps=freeResponseLogic.defaultWidgetOptions;FreeResponseEditor.widgetName="free-response";const CriterionEditor=function(props){return jsxRuntimeExports.jsxs(View,{style:styles$N.criterionContainer,children:[jsxRuntimeExports.jsx("textarea",{"aria-label":`Criterion ${props.index+1}`,onChange:e=>props.onChange(props.index,{text:e.target.value}),value:props.criterion.text}),props.isDeletable&&jsxRuntimeExports.jsx(View,{style:styles$N.deleteButtonContainer,children:jsxRuntimeExports.jsx(Button,{"aria-label":`Delete criterion ${props.index+1}`,actionType:"destructive",disabled:!props.isDeletable,kind:"tertiary",onClick:()=>props.onDelete(props.index),size:"small",startIcon:trashIcon,children:"Delete"})})]})};const styles$N=StyleSheet.create({criteriaList:{gap:spacing.small_12},criterionContainer:{paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,borderBottom:`1px solid ${semanticColor.core.border.neutral.subtle}`,":last-child":{borderBottom:"none"}},deleteButtonContainer:{display:"flex",flexDirection:"row",justifyContent:"flex-end"},labeledInputField:{paddingBottom:spacing.large_24}});
1493
1495
 
1494
- const{InlineIcon: InlineIcon$2,TextInput: TextInput$5}=components;class GradedGroupEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-group-editor",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{className:css(styles$L.title),children:["Title:"," ",jsxRuntimeExports.jsx(TextInput$5,{value:this.props.title,className:css(styles$L.input),onChange:this.change("title")})]})}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,content:this.props.content,widgets:this.props.widgets,apiOptions:this.props.apiOptions,images:this.props.images,widgetEnabled:true,immutableWidgets:false,onChange:this.props.onChange,warnNoPrompt:true,warnNoWidgets:true}),!this.props.hint&&jsxRuntimeExports.jsxs("button",{type:"button",style:{marginTop:10},className:"add-hint simple-button orange",onClick:this.handleAddHint,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconPlus})," Add a hint"]}),this.props.hint&&jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor",children:[jsxRuntimeExports.jsx("div",{className:css(styles$L.hintsTitle),children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.hintEditor,content:this.props.hint?this.props.hint.content:"",widgets:this.props.hint?this.props.hint.widgets:{},apiOptions:this.props.apiOptions,images:this.props.hint&&this.props.hint.images,widgetEnabled:true,immutableWidgets:false,onChange:props=>{this.change("hint",Object.assign({},this.props.hint,props));}}),jsxRuntimeExports.jsxs("button",{type:"button",className:"remove-hint simple-button orange",onClick:this.handleRemoveHint,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconTrash})," Remove this hint"]})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.hintEditor=React.createRef(),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.handleAddHint=()=>{const hint={content:""};this.props.onChange({hint},()=>{this.hintEditor.current?.focus();});},this.handleRemoveHint=e=>{this.props.onChange({hint:null});},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=()=>{return {title:this.props.title,...this.editor.current?.serialize(),hint:this.hintEditor.current?.serialize()}};}}GradedGroupEditor.propTypes={...Changeable.propTypes,title:PropTypes.string,content:PropTypes.string,widgets:PropTypes.object,images:PropTypes.object,apiOptions:ApiOptions.propTypes};GradedGroupEditor.widgetName="graded-group";GradedGroupEditor.defaultProps=gradedGroupLogic.defaultWidgetOptions;const styles$L=StyleSheet.create({title:{fontSize:18,fontWeight:"bold"},input:{fontSize:18},hintsTitle:{marginTop:10,fontSize:"110%",fontWeight:"bold"}});
1496
+ const{InlineIcon: InlineIcon$2,TextInput: TextInput$5}=components;class GradedGroupEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-group-editor",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{className:css(styles$M.title),children:["Title:"," ",jsxRuntimeExports.jsx(TextInput$5,{value:this.props.title,className:css(styles$M.input),onChange:this.change("title")})]})}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,content:this.props.content,widgets:this.props.widgets,apiOptions:this.props.apiOptions,images:this.props.images,widgetEnabled:true,immutableWidgets:false,onChange:this.props.onChange,warnNoPrompt:true,warnNoWidgets:true}),!this.props.hint&&jsxRuntimeExports.jsxs("button",{type:"button",style:{marginTop:10},className:"add-hint simple-button orange",onClick:this.handleAddHint,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconPlus})," Add a hint"]}),this.props.hint&&jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor",children:[jsxRuntimeExports.jsx("div",{className:css(styles$M.hintsTitle),children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.hintEditor,content:this.props.hint?this.props.hint.content:"",widgets:this.props.hint?this.props.hint.widgets:{},apiOptions:this.props.apiOptions,images:this.props.hint&&this.props.hint.images,widgetEnabled:true,immutableWidgets:false,onChange:props=>{this.change("hint",Object.assign({},this.props.hint,props));}}),jsxRuntimeExports.jsxs("button",{type:"button",className:"remove-hint simple-button orange",onClick:this.handleRemoveHint,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconTrash})," Remove this hint"]})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.hintEditor=React.createRef(),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.handleAddHint=()=>{const hint={content:"",images:{},widgets:{}};this.props.onChange({hint},()=>{this.hintEditor.current?.focus();});},this.handleRemoveHint=e=>{this.props.onChange({hint:null});},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=()=>{return {title:this.props.title,...this.editor.current?.serialize(),hint:this.hintEditor.current?.serialize()}};}}GradedGroupEditor.propTypes={...Changeable.propTypes,title:PropTypes.string,content:PropTypes.string,widgets:PropTypes.object,images:PropTypes.object,apiOptions:ApiOptions.propTypes};GradedGroupEditor.widgetName="graded-group";GradedGroupEditor.defaultProps=gradedGroupLogic.defaultWidgetOptions;const styles$M=StyleSheet.create({title:{fontSize:18,fontWeight:"bold"},input:{fontSize:18},hintsTitle:{marginTop:10,fontSize:"110%",fontWeight:"bold"}});
1495
1497
 
1496
1498
  class GradedGroupSetEditor extends React.Component{UNSAFE_componentWillMount(){this._editors=[];}render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-group-editor",children:[this.renderGroups(),jsxRuntimeExports.jsx("button",{onClick:this.addGroup,children:"Add group"})]})}constructor(...args){super(...args),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.getSaveWarnings=()=>{return [].concat(...this._editors.map(editor=>editor?editor.getSaveWarnings():[]))},this.serialize=()=>{return {gradedGroups:this.props.gradedGroups}},this.renderGroups=()=>{if(!this.props.gradedGroups){return null}return this.props.gradedGroups.map((group,i)=>jsxRuntimeExports.jsx(GradedGroupEditor,{ref:el=>this._editors[i]=el,...group,apiOptions:this.props.apiOptions,widgetEnabled:true,immutableWidgets:false,onChange:data=>this.change("gradedGroups",setArrayItem(this.props.gradedGroups,i,{...this.props.gradedGroups[i],...data}))},i))},this.addGroup=()=>{const groups=this.props.gradedGroups||[];this.change("gradedGroups",groups.concat([GradedGroupEditor.defaultProps]));};}}GradedGroupSetEditor.propTypes={...Changeable.propTypes,apiOptions:ApiOptions.propTypes,gradedGroups:PropTypes.array,onChange:PropTypes.func.isRequired};GradedGroupSetEditor.widgetName="graded-group-set";GradedGroupSetEditor.defaultProps=gradedGroupSetLogic.defaultWidgetOptions;const setArrayItem=(list,i,value)=>[...list.slice(0,i),value,...list.slice(i+1)];
1497
1499
 
@@ -1513,7 +1515,7 @@ const{ButtonGroup: ButtonGroup$5}=components;const COLORS=[KhanColors.BLACK,Khan
1513
1515
 
1514
1516
  const{ButtonGroup: ButtonGroup$4}=components;class DashPicker extends React.Component{render(){return jsxRuntimeExports.jsx(ButtonGroup$4,{value:this.props.value,allowEmpty:false,buttons:[{value:"",content:jsxRuntimeExports.jsx("span",{children:"—"})},{value:"-",content:jsxRuntimeExports.jsx("span",{children:"–––"})},{value:"- ",content:jsxRuntimeExports.jsx("span",{children:"–  –"})},{value:".",content:jsxRuntimeExports.jsx("span",{children:"····"})},{value:". ",content:jsxRuntimeExports.jsx("span",{children:"· · ·"})}],onChange:this.props.onChange})}}DashPicker.defaultProps={value:""};
1515
1517
 
1516
- function MathquillInput(props){const mathFieldWrapperRef=useRef(null);const mathFieldInstance=useRef();const{locale,strings}=useMathInputI18n();useEffect(()=>{if(mathFieldWrapperRef.current&&!mathFieldInstance.current){mathFieldInstance.current=createMathField(mathFieldWrapperRef.current,locale,strings,baseConfig=>({...baseConfig,handlers:{edit:mathField=>{let value=mathField.latex();value=value.replace(/<>/g,"\\ne");if(props.value!==value){props.onChange(value);}},upOutOf:mathField=>{mathField.typedText("^");}}}));}});return jsxRuntimeExports.jsx(View,{style:styles$K.outerWrapper,children:jsxRuntimeExports.jsx("span",{ref:mathFieldWrapperRef,className:"perseus-math-input mq-editable-field mq-math-mode"})})}const styles$K=StyleSheet.create({outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:color.offBlack50,borderRadius:3,background:color.white}});
1518
+ function MathquillInput(props){const mathFieldWrapperRef=useRef(null);const mathFieldInstance=useRef();const{locale,strings}=useMathInputI18n();useEffect(()=>{if(mathFieldWrapperRef.current&&!mathFieldInstance.current){mathFieldInstance.current=createMathField(mathFieldWrapperRef.current,locale,strings,baseConfig=>({...baseConfig,handlers:{edit:mathField=>{let value=mathField.latex();value=value.replace(/<>/g,"\\ne");if(props.value!==value){props.onChange(value);}},upOutOf:mathField=>{mathField.typedText("^");}}}));}});return jsxRuntimeExports.jsx(View,{style:styles$L.outerWrapper,children:jsxRuntimeExports.jsx("span",{ref:mathFieldWrapperRef,className:"perseus-math-input mq-editable-field mq-math-mode"})})}const styles$L=StyleSheet.create({outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:color.offBlack50,borderRadius:3,background:color.white}});
1517
1519
 
1518
1520
  const{NumberInput: NumberInput$d}=components;const{getDependencies: getDependencies$8}=Dependencies;class FunctionEditor extends React.Component{render(){const{TeX}=getDependencies$8();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:this.props.funcName+"(x)="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.value,onChange:this.change("value")})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Range: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.rangeMin,onChange:this.change("rangeMin")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.rangeMax,onChange:this.change("rangeMax")}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,onChange:this.change("color")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(DashPicker,{value:this.props.strokeDasharray,onChange:this.change("strokeDasharray")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:["Width:"," ",jsxRuntimeExports.jsx(NumberInput$d,{value:this.props.strokeWidth,placeholder:2,onChange:this.change("strokeWidth")})]})})]})}constructor(...args){super(...args),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}FunctionEditor.defaultProps={value:"x",rangeMin:"-10",rangeMax:"10",color:KhanColors.BLUE,strokeDasharray:"",strokeWidth:2};
1519
1521
 
@@ -1539,109 +1541,109 @@ const{getDependencies}=Dependencies;const{unescapeMathMode}=Util;class Interacti
1539
1541
 
1540
1542
  const UNLIMITED="unlimited";const parsePointCount=points=>{const parsed=parseInt(points,10);if(isNaN(parsed)){return UNLIMITED}return parsed===0?UNLIMITED:parsed};
1541
1543
 
1542
- const GraphPointsCountSelector=({numPoints=1,onChange})=>{return jsxRuntimeExports.jsx(SingleSelect,{selectedValue:`${numPoints}`,onChange:newValue=>{onChange(parsePointCount(newValue));},placeholder:"",style:styles$J.singleSelectShort,children:[...[...Array(7).keys()].map(n=>jsxRuntimeExports.jsx(OptionItem,{value:`${n}`,label:`${n} point${n>1?"s":""}`},n)),jsxRuntimeExports.jsx(OptionItem,{value:UNLIMITED,label:"unlimited"},"unlimited")]})};const styles$J=StyleSheet.create({singleSelectShort:{height:26}});
1544
+ const GraphPointsCountSelector=({numPoints=1,onChange})=>{return jsxRuntimeExports.jsx(SingleSelect,{selectedValue:`${numPoints}`,onChange:newValue=>{onChange(parsePointCount(newValue));},placeholder:"",style:styles$K.singleSelectShort,children:[...[...Array(7).keys()].map(n=>jsxRuntimeExports.jsx(OptionItem,{value:`${n}`,label:`${n} point${n>1?"s":""}`},n)),jsxRuntimeExports.jsx(OptionItem,{value:UNLIMITED,label:"unlimited"},"unlimited")]})};const styles$K=StyleSheet.create({singleSelectShort:{height:26}});
1543
1545
 
1544
- const GraphTypeSelector=props=>{return jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:props.graphType,onChange:props.onChange,placeholder:"Select an answer type",style:styles$I.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"none",label:"None"}),jsxRuntimeExports.jsx(OptionItem,{value:"linear",label:"Linear function"}),jsxRuntimeExports.jsx(OptionItem,{value:"quadratic",label:"Quadratic function"}),jsxRuntimeExports.jsx(OptionItem,{value:"sinusoid",label:"Sinusoid function"}),jsxRuntimeExports.jsx(OptionItem,{value:"circle",label:"Circle"}),jsxRuntimeExports.jsx(OptionItem,{value:"point",label:"Point(s)"}),jsxRuntimeExports.jsx(OptionItem,{value:"linear-system",label:"Linear System"}),jsxRuntimeExports.jsx(OptionItem,{value:"polygon",label:"Polygon"}),jsxRuntimeExports.jsx(OptionItem,{value:"segment",label:"Line Segment(s)"}),jsxRuntimeExports.jsx(OptionItem,{value:"ray",label:"Ray"}),jsxRuntimeExports.jsx(OptionItem,{value:"angle",label:"Angle"})]})};const styles$I=StyleSheet.create({singleSelectShort:{height:26}});
1546
+ const GraphTypeSelector=props=>{return jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:props.graphType,onChange:props.onChange,placeholder:"Select an answer type",style:styles$J.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"none",label:"None"}),jsxRuntimeExports.jsx(OptionItem,{value:"linear",label:"Linear function"}),jsxRuntimeExports.jsx(OptionItem,{value:"quadratic",label:"Quadratic function"}),jsxRuntimeExports.jsx(OptionItem,{value:"sinusoid",label:"Sinusoid function"}),jsxRuntimeExports.jsx(OptionItem,{value:"circle",label:"Circle"}),jsxRuntimeExports.jsx(OptionItem,{value:"point",label:"Point(s)"}),jsxRuntimeExports.jsx(OptionItem,{value:"linear-system",label:"Linear System"}),jsxRuntimeExports.jsx(OptionItem,{value:"polygon",label:"Polygon"}),jsxRuntimeExports.jsx(OptionItem,{value:"segment",label:"Line Segment(s)"}),jsxRuntimeExports.jsx(OptionItem,{value:"ray",label:"Ray"}),jsxRuntimeExports.jsx(OptionItem,{value:"angle",label:"Angle"})]})};const styles$J=StyleSheet.create({singleSelectShort:{height:26}});
1545
1547
 
1546
- function Heading({title,isOpen,isCollapsible,onToggle}){return jsxRuntimeExports.jsx(Clickable,{style:[styles$H.container,!isCollapsible&&styles$H.notClickable],disabled:!isCollapsible,onClick:()=>isCollapsible&&onToggle?.(!isOpen),children:()=>jsxRuntimeExports.jsxs(View,{style:styles$H.heading,children:[jsxRuntimeExports.jsx(LabelLarge,{style:{fontSize:14,fontWeight:600},children:title}),isCollapsible&&jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:isOpen})]})})}const styles$H=StyleSheet.create({container:{marginTop:spacing.small_12,marginInline:-10,backgroundColor:color.offBlack8,padding:spacing.xSmall_8,width:"calc(100% + 20px)"},heading:{flexDirection:"row",justifyContent:"space-between",userSelect:"none"},notClickable:{color:"inherit",cursor:"default"}});
1548
+ function Heading({title,isOpen,isCollapsible,onToggle}){return jsxRuntimeExports.jsx(Clickable,{style:[styles$I.container,!isCollapsible&&styles$I.notClickable],disabled:!isCollapsible,onClick:()=>isCollapsible&&onToggle?.(!isOpen),children:()=>jsxRuntimeExports.jsxs(View,{style:styles$I.heading,children:[jsxRuntimeExports.jsx(LabelLarge,{style:{fontSize:14,fontWeight:600},children:title}),isCollapsible&&jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:isOpen})]})})}const styles$I=StyleSheet.create({container:{marginTop:spacing.small_12,marginInline:-10,backgroundColor:color.offBlack8,padding:spacing.xSmall_8,width:"calc(100% + 20px)"},heading:{flexDirection:"row",justifyContent:"space-between",userSelect:"none"},notClickable:{color:"inherit",cursor:"default"}});
1547
1549
 
1548
1550
  function InteractiveGraphCorrectAnswer(props){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Correct Answer",isOpen:true,isCollapsible:false}),jsxRuntimeExports.jsxs(View,{id:props.id,children:[jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabelXSmall,{style:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxSmall_6,color:color.offBlack64},children:"Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."}),jsxRuntimeExports.jsx(BodyMonospace,{style:{fontSize:12,backgroundColor:"#eee",paddingInline:spacing.xxSmall_6,borderColor:"#ccc",borderStyle:"solid",borderWidth:1},children:props.equationString})]}),props.children]})]})}
1549
1551
 
1550
- function InteractiveGraphDescription(props){const{ariaLabelValue,ariaDescriptionValue,onChange}=props;const[isOpen,setIsOpen]=React.useState(true);return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Description",isCollapsible:true,isOpen:isOpen,onToggle:setIsOpen}),isOpen&&jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabelXSmall,{style:styles$G.caption,children:"Use these fields to describe the graph as a whole. These are used by screen readers to describe content to users who may be visually impaired."}),jsxRuntimeExports.jsxs(LabelLarge,{tag:"label",children:["Title",jsxRuntimeExports.jsx(TextField,{value:ariaLabelValue,onChange:newValue=>onChange({fullGraphAriaLabel:newValue||undefined}),style:styles$G.spaceAbove})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsxs(LabelLarge,{tag:"label",children:["Description",jsxRuntimeExports.jsx(TextArea,{rows:8,resizeType:"vertical",value:ariaDescriptionValue,onChange:newValue=>onChange({fullGraphAriaDescription:newValue||undefined}),style:styles$G.spaceAbove})]})]})]})}const styles$G=StyleSheet.create({caption:{color:color.offBlack64,paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxSmall_6},spaceAbove:{marginTop:spacing.xxxSmall_4}});
1552
+ function InteractiveGraphDescription(props){const{ariaLabelValue,ariaDescriptionValue,onChange}=props;const[isOpen,setIsOpen]=React.useState(true);return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Description",isCollapsible:true,isOpen:isOpen,onToggle:setIsOpen}),isOpen&&jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabelXSmall,{style:styles$H.caption,children:"Use these fields to describe the graph as a whole. These are used by screen readers to describe content to users who may be visually impaired."}),jsxRuntimeExports.jsxs(LabelLarge,{tag:"label",children:["Title",jsxRuntimeExports.jsx(TextField,{value:ariaLabelValue,onChange:newValue=>onChange({fullGraphAriaLabel:newValue||undefined}),style:styles$H.spaceAbove})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsxs(LabelLarge,{tag:"label",children:["Description",jsxRuntimeExports.jsx(TextArea,{rows:8,resizeType:"vertical",value:ariaDescriptionValue,onChange:newValue=>onChange({fullGraphAriaDescription:newValue||undefined}),style:styles$H.spaceAbove})]})]})]})}const styles$H=StyleSheet.create({caption:{color:color.offBlack64,paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxSmall_6},spaceAbove:{marginTop:spacing.xxxSmall_4}});
1551
1553
 
1552
- const LabeledRow=props=>{const{children,label,labelSide="left",style}=props;return jsxRuntimeExports.jsx("label",{className:css(styles$F.label),children:jsxRuntimeExports.jsxs(View,{style:[styles$F.row,style],children:[labelSide==="start"||jsxRuntimeExports.jsx(LabelSmall,{style:styles$F.spaceEnd,children:label}),children,labelSide==="end"&&jsxRuntimeExports.jsx(LabelSmall,{style:styles$F.spaceStart,children:label})]})})};const styles$F=StyleSheet.create({label:{width:"fit-content"},row:{flexDirection:"row",marginTop:spacing.xSmall_8,alignItems:"center",width:"fit-content"},spaceStart:{marginInlineStart:spacing.xSmall_8},spaceEnd:{marginInlineEnd:spacing.xSmall_8}});
1554
+ const LabeledRow=props=>{const{children,label,labelSide="left",style}=props;return jsxRuntimeExports.jsx("label",{className:css(styles$G.label),children:jsxRuntimeExports.jsxs(View,{style:[styles$G.row,style],children:[labelSide==="start"||jsxRuntimeExports.jsx(LabelSmall,{style:styles$G.spaceEnd,children:label}),children,labelSide==="end"&&jsxRuntimeExports.jsx(LabelSmall,{style:styles$G.spaceStart,children:label})]})})};const styles$G=StyleSheet.create({label:{width:"fit-content"},row:{flexDirection:"row",marginTop:spacing.xSmall_8,alignItems:"center",width:"fit-content"},spaceStart:{marginInlineStart:spacing.xSmall_8},spaceEnd:{marginInlineEnd:spacing.xSmall_8}});
1553
1555
 
1554
- const{ButtonGroup: ButtonGroup$1,InfoTip: InfoTip$g,RangeInput: RangeInput$4}=components;const defaultBackgroundImage={url:null,width:0,height:0};function numSteps(range,step){return Math.floor((range[1]-range[0])/step)}class InteractiveGraphSettings extends React.Component{static stateFromProps(props){return {labelsTextbox:props.labels,labelLocation:props.labelLocation,gridStepTextbox:props.gridStep,snapStepTextbox:props.snapStep,stepTextbox:props.step,rangeTextbox:props.range,backgroundImage:{...props.backgroundImage}}}componentDidMount(){this._isMounted=true;this.changeGraph=_.debounce(this.changeGraph,300);}UNSAFE_componentWillReceiveProps(nextProps){if(!_.isEqual(this.props.labels,nextProps.labels)||!_.isEqual(this.props.labelLocation,nextProps.labelLocation)||!_.isEqual(this.props.gridStep,nextProps.gridStep)||!_.isEqual(this.props.snapStep,nextProps.snapStep)||!_.isEqual(this.props.step,nextProps.step)||!_.isEqual(this.props.range,nextProps.range)||!_.isEqual(this.props.backgroundImage,nextProps.backgroundImage)){this.setState(InteractiveGraphSettings.stateFromProps(nextProps));}}componentWillUnmount(){this._isMounted=false;}render(){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Common Graph Settings",isOpen:this.state.isExpanded,isCollapsible:true,onToggle:()=>this.setState({isExpanded:!this.state.isExpanded})}),this.state.isExpanded&&jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Label Location",children:jsxRuntimeExports.jsx(ButtonGroup$1,{value:this.props.labelLocation,allowEmpty:false,buttons:[{value:"onAxis",content:"On Axis"},{value:"alongEdge",content:"Along Graph Edge"}],onChange:this.change("labelLocation")})})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"x Label",children:jsxRuntimeExports.jsx("input",{type:"text",className:"graph-settings-axis-label",ref:this.labelXRef,onChange:e=>this.changeLabel(0,e),value:this.state.labelsTextbox[0]||""})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"y Label",children:jsxRuntimeExports.jsx("input",{type:"text",className:"graph-settings-axis-label",ref:this.labelYRef,onChange:e=>this.changeLabel(1,e),value:this.state.labelsTextbox[1]||""})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"x Range",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.rangeTextbox[0],onChange:vals=>this.changeRange(0,vals),allowPiTruncation:true})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"y Range",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.rangeTextbox[1],onChange:vals=>this.changeRange(1,vals),allowPiTruncation:true})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Tick Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.stepTextbox,onChange:this.changeStep,allowPiTruncation:true})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Grid Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.gridStepTextbox,onChange:this.changeGridStep,allowPiTruncation:true})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Snap Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.snapStepTextbox,onChange:this.changeSnapStep,allowPiTruncation:true})})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-right-col",children:[jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",onClick:()=>{this.changeStepsBasedOnRange();},children:"Auto-adjust steps"}),jsxRuntimeExports.jsxs(InfoTip$g,{children:[jsxRuntimeExports.jsx("p",{children:'Use the "Auto-adjust" steps button to update the tick step, grid step, and snap step to values that are valid for the current range.'}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("p",{children:"This is useful when the range is changed, and the graph errors due to the step sizes being too large or too small."})]})]})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Markings:",children:jsxRuntimeExports.jsx(ButtonGroup$1,{value:this.props.markings,allowEmpty:false,buttons:[{value:"axes",content:"Axes"},{value:"graph",content:"Graph"},{value:"grid",content:"Grid"},{value:"none",content:"None"}],onChange:this.change("markings")})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tooltips",checked:this.props.showTooltips,onChange:value=>{this.change({showTooltips:value});}})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Background image URL:",style:styles$E.resetSpaceTop,children:[jsxRuntimeExports.jsx("input",{type:"text",className:css(styles$E.backgroundUrlInput),ref:this.bgUrlRef,value:this.state.backgroundImage.url||"",onChange:e=>{const image={...this.props.backgroundImage};image.url=e.target.value;this.setState({backgroundImage:image});},onKeyPress:this.changeBackgroundUrl,onBlur:this.changeBackgroundUrl}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]}),jsxRuntimeExports.jsxs(View,{style:styles$E.protractorSection,children:[jsxRuntimeExports.jsx(View,{style:styles$E.checkboxRow,children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.change({showProtractor:value});},style:styles$E.resetSpaceTop})}),this.props.showProtractor&&jsxRuntimeExports.jsx(Banner,{layout:"floating",text:"The protractor is not accessible. Please consider an alternate approach.",kind:"warning"})]})]})]})}constructor(props){super(props),this._isMounted=false,this.bgUrlRef=React.createRef(),this.labelXRef=React.createRef(),this.labelYRef=React.createRef(),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.changeBackgroundUrl=e=>{if(e.type==="keypress"&&e.key!=="Enter"){return}const setUrl=(url,width,height)=>{const image={...this.props.backgroundImage};image.url=url;image.width=width;image.height=height;this.setState({backgroundImage:image},this.changeGraph);};const url=this.bgUrlRef.current?.value;if(url){Util.getImageSize(url,(width,height)=>{if(this._isMounted){setUrl(url,width,height);}});}else {setUrl(null,0,0);}},this.renderLabelChoices=choices=>{return choices.map(nameAndValue=>jsxRuntimeExports.jsx("option",{value:nameAndValue[1],children:nameAndValue[0]},nameAndValue[1]))},this.validRange=range=>{const numbers=_.every(range,function(num){return _.isFinite(num)});if(!numbers){return "Range must be a valid number"}if(range[0]>=range[1]){return "Range must have a higher number on the right"}return true},this.validateStepValue=settings=>{const{step,range,name,minTicks,maxTicks}=settings;const nSteps=numSteps(range,step);if(nSteps<minTicks){return name+" is too large, there must be at least "+minTicks+" ticks."}if(nSteps>maxTicks){return name+" is too small, there can be at most "+maxTicks+" ticks."}return true},this.validSnapStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Snap step",minTicks:5,maxTicks:60})},this.validGridStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Grid step",minTicks:3,maxTicks:60})},this.validStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Step",minTicks:3,maxTicks:20})},this.validBackgroundImageSize=image=>{if(!image.url){return true}const validSize=image.width<=450&&image.height<=450;if(!validSize){return "Image must be smaller than 450px x 450px."}return true},this.validateGraphSettings=(range,step,gridStep,snapStep,image)=>{const self=this;let msg;const goodRange=_.every(range,function(range){msg=self.validRange(range);return msg===true});if(!goodRange){return msg}const goodStep=_.every(step,function(step,i){msg=self.validStep(step,range[i]);return msg===true});if(!goodStep){return msg}const goodGridStep=_.every(gridStep,function(gridStep,i){msg=self.validGridStep(gridStep,range[i]);return msg===true});if(!goodGridStep){return msg}const goodSnapStep=_.every(snapStep,function(snapStep,i){msg=self.validSnapStep(snapStep,range[i]);return msg===true});if(!goodSnapStep){return msg}const goodImageSize=this.validBackgroundImageSize(image);if(goodImageSize!==true){msg=goodImageSize;return msg}return true},this.changeLabel=(i,e)=>{const val=e.target.value;const labels=this.state.labelsTextbox.slice();labels[i]=val;this.setState({labelsTextbox:labels},this.changeGraph);},this.changeRange=(i,values)=>{const ranges=this.state.rangeTextbox.slice();ranges[i]=values;this.setState({rangeTextbox:ranges},this.changeGraph);},this.changeStepsBasedOnRange=()=>{const ranges=this.state.rangeTextbox.slice();const step=this.state.stepTextbox.slice();const gridStep=this.state.gridStepTextbox.slice();const snapStep=this.state.snapStepTextbox.slice();const scaleX=Util.scaleFromExtent(ranges[0],this.props.box[0]);if(this.validRange(ranges[0])===true){step[0]=Util.tickStepFromExtent(ranges[0],this.props.box[0]);const gridStepValue=Util.gridStepFromTickStep(step[0],scaleX);if(gridStepValue){gridStep[0]=gridStepValue;}snapStep[0]=gridStep[0]/2;}const scaleY=Util.scaleFromExtent(ranges[1],this.props.box[1]);if(this.validRange(ranges[1])===true){step[1]=Util.tickStepFromExtent(ranges[1],this.props.box[1]);const gridStepValue=Util.gridStepFromTickStep(step[1],scaleY);if(gridStepValue){gridStep[1]=gridStepValue;}snapStep[1]=gridStep[1]/2;}this.setState({stepTextbox:step,gridStepTextbox:gridStep,snapStepTextbox:snapStep,rangeTextbox:ranges},this.changeGraph);},this.changeStep=step=>{this.setState({stepTextbox:step},this.changeGraph);},this.changeSnapStep=snapStep=>{this.setState({snapStepTextbox:snapStep},this.changeGraph);},this.changeGridStep=gridStep=>{this.setState({gridStepTextbox:gridStep,snapStepTextbox:_.map(gridStep,function(step){return step/2})},this.changeGraph);},this.changeGraph=()=>{const labels=this.state.labelsTextbox;const labelLocation=this.state.labelLocation;const range=_.map(this.state.rangeTextbox,function(range){return _.map(range,Number)});const step=_.map(this.state.stepTextbox,Number);const gridStep=this.state.gridStepTextbox;const snapStep=this.state.snapStepTextbox;const image=this.state.backgroundImage;const validationResult=this.validateGraphSettings(range,step,gridStep,snapStep,image);if(validationResult===true){this.change({valid:true,labels:labels,labelLocation:labelLocation,range:range,step:step,gridStep:gridStep,snapStep:snapStep,backgroundImage:image});}else {this.change({valid:validationResult});}};this.state={isExpanded:true,...InteractiveGraphSettings.stateFromProps(props)};}}InteractiveGraphSettings.defaultProps={box:[interactiveSizes.defaultBoxSizeSmall,interactiveSizes.defaultBoxSizeSmall],labels:["$x$","$y$"],labelLocation:"onAxis",range:[[-10,10],[-10,10]],step:[1,1],gridStep:[1,1],snapStep:[1,1],valid:true,backgroundImage:defaultBackgroundImage,markings:"graph",showProtractor:false,showTooltips:false};const styles$E=StyleSheet.create({resetSpaceTop:{marginTop:0},backgroundUrlInput:{border:`1px solid ${color.offBlack32}`,borderRadius:spacing.xxxSmall_4,padding:spacing.xxxSmall_4},checkboxRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:spacing.xSmall_8},protractorSection:{marginTop:spacing.xSmall_8,borderTop:`1px solid ${color.offBlack16}`,paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,borderBottom:`1px solid ${color.offBlack16}`}});
1556
+ const{ButtonGroup: ButtonGroup$1,InfoTip: InfoTip$g,RangeInput: RangeInput$4}=components;const defaultBackgroundImage={url:null,width:0,height:0};function numSteps(range,step){return Math.floor((range[1]-range[0])/step)}class InteractiveGraphSettings extends React.Component{static stateFromProps(props){return {labelsTextbox:props.labels,labelLocation:props.labelLocation,gridStepTextbox:props.gridStep,snapStepTextbox:props.snapStep,stepTextbox:props.step,rangeTextbox:props.range,backgroundImage:{...props.backgroundImage}}}componentDidMount(){this._isMounted=true;this.changeGraph=_.debounce(this.changeGraph,300);}UNSAFE_componentWillReceiveProps(nextProps){if(!_.isEqual(this.props.labels,nextProps.labels)||!_.isEqual(this.props.labelLocation,nextProps.labelLocation)||!_.isEqual(this.props.gridStep,nextProps.gridStep)||!_.isEqual(this.props.snapStep,nextProps.snapStep)||!_.isEqual(this.props.step,nextProps.step)||!_.isEqual(this.props.range,nextProps.range)||!_.isEqual(this.props.backgroundImage,nextProps.backgroundImage)){this.setState(InteractiveGraphSettings.stateFromProps(nextProps));}}componentWillUnmount(){this._isMounted=false;}render(){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Common Graph Settings",isOpen:this.state.isExpanded,isCollapsible:true,onToggle:()=>this.setState({isExpanded:!this.state.isExpanded})}),this.state.isExpanded&&jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Label Location",children:jsxRuntimeExports.jsx(ButtonGroup$1,{value:this.props.labelLocation,allowEmpty:false,buttons:[{value:"onAxis",content:"On Axis"},{value:"alongEdge",content:"Along Graph Edge"}],onChange:this.change("labelLocation")})})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"x Label",children:jsxRuntimeExports.jsx("input",{type:"text",className:"graph-settings-axis-label",ref:this.labelXRef,onChange:e=>this.changeLabel(0,e),value:this.state.labelsTextbox[0]||""})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"y Label",children:jsxRuntimeExports.jsx("input",{type:"text",className:"graph-settings-axis-label",ref:this.labelYRef,onChange:e=>this.changeLabel(1,e),value:this.state.labelsTextbox[1]||""})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"x Range",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.rangeTextbox[0],onChange:vals=>this.changeRange(0,vals),allowPiTruncation:true})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"y Range",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.rangeTextbox[1],onChange:vals=>this.changeRange(1,vals),allowPiTruncation:true})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Tick Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.stepTextbox,onChange:this.changeStep,allowPiTruncation:true})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Grid Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.gridStepTextbox,onChange:this.changeGridStep,allowPiTruncation:true})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Snap Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.snapStepTextbox,onChange:this.changeSnapStep,allowPiTruncation:true})})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-right-col",children:[jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",onClick:()=>{this.changeStepsBasedOnRange();},children:"Auto-adjust steps"}),jsxRuntimeExports.jsxs(InfoTip$g,{children:[jsxRuntimeExports.jsx("p",{children:'Use the "Auto-adjust" steps button to update the tick step, grid step, and snap step to values that are valid for the current range.'}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("p",{children:"This is useful when the range is changed, and the graph errors due to the step sizes being too large or too small."})]})]})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Markings:",children:jsxRuntimeExports.jsx(ButtonGroup$1,{value:this.props.markings,allowEmpty:false,buttons:[{value:"axes",content:"Axes"},{value:"graph",content:"Graph"},{value:"grid",content:"Grid"},{value:"none",content:"None"}],onChange:this.change("markings")})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tooltips",checked:this.props.showTooltips,onChange:value=>{this.change({showTooltips:value});}})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Background image URL:",style:styles$F.resetSpaceTop,children:[jsxRuntimeExports.jsx("input",{type:"text",className:css(styles$F.backgroundUrlInput),ref:this.bgUrlRef,value:this.state.backgroundImage.url||"",onChange:e=>{const image={...this.props.backgroundImage};image.url=e.target.value;this.setState({backgroundImage:image});},onKeyPress:this.changeBackgroundUrl,onBlur:this.changeBackgroundUrl}),jsxRuntimeExports.jsx(InfoTip$g,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]}),jsxRuntimeExports.jsxs(View,{style:styles$F.protractorSection,children:[jsxRuntimeExports.jsx(View,{style:styles$F.checkboxRow,children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.change({showProtractor:value});},style:styles$F.resetSpaceTop})}),this.props.showProtractor&&jsxRuntimeExports.jsx(Banner,{layout:"floating",text:"The protractor is not accessible. Please consider an alternate approach.",kind:"warning"})]})]})]})}constructor(props){super(props),this._isMounted=false,this.bgUrlRef=React.createRef(),this.labelXRef=React.createRef(),this.labelYRef=React.createRef(),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.changeBackgroundUrl=e=>{if(e.type==="keypress"&&e.key!=="Enter"){return}const setUrl=(url,width,height)=>{const image={...this.props.backgroundImage};image.url=url;image.width=width;image.height=height;this.setState({backgroundImage:image},this.changeGraph);};const url=this.bgUrlRef.current?.value;if(url){Util.getImageSize(url,(width,height)=>{if(this._isMounted){setUrl(url,width,height);}});}else {setUrl(null,0,0);}},this.renderLabelChoices=choices=>{return choices.map(nameAndValue=>jsxRuntimeExports.jsx("option",{value:nameAndValue[1],children:nameAndValue[0]},nameAndValue[1]))},this.validRange=range=>{const numbers=_.every(range,function(num){return _.isFinite(num)});if(!numbers){return "Range must be a valid number"}if(range[0]>=range[1]){return "Range must have a higher number on the right"}return true},this.validateStepValue=settings=>{const{step,range,name,minTicks,maxTicks}=settings;const nSteps=numSteps(range,step);if(nSteps<minTicks){return name+" is too large, there must be at least "+minTicks+" ticks."}if(nSteps>maxTicks){return name+" is too small, there can be at most "+maxTicks+" ticks."}return true},this.validSnapStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Snap step",minTicks:5,maxTicks:60})},this.validGridStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Grid step",minTicks:3,maxTicks:60})},this.validStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Step",minTicks:3,maxTicks:20})},this.validBackgroundImageSize=image=>{if(!image.url){return true}const validSize=image.width<=450&&image.height<=450;if(!validSize){return "Image must be smaller than 450px x 450px."}return true},this.validateGraphSettings=(range,step,gridStep,snapStep,image)=>{const self=this;let msg;const goodRange=_.every(range,function(range){msg=self.validRange(range);return msg===true});if(!goodRange){return msg}const goodStep=_.every(step,function(step,i){msg=self.validStep(step,range[i]);return msg===true});if(!goodStep){return msg}const goodGridStep=_.every(gridStep,function(gridStep,i){msg=self.validGridStep(gridStep,range[i]);return msg===true});if(!goodGridStep){return msg}const goodSnapStep=_.every(snapStep,function(snapStep,i){msg=self.validSnapStep(snapStep,range[i]);return msg===true});if(!goodSnapStep){return msg}const goodImageSize=this.validBackgroundImageSize(image);if(goodImageSize!==true){msg=goodImageSize;return msg}return true},this.changeLabel=(i,e)=>{const val=e.target.value;const labels=this.state.labelsTextbox.slice();labels[i]=val;this.setState({labelsTextbox:labels},this.changeGraph);},this.changeRange=(i,values)=>{const ranges=this.state.rangeTextbox.slice();ranges[i]=values;this.setState({rangeTextbox:ranges},this.changeGraph);},this.changeStepsBasedOnRange=()=>{const ranges=this.state.rangeTextbox.slice();const step=this.state.stepTextbox.slice();const gridStep=this.state.gridStepTextbox.slice();const snapStep=this.state.snapStepTextbox.slice();const scaleX=Util.scaleFromExtent(ranges[0],this.props.box[0]);if(this.validRange(ranges[0])===true){step[0]=Util.tickStepFromExtent(ranges[0],this.props.box[0]);const gridStepValue=Util.gridStepFromTickStep(step[0],scaleX);if(gridStepValue){gridStep[0]=gridStepValue;}snapStep[0]=gridStep[0]/2;}const scaleY=Util.scaleFromExtent(ranges[1],this.props.box[1]);if(this.validRange(ranges[1])===true){step[1]=Util.tickStepFromExtent(ranges[1],this.props.box[1]);const gridStepValue=Util.gridStepFromTickStep(step[1],scaleY);if(gridStepValue){gridStep[1]=gridStepValue;}snapStep[1]=gridStep[1]/2;}this.setState({stepTextbox:step,gridStepTextbox:gridStep,snapStepTextbox:snapStep,rangeTextbox:ranges},this.changeGraph);},this.changeStep=step=>{this.setState({stepTextbox:step},this.changeGraph);},this.changeSnapStep=snapStep=>{this.setState({snapStepTextbox:snapStep},this.changeGraph);},this.changeGridStep=gridStep=>{this.setState({gridStepTextbox:gridStep,snapStepTextbox:_.map(gridStep,function(step){return step/2})},this.changeGraph);},this.changeGraph=()=>{const labels=this.state.labelsTextbox;const labelLocation=this.state.labelLocation;const range=_.map(this.state.rangeTextbox,function(range){return _.map(range,Number)});const step=_.map(this.state.stepTextbox,Number);const gridStep=this.state.gridStepTextbox;const snapStep=this.state.snapStepTextbox;const image=this.state.backgroundImage;const validationResult=this.validateGraphSettings(range,step,gridStep,snapStep,image);if(validationResult===true){this.change({valid:true,labels:labels,labelLocation:labelLocation,range:range,step:step,gridStep:gridStep,snapStep:snapStep,backgroundImage:image});}else {this.change({valid:validationResult});}};this.state={isExpanded:true,...InteractiveGraphSettings.stateFromProps(props)};}}InteractiveGraphSettings.defaultProps={box:[interactiveSizes.defaultBoxSizeSmall,interactiveSizes.defaultBoxSizeSmall],labels:["$x$","$y$"],labelLocation:"onAxis",range:[[-10,10],[-10,10]],step:[1,1],gridStep:[1,1],snapStep:[1,1],valid:true,backgroundImage:defaultBackgroundImage,markings:"graph",showProtractor:false,showTooltips:false};const styles$F=StyleSheet.create({resetSpaceTop:{marginTop:0},backgroundUrlInput:{border:`1px solid ${color.offBlack32}`,borderRadius:spacing.xxxSmall_4,padding:spacing.xxxSmall_4},checkboxRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:spacing.xSmall_8},protractorSection:{marginTop:spacing.xSmall_8,borderTop:`1px solid ${color.offBlack16}`,paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,borderBottom:`1px solid ${color.offBlack16}`}});
1555
1557
 
1556
- const{InfoTip: InfoTip$f}=components;const StyledUl=addStyle("ul");function getAccessibilityAttributes(graphId){const elementArias=[];const container=document.getElementById(graphId);if(!container){return elementArias}container.querySelectorAll("*").forEach(element=>{const elementAttributes=[];const ariaLabel=element.getAttribute("aria-label");const ariaDescribedby=element.getAttribute("aria-describedby");if(ariaLabel){elementAttributes.unshift({name:"label",value:ariaLabel});}if(ariaDescribedby){const descriptions=ariaDescribedby.split(/ +/);for(const description of descriptions){const descriptionString=document.getElementById(description)?.textContent;if(descriptionString){elementAttributes.push({name:"description",value:descriptionString});}}}if(elementAttributes.length>0){elementArias.push({roleOrTag:element.getAttribute("role")||element.tagName.toLowerCase(),className:element.classList[element.classList.length-1]||"",attributes:elementAttributes});}});return elementArias}function SRTree(props){const{elementArias,showTags}=props;return jsxRuntimeExports.jsx("ol",{style:{listStyle:"revert",marginLeft:8},children:elementArias.map((aria,index)=>jsxRuntimeExports.jsxs("li",{children:[showTags&&jsxRuntimeExports.jsx(Pill,{size:"small",kind:"success",style:styles$D.smallSpaceRight,children:aria.roleOrTag}),aria.className,jsxRuntimeExports.jsx(StyledUl,{style:styles$D.indentListLeft,children:aria.attributes.map((value,index)=>jsxRuntimeExports.jsxs("li",{children:[jsxRuntimeExports.jsx(Pill,{size:"small",kind:value.name==="label"?"info":"neutral",style:styles$D.smallSpaceRight,children:value.name}),value.value]},index))})]},index))})}function InteractiveGraphSRTree({graphId,correct,fullGraphAriaLabel,fullGraphAriaDescription,lockedFigures}){const[isExpanded,setIsExpanded]=React.useState(true);const[showTags,setShowTags]=React.useState(false);const[elementArias,setElementArias]=React.useState([]);const switchId=React.useId();React.useEffect(()=>{setElementArias(getAccessibilityAttributes(graphId));},[correct,fullGraphAriaLabel,fullGraphAriaDescription,graphId,lockedFigures]);return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Screen reader tree",isOpen:isExpanded,onToggle:setIsExpanded,isCollapsible:true}),isExpanded&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:[styles$D.row,styles$D.tagSwitch],children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:showTags,onChange:setShowTags}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LabelSmall,{tag:"label",htmlFor:switchId,children:"Show HTML roles/tags"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsx(InfoTip$f,{children:'This screen reader tree shows the ARIA labels and descriptions for elements within the "correct answer" Interactive Graph widget displayed above.'})]}),jsxRuntimeExports.jsx(SRTree,{elementArias:elementArias,showTags:showTags})]})]})}const styles$D=StyleSheet.create({smallSpaceRight:{marginRight:spacing.xxSmall_6},indentListLeft:{listStyle:"revert",marginLeft:spacing.small_12},tagSwitch:{marginTop:spacing.xSmall_8,marginBottom:spacing.xSmall_8},row:{flexDirection:"row",alignItems:"center"}});
1558
+ const{InfoTip: InfoTip$f}=components;const StyledUl=addStyle("ul");function getAccessibilityAttributes(graphId){const elementArias=[];const container=document.getElementById(graphId);if(!container){return elementArias}container.querySelectorAll("*").forEach(element=>{const elementAttributes=[];const ariaLabel=element.getAttribute("aria-label");const ariaDescribedby=element.getAttribute("aria-describedby");if(ariaLabel){elementAttributes.unshift({name:"label",value:ariaLabel});}if(ariaDescribedby){const descriptions=ariaDescribedby.split(/ +/);for(const description of descriptions){const descriptionString=document.getElementById(description)?.textContent;if(descriptionString){elementAttributes.push({name:"description",value:descriptionString});}}}if(elementAttributes.length>0){elementArias.push({roleOrTag:element.getAttribute("role")||element.tagName.toLowerCase(),className:element.classList[element.classList.length-1]||"",attributes:elementAttributes});}});return elementArias}function SRTree(props){const{elementArias,showTags}=props;return jsxRuntimeExports.jsx("ol",{style:{listStyle:"revert",marginLeft:8},children:elementArias.map((aria,index)=>jsxRuntimeExports.jsxs("li",{children:[showTags&&jsxRuntimeExports.jsx(Pill,{size:"small",kind:"success",style:styles$E.smallSpaceRight,children:aria.roleOrTag}),aria.className,jsxRuntimeExports.jsx(StyledUl,{style:styles$E.indentListLeft,children:aria.attributes.map((value,index)=>jsxRuntimeExports.jsxs("li",{children:[jsxRuntimeExports.jsx(Pill,{size:"small",kind:value.name==="label"?"info":"neutral",style:styles$E.smallSpaceRight,children:value.name}),value.value]},index))})]},index))})}function InteractiveGraphSRTree({graphId,correct,fullGraphAriaLabel,fullGraphAriaDescription,lockedFigures}){const[isExpanded,setIsExpanded]=React.useState(true);const[showTags,setShowTags]=React.useState(false);const[elementArias,setElementArias]=React.useState([]);const switchId=React.useId();React.useEffect(()=>{setElementArias(getAccessibilityAttributes(graphId));},[correct,fullGraphAriaLabel,fullGraphAriaDescription,graphId,lockedFigures]);return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Screen reader tree",isOpen:isExpanded,onToggle:setIsExpanded,isCollapsible:true}),isExpanded&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:[styles$E.row,styles$E.tagSwitch],children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:showTags,onChange:setShowTags}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LabelSmall,{tag:"label",htmlFor:switchId,children:"Show HTML roles/tags"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsx(InfoTip$f,{children:'This screen reader tree shows the ARIA labels and descriptions for elements within the "correct answer" Interactive Graph widget displayed above.'})]}),jsxRuntimeExports.jsx(SRTree,{elementArias:elementArias,showTags:showTags})]})]})}const styles$E=StyleSheet.create({smallSpaceRight:{marginRight:spacing.xxSmall_6},indentListLeft:{listStyle:"revert",marginLeft:spacing.small_12},tagSwitch:{marginTop:spacing.xSmall_8,marginBottom:spacing.xSmall_8},row:{flexDirection:"row",alignItems:"center"}});
1557
1559
 
1558
- const SegmentCountSelector=({numSegments=1,onChange})=>jsxRuntimeExports.jsx(SingleSelect,{selectedValue:`${numSegments}`,placeholder:"",onChange:newValue=>{const num=+newValue;onChange(num);},style:styles$C.singleSelectShort,children:_.range(1,7).map(n=>jsxRuntimeExports.jsx(OptionItem,{value:`${n}`,label:`${n} segment${n>1?"s":""}`},n))},"segment-select");const styles$C=StyleSheet.create({singleSelectShort:{height:26}});
1560
+ const SegmentCountSelector=({numSegments=1,onChange})=>jsxRuntimeExports.jsx(SingleSelect,{selectedValue:`${numSegments}`,placeholder:"",onChange:newValue=>{const num=+newValue;onChange(num);},style:styles$D.singleSelectShort,children:_.range(1,7).map(n=>jsxRuntimeExports.jsx(OptionItem,{value:`${n}`,label:`${n} segment${n>1?"s":""}`},n))},"segment-select");const styles$D=StyleSheet.create({singleSelectShort:{height:26}});
1559
1561
 
1560
- const LockedFigureSelect=props=>{const{id,onChange}=props;const figureTypes=["point","line","vector","ellipse","polygon","function","label"];return jsxRuntimeExports.jsx(View,{style:styles$B.container,children:jsxRuntimeExports.jsx(ActionMenu,{menuText:"Add locked figure",style:styles$B.addElementSelect,children:figureTypes.map(figureType=>jsxRuntimeExports.jsx(ActionItem,{label:figureType,onClick:()=>onChange(figureType)},`${id}-${figureType}`))})})};const styles$B=StyleSheet.create({container:{marginTop:spacing.xSmall_8},addElementSelect:{backgroundColor:color.fadedBlue8,borderRadius:spacing.xxxSmall_4}});
1562
+ const LockedFigureSelect=props=>{const{id,onChange}=props;const figureTypes=["point","line","vector","ellipse","polygon","function","label"];return jsxRuntimeExports.jsx(View,{style:styles$C.container,children:jsxRuntimeExports.jsx(ActionMenu,{menuText:"Add locked figure",style:styles$C.addElementSelect,children:figureTypes.map(figureType=>jsxRuntimeExports.jsx(ActionItem,{label:figureType,onClick:()=>onChange(figureType)},`${id}-${figureType}`))})})};const styles$C=StyleSheet.create({container:{marginTop:spacing.xSmall_8},addElementSelect:{backgroundColor:color.fadedBlue8,borderRadius:spacing.xxxSmall_4}});
1561
1563
 
1562
1564
  const ScrolllessNumberTextField=props=>{const{value,onChange,...restOfProps}=props;const[focused,setFocused]=React.useState(false);const[wipValue,setWipValue]=React.useState("");const inputRef=React.useRef(null);React.useEffect(()=>{const ref=inputRef.current;const ignoreScroll=e=>{e.stopPropagation();};ref?.addEventListener("wheel",ignoreScroll);return ()=>{ref?.removeEventListener("wheel",ignoreScroll);}},[inputRef]);return jsxRuntimeExports.jsx(TextField,{...restOfProps,type:"number",value:focused?wipValue:value,onChange:newValue=>{setWipValue(newValue);onChange(newValue);},onFocus:e=>{setWipValue(value);setFocused(true);props.onFocus?.(e);},onBlur:e=>{setFocused(false);props.onBlur?.(e);},ref:inputRef})};
1563
1565
 
1564
- const{convertDegreesToRadians,convertRadiansToDegrees: convertRadiansToDegrees$1}=angles;const AngleInput=props=>{const{angle,onChange}=props;const[angleInput,setAngleInput]=React.useState(convertRadiansToDegrees$1(angle).toString());function handleAngleChange(newValue){setAngleInput(newValue);if(isNaN(+newValue)||newValue===""){return}onChange(convertDegreesToRadians(newValue));}return jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$A.row,children:["angle (degrees)",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:angleInput,onChange:handleAngleChange,style:styles$A.textField}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6})]})};const styles$A=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1566
+ const{convertDegreesToRadians,convertRadiansToDegrees: convertRadiansToDegrees$1}=angles;const AngleInput=props=>{const{angle,onChange}=props;const[angleInput,setAngleInput]=React.useState(convertRadiansToDegrees$1(angle).toString());function handleAngleChange(newValue){setAngleInput(newValue);if(isNaN(+newValue)||newValue===""){return}onChange(convertDegreesToRadians(newValue));}return jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$B.row,children:["angle (degrees)",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:angleInput,onChange:handleAngleChange,style:styles$B.textField}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6})]})};const styles$B=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1565
1567
 
1566
- const CoordinatePairInput=props=>{const{coord,labels,error,style,onChange}=props;const[coordState,setCoordState]=React.useState([coord[0].toString(),coord[1].toString()]);React.useEffect(()=>{setCoordState([coord[0].toString(),coord[1].toString()]);},[coord]);function handleCoordChange(newValue,coordIndex){const newCoordState=[...coordState];newCoordState[coordIndex]=newValue;setCoordState(newCoordState);if(isNaN(+newValue)||newValue===""){return}const newCoords=[...coord];newCoords[coordIndex]=+newValue;onChange(newCoords);}return jsxRuntimeExports.jsxs(View,{style:[styles$z.row,style],children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$z.row,children:[labels?labels[0]:"x coord",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[0],onChange:newValue=>handleCoordChange(newValue,0),style:[styles$z.textField,error?styles$z.errorField:undefined]})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$z.row,children:[labels?labels[1]:"y coord",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[1],onChange:newValue=>handleCoordChange(newValue,1),style:[styles$z.textField,error?styles$z.errorField:undefined]})]})]})};const styles$z=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64},errorField:{borderColor:color.red,backgroundColor:color.fadedRed8}});
1568
+ const CoordinatePairInput=props=>{const{coord,labels,error,style,onChange}=props;const[coordState,setCoordState]=React.useState([coord[0].toString(),coord[1].toString()]);React.useEffect(()=>{setCoordState([coord[0].toString(),coord[1].toString()]);},[coord]);function handleCoordChange(newValue,coordIndex){const newCoordState=[...coordState];newCoordState[coordIndex]=newValue;setCoordState(newCoordState);if(isNaN(+newValue)||newValue===""){return}const newCoords=[...coord];newCoords[coordIndex]=+newValue;onChange(newCoords);}return jsxRuntimeExports.jsxs(View,{style:[styles$A.row,style],children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$A.row,children:[labels?labels[0]:"x coord",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[0],onChange:newValue=>handleCoordChange(newValue,0),style:[styles$A.textField,error?styles$A.errorField:undefined]})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$A.row,children:[labels?labels[1]:"y coord",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[1],onChange:newValue=>handleCoordChange(newValue,1),style:[styles$A.textField,error?styles$A.errorField:undefined]})]})]})};const styles$A=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64},errorField:{borderColor:color.red,backgroundColor:color.fadedRed8}});
1567
1569
 
1568
- const ColorSwatch=props=>{const{color: color$1,filled=true,decorative=false}=props;return jsxRuntimeExports.jsx(View,{"aria-label":!decorative?`${color$1}, ${filled?"filled":"open"}`:undefined,style:[styles$y.colorSwatch,{border:`4px solid ${lockedFigureColors[color$1]}`,backgroundColor:filled?lockedFigureColors[color$1]:color.white}]})};const styles$y=StyleSheet.create({colorSwatch:{outline:`2px solid ${color.offWhite}`,borderRadius:"50%",width:spacing.large_24,height:spacing.large_24}});
1570
+ const ColorSwatch=props=>{const{color: color$1,filled=true,decorative=false}=props;return jsxRuntimeExports.jsx(View,{"aria-label":!decorative?`${color$1}, ${filled?"filled":"open"}`:undefined,style:[styles$z.colorSwatch,{border:`4px solid ${lockedFigureColors[color$1]}`,backgroundColor:filled?lockedFigureColors[color$1]:color.white}]})};const styles$z=StyleSheet.create({colorSwatch:{outline:`2px solid ${color.offWhite}`,borderRadius:"50%",width:spacing.large_24,height:spacing.large_24}});
1569
1571
 
1570
- const possibleColors=Object.keys(lockedFigureColors);const ColorSelect=props=>{const{selectedValue,style,onChange}=props;return jsxRuntimeExports.jsx(View,{style:[styles$x.row,style],children:jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$x.row,children:["color",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:selectedValue,onChange:onChange,placeholder:"",children:possibleColors.map(colorName=>jsxRuntimeExports.jsx(OptionItem,{value:colorName,label:colorName,leftAccessory:jsxRuntimeExports.jsx(ColorSwatch,{color:colorName,decorative:true})},colorName))})]})})};const styles$x=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center",minWidth:"auto"}});
1572
+ const possibleColors=Object.keys(lockedFigureColors);const ColorSelect=props=>{const{selectedValue,style,onChange}=props;return jsxRuntimeExports.jsx(View,{style:[styles$y.row,style],children:jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$y.row,children:["color",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:selectedValue,onChange:onChange,placeholder:"",children:possibleColors.map(colorName=>jsxRuntimeExports.jsx(OptionItem,{value:colorName,label:colorName,leftAccessory:jsxRuntimeExports.jsx(ColorSwatch,{color:colorName,decorative:true})},colorName))})]})})};const styles$y=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center",minWidth:"auto"}});
1571
1573
 
1572
- const EllipseSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$w.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$w.innerCircle,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$w=StyleSheet.create({container:{outline:`2px solid ${color.offWhite}`,borderRadius:"50%",width:spacing.xLarge_32,height:spacing.large_24,backgroundColor:color.white,alignItems:"center",justifyContent:"center"},innerCircle:{width:28,height:20,borderRadius:"50%"}});
1574
+ const EllipseSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$x.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$x.innerCircle,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$x=StyleSheet.create({container:{outline:`2px solid ${color.offWhite}`,borderRadius:"50%",width:spacing.xLarge_32,height:spacing.large_24,backgroundColor:color.white,alignItems:"center",justifyContent:"center"},innerCircle:{width:28,height:20,borderRadius:"50%"}});
1573
1575
 
1574
- const LineStrokeSelect=props=>{const{selectedValue,containerStyle,onChange}=props;return jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$v.lineStrokeSelect,containerStyle],children:["stroke",jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:selectedValue,onChange:onChange,placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"solid",label:"solid"}),jsxRuntimeExports.jsx(OptionItem,{value:"dashed",label:"dashed"})]})]})};const styles$v=StyleSheet.create({lineStrokeSelect:{display:"flex",flexDirection:"row",alignItems:"center",minWidth:0}});
1576
+ const LineStrokeSelect=props=>{const{selectedValue,containerStyle,onChange}=props;return jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$w.lineStrokeSelect,containerStyle],children:["stroke",jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:selectedValue,onChange:onChange,placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"solid",label:"solid"}),jsxRuntimeExports.jsx(OptionItem,{value:"dashed",label:"dashed"})]})]})};const styles$w=StyleSheet.create({lineStrokeSelect:{display:"flex",flexDirection:"row",alignItems:"center",minWidth:0}});
1575
1577
 
1576
1578
  const LineWeightSelect=props=>{const{selectedValue,containerStyle,onChange}=props;return jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[{display:"flex",flexDirection:"row",alignItems:"center",minWidth:0},containerStyle],children:["weight",jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:selectedValue,onChange:value=>onChange(value),placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"thin",label:"thin"}),jsxRuntimeExports.jsx(OptionItem,{value:"medium",label:"medium"}),jsxRuntimeExports.jsx(OptionItem,{value:"thick",label:"thick"})]})]})};
1577
1579
 
1578
- const{InfoTip: InfoTip$e}=components;function LockedFigureAria(props){const{ariaLabel,getPrepopulatedAriaLabel,onChangeProps}=props;const id=React.useId();const ariaLabelId=`aria-label-${id}`;const[loading,setLoading]=React.useState(false);return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsxs(View,{style:styles$u.row,children:[jsxRuntimeExports.jsx(LabelMedium,{tag:"label",htmlFor:ariaLabelId,children:"Aria label"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(InfoTip$e,{children:["Aria label is used by screen readers to describe content to users who may be visually impaired. ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),"Populating this field will make it so that users can use a screen reader to navigate to this point and hear the description.",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),"If you leave this field blank, the point will be hidden from screen readers. Users will not be able to navigate to this point using a screen reader."]})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(LabelXSmall,{style:styles$u.caption,children:"The figure is hidden from screen readers if this field is left blank."}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(TextArea,{id:ariaLabelId,value:loading?"Loading...":ariaLabel??"",onChange:newValue=>{onChangeProps({ariaLabel:newValue||undefined});},placeholder:"Ex. Point at (x, y)",rows:1,resizeType:"vertical"}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:pencilCircle,style:styles$u.button,onClick:()=>{setLoading(true);getPrepopulatedAriaLabel().then(ariaLabel=>{setLoading(false);onChangeProps({ariaLabel});});},children:"Auto-generate"})]})}const styles$u=StyleSheet.create({row:{flexDirection:"row",alignItems:"center"},button:{alignSelf:"start"},caption:{color:color.offBlack64}});
1580
+ const{InfoTip: InfoTip$e}=components;function LockedFigureAria(props){const{ariaLabel,getPrepopulatedAriaLabel,onChangeProps}=props;const id=React.useId();const ariaLabelId=`aria-label-${id}`;const[loading,setLoading]=React.useState(false);return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsxs(View,{style:styles$v.row,children:[jsxRuntimeExports.jsx(LabelMedium,{tag:"label",htmlFor:ariaLabelId,children:"Aria label"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(InfoTip$e,{children:["Aria label is used by screen readers to describe content to users who may be visually impaired. ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),"Populating this field will make it so that users can use a screen reader to navigate to this point and hear the description.",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),"If you leave this field blank, the point will be hidden from screen readers. Users will not be able to navigate to this point using a screen reader."]})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(LabelXSmall,{style:styles$v.caption,children:"The figure is hidden from screen readers if this field is left blank."}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(TextArea,{id:ariaLabelId,value:loading?"Loading...":ariaLabel??"",onChange:newValue=>{onChangeProps({ariaLabel:newValue||undefined});},placeholder:"Ex. Point at (x, y)",rows:1,resizeType:"vertical"}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:pencilCircle,style:styles$v.button,onClick:()=>{setLoading(true);getPrepopulatedAriaLabel().then(ariaLabel=>{setLoading(false);onChangeProps({ariaLabel});});},children:"Auto-generate"})]})}const styles$v=StyleSheet.create({row:{flexDirection:"row",alignItems:"center"},button:{alignSelf:"start"},caption:{color:color.offBlack64}});
1579
1581
 
1580
- const LockedFigureSettingsActions=props=>{const{figureType,onMove,onRemove}=props;return jsxRuntimeExports.jsxs(View,{style:styles$t.container,children:[jsxRuntimeExports.jsx(Button,{startIcon:trashIcon$1,"aria-label":`Delete locked ${figureType}`,onClick:onRemove,kind:"tertiary",style:styles$t.deleteButton,children:"Delete"}),onMove&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsx(IconButton,{icon:caretDoubleUpIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} to the back`,onClick:()=>onMove("back")}),jsxRuntimeExports.jsx(IconButton,{icon:caretUpIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} backward`,onClick:()=>onMove("backward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} forward`,onClick:()=>onMove("forward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDoubleDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} to the front`,onClick:()=>onMove("front")})]})]})};const styles$t=StyleSheet.create({container:{width:"100%",flexDirection:"row",alignItems:"center",marginTop:spacing.xxxSmall_4},deleteButton:{marginInlineStart:-spacing.xxxSmall_4}});
1582
+ const LockedFigureSettingsActions=props=>{const{figureType,onMove,onRemove}=props;return jsxRuntimeExports.jsxs(View,{style:styles$u.container,children:[jsxRuntimeExports.jsx(Button,{startIcon:trashIcon$1,"aria-label":`Delete locked ${figureType}`,onClick:onRemove,kind:"tertiary",style:styles$u.deleteButton,children:"Delete"}),onMove&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsx(IconButton,{icon:caretDoubleUpIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} to the back`,onClick:()=>onMove("back")}),jsxRuntimeExports.jsx(IconButton,{icon:caretUpIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} backward`,onClick:()=>onMove("backward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} forward`,onClick:()=>onMove("forward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDoubleDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} to the front`,onClick:()=>onMove("front")})]})]})};const styles$u=StyleSheet.create({container:{width:"100%",flexDirection:"row",alignItems:"center",marginTop:spacing.xxxSmall_4},deleteButton:{marginInlineStart:-spacing.xxxSmall_4}});
1581
1583
 
1582
- const{InfoTip: InfoTip$d}=components;function LockedLabelSettings(props){const{type,coord,color: color$1,size,text,expanded,onChangeProps,onMove,onRemove,onToggle,containerStyle}=props;return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{style:[styles$s.row,styles$s.accordionHeaderContainer],children:[jsxRuntimeExports.jsxs(LabelLarge,{children:["Label (",coord[0],", ",coord[1],")"]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),text!==""&&jsxRuntimeExports.jsx(LabelLarge,{style:[{backgroundColor:color.white,color:lockedFigureColors[color$1]},styles$s.accordionHeader],children:text})]}),containerStyle:containerStyle,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,onChange:newCoords=>{onChangeProps({coord:newCoords});},style:styles$s.spaceUnder}),jsxRuntimeExports.jsxs(View,{style:styles$s.row,children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$s.row,styles$s.spaceUnder,{flexGrow:1}],children:["text",jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(TextField,{value:text,placeholder:"ex. $x^2$ or $\\frac{1}{2}$",onChange:newValue=>onChangeProps({text:newValue})})]}),jsxRuntimeExports.jsxs(InfoTip$d,{children:["Surround your text with $ for TeX.",jsxRuntimeExports.jsx("br",{}),"Example: ",`This circle has radius $\\frac{1}{2}$ units.`,jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),'It is important to use TeX when appropriate for accessibility. The above example would be read as "This circle has radius one-half units" by screen readers.']})]}),jsxRuntimeExports.jsxs(View,{style:styles$s.row,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color$1,onChange:newColor=>{onChangeProps({color:newColor});},style:styles$s.spaceUnder}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$s.row,children:["size",jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:size,onChange:newValue=>onChangeProps({size:newValue}),placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"small",label:"small"}),jsxRuntimeExports.jsx(OptionItem,{value:"medium",label:"medium"}),jsxRuntimeExports.jsx(OptionItem,{value:"large",label:"large"})]})]})]}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:type,onMove:onMove,onRemove:onRemove})]})}const styles$s=StyleSheet.create({accordionHeaderContainer:{whiteSpace:"nowrap"},accordionHeader:{padding:spacing.xxxSmall_4,marginInlineEnd:spacing.xSmall_8,borderRadius:spacing.xxxSmall_4,textOverflow:"ellipsis",overflow:"hidden"},row:{display:"flex",flexDirection:"row",alignItems:"center",minWidth:0},spaceUnder:{marginBottom:spacing.xSmall_8}});
1584
+ const{InfoTip: InfoTip$d}=components;function LockedLabelSettings(props){const{type,coord,color: color$1,size,text,expanded,onChangeProps,onMove,onRemove,onToggle,containerStyle}=props;return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{style:[styles$t.row,styles$t.accordionHeaderContainer],children:[jsxRuntimeExports.jsxs(LabelLarge,{children:["Label (",coord[0],", ",coord[1],")"]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),text!==""&&jsxRuntimeExports.jsx(LabelLarge,{style:[{backgroundColor:color.white,color:lockedFigureColors[color$1]},styles$t.accordionHeader],children:text})]}),containerStyle:containerStyle,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,onChange:newCoords=>{onChangeProps({coord:newCoords});},style:styles$t.spaceUnder}),jsxRuntimeExports.jsxs(View,{style:styles$t.row,children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$t.row,styles$t.spaceUnder,{flexGrow:1}],children:["text",jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(TextField,{value:text,placeholder:"ex. $x^2$ or $\\frac{1}{2}$",onChange:newValue=>onChangeProps({text:newValue})})]}),jsxRuntimeExports.jsxs(InfoTip$d,{children:["Surround your text with $ for TeX.",jsxRuntimeExports.jsx("br",{}),"Example: ",`This circle has radius $\\frac{1}{2}$ units.`,jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),'It is important to use TeX when appropriate for accessibility. The above example would be read as "This circle has radius one-half units" by screen readers.']})]}),jsxRuntimeExports.jsxs(View,{style:styles$t.row,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color$1,onChange:newColor=>{onChangeProps({color:newColor});},style:styles$t.spaceUnder}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$t.row,children:["size",jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:size,onChange:newValue=>onChangeProps({size:newValue}),placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"small",label:"small"}),jsxRuntimeExports.jsx(OptionItem,{value:"medium",label:"medium"}),jsxRuntimeExports.jsx(OptionItem,{value:"large",label:"large"})]})]})]}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:type,onMove:onMove,onRemove:onRemove})]})}const styles$t=StyleSheet.create({accordionHeaderContainer:{whiteSpace:"nowrap"},accordionHeader:{padding:spacing.xxxSmall_4,marginInlineEnd:spacing.xSmall_8,borderRadius:spacing.xxxSmall_4,textOverflow:"ellipsis",overflow:"hidden"},row:{display:"flex",flexDirection:"row",alignItems:"center",minWidth:0},spaceUnder:{marginBottom:spacing.xSmall_8}});
1583
1585
 
1584
1586
  const DEFAULT_COLOR="grayH";function getDefaultFigureForType(type){switch(type){case "point":return {type:"point",coord:[0,0],color:DEFAULT_COLOR,filled:true,labels:[]};case "line":return {type:"line",kind:"line",points:[getDefaultFigureForType("point"),{...getDefaultFigureForType("point"),coord:[2,2]}],color:DEFAULT_COLOR,lineStyle:"solid",showPoint1:false,showPoint2:false,weight:"medium",labels:[]};case "vector":return {type:"vector",points:[[0,0],[2,2]],color:DEFAULT_COLOR,weight:"medium",labels:[]};case "ellipse":return {type:"ellipse",center:[0,0],radius:[1,1],angle:0,color:DEFAULT_COLOR,fillStyle:"none",strokeStyle:"solid",weight:"medium",labels:[]};case "polygon":return {type:"polygon",points:[[0,2],[-1,0],[1,0]],color:DEFAULT_COLOR,showVertices:false,fillStyle:"none",strokeStyle:"solid",weight:"medium",labels:[]};case "function":return {type:"function",color:DEFAULT_COLOR,strokeStyle:"solid",weight:"medium",equation:"x^2",domain:[-Infinity,Infinity],directionalAxis:"x",labels:[]};case "label":return {type:"label",coord:[0,0],text:"label",color:DEFAULT_COLOR,size:"medium"};default:throw new UnreachableCaseError(type)}}function generateLockedFigureAppearanceDescription(color,strokeStyle="solid",fill,weight="medium"){const convertedColor=color==="grayH"?"gray":color;const weightString=weight==="medium"?"":` ${weight}`;const baseAppearance=`. Appearance${weightString} ${strokeStyle} ${convertedColor}`;switch(fill){case "none":return `${baseAppearance} border, with no fill.`;case "white":return `${baseAppearance} border, with a white fill.`;case "solid":case "translucent":return `${baseAppearance} border, with a ${fill} ${convertedColor} fill.`;case undefined:return `${baseAppearance}.`;default:throw new UnreachableCaseError(fill)}}async function generateSpokenMathDetails(mathString){const engine=await SpeechRuleEngine.setup("en");let convertedSpeech="";const parsedContent=mathOnlyParser(mathString);for(const piece of parsedContent){switch(piece.type){case "math":convertedSpeech+=engine.texToSpeech(piece.content);break;case "specialCharacter":convertedSpeech+=piece.content.length>1?piece.content.slice(1):piece.content;break;default:convertedSpeech+=piece.content;break}}return convertedSpeech}async function joinLabelsAsSpokenMath(labels){if(labels.length===0){return ""}const spokenLabelPromises=labels.map(label=>{return generateSpokenMathDetails(label.text)});const spokenLabels=await Promise.all(spokenLabelPromises);return ` ${spokenLabels.join(", ")}`}
1585
1587
 
1586
- const{convertRadiansToDegrees}=angles;const{InfoTip: InfoTip$c}=components;const LockedEllipseSettings=props=>{const{center,radius,angle,color,labels,ariaLabel,fillStyle,strokeStyle,weight,expanded,onToggle,onChangeProps,onMove,onRemove}=props;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenCenterX=await generateSpokenMathDetails(`$${center[0]}$`);const spokenCenterY=await generateSpokenMathDetails(`$${center[1]}$`);const spokenRotation=await generateSpokenMathDetails(`$${convertRadiansToDegrees(angle)}$`);const isCircle=radius[0]===radius[1];let str="";if(isCircle){str+=`Circle${visiblelabel} with radius ${radius[0]}`;}else {str+=`Ellipse${visiblelabel} with x radius ${radius[0]} and y radius ${radius[1]}`;}str+=`, centered at ${spokenCenterX} comma ${spokenCenterY}`;if(!isCircle&&angle!==0){str+=`, rotated by ${spokenRotation} degrees`;}const ellipseAppearance=generateLockedFigureAppearanceDescription(color,strokeStyle,fillStyle,weight);str+=ellipseAppearance;return str}function handleCenterChange(newCoord){const xOffset=newCoord[0]-center[0];const yOffset=newCoord[1]-center[1];const newProps={center:newCoord};newProps.labels=labels.map(label=>({...label,coord:[label.coord[0]+xOffset,label.coord[1]+yOffset]}));onChangeProps(newProps);}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$r.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`Ellipse (${center[0]}, ${center[1]}), radius ${radius[0]}, ${radius[1]}`}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(EllipseSwatch,{color:props.color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{style:styles$r.row,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:center,style:styles$r.spaceUnder,onChange:handleCenterChange}),jsxRuntimeExports.jsx(View,{style:styles$r.spaceUnder,children:jsxRuntimeExports.jsx(InfoTip$c,{children:"The coordinates for the center of the ellipse."})})]}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:radius,labels:["x radius","y radius"],style:styles$r.spaceUnder,onChange:newCoords=>onChangeProps({radius:newCoords})}),jsxRuntimeExports.jsx(AngleInput,{angle:angle,onChange:newAngle=>onChangeProps({angle:newAngle})}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsxs(View,{style:[styles$r.row,styles$r.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$r.row,styles$r.truncatedWidth],children:["fill",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:fillStyle,onChange:value=>onChangeProps({fillStyle:value}),placeholder:"",children:Object.keys(lockedFigureFillStyles).map(option=>jsxRuntimeExports.jsx(OptionItem,{value:option,label:option},option))})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:{marginBottom:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$r.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$r.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$r.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[center[0],center[1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},style:styles$r.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$r=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:spacing.xSmall_8},truncatedWidth:{minWidth:0},addButton:{alignSelf:"start"},labelContainer:{backgroundColor:color.white},horizontalRule:{height:1,backgroundColor:color.offBlack16}});
1588
+ const{convertRadiansToDegrees}=angles;const{InfoTip: InfoTip$c}=components;const LockedEllipseSettings=props=>{const{center,radius,angle,color,labels,ariaLabel,fillStyle,strokeStyle,weight,expanded,onToggle,onChangeProps,onMove,onRemove}=props;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenCenterX=await generateSpokenMathDetails(`$${center[0]}$`);const spokenCenterY=await generateSpokenMathDetails(`$${center[1]}$`);const spokenRotation=await generateSpokenMathDetails(`$${convertRadiansToDegrees(angle)}$`);const isCircle=radius[0]===radius[1];let str="";if(isCircle){str+=`Circle${visiblelabel} with radius ${radius[0]}`;}else {str+=`Ellipse${visiblelabel} with x radius ${radius[0]} and y radius ${radius[1]}`;}str+=`, centered at ${spokenCenterX} comma ${spokenCenterY}`;if(!isCircle&&angle!==0){str+=`, rotated by ${spokenRotation} degrees`;}const ellipseAppearance=generateLockedFigureAppearanceDescription(color,strokeStyle,fillStyle,weight);str+=ellipseAppearance;return str}function handleCenterChange(newCoord){const xOffset=newCoord[0]-center[0];const yOffset=newCoord[1]-center[1];const newProps={center:newCoord};newProps.labels=labels.map(label=>({...label,coord:[label.coord[0]+xOffset,label.coord[1]+yOffset]}));onChangeProps(newProps);}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$s.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`Ellipse (${center[0]}, ${center[1]}), radius ${radius[0]}, ${radius[1]}`}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(EllipseSwatch,{color:props.color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{style:styles$s.row,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:center,style:styles$s.spaceUnder,onChange:handleCenterChange}),jsxRuntimeExports.jsx(View,{style:styles$s.spaceUnder,children:jsxRuntimeExports.jsx(InfoTip$c,{children:"The coordinates for the center of the ellipse."})})]}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:radius,labels:["x radius","y radius"],style:styles$s.spaceUnder,onChange:newCoords=>onChangeProps({radius:newCoords})}),jsxRuntimeExports.jsx(AngleInput,{angle:angle,onChange:newAngle=>onChangeProps({angle:newAngle})}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsxs(View,{style:[styles$s.row,styles$s.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$s.row,styles$s.truncatedWidth],children:["fill",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:fillStyle,onChange:value=>onChangeProps({fillStyle:value}),placeholder:"",children:Object.keys(lockedFigureFillStyles).map(option=>jsxRuntimeExports.jsx(OptionItem,{value:option,label:option},option))})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:{marginBottom:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$s.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$s.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$s.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[center[0],center[1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},style:styles$s.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$s=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:spacing.xSmall_8},truncatedWidth:{minWidth:0},addButton:{alignSelf:"start"},labelContainer:{backgroundColor:color.white},horizontalRule:{height:1,backgroundColor:color.offBlack16}});
1587
1589
 
1588
- const LineSwatch=props=>{const{color,lineStyle}=props;return jsxRuntimeExports.jsx(View,{style:styles$q.container,children:jsxRuntimeExports.jsx(View,{"aria-label":`${color}, ${lineStyle}`,style:[styles$q.lineSwatch,{border:`5px ${lineStyle} ${lockedFigureColors[color]}`}]})})};const styles$q=StyleSheet.create({container:{backgroundColor:color.white,justifyContent:"center",padding:spacing.xSmall_8,borderRadius:spacing.xxxSmall_4},lineSwatch:{width:40}});
1590
+ const LineSwatch=props=>{const{color,lineStyle}=props;return jsxRuntimeExports.jsx(View,{style:styles$r.container,children:jsxRuntimeExports.jsx(View,{"aria-label":`${color}, ${lineStyle}`,style:[styles$r.lineSwatch,{border:`5px ${lineStyle} ${lockedFigureColors[color]}`}]})})};const styles$r=StyleSheet.create({container:{backgroundColor:color.white,justifyContent:"center",padding:spacing.xSmall_8,borderRadius:spacing.xxxSmall_4},lineSwatch:{width:40}});
1589
1591
 
1590
1592
  const examples={linear:["x + 5","1/2x - 2"],polynomial:["1/2x^2 + 3x - 4","(1/3)x^3 - 2x^2 + 3x - 4"],trigonometric:["sin(x) * 3","arctan(2x) + 4"]};
1591
1593
 
1592
- const LockedFunctionSettings=props=>{const{color:lineColor,strokeStyle,equation,directionalAxis,domain,weight,ariaLabel,onChangeProps,onMove,onRemove}=props;const labels=props.labels;const equationPrefix=directionalAxis==="x"?"y=":"x=";const lineLabel=`Function (${equationPrefix}${equation})`;const getDomainStringValues=domain=>{return [Number.isFinite(domain[0])?domain[0].toString():"",Number.isFinite(domain[1])?domain[1].toString():""]};const[domainEntries,setDomainEntries]=useState(getDomainStringValues(domain));const[exampleCategory,setExampleCategory]=useState("");useEffect(()=>{setDomainEntries(getDomainStringValues(domain));},[domain]);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);let str=`Function${visiblelabel} with equation ${equationPrefix}${equation}`;if(Number.isFinite(domain[0])||Number.isFinite(domain[1])){str+=`, domain from ${domain[0]} to ${domain[1]}`;}const functionAppearance=generateLockedFigureAppearanceDescription(lineColor,strokeStyle,undefined,weight);str+=functionAppearance;return str}function handlePropChange(property,newValue){const updatedProps={};updatedProps[property]=newValue;onChangeProps(updatedProps);}function handleDomainChange(limitIndex,newValueString){const newDomainEntries=[...domainEntries];newDomainEntries[limitIndex]=newValueString;setDomainEntries(newDomainEntries);const newDomain=[...domain];let newValue=parseFloat(newValueString);if(newValueString===""&&limitIndex===0){newValue=-Infinity;}else if(newValueString===""&&limitIndex===1){newValue=Infinity;}newDomain[limitIndex]=newValue;onChangeProps({domain:newDomain});}const exampleCategories=Object.keys(examples);const exampleCategorySelected=exampleCategory!=="";const exampleContent=exampleCategorySelected?examples[exampleCategory]:["Select category to see example equations"];function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$p.row,children:[jsxRuntimeExports.jsx(LabelLarge,{style:styles$p.accordionHeader,children:lineLabel}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{style:[styles$p.row,{marginBottom:sizing.size_080}],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:newValue=>{handlePropChange("strokeStyle",newValue);}})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsxs(View,{style:[styles$p.row,styles$p.rowSpace],children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:directionalAxis,onChange:newValue=>{handlePropChange("directionalAxis",newValue);},"aria-label":"equation prefix",style:[styles$p.dropdownLabel,styles$p.axisMenu],placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"x",label:"y ="}),jsxRuntimeExports.jsx(OptionItem,{value:"y",label:"x ="})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(TextField,{type:"text","aria-label":"equation",value:equation,onChange:newValue=>{handlePropChange("equation",newValue);},style:[styles$p.textField]})]}),jsxRuntimeExports.jsxs(View,{style:[styles$p.row,styles$p.rowSpace],children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$p.dropdownLabel,styles$p.domainMin],children:["domain min",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(TextField,{type:"number",style:styles$p.domainMinField,value:domainEntries[0],onChange:newValue=>{handleDomainChange(0,newValue);}})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label","aria-label":"domain max",style:[styles$p.dropdownLabel,styles$p.domainMax],children:["max",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(TextField,{type:"number",style:styles$p.domainMaxField,value:domainEntries[1],onChange:newValue=>{handleDomainChange(1,newValue);}})]})]}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(LabelLarge,{children:"Example Functions"}),expanded:false,containerStyle:styles$p.exampleWorkspace,panelStyle:styles$p.exampleAccordionPanel,children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$p.dropdownLabel,children:["Choose a category",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:exampleCategory,onChange:setExampleCategory,placeholder:"examples",children:exampleCategories.map(category=>{return jsxRuntimeExports.jsx(OptionItem,{value:category,label:category},category)})})]}),exampleCategorySelected&&jsxRuntimeExports.jsx("ul",{className:css(styles$p.exampleContainer),children:exampleContent.map((example,index)=>jsxRuntimeExports.jsx(ExampleItem,{category:exampleCategory,example:example,index:index,pasteEquationFn:handlePropChange},index))})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$p.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$p.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>jsxRuntimeExports.jsx(LockedLabelSettings,{...label,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$p.labelContainer},labelIndex)),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[0,-labels.length],color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$p.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const ExampleItem=props=>{const{category,example,index,pasteEquationFn}=props;const exampleId=useId();return jsxRuntimeExports.jsxs("li",{className:css(styles$p.exampleRow),children:[jsxRuntimeExports.jsx(IconButton,{icon:autoPasteIcon,kind:"tertiary","aria-label":"paste example","aria-describedby":exampleId,onClick:()=>pasteEquationFn("equation",example),size:"medium",style:styles$p.copyPasteButton}),jsxRuntimeExports.jsx(IconButton,{icon:copyIcon,kind:"tertiary","aria-label":"copy example","aria-describedby":exampleId,onClick:()=>navigator.clipboard.writeText(example),size:"medium",style:styles$p.copyPasteButton}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$p.exampleContent,id:exampleId,children:example})]},`${category}-${index}`)};const styles$p=StyleSheet.create({accordionHeader:{textOverflow:"ellipsis",maxWidth:"calc(100% - 64px)",overflow:"hidden",whiteSpace:"nowrap"},axisMenu:{minWidth:"auto"},copyPasteButton:{flexShrink:"0",margin:"0 2px"},domainMin:{justifyContent:"space-between",width:"calc(((100% - 141px) / 2) + 88.7px)",textWrap:"nowrap"},domainMinField:{width:"calc(100% - 88.7px)"},domainMax:{width:"calc(((100% - 141px) / 2) + 36.2px)"},domainMaxField:{width:"calc(100% - 36.2px)"},dropdownLabel:{alignItems:"center",display:"flex"},exampleAccordionPanel:{alignItems:"start",paddingBottom:"12px",flexDirection:"row",flexWrap:"wrap"},exampleContainer:{background:"white",border:`1px solid ${color.fadedOffBlack16}`,borderRadius:"4px",flexGrow:"1",listStyleType:"none",maxHeight:"88px",margin:"8px 0 0 0",overflowY:"scroll",padding:"4px 12px 4px 4px"},exampleContent:{fontFamily:`"Lato", sans-serif`,flexGrow:"1",color:color.offBlack},exampleRow:{alignItems:"center",display:"flex",flexDirection:"row",minHeight:"44px"},exampleWorkspace:{background:color.white50},rowSpace:{marginTop:spacing.xSmall_8},row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{flexGrow:"1"},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16},labelContainer:{backgroundColor:color.white}});
1594
+ const LockedFunctionSettings=props=>{const{color:lineColor,strokeStyle,equation,directionalAxis,domain,weight,ariaLabel,onChangeProps,onMove,onRemove}=props;const labels=props.labels;const equationPrefix=directionalAxis==="x"?"y=":"x=";const lineLabel=`Function (${equationPrefix}${equation})`;const getDomainStringValues=domain=>{return [Number.isFinite(domain[0])?domain[0].toString():"",Number.isFinite(domain[1])?domain[1].toString():""]};const[domainEntries,setDomainEntries]=useState(getDomainStringValues(domain));const[exampleCategory,setExampleCategory]=useState("");useEffect(()=>{setDomainEntries(getDomainStringValues(domain));},[domain]);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);let str=`Function${visiblelabel} with equation ${equationPrefix}${equation}`;if(Number.isFinite(domain[0])||Number.isFinite(domain[1])){str+=`, domain from ${domain[0]} to ${domain[1]}`;}const functionAppearance=generateLockedFigureAppearanceDescription(lineColor,strokeStyle,undefined,weight);str+=functionAppearance;return str}function handlePropChange(property,newValue){const updatedProps={};updatedProps[property]=newValue;onChangeProps(updatedProps);}function handleDomainChange(limitIndex,newValueString){const newDomainEntries=[...domainEntries];newDomainEntries[limitIndex]=newValueString;setDomainEntries(newDomainEntries);const newDomain=[...domain];let newValue=parseFloat(newValueString);if(newValueString===""&&limitIndex===0){newValue=-Infinity;}else if(newValueString===""&&limitIndex===1){newValue=Infinity;}newDomain[limitIndex]=newValue;onChangeProps({domain:newDomain});}const exampleCategories=Object.keys(examples);const exampleCategorySelected=exampleCategory!=="";const exampleContent=exampleCategorySelected?examples[exampleCategory]:["Select category to see example equations"];function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$q.row,children:[jsxRuntimeExports.jsx(LabelLarge,{style:styles$q.accordionHeader,children:lineLabel}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{style:[styles$q.row,{marginBottom:sizing.size_080}],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:newValue=>{handlePropChange("strokeStyle",newValue);}})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsxs(View,{style:[styles$q.row,styles$q.rowSpace],children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:directionalAxis,onChange:newValue=>{handlePropChange("directionalAxis",newValue);},"aria-label":"equation prefix",style:[styles$q.dropdownLabel,styles$q.axisMenu],placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"x",label:"y ="}),jsxRuntimeExports.jsx(OptionItem,{value:"y",label:"x ="})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(TextField,{type:"text","aria-label":"equation",value:equation,onChange:newValue=>{handlePropChange("equation",newValue);},style:[styles$q.textField]})]}),jsxRuntimeExports.jsxs(View,{style:[styles$q.row,styles$q.rowSpace],children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$q.dropdownLabel,styles$q.domainMin],children:["domain min",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(TextField,{type:"number",style:styles$q.domainMinField,value:domainEntries[0],onChange:newValue=>{handleDomainChange(0,newValue);}})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label","aria-label":"domain max",style:[styles$q.dropdownLabel,styles$q.domainMax],children:["max",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(TextField,{type:"number",style:styles$q.domainMaxField,value:domainEntries[1],onChange:newValue=>{handleDomainChange(1,newValue);}})]})]}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(LabelLarge,{children:"Example Functions"}),expanded:false,containerStyle:styles$q.exampleWorkspace,panelStyle:styles$q.exampleAccordionPanel,children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:styles$q.dropdownLabel,children:["Choose a category",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:exampleCategory,onChange:setExampleCategory,placeholder:"examples",children:exampleCategories.map(category=>{return jsxRuntimeExports.jsx(OptionItem,{value:category,label:category},category)})})]}),exampleCategorySelected&&jsxRuntimeExports.jsx("ul",{className:css(styles$q.exampleContainer),children:exampleContent.map((example,index)=>jsxRuntimeExports.jsx(ExampleItem,{category:exampleCategory,example:example,index:index,pasteEquationFn:handlePropChange},index))})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$q.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$q.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>jsxRuntimeExports.jsx(LockedLabelSettings,{...label,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$q.labelContainer},labelIndex)),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[0,-labels.length],color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$q.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const ExampleItem=props=>{const{category,example,index,pasteEquationFn}=props;const exampleId=useId();return jsxRuntimeExports.jsxs("li",{className:css(styles$q.exampleRow),children:[jsxRuntimeExports.jsx(IconButton,{icon:autoPasteIcon,kind:"tertiary","aria-label":"paste example","aria-describedby":exampleId,onClick:()=>pasteEquationFn("equation",example),size:"medium",style:styles$q.copyPasteButton}),jsxRuntimeExports.jsx(IconButton,{icon:copyIcon,kind:"tertiary","aria-label":"copy example","aria-describedby":exampleId,onClick:()=>navigator.clipboard.writeText(example),size:"medium",style:styles$q.copyPasteButton}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$q.exampleContent,id:exampleId,children:example})]},`${category}-${index}`)};const styles$q=StyleSheet.create({accordionHeader:{textOverflow:"ellipsis",maxWidth:"calc(100% - 64px)",overflow:"hidden",whiteSpace:"nowrap"},axisMenu:{minWidth:"auto"},copyPasteButton:{flexShrink:"0",margin:"0 2px"},domainMin:{justifyContent:"space-between",width:"calc(((100% - 141px) / 2) + 88.7px)",textWrap:"nowrap"},domainMinField:{width:"calc(100% - 88.7px)"},domainMax:{width:"calc(((100% - 141px) / 2) + 36.2px)"},domainMaxField:{width:"calc(100% - 36.2px)"},dropdownLabel:{alignItems:"center",display:"flex"},exampleAccordionPanel:{alignItems:"start",paddingBottom:"12px",flexDirection:"row",flexWrap:"wrap"},exampleContainer:{background:"white",border:`1px solid ${color.fadedOffBlack16}`,borderRadius:"4px",flexGrow:"1",listStyleType:"none",maxHeight:"88px",margin:"8px 0 0 0",overflowY:"scroll",padding:"4px 12px 4px 4px"},exampleContent:{fontFamily:`"Lato", sans-serif`,flexGrow:"1",color:color.offBlack},exampleRow:{alignItems:"center",display:"flex",flexDirection:"row",minHeight:"44px"},exampleWorkspace:{background:color.white50},rowSpace:{marginTop:spacing.xSmall_8},row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{flexGrow:"1"},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16},labelContainer:{backgroundColor:color.white}});
1593
1595
 
1594
- const LabeledSwitch=props=>{const{checked,label,style,onChange}=props;const switchId=useId();return jsxRuntimeExports.jsxs(View,{style:[styles$o.row,style],children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:checked,onChange:onChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LabelMedium,{tag:"label",htmlFor:switchId,children:label})]})};const styles$o=StyleSheet.create({row:{flexDirection:"row",alignItems:"center"}});
1596
+ const LabeledSwitch=props=>{const{checked,label,style,onChange}=props;const switchId=useId();return jsxRuntimeExports.jsxs(View,{style:[styles$p.row,style],children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:checked,onChange:onChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LabelMedium,{tag:"label",htmlFor:switchId,children:label})]})};const styles$p=StyleSheet.create({row:{flexDirection:"row",alignItems:"center"}});
1595
1597
 
1596
- const LockedPointSettings=props=>{const{headerLabel,coord,color:pointColor,filled=true,labels,ariaLabel,onChangeProps,onMove,onRemove,showPoint,error,expanded,onTogglePoint,onToggle}=props;const isDefiningPoint=!onMove&&!onRemove;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenX=await generateSpokenMathDetails(`$${coord[0]}$`);const spokenY=await generateSpokenMathDetails(`$${coord[1]}$`);let str=`Point${visiblelabel} at ${spokenX} comma ${spokenY}`;const pointAppearance=generateLockedFigureAppearanceDescription(pointColor);str+=pointAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleCoordChange(newCoord){const xOffset=newCoord[0]-coord[0];const yOffset=newCoord[1]-coord[1];const newProps={coord:newCoord};newProps.labels=labels.map(label=>({...label,coord:[label.coord[0]+xOffset,label.coord[1]+yOffset]}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,containerStyle:isDefiningPoint?styles$n.definingContainer:undefined,panelStyle:isDefiningPoint?styles$n.definingPanel:undefined,header:jsxRuntimeExports.jsxs(View,{style:styles$n.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`${headerLabel||"Point"} (${coord[0]}, ${coord[1]})`}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(ColorSwatch,{color:pointColor,filled:filled})]}),children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,style:styles$n.spaceUnder,onChange:handleCoordChange,error:!!error}),onTogglePoint&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"show point on graph",checked:!!showPoint,style:showPoint&&styles$n.spaceUnder,onChange:onTogglePoint}),(!isDefiningPoint||showPoint)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:pointColor,onChange:handleColorChange,style:styles$n.spaceUnder}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"open point",checked:!filled,onChange:newValue=>{onChangeProps({filled:!newValue});}})]}),!isDefiningPoint&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$n.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$n.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,containerStyle:!isDefiningPoint&&styles$n.lockedPointLabelContainer,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);}})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[coord[0]+.5,coord[1]-labels.length],color:pointColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$n.addButton,children:"Add visible label"}),onRemove&&jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$n=StyleSheet.create({definingContainer:{marginTop:spacing.xSmall_8,marginBottom:0,marginLeft:-spacing.xxxSmall_4,marginRight:-spacing.xxxSmall_4,backgroundColor:color.white},definingPanel:{paddingBottom:spacing.xxSmall_6},lockedPointLabelContainer:{backgroundColor:color.white},row:{flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:spacing.xSmall_8},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16}});
1598
+ const LockedPointSettings=props=>{const{headerLabel,coord,color:pointColor,filled=true,labels,ariaLabel,onChangeProps,onMove,onRemove,showPoint,error,expanded,onTogglePoint,onToggle}=props;const isDefiningPoint=!onMove&&!onRemove;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenX=await generateSpokenMathDetails(`$${coord[0]}$`);const spokenY=await generateSpokenMathDetails(`$${coord[1]}$`);let str=`Point${visiblelabel} at ${spokenX} comma ${spokenY}`;const pointAppearance=generateLockedFigureAppearanceDescription(pointColor);str+=pointAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleCoordChange(newCoord){const xOffset=newCoord[0]-coord[0];const yOffset=newCoord[1]-coord[1];const newProps={coord:newCoord};newProps.labels=labels.map(label=>({...label,coord:[label.coord[0]+xOffset,label.coord[1]+yOffset]}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,containerStyle:isDefiningPoint?styles$o.definingContainer:undefined,panelStyle:isDefiningPoint?styles$o.definingPanel:undefined,header:jsxRuntimeExports.jsxs(View,{style:styles$o.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`${headerLabel||"Point"} (${coord[0]}, ${coord[1]})`}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(ColorSwatch,{color:pointColor,filled:filled})]}),children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,style:styles$o.spaceUnder,onChange:handleCoordChange,error:!!error}),onTogglePoint&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"show point on graph",checked:!!showPoint,style:showPoint&&styles$o.spaceUnder,onChange:onTogglePoint}),(!isDefiningPoint||showPoint)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:pointColor,onChange:handleColorChange,style:styles$o.spaceUnder}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"open point",checked:!filled,onChange:newValue=>{onChangeProps({filled:!newValue});}})]}),!isDefiningPoint&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$o.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$o.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,containerStyle:!isDefiningPoint&&styles$o.lockedPointLabelContainer,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);}})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[coord[0]+.5,coord[1]-labels.length],color:pointColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$o.addButton,children:"Add visible label"}),onRemove&&jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$o=StyleSheet.create({definingContainer:{marginTop:spacing.xSmall_8,marginBottom:0,marginLeft:-spacing.xxxSmall_4,marginRight:-spacing.xxxSmall_4,backgroundColor:color.white},definingPanel:{paddingBottom:spacing.xxSmall_6},lockedPointLabelContainer:{backgroundColor:color.white},row:{flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:spacing.xSmall_8},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16}});
1597
1599
 
1598
1600
  const lengthZeroStr="The line cannot have length 0.";const LockedLineSettings=props=>{const{kind,points,color:lineColor,lineStyle="solid",showPoint1,showPoint2,weight,labels,ariaLabel,onChangeProps,onMove,onRemove}=props;const[point1,point2]=points;const capitalizeKind=kind.charAt(0).toUpperCase()+kind.slice(1);const lineLabel=`${capitalizeKind} (${point1.coord[0]},
1599
- ${point1.coord[1]}), (${point2.coord[0]}, ${point2.coord[1]})`;const isInvalid=vector.equal(point1.coord,point2.coord);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const point1VisibleLabel=await joinLabelsAsSpokenMath(point1.labels);const point2VisibleLabel=await joinLabelsAsSpokenMath(point2.labels);const spokenPoint1X=await generateSpokenMathDetails(`$${point1.coord[0]}$`);const spokenPoint1Y=await generateSpokenMathDetails(`$${point1.coord[1]}$`);const spokenPoint2X=await generateSpokenMathDetails(`$${point2.coord[0]}$`);const spokenPoint2Y=await generateSpokenMathDetails(`$${point2.coord[1]}$`);let str;switch(kind){case "line":str=`${capitalizeKind}${visiblelabel} through point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} and point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;case "ray":str=`${capitalizeKind}${visiblelabel} from point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} through point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;case "segment":str=`${capitalizeKind}${visiblelabel} from point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} to point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;default:throw new UnreachableCaseError(kind,"Unknown line kind")}const lineAppearance=generateLockedFigureAppearanceDescription(lineColor,lineStyle,undefined,weight);str+=lineAppearance;return str}function handleChangePoint(newPointProps,index){const newPoints=[...points];newPoints[index]={...points[index],...newPointProps};const oldMidpoint=vec.midpoint(points[0].coord,points[1].coord);const newMidpoint=vec.midpoint(newPoints[0].coord,newPoints[1].coord);const offset=[newMidpoint[0]-oldMidpoint[0],newMidpoint[1]-oldMidpoint[1]];const newLabels=labels.map((label,labelIndex)=>({...label,coord:[label.coord[0]+offset[0],label.coord[1]+offset[1]]}));onChangeProps({points:newPoints,labels:newLabels});}function handleColorChange(newColor){const newLabels=labels.map(label=>({...label,color:newColor}));onChangeProps({color:newColor,points:[{...point1,color:newColor,labels:point1.labels.map(label=>({...label,color:newColor}))},{...point2,color:newColor,labels:point2.labels.map(label=>({...label,color:newColor}))}],labels:newLabels});}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$m.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:lineLabel}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:lineStyle})]}),children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$m.row,styles$m.spaceUnder],children:["kind",jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:kind,onChange:value=>onChangeProps({kind:value}),placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"line",label:"line"}),jsxRuntimeExports.jsx(OptionItem,{value:"ray",label:"ray"}),jsxRuntimeExports.jsx(OptionItem,{value:"segment",label:"segment"})]})]}),jsxRuntimeExports.jsxs(View,{style:[styles$m.row,styles$m.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:lineStyle,onChange:value=>onChangeProps({lineStyle:value})})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(LabelMedium,{style:styles$m.errorText,children:lengthZeroStr}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 1",expanded:true,showPoint:showPoint1,error:isInvalid?lengthZeroStr:null,...point1,onTogglePoint:newValue=>onChangeProps({showPoint1:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,0)}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 2",expanded:true,showPoint:showPoint2,error:isInvalid?lengthZeroStr:null,...point2,onTogglePoint:newValue=>onChangeProps({showPoint2:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,1)}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$m.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$m.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$m.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const offsetPerLabel=[0,-1];const labelLocation=vec.add(vec.scale(offsetPerLabel,labels.length),vec.midpoint(points[0].coord,points[1].coord));const newLabel={...getDefaultFigureForType("label"),coord:labelLocation,color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$m.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$m=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:spacing.xSmall_8},errorText:{color:color.red},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16},labelContainer:{backgroundColor:color.white}});
1601
+ ${point1.coord[1]}), (${point2.coord[0]}, ${point2.coord[1]})`;const isInvalid=vector.equal(point1.coord,point2.coord);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const point1VisibleLabel=await joinLabelsAsSpokenMath(point1.labels);const point2VisibleLabel=await joinLabelsAsSpokenMath(point2.labels);const spokenPoint1X=await generateSpokenMathDetails(`$${point1.coord[0]}$`);const spokenPoint1Y=await generateSpokenMathDetails(`$${point1.coord[1]}$`);const spokenPoint2X=await generateSpokenMathDetails(`$${point2.coord[0]}$`);const spokenPoint2Y=await generateSpokenMathDetails(`$${point2.coord[1]}$`);let str;switch(kind){case "line":str=`${capitalizeKind}${visiblelabel} through point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} and point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;case "ray":str=`${capitalizeKind}${visiblelabel} from point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} through point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;case "segment":str=`${capitalizeKind}${visiblelabel} from point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} to point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;default:throw new UnreachableCaseError(kind,"Unknown line kind")}const lineAppearance=generateLockedFigureAppearanceDescription(lineColor,lineStyle,undefined,weight);str+=lineAppearance;return str}function handleChangePoint(newPointProps,index){const newPoints=[...points];newPoints[index]={...points[index],...newPointProps};const oldMidpoint=vec.midpoint(points[0].coord,points[1].coord);const newMidpoint=vec.midpoint(newPoints[0].coord,newPoints[1].coord);const offset=[newMidpoint[0]-oldMidpoint[0],newMidpoint[1]-oldMidpoint[1]];const newLabels=labels.map((label,labelIndex)=>({...label,coord:[label.coord[0]+offset[0],label.coord[1]+offset[1]]}));onChangeProps({points:newPoints,labels:newLabels});}function handleColorChange(newColor){const newLabels=labels.map(label=>({...label,color:newColor}));onChangeProps({color:newColor,points:[{...point1,color:newColor,labels:point1.labels.map(label=>({...label,color:newColor}))},{...point2,color:newColor,labels:point2.labels.map(label=>({...label,color:newColor}))}],labels:newLabels});}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$n.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:lineLabel}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:lineStyle})]}),children:[jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$n.row,styles$n.spaceUnder],children:["kind",jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:kind,onChange:value=>onChangeProps({kind:value}),placeholder:"",children:[jsxRuntimeExports.jsx(OptionItem,{value:"line",label:"line"}),jsxRuntimeExports.jsx(OptionItem,{value:"ray",label:"ray"}),jsxRuntimeExports.jsx(OptionItem,{value:"segment",label:"segment"})]})]}),jsxRuntimeExports.jsxs(View,{style:[styles$n.row,styles$n.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:lineStyle,onChange:value=>onChangeProps({lineStyle:value})})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(LabelMedium,{style:styles$n.errorText,children:lengthZeroStr}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 1",expanded:true,showPoint:showPoint1,error:isInvalid?lengthZeroStr:null,...point1,onTogglePoint:newValue=>onChangeProps({showPoint1:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,0)}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 2",expanded:true,showPoint:showPoint2,error:isInvalid?lengthZeroStr:null,...point2,onTogglePoint:newValue=>onChangeProps({showPoint2:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,1)}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$n.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$n.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$n.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const offsetPerLabel=[0,-1];const labelLocation=vec.add(vec.scale(offsetPerLabel,labels.length),vec.midpoint(points[0].coord,points[1].coord));const newLabel={...getDefaultFigureForType("label"),coord:labelLocation,color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$n.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$n=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:spacing.xSmall_8},errorText:{color:color.red},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16},labelContainer:{backgroundColor:color.white}});
1600
1602
 
1601
- const PolygonSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$l.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$l.innerSquare,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$l=StyleSheet.create({container:{outline:`2px solid ${color.offWhite}`,width:spacing.large_24,height:spacing.large_24,backgroundColor:color.white,alignItems:"center",justifyContent:"center"},innerSquare:{width:20,height:20}});
1603
+ const PolygonSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$m.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$m.innerSquare,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$m=StyleSheet.create({container:{outline:`2px solid ${color.offWhite}`,width:spacing.large_24,height:spacing.large_24,backgroundColor:color.white,alignItems:"center",justifyContent:"center"},innerSquare:{width:20,height:20}});
1602
1604
 
1603
- const LockedPolygonSettings=props=>{const{points,color,showVertices,fillStyle,strokeStyle,weight,labels,ariaLabel,expanded,onToggle,onChangeProps,onMove,onRemove}=props;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);let str=`Polygon${visiblelabel} with ${points.length} sides, vertices at `;const pointsList=await Promise.all(points.map(async([x,y])=>{const spokenX=await generateSpokenMathDetails(`$${x}$`);const spokenY=await generateSpokenMathDetails(`$${y}$`);return `${spokenX} comma ${spokenY}`}));str+=pointsList.join(", ");const polygonAppearance=generateLockedFigureAppearanceDescription(color,strokeStyle,fillStyle,weight);str+=polygonAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handlePolygonMove(movement){switch(movement){case "up":onChangeProps({points:points.map(([x,y])=>[x,y+1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]+1]}))});break;case "down":onChangeProps({points:points.map(([x,y])=>[x,y-1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]-1]}))});break;case "left":onChangeProps({points:points.map(([x,y])=>[x-1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]-1,label.coord[1]]}))});break;case "right":onChangeProps({points:points.map(([x,y])=>[x+1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]+1,label.coord[1]]}))});break}}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$k.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`Polygon, ${points.length} sides`}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(PolygonSwatch,{color:color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{style:[styles$k.row,styles$k.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$k.row,styles$k.truncatedWidth],children:["fill",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:fillStyle,onChange:value=>onChangeProps({fillStyle:value}),placeholder:"",children:Object.keys(lockedFigureFillStyles).map(option=>jsxRuntimeExports.jsx(OptionItem,{value:option,label:option},option))})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:styles$k.spaceUnder}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value}),containerStyle:styles$k.spaceUnder}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"show vertices",checked:showVertices,onChange:newValue=>onChangeProps({showVertices:newValue}),style:styles$k.spaceUnder}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(LabelLarge,{children:"Points"}),expanded:true,containerStyle:styles$k.pointAccordionContainer,panelStyle:styles$k.pointAccordionPanel,children:[points.map((point,index)=>{const pointLabel=String.fromCharCode(65+index);return jsxRuntimeExports.jsxs(View,{style:[styles$k.row,styles$k.spaceUnder],children:[jsxRuntimeExports.jsx(LabelLarge,{children:`${pointLabel}:`}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:point,labels:["x","y"],onChange:newValue=>{const newPoints=[...points];newPoints[index]=newValue;props.onChangeProps({points:newPoints});}}),points.length>3&&jsxRuntimeExports.jsx(IconButton,{"aria-label":`Delete polygon point ${pointLabel}`,icon:minusCircle,kind:"tertiary",actionType:"destructive",onClick:()=>{const newPoints=[...points];newPoints.splice(index,1);props.onChangeProps({points:newPoints});},style:styles$k.icon})]},`locked-polygon-point-index-${index}`)}),jsxRuntimeExports.jsxs(View,{style:[styles$k.row,styles$k.polygonActionsContainer],children:[jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{props.onChangeProps({points:[...points,[0,0]]});},children:"Add point"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(View,{style:styles$k.movementButtonsContainer,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon up",size:"small",icon:arrowFatUp,kind:"tertiary",onClick:()=>handlePolygonMove("up")}),jsxRuntimeExports.jsxs(View,{style:styles$k.row,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon left",size:"small",icon:arrowFatLeft,kind:"tertiary",onClick:()=>handlePolygonMove("left")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon down",size:"small",icon:arrowFatDown,kind:"tertiary",onClick:()=>handlePolygonMove("down")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon right",size:"small",icon:arrowFatRight,kind:"tertiary",onClick:()=>handlePolygonMove("right")})]})]})]})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$k.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$k.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$k.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[points[0][0],points[0][1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},style:styles$k.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$k=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},pointAccordionContainer:{backgroundColor:color.white},pointAccordionPanel:{alignItems:"start"},icon:{marginInlineStart:spacing.xxxSmall_4},polygonActionsContainer:{width:"100%"},movementButtonsContainer:{display:"flex",flexDirection:"column",alignItems:"center",minWidth:"fit-content"},spaceUnder:{marginBottom:spacing.xSmall_8},truncatedWidth:{minWidth:0},addButton:{alignSelf:"start"},labelContainer:{backgroundColor:color.white},horizontalRule:{height:1,backgroundColor:color.offBlack16}});
1605
+ const LockedPolygonSettings=props=>{const{points,color,showVertices,fillStyle,strokeStyle,weight,labels,ariaLabel,expanded,onToggle,onChangeProps,onMove,onRemove}=props;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);let str=`Polygon${visiblelabel} with ${points.length} sides, vertices at `;const pointsList=await Promise.all(points.map(async([x,y])=>{const spokenX=await generateSpokenMathDetails(`$${x}$`);const spokenY=await generateSpokenMathDetails(`$${y}$`);return `${spokenX} comma ${spokenY}`}));str+=pointsList.join(", ");const polygonAppearance=generateLockedFigureAppearanceDescription(color,strokeStyle,fillStyle,weight);str+=polygonAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handlePolygonMove(movement){switch(movement){case "up":onChangeProps({points:points.map(([x,y])=>[x,y+1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]+1]}))});break;case "down":onChangeProps({points:points.map(([x,y])=>[x,y-1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]-1]}))});break;case "left":onChangeProps({points:points.map(([x,y])=>[x-1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]-1,label.coord[1]]}))});break;case "right":onChangeProps({points:points.map(([x,y])=>[x+1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]+1,label.coord[1]]}))});break}}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$l.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`Polygon, ${points.length} sides`}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(PolygonSwatch,{color:color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{style:[styles$l.row,styles$l.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,onChange:handleColorChange}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsxs(LabelMedium,{tag:"label",style:[styles$l.row,styles$l.truncatedWidth],children:["fill",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(SingleSelect,{selectedValue:fillStyle,onChange:value=>onChangeProps({fillStyle:value}),placeholder:"",children:Object.keys(lockedFigureFillStyles).map(option=>jsxRuntimeExports.jsx(OptionItem,{value:option,label:option},option))})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:styles$l.spaceUnder}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value}),containerStyle:styles$l.spaceUnder}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"show vertices",checked:showVertices,onChange:newValue=>onChangeProps({showVertices:newValue}),style:styles$l.spaceUnder}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(LabelLarge,{children:"Points"}),expanded:true,containerStyle:styles$l.pointAccordionContainer,panelStyle:styles$l.pointAccordionPanel,children:[points.map((point,index)=>{const pointLabel=String.fromCharCode(65+index);return jsxRuntimeExports.jsxs(View,{style:[styles$l.row,styles$l.spaceUnder],children:[jsxRuntimeExports.jsx(LabelLarge,{children:`${pointLabel}:`}),jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:point,labels:["x","y"],onChange:newValue=>{const newPoints=[...points];newPoints[index]=newValue;props.onChangeProps({points:newPoints});}}),points.length>3&&jsxRuntimeExports.jsx(IconButton,{"aria-label":`Delete polygon point ${pointLabel}`,icon:minusCircle,kind:"tertiary",actionType:"destructive",onClick:()=>{const newPoints=[...points];newPoints.splice(index,1);props.onChangeProps({points:newPoints});},style:styles$l.icon})]},`locked-polygon-point-index-${index}`)}),jsxRuntimeExports.jsxs(View,{style:[styles$l.row,styles$l.polygonActionsContainer],children:[jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{props.onChangeProps({points:[...points,[0,0]]});},children:"Add point"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(View,{style:styles$l.movementButtonsContainer,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon up",size:"small",icon:arrowFatUp,kind:"tertiary",onClick:()=>handlePolygonMove("up")}),jsxRuntimeExports.jsxs(View,{style:styles$l.row,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon left",size:"small",icon:arrowFatLeft,kind:"tertiary",onClick:()=>handlePolygonMove("left")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon down",size:"small",icon:arrowFatDown,kind:"tertiary",onClick:()=>handlePolygonMove("down")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon right",size:"small",icon:arrowFatRight,kind:"tertiary",onClick:()=>handlePolygonMove("right")})]})]})]})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$l.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$l.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$l.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[points[0][0],points[0][1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},style:styles$l.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$l=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},pointAccordionContainer:{backgroundColor:color.white},pointAccordionPanel:{alignItems:"start"},icon:{marginInlineStart:spacing.xxxSmall_4},polygonActionsContainer:{width:"100%"},movementButtonsContainer:{display:"flex",flexDirection:"column",alignItems:"center",minWidth:"fit-content"},spaceUnder:{marginBottom:spacing.xSmall_8},truncatedWidth:{minWidth:0},addButton:{alignSelf:"start"},labelContainer:{backgroundColor:color.white},horizontalRule:{height:1,backgroundColor:color.offBlack16}});
1604
1606
 
1605
- const lengthErrorMessage="The vector cannot have length 0.";const LockedVectorSettings=props=>{const{points,color:lineColor,weight,labels,ariaLabel,onChangeProps,onMove,onRemove}=props;const[tail,tip]=points;const lineLabel=`Vector (${tail[0]}, ${tail[1]}), (${tip[0]}, ${tip[1]})`;const isInvalid=vector.equal(tail,tip);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenTailX=await generateSpokenMathDetails(`$${tail[0]}$`);const spokenTailY=await generateSpokenMathDetails(`$${tail[1]}$`);const spokenTipX=await generateSpokenMathDetails(`$${tip[0]}$`);const spokenTipY=await generateSpokenMathDetails(`$${tip[1]}$`);let str=`Vector${visiblelabel} from ${spokenTailX} comma ${spokenTailY} to ${spokenTipX} comma ${spokenTipY}`;const vectorAppearance=generateLockedFigureAppearanceDescription(lineColor,"solid",undefined,weight);str+=vectorAppearance;return str}function handleChangePoint(newCoord,index){if(typeof newCoord!=="undefined"){const newPoints=[...points];newPoints[index]=[...newCoord];const oldMidpoint=vec.midpoint(tail,tip);const newMidpoint=vec.midpoint(newPoints[0],newPoints[1]);const offset=vec.sub(newMidpoint,oldMidpoint);const newLabels=labels.map(label=>({...label,coord:vec.add(label.coord,offset)}));onChangeProps({points:newPoints,labels:newLabels});}}function handleColorChange(newColor){const newProps={color:newColor};newProps.labels=labels.map(label=>({...label,color:newColor}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$j.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:lineLabel}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:"solid"})]}),children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange,style:{marginBottom:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(LabelMedium,{style:styles$j.errorText,children:lengthErrorMessage}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:styles$j.container,panelStyle:styles$j.accordionPanel,header:jsxRuntimeExports.jsx(View,{style:styles$j.row,children:jsxRuntimeExports.jsx(LabelLarge,{children:`Tail (${tail[0]}, ${tail[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tail,error:isInvalid,onChange:newProps=>{handleChangePoint(newProps,0);}})}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:styles$j.container,panelStyle:styles$j.accordionPanel,header:jsxRuntimeExports.jsx(View,{style:styles$j.row,children:jsxRuntimeExports.jsx(LabelLarge,{children:`Tip (${tip[0]}, ${tip[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tip,error:isInvalid,onChange:newProps=>{handleChangePoint(newProps,1);}})}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$j.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$j.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$j.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const offsetPerLabel=[0,-1];const labelLocation=vec.add(vec.scale(offsetPerLabel,labels.length),vec.midpoint(tail,tip));const newLabel={...getDefaultFigureForType("label"),coord:labelLocation,color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$j.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$j=StyleSheet.create({accordionPanel:{paddingBottom:spacing.medium_16},container:{marginTop:spacing.xSmall_8,marginBottom:0,marginLeft:-spacing.xxxSmall_4,marginRight:-spacing.xxxSmall_4,backgroundColor:color.white},errorText:{color:color.red,marginTop:spacing.xSmall_8},row:{flexDirection:"row",alignItems:"center"},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16},labelContainer:{backgroundColor:color.white}});
1607
+ const lengthErrorMessage="The vector cannot have length 0.";const LockedVectorSettings=props=>{const{points,color:lineColor,weight,labels,ariaLabel,onChangeProps,onMove,onRemove}=props;const[tail,tip]=points;const lineLabel=`Vector (${tail[0]}, ${tail[1]}), (${tip[0]}, ${tip[1]})`;const isInvalid=vector.equal(tail,tip);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenTailX=await generateSpokenMathDetails(`$${tail[0]}$`);const spokenTailY=await generateSpokenMathDetails(`$${tail[1]}$`);const spokenTipX=await generateSpokenMathDetails(`$${tip[0]}$`);const spokenTipY=await generateSpokenMathDetails(`$${tip[1]}$`);let str=`Vector${visiblelabel} from ${spokenTailX} comma ${spokenTailY} to ${spokenTipX} comma ${spokenTipY}`;const vectorAppearance=generateLockedFigureAppearanceDescription(lineColor,"solid",undefined,weight);str+=vectorAppearance;return str}function handleChangePoint(newCoord,index){if(typeof newCoord!=="undefined"){const newPoints=[...points];newPoints[index]=[...newCoord];const oldMidpoint=vec.midpoint(tail,tip);const newMidpoint=vec.midpoint(newPoints[0],newPoints[1]);const offset=vec.sub(newMidpoint,oldMidpoint);const newLabels=labels.map(label=>({...label,coord:vec.add(label.coord,offset)}));onChangeProps({points:newPoints,labels:newLabels});}}function handleColorChange(newColor){const newProps={color:newColor};newProps.labels=labels.map(label=>({...label,color:newColor}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(View,{style:styles$k.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:lineLabel}),jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:"solid"})]}),children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange,style:{marginBottom:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(LabelMedium,{style:styles$k.errorText,children:lengthErrorMessage}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:styles$k.container,panelStyle:styles$k.accordionPanel,header:jsxRuntimeExports.jsx(View,{style:styles$k.row,children:jsxRuntimeExports.jsx(LabelLarge,{children:`Tail (${tail[0]}, ${tail[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tail,error:isInvalid,onChange:newProps=>{handleChangePoint(newProps,0);}})}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:styles$k.container,panelStyle:styles$k.accordionPanel,header:jsxRuntimeExports.jsx(View,{style:styles$k.row,children:jsxRuntimeExports.jsx(LabelLarge,{children:`Tip (${tip[0]}, ${tip[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tip,error:isInvalid,onChange:newProps=>{handleChangePoint(newProps,1);}})}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$k.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxxSmall_4}),jsxRuntimeExports.jsx(View,{style:styles$k.horizontalRule}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(LabelMedium,{children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$k.labelContainer})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,onClick:()=>{const offsetPerLabel=[0,-1];const labelLocation=vec.add(vec.scale(offsetPerLabel,labels.length),vec.midpoint(tail,tip));const newLabel={...getDefaultFigureForType("label"),coord:labelLocation,color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$k.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$k=StyleSheet.create({accordionPanel:{paddingBottom:spacing.medium_16},container:{marginTop:spacing.xSmall_8,marginBottom:0,marginLeft:-spacing.xxxSmall_4,marginRight:-spacing.xxxSmall_4,backgroundColor:color.white},errorText:{color:color.red,marginTop:spacing.xSmall_8},row:{flexDirection:"row",alignItems:"center"},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:color.offBlack16},labelContainer:{backgroundColor:color.white}});
1606
1608
 
1607
1609
  const LockedFigureSettings=props=>{switch(props.type){case "point":return jsxRuntimeExports.jsx(LockedPointSettings,{...props});case "line":return jsxRuntimeExports.jsx(LockedLineSettings,{...props});case "vector":return jsxRuntimeExports.jsx(LockedVectorSettings,{...props});case "ellipse":return jsxRuntimeExports.jsx(LockedEllipseSettings,{...props});case "polygon":return jsxRuntimeExports.jsx(LockedPolygonSettings,{...props});case "function":return jsxRuntimeExports.jsx(LockedFunctionSettings,{...props});case "label":return jsxRuntimeExports.jsx(LockedLabelSettings,{...props});default:throw new UnreachableCaseError(props)}};
1608
1610
 
1609
- const LockedFiguresSection=props=>{const collapsedStateArray=Array((props.figures??[]).length).fill(false);const[expandedStates,setExpandedStates]=React.useState(collapsedStateArray);const[isExpanded,setIsExpanded]=React.useState(true);const uniqueId=useId();const{figures,onChange}=props;function addLockedFigure(newFigure){const lockedFigures=figures||[];const newProps={lockedFigures:[...lockedFigures,getDefaultFigureForType(newFigure)]};onChange(newProps);setExpandedStates([...expandedStates,true]);}function moveLockedFigure(index,movement){if(index===0&&(movement==="back"||movement==="backward")){return}if(figures&&index===figures.length-1&&(movement==="front"||movement==="forward")){return}const lockedFigures=figures||[];const newFigures=[...lockedFigures];const newExpandedStates=[...expandedStates];const[removedFigure]=newFigures.splice(index,1);newExpandedStates.splice(index,1);switch(movement){case "back":newFigures.unshift(removedFigure);newExpandedStates.unshift(true);break;case "backward":newFigures.splice(index-1,0,removedFigure);newExpandedStates.splice(index-1,0,true);break;case "forward":newFigures.splice(index+1,0,removedFigure);newExpandedStates.splice(index+1,0,true);break;case "front":newFigures.push(removedFigure);newExpandedStates.push(true);break}onChange({lockedFigures:newFigures});setExpandedStates(newExpandedStates);}function removeLockedFigure(index){if(window.confirm("Are you sure you want to delete this figure?")){const lockedFigures=figures||[];onChange({lockedFigures:[...lockedFigures.slice(0,index),...lockedFigures.slice(index+1)]});const newExpandedStates=[...expandedStates];newExpandedStates.splice(index,1);setExpandedStates(newExpandedStates);}}function changeProps(index,figureProps){const lockedFigures=figures||[];const newFigures={lockedFigures:[...lockedFigures.slice(0,index),{...lockedFigures[index],...figureProps},...lockedFigures.slice(index+1)]};onChange(newFigures);}function toggleExpanded(newValue){setExpandedStates(Array(figures?.length).fill(newValue));}const allCollapsed=expandedStates.every(value=>!value);const buttonLabel=allCollapsed?"Expand all":"Collapse all";const showExpandButton=!!figures?.length;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Locked Figures",isOpen:isExpanded,onToggle:()=>setIsExpanded(!isExpanded),isCollapsible:true}),isExpanded&&jsxRuntimeExports.jsxs(View,{children:[figures?.map((figure,index)=>{return jsxRuntimeExports.jsx(LockedFigureSettings,{expanded:expandedStates[index],onToggle:newValue=>{const newExpanded=[...expandedStates];newExpanded[index]=newValue;setExpandedStates(newExpanded);},...figure,onChangeProps:newProps=>changeProps(index,newProps),onMove:movement=>moveLockedFigure(index,movement),onRemove:()=>removeLockedFigure(index)},`${uniqueId}-locked-${figure}-${index}`)}),jsxRuntimeExports.jsxs(View,{style:styles$i.buttonContainer,children:[jsxRuntimeExports.jsx(LockedFigureSelect,{id:`${uniqueId}-select`,onChange:addLockedFigure}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),showExpandButton&&jsxRuntimeExports.jsx(Button,{kind:"secondary",onClick:()=>toggleExpanded(allCollapsed),style:styles$i.button,children:buttonLabel})]})]})]})};const styles$i=StyleSheet.create({buttonContainer:{flexDirection:"row",alignItems:"center"},button:{marginTop:spacing.xSmall_8,flexGrow:1}});
1611
+ const LockedFiguresSection=props=>{const collapsedStateArray=Array((props.figures??[]).length).fill(false);const[expandedStates,setExpandedStates]=React.useState(collapsedStateArray);const[isExpanded,setIsExpanded]=React.useState(true);const uniqueId=useId();const{figures,onChange}=props;function addLockedFigure(newFigure){const lockedFigures=figures||[];const newProps={lockedFigures:[...lockedFigures,getDefaultFigureForType(newFigure)]};onChange(newProps);setExpandedStates([...expandedStates,true]);}function moveLockedFigure(index,movement){if(index===0&&(movement==="back"||movement==="backward")){return}if(figures&&index===figures.length-1&&(movement==="front"||movement==="forward")){return}const lockedFigures=figures||[];const newFigures=[...lockedFigures];const newExpandedStates=[...expandedStates];const[removedFigure]=newFigures.splice(index,1);newExpandedStates.splice(index,1);switch(movement){case "back":newFigures.unshift(removedFigure);newExpandedStates.unshift(true);break;case "backward":newFigures.splice(index-1,0,removedFigure);newExpandedStates.splice(index-1,0,true);break;case "forward":newFigures.splice(index+1,0,removedFigure);newExpandedStates.splice(index+1,0,true);break;case "front":newFigures.push(removedFigure);newExpandedStates.push(true);break}onChange({lockedFigures:newFigures});setExpandedStates(newExpandedStates);}function removeLockedFigure(index){if(window.confirm("Are you sure you want to delete this figure?")){const lockedFigures=figures||[];onChange({lockedFigures:[...lockedFigures.slice(0,index),...lockedFigures.slice(index+1)]});const newExpandedStates=[...expandedStates];newExpandedStates.splice(index,1);setExpandedStates(newExpandedStates);}}function changeProps(index,figureProps){const lockedFigures=figures||[];const newFigures={lockedFigures:[...lockedFigures.slice(0,index),{...lockedFigures[index],...figureProps},...lockedFigures.slice(index+1)]};onChange(newFigures);}function toggleExpanded(newValue){setExpandedStates(Array(figures?.length).fill(newValue));}const allCollapsed=expandedStates.every(value=>!value);const buttonLabel=allCollapsed?"Expand all":"Collapse all";const showExpandButton=!!figures?.length;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Locked Figures",isOpen:isExpanded,onToggle:()=>setIsExpanded(!isExpanded),isCollapsible:true}),isExpanded&&jsxRuntimeExports.jsxs(View,{children:[figures?.map((figure,index)=>{return jsxRuntimeExports.jsx(LockedFigureSettings,{expanded:expandedStates[index],onToggle:newValue=>{const newExpanded=[...expandedStates];newExpanded[index]=newValue;setExpandedStates(newExpanded);},...figure,onChangeProps:newProps=>changeProps(index,newProps),onMove:movement=>moveLockedFigure(index,movement),onRemove:()=>removeLockedFigure(index)},`${uniqueId}-locked-${figure}-${index}`)}),jsxRuntimeExports.jsxs(View,{style:styles$j.buttonContainer,children:[jsxRuntimeExports.jsx(LockedFigureSelect,{id:`${uniqueId}-select`,onChange:addLockedFigure}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),showExpandButton&&jsxRuntimeExports.jsx(Button,{kind:"secondary",onClick:()=>toggleExpanded(allCollapsed),style:styles$j.button,children:buttonLabel})]})]})]})};const styles$j=StyleSheet.create({buttonContainer:{flexDirection:"row",alignItems:"center"},button:{marginTop:spacing.xSmall_8,flexGrow:1}});
1610
1612
 
1611
1613
  const{getClockwiseAngle}=angles;function getStartCoords(graph){if("startCoords"in graph){return graph.startCoords}return undefined}function getDefaultGraphStartCoords(graph,range,step){switch(graph.type){case "linear":case "ray":return getLineCoords({...graph,startCoords:undefined},range,step);case "segment":return getSegmentCoords({...graph,startCoords:undefined},range,step);case "linear-system":return getLinearSystemCoords({...graph,startCoords:undefined},range,step);case "circle":const startCoords=getCircleCoords({...graph,startCoords:undefined});const radius=vector.length(vector.subtract(startCoords.radiusPoint,startCoords.center));return {center:startCoords.center,radius};case "sinusoid":return getSinusoidCoords({...graph,startCoords:undefined},range,step);case "quadratic":return getQuadraticCoords({...graph,startCoords:undefined},range,step);case "point":return getPointCoords({...graph,startCoords:undefined},range,step);case "polygon":return getPolygonCoords({...graph,startCoords:undefined},range,step);case "angle":return getAngleCoords({graph:{...graph,startCoords:undefined},range,step});default:return undefined}}const getSinusoidEquation=startCoords=>{const p1=startCoords[0];const p2=startCoords[1];const amplitude=p2[1]-p1[1];const angularFrequency=Math.PI/(2*(p2[0]-p1[0]));const phase=p1[0]*angularFrequency;const verticalOffset=p1[1];return "y = "+amplitude.toFixed(3)+"sin("+angularFrequency.toFixed(3)+"x - "+phase.toFixed(3)+") + "+verticalOffset.toFixed(3)};const getQuadraticEquation=startCoords=>{const p1=startCoords[0];const p2=startCoords[1];const p3=startCoords[2];const denom=(p1[0]-p2[0])*(p1[0]-p3[0])*(p2[0]-p3[0]);if(denom===0){return "Division by zero error"}const a=(p3[0]*(p2[1]-p1[1])+p2[0]*(p1[1]-p3[1])+p1[0]*(p3[1]-p2[1]))/denom;const b=(p3[0]*p3[0]*(p1[1]-p2[1])+p2[0]*p2[0]*(p3[1]-p1[1])+p1[0]*p1[0]*(p2[1]-p3[1]))/denom;const c=(p2[0]*p3[0]*(p2[0]-p3[0])*p1[1]+p3[0]*p1[0]*(p3[0]-p1[0])*p2[1]+p1[0]*p2[0]*(p1[0]-p2[0])*p3[1])/denom;return "y = "+a.toFixed(3)+"x^2 + "+b.toFixed(3)+"x + "+c.toFixed(3)};const getAngleEquation=(startCoords,allowReflexAngles=false)=>{const vertex=startCoords[1];const roundedAngle=getClockwiseAngle(startCoords,allowReflexAngles).toFixed(0);return `${roundedAngle}\u00B0 angle at (${vertex[0]}, ${vertex[1]})`};const shouldShowStartCoordsUI=(graph,isStatic)=>{if(isStatic){return false}switch(graph.type){case "point":return graph.numPoints!=="unlimited";case "polygon":return graph.numSides!=="unlimited"&&graph.snapTo!=="angles"&&graph.snapTo!=="sides";case "none":return false;case "angle":case "circle":case "linear":case "linear-system":case "quadratic":case "ray":case "segment":case "sinusoid":return true;default:throw new UnreachableCaseError(graph)}};
1612
1614
 
1613
- const StartCoordsAngle=props=>{const{startCoords,allowReflexAngles,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$h.equationSection,children:[jsxRuntimeExports.jsx(LabelMedium,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$h.equationBody,children:getAngleEquation(startCoords,allowReflexAngles)})]}),jsxRuntimeExports.jsxs(View,{style:styles$h.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1],startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$h.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Vertex:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value,startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$h.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[2],labels:["x","y"],onChange:value=>onChange([startCoords[0],startCoords[1],value])})]})]})};const styles$h=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"},equationSection:{marginTop:spacing.small_12},equationBody:{backgroundColor:color.fadedOffBlack8,border:`1px solid ${color.fadedOffBlack32}`,marginTop:spacing.xSmall_8,paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8,fontSize:font.size.xSmall}});
1615
+ const StartCoordsAngle=props=>{const{startCoords,allowReflexAngles,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$i.equationSection,children:[jsxRuntimeExports.jsx(LabelMedium,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$i.equationBody,children:getAngleEquation(startCoords,allowReflexAngles)})]}),jsxRuntimeExports.jsxs(View,{style:styles$i.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1],startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$i.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Vertex:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value,startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$i.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[2],labels:["x","y"],onChange:value=>onChange([startCoords[0],startCoords[1],value])})]})]})};const styles$i=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"},equationSection:{marginTop:spacing.small_12},equationBody:{backgroundColor:color.fadedOffBlack8,border:`1px solid ${color.fadedOffBlack32}`,marginTop:spacing.xSmall_8,paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8,fontSize:font.size.xSmall}});
1614
1616
 
1615
- const StartCoordsCircle=props=>{const{startCoords,onChange}=props;const[radiusState,setRadiusState]=React.useState(startCoords.radius.toString());React.useEffect(()=>{setRadiusState(startCoords.radius.toString());},[startCoords.radius]);function handleRadiuschange(newValue){setRadiusState(newValue);if(isNaN(+newValue)||newValue===""||+newValue===0){return}onChange({center:startCoords.center,radius:parseFloat(newValue)});}return jsxRuntimeExports.jsxs(View,{style:styles$g.tile,children:[jsxRuntimeExports.jsxs(View,{style:styles$g.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Center:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords.center,labels:["x","y"],onChange:coord=>onChange({center:coord,radius:startCoords.radius})})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsxs(LabelLarge,{tag:"label",style:styles$g.row,children:["Radius:",jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:radiusState,onChange:handleRadiuschange,style:styles$g.textField})]})]})};const styles$g=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8},row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1617
+ const StartCoordsCircle=props=>{const{startCoords,onChange}=props;const[radiusState,setRadiusState]=React.useState(startCoords.radius.toString());React.useEffect(()=>{setRadiusState(startCoords.radius.toString());},[startCoords.radius]);function handleRadiuschange(newValue){setRadiusState(newValue);if(isNaN(+newValue)||newValue===""||+newValue===0){return}onChange({center:startCoords.center,radius:parseFloat(newValue)});}return jsxRuntimeExports.jsxs(View,{style:styles$h.tile,children:[jsxRuntimeExports.jsxs(View,{style:styles$h.row,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Center:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords.center,labels:["x","y"],onChange:coord=>onChange({center:coord,radius:startCoords.radius})})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsxs(LabelLarge,{tag:"label",style:styles$h.row,children:["Radius:",jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:radiusState,onChange:handleRadiuschange,style:styles$h.textField})]})]})};const styles$h=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8},row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1616
1618
 
1617
- const StartCoordsLine=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$f.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$f.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value])})]})]})};const styles$f=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"}});
1619
+ const StartCoordsLine=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$g.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$g.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value])})]})]})};const styles$g=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"}});
1618
1620
 
1619
- const StartCoordsMultiline=props=>{const{startCoords,type,onChange}=props;const graphName=type==="segment"?"Segment":"Line";return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:startCoords.map((coordPair,i)=>jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(LabelLarge,{children:`${graphName} ${i+1}`}),expanded:true,children:[jsxRuntimeExports.jsxs(View,{style:styles$e.nestedTile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coordPair[0],labels:["x","y"],onChange:value=>{const newCoords=[...startCoords];newCoords[i]=[value,coordPair[1]];onChange(newCoords);}})]}),jsxRuntimeExports.jsxs(View,{style:styles$e.nestedTile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coordPair[1],labels:["x","y"],onChange:value=>{const newCoords=[...startCoords];newCoords[i]=[coordPair[0],value];onChange(newCoords);}})]})]},`segment-${i}-start-coords`))})};const styles$e=StyleSheet.create({nestedTile:{paddingBottom:spacing.small_12,flexDirection:"row",alignItems:"center"}});
1621
+ const StartCoordsMultiline=props=>{const{startCoords,type,onChange}=props;const graphName=type==="segment"?"Segment":"Line";return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:startCoords.map((coordPair,i)=>jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(LabelLarge,{children:`${graphName} ${i+1}`}),expanded:true,children:[jsxRuntimeExports.jsxs(View,{style:styles$f.nestedTile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coordPair[0],labels:["x","y"],onChange:value=>{const newCoords=[...startCoords];newCoords[i]=[value,coordPair[1]];onChange(newCoords);}})]}),jsxRuntimeExports.jsxs(View,{style:styles$f.nestedTile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coordPair[1],labels:["x","y"],onChange:value=>{const newCoords=[...startCoords];newCoords[i]=[coordPair[0],value];onChange(newCoords);}})]})]},`segment-${i}-start-coords`))})};const styles$f=StyleSheet.create({nestedTile:{paddingBottom:spacing.small_12,flexDirection:"row",alignItems:"center"}});
1620
1622
 
1621
- const StartCoordsPoint=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:startCoords.map((coord,index)=>{return jsxRuntimeExports.jsxs(View,{style:styles$d.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`Point ${index+1}:`}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,labels:["x","y"],onChange:newCoord=>{const newStartCoords=[...startCoords];newStartCoords[index]=newCoord;onChange(newStartCoords);}})]},index)})})};const styles$d=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"}});
1623
+ const StartCoordsPoint=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:startCoords.map((coord,index)=>{return jsxRuntimeExports.jsxs(View,{style:styles$e.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:`Point ${index+1}:`}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,labels:["x","y"],onChange:newCoord=>{const newStartCoords=[...startCoords];newStartCoords[index]=newCoord;onChange(newStartCoords);}})]},index)})})};const styles$e=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"}});
1622
1624
 
1623
- const StartCoordsQuadratic=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$c.equationSection,children:[jsxRuntimeExports.jsx(LabelMedium,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$c.equationBody,children:getQuadraticEquation(startCoords)})]}),jsxRuntimeExports.jsxs(View,{style:styles$c.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1],startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$c.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value,startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$c.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 3:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[2],labels:["x","y"],onChange:value=>onChange([startCoords[0],startCoords[1],value])})]})]})};const styles$c=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"},equationSection:{marginTop:spacing.small_12},equationBody:{backgroundColor:color.fadedOffBlack8,border:`1px solid ${color.fadedOffBlack32}`,marginTop:spacing.xSmall_8,paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8,fontSize:font.size.xSmall}});
1625
+ const StartCoordsQuadratic=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$d.equationSection,children:[jsxRuntimeExports.jsx(LabelMedium,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$d.equationBody,children:getQuadraticEquation(startCoords)})]}),jsxRuntimeExports.jsxs(View,{style:styles$d.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1],startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$d.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value,startCoords[2]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$d.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 3:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[2],labels:["x","y"],onChange:value=>onChange([startCoords[0],startCoords[1],value])})]})]})};const styles$d=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"},equationSection:{marginTop:spacing.small_12},equationBody:{backgroundColor:color.fadedOffBlack8,border:`1px solid ${color.fadedOffBlack32}`,marginTop:spacing.xSmall_8,paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8,fontSize:font.size.xSmall}});
1624
1626
 
1625
- const StartCoordsSinusoid=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$b.equationSection,children:[jsxRuntimeExports.jsx(LabelMedium,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$b.equationBody,children:getSinusoidEquation(startCoords)})]}),jsxRuntimeExports.jsxs(View,{style:styles$b.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$b.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value])})]})]})};const styles$b=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"},equationSection:{marginTop:spacing.small_12},equationBody:{backgroundColor:color.fadedOffBlack8,border:`1px solid ${color.fadedOffBlack32}`,marginTop:spacing.xSmall_8,paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8,fontSize:font.size.xSmall}});
1627
+ const StartCoordsSinusoid=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$c.equationSection,children:[jsxRuntimeExports.jsx(LabelMedium,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$c.equationBody,children:getSinusoidEquation(startCoords)})]}),jsxRuntimeExports.jsxs(View,{style:styles$c.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 1:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[0],labels:["x","y"],onChange:value=>onChange([value,startCoords[1]])})]}),jsxRuntimeExports.jsxs(View,{style:styles$c.tile,children:[jsxRuntimeExports.jsx(LabelLarge,{children:"Point 2:"}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:startCoords[1],labels:["x","y"],onChange:value=>onChange([startCoords[0],value])})]})]})};const styles$c=StyleSheet.create({tile:{backgroundColor:color.fadedBlue8,marginTop:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8,flexDirection:"row",alignItems:"center"},equationSection:{marginTop:spacing.small_12},equationBody:{backgroundColor:color.fadedOffBlack8,border:`1px solid ${color.fadedOffBlack32}`,marginTop:spacing.xSmall_8,paddingLeft:spacing.xSmall_8,paddingRight:spacing.xSmall_8,fontSize:font.size.xSmall}});
1626
1628
 
1627
1629
  const StartCoordsSettingsInner=props=>{const{type,range,step,allowReflexAngles,onChange}=props;switch(type){case "linear":case "ray":const linearCoords=getLineCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsLine,{startCoords:linearCoords,onChange:onChange});case "linear-system":case "segment":const multiLineCoords=type==="segment"?getSegmentCoords(props,range,step):getLinearSystemCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsMultiline,{type:type,startCoords:multiLineCoords,onChange:onChange});case "circle":const circleCoords=getCircleCoords(props);const radius=vector.length(vector.subtract(circleCoords.radiusPoint,circleCoords.center));return jsxRuntimeExports.jsx(StartCoordsCircle,{startCoords:{center:circleCoords.center,radius},onChange:onChange});case "sinusoid":const sinusoidCoords=getSinusoidCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsSinusoid,{startCoords:sinusoidCoords,onChange:onChange});case "quadratic":const quadraticCoords=getQuadraticCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsQuadratic,{startCoords:quadraticCoords,onChange:onChange});case "point":case "polygon":const pointCoords=type==="point"?getPointCoords(props,range,step):getPolygonCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsPoint,{startCoords:pointCoords,onChange:onChange});case "angle":const angleCoords=getAngleCoords({graph:props,range,step});return jsxRuntimeExports.jsx(StartCoordsAngle,{startCoords:angleCoords,allowReflexAngles:allowReflexAngles,onChange:onChange});default:return null}};const StartCoordsSettings=props=>{const{range,step,onChange}=props;const[isOpen,setIsOpen]=React.useState(true);return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Heading,{isCollapsible:true,title:"Start coordinates",isOpen:isOpen,onToggle:()=>setIsOpen(!isOpen)}),isOpen&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(StartCoordsSettingsInner,{...props}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(Button,{startIcon:arrowCounterClockwise,kind:"tertiary",size:"small",onClick:()=>{onChange(getDefaultGraphStartCoords(props,range,step));},children:"Use default start coordinates"})]})]})};
1628
1630
 
1629
- const{InfoTip: InfoTip$b}=components;const InteractiveGraph=InteractiveGraphWidget.widget;const POLYGON_SIDES=_.map(_.range(3,13),function(value){return jsxRuntimeExports.jsx(OptionItem,{value:`${value}`,label:`${value} sides`},`polygon-sides-${value}`)});class InteractiveGraphEditor extends React.Component{serialize(){const json=_.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();_.extend(json,{graph:{type:correct.type,startCoords:this.props.graph&&getStartCoords(this.props.graph)},correct:correct});_.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(_.has(correct,key)){json.graph[key]=correct[key];}});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const sizeClass=containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct;const graphProps={ref:"graph",box:this.props.box,range:this.props.range,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,trackInteraction:function(){},userInput:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant(newGraph!=null);if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(Id,{children:graphId=>jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type:",children:jsxRuntimeExports.jsx(GraphTypeSelector,{graphType:this.props.graph?.type??InteractiveGraph.defaultProps.userInput.type,onChange:type=>{this.props.onChange({graph:{type},correct:{type}});}})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(LabeledRow,{label:"Number of Points:",children:jsxRuntimeExports.jsx(GraphPointsCountSelector,{numPoints:this.props.correct?.numPoints,onChange:points=>{this.props.onChange({correct:{type:"point",numPoints:points},graph:{type:"point",numPoints:points}});}})}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$a.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Show angle measures"}),checked:!!this.props.correct?.showAngles,onChange:newValue=>{if(this.props.graph?.type==="angle"){invariant(this.props.correct.type==="angle",`Expected graph type to be angle, but got ${this.props.correct.type}`);this.props.onChange({correct:{...this.props.correct,showAngles:newValue},graph:{...this.props.graph,showAngles:newValue}});}}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{style:styles$a.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Allow reflex angles"}),checked:!!this.props.correct?.allowReflexAngles,onChange:newValue=>{invariant(this.props.correct.type==="angle",`Expected graph type to be angle, but got ${this.props.correct.type}`);invariant(this.props.graph?.type==="angle",`Expected graph type to be angle, but got ${this.props.graph?.type}`);const update={allowReflexAngles:newValue};this.props.onChange({correct:{...this.props.correct,...update},graph:{...this.props.graph,...update}});}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Allow students to be able to create reflex angles."})})]})]}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Number of sides:",children:jsxRuntimeExports.jsx(SingleSelect,{selectedValue:this.props.correct?.numSides?`${this.props.correct.numSides}`:"3",placeholder:"",onChange:newValue=>{invariant(this.props.graph?.type==="polygon");const updates={numSides:parsePointCount(newValue),coords:undefined,startCoords:undefined,snapTo:"grid"};this.props.onChange({correct:{...this.props.correct,...updates},graph:{...this.props.graph,...updates}});},style:styles$a.singleSelectShort,children:[...POLYGON_SIDES,jsxRuntimeExports.jsx(OptionItem,{value:"unlimited",label:"unlimited sides"},"unlimited")]},"polygon-select")}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Snap to:",children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.correct?.snapTo||"grid",placeholder:"",onChange:newValue=>{invariant(this.props.correct.type==="polygon",`Expected correct answer type to be polygon, but got ${this.props.correct.type}`);invariant(this.props.graph?.type==="polygon",`Expected graph type to be polygon, but got ${this.props.graph?.type}`);const updates={snapTo:newValue,coords:null};this.props.onChange({correct:{...this.props.correct,...updates},graph:{...this.props.graph,...updates}});},style:styles$a.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"grid",label:"grid"}),this.props.correct?.numSides!=="unlimited"&&jsxRuntimeExports.jsx(OptionItem,{value:"angles",label:"interior angles"}),this.props.correct?.numSides!=="unlimited"&&jsxRuntimeExports.jsx(OptionItem,{value:"sides",label:"side measures"})]}),jsxRuntimeExports.jsxs(InfoTip$b,{children:[jsxRuntimeExports.jsx("p",{children:"These options affect the movement of the vertex points. The grid option will guide the points to the nearest half step along the grid."}),jsxRuntimeExports.jsx("p",{children:"The interior angle and side measure options guide the points to the nearest whole angle or side measure respectively."})]})]}),jsxRuntimeExports.jsxs(View,{style:styles$a.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Show angle measures"}),checked:!!this.props.correct?.showAngles,onChange:()=>{if(this.props.graph?.type==="polygon"){invariant(this.props.correct.type==="polygon",`Expected graph type to be polygon, but got ${this.props.correct.type}`);this.props.onChange({correct:{...this.props.correct,showAngles:!this.props.correct.showAngles},graph:{...this.props.graph,showAngles:!this.props.graph.showAngles}});}}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{style:styles$a.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Show side measures"}),checked:!!this.props.correct?.showSides,onChange:()=>{if(this.props.graph?.type==="polygon"&&this.props.correct.type==="polygon"){this.props.onChange({correct:{...this.props.correct,showSides:!this.props.correct.showSides},graph:{...this.props.graph,showSides:!this.props.graph.showSides}});}}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Displays the side lengths."})})]})]}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(LabeledRow,{label:"Number of segments:",children:jsxRuntimeExports.jsx(SegmentCountSelector,{numSegments:this.props.correct?.numSegments,onChange:sides=>{this.props.onChange({correct:{type:"segment",numSegments:sides,coords:null},graph:{type:"segment",numSegments:sides}});}})}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,onChange:this.changeStartCoords}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange}),this.props.correct.type==="polygon"&&jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.correct.match||"exact",onChange:newValue=>{invariant(this.props.correct.type==="polygon",`Expected graph type to be polygon, but got ${this.props.correct.type}`);const correct={...this.props.correct,match:newValue};this.props.onChange({correct});},placeholder:"",style:styles$a.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"exact",label:"match exactly"}),jsxRuntimeExports.jsx(OptionItem,{value:"congruent",label:"be congruent"}),jsxRuntimeExports.jsx(OptionItem,{value:"approx",label:"be approximately congruent"}),jsxRuntimeExports.jsx(OptionItem,{value:"similar",label:"be similar"})]}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsxs("ul",{children:[jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Match Exactly:"})," Match exactly in size, orientation, and location on the grid even if it is not shown in the background."]})}),jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Be Congruent:"})," Be congruent in size and shape, but can be located anywhere on the grid."]})}),jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Be Approximately Congruent:"})," ","Be exactly similar, and congruent in size and shape to within 0.1 units, but can be located anywhere on the grid."," ",jsxRuntimeExports.jsx("em",{children:"Use this with snapping to angle measure."})]})}),jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Be Similar:"})," Be similar with matching interior angles, and side measures that are matching or a multiple of the correct side measures. The figure can be located anywhere on the grid."]})})]})})]}),this.props.correct.type==="angle"&&jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.correct.match||"exact",onChange:newValue=>{invariant(this.props.correct.type==="angle",`Expected graph type to be angle, but got ${this.props.correct.type}`);this.props.onChange({correct:{...this.props.correct,match:newValue}});},placeholder:"",style:styles$a.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"exact",label:"match exactly"}),jsxRuntimeExports.jsx(OptionItem,{value:"congruent",label:"be congruent"})]}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Congruency requires only that the angle measures are the same. An exact match implies congruency, but also requires that the angles have the same orientation and that the vertices are in the same position."})})]}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}return issues};}}InteractiveGraphEditor.widgetName="interactive-graph";InteractiveGraphEditor.defaultProps={...interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant(b.type==="angle");return {...a,...b};case "circle":invariant(b.type==="circle");return {...a,...b};case "linear":invariant(b.type==="linear");return {...a,...b};case "linear-system":invariant(b.type==="linear-system");return {...a,...b};case "none":invariant(b.type==="none");return {...a,...b};case "point":invariant(b.type==="point");return {...a,...b};case "polygon":invariant(b.type==="polygon");return {...a,...b};case "quadratic":invariant(b.type==="quadratic");return {...a,...b};case "ray":invariant(b.type==="ray");return {...a,...b};case "segment":invariant(b.type==="segment");return {...a,...b};case "sinusoid":invariant(b.type==="sinusoid");return {...a,...b};default:throw new UnreachableCaseError(a)}}const styles$a=StyleSheet.create({singleSelectShort:{height:26},row:{flexDirection:"row",marginTop:spacing.xSmall_8,alignItems:"center"}});
1631
+ const{InfoTip: InfoTip$b}=components;const InteractiveGraph=InteractiveGraphWidget.widget;const POLYGON_SIDES=_.map(_.range(3,13),function(value){return jsxRuntimeExports.jsx(OptionItem,{value:`${value}`,label:`${value} sides`},`polygon-sides-${value}`)});class InteractiveGraphEditor extends React.Component{serialize(){const json=_.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();_.extend(json,{graph:{type:correct.type,startCoords:this.props.graph&&getStartCoords(this.props.graph)},correct:correct});_.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(_.has(correct,key)){json.graph[key]=correct[key];}});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const sizeClass=containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct;const graphProps={ref:"graph",box:this.props.box,range:this.props.range,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,trackInteraction:function(){},userInput:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant(newGraph!=null);if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(Id,{children:graphId=>jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type:",children:jsxRuntimeExports.jsx(GraphTypeSelector,{graphType:this.props.graph?.type??InteractiveGraph.defaultProps.userInput.type,onChange:type=>{this.props.onChange({graph:{type},correct:{type}});}})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(LabeledRow,{label:"Number of Points:",children:jsxRuntimeExports.jsx(GraphPointsCountSelector,{numPoints:this.props.correct?.numPoints,onChange:points=>{this.props.onChange({correct:{type:"point",numPoints:points},graph:{type:"point",numPoints:points}});}})}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$b.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Show angle measures"}),checked:!!this.props.correct?.showAngles,onChange:newValue=>{if(this.props.graph?.type==="angle"){invariant(this.props.correct.type==="angle",`Expected graph type to be angle, but got ${this.props.correct.type}`);this.props.onChange({correct:{...this.props.correct,showAngles:newValue},graph:{...this.props.graph,showAngles:newValue}});}}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{style:styles$b.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Allow reflex angles"}),checked:!!this.props.correct?.allowReflexAngles,onChange:newValue=>{invariant(this.props.correct.type==="angle",`Expected graph type to be angle, but got ${this.props.correct.type}`);invariant(this.props.graph?.type==="angle",`Expected graph type to be angle, but got ${this.props.graph?.type}`);const update={allowReflexAngles:newValue};this.props.onChange({correct:{...this.props.correct,...update},graph:{...this.props.graph,...update}});}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Allow students to be able to create reflex angles."})})]})]}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Number of sides:",children:jsxRuntimeExports.jsx(SingleSelect,{selectedValue:this.props.correct?.numSides?`${this.props.correct.numSides}`:"3",placeholder:"",onChange:newValue=>{invariant(this.props.graph?.type==="polygon");const updates={numSides:parsePointCount(newValue),coords:undefined,startCoords:undefined,snapTo:"grid"};this.props.onChange({correct:{...this.props.correct,...updates},graph:{...this.props.graph,...updates}});},style:styles$b.singleSelectShort,children:[...POLYGON_SIDES,jsxRuntimeExports.jsx(OptionItem,{value:"unlimited",label:"unlimited sides"},"unlimited")]},"polygon-select")}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Snap to:",children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.correct?.snapTo||"grid",placeholder:"",onChange:newValue=>{invariant(this.props.correct.type==="polygon",`Expected correct answer type to be polygon, but got ${this.props.correct.type}`);invariant(this.props.graph?.type==="polygon",`Expected graph type to be polygon, but got ${this.props.graph?.type}`);const updates={snapTo:newValue,coords:null};this.props.onChange({correct:{...this.props.correct,...updates},graph:{...this.props.graph,...updates}});},style:styles$b.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"grid",label:"grid"}),this.props.correct?.numSides!=="unlimited"&&jsxRuntimeExports.jsx(OptionItem,{value:"angles",label:"interior angles"}),this.props.correct?.numSides!=="unlimited"&&jsxRuntimeExports.jsx(OptionItem,{value:"sides",label:"side measures"})]}),jsxRuntimeExports.jsxs(InfoTip$b,{children:[jsxRuntimeExports.jsx("p",{children:"These options affect the movement of the vertex points. The grid option will guide the points to the nearest half step along the grid."}),jsxRuntimeExports.jsx("p",{children:"The interior angle and side measure options guide the points to the nearest whole angle or side measure respectively."})]})]}),jsxRuntimeExports.jsxs(View,{style:styles$b.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Show angle measures"}),checked:!!this.props.correct?.showAngles,onChange:()=>{if(this.props.graph?.type==="polygon"){invariant(this.props.correct.type==="polygon",`Expected graph type to be polygon, but got ${this.props.correct.type}`);this.props.onChange({correct:{...this.props.correct,showAngles:!this.props.correct.showAngles},graph:{...this.props.graph,showAngles:!this.props.graph.showAngles}});}}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{style:styles$b.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(LabelSmall,{children:"Show side measures"}),checked:!!this.props.correct?.showSides,onChange:()=>{if(this.props.graph?.type==="polygon"&&this.props.correct.type==="polygon"){this.props.onChange({correct:{...this.props.correct,showSides:!this.props.correct.showSides},graph:{...this.props.graph,showSides:!this.props.graph.showSides}});}}}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Displays the side lengths."})})]})]}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(LabeledRow,{label:"Number of segments:",children:jsxRuntimeExports.jsx(SegmentCountSelector,{numSegments:this.props.correct?.numSegments,onChange:sides=>{this.props.onChange({correct:{type:"segment",numSegments:sides,coords:null},graph:{type:"segment",numSegments:sides}});}})}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,onChange:this.changeStartCoords}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange}),this.props.correct.type==="polygon"&&jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.correct.match||"exact",onChange:newValue=>{invariant(this.props.correct.type==="polygon",`Expected graph type to be polygon, but got ${this.props.correct.type}`);const correct={...this.props.correct,match:newValue};this.props.onChange({correct});},placeholder:"",style:styles$b.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"exact",label:"match exactly"}),jsxRuntimeExports.jsx(OptionItem,{value:"congruent",label:"be congruent"}),jsxRuntimeExports.jsx(OptionItem,{value:"approx",label:"be approximately congruent"}),jsxRuntimeExports.jsx(OptionItem,{value:"similar",label:"be similar"})]}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsxs("ul",{children:[jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Match Exactly:"})," Match exactly in size, orientation, and location on the grid even if it is not shown in the background."]})}),jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Be Congruent:"})," Be congruent in size and shape, but can be located anywhere on the grid."]})}),jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Be Approximately Congruent:"})," ","Be exactly similar, and congruent in size and shape to within 0.1 units, but can be located anywhere on the grid."," ",jsxRuntimeExports.jsx("em",{children:"Use this with snapping to angle measure."})]})}),jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("p",{children:[jsxRuntimeExports.jsx("b",{children:"Be Similar:"})," Be similar with matching interior angles, and side measures that are matching or a multiple of the correct side measures. The figure can be located anywhere on the grid."]})})]})})]}),this.props.correct.type==="angle"&&jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:this.props.correct.match||"exact",onChange:newValue=>{invariant(this.props.correct.type==="angle",`Expected graph type to be angle, but got ${this.props.correct.type}`);this.props.onChange({correct:{...this.props.correct,match:newValue}});},placeholder:"",style:styles$b.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"exact",label:"match exactly"}),jsxRuntimeExports.jsx(OptionItem,{value:"congruent",label:"be congruent"})]}),jsxRuntimeExports.jsx(InfoTip$b,{children:jsxRuntimeExports.jsx("p",{children:"Congruency requires only that the angle measures are the same. An exact match implies congruency, but also requires that the angles have the same orientation and that the vertices are in the same position."})})]}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}return issues};}}InteractiveGraphEditor.widgetName="interactive-graph";InteractiveGraphEditor.defaultProps={...interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant(b.type==="angle");return {...a,...b};case "circle":invariant(b.type==="circle");return {...a,...b};case "linear":invariant(b.type==="linear");return {...a,...b};case "linear-system":invariant(b.type==="linear-system");return {...a,...b};case "none":invariant(b.type==="none");return {...a,...b};case "point":invariant(b.type==="point");return {...a,...b};case "polygon":invariant(b.type==="polygon");return {...a,...b};case "quadratic":invariant(b.type==="quadratic");return {...a,...b};case "ray":invariant(b.type==="ray");return {...a,...b};case "segment":invariant(b.type==="segment");return {...a,...b};case "sinusoid":invariant(b.type==="sinusoid");return {...a,...b};default:throw new UnreachableCaseError(a)}}const styles$b=StyleSheet.create({singleSelectShort:{height:26},row:{flexDirection:"row",marginTop:spacing.xSmall_8,alignItems:"center"}});
1630
1632
 
1631
1633
  const gray98="#FAFAFA";const gray95="#F0F1F2";const gray85="#D6D8DA";const gray76="#BABEC2";const gray68="#888D93";const gray41="#626569";const gray17="#21242C";
1632
1634
 
1633
- class FormWrappedTextField extends React.Component{render(){const{forwardedRef,width,grow,shrink,icon,backgroundColor,focusBorderColor,borderColor,color: color$1,onSubmit,leftSideIcon,id,testId,type,labelMediumInputText,...allProps}=this.props;const{focused}=this.state;const extraStyles={};const spanStyle=[styles$9.input,styles$9.container];if(width){extraStyles.width=width;}if(grow){extraStyles.flexGrow=grow===true?1:grow;}if(shrink||shrink===0){extraStyles.flexShrink=shrink===true?0:shrink;}if(backgroundColor){extraStyles.backgroundColor=backgroundColor;}else {spanStyle.push(styles$9.defaultBackground);}if(color$1){extraStyles.color=color$1;}const borderColorStyle=focused?focusBorderColor||color.blue:borderColor||color.offBlack16;extraStyles.border=`1px solid ${borderColorStyle}`;const wrappedIcon=icon&&jsxRuntimeExports.jsx("span",{className:css(styles$9.icon),children:icon});const inputBase=labelMediumInputText?styles$9.labelMediumInputBase:styles$9.inputBase;return jsxRuntimeExports.jsxs("form",{className:css(...spanStyle),style:extraStyles,onSubmit:onSubmit||this.disableDefault,children:[leftSideIcon&&wrappedIcon,jsxRuntimeExports.jsx("input",{...allProps,onFocus:this.handleFocus,onBlur:this.handleBlur,type:type,className:css(inputBase),ref:forwardedRef,id:id,"data-testid":testId}),!leftSideIcon&&wrappedIcon]})}constructor(...args){super(...args),this.state={focused:false},this.handleBlur=e=>{const{onBlur}=this.props;onBlur?.(e);this.setState({focused:false});},this.handleFocus=e=>{const{onFocus}=this.props;onFocus?.(e);this.setState({focused:true});},this.disableDefault=e=>{e.preventDefault();};}}const styles$9=StyleSheet.create({inputBase:{background:"inherit",border:"none",fontFamily:"inherit",fontSize:15,lineHeight:"22px",outline:"none","::placeholder":{color:gray41},width:"100%",color:"inherit",marginBottom:0,paddingLeft:0,boxShadow:"none",padding:0,margin:0},labelMediumInputBase:{background:"inherit",border:"none",outline:"none","::placeholder":{color:gray41},width:"100%",fontWeight:"normal",fontFamily:"Lato, san-serif",fontSize:"16px",lineHeight:"20px"},input:{height:40,borderRadius:4,boxSizing:"border-box",padding:"8px 10px"},container:{display:"inline-flex",alignItems:"center",marginBottom:0},defaultBackground:{backgroundColor:color.white},icon:{display:"flex",alignItems:"center",justifyContent:"center"}});var FormWrappedTextField$1 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(FormWrappedTextField,{...props,forwardedRef:ref}));
1635
+ class FormWrappedTextField extends React.Component{render(){const{forwardedRef,width,grow,shrink,icon,backgroundColor,focusBorderColor,borderColor,color: color$1,onSubmit,leftSideIcon,id,testId,type,labelMediumInputText,...allProps}=this.props;const{focused}=this.state;const extraStyles={};const spanStyle=[styles$a.input,styles$a.container];if(width){extraStyles.width=width;}if(grow){extraStyles.flexGrow=grow===true?1:grow;}if(shrink||shrink===0){extraStyles.flexShrink=shrink===true?0:shrink;}if(backgroundColor){extraStyles.backgroundColor=backgroundColor;}else {spanStyle.push(styles$a.defaultBackground);}if(color$1){extraStyles.color=color$1;}const borderColorStyle=focused?focusBorderColor||color.blue:borderColor||color.offBlack16;extraStyles.border=`1px solid ${borderColorStyle}`;const wrappedIcon=icon&&jsxRuntimeExports.jsx("span",{className:css(styles$a.icon),children:icon});const inputBase=labelMediumInputText?styles$a.labelMediumInputBase:styles$a.inputBase;return jsxRuntimeExports.jsxs("form",{className:css(...spanStyle),style:extraStyles,onSubmit:onSubmit||this.disableDefault,children:[leftSideIcon&&wrappedIcon,jsxRuntimeExports.jsx("input",{...allProps,onFocus:this.handleFocus,onBlur:this.handleBlur,type:type,className:css(inputBase),ref:forwardedRef,id:id,"data-testid":testId}),!leftSideIcon&&wrappedIcon]})}constructor(...args){super(...args),this.state={focused:false},this.handleBlur=e=>{const{onBlur}=this.props;onBlur?.(e);this.setState({focused:false});},this.handleFocus=e=>{const{onFocus}=this.props;onFocus?.(e);this.setState({focused:true});},this.disableDefault=e=>{e.preventDefault();};}}const styles$a=StyleSheet.create({inputBase:{background:"inherit",border:"none",fontFamily:"inherit",fontSize:15,lineHeight:"22px",outline:"none","::placeholder":{color:gray41},width:"100%",color:"inherit",marginBottom:0,paddingLeft:0,boxShadow:"none",padding:0,margin:0},labelMediumInputBase:{background:"inherit",border:"none",outline:"none","::placeholder":{color:gray41},width:"100%",fontWeight:"normal",fontFamily:"Lato, san-serif",fontSize:"16px",lineHeight:"20px"},input:{height:40,borderRadius:4,boxSizing:"border-box",padding:"8px 10px"},container:{display:"inline-flex",alignItems:"center",marginBottom:0},defaultBackground:{backgroundColor:color.white},icon:{display:"flex",alignItems:"center",justifyContent:"center"}});var FormWrappedTextField$1 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(FormWrappedTextField,{...props,forwardedRef:ref}));
1634
1636
 
1635
- const DEFAULT_HREF="javascript:void(0)";class Link extends React.Component{render(){const{children,className,highlighted,href,inlineStyles,referrer,style,target,testId,element,...otherProps}=this.props;const[hrefWithoutHash,hash]=href?href.split("#"):[DEFAULT_HREF];let url=hrefWithoutHash;if(referrer){if(url.indexOf("?")>-1){url+="&ref="+referrer;}else {url+="?ref="+referrer;}}if(hash){url+="#"+hash;}const delegatedStyles=[styles$8.link,highlighted&&styles$8.highlighted];if(Array.isArray(style)){delegatedStyles.push(...style);}else {delegatedStyles.push(style);}const delegatedClassName=className?" "+className:"";const urlProp=element==="a"?{href:url}:{to:url};let rel=otherProps.rel;if(target==="_blank"&&!rel){rel="noopener noreferrer";}return React.createElement(element,{"data-testid":testId,...otherProps,...urlProp,className:css(...delegatedStyles)+delegatedClassName,style:inlineStyles,target,rel},children)}}Link.defaultProps={highlighted:false,href:DEFAULT_HREF,style:[],element:"a"};const styles$8=StyleSheet.create({link:{backgroundColor:"transparent",color:"inherit",textDecoration:"none",":hover":{textDecoration:"underline"}},highlighted:{textDecoration:"underline"}});
1637
+ const DEFAULT_HREF="javascript:void(0)";class Link extends React.Component{render(){const{children,className,highlighted,href,inlineStyles,referrer,style,target,testId,element,...otherProps}=this.props;const[hrefWithoutHash,hash]=href?href.split("#"):[DEFAULT_HREF];let url=hrefWithoutHash;if(referrer){if(url.indexOf("?")>-1){url+="&ref="+referrer;}else {url+="?ref="+referrer;}}if(hash){url+="#"+hash;}const delegatedStyles=[styles$9.link,highlighted&&styles$9.highlighted];if(Array.isArray(style)){delegatedStyles.push(...style);}else {delegatedStyles.push(style);}const delegatedClassName=className?" "+className:"";const urlProp=element==="a"?{href:url}:{to:url};let rel=otherProps.rel;if(target==="_blank"&&!rel){rel="noopener noreferrer";}return React.createElement(element,{"data-testid":testId,...otherProps,...urlProp,className:css(...delegatedStyles)+delegatedClassName,style:inlineStyles,target,rel},children)}}Link.defaultProps={highlighted:false,href:DEFAULT_HREF,style:[],element:"a"};const styles$9=StyleSheet.create({link:{backgroundColor:"transparent",color:"inherit",textDecoration:"none",":hover":{textDecoration:"underline"}},highlighted:{textDecoration:"underline"}});
1636
1638
 
1637
- const{Icon: Icon$1}=components;const addIcon={path:"M11 11V7a1 1 0 0 1 2 0v4h4a1 1 0 0 1 0 2h-4v4a1 1 0 0 1-2 0v-4H7a1 1 0 0 1 0-2h4zm1 13C5.373 24 0 18.627 0 12S5.373 0 12 0s12 5.373 12 12-5.373 12-12 12zm0-2c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z",width:24,height:24};const removeIcon={path:"M12 24C5.373 24 0 18.627 0 12S5.373 0 12 0s12 5.373 12 12-5.373 12-12 12zm0-2c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zm-5-9a1 1 0 0 1 0-2h10a1 1 0 0 1 0 2H7z",width:24,height:24};const DraggableGripIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",children:[jsxRuntimeExports.jsxs("filter",{id:"draggable-grip-shadow",width:"112.5%",height:"116.7%",x:"-6.2%",y:"-8.3%",filterUnits:"objectBoundingBox",children:[jsxRuntimeExports.jsx("feGaussianBlur",{in:"SourceAlpha",stdDeviation:".5",result:"shadowBlurInner"}),jsxRuntimeExports.jsx("feOffset",{in:"shadowBlurInner",dy:"1",result:"shadowOffsetInner"}),jsxRuntimeExports.jsx("feComposite",{in:"shadowOffsetInner",in2:"SourceAlpha",k2:"-1",k3:"1",operator:"arithmetic",result:"shadowInnerInner"}),jsxRuntimeExports.jsx("feColorMatrix",{in:"shadowInnerInner",values:"0 0 0 0 0.129411765 0 0 0 0 0.141176471 0 0 0 0 0.17254902 0 0 0 0.2 0"})]}),jsxRuntimeExports.jsx("path",{d:"M1 4a1 1 0 1 1 0-2h14a1 1 0 0 1 0 2H1zm0 10a1 1 0 0 1 0-2h14a1 1 0 0 1 0 2H1zm0-5a1 1 0 1 1 0-2h14a1 1 0 0 1 0 2H1z",fill:gray17,filter:"url(#draggable-grip-shadow)"})]});const AddAnswer=({onClick})=>jsxRuntimeExports.jsxs(Link,{className:css(styles$7.addAnswer,editorStyles.addAnswer),onClick:onClick,children:[jsxRuntimeExports.jsx(Icon$1,{icon:addIcon,size:24}),jsxRuntimeExports.jsx("div",{className:css(styles$7.spacer)}),"Add an answer choice"]});const Answer=({answer,onChange,onRemove})=>jsxRuntimeExports.jsxs("li",{className:css(styles$7.answer),children:[jsxRuntimeExports.jsx(Link,{onClick:onRemove,children:jsxRuntimeExports.jsx(Icon$1,{icon:removeIcon,size:24,color:"#D92916"})}),jsxRuntimeExports.jsx("div",{className:css(styles$7.spacer)}),jsxRuntimeExports.jsx(FormWrappedTextField$1,{grow:1,onChange:e=>onChange(e.target.value),value:answer}),jsxRuntimeExports.jsx("div",{className:css(styles$7.spacer)}),jsxRuntimeExports.jsx(Link,{style:[styles$7.disabled],title:"Answer reordering is not implemented.",children:jsxRuntimeExports.jsx(DraggableGripIcon,{})})]});const AnswerChoices=({choices,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$7.title),children:"Answer Choices"}),jsxRuntimeExports.jsx("ul",{className:css(styles$7.answers),children:choices.map((answer,index)=>jsxRuntimeExports.jsx(Answer,{answer:answer,onChange:answer=>onChange([...choices.slice(0,index),answer,...choices.slice(index+1)]),onRemove:()=>onChange([...choices.slice(0,index),...choices.slice(index+1)])},index))}),jsxRuntimeExports.jsx(AddAnswer,{onClick:()=>onChange([...choices,""])})]});const styles$7=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},answers:{marginTop:12,marginBottom:12},answer:{display:"flex",flexDirection:"row",alignItems:"center",":not(:first-child)":{marginTop:12}},addAnswer:{...bodyXsmallBold,display:"flex",flexDirection:"row",alignItems:"center",color:"#1865f2"},spacer:{width:16},disabled:{cursor:"not-allowed"}});const editorStyles=StyleSheet.create({addAnswer:{":link":{color:"#1865f2"}}});
1639
+ const{Icon: Icon$1}=components;const addIcon={path:"M11 11V7a1 1 0 0 1 2 0v4h4a1 1 0 0 1 0 2h-4v4a1 1 0 0 1-2 0v-4H7a1 1 0 0 1 0-2h4zm1 13C5.373 24 0 18.627 0 12S5.373 0 12 0s12 5.373 12 12-5.373 12-12 12zm0-2c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z",width:24,height:24};const removeIcon={path:"M12 24C5.373 24 0 18.627 0 12S5.373 0 12 0s12 5.373 12 12-5.373 12-12 12zm0-2c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zm-5-9a1 1 0 0 1 0-2h10a1 1 0 0 1 0 2H7z",width:24,height:24};const DraggableGripIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",children:[jsxRuntimeExports.jsxs("filter",{id:"draggable-grip-shadow",width:"112.5%",height:"116.7%",x:"-6.2%",y:"-8.3%",filterUnits:"objectBoundingBox",children:[jsxRuntimeExports.jsx("feGaussianBlur",{in:"SourceAlpha",stdDeviation:".5",result:"shadowBlurInner"}),jsxRuntimeExports.jsx("feOffset",{in:"shadowBlurInner",dy:"1",result:"shadowOffsetInner"}),jsxRuntimeExports.jsx("feComposite",{in:"shadowOffsetInner",in2:"SourceAlpha",k2:"-1",k3:"1",operator:"arithmetic",result:"shadowInnerInner"}),jsxRuntimeExports.jsx("feColorMatrix",{in:"shadowInnerInner",values:"0 0 0 0 0.129411765 0 0 0 0 0.141176471 0 0 0 0 0.17254902 0 0 0 0.2 0"})]}),jsxRuntimeExports.jsx("path",{d:"M1 4a1 1 0 1 1 0-2h14a1 1 0 0 1 0 2H1zm0 10a1 1 0 0 1 0-2h14a1 1 0 0 1 0 2H1zm0-5a1 1 0 1 1 0-2h14a1 1 0 0 1 0 2H1z",fill:gray17,filter:"url(#draggable-grip-shadow)"})]});const AddAnswer=({onClick})=>jsxRuntimeExports.jsxs(Link,{className:css(styles$8.addAnswer,editorStyles.addAnswer),onClick:onClick,children:[jsxRuntimeExports.jsx(Icon$1,{icon:addIcon,size:24}),jsxRuntimeExports.jsx("div",{className:css(styles$8.spacer)}),"Add an answer choice"]});const Answer=({answer,onChange,onRemove})=>jsxRuntimeExports.jsxs("li",{className:css(styles$8.answer),children:[jsxRuntimeExports.jsx(Link,{onClick:onRemove,children:jsxRuntimeExports.jsx(Icon$1,{icon:removeIcon,size:24,color:"#D92916"})}),jsxRuntimeExports.jsx("div",{className:css(styles$8.spacer)}),jsxRuntimeExports.jsx(FormWrappedTextField$1,{grow:1,onChange:e=>onChange(e.target.value),value:answer}),jsxRuntimeExports.jsx("div",{className:css(styles$8.spacer)}),jsxRuntimeExports.jsx(Link,{style:[styles$8.disabled],title:"Answer reordering is not implemented.",children:jsxRuntimeExports.jsx(DraggableGripIcon,{})})]});const AnswerChoices=({choices,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$8.title),children:"Answer Choices"}),jsxRuntimeExports.jsx("ul",{className:css(styles$8.answers),children:choices.map((answer,index)=>jsxRuntimeExports.jsx(Answer,{answer:answer,onChange:answer=>onChange([...choices.slice(0,index),answer,...choices.slice(index+1)]),onRemove:()=>onChange([...choices.slice(0,index),...choices.slice(index+1)])},index))}),jsxRuntimeExports.jsx(AddAnswer,{onClick:()=>onChange([...choices,""])})]});const styles$8=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},answers:{marginTop:12,marginBottom:12},answer:{display:"flex",flexDirection:"row",alignItems:"center",":not(:first-child)":{marginTop:12}},addAnswer:{...bodyXsmallBold,display:"flex",flexDirection:"row",alignItems:"center",color:"#1865f2"},spacer:{width:16},disabled:{cursor:"not-allowed"}});const editorStyles=StyleSheet.create({addAnswer:{":link":{color:"#1865f2"}}});
1638
1640
 
1639
1641
  class HoverBehavior extends React.Component{render(){const handlers={onBlur:this.handleBlur,onClick:this.handleClick,onFocus:this.handleFocus,onMouseDown:this.handleMouseDown,onMouseEnter:this.handleMouseEnter,onMouseLeave:this.handleMouseLeave,onTouchStart:this.handleTouchStart,onTouchEnd:this.handleTouchEnd};const{children}=this.props;return children?.(this.state,handlers)||null}constructor(props){super(props),this.handleClick=e=>{if(!this.props.disabled){if(this.props.shouldUpdate()){this.waitingForClick=false;}if(this.props.onClick&&!this.props.disabled){this.props.onClick(e);}}},this.handleMouseEnter=()=>{if(!this.props.disabled&&this.props.shouldUpdate()&&!this.waitingForClick){this.setState({hovered:true});}},this.handleMouseLeave=()=>{if(!this.props.disabled&&this.props.shouldUpdate()&&!this.waitingForClick){this.setState({hovered:false});}},this.handleTouchStart=()=>{if(!this.props.disabled&&this.props.shouldUpdate()){this.setState({hovered:true});}},this.handleTouchEnd=()=>{if(!this.props.disabled&&this.props.shouldUpdate()){this.setState({hovered:false});this.waitingForClick=true;}},this.handleMouseDown=()=>{if(!this.props.disabled&&this.props.shouldUpdate()){this.setState({focused:false});this.focusFlag=true;}},this.handleBlur=()=>{if(!this.props.disabled&&this.props.shouldUpdate()){this.setState({focused:false});}},this.handleFocus=()=>{if(!this.props.disabled&&this.props.shouldUpdate()){if(this.focusFlag){this.focusFlag=false;}else {this.setState({focused:true});}}};this.state={focused:false,hovered:props.startHovered};}}HoverBehavior.defaultProps={startHovered:false,shouldUpdate:()=>true};
1640
1642
 
1641
- const borderRadius=4;const onChangeCheckboxNoop=event=>{};class Checkbox extends React.Component{render(){const{checked,disabled,appearDisabled,onChange,tabIndex,style,dataTestId,id}=this.props;const checkedColor=gray41;return jsxRuntimeExports.jsx(HoverBehavior,{children:({focused},handlers)=>jsxRuntimeExports.jsxs("div",{...handlers,className:css(styles$6.container,focused&&styles$6.focused),style:style,"data-testid":dataTestId,"data-checked":checked,children:[jsxRuntimeExports.jsx("svg",{className:css(styles$6.svg,(disabled||appearDisabled)&&styles$6.disabled),width:sizeWithPadding,height:sizeWithPadding,viewBox:`-${padding} -${padding}
1642
- ${sizeWithPadding} ${sizeWithPadding}`,children:jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[checked&&jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx("rect",{fill:checkedColor,width:size,height:size,x:"0",y:"0",rx:borderRadius}),jsxRuntimeExports.jsx("path",{fill:color.white,stroke:color.white,d:"M4.98 7.41a0.58.58 0 1 0-0.81.81L6.47 10.53c0.23.23.59.23.81 0l4.55-4.55a0.58.58 0 0 0-0.81-0.81L6.88 9.31 4.98 7.41z"})]}),!checked&&jsxRuntimeExports.jsx("rect",{fill:color.white,stroke:gray68,width:size-2*padding,height:size-2*padding,x:padding,y:padding,rx:"4",strokeWidth:borderWidth})]})}),jsxRuntimeExports.jsx("input",{type:"checkbox",id:id,checked:checked,className:css(styles$6.checkbox,disabled&&styles$6.defaultCursor),disabled:disabled,onChange:onChange,tabIndex:tabIndex})]})})}}Checkbox.defaultProps={checked:false,onChange:onChangeCheckboxNoop};const size=16;const padding=.5;const borderWidth=1;const sizeWithPadding=size+2*padding;const styles$6=StyleSheet.create({container:{position:"relative",display:"inline-block",verticalAlign:"middle",lineHeight:0,borderRadius:borderRadius,width:sizeWithPadding,height:sizeWithPadding,flexShrink:0},focused:{"::before":{content:'""',position:"absolute",top:-2,right:-2,bottom:-2,left:-2,borderRadius:borderRadius+2,backgroundColor:"lightblue"}},svg:{position:"absolute",left:0,top:0},checkbox:{appearance:"none",opacity:0,position:"absolute",top:padding,width:size,height:size,margin:0,outline:"none",cursor:"pointer"},disabled:{opacity:.5},defaultCursor:{cursor:"default"}});
1643
+ const borderRadius=4;const onChangeCheckboxNoop=event=>{};class Checkbox extends React.Component{render(){const{checked,disabled,appearDisabled,onChange,tabIndex,style,dataTestId,id}=this.props;const checkedColor=gray41;return jsxRuntimeExports.jsx(HoverBehavior,{children:({focused},handlers)=>jsxRuntimeExports.jsxs("div",{...handlers,className:css(styles$7.container,focused&&styles$7.focused),style:style,"data-testid":dataTestId,"data-checked":checked,children:[jsxRuntimeExports.jsx("svg",{className:css(styles$7.svg,(disabled||appearDisabled)&&styles$7.disabled),width:sizeWithPadding,height:sizeWithPadding,viewBox:`-${padding} -${padding}
1644
+ ${sizeWithPadding} ${sizeWithPadding}`,children:jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[checked&&jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx("rect",{fill:checkedColor,width:size,height:size,x:"0",y:"0",rx:borderRadius}),jsxRuntimeExports.jsx("path",{fill:color.white,stroke:color.white,d:"M4.98 7.41a0.58.58 0 1 0-0.81.81L6.47 10.53c0.23.23.59.23.81 0l4.55-4.55a0.58.58 0 0 0-0.81-0.81L6.88 9.31 4.98 7.41z"})]}),!checked&&jsxRuntimeExports.jsx("rect",{fill:color.white,stroke:gray68,width:size-2*padding,height:size-2*padding,x:padding,y:padding,rx:"4",strokeWidth:borderWidth})]})}),jsxRuntimeExports.jsx("input",{type:"checkbox",id:id,checked:checked,className:css(styles$7.checkbox,disabled&&styles$7.defaultCursor),disabled:disabled,onChange:onChange,tabIndex:tabIndex})]})})}}Checkbox.defaultProps={checked:false,onChange:onChangeCheckboxNoop};const size=16;const padding=.5;const borderWidth=1;const sizeWithPadding=size+2*padding;const styles$7=StyleSheet.create({container:{position:"relative",display:"inline-block",verticalAlign:"middle",lineHeight:0,borderRadius:borderRadius,width:sizeWithPadding,height:sizeWithPadding,flexShrink:0},focused:{"::before":{content:'""',position:"absolute",top:-2,right:-2,bottom:-2,left:-2,borderRadius:borderRadius+2,backgroundColor:"lightblue"}},svg:{position:"absolute",left:0,top:0},checkbox:{appearance:"none",opacity:0,position:"absolute",top:padding,width:size,height:size,margin:0,outline:"none",cursor:"pointer"},disabled:{opacity:.5},defaultCursor:{cursor:"default"}});
1643
1645
 
1644
- const Behavior=({multipleAnswers,hideChoicesFromInstructions,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$5.title),children:"Behavior"}),jsxRuntimeExports.jsxs("ul",{children:[jsxRuntimeExports.jsxs("li",{className:css(styles$5.option),children:[jsxRuntimeExports.jsx(Checkbox,{checked:multipleAnswers,onChange:()=>onChange({multipleAnswers:!multipleAnswers})}),jsxRuntimeExports.jsx("span",{className:css(styles$5.label),children:"Allow multiple answers per marker"})]}),jsxRuntimeExports.jsxs("li",{className:css(styles$5.option),children:[jsxRuntimeExports.jsx(Checkbox,{checked:hideChoicesFromInstructions,onChange:()=>onChange({hideChoicesFromInstructions:!hideChoicesFromInstructions})}),jsxRuntimeExports.jsx("span",{className:css(styles$5.label),children:"Do not display answer choices in instructions"})]})]})]});const styles$5=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},option:{display:"flex",padding:"6px 0"},label:{fontFamily:"inherit",fontSize:15,lineHeight:1.25,marginLeft:16,color:gray17}});
1646
+ const Behavior=({multipleAnswers,hideChoicesFromInstructions,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$6.title),children:"Behavior"}),jsxRuntimeExports.jsxs("ul",{children:[jsxRuntimeExports.jsxs("li",{className:css(styles$6.option),children:[jsxRuntimeExports.jsx(Checkbox,{checked:multipleAnswers,onChange:()=>onChange({multipleAnswers:!multipleAnswers})}),jsxRuntimeExports.jsx("span",{className:css(styles$6.label),children:"Allow multiple answers per marker"})]}),jsxRuntimeExports.jsxs("li",{className:css(styles$6.option),children:[jsxRuntimeExports.jsx(Checkbox,{checked:hideChoicesFromInstructions,onChange:()=>onChange({hideChoicesFromInstructions:!hideChoicesFromInstructions})}),jsxRuntimeExports.jsx("span",{className:css(styles$6.label),children:"Do not display answer choices in instructions"})]})]})]});const styles$6=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},option:{display:"flex",padding:"6px 0"},label:{fontFamily:"inherit",fontSize:15,lineHeight:1.25,marginLeft:16,color:gray17}});
1645
1647
 
1646
1648
  function focusWithChromeStickyFocusBugWorkaround(element){element.focus({preventScroll:true});}
1647
1649
 
@@ -1649,15 +1651,15 @@ const{Icon}=components;const findAndFocusElement=component=>{const DOMNode=React
1649
1651
  S3.5,9.9,3.4,9.8L2.5,8.9L0.2,6.6C0.1,6.5,0,6.3,0,6.2s0.1-0.3,0.2-0.4
1650
1652
  l0.9-0.9c0.1-0.1,0.3-0.2,0.4-0.2s0.3,0.1,0.4,0.2l1.9,1.9l4.2-4.2c0.1
1651
1653
  -0.1,0.3-0.2,0.4-0.2c0.2,0,0.3,0.1,0.4,0.2l0.9,0.9C9.9,3.5,10,3.7,
1652
- 10,3.8z`;const optionHeight=30;class Option extends React.Component{handleKeyDown(event){const{onDropdownClose}=this.props;const pressedKey=event.key;const focusedElement=event.target;if(pressedKey==="ArrowDown"&&focusedElement.nextSibling){event.preventDefault();focusedElement.nextSibling.focus();}if(pressedKey==="ArrowUp"&&focusedElement.previousSibling){event.preventDefault();focusedElement.previousSibling.focus();}if(pressedKey==="ArrowUp"&&!focusedElement.previousSibling&&onDropdownClose){event.preventDefault();onDropdownClose();}if((pressedKey==="Escape"||pressedKey==="Tab")&&onDropdownClose){onDropdownClose();}}render(){const{selected,value,onClick,children,disabled,hideFocusState,testId,ariaLabel}=this.props;return jsxRuntimeExports.jsx("button",{ref:node=>this.node=node,value:value,role:"menuitemradio","aria-checked":selected,className:css(styles$4.notAButton,disabled&&styles$4.cursorDefault,hideFocusState&&styles$4.noFocus),onClick:value=>{if(!disabled&&onClick){onClick(value);}},onKeyDown:event=>this.handleKeyDown(event),"aria-disabled":disabled,"aria-label":ariaLabel,"data-testid":testId,children:jsxRuntimeExports.jsxs("span",{className:css(styles$4.option,selected&&styles$4.optionSelected,disabled&&styles$4.optionDisabled),children:[children,selected&&jsxRuntimeExports.jsx("span",{className:css(styles$4.check),children:jsxRuntimeExports.jsx(Icon,{icon:check})})]})})}}class OptionGroup extends React.Component{componentDidMount(){if(this.focusedElement){findAndFocusElement(this.focusedElement);}}render(){const{children,onSelected,selectedValues,noMargin,onDropdownClose,hideFocusState}=this.props;return jsxRuntimeExports.jsx("div",{style:{top},className:css(styles$4.optionGroup,noMargin&&styles$4.optionGroupNoMargin),children:React.Children.map(children,(child,index)=>{const selected=selectedValues.includes(child.props.value);const reference=selected||index===0?node=>this.focusedElement=node:null;return React.cloneElement(child,{...child.props,key:index,selected:selected,onClick:()=>onSelected(child.props.value),ref:reference,onDropdownClose:onDropdownClose,hideFocusState:hideFocusState})})})}}const styles$4=StyleSheet.create({optionGroup:{margin:"4px 0"},optionGroupNoMargin:{margin:0},option:{display:"flex",flexDirection:"row",alignItems:"center",paddingLeft:32,paddingRight:32,height:optionHeight,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",color:gray17,userSelect:"none",":hover":{backgroundColor:gray95}},optionSelected:{backgroundColor:gray95,color:"#11ACCD"},optionDisabled:{color:gray76,":hover":{backgroundColor:"transparent"}},check:{position:"absolute",left:11},notAButton:{backgroundColor:"transparent",border:"none",display:"block",padding:0,margin:0,width:"100%",font:"inherit"},noFocus:{outline:"none"},cursorDefault:{cursor:"default"}});
1654
+ 10,3.8z`;const optionHeight=30;class Option extends React.Component{handleKeyDown(event){const{onDropdownClose}=this.props;const pressedKey=event.key;const focusedElement=event.target;if(pressedKey==="ArrowDown"&&focusedElement.nextSibling){event.preventDefault();focusedElement.nextSibling.focus();}if(pressedKey==="ArrowUp"&&focusedElement.previousSibling){event.preventDefault();focusedElement.previousSibling.focus();}if(pressedKey==="ArrowUp"&&!focusedElement.previousSibling&&onDropdownClose){event.preventDefault();onDropdownClose();}if((pressedKey==="Escape"||pressedKey==="Tab")&&onDropdownClose){onDropdownClose();}}render(){const{selected,value,onClick,children,disabled,hideFocusState,testId,ariaLabel}=this.props;return jsxRuntimeExports.jsx("button",{ref:node=>this.node=node,value:value,role:"menuitemradio","aria-checked":selected,className:css(styles$5.notAButton,disabled&&styles$5.cursorDefault,hideFocusState&&styles$5.noFocus),onClick:value=>{if(!disabled&&onClick){onClick(value);}},onKeyDown:event=>this.handleKeyDown(event),"aria-disabled":disabled,"aria-label":ariaLabel,"data-testid":testId,children:jsxRuntimeExports.jsxs("span",{className:css(styles$5.option,selected&&styles$5.optionSelected,disabled&&styles$5.optionDisabled),children:[children,selected&&jsxRuntimeExports.jsx("span",{className:css(styles$5.check),children:jsxRuntimeExports.jsx(Icon,{icon:check})})]})})}}class OptionGroup extends React.Component{componentDidMount(){if(this.focusedElement){findAndFocusElement(this.focusedElement);}}render(){const{children,onSelected,selectedValues,noMargin,onDropdownClose,hideFocusState}=this.props;return jsxRuntimeExports.jsx("div",{style:{top},className:css(styles$5.optionGroup,noMargin&&styles$5.optionGroupNoMargin),children:React.Children.map(children,(child,index)=>{const selected=selectedValues.includes(child.props.value);const reference=selected||index===0?node=>this.focusedElement=node:null;return React.cloneElement(child,{...child.props,key:index,selected:selected,onClick:()=>onSelected(child.props.value),ref:reference,onDropdownClose:onDropdownClose,hideFocusState:hideFocusState})})})}}const styles$5=StyleSheet.create({optionGroup:{margin:"4px 0"},optionGroupNoMargin:{margin:0},option:{display:"flex",flexDirection:"row",alignItems:"center",paddingLeft:32,paddingRight:32,height:optionHeight,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",color:gray17,userSelect:"none",":hover":{backgroundColor:gray95}},optionSelected:{backgroundColor:gray95,color:"#11ACCD"},optionDisabled:{color:gray76,":hover":{backgroundColor:"transparent"}},check:{position:"absolute",left:11},notAButton:{backgroundColor:"transparent",border:"none",display:"block",padding:0,margin:0,width:"100%",font:"inherit"},noFocus:{outline:"none"},cursorDefault:{cursor:"default"}});
1653
1655
 
1654
- class Marker extends React.Component{componentDidMount(){document.addEventListener("click",this.handleClick,true);}UNSAFE_componentWillReceiveProps(nextProps){const{answers}=this.props;const filteredAnswers=answers.filter(answer=>nextProps.choices.includes(answer));if(JSON.stringify(answers)!==JSON.stringify(filteredAnswers)){setTimeout(()=>this.updateMarker({answers:filteredAnswers}));}}componentWillUnmount(){document.removeEventListener("click",this.handleClick,true);}openDropdown(){this.setState({showDropdown:true});}updateMarker(props){const{answers,label,onChange,x,y}=this.props;onChange({answers,label,x,y,...props});}render(){const{answers,choices,label,onRemove,x,y}=this.props;const{showDropdown}=this.state;return jsxRuntimeExports.jsx("div",{className:css(styles$3.marker,answers.length>0&&styles$3.markerWithAnswers,showDropdown&&styles$3.markerSelected),ref:node=>this._marker=node,style:{left:`${x}%`,top:`${y}%`},title:"Click to select marker answers or to delete marker. "+"Repositioning marker is not implemented.",children:showDropdown&&jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("div",{className:css(styles$3.dropdownBody,styles$3.dropdownPositionWithArrow),children:[jsxRuntimeExports.jsx(Option,{value:"",onClick:()=>onRemove(),children:"Delete marker"}),jsxRuntimeExports.jsx("hr",{className:css(styles$3.dividerHorizontal)}),jsxRuntimeExports.jsx(OptionGroup,{onSelected:this.handleSelectAnswer,selectedValues:answers,children:choices.map(choice=>jsxRuntimeExports.jsx(Option,{value:choice,children:choice},choice))}),jsxRuntimeExports.jsx("div",{className:css(styles$3.labelContainer),children:jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"ARIA label (for screen readers)",onChange:this.handleLabelChange,value:label,width:"100%"})})]})})})}constructor(props){super(props),this.handleClick=e=>{const{showDropdown}=this.state;if(this._marker===e.target){this.setState({showDropdown:!showDropdown});}else if(showDropdown){if(this._marker&&!this._marker.contains(e.target)){e.stopPropagation();this.setState({showDropdown:false});}}},this.handleLabelChange=e=>{this.updateMarker({label:e.target.value});},this.handleSelectAnswer=toggleAnswer=>{let{answers}=this.props;if(answers.includes(toggleAnswer)){answers=answers.filter(answer=>answer!==toggleAnswer);}else {answers=[...answers,toggleAnswer];}this.updateMarker({answers});};this.state={showDropdown:false};}}const styles$3=StyleSheet.create({marker:{position:"absolute",boxSizing:"content-box",width:16,height:16,marginLeft:-8,marginTop:-8,cursor:"pointer",background:"linear-gradient(to bottom, rgba(33, 36, 44, 0.2), rgba(33, 36, 44, 0.5))",border:"solid 2px #ffffff",borderRadius:16,boxShadow:"0 2px 10px 0 rgba(33, 36, 44, 0.1)"},markerSelected:{width:28,height:28,marginLeft:-12,marginTop:-12,border:"none",borderRadius:28,"::before":{content:"''",display:"block",width:20,height:20,marginLeft:2,marginTop:2,border:"solid 2px #ffffff",borderRadius:20}},markerWithAnswers:{background:"#1865f2"},dropdownPositionWithArrow:{left:46,bottom:-12,"::before":{content:"''",display:"block",position:"absolute",width:0,height:0,left:-16,bottom:8,borderRight:`solid 16px ${gray98}`,borderTop:"solid 16px transparent",borderBottom:"solid 16px transparent"}},labelContainer:{padding:4},dividerHorizontal:{height:0,margin:0,border:`solid ${gray85}`,borderWidth:"0 0 1px",boxShadow:"none"},dropdownBody:{position:"absolute",border:"solid 1px rgba(0, 0, 0, 0.1)",zIndex:1e3,color:gray17,backgroundColor:gray98,borderRadius:4,maxHeight:320,cursor:"pointer"}});
1656
+ class Marker extends React.Component{componentDidMount(){document.addEventListener("click",this.handleClick,true);}UNSAFE_componentWillReceiveProps(nextProps){const{answers}=this.props;const filteredAnswers=answers.filter(answer=>nextProps.choices.includes(answer));if(JSON.stringify(answers)!==JSON.stringify(filteredAnswers)){setTimeout(()=>this.updateMarker({answers:filteredAnswers}));}}componentWillUnmount(){document.removeEventListener("click",this.handleClick,true);}openDropdown(){this.setState({showDropdown:true});}updateMarker(props){const{answers,label,onChange,x,y}=this.props;onChange({answers,label,x,y,...props});}render(){const{answers,choices,label,onRemove,x,y}=this.props;const{showDropdown}=this.state;return jsxRuntimeExports.jsx("div",{className:css(styles$4.marker,answers.length>0&&styles$4.markerWithAnswers,showDropdown&&styles$4.markerSelected),ref:node=>this._marker=node,style:{left:`${x}%`,top:`${y}%`},title:"Click to select marker answers or to delete marker. "+"Repositioning marker is not implemented.",children:showDropdown&&jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("div",{className:css(styles$4.dropdownBody,styles$4.dropdownPositionWithArrow),children:[jsxRuntimeExports.jsx(Option,{value:"",onClick:()=>onRemove(),children:"Delete marker"}),jsxRuntimeExports.jsx("hr",{className:css(styles$4.dividerHorizontal)}),jsxRuntimeExports.jsx(OptionGroup,{onSelected:this.handleSelectAnswer,selectedValues:answers,children:choices.map(choice=>jsxRuntimeExports.jsx(Option,{value:choice,children:choice},choice))}),jsxRuntimeExports.jsx("div",{className:css(styles$4.labelContainer),children:jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"ARIA label (for screen readers)",onChange:this.handleLabelChange,value:label,width:"100%"})})]})})})}constructor(props){super(props),this.handleClick=e=>{const{showDropdown}=this.state;if(this._marker===e.target){this.setState({showDropdown:!showDropdown});}else if(showDropdown){if(this._marker&&!this._marker.contains(e.target)){e.stopPropagation();this.setState({showDropdown:false});}}},this.handleLabelChange=e=>{this.updateMarker({label:e.target.value});},this.handleSelectAnswer=toggleAnswer=>{let{answers}=this.props;if(answers.includes(toggleAnswer)){answers=answers.filter(answer=>answer!==toggleAnswer);}else {answers=[...answers,toggleAnswer];}this.updateMarker({answers});};this.state={showDropdown:false};}}const styles$4=StyleSheet.create({marker:{position:"absolute",boxSizing:"content-box",width:16,height:16,marginLeft:-8,marginTop:-8,cursor:"pointer",background:"linear-gradient(to bottom, rgba(33, 36, 44, 0.2), rgba(33, 36, 44, 0.5))",border:"solid 2px #ffffff",borderRadius:16,boxShadow:"0 2px 10px 0 rgba(33, 36, 44, 0.1)"},markerSelected:{width:28,height:28,marginLeft:-12,marginTop:-12,border:"none",borderRadius:28,"::before":{content:"''",display:"block",width:20,height:20,marginLeft:2,marginTop:2,border:"solid 2px #ffffff",borderRadius:20}},markerWithAnswers:{background:"#1865f2"},dropdownPositionWithArrow:{left:46,bottom:-12,"::before":{content:"''",display:"block",position:"absolute",width:0,height:0,left:-16,bottom:8,borderRight:`solid 16px ${gray98}`,borderTop:"solid 16px transparent",borderBottom:"solid 16px transparent"}},labelContainer:{padding:4},dividerHorizontal:{height:0,margin:0,border:`solid ${gray85}`,borderWidth:"0 0 1px",boxShadow:"none"},dropdownBody:{position:"absolute",border:"solid 1px rgba(0, 0, 0, 0.1)",zIndex:1e3,color:gray17,backgroundColor:gray98,borderRadius:4,maxHeight:320,cursor:"pointer"}});
1655
1657
 
1656
- class QuestionMarkers extends React.Component{openDropdownForMarkerIndices(indices){indices.forEach(index=>{if(this._markers[index]){this._markers[index]?.openDropdown();}});}render(){const{choices,imageUrl,imageWidth,imageHeight,markers,onChange}=this.props;const staticUrl=Dependencies.getDependencies().staticUrl;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$2.title),children:"Markers"}),jsxRuntimeExports.jsx("div",{className:css(styles$2.subtitle),children:imageUrl?jsxRuntimeExports.jsxs("span",{children:["Double-click on the image to add a marker.",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),"Markers are read by screen readers in the order that you add them here, so add in a logical order for the learner (e.g. sequentially, clockwise). You can test order by using keyboard tabbing."]}):"Upload an image to place markers."}),imageUrl&&jsxRuntimeExports.jsxs("div",{className:css(styles$2.markersCanvas),style:{maxWidth:imageWidth,maxHeight:imageHeight},children:[jsxRuntimeExports.jsx("img",{alt:"",className:css(styles$2.image),src:staticUrl(Util.getRealImageUrl(imageUrl)),onDoubleClick:this.handleImageDoubleClick}),markers.map((marker,index)=>createElement(Marker,{...marker,choices:choices,key:`${marker.x}.${marker.y}`,onChange:marker=>onChange([...markers.slice(0,index),marker,...markers.slice(index+1)]),onRemove:()=>onChange([...markers.slice(0,index),...markers.slice(index+1)]),ref:node=>this._markers[index]=node}))]})]})}constructor(...args){super(...args),this._markers=[],this.handleImageDoubleClick=e=>{e.preventDefault();const rect=e.currentTarget.getBoundingClientRect();const x=Math.round((e.clientX-rect.left)/rect.width*1e3)/10;const y=Math.round((e.clientY-rect.top)/rect.height*1e3)/10;const{markers,onChange}=this.props;onChange([...markers,{answers:[],label:"",x,y}]);};}}const styles$2=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},subtitle:{fontFamily:"inherit",fontSize:12,lineHeight:"14px",marginBottom:12,color:gray68},markersCanvas:{position:"relative",border:"solid 1px rgba(33, 36, 44, 0.16)"},image:{display:"block",maxWidth:"100%"}});
1658
+ class QuestionMarkers extends React.Component{openDropdownForMarkerIndices(indices){indices.forEach(index=>{if(this._markers[index]){this._markers[index]?.openDropdown();}});}render(){const{choices,imageUrl,imageWidth,imageHeight,markers,onChange}=this.props;const staticUrl=Dependencies.getDependencies().staticUrl;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$3.title),children:"Markers"}),jsxRuntimeExports.jsx("div",{className:css(styles$3.subtitle),children:imageUrl?jsxRuntimeExports.jsxs("span",{children:["Double-click on the image to add a marker.",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("br",{}),"Markers are read by screen readers in the order that you add them here, so add in a logical order for the learner (e.g. sequentially, clockwise). You can test order by using keyboard tabbing."]}):"Upload an image to place markers."}),imageUrl&&jsxRuntimeExports.jsxs("div",{className:css(styles$3.markersCanvas),style:{maxWidth:imageWidth,maxHeight:imageHeight},children:[jsxRuntimeExports.jsx("img",{alt:"",className:css(styles$3.image),src:staticUrl(Util.getRealImageUrl(imageUrl)),onDoubleClick:this.handleImageDoubleClick}),markers.map((marker,index)=>createElement(Marker,{...marker,choices:choices,key:`${marker.x}.${marker.y}`,onChange:marker=>onChange([...markers.slice(0,index),marker,...markers.slice(index+1)]),onRemove:()=>onChange([...markers.slice(0,index),...markers.slice(index+1)]),ref:node=>this._markers[index]=node}))]})]})}constructor(...args){super(...args),this._markers=[],this.handleImageDoubleClick=e=>{e.preventDefault();const rect=e.currentTarget.getBoundingClientRect();const x=Math.round((e.clientX-rect.left)/rect.width*1e3)/10;const y=Math.round((e.clientY-rect.top)/rect.height*1e3)/10;const{markers,onChange}=this.props;onChange([...markers,{answers:[],label:"",x,y}]);};}}const styles$3=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},subtitle:{fontFamily:"inherit",fontSize:12,lineHeight:"14px",marginBottom:12,color:gray68},markersCanvas:{position:"relative",border:"solid 1px rgba(33, 36, 44, 0.16)"},image:{display:"block",maxWidth:"100%"}});
1657
1659
 
1658
- const SelectImage=({onChange,url})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$1.title),children:"Image"}),jsxRuntimeExports.jsxs("div",{className:css(styles$1.components),children:[jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"URL",grow:1,onChange:e=>onChange(e.target.value),value:url}),jsxRuntimeExports.jsx("div",{className:css(styles$1.spacer)}),jsxRuntimeExports.jsx(Button,{disabled:!url,"aria-label":url?"":"Not implemented. Use the 'Add Image' button in "+"the editor to upload image, then copy the URL here.",onClick:()=>onChange(""),style:styles$1.btn,children:url?"Remove":"Upload"})]})]});const styles$1=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},components:{display:"flex"},spacer:{width:16},btn:{minWidth:90}});
1660
+ const SelectImage=({onChange,url})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:css(styles$2.title),children:"Image"}),jsxRuntimeExports.jsxs("div",{className:css(styles$2.components),children:[jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"URL",grow:1,onChange:e=>onChange(e.target.value),value:url}),jsxRuntimeExports.jsx("div",{className:css(styles$2.spacer)}),jsxRuntimeExports.jsx(Button,{disabled:!url,"aria-label":url?"":"Not implemented. Use the 'Add Image' button in "+"the editor to upload image, then copy the URL here.",onClick:()=>onChange(""),style:styles$2.btn,children:url?"Remove":"Upload"})]})]});const styles$2=StyleSheet.create({title:{...bodyXsmallBold,marginBottom:6,color:gray17},components:{display:"flex"},spacer:{width:16},btn:{minWidth:90}});
1659
1661
 
1660
- class LabelImageEditor extends React.Component{componentDidUpdate(prevProps){const coordsToMarkers={};prevProps.markers.forEach(marker=>coordsToMarkers[`${marker.x}.${marker.y}`]=marker);const newIndices=this.props.markers.map((marker,index)=>coordsToMarkers.hasOwnProperty(`${marker.x}.${marker.y}`)?-1:index).filter(index=>index!==-1);if(newIndices.length&&this._questionMarkers){this._questionMarkers.openDropdownForMarkerIndices(newIndices);}}serialize(){return EditorJsonify.serialize.call(this)}render(){const{choices,imageAlt,imageUrl,imageWidth,imageHeight,markers,multipleAnswers,hideChoicesFromInstructions}=this.props;const imageSelected=imageUrl&&imageWidth>0&&imageHeight>0;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(SelectImage,{onChange:this.handleImageChange,url:imageUrl}),jsxRuntimeExports.jsx("div",{className:css(styles.smallSpacer)}),imageSelected&&jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"Alt text (for screen readers)",onChange:e=>this.handleAltChange(e.target.value),value:imageAlt,width:"100%"}),jsxRuntimeExports.jsx("div",{className:css(styles.largeSpacer)}),jsxRuntimeExports.jsx(QuestionMarkers,{choices:choices,imageUrl:imageSelected?imageUrl:"",imageWidth:imageWidth,imageHeight:imageHeight,markers:markers,onChange:this.handleMarkersChange,ref:node=>this._questionMarkers=node}),jsxRuntimeExports.jsx("div",{className:css(styles.largeSpacer)}),jsxRuntimeExports.jsx(AnswerChoices,{choices:choices,onChange:this.handleChoicesChange}),jsxRuntimeExports.jsx("div",{className:css(styles.largeSpacer)}),jsxRuntimeExports.jsx(Behavior,{multipleAnswers:multipleAnswers,hideChoicesFromInstructions:hideChoicesFromInstructions,onChange:this.handleBehaviorChange})]})}constructor(...args){super(...args),this.getSaveWarnings=()=>{const{choices,imageAlt,imageUrl,markers}=this.props;const warnings=[];if(choices.length<2){warnings.push("Question requires at least two answer choices");}if(!imageUrl){warnings.push("Image is not specified for question");}else if(!imageAlt){warnings.push("Question image has no alt text");}if(!markers.length){warnings.push("Question has no markers, to label answers on image");}else {let numNoAnswers=0;let numNoLabels=0;for(const marker of markers){if(!marker.answers.length){numNoAnswers++;}if(!marker.label){numNoLabels++;}}if(numNoAnswers){warnings.push(`Question has ${numNoAnswers} markers with no `+"answers selected");}if(numNoLabels){warnings.push(`Question has ${numNoLabels} markers with no `+"ARIA label");}}return warnings},this.handleImageChange=url=>{this.props.onChange({imageUrl:url,imageWidth:0,imageHeight:0});if(url){Util.getImageSize(url,(width,height)=>{this.props.onChange({imageUrl:url,imageWidth:width,imageHeight:height});});}},this.handleAltChange=alt=>{this.props.onChange({imageAlt:alt});},this.handleChoicesChange=choices=>{this.props.onChange({choices});},this.handleMarkersChange=markers=>{this.props.onChange({markers});},this.handleBehaviorChange=options=>{this.props.onChange(options);};}}LabelImageEditor.defaultProps=labelImageLogic.defaultWidgetOptions;LabelImageEditor.widgetName="label-image";const styles=StyleSheet.create({largeSpacer:{height:32},smallSpacer:{height:16}});
1662
+ class LabelImageEditor extends React.Component{componentDidUpdate(prevProps){const coordsToMarkers={};prevProps.markers.forEach(marker=>coordsToMarkers[`${marker.x}.${marker.y}`]=marker);const newIndices=this.props.markers.map((marker,index)=>coordsToMarkers.hasOwnProperty(`${marker.x}.${marker.y}`)?-1:index).filter(index=>index!==-1);if(newIndices.length&&this._questionMarkers){this._questionMarkers.openDropdownForMarkerIndices(newIndices);}}serialize(){return EditorJsonify.serialize.call(this)}render(){const{choices,imageAlt,imageUrl,imageWidth,imageHeight,markers,multipleAnswers,hideChoicesFromInstructions}=this.props;const imageSelected=imageUrl&&imageWidth>0&&imageHeight>0;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(SelectImage,{onChange:this.handleImageChange,url:imageUrl}),jsxRuntimeExports.jsx("div",{className:css(styles$1.smallSpacer)}),imageSelected&&jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"Alt text (for screen readers)",onChange:e=>this.handleAltChange(e.target.value),value:imageAlt,width:"100%"}),jsxRuntimeExports.jsx("div",{className:css(styles$1.largeSpacer)}),jsxRuntimeExports.jsx(QuestionMarkers,{choices:choices,imageUrl:imageSelected?imageUrl:"",imageWidth:imageWidth,imageHeight:imageHeight,markers:markers,onChange:this.handleMarkersChange,ref:node=>this._questionMarkers=node}),jsxRuntimeExports.jsx("div",{className:css(styles$1.largeSpacer)}),jsxRuntimeExports.jsx(AnswerChoices,{choices:choices,onChange:this.handleChoicesChange}),jsxRuntimeExports.jsx("div",{className:css(styles$1.largeSpacer)}),jsxRuntimeExports.jsx(Behavior,{multipleAnswers:multipleAnswers,hideChoicesFromInstructions:hideChoicesFromInstructions,onChange:this.handleBehaviorChange})]})}constructor(...args){super(...args),this.getSaveWarnings=()=>{const{choices,imageAlt,imageUrl,markers}=this.props;const warnings=[];if(choices.length<2){warnings.push("Question requires at least two answer choices");}if(!imageUrl){warnings.push("Image is not specified for question");}else if(!imageAlt){warnings.push("Question image has no alt text");}if(!markers.length){warnings.push("Question has no markers, to label answers on image");}else {let numNoAnswers=0;let numNoLabels=0;for(const marker of markers){if(!marker.answers.length){numNoAnswers++;}if(!marker.label){numNoLabels++;}}if(numNoAnswers){warnings.push(`Question has ${numNoAnswers} markers with no `+"answers selected");}if(numNoLabels){warnings.push(`Question has ${numNoLabels} markers with no `+"ARIA label");}}return warnings},this.handleImageChange=url=>{this.props.onChange({imageUrl:url,imageWidth:0,imageHeight:0});if(url){Util.getImageSize(url,(width,height)=>{this.props.onChange({imageUrl:url,imageWidth:width,imageHeight:height});});}},this.handleAltChange=alt=>{this.props.onChange({imageAlt:alt});},this.handleChoicesChange=choices=>{this.props.onChange({choices});},this.handleMarkersChange=markers=>{this.props.onChange({markers});},this.handleBehaviorChange=options=>{this.props.onChange(options);};}}LabelImageEditor.defaultProps=labelImageLogic.defaultWidgetOptions;LabelImageEditor.widgetName="label-image";const styles$1=StyleSheet.create({largeSpacer:{height:32},smallSpacer:{height:16}});
1661
1663
 
1662
1664
  const{InfoTip: InfoTip$a,TextListEditor: TextListEditor$3}=components;class MatcherEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-matcher-editor",children:[jsxRuntimeExports.jsxs("div",{children:[" ","Correct answer:"," ",jsxRuntimeExports.jsx(InfoTip$a,{children:jsxRuntimeExports.jsx("p",{children:"Enter the correct answers here. The preview on the right will show the cards in a randomized order, which is how the student will see them."})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-clearfix",children:[jsxRuntimeExports.jsx(TextListEditor$3,{options:this.props.left,onChange:(options,cb)=>{this.props.onChange({left:options},cb);},layout:"vertical"}),jsxRuntimeExports.jsx(TextListEditor$3,{options:this.props.right,onChange:(options,cb)=>{this.props.onChange({right:options},cb);},layout:"vertical"})]}),jsxRuntimeExports.jsxs("span",{children:[" ","Labels:"," ",jsxRuntimeExports.jsx(InfoTip$a,{children:jsxRuntimeExports.jsx("p",{children:"These are entirely optional."})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("input",{type:"text",defaultValue:this.props.labels[0],onChange:this.onLabelChange.bind(this,0)}),jsxRuntimeExports.jsx("input",{type:"text",defaultValue:this.props.labels[1],onChange:this.onLabelChange.bind(this,1)})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Checkbox$1,{label:"Order of the matched pairs matters:",checked:this.props.orderMatters,onChange:value=>{this.props.onChange({orderMatters:value});}}),jsxRuntimeExports.jsxs(InfoTip$a,{children:[jsxRuntimeExports.jsx("p",{children:"With this option enabled, only the order provided above will be treated as correct. This is useful when ordering is significant, such as in the context of a proof."}),jsxRuntimeExports.jsx("p",{children:"If disabled, pairwise matching is sufficient. To make this clear, the left column becomes fixed in the provided order and only the cards in the right column can be moved."})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Checkbox$1,{label:"Padding:",checked:this.props.padding,onChange:value=>{this.props.onChange({padding:value});}}),jsxRuntimeExports.jsx(InfoTip$a,{children:jsxRuntimeExports.jsx("p",{children:"Padding is good for text, but not needed for images."})})]})]})}constructor(...args){super(...args),this.onLabelChange=(index,e)=>{const labels=_.clone(this.props.labels);labels[index]=e.target.value;this.props.onChange({labels:labels});},this.getSaveWarnings=()=>{if(this.props.left.length!==this.props.right.length){return ["The two halves of the matcher have different numbers"+" of cards."]}return []},this.serialize=()=>{return _.pick(this.props,"left","right","labels","orderMatters","padding")};}}MatcherEditor.propTypes={left:PropTypes.array,right:PropTypes.array,labels:PropTypes.array,orderMatters:PropTypes.bool,padding:PropTypes.bool};MatcherEditor.widgetName="matcher";MatcherEditor.defaultProps=matcherLogic.defaultWidgetOptions;
1663
1665
 
@@ -1685,7 +1687,15 @@ const{InfoTip: InfoTip$3,NumberInput: NumberInput$2,RangeInput,TextListEditor: T
1685
1687
 
1686
1688
  const{NumberInput: NumberInput$1,TextInput}=components;function validateOptions(height,programID){const errors=[];if(programID===""){errors.push("The program ID is required.");}if(!Number.isInteger(height)||height<1){errors.push("The height must be a positive integer.");}return errors}class PythonProgramEditor extends React.Component{serialize(){return {programID:this.props.programID,height:this.props.height}}render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["User Program ID:"," ",jsxRuntimeExports.jsx(TextInput,{value:this.props.programID,onChange:this.change("programID"),placeholder:"123"})]}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsxs("label",{children:["Height:"," ",jsxRuntimeExports.jsx(NumberInput$1,{value:this.props.height,onChange:this.change("height"),placeholder:"400"})]})]})}constructor(...args){super(...args),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.getSaveWarnings=()=>{return validateOptions(this.props.height,this.props.programID)};}}PythonProgramEditor.widgetName="python-program";PythonProgramEditor.defaultProps=pythonProgramLogic.defaultWidgetOptions;
1687
1689
 
1688
- class ChoiceEditor extends React.Component{render(){const checkedClass=this.props.choice.correct?"correct":"incorrect";let placeholder="Type a choice here...";if(this.props.choice.isNoneOfTheAbove){placeholder=this.props.choice.correct?"Type the answer to reveal to the user...":"None of the above";}const editor=jsxRuntimeExports.jsx(Editor,{ref:"content-editor",apiOptions:this.props.apiOptions,content:this.props.choice.content||"",widgetEnabled:false,placeholder:placeholder,disabled:this.props.choice.isNoneOfTheAbove&&!this.props.choice.correct,onChange:this.props.onContentChange});const rationaleEditor=jsxRuntimeExports.jsx(Editor,{ref:"rationale-editor",apiOptions:this.props.apiOptions,content:this.props.choice.rationale||"",widgetEnabled:false,placeholder:`Why is this choice ${checkedClass}?`,onChange:this.props.onRationaleChange});const deleteLink=jsxRuntimeExports.jsx("a",{className:"simple-button orange delete-choice",href:"#",onClick:e=>{e.stopPropagation();e.preventDefault();this.props.onDelete();},title:"Remove this choice",children:"Remove this choice"});return jsxRuntimeExports.jsxs("div",{className:"choice-rationale-editors",children:[jsxRuntimeExports.jsx("div",{className:`choice-editor ${checkedClass}`,children:editor}),jsxRuntimeExports.jsx("div",{className:"rationale-editor",children:rationaleEditor}),this.props.showDelete&&deleteLink]})}}class RadioEditor extends React.Component{onRationaleChange(choiceIndex,newRationale){const choices=this.props.choices.slice();choices[choiceIndex]=_.extend({},choices[choiceIndex],{rationale:newRationale});if(newRationale===""){delete choices[choiceIndex].rationale;}this.props.onChange({choices:choices});}serialize(){const{choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled}=this.props;return {choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled,numCorrect:deriveNumCorrect(choices)}}render(){const numCorrect=deriveNumCorrect(this.props.choices);return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Link$1,{href:"https://www.khanacademy.org/internal-courses/content-creation-best-practices/xe46daa512cd9c644:question-writing/xe46daa512cd9c644:multiple-choice/a/stems",target:"_blank",children:"Multiple choice best practices"}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Randomize order",checked:this.props.randomize,onChange:value=>{this.props.onChange({randomize:value});},style:{marginBlockEnd:sizing.size_060}}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Multiple selections",checked:this.props.multipleSelect,onChange:value=>{this.onMultipleSelectChange({multipleSelect:value});},style:{marginBlockEnd:sizing.size_060}}),this.props.multipleSelect&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"Specify number correct",checked:this.props.countChoices,onChange:value=>{this.onCountChoicesChange({countChoices:value});},style:{marginBlockEnd:sizing.size_060}})]}),jsxRuntimeExports.jsx(BaseRadio,{multipleSelect:this.props.multipleSelect,countChoices:this.props.countChoices,numCorrect:numCorrect,editMode:true,labelWrap:false,apiOptions:this.props.apiOptions,reviewMode:false,choices:this.props.choices.map((choice,i)=>{return {content:jsxRuntimeExports.jsx(ChoiceEditor,{ref:`choice-editor${i}`,apiOptions:this.props.apiOptions,choice:choice,onContentChange:newProps=>{if(newProps.content!=null){this.onContentChange(i,newProps.content);}},onRationaleChange:newProps=>{if(newProps.content!=null){this.onRationaleChange(i,newProps.content);}},onDelete:()=>this.onDelete(i),showDelete:this.props.choices.length>=2}),isNoneOfTheAbove:choice.isNoneOfTheAbove,checked:choice.correct}},this),onChange:this.onChange}),jsxRuntimeExports.jsxs("div",{className:"add-choice-container",children:[jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:plusIcon,onClick:this.addChoice.bind(this,false),children:"Add a choice"}),jsxRuntimeExports.jsx(Strut,{size:spacing.large_24}),jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:plusIcon,onClick:this.addChoice.bind(this,true),children:"None of the above"})]})]})}constructor(...args){super(...args),this.onMultipleSelectChange=allowMultiple=>{const isMultipleSelect=allowMultiple.multipleSelect;let choices=this.props.choices;if(!isMultipleSelect){const numCorrect=deriveNumCorrect(choices);if(numCorrect>1){choices=choices.map(choice=>{return {...choice,correct:false}});}}this.props.onChange({multipleSelect:isMultipleSelect,choices,numCorrect:deriveNumCorrect(choices)});},this.onCountChoicesChange=count=>{const countChoices=count.countChoices;this.props.onChange({countChoices});},this.onChange=({checked})=>{const choices=this.props.choices.map((choice,i)=>{return {...choice,correct:checked[i],content:choice.isNoneOfTheAbove&&!checked[i]?"":choice.content}});this.props.onChange({choices,numCorrect:deriveNumCorrect(choices)});},this.onContentChange=(choiceIndex,newContent)=>{const choices=this.props.choices.slice();choices[choiceIndex]=_.extend({},choices[choiceIndex],{content:newContent});this.props.onChange({choices:choices});},this.onDelete=choiceIndex=>{const choices=this.props.choices.slice();const deleted=choices[choiceIndex];choices.splice(choiceIndex,1);this.props.onChange({choices,hasNoneOfTheAbove:this.props.hasNoneOfTheAbove&&!deleted.isNoneOfTheAbove,numCorrect:deriveNumCorrect(choices)});},this.addChoice=(noneOfTheAbove,e)=>{e.preventDefault();const choices=this.props.choices.slice();const newChoice={isNoneOfTheAbove:noneOfTheAbove,content:""};const addIndex=choices.length-(this.props.hasNoneOfTheAbove?1:0);choices.splice(addIndex,0,newChoice);this.props.onChange({choices:choices,hasNoneOfTheAbove:noneOfTheAbove||this.props.hasNoneOfTheAbove},()=>{this.refs[`choice-editor${addIndex}`].refs["content-editor"].focus();});},this.focus=()=>{this.refs["choice-editor0"].refs["content-editor"].focus();return true},this.getSaveWarnings=()=>{if(!_.some(_.pluck(this.props.choices,"correct"))){return ["No choice is marked as correct."]}return []};}}RadioEditor.widgetName="radio";RadioEditor.defaultProps=radioLogic.defaultWidgetOptions;
1690
+ var styles = {"tile":"perseus_fAVMAcnB","contentHeading":"perseus_zuVKqxUV"};
1691
+
1692
+ function RadioStatusPill({index,correct,multipleSelect,onClick}){return jsxRuntimeExports.jsx(Pill,{size:"large",style:{marginInlineEnd:sizing.size_080,color:correct?color.white:color.red,backgroundColor:correct?color.activeGreen:color.fadedRed8,borderRadius:multipleSelect?border.radius.radius_040:sizing.size_240,border:`1px solid ${correct?color.activeGreen:color.red}`,width:sizing.size_560,flexDirection:"row"},onClick:onClick,children:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(PhosphorIcon,{size:"small",icon:correct?checkIcon:minusCircleIcon,style:{marginInlineEnd:sizing.size_060},color:correct?color.white:color.red}),String.fromCharCode(65+index)]})})}
1693
+
1694
+ function RadioOptionSettings({index,choice,multipleSelect,onStatusChange,onContentChange,onRationaleChange,showDelete,onDelete}){const{content,rationale,correct,isNoneOfTheAbove}=choice;return jsxRuntimeExports.jsxs("div",{className:styles.tile,children:[jsxRuntimeExports.jsxs("fieldset",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(RadioStatusPill,{index:index,correct:correct,multipleSelect:multipleSelect,onClick:()=>{onStatusChange(index,!correct);}}),jsxRuntimeExports.jsx(HeadingXSmall,{style:{display:"inline",marginInlineEnd:sizing.size_080},children:"Status"}),jsxRuntimeExports.jsx(Pill,{kind:correct?"accent":"transparent",onClick:()=>{onStatusChange(index,true);},style:{marginInlineEnd:sizing.size_080,outlineColor:correct?semanticColor.core.background.instructive.default:semanticColor.core.border.neutral.default},children:"Correct"}),jsxRuntimeExports.jsx(Pill,{kind:correct?"transparent":"accent",onClick:()=>{onStatusChange(index,false);},style:{marginInlineEnd:sizing.size_080,outlineColor:!correct?semanticColor.core.background.instructive.default:semanticColor.core.border.neutral.default},children:"Incorrect"})]}),jsxRuntimeExports.jsxs(HeadingXSmall,{tag:"label",className:styles.contentHeading,children:["Content",jsxRuntimeExports.jsx(TextArea,{value:isNoneOfTheAbove?"None of the above":content,disabled:isNoneOfTheAbove,placeholder:"Type a choice here...",resizeType:"vertical",rows:1,onChange:value=>{onContentChange(index,value);}})]}),jsxRuntimeExports.jsxs(HeadingXSmall,{tag:"label",children:["Rationale",jsxRuntimeExports.jsx(TextArea,{value:rationale??"",placeholder:`Why is this choice ${correct?"correct":"incorrect"}?`,resizeType:"vertical",rows:1,onChange:value=>{onRationaleChange(index,value);}})]}),showDelete&&jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:trashIcon$1,onClick:()=>{if(window.confirm(`Are you sure you want to remove this choice?
1695
+
1696
+ ${content}`)){onDelete();}},style:{alignSelf:"flex-start"},children:"Remove"})]})}
1697
+
1698
+ class RadioEditor extends React.Component{serialize(){const{choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled}=this.props;return {choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled,numCorrect:deriveNumCorrect(choices)}}render(){const numCorrect=deriveNumCorrect(this.props.choices);return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Link$1,{href:"https://www.khanacademy.org/internal-courses/content-creation-best-practices/xe46daa512cd9c644:question-writing/xe46daa512cd9c644:multiple-choice/a/stems",target:"_blank",children:"Multiple choice best practices"}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Randomize order",checked:this.props.randomize,onChange:value=>{this.props.onChange({randomize:value});},style:{marginBlockEnd:sizing.size_060}}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Multiple selections",checked:this.props.multipleSelect,onChange:value=>{this.onMultipleSelectChange({multipleSelect:value});},style:{marginBlockEnd:sizing.size_060}}),this.props.multipleSelect&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Specify number correct",checked:this.props.countChoices,onChange:value=>{this.onCountChoicesChange({countChoices:value});},style:{marginBlockEnd:sizing.size_060}}),jsxRuntimeExports.jsxs(Footnote,{children:["Current number correct: ",numCorrect]})]})]}),this.props.choices.map((choice,index)=>jsxRuntimeExports.jsx(RadioOptionSettings,{index:index,choice:choice,multipleSelect:this.props.multipleSelect,onStatusChange:this.onStatusChange,onContentChange:this.onContentChange,onRationaleChange:this.onRationaleChange,onDelete:()=>this.onDelete(index),showDelete:this.props.choices.length>=2},`choice-${index}}`)),jsxRuntimeExports.jsxs("div",{className:"add-choice-container",children:[jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:plusIcon,onClick:this.addChoice.bind(this,false),style:{marginInlineEnd:"2.4rem"},children:"Add a choice"}),!this.props.hasNoneOfTheAbove&&jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:plusIcon,onClick:this.addChoice.bind(this,true),children:"None of the above"})]})]})}constructor(...args){super(...args),this.onMultipleSelectChange=allowMultiple=>{const isMultipleSelect=allowMultiple.multipleSelect;let choices=this.props.choices;if(!isMultipleSelect){const numCorrect=deriveNumCorrect(choices);if(numCorrect>1){choices=choices.map(choice=>{return {...choice,correct:false}});}}this.props.onChange({multipleSelect:isMultipleSelect,choices,numCorrect:deriveNumCorrect(choices)});},this.onCountChoicesChange=count=>{const countChoices=count.countChoices;this.props.onChange({countChoices});},this.onChange=({checked})=>{const choices=this.props.choices.map((choice,i)=>{return {...choice,correct:checked[i],content:choice.isNoneOfTheAbove&&!checked[i]?"":choice.content}});this.props.onChange({choices,numCorrect:deriveNumCorrect(choices)});},this.onStatusChange=(choiceIndex,correct)=>{let newCheckedList;if(correct&&!this.props.multipleSelect){newCheckedList=this.props.choices.map(_=>false);}else {newCheckedList=this.props.choices.map(c=>c.correct);}newCheckedList[choiceIndex]=correct;this.onChange({checked:newCheckedList});},this.onContentChange=(choiceIndex,newContent)=>{const choices=[...this.props.choices];choices[choiceIndex]={...choices[choiceIndex],content:newContent};this.props.onChange({choices:choices});},this.onRationaleChange=(choiceIndex,newRationale)=>{const choices=[...this.props.choices];choices[choiceIndex]={...choices[choiceIndex],rationale:newRationale};if(newRationale===""){delete choices[choiceIndex].rationale;}this.props.onChange({choices:choices});},this.onDelete=choiceIndex=>{const choices=this.props.choices.slice();const deleted=choices[choiceIndex];choices.splice(choiceIndex,1);this.props.onChange({choices,hasNoneOfTheAbove:this.props.hasNoneOfTheAbove&&!deleted.isNoneOfTheAbove,numCorrect:deriveNumCorrect(choices)});},this.addChoice=(noneOfTheAbove,e)=>{e.preventDefault();const choices=this.props.choices.slice();const newChoice={isNoneOfTheAbove:noneOfTheAbove,content:""};const addIndex=choices.length-(this.props.hasNoneOfTheAbove?1:0);choices.splice(addIndex,0,newChoice);this.props.onChange({choices:choices,hasNoneOfTheAbove:noneOfTheAbove||this.props.hasNoneOfTheAbove},()=>{this.refs[`choice-editor${addIndex}`].refs["content-editor"].focus();});},this.focus=()=>{this.refs["choice-editor0"].refs["content-editor"].focus();return true},this.getSaveWarnings=()=>{if(!_.some(_.pluck(this.props.choices,"correct"))){return ["No choice is marked as correct."]}return []};}}RadioEditor.widgetName="radio";RadioEditor.defaultProps=radioLogic.defaultWidgetOptions;
1689
1699
 
1690
1700
  const{InfoTip: InfoTip$2,TextListEditor}=components;const HORIZONTAL="horizontal";const VERTICAL="vertical";class SorterEditor extends React.Component{render(){const editor=this;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{children:[" ","Correct answer:"," ",jsxRuntimeExports.jsx(InfoTip$2,{children:jsxRuntimeExports.jsx("p",{children:"Enter the correct answer (in the correct order) here. The preview on the right will have the cards in a randomized order, which is how the student will see them."})})]}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.correct,onChange:function(options,cb){editor.props.onChange({correct:options},cb);},layout:this.props.layout}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Layout:"," ",jsxRuntimeExports.jsxs("select",{value:this.props.layout,onChange:this.onLayoutChange,children:[jsxRuntimeExports.jsx("option",{value:HORIZONTAL,children:"Horizontal"}),jsxRuntimeExports.jsx("option",{value:VERTICAL,children:"Vertical"})]})]}),jsxRuntimeExports.jsx(InfoTip$2,{children:jsxRuntimeExports.jsx("p",{children:"Use the horizontal layout for short text and small images. The vertical layout is best for longer text and larger images."})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Checkbox$1,{label:"Padding:",checked:this.props.padding,onChange:value=>{this.props.onChange({padding:value});}}),jsxRuntimeExports.jsx(InfoTip$2,{children:jsxRuntimeExports.jsx("p",{children:"Padding is good for text, but not needed for images."})})]})]})}constructor(...args){super(...args),this.onLayoutChange=e=>{this.props.onChange({layout:e.target.value});},this.serialize=()=>{return _.pick(this.props,"correct","layout","padding")};}}SorterEditor.propTypes={correct:PropTypes.array,layout:PropTypes.oneOf([HORIZONTAL,VERTICAL]),padding:PropTypes.bool};SorterEditor.widgetName="sorter";SorterEditor.defaultProps=sorterLogic.defaultWidgetOptions;
1691
1701